summaryrefslogtreecommitdiff
path: root/fs/bcachefs/subvolume.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/subvolume.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/subvolume.c')
-rw-r--r--fs/bcachefs/subvolume.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/fs/bcachefs/subvolume.c b/fs/bcachefs/subvolume.c
index d090a74bd052..3f5893f317d1 100644
--- a/fs/bcachefs/subvolume.c
+++ b/fs/bcachefs/subvolume.c
@@ -706,16 +706,14 @@ static void bch2_delete_dead_snapshots_work(struct work_struct *work)
struct bch_fs *c = container_of(work, struct bch_fs, snapshot_delete_work);
bch2_delete_dead_snapshots(c);
- percpu_ref_put(&c->writes);
+ bch2_write_ref_put(c, BCH_WRITE_REF_delete_dead_snapshots);
}
void bch2_delete_dead_snapshots_async(struct bch_fs *c)
{
- if (!percpu_ref_tryget_live(&c->writes))
- return;
-
- if (!queue_work(system_long_wq, &c->snapshot_delete_work))
- percpu_ref_put(&c->writes);
+ if (bch2_write_ref_tryget(c, BCH_WRITE_REF_delete_dead_snapshots) &&
+ !queue_work(system_long_wq, &c->snapshot_delete_work))
+ bch2_write_ref_put(c, BCH_WRITE_REF_delete_dead_snapshots);
}
static int bch2_delete_dead_snapshots_hook(struct btree_trans *trans,
@@ -900,7 +898,7 @@ void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work)
darray_exit(&s);
}
- percpu_ref_put(&c->writes);
+ bch2_write_ref_put(c, BCH_WRITE_REF_snapshot_delete_pagecache);
}
struct subvolume_unlink_hook {
@@ -923,11 +921,11 @@ int bch2_subvolume_wait_for_pagecache_and_delete_hook(struct btree_trans *trans,
if (ret)
return ret;
- if (unlikely(!percpu_ref_tryget_live(&c->writes)))
+ if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_snapshot_delete_pagecache))
return -EROFS;
if (!queue_work(system_long_wq, &c->snapshot_wait_for_pagecache_and_delete_work))
- percpu_ref_put(&c->writes);
+ bch2_write_ref_put(c, BCH_WRITE_REF_snapshot_delete_pagecache);
return 0;
}