Commit 7d4ef76c authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] nfsd4: allow some reads and writes during the grace period

Allow READ and WRITE during the grace period on OPEN or LOCK state that has
been reclaimed, for files for which mandatory locking is not in force.  (Reads
and writes to files with mandatory locking must be delayed until we're sure
all the other clients have had a chance to recover locks.)
Signed-off-by: default avatarAndy Adamson <andros@citi.umich.edu>
Signed-off-by: default avatarJ. Bruce Fields <bfields@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 23b08769
......@@ -466,8 +466,6 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read
int status;
/* no need to check permission - this will be done in nfsd_read() */
if (nfs4_in_grace())
return nfserr_grace;
if (read->rd_offset >= OFFSET_MAX)
return nfserr_inval;
......@@ -568,9 +566,6 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
{
int status = nfs_ok;
if (nfs4_in_grace())
return nfserr_grace;
if (!current_fh->fh_dentry)
return nfserr_nofilehandle;
......@@ -606,9 +601,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
u32 *p;
int status = nfs_ok;
if (nfs4_in_grace())
return nfserr_grace;
/* no need to check permission - this will be done in nfsd_write() */
if (write->wr_offset >= OFFSET_MAX)
......
......@@ -2015,7 +2015,11 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
return nfserr_bad_stateid;
else if (ONE_STATEID(stateid) && (flags & RD_STATE))
return nfs_ok;
else if (flags & WR_STATE)
else if (nfs4_in_grace()) {
/* Answer in remaining cases depends on existance of
* conflicting state; so we must wait out the grace period. */
return nfserr_grace;
} else if (flags & WR_STATE)
return nfs4_share_conflict(current_fh,
NFS4_SHARE_DENY_WRITE);
else /* (flags & RD_STATE) && ZERO_STATEID(stateid) */
......@@ -2023,6 +2027,17 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
NFS4_SHARE_DENY_READ);
}
/*
* Allow READ/WRITE during grace period on recovered state only for files
* that are not able to provide mandatory locking.
*/
static inline int
io_during_grace_disallowed(struct inode *inode, int flags)
{
return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))
&& MANDATORY_LOCK(inode);
}
/*
* Checks for stateid operations
*/
......@@ -2032,12 +2047,16 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
struct nfs4_stateid *stp = NULL;
struct nfs4_delegation *dp = NULL;
stateid_t *stidp;
struct inode *ino = current_fh->fh_dentry->d_inode;
int status;
dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n",
stateid->si_boot, stateid->si_stateownerid,
stateid->si_fileid, stateid->si_generation);
if (io_during_grace_disallowed(ino, flags))
return nfserr_grace;
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
return check_special_stateids(current_fh, stateid, flags);
......@@ -2049,16 +2068,18 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
/* BAD STATEID */
status = nfserr_bad_stateid;
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");
if (nfs4_in_grace())
status = nfserr_grace;
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");
if (nfs4_in_grace())
status = nfserr_grace;
goto out;
}
if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))
......
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