aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback_proc.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/nfs/callback_proc.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/nfs/callback_proc.c')
-rw-r--r--fs/nfs/callback_proc.c379
1 files changed, 268 insertions, 111 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 930d10fecdaf..d4d1954e9bb9 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -12,30 +12,33 @@
12#include "callback.h" 12#include "callback.h"
13#include "delegation.h" 13#include "delegation.h"
14#include "internal.h" 14#include "internal.h"
15#include "pnfs.h"
15 16
16#ifdef NFS_DEBUG 17#ifdef NFS_DEBUG
17#define NFSDBG_FACILITY NFSDBG_CALLBACK 18#define NFSDBG_FACILITY NFSDBG_CALLBACK
18#endif 19#endif
19 20
20__be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res) 21__be32 nfs4_callback_getattr(struct cb_getattrargs *args,
22 struct cb_getattrres *res,
23 struct cb_process_state *cps)
21{ 24{
22 struct nfs_client *clp;
23 struct nfs_delegation *delegation; 25 struct nfs_delegation *delegation;
24 struct nfs_inode *nfsi; 26 struct nfs_inode *nfsi;
25 struct inode *inode; 27 struct inode *inode;
26 28
29 res->status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
30 if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */
31 goto out;
32
27 res->bitmap[0] = res->bitmap[1] = 0; 33 res->bitmap[0] = res->bitmap[1] = 0;
28 res->status = htonl(NFS4ERR_BADHANDLE); 34 res->status = htonl(NFS4ERR_BADHANDLE);
29 clp = nfs_find_client(args->addr, 4);
30 if (clp == NULL)
31 goto out;
32 35
33 dprintk("NFS: GETATTR callback request from %s\n", 36 dprintk("NFS: GETATTR callback request from %s\n",
34 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); 37 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
35 38
36 inode = nfs_delegation_find_inode(clp, &args->fh); 39 inode = nfs_delegation_find_inode(cps->clp, &args->fh);
37 if (inode == NULL) 40 if (inode == NULL)
38 goto out_putclient; 41 goto out;
39 nfsi = NFS_I(inode); 42 nfsi = NFS_I(inode);
40 rcu_read_lock(); 43 rcu_read_lock();
41 delegation = rcu_dereference(nfsi->delegation); 44 delegation = rcu_dereference(nfsi->delegation);
@@ -55,49 +58,41 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *
55out_iput: 58out_iput:
56 rcu_read_unlock(); 59 rcu_read_unlock();
57 iput(inode); 60 iput(inode);
58out_putclient:
59 nfs_put_client(clp);
60out: 61out:
61 dprintk("%s: exit with status = %d\n", __func__, ntohl(res->status)); 62 dprintk("%s: exit with status = %d\n", __func__, ntohl(res->status));
62 return res->status; 63 return res->status;
63} 64}
64 65
65__be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) 66__be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
67 struct cb_process_state *cps)
66{ 68{
67 struct nfs_client *clp;
68 struct inode *inode; 69 struct inode *inode;
69 __be32 res; 70 __be32 res;
70 71
71 res = htonl(NFS4ERR_BADHANDLE); 72 res = htonl(NFS4ERR_OP_NOT_IN_SESSION);
72 clp = nfs_find_client(args->addr, 4); 73 if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */
73 if (clp == NULL)
74 goto out; 74 goto out;
75 75
76 dprintk("NFS: RECALL callback request from %s\n", 76 dprintk("NFS: RECALL callback request from %s\n",
77 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); 77 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
78 78
79 do { 79 res = htonl(NFS4ERR_BADHANDLE);
80 struct nfs_client *prev = clp; 80 inode = nfs_delegation_find_inode(cps->clp, &args->fh);
81 81 if (inode == NULL)
82 inode = nfs_delegation_find_inode(clp, &args->fh); 82 goto out;
83 if (inode != NULL) { 83 /* Set up a helper thread to actually return the delegation */
84 /* Set up a helper thread to actually return the delegation */ 84 switch (nfs_async_inode_return_delegation(inode, &args->stateid)) {
85 switch (nfs_async_inode_return_delegation(inode, &args->stateid)) { 85 case 0:
86 case 0: 86 res = 0;
87 res = 0; 87 break;
88 break; 88 case -ENOENT:
89 case -ENOENT: 89 if (res != 0)
90 if (res != 0) 90 res = htonl(NFS4ERR_BAD_STATEID);
91 res = htonl(NFS4ERR_BAD_STATEID); 91 break;
92 break; 92 default:
93 default: 93 res = htonl(NFS4ERR_RESOURCE);
94 res = htonl(NFS4ERR_RESOURCE); 94 }
95 } 95 iput(inode);
96 iput(inode);
97 }
98 clp = nfs_find_client_next(prev);
99 nfs_put_client(prev);
100 } while (clp != NULL);
101out: 96out:
102 dprintk("%s: exit with status = %d\n", __func__, ntohl(res)); 97 dprintk("%s: exit with status = %d\n", __func__, ntohl(res));
103 return res; 98 return res;
@@ -113,16 +108,196 @@ int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nf
113 108
114#if defined(CONFIG_NFS_V4_1) 109#if defined(CONFIG_NFS_V4_1)
115 110
111static u32 initiate_file_draining(struct nfs_client *clp,
112 struct cb_layoutrecallargs *args)
113{
114 struct pnfs_layout_hdr *lo;
115 struct inode *ino;
116 bool found = false;
117 u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
118 LIST_HEAD(free_me_list);
119
120 spin_lock(&clp->cl_lock);
121 list_for_each_entry(lo, &clp->cl_layouts, plh_layouts) {
122 if (nfs_compare_fh(&args->cbl_fh,
123 &NFS_I(lo->plh_inode)->fh))
124 continue;
125 ino = igrab(lo->plh_inode);
126 if (!ino)
127 continue;
128 found = true;
129 /* Without this, layout can be freed as soon
130 * as we release cl_lock.
131 */
132 get_layout_hdr(lo);
133 break;
134 }
135 spin_unlock(&clp->cl_lock);
136 if (!found)
137 return NFS4ERR_NOMATCHING_LAYOUT;
138
139 spin_lock(&ino->i_lock);
140 if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) ||
141 mark_matching_lsegs_invalid(lo, &free_me_list,
142 &args->cbl_range))
143 rv = NFS4ERR_DELAY;
144 else
145 rv = NFS4ERR_NOMATCHING_LAYOUT;
146 pnfs_set_layout_stateid(lo, &args->cbl_stateid, true);
147 spin_unlock(&ino->i_lock);
148 pnfs_free_lseg_list(&free_me_list);
149 put_layout_hdr(lo);
150 iput(ino);
151 return rv;
152}
153
154static u32 initiate_bulk_draining(struct nfs_client *clp,
155 struct cb_layoutrecallargs *args)
156{
157 struct pnfs_layout_hdr *lo;
158 struct inode *ino;
159 u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
160 struct pnfs_layout_hdr *tmp;
161 LIST_HEAD(recall_list);
162 LIST_HEAD(free_me_list);
163 struct pnfs_layout_range range = {
164 .iomode = IOMODE_ANY,
165 .offset = 0,
166 .length = NFS4_MAX_UINT64,
167 };
168
169 spin_lock(&clp->cl_lock);
170 list_for_each_entry(lo, &clp->cl_layouts, plh_layouts) {
171 if ((args->cbl_recall_type == RETURN_FSID) &&
172 memcmp(&NFS_SERVER(lo->plh_inode)->fsid,
173 &args->cbl_fsid, sizeof(struct nfs_fsid)))
174 continue;
175 if (!igrab(lo->plh_inode))
176 continue;
177 get_layout_hdr(lo);
178 BUG_ON(!list_empty(&lo->plh_bulk_recall));
179 list_add(&lo->plh_bulk_recall, &recall_list);
180 }
181 spin_unlock(&clp->cl_lock);
182 list_for_each_entry_safe(lo, tmp,
183 &recall_list, plh_bulk_recall) {
184 ino = lo->plh_inode;
185 spin_lock(&ino->i_lock);
186 set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
187 if (mark_matching_lsegs_invalid(lo, &free_me_list, &range))
188 rv = NFS4ERR_DELAY;
189 list_del_init(&lo->plh_bulk_recall);
190 spin_unlock(&ino->i_lock);
191 pnfs_free_lseg_list(&free_me_list);
192 put_layout_hdr(lo);
193 iput(ino);
194 }
195 return rv;
196}
197
198static u32 do_callback_layoutrecall(struct nfs_client *clp,
199 struct cb_layoutrecallargs *args)
200{
201 u32 res = NFS4ERR_DELAY;
202
203 dprintk("%s enter, type=%i\n", __func__, args->cbl_recall_type);
204 if (test_and_set_bit(NFS4CLNT_LAYOUTRECALL, &clp->cl_state))
205 goto out;
206 if (args->cbl_recall_type == RETURN_FILE)
207 res = initiate_file_draining(clp, args);
208 else
209 res = initiate_bulk_draining(clp, args);
210 clear_bit(NFS4CLNT_LAYOUTRECALL, &clp->cl_state);
211out:
212 dprintk("%s returning %i\n", __func__, res);
213 return res;
214
215}
216
217__be32 nfs4_callback_layoutrecall(struct cb_layoutrecallargs *args,
218 void *dummy, struct cb_process_state *cps)
219{
220 u32 res;
221
222 dprintk("%s: -->\n", __func__);
223
224 if (cps->clp)
225 res = do_callback_layoutrecall(cps->clp, args);
226 else
227 res = NFS4ERR_OP_NOT_IN_SESSION;
228
229 dprintk("%s: exit with status = %d\n", __func__, res);
230 return cpu_to_be32(res);
231}
232
233static void pnfs_recall_all_layouts(struct nfs_client *clp)
234{
235 struct cb_layoutrecallargs args;
236
237 /* Pretend we got a CB_LAYOUTRECALL(ALL) */
238 memset(&args, 0, sizeof(args));
239 args.cbl_recall_type = RETURN_ALL;
240 /* FIXME we ignore errors, what should we do? */
241 do_callback_layoutrecall(clp, &args);
242}
243
244__be32 nfs4_callback_devicenotify(struct cb_devicenotifyargs *args,
245 void *dummy, struct cb_process_state *cps)
246{
247 int i;
248 __be32 res = 0;
249 struct nfs_client *clp = cps->clp;
250 struct nfs_server *server = NULL;
251
252 dprintk("%s: -->\n", __func__);
253
254 if (!clp) {
255 res = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
256 goto out;
257 }
258
259 for (i = 0; i < args->ndevs; i++) {
260 struct cb_devicenotifyitem *dev = &args->devs[i];
261
262 if (!server ||
263 server->pnfs_curr_ld->id != dev->cbd_layout_type) {
264 rcu_read_lock();
265 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
266 if (server->pnfs_curr_ld &&
267 server->pnfs_curr_ld->id == dev->cbd_layout_type) {
268 rcu_read_unlock();
269 goto found;
270 }
271 rcu_read_unlock();
272 dprintk("%s: layout type %u not found\n",
273 __func__, dev->cbd_layout_type);
274 continue;
275 }
276
277 found:
278 if (dev->cbd_notify_type == NOTIFY_DEVICEID4_CHANGE)
279 dprintk("%s: NOTIFY_DEVICEID4_CHANGE not supported, "
280 "deleting instead\n", __func__);
281 nfs4_delete_deviceid(server->pnfs_curr_ld, clp, &dev->cbd_dev_id);
282 }
283
284out:
285 kfree(args->devs);
286 dprintk("%s: exit with status = %u\n",
287 __func__, be32_to_cpu(res));
288 return res;
289}
290
116int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) 291int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid)
117{ 292{
118 if (delegation == NULL) 293 if (delegation == NULL)
119 return 0; 294 return 0;
120 295
121 /* seqid is 4-bytes long */ 296 if (stateid->stateid.seqid != 0)
122 if (((u32 *) &stateid->data)[0] != 0)
123 return 0; 297 return 0;
124 if (memcmp(&delegation->stateid.data[4], &stateid->data[4], 298 if (memcmp(&delegation->stateid.stateid.other,
125 sizeof(stateid->data)-4)) 299 &stateid->stateid.other,
300 NFS4_STATEID_OTHER_SIZE))
126 return 0; 301 return 0;
127 302
128 return 1; 303 return 1;
@@ -185,42 +360,6 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
185} 360}
186 361
187/* 362/*
188 * Returns a pointer to a held 'struct nfs_client' that matches the server's
189 * address, major version number, and session ID. It is the caller's
190 * responsibility to release the returned reference.
191 *
192 * Returns NULL if there are no connections with sessions, or if no session
193 * matches the one of interest.
194 */
195 static struct nfs_client *find_client_with_session(
196 const struct sockaddr *addr, u32 nfsversion,
197 struct nfs4_sessionid *sessionid)
198{
199 struct nfs_client *clp;
200
201 clp = nfs_find_client(addr, 4);
202 if (clp == NULL)
203 return NULL;
204
205 do {
206 struct nfs_client *prev = clp;
207
208 if (clp->cl_session != NULL) {
209 if (memcmp(clp->cl_session->sess_id.data,
210 sessionid->data,
211 NFS4_MAX_SESSIONID_LEN) == 0) {
212 /* Returns a held reference to clp */
213 return clp;
214 }
215 }
216 clp = nfs_find_client_next(prev);
217 nfs_put_client(prev);
218 } while (clp != NULL);
219
220 return NULL;
221}
222
223/*
224 * For each referring call triple, check the session's slot table for 363 * For each referring call triple, check the session's slot table for
225 * a match. If the slot is in use and the sequence numbers match, the 364 * a match. If the slot is in use and the sequence numbers match, the
226 * client is still waiting for a response to the original request. 365 * client is still waiting for a response to the original request.
@@ -276,20 +415,28 @@ out:
276} 415}
277 416
278__be32 nfs4_callback_sequence(struct cb_sequenceargs *args, 417__be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
279 struct cb_sequenceres *res) 418 struct cb_sequenceres *res,
419 struct cb_process_state *cps)
280{ 420{
281 struct nfs_client *clp; 421 struct nfs_client *clp;
282 int i; 422 int i;
283 __be32 status; 423 __be32 status = htonl(NFS4ERR_BADSESSION);
284 424
285 status = htonl(NFS4ERR_BADSESSION); 425 cps->clp = NULL;
286 clp = find_client_with_session(args->csa_addr, 4, &args->csa_sessionid); 426
427 clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid);
287 if (clp == NULL) 428 if (clp == NULL)
288 goto out; 429 goto out;
289 430
431 /* state manager is resetting the session */
432 if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) {
433 status = NFS4ERR_DELAY;
434 goto out;
435 }
436
290 status = validate_seqid(&clp->cl_session->bc_slot_table, args); 437 status = validate_seqid(&clp->cl_session->bc_slot_table, args);
291 if (status) 438 if (status)
292 goto out_putclient; 439 goto out;
293 440
294 /* 441 /*
295 * Check for pending referring calls. If a match is found, a 442 * Check for pending referring calls. If a match is found, a
@@ -298,7 +445,7 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
298 */ 445 */
299 if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists)) { 446 if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists)) {
300 status = htonl(NFS4ERR_DELAY); 447 status = htonl(NFS4ERR_DELAY);
301 goto out_putclient; 448 goto out;
302 } 449 }
303 450
304 memcpy(&res->csr_sessionid, &args->csa_sessionid, 451 memcpy(&res->csr_sessionid, &args->csa_sessionid,
@@ -307,83 +454,93 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
307 res->csr_slotid = args->csa_slotid; 454 res->csr_slotid = args->csa_slotid;
308 res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1; 455 res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
309 res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1; 456 res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
457 nfs4_cb_take_slot(clp);
310 458
311out_putclient:
312 nfs_put_client(clp);
313out: 459out:
460 cps->clp = clp; /* put in nfs4_callback_compound */
314 for (i = 0; i < args->csa_nrclists; i++) 461 for (i = 0; i < args->csa_nrclists; i++)
315 kfree(args->csa_rclists[i].rcl_refcalls); 462 kfree(args->csa_rclists[i].rcl_refcalls);
316 kfree(args->csa_rclists); 463 kfree(args->csa_rclists);
317 464
318 if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP)) 465 if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP)) {
319 res->csr_status = 0; 466 cps->drc_status = status;
320 else 467 status = 0;
468 } else
321 res->csr_status = status; 469 res->csr_status = status;
470
322 dprintk("%s: exit with status = %d res->csr_status %d\n", __func__, 471 dprintk("%s: exit with status = %d res->csr_status %d\n", __func__,
323 ntohl(status), ntohl(res->csr_status)); 472 ntohl(status), ntohl(res->csr_status));
324 return status; 473 return status;
325} 474}
326 475
327__be32 nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy) 476static bool
477validate_bitmap_values(unsigned long mask)
478{
479 return (mask & ~RCA4_TYPE_MASK_ALL) == 0;
480}
481
482__be32 nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy,
483 struct cb_process_state *cps)
328{ 484{
329 struct nfs_client *clp;
330 __be32 status; 485 __be32 status;
331 fmode_t flags = 0; 486 fmode_t flags = 0;
332 487
333 status = htonl(NFS4ERR_OP_NOT_IN_SESSION); 488 status = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
334 clp = nfs_find_client(args->craa_addr, 4); 489 if (!cps->clp) /* set in cb_sequence */
335 if (clp == NULL)
336 goto out; 490 goto out;
337 491
338 dprintk("NFS: RECALL_ANY callback request from %s\n", 492 dprintk("NFS: RECALL_ANY callback request from %s\n",
339 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); 493 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
340 494
495 status = cpu_to_be32(NFS4ERR_INVAL);
496 if (!validate_bitmap_values(args->craa_type_mask))
497 goto out;
498
499 status = cpu_to_be32(NFS4_OK);
341 if (test_bit(RCA4_TYPE_MASK_RDATA_DLG, (const unsigned long *) 500 if (test_bit(RCA4_TYPE_MASK_RDATA_DLG, (const unsigned long *)
342 &args->craa_type_mask)) 501 &args->craa_type_mask))
343 flags = FMODE_READ; 502 flags = FMODE_READ;
344 if (test_bit(RCA4_TYPE_MASK_WDATA_DLG, (const unsigned long *) 503 if (test_bit(RCA4_TYPE_MASK_WDATA_DLG, (const unsigned long *)
345 &args->craa_type_mask)) 504 &args->craa_type_mask))
346 flags |= FMODE_WRITE; 505 flags |= FMODE_WRITE;
347 506 if (test_bit(RCA4_TYPE_MASK_FILE_LAYOUT, (const unsigned long *)
507 &args->craa_type_mask))
508 pnfs_recall_all_layouts(cps->clp);
348 if (flags) 509 if (flags)
349 nfs_expire_all_delegation_types(clp, flags); 510 nfs_expire_all_delegation_types(cps->clp, flags);
350 status = htonl(NFS4_OK);
351out: 511out:
352 dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); 512 dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
353 return status; 513 return status;
354} 514}
355 515
356/* Reduce the fore channel's max_slots to the target value */ 516/* Reduce the fore channel's max_slots to the target value */
357__be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy) 517__be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy,
518 struct cb_process_state *cps)
358{ 519{
359 struct nfs_client *clp;
360 struct nfs4_slot_table *fc_tbl; 520 struct nfs4_slot_table *fc_tbl;
361 __be32 status; 521 __be32 status;
362 522
363 status = htonl(NFS4ERR_OP_NOT_IN_SESSION); 523 status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
364 clp = nfs_find_client(args->crsa_addr, 4); 524 if (!cps->clp) /* set in cb_sequence */
365 if (clp == NULL)
366 goto out; 525 goto out;
367 526
368 dprintk("NFS: CB_RECALL_SLOT request from %s target max slots %d\n", 527 dprintk("NFS: CB_RECALL_SLOT request from %s target max slots %d\n",
369 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR), 528 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR),
370 args->crsa_target_max_slots); 529 args->crsa_target_max_slots);
371 530
372 fc_tbl = &clp->cl_session->fc_slot_table; 531 fc_tbl = &cps->clp->cl_session->fc_slot_table;
373 532
374 status = htonl(NFS4ERR_BAD_HIGH_SLOT); 533 status = htonl(NFS4ERR_BAD_HIGH_SLOT);
375 if (args->crsa_target_max_slots > fc_tbl->max_slots || 534 if (args->crsa_target_max_slots > fc_tbl->max_slots ||
376 args->crsa_target_max_slots < 1) 535 args->crsa_target_max_slots < 1)
377 goto out_putclient; 536 goto out;
378 537
379 status = htonl(NFS4_OK); 538 status = htonl(NFS4_OK);
380 if (args->crsa_target_max_slots == fc_tbl->max_slots) 539 if (args->crsa_target_max_slots == fc_tbl->max_slots)
381 goto out_putclient; 540 goto out;
382 541
383 fc_tbl->target_max_slots = args->crsa_target_max_slots; 542 fc_tbl->target_max_slots = args->crsa_target_max_slots;
384 nfs41_handle_recall_slot(clp); 543 nfs41_handle_recall_slot(cps->clp);
385out_putclient:
386 nfs_put_client(clp); /* balance nfs_find_client */
387out: 544out:
388 dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); 545 dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
389 return status; 546 return status;