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 <[email protected]>
cc: [email protected]
---

 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();
 }
 
 /*

Reply via email to