From: NeilBrown 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: Andy Adamson Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton --- 25-akpm/fs/nfsd/nfs4proc.c | 8 -------- 25-akpm/fs/nfsd/nfs4state.c | 27 ++++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 11 deletions(-) diff -puN fs/nfsd/nfs4proc.c~nfsd4-allow-some-reads-and-writes-during-the-grace-period fs/nfsd/nfs4proc.c --- 25/fs/nfsd/nfs4proc.c~nfsd4-allow-some-reads-and-writes-during-the-grace-period 2005-03-07 23:55:19.000000000 -0800 +++ 25-akpm/fs/nfsd/nfs4proc.c 2005-03-07 23:55:19.000000000 -0800 @@ -466,8 +466,6 @@ nfsd4_read(struct svc_rqst *rqstp, struc 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, st { 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, stru 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) diff -puN fs/nfsd/nfs4state.c~nfsd4-allow-some-reads-and-writes-during-the-grace-period fs/nfsd/nfs4state.c --- 25/fs/nfsd/nfs4state.c~nfsd4-allow-some-reads-and-writes-during-the-grace-period 2005-03-07 23:55:19.000000000 -0800 +++ 25-akpm/fs/nfsd/nfs4state.c 2005-03-07 23:55:19.000000000 -0800 @@ -2015,7 +2015,11 @@ check_special_stateids(svc_fh *current_f 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) */ @@ -2024,6 +2028,17 @@ check_special_stateids(svc_fh *current_f } /* + * 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 */ int @@ -2032,12 +2047,16 @@ nfs4_preprocess_stateid_op(struct svc_fh 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 /* 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)) _