summaryrefslogtreecommitdiff
path: root/fs/bcachefs/sysfs.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-02-09 12:21:45 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:50 -0400
commitd94189ad568f6cbd80d372cf7aa6e4898b6c5c17 (patch)
tree4e23dbd00746c19092bcdb8604903cab7049a83b /fs/bcachefs/sysfs.c
parentdd81a060eb0680e09d133b81db54b90442c32b5e (diff)
bcachefs: Debug mode for c->writes references
This adds a debug mode where we split up the c->writes refcount into distinct refcounts for every codepath that takes a reference, and adds sysfs code to print the value of each ref. This will make it easier to debug shutdown hangs due to refcount leaks. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/sysfs.c')
-rw-r--r--fs/bcachefs/sysfs.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c
index 7ccdf3197d51..20484f67c3bc 100644
--- a/fs/bcachefs/sysfs.c
+++ b/fs/bcachefs/sysfs.c
@@ -195,6 +195,29 @@ read_attribute(stripes_heap);
read_attribute(open_buckets);
read_attribute(write_points);
+#ifdef BCH_WRITE_REF_DEBUG
+read_attribute(write_refs);
+
+const char * const bch2_write_refs[] = {
+#define x(n) #n,
+ BCH_WRITE_REFS()
+#undef x
+ NULL
+};
+
+static void bch2_write_refs_to_text(struct printbuf *out, struct bch_fs *c)
+{
+ bch2_printbuf_tabstop_push(out, 24);
+
+ for (unsigned i = 0; i < ARRAY_SIZE(c->writes); i++) {
+ prt_str(out, bch2_write_refs[i]);
+ prt_tab(out);
+ prt_printf(out, "%li", atomic_long_read(&c->writes[i]));
+ prt_newline(out);
+ }
+}
+#endif
+
read_attribute(internal_uuid);
read_attribute(has_data);
@@ -448,6 +471,11 @@ SHOW(bch2_fs)
if (attr == &sysfs_data_jobs)
data_progress_to_text(out, c);
+#ifdef BCH_WRITE_REF_DEBUG
+ if (attr == &sysfs_write_refs)
+ bch2_write_refs_to_text(out, c);
+#endif
+
return 0;
}
@@ -631,6 +659,9 @@ struct attribute *bch2_fs_internal_files[] = {
&sysfs_stripes_heap,
&sysfs_open_buckets,
&sysfs_write_points,
+#ifdef BCH_WRITE_REF_DEBUG
+ &sysfs_write_refs,
+#endif
&sysfs_io_timers_read,
&sysfs_io_timers_write,
@@ -682,7 +713,7 @@ STORE(bch2_fs_opts_dir)
* We don't need to take c->writes for correctness, but it eliminates an
* unsightly error message in the dmesg log when we're RO:
*/
- if (unlikely(!percpu_ref_tryget_live(&c->writes)))
+ if (unlikely(!bch2_write_ref_tryget(c, BCH_WRITE_REF_sysfs)))
return -EROFS;
tmp = kstrdup(buf, GFP_KERNEL);
@@ -712,7 +743,7 @@ STORE(bch2_fs_opts_dir)
ret = size;
err:
- percpu_ref_put(&c->writes);
+ bch2_write_ref_put(c, BCH_WRITE_REF_sysfs);
return ret;
}
SYSFS_OPS(bch2_fs_opts_dir);