diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 94 |
1 files changed, 30 insertions, 64 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 2d5a6a2b9dec..0675f3215e0a 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -69,10 +69,8 @@ init_nfsv4_state(struct nfs_server *server) | |||
69 | void | 69 | void |
70 | destroy_nfsv4_state(struct nfs_server *server) | 70 | destroy_nfsv4_state(struct nfs_server *server) |
71 | { | 71 | { |
72 | if (server->mnt_path) { | 72 | kfree(server->mnt_path); |
73 | kfree(server->mnt_path); | 73 | server->mnt_path = NULL; |
74 | server->mnt_path = NULL; | ||
75 | } | ||
76 | if (server->nfs4_state) { | 74 | if (server->nfs4_state) { |
77 | nfs4_put_client(server->nfs4_state); | 75 | nfs4_put_client(server->nfs4_state); |
78 | server->nfs4_state = NULL; | 76 | server->nfs4_state = NULL; |
@@ -311,8 +309,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct | |||
311 | new = NULL; | 309 | new = NULL; |
312 | } | 310 | } |
313 | spin_unlock(&clp->cl_lock); | 311 | spin_unlock(&clp->cl_lock); |
314 | if (new) | 312 | kfree(new); |
315 | kfree(new); | ||
316 | if (sp != NULL) | 313 | if (sp != NULL) |
317 | return sp; | 314 | return sp; |
318 | put_rpccred(cred); | 315 | put_rpccred(cred); |
@@ -366,30 +363,21 @@ nfs4_alloc_open_state(void) | |||
366 | return state; | 363 | return state; |
367 | } | 364 | } |
368 | 365 | ||
369 | static struct nfs4_state * | 366 | void |
370 | __nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode) | 367 | nfs4_state_set_mode_locked(struct nfs4_state *state, mode_t mode) |
371 | { | 368 | { |
372 | struct nfs_inode *nfsi = NFS_I(inode); | 369 | if (state->state == mode) |
373 | struct nfs4_state *state; | 370 | return; |
374 | 371 | /* NB! List reordering - see the reclaim code for why. */ | |
375 | mode &= (FMODE_READ|FMODE_WRITE); | 372 | if ((mode & FMODE_WRITE) != (state->state & FMODE_WRITE)) { |
376 | list_for_each_entry(state, &nfsi->open_states, inode_states) { | ||
377 | if (state->owner->so_cred != cred) | ||
378 | continue; | ||
379 | if ((mode & FMODE_READ) != 0 && state->nreaders == 0) | ||
380 | continue; | ||
381 | if ((mode & FMODE_WRITE) != 0 && state->nwriters == 0) | ||
382 | continue; | ||
383 | if ((state->state & mode) != mode) | ||
384 | continue; | ||
385 | atomic_inc(&state->count); | ||
386 | if (mode & FMODE_READ) | ||
387 | state->nreaders++; | ||
388 | if (mode & FMODE_WRITE) | 373 | if (mode & FMODE_WRITE) |
389 | state->nwriters++; | 374 | list_move(&state->open_states, &state->owner->so_states); |
390 | return state; | 375 | else |
376 | list_move_tail(&state->open_states, &state->owner->so_states); | ||
391 | } | 377 | } |
392 | return NULL; | 378 | if (mode == 0) |
379 | list_del_init(&state->inode_states); | ||
380 | state->state = mode; | ||
393 | } | 381 | } |
394 | 382 | ||
395 | static struct nfs4_state * | 383 | static struct nfs4_state * |
@@ -400,7 +388,7 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner) | |||
400 | 388 | ||
401 | list_for_each_entry(state, &nfsi->open_states, inode_states) { | 389 | list_for_each_entry(state, &nfsi->open_states, inode_states) { |
402 | /* Is this in the process of being freed? */ | 390 | /* Is this in the process of being freed? */ |
403 | if (state->nreaders == 0 && state->nwriters == 0) | 391 | if (state->state == 0) |
404 | continue; | 392 | continue; |
405 | if (state->owner == owner) { | 393 | if (state->owner == owner) { |
406 | atomic_inc(&state->count); | 394 | atomic_inc(&state->count); |
@@ -410,17 +398,6 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner) | |||
410 | return NULL; | 398 | return NULL; |
411 | } | 399 | } |
412 | 400 | ||
413 | struct nfs4_state * | ||
414 | nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode) | ||
415 | { | ||
416 | struct nfs4_state *state; | ||
417 | |||
418 | spin_lock(&inode->i_lock); | ||
419 | state = __nfs4_find_state(inode, cred, mode); | ||
420 | spin_unlock(&inode->i_lock); | ||
421 | return state; | ||
422 | } | ||
423 | |||
424 | static void | 401 | static void |
425 | nfs4_free_open_state(struct nfs4_state *state) | 402 | nfs4_free_open_state(struct nfs4_state *state) |
426 | { | 403 | { |
@@ -481,7 +458,6 @@ void nfs4_put_open_state(struct nfs4_state *state) | |||
481 | spin_unlock(&inode->i_lock); | 458 | spin_unlock(&inode->i_lock); |
482 | spin_unlock(&owner->so_lock); | 459 | spin_unlock(&owner->so_lock); |
483 | iput(inode); | 460 | iput(inode); |
484 | BUG_ON (state->state != 0); | ||
485 | nfs4_free_open_state(state); | 461 | nfs4_free_open_state(state); |
486 | nfs4_put_state_owner(owner); | 462 | nfs4_put_state_owner(owner); |
487 | } | 463 | } |
@@ -493,7 +469,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode) | |||
493 | { | 469 | { |
494 | struct inode *inode = state->inode; | 470 | struct inode *inode = state->inode; |
495 | struct nfs4_state_owner *owner = state->owner; | 471 | struct nfs4_state_owner *owner = state->owner; |
496 | int newstate; | 472 | int oldstate, newstate = 0; |
497 | 473 | ||
498 | atomic_inc(&owner->so_count); | 474 | atomic_inc(&owner->so_count); |
499 | /* Protect against nfs4_find_state() */ | 475 | /* Protect against nfs4_find_state() */ |
@@ -503,30 +479,20 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode) | |||
503 | state->nreaders--; | 479 | state->nreaders--; |
504 | if (mode & FMODE_WRITE) | 480 | if (mode & FMODE_WRITE) |
505 | state->nwriters--; | 481 | state->nwriters--; |
506 | if (state->nwriters == 0) { | 482 | oldstate = newstate = state->state; |
507 | if (state->nreaders == 0) | 483 | if (state->nreaders == 0) |
508 | list_del_init(&state->inode_states); | 484 | newstate &= ~FMODE_READ; |
509 | /* See reclaim code */ | 485 | if (state->nwriters == 0) |
510 | list_move_tail(&state->open_states, &owner->so_states); | 486 | newstate &= ~FMODE_WRITE; |
487 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { | ||
488 | nfs4_state_set_mode_locked(state, newstate); | ||
489 | oldstate = newstate; | ||
511 | } | 490 | } |
512 | spin_unlock(&inode->i_lock); | 491 | spin_unlock(&inode->i_lock); |
513 | spin_unlock(&owner->so_lock); | 492 | spin_unlock(&owner->so_lock); |
514 | newstate = 0; | 493 | |
515 | if (state->state != 0) { | 494 | if (oldstate != newstate && nfs4_do_close(inode, state) == 0) |
516 | if (state->nreaders) | 495 | return; |
517 | newstate |= FMODE_READ; | ||
518 | if (state->nwriters) | ||
519 | newstate |= FMODE_WRITE; | ||
520 | if (state->state == newstate) | ||
521 | goto out; | ||
522 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { | ||
523 | state->state = newstate; | ||
524 | goto out; | ||
525 | } | ||
526 | if (nfs4_do_close(inode, state, newstate) == 0) | ||
527 | return; | ||
528 | } | ||
529 | out: | ||
530 | nfs4_put_open_state(state); | 496 | nfs4_put_open_state(state); |
531 | nfs4_put_state_owner(owner); | 497 | nfs4_put_state_owner(owner); |
532 | } | 498 | } |
@@ -815,7 +781,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s | |||
815 | int status = 0; | 781 | int status = 0; |
816 | 782 | ||
817 | for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { | 783 | for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { |
818 | if (!(fl->fl_flags & FL_POSIX)) | 784 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) |
819 | continue; | 785 | continue; |
820 | if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state) | 786 | if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state) |
821 | continue; | 787 | continue; |
@@ -830,7 +796,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s | |||
830 | case -NFS4ERR_NO_GRACE: | 796 | case -NFS4ERR_NO_GRACE: |
831 | case -NFS4ERR_RECLAIM_BAD: | 797 | case -NFS4ERR_RECLAIM_BAD: |
832 | case -NFS4ERR_RECLAIM_CONFLICT: | 798 | case -NFS4ERR_RECLAIM_CONFLICT: |
833 | /* kill_proc(fl->fl_owner, SIGLOST, 1); */ | 799 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ |
834 | break; | 800 | break; |
835 | case -NFS4ERR_STALE_CLIENTID: | 801 | case -NFS4ERR_STALE_CLIENTID: |
836 | goto out_err; | 802 | goto out_err; |