aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c55
1 files changed, 19 insertions, 36 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 91e7fe867d58..af80b5981486 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -756,11 +756,10 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
756 756
757 fattr->valid = 0; 757 fattr->valid = 0;
758 758
759 if (state != NULL) 759 if (state != NULL) {
760 msg.rpc_cred = state->owner->so_cred; 760 msg.rpc_cred = state->owner->so_cred;
761 if (sattr->ia_valid & ATTR_SIZE) 761 nfs4_copy_stateid(&arg.stateid, state, current->files);
762 nfs4_copy_stateid(&arg.stateid, state, NULL); 762 } else
763 else
764 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); 763 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
765 764
766 return rpc_call_sync(server->client, &msg, 0); 765 return rpc_call_sync(server->client, &msg, 0);
@@ -1124,47 +1123,31 @@ static int
1124nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, 1123nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
1125 struct iattr *sattr) 1124 struct iattr *sattr)
1126{ 1125{
1127 struct inode * inode = dentry->d_inode; 1126 struct rpc_cred *cred;
1128 int size_change = sattr->ia_valid & ATTR_SIZE; 1127 struct inode *inode = dentry->d_inode;
1129 struct nfs4_state *state = NULL; 1128 struct nfs4_state *state;
1130 int need_iput = 0;
1131 int status; 1129 int status;
1132 1130
1133 fattr->valid = 0; 1131 fattr->valid = 0;
1134 1132
1135 if (size_change) { 1133 cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
1136 struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); 1134 if (IS_ERR(cred))
1137 if (IS_ERR(cred)) 1135 return PTR_ERR(cred);
1138 return PTR_ERR(cred); 1136 /* Search for an existing WRITE delegation first */
1137 state = nfs4_open_delegated(inode, FMODE_WRITE, cred);
1138 if (!IS_ERR(state)) {
1139 /* NB: nfs4_open_delegated() bumps the inode->i_count */
1140 iput(inode);
1141 } else {
1142 /* Search for an existing open(O_WRITE) stateid */
1139 state = nfs4_find_state(inode, cred, FMODE_WRITE); 1143 state = nfs4_find_state(inode, cred, FMODE_WRITE);
1140 if (state == NULL) {
1141 state = nfs4_open_delegated(dentry->d_inode,
1142 FMODE_WRITE, cred);
1143 if (IS_ERR(state))
1144 state = nfs4_do_open(dentry->d_parent->d_inode,
1145 dentry, FMODE_WRITE,
1146 NULL, cred);
1147 need_iput = 1;
1148 }
1149 put_rpccred(cred);
1150 if (IS_ERR(state))
1151 return PTR_ERR(state);
1152
1153 if (state->inode != inode) {
1154 printk(KERN_WARNING "nfs: raced in setattr (%p != %p), returning -EIO\n", inode, state->inode);
1155 status = -EIO;
1156 goto out;
1157 }
1158 } 1144 }
1145
1159 status = nfs4_do_setattr(NFS_SERVER(inode), fattr, 1146 status = nfs4_do_setattr(NFS_SERVER(inode), fattr,
1160 NFS_FH(inode), sattr, state); 1147 NFS_FH(inode), sattr, state);
1161out: 1148 if (state != NULL)
1162 if (state) {
1163 inode = state->inode;
1164 nfs4_close_state(state, FMODE_WRITE); 1149 nfs4_close_state(state, FMODE_WRITE);
1165 if (need_iput) 1150 put_rpccred(cred);
1166 iput(inode);
1167 }
1168 return status; 1151 return status;
1169} 1152}
1170 1153