On Tue, Jul 23, 2024 at 09:55:19PM -0400, Waiman Long wrote:
Could you use the "-v <n>" option of git-format-patch to add a version number to the patch title? Without that, it can be confusing as to whether the patch is new or a resend of the previous one.
+1
@@ -775,6 +775,11 @@ struct cgroup_subsys { extern struct percpu_rw_semaphore cgroup_threadgroup_rwsem; +struct cgroup_of_peak {
- long value;
- struct list_head list;
+};
The name "cgroup_of_peak" is kind of confusing. Maybe local_peak?
It's the peak associated with an 'of' (which is a known concept in cgroup code), and it pairs up nicely with of_peak(). I'd prefer keeping that over local_peak.
@@ -26,6 +26,7 @@ struct page_counter { atomic_long_t children_low_usage; unsigned long watermark;
- unsigned long local_watermark; /* track min of fd-local resets */
track "min"? I thought it is used to track local maximum after a reset.
Yeah, the comment doesn't sound quite right.
However, I think we'd be hard-pressed to explain correctly and comprehensively what this thing does in <40 characters.
I'd just remove the comment tbh.
@@ -78,7 +79,10 @@ int page_counter_memparse(const char *buf, const char *max, static inline void page_counter_reset_watermark(struct page_counter *counter) {
- counter->watermark = page_counter_read(counter);
- unsigned long usage = page_counter_read(counter);
- counter->watermark = usage;
- counter->local_watermark = usage; }
Could you set the local_watermark first before setting watermark? There is a very small time window that the invariant "local_watermark <= watermark" is not true.
Does it matter? Only cgroup1 supports global resets; only cgroup2 supports local peaks watching. This doesn't add anything to the race that already exists between reset and global watermark update on cg1.
@@ -3950,12 +3955,90 @@ static u64 memory_current_read(struct cgroup_subsys_state *css, return (u64)page_counter_read(&memcg->memory) * PAGE_SIZE; } -static u64 memory_peak_read(struct cgroup_subsys_state *css,
struct cftype *cft)
+static int peak_show(struct seq_file *sf, void *v, struct page_counter *pc) {
- struct mem_cgroup *memcg = mem_cgroup_from_css(css);
- struct cgroup_of_peak *ofp = of_peak(sf->private);
- s64 fd_peak = ofp->value, peak;
- /* User wants global or local peak? */
- if (fd_peak == -1)
peak = pc->watermark;
- else
peak = max(fd_peak, (s64)pc->local_watermark);
Should you save the local_watermark value into ofp->value if local_watermark is bigger? This will ensure that each successive read of the fd is monotonically increasing. Otherwise the value may go up or down if there are multiple resets in between.
The reset saves local_watermark into ofp->value if it's bigger..?
I do see another problem, though. The compiler might issue multiple reads to ofp->value in arbitrary order. We could print max(-1, ...) which is nonsense. Saving ofp->value into a local variable is the right idea, but the compiler might still issue two reads anyway. It needs a READ_ONCE() to force a single read.
I'd use unsigned long for fd_peak. This way the "specialness" is on the -1UL comparison. The max() must be between two positive numbers, so the (s64) there is confusing.