diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 34acf5926fdc..3e2f19b04c06 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -145,7 +145,9 @@ static void nfs4_end_drain_session(struct nfs_client *clp) | |||
145 | struct nfs4_session *ses = clp->cl_session; | 145 | struct nfs4_session *ses = clp->cl_session; |
146 | int max_slots; | 146 | int max_slots; |
147 | 147 | ||
148 | if (test_and_clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) { | 148 | if (ses == NULL) |
149 | return; | ||
150 | if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { | ||
149 | spin_lock(&ses->fc_slot_table.slot_tbl_lock); | 151 | spin_lock(&ses->fc_slot_table.slot_tbl_lock); |
150 | max_slots = ses->fc_slot_table.max_slots; | 152 | max_slots = ses->fc_slot_table.max_slots; |
151 | while (max_slots--) { | 153 | while (max_slots--) { |
@@ -167,7 +169,7 @@ static int nfs4_begin_drain_session(struct nfs_client *clp) | |||
167 | struct nfs4_slot_table *tbl = &ses->fc_slot_table; | 169 | struct nfs4_slot_table *tbl = &ses->fc_slot_table; |
168 | 170 | ||
169 | spin_lock(&tbl->slot_tbl_lock); | 171 | spin_lock(&tbl->slot_tbl_lock); |
170 | set_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state); | 172 | set_bit(NFS4_SESSION_DRAINING, &ses->session_state); |
171 | if (tbl->highest_used_slotid != -1) { | 173 | if (tbl->highest_used_slotid != -1) { |
172 | INIT_COMPLETION(ses->complete); | 174 | INIT_COMPLETION(ses->complete); |
173 | spin_unlock(&tbl->slot_tbl_lock); | 175 | spin_unlock(&tbl->slot_tbl_lock); |
@@ -371,7 +373,6 @@ nfs4_alloc_state_owner(void) | |||
371 | return NULL; | 373 | return NULL; |
372 | spin_lock_init(&sp->so_lock); | 374 | spin_lock_init(&sp->so_lock); |
373 | INIT_LIST_HEAD(&sp->so_states); | 375 | INIT_LIST_HEAD(&sp->so_states); |
374 | INIT_LIST_HEAD(&sp->so_delegations); | ||
375 | rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue"); | 376 | rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue"); |
376 | sp->so_seqid.sequence = &sp->so_sequence; | 377 | sp->so_seqid.sequence = &sp->so_sequence; |
377 | spin_lock_init(&sp->so_sequence.lock); | 378 | spin_lock_init(&sp->so_sequence.lock); |
@@ -384,7 +385,7 @@ static void | |||
384 | nfs4_drop_state_owner(struct nfs4_state_owner *sp) | 385 | nfs4_drop_state_owner(struct nfs4_state_owner *sp) |
385 | { | 386 | { |
386 | if (!RB_EMPTY_NODE(&sp->so_client_node)) { | 387 | if (!RB_EMPTY_NODE(&sp->so_client_node)) { |
387 | struct nfs_client *clp = sp->so_client; | 388 | struct nfs_client *clp = sp->so_server->nfs_client; |
388 | 389 | ||
389 | spin_lock(&clp->cl_lock); | 390 | spin_lock(&clp->cl_lock); |
390 | rb_erase(&sp->so_client_node, &clp->cl_state_owners); | 391 | rb_erase(&sp->so_client_node, &clp->cl_state_owners); |
@@ -406,7 +407,6 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct | |||
406 | new = nfs4_alloc_state_owner(); | 407 | new = nfs4_alloc_state_owner(); |
407 | if (new == NULL) | 408 | if (new == NULL) |
408 | return NULL; | 409 | return NULL; |
409 | new->so_client = clp; | ||
410 | new->so_server = server; | 410 | new->so_server = server; |
411 | new->so_cred = cred; | 411 | new->so_cred = cred; |
412 | spin_lock(&clp->cl_lock); | 412 | spin_lock(&clp->cl_lock); |
@@ -423,7 +423,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct | |||
423 | 423 | ||
424 | void nfs4_put_state_owner(struct nfs4_state_owner *sp) | 424 | void nfs4_put_state_owner(struct nfs4_state_owner *sp) |
425 | { | 425 | { |
426 | struct nfs_client *clp = sp->so_client; | 426 | struct nfs_client *clp = sp->so_server->nfs_client; |
427 | struct rpc_cred *cred = sp->so_cred; | 427 | struct rpc_cred *cred = sp->so_cred; |
428 | 428 | ||
429 | if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) | 429 | if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) |
@@ -602,12 +602,21 @@ void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode) | |||
602 | * that is compatible with current->files | 602 | * that is compatible with current->files |
603 | */ | 603 | */ |
604 | static struct nfs4_lock_state * | 604 | static struct nfs4_lock_state * |
605 | __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | 605 | __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type) |
606 | { | 606 | { |
607 | struct nfs4_lock_state *pos; | 607 | struct nfs4_lock_state *pos; |
608 | list_for_each_entry(pos, &state->lock_states, ls_locks) { | 608 | list_for_each_entry(pos, &state->lock_states, ls_locks) { |
609 | if (pos->ls_owner != fl_owner) | 609 | if (type != NFS4_ANY_LOCK_TYPE && pos->ls_owner.lo_type != type) |
610 | continue; | 610 | continue; |
611 | switch (pos->ls_owner.lo_type) { | ||
612 | case NFS4_POSIX_LOCK_TYPE: | ||
613 | if (pos->ls_owner.lo_u.posix_owner != fl_owner) | ||
614 | continue; | ||
615 | break; | ||
616 | case NFS4_FLOCK_LOCK_TYPE: | ||
617 | if (pos->ls_owner.lo_u.flock_owner != fl_pid) | ||
618 | continue; | ||
619 | } | ||
611 | atomic_inc(&pos->ls_count); | 620 | atomic_inc(&pos->ls_count); |
612 | return pos; | 621 | return pos; |
613 | } | 622 | } |
@@ -619,10 +628,10 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | |||
619 | * exists, return an uninitialized one. | 628 | * exists, return an uninitialized one. |
620 | * | 629 | * |
621 | */ | 630 | */ |
622 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | 631 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type) |
623 | { | 632 | { |
624 | struct nfs4_lock_state *lsp; | 633 | struct nfs4_lock_state *lsp; |
625 | struct nfs_client *clp = state->owner->so_client; | 634 | struct nfs_client *clp = state->owner->so_server->nfs_client; |
626 | 635 | ||
627 | lsp = kzalloc(sizeof(*lsp), GFP_NOFS); | 636 | lsp = kzalloc(sizeof(*lsp), GFP_NOFS); |
628 | if (lsp == NULL) | 637 | if (lsp == NULL) |
@@ -633,7 +642,18 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
633 | lsp->ls_seqid.sequence = &lsp->ls_sequence; | 642 | lsp->ls_seqid.sequence = &lsp->ls_sequence; |
634 | atomic_set(&lsp->ls_count, 1); | 643 | atomic_set(&lsp->ls_count, 1); |
635 | lsp->ls_state = state; | 644 | lsp->ls_state = state; |
636 | lsp->ls_owner = fl_owner; | 645 | lsp->ls_owner.lo_type = type; |
646 | switch (lsp->ls_owner.lo_type) { | ||
647 | case NFS4_FLOCK_LOCK_TYPE: | ||
648 | lsp->ls_owner.lo_u.flock_owner = fl_pid; | ||
649 | break; | ||
650 | case NFS4_POSIX_LOCK_TYPE: | ||
651 | lsp->ls_owner.lo_u.posix_owner = fl_owner; | ||
652 | break; | ||
653 | default: | ||
654 | kfree(lsp); | ||
655 | return NULL; | ||
656 | } | ||
637 | spin_lock(&clp->cl_lock); | 657 | spin_lock(&clp->cl_lock); |
638 | nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64); | 658 | nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64); |
639 | spin_unlock(&clp->cl_lock); | 659 | spin_unlock(&clp->cl_lock); |
@@ -643,7 +663,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
643 | 663 | ||
644 | static void nfs4_free_lock_state(struct nfs4_lock_state *lsp) | 664 | static void nfs4_free_lock_state(struct nfs4_lock_state *lsp) |
645 | { | 665 | { |
646 | struct nfs_client *clp = lsp->ls_state->owner->so_client; | 666 | struct nfs_client *clp = lsp->ls_state->owner->so_server->nfs_client; |
647 | 667 | ||
648 | spin_lock(&clp->cl_lock); | 668 | spin_lock(&clp->cl_lock); |
649 | nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id); | 669 | nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id); |
@@ -657,13 +677,13 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp) | |||
657 | * exists, return an uninitialized one. | 677 | * exists, return an uninitialized one. |
658 | * | 678 | * |
659 | */ | 679 | */ |
660 | static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) | 680 | static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner, pid_t pid, unsigned int type) |
661 | { | 681 | { |
662 | struct nfs4_lock_state *lsp, *new = NULL; | 682 | struct nfs4_lock_state *lsp, *new = NULL; |
663 | 683 | ||
664 | for(;;) { | 684 | for(;;) { |
665 | spin_lock(&state->state_lock); | 685 | spin_lock(&state->state_lock); |
666 | lsp = __nfs4_find_lock_state(state, owner); | 686 | lsp = __nfs4_find_lock_state(state, owner, pid, type); |
667 | if (lsp != NULL) | 687 | if (lsp != NULL) |
668 | break; | 688 | break; |
669 | if (new != NULL) { | 689 | if (new != NULL) { |
@@ -674,7 +694,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_ | |||
674 | break; | 694 | break; |
675 | } | 695 | } |
676 | spin_unlock(&state->state_lock); | 696 | spin_unlock(&state->state_lock); |
677 | new = nfs4_alloc_lock_state(state, owner); | 697 | new = nfs4_alloc_lock_state(state, owner, pid, type); |
678 | if (new == NULL) | 698 | if (new == NULL) |
679 | return NULL; | 699 | return NULL; |
680 | } | 700 | } |
@@ -701,6 +721,8 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp) | |||
701 | if (list_empty(&state->lock_states)) | 721 | if (list_empty(&state->lock_states)) |
702 | clear_bit(LK_STATE_IN_USE, &state->flags); | 722 | clear_bit(LK_STATE_IN_USE, &state->flags); |
703 | spin_unlock(&state->state_lock); | 723 | spin_unlock(&state->state_lock); |
724 | if (lsp->ls_flags & NFS_LOCK_INITIALIZED) | ||
725 | nfs4_release_lockowner(lsp); | ||
704 | nfs4_free_lock_state(lsp); | 726 | nfs4_free_lock_state(lsp); |
705 | } | 727 | } |
706 | 728 | ||
@@ -728,7 +750,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) | |||
728 | 750 | ||
729 | if (fl->fl_ops != NULL) | 751 | if (fl->fl_ops != NULL) |
730 | return 0; | 752 | return 0; |
731 | lsp = nfs4_get_lock_state(state, fl->fl_owner); | 753 | if (fl->fl_flags & FL_POSIX) |
754 | lsp = nfs4_get_lock_state(state, fl->fl_owner, 0, NFS4_POSIX_LOCK_TYPE); | ||
755 | else if (fl->fl_flags & FL_FLOCK) | ||
756 | lsp = nfs4_get_lock_state(state, 0, fl->fl_pid, NFS4_FLOCK_LOCK_TYPE); | ||
757 | else | ||
758 | return -EINVAL; | ||
732 | if (lsp == NULL) | 759 | if (lsp == NULL) |
733 | return -ENOMEM; | 760 | return -ENOMEM; |
734 | fl->fl_u.nfs4_fl.owner = lsp; | 761 | fl->fl_u.nfs4_fl.owner = lsp; |
@@ -740,7 +767,7 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) | |||
740 | * Byte-range lock aware utility to initialize the stateid of read/write | 767 | * Byte-range lock aware utility to initialize the stateid of read/write |
741 | * requests. | 768 | * requests. |
742 | */ | 769 | */ |
743 | void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner) | 770 | void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid) |
744 | { | 771 | { |
745 | struct nfs4_lock_state *lsp; | 772 | struct nfs4_lock_state *lsp; |
746 | int seq; | 773 | int seq; |
@@ -753,7 +780,7 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
753 | return; | 780 | return; |
754 | 781 | ||
755 | spin_lock(&state->state_lock); | 782 | spin_lock(&state->state_lock); |
756 | lsp = __nfs4_find_lock_state(state, fl_owner); | 783 | lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE); |
757 | if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | 784 | if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) |
758 | memcpy(dst, &lsp->ls_stateid, sizeof(*dst)); | 785 | memcpy(dst, &lsp->ls_stateid, sizeof(*dst)); |
759 | spin_unlock(&state->state_lock); | 786 | spin_unlock(&state->state_lock); |
@@ -1041,11 +1068,11 @@ restart: | |||
1041 | case -NFS4ERR_BAD_STATEID: | 1068 | case -NFS4ERR_BAD_STATEID: |
1042 | case -NFS4ERR_RECLAIM_BAD: | 1069 | case -NFS4ERR_RECLAIM_BAD: |
1043 | case -NFS4ERR_RECLAIM_CONFLICT: | 1070 | case -NFS4ERR_RECLAIM_CONFLICT: |
1044 | nfs4_state_mark_reclaim_nograce(sp->so_client, state); | 1071 | nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state); |
1045 | break; | 1072 | break; |
1046 | case -NFS4ERR_EXPIRED: | 1073 | case -NFS4ERR_EXPIRED: |
1047 | case -NFS4ERR_NO_GRACE: | 1074 | case -NFS4ERR_NO_GRACE: |
1048 | nfs4_state_mark_reclaim_nograce(sp->so_client, state); | 1075 | nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state); |
1049 | case -NFS4ERR_STALE_CLIENTID: | 1076 | case -NFS4ERR_STALE_CLIENTID: |
1050 | case -NFS4ERR_BADSESSION: | 1077 | case -NFS4ERR_BADSESSION: |
1051 | case -NFS4ERR_BADSLOT: | 1078 | case -NFS4ERR_BADSLOT: |
@@ -1120,8 +1147,7 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | |||
1120 | if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) | 1147 | if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) |
1121 | return; | 1148 | return; |
1122 | 1149 | ||
1123 | nfs4_reclaim_complete(clp, | 1150 | nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops); |
1124 | nfs4_reboot_recovery_ops[clp->cl_minorversion]); | ||
1125 | 1151 | ||
1126 | for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { | 1152 | for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { |
1127 | sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); | 1153 | sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); |
@@ -1211,8 +1237,8 @@ restart: | |||
1211 | static int nfs4_check_lease(struct nfs_client *clp) | 1237 | static int nfs4_check_lease(struct nfs_client *clp) |
1212 | { | 1238 | { |
1213 | struct rpc_cred *cred; | 1239 | struct rpc_cred *cred; |
1214 | struct nfs4_state_maintenance_ops *ops = | 1240 | const struct nfs4_state_maintenance_ops *ops = |
1215 | nfs4_state_renewal_ops[clp->cl_minorversion]; | 1241 | clp->cl_mvops->state_renewal_ops; |
1216 | int status = -NFS4ERR_EXPIRED; | 1242 | int status = -NFS4ERR_EXPIRED; |
1217 | 1243 | ||
1218 | /* Is the client already known to have an expired lease? */ | 1244 | /* Is the client already known to have an expired lease? */ |
@@ -1235,8 +1261,8 @@ out: | |||
1235 | static int nfs4_reclaim_lease(struct nfs_client *clp) | 1261 | static int nfs4_reclaim_lease(struct nfs_client *clp) |
1236 | { | 1262 | { |
1237 | struct rpc_cred *cred; | 1263 | struct rpc_cred *cred; |
1238 | struct nfs4_state_recovery_ops *ops = | 1264 | const struct nfs4_state_recovery_ops *ops = |
1239 | nfs4_reboot_recovery_ops[clp->cl_minorversion]; | 1265 | clp->cl_mvops->reboot_recovery_ops; |
1240 | int status = -ENOENT; | 1266 | int status = -ENOENT; |
1241 | 1267 | ||
1242 | cred = ops->get_clid_cred(clp); | 1268 | cred = ops->get_clid_cred(clp); |
@@ -1444,7 +1470,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1444 | /* First recover reboot state... */ | 1470 | /* First recover reboot state... */ |
1445 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { | 1471 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { |
1446 | status = nfs4_do_reclaim(clp, | 1472 | status = nfs4_do_reclaim(clp, |
1447 | nfs4_reboot_recovery_ops[clp->cl_minorversion]); | 1473 | clp->cl_mvops->reboot_recovery_ops); |
1448 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || | 1474 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
1449 | test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) | 1475 | test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) |
1450 | continue; | 1476 | continue; |
@@ -1458,7 +1484,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1458 | /* Now recover expired state... */ | 1484 | /* Now recover expired state... */ |
1459 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { | 1485 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { |
1460 | status = nfs4_do_reclaim(clp, | 1486 | status = nfs4_do_reclaim(clp, |
1461 | nfs4_nograce_recovery_ops[clp->cl_minorversion]); | 1487 | clp->cl_mvops->nograce_recovery_ops); |
1462 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || | 1488 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
1463 | test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) || | 1489 | test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) || |
1464 | test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) | 1490 | test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) |