Commit 268b9345 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] knfsd: add checking of delegation stateids to nfs4_preprocess_stateid_op.

Call release_delegation on delegreturn (DELEG_RET).
Signed-off-by: default avatarAndy Adamson <andros@citi.umich.edu>
Signed-off-by: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 55d06611
...@@ -1943,7 +1943,7 @@ access_permit_write(unsigned long access_bmap) ...@@ -1943,7 +1943,7 @@ access_permit_write(unsigned long access_bmap)
} }
static static
int check_openmode(struct nfs4_stateid *stp, int flags) int nfs4_check_openmode(struct nfs4_stateid *stp, int flags)
{ {
int status = nfserr_openmode; int status = nfserr_openmode;
...@@ -1976,7 +1976,9 @@ nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) ...@@ -1976,7 +1976,9 @@ nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
int int
nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags) 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; int status;
dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n", 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 ...@@ -1990,35 +1992,47 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
/* BAD STATEID */ /* BAD STATEID */
status = nfserr_bad_stateid; status = nfserr_bad_stateid;
if (!(stp = find_stateid(stateid, flags))) { if (!stateid->si_fileid) { /* delegation stateid */
dprintk("NFSD: preprocess_stateid_op: no open stateid!\n"); struct inode *ino = current_fh->fh_dentry->d_inode;
goto out;
} if(!(dp = find_delegation_stateid(ino, stateid))) {
if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { dprintk("NFSD: delegation stateid not found\n");
dprintk("NFSD: preprocess_stateid_op: fh-stateid mismatch!\n"); goto out;
stp->st_vfs_set = 0; }
goto out; stidp = &dp->dl_stateid;
} } else { /* open or lock stateid */
if (!stp->st_stateowner->so_confirmed) { if (!(stp = find_stateid(stateid, flags))) {
dprintk("preprocess_stateid_op: lockowner not confirmed yet!\n"); dprintk("NFSD: open or lock stateid not found\n");
goto out; 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) { if (stateid->si_generation > stidp->si_generation)
dprintk("preprocess_stateid_op: future stateid?!\n");
goto out; goto out;
}
/* OLD STATEID */ /* OLD STATEID */
status = nfserr_old_stateid; status = nfserr_old_stateid;
if (stateid->si_generation < stp->st_stateid.si_generation) { if (stateid->si_generation < stidp->si_generation)
dprintk("preprocess_stateid_op: old stateid!\n");
goto out; 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; status = nfs_ok;
out: out:
return status; return status;
......
...@@ -271,6 +271,7 @@ struct nfs4_stateid { ...@@ -271,6 +271,7 @@ struct nfs4_stateid {
#define RD_STATE 0x00000010 #define RD_STATE 0x00000010
#define WR_STATE 0x00000020 #define WR_STATE 0x00000020
#define CLOSE_STATE 0x00000040 #define CLOSE_STATE 0x00000040
#define DELEG_RET 0x00000080
#define seqid_mutating_err(err) \ #define seqid_mutating_err(err) \
(((err) != nfserr_stale_clientid) && \ (((err) != nfserr_stale_clientid) && \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment