2 * linux/fs/nfs/callback_proc.c
4 * Copyright (C) 2004 Trond Myklebust
6 * NFSv4 callback procedures
8 #include <linux/nfs4.h>
9 #include <linux/nfs_fs.h>
10 #include <linux/slab.h>
13 #include "delegation.h"
18 #define NFSDBG_FACILITY NFSDBG_CALLBACK
21 __be32
nfs4_callback_getattr(struct cb_getattrargs
*args
,
22 struct cb_getattrres
*res
,
23 struct cb_process_state
*cps
)
25 struct nfs_delegation
*delegation
;
26 struct nfs_inode
*nfsi
;
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 */
33 res
->bitmap
[0] = res
->bitmap
[1] = 0;
34 res
->status
= htonl(NFS4ERR_BADHANDLE
);
36 dprintk("NFS: GETATTR callback request from %s\n",
37 rpc_peeraddr2str(cps
->clp
->cl_rpcclient
, RPC_DISPLAY_ADDR
));
39 inode
= nfs_delegation_find_inode(cps
->clp
, &args
->fh
);
44 delegation
= rcu_dereference(nfsi
->delegation
);
45 if (delegation
== NULL
|| (delegation
->type
& FMODE_WRITE
) == 0)
47 res
->size
= i_size_read(inode
);
48 res
->change_attr
= delegation
->change_attr
;
49 if (nfsi
->npages
!= 0)
51 res
->ctime
= inode
->i_ctime
;
52 res
->mtime
= inode
->i_mtime
;
53 res
->bitmap
[0] = (FATTR4_WORD0_CHANGE
|FATTR4_WORD0_SIZE
) &
55 res
->bitmap
[1] = (FATTR4_WORD1_TIME_METADATA
|FATTR4_WORD1_TIME_MODIFY
) &
62 dprintk("%s: exit with status = %d\n", __func__
, ntohl(res
->status
));
66 __be32
nfs4_callback_recall(struct cb_recallargs
*args
, void *dummy
,
67 struct cb_process_state
*cps
)
72 res
= htonl(NFS4ERR_OP_NOT_IN_SESSION
);
73 if (!cps
->clp
) /* Always set for v4.0. Set in cb_sequence for v4.1 */
76 dprintk("NFS: RECALL callback request from %s\n",
77 rpc_peeraddr2str(cps
->clp
->cl_rpcclient
, RPC_DISPLAY_ADDR
));
79 res
= htonl(NFS4ERR_BADHANDLE
);
80 inode
= nfs_delegation_find_inode(cps
->clp
, &args
->fh
);
83 /* Set up a helper thread to actually return the delegation */
84 switch (nfs_async_inode_return_delegation(inode
, &args
->stateid
)) {
90 res
= htonl(NFS4ERR_BAD_STATEID
);
93 res
= htonl(NFS4ERR_RESOURCE
);
97 dprintk("%s: exit with status = %d\n", __func__
, ntohl(res
));
101 int nfs4_validate_delegation_stateid(struct nfs_delegation
*delegation
, const nfs4_stateid
*stateid
)
103 if (delegation
== NULL
|| memcmp(delegation
->stateid
.data
, stateid
->data
,
104 sizeof(delegation
->stateid
.data
)) != 0)
109 #if defined(CONFIG_NFS_V4_1)
111 static u32
initiate_file_draining(struct nfs_client
*clp
,
112 struct cb_layoutrecallargs
*args
)
114 struct nfs_server
*server
;
115 struct pnfs_layout_hdr
*lo
;
118 u32 rv
= NFS4ERR_NOMATCHING_LAYOUT
;
119 LIST_HEAD(free_me_list
);
121 spin_lock(&clp
->cl_lock
);
123 list_for_each_entry_rcu(server
, &clp
->cl_superblocks
, client_link
) {
124 list_for_each_entry(lo
, &server
->layouts
, plh_layouts
) {
125 if (nfs_compare_fh(&args
->cbl_fh
,
126 &NFS_I(lo
->plh_inode
)->fh
))
128 ino
= igrab(lo
->plh_inode
);
132 /* Without this, layout can be freed as soon
133 * as we release cl_lock.
142 spin_unlock(&clp
->cl_lock
);
145 return NFS4ERR_NOMATCHING_LAYOUT
;
147 spin_lock(&ino
->i_lock
);
148 if (test_bit(NFS_LAYOUT_BULK_RECALL
, &lo
->plh_flags
) ||
149 mark_matching_lsegs_invalid(lo
, &free_me_list
,
153 rv
= NFS4ERR_NOMATCHING_LAYOUT
;
154 pnfs_set_layout_stateid(lo
, &args
->cbl_stateid
, true);
155 spin_unlock(&ino
->i_lock
);
156 pnfs_free_lseg_list(&free_me_list
);
162 static u32
initiate_bulk_draining(struct nfs_client
*clp
,
163 struct cb_layoutrecallargs
*args
)
165 struct nfs_server
*server
;
166 struct pnfs_layout_hdr
*lo
;
168 u32 rv
= NFS4ERR_NOMATCHING_LAYOUT
;
169 struct pnfs_layout_hdr
*tmp
;
170 LIST_HEAD(recall_list
);
171 LIST_HEAD(free_me_list
);
172 struct pnfs_layout_range range
= {
173 .iomode
= IOMODE_ANY
,
175 .length
= NFS4_MAX_UINT64
,
178 spin_lock(&clp
->cl_lock
);
180 list_for_each_entry_rcu(server
, &clp
->cl_superblocks
, client_link
) {
181 if ((args
->cbl_recall_type
== RETURN_FSID
) &&
182 memcmp(&server
->fsid
, &args
->cbl_fsid
,
183 sizeof(struct nfs_fsid
)))
186 list_for_each_entry(lo
, &server
->layouts
, plh_layouts
) {
187 if (!igrab(lo
->plh_inode
))
190 BUG_ON(!list_empty(&lo
->plh_bulk_recall
));
191 list_add(&lo
->plh_bulk_recall
, &recall_list
);
195 spin_unlock(&clp
->cl_lock
);
197 list_for_each_entry_safe(lo
, tmp
,
198 &recall_list
, plh_bulk_recall
) {
200 spin_lock(&ino
->i_lock
);
201 set_bit(NFS_LAYOUT_BULK_RECALL
, &lo
->plh_flags
);
202 if (mark_matching_lsegs_invalid(lo
, &free_me_list
, &range
))
204 list_del_init(&lo
->plh_bulk_recall
);
205 spin_unlock(&ino
->i_lock
);
206 pnfs_free_lseg_list(&free_me_list
);
213 static u32
do_callback_layoutrecall(struct nfs_client
*clp
,
214 struct cb_layoutrecallargs
*args
)
216 u32 res
= NFS4ERR_DELAY
;
218 dprintk("%s enter, type=%i\n", __func__
, args
->cbl_recall_type
);
219 if (test_and_set_bit(NFS4CLNT_LAYOUTRECALL
, &clp
->cl_state
))
221 if (args
->cbl_recall_type
== RETURN_FILE
)
222 res
= initiate_file_draining(clp
, args
);
224 res
= initiate_bulk_draining(clp
, args
);
225 clear_bit(NFS4CLNT_LAYOUTRECALL
, &clp
->cl_state
);
227 dprintk("%s returning %i\n", __func__
, res
);
232 __be32
nfs4_callback_layoutrecall(struct cb_layoutrecallargs
*args
,
233 void *dummy
, struct cb_process_state
*cps
)
237 dprintk("%s: -->\n", __func__
);
240 res
= do_callback_layoutrecall(cps
->clp
, args
);
242 res
= NFS4ERR_OP_NOT_IN_SESSION
;
244 dprintk("%s: exit with status = %d\n", __func__
, res
);
245 return cpu_to_be32(res
);
248 static void pnfs_recall_all_layouts(struct nfs_client
*clp
)
250 struct cb_layoutrecallargs args
;
252 /* Pretend we got a CB_LAYOUTRECALL(ALL) */
253 memset(&args
, 0, sizeof(args
));
254 args
.cbl_recall_type
= RETURN_ALL
;
255 /* FIXME we ignore errors, what should we do? */
256 do_callback_layoutrecall(clp
, &args
);
259 __be32
nfs4_callback_devicenotify(struct cb_devicenotifyargs
*args
,
260 void *dummy
, struct cb_process_state
*cps
)
264 struct nfs_client
*clp
= cps
->clp
;
265 struct nfs_server
*server
= NULL
;
267 dprintk("%s: -->\n", __func__
);
270 res
= cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION
);
274 for (i
= 0; i
< args
->ndevs
; i
++) {
275 struct cb_devicenotifyitem
*dev
= &args
->devs
[i
];
278 server
->pnfs_curr_ld
->id
!= dev
->cbd_layout_type
) {
280 list_for_each_entry_rcu(server
, &clp
->cl_superblocks
, client_link
)
281 if (server
->pnfs_curr_ld
&&
282 server
->pnfs_curr_ld
->id
== dev
->cbd_layout_type
) {
287 dprintk("%s: layout type %u not found\n",
288 __func__
, dev
->cbd_layout_type
);
293 if (dev
->cbd_notify_type
== NOTIFY_DEVICEID4_CHANGE
)
294 dprintk("%s: NOTIFY_DEVICEID4_CHANGE not supported, "
295 "deleting instead\n", __func__
);
296 nfs4_delete_deviceid(server
->pnfs_curr_ld
, clp
, &dev
->cbd_dev_id
);
301 dprintk("%s: exit with status = %u\n",
302 __func__
, be32_to_cpu(res
));
306 int nfs41_validate_delegation_stateid(struct nfs_delegation
*delegation
, const nfs4_stateid
*stateid
)
308 if (delegation
== NULL
)
311 if (stateid
->stateid
.seqid
!= 0)
313 if (memcmp(&delegation
->stateid
.stateid
.other
,
314 &stateid
->stateid
.other
,
315 NFS4_STATEID_OTHER_SIZE
))
322 * Validate the sequenceID sent by the server.
323 * Return success if the sequenceID is one more than what we last saw on
324 * this slot, accounting for wraparound. Increments the slot's sequence.
326 * We don't yet implement a duplicate request cache, instead we set the
327 * back channel ca_maxresponsesize_cached to zero. This is OK for now
328 * since we only currently implement idempotent callbacks anyway.
330 * We have a single slot backchannel at this time, so we don't bother
331 * checking the used_slots bit array on the table. The lower layer guarantees
332 * a single outstanding callback request at a time.
335 validate_seqid(struct nfs4_slot_table
*tbl
, struct cb_sequenceargs
* args
)
337 struct nfs4_slot
*slot
;
339 dprintk("%s enter. slotid %d seqid %d\n",
340 __func__
, args
->csa_slotid
, args
->csa_sequenceid
);
342 if (args
->csa_slotid
> NFS41_BC_MAX_CALLBACKS
)
343 return htonl(NFS4ERR_BADSLOT
);
345 slot
= tbl
->slots
+ args
->csa_slotid
;
346 dprintk("%s slot table seqid: %d\n", __func__
, slot
->seq_nr
);
349 if (likely(args
->csa_sequenceid
== slot
->seq_nr
+ 1)) {
355 if (args
->csa_sequenceid
== slot
->seq_nr
) {
356 dprintk("%s seqid %d is a replay\n",
357 __func__
, args
->csa_sequenceid
);
358 /* Signal process_op to set this error on next op */
359 if (args
->csa_cachethis
== 0)
360 return htonl(NFS4ERR_RETRY_UNCACHED_REP
);
362 /* The ca_maxresponsesize_cached is 0 with no DRC */
363 else if (args
->csa_cachethis
== 1)
364 return htonl(NFS4ERR_REP_TOO_BIG_TO_CACHE
);
368 if (args
->csa_sequenceid
== 1 && (slot
->seq_nr
+ 1) == 0) {
373 /* Misordered request */
374 return htonl(NFS4ERR_SEQ_MISORDERED
);
376 tbl
->highest_used_slotid
= args
->csa_slotid
;
377 return htonl(NFS4_OK
);
381 * For each referring call triple, check the session's slot table for
382 * a match. If the slot is in use and the sequence numbers match, the
383 * client is still waiting for a response to the original request.
385 static bool referring_call_exists(struct nfs_client
*clp
,
387 struct referring_call_list
*rclists
)
391 struct nfs4_session
*session
;
392 struct nfs4_slot_table
*tbl
;
393 struct referring_call_list
*rclist
;
394 struct referring_call
*ref
;
397 * XXX When client trunking is implemented, this becomes
398 * a session lookup from within the loop
400 session
= clp
->cl_session
;
401 tbl
= &session
->fc_slot_table
;
403 for (i
= 0; i
< nrclists
; i
++) {
404 rclist
= &rclists
[i
];
405 if (memcmp(session
->sess_id
.data
,
406 rclist
->rcl_sessionid
.data
,
407 NFS4_MAX_SESSIONID_LEN
) != 0)
410 for (j
= 0; j
< rclist
->rcl_nrefcalls
; j
++) {
411 ref
= &rclist
->rcl_refcalls
[j
];
413 dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u "
414 "slotid %u\n", __func__
,
415 ((u32
*)&rclist
->rcl_sessionid
.data
)[0],
416 ((u32
*)&rclist
->rcl_sessionid
.data
)[1],
417 ((u32
*)&rclist
->rcl_sessionid
.data
)[2],
418 ((u32
*)&rclist
->rcl_sessionid
.data
)[3],
419 ref
->rc_sequenceid
, ref
->rc_slotid
);
421 spin_lock(&tbl
->slot_tbl_lock
);
422 status
= (test_bit(ref
->rc_slotid
, tbl
->used_slots
) &&
423 tbl
->slots
[ref
->rc_slotid
].seq_nr
==
425 spin_unlock(&tbl
->slot_tbl_lock
);
435 __be32
nfs4_callback_sequence(struct cb_sequenceargs
*args
,
436 struct cb_sequenceres
*res
,
437 struct cb_process_state
*cps
)
439 struct nfs4_slot_table
*tbl
;
440 struct nfs_client
*clp
;
442 __be32 status
= htonl(NFS4ERR_BADSESSION
);
444 clp
= nfs4_find_client_sessionid(args
->csa_addr
, &args
->csa_sessionid
);
448 tbl
= &clp
->cl_session
->bc_slot_table
;
450 spin_lock(&tbl
->slot_tbl_lock
);
451 /* state manager is resetting the session */
452 if (test_bit(NFS4_SESSION_DRAINING
, &clp
->cl_session
->session_state
)) {
453 spin_unlock(&tbl
->slot_tbl_lock
);
454 status
= htonl(NFS4ERR_DELAY
);
455 /* Return NFS4ERR_BADSESSION if we're draining the session
456 * in order to reset it.
458 if (test_bit(NFS4CLNT_SESSION_RESET
, &clp
->cl_state
))
459 status
= htonl(NFS4ERR_BADSESSION
);
463 status
= validate_seqid(&clp
->cl_session
->bc_slot_table
, args
);
464 spin_unlock(&tbl
->slot_tbl_lock
);
468 cps
->slotid
= args
->csa_slotid
;
471 * Check for pending referring calls. If a match is found, a
472 * related callback was received before the response to the original
475 if (referring_call_exists(clp
, args
->csa_nrclists
, args
->csa_rclists
)) {
476 status
= htonl(NFS4ERR_DELAY
);
480 memcpy(&res
->csr_sessionid
, &args
->csa_sessionid
,
481 sizeof(res
->csr_sessionid
));
482 res
->csr_sequenceid
= args
->csa_sequenceid
;
483 res
->csr_slotid
= args
->csa_slotid
;
484 res
->csr_highestslotid
= NFS41_BC_MAX_CALLBACKS
- 1;
485 res
->csr_target_highestslotid
= NFS41_BC_MAX_CALLBACKS
- 1;
488 cps
->clp
= clp
; /* put in nfs4_callback_compound */
489 for (i
= 0; i
< args
->csa_nrclists
; i
++)
490 kfree(args
->csa_rclists
[i
].rcl_refcalls
);
491 kfree(args
->csa_rclists
);
493 if (status
== htonl(NFS4ERR_RETRY_UNCACHED_REP
)) {
494 cps
->drc_status
= status
;
497 res
->csr_status
= status
;
499 dprintk("%s: exit with status = %d res->csr_status %d\n", __func__
,
500 ntohl(status
), ntohl(res
->csr_status
));
505 validate_bitmap_values(unsigned long mask
)
507 return (mask
& ~RCA4_TYPE_MASK_ALL
) == 0;
510 __be32
nfs4_callback_recallany(struct cb_recallanyargs
*args
, void *dummy
,
511 struct cb_process_state
*cps
)
516 status
= cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION
);
517 if (!cps
->clp
) /* set in cb_sequence */
520 dprintk("NFS: RECALL_ANY callback request from %s\n",
521 rpc_peeraddr2str(cps
->clp
->cl_rpcclient
, RPC_DISPLAY_ADDR
));
523 status
= cpu_to_be32(NFS4ERR_INVAL
);
524 if (!validate_bitmap_values(args
->craa_type_mask
))
527 status
= cpu_to_be32(NFS4_OK
);
528 if (test_bit(RCA4_TYPE_MASK_RDATA_DLG
, (const unsigned long *)
529 &args
->craa_type_mask
))
531 if (test_bit(RCA4_TYPE_MASK_WDATA_DLG
, (const unsigned long *)
532 &args
->craa_type_mask
))
533 flags
|= FMODE_WRITE
;
534 if (test_bit(RCA4_TYPE_MASK_FILE_LAYOUT
, (const unsigned long *)
535 &args
->craa_type_mask
))
536 pnfs_recall_all_layouts(cps
->clp
);
538 nfs_expire_all_delegation_types(cps
->clp
, flags
);
540 dprintk("%s: exit with status = %d\n", __func__
, ntohl(status
));
544 /* Reduce the fore channel's max_slots to the target value */
545 __be32
nfs4_callback_recallslot(struct cb_recallslotargs
*args
, void *dummy
,
546 struct cb_process_state
*cps
)
548 struct nfs4_slot_table
*fc_tbl
;
551 status
= htonl(NFS4ERR_OP_NOT_IN_SESSION
);
552 if (!cps
->clp
) /* set in cb_sequence */
555 dprintk("NFS: CB_RECALL_SLOT request from %s target max slots %d\n",
556 rpc_peeraddr2str(cps
->clp
->cl_rpcclient
, RPC_DISPLAY_ADDR
),
557 args
->crsa_target_max_slots
);
559 fc_tbl
= &cps
->clp
->cl_session
->fc_slot_table
;
561 status
= htonl(NFS4ERR_BAD_HIGH_SLOT
);
562 if (args
->crsa_target_max_slots
> fc_tbl
->max_slots
||
563 args
->crsa_target_max_slots
< 1)
566 status
= htonl(NFS4_OK
);
567 if (args
->crsa_target_max_slots
== fc_tbl
->max_slots
)
570 fc_tbl
->target_max_slots
= args
->crsa_target_max_slots
;
571 nfs41_handle_recall_slot(cps
->clp
);
573 dprintk("%s: exit with status = %d\n", __func__
, ntohl(status
));
576 #endif /* CONFIG_NFS_V4_1 */