From 3fbd67ad61f6d5a09ea717b56c50bc5c3d8042a8 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 26 Jan 2008 01:06:40 -0500 Subject: NFSv4: Iterate through all nfs_clients when the server recalls a delegation The same delegation may have been handed out to more than one nfs_client. Ensure that if a recall occurs, we return all instances. Signed-off-by: Trond Myklebust --- fs/nfs/callback_proc.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'fs/nfs/callback_proc.c') diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index e89a9007c91..15f7785048d 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -75,23 +75,28 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) dprintk("NFS: RECALL callback request from %s\n", rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); - inode = nfs_delegation_find_inode(clp, &args->fh); - if (inode == NULL) - goto out_putclient; - /* Set up a helper thread to actually return the delegation */ - switch(nfs_async_inode_return_delegation(inode, &args->stateid)) { - case 0: - res = 0; - break; - case -ENOENT: - res = htonl(NFS4ERR_BAD_STATEID); - break; - default: - res = htonl(NFS4ERR_RESOURCE); - } - iput(inode); -out_putclient: - nfs_put_client(clp); + do { + struct nfs_client *prev = clp; + + inode = nfs_delegation_find_inode(clp, &args->fh); + if (inode != NULL) { + /* Set up a helper thread to actually return the delegation */ + switch(nfs_async_inode_return_delegation(inode, &args->stateid)) { + case 0: + res = 0; + break; + case -ENOENT: + if (res != 0) + res = htonl(NFS4ERR_BAD_STATEID); + break; + default: + res = htonl(NFS4ERR_RESOURCE); + } + iput(inode); + } + clp = nfs_find_client_next(prev); + nfs_put_client(prev); + } while (clp != NULL); out: dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res)); return res; -- cgit v1.2.3