Search the inode cache under "RCU conditions" when trying to find a vnode to break the callback on. We don't want to be taking the icache lock if we can avoid it. Signed-off-by: David Howells <dhowells@xxxxxxxxxx> cc: linux-afs@xxxxxxxxxxxxxxxxxxx --- fs/afs/callback.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/afs/callback.c b/fs/afs/callback.c index 128f2dbe256a..3d0280d4fbf0 100644 --- a/fs/afs/callback.c +++ b/fs/afs/callback.c @@ -251,6 +251,7 @@ static void afs_break_one_callback(struct afs_server *server, struct afs_vnode *vnode; struct inode *inode; + rcu_read_lock(); read_lock(&server->cb_break_lock); hlist_for_each_entry(vi, &server->cb_volumes, srv_link) { if (vi->vid < fid->vid) @@ -284,18 +285,23 @@ static void afs_break_one_callback(struct afs_server *server, } else { data.volume = NULL; data.fid = *fid; - inode = ilookup5_nowait(cbi->sb, fid->vnode, - afs_iget5_test, &data); + + /* See if we can find a matching inode - even an I_NEW + * inode needs to be marked as it can have its callback + * broken before we finish setting up the local inode. + */ + inode = find_inode_rcu(cbi->sb, fid->vnode, + afs_iget5_test, &data); if (inode) { vnode = AFS_FS_I(inode); afs_break_callback(vnode); - iput(inode); } } } out: read_unlock(&server->cb_break_lock); + rcu_read_unlock(); } /*