.. | .. |
---|
42 | 42 | #include <linux/sunrpc/svcauth_gss.h> |
---|
43 | 43 | #include <linux/sunrpc/addr.h> |
---|
44 | 44 | #include <linux/jhash.h> |
---|
| 45 | +#include <linux/string_helpers.h> |
---|
45 | 46 | #include "xdr4.h" |
---|
46 | 47 | #include "xdr4cb.h" |
---|
47 | 48 | #include "vfs.h" |
---|
.. | .. |
---|
49 | 50 | |
---|
50 | 51 | #include "netns.h" |
---|
51 | 52 | #include "pnfs.h" |
---|
| 53 | +#include "filecache.h" |
---|
| 54 | +#include "trace.h" |
---|
52 | 55 | |
---|
53 | 56 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
---|
54 | 57 | |
---|
.. | .. |
---|
77 | 80 | /* forward declarations */ |
---|
78 | 81 | static bool check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner); |
---|
79 | 82 | static void nfs4_free_ol_stateid(struct nfs4_stid *stid); |
---|
| 83 | +void nfsd4_end_grace(struct nfsd_net *nn); |
---|
| 84 | +static void _free_cpntf_state_locked(struct nfsd_net *nn, struct nfs4_cpntf_state *cps); |
---|
80 | 85 | |
---|
81 | 86 | /* Locking: */ |
---|
82 | 87 | |
---|
.. | .. |
---|
97 | 102 | * the refcount on the open stateid to drop. |
---|
98 | 103 | */ |
---|
99 | 104 | static DECLARE_WAIT_QUEUE_HEAD(close_wq); |
---|
| 105 | + |
---|
| 106 | +/* |
---|
| 107 | + * A waitqueue where a writer to clients/#/ctl destroying a client can |
---|
| 108 | + * wait for cl_rpc_users to drop to 0 and then for the client to be |
---|
| 109 | + * unhashed. |
---|
| 110 | + */ |
---|
| 111 | +static DECLARE_WAIT_QUEUE_HEAD(expiry_wq); |
---|
100 | 112 | |
---|
101 | 113 | static struct kmem_cache *client_slab; |
---|
102 | 114 | static struct kmem_cache *openowner_slab; |
---|
.. | .. |
---|
137 | 149 | |
---|
138 | 150 | if (is_client_expired(clp)) |
---|
139 | 151 | return nfserr_expired; |
---|
140 | | - atomic_inc(&clp->cl_refcount); |
---|
| 152 | + atomic_inc(&clp->cl_rpc_users); |
---|
141 | 153 | return nfs_ok; |
---|
142 | 154 | } |
---|
143 | 155 | |
---|
.. | .. |
---|
156 | 168 | return; |
---|
157 | 169 | } |
---|
158 | 170 | |
---|
159 | | - dprintk("renewing client (clientid %08x/%08x)\n", |
---|
160 | | - clp->cl_clientid.cl_boot, |
---|
161 | | - clp->cl_clientid.cl_id); |
---|
162 | 171 | list_move_tail(&clp->cl_lru, &nn->client_lru); |
---|
163 | | - clp->cl_time = get_seconds(); |
---|
| 172 | + clp->cl_time = ktime_get_boottime_seconds(); |
---|
164 | 173 | } |
---|
165 | 174 | |
---|
166 | 175 | static void put_client_renew_locked(struct nfs4_client *clp) |
---|
.. | .. |
---|
169 | 178 | |
---|
170 | 179 | lockdep_assert_held(&nn->client_lock); |
---|
171 | 180 | |
---|
172 | | - if (!atomic_dec_and_test(&clp->cl_refcount)) |
---|
| 181 | + if (!atomic_dec_and_test(&clp->cl_rpc_users)) |
---|
173 | 182 | return; |
---|
174 | 183 | if (!is_client_expired(clp)) |
---|
175 | 184 | renew_client_locked(clp); |
---|
| 185 | + else |
---|
| 186 | + wake_up_all(&expiry_wq); |
---|
176 | 187 | } |
---|
177 | 188 | |
---|
178 | 189 | static void put_client_renew(struct nfs4_client *clp) |
---|
179 | 190 | { |
---|
180 | 191 | struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); |
---|
181 | 192 | |
---|
182 | | - if (!atomic_dec_and_lock(&clp->cl_refcount, &nn->client_lock)) |
---|
| 193 | + if (!atomic_dec_and_lock(&clp->cl_rpc_users, &nn->client_lock)) |
---|
183 | 194 | return; |
---|
184 | 195 | if (!is_client_expired(clp)) |
---|
185 | 196 | renew_client_locked(clp); |
---|
| 197 | + else |
---|
| 198 | + wake_up_all(&expiry_wq); |
---|
186 | 199 | spin_unlock(&nn->client_lock); |
---|
187 | 200 | } |
---|
188 | 201 | |
---|
.. | .. |
---|
238 | 251 | } |
---|
239 | 252 | spin_unlock(&nn->blocked_locks_lock); |
---|
240 | 253 | if (found) |
---|
241 | | - posix_unblock_lock(&found->nbl_lock); |
---|
| 254 | + locks_delete_block(&found->nbl_lock); |
---|
242 | 255 | return found; |
---|
243 | 256 | } |
---|
244 | 257 | |
---|
.. | .. |
---|
267 | 280 | static void |
---|
268 | 281 | free_blocked_lock(struct nfsd4_blocked_lock *nbl) |
---|
269 | 282 | { |
---|
| 283 | + locks_delete_block(&nbl->nbl_lock); |
---|
270 | 284 | locks_release_private(&nbl->nbl_lock); |
---|
271 | 285 | kfree(nbl); |
---|
272 | 286 | } |
---|
.. | .. |
---|
295 | 309 | nbl = list_first_entry(&reaplist, struct nfsd4_blocked_lock, |
---|
296 | 310 | nbl_lru); |
---|
297 | 311 | list_del_init(&nbl->nbl_lru); |
---|
298 | | - posix_unblock_lock(&nbl->nbl_lock); |
---|
299 | 312 | free_blocked_lock(nbl); |
---|
300 | 313 | } |
---|
| 314 | +} |
---|
| 315 | + |
---|
| 316 | +static void |
---|
| 317 | +nfsd4_cb_notify_lock_prepare(struct nfsd4_callback *cb) |
---|
| 318 | +{ |
---|
| 319 | + struct nfsd4_blocked_lock *nbl = container_of(cb, |
---|
| 320 | + struct nfsd4_blocked_lock, nbl_cb); |
---|
| 321 | + locks_delete_block(&nbl->nbl_lock); |
---|
301 | 322 | } |
---|
302 | 323 | |
---|
303 | 324 | static int |
---|
.. | .. |
---|
327 | 348 | } |
---|
328 | 349 | |
---|
329 | 350 | static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops = { |
---|
| 351 | + .prepare = nfsd4_cb_notify_lock_prepare, |
---|
330 | 352 | .done = nfsd4_cb_notify_lock_done, |
---|
331 | 353 | .release = nfsd4_cb_notify_lock_release, |
---|
332 | 354 | }; |
---|
.. | .. |
---|
409 | 431 | } |
---|
410 | 432 | } |
---|
411 | 433 | |
---|
412 | | -static struct file * |
---|
| 434 | +static struct nfsd_file * |
---|
413 | 435 | __nfs4_get_fd(struct nfs4_file *f, int oflag) |
---|
414 | 436 | { |
---|
415 | 437 | if (f->fi_fds[oflag]) |
---|
416 | | - return get_file(f->fi_fds[oflag]); |
---|
| 438 | + return nfsd_file_get(f->fi_fds[oflag]); |
---|
417 | 439 | return NULL; |
---|
418 | 440 | } |
---|
419 | 441 | |
---|
420 | | -static struct file * |
---|
| 442 | +static struct nfsd_file * |
---|
421 | 443 | find_writeable_file_locked(struct nfs4_file *f) |
---|
422 | 444 | { |
---|
423 | | - struct file *ret; |
---|
| 445 | + struct nfsd_file *ret; |
---|
424 | 446 | |
---|
425 | 447 | lockdep_assert_held(&f->fi_lock); |
---|
426 | 448 | |
---|
.. | .. |
---|
430 | 452 | return ret; |
---|
431 | 453 | } |
---|
432 | 454 | |
---|
433 | | -static struct file * |
---|
| 455 | +static struct nfsd_file * |
---|
434 | 456 | find_writeable_file(struct nfs4_file *f) |
---|
435 | 457 | { |
---|
436 | | - struct file *ret; |
---|
| 458 | + struct nfsd_file *ret; |
---|
437 | 459 | |
---|
438 | 460 | spin_lock(&f->fi_lock); |
---|
439 | 461 | ret = find_writeable_file_locked(f); |
---|
.. | .. |
---|
442 | 464 | return ret; |
---|
443 | 465 | } |
---|
444 | 466 | |
---|
445 | | -static struct file *find_readable_file_locked(struct nfs4_file *f) |
---|
| 467 | +static struct nfsd_file * |
---|
| 468 | +find_readable_file_locked(struct nfs4_file *f) |
---|
446 | 469 | { |
---|
447 | | - struct file *ret; |
---|
| 470 | + struct nfsd_file *ret; |
---|
448 | 471 | |
---|
449 | 472 | lockdep_assert_held(&f->fi_lock); |
---|
450 | 473 | |
---|
.. | .. |
---|
454 | 477 | return ret; |
---|
455 | 478 | } |
---|
456 | 479 | |
---|
457 | | -static struct file * |
---|
| 480 | +static struct nfsd_file * |
---|
458 | 481 | find_readable_file(struct nfs4_file *f) |
---|
459 | 482 | { |
---|
460 | | - struct file *ret; |
---|
| 483 | + struct nfsd_file *ret; |
---|
461 | 484 | |
---|
462 | 485 | spin_lock(&f->fi_lock); |
---|
463 | 486 | ret = find_readable_file_locked(f); |
---|
.. | .. |
---|
466 | 489 | return ret; |
---|
467 | 490 | } |
---|
468 | 491 | |
---|
469 | | -struct file * |
---|
| 492 | +struct nfsd_file * |
---|
470 | 493 | find_any_file(struct nfs4_file *f) |
---|
471 | 494 | { |
---|
472 | | - struct file *ret; |
---|
| 495 | + struct nfsd_file *ret; |
---|
473 | 496 | |
---|
474 | 497 | if (!f) |
---|
475 | 498 | return NULL; |
---|
.. | .. |
---|
482 | 505 | } |
---|
483 | 506 | spin_unlock(&f->fi_lock); |
---|
484 | 507 | return ret; |
---|
| 508 | +} |
---|
| 509 | + |
---|
| 510 | +static struct nfsd_file *find_any_file_locked(struct nfs4_file *f) |
---|
| 511 | +{ |
---|
| 512 | + lockdep_assert_held(&f->fi_lock); |
---|
| 513 | + |
---|
| 514 | + if (f->fi_fds[O_RDWR]) |
---|
| 515 | + return f->fi_fds[O_RDWR]; |
---|
| 516 | + if (f->fi_fds[O_WRONLY]) |
---|
| 517 | + return f->fi_fds[O_WRONLY]; |
---|
| 518 | + if (f->fi_fds[O_RDONLY]) |
---|
| 519 | + return f->fi_fds[O_RDONLY]; |
---|
| 520 | + return NULL; |
---|
| 521 | +} |
---|
| 522 | + |
---|
| 523 | +static struct nfsd_file *find_deleg_file_locked(struct nfs4_file *f) |
---|
| 524 | +{ |
---|
| 525 | + lockdep_assert_held(&f->fi_lock); |
---|
| 526 | + |
---|
| 527 | + if (f->fi_deleg_file) |
---|
| 528 | + return f->fi_deleg_file; |
---|
| 529 | + return NULL; |
---|
485 | 530 | } |
---|
486 | 531 | |
---|
487 | 532 | static atomic_long_t num_delegations; |
---|
.. | .. |
---|
572 | 617 | might_lock(&fp->fi_lock); |
---|
573 | 618 | |
---|
574 | 619 | if (atomic_dec_and_lock(&fp->fi_access[oflag], &fp->fi_lock)) { |
---|
575 | | - struct file *f1 = NULL; |
---|
576 | | - struct file *f2 = NULL; |
---|
| 620 | + struct nfsd_file *f1 = NULL; |
---|
| 621 | + struct nfsd_file *f2 = NULL; |
---|
577 | 622 | |
---|
578 | 623 | swap(f1, fp->fi_fds[oflag]); |
---|
579 | 624 | if (atomic_read(&fp->fi_access[1 - oflag]) == 0) |
---|
580 | 625 | swap(f2, fp->fi_fds[O_RDWR]); |
---|
581 | 626 | spin_unlock(&fp->fi_lock); |
---|
582 | 627 | if (f1) |
---|
583 | | - fput(f1); |
---|
| 628 | + nfsd_file_put(f1); |
---|
584 | 629 | if (f2) |
---|
585 | | - fput(f2); |
---|
| 630 | + nfsd_file_put(f2); |
---|
586 | 631 | } |
---|
587 | 632 | } |
---|
588 | 633 | |
---|
.. | .. |
---|
688 | 733 | |
---|
689 | 734 | idr_preload(GFP_KERNEL); |
---|
690 | 735 | spin_lock(&cl->cl_lock); |
---|
691 | | - new_id = idr_alloc_cyclic(&cl->cl_stateids, stid, 0, 0, GFP_NOWAIT); |
---|
| 736 | + /* Reserving 0 for start of file in nfsdfs "states" file: */ |
---|
| 737 | + new_id = idr_alloc_cyclic(&cl->cl_stateids, stid, 1, 0, GFP_NOWAIT); |
---|
692 | 738 | spin_unlock(&cl->cl_lock); |
---|
693 | 739 | idr_preload_end(); |
---|
694 | 740 | if (new_id < 0) |
---|
.. | .. |
---|
701 | 747 | /* Will be incremented before return to client: */ |
---|
702 | 748 | refcount_set(&stid->sc_count, 1); |
---|
703 | 749 | spin_lock_init(&stid->sc_lock); |
---|
| 750 | + INIT_LIST_HEAD(&stid->sc_cp_list); |
---|
704 | 751 | |
---|
705 | 752 | /* |
---|
706 | 753 | * It shouldn't be a problem to reuse an opaque stateid value. |
---|
.. | .. |
---|
717 | 764 | return NULL; |
---|
718 | 765 | } |
---|
719 | 766 | |
---|
| 767 | +/* |
---|
| 768 | + * Create a unique stateid_t to represent each COPY. |
---|
| 769 | + */ |
---|
| 770 | +static int nfs4_init_cp_state(struct nfsd_net *nn, copy_stateid_t *stid, |
---|
| 771 | + unsigned char sc_type) |
---|
| 772 | +{ |
---|
| 773 | + int new_id; |
---|
| 774 | + |
---|
| 775 | + stid->stid.si_opaque.so_clid.cl_boot = (u32)nn->boot_time; |
---|
| 776 | + stid->stid.si_opaque.so_clid.cl_id = nn->s2s_cp_cl_id; |
---|
| 777 | + stid->sc_type = sc_type; |
---|
| 778 | + |
---|
| 779 | + idr_preload(GFP_KERNEL); |
---|
| 780 | + spin_lock(&nn->s2s_cp_lock); |
---|
| 781 | + new_id = idr_alloc_cyclic(&nn->s2s_cp_stateids, stid, 0, 0, GFP_NOWAIT); |
---|
| 782 | + stid->stid.si_opaque.so_id = new_id; |
---|
| 783 | + stid->stid.si_generation = 1; |
---|
| 784 | + spin_unlock(&nn->s2s_cp_lock); |
---|
| 785 | + idr_preload_end(); |
---|
| 786 | + if (new_id < 0) |
---|
| 787 | + return 0; |
---|
| 788 | + return 1; |
---|
| 789 | +} |
---|
| 790 | + |
---|
| 791 | +int nfs4_init_copy_state(struct nfsd_net *nn, struct nfsd4_copy *copy) |
---|
| 792 | +{ |
---|
| 793 | + return nfs4_init_cp_state(nn, ©->cp_stateid, NFS4_COPY_STID); |
---|
| 794 | +} |
---|
| 795 | + |
---|
| 796 | +struct nfs4_cpntf_state *nfs4_alloc_init_cpntf_state(struct nfsd_net *nn, |
---|
| 797 | + struct nfs4_stid *p_stid) |
---|
| 798 | +{ |
---|
| 799 | + struct nfs4_cpntf_state *cps; |
---|
| 800 | + |
---|
| 801 | + cps = kzalloc(sizeof(struct nfs4_cpntf_state), GFP_KERNEL); |
---|
| 802 | + if (!cps) |
---|
| 803 | + return NULL; |
---|
| 804 | + cps->cpntf_time = ktime_get_boottime_seconds(); |
---|
| 805 | + refcount_set(&cps->cp_stateid.sc_count, 1); |
---|
| 806 | + if (!nfs4_init_cp_state(nn, &cps->cp_stateid, NFS4_COPYNOTIFY_STID)) |
---|
| 807 | + goto out_free; |
---|
| 808 | + spin_lock(&nn->s2s_cp_lock); |
---|
| 809 | + list_add(&cps->cp_list, &p_stid->sc_cp_list); |
---|
| 810 | + spin_unlock(&nn->s2s_cp_lock); |
---|
| 811 | + return cps; |
---|
| 812 | +out_free: |
---|
| 813 | + kfree(cps); |
---|
| 814 | + return NULL; |
---|
| 815 | +} |
---|
| 816 | + |
---|
| 817 | +void nfs4_free_copy_state(struct nfsd4_copy *copy) |
---|
| 818 | +{ |
---|
| 819 | + struct nfsd_net *nn; |
---|
| 820 | + |
---|
| 821 | + WARN_ON_ONCE(copy->cp_stateid.sc_type != NFS4_COPY_STID); |
---|
| 822 | + nn = net_generic(copy->cp_clp->net, nfsd_net_id); |
---|
| 823 | + spin_lock(&nn->s2s_cp_lock); |
---|
| 824 | + idr_remove(&nn->s2s_cp_stateids, |
---|
| 825 | + copy->cp_stateid.stid.si_opaque.so_id); |
---|
| 826 | + spin_unlock(&nn->s2s_cp_lock); |
---|
| 827 | +} |
---|
| 828 | + |
---|
| 829 | +static void nfs4_free_cpntf_statelist(struct net *net, struct nfs4_stid *stid) |
---|
| 830 | +{ |
---|
| 831 | + struct nfs4_cpntf_state *cps; |
---|
| 832 | + struct nfsd_net *nn; |
---|
| 833 | + |
---|
| 834 | + nn = net_generic(net, nfsd_net_id); |
---|
| 835 | + spin_lock(&nn->s2s_cp_lock); |
---|
| 836 | + while (!list_empty(&stid->sc_cp_list)) { |
---|
| 837 | + cps = list_first_entry(&stid->sc_cp_list, |
---|
| 838 | + struct nfs4_cpntf_state, cp_list); |
---|
| 839 | + _free_cpntf_state_locked(nn, cps); |
---|
| 840 | + } |
---|
| 841 | + spin_unlock(&nn->s2s_cp_lock); |
---|
| 842 | +} |
---|
| 843 | + |
---|
720 | 844 | static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp) |
---|
721 | 845 | { |
---|
722 | 846 | struct nfs4_stid *stid; |
---|
.. | .. |
---|
730 | 854 | |
---|
731 | 855 | static void nfs4_free_deleg(struct nfs4_stid *stid) |
---|
732 | 856 | { |
---|
| 857 | + WARN_ON(!list_empty(&stid->sc_cp_list)); |
---|
733 | 858 | kmem_cache_free(deleg_slab, stid); |
---|
734 | 859 | atomic_long_dec(&num_delegations); |
---|
735 | 860 | } |
---|
.. | .. |
---|
755 | 880 | static DEFINE_SPINLOCK(blocked_delegations_lock); |
---|
756 | 881 | static struct bloom_pair { |
---|
757 | 882 | int entries, old_entries; |
---|
758 | | - time_t swap_time; |
---|
| 883 | + time64_t swap_time; |
---|
759 | 884 | int new; /* index into 'set' */ |
---|
760 | 885 | DECLARE_BITMAP(set[2], 256); |
---|
761 | 886 | } blocked_delegations; |
---|
.. | .. |
---|
767 | 892 | |
---|
768 | 893 | if (bd->entries == 0) |
---|
769 | 894 | return 0; |
---|
770 | | - if (seconds_since_boot() - bd->swap_time > 30) { |
---|
| 895 | + if (ktime_get_seconds() - bd->swap_time > 30) { |
---|
771 | 896 | spin_lock(&blocked_delegations_lock); |
---|
772 | | - if (seconds_since_boot() - bd->swap_time > 30) { |
---|
| 897 | + if (ktime_get_seconds() - bd->swap_time > 30) { |
---|
773 | 898 | bd->entries -= bd->old_entries; |
---|
774 | 899 | bd->old_entries = bd->entries; |
---|
775 | 900 | memset(bd->set[bd->new], 0, |
---|
776 | 901 | sizeof(bd->set[0])); |
---|
777 | 902 | bd->new = 1-bd->new; |
---|
778 | | - bd->swap_time = seconds_since_boot(); |
---|
| 903 | + bd->swap_time = ktime_get_seconds(); |
---|
779 | 904 | } |
---|
780 | 905 | spin_unlock(&blocked_delegations_lock); |
---|
781 | 906 | } |
---|
.. | .. |
---|
805 | 930 | __set_bit((hash>>8)&255, bd->set[bd->new]); |
---|
806 | 931 | __set_bit((hash>>16)&255, bd->set[bd->new]); |
---|
807 | 932 | if (bd->entries == 0) |
---|
808 | | - bd->swap_time = seconds_since_boot(); |
---|
| 933 | + bd->swap_time = ktime_get_seconds(); |
---|
809 | 934 | bd->entries += 1; |
---|
810 | 935 | spin_unlock(&blocked_delegations_lock); |
---|
811 | 936 | } |
---|
.. | .. |
---|
864 | 989 | return; |
---|
865 | 990 | } |
---|
866 | 991 | idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id); |
---|
| 992 | + nfs4_free_cpntf_statelist(clp->net, s); |
---|
867 | 993 | spin_unlock(&clp->cl_lock); |
---|
868 | 994 | s->sc_free(s); |
---|
869 | 995 | if (fp) |
---|
.. | .. |
---|
884 | 1010 | |
---|
885 | 1011 | static void put_deleg_file(struct nfs4_file *fp) |
---|
886 | 1012 | { |
---|
887 | | - struct file *filp = NULL; |
---|
| 1013 | + struct nfsd_file *nf = NULL; |
---|
888 | 1014 | |
---|
889 | 1015 | spin_lock(&fp->fi_lock); |
---|
890 | 1016 | if (--fp->fi_delegees == 0) |
---|
891 | | - swap(filp, fp->fi_deleg_file); |
---|
| 1017 | + swap(nf, fp->fi_deleg_file); |
---|
892 | 1018 | spin_unlock(&fp->fi_lock); |
---|
893 | 1019 | |
---|
894 | | - if (filp) |
---|
895 | | - fput(filp); |
---|
| 1020 | + if (nf) |
---|
| 1021 | + nfsd_file_put(nf); |
---|
896 | 1022 | } |
---|
897 | 1023 | |
---|
898 | 1024 | static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp) |
---|
899 | 1025 | { |
---|
900 | 1026 | struct nfs4_file *fp = dp->dl_stid.sc_file; |
---|
901 | | - struct file *filp = fp->fi_deleg_file; |
---|
| 1027 | + struct nfsd_file *nf = fp->fi_deleg_file; |
---|
902 | 1028 | |
---|
903 | 1029 | WARN_ON_ONCE(!fp->fi_delegees); |
---|
904 | 1030 | |
---|
905 | | - vfs_setlease(filp, F_UNLCK, NULL, (void **)&dp); |
---|
| 1031 | + vfs_setlease(nf->nf_file, F_UNLCK, NULL, (void **)&dp); |
---|
906 | 1032 | put_deleg_file(fp); |
---|
907 | 1033 | } |
---|
908 | 1034 | |
---|
.. | .. |
---|
1019 | 1145 | WARN_ON(!list_empty(&dp->dl_recall_lru)); |
---|
1020 | 1146 | |
---|
1021 | 1147 | if (clp->cl_minorversion) { |
---|
| 1148 | + spin_lock(&clp->cl_lock); |
---|
1022 | 1149 | dp->dl_stid.sc_type = NFS4_REVOKED_DELEG_STID; |
---|
1023 | 1150 | refcount_inc(&dp->dl_stid.sc_count); |
---|
1024 | | - spin_lock(&clp->cl_lock); |
---|
1025 | 1151 | list_add(&dp->dl_recall_lru, &clp->cl_revoked); |
---|
1026 | 1152 | spin_unlock(&clp->cl_lock); |
---|
1027 | 1153 | } |
---|
.. | .. |
---|
1037 | 1163 | return id & CLIENT_HASH_MASK; |
---|
1038 | 1164 | } |
---|
1039 | 1165 | |
---|
1040 | | -static unsigned int clientstr_hashval(const char *name) |
---|
| 1166 | +static unsigned int clientstr_hashval(struct xdr_netobj name) |
---|
1041 | 1167 | { |
---|
1042 | | - return opaque_hashval(name, 8) & CLIENT_HASH_MASK; |
---|
| 1168 | + return opaque_hashval(name.data, 8) & CLIENT_HASH_MASK; |
---|
1043 | 1169 | } |
---|
1044 | 1170 | |
---|
1045 | 1171 | /* |
---|
.. | .. |
---|
1244 | 1370 | release_all_access(stp); |
---|
1245 | 1371 | if (stp->st_stateowner) |
---|
1246 | 1372 | nfs4_put_stateowner(stp->st_stateowner); |
---|
| 1373 | + WARN_ON(!list_empty(&stid->sc_cp_list)); |
---|
1247 | 1374 | kmem_cache_free(stateid_slab, stid); |
---|
1248 | 1375 | } |
---|
1249 | 1376 | |
---|
.. | .. |
---|
1251 | 1378 | { |
---|
1252 | 1379 | struct nfs4_ol_stateid *stp = openlockstateid(stid); |
---|
1253 | 1380 | struct nfs4_lockowner *lo = lockowner(stp->st_stateowner); |
---|
1254 | | - struct file *file; |
---|
| 1381 | + struct nfsd_file *nf; |
---|
1255 | 1382 | |
---|
1256 | | - file = find_any_file(stp->st_stid.sc_file); |
---|
1257 | | - if (file) |
---|
1258 | | - filp_close(file, (fl_owner_t)lo); |
---|
| 1383 | + nf = find_any_file(stp->st_stid.sc_file); |
---|
| 1384 | + if (nf) { |
---|
| 1385 | + get_file(nf->nf_file); |
---|
| 1386 | + filp_close(nf->nf_file, (fl_owner_t)lo); |
---|
| 1387 | + nfsd_file_put(nf); |
---|
| 1388 | + } |
---|
1259 | 1389 | nfs4_free_ol_stateid(stid); |
---|
1260 | 1390 | } |
---|
1261 | 1391 | |
---|
.. | .. |
---|
1526 | 1656 | * re-negotiate active sessions and reduce their slot usage to make |
---|
1527 | 1657 | * room for new connections. For now we just fail the create session. |
---|
1528 | 1658 | */ |
---|
1529 | | -static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca) |
---|
| 1659 | +static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca, struct nfsd_net *nn) |
---|
1530 | 1660 | { |
---|
1531 | 1661 | u32 slotsize = slot_bytes(ca); |
---|
1532 | 1662 | u32 num = ca->maxreqs; |
---|
1533 | 1663 | unsigned long avail, total_avail; |
---|
| 1664 | + unsigned int scale_factor; |
---|
1534 | 1665 | |
---|
1535 | 1666 | spin_lock(&nfsd_drc_lock); |
---|
1536 | | - total_avail = nfsd_drc_max_mem - nfsd_drc_mem_used; |
---|
| 1667 | + if (nfsd_drc_max_mem > nfsd_drc_mem_used) |
---|
| 1668 | + total_avail = nfsd_drc_max_mem - nfsd_drc_mem_used; |
---|
| 1669 | + else |
---|
| 1670 | + /* We have handed out more space than we chose in |
---|
| 1671 | + * set_max_drc() to allow. That isn't really a |
---|
| 1672 | + * problem as long as that doesn't make us think we |
---|
| 1673 | + * have lots more due to integer overflow. |
---|
| 1674 | + */ |
---|
| 1675 | + total_avail = 0; |
---|
1537 | 1676 | avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION, total_avail); |
---|
1538 | 1677 | /* |
---|
1539 | | - * Never use more than a third of the remaining memory, |
---|
1540 | | - * unless it's the only way to give this client a slot: |
---|
| 1678 | + * Never use more than a fraction of the remaining memory, |
---|
| 1679 | + * unless it's the only way to give this client a slot. |
---|
| 1680 | + * The chosen fraction is either 1/8 or 1/number of threads, |
---|
| 1681 | + * whichever is smaller. This ensures there are adequate |
---|
| 1682 | + * slots to support multiple clients per thread. |
---|
| 1683 | + * Give the client one slot even if that would require |
---|
| 1684 | + * over-allocation--it is better than failure. |
---|
1541 | 1685 | */ |
---|
1542 | | - avail = clamp_t(unsigned long, avail, slotsize, total_avail/3); |
---|
| 1686 | + scale_factor = max_t(unsigned int, 8, nn->nfsd_serv->sv_nrthreads); |
---|
| 1687 | + |
---|
| 1688 | + avail = clamp_t(unsigned long, avail, slotsize, |
---|
| 1689 | + total_avail/scale_factor); |
---|
1543 | 1690 | num = min_t(int, num, avail / slotsize); |
---|
| 1691 | + num = max_t(int, num, 1); |
---|
1544 | 1692 | nfsd_drc_mem_used += num * slotsize; |
---|
1545 | 1693 | spin_unlock(&nfsd_drc_lock); |
---|
1546 | 1694 | |
---|
.. | .. |
---|
1802 | 1950 | */ |
---|
1803 | 1951 | if (clid->cl_boot == (u32)nn->boot_time) |
---|
1804 | 1952 | return 0; |
---|
1805 | | - dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n", |
---|
1806 | | - clid->cl_boot, clid->cl_id, nn->boot_time); |
---|
| 1953 | + trace_nfsd_clid_stale(clid); |
---|
1807 | 1954 | return 1; |
---|
1808 | 1955 | } |
---|
1809 | 1956 | |
---|
.. | .. |
---|
1820 | 1967 | clp = kmem_cache_zalloc(client_slab, GFP_KERNEL); |
---|
1821 | 1968 | if (clp == NULL) |
---|
1822 | 1969 | return NULL; |
---|
1823 | | - clp->cl_name.data = kmemdup(name.data, name.len, GFP_KERNEL); |
---|
| 1970 | + xdr_netobj_dup(&clp->cl_name, &name, GFP_KERNEL); |
---|
1824 | 1971 | if (clp->cl_name.data == NULL) |
---|
1825 | 1972 | goto err_no_name; |
---|
1826 | 1973 | clp->cl_ownerstr_hashtbl = kmalloc_array(OWNER_HASH_SIZE, |
---|
.. | .. |
---|
1830 | 1977 | goto err_no_hashtbl; |
---|
1831 | 1978 | for (i = 0; i < OWNER_HASH_SIZE; i++) |
---|
1832 | 1979 | INIT_LIST_HEAD(&clp->cl_ownerstr_hashtbl[i]); |
---|
1833 | | - clp->cl_name.len = name.len; |
---|
1834 | 1980 | INIT_LIST_HEAD(&clp->cl_sessions); |
---|
1835 | 1981 | idr_init(&clp->cl_stateids); |
---|
1836 | | - atomic_set(&clp->cl_refcount, 0); |
---|
| 1982 | + atomic_set(&clp->cl_rpc_users, 0); |
---|
1837 | 1983 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; |
---|
1838 | 1984 | INIT_LIST_HEAD(&clp->cl_idhash); |
---|
1839 | 1985 | INIT_LIST_HEAD(&clp->cl_openowners); |
---|
.. | .. |
---|
1843 | 1989 | #ifdef CONFIG_NFSD_PNFS |
---|
1844 | 1990 | INIT_LIST_HEAD(&clp->cl_lo_states); |
---|
1845 | 1991 | #endif |
---|
| 1992 | + INIT_LIST_HEAD(&clp->async_copies); |
---|
| 1993 | + spin_lock_init(&clp->async_lock); |
---|
1846 | 1994 | spin_lock_init(&clp->cl_lock); |
---|
1847 | 1995 | rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); |
---|
1848 | 1996 | return clp; |
---|
.. | .. |
---|
1851 | 1999 | err_no_name: |
---|
1852 | 2000 | kmem_cache_free(client_slab, clp); |
---|
1853 | 2001 | return NULL; |
---|
| 2002 | +} |
---|
| 2003 | + |
---|
| 2004 | +static void __free_client(struct kref *k) |
---|
| 2005 | +{ |
---|
| 2006 | + struct nfsdfs_client *c = container_of(k, struct nfsdfs_client, cl_ref); |
---|
| 2007 | + struct nfs4_client *clp = container_of(c, struct nfs4_client, cl_nfsdfs); |
---|
| 2008 | + |
---|
| 2009 | + free_svc_cred(&clp->cl_cred); |
---|
| 2010 | + kfree(clp->cl_ownerstr_hashtbl); |
---|
| 2011 | + kfree(clp->cl_name.data); |
---|
| 2012 | + kfree(clp->cl_nii_domain.data); |
---|
| 2013 | + kfree(clp->cl_nii_name.data); |
---|
| 2014 | + idr_destroy(&clp->cl_stateids); |
---|
| 2015 | + kmem_cache_free(client_slab, clp); |
---|
| 2016 | +} |
---|
| 2017 | + |
---|
| 2018 | +static void drop_client(struct nfs4_client *clp) |
---|
| 2019 | +{ |
---|
| 2020 | + kref_put(&clp->cl_nfsdfs.cl_ref, __free_client); |
---|
1854 | 2021 | } |
---|
1855 | 2022 | |
---|
1856 | 2023 | static void |
---|
.. | .. |
---|
1865 | 2032 | free_session(ses); |
---|
1866 | 2033 | } |
---|
1867 | 2034 | rpc_destroy_wait_queue(&clp->cl_cb_waitq); |
---|
1868 | | - free_svc_cred(&clp->cl_cred); |
---|
1869 | | - kfree(clp->cl_ownerstr_hashtbl); |
---|
1870 | | - kfree(clp->cl_name.data); |
---|
1871 | | - idr_destroy(&clp->cl_stateids); |
---|
1872 | | - kmem_cache_free(client_slab, clp); |
---|
| 2035 | + if (clp->cl_nfsd_dentry) { |
---|
| 2036 | + nfsd_client_rmdir(clp->cl_nfsd_dentry); |
---|
| 2037 | + clp->cl_nfsd_dentry = NULL; |
---|
| 2038 | + wake_up_all(&expiry_wq); |
---|
| 2039 | + } |
---|
| 2040 | + drop_client(clp); |
---|
1873 | 2041 | } |
---|
1874 | 2042 | |
---|
1875 | 2043 | /* must be called under the client_lock */ |
---|
.. | .. |
---|
1910 | 2078 | |
---|
1911 | 2079 | static __be32 mark_client_expired_locked(struct nfs4_client *clp) |
---|
1912 | 2080 | { |
---|
1913 | | - if (atomic_read(&clp->cl_refcount)) |
---|
| 2081 | + if (atomic_read(&clp->cl_rpc_users)) |
---|
1914 | 2082 | return nfserr_jukebox; |
---|
1915 | 2083 | unhash_client_locked(clp); |
---|
1916 | 2084 | return nfs_ok; |
---|
.. | .. |
---|
1958 | 2126 | } |
---|
1959 | 2127 | } |
---|
1960 | 2128 | nfsd4_return_all_client_layouts(clp); |
---|
| 2129 | + nfsd4_shutdown_copy(clp); |
---|
1961 | 2130 | nfsd4_shutdown_callback(clp); |
---|
1962 | 2131 | if (clp->cl_cb_conn.cb_xprt) |
---|
1963 | 2132 | svc_xprt_put(clp->cl_cb_conn.cb_xprt); |
---|
1964 | 2133 | free_client(clp); |
---|
| 2134 | + wake_up_all(&expiry_wq); |
---|
1965 | 2135 | } |
---|
1966 | 2136 | |
---|
1967 | 2137 | static void |
---|
.. | .. |
---|
1969 | 2139 | { |
---|
1970 | 2140 | unhash_client(clp); |
---|
1971 | 2141 | __destroy_client(clp); |
---|
| 2142 | +} |
---|
| 2143 | + |
---|
| 2144 | +static void inc_reclaim_complete(struct nfs4_client *clp) |
---|
| 2145 | +{ |
---|
| 2146 | + struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); |
---|
| 2147 | + |
---|
| 2148 | + if (!nn->track_reclaim_completes) |
---|
| 2149 | + return; |
---|
| 2150 | + if (!nfsd4_find_reclaim_client(clp->cl_name, nn)) |
---|
| 2151 | + return; |
---|
| 2152 | + if (atomic_inc_return(&nn->nr_reclaim_complete) == |
---|
| 2153 | + nn->reclaim_str_hashtbl_size) { |
---|
| 2154 | + printk(KERN_INFO "NFSD: all clients done reclaiming, ending NFSv4 grace period (net %x)\n", |
---|
| 2155 | + clp->net->ns.inum); |
---|
| 2156 | + nfsd4_end_grace(nn); |
---|
| 2157 | + } |
---|
1972 | 2158 | } |
---|
1973 | 2159 | |
---|
1974 | 2160 | static void expire_client(struct nfs4_client *clp) |
---|
.. | .. |
---|
2020 | 2206 | if (o1->len > o2->len) |
---|
2021 | 2207 | return 1; |
---|
2022 | 2208 | return memcmp(o1->data, o2->data, o1->len); |
---|
2023 | | -} |
---|
2024 | | - |
---|
2025 | | -static int same_name(const char *n1, const char *n2) |
---|
2026 | | -{ |
---|
2027 | | - return 0 == memcmp(n1, n2, HEXDIR_LEN); |
---|
2028 | 2209 | } |
---|
2029 | 2210 | |
---|
2030 | 2211 | static int |
---|
.. | .. |
---|
2121 | 2302 | * This is opaque to client, so no need to byte-swap. Use |
---|
2122 | 2303 | * __force to keep sparse happy |
---|
2123 | 2304 | */ |
---|
2124 | | - verf[0] = (__force __be32)get_seconds(); |
---|
| 2305 | + verf[0] = (__force __be32)(u32)ktime_get_real_seconds(); |
---|
2125 | 2306 | verf[1] = (__force __be32)nn->clverifier_counter++; |
---|
2126 | 2307 | memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data)); |
---|
2127 | 2308 | } |
---|
2128 | 2309 | |
---|
2129 | 2310 | static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn) |
---|
2130 | 2311 | { |
---|
2131 | | - clp->cl_clientid.cl_boot = nn->boot_time; |
---|
| 2312 | + clp->cl_clientid.cl_boot = (u32)nn->boot_time; |
---|
2132 | 2313 | clp->cl_clientid.cl_id = nn->clientid_counter++; |
---|
2133 | 2314 | gen_confirm(clp, nn); |
---|
2134 | 2315 | } |
---|
.. | .. |
---|
2161 | 2342 | return s; |
---|
2162 | 2343 | } |
---|
2163 | 2344 | |
---|
| 2345 | +static struct nfs4_client *get_nfsdfs_clp(struct inode *inode) |
---|
| 2346 | +{ |
---|
| 2347 | + struct nfsdfs_client *nc; |
---|
| 2348 | + nc = get_nfsdfs_client(inode); |
---|
| 2349 | + if (!nc) |
---|
| 2350 | + return NULL; |
---|
| 2351 | + return container_of(nc, struct nfs4_client, cl_nfsdfs); |
---|
| 2352 | +} |
---|
| 2353 | + |
---|
| 2354 | +static void seq_quote_mem(struct seq_file *m, char *data, int len) |
---|
| 2355 | +{ |
---|
| 2356 | + seq_printf(m, "\""); |
---|
| 2357 | + seq_escape_mem_ascii(m, data, len); |
---|
| 2358 | + seq_printf(m, "\""); |
---|
| 2359 | +} |
---|
| 2360 | + |
---|
| 2361 | +static int client_info_show(struct seq_file *m, void *v) |
---|
| 2362 | +{ |
---|
| 2363 | + struct inode *inode = m->private; |
---|
| 2364 | + struct nfs4_client *clp; |
---|
| 2365 | + u64 clid; |
---|
| 2366 | + |
---|
| 2367 | + clp = get_nfsdfs_clp(inode); |
---|
| 2368 | + if (!clp) |
---|
| 2369 | + return -ENXIO; |
---|
| 2370 | + memcpy(&clid, &clp->cl_clientid, sizeof(clid)); |
---|
| 2371 | + seq_printf(m, "clientid: 0x%llx\n", clid); |
---|
| 2372 | + seq_printf(m, "address: \"%pISpc\"\n", (struct sockaddr *)&clp->cl_addr); |
---|
| 2373 | + seq_printf(m, "name: "); |
---|
| 2374 | + seq_quote_mem(m, clp->cl_name.data, clp->cl_name.len); |
---|
| 2375 | + seq_printf(m, "\nminor version: %d\n", clp->cl_minorversion); |
---|
| 2376 | + if (clp->cl_nii_domain.data) { |
---|
| 2377 | + seq_printf(m, "Implementation domain: "); |
---|
| 2378 | + seq_quote_mem(m, clp->cl_nii_domain.data, |
---|
| 2379 | + clp->cl_nii_domain.len); |
---|
| 2380 | + seq_printf(m, "\nImplementation name: "); |
---|
| 2381 | + seq_quote_mem(m, clp->cl_nii_name.data, clp->cl_nii_name.len); |
---|
| 2382 | + seq_printf(m, "\nImplementation time: [%lld, %ld]\n", |
---|
| 2383 | + clp->cl_nii_time.tv_sec, clp->cl_nii_time.tv_nsec); |
---|
| 2384 | + } |
---|
| 2385 | + drop_client(clp); |
---|
| 2386 | + |
---|
| 2387 | + return 0; |
---|
| 2388 | +} |
---|
| 2389 | + |
---|
| 2390 | +static int client_info_open(struct inode *inode, struct file *file) |
---|
| 2391 | +{ |
---|
| 2392 | + return single_open(file, client_info_show, inode); |
---|
| 2393 | +} |
---|
| 2394 | + |
---|
| 2395 | +static const struct file_operations client_info_fops = { |
---|
| 2396 | + .open = client_info_open, |
---|
| 2397 | + .read = seq_read, |
---|
| 2398 | + .llseek = seq_lseek, |
---|
| 2399 | + .release = single_release, |
---|
| 2400 | +}; |
---|
| 2401 | + |
---|
| 2402 | +static void *states_start(struct seq_file *s, loff_t *pos) |
---|
| 2403 | + __acquires(&clp->cl_lock) |
---|
| 2404 | +{ |
---|
| 2405 | + struct nfs4_client *clp = s->private; |
---|
| 2406 | + unsigned long id = *pos; |
---|
| 2407 | + void *ret; |
---|
| 2408 | + |
---|
| 2409 | + spin_lock(&clp->cl_lock); |
---|
| 2410 | + ret = idr_get_next_ul(&clp->cl_stateids, &id); |
---|
| 2411 | + *pos = id; |
---|
| 2412 | + return ret; |
---|
| 2413 | +} |
---|
| 2414 | + |
---|
| 2415 | +static void *states_next(struct seq_file *s, void *v, loff_t *pos) |
---|
| 2416 | +{ |
---|
| 2417 | + struct nfs4_client *clp = s->private; |
---|
| 2418 | + unsigned long id = *pos; |
---|
| 2419 | + void *ret; |
---|
| 2420 | + |
---|
| 2421 | + id = *pos; |
---|
| 2422 | + id++; |
---|
| 2423 | + ret = idr_get_next_ul(&clp->cl_stateids, &id); |
---|
| 2424 | + *pos = id; |
---|
| 2425 | + return ret; |
---|
| 2426 | +} |
---|
| 2427 | + |
---|
| 2428 | +static void states_stop(struct seq_file *s, void *v) |
---|
| 2429 | + __releases(&clp->cl_lock) |
---|
| 2430 | +{ |
---|
| 2431 | + struct nfs4_client *clp = s->private; |
---|
| 2432 | + |
---|
| 2433 | + spin_unlock(&clp->cl_lock); |
---|
| 2434 | +} |
---|
| 2435 | + |
---|
| 2436 | +static void nfs4_show_fname(struct seq_file *s, struct nfsd_file *f) |
---|
| 2437 | +{ |
---|
| 2438 | + seq_printf(s, "filename: \"%pD2\"", f->nf_file); |
---|
| 2439 | +} |
---|
| 2440 | + |
---|
| 2441 | +static void nfs4_show_superblock(struct seq_file *s, struct nfsd_file *f) |
---|
| 2442 | +{ |
---|
| 2443 | + struct inode *inode = f->nf_inode; |
---|
| 2444 | + |
---|
| 2445 | + seq_printf(s, "superblock: \"%02x:%02x:%ld\"", |
---|
| 2446 | + MAJOR(inode->i_sb->s_dev), |
---|
| 2447 | + MINOR(inode->i_sb->s_dev), |
---|
| 2448 | + inode->i_ino); |
---|
| 2449 | +} |
---|
| 2450 | + |
---|
| 2451 | +static void nfs4_show_owner(struct seq_file *s, struct nfs4_stateowner *oo) |
---|
| 2452 | +{ |
---|
| 2453 | + seq_printf(s, "owner: "); |
---|
| 2454 | + seq_quote_mem(s, oo->so_owner.data, oo->so_owner.len); |
---|
| 2455 | +} |
---|
| 2456 | + |
---|
| 2457 | +static void nfs4_show_stateid(struct seq_file *s, stateid_t *stid) |
---|
| 2458 | +{ |
---|
| 2459 | + seq_printf(s, "0x%.8x", stid->si_generation); |
---|
| 2460 | + seq_printf(s, "%12phN", &stid->si_opaque); |
---|
| 2461 | +} |
---|
| 2462 | + |
---|
| 2463 | +static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st) |
---|
| 2464 | +{ |
---|
| 2465 | + struct nfs4_ol_stateid *ols; |
---|
| 2466 | + struct nfs4_file *nf; |
---|
| 2467 | + struct nfsd_file *file; |
---|
| 2468 | + struct nfs4_stateowner *oo; |
---|
| 2469 | + unsigned int access, deny; |
---|
| 2470 | + |
---|
| 2471 | + if (st->sc_type != NFS4_OPEN_STID && st->sc_type != NFS4_LOCK_STID) |
---|
| 2472 | + return 0; /* XXX: or SEQ_SKIP? */ |
---|
| 2473 | + ols = openlockstateid(st); |
---|
| 2474 | + oo = ols->st_stateowner; |
---|
| 2475 | + nf = st->sc_file; |
---|
| 2476 | + |
---|
| 2477 | + spin_lock(&nf->fi_lock); |
---|
| 2478 | + file = find_any_file_locked(nf); |
---|
| 2479 | + if (!file) |
---|
| 2480 | + goto out; |
---|
| 2481 | + |
---|
| 2482 | + seq_printf(s, "- "); |
---|
| 2483 | + nfs4_show_stateid(s, &st->sc_stateid); |
---|
| 2484 | + seq_printf(s, ": { type: open, "); |
---|
| 2485 | + |
---|
| 2486 | + access = bmap_to_share_mode(ols->st_access_bmap); |
---|
| 2487 | + deny = bmap_to_share_mode(ols->st_deny_bmap); |
---|
| 2488 | + |
---|
| 2489 | + seq_printf(s, "access: %s%s, ", |
---|
| 2490 | + access & NFS4_SHARE_ACCESS_READ ? "r" : "-", |
---|
| 2491 | + access & NFS4_SHARE_ACCESS_WRITE ? "w" : "-"); |
---|
| 2492 | + seq_printf(s, "deny: %s%s, ", |
---|
| 2493 | + deny & NFS4_SHARE_ACCESS_READ ? "r" : "-", |
---|
| 2494 | + deny & NFS4_SHARE_ACCESS_WRITE ? "w" : "-"); |
---|
| 2495 | + |
---|
| 2496 | + nfs4_show_superblock(s, file); |
---|
| 2497 | + seq_printf(s, ", "); |
---|
| 2498 | + nfs4_show_fname(s, file); |
---|
| 2499 | + seq_printf(s, ", "); |
---|
| 2500 | + nfs4_show_owner(s, oo); |
---|
| 2501 | + seq_printf(s, " }\n"); |
---|
| 2502 | +out: |
---|
| 2503 | + spin_unlock(&nf->fi_lock); |
---|
| 2504 | + return 0; |
---|
| 2505 | +} |
---|
| 2506 | + |
---|
| 2507 | +static int nfs4_show_lock(struct seq_file *s, struct nfs4_stid *st) |
---|
| 2508 | +{ |
---|
| 2509 | + struct nfs4_ol_stateid *ols; |
---|
| 2510 | + struct nfs4_file *nf; |
---|
| 2511 | + struct nfsd_file *file; |
---|
| 2512 | + struct nfs4_stateowner *oo; |
---|
| 2513 | + |
---|
| 2514 | + ols = openlockstateid(st); |
---|
| 2515 | + oo = ols->st_stateowner; |
---|
| 2516 | + nf = st->sc_file; |
---|
| 2517 | + spin_lock(&nf->fi_lock); |
---|
| 2518 | + file = find_any_file_locked(nf); |
---|
| 2519 | + if (!file) |
---|
| 2520 | + goto out; |
---|
| 2521 | + |
---|
| 2522 | + seq_printf(s, "- "); |
---|
| 2523 | + nfs4_show_stateid(s, &st->sc_stateid); |
---|
| 2524 | + seq_printf(s, ": { type: lock, "); |
---|
| 2525 | + |
---|
| 2526 | + /* |
---|
| 2527 | + * Note: a lock stateid isn't really the same thing as a lock, |
---|
| 2528 | + * it's the locking state held by one owner on a file, and there |
---|
| 2529 | + * may be multiple (or no) lock ranges associated with it. |
---|
| 2530 | + * (Same for the matter is true of open stateids.) |
---|
| 2531 | + */ |
---|
| 2532 | + |
---|
| 2533 | + nfs4_show_superblock(s, file); |
---|
| 2534 | + /* XXX: open stateid? */ |
---|
| 2535 | + seq_printf(s, ", "); |
---|
| 2536 | + nfs4_show_fname(s, file); |
---|
| 2537 | + seq_printf(s, ", "); |
---|
| 2538 | + nfs4_show_owner(s, oo); |
---|
| 2539 | + seq_printf(s, " }\n"); |
---|
| 2540 | +out: |
---|
| 2541 | + spin_unlock(&nf->fi_lock); |
---|
| 2542 | + return 0; |
---|
| 2543 | +} |
---|
| 2544 | + |
---|
| 2545 | +static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st) |
---|
| 2546 | +{ |
---|
| 2547 | + struct nfs4_delegation *ds; |
---|
| 2548 | + struct nfs4_file *nf; |
---|
| 2549 | + struct nfsd_file *file; |
---|
| 2550 | + |
---|
| 2551 | + ds = delegstateid(st); |
---|
| 2552 | + nf = st->sc_file; |
---|
| 2553 | + spin_lock(&nf->fi_lock); |
---|
| 2554 | + file = find_deleg_file_locked(nf); |
---|
| 2555 | + if (!file) |
---|
| 2556 | + goto out; |
---|
| 2557 | + |
---|
| 2558 | + seq_printf(s, "- "); |
---|
| 2559 | + nfs4_show_stateid(s, &st->sc_stateid); |
---|
| 2560 | + seq_printf(s, ": { type: deleg, "); |
---|
| 2561 | + |
---|
| 2562 | + /* Kinda dead code as long as we only support read delegs: */ |
---|
| 2563 | + seq_printf(s, "access: %s, ", |
---|
| 2564 | + ds->dl_type == NFS4_OPEN_DELEGATE_READ ? "r" : "w"); |
---|
| 2565 | + |
---|
| 2566 | + /* XXX: lease time, whether it's being recalled. */ |
---|
| 2567 | + |
---|
| 2568 | + nfs4_show_superblock(s, file); |
---|
| 2569 | + seq_printf(s, ", "); |
---|
| 2570 | + nfs4_show_fname(s, file); |
---|
| 2571 | + seq_printf(s, " }\n"); |
---|
| 2572 | +out: |
---|
| 2573 | + spin_unlock(&nf->fi_lock); |
---|
| 2574 | + return 0; |
---|
| 2575 | +} |
---|
| 2576 | + |
---|
| 2577 | +static int nfs4_show_layout(struct seq_file *s, struct nfs4_stid *st) |
---|
| 2578 | +{ |
---|
| 2579 | + struct nfs4_layout_stateid *ls; |
---|
| 2580 | + struct nfsd_file *file; |
---|
| 2581 | + |
---|
| 2582 | + ls = container_of(st, struct nfs4_layout_stateid, ls_stid); |
---|
| 2583 | + file = ls->ls_file; |
---|
| 2584 | + |
---|
| 2585 | + seq_printf(s, "- "); |
---|
| 2586 | + nfs4_show_stateid(s, &st->sc_stateid); |
---|
| 2587 | + seq_printf(s, ": { type: layout, "); |
---|
| 2588 | + |
---|
| 2589 | + /* XXX: What else would be useful? */ |
---|
| 2590 | + |
---|
| 2591 | + nfs4_show_superblock(s, file); |
---|
| 2592 | + seq_printf(s, ", "); |
---|
| 2593 | + nfs4_show_fname(s, file); |
---|
| 2594 | + seq_printf(s, " }\n"); |
---|
| 2595 | + |
---|
| 2596 | + return 0; |
---|
| 2597 | +} |
---|
| 2598 | + |
---|
| 2599 | +static int states_show(struct seq_file *s, void *v) |
---|
| 2600 | +{ |
---|
| 2601 | + struct nfs4_stid *st = v; |
---|
| 2602 | + |
---|
| 2603 | + switch (st->sc_type) { |
---|
| 2604 | + case NFS4_OPEN_STID: |
---|
| 2605 | + return nfs4_show_open(s, st); |
---|
| 2606 | + case NFS4_LOCK_STID: |
---|
| 2607 | + return nfs4_show_lock(s, st); |
---|
| 2608 | + case NFS4_DELEG_STID: |
---|
| 2609 | + return nfs4_show_deleg(s, st); |
---|
| 2610 | + case NFS4_LAYOUT_STID: |
---|
| 2611 | + return nfs4_show_layout(s, st); |
---|
| 2612 | + default: |
---|
| 2613 | + return 0; /* XXX: or SEQ_SKIP? */ |
---|
| 2614 | + } |
---|
| 2615 | + /* XXX: copy stateids? */ |
---|
| 2616 | +} |
---|
| 2617 | + |
---|
| 2618 | +static struct seq_operations states_seq_ops = { |
---|
| 2619 | + .start = states_start, |
---|
| 2620 | + .next = states_next, |
---|
| 2621 | + .stop = states_stop, |
---|
| 2622 | + .show = states_show |
---|
| 2623 | +}; |
---|
| 2624 | + |
---|
| 2625 | +static int client_states_open(struct inode *inode, struct file *file) |
---|
| 2626 | +{ |
---|
| 2627 | + struct seq_file *s; |
---|
| 2628 | + struct nfs4_client *clp; |
---|
| 2629 | + int ret; |
---|
| 2630 | + |
---|
| 2631 | + clp = get_nfsdfs_clp(inode); |
---|
| 2632 | + if (!clp) |
---|
| 2633 | + return -ENXIO; |
---|
| 2634 | + |
---|
| 2635 | + ret = seq_open(file, &states_seq_ops); |
---|
| 2636 | + if (ret) |
---|
| 2637 | + return ret; |
---|
| 2638 | + s = file->private_data; |
---|
| 2639 | + s->private = clp; |
---|
| 2640 | + return 0; |
---|
| 2641 | +} |
---|
| 2642 | + |
---|
| 2643 | +static int client_opens_release(struct inode *inode, struct file *file) |
---|
| 2644 | +{ |
---|
| 2645 | + struct seq_file *m = file->private_data; |
---|
| 2646 | + struct nfs4_client *clp = m->private; |
---|
| 2647 | + |
---|
| 2648 | + /* XXX: alternatively, we could get/drop in seq start/stop */ |
---|
| 2649 | + drop_client(clp); |
---|
| 2650 | + return 0; |
---|
| 2651 | +} |
---|
| 2652 | + |
---|
| 2653 | +static const struct file_operations client_states_fops = { |
---|
| 2654 | + .open = client_states_open, |
---|
| 2655 | + .read = seq_read, |
---|
| 2656 | + .llseek = seq_lseek, |
---|
| 2657 | + .release = client_opens_release, |
---|
| 2658 | +}; |
---|
| 2659 | + |
---|
| 2660 | +/* |
---|
| 2661 | + * Normally we refuse to destroy clients that are in use, but here the |
---|
| 2662 | + * administrator is telling us to just do it. We also want to wait |
---|
| 2663 | + * so the caller has a guarantee that the client's locks are gone by |
---|
| 2664 | + * the time the write returns: |
---|
| 2665 | + */ |
---|
| 2666 | +static void force_expire_client(struct nfs4_client *clp) |
---|
| 2667 | +{ |
---|
| 2668 | + struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); |
---|
| 2669 | + bool already_expired; |
---|
| 2670 | + |
---|
| 2671 | + spin_lock(&nn->client_lock); |
---|
| 2672 | + clp->cl_time = 0; |
---|
| 2673 | + spin_unlock(&nn->client_lock); |
---|
| 2674 | + |
---|
| 2675 | + wait_event(expiry_wq, atomic_read(&clp->cl_rpc_users) == 0); |
---|
| 2676 | + spin_lock(&nn->client_lock); |
---|
| 2677 | + already_expired = list_empty(&clp->cl_lru); |
---|
| 2678 | + if (!already_expired) |
---|
| 2679 | + unhash_client_locked(clp); |
---|
| 2680 | + spin_unlock(&nn->client_lock); |
---|
| 2681 | + |
---|
| 2682 | + if (!already_expired) |
---|
| 2683 | + expire_client(clp); |
---|
| 2684 | + else |
---|
| 2685 | + wait_event(expiry_wq, clp->cl_nfsd_dentry == NULL); |
---|
| 2686 | +} |
---|
| 2687 | + |
---|
| 2688 | +static ssize_t client_ctl_write(struct file *file, const char __user *buf, |
---|
| 2689 | + size_t size, loff_t *pos) |
---|
| 2690 | +{ |
---|
| 2691 | + char *data; |
---|
| 2692 | + struct nfs4_client *clp; |
---|
| 2693 | + |
---|
| 2694 | + data = simple_transaction_get(file, buf, size); |
---|
| 2695 | + if (IS_ERR(data)) |
---|
| 2696 | + return PTR_ERR(data); |
---|
| 2697 | + if (size != 7 || 0 != memcmp(data, "expire\n", 7)) |
---|
| 2698 | + return -EINVAL; |
---|
| 2699 | + clp = get_nfsdfs_clp(file_inode(file)); |
---|
| 2700 | + if (!clp) |
---|
| 2701 | + return -ENXIO; |
---|
| 2702 | + force_expire_client(clp); |
---|
| 2703 | + drop_client(clp); |
---|
| 2704 | + return 7; |
---|
| 2705 | +} |
---|
| 2706 | + |
---|
| 2707 | +static const struct file_operations client_ctl_fops = { |
---|
| 2708 | + .write = client_ctl_write, |
---|
| 2709 | + .release = simple_transaction_release, |
---|
| 2710 | +}; |
---|
| 2711 | + |
---|
| 2712 | +static const struct tree_descr client_files[] = { |
---|
| 2713 | + [0] = {"info", &client_info_fops, S_IRUSR}, |
---|
| 2714 | + [1] = {"states", &client_states_fops, S_IRUSR}, |
---|
| 2715 | + [2] = {"ctl", &client_ctl_fops, S_IWUSR}, |
---|
| 2716 | + [3] = {""}, |
---|
| 2717 | +}; |
---|
| 2718 | + |
---|
2164 | 2719 | static struct nfs4_client *create_client(struct xdr_netobj name, |
---|
2165 | 2720 | struct svc_rqst *rqstp, nfs4_verifier *verf) |
---|
2166 | 2721 | { |
---|
.. | .. |
---|
2168 | 2723 | struct sockaddr *sa = svc_addr(rqstp); |
---|
2169 | 2724 | int ret; |
---|
2170 | 2725 | struct net *net = SVC_NET(rqstp); |
---|
| 2726 | + struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
---|
2171 | 2727 | |
---|
2172 | 2728 | clp = alloc_client(name); |
---|
2173 | 2729 | if (clp == NULL) |
---|
.. | .. |
---|
2178 | 2734 | free_client(clp); |
---|
2179 | 2735 | return NULL; |
---|
2180 | 2736 | } |
---|
| 2737 | + gen_clid(clp, nn); |
---|
| 2738 | + kref_init(&clp->cl_nfsdfs.cl_ref); |
---|
2181 | 2739 | nfsd4_init_cb(&clp->cl_cb_null, clp, NULL, NFSPROC4_CLNT_CB_NULL); |
---|
2182 | | - clp->cl_time = get_seconds(); |
---|
| 2740 | + clp->cl_time = ktime_get_boottime_seconds(); |
---|
2183 | 2741 | clear_bit(0, &clp->cl_cb_slot_busy); |
---|
2184 | 2742 | copy_verf(clp, verf); |
---|
2185 | | - rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa); |
---|
| 2743 | + memcpy(&clp->cl_addr, sa, sizeof(struct sockaddr_storage)); |
---|
2186 | 2744 | clp->cl_cb_session = NULL; |
---|
2187 | 2745 | clp->net = net; |
---|
| 2746 | + clp->cl_nfsd_dentry = nfsd_client_mkdir(nn, &clp->cl_nfsdfs, |
---|
| 2747 | + clp->cl_clientid.cl_id - nn->clientid_base, |
---|
| 2748 | + client_files); |
---|
| 2749 | + if (!clp->cl_nfsd_dentry) { |
---|
| 2750 | + free_client(clp); |
---|
| 2751 | + return NULL; |
---|
| 2752 | + } |
---|
2188 | 2753 | return clp; |
---|
2189 | 2754 | } |
---|
2190 | 2755 | |
---|
.. | .. |
---|
2345 | 2910 | conn->cb_prog = se->se_callback_prog; |
---|
2346 | 2911 | conn->cb_ident = se->se_callback_ident; |
---|
2347 | 2912 | memcpy(&conn->cb_saddr, &rqstp->rq_daddr, rqstp->rq_daddrlen); |
---|
| 2913 | + trace_nfsd_cb_args(clp, conn); |
---|
2348 | 2914 | return; |
---|
2349 | 2915 | out_err: |
---|
2350 | 2916 | conn->cb_addr.ss_family = AF_UNSPEC; |
---|
2351 | 2917 | conn->cb_addrlen = 0; |
---|
2352 | | - dprintk("NFSD: this client (clientid %08x/%08x) " |
---|
2353 | | - "will not receive delegations\n", |
---|
2354 | | - clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); |
---|
2355 | | - |
---|
| 2918 | + trace_nfsd_cb_nodelegs(clp); |
---|
2356 | 2919 | return; |
---|
2357 | 2920 | } |
---|
2358 | 2921 | |
---|
.. | .. |
---|
2491 | 3054 | || !list_empty(&clp->cl_lo_states) |
---|
2492 | 3055 | #endif |
---|
2493 | 3056 | || !list_empty(&clp->cl_delegations) |
---|
2494 | | - || !list_empty(&clp->cl_sessions); |
---|
| 3057 | + || !list_empty(&clp->cl_sessions) |
---|
| 3058 | + || !list_empty(&clp->async_copies); |
---|
| 3059 | +} |
---|
| 3060 | + |
---|
| 3061 | +static __be32 copy_impl_id(struct nfs4_client *clp, |
---|
| 3062 | + struct nfsd4_exchange_id *exid) |
---|
| 3063 | +{ |
---|
| 3064 | + if (!exid->nii_domain.data) |
---|
| 3065 | + return 0; |
---|
| 3066 | + xdr_netobj_dup(&clp->cl_nii_domain, &exid->nii_domain, GFP_KERNEL); |
---|
| 3067 | + if (!clp->cl_nii_domain.data) |
---|
| 3068 | + return nfserr_jukebox; |
---|
| 3069 | + xdr_netobj_dup(&clp->cl_nii_name, &exid->nii_name, GFP_KERNEL); |
---|
| 3070 | + if (!clp->cl_nii_name.data) |
---|
| 3071 | + return nfserr_jukebox; |
---|
| 3072 | + clp->cl_nii_time = exid->nii_time; |
---|
| 3073 | + return 0; |
---|
2495 | 3074 | } |
---|
2496 | 3075 | |
---|
2497 | 3076 | __be32 |
---|
.. | .. |
---|
2520 | 3099 | new = create_client(exid->clname, rqstp, &verf); |
---|
2521 | 3100 | if (new == NULL) |
---|
2522 | 3101 | return nfserr_jukebox; |
---|
| 3102 | + status = copy_impl_id(new, exid); |
---|
| 3103 | + if (status) |
---|
| 3104 | + goto out_nolock; |
---|
2523 | 3105 | |
---|
2524 | 3106 | switch (exid->spa_how) { |
---|
2525 | 3107 | case SP4_MACH_CRED: |
---|
.. | .. |
---|
2558 | 3140 | break; |
---|
2559 | 3141 | default: /* checked by xdr code */ |
---|
2560 | 3142 | WARN_ON_ONCE(1); |
---|
| 3143 | + fallthrough; |
---|
2561 | 3144 | case SP4_SSV: |
---|
2562 | 3145 | status = nfserr_encr_alg_unsupp; |
---|
2563 | 3146 | goto out_nolock; |
---|
.. | .. |
---|
2627 | 3210 | new->cl_spo_must_allow.u.words[0] = exid->spo_must_allow[0]; |
---|
2628 | 3211 | new->cl_spo_must_allow.u.words[1] = exid->spo_must_allow[1]; |
---|
2629 | 3212 | |
---|
2630 | | - gen_clid(new, nn); |
---|
2631 | 3213 | add_to_unconfirmed(new); |
---|
2632 | 3214 | swap(new, conf); |
---|
2633 | 3215 | out_copy: |
---|
.. | .. |
---|
2732 | 3314 | * performance. When short on memory we therefore prefer to |
---|
2733 | 3315 | * decrease number of slots instead of their size. Clients that |
---|
2734 | 3316 | * request larger slots than they need will get poor results: |
---|
| 3317 | + * Note that we always allow at least one slot, because our |
---|
| 3318 | + * accounting is soft and provides no guarantees either way. |
---|
2735 | 3319 | */ |
---|
2736 | | - ca->maxreqs = nfsd4_get_drc_mem(ca); |
---|
2737 | | - if (!ca->maxreqs) |
---|
2738 | | - return nfserr_jukebox; |
---|
| 3320 | + ca->maxreqs = nfsd4_get_drc_mem(ca, nn); |
---|
2739 | 3321 | |
---|
2740 | 3322 | return nfs_ok; |
---|
2741 | 3323 | } |
---|
.. | .. |
---|
2913 | 3495 | case NFS4_CDFC4_BACK_OR_BOTH: |
---|
2914 | 3496 | *dir = NFS4_CDFC4_BOTH; |
---|
2915 | 3497 | return nfs_ok; |
---|
2916 | | - }; |
---|
| 3498 | + } |
---|
2917 | 3499 | return nfserr_inval; |
---|
2918 | 3500 | } |
---|
2919 | 3501 | |
---|
.. | .. |
---|
2939 | 3521 | return nfs_ok; |
---|
2940 | 3522 | } |
---|
2941 | 3523 | |
---|
| 3524 | +static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s) |
---|
| 3525 | +{ |
---|
| 3526 | + struct nfsd4_conn *c; |
---|
| 3527 | + |
---|
| 3528 | + list_for_each_entry(c, &s->se_conns, cn_persession) { |
---|
| 3529 | + if (c->cn_xprt == xpt) { |
---|
| 3530 | + return c; |
---|
| 3531 | + } |
---|
| 3532 | + } |
---|
| 3533 | + return NULL; |
---|
| 3534 | +} |
---|
| 3535 | + |
---|
| 3536 | +static __be32 nfsd4_match_existing_connection(struct svc_rqst *rqst, |
---|
| 3537 | + struct nfsd4_session *session, u32 req, struct nfsd4_conn **conn) |
---|
| 3538 | +{ |
---|
| 3539 | + struct nfs4_client *clp = session->se_client; |
---|
| 3540 | + struct svc_xprt *xpt = rqst->rq_xprt; |
---|
| 3541 | + struct nfsd4_conn *c; |
---|
| 3542 | + __be32 status; |
---|
| 3543 | + |
---|
| 3544 | + /* Following the last paragraph of RFC 5661 Section 18.34.3: */ |
---|
| 3545 | + spin_lock(&clp->cl_lock); |
---|
| 3546 | + c = __nfsd4_find_conn(xpt, session); |
---|
| 3547 | + if (!c) |
---|
| 3548 | + status = nfserr_noent; |
---|
| 3549 | + else if (req == c->cn_flags) |
---|
| 3550 | + status = nfs_ok; |
---|
| 3551 | + else if (req == NFS4_CDFC4_FORE_OR_BOTH && |
---|
| 3552 | + c->cn_flags != NFS4_CDFC4_BACK) |
---|
| 3553 | + status = nfs_ok; |
---|
| 3554 | + else if (req == NFS4_CDFC4_BACK_OR_BOTH && |
---|
| 3555 | + c->cn_flags != NFS4_CDFC4_FORE) |
---|
| 3556 | + status = nfs_ok; |
---|
| 3557 | + else |
---|
| 3558 | + status = nfserr_inval; |
---|
| 3559 | + spin_unlock(&clp->cl_lock); |
---|
| 3560 | + if (status == nfs_ok && conn) |
---|
| 3561 | + *conn = c; |
---|
| 3562 | + return status; |
---|
| 3563 | +} |
---|
| 3564 | + |
---|
2942 | 3565 | __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp, |
---|
2943 | 3566 | struct nfsd4_compound_state *cstate, |
---|
2944 | 3567 | union nfsd4_op_u *u) |
---|
.. | .. |
---|
2959 | 3582 | goto out_no_session; |
---|
2960 | 3583 | status = nfserr_wrong_cred; |
---|
2961 | 3584 | if (!nfsd4_mach_creds_match(session->se_client, rqstp)) |
---|
| 3585 | + goto out; |
---|
| 3586 | + status = nfsd4_match_existing_connection(rqstp, session, |
---|
| 3587 | + bcts->dir, &conn); |
---|
| 3588 | + if (status == nfs_ok) { |
---|
| 3589 | + if (bcts->dir == NFS4_CDFC4_FORE_OR_BOTH || |
---|
| 3590 | + bcts->dir == NFS4_CDFC4_BACK) |
---|
| 3591 | + conn->cn_flags |= NFS4_CDFC4_BACK; |
---|
| 3592 | + nfsd4_probe_callback(session->se_client); |
---|
| 3593 | + goto out; |
---|
| 3594 | + } |
---|
| 3595 | + if (status == nfserr_inval) |
---|
2962 | 3596 | goto out; |
---|
2963 | 3597 | status = nfsd4_map_bcts_dir(&bcts->dir); |
---|
2964 | 3598 | if (status) |
---|
.. | .. |
---|
3023 | 3657 | spin_unlock(&nn->client_lock); |
---|
3024 | 3658 | out: |
---|
3025 | 3659 | return status; |
---|
3026 | | -} |
---|
3027 | | - |
---|
3028 | | -static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s) |
---|
3029 | | -{ |
---|
3030 | | - struct nfsd4_conn *c; |
---|
3031 | | - |
---|
3032 | | - list_for_each_entry(c, &s->se_conns, cn_persession) { |
---|
3033 | | - if (c->cn_xprt == xpt) { |
---|
3034 | | - return c; |
---|
3035 | | - } |
---|
3036 | | - } |
---|
3037 | | - return NULL; |
---|
3038 | 3660 | } |
---|
3039 | 3661 | |
---|
3040 | 3662 | static __be32 nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses) |
---|
.. | .. |
---|
3331 | 3953 | |
---|
3332 | 3954 | status = nfs_ok; |
---|
3333 | 3955 | nfsd4_client_record_create(cstate->session->se_client); |
---|
| 3956 | + inc_reclaim_complete(cstate->session->se_client); |
---|
3334 | 3957 | out: |
---|
3335 | 3958 | return status; |
---|
3336 | 3959 | } |
---|
.. | .. |
---|
3359 | 3982 | if (clp_used_exchangeid(conf)) |
---|
3360 | 3983 | goto out; |
---|
3361 | 3984 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) { |
---|
3362 | | - char addr_str[INET6_ADDRSTRLEN]; |
---|
3363 | | - rpc_ntop((struct sockaddr *) &conf->cl_addr, addr_str, |
---|
3364 | | - sizeof(addr_str)); |
---|
3365 | | - dprintk("NFSD: setclientid: string in use by client " |
---|
3366 | | - "at %s\n", addr_str); |
---|
| 3985 | + trace_nfsd_clid_inuse_err(conf); |
---|
3367 | 3986 | goto out; |
---|
3368 | 3987 | } |
---|
3369 | 3988 | } |
---|
3370 | 3989 | unconf = find_unconfirmed_client_by_name(&clname, nn); |
---|
3371 | 3990 | if (unconf) |
---|
3372 | 3991 | unhash_client_locked(unconf); |
---|
| 3992 | + /* We need to handle only case 1: probable callback update */ |
---|
3373 | 3993 | if (conf && same_verf(&conf->cl_verifier, &clverifier)) { |
---|
3374 | | - /* case 1: probable callback update */ |
---|
3375 | 3994 | copy_clid(new, conf); |
---|
3376 | 3995 | gen_confirm(new, nn); |
---|
3377 | | - } else /* case 4 (new client) or cases 2, 3 (client reboot): */ |
---|
3378 | | - gen_clid(new, nn); |
---|
| 3996 | + } |
---|
3379 | 3997 | new->cl_minorversion = 0; |
---|
3380 | 3998 | gen_callback(new, setclid, rqstp); |
---|
3381 | 3999 | add_to_unconfirmed(new); |
---|
.. | .. |
---|
3558 | 4176 | out_free_client_slab: |
---|
3559 | 4177 | kmem_cache_destroy(client_slab); |
---|
3560 | 4178 | out: |
---|
3561 | | - dprintk("nfsd4: out of memory while initializing nfsv4\n"); |
---|
3562 | 4179 | return -ENOMEM; |
---|
3563 | 4180 | } |
---|
3564 | 4181 | |
---|
.. | .. |
---|
3598 | 4215 | if (!sop) |
---|
3599 | 4216 | return NULL; |
---|
3600 | 4217 | |
---|
3601 | | - sop->so_owner.data = kmemdup(owner->data, owner->len, GFP_KERNEL); |
---|
| 4218 | + xdr_netobj_dup(&sop->so_owner, owner, GFP_KERNEL); |
---|
3602 | 4219 | if (!sop->so_owner.data) { |
---|
3603 | 4220 | kmem_cache_free(slab, sop); |
---|
3604 | 4221 | return NULL; |
---|
3605 | 4222 | } |
---|
3606 | | - sop->so_owner.len = owner->len; |
---|
3607 | 4223 | |
---|
3608 | 4224 | INIT_LIST_HEAD(&sop->so_stateids); |
---|
3609 | 4225 | sop->so_client = clp; |
---|
.. | .. |
---|
3825 | 4441 | last = oo->oo_last_closed_stid; |
---|
3826 | 4442 | oo->oo_last_closed_stid = s; |
---|
3827 | 4443 | list_move_tail(&oo->oo_close_lru, &nn->close_lru); |
---|
3828 | | - oo->oo_time = get_seconds(); |
---|
| 4444 | + oo->oo_time = ktime_get_boottime_seconds(); |
---|
3829 | 4445 | spin_unlock(&nn->client_lock); |
---|
3830 | 4446 | if (last) |
---|
3831 | 4447 | nfs4_put_stid(&last->st_stid); |
---|
.. | .. |
---|
3837 | 4453 | { |
---|
3838 | 4454 | struct nfs4_file *fp; |
---|
3839 | 4455 | |
---|
3840 | | - hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash) { |
---|
| 4456 | + hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash, |
---|
| 4457 | + lockdep_is_held(&state_lock)) { |
---|
3841 | 4458 | if (fh_match(&fp->fi_fhandle, fh)) { |
---|
3842 | 4459 | if (refcount_inc_not_zero(&fp->fi_ref)) |
---|
3843 | 4460 | return fp; |
---|
.. | .. |
---|
3920 | 4537 | */ |
---|
3921 | 4538 | spin_lock(&state_lock); |
---|
3922 | 4539 | if (delegation_hashed(dp) && dp->dl_time == 0) { |
---|
3923 | | - dp->dl_time = get_seconds(); |
---|
| 4540 | + dp->dl_time = ktime_get_boottime_seconds(); |
---|
3924 | 4541 | list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru); |
---|
3925 | 4542 | } |
---|
3926 | 4543 | spin_unlock(&state_lock); |
---|
.. | .. |
---|
3931 | 4548 | { |
---|
3932 | 4549 | struct nfs4_delegation *dp = cb_to_delegation(cb); |
---|
3933 | 4550 | |
---|
3934 | | - if (dp->dl_stid.sc_type == NFS4_CLOSED_DELEG_STID) |
---|
| 4551 | + if (dp->dl_stid.sc_type == NFS4_CLOSED_DELEG_STID || |
---|
| 4552 | + dp->dl_stid.sc_type == NFS4_REVOKED_DELEG_STID) |
---|
3935 | 4553 | return 1; |
---|
3936 | 4554 | |
---|
3937 | 4555 | switch (task->tk_status) { |
---|
3938 | 4556 | case 0: |
---|
3939 | 4557 | return 1; |
---|
| 4558 | + case -NFS4ERR_DELAY: |
---|
| 4559 | + rpc_delay(task, 2 * HZ); |
---|
| 4560 | + return 0; |
---|
3940 | 4561 | case -EBADHANDLE: |
---|
3941 | 4562 | case -NFS4ERR_BAD_STATEID: |
---|
3942 | 4563 | /* |
---|
.. | .. |
---|
3947 | 4568 | rpc_delay(task, 2 * HZ); |
---|
3948 | 4569 | return 0; |
---|
3949 | 4570 | } |
---|
3950 | | - /*FALLTHRU*/ |
---|
| 4571 | + fallthrough; |
---|
3951 | 4572 | default: |
---|
3952 | | - return -1; |
---|
| 4573 | + return 1; |
---|
3953 | 4574 | } |
---|
3954 | 4575 | } |
---|
3955 | 4576 | |
---|
.. | .. |
---|
3987 | 4608 | struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner; |
---|
3988 | 4609 | struct nfs4_file *fp = dp->dl_stid.sc_file; |
---|
3989 | 4610 | |
---|
| 4611 | + trace_nfsd_deleg_break(&dp->dl_stid.sc_stateid); |
---|
| 4612 | + |
---|
3990 | 4613 | /* |
---|
3991 | 4614 | * We don't want the locks code to timeout the lease for us; |
---|
3992 | 4615 | * we'll remove it ourself if a delegation isn't returned |
---|
.. | .. |
---|
4001 | 4624 | return ret; |
---|
4002 | 4625 | } |
---|
4003 | 4626 | |
---|
| 4627 | +/** |
---|
| 4628 | + * nfsd_breaker_owns_lease - Check if lease conflict was resolved |
---|
| 4629 | + * @fl: Lock state to check |
---|
| 4630 | + * |
---|
| 4631 | + * Return values: |
---|
| 4632 | + * %true: Lease conflict was resolved |
---|
| 4633 | + * %false: Lease conflict was not resolved. |
---|
| 4634 | + */ |
---|
| 4635 | +static bool nfsd_breaker_owns_lease(struct file_lock *fl) |
---|
| 4636 | +{ |
---|
| 4637 | + struct nfs4_delegation *dl = fl->fl_owner; |
---|
| 4638 | + struct svc_rqst *rqst; |
---|
| 4639 | + struct nfs4_client *clp; |
---|
| 4640 | + |
---|
| 4641 | + if (!i_am_nfsd()) |
---|
| 4642 | + return false; |
---|
| 4643 | + rqst = kthread_data(current); |
---|
| 4644 | + /* Note rq_prog == NFS_ACL_PROGRAM is also possible: */ |
---|
| 4645 | + if (rqst->rq_prog != NFS_PROGRAM || rqst->rq_vers < 4) |
---|
| 4646 | + return false; |
---|
| 4647 | + clp = *(rqst->rq_lease_breaker); |
---|
| 4648 | + return dl->dl_stid.sc_client == clp; |
---|
| 4649 | +} |
---|
| 4650 | + |
---|
4004 | 4651 | static int |
---|
4005 | 4652 | nfsd_change_deleg_cb(struct file_lock *onlist, int arg, |
---|
4006 | 4653 | struct list_head *dispose) |
---|
.. | .. |
---|
4012 | 4659 | } |
---|
4013 | 4660 | |
---|
4014 | 4661 | static const struct lock_manager_operations nfsd_lease_mng_ops = { |
---|
| 4662 | + .lm_breaker_owns_lease = nfsd_breaker_owns_lease, |
---|
4015 | 4663 | .lm_break = nfsd_break_deleg_cb, |
---|
4016 | 4664 | .lm_change = nfsd_change_deleg_cb, |
---|
4017 | 4665 | }; |
---|
.. | .. |
---|
4029 | 4677 | |
---|
4030 | 4678 | static __be32 lookup_clientid(clientid_t *clid, |
---|
4031 | 4679 | struct nfsd4_compound_state *cstate, |
---|
4032 | | - struct nfsd_net *nn) |
---|
| 4680 | + struct nfsd_net *nn, |
---|
| 4681 | + bool sessions) |
---|
4033 | 4682 | { |
---|
4034 | 4683 | struct nfs4_client *found; |
---|
4035 | 4684 | |
---|
.. | .. |
---|
4050 | 4699 | */ |
---|
4051 | 4700 | WARN_ON_ONCE(cstate->session); |
---|
4052 | 4701 | spin_lock(&nn->client_lock); |
---|
4053 | | - found = find_confirmed_client(clid, false, nn); |
---|
| 4702 | + found = find_confirmed_client(clid, sessions, nn); |
---|
4054 | 4703 | if (!found) { |
---|
4055 | 4704 | spin_unlock(&nn->client_lock); |
---|
4056 | 4705 | return nfserr_expired; |
---|
4057 | 4706 | } |
---|
4058 | | - atomic_inc(&found->cl_refcount); |
---|
| 4707 | + atomic_inc(&found->cl_rpc_users); |
---|
4059 | 4708 | spin_unlock(&nn->client_lock); |
---|
4060 | 4709 | |
---|
4061 | 4710 | /* Cache the nfs4_client in cstate! */ |
---|
.. | .. |
---|
4083 | 4732 | if (open->op_file == NULL) |
---|
4084 | 4733 | return nfserr_jukebox; |
---|
4085 | 4734 | |
---|
4086 | | - status = lookup_clientid(clientid, cstate, nn); |
---|
| 4735 | + status = lookup_clientid(clientid, cstate, nn, false); |
---|
4087 | 4736 | if (status) |
---|
4088 | 4737 | return status; |
---|
4089 | 4738 | clp = cstate->clp; |
---|
.. | .. |
---|
4211 | 4860 | return 0; |
---|
4212 | 4861 | if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) |
---|
4213 | 4862 | return nfserr_inval; |
---|
4214 | | - return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0); |
---|
| 4863 | + return nfsd_setattr(rqstp, fh, &iattr, 0, (time64_t)0); |
---|
4215 | 4864 | } |
---|
4216 | 4865 | |
---|
4217 | 4866 | static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp, |
---|
4218 | 4867 | struct svc_fh *cur_fh, struct nfs4_ol_stateid *stp, |
---|
4219 | 4868 | struct nfsd4_open *open) |
---|
4220 | 4869 | { |
---|
4221 | | - struct file *filp = NULL; |
---|
| 4870 | + struct nfsd_file *nf = NULL; |
---|
4222 | 4871 | __be32 status; |
---|
4223 | 4872 | int oflag = nfs4_access_to_omode(open->op_share_access); |
---|
4224 | 4873 | int access = nfs4_access_to_access(open->op_share_access); |
---|
.. | .. |
---|
4254 | 4903 | |
---|
4255 | 4904 | if (!fp->fi_fds[oflag]) { |
---|
4256 | 4905 | spin_unlock(&fp->fi_lock); |
---|
4257 | | - status = nfsd_open(rqstp, cur_fh, S_IFREG, access, &filp); |
---|
| 4906 | + status = nfsd_file_acquire(rqstp, cur_fh, access, &nf); |
---|
4258 | 4907 | if (status) |
---|
4259 | 4908 | goto out_put_access; |
---|
4260 | 4909 | spin_lock(&fp->fi_lock); |
---|
4261 | 4910 | if (!fp->fi_fds[oflag]) { |
---|
4262 | | - fp->fi_fds[oflag] = filp; |
---|
4263 | | - filp = NULL; |
---|
| 4911 | + fp->fi_fds[oflag] = nf; |
---|
| 4912 | + nf = NULL; |
---|
4264 | 4913 | } |
---|
4265 | 4914 | } |
---|
4266 | 4915 | spin_unlock(&fp->fi_lock); |
---|
4267 | | - if (filp) |
---|
4268 | | - fput(filp); |
---|
| 4916 | + if (nf) |
---|
| 4917 | + nfsd_file_put(nf); |
---|
| 4918 | + |
---|
| 4919 | + status = nfserrno(nfsd_open_break_lease(cur_fh->fh_dentry->d_inode, |
---|
| 4920 | + access)); |
---|
| 4921 | + if (status) |
---|
| 4922 | + goto out_put_access; |
---|
4269 | 4923 | |
---|
4270 | 4924 | status = nfsd4_truncate(rqstp, cur_fh, open); |
---|
4271 | 4925 | if (status) |
---|
.. | .. |
---|
4334 | 4988 | fl->fl_end = OFFSET_MAX; |
---|
4335 | 4989 | fl->fl_owner = (fl_owner_t)dp; |
---|
4336 | 4990 | fl->fl_pid = current->tgid; |
---|
4337 | | - fl->fl_file = dp->dl_stid.sc_file->fi_deleg_file; |
---|
| 4991 | + fl->fl_file = dp->dl_stid.sc_file->fi_deleg_file->nf_file; |
---|
4338 | 4992 | return fl; |
---|
4339 | 4993 | } |
---|
4340 | 4994 | |
---|
.. | .. |
---|
4344 | 4998 | { |
---|
4345 | 4999 | int status = 0; |
---|
4346 | 5000 | struct nfs4_delegation *dp; |
---|
4347 | | - struct file *filp; |
---|
| 5001 | + struct nfsd_file *nf; |
---|
4348 | 5002 | struct file_lock *fl; |
---|
4349 | 5003 | |
---|
4350 | 5004 | /* |
---|
.. | .. |
---|
4355 | 5009 | if (fp->fi_had_conflict) |
---|
4356 | 5010 | return ERR_PTR(-EAGAIN); |
---|
4357 | 5011 | |
---|
4358 | | - filp = find_readable_file(fp); |
---|
4359 | | - if (!filp) { |
---|
| 5012 | + nf = find_readable_file(fp); |
---|
| 5013 | + if (!nf) { |
---|
4360 | 5014 | /* We should always have a readable file here */ |
---|
4361 | 5015 | WARN_ON_ONCE(1); |
---|
4362 | 5016 | return ERR_PTR(-EBADF); |
---|
.. | .. |
---|
4366 | 5020 | if (nfs4_delegation_exists(clp, fp)) |
---|
4367 | 5021 | status = -EAGAIN; |
---|
4368 | 5022 | else if (!fp->fi_deleg_file) { |
---|
4369 | | - fp->fi_deleg_file = filp; |
---|
| 5023 | + fp->fi_deleg_file = nf; |
---|
4370 | 5024 | /* increment early to prevent fi_deleg_file from being |
---|
4371 | 5025 | * cleared */ |
---|
4372 | 5026 | fp->fi_delegees = 1; |
---|
4373 | | - filp = NULL; |
---|
| 5027 | + nf = NULL; |
---|
4374 | 5028 | } else |
---|
4375 | 5029 | fp->fi_delegees++; |
---|
4376 | 5030 | spin_unlock(&fp->fi_lock); |
---|
4377 | 5031 | spin_unlock(&state_lock); |
---|
4378 | | - if (filp) |
---|
4379 | | - fput(filp); |
---|
| 5032 | + if (nf) |
---|
| 5033 | + nfsd_file_put(nf); |
---|
4380 | 5034 | if (status) |
---|
4381 | 5035 | return ERR_PTR(status); |
---|
4382 | 5036 | |
---|
.. | .. |
---|
4389 | 5043 | if (!fl) |
---|
4390 | 5044 | goto out_clnt_odstate; |
---|
4391 | 5045 | |
---|
4392 | | - status = vfs_setlease(fp->fi_deleg_file, fl->fl_type, &fl, NULL); |
---|
| 5046 | + status = vfs_setlease(fp->fi_deleg_file->nf_file, fl->fl_type, &fl, NULL); |
---|
4393 | 5047 | if (fl) |
---|
4394 | 5048 | locks_free_lock(fl); |
---|
4395 | 5049 | if (status) |
---|
.. | .. |
---|
4409 | 5063 | |
---|
4410 | 5064 | return dp; |
---|
4411 | 5065 | out_unlock: |
---|
4412 | | - vfs_setlease(fp->fi_deleg_file, F_UNLCK, NULL, (void **)&dp); |
---|
| 5066 | + vfs_setlease(fp->fi_deleg_file->nf_file, F_UNLCK, NULL, (void **)&dp); |
---|
4413 | 5067 | out_clnt_odstate: |
---|
4414 | 5068 | put_clnt_odstate(dp->dl_clnt_odstate); |
---|
4415 | 5069 | nfs4_put_stid(&dp->dl_stid); |
---|
.. | .. |
---|
4496 | 5150 | |
---|
4497 | 5151 | memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid)); |
---|
4498 | 5152 | |
---|
4499 | | - dprintk("NFSD: delegation stateid=" STATEID_FMT "\n", |
---|
4500 | | - STATEID_VAL(&dp->dl_stid.sc_stateid)); |
---|
| 5153 | + trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid); |
---|
4501 | 5154 | open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; |
---|
4502 | 5155 | nfs4_put_stid(&dp->dl_stid); |
---|
4503 | 5156 | return; |
---|
.. | .. |
---|
4614 | 5267 | nfs4_open_delegation(current_fh, open, stp); |
---|
4615 | 5268 | nodeleg: |
---|
4616 | 5269 | status = nfs_ok; |
---|
4617 | | - |
---|
4618 | | - dprintk("%s: stateid=" STATEID_FMT "\n", __func__, |
---|
4619 | | - STATEID_VAL(&stp->st_stid.sc_stateid)); |
---|
| 5270 | + trace_nfsd_open(&stp->st_stid.sc_stateid); |
---|
4620 | 5271 | out: |
---|
4621 | 5272 | /* 4.1 client trying to upgrade/downgrade delegation? */ |
---|
4622 | 5273 | if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp && |
---|
.. | .. |
---|
4670 | 5321 | __be32 status; |
---|
4671 | 5322 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
---|
4672 | 5323 | |
---|
4673 | | - dprintk("process_renew(%08x/%08x): starting\n", |
---|
4674 | | - clid->cl_boot, clid->cl_id); |
---|
4675 | | - status = lookup_clientid(clid, cstate, nn); |
---|
| 5324 | + trace_nfsd_clid_renew(clid); |
---|
| 5325 | + status = lookup_clientid(clid, cstate, nn, false); |
---|
4676 | 5326 | if (status) |
---|
4677 | 5327 | goto out; |
---|
4678 | 5328 | clp = cstate->clp; |
---|
.. | .. |
---|
4692 | 5342 | if (nn->grace_ended) |
---|
4693 | 5343 | return; |
---|
4694 | 5344 | |
---|
4695 | | - dprintk("NFSD: end of grace period\n"); |
---|
| 5345 | + trace_nfsd_grace_complete(nn); |
---|
4696 | 5346 | nn->grace_ended = true; |
---|
4697 | 5347 | /* |
---|
4698 | 5348 | * If the server goes down again right now, an NFSv4 |
---|
.. | .. |
---|
4724 | 5374 | */ |
---|
4725 | 5375 | static bool clients_still_reclaiming(struct nfsd_net *nn) |
---|
4726 | 5376 | { |
---|
4727 | | - unsigned long now = get_seconds(); |
---|
4728 | | - unsigned long double_grace_period_end = nn->boot_time + |
---|
4729 | | - 2 * nn->nfsd4_lease; |
---|
| 5377 | + time64_t double_grace_period_end = nn->boot_time + |
---|
| 5378 | + 2 * nn->nfsd4_lease; |
---|
4730 | 5379 | |
---|
| 5380 | + if (nn->track_reclaim_completes && |
---|
| 5381 | + atomic_read(&nn->nr_reclaim_complete) == |
---|
| 5382 | + nn->reclaim_str_hashtbl_size) |
---|
| 5383 | + return false; |
---|
4731 | 5384 | if (!nn->somebody_reclaimed) |
---|
4732 | 5385 | return false; |
---|
4733 | 5386 | nn->somebody_reclaimed = false; |
---|
.. | .. |
---|
4735 | 5388 | * If we've given them *two* lease times to reclaim, and they're |
---|
4736 | 5389 | * still not done, give up: |
---|
4737 | 5390 | */ |
---|
4738 | | - if (time_after(now, double_grace_period_end)) |
---|
| 5391 | + if (ktime_get_boottime_seconds() > double_grace_period_end) |
---|
4739 | 5392 | return false; |
---|
4740 | 5393 | return true; |
---|
4741 | 5394 | } |
---|
4742 | 5395 | |
---|
4743 | | -static time_t |
---|
| 5396 | +static time64_t |
---|
4744 | 5397 | nfs4_laundromat(struct nfsd_net *nn) |
---|
4745 | 5398 | { |
---|
4746 | 5399 | struct nfs4_client *clp; |
---|
.. | .. |
---|
4749 | 5402 | struct nfs4_ol_stateid *stp; |
---|
4750 | 5403 | struct nfsd4_blocked_lock *nbl; |
---|
4751 | 5404 | struct list_head *pos, *next, reaplist; |
---|
4752 | | - time_t cutoff = get_seconds() - nn->nfsd4_lease; |
---|
4753 | | - time_t t, new_timeo = nn->nfsd4_lease; |
---|
4754 | | - |
---|
4755 | | - dprintk("NFSD: laundromat service - starting\n"); |
---|
| 5405 | + time64_t cutoff = ktime_get_boottime_seconds() - nn->nfsd4_lease; |
---|
| 5406 | + time64_t t, new_timeo = nn->nfsd4_lease; |
---|
| 5407 | + struct nfs4_cpntf_state *cps; |
---|
| 5408 | + copy_stateid_t *cps_t; |
---|
| 5409 | + int i; |
---|
4756 | 5410 | |
---|
4757 | 5411 | if (clients_still_reclaiming(nn)) { |
---|
4758 | 5412 | new_timeo = 0; |
---|
.. | .. |
---|
4760 | 5414 | } |
---|
4761 | 5415 | nfsd4_end_grace(nn); |
---|
4762 | 5416 | INIT_LIST_HEAD(&reaplist); |
---|
| 5417 | + |
---|
| 5418 | + spin_lock(&nn->s2s_cp_lock); |
---|
| 5419 | + idr_for_each_entry(&nn->s2s_cp_stateids, cps_t, i) { |
---|
| 5420 | + cps = container_of(cps_t, struct nfs4_cpntf_state, cp_stateid); |
---|
| 5421 | + if (cps->cp_stateid.sc_type == NFS4_COPYNOTIFY_STID && |
---|
| 5422 | + cps->cpntf_time < cutoff) |
---|
| 5423 | + _free_cpntf_state_locked(nn, cps); |
---|
| 5424 | + } |
---|
| 5425 | + spin_unlock(&nn->s2s_cp_lock); |
---|
| 5426 | + |
---|
4763 | 5427 | spin_lock(&nn->client_lock); |
---|
4764 | 5428 | list_for_each_safe(pos, next, &nn->client_lru) { |
---|
4765 | 5429 | clp = list_entry(pos, struct nfs4_client, cl_lru); |
---|
4766 | | - if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) { |
---|
| 5430 | + if (clp->cl_time > cutoff) { |
---|
4767 | 5431 | t = clp->cl_time - cutoff; |
---|
4768 | 5432 | new_timeo = min(new_timeo, t); |
---|
4769 | 5433 | break; |
---|
4770 | 5434 | } |
---|
4771 | 5435 | if (mark_client_expired_locked(clp)) { |
---|
4772 | | - dprintk("NFSD: client in use (clientid %08x)\n", |
---|
4773 | | - clp->cl_clientid.cl_id); |
---|
| 5436 | + trace_nfsd_clid_expired(&clp->cl_clientid); |
---|
4774 | 5437 | continue; |
---|
4775 | 5438 | } |
---|
4776 | 5439 | list_add(&clp->cl_lru, &reaplist); |
---|
.. | .. |
---|
4778 | 5441 | spin_unlock(&nn->client_lock); |
---|
4779 | 5442 | list_for_each_safe(pos, next, &reaplist) { |
---|
4780 | 5443 | clp = list_entry(pos, struct nfs4_client, cl_lru); |
---|
4781 | | - dprintk("NFSD: purging unused client (clientid %08x)\n", |
---|
4782 | | - clp->cl_clientid.cl_id); |
---|
| 5444 | + trace_nfsd_clid_purged(&clp->cl_clientid); |
---|
4783 | 5445 | list_del_init(&clp->cl_lru); |
---|
4784 | 5446 | expire_client(clp); |
---|
4785 | 5447 | } |
---|
4786 | 5448 | spin_lock(&state_lock); |
---|
4787 | 5449 | list_for_each_safe(pos, next, &nn->del_recall_lru) { |
---|
4788 | 5450 | dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); |
---|
4789 | | - if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) { |
---|
| 5451 | + if (dp->dl_time > cutoff) { |
---|
4790 | 5452 | t = dp->dl_time - cutoff; |
---|
4791 | 5453 | new_timeo = min(new_timeo, t); |
---|
4792 | 5454 | break; |
---|
.. | .. |
---|
4806 | 5468 | while (!list_empty(&nn->close_lru)) { |
---|
4807 | 5469 | oo = list_first_entry(&nn->close_lru, struct nfs4_openowner, |
---|
4808 | 5470 | oo_close_lru); |
---|
4809 | | - if (time_after((unsigned long)oo->oo_time, |
---|
4810 | | - (unsigned long)cutoff)) { |
---|
| 5471 | + if (oo->oo_time > cutoff) { |
---|
4811 | 5472 | t = oo->oo_time - cutoff; |
---|
4812 | 5473 | new_timeo = min(new_timeo, t); |
---|
4813 | 5474 | break; |
---|
.. | .. |
---|
4837 | 5498 | while (!list_empty(&nn->blocked_locks_lru)) { |
---|
4838 | 5499 | nbl = list_first_entry(&nn->blocked_locks_lru, |
---|
4839 | 5500 | struct nfsd4_blocked_lock, nbl_lru); |
---|
4840 | | - if (time_after((unsigned long)nbl->nbl_time, |
---|
4841 | | - (unsigned long)cutoff)) { |
---|
| 5501 | + if (nbl->nbl_time > cutoff) { |
---|
4842 | 5502 | t = nbl->nbl_time - cutoff; |
---|
4843 | 5503 | new_timeo = min(new_timeo, t); |
---|
4844 | 5504 | break; |
---|
.. | .. |
---|
4852 | 5512 | nbl = list_first_entry(&reaplist, |
---|
4853 | 5513 | struct nfsd4_blocked_lock, nbl_lru); |
---|
4854 | 5514 | list_del_init(&nbl->nbl_lru); |
---|
4855 | | - posix_unblock_lock(&nbl->nbl_lock); |
---|
4856 | 5515 | free_blocked_lock(nbl); |
---|
4857 | 5516 | } |
---|
4858 | 5517 | out: |
---|
4859 | | - new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT); |
---|
| 5518 | + new_timeo = max_t(time64_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT); |
---|
4860 | 5519 | return new_timeo; |
---|
4861 | 5520 | } |
---|
4862 | 5521 | |
---|
.. | .. |
---|
4866 | 5525 | static void |
---|
4867 | 5526 | laundromat_main(struct work_struct *laundry) |
---|
4868 | 5527 | { |
---|
4869 | | - time_t t; |
---|
| 5528 | + time64_t t; |
---|
4870 | 5529 | struct delayed_work *dwork = to_delayed_work(laundry); |
---|
4871 | 5530 | struct nfsd_net *nn = container_of(dwork, struct nfsd_net, |
---|
4872 | 5531 | laundromat_work); |
---|
4873 | 5532 | |
---|
4874 | 5533 | t = nfs4_laundromat(nn); |
---|
4875 | | - dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t); |
---|
4876 | 5534 | queue_delayed_work(laundry_wq, &nn->laundromat_work, t*HZ); |
---|
4877 | 5535 | } |
---|
4878 | 5536 | |
---|
.. | .. |
---|
4998 | 5656 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) || |
---|
4999 | 5657 | CLOSE_STATEID(stateid)) |
---|
5000 | 5658 | return status; |
---|
5001 | | - /* Client debugging aid. */ |
---|
5002 | | - if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid)) { |
---|
5003 | | - char addr_str[INET6_ADDRSTRLEN]; |
---|
5004 | | - rpc_ntop((struct sockaddr *)&cl->cl_addr, addr_str, |
---|
5005 | | - sizeof(addr_str)); |
---|
5006 | | - pr_warn_ratelimited("NFSD: client %s testing state ID " |
---|
5007 | | - "with incorrect client ID\n", addr_str); |
---|
5008 | | - return status; |
---|
5009 | | - } |
---|
5010 | 5659 | spin_lock(&cl->cl_lock); |
---|
5011 | 5660 | s = find_stateid_locked(cl, stateid); |
---|
5012 | 5661 | if (!s) |
---|
.. | .. |
---|
5027 | 5676 | break; |
---|
5028 | 5677 | default: |
---|
5029 | 5678 | printk("unknown stateid type %x\n", s->sc_type); |
---|
5030 | | - /* Fallthrough */ |
---|
| 5679 | + fallthrough; |
---|
5031 | 5680 | case NFS4_CLOSED_STID: |
---|
5032 | 5681 | case NFS4_CLOSED_DELEG_STID: |
---|
5033 | 5682 | status = nfserr_bad_stateid; |
---|
.. | .. |
---|
5057 | 5706 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) || |
---|
5058 | 5707 | CLOSE_STATEID(stateid)) |
---|
5059 | 5708 | return nfserr_bad_stateid; |
---|
5060 | | - status = lookup_clientid(&stateid->si_opaque.so_clid, cstate, nn); |
---|
| 5709 | + status = lookup_clientid(&stateid->si_opaque.so_clid, cstate, nn, |
---|
| 5710 | + false); |
---|
5061 | 5711 | if (status == nfserr_stale_clientid) { |
---|
5062 | 5712 | if (cstate->session) |
---|
5063 | 5713 | return nfserr_bad_stateid; |
---|
.. | .. |
---|
5077 | 5727 | return nfs_ok; |
---|
5078 | 5728 | } |
---|
5079 | 5729 | |
---|
5080 | | -static struct file * |
---|
| 5730 | +static struct nfsd_file * |
---|
5081 | 5731 | nfs4_find_file(struct nfs4_stid *s, int flags) |
---|
5082 | 5732 | { |
---|
5083 | 5733 | if (!s) |
---|
.. | .. |
---|
5087 | 5737 | case NFS4_DELEG_STID: |
---|
5088 | 5738 | if (WARN_ON_ONCE(!s->sc_file->fi_deleg_file)) |
---|
5089 | 5739 | return NULL; |
---|
5090 | | - return get_file(s->sc_file->fi_deleg_file); |
---|
| 5740 | + return nfsd_file_get(s->sc_file->fi_deleg_file); |
---|
5091 | 5741 | case NFS4_OPEN_STID: |
---|
5092 | 5742 | case NFS4_LOCK_STID: |
---|
5093 | 5743 | if (flags & RD_STATE) |
---|
5094 | 5744 | return find_readable_file(s->sc_file); |
---|
5095 | 5745 | else |
---|
5096 | 5746 | return find_writeable_file(s->sc_file); |
---|
5097 | | - break; |
---|
5098 | 5747 | } |
---|
5099 | 5748 | |
---|
5100 | 5749 | return NULL; |
---|
5101 | 5750 | } |
---|
5102 | 5751 | |
---|
5103 | 5752 | static __be32 |
---|
5104 | | -nfs4_check_olstateid(struct svc_fh *fhp, struct nfs4_ol_stateid *ols, int flags) |
---|
| 5753 | +nfs4_check_olstateid(struct nfs4_ol_stateid *ols, int flags) |
---|
5105 | 5754 | { |
---|
5106 | 5755 | __be32 status; |
---|
5107 | 5756 | |
---|
.. | .. |
---|
5113 | 5762 | |
---|
5114 | 5763 | static __be32 |
---|
5115 | 5764 | nfs4_check_file(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfs4_stid *s, |
---|
5116 | | - struct file **filpp, bool *tmp_file, int flags) |
---|
| 5765 | + struct nfsd_file **nfp, int flags) |
---|
5117 | 5766 | { |
---|
5118 | 5767 | int acc = (flags & RD_STATE) ? NFSD_MAY_READ : NFSD_MAY_WRITE; |
---|
5119 | | - struct file *file; |
---|
| 5768 | + struct nfsd_file *nf; |
---|
5120 | 5769 | __be32 status; |
---|
5121 | 5770 | |
---|
5122 | | - file = nfs4_find_file(s, flags); |
---|
5123 | | - if (file) { |
---|
| 5771 | + nf = nfs4_find_file(s, flags); |
---|
| 5772 | + if (nf) { |
---|
5124 | 5773 | status = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, |
---|
5125 | 5774 | acc | NFSD_MAY_OWNER_OVERRIDE); |
---|
5126 | 5775 | if (status) { |
---|
5127 | | - fput(file); |
---|
5128 | | - return status; |
---|
| 5776 | + nfsd_file_put(nf); |
---|
| 5777 | + goto out; |
---|
5129 | 5778 | } |
---|
5130 | | - |
---|
5131 | | - *filpp = file; |
---|
5132 | 5779 | } else { |
---|
5133 | | - status = nfsd_open(rqstp, fhp, S_IFREG, acc, filpp); |
---|
| 5780 | + status = nfsd_file_acquire(rqstp, fhp, acc, &nf); |
---|
5134 | 5781 | if (status) |
---|
5135 | 5782 | return status; |
---|
5136 | | - |
---|
5137 | | - if (tmp_file) |
---|
5138 | | - *tmp_file = true; |
---|
5139 | 5783 | } |
---|
| 5784 | + *nfp = nf; |
---|
| 5785 | +out: |
---|
| 5786 | + return status; |
---|
| 5787 | +} |
---|
| 5788 | +static void |
---|
| 5789 | +_free_cpntf_state_locked(struct nfsd_net *nn, struct nfs4_cpntf_state *cps) |
---|
| 5790 | +{ |
---|
| 5791 | + WARN_ON_ONCE(cps->cp_stateid.sc_type != NFS4_COPYNOTIFY_STID); |
---|
| 5792 | + if (!refcount_dec_and_test(&cps->cp_stateid.sc_count)) |
---|
| 5793 | + return; |
---|
| 5794 | + list_del(&cps->cp_list); |
---|
| 5795 | + idr_remove(&nn->s2s_cp_stateids, |
---|
| 5796 | + cps->cp_stateid.stid.si_opaque.so_id); |
---|
| 5797 | + kfree(cps); |
---|
| 5798 | +} |
---|
| 5799 | +/* |
---|
| 5800 | + * A READ from an inter server to server COPY will have a |
---|
| 5801 | + * copy stateid. Look up the copy notify stateid from the |
---|
| 5802 | + * idr structure and take a reference on it. |
---|
| 5803 | + */ |
---|
| 5804 | +__be32 manage_cpntf_state(struct nfsd_net *nn, stateid_t *st, |
---|
| 5805 | + struct nfs4_client *clp, |
---|
| 5806 | + struct nfs4_cpntf_state **cps) |
---|
| 5807 | +{ |
---|
| 5808 | + copy_stateid_t *cps_t; |
---|
| 5809 | + struct nfs4_cpntf_state *state = NULL; |
---|
5140 | 5810 | |
---|
| 5811 | + if (st->si_opaque.so_clid.cl_id != nn->s2s_cp_cl_id) |
---|
| 5812 | + return nfserr_bad_stateid; |
---|
| 5813 | + spin_lock(&nn->s2s_cp_lock); |
---|
| 5814 | + cps_t = idr_find(&nn->s2s_cp_stateids, st->si_opaque.so_id); |
---|
| 5815 | + if (cps_t) { |
---|
| 5816 | + state = container_of(cps_t, struct nfs4_cpntf_state, |
---|
| 5817 | + cp_stateid); |
---|
| 5818 | + if (state->cp_stateid.sc_type != NFS4_COPYNOTIFY_STID) { |
---|
| 5819 | + state = NULL; |
---|
| 5820 | + goto unlock; |
---|
| 5821 | + } |
---|
| 5822 | + if (!clp) |
---|
| 5823 | + refcount_inc(&state->cp_stateid.sc_count); |
---|
| 5824 | + else |
---|
| 5825 | + _free_cpntf_state_locked(nn, state); |
---|
| 5826 | + } |
---|
| 5827 | +unlock: |
---|
| 5828 | + spin_unlock(&nn->s2s_cp_lock); |
---|
| 5829 | + if (!state) |
---|
| 5830 | + return nfserr_bad_stateid; |
---|
| 5831 | + if (!clp && state) |
---|
| 5832 | + *cps = state; |
---|
5141 | 5833 | return 0; |
---|
| 5834 | +} |
---|
| 5835 | + |
---|
| 5836 | +static __be32 find_cpntf_state(struct nfsd_net *nn, stateid_t *st, |
---|
| 5837 | + struct nfs4_stid **stid) |
---|
| 5838 | +{ |
---|
| 5839 | + __be32 status; |
---|
| 5840 | + struct nfs4_cpntf_state *cps = NULL; |
---|
| 5841 | + struct nfsd4_compound_state cstate; |
---|
| 5842 | + |
---|
| 5843 | + status = manage_cpntf_state(nn, st, NULL, &cps); |
---|
| 5844 | + if (status) |
---|
| 5845 | + return status; |
---|
| 5846 | + |
---|
| 5847 | + cps->cpntf_time = ktime_get_boottime_seconds(); |
---|
| 5848 | + memset(&cstate, 0, sizeof(cstate)); |
---|
| 5849 | + status = lookup_clientid(&cps->cp_p_clid, &cstate, nn, true); |
---|
| 5850 | + if (status) |
---|
| 5851 | + goto out; |
---|
| 5852 | + status = nfsd4_lookup_stateid(&cstate, &cps->cp_p_stateid, |
---|
| 5853 | + NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, |
---|
| 5854 | + stid, nn); |
---|
| 5855 | + put_client_renew(cstate.clp); |
---|
| 5856 | +out: |
---|
| 5857 | + nfs4_put_cpntf_state(nn, cps); |
---|
| 5858 | + return status; |
---|
| 5859 | +} |
---|
| 5860 | + |
---|
| 5861 | +void nfs4_put_cpntf_state(struct nfsd_net *nn, struct nfs4_cpntf_state *cps) |
---|
| 5862 | +{ |
---|
| 5863 | + spin_lock(&nn->s2s_cp_lock); |
---|
| 5864 | + _free_cpntf_state_locked(nn, cps); |
---|
| 5865 | + spin_unlock(&nn->s2s_cp_lock); |
---|
5142 | 5866 | } |
---|
5143 | 5867 | |
---|
5144 | 5868 | /* |
---|
.. | .. |
---|
5147 | 5871 | __be32 |
---|
5148 | 5872 | nfs4_preprocess_stateid_op(struct svc_rqst *rqstp, |
---|
5149 | 5873 | struct nfsd4_compound_state *cstate, struct svc_fh *fhp, |
---|
5150 | | - stateid_t *stateid, int flags, struct file **filpp, bool *tmp_file) |
---|
| 5874 | + stateid_t *stateid, int flags, struct nfsd_file **nfp, |
---|
| 5875 | + struct nfs4_stid **cstid) |
---|
5151 | 5876 | { |
---|
5152 | 5877 | struct inode *ino = d_inode(fhp->fh_dentry); |
---|
5153 | 5878 | struct net *net = SVC_NET(rqstp); |
---|
.. | .. |
---|
5155 | 5880 | struct nfs4_stid *s = NULL; |
---|
5156 | 5881 | __be32 status; |
---|
5157 | 5882 | |
---|
5158 | | - if (filpp) |
---|
5159 | | - *filpp = NULL; |
---|
5160 | | - if (tmp_file) |
---|
5161 | | - *tmp_file = false; |
---|
| 5883 | + if (nfp) |
---|
| 5884 | + *nfp = NULL; |
---|
5162 | 5885 | |
---|
5163 | 5886 | if (grace_disallows_io(net, ino)) |
---|
5164 | 5887 | return nfserr_grace; |
---|
.. | .. |
---|
5171 | 5894 | status = nfsd4_lookup_stateid(cstate, stateid, |
---|
5172 | 5895 | NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, |
---|
5173 | 5896 | &s, nn); |
---|
| 5897 | + if (status == nfserr_bad_stateid) |
---|
| 5898 | + status = find_cpntf_state(nn, stateid, &s); |
---|
5174 | 5899 | if (status) |
---|
5175 | 5900 | return status; |
---|
5176 | 5901 | status = nfsd4_stid_check_stateid_generation(stateid, s, |
---|
.. | .. |
---|
5184 | 5909 | break; |
---|
5185 | 5910 | case NFS4_OPEN_STID: |
---|
5186 | 5911 | case NFS4_LOCK_STID: |
---|
5187 | | - status = nfs4_check_olstateid(fhp, openlockstateid(s), flags); |
---|
| 5912 | + status = nfs4_check_olstateid(openlockstateid(s), flags); |
---|
5188 | 5913 | break; |
---|
5189 | 5914 | default: |
---|
5190 | 5915 | status = nfserr_bad_stateid; |
---|
.. | .. |
---|
5195 | 5920 | status = nfs4_check_fh(fhp, s); |
---|
5196 | 5921 | |
---|
5197 | 5922 | done: |
---|
5198 | | - if (!status && filpp) |
---|
5199 | | - status = nfs4_check_file(rqstp, fhp, s, filpp, tmp_file, flags); |
---|
| 5923 | + if (status == nfs_ok && nfp) |
---|
| 5924 | + status = nfs4_check_file(rqstp, fhp, s, nfp, flags); |
---|
5200 | 5925 | out: |
---|
5201 | | - if (s) |
---|
5202 | | - nfs4_put_stid(s); |
---|
| 5926 | + if (s) { |
---|
| 5927 | + if (!status && cstid) |
---|
| 5928 | + *cstid = s; |
---|
| 5929 | + else |
---|
| 5930 | + nfs4_put_stid(s); |
---|
| 5931 | + } |
---|
5203 | 5932 | return status; |
---|
5204 | 5933 | } |
---|
5205 | 5934 | |
---|
.. | .. |
---|
5339 | 6068 | struct nfs4_stid *s; |
---|
5340 | 6069 | struct nfs4_ol_stateid *stp = NULL; |
---|
5341 | 6070 | |
---|
5342 | | - dprintk("NFSD: %s: seqid=%d stateid = " STATEID_FMT "\n", __func__, |
---|
5343 | | - seqid, STATEID_VAL(stateid)); |
---|
| 6071 | + trace_nfsd_preprocess(seqid, stateid); |
---|
5344 | 6072 | |
---|
5345 | 6073 | *stpp = NULL; |
---|
5346 | 6074 | status = nfsd4_lookup_stateid(cstate, stateid, typemask, &s, nn); |
---|
.. | .. |
---|
5409 | 6137 | oo->oo_flags |= NFS4_OO_CONFIRMED; |
---|
5410 | 6138 | nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid); |
---|
5411 | 6139 | mutex_unlock(&stp->st_mutex); |
---|
5412 | | - dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", |
---|
5413 | | - __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); |
---|
5414 | | - |
---|
| 6140 | + trace_nfsd_open_confirm(oc->oc_seqid, &stp->st_stid.sc_stateid); |
---|
5415 | 6141 | nfsd4_client_record_create(oo->oo_owner.so_client); |
---|
5416 | 6142 | status = nfs_ok; |
---|
5417 | 6143 | put_stateid: |
---|
.. | .. |
---|
5496 | 6222 | struct nfs4_client *clp = s->st_stid.sc_client; |
---|
5497 | 6223 | bool unhashed; |
---|
5498 | 6224 | LIST_HEAD(reaplist); |
---|
| 6225 | + struct nfs4_ol_stateid *stp; |
---|
5499 | 6226 | |
---|
5500 | 6227 | spin_lock(&clp->cl_lock); |
---|
5501 | 6228 | unhashed = unhash_open_stateid(s, &reaplist); |
---|
.. | .. |
---|
5504 | 6231 | if (unhashed) |
---|
5505 | 6232 | put_ol_stateid_locked(s, &reaplist); |
---|
5506 | 6233 | spin_unlock(&clp->cl_lock); |
---|
| 6234 | + list_for_each_entry(stp, &reaplist, st_locks) |
---|
| 6235 | + nfs4_free_cpntf_statelist(clp->net, &stp->st_stid); |
---|
5507 | 6236 | free_ol_stateid_reaplist(&reaplist); |
---|
5508 | 6237 | } else { |
---|
5509 | 6238 | spin_unlock(&clp->cl_lock); |
---|
.. | .. |
---|
5685 | 6414 | |
---|
5686 | 6415 | if (fl->fl_lmops == &nfsd_posix_mng_ops) { |
---|
5687 | 6416 | lo = (struct nfs4_lockowner *) fl->fl_owner; |
---|
5688 | | - deny->ld_owner.data = kmemdup(lo->lo_owner.so_owner.data, |
---|
5689 | | - lo->lo_owner.so_owner.len, GFP_KERNEL); |
---|
| 6417 | + xdr_netobj_dup(&deny->ld_owner, &lo->lo_owner.so_owner, |
---|
| 6418 | + GFP_KERNEL); |
---|
5690 | 6419 | if (!deny->ld_owner.data) |
---|
5691 | 6420 | /* We just don't care that much */ |
---|
5692 | 6421 | goto nevermind; |
---|
5693 | | - deny->ld_owner.len = lo->lo_owner.so_owner.len; |
---|
5694 | 6422 | deny->ld_clientid = lo->lo_owner.so_client->cl_clientid; |
---|
5695 | 6423 | } else { |
---|
5696 | 6424 | nevermind: |
---|
.. | .. |
---|
5961 | 6689 | struct nfs4_ol_stateid *lock_stp = NULL; |
---|
5962 | 6690 | struct nfs4_ol_stateid *open_stp = NULL; |
---|
5963 | 6691 | struct nfs4_file *fp; |
---|
5964 | | - struct file *filp = NULL; |
---|
| 6692 | + struct nfsd_file *nf = NULL; |
---|
5965 | 6693 | struct nfsd4_blocked_lock *nbl = NULL; |
---|
5966 | 6694 | struct file_lock *file_lock = NULL; |
---|
5967 | 6695 | struct file_lock *conflock = NULL; |
---|
.. | .. |
---|
6040 | 6768 | case NFS4_READW_LT: |
---|
6041 | 6769 | if (nfsd4_has_session(cstate)) |
---|
6042 | 6770 | fl_flags |= FL_SLEEP; |
---|
6043 | | - /* Fallthrough */ |
---|
| 6771 | + fallthrough; |
---|
6044 | 6772 | case NFS4_READ_LT: |
---|
6045 | 6773 | spin_lock(&fp->fi_lock); |
---|
6046 | | - filp = find_readable_file_locked(fp); |
---|
6047 | | - if (filp) |
---|
| 6774 | + nf = find_readable_file_locked(fp); |
---|
| 6775 | + if (nf) |
---|
6048 | 6776 | get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ); |
---|
6049 | 6777 | spin_unlock(&fp->fi_lock); |
---|
6050 | 6778 | fl_type = F_RDLCK; |
---|
.. | .. |
---|
6052 | 6780 | case NFS4_WRITEW_LT: |
---|
6053 | 6781 | if (nfsd4_has_session(cstate)) |
---|
6054 | 6782 | fl_flags |= FL_SLEEP; |
---|
6055 | | - /* Fallthrough */ |
---|
| 6783 | + fallthrough; |
---|
6056 | 6784 | case NFS4_WRITE_LT: |
---|
6057 | 6785 | spin_lock(&fp->fi_lock); |
---|
6058 | | - filp = find_writeable_file_locked(fp); |
---|
6059 | | - if (filp) |
---|
| 6786 | + nf = find_writeable_file_locked(fp); |
---|
| 6787 | + if (nf) |
---|
6060 | 6788 | get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE); |
---|
6061 | 6789 | spin_unlock(&fp->fi_lock); |
---|
6062 | 6790 | fl_type = F_WRLCK; |
---|
.. | .. |
---|
6066 | 6794 | goto out; |
---|
6067 | 6795 | } |
---|
6068 | 6796 | |
---|
6069 | | - if (!filp) { |
---|
| 6797 | + if (!nf) { |
---|
6070 | 6798 | status = nfserr_openmode; |
---|
6071 | 6799 | goto out; |
---|
6072 | 6800 | } |
---|
.. | .. |
---|
6082 | 6810 | file_lock->fl_type = fl_type; |
---|
6083 | 6811 | file_lock->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(&lock_sop->lo_owner)); |
---|
6084 | 6812 | file_lock->fl_pid = current->tgid; |
---|
6085 | | - file_lock->fl_file = filp; |
---|
| 6813 | + file_lock->fl_file = nf->nf_file; |
---|
6086 | 6814 | file_lock->fl_flags = fl_flags; |
---|
6087 | 6815 | file_lock->fl_lmops = &nfsd_posix_mng_ops; |
---|
6088 | 6816 | file_lock->fl_start = lock->lk_offset; |
---|
.. | .. |
---|
6097 | 6825 | } |
---|
6098 | 6826 | |
---|
6099 | 6827 | if (fl_flags & FL_SLEEP) { |
---|
6100 | | - nbl->nbl_time = get_seconds(); |
---|
| 6828 | + nbl->nbl_time = ktime_get_boottime_seconds(); |
---|
6101 | 6829 | spin_lock(&nn->blocked_locks_lock); |
---|
6102 | 6830 | list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked); |
---|
6103 | 6831 | list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru); |
---|
6104 | 6832 | spin_unlock(&nn->blocked_locks_lock); |
---|
6105 | 6833 | } |
---|
6106 | 6834 | |
---|
6107 | | - err = vfs_lock_file(filp, F_SETLK, file_lock, conflock); |
---|
| 6835 | + err = vfs_lock_file(nf->nf_file, F_SETLK, file_lock, conflock); |
---|
6108 | 6836 | switch (err) { |
---|
6109 | 6837 | case 0: /* success! */ |
---|
6110 | 6838 | nfs4_inc_and_copy_stateid(&lock->lk_resp_stateid, &lock_stp->st_stid); |
---|
.. | .. |
---|
6114 | 6842 | break; |
---|
6115 | 6843 | case FILE_LOCK_DEFERRED: |
---|
6116 | 6844 | nbl = NULL; |
---|
6117 | | - /* Fallthrough */ |
---|
| 6845 | + fallthrough; |
---|
6118 | 6846 | case -EAGAIN: /* conflock holds conflicting lock */ |
---|
6119 | 6847 | status = nfserr_denied; |
---|
6120 | 6848 | dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); |
---|
.. | .. |
---|
6139 | 6867 | } |
---|
6140 | 6868 | free_blocked_lock(nbl); |
---|
6141 | 6869 | } |
---|
6142 | | - if (filp) |
---|
6143 | | - fput(filp); |
---|
| 6870 | + if (nf) |
---|
| 6871 | + nfsd_file_put(nf); |
---|
6144 | 6872 | if (lock_stp) { |
---|
6145 | 6873 | /* Bump seqid manually if the 4.0 replay owner is openowner */ |
---|
6146 | 6874 | if (cstate->replay_owner && |
---|
.. | .. |
---|
6170 | 6898 | /* |
---|
6171 | 6899 | * The NFSv4 spec allows a client to do a LOCKT without holding an OPEN, |
---|
6172 | 6900 | * so we do a temporary open here just to get an open file to pass to |
---|
6173 | | - * vfs_test_lock. (Arguably perhaps test_lock should be done with an |
---|
6174 | | - * inode operation.) |
---|
| 6901 | + * vfs_test_lock. |
---|
6175 | 6902 | */ |
---|
6176 | 6903 | static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock) |
---|
6177 | 6904 | { |
---|
6178 | | - struct file *file; |
---|
6179 | | - __be32 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); |
---|
6180 | | - if (!err) { |
---|
6181 | | - err = nfserrno(vfs_test_lock(file, lock)); |
---|
6182 | | - fput(file); |
---|
6183 | | - } |
---|
| 6905 | + struct nfsd_file *nf; |
---|
| 6906 | + __be32 err; |
---|
| 6907 | + |
---|
| 6908 | + err = nfsd_file_acquire(rqstp, fhp, NFSD_MAY_READ, &nf); |
---|
| 6909 | + if (err) |
---|
| 6910 | + return err; |
---|
| 6911 | + fh_lock(fhp); /* to block new leases till after test_lock: */ |
---|
| 6912 | + err = nfserrno(nfsd_open_break_lease(fhp->fh_dentry->d_inode, |
---|
| 6913 | + NFSD_MAY_READ)); |
---|
| 6914 | + if (err) |
---|
| 6915 | + goto out; |
---|
| 6916 | + lock->fl_file = nf->nf_file; |
---|
| 6917 | + err = nfserrno(vfs_test_lock(nf->nf_file, lock)); |
---|
| 6918 | + lock->fl_file = NULL; |
---|
| 6919 | +out: |
---|
| 6920 | + fh_unlock(fhp); |
---|
| 6921 | + nfsd_file_put(nf); |
---|
6184 | 6922 | return err; |
---|
6185 | 6923 | } |
---|
6186 | 6924 | |
---|
.. | .. |
---|
6204 | 6942 | return nfserr_inval; |
---|
6205 | 6943 | |
---|
6206 | 6944 | if (!nfsd4_has_session(cstate)) { |
---|
6207 | | - status = lookup_clientid(&lockt->lt_clientid, cstate, nn); |
---|
| 6945 | + status = lookup_clientid(&lockt->lt_clientid, cstate, nn, |
---|
| 6946 | + false); |
---|
6208 | 6947 | if (status) |
---|
6209 | 6948 | goto out; |
---|
6210 | 6949 | } |
---|
.. | .. |
---|
6223 | 6962 | case NFS4_READ_LT: |
---|
6224 | 6963 | case NFS4_READW_LT: |
---|
6225 | 6964 | file_lock->fl_type = F_RDLCK; |
---|
6226 | | - break; |
---|
| 6965 | + break; |
---|
6227 | 6966 | case NFS4_WRITE_LT: |
---|
6228 | 6967 | case NFS4_WRITEW_LT: |
---|
6229 | 6968 | file_lock->fl_type = F_WRLCK; |
---|
6230 | | - break; |
---|
| 6969 | + break; |
---|
6231 | 6970 | default: |
---|
6232 | 6971 | dprintk("NFSD: nfs4_lockt: bad lock type!\n"); |
---|
6233 | 6972 | status = nfserr_inval; |
---|
6234 | | - goto out; |
---|
| 6973 | + goto out; |
---|
6235 | 6974 | } |
---|
6236 | 6975 | |
---|
6237 | 6976 | lo = find_lockowner_str(cstate->clp, &lockt->lt_owner); |
---|
.. | .. |
---|
6267 | 7006 | { |
---|
6268 | 7007 | struct nfsd4_locku *locku = &u->locku; |
---|
6269 | 7008 | struct nfs4_ol_stateid *stp; |
---|
6270 | | - struct file *filp = NULL; |
---|
| 7009 | + struct nfsd_file *nf = NULL; |
---|
6271 | 7010 | struct file_lock *file_lock = NULL; |
---|
6272 | 7011 | __be32 status; |
---|
6273 | 7012 | int err; |
---|
.. | .. |
---|
6285 | 7024 | &stp, nn); |
---|
6286 | 7025 | if (status) |
---|
6287 | 7026 | goto out; |
---|
6288 | | - filp = find_any_file(stp->st_stid.sc_file); |
---|
6289 | | - if (!filp) { |
---|
| 7027 | + nf = find_any_file(stp->st_stid.sc_file); |
---|
| 7028 | + if (!nf) { |
---|
6290 | 7029 | status = nfserr_lock_range; |
---|
6291 | 7030 | goto put_stateid; |
---|
6292 | 7031 | } |
---|
.. | .. |
---|
6294 | 7033 | if (!file_lock) { |
---|
6295 | 7034 | dprintk("NFSD: %s: unable to allocate lock!\n", __func__); |
---|
6296 | 7035 | status = nfserr_jukebox; |
---|
6297 | | - goto fput; |
---|
| 7036 | + goto put_file; |
---|
6298 | 7037 | } |
---|
6299 | 7038 | |
---|
6300 | 7039 | file_lock->fl_type = F_UNLCK; |
---|
6301 | 7040 | file_lock->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(stp->st_stateowner)); |
---|
6302 | 7041 | file_lock->fl_pid = current->tgid; |
---|
6303 | | - file_lock->fl_file = filp; |
---|
| 7042 | + file_lock->fl_file = nf->nf_file; |
---|
6304 | 7043 | file_lock->fl_flags = FL_POSIX; |
---|
6305 | 7044 | file_lock->fl_lmops = &nfsd_posix_mng_ops; |
---|
6306 | 7045 | file_lock->fl_start = locku->lu_offset; |
---|
.. | .. |
---|
6309 | 7048 | locku->lu_length); |
---|
6310 | 7049 | nfs4_transform_lock_offset(file_lock); |
---|
6311 | 7050 | |
---|
6312 | | - err = vfs_lock_file(filp, F_SETLK, file_lock, NULL); |
---|
| 7051 | + err = vfs_lock_file(nf->nf_file, F_SETLK, file_lock, NULL); |
---|
6313 | 7052 | if (err) { |
---|
6314 | 7053 | dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n"); |
---|
6315 | 7054 | goto out_nfserr; |
---|
6316 | 7055 | } |
---|
6317 | 7056 | nfs4_inc_and_copy_stateid(&locku->lu_stateid, &stp->st_stid); |
---|
6318 | | -fput: |
---|
6319 | | - fput(filp); |
---|
| 7057 | +put_file: |
---|
| 7058 | + nfsd_file_put(nf); |
---|
6320 | 7059 | put_stateid: |
---|
6321 | 7060 | mutex_unlock(&stp->st_mutex); |
---|
6322 | 7061 | nfs4_put_stid(&stp->st_stid); |
---|
.. | .. |
---|
6328 | 7067 | |
---|
6329 | 7068 | out_nfserr: |
---|
6330 | 7069 | status = nfserrno(err); |
---|
6331 | | - goto fput; |
---|
| 7070 | + goto put_file; |
---|
6332 | 7071 | } |
---|
6333 | 7072 | |
---|
6334 | 7073 | /* |
---|
.. | .. |
---|
6341 | 7080 | { |
---|
6342 | 7081 | struct file_lock *fl; |
---|
6343 | 7082 | int status = false; |
---|
6344 | | - struct file *filp = find_any_file(fp); |
---|
| 7083 | + struct nfsd_file *nf = find_any_file(fp); |
---|
6345 | 7084 | struct inode *inode; |
---|
6346 | 7085 | struct file_lock_context *flctx; |
---|
6347 | 7086 | |
---|
6348 | | - if (!filp) { |
---|
| 7087 | + if (!nf) { |
---|
6349 | 7088 | /* Any valid lock stateid should have some sort of access */ |
---|
6350 | 7089 | WARN_ON_ONCE(1); |
---|
6351 | 7090 | return status; |
---|
6352 | 7091 | } |
---|
6353 | 7092 | |
---|
6354 | | - inode = locks_inode(filp); |
---|
| 7093 | + inode = locks_inode(nf->nf_file); |
---|
6355 | 7094 | flctx = inode->i_flctx; |
---|
6356 | 7095 | |
---|
6357 | 7096 | if (flctx && !list_empty_careful(&flctx->flc_posix)) { |
---|
.. | .. |
---|
6364 | 7103 | } |
---|
6365 | 7104 | spin_unlock(&flctx->flc_lock); |
---|
6366 | 7105 | } |
---|
6367 | | - fput(filp); |
---|
| 7106 | + nfsd_file_put(nf); |
---|
6368 | 7107 | return status; |
---|
6369 | 7108 | } |
---|
6370 | 7109 | |
---|
.. | .. |
---|
6388 | 7127 | dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", |
---|
6389 | 7128 | clid->cl_boot, clid->cl_id); |
---|
6390 | 7129 | |
---|
6391 | | - status = lookup_clientid(clid, cstate, nn); |
---|
| 7130 | + status = lookup_clientid(clid, cstate, nn, false); |
---|
6392 | 7131 | if (status) |
---|
6393 | 7132 | return status; |
---|
6394 | 7133 | |
---|
.. | .. |
---|
6401 | 7140 | if (sop->so_is_open_owner || !same_owner_str(sop, owner)) |
---|
6402 | 7141 | continue; |
---|
6403 | 7142 | |
---|
6404 | | - /* see if there are still any locks associated with it */ |
---|
6405 | | - lo = lockowner(sop); |
---|
6406 | | - list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) { |
---|
6407 | | - if (check_for_locks(stp->st_stid.sc_file, lo)) { |
---|
6408 | | - status = nfserr_locks_held; |
---|
6409 | | - spin_unlock(&clp->cl_lock); |
---|
6410 | | - return status; |
---|
6411 | | - } |
---|
| 7143 | + if (atomic_read(&sop->so_count) != 1) { |
---|
| 7144 | + spin_unlock(&clp->cl_lock); |
---|
| 7145 | + return nfserr_locks_held; |
---|
6412 | 7146 | } |
---|
6413 | 7147 | |
---|
| 7148 | + lo = lockowner(sop); |
---|
6414 | 7149 | nfs4_get_stateowner(sop); |
---|
6415 | 7150 | break; |
---|
6416 | 7151 | } |
---|
.. | .. |
---|
6442 | 7177 | } |
---|
6443 | 7178 | |
---|
6444 | 7179 | bool |
---|
6445 | | -nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn) |
---|
| 7180 | +nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn) |
---|
6446 | 7181 | { |
---|
6447 | 7182 | struct nfs4_client_reclaim *crp; |
---|
6448 | 7183 | |
---|
.. | .. |
---|
6452 | 7187 | |
---|
6453 | 7188 | /* |
---|
6454 | 7189 | * failure => all reset bets are off, nfserr_no_grace... |
---|
| 7190 | + * |
---|
| 7191 | + * The caller is responsible for freeing name.data if NULL is returned (it |
---|
| 7192 | + * will be freed in nfs4_remove_reclaim_record in the normal case). |
---|
6455 | 7193 | */ |
---|
6456 | 7194 | struct nfs4_client_reclaim * |
---|
6457 | | -nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn) |
---|
| 7195 | +nfs4_client_to_reclaim(struct xdr_netobj name, struct xdr_netobj princhash, |
---|
| 7196 | + struct nfsd_net *nn) |
---|
6458 | 7197 | { |
---|
6459 | 7198 | unsigned int strhashval; |
---|
6460 | 7199 | struct nfs4_client_reclaim *crp; |
---|
6461 | 7200 | |
---|
6462 | | - dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name); |
---|
6463 | 7201 | crp = alloc_reclaim(); |
---|
6464 | 7202 | if (crp) { |
---|
6465 | 7203 | strhashval = clientstr_hashval(name); |
---|
6466 | 7204 | INIT_LIST_HEAD(&crp->cr_strhash); |
---|
6467 | 7205 | list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]); |
---|
6468 | | - memcpy(crp->cr_recdir, name, HEXDIR_LEN); |
---|
| 7206 | + crp->cr_name.data = name.data; |
---|
| 7207 | + crp->cr_name.len = name.len; |
---|
| 7208 | + crp->cr_princhash.data = princhash.data; |
---|
| 7209 | + crp->cr_princhash.len = princhash.len; |
---|
6469 | 7210 | crp->cr_clp = NULL; |
---|
6470 | 7211 | nn->reclaim_str_hashtbl_size++; |
---|
6471 | 7212 | } |
---|
.. | .. |
---|
6476 | 7217 | nfs4_remove_reclaim_record(struct nfs4_client_reclaim *crp, struct nfsd_net *nn) |
---|
6477 | 7218 | { |
---|
6478 | 7219 | list_del(&crp->cr_strhash); |
---|
| 7220 | + kfree(crp->cr_name.data); |
---|
| 7221 | + kfree(crp->cr_princhash.data); |
---|
6479 | 7222 | kfree(crp); |
---|
6480 | 7223 | nn->reclaim_str_hashtbl_size--; |
---|
6481 | 7224 | } |
---|
.. | .. |
---|
6499 | 7242 | /* |
---|
6500 | 7243 | * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ |
---|
6501 | 7244 | struct nfs4_client_reclaim * |
---|
6502 | | -nfsd4_find_reclaim_client(const char *recdir, struct nfsd_net *nn) |
---|
| 7245 | +nfsd4_find_reclaim_client(struct xdr_netobj name, struct nfsd_net *nn) |
---|
6503 | 7246 | { |
---|
6504 | 7247 | unsigned int strhashval; |
---|
6505 | 7248 | struct nfs4_client_reclaim *crp = NULL; |
---|
6506 | 7249 | |
---|
6507 | | - dprintk("NFSD: nfs4_find_reclaim_client for recdir %s\n", recdir); |
---|
6508 | | - |
---|
6509 | | - strhashval = clientstr_hashval(recdir); |
---|
| 7250 | + strhashval = clientstr_hashval(name); |
---|
6510 | 7251 | list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) { |
---|
6511 | | - if (same_name(crp->cr_recdir, recdir)) { |
---|
| 7252 | + if (compare_blob(&crp->cr_name, &name) == 0) { |
---|
6512 | 7253 | return crp; |
---|
6513 | 7254 | } |
---|
6514 | 7255 | } |
---|
.. | .. |
---|
6526 | 7267 | __be32 status; |
---|
6527 | 7268 | |
---|
6528 | 7269 | /* find clientid in conf_id_hashtbl */ |
---|
6529 | | - status = lookup_clientid(clid, cstate, nn); |
---|
| 7270 | + status = lookup_clientid(clid, cstate, nn, false); |
---|
6530 | 7271 | if (status) |
---|
6531 | 7272 | return nfserr_reclaim_bad; |
---|
6532 | 7273 | |
---|
.. | .. |
---|
6538 | 7279 | |
---|
6539 | 7280 | return nfs_ok; |
---|
6540 | 7281 | } |
---|
6541 | | - |
---|
6542 | | -#ifdef CONFIG_NFSD_FAULT_INJECTION |
---|
6543 | | -static inline void |
---|
6544 | | -put_client(struct nfs4_client *clp) |
---|
6545 | | -{ |
---|
6546 | | - atomic_dec(&clp->cl_refcount); |
---|
6547 | | -} |
---|
6548 | | - |
---|
6549 | | -static struct nfs4_client * |
---|
6550 | | -nfsd_find_client(struct sockaddr_storage *addr, size_t addr_size) |
---|
6551 | | -{ |
---|
6552 | | - struct nfs4_client *clp; |
---|
6553 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6554 | | - nfsd_net_id); |
---|
6555 | | - |
---|
6556 | | - if (!nfsd_netns_ready(nn)) |
---|
6557 | | - return NULL; |
---|
6558 | | - |
---|
6559 | | - list_for_each_entry(clp, &nn->client_lru, cl_lru) { |
---|
6560 | | - if (memcmp(&clp->cl_addr, addr, addr_size) == 0) |
---|
6561 | | - return clp; |
---|
6562 | | - } |
---|
6563 | | - return NULL; |
---|
6564 | | -} |
---|
6565 | | - |
---|
6566 | | -u64 |
---|
6567 | | -nfsd_inject_print_clients(void) |
---|
6568 | | -{ |
---|
6569 | | - struct nfs4_client *clp; |
---|
6570 | | - u64 count = 0; |
---|
6571 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6572 | | - nfsd_net_id); |
---|
6573 | | - char buf[INET6_ADDRSTRLEN]; |
---|
6574 | | - |
---|
6575 | | - if (!nfsd_netns_ready(nn)) |
---|
6576 | | - return 0; |
---|
6577 | | - |
---|
6578 | | - spin_lock(&nn->client_lock); |
---|
6579 | | - list_for_each_entry(clp, &nn->client_lru, cl_lru) { |
---|
6580 | | - rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf)); |
---|
6581 | | - pr_info("NFS Client: %s\n", buf); |
---|
6582 | | - ++count; |
---|
6583 | | - } |
---|
6584 | | - spin_unlock(&nn->client_lock); |
---|
6585 | | - |
---|
6586 | | - return count; |
---|
6587 | | -} |
---|
6588 | | - |
---|
6589 | | -u64 |
---|
6590 | | -nfsd_inject_forget_client(struct sockaddr_storage *addr, size_t addr_size) |
---|
6591 | | -{ |
---|
6592 | | - u64 count = 0; |
---|
6593 | | - struct nfs4_client *clp; |
---|
6594 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6595 | | - nfsd_net_id); |
---|
6596 | | - |
---|
6597 | | - if (!nfsd_netns_ready(nn)) |
---|
6598 | | - return count; |
---|
6599 | | - |
---|
6600 | | - spin_lock(&nn->client_lock); |
---|
6601 | | - clp = nfsd_find_client(addr, addr_size); |
---|
6602 | | - if (clp) { |
---|
6603 | | - if (mark_client_expired_locked(clp) == nfs_ok) |
---|
6604 | | - ++count; |
---|
6605 | | - else |
---|
6606 | | - clp = NULL; |
---|
6607 | | - } |
---|
6608 | | - spin_unlock(&nn->client_lock); |
---|
6609 | | - |
---|
6610 | | - if (clp) |
---|
6611 | | - expire_client(clp); |
---|
6612 | | - |
---|
6613 | | - return count; |
---|
6614 | | -} |
---|
6615 | | - |
---|
6616 | | -u64 |
---|
6617 | | -nfsd_inject_forget_clients(u64 max) |
---|
6618 | | -{ |
---|
6619 | | - u64 count = 0; |
---|
6620 | | - struct nfs4_client *clp, *next; |
---|
6621 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6622 | | - nfsd_net_id); |
---|
6623 | | - LIST_HEAD(reaplist); |
---|
6624 | | - |
---|
6625 | | - if (!nfsd_netns_ready(nn)) |
---|
6626 | | - return count; |
---|
6627 | | - |
---|
6628 | | - spin_lock(&nn->client_lock); |
---|
6629 | | - list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) { |
---|
6630 | | - if (mark_client_expired_locked(clp) == nfs_ok) { |
---|
6631 | | - list_add(&clp->cl_lru, &reaplist); |
---|
6632 | | - if (max != 0 && ++count >= max) |
---|
6633 | | - break; |
---|
6634 | | - } |
---|
6635 | | - } |
---|
6636 | | - spin_unlock(&nn->client_lock); |
---|
6637 | | - |
---|
6638 | | - list_for_each_entry_safe(clp, next, &reaplist, cl_lru) |
---|
6639 | | - expire_client(clp); |
---|
6640 | | - |
---|
6641 | | - return count; |
---|
6642 | | -} |
---|
6643 | | - |
---|
6644 | | -static void nfsd_print_count(struct nfs4_client *clp, unsigned int count, |
---|
6645 | | - const char *type) |
---|
6646 | | -{ |
---|
6647 | | - char buf[INET6_ADDRSTRLEN]; |
---|
6648 | | - rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf)); |
---|
6649 | | - printk(KERN_INFO "NFS Client: %s has %u %s\n", buf, count, type); |
---|
6650 | | -} |
---|
6651 | | - |
---|
6652 | | -static void |
---|
6653 | | -nfsd_inject_add_lock_to_list(struct nfs4_ol_stateid *lst, |
---|
6654 | | - struct list_head *collect) |
---|
6655 | | -{ |
---|
6656 | | - struct nfs4_client *clp = lst->st_stid.sc_client; |
---|
6657 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6658 | | - nfsd_net_id); |
---|
6659 | | - |
---|
6660 | | - if (!collect) |
---|
6661 | | - return; |
---|
6662 | | - |
---|
6663 | | - lockdep_assert_held(&nn->client_lock); |
---|
6664 | | - atomic_inc(&clp->cl_refcount); |
---|
6665 | | - list_add(&lst->st_locks, collect); |
---|
6666 | | -} |
---|
6667 | | - |
---|
6668 | | -static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max, |
---|
6669 | | - struct list_head *collect, |
---|
6670 | | - bool (*func)(struct nfs4_ol_stateid *)) |
---|
6671 | | -{ |
---|
6672 | | - struct nfs4_openowner *oop; |
---|
6673 | | - struct nfs4_ol_stateid *stp, *st_next; |
---|
6674 | | - struct nfs4_ol_stateid *lst, *lst_next; |
---|
6675 | | - u64 count = 0; |
---|
6676 | | - |
---|
6677 | | - spin_lock(&clp->cl_lock); |
---|
6678 | | - list_for_each_entry(oop, &clp->cl_openowners, oo_perclient) { |
---|
6679 | | - list_for_each_entry_safe(stp, st_next, |
---|
6680 | | - &oop->oo_owner.so_stateids, st_perstateowner) { |
---|
6681 | | - list_for_each_entry_safe(lst, lst_next, |
---|
6682 | | - &stp->st_locks, st_locks) { |
---|
6683 | | - if (func) { |
---|
6684 | | - if (func(lst)) |
---|
6685 | | - nfsd_inject_add_lock_to_list(lst, |
---|
6686 | | - collect); |
---|
6687 | | - } |
---|
6688 | | - ++count; |
---|
6689 | | - /* |
---|
6690 | | - * Despite the fact that these functions deal |
---|
6691 | | - * with 64-bit integers for "count", we must |
---|
6692 | | - * ensure that it doesn't blow up the |
---|
6693 | | - * clp->cl_refcount. Throw a warning if we |
---|
6694 | | - * start to approach INT_MAX here. |
---|
6695 | | - */ |
---|
6696 | | - WARN_ON_ONCE(count == (INT_MAX / 2)); |
---|
6697 | | - if (count == max) |
---|
6698 | | - goto out; |
---|
6699 | | - } |
---|
6700 | | - } |
---|
6701 | | - } |
---|
6702 | | -out: |
---|
6703 | | - spin_unlock(&clp->cl_lock); |
---|
6704 | | - |
---|
6705 | | - return count; |
---|
6706 | | -} |
---|
6707 | | - |
---|
6708 | | -static u64 |
---|
6709 | | -nfsd_collect_client_locks(struct nfs4_client *clp, struct list_head *collect, |
---|
6710 | | - u64 max) |
---|
6711 | | -{ |
---|
6712 | | - return nfsd_foreach_client_lock(clp, max, collect, unhash_lock_stateid); |
---|
6713 | | -} |
---|
6714 | | - |
---|
6715 | | -static u64 |
---|
6716 | | -nfsd_print_client_locks(struct nfs4_client *clp) |
---|
6717 | | -{ |
---|
6718 | | - u64 count = nfsd_foreach_client_lock(clp, 0, NULL, NULL); |
---|
6719 | | - nfsd_print_count(clp, count, "locked files"); |
---|
6720 | | - return count; |
---|
6721 | | -} |
---|
6722 | | - |
---|
6723 | | -u64 |
---|
6724 | | -nfsd_inject_print_locks(void) |
---|
6725 | | -{ |
---|
6726 | | - struct nfs4_client *clp; |
---|
6727 | | - u64 count = 0; |
---|
6728 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6729 | | - nfsd_net_id); |
---|
6730 | | - |
---|
6731 | | - if (!nfsd_netns_ready(nn)) |
---|
6732 | | - return 0; |
---|
6733 | | - |
---|
6734 | | - spin_lock(&nn->client_lock); |
---|
6735 | | - list_for_each_entry(clp, &nn->client_lru, cl_lru) |
---|
6736 | | - count += nfsd_print_client_locks(clp); |
---|
6737 | | - spin_unlock(&nn->client_lock); |
---|
6738 | | - |
---|
6739 | | - return count; |
---|
6740 | | -} |
---|
6741 | | - |
---|
6742 | | -static void |
---|
6743 | | -nfsd_reap_locks(struct list_head *reaplist) |
---|
6744 | | -{ |
---|
6745 | | - struct nfs4_client *clp; |
---|
6746 | | - struct nfs4_ol_stateid *stp, *next; |
---|
6747 | | - |
---|
6748 | | - list_for_each_entry_safe(stp, next, reaplist, st_locks) { |
---|
6749 | | - list_del_init(&stp->st_locks); |
---|
6750 | | - clp = stp->st_stid.sc_client; |
---|
6751 | | - nfs4_put_stid(&stp->st_stid); |
---|
6752 | | - put_client(clp); |
---|
6753 | | - } |
---|
6754 | | -} |
---|
6755 | | - |
---|
6756 | | -u64 |
---|
6757 | | -nfsd_inject_forget_client_locks(struct sockaddr_storage *addr, size_t addr_size) |
---|
6758 | | -{ |
---|
6759 | | - unsigned int count = 0; |
---|
6760 | | - struct nfs4_client *clp; |
---|
6761 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6762 | | - nfsd_net_id); |
---|
6763 | | - LIST_HEAD(reaplist); |
---|
6764 | | - |
---|
6765 | | - if (!nfsd_netns_ready(nn)) |
---|
6766 | | - return count; |
---|
6767 | | - |
---|
6768 | | - spin_lock(&nn->client_lock); |
---|
6769 | | - clp = nfsd_find_client(addr, addr_size); |
---|
6770 | | - if (clp) |
---|
6771 | | - count = nfsd_collect_client_locks(clp, &reaplist, 0); |
---|
6772 | | - spin_unlock(&nn->client_lock); |
---|
6773 | | - nfsd_reap_locks(&reaplist); |
---|
6774 | | - return count; |
---|
6775 | | -} |
---|
6776 | | - |
---|
6777 | | -u64 |
---|
6778 | | -nfsd_inject_forget_locks(u64 max) |
---|
6779 | | -{ |
---|
6780 | | - u64 count = 0; |
---|
6781 | | - struct nfs4_client *clp; |
---|
6782 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6783 | | - nfsd_net_id); |
---|
6784 | | - LIST_HEAD(reaplist); |
---|
6785 | | - |
---|
6786 | | - if (!nfsd_netns_ready(nn)) |
---|
6787 | | - return count; |
---|
6788 | | - |
---|
6789 | | - spin_lock(&nn->client_lock); |
---|
6790 | | - list_for_each_entry(clp, &nn->client_lru, cl_lru) { |
---|
6791 | | - count += nfsd_collect_client_locks(clp, &reaplist, max - count); |
---|
6792 | | - if (max != 0 && count >= max) |
---|
6793 | | - break; |
---|
6794 | | - } |
---|
6795 | | - spin_unlock(&nn->client_lock); |
---|
6796 | | - nfsd_reap_locks(&reaplist); |
---|
6797 | | - return count; |
---|
6798 | | -} |
---|
6799 | | - |
---|
6800 | | -static u64 |
---|
6801 | | -nfsd_foreach_client_openowner(struct nfs4_client *clp, u64 max, |
---|
6802 | | - struct list_head *collect, |
---|
6803 | | - void (*func)(struct nfs4_openowner *)) |
---|
6804 | | -{ |
---|
6805 | | - struct nfs4_openowner *oop, *next; |
---|
6806 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6807 | | - nfsd_net_id); |
---|
6808 | | - u64 count = 0; |
---|
6809 | | - |
---|
6810 | | - lockdep_assert_held(&nn->client_lock); |
---|
6811 | | - |
---|
6812 | | - spin_lock(&clp->cl_lock); |
---|
6813 | | - list_for_each_entry_safe(oop, next, &clp->cl_openowners, oo_perclient) { |
---|
6814 | | - if (func) { |
---|
6815 | | - func(oop); |
---|
6816 | | - if (collect) { |
---|
6817 | | - atomic_inc(&clp->cl_refcount); |
---|
6818 | | - list_add(&oop->oo_perclient, collect); |
---|
6819 | | - } |
---|
6820 | | - } |
---|
6821 | | - ++count; |
---|
6822 | | - /* |
---|
6823 | | - * Despite the fact that these functions deal with |
---|
6824 | | - * 64-bit integers for "count", we must ensure that |
---|
6825 | | - * it doesn't blow up the clp->cl_refcount. Throw a |
---|
6826 | | - * warning if we start to approach INT_MAX here. |
---|
6827 | | - */ |
---|
6828 | | - WARN_ON_ONCE(count == (INT_MAX / 2)); |
---|
6829 | | - if (count == max) |
---|
6830 | | - break; |
---|
6831 | | - } |
---|
6832 | | - spin_unlock(&clp->cl_lock); |
---|
6833 | | - |
---|
6834 | | - return count; |
---|
6835 | | -} |
---|
6836 | | - |
---|
6837 | | -static u64 |
---|
6838 | | -nfsd_print_client_openowners(struct nfs4_client *clp) |
---|
6839 | | -{ |
---|
6840 | | - u64 count = nfsd_foreach_client_openowner(clp, 0, NULL, NULL); |
---|
6841 | | - |
---|
6842 | | - nfsd_print_count(clp, count, "openowners"); |
---|
6843 | | - return count; |
---|
6844 | | -} |
---|
6845 | | - |
---|
6846 | | -static u64 |
---|
6847 | | -nfsd_collect_client_openowners(struct nfs4_client *clp, |
---|
6848 | | - struct list_head *collect, u64 max) |
---|
6849 | | -{ |
---|
6850 | | - return nfsd_foreach_client_openowner(clp, max, collect, |
---|
6851 | | - unhash_openowner_locked); |
---|
6852 | | -} |
---|
6853 | | - |
---|
6854 | | -u64 |
---|
6855 | | -nfsd_inject_print_openowners(void) |
---|
6856 | | -{ |
---|
6857 | | - struct nfs4_client *clp; |
---|
6858 | | - u64 count = 0; |
---|
6859 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6860 | | - nfsd_net_id); |
---|
6861 | | - |
---|
6862 | | - if (!nfsd_netns_ready(nn)) |
---|
6863 | | - return 0; |
---|
6864 | | - |
---|
6865 | | - spin_lock(&nn->client_lock); |
---|
6866 | | - list_for_each_entry(clp, &nn->client_lru, cl_lru) |
---|
6867 | | - count += nfsd_print_client_openowners(clp); |
---|
6868 | | - spin_unlock(&nn->client_lock); |
---|
6869 | | - |
---|
6870 | | - return count; |
---|
6871 | | -} |
---|
6872 | | - |
---|
6873 | | -static void |
---|
6874 | | -nfsd_reap_openowners(struct list_head *reaplist) |
---|
6875 | | -{ |
---|
6876 | | - struct nfs4_client *clp; |
---|
6877 | | - struct nfs4_openowner *oop, *next; |
---|
6878 | | - |
---|
6879 | | - list_for_each_entry_safe(oop, next, reaplist, oo_perclient) { |
---|
6880 | | - list_del_init(&oop->oo_perclient); |
---|
6881 | | - clp = oop->oo_owner.so_client; |
---|
6882 | | - release_openowner(oop); |
---|
6883 | | - put_client(clp); |
---|
6884 | | - } |
---|
6885 | | -} |
---|
6886 | | - |
---|
6887 | | -u64 |
---|
6888 | | -nfsd_inject_forget_client_openowners(struct sockaddr_storage *addr, |
---|
6889 | | - size_t addr_size) |
---|
6890 | | -{ |
---|
6891 | | - unsigned int count = 0; |
---|
6892 | | - struct nfs4_client *clp; |
---|
6893 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6894 | | - nfsd_net_id); |
---|
6895 | | - LIST_HEAD(reaplist); |
---|
6896 | | - |
---|
6897 | | - if (!nfsd_netns_ready(nn)) |
---|
6898 | | - return count; |
---|
6899 | | - |
---|
6900 | | - spin_lock(&nn->client_lock); |
---|
6901 | | - clp = nfsd_find_client(addr, addr_size); |
---|
6902 | | - if (clp) |
---|
6903 | | - count = nfsd_collect_client_openowners(clp, &reaplist, 0); |
---|
6904 | | - spin_unlock(&nn->client_lock); |
---|
6905 | | - nfsd_reap_openowners(&reaplist); |
---|
6906 | | - return count; |
---|
6907 | | -} |
---|
6908 | | - |
---|
6909 | | -u64 |
---|
6910 | | -nfsd_inject_forget_openowners(u64 max) |
---|
6911 | | -{ |
---|
6912 | | - u64 count = 0; |
---|
6913 | | - struct nfs4_client *clp; |
---|
6914 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6915 | | - nfsd_net_id); |
---|
6916 | | - LIST_HEAD(reaplist); |
---|
6917 | | - |
---|
6918 | | - if (!nfsd_netns_ready(nn)) |
---|
6919 | | - return count; |
---|
6920 | | - |
---|
6921 | | - spin_lock(&nn->client_lock); |
---|
6922 | | - list_for_each_entry(clp, &nn->client_lru, cl_lru) { |
---|
6923 | | - count += nfsd_collect_client_openowners(clp, &reaplist, |
---|
6924 | | - max - count); |
---|
6925 | | - if (max != 0 && count >= max) |
---|
6926 | | - break; |
---|
6927 | | - } |
---|
6928 | | - spin_unlock(&nn->client_lock); |
---|
6929 | | - nfsd_reap_openowners(&reaplist); |
---|
6930 | | - return count; |
---|
6931 | | -} |
---|
6932 | | - |
---|
6933 | | -static u64 nfsd_find_all_delegations(struct nfs4_client *clp, u64 max, |
---|
6934 | | - struct list_head *victims) |
---|
6935 | | -{ |
---|
6936 | | - struct nfs4_delegation *dp, *next; |
---|
6937 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6938 | | - nfsd_net_id); |
---|
6939 | | - u64 count = 0; |
---|
6940 | | - |
---|
6941 | | - lockdep_assert_held(&nn->client_lock); |
---|
6942 | | - |
---|
6943 | | - spin_lock(&state_lock); |
---|
6944 | | - list_for_each_entry_safe(dp, next, &clp->cl_delegations, dl_perclnt) { |
---|
6945 | | - if (victims) { |
---|
6946 | | - /* |
---|
6947 | | - * It's not safe to mess with delegations that have a |
---|
6948 | | - * non-zero dl_time. They might have already been broken |
---|
6949 | | - * and could be processed by the laundromat outside of |
---|
6950 | | - * the state_lock. Just leave them be. |
---|
6951 | | - */ |
---|
6952 | | - if (dp->dl_time != 0) |
---|
6953 | | - continue; |
---|
6954 | | - |
---|
6955 | | - atomic_inc(&clp->cl_refcount); |
---|
6956 | | - WARN_ON(!unhash_delegation_locked(dp)); |
---|
6957 | | - list_add(&dp->dl_recall_lru, victims); |
---|
6958 | | - } |
---|
6959 | | - ++count; |
---|
6960 | | - /* |
---|
6961 | | - * Despite the fact that these functions deal with |
---|
6962 | | - * 64-bit integers for "count", we must ensure that |
---|
6963 | | - * it doesn't blow up the clp->cl_refcount. Throw a |
---|
6964 | | - * warning if we start to approach INT_MAX here. |
---|
6965 | | - */ |
---|
6966 | | - WARN_ON_ONCE(count == (INT_MAX / 2)); |
---|
6967 | | - if (count == max) |
---|
6968 | | - break; |
---|
6969 | | - } |
---|
6970 | | - spin_unlock(&state_lock); |
---|
6971 | | - return count; |
---|
6972 | | -} |
---|
6973 | | - |
---|
6974 | | -static u64 |
---|
6975 | | -nfsd_print_client_delegations(struct nfs4_client *clp) |
---|
6976 | | -{ |
---|
6977 | | - u64 count = nfsd_find_all_delegations(clp, 0, NULL); |
---|
6978 | | - |
---|
6979 | | - nfsd_print_count(clp, count, "delegations"); |
---|
6980 | | - return count; |
---|
6981 | | -} |
---|
6982 | | - |
---|
6983 | | -u64 |
---|
6984 | | -nfsd_inject_print_delegations(void) |
---|
6985 | | -{ |
---|
6986 | | - struct nfs4_client *clp; |
---|
6987 | | - u64 count = 0; |
---|
6988 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
6989 | | - nfsd_net_id); |
---|
6990 | | - |
---|
6991 | | - if (!nfsd_netns_ready(nn)) |
---|
6992 | | - return 0; |
---|
6993 | | - |
---|
6994 | | - spin_lock(&nn->client_lock); |
---|
6995 | | - list_for_each_entry(clp, &nn->client_lru, cl_lru) |
---|
6996 | | - count += nfsd_print_client_delegations(clp); |
---|
6997 | | - spin_unlock(&nn->client_lock); |
---|
6998 | | - |
---|
6999 | | - return count; |
---|
7000 | | -} |
---|
7001 | | - |
---|
7002 | | -static void |
---|
7003 | | -nfsd_forget_delegations(struct list_head *reaplist) |
---|
7004 | | -{ |
---|
7005 | | - struct nfs4_client *clp; |
---|
7006 | | - struct nfs4_delegation *dp, *next; |
---|
7007 | | - |
---|
7008 | | - list_for_each_entry_safe(dp, next, reaplist, dl_recall_lru) { |
---|
7009 | | - list_del_init(&dp->dl_recall_lru); |
---|
7010 | | - clp = dp->dl_stid.sc_client; |
---|
7011 | | - revoke_delegation(dp); |
---|
7012 | | - put_client(clp); |
---|
7013 | | - } |
---|
7014 | | -} |
---|
7015 | | - |
---|
7016 | | -u64 |
---|
7017 | | -nfsd_inject_forget_client_delegations(struct sockaddr_storage *addr, |
---|
7018 | | - size_t addr_size) |
---|
7019 | | -{ |
---|
7020 | | - u64 count = 0; |
---|
7021 | | - struct nfs4_client *clp; |
---|
7022 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
7023 | | - nfsd_net_id); |
---|
7024 | | - LIST_HEAD(reaplist); |
---|
7025 | | - |
---|
7026 | | - if (!nfsd_netns_ready(nn)) |
---|
7027 | | - return count; |
---|
7028 | | - |
---|
7029 | | - spin_lock(&nn->client_lock); |
---|
7030 | | - clp = nfsd_find_client(addr, addr_size); |
---|
7031 | | - if (clp) |
---|
7032 | | - count = nfsd_find_all_delegations(clp, 0, &reaplist); |
---|
7033 | | - spin_unlock(&nn->client_lock); |
---|
7034 | | - |
---|
7035 | | - nfsd_forget_delegations(&reaplist); |
---|
7036 | | - return count; |
---|
7037 | | -} |
---|
7038 | | - |
---|
7039 | | -u64 |
---|
7040 | | -nfsd_inject_forget_delegations(u64 max) |
---|
7041 | | -{ |
---|
7042 | | - u64 count = 0; |
---|
7043 | | - struct nfs4_client *clp; |
---|
7044 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
7045 | | - nfsd_net_id); |
---|
7046 | | - LIST_HEAD(reaplist); |
---|
7047 | | - |
---|
7048 | | - if (!nfsd_netns_ready(nn)) |
---|
7049 | | - return count; |
---|
7050 | | - |
---|
7051 | | - spin_lock(&nn->client_lock); |
---|
7052 | | - list_for_each_entry(clp, &nn->client_lru, cl_lru) { |
---|
7053 | | - count += nfsd_find_all_delegations(clp, max - count, &reaplist); |
---|
7054 | | - if (max != 0 && count >= max) |
---|
7055 | | - break; |
---|
7056 | | - } |
---|
7057 | | - spin_unlock(&nn->client_lock); |
---|
7058 | | - nfsd_forget_delegations(&reaplist); |
---|
7059 | | - return count; |
---|
7060 | | -} |
---|
7061 | | - |
---|
7062 | | -static void |
---|
7063 | | -nfsd_recall_delegations(struct list_head *reaplist) |
---|
7064 | | -{ |
---|
7065 | | - struct nfs4_client *clp; |
---|
7066 | | - struct nfs4_delegation *dp, *next; |
---|
7067 | | - |
---|
7068 | | - list_for_each_entry_safe(dp, next, reaplist, dl_recall_lru) { |
---|
7069 | | - list_del_init(&dp->dl_recall_lru); |
---|
7070 | | - clp = dp->dl_stid.sc_client; |
---|
7071 | | - /* |
---|
7072 | | - * We skipped all entries that had a zero dl_time before, |
---|
7073 | | - * so we can now reset the dl_time back to 0. If a delegation |
---|
7074 | | - * break comes in now, then it won't make any difference since |
---|
7075 | | - * we're recalling it either way. |
---|
7076 | | - */ |
---|
7077 | | - spin_lock(&state_lock); |
---|
7078 | | - dp->dl_time = 0; |
---|
7079 | | - spin_unlock(&state_lock); |
---|
7080 | | - nfsd_break_one_deleg(dp); |
---|
7081 | | - put_client(clp); |
---|
7082 | | - } |
---|
7083 | | -} |
---|
7084 | | - |
---|
7085 | | -u64 |
---|
7086 | | -nfsd_inject_recall_client_delegations(struct sockaddr_storage *addr, |
---|
7087 | | - size_t addr_size) |
---|
7088 | | -{ |
---|
7089 | | - u64 count = 0; |
---|
7090 | | - struct nfs4_client *clp; |
---|
7091 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
7092 | | - nfsd_net_id); |
---|
7093 | | - LIST_HEAD(reaplist); |
---|
7094 | | - |
---|
7095 | | - if (!nfsd_netns_ready(nn)) |
---|
7096 | | - return count; |
---|
7097 | | - |
---|
7098 | | - spin_lock(&nn->client_lock); |
---|
7099 | | - clp = nfsd_find_client(addr, addr_size); |
---|
7100 | | - if (clp) |
---|
7101 | | - count = nfsd_find_all_delegations(clp, 0, &reaplist); |
---|
7102 | | - spin_unlock(&nn->client_lock); |
---|
7103 | | - |
---|
7104 | | - nfsd_recall_delegations(&reaplist); |
---|
7105 | | - return count; |
---|
7106 | | -} |
---|
7107 | | - |
---|
7108 | | -u64 |
---|
7109 | | -nfsd_inject_recall_delegations(u64 max) |
---|
7110 | | -{ |
---|
7111 | | - u64 count = 0; |
---|
7112 | | - struct nfs4_client *clp, *next; |
---|
7113 | | - struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, |
---|
7114 | | - nfsd_net_id); |
---|
7115 | | - LIST_HEAD(reaplist); |
---|
7116 | | - |
---|
7117 | | - if (!nfsd_netns_ready(nn)) |
---|
7118 | | - return count; |
---|
7119 | | - |
---|
7120 | | - spin_lock(&nn->client_lock); |
---|
7121 | | - list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) { |
---|
7122 | | - count += nfsd_find_all_delegations(clp, max - count, &reaplist); |
---|
7123 | | - if (max != 0 && ++count >= max) |
---|
7124 | | - break; |
---|
7125 | | - } |
---|
7126 | | - spin_unlock(&nn->client_lock); |
---|
7127 | | - nfsd_recall_delegations(&reaplist); |
---|
7128 | | - return count; |
---|
7129 | | -} |
---|
7130 | | -#endif /* CONFIG_NFSD_FAULT_INJECTION */ |
---|
7131 | 7282 | |
---|
7132 | 7283 | /* |
---|
7133 | 7284 | * Since the lifetime of a delegation isn't limited to that of an open, a |
---|
.. | .. |
---|
7179 | 7330 | INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]); |
---|
7180 | 7331 | nn->conf_name_tree = RB_ROOT; |
---|
7181 | 7332 | nn->unconf_name_tree = RB_ROOT; |
---|
7182 | | - nn->boot_time = get_seconds(); |
---|
| 7333 | + nn->boot_time = ktime_get_real_seconds(); |
---|
7183 | 7334 | nn->grace_ended = false; |
---|
7184 | 7335 | nn->nfsd4_manager.block_opens = true; |
---|
7185 | 7336 | INIT_LIST_HEAD(&nn->nfsd4_manager.list); |
---|
.. | .. |
---|
7187 | 7338 | INIT_LIST_HEAD(&nn->close_lru); |
---|
7188 | 7339 | INIT_LIST_HEAD(&nn->del_recall_lru); |
---|
7189 | 7340 | spin_lock_init(&nn->client_lock); |
---|
| 7341 | + spin_lock_init(&nn->s2s_cp_lock); |
---|
| 7342 | + idr_init(&nn->s2s_cp_stateids); |
---|
7190 | 7343 | |
---|
7191 | 7344 | spin_lock_init(&nn->blocked_locks_lock); |
---|
7192 | 7345 | INIT_LIST_HEAD(&nn->blocked_locks_lru); |
---|
.. | .. |
---|
7244 | 7397 | return ret; |
---|
7245 | 7398 | locks_start_grace(net, &nn->nfsd4_manager); |
---|
7246 | 7399 | nfsd4_client_tracking_init(net); |
---|
7247 | | - printk(KERN_INFO "NFSD: starting %ld-second grace period (net %x)\n", |
---|
| 7400 | + if (nn->track_reclaim_completes && nn->reclaim_str_hashtbl_size == 0) |
---|
| 7401 | + goto skip_grace; |
---|
| 7402 | + printk(KERN_INFO "NFSD: starting %lld-second grace period (net %x)\n", |
---|
7248 | 7403 | nn->nfsd4_grace, net->ns.inum); |
---|
| 7404 | + trace_nfsd_grace_start(nn); |
---|
7249 | 7405 | queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ); |
---|
| 7406 | + return 0; |
---|
| 7407 | + |
---|
| 7408 | +skip_grace: |
---|
| 7409 | + printk(KERN_INFO "NFSD: no clients to reclaim, skipping NFSv4 grace period (net %x)\n", |
---|
| 7410 | + net->ns.inum); |
---|
| 7411 | + queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_lease * HZ); |
---|
| 7412 | + nfsd4_end_grace(nn); |
---|
7250 | 7413 | return 0; |
---|
7251 | 7414 | } |
---|
7252 | 7415 | |
---|
.. | .. |
---|
7313 | 7476 | static void |
---|
7314 | 7477 | get_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid) |
---|
7315 | 7478 | { |
---|
7316 | | - if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG) && CURRENT_STATEID(stateid)) |
---|
| 7479 | + if (HAS_CSTATE_FLAG(cstate, CURRENT_STATE_ID_FLAG) && |
---|
| 7480 | + CURRENT_STATEID(stateid)) |
---|
7317 | 7481 | memcpy(stateid, &cstate->current_stateid, sizeof(stateid_t)); |
---|
7318 | 7482 | } |
---|
7319 | 7483 | |
---|
.. | .. |
---|
7322 | 7486 | { |
---|
7323 | 7487 | if (cstate->minorversion) { |
---|
7324 | 7488 | memcpy(&cstate->current_stateid, stateid, sizeof(stateid_t)); |
---|
7325 | | - SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG); |
---|
| 7489 | + SET_CSTATE_FLAG(cstate, CURRENT_STATE_ID_FLAG); |
---|
7326 | 7490 | } |
---|
7327 | 7491 | } |
---|
7328 | 7492 | |
---|
7329 | 7493 | void |
---|
7330 | 7494 | clear_current_stateid(struct nfsd4_compound_state *cstate) |
---|
7331 | 7495 | { |
---|
7332 | | - CLEAR_STATE_ID(cstate, CURRENT_STATE_ID_FLAG); |
---|
| 7496 | + CLEAR_CSTATE_FLAG(cstate, CURRENT_STATE_ID_FLAG); |
---|
7333 | 7497 | } |
---|
7334 | 7498 | |
---|
7335 | 7499 | /* |
---|