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 | } |