blk-cgroup: pass blkg_rwstat structures by reference [Linux 5.3]

This Linux kernel change "blk-cgroup: pass blkg_rwstat structures by reference" is included in the Linux 5.3 release. This change is authored by Christoph Hellwig <hch [at] lst.de> on Thu Jun 6 12:26:20 2019 +0200. The commit for this change in Linux stable tree is 5d0b6e4 (patch).

blk-cgroup: pass blkg_rwstat structures by reference

Returning a structure generates rather bad code, so switch to passing
by reference.  Also don't require the structure to be zeroed and add
to the 0-initialized counters, but actually set the counters to the
calculated value.

Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

There are 60 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 block/bfq-cgroup.c         | 15 +++++++++------
 block/blk-cgroup.c         | 31 ++++++++++++++++---------------
 include/linux/blk-cgroup.h | 14 +++++++-------
 3 files changed, 32 insertions(+), 28 deletions(-)

diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index b3796a4..66abc82 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -935,9 +935,9 @@ static u64 bfqg_prfill_stat_recursive(struct seq_file *sf,
 static u64 bfqg_prfill_rwstat_recursive(struct seq_file *sf,
                    struct blkg_policy_data *pd, int off)
 {
-   struct blkg_rwstat sum = blkg_rwstat_recursive_sum(pd_to_blkg(pd),
-                              &blkcg_policy_bfq,
-                              off);
+   struct blkg_rwstat sum;
+
+   blkg_rwstat_recursive_sum(pd_to_blkg(pd), &blkcg_policy_bfq, off, &sum);
    return __blkg_prfill_rwstat(sf, pd, &sum);
 }

@@ -975,9 +975,12 @@ static int bfqg_print_stat_sectors(struct seq_file *sf, void *v)
 static u64 bfqg_prfill_sectors_recursive(struct seq_file *sf,
                     struct blkg_policy_data *pd, int off)
 {
-   struct blkg_rwstat tmp = blkg_rwstat_recursive_sum(pd->blkg, NULL,
-                   offsetof(struct blkcg_gq, stat_bytes));
-   u64 sum = atomic64_read(&tmp.aux_cnt[BLKG_RWSTAT_READ]) +
+   struct blkg_rwstat tmp;
+   u64 sum;
+
+   blkg_rwstat_recursive_sum(pd->blkg, NULL,
+           offsetof(struct blkcg_gq, stat_bytes), &tmp);
+   sum = atomic64_read(&tmp.aux_cnt[BLKG_RWSTAT_READ]) +
        atomic64_read(&tmp.aux_cnt[BLKG_RWSTAT_WRITE]);

    return __blkg_prfill_u64(sf, pd, sum >> 9);
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 0778e52..db039a8 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -597,8 +597,9 @@ u64 blkg_prfill_stat(struct seq_file *sf, struct blkg_policy_data *pd, int off)
 u64 blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd,
               int off)
 {
-   struct blkg_rwstat rwstat = blkg_rwstat_read((void *)pd + off);
+   struct blkg_rwstat rwstat = { };

+   blkg_rwstat_read((void *)pd + off, &rwstat);
    return __blkg_prfill_rwstat(sf, pd, &rwstat);
 }
 EXPORT_SYMBOL_GPL(blkg_prfill_rwstat);
@@ -606,8 +607,9 @@ u64 blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd,
 static u64 blkg_prfill_rwstat_field(struct seq_file *sf,
                    struct blkg_policy_data *pd, int off)
 {
-   struct blkg_rwstat rwstat = blkg_rwstat_read((void *)pd->blkg + off);
+   struct blkg_rwstat rwstat = { };

+   blkg_rwstat_read((void *)pd->blkg + off, &rwstat);
    return __blkg_prfill_rwstat(sf, pd, &rwstat);
 }

@@ -649,8 +651,9 @@ static u64 blkg_prfill_rwstat_field_recursive(struct seq_file *sf,
                          struct blkg_policy_data *pd,
                          int off)
 {
-   struct blkg_rwstat rwstat = blkg_rwstat_recursive_sum(pd->blkg,
-                                 NULL, off);
+   struct blkg_rwstat rwstat;
+
+   blkg_rwstat_recursive_sum(pd->blkg, NULL, off, &rwstat);
    return __blkg_prfill_rwstat(sf, pd, &rwstat);
 }

@@ -731,6 +734,7 @@ u64 blkg_stat_recursive_sum(struct blkcg_gq *blkg,
  * @blkg: blkg of interest
  * @pol: blkcg_policy which contains the blkg_rwstat
  * @off: offset to the blkg_rwstat in blkg_policy_data or @blkg
+ * @sum: blkg_rwstat structure containing the results
  *
  * Collect the blkg_rwstat specified by @blkg, @pol and @off and all its
  * online descendants and their aux counts.  The caller must be holding the
@@ -739,12 +743,11 @@ u64 blkg_stat_recursive_sum(struct blkcg_gq *blkg,
  * If @pol is NULL, blkg_rwstat is at @off bytes into @blkg; otherwise, it
  * is at @off bytes into @blkg's blkg_policy_data of the policy.
  */
-struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkcg_gq *blkg,
-                        struct blkcg_policy *pol, int off)
+void blkg_rwstat_recursive_sum(struct blkcg_gq *blkg, struct blkcg_policy *pol,
+       int off, struct blkg_rwstat *sum)
 {
    struct blkcg_gq *pos_blkg;
    struct cgroup_subsys_state *pos_css;
-   struct blkg_rwstat sum = { };
    unsigned int i;

    lockdep_assert_held(&blkg->q->queue_lock);
@@ -762,12 +765,10 @@ struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkcg_gq *blkg,
            rwstat = (void *)pos_blkg + off;

        for (i = 0; i < BLKG_RWSTAT_NR; i++)
-           atomic64_add(blkg_rwstat_read_counter(rwstat, i),
-               &sum.aux_cnt[i]);
+           atomic64_set(&sum->aux_cnt[i],
+               blkg_rwstat_read_counter(rwstat, i));
    }
    rcu_read_unlock();
-
-   return sum;
 }
 EXPORT_SYMBOL_GPL(blkg_rwstat_recursive_sum);

@@ -953,14 +954,14 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)

        spin_lock_irq(&blkg->q->queue_lock);

-       rwstat = blkg_rwstat_recursive_sum(blkg, NULL,
-                   offsetof(struct blkcg_gq, stat_bytes));
+       blkg_rwstat_recursive_sum(blkg, NULL,
+               offsetof(struct blkcg_gq, stat_bytes), &rwstat);
        rbytes = atomic64_read(&rwstat.aux_cnt[BLKG_RWSTAT_READ]);
        wbytes = atomic64_read(&rwstat.aux_cnt[BLKG_RWSTAT_WRITE]);
        dbytes = atomic64_read(&rwstat.aux_cnt[BLKG_RWSTAT_DISCARD]);

-       rwstat = blkg_rwstat_recursive_sum(blkg, NULL,
-                   offsetof(struct blkcg_gq, stat_ios));
+       blkg_rwstat_recursive_sum(blkg, NULL,
+                   offsetof(struct blkcg_gq, stat_ios), &rwstat);
        rios = atomic64_read(&rwstat.aux_cnt[BLKG_RWSTAT_READ]);
        wios = atomic64_read(&rwstat.aux_cnt[BLKG_RWSTAT_WRITE]);
        dios = atomic64_read(&rwstat.aux_cnt[BLKG_RWSTAT_DISCARD]);
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h
index 06236f5..3ee8581 100644
--- a/include/linux/blk-cgroup.h
+++ b/include/linux/blk-cgroup.h
@@ -224,8 +224,8 @@ u64 blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd,

 u64 blkg_stat_recursive_sum(struct blkcg_gq *blkg,
                struct blkcg_policy *pol, int off);
-struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkcg_gq *blkg,
-                        struct blkcg_policy *pol, int off);
+void blkg_rwstat_recursive_sum(struct blkcg_gq *blkg, struct blkcg_policy *pol,
+       int off, struct blkg_rwstat *sum);

 struct blkg_conf_ctx {
    struct gendisk          *disk;
@@ -700,15 +700,14 @@ static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat,
  *
  * Read the current snapshot of @rwstat and return it in the aux counts.
  */
-static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat)
+static inline void blkg_rwstat_read(struct blkg_rwstat *rwstat,
+       struct blkg_rwstat *result)
 {
-   struct blkg_rwstat result;
    int i;

    for (i = 0; i < BLKG_RWSTAT_NR; i++)
-       atomic64_set(&result.aux_cnt[i],
+       atomic64_set(&result->aux_cnt[i],
                 percpu_counter_sum_positive(&rwstat->cpu_cnt[i]));
-   return result;
 }

 /**
@@ -721,8 +720,9 @@ static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat)
  */
 static inline uint64_t blkg_rwstat_total(struct blkg_rwstat *rwstat)
 {
-   struct blkg_rwstat tmp = blkg_rwstat_read(rwstat);
+   struct blkg_rwstat tmp = { };

+   blkg_rwstat_read(rwstat, &tmp);
    return atomic64_read(&tmp.aux_cnt[BLKG_RWSTAT_READ]) +
        atomic64_read(&tmp.aux_cnt[BLKG_RWSTAT_WRITE]);
 }

Leave a Reply

Your email address will not be published. Required fields are marked *