Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 873e3851 authored by Jeff Layton's avatar Jeff Layton Committed by Trond Myklebust
Browse files

nfs: make nfs4_init_uniform_client_string use a dynamically allocated buffer



Change the uniform client string generator to dynamically allocate the
NFSv4 client name string buffer. With this patch, we can eliminate the
buffers that are embedded within the "args" structs and simply use the
name string that is hanging off the client.

This uniform string case is a little simpler than the nonuniform since
we don't need to deal with RCU, but we do have two different cases,
depending on whether there is a uniquifier or not.

Signed-off-by: default avatarJeff Layton <jeff.layton@primarydata.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent a3192688
Loading
Loading
Loading
Loading
+77 −35
Original line number Diff line number Diff line
@@ -5007,28 +5007,78 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
	return 0;
}

static unsigned int
nfs4_init_uniform_client_string(struct nfs_client *clp,
				char *buf, size_t len)
static int
nfs4_init_uniquifier_client_string(struct nfs_client *clp)
{
	const char *nodename = clp->cl_rpcclient->cl_nodename;
	unsigned int result;
	int result;
	size_t len;
	char *str;

	len = 10 + 10 + 1 + 10 + 1 +
		strlen(nfs4_client_id_uniquifier) + 1 +
		strlen(clp->cl_rpcclient->cl_nodename) + 1;

	if (len > NFS4_OPAQUE_LIMIT + 1)
		return -EINVAL;

	/*
	 * Since this string is allocated at mount time, and held until the
	 * nfs_client is destroyed, we can use GFP_KERNEL here w/o worrying
	 * about a memory-reclaim deadlock.
	 */
	str = kmalloc(len, GFP_KERNEL);
	if (!str)
		return -ENOMEM;

	result = scnprintf(str, len, "Linux NFSv%u.%u %s/%s",
			clp->rpc_ops->version, clp->cl_minorversion,
			nfs4_client_id_uniquifier,
			clp->cl_rpcclient->cl_nodename);
	if (result >= len) {
		kfree(str);
		return -EINVAL;
	}
	clp->cl_owner_id = str;
	return 0;
}

static int
nfs4_init_uniform_client_string(struct nfs_client *clp)
{
	int result;
	size_t len;
	char *str;

	if (clp->cl_owner_id != NULL)
		return strlcpy(buf, clp->cl_owner_id, len);
		return 0;

	if (nfs4_client_id_uniquifier[0] != '\0')
		result = scnprintf(buf, len, "Linux NFSv%u.%u %s/%s",
				clp->rpc_ops->version,
				clp->cl_minorversion,
				nfs4_client_id_uniquifier,
				nodename);
	else
		result = scnprintf(buf, len, "Linux NFSv%u.%u %s",
		return nfs4_init_uniquifier_client_string(clp);

	len = 10 + 10 + 1 + 10 + 1 +
		strlen(clp->cl_rpcclient->cl_nodename) + 1;

	if (len > NFS4_OPAQUE_LIMIT + 1)
		return -EINVAL;

	/*
	 * Since this string is allocated at mount time, and held until the
	 * nfs_client is destroyed, we can use GFP_KERNEL here w/o worrying
	 * about a memory-reclaim deadlock.
	 */
	str = kmalloc(len, GFP_KERNEL);
	if (!str)
		return -ENOMEM;

	result = scnprintf(str, len, "Linux NFSv%u.%u %s",
			clp->rpc_ops->version, clp->cl_minorversion,
				nodename);
	clp->cl_owner_id = kstrdup(buf, GFP_KERNEL);
	return result;
			clp->cl_rpcclient->cl_nodename);
	if (result >= len) {
		kfree(str);
		return -EINVAL;
	}
	clp->cl_owner_id = str;
	return 0;
}

/*
@@ -5095,20 +5145,14 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,

	/* nfs_client_id4 */
	nfs4_init_boot_verifier(clp, &sc_verifier);
	if (test_bit(NFS_CS_MIGRATION, &clp->cl_flags)) {
		setclientid.sc_name_len =
				nfs4_init_uniform_client_string(clp,
						setclientid.sc_name,
						sizeof(setclientid.sc_name));
		if (!clp->cl_owner_id) {
			status = -ENOMEM;
			goto out;
		}
	} else {

	if (test_bit(NFS_CS_MIGRATION, &clp->cl_flags))
		status = nfs4_init_uniform_client_string(clp);
	else
		status = nfs4_init_nonuniform_client_string(clp);

	if (status)
		goto out;
	}

	/* cb_client4 */
	setclientid.sc_netid_len =
@@ -6882,12 +6926,10 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
	};

	nfs4_init_boot_verifier(clp, &verifier);
	args.id_len = nfs4_init_uniform_client_string(clp, args.id,
							sizeof(args.id));
	if (!clp->cl_owner_id) {
		status = -ENOMEM;

	status = nfs4_init_uniform_client_string(clp);
	if (status)
		goto out;
	}

	dprintk("NFS call  exchange_id auth=%s, '%s'\n",
		clp->cl_rpcclient->cl_auth->au_ops->au_name,
+0 −6
Original line number Diff line number Diff line
@@ -984,11 +984,8 @@ struct nfs4_readlink_res {
	struct nfs4_sequence_res	seq_res;
};

#define NFS4_SETCLIENTID_NAMELEN	(127)
struct nfs4_setclientid {
	const nfs4_verifier *		sc_verifier;
	unsigned int			sc_name_len;
	char				sc_name[NFS4_SETCLIENTID_NAMELEN + 1];
	u32				sc_prog;
	unsigned int			sc_netid_len;
	char				sc_netid[RPCBIND_MAXNETIDLEN + 1];
@@ -1142,12 +1139,9 @@ struct nfs41_state_protection {
	struct nfs4_op_map allow;
};

#define NFS4_EXCHANGE_ID_LEN	(127)
struct nfs41_exchange_id_args {
	struct nfs_client		*client;
	nfs4_verifier			*verifier;
	unsigned int 			id_len;
	char 				id[NFS4_EXCHANGE_ID_LEN];
	u32				flags;
	struct nfs41_state_protection	state_protect;
};