diff options
| author | James Bottomley <jejb@sparkweed.localdomain> | 2006-09-23 22:03:52 -0400 |
|---|---|---|
| committer | James Bottomley <jejb@sparkweed.localdomain> | 2006-09-23 22:03:52 -0400 |
| commit | 1aedf2ccc60fade26c46fae12e28664d0da3f199 (patch) | |
| tree | d91083e3079f1ddb942a382ac2b5a7525570ad59 /fs/nfs/nfs4state.c | |
| parent | dfdc58ba354adb80d67c99f7be84f95a8e02e466 (diff) | |
| parent | 1ab9dd0902df4f4ff56fbf672220549090ab28ba (diff) | |
Merge mulgrave-w:git/linux-2.6
Conflicts:
include/linux/blkdev.h
Trivial merge to incorporate tag prototypes.
Diffstat (limited to 'fs/nfs/nfs4state.c')
| -rw-r--r-- | fs/nfs/nfs4state.c | 174 |
1 files changed, 20 insertions, 154 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 090a36b07a22..5fffbdfa971f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -50,149 +50,15 @@ | |||
| 50 | #include "nfs4_fs.h" | 50 | #include "nfs4_fs.h" |
| 51 | #include "callback.h" | 51 | #include "callback.h" |
| 52 | #include "delegation.h" | 52 | #include "delegation.h" |
| 53 | #include "internal.h" | ||
| 53 | 54 | ||
| 54 | #define OPENOWNER_POOL_SIZE 8 | 55 | #define OPENOWNER_POOL_SIZE 8 |
| 55 | 56 | ||
| 56 | const nfs4_stateid zero_stateid; | 57 | const nfs4_stateid zero_stateid; |
| 57 | 58 | ||
| 58 | static DEFINE_SPINLOCK(state_spinlock); | ||
| 59 | static LIST_HEAD(nfs4_clientid_list); | 59 | static LIST_HEAD(nfs4_clientid_list); |
| 60 | 60 | ||
| 61 | void | 61 | static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred) |
| 62 | init_nfsv4_state(struct nfs_server *server) | ||
| 63 | { | ||
| 64 | server->nfs4_state = NULL; | ||
| 65 | INIT_LIST_HEAD(&server->nfs4_siblings); | ||
| 66 | } | ||
| 67 | |||
| 68 | void | ||
| 69 | destroy_nfsv4_state(struct nfs_server *server) | ||
| 70 | { | ||
| 71 | kfree(server->mnt_path); | ||
| 72 | server->mnt_path = NULL; | ||
| 73 | if (server->nfs4_state) { | ||
| 74 | nfs4_put_client(server->nfs4_state); | ||
| 75 | server->nfs4_state = NULL; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | /* | ||
| 80 | * nfs4_get_client(): returns an empty client structure | ||
| 81 | * nfs4_put_client(): drops reference to client structure | ||
| 82 | * | ||
| 83 | * Since these are allocated/deallocated very rarely, we don't | ||
| 84 | * bother putting them in a slab cache... | ||
| 85 | */ | ||
| 86 | static struct nfs4_client * | ||
| 87 | nfs4_alloc_client(struct in_addr *addr) | ||
| 88 | { | ||
| 89 | struct nfs4_client *clp; | ||
| 90 | |||
| 91 | if (nfs_callback_up() < 0) | ||
| 92 | return NULL; | ||
| 93 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) { | ||
| 94 | nfs_callback_down(); | ||
| 95 | return NULL; | ||
| 96 | } | ||
| 97 | memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr)); | ||
| 98 | init_rwsem(&clp->cl_sem); | ||
| 99 | INIT_LIST_HEAD(&clp->cl_delegations); | ||
| 100 | INIT_LIST_HEAD(&clp->cl_state_owners); | ||
| 101 | INIT_LIST_HEAD(&clp->cl_unused); | ||
| 102 | spin_lock_init(&clp->cl_lock); | ||
| 103 | atomic_set(&clp->cl_count, 1); | ||
| 104 | INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); | ||
| 105 | INIT_LIST_HEAD(&clp->cl_superblocks); | ||
| 106 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client"); | ||
| 107 | clp->cl_rpcclient = ERR_PTR(-EINVAL); | ||
| 108 | clp->cl_boot_time = CURRENT_TIME; | ||
| 109 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | ||
| 110 | return clp; | ||
| 111 | } | ||
| 112 | |||
| 113 | static void | ||
| 114 | nfs4_free_client(struct nfs4_client *clp) | ||
| 115 | { | ||
| 116 | struct nfs4_state_owner *sp; | ||
| 117 | |||
| 118 | while (!list_empty(&clp->cl_unused)) { | ||
| 119 | sp = list_entry(clp->cl_unused.next, | ||
| 120 | struct nfs4_state_owner, | ||
| 121 | so_list); | ||
| 122 | list_del(&sp->so_list); | ||
| 123 | kfree(sp); | ||
| 124 | } | ||
| 125 | BUG_ON(!list_empty(&clp->cl_state_owners)); | ||
| 126 | nfs_idmap_delete(clp); | ||
| 127 | if (!IS_ERR(clp->cl_rpcclient)) | ||
| 128 | rpc_shutdown_client(clp->cl_rpcclient); | ||
| 129 | kfree(clp); | ||
| 130 | nfs_callback_down(); | ||
| 131 | } | ||
| 132 | |||
| 133 | static struct nfs4_client *__nfs4_find_client(struct in_addr *addr) | ||
| 134 | { | ||
| 135 | struct nfs4_client *clp; | ||
| 136 | list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) { | ||
| 137 | if (memcmp(&clp->cl_addr, addr, sizeof(clp->cl_addr)) == 0) { | ||
| 138 | atomic_inc(&clp->cl_count); | ||
| 139 | return clp; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | return NULL; | ||
| 143 | } | ||
| 144 | |||
| 145 | struct nfs4_client *nfs4_find_client(struct in_addr *addr) | ||
| 146 | { | ||
| 147 | struct nfs4_client *clp; | ||
| 148 | spin_lock(&state_spinlock); | ||
| 149 | clp = __nfs4_find_client(addr); | ||
| 150 | spin_unlock(&state_spinlock); | ||
| 151 | return clp; | ||
| 152 | } | ||
| 153 | |||
| 154 | struct nfs4_client * | ||
| 155 | nfs4_get_client(struct in_addr *addr) | ||
| 156 | { | ||
| 157 | struct nfs4_client *clp, *new = NULL; | ||
| 158 | |||
| 159 | spin_lock(&state_spinlock); | ||
| 160 | for (;;) { | ||
| 161 | clp = __nfs4_find_client(addr); | ||
| 162 | if (clp != NULL) | ||
| 163 | break; | ||
| 164 | clp = new; | ||
| 165 | if (clp != NULL) { | ||
| 166 | list_add(&clp->cl_servers, &nfs4_clientid_list); | ||
| 167 | new = NULL; | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | spin_unlock(&state_spinlock); | ||
| 171 | new = nfs4_alloc_client(addr); | ||
| 172 | spin_lock(&state_spinlock); | ||
| 173 | if (new == NULL) | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | spin_unlock(&state_spinlock); | ||
| 177 | if (new) | ||
| 178 | nfs4_free_client(new); | ||
| 179 | return clp; | ||
| 180 | } | ||
| 181 | |||
| 182 | void | ||
| 183 | nfs4_put_client(struct nfs4_client *clp) | ||
| 184 | { | ||
| 185 | if (!atomic_dec_and_lock(&clp->cl_count, &state_spinlock)) | ||
| 186 | return; | ||
| 187 | list_del(&clp->cl_servers); | ||
| 188 | spin_unlock(&state_spinlock); | ||
| 189 | BUG_ON(!list_empty(&clp->cl_superblocks)); | ||
| 190 | rpc_wake_up(&clp->cl_rpcwaitq); | ||
| 191 | nfs4_kill_renewd(clp); | ||
| 192 | nfs4_free_client(clp); | ||
| 193 | } | ||
| 194 | |||
| 195 | static int nfs4_init_client(struct nfs4_client *clp, struct rpc_cred *cred) | ||
| 196 | { | 62 | { |
| 197 | int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, | 63 | int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, |
| 198 | nfs_callback_tcpport, cred); | 64 | nfs_callback_tcpport, cred); |
| @@ -204,13 +70,13 @@ static int nfs4_init_client(struct nfs4_client *clp, struct rpc_cred *cred) | |||
| 204 | } | 70 | } |
| 205 | 71 | ||
| 206 | u32 | 72 | u32 |
| 207 | nfs4_alloc_lockowner_id(struct nfs4_client *clp) | 73 | nfs4_alloc_lockowner_id(struct nfs_client *clp) |
| 208 | { | 74 | { |
| 209 | return clp->cl_lockowner_id ++; | 75 | return clp->cl_lockowner_id ++; |
| 210 | } | 76 | } |
| 211 | 77 | ||
| 212 | static struct nfs4_state_owner * | 78 | static struct nfs4_state_owner * |
| 213 | nfs4_client_grab_unused(struct nfs4_client *clp, struct rpc_cred *cred) | 79 | nfs4_client_grab_unused(struct nfs_client *clp, struct rpc_cred *cred) |
| 214 | { | 80 | { |
| 215 | struct nfs4_state_owner *sp = NULL; | 81 | struct nfs4_state_owner *sp = NULL; |
| 216 | 82 | ||
| @@ -224,7 +90,7 @@ nfs4_client_grab_unused(struct nfs4_client *clp, struct rpc_cred *cred) | |||
| 224 | return sp; | 90 | return sp; |
| 225 | } | 91 | } |
| 226 | 92 | ||
| 227 | struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp) | 93 | struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp) |
| 228 | { | 94 | { |
| 229 | struct nfs4_state_owner *sp; | 95 | struct nfs4_state_owner *sp; |
| 230 | struct rpc_cred *cred = NULL; | 96 | struct rpc_cred *cred = NULL; |
| @@ -238,7 +104,7 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp) | |||
| 238 | return cred; | 104 | return cred; |
| 239 | } | 105 | } |
| 240 | 106 | ||
| 241 | struct rpc_cred *nfs4_get_setclientid_cred(struct nfs4_client *clp) | 107 | struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) |
| 242 | { | 108 | { |
| 243 | struct nfs4_state_owner *sp; | 109 | struct nfs4_state_owner *sp; |
| 244 | 110 | ||
| @@ -251,7 +117,7 @@ struct rpc_cred *nfs4_get_setclientid_cred(struct nfs4_client *clp) | |||
| 251 | } | 117 | } |
| 252 | 118 | ||
| 253 | static struct nfs4_state_owner * | 119 | static struct nfs4_state_owner * |
| 254 | nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred) | 120 | nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred) |
| 255 | { | 121 | { |
| 256 | struct nfs4_state_owner *sp, *res = NULL; | 122 | struct nfs4_state_owner *sp, *res = NULL; |
| 257 | 123 | ||
| @@ -294,7 +160,7 @@ nfs4_alloc_state_owner(void) | |||
| 294 | void | 160 | void |
| 295 | nfs4_drop_state_owner(struct nfs4_state_owner *sp) | 161 | nfs4_drop_state_owner(struct nfs4_state_owner *sp) |
| 296 | { | 162 | { |
| 297 | struct nfs4_client *clp = sp->so_client; | 163 | struct nfs_client *clp = sp->so_client; |
| 298 | spin_lock(&clp->cl_lock); | 164 | spin_lock(&clp->cl_lock); |
| 299 | list_del_init(&sp->so_list); | 165 | list_del_init(&sp->so_list); |
| 300 | spin_unlock(&clp->cl_lock); | 166 | spin_unlock(&clp->cl_lock); |
| @@ -306,7 +172,7 @@ nfs4_drop_state_owner(struct nfs4_state_owner *sp) | |||
| 306 | */ | 172 | */ |
| 307 | struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred) | 173 | struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred) |
| 308 | { | 174 | { |
| 309 | struct nfs4_client *clp = server->nfs4_state; | 175 | struct nfs_client *clp = server->nfs_client; |
| 310 | struct nfs4_state_owner *sp, *new; | 176 | struct nfs4_state_owner *sp, *new; |
| 311 | 177 | ||
| 312 | get_rpccred(cred); | 178 | get_rpccred(cred); |
| @@ -337,7 +203,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct | |||
| 337 | */ | 203 | */ |
| 338 | void nfs4_put_state_owner(struct nfs4_state_owner *sp) | 204 | void nfs4_put_state_owner(struct nfs4_state_owner *sp) |
| 339 | { | 205 | { |
| 340 | struct nfs4_client *clp = sp->so_client; | 206 | struct nfs_client *clp = sp->so_client; |
| 341 | struct rpc_cred *cred = sp->so_cred; | 207 | struct rpc_cred *cred = sp->so_cred; |
| 342 | 208 | ||
| 343 | if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) | 209 | if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) |
| @@ -540,7 +406,7 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | |||
| 540 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | 406 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) |
| 541 | { | 407 | { |
| 542 | struct nfs4_lock_state *lsp; | 408 | struct nfs4_lock_state *lsp; |
| 543 | struct nfs4_client *clp = state->owner->so_client; | 409 | struct nfs_client *clp = state->owner->so_client; |
| 544 | 410 | ||
| 545 | lsp = kzalloc(sizeof(*lsp), GFP_KERNEL); | 411 | lsp = kzalloc(sizeof(*lsp), GFP_KERNEL); |
| 546 | if (lsp == NULL) | 412 | if (lsp == NULL) |
| @@ -752,7 +618,7 @@ out: | |||
| 752 | 618 | ||
| 753 | static int reclaimer(void *); | 619 | static int reclaimer(void *); |
| 754 | 620 | ||
| 755 | static inline void nfs4_clear_recover_bit(struct nfs4_client *clp) | 621 | static inline void nfs4_clear_recover_bit(struct nfs_client *clp) |
| 756 | { | 622 | { |
| 757 | smp_mb__before_clear_bit(); | 623 | smp_mb__before_clear_bit(); |
| 758 | clear_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state); | 624 | clear_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state); |
| @@ -764,25 +630,25 @@ static inline void nfs4_clear_recover_bit(struct nfs4_client *clp) | |||
| 764 | /* | 630 | /* |
| 765 | * State recovery routine | 631 | * State recovery routine |
| 766 | */ | 632 | */ |
| 767 | static void nfs4_recover_state(struct nfs4_client *clp) | 633 | static void nfs4_recover_state(struct nfs_client *clp) |
| 768 | { | 634 | { |
| 769 | struct task_struct *task; | 635 | struct task_struct *task; |
| 770 | 636 | ||
| 771 | __module_get(THIS_MODULE); | 637 | __module_get(THIS_MODULE); |
| 772 | atomic_inc(&clp->cl_count); | 638 | atomic_inc(&clp->cl_count); |
| 773 | task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim", | 639 | task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim", |
| 774 | NIPQUAD(clp->cl_addr)); | 640 | NIPQUAD(clp->cl_addr.sin_addr)); |
| 775 | if (!IS_ERR(task)) | 641 | if (!IS_ERR(task)) |
| 776 | return; | 642 | return; |
| 777 | nfs4_clear_recover_bit(clp); | 643 | nfs4_clear_recover_bit(clp); |
| 778 | nfs4_put_client(clp); | 644 | nfs_put_client(clp); |
| 779 | module_put(THIS_MODULE); | 645 | module_put(THIS_MODULE); |
| 780 | } | 646 | } |
| 781 | 647 | ||
| 782 | /* | 648 | /* |
| 783 | * Schedule a state recovery attempt | 649 | * Schedule a state recovery attempt |
| 784 | */ | 650 | */ |
| 785 | void nfs4_schedule_state_recovery(struct nfs4_client *clp) | 651 | void nfs4_schedule_state_recovery(struct nfs_client *clp) |
| 786 | { | 652 | { |
| 787 | if (!clp) | 653 | if (!clp) |
| 788 | return; | 654 | return; |
| @@ -879,7 +745,7 @@ out_err: | |||
| 879 | return status; | 745 | return status; |
| 880 | } | 746 | } |
| 881 | 747 | ||
| 882 | static void nfs4_state_mark_reclaim(struct nfs4_client *clp) | 748 | static void nfs4_state_mark_reclaim(struct nfs_client *clp) |
| 883 | { | 749 | { |
| 884 | struct nfs4_state_owner *sp; | 750 | struct nfs4_state_owner *sp; |
| 885 | struct nfs4_state *state; | 751 | struct nfs4_state *state; |
| @@ -903,7 +769,7 @@ static void nfs4_state_mark_reclaim(struct nfs4_client *clp) | |||
| 903 | 769 | ||
| 904 | static int reclaimer(void *ptr) | 770 | static int reclaimer(void *ptr) |
| 905 | { | 771 | { |
| 906 | struct nfs4_client *clp = ptr; | 772 | struct nfs_client *clp = ptr; |
| 907 | struct nfs4_state_owner *sp; | 773 | struct nfs4_state_owner *sp; |
| 908 | struct nfs4_state_recovery_ops *ops; | 774 | struct nfs4_state_recovery_ops *ops; |
| 909 | struct rpc_cred *cred; | 775 | struct rpc_cred *cred; |
| @@ -970,12 +836,12 @@ out: | |||
| 970 | if (status == -NFS4ERR_CB_PATH_DOWN) | 836 | if (status == -NFS4ERR_CB_PATH_DOWN) |
| 971 | nfs_handle_cb_pathdown(clp); | 837 | nfs_handle_cb_pathdown(clp); |
| 972 | nfs4_clear_recover_bit(clp); | 838 | nfs4_clear_recover_bit(clp); |
| 973 | nfs4_put_client(clp); | 839 | nfs_put_client(clp); |
| 974 | module_put_and_exit(0); | 840 | module_put_and_exit(0); |
| 975 | return 0; | 841 | return 0; |
| 976 | out_error: | 842 | out_error: |
| 977 | printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n", | 843 | printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n", |
| 978 | NIPQUAD(clp->cl_addr.s_addr), -status); | 844 | NIPQUAD(clp->cl_addr.sin_addr), -status); |
| 979 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 845 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
| 980 | goto out; | 846 | goto out; |
| 981 | } | 847 | } |
