nfsd: add support for upcall version 2
Version 2 upcalls will allow the nfsd to include a hash of the kerberos principal string in the Cld_Create upcall. If a principal is present in the svc_cred, then the hash will be included in the Cld_Create upcall. We attempt to use the svc_cred.cr_raw_principal (which is returned by gssproxy) first, and then fall back to using the svc_cred.cr_principal (which is returned by both gssproxy and rpc.svcgssd). Upon a subsequent restart, the hash will be returned in the Cld_Gracestart downcall and stored in the reclaim_str_hashtbl so it can be used when handling reclaim opens. Signed-off-by: Scott Mayhew <smayhew@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
11a60d1592
commit
6ee95d1c89
@ -64,6 +64,7 @@ struct nfsd4_client_tracking_ops {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops;
|
static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops;
|
||||||
|
static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2;
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
|
static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
|
||||||
@ -177,6 +178,7 @@ __nfsd4_create_reclaim_record_grace(struct nfs4_client *clp,
|
|||||||
const char *dname, int len, struct nfsd_net *nn)
|
const char *dname, int len, struct nfsd_net *nn)
|
||||||
{
|
{
|
||||||
struct xdr_netobj name;
|
struct xdr_netobj name;
|
||||||
|
struct xdr_netobj princhash = { .len = 0, .data = NULL };
|
||||||
struct nfs4_client_reclaim *crp;
|
struct nfs4_client_reclaim *crp;
|
||||||
|
|
||||||
name.data = kmemdup(dname, len, GFP_KERNEL);
|
name.data = kmemdup(dname, len, GFP_KERNEL);
|
||||||
@ -186,7 +188,7 @@ __nfsd4_create_reclaim_record_grace(struct nfs4_client *clp,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
name.len = len;
|
name.len = len;
|
||||||
crp = nfs4_client_to_reclaim(name, nn);
|
crp = nfs4_client_to_reclaim(name, princhash, nn);
|
||||||
if (!crp) {
|
if (!crp) {
|
||||||
kfree(name.data);
|
kfree(name.data);
|
||||||
return;
|
return;
|
||||||
@ -486,6 +488,7 @@ static int
|
|||||||
load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
|
load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
|
||||||
{
|
{
|
||||||
struct xdr_netobj name;
|
struct xdr_netobj name;
|
||||||
|
struct xdr_netobj princhash = { .len = 0, .data = NULL };
|
||||||
|
|
||||||
if (child->d_name.len != HEXDIR_LEN - 1) {
|
if (child->d_name.len != HEXDIR_LEN - 1) {
|
||||||
printk("%s: illegal name %pd in recovery directory\n",
|
printk("%s: illegal name %pd in recovery directory\n",
|
||||||
@ -500,7 +503,7 @@ load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
name.len = HEXDIR_LEN;
|
name.len = HEXDIR_LEN;
|
||||||
if (!nfs4_client_to_reclaim(name, nn))
|
if (!nfs4_client_to_reclaim(name, princhash, nn))
|
||||||
kfree(name.data);
|
kfree(name.data);
|
||||||
out:
|
out:
|
||||||
return 0;
|
return 0;
|
||||||
@ -737,6 +740,7 @@ struct cld_net {
|
|||||||
struct list_head cn_list;
|
struct list_head cn_list;
|
||||||
unsigned int cn_xid;
|
unsigned int cn_xid;
|
||||||
bool cn_has_legacy;
|
bool cn_has_legacy;
|
||||||
|
struct crypto_shash *cn_tfm;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cld_upcall {
|
struct cld_upcall {
|
||||||
@ -746,6 +750,7 @@ struct cld_upcall {
|
|||||||
union {
|
union {
|
||||||
struct cld_msg_hdr cu_hdr;
|
struct cld_msg_hdr cu_hdr;
|
||||||
struct cld_msg cu_msg;
|
struct cld_msg cu_msg;
|
||||||
|
struct cld_msg_v2 cu_msg_v2;
|
||||||
} cu_u;
|
} cu_u;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -792,11 +797,11 @@ cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
__cld_pipe_inprogress_downcall(const struct cld_msg __user *cmsg,
|
__cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,
|
||||||
struct nfsd_net *nn)
|
struct nfsd_net *nn)
|
||||||
{
|
{
|
||||||
uint8_t cmd;
|
uint8_t cmd, princhashlen;
|
||||||
struct xdr_netobj name;
|
struct xdr_netobj name, princhash = { .len = 0, .data = NULL };
|
||||||
uint16_t namelen;
|
uint16_t namelen;
|
||||||
struct cld_net *cn = nn->cld_net;
|
struct cld_net *cn = nn->cld_net;
|
||||||
|
|
||||||
@ -805,19 +810,45 @@ __cld_pipe_inprogress_downcall(const struct cld_msg __user *cmsg,
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
if (cmd == Cld_GraceStart) {
|
if (cmd == Cld_GraceStart) {
|
||||||
if (get_user(namelen, &cmsg->cm_u.cm_name.cn_len))
|
if (nn->client_tracking_ops->version >= 2) {
|
||||||
return -EFAULT;
|
const struct cld_clntinfo __user *ci;
|
||||||
name.data = memdup_user(&cmsg->cm_u.cm_name.cn_id, namelen);
|
|
||||||
if (IS_ERR_OR_NULL(name.data))
|
ci = &cmsg->cm_u.cm_clntinfo;
|
||||||
return -EFAULT;
|
if (get_user(namelen, &ci->cc_name.cn_len))
|
||||||
name.len = namelen;
|
return -EFAULT;
|
||||||
|
name.data = memdup_user(&ci->cc_name.cn_id, namelen);
|
||||||
|
if (IS_ERR_OR_NULL(name.data))
|
||||||
|
return -EFAULT;
|
||||||
|
name.len = namelen;
|
||||||
|
get_user(princhashlen, &ci->cc_princhash.cp_len);
|
||||||
|
if (princhashlen > 0) {
|
||||||
|
princhash.data = memdup_user(
|
||||||
|
&ci->cc_princhash.cp_data,
|
||||||
|
princhashlen);
|
||||||
|
if (IS_ERR_OR_NULL(princhash.data))
|
||||||
|
return -EFAULT;
|
||||||
|
princhash.len = princhashlen;
|
||||||
|
} else
|
||||||
|
princhash.len = 0;
|
||||||
|
} else {
|
||||||
|
const struct cld_name __user *cnm;
|
||||||
|
|
||||||
|
cnm = &cmsg->cm_u.cm_name;
|
||||||
|
if (get_user(namelen, &cnm->cn_len))
|
||||||
|
return -EFAULT;
|
||||||
|
name.data = memdup_user(&cnm->cn_id, namelen);
|
||||||
|
if (IS_ERR_OR_NULL(name.data))
|
||||||
|
return -EFAULT;
|
||||||
|
name.len = namelen;
|
||||||
|
}
|
||||||
if (name.len > 5 && memcmp(name.data, "hash:", 5) == 0) {
|
if (name.len > 5 && memcmp(name.data, "hash:", 5) == 0) {
|
||||||
name.len = name.len - 5;
|
name.len = name.len - 5;
|
||||||
memmove(name.data, name.data + 5, name.len);
|
memmove(name.data, name.data + 5, name.len);
|
||||||
cn->cn_has_legacy = true;
|
cn->cn_has_legacy = true;
|
||||||
}
|
}
|
||||||
if (!nfs4_client_to_reclaim(name, nn)) {
|
if (!nfs4_client_to_reclaim(name, princhash, nn)) {
|
||||||
kfree(name.data);
|
kfree(name.data);
|
||||||
|
kfree(princhash.data);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
return nn->client_tracking_ops->msglen;
|
return nn->client_tracking_ops->msglen;
|
||||||
@ -830,7 +861,7 @@ cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
|
|||||||
{
|
{
|
||||||
struct cld_upcall *tmp, *cup;
|
struct cld_upcall *tmp, *cup;
|
||||||
struct cld_msg_hdr __user *hdr = (struct cld_msg_hdr __user *)src;
|
struct cld_msg_hdr __user *hdr = (struct cld_msg_hdr __user *)src;
|
||||||
struct cld_msg __user *cmsg = (struct cld_msg __user *)src;
|
struct cld_msg_v2 __user *cmsg = (struct cld_msg_v2 __user *)src;
|
||||||
uint32_t xid;
|
uint32_t xid;
|
||||||
struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info,
|
struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info,
|
||||||
nfsd_net_id);
|
nfsd_net_id);
|
||||||
@ -881,7 +912,7 @@ cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
|
|||||||
if (status == -EINPROGRESS)
|
if (status == -EINPROGRESS)
|
||||||
return __cld_pipe_inprogress_downcall(cmsg, nn);
|
return __cld_pipe_inprogress_downcall(cmsg, nn);
|
||||||
|
|
||||||
if (copy_from_user(&cup->cu_u.cu_msg, src, mlen) != 0)
|
if (copy_from_user(&cup->cu_u.cu_msg_v2, src, mlen) != 0)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
complete(&cup->cu_done);
|
complete(&cup->cu_done);
|
||||||
@ -1019,6 +1050,8 @@ nfsd4_remove_cld_pipe(struct net *net)
|
|||||||
|
|
||||||
nfsd4_cld_unregister_net(net, cn->cn_pipe);
|
nfsd4_cld_unregister_net(net, cn->cn_pipe);
|
||||||
rpc_destroy_pipe_data(cn->cn_pipe);
|
rpc_destroy_pipe_data(cn->cn_pipe);
|
||||||
|
if (cn->cn_tfm)
|
||||||
|
crypto_free_shash(cn->cn_tfm);
|
||||||
kfree(nn->cld_net);
|
kfree(nn->cld_net);
|
||||||
nn->cld_net = NULL;
|
nn->cld_net = NULL;
|
||||||
}
|
}
|
||||||
@ -1103,6 +1136,75 @@ out_err:
|
|||||||
"record on stable storage: %d\n", ret);
|
"record on stable storage: %d\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ask daemon to create a new record */
|
||||||
|
static void
|
||||||
|
nfsd4_cld_create_v2(struct nfs4_client *clp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct cld_upcall *cup;
|
||||||
|
struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
|
||||||
|
struct cld_net *cn = nn->cld_net;
|
||||||
|
struct cld_msg_v2 *cmsg;
|
||||||
|
struct crypto_shash *tfm = cn->cn_tfm;
|
||||||
|
struct xdr_netobj cksum;
|
||||||
|
char *principal = NULL;
|
||||||
|
SHASH_DESC_ON_STACK(desc, tfm);
|
||||||
|
|
||||||
|
/* Don't upcall if it's already stored */
|
||||||
|
if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cup = alloc_cld_upcall(nn);
|
||||||
|
if (!cup) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsg = &cup->cu_u.cu_msg_v2;
|
||||||
|
cmsg->cm_cmd = Cld_Create;
|
||||||
|
cmsg->cm_u.cm_clntinfo.cc_name.cn_len = clp->cl_name.len;
|
||||||
|
memcpy(cmsg->cm_u.cm_clntinfo.cc_name.cn_id, clp->cl_name.data,
|
||||||
|
clp->cl_name.len);
|
||||||
|
if (clp->cl_cred.cr_raw_principal)
|
||||||
|
principal = clp->cl_cred.cr_raw_principal;
|
||||||
|
else if (clp->cl_cred.cr_principal)
|
||||||
|
principal = clp->cl_cred.cr_principal;
|
||||||
|
if (principal) {
|
||||||
|
desc->tfm = tfm;
|
||||||
|
cksum.len = crypto_shash_digestsize(tfm);
|
||||||
|
cksum.data = kmalloc(cksum.len, GFP_KERNEL);
|
||||||
|
if (cksum.data == NULL) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = crypto_shash_digest(desc, principal, strlen(principal),
|
||||||
|
cksum.data);
|
||||||
|
shash_desc_zero(desc);
|
||||||
|
if (ret) {
|
||||||
|
kfree(cksum.data);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = cksum.len;
|
||||||
|
memcpy(cmsg->cm_u.cm_clntinfo.cc_princhash.cp_data,
|
||||||
|
cksum.data, cksum.len);
|
||||||
|
kfree(cksum.data);
|
||||||
|
} else
|
||||||
|
cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = 0;
|
||||||
|
|
||||||
|
ret = cld_pipe_upcall(cn->cn_pipe, cmsg);
|
||||||
|
if (!ret) {
|
||||||
|
ret = cmsg->cm_status;
|
||||||
|
set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
free_cld_upcall(cup);
|
||||||
|
out_err:
|
||||||
|
if (ret)
|
||||||
|
pr_err("NFSD: Unable to create client record on stable storage: %d\n",
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
|
||||||
/* Ask daemon to create a new record */
|
/* Ask daemon to create a new record */
|
||||||
static void
|
static void
|
||||||
nfsd4_cld_remove(struct nfs4_client *clp)
|
nfsd4_cld_remove(struct nfs4_client *clp)
|
||||||
@ -1229,6 +1331,79 @@ found:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nfsd4_cld_check_v2(struct nfs4_client *clp)
|
||||||
|
{
|
||||||
|
struct nfs4_client_reclaim *crp;
|
||||||
|
struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
|
||||||
|
struct cld_net *cn = nn->cld_net;
|
||||||
|
int status;
|
||||||
|
char dname[HEXDIR_LEN];
|
||||||
|
struct xdr_netobj name;
|
||||||
|
struct crypto_shash *tfm = cn->cn_tfm;
|
||||||
|
struct xdr_netobj cksum;
|
||||||
|
char *principal = NULL;
|
||||||
|
SHASH_DESC_ON_STACK(desc, tfm);
|
||||||
|
|
||||||
|
/* did we already find that this client is stable? */
|
||||||
|
if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* look for it in the reclaim hashtable otherwise */
|
||||||
|
crp = nfsd4_find_reclaim_client(clp->cl_name, nn);
|
||||||
|
if (crp)
|
||||||
|
goto found;
|
||||||
|
|
||||||
|
if (cn->cn_has_legacy) {
|
||||||
|
status = nfs4_make_rec_clidname(dname, &clp->cl_name);
|
||||||
|
if (status)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
|
||||||
|
if (!name.data) {
|
||||||
|
dprintk("%s: failed to allocate memory for name.data\n",
|
||||||
|
__func__);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
name.len = HEXDIR_LEN;
|
||||||
|
crp = nfsd4_find_reclaim_client(name, nn);
|
||||||
|
kfree(name.data);
|
||||||
|
if (crp)
|
||||||
|
goto found;
|
||||||
|
|
||||||
|
}
|
||||||
|
return -ENOENT;
|
||||||
|
found:
|
||||||
|
if (crp->cr_princhash.len) {
|
||||||
|
if (clp->cl_cred.cr_raw_principal)
|
||||||
|
principal = clp->cl_cred.cr_raw_principal;
|
||||||
|
else if (clp->cl_cred.cr_principal)
|
||||||
|
principal = clp->cl_cred.cr_principal;
|
||||||
|
if (principal == NULL)
|
||||||
|
return -ENOENT;
|
||||||
|
desc->tfm = tfm;
|
||||||
|
cksum.len = crypto_shash_digestsize(tfm);
|
||||||
|
cksum.data = kmalloc(cksum.len, GFP_KERNEL);
|
||||||
|
if (cksum.data == NULL)
|
||||||
|
return -ENOENT;
|
||||||
|
status = crypto_shash_digest(desc, principal, strlen(principal),
|
||||||
|
cksum.data);
|
||||||
|
shash_desc_zero(desc);
|
||||||
|
if (status) {
|
||||||
|
kfree(cksum.data);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
if (memcmp(crp->cr_princhash.data, cksum.data,
|
||||||
|
crp->cr_princhash.len)) {
|
||||||
|
kfree(cksum.data);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
kfree(cksum.data);
|
||||||
|
}
|
||||||
|
crp->cr_clp = clp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nfsd4_cld_grace_start(struct nfsd_net *nn)
|
nfsd4_cld_grace_start(struct nfsd_net *nn)
|
||||||
{
|
{
|
||||||
@ -1380,6 +1555,9 @@ nfsd4_cld_get_version(struct nfsd_net *nn)
|
|||||||
case 1:
|
case 1:
|
||||||
nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
|
nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
|
nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v2;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1408,6 +1586,11 @@ nfsd4_cld_tracking_init(struct net *net)
|
|||||||
status = __nfsd4_init_cld_pipe(net);
|
status = __nfsd4_init_cld_pipe(net);
|
||||||
if (status)
|
if (status)
|
||||||
goto err_shutdown;
|
goto err_shutdown;
|
||||||
|
nn->cld_net->cn_tfm = crypto_alloc_shash("sha256", 0, 0);
|
||||||
|
if (IS_ERR(nn->cld_net->cn_tfm)) {
|
||||||
|
status = PTR_ERR(nn->cld_net->cn_tfm);
|
||||||
|
goto err_remove;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rpc pipe upcalls take 30 seconds to time out, so we don't want to
|
* rpc pipe upcalls take 30 seconds to time out, so we don't want to
|
||||||
@ -1480,6 +1663,18 @@ static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
|
|||||||
.msglen = sizeof(struct cld_msg),
|
.msglen = sizeof(struct cld_msg),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* v2 create/check ops include the principal, if available */
|
||||||
|
static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2 = {
|
||||||
|
.init = nfsd4_cld_tracking_init,
|
||||||
|
.exit = nfsd4_cld_tracking_exit,
|
||||||
|
.create = nfsd4_cld_create_v2,
|
||||||
|
.remove = nfsd4_cld_remove,
|
||||||
|
.check = nfsd4_cld_check_v2,
|
||||||
|
.grace_done = nfsd4_cld_grace_done,
|
||||||
|
.version = 2,
|
||||||
|
.msglen = sizeof(struct cld_msg_v2),
|
||||||
|
};
|
||||||
|
|
||||||
/* upcall via usermodehelper */
|
/* upcall via usermodehelper */
|
||||||
static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack";
|
static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack";
|
||||||
module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog),
|
module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog),
|
||||||
|
@ -6887,7 +6887,8 @@ nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn)
|
|||||||
* will be freed in nfs4_remove_reclaim_record in the normal case).
|
* will be freed in nfs4_remove_reclaim_record in the normal case).
|
||||||
*/
|
*/
|
||||||
struct nfs4_client_reclaim *
|
struct nfs4_client_reclaim *
|
||||||
nfs4_client_to_reclaim(struct xdr_netobj name, struct nfsd_net *nn)
|
nfs4_client_to_reclaim(struct xdr_netobj name, struct xdr_netobj princhash,
|
||||||
|
struct nfsd_net *nn)
|
||||||
{
|
{
|
||||||
unsigned int strhashval;
|
unsigned int strhashval;
|
||||||
struct nfs4_client_reclaim *crp;
|
struct nfs4_client_reclaim *crp;
|
||||||
@ -6900,6 +6901,8 @@ nfs4_client_to_reclaim(struct xdr_netobj name, struct nfsd_net *nn)
|
|||||||
list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]);
|
list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]);
|
||||||
crp->cr_name.data = name.data;
|
crp->cr_name.data = name.data;
|
||||||
crp->cr_name.len = name.len;
|
crp->cr_name.len = name.len;
|
||||||
|
crp->cr_princhash.data = princhash.data;
|
||||||
|
crp->cr_princhash.len = princhash.len;
|
||||||
crp->cr_clp = NULL;
|
crp->cr_clp = NULL;
|
||||||
nn->reclaim_str_hashtbl_size++;
|
nn->reclaim_str_hashtbl_size++;
|
||||||
}
|
}
|
||||||
@ -6911,6 +6914,7 @@ nfs4_remove_reclaim_record(struct nfs4_client_reclaim *crp, struct nfsd_net *nn)
|
|||||||
{
|
{
|
||||||
list_del(&crp->cr_strhash);
|
list_del(&crp->cr_strhash);
|
||||||
kfree(crp->cr_name.data);
|
kfree(crp->cr_name.data);
|
||||||
|
kfree(crp->cr_princhash.data);
|
||||||
kfree(crp);
|
kfree(crp);
|
||||||
nn->reclaim_str_hashtbl_size--;
|
nn->reclaim_str_hashtbl_size--;
|
||||||
}
|
}
|
||||||
|
@ -378,6 +378,7 @@ struct nfs4_client_reclaim {
|
|||||||
struct list_head cr_strhash; /* hash by cr_name */
|
struct list_head cr_strhash; /* hash by cr_name */
|
||||||
struct nfs4_client *cr_clp; /* pointer to associated clp */
|
struct nfs4_client *cr_clp; /* pointer to associated clp */
|
||||||
struct xdr_netobj cr_name; /* recovery dir name */
|
struct xdr_netobj cr_name; /* recovery dir name */
|
||||||
|
struct xdr_netobj cr_princhash;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A reasonable value for REPLAY_ISIZE was estimated as follows:
|
/* A reasonable value for REPLAY_ISIZE was estimated as follows:
|
||||||
@ -645,7 +646,7 @@ extern void nfsd4_shutdown_callback(struct nfs4_client *);
|
|||||||
extern void nfsd4_shutdown_copy(struct nfs4_client *clp);
|
extern void nfsd4_shutdown_copy(struct nfs4_client *clp);
|
||||||
extern void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp);
|
extern void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp);
|
||||||
extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name,
|
extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name,
|
||||||
struct nfsd_net *nn);
|
struct xdr_netobj princhash, struct nfsd_net *nn);
|
||||||
extern bool nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn);
|
extern bool nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn);
|
||||||
|
|
||||||
struct nfs4_file *find_file(struct knfsd_fh *fh);
|
struct nfs4_file *find_file(struct knfsd_fh *fh);
|
||||||
|
@ -26,11 +26,15 @@
|
|||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
/* latest upcall version available */
|
/* latest upcall version available */
|
||||||
#define CLD_UPCALL_VERSION 1
|
#define CLD_UPCALL_VERSION 2
|
||||||
|
|
||||||
/* defined by RFC3530 */
|
/* defined by RFC3530 */
|
||||||
#define NFS4_OPAQUE_LIMIT 1024
|
#define NFS4_OPAQUE_LIMIT 1024
|
||||||
|
|
||||||
|
#ifndef SHA256_DIGEST_SIZE
|
||||||
|
#define SHA256_DIGEST_SIZE 32
|
||||||
|
#endif
|
||||||
|
|
||||||
enum cld_command {
|
enum cld_command {
|
||||||
Cld_Create, /* create a record for this cm_id */
|
Cld_Create, /* create a record for this cm_id */
|
||||||
Cld_Remove, /* remove record of this cm_id */
|
Cld_Remove, /* remove record of this cm_id */
|
||||||
@ -46,6 +50,17 @@ struct cld_name {
|
|||||||
unsigned char cn_id[NFS4_OPAQUE_LIMIT]; /* client-provided */
|
unsigned char cn_id[NFS4_OPAQUE_LIMIT]; /* client-provided */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* sha256 hash of the kerberos principal */
|
||||||
|
struct cld_princhash {
|
||||||
|
__u8 cp_len; /* length of cp_data */
|
||||||
|
unsigned char cp_data[SHA256_DIGEST_SIZE]; /* hash of principal */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct cld_clntinfo {
|
||||||
|
struct cld_name cc_name;
|
||||||
|
struct cld_princhash cc_princhash;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* message struct for communication with userspace */
|
/* message struct for communication with userspace */
|
||||||
struct cld_msg {
|
struct cld_msg {
|
||||||
__u8 cm_vers; /* upcall version */
|
__u8 cm_vers; /* upcall version */
|
||||||
@ -59,6 +74,19 @@ struct cld_msg {
|
|||||||
} __attribute__((packed)) cm_u;
|
} __attribute__((packed)) cm_u;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* version 2 message can include hash of kerberos principal */
|
||||||
|
struct cld_msg_v2 {
|
||||||
|
__u8 cm_vers; /* upcall version */
|
||||||
|
__u8 cm_cmd; /* upcall command */
|
||||||
|
__s16 cm_status; /* return code */
|
||||||
|
__u32 cm_xid; /* transaction id */
|
||||||
|
union {
|
||||||
|
struct cld_name cm_name;
|
||||||
|
__u8 cm_version; /* for getting max version */
|
||||||
|
struct cld_clntinfo cm_clntinfo; /* name & princ hash */
|
||||||
|
} __attribute__((packed)) cm_u;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct cld_msg_hdr {
|
struct cld_msg_hdr {
|
||||||
__u8 cm_vers; /* upcall version */
|
__u8 cm_vers; /* upcall version */
|
||||||
__u8 cm_cmd; /* upcall command */
|
__u8 cm_cmd; /* upcall command */
|
||||||
|
Loading…
Reference in New Issue
Block a user