aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-04-29 10:35:36 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-04-29 11:11:39 -0400
commitee3ae84ef40154c734dc2cbca5cf4b2f54c6c7c7 (patch)
tree7369401ff7712c5c0c4a7ab8378dc41986c5cba7
parentb0212b84fb19cf89305ab96c73abdf3a76d05ef8 (diff)
NFSv4: Servers should only check SETATTR stateid open mode on size change
The NFSv4 and NFSv4.1 specs are both clear that the server should only check stateid open mode if a SETATTR specifies the size attribute. If the open mode is not one that allows writing, then it returns NFS4ERR_OPENMODE. In the case where the SETATTR is not changing the size, the client will still pass it the delegation stateid to ensure that the server does not recall that delegation. In that case, the server should _ignore_ the delegation open mode, and simply apply standard permission checks. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs4proc.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3bc847ce4838..982b4527551d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2142,20 +2142,25 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
2142 .rpc_cred = cred, 2142 .rpc_cred = cred,
2143 }; 2143 };
2144 unsigned long timestamp = jiffies; 2144 unsigned long timestamp = jiffies;
2145 fmode_t fmode;
2146 bool truncate;
2145 int status; 2147 int status;
2146 2148
2147 nfs_fattr_init(fattr); 2149 nfs_fattr_init(fattr);
2148 2150
2149 if (state != NULL && nfs4_valid_open_stateid(state)) { 2151 /* Servers should only apply open mode checks for file size changes */
2152 truncate = (sattr->ia_valid & ATTR_SIZE) ? true : false;
2153 fmode = truncate ? FMODE_WRITE : FMODE_READ;
2154
2155 if (nfs4_copy_delegation_stateid(&arg.stateid, inode, fmode)) {
2156 /* Use that stateid */
2157 } else if (truncate && state != NULL && nfs4_valid_open_stateid(state)) {
2150 struct nfs_lockowner lockowner = { 2158 struct nfs_lockowner lockowner = {
2151 .l_owner = current->files, 2159 .l_owner = current->files,
2152 .l_pid = current->tgid, 2160 .l_pid = current->tgid,
2153 }; 2161 };
2154 nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE, 2162 nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE,
2155 &lockowner); 2163 &lockowner);
2156 } else if (nfs4_copy_delegation_stateid(&arg.stateid, inode,
2157 FMODE_WRITE)) {
2158 /* Use that stateid */
2159 } else 2164 } else
2160 nfs4_stateid_copy(&arg.stateid, &zero_stateid); 2165 nfs4_stateid_copy(&arg.stateid, &zero_stateid);
2161 2166