aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c174
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
56const nfs4_stateid zero_stateid; 57const nfs4_stateid zero_stateid;
57 58
58static DEFINE_SPINLOCK(state_spinlock);
59static LIST_HEAD(nfs4_clientid_list); 59static LIST_HEAD(nfs4_clientid_list);
60 60
61void 61static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
62init_nfsv4_state(struct nfs_server *server)
63{
64 server->nfs4_state = NULL;
65 INIT_LIST_HEAD(&server->nfs4_siblings);
66}
67
68void
69destroy_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 */
86static struct nfs4_client *
87nfs4_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
113static void
114nfs4_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
133static 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
145struct 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
154struct nfs4_client *
155nfs4_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
182void
183nfs4_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
195static 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
206u32 72u32
207nfs4_alloc_lockowner_id(struct nfs4_client *clp) 73nfs4_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
212static struct nfs4_state_owner * 78static struct nfs4_state_owner *
213nfs4_client_grab_unused(struct nfs4_client *clp, struct rpc_cred *cred) 79nfs4_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
227struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp) 93struct 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
241struct rpc_cred *nfs4_get_setclientid_cred(struct nfs4_client *clp) 107struct 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
253static struct nfs4_state_owner * 119static struct nfs4_state_owner *
254nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred) 120nfs4_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)
294void 160void
295nfs4_drop_state_owner(struct nfs4_state_owner *sp) 161nfs4_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 */
307struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred) 173struct 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 */
338void nfs4_put_state_owner(struct nfs4_state_owner *sp) 204void 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)
540static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) 406static 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
753static int reclaimer(void *); 619static int reclaimer(void *);
754 620
755static inline void nfs4_clear_recover_bit(struct nfs4_client *clp) 621static 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 */
767static void nfs4_recover_state(struct nfs4_client *clp) 633static 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 */
785void nfs4_schedule_state_recovery(struct nfs4_client *clp) 651void 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
882static void nfs4_state_mark_reclaim(struct nfs4_client *clp) 748static 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
904static int reclaimer(void *ptr) 770static 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;
976out_error: 842out_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}