From: NeilBrown An OPEN upgrade on a file already open for WRITE will not upgrade the OPEN, but can still truncate the file. 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 | 29 +++++++++++++++-------------- 1 files changed, 15 insertions(+), 14 deletions(-) diff -puN fs/nfsd/nfs4state.c~nfsd4-fix-failure-to-truncate-on-some-opens fs/nfsd/nfs4state.c --- 25/fs/nfsd/nfs4state.c~nfsd4-fix-failure-to-truncate-on-some-opens 2005-03-21 22:49:58.000000000 -0800 +++ 25-akpm/fs/nfsd/nfs4state.c 2005-03-21 22:49:58.000000000 -0800 @@ -1602,21 +1602,22 @@ nfs4_upgrade_open(struct svc_rqst *rqstp share_access = ~share_access; share_access &= open->op_share_access; - /* update the struct file */ - if (share_access & NFS4_SHARE_ACCESS_WRITE) { - status = get_write_access(inode); - if (status) - return nfserrno(status); - status = nfsd4_truncate(rqstp, cur_fh, open); - if (status) { - put_write_access(inode); - return status; - } - /* remember the open */ - filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ; - set_bit(open->op_share_access, &stp->st_access_bmap); - set_bit(open->op_share_deny, &stp->st_deny_bmap); + if (!(share_access & NFS4_SHARE_ACCESS_WRITE)) + return nfsd4_truncate(rqstp, cur_fh, open); + + status = get_write_access(inode); + if (status) + return nfserrno(status); + status = nfsd4_truncate(rqstp, cur_fh, open); + if (status) { + put_write_access(inode); + return status; } + /* remember the open */ + filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ; + set_bit(open->op_share_access, &stp->st_access_bmap); + set_bit(open->op_share_deny, &stp->st_deny_bmap); + return nfs_ok; } _