NFS: Clean up nfs4_proc_setclientid() and friends
[pandora-kernel.git] / fs / nfs / callback_proc.c
1 /*
2  * linux/fs/nfs/callback_proc.c
3  *
4  * Copyright (C) 2004 Trond Myklebust
5  *
6  * NFSv4 callback procedures
7  */
8 #include <linux/nfs4.h>
9 #include <linux/nfs_fs.h>
10 #include <linux/slab.h>
11 #include <linux/rcupdate.h>
12 #include "nfs4_fs.h"
13 #include "callback.h"
14 #include "delegation.h"
15 #include "internal.h"
16 #include "pnfs.h"
17
18 #ifdef NFS_DEBUG
19 #define NFSDBG_FACILITY NFSDBG_CALLBACK
20 #endif
21
22 __be32 nfs4_callback_getattr(struct cb_getattrargs *args,
23                              struct cb_getattrres *res,
24                              struct cb_process_state *cps)
25 {
26         struct nfs_delegation *delegation;
27         struct nfs_inode *nfsi;
28         struct inode *inode;
29
30         res->status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
31         if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */
32                 goto out;
33
34         res->bitmap[0] = res->bitmap[1] = 0;
35         res->status = htonl(NFS4ERR_BADHANDLE);
36
37         dprintk_rcu("NFS: GETATTR callback request from %s\n",
38                 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
39
40         inode = nfs_delegation_find_inode(cps->clp, &args->fh);
41         if (inode == NULL)
42                 goto out;
43         nfsi = NFS_I(inode);
44         rcu_read_lock();
45         delegation = rcu_dereference(nfsi->delegation);
46         if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0)
47                 goto out_iput;
48         res->size = i_size_read(inode);
49         res->change_attr = delegation->change_attr;
50         if (nfsi->npages != 0)
51                 res->change_attr++;
52         res->ctime = inode->i_ctime;
53         res->mtime = inode->i_mtime;
54         res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) &
55                 args->bitmap[0];
56         res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) &
57                 args->bitmap[1];
58         res->status = 0;
59 out_iput:
60         rcu_read_unlock();
61         iput(inode);
62 out:
63         dprintk("%s: exit with status = %d\n", __func__, ntohl(res->status));
64         return res->status;
65 }
66
67 __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
68                             struct cb_process_state *cps)
69 {
70         struct inode *inode;
71         __be32 res;
72         
73         res = htonl(NFS4ERR_OP_NOT_IN_SESSION);
74         if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */
75                 goto out;
76
77         dprintk_rcu("NFS: RECALL callback request from %s\n",
78                 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
79
80         res = htonl(NFS4ERR_BADHANDLE);
81         inode = nfs_delegation_find_inode(cps->clp, &args->fh);
82         if (inode == NULL)
83                 goto out;
84         /* Set up a helper thread to actually return the delegation */
85         switch (nfs_async_inode_return_delegation(inode, &args->stateid)) {
86         case 0:
87                 res = 0;
88                 break;
89         case -ENOENT:
90                 res = htonl(NFS4ERR_BAD_STATEID);
91                 break;
92         default:
93                 res = htonl(NFS4ERR_RESOURCE);
94         }
95         iput(inode);
96 out:
97         dprintk("%s: exit with status = %d\n", __func__, ntohl(res));
98         return res;
99 }
100
101 #if defined(CONFIG_NFS_V4_1)
102
103 /*
104  * Lookup a layout by filehandle.
105  *
106  * Note: gets a refcount on the layout hdr and on its respective inode.
107  * Caller must put the layout hdr and the inode.
108  *
109  * TODO: keep track of all layouts (and delegations) in a hash table
110  * hashed by filehandle.
111  */
112 static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp, struct nfs_fh *fh)
113 {
114         struct nfs_server *server;
115         struct inode *ino;
116         struct pnfs_layout_hdr *lo;
117
118         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
119                 list_for_each_entry(lo, &server->layouts, plh_layouts) {
120                         if (nfs_compare_fh(fh, &NFS_I(lo->plh_inode)->fh))
121                                 continue;
122                         ino = igrab(lo->plh_inode);
123                         if (!ino)
124                                 continue;
125                         get_layout_hdr(lo);
126                         return lo;
127                 }
128         }
129
130         return NULL;
131 }
132
133 static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp, struct nfs_fh *fh)
134 {
135         struct pnfs_layout_hdr *lo;
136
137         spin_lock(&clp->cl_lock);
138         rcu_read_lock();
139         lo = get_layout_by_fh_locked(clp, fh);
140         rcu_read_unlock();
141         spin_unlock(&clp->cl_lock);
142
143         return lo;
144 }
145
146 static u32 initiate_file_draining(struct nfs_client *clp,
147                                   struct cb_layoutrecallargs *args)
148 {
149         struct inode *ino;
150         struct pnfs_layout_hdr *lo;
151         u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
152         LIST_HEAD(free_me_list);
153
154         lo = get_layout_by_fh(clp, &args->cbl_fh);
155         if (!lo)
156                 return NFS4ERR_NOMATCHING_LAYOUT;
157
158         ino = lo->plh_inode;
159         spin_lock(&ino->i_lock);
160         if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) ||
161             mark_matching_lsegs_invalid(lo, &free_me_list,
162                                         &args->cbl_range))
163                 rv = NFS4ERR_DELAY;
164         else
165                 rv = NFS4ERR_NOMATCHING_LAYOUT;
166         pnfs_set_layout_stateid(lo, &args->cbl_stateid, true);
167         spin_unlock(&ino->i_lock);
168         pnfs_free_lseg_list(&free_me_list);
169         put_layout_hdr(lo);
170         iput(ino);
171         return rv;
172 }
173
174 static u32 initiate_bulk_draining(struct nfs_client *clp,
175                                   struct cb_layoutrecallargs *args)
176 {
177         struct nfs_server *server;
178         struct pnfs_layout_hdr *lo;
179         struct inode *ino;
180         u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
181         struct pnfs_layout_hdr *tmp;
182         LIST_HEAD(recall_list);
183         LIST_HEAD(free_me_list);
184         struct pnfs_layout_range range = {
185                 .iomode = IOMODE_ANY,
186                 .offset = 0,
187                 .length = NFS4_MAX_UINT64,
188         };
189
190         spin_lock(&clp->cl_lock);
191         rcu_read_lock();
192         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
193                 if ((args->cbl_recall_type == RETURN_FSID) &&
194                     memcmp(&server->fsid, &args->cbl_fsid,
195                            sizeof(struct nfs_fsid)))
196                         continue;
197
198                 list_for_each_entry(lo, &server->layouts, plh_layouts) {
199                         if (!igrab(lo->plh_inode))
200                                 continue;
201                         get_layout_hdr(lo);
202                         BUG_ON(!list_empty(&lo->plh_bulk_recall));
203                         list_add(&lo->plh_bulk_recall, &recall_list);
204                 }
205         }
206         rcu_read_unlock();
207         spin_unlock(&clp->cl_lock);
208
209         list_for_each_entry_safe(lo, tmp,
210                                  &recall_list, plh_bulk_recall) {
211                 ino = lo->plh_inode;
212                 spin_lock(&ino->i_lock);
213                 set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
214                 if (mark_matching_lsegs_invalid(lo, &free_me_list, &range))
215                         rv = NFS4ERR_DELAY;
216                 list_del_init(&lo->plh_bulk_recall);
217                 spin_unlock(&ino->i_lock);
218                 pnfs_free_lseg_list(&free_me_list);
219                 put_layout_hdr(lo);
220                 iput(ino);
221         }
222         return rv;
223 }
224
225 static u32 do_callback_layoutrecall(struct nfs_client *clp,
226                                     struct cb_layoutrecallargs *args)
227 {
228         u32 res;
229
230         dprintk("%s enter, type=%i\n", __func__, args->cbl_recall_type);
231         if (args->cbl_recall_type == RETURN_FILE)
232                 res = initiate_file_draining(clp, args);
233         else
234                 res = initiate_bulk_draining(clp, args);
235         dprintk("%s returning %i\n", __func__, res);
236         return res;
237
238 }
239
240 __be32 nfs4_callback_layoutrecall(struct cb_layoutrecallargs *args,
241                                   void *dummy, struct cb_process_state *cps)
242 {
243         u32 res;
244
245         dprintk("%s: -->\n", __func__);
246
247         if (cps->clp)
248                 res = do_callback_layoutrecall(cps->clp, args);
249         else
250                 res = NFS4ERR_OP_NOT_IN_SESSION;
251
252         dprintk("%s: exit with status = %d\n", __func__, res);
253         return cpu_to_be32(res);
254 }
255
256 static void pnfs_recall_all_layouts(struct nfs_client *clp)
257 {
258         struct cb_layoutrecallargs args;
259
260         /* Pretend we got a CB_LAYOUTRECALL(ALL) */
261         memset(&args, 0, sizeof(args));
262         args.cbl_recall_type = RETURN_ALL;
263         /* FIXME we ignore errors, what should we do? */
264         do_callback_layoutrecall(clp, &args);
265 }
266
267 __be32 nfs4_callback_devicenotify(struct cb_devicenotifyargs *args,
268                                   void *dummy, struct cb_process_state *cps)
269 {
270         int i;
271         __be32 res = 0;
272         struct nfs_client *clp = cps->clp;
273         struct nfs_server *server = NULL;
274
275         dprintk("%s: -->\n", __func__);
276
277         if (!clp) {
278                 res = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
279                 goto out;
280         }
281
282         for (i = 0; i < args->ndevs; i++) {
283                 struct cb_devicenotifyitem *dev = &args->devs[i];
284
285                 if (!server ||
286                     server->pnfs_curr_ld->id != dev->cbd_layout_type) {
287                         rcu_read_lock();
288                         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
289                                 if (server->pnfs_curr_ld &&
290                                     server->pnfs_curr_ld->id == dev->cbd_layout_type) {
291                                         rcu_read_unlock();
292                                         goto found;
293                                 }
294                         rcu_read_unlock();
295                         dprintk("%s: layout type %u not found\n",
296                                 __func__, dev->cbd_layout_type);
297                         continue;
298                 }
299
300         found:
301                 if (dev->cbd_notify_type == NOTIFY_DEVICEID4_CHANGE)
302                         dprintk("%s: NOTIFY_DEVICEID4_CHANGE not supported, "
303                                 "deleting instead\n", __func__);
304                 nfs4_delete_deviceid(server->pnfs_curr_ld, clp, &dev->cbd_dev_id);
305         }
306
307 out:
308         kfree(args->devs);
309         dprintk("%s: exit with status = %u\n",
310                 __func__, be32_to_cpu(res));
311         return res;
312 }
313
314 /*
315  * Validate the sequenceID sent by the server.
316  * Return success if the sequenceID is one more than what we last saw on
317  * this slot, accounting for wraparound.  Increments the slot's sequence.
318  *
319  * We don't yet implement a duplicate request cache, instead we set the
320  * back channel ca_maxresponsesize_cached to zero. This is OK for now
321  * since we only currently implement idempotent callbacks anyway.
322  *
323  * We have a single slot backchannel at this time, so we don't bother
324  * checking the used_slots bit array on the table.  The lower layer guarantees
325  * a single outstanding callback request at a time.
326  */
327 static __be32
328 validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
329 {
330         struct nfs4_slot *slot;
331
332         dprintk("%s enter. slotid %d seqid %d\n",
333                 __func__, args->csa_slotid, args->csa_sequenceid);
334
335         if (args->csa_slotid >= NFS41_BC_MAX_CALLBACKS)
336                 return htonl(NFS4ERR_BADSLOT);
337
338         slot = tbl->slots + args->csa_slotid;
339         dprintk("%s slot table seqid: %d\n", __func__, slot->seq_nr);
340
341         /* Normal */
342         if (likely(args->csa_sequenceid == slot->seq_nr + 1)) {
343                 slot->seq_nr++;
344                 goto out_ok;
345         }
346
347         /* Replay */
348         if (args->csa_sequenceid == slot->seq_nr) {
349                 dprintk("%s seqid %d is a replay\n",
350                         __func__, args->csa_sequenceid);
351                 /* Signal process_op to set this error on next op */
352                 if (args->csa_cachethis == 0)
353                         return htonl(NFS4ERR_RETRY_UNCACHED_REP);
354
355                 /* The ca_maxresponsesize_cached is 0 with no DRC */
356                 else if (args->csa_cachethis == 1)
357                         return htonl(NFS4ERR_REP_TOO_BIG_TO_CACHE);
358         }
359
360         /* Wraparound */
361         if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) {
362                 slot->seq_nr = 1;
363                 goto out_ok;
364         }
365
366         /* Misordered request */
367         return htonl(NFS4ERR_SEQ_MISORDERED);
368 out_ok:
369         tbl->highest_used_slotid = args->csa_slotid;
370         return htonl(NFS4_OK);
371 }
372
373 /*
374  * For each referring call triple, check the session's slot table for
375  * a match.  If the slot is in use and the sequence numbers match, the
376  * client is still waiting for a response to the original request.
377  */
378 static bool referring_call_exists(struct nfs_client *clp,
379                                   uint32_t nrclists,
380                                   struct referring_call_list *rclists)
381 {
382         bool status = 0;
383         int i, j;
384         struct nfs4_session *session;
385         struct nfs4_slot_table *tbl;
386         struct referring_call_list *rclist;
387         struct referring_call *ref;
388
389         /*
390          * XXX When client trunking is implemented, this becomes
391          * a session lookup from within the loop
392          */
393         session = clp->cl_session;
394         tbl = &session->fc_slot_table;
395
396         for (i = 0; i < nrclists; i++) {
397                 rclist = &rclists[i];
398                 if (memcmp(session->sess_id.data,
399                            rclist->rcl_sessionid.data,
400                            NFS4_MAX_SESSIONID_LEN) != 0)
401                         continue;
402
403                 for (j = 0; j < rclist->rcl_nrefcalls; j++) {
404                         ref = &rclist->rcl_refcalls[j];
405
406                         dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u "
407                                 "slotid %u\n", __func__,
408                                 ((u32 *)&rclist->rcl_sessionid.data)[0],
409                                 ((u32 *)&rclist->rcl_sessionid.data)[1],
410                                 ((u32 *)&rclist->rcl_sessionid.data)[2],
411                                 ((u32 *)&rclist->rcl_sessionid.data)[3],
412                                 ref->rc_sequenceid, ref->rc_slotid);
413
414                         spin_lock(&tbl->slot_tbl_lock);
415                         status = (test_bit(ref->rc_slotid, tbl->used_slots) &&
416                                   tbl->slots[ref->rc_slotid].seq_nr ==
417                                         ref->rc_sequenceid);
418                         spin_unlock(&tbl->slot_tbl_lock);
419                         if (status)
420                                 goto out;
421                 }
422         }
423
424 out:
425         return status;
426 }
427
428 __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
429                               struct cb_sequenceres *res,
430                               struct cb_process_state *cps)
431 {
432         struct nfs4_slot_table *tbl;
433         struct nfs_client *clp;
434         int i;
435         __be32 status = htonl(NFS4ERR_BADSESSION);
436
437         clp = nfs4_find_client_sessionid(cps->net, args->csa_addr, &args->csa_sessionid);
438         if (clp == NULL)
439                 goto out;
440
441         tbl = &clp->cl_session->bc_slot_table;
442
443         spin_lock(&tbl->slot_tbl_lock);
444         /* state manager is resetting the session */
445         if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) {
446                 spin_unlock(&tbl->slot_tbl_lock);
447                 status = htonl(NFS4ERR_DELAY);
448                 /* Return NFS4ERR_BADSESSION if we're draining the session
449                  * in order to reset it.
450                  */
451                 if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state))
452                         status = htonl(NFS4ERR_BADSESSION);
453                 goto out;
454         }
455
456         status = validate_seqid(&clp->cl_session->bc_slot_table, args);
457         spin_unlock(&tbl->slot_tbl_lock);
458         if (status)
459                 goto out;
460
461         cps->slotid = args->csa_slotid;
462
463         /*
464          * Check for pending referring calls.  If a match is found, a
465          * related callback was received before the response to the original
466          * call.
467          */
468         if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists)) {
469                 status = htonl(NFS4ERR_DELAY);
470                 goto out;
471         }
472
473         memcpy(&res->csr_sessionid, &args->csa_sessionid,
474                sizeof(res->csr_sessionid));
475         res->csr_sequenceid = args->csa_sequenceid;
476         res->csr_slotid = args->csa_slotid;
477         res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
478         res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
479
480 out:
481         cps->clp = clp; /* put in nfs4_callback_compound */
482         for (i = 0; i < args->csa_nrclists; i++)
483                 kfree(args->csa_rclists[i].rcl_refcalls);
484         kfree(args->csa_rclists);
485
486         if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP)) {
487                 cps->drc_status = status;
488                 status = 0;
489         } else
490                 res->csr_status = status;
491
492         dprintk("%s: exit with status = %d res->csr_status %d\n", __func__,
493                 ntohl(status), ntohl(res->csr_status));
494         return status;
495 }
496
497 static bool
498 validate_bitmap_values(unsigned long mask)
499 {
500         return (mask & ~RCA4_TYPE_MASK_ALL) == 0;
501 }
502
503 __be32 nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy,
504                                struct cb_process_state *cps)
505 {
506         __be32 status;
507         fmode_t flags = 0;
508
509         status = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
510         if (!cps->clp) /* set in cb_sequence */
511                 goto out;
512
513         dprintk_rcu("NFS: RECALL_ANY callback request from %s\n",
514                 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
515
516         status = cpu_to_be32(NFS4ERR_INVAL);
517         if (!validate_bitmap_values(args->craa_type_mask))
518                 goto out;
519
520         status = cpu_to_be32(NFS4_OK);
521         if (test_bit(RCA4_TYPE_MASK_RDATA_DLG, (const unsigned long *)
522                      &args->craa_type_mask))
523                 flags = FMODE_READ;
524         if (test_bit(RCA4_TYPE_MASK_WDATA_DLG, (const unsigned long *)
525                      &args->craa_type_mask))
526                 flags |= FMODE_WRITE;
527         if (test_bit(RCA4_TYPE_MASK_FILE_LAYOUT, (const unsigned long *)
528                      &args->craa_type_mask))
529                 pnfs_recall_all_layouts(cps->clp);
530         if (flags)
531                 nfs_expire_all_delegation_types(cps->clp, flags);
532 out:
533         dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
534         return status;
535 }
536
537 /* Reduce the fore channel's max_slots to the target value */
538 __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy,
539                                 struct cb_process_state *cps)
540 {
541         struct nfs4_slot_table *fc_tbl;
542         __be32 status;
543
544         status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
545         if (!cps->clp) /* set in cb_sequence */
546                 goto out;
547
548         dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target max slots %d\n",
549                 rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR),
550                 args->crsa_target_max_slots);
551
552         fc_tbl = &cps->clp->cl_session->fc_slot_table;
553
554         status = htonl(NFS4ERR_BAD_HIGH_SLOT);
555         if (args->crsa_target_max_slots > fc_tbl->max_slots ||
556             args->crsa_target_max_slots < 1)
557                 goto out;
558
559         status = htonl(NFS4_OK);
560         if (args->crsa_target_max_slots == fc_tbl->max_slots)
561                 goto out;
562
563         fc_tbl->target_max_slots = args->crsa_target_max_slots;
564         nfs41_handle_recall_slot(cps->clp);
565 out:
566         dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
567         return status;
568 }
569 #endif /* CONFIG_NFS_V4_1 */