diff options
author | Neil Brown <neilb@cse.unsw.edu.au> | 2005-01-04 05:51:59 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-01-04 05:51:59 -0800 |
commit | 268b934510490eb490e88d7b0fa1a7b6c4d1ff04 (patch) | |
tree | fb85aae47f3a8ea52c8f64c63e835b3c2bed00e5 /fs | |
parent | 55d066111e4917f5b26604335fb79aaec6cdbc56 (diff) | |
download | history-268b934510490eb490e88d7b0fa1a7b6c4d1ff04.tar.gz |
[PATCH] knfsd: add checking of delegation stateids to nfs4_preprocess_stateid_op.
Call release_delegation on delegreturn (DELEG_RET).
Signed-off-by: Andy Adamson <andros@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/nfs4state.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 091359052cdf3e..39f98a4834fb14 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1943,7 +1943,7 @@ access_permit_write(unsigned long access_bmap) } static -int check_openmode(struct nfs4_stateid *stp, int flags) +int nfs4_check_openmode(struct nfs4_stateid *stp, int flags) { int status = nfserr_openmode; @@ -1976,7 +1976,9 @@ out: int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags) { - struct nfs4_stateid *stp; + struct nfs4_stateid *stp = NULL; + struct nfs4_delegation *dp = NULL; + stateid_t *stidp; int status; dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n", @@ -1990,35 +1992,47 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl /* BAD STATEID */ status = nfserr_bad_stateid; - if (!(stp = find_stateid(stateid, flags))) { - dprintk("NFSD: preprocess_stateid_op: no open stateid!\n"); - goto out; - } - if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { - dprintk("NFSD: preprocess_stateid_op: fh-stateid mismatch!\n"); - stp->st_vfs_set = 0; - goto out; - } - if (!stp->st_stateowner->so_confirmed) { - dprintk("preprocess_stateid_op: lockowner not confirmed yet!\n"); - goto out; + if (!stateid->si_fileid) { /* delegation stateid */ + struct inode *ino = current_fh->fh_dentry->d_inode; + + if(!(dp = find_delegation_stateid(ino, stateid))) { + dprintk("NFSD: delegation stateid not found\n"); + goto out; + } + stidp = &dp->dl_stateid; + } else { /* open or lock stateid */ + if (!(stp = find_stateid(stateid, flags))) { + dprintk("NFSD: open or lock stateid not found\n"); + goto out; + } + if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) + goto out; + if (!stp->st_stateowner->so_confirmed) + goto out; + stidp = &stp->st_stateid; } - if (stateid->si_generation > stp->st_stateid.si_generation) { - dprintk("preprocess_stateid_op: future stateid?!\n"); + if (stateid->si_generation > stidp->si_generation) goto out; - } /* OLD STATEID */ status = nfserr_old_stateid; - if (stateid->si_generation < stp->st_stateid.si_generation) { - dprintk("preprocess_stateid_op: old stateid!\n"); + if (stateid->si_generation < stidp->si_generation) goto out; + if (stp) { + if ((status = nfs4_check_openmode(stp,flags))) + goto out; + renew_client(stp->st_stateowner->so_client); + } else if (dp) { + if ((status = nfs4_check_delegmode(dp, flags))) + goto out; + renew_client(dp->dl_client); + if (flags & DELEG_RET) { + atomic_set(&dp->dl_state,NFS4_RECALL_COMPLETE); + spin_lock(&recall_lock); + release_delegation(dp); + spin_unlock(&recall_lock); + } } - renew_client(stp->st_stateowner->so_client); - - if((status = check_openmode(stp, flags))) - goto out; - status = nfs_ok; out: return status; |