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