diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 55 |
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 | |||
1124 | nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | 1123 | nfs4_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); |
1161 | out: | 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 | ||