0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <crypto/hash.h>
0036 #include <linux/file.h>
0037 #include <linux/slab.h>
0038 #include <linux/namei.h>
0039 #include <linux/sched.h>
0040 #include <linux/fs.h>
0041 #include <linux/module.h>
0042 #include <net/net_namespace.h>
0043 #include <linux/sunrpc/rpc_pipe_fs.h>
0044 #include <linux/sunrpc/clnt.h>
0045 #include <linux/nfsd/cld.h>
0046
0047 #include "nfsd.h"
0048 #include "state.h"
0049 #include "vfs.h"
0050 #include "netns.h"
0051
0052 #define NFSDDBG_FACILITY NFSDDBG_PROC
0053
0054
0055 struct nfsd4_client_tracking_ops {
0056 int (*init)(struct net *);
0057 void (*exit)(struct net *);
0058 void (*create)(struct nfs4_client *);
0059 void (*remove)(struct nfs4_client *);
0060 int (*check)(struct nfs4_client *);
0061 void (*grace_done)(struct nfsd_net *);
0062 uint8_t version;
0063 size_t msglen;
0064 };
0065
0066 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops;
0067 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2;
0068
0069
0070 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
0071
0072 static int
0073 nfs4_save_creds(const struct cred **original_creds)
0074 {
0075 struct cred *new;
0076
0077 new = prepare_creds();
0078 if (!new)
0079 return -ENOMEM;
0080
0081 new->fsuid = GLOBAL_ROOT_UID;
0082 new->fsgid = GLOBAL_ROOT_GID;
0083 *original_creds = override_creds(new);
0084 put_cred(new);
0085 return 0;
0086 }
0087
0088 static void
0089 nfs4_reset_creds(const struct cred *original)
0090 {
0091 revert_creds(original);
0092 }
0093
0094 static void
0095 md5_to_hex(char *out, char *md5)
0096 {
0097 int i;
0098
0099 for (i=0; i<16; i++) {
0100 unsigned char c = md5[i];
0101
0102 *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
0103 *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
0104 }
0105 *out = '\0';
0106 }
0107
0108 static int
0109 nfs4_make_rec_clidname(char *dname, const struct xdr_netobj *clname)
0110 {
0111 struct xdr_netobj cksum;
0112 struct crypto_shash *tfm;
0113 int status;
0114
0115 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
0116 clname->len, clname->data);
0117 tfm = crypto_alloc_shash("md5", 0, 0);
0118 if (IS_ERR(tfm)) {
0119 status = PTR_ERR(tfm);
0120 goto out_no_tfm;
0121 }
0122
0123 cksum.len = crypto_shash_digestsize(tfm);
0124 cksum.data = kmalloc(cksum.len, GFP_KERNEL);
0125 if (cksum.data == NULL) {
0126 status = -ENOMEM;
0127 goto out;
0128 }
0129
0130 status = crypto_shash_tfm_digest(tfm, clname->data, clname->len,
0131 cksum.data);
0132 if (status)
0133 goto out;
0134
0135 md5_to_hex(dname, cksum.data);
0136
0137 status = 0;
0138 out:
0139 kfree(cksum.data);
0140 crypto_free_shash(tfm);
0141 out_no_tfm:
0142 return status;
0143 }
0144
0145
0146
0147
0148
0149
0150 static void
0151 legacy_recdir_name_error(struct nfs4_client *clp, int error)
0152 {
0153 printk(KERN_ERR "NFSD: unable to generate recoverydir "
0154 "name (%d).\n", error);
0155
0156
0157
0158
0159
0160
0161 if (error == -ENOENT) {
0162 printk(KERN_ERR "NFSD: disabling legacy clientid tracking. "
0163 "Reboot recovery will not function correctly!\n");
0164 nfsd4_client_tracking_exit(clp->net);
0165 }
0166 }
0167
0168 static void
0169 __nfsd4_create_reclaim_record_grace(struct nfs4_client *clp,
0170 const char *dname, int len, struct nfsd_net *nn)
0171 {
0172 struct xdr_netobj name;
0173 struct xdr_netobj princhash = { .len = 0, .data = NULL };
0174 struct nfs4_client_reclaim *crp;
0175
0176 name.data = kmemdup(dname, len, GFP_KERNEL);
0177 if (!name.data) {
0178 dprintk("%s: failed to allocate memory for name.data!\n",
0179 __func__);
0180 return;
0181 }
0182 name.len = len;
0183 crp = nfs4_client_to_reclaim(name, princhash, nn);
0184 if (!crp) {
0185 kfree(name.data);
0186 return;
0187 }
0188 crp->cr_clp = clp;
0189 }
0190
0191 static void
0192 nfsd4_create_clid_dir(struct nfs4_client *clp)
0193 {
0194 const struct cred *original_cred;
0195 char dname[HEXDIR_LEN];
0196 struct dentry *dir, *dentry;
0197 int status;
0198 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
0199
0200 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
0201 return;
0202 if (!nn->rec_file)
0203 return;
0204
0205 status = nfs4_make_rec_clidname(dname, &clp->cl_name);
0206 if (status)
0207 return legacy_recdir_name_error(clp, status);
0208
0209 status = nfs4_save_creds(&original_cred);
0210 if (status < 0)
0211 return;
0212
0213 status = mnt_want_write_file(nn->rec_file);
0214 if (status)
0215 goto out_creds;
0216
0217 dir = nn->rec_file->f_path.dentry;
0218
0219 inode_lock(d_inode(dir));
0220
0221 dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1);
0222 if (IS_ERR(dentry)) {
0223 status = PTR_ERR(dentry);
0224 goto out_unlock;
0225 }
0226 if (d_really_is_positive(dentry))
0227
0228
0229
0230
0231
0232
0233
0234
0235 goto out_put;
0236 status = vfs_mkdir(&init_user_ns, d_inode(dir), dentry, S_IRWXU);
0237 out_put:
0238 dput(dentry);
0239 out_unlock:
0240 inode_unlock(d_inode(dir));
0241 if (status == 0) {
0242 if (nn->in_grace)
0243 __nfsd4_create_reclaim_record_grace(clp, dname,
0244 HEXDIR_LEN, nn);
0245 vfs_fsync(nn->rec_file, 0);
0246 } else {
0247 printk(KERN_ERR "NFSD: failed to write recovery record"
0248 " (err %d); please check that %s exists"
0249 " and is writeable", status,
0250 user_recovery_dirname);
0251 }
0252 mnt_drop_write_file(nn->rec_file);
0253 out_creds:
0254 nfs4_reset_creds(original_cred);
0255 }
0256
0257 typedef int (recdir_func)(struct dentry *, struct dentry *, struct nfsd_net *);
0258
0259 struct name_list {
0260 char name[HEXDIR_LEN];
0261 struct list_head list;
0262 };
0263
0264 struct nfs4_dir_ctx {
0265 struct dir_context ctx;
0266 struct list_head names;
0267 };
0268
0269 static int
0270 nfsd4_build_namelist(struct dir_context *__ctx, const char *name, int namlen,
0271 loff_t offset, u64 ino, unsigned int d_type)
0272 {
0273 struct nfs4_dir_ctx *ctx =
0274 container_of(__ctx, struct nfs4_dir_ctx, ctx);
0275 struct name_list *entry;
0276
0277 if (namlen != HEXDIR_LEN - 1)
0278 return 0;
0279 entry = kmalloc(sizeof(struct name_list), GFP_KERNEL);
0280 if (entry == NULL)
0281 return -ENOMEM;
0282 memcpy(entry->name, name, HEXDIR_LEN - 1);
0283 entry->name[HEXDIR_LEN - 1] = '\0';
0284 list_add(&entry->list, &ctx->names);
0285 return 0;
0286 }
0287
0288 static int
0289 nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
0290 {
0291 const struct cred *original_cred;
0292 struct dentry *dir = nn->rec_file->f_path.dentry;
0293 struct nfs4_dir_ctx ctx = {
0294 .ctx.actor = nfsd4_build_namelist,
0295 .names = LIST_HEAD_INIT(ctx.names)
0296 };
0297 struct name_list *entry, *tmp;
0298 int status;
0299
0300 status = nfs4_save_creds(&original_cred);
0301 if (status < 0)
0302 return status;
0303
0304 status = vfs_llseek(nn->rec_file, 0, SEEK_SET);
0305 if (status < 0) {
0306 nfs4_reset_creds(original_cred);
0307 return status;
0308 }
0309
0310 status = iterate_dir(nn->rec_file, &ctx.ctx);
0311 inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
0312
0313 list_for_each_entry_safe(entry, tmp, &ctx.names, list) {
0314 if (!status) {
0315 struct dentry *dentry;
0316 dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
0317 if (IS_ERR(dentry)) {
0318 status = PTR_ERR(dentry);
0319 break;
0320 }
0321 status = f(dir, dentry, nn);
0322 dput(dentry);
0323 }
0324 list_del(&entry->list);
0325 kfree(entry);
0326 }
0327 inode_unlock(d_inode(dir));
0328 nfs4_reset_creds(original_cred);
0329
0330 list_for_each_entry_safe(entry, tmp, &ctx.names, list) {
0331 dprintk("NFSD: %s. Left entry %s\n", __func__, entry->name);
0332 list_del(&entry->list);
0333 kfree(entry);
0334 }
0335 return status;
0336 }
0337
0338 static int
0339 nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn)
0340 {
0341 struct dentry *dir, *dentry;
0342 int status;
0343
0344 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
0345
0346 dir = nn->rec_file->f_path.dentry;
0347 inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
0348 dentry = lookup_one_len(name, dir, namlen);
0349 if (IS_ERR(dentry)) {
0350 status = PTR_ERR(dentry);
0351 goto out_unlock;
0352 }
0353 status = -ENOENT;
0354 if (d_really_is_negative(dentry))
0355 goto out;
0356 status = vfs_rmdir(&init_user_ns, d_inode(dir), dentry);
0357 out:
0358 dput(dentry);
0359 out_unlock:
0360 inode_unlock(d_inode(dir));
0361 return status;
0362 }
0363
0364 static void
0365 __nfsd4_remove_reclaim_record_grace(const char *dname, int len,
0366 struct nfsd_net *nn)
0367 {
0368 struct xdr_netobj name;
0369 struct nfs4_client_reclaim *crp;
0370
0371 name.data = kmemdup(dname, len, GFP_KERNEL);
0372 if (!name.data) {
0373 dprintk("%s: failed to allocate memory for name.data!\n",
0374 __func__);
0375 return;
0376 }
0377 name.len = len;
0378 crp = nfsd4_find_reclaim_client(name, nn);
0379 kfree(name.data);
0380 if (crp)
0381 nfs4_remove_reclaim_record(crp, nn);
0382 }
0383
0384 static void
0385 nfsd4_remove_clid_dir(struct nfs4_client *clp)
0386 {
0387 const struct cred *original_cred;
0388 char dname[HEXDIR_LEN];
0389 int status;
0390 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
0391
0392 if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
0393 return;
0394
0395 status = nfs4_make_rec_clidname(dname, &clp->cl_name);
0396 if (status)
0397 return legacy_recdir_name_error(clp, status);
0398
0399 status = mnt_want_write_file(nn->rec_file);
0400 if (status)
0401 goto out;
0402 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
0403
0404 status = nfs4_save_creds(&original_cred);
0405 if (status < 0)
0406 goto out_drop_write;
0407
0408 status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn);
0409 nfs4_reset_creds(original_cred);
0410 if (status == 0) {
0411 vfs_fsync(nn->rec_file, 0);
0412 if (nn->in_grace)
0413 __nfsd4_remove_reclaim_record_grace(dname,
0414 HEXDIR_LEN, nn);
0415 }
0416 out_drop_write:
0417 mnt_drop_write_file(nn->rec_file);
0418 out:
0419 if (status)
0420 printk("NFSD: Failed to remove expired client state directory"
0421 " %.*s\n", HEXDIR_LEN, dname);
0422 }
0423
0424 static int
0425 purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
0426 {
0427 int status;
0428 struct xdr_netobj name;
0429
0430 if (child->d_name.len != HEXDIR_LEN - 1) {
0431 printk("%s: illegal name %pd in recovery directory\n",
0432 __func__, child);
0433
0434 return 0;
0435 }
0436 name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
0437 if (!name.data) {
0438 dprintk("%s: failed to allocate memory for name.data!\n",
0439 __func__);
0440 goto out;
0441 }
0442 name.len = HEXDIR_LEN;
0443 if (nfs4_has_reclaimed_state(name, nn))
0444 goto out_free;
0445
0446 status = vfs_rmdir(&init_user_ns, d_inode(parent), child);
0447 if (status)
0448 printk("failed to remove client recovery directory %pd\n",
0449 child);
0450 out_free:
0451 kfree(name.data);
0452 out:
0453
0454 return 0;
0455 }
0456
0457 static void
0458 nfsd4_recdir_purge_old(struct nfsd_net *nn)
0459 {
0460 int status;
0461
0462 nn->in_grace = false;
0463 if (!nn->rec_file)
0464 return;
0465 status = mnt_want_write_file(nn->rec_file);
0466 if (status)
0467 goto out;
0468 status = nfsd4_list_rec_dir(purge_old, nn);
0469 if (status == 0)
0470 vfs_fsync(nn->rec_file, 0);
0471 mnt_drop_write_file(nn->rec_file);
0472 out:
0473 nfs4_release_reclaim(nn);
0474 if (status)
0475 printk("nfsd4: failed to purge old clients from recovery"
0476 " directory %pD\n", nn->rec_file);
0477 }
0478
0479 static int
0480 load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
0481 {
0482 struct xdr_netobj name;
0483 struct xdr_netobj princhash = { .len = 0, .data = NULL };
0484
0485 if (child->d_name.len != HEXDIR_LEN - 1) {
0486 printk("%s: illegal name %pd in recovery directory\n",
0487 __func__, child);
0488
0489 return 0;
0490 }
0491 name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
0492 if (!name.data) {
0493 dprintk("%s: failed to allocate memory for name.data!\n",
0494 __func__);
0495 goto out;
0496 }
0497 name.len = HEXDIR_LEN;
0498 if (!nfs4_client_to_reclaim(name, princhash, nn))
0499 kfree(name.data);
0500 out:
0501 return 0;
0502 }
0503
0504 static int
0505 nfsd4_recdir_load(struct net *net) {
0506 int status;
0507 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0508
0509 if (!nn->rec_file)
0510 return 0;
0511
0512 status = nfsd4_list_rec_dir(load_recdir, nn);
0513 if (status)
0514 printk("nfsd4: failed loading clients from recovery"
0515 " directory %pD\n", nn->rec_file);
0516 return status;
0517 }
0518
0519
0520
0521
0522
0523 static int
0524 nfsd4_init_recdir(struct net *net)
0525 {
0526 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0527 const struct cred *original_cred;
0528 int status;
0529
0530 printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
0531 user_recovery_dirname);
0532
0533 BUG_ON(nn->rec_file);
0534
0535 status = nfs4_save_creds(&original_cred);
0536 if (status < 0) {
0537 printk("NFSD: Unable to change credentials to find recovery"
0538 " directory: error %d\n",
0539 status);
0540 return status;
0541 }
0542
0543 nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
0544 if (IS_ERR(nn->rec_file)) {
0545 printk("NFSD: unable to find recovery directory %s\n",
0546 user_recovery_dirname);
0547 status = PTR_ERR(nn->rec_file);
0548 nn->rec_file = NULL;
0549 }
0550
0551 nfs4_reset_creds(original_cred);
0552 if (!status)
0553 nn->in_grace = true;
0554 return status;
0555 }
0556
0557 static void
0558 nfsd4_shutdown_recdir(struct net *net)
0559 {
0560 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0561
0562 if (!nn->rec_file)
0563 return;
0564 fput(nn->rec_file);
0565 nn->rec_file = NULL;
0566 }
0567
0568 static int
0569 nfs4_legacy_state_init(struct net *net)
0570 {
0571 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0572 int i;
0573
0574 nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
0575 sizeof(struct list_head),
0576 GFP_KERNEL);
0577 if (!nn->reclaim_str_hashtbl)
0578 return -ENOMEM;
0579
0580 for (i = 0; i < CLIENT_HASH_SIZE; i++)
0581 INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
0582 nn->reclaim_str_hashtbl_size = 0;
0583
0584 return 0;
0585 }
0586
0587 static void
0588 nfs4_legacy_state_shutdown(struct net *net)
0589 {
0590 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0591
0592 kfree(nn->reclaim_str_hashtbl);
0593 }
0594
0595 static int
0596 nfsd4_load_reboot_recovery_data(struct net *net)
0597 {
0598 int status;
0599
0600 status = nfsd4_init_recdir(net);
0601 if (status)
0602 return status;
0603
0604 status = nfsd4_recdir_load(net);
0605 if (status)
0606 nfsd4_shutdown_recdir(net);
0607
0608 return status;
0609 }
0610
0611 static int
0612 nfsd4_legacy_tracking_init(struct net *net)
0613 {
0614 int status;
0615
0616
0617 if (net != &init_net) {
0618 pr_warn("NFSD: attempt to initialize legacy client tracking in a container ignored.\n");
0619 return -EINVAL;
0620 }
0621
0622 status = nfs4_legacy_state_init(net);
0623 if (status)
0624 return status;
0625
0626 status = nfsd4_load_reboot_recovery_data(net);
0627 if (status)
0628 goto err;
0629 pr_info("NFSD: Using legacy client tracking operations.\n");
0630 return 0;
0631
0632 err:
0633 nfs4_legacy_state_shutdown(net);
0634 return status;
0635 }
0636
0637 static void
0638 nfsd4_legacy_tracking_exit(struct net *net)
0639 {
0640 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0641
0642 nfs4_release_reclaim(nn);
0643 nfsd4_shutdown_recdir(net);
0644 nfs4_legacy_state_shutdown(net);
0645 }
0646
0647
0648
0649
0650 int
0651 nfs4_reset_recoverydir(char *recdir)
0652 {
0653 int status;
0654 struct path path;
0655
0656 status = kern_path(recdir, LOOKUP_FOLLOW, &path);
0657 if (status)
0658 return status;
0659 status = -ENOTDIR;
0660 if (d_is_dir(path.dentry)) {
0661 strcpy(user_recovery_dirname, recdir);
0662 status = 0;
0663 }
0664 path_put(&path);
0665 return status;
0666 }
0667
0668 char *
0669 nfs4_recoverydir(void)
0670 {
0671 return user_recovery_dirname;
0672 }
0673
0674 static int
0675 nfsd4_check_legacy_client(struct nfs4_client *clp)
0676 {
0677 int status;
0678 char dname[HEXDIR_LEN];
0679 struct nfs4_client_reclaim *crp;
0680 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
0681 struct xdr_netobj name;
0682
0683
0684 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
0685 return 0;
0686
0687 status = nfs4_make_rec_clidname(dname, &clp->cl_name);
0688 if (status) {
0689 legacy_recdir_name_error(clp, status);
0690 return status;
0691 }
0692
0693
0694 name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
0695 if (!name.data) {
0696 dprintk("%s: failed to allocate memory for name.data!\n",
0697 __func__);
0698 goto out_enoent;
0699 }
0700 name.len = HEXDIR_LEN;
0701 crp = nfsd4_find_reclaim_client(name, nn);
0702 kfree(name.data);
0703 if (crp) {
0704 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
0705 crp->cr_clp = clp;
0706 return 0;
0707 }
0708
0709 out_enoent:
0710 return -ENOENT;
0711 }
0712
0713 static const struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
0714 .init = nfsd4_legacy_tracking_init,
0715 .exit = nfsd4_legacy_tracking_exit,
0716 .create = nfsd4_create_clid_dir,
0717 .remove = nfsd4_remove_clid_dir,
0718 .check = nfsd4_check_legacy_client,
0719 .grace_done = nfsd4_recdir_purge_old,
0720 .version = 1,
0721 .msglen = 0,
0722 };
0723
0724
0725 #define NFSD_PIPE_DIR "nfsd"
0726 #define NFSD_CLD_PIPE "cld"
0727
0728
0729 struct cld_net {
0730 struct rpc_pipe *cn_pipe;
0731 spinlock_t cn_lock;
0732 struct list_head cn_list;
0733 unsigned int cn_xid;
0734 bool cn_has_legacy;
0735 struct crypto_shash *cn_tfm;
0736 };
0737
0738 struct cld_upcall {
0739 struct list_head cu_list;
0740 struct cld_net *cu_net;
0741 struct completion cu_done;
0742 union {
0743 struct cld_msg_hdr cu_hdr;
0744 struct cld_msg cu_msg;
0745 struct cld_msg_v2 cu_msg_v2;
0746 } cu_u;
0747 };
0748
0749 static int
0750 __cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
0751 {
0752 int ret;
0753 struct rpc_pipe_msg msg;
0754 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_u);
0755
0756 memset(&msg, 0, sizeof(msg));
0757 msg.data = cmsg;
0758 msg.len = nn->client_tracking_ops->msglen;
0759
0760 ret = rpc_queue_upcall(pipe, &msg);
0761 if (ret < 0) {
0762 goto out;
0763 }
0764
0765 wait_for_completion(&cup->cu_done);
0766
0767 if (msg.errno < 0)
0768 ret = msg.errno;
0769 out:
0770 return ret;
0771 }
0772
0773 static int
0774 cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
0775 {
0776 int ret;
0777
0778
0779
0780
0781
0782 do {
0783 ret = __cld_pipe_upcall(pipe, cmsg, nn);
0784 } while (ret == -EAGAIN);
0785
0786 return ret;
0787 }
0788
0789 static ssize_t
0790 __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,
0791 struct nfsd_net *nn)
0792 {
0793 uint8_t cmd, princhashlen;
0794 struct xdr_netobj name, princhash = { .len = 0, .data = NULL };
0795 uint16_t namelen;
0796 struct cld_net *cn = nn->cld_net;
0797
0798 if (get_user(cmd, &cmsg->cm_cmd)) {
0799 dprintk("%s: error when copying cmd from userspace", __func__);
0800 return -EFAULT;
0801 }
0802 if (cmd == Cld_GraceStart) {
0803 if (nn->client_tracking_ops->version >= 2) {
0804 const struct cld_clntinfo __user *ci;
0805
0806 ci = &cmsg->cm_u.cm_clntinfo;
0807 if (get_user(namelen, &ci->cc_name.cn_len))
0808 return -EFAULT;
0809 name.data = memdup_user(&ci->cc_name.cn_id, namelen);
0810 if (IS_ERR_OR_NULL(name.data))
0811 return -EFAULT;
0812 name.len = namelen;
0813 get_user(princhashlen, &ci->cc_princhash.cp_len);
0814 if (princhashlen > 0) {
0815 princhash.data = memdup_user(
0816 &ci->cc_princhash.cp_data,
0817 princhashlen);
0818 if (IS_ERR_OR_NULL(princhash.data))
0819 return -EFAULT;
0820 princhash.len = princhashlen;
0821 } else
0822 princhash.len = 0;
0823 } else {
0824 const struct cld_name __user *cnm;
0825
0826 cnm = &cmsg->cm_u.cm_name;
0827 if (get_user(namelen, &cnm->cn_len))
0828 return -EFAULT;
0829 name.data = memdup_user(&cnm->cn_id, namelen);
0830 if (IS_ERR_OR_NULL(name.data))
0831 return -EFAULT;
0832 name.len = namelen;
0833 }
0834 if (name.len > 5 && memcmp(name.data, "hash:", 5) == 0) {
0835 name.len = name.len - 5;
0836 memmove(name.data, name.data + 5, name.len);
0837 cn->cn_has_legacy = true;
0838 }
0839 if (!nfs4_client_to_reclaim(name, princhash, nn)) {
0840 kfree(name.data);
0841 kfree(princhash.data);
0842 return -EFAULT;
0843 }
0844 return nn->client_tracking_ops->msglen;
0845 }
0846 return -EFAULT;
0847 }
0848
0849 static ssize_t
0850 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
0851 {
0852 struct cld_upcall *tmp, *cup;
0853 struct cld_msg_hdr __user *hdr = (struct cld_msg_hdr __user *)src;
0854 struct cld_msg_v2 __user *cmsg = (struct cld_msg_v2 __user *)src;
0855 uint32_t xid;
0856 struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info,
0857 nfsd_net_id);
0858 struct cld_net *cn = nn->cld_net;
0859 int16_t status;
0860
0861 if (mlen != nn->client_tracking_ops->msglen) {
0862 dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen,
0863 nn->client_tracking_ops->msglen);
0864 return -EINVAL;
0865 }
0866
0867
0868 if (copy_from_user(&xid, &hdr->cm_xid, sizeof(xid)) != 0) {
0869 dprintk("%s: error when copying xid from userspace", __func__);
0870 return -EFAULT;
0871 }
0872
0873
0874
0875
0876
0877
0878 if (get_user(status, &hdr->cm_status)) {
0879 dprintk("%s: error when copying status from userspace", __func__);
0880 return -EFAULT;
0881 }
0882
0883
0884 cup = NULL;
0885 spin_lock(&cn->cn_lock);
0886 list_for_each_entry(tmp, &cn->cn_list, cu_list) {
0887 if (get_unaligned(&tmp->cu_u.cu_hdr.cm_xid) == xid) {
0888 cup = tmp;
0889 if (status != -EINPROGRESS)
0890 list_del_init(&cup->cu_list);
0891 break;
0892 }
0893 }
0894 spin_unlock(&cn->cn_lock);
0895
0896
0897 if (!cup) {
0898 dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid);
0899 return -EINVAL;
0900 }
0901
0902 if (status == -EINPROGRESS)
0903 return __cld_pipe_inprogress_downcall(cmsg, nn);
0904
0905 if (copy_from_user(&cup->cu_u.cu_msg_v2, src, mlen) != 0)
0906 return -EFAULT;
0907
0908 complete(&cup->cu_done);
0909 return mlen;
0910 }
0911
0912 static void
0913 cld_pipe_destroy_msg(struct rpc_pipe_msg *msg)
0914 {
0915 struct cld_msg *cmsg = msg->data;
0916 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall,
0917 cu_u.cu_msg);
0918
0919
0920 if (msg->errno >= 0)
0921 return;
0922
0923 complete(&cup->cu_done);
0924 }
0925
0926 static const struct rpc_pipe_ops cld_upcall_ops = {
0927 .upcall = rpc_pipe_generic_upcall,
0928 .downcall = cld_pipe_downcall,
0929 .destroy_msg = cld_pipe_destroy_msg,
0930 };
0931
0932 static struct dentry *
0933 nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
0934 {
0935 struct dentry *dir, *dentry;
0936
0937 dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR);
0938 if (dir == NULL)
0939 return ERR_PTR(-ENOENT);
0940 dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe);
0941 dput(dir);
0942 return dentry;
0943 }
0944
0945 static void
0946 nfsd4_cld_unregister_sb(struct rpc_pipe *pipe)
0947 {
0948 if (pipe->dentry)
0949 rpc_unlink(pipe->dentry);
0950 }
0951
0952 static struct dentry *
0953 nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
0954 {
0955 struct super_block *sb;
0956 struct dentry *dentry;
0957
0958 sb = rpc_get_sb_net(net);
0959 if (!sb)
0960 return NULL;
0961 dentry = nfsd4_cld_register_sb(sb, pipe);
0962 rpc_put_sb_net(net);
0963 return dentry;
0964 }
0965
0966 static void
0967 nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe)
0968 {
0969 struct super_block *sb;
0970
0971 sb = rpc_get_sb_net(net);
0972 if (sb) {
0973 nfsd4_cld_unregister_sb(pipe);
0974 rpc_put_sb_net(net);
0975 }
0976 }
0977
0978
0979 static int
0980 __nfsd4_init_cld_pipe(struct net *net)
0981 {
0982 int ret;
0983 struct dentry *dentry;
0984 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0985 struct cld_net *cn;
0986
0987 if (nn->cld_net)
0988 return 0;
0989
0990 cn = kzalloc(sizeof(*cn), GFP_KERNEL);
0991 if (!cn) {
0992 ret = -ENOMEM;
0993 goto err;
0994 }
0995
0996 cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
0997 if (IS_ERR(cn->cn_pipe)) {
0998 ret = PTR_ERR(cn->cn_pipe);
0999 goto err;
1000 }
1001 spin_lock_init(&cn->cn_lock);
1002 INIT_LIST_HEAD(&cn->cn_list);
1003
1004 dentry = nfsd4_cld_register_net(net, cn->cn_pipe);
1005 if (IS_ERR(dentry)) {
1006 ret = PTR_ERR(dentry);
1007 goto err_destroy_data;
1008 }
1009
1010 cn->cn_pipe->dentry = dentry;
1011 cn->cn_has_legacy = false;
1012 nn->cld_net = cn;
1013 return 0;
1014
1015 err_destroy_data:
1016 rpc_destroy_pipe_data(cn->cn_pipe);
1017 err:
1018 kfree(cn);
1019 printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n",
1020 ret);
1021 return ret;
1022 }
1023
1024 static int
1025 nfsd4_init_cld_pipe(struct net *net)
1026 {
1027 int status;
1028
1029 status = __nfsd4_init_cld_pipe(net);
1030 if (!status)
1031 pr_info("NFSD: Using old nfsdcld client tracking operations.\n");
1032 return status;
1033 }
1034
1035 static void
1036 nfsd4_remove_cld_pipe(struct net *net)
1037 {
1038 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1039 struct cld_net *cn = nn->cld_net;
1040
1041 nfsd4_cld_unregister_net(net, cn->cn_pipe);
1042 rpc_destroy_pipe_data(cn->cn_pipe);
1043 if (cn->cn_tfm)
1044 crypto_free_shash(cn->cn_tfm);
1045 kfree(nn->cld_net);
1046 nn->cld_net = NULL;
1047 }
1048
1049 static struct cld_upcall *
1050 alloc_cld_upcall(struct nfsd_net *nn)
1051 {
1052 struct cld_upcall *new, *tmp;
1053 struct cld_net *cn = nn->cld_net;
1054
1055 new = kzalloc(sizeof(*new), GFP_KERNEL);
1056 if (!new)
1057 return new;
1058
1059
1060 restart_search:
1061 spin_lock(&cn->cn_lock);
1062 list_for_each_entry(tmp, &cn->cn_list, cu_list) {
1063 if (tmp->cu_u.cu_msg.cm_xid == cn->cn_xid) {
1064 cn->cn_xid++;
1065 spin_unlock(&cn->cn_lock);
1066 goto restart_search;
1067 }
1068 }
1069 init_completion(&new->cu_done);
1070 new->cu_u.cu_msg.cm_vers = nn->client_tracking_ops->version;
1071 put_unaligned(cn->cn_xid++, &new->cu_u.cu_msg.cm_xid);
1072 new->cu_net = cn;
1073 list_add(&new->cu_list, &cn->cn_list);
1074 spin_unlock(&cn->cn_lock);
1075
1076 dprintk("%s: allocated xid %u\n", __func__, new->cu_u.cu_msg.cm_xid);
1077
1078 return new;
1079 }
1080
1081 static void
1082 free_cld_upcall(struct cld_upcall *victim)
1083 {
1084 struct cld_net *cn = victim->cu_net;
1085
1086 spin_lock(&cn->cn_lock);
1087 list_del(&victim->cu_list);
1088 spin_unlock(&cn->cn_lock);
1089 kfree(victim);
1090 }
1091
1092
1093 static void
1094 nfsd4_cld_create(struct nfs4_client *clp)
1095 {
1096 int ret;
1097 struct cld_upcall *cup;
1098 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1099 struct cld_net *cn = nn->cld_net;
1100
1101
1102 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1103 return;
1104
1105 cup = alloc_cld_upcall(nn);
1106 if (!cup) {
1107 ret = -ENOMEM;
1108 goto out_err;
1109 }
1110
1111 cup->cu_u.cu_msg.cm_cmd = Cld_Create;
1112 cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
1113 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
1114 clp->cl_name.len);
1115
1116 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1117 if (!ret) {
1118 ret = cup->cu_u.cu_msg.cm_status;
1119 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1120 }
1121
1122 free_cld_upcall(cup);
1123 out_err:
1124 if (ret)
1125 printk(KERN_ERR "NFSD: Unable to create client "
1126 "record on stable storage: %d\n", ret);
1127 }
1128
1129
1130 static void
1131 nfsd4_cld_create_v2(struct nfs4_client *clp)
1132 {
1133 int ret;
1134 struct cld_upcall *cup;
1135 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1136 struct cld_net *cn = nn->cld_net;
1137 struct cld_msg_v2 *cmsg;
1138 struct crypto_shash *tfm = cn->cn_tfm;
1139 struct xdr_netobj cksum;
1140 char *principal = NULL;
1141
1142
1143 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1144 return;
1145
1146 cup = alloc_cld_upcall(nn);
1147 if (!cup) {
1148 ret = -ENOMEM;
1149 goto out_err;
1150 }
1151
1152 cmsg = &cup->cu_u.cu_msg_v2;
1153 cmsg->cm_cmd = Cld_Create;
1154 cmsg->cm_u.cm_clntinfo.cc_name.cn_len = clp->cl_name.len;
1155 memcpy(cmsg->cm_u.cm_clntinfo.cc_name.cn_id, clp->cl_name.data,
1156 clp->cl_name.len);
1157 if (clp->cl_cred.cr_raw_principal)
1158 principal = clp->cl_cred.cr_raw_principal;
1159 else if (clp->cl_cred.cr_principal)
1160 principal = clp->cl_cred.cr_principal;
1161 if (principal) {
1162 cksum.len = crypto_shash_digestsize(tfm);
1163 cksum.data = kmalloc(cksum.len, GFP_KERNEL);
1164 if (cksum.data == NULL) {
1165 ret = -ENOMEM;
1166 goto out;
1167 }
1168 ret = crypto_shash_tfm_digest(tfm, principal, strlen(principal),
1169 cksum.data);
1170 if (ret) {
1171 kfree(cksum.data);
1172 goto out;
1173 }
1174 cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = cksum.len;
1175 memcpy(cmsg->cm_u.cm_clntinfo.cc_princhash.cp_data,
1176 cksum.data, cksum.len);
1177 kfree(cksum.data);
1178 } else
1179 cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = 0;
1180
1181 ret = cld_pipe_upcall(cn->cn_pipe, cmsg, nn);
1182 if (!ret) {
1183 ret = cmsg->cm_status;
1184 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1185 }
1186
1187 out:
1188 free_cld_upcall(cup);
1189 out_err:
1190 if (ret)
1191 pr_err("NFSD: Unable to create client record on stable storage: %d\n",
1192 ret);
1193 }
1194
1195
1196 static void
1197 nfsd4_cld_remove(struct nfs4_client *clp)
1198 {
1199 int ret;
1200 struct cld_upcall *cup;
1201 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1202 struct cld_net *cn = nn->cld_net;
1203
1204
1205 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1206 return;
1207
1208 cup = alloc_cld_upcall(nn);
1209 if (!cup) {
1210 ret = -ENOMEM;
1211 goto out_err;
1212 }
1213
1214 cup->cu_u.cu_msg.cm_cmd = Cld_Remove;
1215 cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
1216 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
1217 clp->cl_name.len);
1218
1219 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1220 if (!ret) {
1221 ret = cup->cu_u.cu_msg.cm_status;
1222 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1223 }
1224
1225 free_cld_upcall(cup);
1226 out_err:
1227 if (ret)
1228 printk(KERN_ERR "NFSD: Unable to remove client "
1229 "record from stable storage: %d\n", ret);
1230 }
1231
1232
1233
1234
1235
1236
1237
1238 static int
1239 nfsd4_cld_check_v0(struct nfs4_client *clp)
1240 {
1241 int ret;
1242 struct cld_upcall *cup;
1243 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1244 struct cld_net *cn = nn->cld_net;
1245
1246
1247 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1248 return 0;
1249
1250 cup = alloc_cld_upcall(nn);
1251 if (!cup) {
1252 printk(KERN_ERR "NFSD: Unable to check client record on "
1253 "stable storage: %d\n", -ENOMEM);
1254 return -ENOMEM;
1255 }
1256
1257 cup->cu_u.cu_msg.cm_cmd = Cld_Check;
1258 cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
1259 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
1260 clp->cl_name.len);
1261
1262 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1263 if (!ret) {
1264 ret = cup->cu_u.cu_msg.cm_status;
1265 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1266 }
1267
1268 free_cld_upcall(cup);
1269 return ret;
1270 }
1271
1272
1273
1274
1275
1276
1277
1278 static int
1279 nfsd4_cld_check(struct nfs4_client *clp)
1280 {
1281 struct nfs4_client_reclaim *crp;
1282 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1283 struct cld_net *cn = nn->cld_net;
1284 int status;
1285 char dname[HEXDIR_LEN];
1286 struct xdr_netobj name;
1287
1288
1289 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1290 return 0;
1291
1292
1293 crp = nfsd4_find_reclaim_client(clp->cl_name, nn);
1294 if (crp)
1295 goto found;
1296
1297 if (cn->cn_has_legacy) {
1298 status = nfs4_make_rec_clidname(dname, &clp->cl_name);
1299 if (status)
1300 return -ENOENT;
1301
1302 name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
1303 if (!name.data) {
1304 dprintk("%s: failed to allocate memory for name.data!\n",
1305 __func__);
1306 return -ENOENT;
1307 }
1308 name.len = HEXDIR_LEN;
1309 crp = nfsd4_find_reclaim_client(name, nn);
1310 kfree(name.data);
1311 if (crp)
1312 goto found;
1313
1314 }
1315 return -ENOENT;
1316 found:
1317 crp->cr_clp = clp;
1318 return 0;
1319 }
1320
1321 static int
1322 nfsd4_cld_check_v2(struct nfs4_client *clp)
1323 {
1324 struct nfs4_client_reclaim *crp;
1325 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1326 struct cld_net *cn = nn->cld_net;
1327 int status;
1328 char dname[HEXDIR_LEN];
1329 struct xdr_netobj name;
1330 struct crypto_shash *tfm = cn->cn_tfm;
1331 struct xdr_netobj cksum;
1332 char *principal = NULL;
1333
1334
1335 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1336 return 0;
1337
1338
1339 crp = nfsd4_find_reclaim_client(clp->cl_name, nn);
1340 if (crp)
1341 goto found;
1342
1343 if (cn->cn_has_legacy) {
1344 status = nfs4_make_rec_clidname(dname, &clp->cl_name);
1345 if (status)
1346 return -ENOENT;
1347
1348 name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
1349 if (!name.data) {
1350 dprintk("%s: failed to allocate memory for name.data\n",
1351 __func__);
1352 return -ENOENT;
1353 }
1354 name.len = HEXDIR_LEN;
1355 crp = nfsd4_find_reclaim_client(name, nn);
1356 kfree(name.data);
1357 if (crp)
1358 goto found;
1359
1360 }
1361 return -ENOENT;
1362 found:
1363 if (crp->cr_princhash.len) {
1364 if (clp->cl_cred.cr_raw_principal)
1365 principal = clp->cl_cred.cr_raw_principal;
1366 else if (clp->cl_cred.cr_principal)
1367 principal = clp->cl_cred.cr_principal;
1368 if (principal == NULL)
1369 return -ENOENT;
1370 cksum.len = crypto_shash_digestsize(tfm);
1371 cksum.data = kmalloc(cksum.len, GFP_KERNEL);
1372 if (cksum.data == NULL)
1373 return -ENOENT;
1374 status = crypto_shash_tfm_digest(tfm, principal,
1375 strlen(principal), cksum.data);
1376 if (status) {
1377 kfree(cksum.data);
1378 return -ENOENT;
1379 }
1380 if (memcmp(crp->cr_princhash.data, cksum.data,
1381 crp->cr_princhash.len)) {
1382 kfree(cksum.data);
1383 return -ENOENT;
1384 }
1385 kfree(cksum.data);
1386 }
1387 crp->cr_clp = clp;
1388 return 0;
1389 }
1390
1391 static int
1392 nfsd4_cld_grace_start(struct nfsd_net *nn)
1393 {
1394 int ret;
1395 struct cld_upcall *cup;
1396 struct cld_net *cn = nn->cld_net;
1397
1398 cup = alloc_cld_upcall(nn);
1399 if (!cup) {
1400 ret = -ENOMEM;
1401 goto out_err;
1402 }
1403
1404 cup->cu_u.cu_msg.cm_cmd = Cld_GraceStart;
1405 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1406 if (!ret)
1407 ret = cup->cu_u.cu_msg.cm_status;
1408
1409 free_cld_upcall(cup);
1410 out_err:
1411 if (ret)
1412 dprintk("%s: Unable to get clients from userspace: %d\n",
1413 __func__, ret);
1414 return ret;
1415 }
1416
1417
1418 static void
1419 nfsd4_cld_grace_done_v0(struct nfsd_net *nn)
1420 {
1421 int ret;
1422 struct cld_upcall *cup;
1423 struct cld_net *cn = nn->cld_net;
1424
1425 cup = alloc_cld_upcall(nn);
1426 if (!cup) {
1427 ret = -ENOMEM;
1428 goto out_err;
1429 }
1430
1431 cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
1432 cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time;
1433 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1434 if (!ret)
1435 ret = cup->cu_u.cu_msg.cm_status;
1436
1437 free_cld_upcall(cup);
1438 out_err:
1439 if (ret)
1440 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
1441 }
1442
1443
1444
1445
1446
1447 static void
1448 nfsd4_cld_grace_done(struct nfsd_net *nn)
1449 {
1450 int ret;
1451 struct cld_upcall *cup;
1452 struct cld_net *cn = nn->cld_net;
1453
1454 cup = alloc_cld_upcall(nn);
1455 if (!cup) {
1456 ret = -ENOMEM;
1457 goto out_err;
1458 }
1459
1460 cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
1461 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1462 if (!ret)
1463 ret = cup->cu_u.cu_msg.cm_status;
1464
1465 free_cld_upcall(cup);
1466 out_err:
1467 nfs4_release_reclaim(nn);
1468 if (ret)
1469 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
1470 }
1471
1472 static int
1473 nfs4_cld_state_init(struct net *net)
1474 {
1475 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1476 int i;
1477
1478 nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
1479 sizeof(struct list_head),
1480 GFP_KERNEL);
1481 if (!nn->reclaim_str_hashtbl)
1482 return -ENOMEM;
1483
1484 for (i = 0; i < CLIENT_HASH_SIZE; i++)
1485 INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
1486 nn->reclaim_str_hashtbl_size = 0;
1487 nn->track_reclaim_completes = true;
1488 atomic_set(&nn->nr_reclaim_complete, 0);
1489
1490 return 0;
1491 }
1492
1493 static void
1494 nfs4_cld_state_shutdown(struct net *net)
1495 {
1496 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1497
1498 nn->track_reclaim_completes = false;
1499 kfree(nn->reclaim_str_hashtbl);
1500 }
1501
1502 static bool
1503 cld_running(struct nfsd_net *nn)
1504 {
1505 struct cld_net *cn = nn->cld_net;
1506 struct rpc_pipe *pipe = cn->cn_pipe;
1507
1508 return pipe->nreaders || pipe->nwriters;
1509 }
1510
1511 static int
1512 nfsd4_cld_get_version(struct nfsd_net *nn)
1513 {
1514 int ret = 0;
1515 struct cld_upcall *cup;
1516 struct cld_net *cn = nn->cld_net;
1517 uint8_t version;
1518
1519 cup = alloc_cld_upcall(nn);
1520 if (!cup) {
1521 ret = -ENOMEM;
1522 goto out_err;
1523 }
1524 cup->cu_u.cu_msg.cm_cmd = Cld_GetVersion;
1525 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1526 if (!ret) {
1527 ret = cup->cu_u.cu_msg.cm_status;
1528 if (ret)
1529 goto out_free;
1530 version = cup->cu_u.cu_msg.cm_u.cm_version;
1531 dprintk("%s: userspace returned version %u\n",
1532 __func__, version);
1533 if (version < 1)
1534 version = 1;
1535 else if (version > CLD_UPCALL_VERSION)
1536 version = CLD_UPCALL_VERSION;
1537
1538 switch (version) {
1539 case 1:
1540 nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
1541 break;
1542 case 2:
1543 nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v2;
1544 break;
1545 default:
1546 break;
1547 }
1548 }
1549 out_free:
1550 free_cld_upcall(cup);
1551 out_err:
1552 if (ret)
1553 dprintk("%s: Unable to get version from userspace: %d\n",
1554 __func__, ret);
1555 return ret;
1556 }
1557
1558 static int
1559 nfsd4_cld_tracking_init(struct net *net)
1560 {
1561 int status;
1562 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1563 bool running;
1564 int retries = 10;
1565 struct crypto_shash *tfm;
1566
1567 status = nfs4_cld_state_init(net);
1568 if (status)
1569 return status;
1570
1571 status = __nfsd4_init_cld_pipe(net);
1572 if (status)
1573 goto err_shutdown;
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583 while (!(running = cld_running(nn)) && retries--)
1584 msleep(100);
1585
1586 if (!running) {
1587 status = -ETIMEDOUT;
1588 goto err_remove;
1589 }
1590 tfm = crypto_alloc_shash("sha256", 0, 0);
1591 if (IS_ERR(tfm)) {
1592 status = PTR_ERR(tfm);
1593 goto err_remove;
1594 }
1595 nn->cld_net->cn_tfm = tfm;
1596
1597 status = nfsd4_cld_get_version(nn);
1598 if (status == -EOPNOTSUPP)
1599 pr_warn("NFSD: nfsdcld GetVersion upcall failed. Please upgrade nfsdcld.\n");
1600
1601 status = nfsd4_cld_grace_start(nn);
1602 if (status) {
1603 if (status == -EOPNOTSUPP)
1604 pr_warn("NFSD: nfsdcld GraceStart upcall failed. Please upgrade nfsdcld.\n");
1605 nfs4_release_reclaim(nn);
1606 goto err_remove;
1607 } else
1608 pr_info("NFSD: Using nfsdcld client tracking operations.\n");
1609 return 0;
1610
1611 err_remove:
1612 nfsd4_remove_cld_pipe(net);
1613 err_shutdown:
1614 nfs4_cld_state_shutdown(net);
1615 return status;
1616 }
1617
1618 static void
1619 nfsd4_cld_tracking_exit(struct net *net)
1620 {
1621 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1622
1623 nfs4_release_reclaim(nn);
1624 nfsd4_remove_cld_pipe(net);
1625 nfs4_cld_state_shutdown(net);
1626 }
1627
1628
1629 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v0 = {
1630 .init = nfsd4_init_cld_pipe,
1631 .exit = nfsd4_remove_cld_pipe,
1632 .create = nfsd4_cld_create,
1633 .remove = nfsd4_cld_remove,
1634 .check = nfsd4_cld_check_v0,
1635 .grace_done = nfsd4_cld_grace_done_v0,
1636 .version = 1,
1637 .msglen = sizeof(struct cld_msg),
1638 };
1639
1640
1641 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
1642 .init = nfsd4_cld_tracking_init,
1643 .exit = nfsd4_cld_tracking_exit,
1644 .create = nfsd4_cld_create,
1645 .remove = nfsd4_cld_remove,
1646 .check = nfsd4_cld_check,
1647 .grace_done = nfsd4_cld_grace_done,
1648 .version = 1,
1649 .msglen = sizeof(struct cld_msg),
1650 };
1651
1652
1653 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2 = {
1654 .init = nfsd4_cld_tracking_init,
1655 .exit = nfsd4_cld_tracking_exit,
1656 .create = nfsd4_cld_create_v2,
1657 .remove = nfsd4_cld_remove,
1658 .check = nfsd4_cld_check_v2,
1659 .grace_done = nfsd4_cld_grace_done,
1660 .version = 2,
1661 .msglen = sizeof(struct cld_msg_v2),
1662 };
1663
1664
1665 static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack";
1666 module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog),
1667 S_IRUGO|S_IWUSR);
1668 MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program");
1669
1670 static bool cltrack_legacy_disable;
1671 module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR);
1672 MODULE_PARM_DESC(cltrack_legacy_disable,
1673 "Disable legacy recoverydir conversion. Default: false");
1674
1675 #define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR="
1676 #define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR="
1677 #define HAS_SESSION_ENV_PREFIX "NFSDCLTRACK_CLIENT_HAS_SESSION="
1678 #define GRACE_START_ENV_PREFIX "NFSDCLTRACK_GRACE_START="
1679
1680 static char *
1681 nfsd4_cltrack_legacy_topdir(void)
1682 {
1683 int copied;
1684 size_t len;
1685 char *result;
1686
1687 if (cltrack_legacy_disable)
1688 return NULL;
1689
1690 len = strlen(LEGACY_TOPDIR_ENV_PREFIX) +
1691 strlen(nfs4_recoverydir()) + 1;
1692
1693 result = kmalloc(len, GFP_KERNEL);
1694 if (!result)
1695 return result;
1696
1697 copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s",
1698 nfs4_recoverydir());
1699 if (copied >= len) {
1700
1701 kfree(result);
1702 return NULL;
1703 }
1704
1705 return result;
1706 }
1707
1708 static char *
1709 nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name)
1710 {
1711 int copied;
1712 size_t len;
1713 char *result;
1714
1715 if (cltrack_legacy_disable)
1716 return NULL;
1717
1718
1719 len = strlen(LEGACY_RECDIR_ENV_PREFIX) +
1720 strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN;
1721
1722 result = kmalloc(len, GFP_KERNEL);
1723 if (!result)
1724 return result;
1725
1726 copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/",
1727 nfs4_recoverydir());
1728 if (copied > (len - HEXDIR_LEN)) {
1729
1730 kfree(result);
1731 return NULL;
1732 }
1733
1734 copied = nfs4_make_rec_clidname(result + copied, name);
1735 if (copied) {
1736 kfree(result);
1737 return NULL;
1738 }
1739
1740 return result;
1741 }
1742
1743 static char *
1744 nfsd4_cltrack_client_has_session(struct nfs4_client *clp)
1745 {
1746 int copied;
1747 size_t len;
1748 char *result;
1749
1750
1751 len = strlen(HAS_SESSION_ENV_PREFIX) + 1 + 1;
1752
1753 result = kmalloc(len, GFP_KERNEL);
1754 if (!result)
1755 return result;
1756
1757 copied = snprintf(result, len, HAS_SESSION_ENV_PREFIX "%c",
1758 clp->cl_minorversion ? 'Y' : 'N');
1759 if (copied >= len) {
1760
1761 kfree(result);
1762 return NULL;
1763 }
1764
1765 return result;
1766 }
1767
1768 static char *
1769 nfsd4_cltrack_grace_start(time64_t grace_start)
1770 {
1771 int copied;
1772 size_t len;
1773 char *result;
1774
1775
1776 len = strlen(GRACE_START_ENV_PREFIX) + 22 + 1;
1777
1778 result = kmalloc(len, GFP_KERNEL);
1779 if (!result)
1780 return result;
1781
1782 copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%lld",
1783 grace_start);
1784 if (copied >= len) {
1785
1786 kfree(result);
1787 return NULL;
1788 }
1789
1790 return result;
1791 }
1792
1793 static int
1794 nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
1795 {
1796 char *envp[3];
1797 char *argv[4];
1798 int ret;
1799
1800 if (unlikely(!cltrack_prog[0])) {
1801 dprintk("%s: cltrack_prog is disabled\n", __func__);
1802 return -EACCES;
1803 }
1804
1805 dprintk("%s: cmd: %s\n", __func__, cmd);
1806 dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)");
1807 dprintk("%s: env0: %s\n", __func__, env0 ? env0 : "(null)");
1808 dprintk("%s: env1: %s\n", __func__, env1 ? env1 : "(null)");
1809
1810 envp[0] = env0;
1811 envp[1] = env1;
1812 envp[2] = NULL;
1813
1814 argv[0] = (char *)cltrack_prog;
1815 argv[1] = cmd;
1816 argv[2] = arg;
1817 argv[3] = NULL;
1818
1819 ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
1820
1821
1822
1823
1824
1825 if (ret == -ENOENT || ret == -EACCES) {
1826 dprintk("NFSD: %s was not found or isn't executable (%d). "
1827 "Setting cltrack_prog to blank string!",
1828 cltrack_prog, ret);
1829 cltrack_prog[0] = '\0';
1830 }
1831 dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret);
1832
1833 return ret;
1834 }
1835
1836 static char *
1837 bin_to_hex_dup(const unsigned char *src, int srclen)
1838 {
1839 char *buf;
1840
1841
1842 buf = kzalloc((srclen * 2) + 1, GFP_KERNEL);
1843 if (!buf)
1844 return buf;
1845
1846 bin2hex(buf, src, srclen);
1847 return buf;
1848 }
1849
1850 static int
1851 nfsd4_umh_cltrack_init(struct net *net)
1852 {
1853 int ret;
1854 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1855 char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
1856
1857
1858 if (net != &init_net) {
1859 pr_warn("NFSD: attempt to initialize umh client tracking in a container ignored.\n");
1860 kfree(grace_start);
1861 return -EINVAL;
1862 }
1863
1864 ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL);
1865 kfree(grace_start);
1866 if (!ret)
1867 pr_info("NFSD: Using UMH upcall client tracking operations.\n");
1868 return ret;
1869 }
1870
1871 static void
1872 nfsd4_cltrack_upcall_lock(struct nfs4_client *clp)
1873 {
1874 wait_on_bit_lock(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK,
1875 TASK_UNINTERRUPTIBLE);
1876 }
1877
1878 static void
1879 nfsd4_cltrack_upcall_unlock(struct nfs4_client *clp)
1880 {
1881 smp_mb__before_atomic();
1882 clear_bit(NFSD4_CLIENT_UPCALL_LOCK, &clp->cl_flags);
1883 smp_mb__after_atomic();
1884 wake_up_bit(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK);
1885 }
1886
1887 static void
1888 nfsd4_umh_cltrack_create(struct nfs4_client *clp)
1889 {
1890 char *hexid, *has_session, *grace_start;
1891 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905 if (clp->cl_minorversion == 0 &&
1906 test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1907 return;
1908
1909 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
1910 if (!hexid) {
1911 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1912 return;
1913 }
1914
1915 has_session = nfsd4_cltrack_client_has_session(clp);
1916 grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
1917
1918 nfsd4_cltrack_upcall_lock(clp);
1919 if (!nfsd4_umh_cltrack_upcall("create", hexid, has_session, grace_start))
1920 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1921 nfsd4_cltrack_upcall_unlock(clp);
1922
1923 kfree(has_session);
1924 kfree(grace_start);
1925 kfree(hexid);
1926 }
1927
1928 static void
1929 nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
1930 {
1931 char *hexid;
1932
1933 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1934 return;
1935
1936 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
1937 if (!hexid) {
1938 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1939 return;
1940 }
1941
1942 nfsd4_cltrack_upcall_lock(clp);
1943 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags) &&
1944 nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL) == 0)
1945 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1946 nfsd4_cltrack_upcall_unlock(clp);
1947
1948 kfree(hexid);
1949 }
1950
1951 static int
1952 nfsd4_umh_cltrack_check(struct nfs4_client *clp)
1953 {
1954 int ret;
1955 char *hexid, *has_session, *legacy;
1956
1957 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1958 return 0;
1959
1960 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
1961 if (!hexid) {
1962 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1963 return -ENOMEM;
1964 }
1965
1966 has_session = nfsd4_cltrack_client_has_session(clp);
1967 legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name);
1968
1969 nfsd4_cltrack_upcall_lock(clp);
1970 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) {
1971 ret = 0;
1972 } else {
1973 ret = nfsd4_umh_cltrack_upcall("check", hexid, has_session, legacy);
1974 if (ret == 0)
1975 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1976 }
1977 nfsd4_cltrack_upcall_unlock(clp);
1978 kfree(has_session);
1979 kfree(legacy);
1980 kfree(hexid);
1981
1982 return ret;
1983 }
1984
1985 static void
1986 nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn)
1987 {
1988 char *legacy;
1989 char timestr[22];
1990
1991 sprintf(timestr, "%lld", nn->boot_time);
1992 legacy = nfsd4_cltrack_legacy_topdir();
1993 nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL);
1994 kfree(legacy);
1995 }
1996
1997 static const struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = {
1998 .init = nfsd4_umh_cltrack_init,
1999 .exit = NULL,
2000 .create = nfsd4_umh_cltrack_create,
2001 .remove = nfsd4_umh_cltrack_remove,
2002 .check = nfsd4_umh_cltrack_check,
2003 .grace_done = nfsd4_umh_cltrack_grace_done,
2004 .version = 1,
2005 .msglen = 0,
2006 };
2007
2008 int
2009 nfsd4_client_tracking_init(struct net *net)
2010 {
2011 int status;
2012 struct path path;
2013 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
2014
2015
2016 if (nn->client_tracking_ops)
2017 goto do_init;
2018
2019
2020 nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
2021 status = nn->client_tracking_ops->init(net);
2022 if (!status)
2023 return status;
2024 if (status != -ETIMEDOUT) {
2025 nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v0;
2026 status = nn->client_tracking_ops->init(net);
2027 if (!status)
2028 return status;
2029 }
2030
2031
2032
2033
2034 nn->client_tracking_ops = &nfsd4_umh_tracking_ops;
2035 status = nn->client_tracking_ops->init(net);
2036 if (!status)
2037 return status;
2038
2039
2040
2041
2042
2043 nn->client_tracking_ops = &nfsd4_legacy_tracking_ops;
2044 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
2045 if (!status) {
2046 status = d_is_dir(path.dentry);
2047 path_put(&path);
2048 if (!status) {
2049 status = -EINVAL;
2050 goto out;
2051 }
2052 }
2053
2054 do_init:
2055 status = nn->client_tracking_ops->init(net);
2056 out:
2057 if (status) {
2058 printk(KERN_WARNING "NFSD: Unable to initialize client "
2059 "recovery tracking! (%d)\n", status);
2060 nn->client_tracking_ops = NULL;
2061 }
2062 return status;
2063 }
2064
2065 void
2066 nfsd4_client_tracking_exit(struct net *net)
2067 {
2068 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
2069
2070 if (nn->client_tracking_ops) {
2071 if (nn->client_tracking_ops->exit)
2072 nn->client_tracking_ops->exit(net);
2073 nn->client_tracking_ops = NULL;
2074 }
2075 }
2076
2077 void
2078 nfsd4_client_record_create(struct nfs4_client *clp)
2079 {
2080 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
2081
2082 if (nn->client_tracking_ops)
2083 nn->client_tracking_ops->create(clp);
2084 }
2085
2086 void
2087 nfsd4_client_record_remove(struct nfs4_client *clp)
2088 {
2089 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
2090
2091 if (nn->client_tracking_ops)
2092 nn->client_tracking_ops->remove(clp);
2093 }
2094
2095 int
2096 nfsd4_client_record_check(struct nfs4_client *clp)
2097 {
2098 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
2099
2100 if (nn->client_tracking_ops)
2101 return nn->client_tracking_ops->check(clp);
2102
2103 return -EOPNOTSUPP;
2104 }
2105
2106 void
2107 nfsd4_record_grace_done(struct nfsd_net *nn)
2108 {
2109 if (nn->client_tracking_ops)
2110 nn->client_tracking_ops->grace_done(nn);
2111 }
2112
2113 static int
2114 rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr)
2115 {
2116 struct super_block *sb = ptr;
2117 struct net *net = sb->s_fs_info;
2118 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
2119 struct cld_net *cn = nn->cld_net;
2120 struct dentry *dentry;
2121 int ret = 0;
2122
2123 if (!try_module_get(THIS_MODULE))
2124 return 0;
2125
2126 if (!cn) {
2127 module_put(THIS_MODULE);
2128 return 0;
2129 }
2130
2131 switch (event) {
2132 case RPC_PIPEFS_MOUNT:
2133 dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe);
2134 if (IS_ERR(dentry)) {
2135 ret = PTR_ERR(dentry);
2136 break;
2137 }
2138 cn->cn_pipe->dentry = dentry;
2139 break;
2140 case RPC_PIPEFS_UMOUNT:
2141 if (cn->cn_pipe->dentry)
2142 nfsd4_cld_unregister_sb(cn->cn_pipe);
2143 break;
2144 default:
2145 ret = -ENOTSUPP;
2146 break;
2147 }
2148 module_put(THIS_MODULE);
2149 return ret;
2150 }
2151
2152 static struct notifier_block nfsd4_cld_block = {
2153 .notifier_call = rpc_pipefs_event,
2154 };
2155
2156 int
2157 register_cld_notifier(void)
2158 {
2159 WARN_ON(!nfsd_net_id);
2160 return rpc_pipefs_notifier_register(&nfsd4_cld_block);
2161 }
2162
2163 void
2164 unregister_cld_notifier(void)
2165 {
2166 rpc_pipefs_notifier_unregister(&nfsd4_cld_block);
2167 }