Skip to content

Commit 6b63a94

Browse files
author
Kent Overstreet
committed
bcachefs: Add missing wakeup to bch2_inode_hash_remove()
This fixes two different bugs: - Looser locking with the rhashtable means we need to recheck if the inode is still hashed after prepare_to_wait(), and add a corresponding wakeup after removing from the hash table. - da18ecb ("fs: add i_state helpers") changed the bit waitqueues used for inodes, and bcachefs wasn't updated and thus broke; this updates bcachefs to the new helper. Fixes: 112d21f ("bcachefs: switch to rhashtable for vfs inodes hash") Signed-off-by: Kent Overstreet <[email protected]>
1 parent d287866 commit 6b63a94

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

fs/bcachefs/fs.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -174,20 +174,24 @@ static const struct rhashtable_params bch2_vfs_inodes_params = {
174174
.automatic_shrinking = true,
175175
};
176176

177-
static void __wait_on_freeing_inode(struct inode *inode)
177+
struct bch_inode_info *__bch2_inode_hash_find(struct bch_fs *c, subvol_inum inum)
178178
{
179-
wait_queue_head_t *wq;
180-
DEFINE_WAIT_BIT(wait, &inode->i_state, __I_NEW);
181-
wq = bit_waitqueue(&inode->i_state, __I_NEW);
182-
prepare_to_wait(wq, &wait.wq_entry, TASK_UNINTERRUPTIBLE);
183-
spin_unlock(&inode->i_lock);
184-
schedule();
185-
finish_wait(wq, &wait.wq_entry);
179+
return rhashtable_lookup_fast(&c->vfs_inodes_table, &inum, bch2_vfs_inodes_params);
186180
}
187181

188-
struct bch_inode_info *__bch2_inode_hash_find(struct bch_fs *c, subvol_inum inum)
182+
static void __wait_on_freeing_inode(struct bch_fs *c,
183+
struct bch_inode_info *inode,
184+
subvol_inum inum)
189185
{
190-
return rhashtable_lookup_fast(&c->vfs_inodes_table, &inum, bch2_vfs_inodes_params);
186+
wait_queue_head_t *wq;
187+
DEFINE_WAIT_BIT(wait, &inode->v.i_state, __I_NEW);
188+
wq = inode_bit_waitqueue(&wait, &inode->v, __I_NEW);
189+
prepare_to_wait(wq, &wait.wq_entry, TASK_UNINTERRUPTIBLE);
190+
spin_unlock(&inode->v.i_lock);
191+
192+
if (__bch2_inode_hash_find(c, inum) == inode)
193+
schedule_timeout(HZ * 10);
194+
finish_wait(wq, &wait.wq_entry);
191195
}
192196

193197
static struct bch_inode_info *bch2_inode_hash_find(struct bch_fs *c, struct btree_trans *trans,
@@ -204,10 +208,10 @@ static struct bch_inode_info *bch2_inode_hash_find(struct bch_fs *c, struct btre
204208
}
205209
if ((inode->v.i_state & (I_FREEING|I_WILL_FREE))) {
206210
if (!trans) {
207-
__wait_on_freeing_inode(&inode->v);
211+
__wait_on_freeing_inode(c, inode, inum);
208212
} else {
209213
bch2_trans_unlock(trans);
210-
__wait_on_freeing_inode(&inode->v);
214+
__wait_on_freeing_inode(c, inode, inum);
211215
int ret = bch2_trans_relock(trans);
212216
if (ret)
213217
return ERR_PTR(ret);
@@ -232,6 +236,11 @@ static void bch2_inode_hash_remove(struct bch_fs *c, struct bch_inode_info *inod
232236
&inode->hash, bch2_vfs_inodes_params);
233237
BUG_ON(ret);
234238
inode->v.i_hash.pprev = NULL;
239+
/*
240+
* This pairs with the bch2_inode_hash_find() ->
241+
* __wait_on_freeing_inode() path
242+
*/
243+
inode_wake_up_bit(&inode->v, __I_NEW);
235244
}
236245
}
237246

0 commit comments

Comments
 (0)