hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/fs/nfsd/nfs4recover.c
....@@ -59,7 +59,12 @@
5959 void (*remove)(struct nfs4_client *);
6060 int (*check)(struct nfs4_client *);
6161 void (*grace_done)(struct nfsd_net *);
62
+ uint8_t version;
63
+ size_t msglen;
6264 };
65
+
66
+static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops;
67
+static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2;
6368
6469 /* Globals */
6570 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
....@@ -122,17 +127,8 @@
122127 goto out;
123128 }
124129
125
- {
126
- SHASH_DESC_ON_STACK(desc, tfm);
127
-
128
- desc->tfm = tfm;
129
- desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
130
-
131
- status = crypto_shash_digest(desc, clname->data, clname->len,
132
- cksum.data);
133
- shash_desc_zero(desc);
134
- }
135
-
130
+ status = crypto_shash_tfm_digest(tfm, clname->data, clname->len,
131
+ cksum.data);
136132 if (status)
137133 goto out;
138134
....@@ -170,12 +166,34 @@
170166 }
171167
172168 static void
169
+__nfsd4_create_reclaim_record_grace(struct nfs4_client *clp,
170
+ const char *dname, int len, struct nfsd_net *nn)
171
+{
172
+ struct xdr_netobj name;
173
+ struct xdr_netobj princhash = { .len = 0, .data = NULL };
174
+ struct nfs4_client_reclaim *crp;
175
+
176
+ name.data = kmemdup(dname, len, GFP_KERNEL);
177
+ if (!name.data) {
178
+ dprintk("%s: failed to allocate memory for name.data!\n",
179
+ __func__);
180
+ return;
181
+ }
182
+ name.len = len;
183
+ crp = nfs4_client_to_reclaim(name, princhash, nn);
184
+ if (!crp) {
185
+ kfree(name.data);
186
+ return;
187
+ }
188
+ crp->cr_clp = clp;
189
+}
190
+
191
+static void
173192 nfsd4_create_clid_dir(struct nfs4_client *clp)
174193 {
175194 const struct cred *original_cred;
176195 char dname[HEXDIR_LEN];
177196 struct dentry *dir, *dentry;
178
- struct nfs4_client_reclaim *crp;
179197 int status;
180198 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
181199
....@@ -221,11 +239,9 @@
221239 out_unlock:
222240 inode_unlock(d_inode(dir));
223241 if (status == 0) {
224
- if (nn->in_grace) {
225
- crp = nfs4_client_to_reclaim(dname, nn);
226
- if (crp)
227
- crp->cr_clp = clp;
228
- }
242
+ if (nn->in_grace)
243
+ __nfsd4_create_reclaim_record_grace(clp, dname,
244
+ HEXDIR_LEN, nn);
229245 vfs_fsync(nn->rec_file, 0);
230246 } else {
231247 printk(KERN_ERR "NFSD: failed to write recovery record"
....@@ -346,10 +362,29 @@
346362 }
347363
348364 static void
365
+__nfsd4_remove_reclaim_record_grace(const char *dname, int len,
366
+ struct nfsd_net *nn)
367
+{
368
+ struct xdr_netobj name;
369
+ struct nfs4_client_reclaim *crp;
370
+
371
+ name.data = kmemdup(dname, len, GFP_KERNEL);
372
+ if (!name.data) {
373
+ dprintk("%s: failed to allocate memory for name.data!\n",
374
+ __func__);
375
+ return;
376
+ }
377
+ name.len = len;
378
+ crp = nfsd4_find_reclaim_client(name, nn);
379
+ kfree(name.data);
380
+ if (crp)
381
+ nfs4_remove_reclaim_record(crp, nn);
382
+}
383
+
384
+static void
349385 nfsd4_remove_clid_dir(struct nfs4_client *clp)
350386 {
351387 const struct cred *original_cred;
352
- struct nfs4_client_reclaim *crp;
353388 char dname[HEXDIR_LEN];
354389 int status;
355390 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
....@@ -374,12 +409,9 @@
374409 nfs4_reset_creds(original_cred);
375410 if (status == 0) {
376411 vfs_fsync(nn->rec_file, 0);
377
- if (nn->in_grace) {
378
- /* remove reclaim record */
379
- crp = nfsd4_find_reclaim_client(dname, nn);
380
- if (crp)
381
- nfs4_remove_reclaim_record(crp, nn);
382
- }
412
+ if (nn->in_grace)
413
+ __nfsd4_remove_reclaim_record_grace(dname,
414
+ HEXDIR_LEN, nn);
383415 }
384416 out_drop_write:
385417 mnt_drop_write_file(nn->rec_file);
....@@ -393,14 +425,31 @@
393425 purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
394426 {
395427 int status;
428
+ struct xdr_netobj name;
396429
397
- if (nfs4_has_reclaimed_state(child->d_name.name, nn))
430
+ if (child->d_name.len != HEXDIR_LEN - 1) {
431
+ printk("%s: illegal name %pd in recovery directory\n",
432
+ __func__, child);
433
+ /* Keep trying; maybe the others are OK: */
398434 return 0;
435
+ }
436
+ name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
437
+ if (!name.data) {
438
+ dprintk("%s: failed to allocate memory for name.data!\n",
439
+ __func__);
440
+ goto out;
441
+ }
442
+ name.len = HEXDIR_LEN;
443
+ if (nfs4_has_reclaimed_state(name, nn))
444
+ goto out_free;
399445
400446 status = vfs_rmdir(d_inode(parent), child);
401447 if (status)
402448 printk("failed to remove client recovery directory %pd\n",
403449 child);
450
+out_free:
451
+ kfree(name.data);
452
+out:
404453 /* Keep trying, success or failure: */
405454 return 0;
406455 }
....@@ -430,13 +479,25 @@
430479 static int
431480 load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
432481 {
482
+ struct xdr_netobj name;
483
+ struct xdr_netobj princhash = { .len = 0, .data = NULL };
484
+
433485 if (child->d_name.len != HEXDIR_LEN - 1) {
434
- printk("nfsd4: illegal name %pd in recovery directory\n",
435
- child);
486
+ printk("%s: illegal name %pd in recovery directory\n",
487
+ __func__, child);
436488 /* Keep trying; maybe the others are OK: */
437489 return 0;
438490 }
439
- nfs4_client_to_reclaim(child->d_name.name, nn);
491
+ name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
492
+ if (!name.data) {
493
+ dprintk("%s: failed to allocate memory for name.data!\n",
494
+ __func__);
495
+ goto out;
496
+ }
497
+ name.len = HEXDIR_LEN;
498
+ if (!nfs4_client_to_reclaim(name, princhash, nn))
499
+ kfree(name.data);
500
+out:
440501 return 0;
441502 }
442503
....@@ -565,6 +626,7 @@
565626 status = nfsd4_load_reboot_recovery_data(net);
566627 if (status)
567628 goto err;
629
+ printk("NFSD: Using legacy client tracking operations.\n");
568630 return 0;
569631
570632 err:
....@@ -616,6 +678,7 @@
616678 char dname[HEXDIR_LEN];
617679 struct nfs4_client_reclaim *crp;
618680 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
681
+ struct xdr_netobj name;
619682
620683 /* did we already find that this client is stable? */
621684 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
....@@ -628,13 +691,22 @@
628691 }
629692
630693 /* look for it in the reclaim hashtable otherwise */
631
- crp = nfsd4_find_reclaim_client(dname, nn);
694
+ name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
695
+ if (!name.data) {
696
+ dprintk("%s: failed to allocate memory for name.data!\n",
697
+ __func__);
698
+ goto out_enoent;
699
+ }
700
+ name.len = HEXDIR_LEN;
701
+ crp = nfsd4_find_reclaim_client(name, nn);
702
+ kfree(name.data);
632703 if (crp) {
633704 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
634705 crp->cr_clp = clp;
635706 return 0;
636707 }
637708
709
+out_enoent:
638710 return -ENOENT;
639711 }
640712
....@@ -645,6 +717,8 @@
645717 .remove = nfsd4_remove_clid_dir,
646718 .check = nfsd4_check_legacy_client,
647719 .grace_done = nfsd4_recdir_purge_old,
720
+ .version = 1,
721
+ .msglen = 0,
648722 };
649723
650724 /* Globals */
....@@ -657,25 +731,31 @@
657731 spinlock_t cn_lock;
658732 struct list_head cn_list;
659733 unsigned int cn_xid;
734
+ bool cn_has_legacy;
735
+ struct crypto_shash *cn_tfm;
660736 };
661737
662738 struct cld_upcall {
663739 struct list_head cu_list;
664740 struct cld_net *cu_net;
665741 struct completion cu_done;
666
- struct cld_msg cu_msg;
742
+ union {
743
+ struct cld_msg_hdr cu_hdr;
744
+ struct cld_msg cu_msg;
745
+ struct cld_msg_v2 cu_msg_v2;
746
+ } cu_u;
667747 };
668748
669749 static int
670
-__cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
750
+__cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
671751 {
672752 int ret;
673753 struct rpc_pipe_msg msg;
674
- struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_msg);
754
+ struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_u);
675755
676756 memset(&msg, 0, sizeof(msg));
677757 msg.data = cmsg;
678
- msg.len = sizeof(*cmsg);
758
+ msg.len = nn->client_tracking_ops->msglen;
679759
680760 ret = rpc_queue_upcall(pipe, &msg);
681761 if (ret < 0) {
....@@ -691,7 +771,7 @@
691771 }
692772
693773 static int
694
-cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
774
+cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
695775 {
696776 int ret;
697777
....@@ -700,31 +780,105 @@
700780 * upcalls queued.
701781 */
702782 do {
703
- ret = __cld_pipe_upcall(pipe, cmsg);
783
+ ret = __cld_pipe_upcall(pipe, cmsg, nn);
704784 } while (ret == -EAGAIN);
705785
706786 return ret;
707787 }
708788
709789 static ssize_t
790
+__cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,
791
+ struct nfsd_net *nn)
792
+{
793
+ uint8_t cmd, princhashlen;
794
+ struct xdr_netobj name, princhash = { .len = 0, .data = NULL };
795
+ uint16_t namelen;
796
+ struct cld_net *cn = nn->cld_net;
797
+
798
+ if (get_user(cmd, &cmsg->cm_cmd)) {
799
+ dprintk("%s: error when copying cmd from userspace", __func__);
800
+ return -EFAULT;
801
+ }
802
+ if (cmd == Cld_GraceStart) {
803
+ if (nn->client_tracking_ops->version >= 2) {
804
+ const struct cld_clntinfo __user *ci;
805
+
806
+ ci = &cmsg->cm_u.cm_clntinfo;
807
+ if (get_user(namelen, &ci->cc_name.cn_len))
808
+ return -EFAULT;
809
+ name.data = memdup_user(&ci->cc_name.cn_id, namelen);
810
+ if (IS_ERR_OR_NULL(name.data))
811
+ return -EFAULT;
812
+ name.len = namelen;
813
+ get_user(princhashlen, &ci->cc_princhash.cp_len);
814
+ if (princhashlen > 0) {
815
+ princhash.data = memdup_user(
816
+ &ci->cc_princhash.cp_data,
817
+ princhashlen);
818
+ if (IS_ERR_OR_NULL(princhash.data)) {
819
+ kfree(name.data);
820
+ return -EFAULT;
821
+ }
822
+ princhash.len = princhashlen;
823
+ } else
824
+ princhash.len = 0;
825
+ } else {
826
+ const struct cld_name __user *cnm;
827
+
828
+ cnm = &cmsg->cm_u.cm_name;
829
+ if (get_user(namelen, &cnm->cn_len))
830
+ return -EFAULT;
831
+ name.data = memdup_user(&cnm->cn_id, namelen);
832
+ if (IS_ERR_OR_NULL(name.data))
833
+ return -EFAULT;
834
+ name.len = namelen;
835
+ }
836
+ if (name.len > 5 && memcmp(name.data, "hash:", 5) == 0) {
837
+ name.len = name.len - 5;
838
+ memmove(name.data, name.data + 5, name.len);
839
+ cn->cn_has_legacy = true;
840
+ }
841
+ if (!nfs4_client_to_reclaim(name, princhash, nn)) {
842
+ kfree(name.data);
843
+ kfree(princhash.data);
844
+ return -EFAULT;
845
+ }
846
+ return nn->client_tracking_ops->msglen;
847
+ }
848
+ return -EFAULT;
849
+}
850
+
851
+static ssize_t
710852 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
711853 {
712854 struct cld_upcall *tmp, *cup;
713
- struct cld_msg __user *cmsg = (struct cld_msg __user *)src;
855
+ struct cld_msg_hdr __user *hdr = (struct cld_msg_hdr __user *)src;
856
+ struct cld_msg_v2 __user *cmsg = (struct cld_msg_v2 __user *)src;
714857 uint32_t xid;
715858 struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info,
716859 nfsd_net_id);
717860 struct cld_net *cn = nn->cld_net;
861
+ int16_t status;
718862
719
- if (mlen != sizeof(*cmsg)) {
863
+ if (mlen != nn->client_tracking_ops->msglen) {
720864 dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen,
721
- sizeof(*cmsg));
865
+ nn->client_tracking_ops->msglen);
722866 return -EINVAL;
723867 }
724868
725869 /* copy just the xid so we can try to find that */
726
- if (copy_from_user(&xid, &cmsg->cm_xid, sizeof(xid)) != 0) {
870
+ if (copy_from_user(&xid, &hdr->cm_xid, sizeof(xid)) != 0) {
727871 dprintk("%s: error when copying xid from userspace", __func__);
872
+ return -EFAULT;
873
+ }
874
+
875
+ /*
876
+ * copy the status so we know whether to remove the upcall from the
877
+ * list (for -EINPROGRESS, we just want to make sure the xid is
878
+ * valid, not remove the upcall from the list)
879
+ */
880
+ if (get_user(status, &hdr->cm_status)) {
881
+ dprintk("%s: error when copying status from userspace", __func__);
728882 return -EFAULT;
729883 }
730884
....@@ -732,9 +886,10 @@
732886 cup = NULL;
733887 spin_lock(&cn->cn_lock);
734888 list_for_each_entry(tmp, &cn->cn_list, cu_list) {
735
- if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) {
889
+ if (get_unaligned(&tmp->cu_u.cu_hdr.cm_xid) == xid) {
736890 cup = tmp;
737
- list_del_init(&cup->cu_list);
891
+ if (status != -EINPROGRESS)
892
+ list_del_init(&cup->cu_list);
738893 break;
739894 }
740895 }
....@@ -746,7 +901,10 @@
746901 return -EINVAL;
747902 }
748903
749
- if (copy_from_user(&cup->cu_msg, src, mlen) != 0)
904
+ if (status == -EINPROGRESS)
905
+ return __cld_pipe_inprogress_downcall(cmsg, nn);
906
+
907
+ if (copy_from_user(&cup->cu_u.cu_msg_v2, src, mlen) != 0)
750908 return -EFAULT;
751909
752910 complete(&cup->cu_done);
....@@ -758,7 +916,7 @@
758916 {
759917 struct cld_msg *cmsg = msg->data;
760918 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall,
761
- cu_msg);
919
+ cu_u.cu_msg);
762920
763921 /* errno >= 0 means we got a downcall */
764922 if (msg->errno >= 0)
....@@ -821,7 +979,7 @@
821979
822980 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */
823981 static int
824
-nfsd4_init_cld_pipe(struct net *net)
982
+__nfsd4_init_cld_pipe(struct net *net)
825983 {
826984 int ret;
827985 struct dentry *dentry;
....@@ -852,6 +1010,7 @@
8521010 }
8531011
8541012 cn->cn_pipe->dentry = dentry;
1013
+ cn->cn_has_legacy = false;
8551014 nn->cld_net = cn;
8561015 return 0;
8571016
....@@ -864,6 +1023,17 @@
8641023 return ret;
8651024 }
8661025
1026
+static int
1027
+nfsd4_init_cld_pipe(struct net *net)
1028
+{
1029
+ int status;
1030
+
1031
+ status = __nfsd4_init_cld_pipe(net);
1032
+ if (!status)
1033
+ printk("NFSD: Using old nfsdcld client tracking operations.\n");
1034
+ return status;
1035
+}
1036
+
8671037 static void
8681038 nfsd4_remove_cld_pipe(struct net *net)
8691039 {
....@@ -872,14 +1042,17 @@
8721042
8731043 nfsd4_cld_unregister_net(net, cn->cn_pipe);
8741044 rpc_destroy_pipe_data(cn->cn_pipe);
1045
+ if (cn->cn_tfm)
1046
+ crypto_free_shash(cn->cn_tfm);
8751047 kfree(nn->cld_net);
8761048 nn->cld_net = NULL;
8771049 }
8781050
8791051 static struct cld_upcall *
880
-alloc_cld_upcall(struct cld_net *cn)
1052
+alloc_cld_upcall(struct nfsd_net *nn)
8811053 {
8821054 struct cld_upcall *new, *tmp;
1055
+ struct cld_net *cn = nn->cld_net;
8831056
8841057 new = kzalloc(sizeof(*new), GFP_KERNEL);
8851058 if (!new)
....@@ -889,20 +1062,20 @@
8891062 restart_search:
8901063 spin_lock(&cn->cn_lock);
8911064 list_for_each_entry(tmp, &cn->cn_list, cu_list) {
892
- if (tmp->cu_msg.cm_xid == cn->cn_xid) {
1065
+ if (tmp->cu_u.cu_msg.cm_xid == cn->cn_xid) {
8931066 cn->cn_xid++;
8941067 spin_unlock(&cn->cn_lock);
8951068 goto restart_search;
8961069 }
8971070 }
8981071 init_completion(&new->cu_done);
899
- new->cu_msg.cm_vers = CLD_UPCALL_VERSION;
900
- put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid);
1072
+ new->cu_u.cu_msg.cm_vers = nn->client_tracking_ops->version;
1073
+ put_unaligned(cn->cn_xid++, &new->cu_u.cu_msg.cm_xid);
9011074 new->cu_net = cn;
9021075 list_add(&new->cu_list, &cn->cn_list);
9031076 spin_unlock(&cn->cn_lock);
9041077
905
- dprintk("%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid);
1078
+ dprintk("%s: allocated xid %u\n", __func__, new->cu_u.cu_msg.cm_xid);
9061079
9071080 return new;
9081081 }
....@@ -931,20 +1104,20 @@
9311104 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
9321105 return;
9331106
934
- cup = alloc_cld_upcall(cn);
1107
+ cup = alloc_cld_upcall(nn);
9351108 if (!cup) {
9361109 ret = -ENOMEM;
9371110 goto out_err;
9381111 }
9391112
940
- cup->cu_msg.cm_cmd = Cld_Create;
941
- cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
942
- memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
1113
+ cup->cu_u.cu_msg.cm_cmd = Cld_Create;
1114
+ cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
1115
+ memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
9431116 clp->cl_name.len);
9441117
945
- ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
1118
+ ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
9461119 if (!ret) {
947
- ret = cup->cu_msg.cm_status;
1120
+ ret = cup->cu_u.cu_msg.cm_status;
9481121 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
9491122 }
9501123
....@@ -953,6 +1126,72 @@
9531126 if (ret)
9541127 printk(KERN_ERR "NFSD: Unable to create client "
9551128 "record on stable storage: %d\n", ret);
1129
+}
1130
+
1131
+/* Ask daemon to create a new record */
1132
+static void
1133
+nfsd4_cld_create_v2(struct nfs4_client *clp)
1134
+{
1135
+ int ret;
1136
+ struct cld_upcall *cup;
1137
+ struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1138
+ struct cld_net *cn = nn->cld_net;
1139
+ struct cld_msg_v2 *cmsg;
1140
+ struct crypto_shash *tfm = cn->cn_tfm;
1141
+ struct xdr_netobj cksum;
1142
+ char *principal = NULL;
1143
+
1144
+ /* Don't upcall if it's already stored */
1145
+ if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1146
+ return;
1147
+
1148
+ cup = alloc_cld_upcall(nn);
1149
+ if (!cup) {
1150
+ ret = -ENOMEM;
1151
+ goto out_err;
1152
+ }
1153
+
1154
+ cmsg = &cup->cu_u.cu_msg_v2;
1155
+ cmsg->cm_cmd = Cld_Create;
1156
+ cmsg->cm_u.cm_clntinfo.cc_name.cn_len = clp->cl_name.len;
1157
+ memcpy(cmsg->cm_u.cm_clntinfo.cc_name.cn_id, clp->cl_name.data,
1158
+ clp->cl_name.len);
1159
+ if (clp->cl_cred.cr_raw_principal)
1160
+ principal = clp->cl_cred.cr_raw_principal;
1161
+ else if (clp->cl_cred.cr_principal)
1162
+ principal = clp->cl_cred.cr_principal;
1163
+ if (principal) {
1164
+ cksum.len = crypto_shash_digestsize(tfm);
1165
+ cksum.data = kmalloc(cksum.len, GFP_KERNEL);
1166
+ if (cksum.data == NULL) {
1167
+ ret = -ENOMEM;
1168
+ goto out;
1169
+ }
1170
+ ret = crypto_shash_tfm_digest(tfm, principal, strlen(principal),
1171
+ cksum.data);
1172
+ if (ret) {
1173
+ kfree(cksum.data);
1174
+ goto out;
1175
+ }
1176
+ cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = cksum.len;
1177
+ memcpy(cmsg->cm_u.cm_clntinfo.cc_princhash.cp_data,
1178
+ cksum.data, cksum.len);
1179
+ kfree(cksum.data);
1180
+ } else
1181
+ cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = 0;
1182
+
1183
+ ret = cld_pipe_upcall(cn->cn_pipe, cmsg, nn);
1184
+ if (!ret) {
1185
+ ret = cmsg->cm_status;
1186
+ set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1187
+ }
1188
+
1189
+out:
1190
+ free_cld_upcall(cup);
1191
+out_err:
1192
+ if (ret)
1193
+ pr_err("NFSD: Unable to create client record on stable storage: %d\n",
1194
+ ret);
9561195 }
9571196
9581197 /* Ask daemon to create a new record */
....@@ -968,20 +1207,20 @@
9681207 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
9691208 return;
9701209
971
- cup = alloc_cld_upcall(cn);
1210
+ cup = alloc_cld_upcall(nn);
9721211 if (!cup) {
9731212 ret = -ENOMEM;
9741213 goto out_err;
9751214 }
9761215
977
- cup->cu_msg.cm_cmd = Cld_Remove;
978
- cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
979
- memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
1216
+ cup->cu_u.cu_msg.cm_cmd = Cld_Remove;
1217
+ cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
1218
+ memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
9801219 clp->cl_name.len);
9811220
982
- ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
1221
+ ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
9831222 if (!ret) {
984
- ret = cup->cu_msg.cm_status;
1223
+ ret = cup->cu_u.cu_msg.cm_status;
9851224 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
9861225 }
9871226
....@@ -992,9 +1231,14 @@
9921231 "record from stable storage: %d\n", ret);
9931232 }
9941233
995
-/* Check for presence of a record, and update its timestamp */
1234
+/*
1235
+ * For older nfsdcld's that do not allow us to "slurp" the clients
1236
+ * from the tracking database during startup.
1237
+ *
1238
+ * Check for presence of a record, and update its timestamp
1239
+ */
9961240 static int
997
-nfsd4_cld_check(struct nfs4_client *clp)
1241
+nfsd4_cld_check_v0(struct nfs4_client *clp)
9981242 {
9991243 int ret;
10001244 struct cld_upcall *cup;
....@@ -1005,21 +1249,21 @@
10051249 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
10061250 return 0;
10071251
1008
- cup = alloc_cld_upcall(cn);
1252
+ cup = alloc_cld_upcall(nn);
10091253 if (!cup) {
10101254 printk(KERN_ERR "NFSD: Unable to check client record on "
10111255 "stable storage: %d\n", -ENOMEM);
10121256 return -ENOMEM;
10131257 }
10141258
1015
- cup->cu_msg.cm_cmd = Cld_Check;
1016
- cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
1017
- memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
1259
+ cup->cu_u.cu_msg.cm_cmd = Cld_Check;
1260
+ cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
1261
+ memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
10181262 clp->cl_name.len);
10191263
1020
- ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
1264
+ ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
10211265 if (!ret) {
1022
- ret = cup->cu_msg.cm_status;
1266
+ ret = cup->cu_u.cu_msg.cm_status;
10231267 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
10241268 }
10251269
....@@ -1027,24 +1271,170 @@
10271271 return ret;
10281272 }
10291273
1030
-static void
1031
-nfsd4_cld_grace_done(struct nfsd_net *nn)
1274
+/*
1275
+ * For newer nfsdcld's that allow us to "slurp" the clients
1276
+ * from the tracking database during startup.
1277
+ *
1278
+ * Check for presence of a record in the reclaim_str_hashtbl
1279
+ */
1280
+static int
1281
+nfsd4_cld_check(struct nfs4_client *clp)
1282
+{
1283
+ struct nfs4_client_reclaim *crp;
1284
+ struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1285
+ struct cld_net *cn = nn->cld_net;
1286
+ int status;
1287
+ char dname[HEXDIR_LEN];
1288
+ struct xdr_netobj name;
1289
+
1290
+ /* did we already find that this client is stable? */
1291
+ if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1292
+ return 0;
1293
+
1294
+ /* look for it in the reclaim hashtable otherwise */
1295
+ crp = nfsd4_find_reclaim_client(clp->cl_name, nn);
1296
+ if (crp)
1297
+ goto found;
1298
+
1299
+ if (cn->cn_has_legacy) {
1300
+ status = nfs4_make_rec_clidname(dname, &clp->cl_name);
1301
+ if (status)
1302
+ return -ENOENT;
1303
+
1304
+ name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
1305
+ if (!name.data) {
1306
+ dprintk("%s: failed to allocate memory for name.data!\n",
1307
+ __func__);
1308
+ return -ENOENT;
1309
+ }
1310
+ name.len = HEXDIR_LEN;
1311
+ crp = nfsd4_find_reclaim_client(name, nn);
1312
+ kfree(name.data);
1313
+ if (crp)
1314
+ goto found;
1315
+
1316
+ }
1317
+ return -ENOENT;
1318
+found:
1319
+ crp->cr_clp = clp;
1320
+ return 0;
1321
+}
1322
+
1323
+static int
1324
+nfsd4_cld_check_v2(struct nfs4_client *clp)
1325
+{
1326
+ struct nfs4_client_reclaim *crp;
1327
+ struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1328
+ struct cld_net *cn = nn->cld_net;
1329
+ int status;
1330
+ char dname[HEXDIR_LEN];
1331
+ struct xdr_netobj name;
1332
+ struct crypto_shash *tfm = cn->cn_tfm;
1333
+ struct xdr_netobj cksum;
1334
+ char *principal = NULL;
1335
+
1336
+ /* did we already find that this client is stable? */
1337
+ if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1338
+ return 0;
1339
+
1340
+ /* look for it in the reclaim hashtable otherwise */
1341
+ crp = nfsd4_find_reclaim_client(clp->cl_name, nn);
1342
+ if (crp)
1343
+ goto found;
1344
+
1345
+ if (cn->cn_has_legacy) {
1346
+ status = nfs4_make_rec_clidname(dname, &clp->cl_name);
1347
+ if (status)
1348
+ return -ENOENT;
1349
+
1350
+ name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
1351
+ if (!name.data) {
1352
+ dprintk("%s: failed to allocate memory for name.data\n",
1353
+ __func__);
1354
+ return -ENOENT;
1355
+ }
1356
+ name.len = HEXDIR_LEN;
1357
+ crp = nfsd4_find_reclaim_client(name, nn);
1358
+ kfree(name.data);
1359
+ if (crp)
1360
+ goto found;
1361
+
1362
+ }
1363
+ return -ENOENT;
1364
+found:
1365
+ if (crp->cr_princhash.len) {
1366
+ if (clp->cl_cred.cr_raw_principal)
1367
+ principal = clp->cl_cred.cr_raw_principal;
1368
+ else if (clp->cl_cred.cr_principal)
1369
+ principal = clp->cl_cred.cr_principal;
1370
+ if (principal == NULL)
1371
+ return -ENOENT;
1372
+ cksum.len = crypto_shash_digestsize(tfm);
1373
+ cksum.data = kmalloc(cksum.len, GFP_KERNEL);
1374
+ if (cksum.data == NULL)
1375
+ return -ENOENT;
1376
+ status = crypto_shash_tfm_digest(tfm, principal,
1377
+ strlen(principal), cksum.data);
1378
+ if (status) {
1379
+ kfree(cksum.data);
1380
+ return -ENOENT;
1381
+ }
1382
+ if (memcmp(crp->cr_princhash.data, cksum.data,
1383
+ crp->cr_princhash.len)) {
1384
+ kfree(cksum.data);
1385
+ return -ENOENT;
1386
+ }
1387
+ kfree(cksum.data);
1388
+ }
1389
+ crp->cr_clp = clp;
1390
+ return 0;
1391
+}
1392
+
1393
+static int
1394
+nfsd4_cld_grace_start(struct nfsd_net *nn)
10321395 {
10331396 int ret;
10341397 struct cld_upcall *cup;
10351398 struct cld_net *cn = nn->cld_net;
10361399
1037
- cup = alloc_cld_upcall(cn);
1400
+ cup = alloc_cld_upcall(nn);
10381401 if (!cup) {
10391402 ret = -ENOMEM;
10401403 goto out_err;
10411404 }
10421405
1043
- cup->cu_msg.cm_cmd = Cld_GraceDone;
1044
- cup->cu_msg.cm_u.cm_gracetime = (int64_t)nn->boot_time;
1045
- ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
1406
+ cup->cu_u.cu_msg.cm_cmd = Cld_GraceStart;
1407
+ ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
10461408 if (!ret)
1047
- ret = cup->cu_msg.cm_status;
1409
+ ret = cup->cu_u.cu_msg.cm_status;
1410
+
1411
+ free_cld_upcall(cup);
1412
+out_err:
1413
+ if (ret)
1414
+ dprintk("%s: Unable to get clients from userspace: %d\n",
1415
+ __func__, ret);
1416
+ return ret;
1417
+}
1418
+
1419
+/* For older nfsdcld's that need cm_gracetime */
1420
+static void
1421
+nfsd4_cld_grace_done_v0(struct nfsd_net *nn)
1422
+{
1423
+ int ret;
1424
+ struct cld_upcall *cup;
1425
+ struct cld_net *cn = nn->cld_net;
1426
+
1427
+ cup = alloc_cld_upcall(nn);
1428
+ if (!cup) {
1429
+ ret = -ENOMEM;
1430
+ goto out_err;
1431
+ }
1432
+
1433
+ cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
1434
+ cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time;
1435
+ ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1436
+ if (!ret)
1437
+ ret = cup->cu_u.cu_msg.cm_status;
10481438
10491439 free_cld_upcall(cup);
10501440 out_err:
....@@ -1052,13 +1442,225 @@
10521442 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
10531443 }
10541444
1055
-static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
1445
+/*
1446
+ * For newer nfsdcld's that do not need cm_gracetime. We also need to call
1447
+ * nfs4_release_reclaim() to clear out the reclaim_str_hashtbl.
1448
+ */
1449
+static void
1450
+nfsd4_cld_grace_done(struct nfsd_net *nn)
1451
+{
1452
+ int ret;
1453
+ struct cld_upcall *cup;
1454
+ struct cld_net *cn = nn->cld_net;
1455
+
1456
+ cup = alloc_cld_upcall(nn);
1457
+ if (!cup) {
1458
+ ret = -ENOMEM;
1459
+ goto out_err;
1460
+ }
1461
+
1462
+ cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
1463
+ ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1464
+ if (!ret)
1465
+ ret = cup->cu_u.cu_msg.cm_status;
1466
+
1467
+ free_cld_upcall(cup);
1468
+out_err:
1469
+ nfs4_release_reclaim(nn);
1470
+ if (ret)
1471
+ printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
1472
+}
1473
+
1474
+static int
1475
+nfs4_cld_state_init(struct net *net)
1476
+{
1477
+ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1478
+ int i;
1479
+
1480
+ nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
1481
+ sizeof(struct list_head),
1482
+ GFP_KERNEL);
1483
+ if (!nn->reclaim_str_hashtbl)
1484
+ return -ENOMEM;
1485
+
1486
+ for (i = 0; i < CLIENT_HASH_SIZE; i++)
1487
+ INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
1488
+ nn->reclaim_str_hashtbl_size = 0;
1489
+ nn->track_reclaim_completes = true;
1490
+ atomic_set(&nn->nr_reclaim_complete, 0);
1491
+
1492
+ return 0;
1493
+}
1494
+
1495
+static void
1496
+nfs4_cld_state_shutdown(struct net *net)
1497
+{
1498
+ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1499
+
1500
+ nn->track_reclaim_completes = false;
1501
+ kfree(nn->reclaim_str_hashtbl);
1502
+}
1503
+
1504
+static bool
1505
+cld_running(struct nfsd_net *nn)
1506
+{
1507
+ struct cld_net *cn = nn->cld_net;
1508
+ struct rpc_pipe *pipe = cn->cn_pipe;
1509
+
1510
+ return pipe->nreaders || pipe->nwriters;
1511
+}
1512
+
1513
+static int
1514
+nfsd4_cld_get_version(struct nfsd_net *nn)
1515
+{
1516
+ int ret = 0;
1517
+ struct cld_upcall *cup;
1518
+ struct cld_net *cn = nn->cld_net;
1519
+ uint8_t version;
1520
+
1521
+ cup = alloc_cld_upcall(nn);
1522
+ if (!cup) {
1523
+ ret = -ENOMEM;
1524
+ goto out_err;
1525
+ }
1526
+ cup->cu_u.cu_msg.cm_cmd = Cld_GetVersion;
1527
+ ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1528
+ if (!ret) {
1529
+ ret = cup->cu_u.cu_msg.cm_status;
1530
+ if (ret)
1531
+ goto out_free;
1532
+ version = cup->cu_u.cu_msg.cm_u.cm_version;
1533
+ dprintk("%s: userspace returned version %u\n",
1534
+ __func__, version);
1535
+ if (version < 1)
1536
+ version = 1;
1537
+ else if (version > CLD_UPCALL_VERSION)
1538
+ version = CLD_UPCALL_VERSION;
1539
+
1540
+ switch (version) {
1541
+ case 1:
1542
+ nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
1543
+ break;
1544
+ case 2:
1545
+ nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v2;
1546
+ break;
1547
+ default:
1548
+ break;
1549
+ }
1550
+ }
1551
+out_free:
1552
+ free_cld_upcall(cup);
1553
+out_err:
1554
+ if (ret)
1555
+ dprintk("%s: Unable to get version from userspace: %d\n",
1556
+ __func__, ret);
1557
+ return ret;
1558
+}
1559
+
1560
+static int
1561
+nfsd4_cld_tracking_init(struct net *net)
1562
+{
1563
+ int status;
1564
+ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1565
+ bool running;
1566
+ int retries = 10;
1567
+ struct crypto_shash *tfm;
1568
+
1569
+ status = nfs4_cld_state_init(net);
1570
+ if (status)
1571
+ return status;
1572
+
1573
+ status = __nfsd4_init_cld_pipe(net);
1574
+ if (status)
1575
+ goto err_shutdown;
1576
+
1577
+ /*
1578
+ * rpc pipe upcalls take 30 seconds to time out, so we don't want to
1579
+ * queue an upcall unless we know that nfsdcld is running (because we
1580
+ * want this to fail fast so that nfsd4_client_tracking_init() can try
1581
+ * the next client tracking method). nfsdcld should already be running
1582
+ * before nfsd is started, so the wait here is for nfsdcld to open the
1583
+ * pipefs file we just created.
1584
+ */
1585
+ while (!(running = cld_running(nn)) && retries--)
1586
+ msleep(100);
1587
+
1588
+ if (!running) {
1589
+ status = -ETIMEDOUT;
1590
+ goto err_remove;
1591
+ }
1592
+ tfm = crypto_alloc_shash("sha256", 0, 0);
1593
+ if (IS_ERR(tfm)) {
1594
+ status = PTR_ERR(tfm);
1595
+ goto err_remove;
1596
+ }
1597
+ nn->cld_net->cn_tfm = tfm;
1598
+
1599
+ status = nfsd4_cld_get_version(nn);
1600
+ if (status == -EOPNOTSUPP)
1601
+ pr_warn("NFSD: nfsdcld GetVersion upcall failed. Please upgrade nfsdcld.\n");
1602
+
1603
+ status = nfsd4_cld_grace_start(nn);
1604
+ if (status) {
1605
+ if (status == -EOPNOTSUPP)
1606
+ pr_warn("NFSD: nfsdcld GraceStart upcall failed. Please upgrade nfsdcld.\n");
1607
+ nfs4_release_reclaim(nn);
1608
+ goto err_remove;
1609
+ } else
1610
+ printk("NFSD: Using nfsdcld client tracking operations.\n");
1611
+ return 0;
1612
+
1613
+err_remove:
1614
+ nfsd4_remove_cld_pipe(net);
1615
+err_shutdown:
1616
+ nfs4_cld_state_shutdown(net);
1617
+ return status;
1618
+}
1619
+
1620
+static void
1621
+nfsd4_cld_tracking_exit(struct net *net)
1622
+{
1623
+ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1624
+
1625
+ nfs4_release_reclaim(nn);
1626
+ nfsd4_remove_cld_pipe(net);
1627
+ nfs4_cld_state_shutdown(net);
1628
+}
1629
+
1630
+/* For older nfsdcld's */
1631
+static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v0 = {
10561632 .init = nfsd4_init_cld_pipe,
10571633 .exit = nfsd4_remove_cld_pipe,
10581634 .create = nfsd4_cld_create,
10591635 .remove = nfsd4_cld_remove,
1636
+ .check = nfsd4_cld_check_v0,
1637
+ .grace_done = nfsd4_cld_grace_done_v0,
1638
+ .version = 1,
1639
+ .msglen = sizeof(struct cld_msg),
1640
+};
1641
+
1642
+/* For newer nfsdcld's */
1643
+static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
1644
+ .init = nfsd4_cld_tracking_init,
1645
+ .exit = nfsd4_cld_tracking_exit,
1646
+ .create = nfsd4_cld_create,
1647
+ .remove = nfsd4_cld_remove,
10601648 .check = nfsd4_cld_check,
10611649 .grace_done = nfsd4_cld_grace_done,
1650
+ .version = 1,
1651
+ .msglen = sizeof(struct cld_msg),
1652
+};
1653
+
1654
+/* v2 create/check ops include the principal, if available */
1655
+static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2 = {
1656
+ .init = nfsd4_cld_tracking_init,
1657
+ .exit = nfsd4_cld_tracking_exit,
1658
+ .create = nfsd4_cld_create_v2,
1659
+ .remove = nfsd4_cld_remove,
1660
+ .check = nfsd4_cld_check_v2,
1661
+ .grace_done = nfsd4_cld_grace_done,
1662
+ .version = 2,
1663
+ .msglen = sizeof(struct cld_msg_v2),
10621664 };
10631665
10641666 /* upcall via usermodehelper */
....@@ -1166,7 +1768,7 @@
11661768 }
11671769
11681770 static char *
1169
-nfsd4_cltrack_grace_start(time_t grace_start)
1771
+nfsd4_cltrack_grace_start(time64_t grace_start)
11701772 {
11711773 int copied;
11721774 size_t len;
....@@ -1179,7 +1781,7 @@
11791781 if (!result)
11801782 return result;
11811783
1182
- copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%ld",
1784
+ copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%lld",
11831785 grace_start);
11841786 if (copied >= len) {
11851787 /* just return nothing if output was truncated */
....@@ -1236,19 +1838,14 @@
12361838 static char *
12371839 bin_to_hex_dup(const unsigned char *src, int srclen)
12381840 {
1239
- int i;
1240
- char *buf, *hex;
1841
+ char *buf;
12411842
12421843 /* +1 for terminating NULL */
1243
- buf = kmalloc((srclen * 2) + 1, GFP_KERNEL);
1844
+ buf = kzalloc((srclen * 2) + 1, GFP_KERNEL);
12441845 if (!buf)
12451846 return buf;
12461847
1247
- hex = buf;
1248
- for (i = 0; i < srclen; i++) {
1249
- sprintf(hex, "%2.2x", *src++);
1250
- hex += 2;
1251
- }
1848
+ bin2hex(buf, src, srclen);
12521849 return buf;
12531850 }
12541851
....@@ -1268,6 +1865,8 @@
12681865
12691866 ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL);
12701867 kfree(grace_start);
1868
+ if (!ret)
1869
+ printk("NFSD: Using UMH upcall client tracking operations.\n");
12711870 return ret;
12721871 }
12731872
....@@ -1391,7 +1990,7 @@
13911990 char *legacy;
13921991 char timestr[22]; /* FIXME: better way to determine max size? */
13931992
1394
- sprintf(timestr, "%ld", nn->boot_time);
1993
+ sprintf(timestr, "%lld", nn->boot_time);
13951994 legacy = nfsd4_cltrack_legacy_topdir();
13961995 nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL);
13971996 kfree(legacy);
....@@ -1404,6 +2003,8 @@
14042003 .remove = nfsd4_umh_cltrack_remove,
14052004 .check = nfsd4_umh_cltrack_check,
14062005 .grace_done = nfsd4_umh_cltrack_grace_done,
2006
+ .version = 1,
2007
+ .msglen = 0,
14072008 };
14082009
14092010 int
....@@ -1417,9 +2018,20 @@
14172018 if (nn->client_tracking_ops)
14182019 goto do_init;
14192020
2021
+ /* First, try to use nfsdcld */
2022
+ nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
2023
+ status = nn->client_tracking_ops->init(net);
2024
+ if (!status)
2025
+ return status;
2026
+ if (status != -ETIMEDOUT) {
2027
+ nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v0;
2028
+ status = nn->client_tracking_ops->init(net);
2029
+ if (!status)
2030
+ return status;
2031
+ }
2032
+
14202033 /*
1421
- * First, try a UMH upcall. It should succeed or fail quickly, so
1422
- * there's little harm in trying that first.
2034
+ * Next, try the UMH upcall.
14232035 */
14242036 nn->client_tracking_ops = &nfsd4_umh_tracking_ops;
14252037 status = nn->client_tracking_ops->init(net);
....@@ -1427,25 +2039,23 @@
14272039 return status;
14282040
14292041 /*
1430
- * See if the recoverydir exists and is a directory. If it is,
1431
- * then use the legacy ops.
2042
+ * Finally, See if the recoverydir exists and is a directory.
2043
+ * If it is, then use the legacy ops.
14322044 */
14332045 nn->client_tracking_ops = &nfsd4_legacy_tracking_ops;
14342046 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
14352047 if (!status) {
14362048 status = d_is_dir(path.dentry);
14372049 path_put(&path);
1438
- if (status)
1439
- goto do_init;
2050
+ if (!status) {
2051
+ status = -EINVAL;
2052
+ goto out;
2053
+ }
14402054 }
14412055
1442
- /* Finally, try to use nfsdcld */
1443
- nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
1444
- printk(KERN_WARNING "NFSD: the nfsdcld client tracking upcall will be "
1445
- "removed in 3.10. Please transition to using "
1446
- "nfsdcltrack.\n");
14472056 do_init:
14482057 status = nn->client_tracking_ops->init(net);
2058
+out:
14492059 if (status) {
14502060 printk(KERN_WARNING "NFSD: Unable to initialize client "
14512061 "recovery tracking! (%d)\n", status);
....@@ -1548,6 +2158,7 @@
15482158 int
15492159 register_cld_notifier(void)
15502160 {
2161
+ WARN_ON(!nfsd_net_id);
15512162 return rpc_pipefs_notifier_register(&nfsd4_cld_block);
15522163 }
15532164