btrfs: sysfs: export commit stats
authorIoannis Angelakopoulos <iangelak@fb.com>
Tue, 14 Jun 2022 22:22:34 +0000 (15:22 -0700)
committerDavid Sterba <dsterba@suse.com>
Mon, 25 Jul 2022 15:45:37 +0000 (17:45 +0200)
Export commit stats in file

  /sys/fs/btrfs/UUID/commit_stats

with example output like:

  commits 123
  last_commit_ms 11
  max_commit_ms 150
  total_commit_ms 2000

The values are in one file so reading them at a single time will give a
more consistent view. The stats are internally tracked in nanoseconds so
the cumulative values should not suffer from rounding errors.

Writing 0 to the file 'commit_stats' will reset max_commit_ms.
Initial values are set at first mount of the filesystem.

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Ioannis Angelakopoulos <iangelak@fb.com>
[ update changelog ]
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/sysfs.c

index db3736de14a5f3d663a6d5104d8a226e3a2d25ff..c6307b111c2c758a266d340eec15d52408c5ba33 100644 (file)
@@ -991,6 +991,48 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj,
 
 BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show);
 
+static ssize_t btrfs_commit_stats_show(struct kobject *kobj,
+                                      struct kobj_attribute *a, char *buf)
+{
+       struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+
+       return sysfs_emit(buf,
+               "commits %llu\n"
+               "last_commit_ms %llu\n"
+               "max_commit_ms %llu\n"
+               "total_commit_ms %llu\n",
+               fs_info->commit_stats.commit_count,
+               div_u64(fs_info->commit_stats.last_commit_dur, NSEC_PER_MSEC),
+               div_u64(fs_info->commit_stats.max_commit_dur, NSEC_PER_MSEC),
+               div_u64(fs_info->commit_stats.total_commit_dur, NSEC_PER_MSEC));
+}
+
+static ssize_t btrfs_commit_stats_store(struct kobject *kobj,
+                                       struct kobj_attribute *a,
+                                       const char *buf, size_t len)
+{
+       struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+       unsigned long val;
+       int ret;
+
+       if (!fs_info)
+               return -EPERM;
+
+       if (!capable(CAP_SYS_RESOURCE))
+               return -EPERM;
+
+       ret = kstrtoul(buf, 10, &val);
+       if (ret)
+               return ret;
+       if (val)
+               return -EINVAL;
+
+       WRITE_ONCE(fs_info->commit_stats.max_commit_dur, 0);
+
+       return len;
+}
+BTRFS_ATTR_RW(, commit_stats, btrfs_commit_stats_show, btrfs_commit_stats_store);
+
 static ssize_t btrfs_clone_alignment_show(struct kobject *kobj,
                                struct kobj_attribute *a, char *buf)
 {
@@ -1230,6 +1272,7 @@ static const struct attribute *btrfs_attrs[] = {
        BTRFS_ATTR_PTR(, generation),
        BTRFS_ATTR_PTR(, read_policy),
        BTRFS_ATTR_PTR(, bg_reclaim_threshold),
+       BTRFS_ATTR_PTR(, commit_stats),
        NULL,
 };
 
@@ -2236,4 +2279,3 @@ void __cold btrfs_exit_sysfs(void)
 #endif
        kset_unregister(btrfs_kset);
 }
-