summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-11-22 15:33:29 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2024-11-22 16:37:07 -0500
commit7f0ae9ab2f5f2ea12951f1d5ff04ff35bbee8d3f (patch)
treede26d1aa97527aec1d721572772c5b0d84ba52c4
parentb2cc9c6fcee366ba4988ba0eec63bb2932cccadd (diff)
bcachefs: Debug counters for bch2_inode_hash_find()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/fs.c64
1 files changed, 50 insertions, 14 deletions
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 50d323fca001..a5b92a34a3b6 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -284,6 +284,15 @@ err:
return ret;
}
+struct inode_hash_find_counters {
+ size_t calls;
+ size_t finds;
+ size_t founds;
+ size_t unhashed;
+ size_t i_freeing;
+ size_t i_will_free;
+};
+
static struct bch_inode_info *__bch2_inode_hash_find(struct bch_fs *c, subvol_inum inum)
{
return rhashtable_lookup_fast(&c->vfs_inodes_table, &inum, bch2_vfs_inodes_params);
@@ -306,18 +315,39 @@ static void __wait_on_freeing_inode(struct bch_fs *c,
}
static struct bch_inode_info *bch2_inode_hash_find(struct bch_fs *c, struct btree_trans *trans,
- subvol_inum inum)
+ subvol_inum inum,
+ struct inode_hash_find_counters *s)
{
struct bch_inode_info *inode;
+
+ s->calls++;
repeat:
+ s->finds++;
+ if (s->finds > 10)
+ pr_info_ratelimited("%ps calls %zu finds %zu founds %zu unhashed %zu i_freeing %zu i_will_free %zu",
+ (void *) _RET_IP_,
+ s->calls,
+ s->finds,
+ s->founds,
+ s->unhashed,
+ s->i_freeing,
+ s->i_will_free);
+
inode = __bch2_inode_hash_find(c, inum);
if (inode) {
+ s->founds++;
+
spin_lock(&inode->v.i_lock);
if (!test_bit(EI_INODE_HASHED, &inode->ei_flags)) {
spin_unlock(&inode->v.i_lock);
+ s->unhashed++;
return NULL;
}
+
if ((inode->v.i_state & (I_FREEING|I_WILL_FREE))) {
+ s->i_freeing += (inode->v.i_state & I_FREEING) != 0;
+ s->i_will_free += (inode->v.i_state & I_WILL_FREE) != 0;
+
if (!trans) {
__wait_on_freeing_inode(c, inode, inum);
} else {
@@ -360,14 +390,18 @@ static struct bch_inode_info *bch2_inode_hash_insert(struct bch_fs *c,
struct bch_inode_info *inode)
{
struct bch_inode_info *old = inode;
+ struct inode_hash_find_counters s = {};
set_bit(EI_INODE_HASHED, &inode->ei_flags);
+ smp_mb__after_atomic();
retry:
- if (unlikely(rhashtable_lookup_insert_key(&c->vfs_inodes_table,
+ int ret = rhashtable_lookup_insert_key(&c->vfs_inodes_table,
&inode->ei_inum,
&inode->hash,
- bch2_vfs_inodes_params))) {
- old = bch2_inode_hash_find(c, trans, inode->ei_inum);
+ bch2_vfs_inodes_params);
+ if (unlikely(ret)) {
+ pr_info("%s", bch2_err_str(ret));
+ old = bch2_inode_hash_find(c, trans, inode->ei_inum, &s);
if (!old)
goto retry;
@@ -387,16 +421,16 @@ retry:
set_nlink(&inode->v, 1);
discard_new_inode(&inode->v);
return old;
- } else {
- inode_fake_hash(&inode->v);
+ }
- inode_sb_list_add(&inode->v);
+ inode_fake_hash(&inode->v);
- mutex_lock(&c->vfs_inodes_lock);
- list_add(&inode->ei_vfs_inode_list, &c->vfs_inodes_list);
- mutex_unlock(&c->vfs_inodes_lock);
- return inode;
- }
+ inode_sb_list_add(&inode->v);
+
+ mutex_lock(&c->vfs_inodes_lock);
+ list_add(&inode->ei_vfs_inode_list, &c->vfs_inodes_list);
+ mutex_unlock(&c->vfs_inodes_lock);
+ return inode;
}
#define memalloc_flags_do(_flags, _do) \
@@ -472,7 +506,8 @@ static struct bch_inode_info *bch2_inode_hash_init_insert(struct btree_trans *tr
struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum)
{
- struct bch_inode_info *inode = bch2_inode_hash_find(c, NULL, inum);
+ struct inode_hash_find_counters s = {};
+ struct bch_inode_info *inode = bch2_inode_hash_find(c, NULL, inum, &s);
if (inode)
return &inode->v;
@@ -611,6 +646,7 @@ static struct bch_inode_info *bch2_lookup_trans(struct btree_trans *trans,
const struct qstr *name)
{
struct bch_fs *c = trans->c;
+ struct inode_hash_find_counters s = {};
struct btree_iter dirent_iter = {};
subvol_inum inum = {};
struct printbuf buf = PRINTBUF;
@@ -627,7 +663,7 @@ static struct bch_inode_info *bch2_lookup_trans(struct btree_trans *trans,
if (ret)
goto err;
- struct bch_inode_info *inode = bch2_inode_hash_find(c, trans, inum);
+ struct bch_inode_info *inode = bch2_inode_hash_find(c, trans, inum, &s);
if (inode)
goto out;