From: NeilBrown Don't hand out a delegation to a client that already has one. Minor simplification and reformatting. Signed-off-by: Andy Adamson Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton --- 25-akpm/fs/nfsd/nfs4state.c | 31 +++++++++---------------------- 1 files changed, 9 insertions(+), 22 deletions(-) diff -puN fs/nfsd/nfs4state.c~nfsd4-miscellaneous-delegation-fixes fs/nfsd/nfs4state.c --- 25/fs/nfsd/nfs4state.c~nfsd4-miscellaneous-delegation-fixes 2005-03-07 23:55:31.000000000 -0800 +++ 25-akpm/fs/nfsd/nfs4state.c 2005-03-07 23:55:31.000000000 -0800 @@ -1514,22 +1514,6 @@ out: } static int -nfs4_deleg_conflict(u32 share, u32 dtype) -{ - return (((share & NFS4_SHARE_ACCESS_WRITE) && - dtype == NFS4_OPEN_DELEGATE_READ) || - ((share & NFS4_SHARE_ACCESS_READ) && - dtype == NFS4_OPEN_DELEGATE_WRITE)); -} - -/* - * nfs4_check_deleg_recall() - * - * Test any delegation that is currently within an incompleted recalled - * state, and return NFSERR_DELAY for conflicting open share. - * flag is set to DONT_DELEGATE for shares that match the deleg type. - */ -static int nfs4_check_deleg_recall(struct nfs4_file *fp, struct nfsd4_open *op, int *flag) { struct nfs4_delegation *dp; @@ -1538,13 +1522,16 @@ nfs4_check_deleg_recall(struct nfs4_file list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) { dprintk("NFSD: found delegation %p with dl_state %d\n", dp, atomic_read(&dp->dl_state)); - if (atomic_read(&dp->dl_state) == NFS4_RECALL_IN_PROGRESS) { - if(nfs4_deleg_conflict(op->op_share_access, dp->dl_type)) - status = nfserr_jukebox; - else - *flag = NFS4_OPEN_DELEGATE_NONE; + if (op->op_share_access & NFS4_SHARE_ACCESS_WRITE + || op->op_stateowner->so_client == dp->dl_client + || atomic_read(&dp->dl_state) != NFS4_NO_RECALL) { + *flag = NFS4_OPEN_DELEGATE_NONE; + goto out; } } +out: + dprintk("NFSD: nfs4_check_deleg_recall returns %d with flag %d\n", + status, *flag); return status; } @@ -1718,7 +1705,7 @@ nfsd4_process_open2(struct svc_rqst *rqs struct inode *ino = current_fh->fh_dentry->d_inode; unsigned int fi_hashval; struct nfs4_stateid *stp = NULL; - int status, delegflag = 0; + int status, delegflag = -1; status = nfserr_inval; if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) _