aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-05 18:07:55 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-10 23:40:41 -0400
commit003707c7225dbd4bf879b6c204743554de0a08d6 (patch)
treeb5ca79744badf011d15111d819f629cfc69452ba /fs/nfs/nfs4proc.c
parent0f9f95e0ad1f9d07d77832c5b60f7d30440602ee (diff)
NFSv4: Always use the delegation if we have one
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c88
1 files changed, 66 insertions, 22 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 61ba32af4d2f..128fe23d3f1e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -319,7 +319,7 @@ static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
319 return ret; 319 return ret;
320} 320}
321 321
322static inline void update_open_stateflags(struct nfs4_state *state, mode_t open_flags) 322static void update_open_stateflags(struct nfs4_state *state, mode_t open_flags)
323{ 323{
324 switch (open_flags) { 324 switch (open_flags) {
325 case FMODE_WRITE: 325 case FMODE_WRITE:
@@ -331,9 +331,36 @@ static inline void update_open_stateflags(struct nfs4_state *state, mode_t open_
331 case FMODE_READ|FMODE_WRITE: 331 case FMODE_READ|FMODE_WRITE:
332 state->n_rdwr++; 332 state->n_rdwr++;
333 } 333 }
334 nfs4_state_set_mode_locked(state, state->state | open_flags);
335}
336
337static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
338{
339 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
340 memcpy(state->stateid.data, stateid->data, sizeof(state->stateid.data));
341 memcpy(state->open_stateid.data, stateid->data, sizeof(state->open_stateid.data));
342 switch (open_flags) {
343 case FMODE_READ:
344 set_bit(NFS_O_RDONLY_STATE, &state->flags);
345 break;
346 case FMODE_WRITE:
347 set_bit(NFS_O_WRONLY_STATE, &state->flags);
348 break;
349 case FMODE_READ|FMODE_WRITE:
350 set_bit(NFS_O_RDWR_STATE, &state->flags);
351 }
334} 352}
335 353
336static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags) 354static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
355{
356 spin_lock(&state->owner->so_lock);
357 spin_lock(&state->inode->i_lock);
358 nfs_set_open_stateid_locked(state, stateid, open_flags);
359 spin_unlock(&state->inode->i_lock);
360 spin_unlock(&state->owner->so_lock);
361}
362
363static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *deleg_stateid, int open_flags)
337{ 364{
338 struct inode *inode = state->inode; 365 struct inode *inode = state->inode;
339 366
@@ -341,9 +368,13 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
341 /* Protect against nfs4_find_state_byowner() */ 368 /* Protect against nfs4_find_state_byowner() */
342 spin_lock(&state->owner->so_lock); 369 spin_lock(&state->owner->so_lock);
343 spin_lock(&inode->i_lock); 370 spin_lock(&inode->i_lock);
344 memcpy(&state->stateid, stateid, sizeof(state->stateid)); 371 if (deleg_stateid != NULL) {
372 memcpy(state->stateid.data, deleg_stateid->data, sizeof(state->stateid.data));
373 set_bit(NFS_DELEGATED_STATE, &state->flags);
374 }
375 if (open_stateid != NULL)
376 nfs_set_open_stateid_locked(state, open_stateid, open_flags);
345 update_open_stateflags(state, open_flags); 377 update_open_stateflags(state, open_flags);
346 nfs4_state_set_mode_locked(state, state->state | open_flags);
347 spin_unlock(&inode->i_lock); 378 spin_unlock(&inode->i_lock);
348 spin_unlock(&state->owner->so_lock); 379 spin_unlock(&state->owner->so_lock);
349} 380}
@@ -352,6 +383,8 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
352{ 383{
353 struct inode *inode; 384 struct inode *inode;
354 struct nfs4_state *state = NULL; 385 struct nfs4_state *state = NULL;
386 struct nfs_delegation *delegation;
387 nfs4_stateid *deleg_stateid = NULL;
355 388
356 if (!(data->f_attr.valid & NFS_ATTR_FATTR)) 389 if (!(data->f_attr.valid & NFS_ATTR_FATTR))
357 goto out; 390 goto out;
@@ -361,13 +394,14 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
361 state = nfs4_get_open_state(inode, data->owner); 394 state = nfs4_get_open_state(inode, data->owner);
362 if (state == NULL) 395 if (state == NULL)
363 goto put_inode; 396 goto put_inode;
364 update_open_stateid(state, &data->o_res.stateid, data->o_arg.open_flags);
365 if (data->o_res.delegation_type != 0) { 397 if (data->o_res.delegation_type != 0) {
366 struct nfs_inode *nfsi = NFS_I(inode);
367 int delegation_flags = 0; 398 int delegation_flags = 0;
368 399
369 if (nfsi->delegation) 400 rcu_read_lock();
370 delegation_flags = nfsi->delegation->flags; 401 delegation = rcu_dereference(NFS_I(inode)->delegation);
402 if (delegation)
403 delegation_flags = delegation->flags;
404 rcu_read_unlock();
371 if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM)) 405 if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
372 nfs_inode_set_delegation(state->inode, 406 nfs_inode_set_delegation(state->inode,
373 data->owner->so_cred, 407 data->owner->so_cred,
@@ -377,6 +411,12 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
377 data->owner->so_cred, 411 data->owner->so_cred,
378 &data->o_res); 412 &data->o_res);
379 } 413 }
414 rcu_read_lock();
415 delegation = rcu_dereference(NFS_I(inode)->delegation);
416 if (delegation != NULL)
417 deleg_stateid = &delegation->stateid;
418 update_open_stateid(state, &data->o_res.stateid, deleg_stateid, data->o_arg.open_flags);
419 rcu_read_unlock();
380put_inode: 420put_inode:
381 iput(inode); 421 iput(inode);
382out: 422out:
@@ -911,8 +951,7 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred
911 unlock_kernel(); 951 unlock_kernel();
912 if (err != 0) 952 if (err != 0)
913 goto out_put_open_state; 953 goto out_put_open_state;
914 set_bit(NFS_DELEGATED_STATE, &state->flags); 954 update_open_stateid(state, NULL, &delegation->stateid, open_flags);
915 update_open_stateid(state, &delegation->stateid, open_flags);
916out_ok: 955out_ok:
917 nfs4_put_state_owner(sp); 956 nfs4_put_state_owner(sp);
918 up_read(&nfsi->rwsem); 957 up_read(&nfsi->rwsem);
@@ -1149,8 +1188,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
1149 nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid); 1188 nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
1150 switch (task->tk_status) { 1189 switch (task->tk_status) {
1151 case 0: 1190 case 0:
1152 memcpy(&state->stateid, &calldata->res.stateid, 1191 nfs_set_open_stateid(state, &calldata->res.stateid, calldata->arg.open_flags);
1153 sizeof(state->stateid));
1154 renew_lease(server, calldata->timestamp); 1192 renew_lease(server, calldata->timestamp);
1155 break; 1193 break;
1156 case -NFS4ERR_STALE_STATEID: 1194 case -NFS4ERR_STALE_STATEID:
@@ -1175,26 +1213,32 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
1175 .rpc_resp = &calldata->res, 1213 .rpc_resp = &calldata->res,
1176 .rpc_cred = state->owner->so_cred, 1214 .rpc_cred = state->owner->so_cred,
1177 }; 1215 };
1178 int mode = 0, old_mode; 1216 int clear_rd, clear_wr, clear_rdwr;
1217 int mode;
1179 1218
1180 if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) 1219 if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
1181 return; 1220 return;
1182 /* Recalculate the new open mode in case someone reopened the file 1221
1183 * while we were waiting in line to be scheduled. 1222 mode = FMODE_READ|FMODE_WRITE;
1184 */ 1223 clear_rd = clear_wr = clear_rdwr = 0;
1185 spin_lock(&state->owner->so_lock); 1224 spin_lock(&state->owner->so_lock);
1186 spin_lock(&calldata->inode->i_lock); 1225 spin_lock(&calldata->inode->i_lock);
1187 mode = old_mode = state->state; 1226 /* Calculate the change in open mode */
1188 if (state->n_rdwr == 0) { 1227 if (state->n_rdwr == 0) {
1189 if (state->n_rdonly == 0) 1228 if (state->n_rdonly == 0) {
1190 mode &= ~FMODE_READ; 1229 mode &= ~FMODE_READ;
1191 if (state->n_wronly == 0) 1230 clear_rd |= test_and_clear_bit(NFS_O_RDONLY_STATE, &state->flags);
1231 clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
1232 }
1233 if (state->n_wronly == 0) {
1192 mode &= ~FMODE_WRITE; 1234 mode &= ~FMODE_WRITE;
1235 clear_wr |= test_and_clear_bit(NFS_O_WRONLY_STATE, &state->flags);
1236 clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
1237 }
1193 } 1238 }
1194 nfs4_state_set_mode_locked(state, mode);
1195 spin_unlock(&calldata->inode->i_lock); 1239 spin_unlock(&calldata->inode->i_lock);
1196 spin_unlock(&state->owner->so_lock); 1240 spin_unlock(&state->owner->so_lock);
1197 if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) { 1241 if (!clear_rd && !clear_wr && !clear_rdwr) {
1198 /* Note: exit _without_ calling nfs4_close_done */ 1242 /* Note: exit _without_ calling nfs4_close_done */
1199 task->tk_action = NULL; 1243 task->tk_action = NULL;
1200 return; 1244 return;
@@ -1238,7 +1282,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state)
1238 calldata->inode = state->inode; 1282 calldata->inode = state->inode;
1239 calldata->state = state; 1283 calldata->state = state;
1240 calldata->arg.fh = NFS_FH(state->inode); 1284 calldata->arg.fh = NFS_FH(state->inode);
1241 calldata->arg.stateid = &state->stateid; 1285 calldata->arg.stateid = &state->open_stateid;
1242 /* Serialization for the sequence id */ 1286 /* Serialization for the sequence id */
1243 calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); 1287 calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
1244 if (calldata->arg.seqid == NULL) 1288 if (calldata->arg.seqid == NULL)