Re: [PATCH 1/3] Add network context to struct nfs_client and makeNFSv3 use it.

From: Serge E. Hallyn
Date: Mon Apr 04 2011 - 22:52:37 EST


Quoting Rob Landley (rlandley@xxxxxxxxxxxxx):
> From: Rob Landley <rlandley@xxxxxxxxxxxxx>
>
> This patch:
>
> Adds struct net *cl_net to struct nfs_client.
> Intializes it from mount process context.
> Copies it down through nfs_client_initdata and similar.
> Replaces existing init_net uses with cl_net.
> Adds net_eq() checks to nfs_match_client() and nfs_compare_super_address().
>
> Remount copies the existing network context rather than any associated with
> the new mount process. NFSv4 is still using init_net. Reference counting
> for struct net follows the struct nfs_client object lifetimes (pinned by
> task context outside of that).
>
> Signed-off-by: Rob Landley <rlandley@xxxxxxxxxxxxx>

Sorry for the delay. Took me two long readings to feel like I've got
it.

Acked-by: Serge Hallyn <serge.hallyn@xxxxxxxxxx>

Do you have any testcases coded up for this?

thanks,
-serge

> ---
>
> fs/nfs/client.c | 13 ++++++++++++-
> fs/nfs/internal.h | 2 ++
> fs/nfs/mount_clnt.c | 4 ++--
> fs/nfs/super.c | 15 +++++++++++++++
> include/linux/nfs_fs_sb.h | 1 +
> 5 files changed, 32 insertions(+), 3 deletions(-)
>
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index 139be96..99bfaa6 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -130,6 +130,7 @@ struct rpc_program nfsacl_program = {
>
> struct nfs_client_initdata {
> const char *hostname;
> + struct net *net;
> const struct sockaddr *addr;
> size_t addrlen;
> const struct nfs_rpc_ops *rpc_ops;
> @@ -157,6 +158,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
> atomic_set(&clp->cl_count, 1);
> clp->cl_cons_state = NFS_CS_INITING;
>
> + clp->cl_net = get_net(cl_init->net);
> memcpy(&clp->cl_addr, cl_init->addr, cl_init->addrlen);
> clp->cl_addrlen = cl_init->addrlen;
>
> @@ -196,6 +198,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
> return clp;
>
> error_cleanup:
> + put_net(clp->cl_net);
> kfree(clp);
> error_0:
> return ERR_PTR(err);
> @@ -290,6 +293,9 @@ static void nfs_free_client(struct nfs_client *clp)
> if (clp->cl_machine_cred != NULL)
> put_rpccred(clp->cl_machine_cred);
>
> + if (clp->cl_net)
> + put_net(clp->cl_net);
> +
> kfree(clp->cl_hostname);
> kfree(clp);
>
> @@ -473,6 +479,8 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
> if (clp->cl_minorversion != data->minorversion)
> continue;
> /* Match the full socket address */
> + if (!net_eq(clp->cl_net, data->net))
> + continue;
> if (!nfs_sockaddr_cmp(sap, clap))
> continue;
>
> @@ -636,7 +644,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
> {
> struct rpc_clnt *clnt = NULL;
> struct rpc_create_args args = {
> - .net = &init_net,
> + .net = clp->cl_net,
> .protocol = clp->cl_proto,
> .address = (struct sockaddr *)&clp->cl_addr,
> .addrsize = clp->cl_addrlen,
> @@ -821,6 +829,7 @@ static int nfs_init_server(struct nfs_server *server,
> {
> struct nfs_client_initdata cl_init = {
> .hostname = data->nfs_server.hostname,
> + .net = data->net,
> .addr = (const struct sockaddr *)&data->nfs_server.address,
> .addrlen = data->nfs_server.addrlen,
> .rpc_ops = &nfs_v2_clientops,
> @@ -1386,6 +1395,7 @@ static int nfs4_set_client(struct nfs_server *server,
> {
> struct nfs_client_initdata cl_init = {
> .hostname = hostname,
> + .net = &init_net,
> .addr = addr,
> .addrlen = addrlen,
> .rpc_ops = &nfs_v4_clientops,
> @@ -1438,6 +1448,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
> {
> struct nfs_client_initdata cl_init = {
> .addr = ds_addr,
> + .net = &init_net,
> .addrlen = ds_addrlen,
> .rpc_ops = &nfs_v4_clientops,
> .proto = ds_proto,
> diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
> index 72e0bdd..006ab1a 100644
> --- a/fs/nfs/internal.h
> +++ b/fs/nfs/internal.h
> @@ -86,6 +86,7 @@ struct nfs_parsed_mount_data {
> unsigned int version;
> unsigned int minorversion;
> char *fscache_uniq;
> + struct net *net;
>
> struct {
> struct sockaddr_storage address;
> @@ -111,6 +112,7 @@ struct nfs_parsed_mount_data {
> /* mount_clnt.c */
> struct nfs_mount_request {
> struct sockaddr *sap;
> + struct net *net;
> size_t salen;
> char *hostname;
> char *dirpath;
> diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
> index d4c2d6b..4fbe3a8 100644
> --- a/fs/nfs/mount_clnt.c
> +++ b/fs/nfs/mount_clnt.c
> @@ -153,7 +153,7 @@ int nfs_mount(struct nfs_mount_request *info)
> .rpc_resp = &result,
> };
> struct rpc_create_args args = {
> - .net = &init_net,
> + .net = info->net,
> .protocol = info->protocol,
> .address = info->sap,
> .addrsize = info->salen,
> @@ -225,7 +225,7 @@ void nfs_umount(const struct nfs_mount_request *info)
> .to_retries = 2,
> };
> struct rpc_create_args args = {
> - .net = &init_net,
> + .net = info->net,
> .protocol = IPPROTO_UDP,
> .address = info->sap,
> .addrsize = info->salen,
> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
> index 2b8e9a5..b0d869f 100644
> --- a/fs/nfs/super.c
> +++ b/fs/nfs/super.c
> @@ -53,6 +53,7 @@
> #include <linux/nfs_xdr.h>
> #include <linux/magic.h>
> #include <linux/parser.h>
> +#include <linux/user_namespace.h>
>
> #include <asm/system.h>
> #include <asm/uaccess.h>
> @@ -1572,6 +1573,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
> struct nfs_mount_request request = {
> .sap = (struct sockaddr *)
> &args->mount_server.address,
> + .net = args->net,
> .dirpath = args->nfs_server.export_path,
> .protocol = args->mount_server.protocol,
> .fh = root_fh,
> @@ -1726,6 +1728,11 @@ static int nfs_validate_mount_data(void *options,
> if (data == NULL)
> goto out_no_data;
>
> + /* Grab network context from mount process. We'll increment the
> + reference count when we copy it to nfs_client->cl_net. */
> +
> + args->net = current->nsproxy->net_ns;
> +
> switch (data->version) {
> case 1:
> data->namlen = 0;
> @@ -1971,6 +1978,9 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
> memcpy(&data->nfs_server.address, &nfss->nfs_client->cl_addr,
> data->nfs_server.addrlen);
>
> + /* Use original mount's network context, not remount process's */
> + data->net = nfss->nfs_client->cl_net;
> +
> /* overwrite those values with any that were specified */
> error = nfs_parse_mount_options((char *)options, data);
> if (error < 0)
> @@ -2119,6 +2129,9 @@ static int nfs_compare_super_address(struct nfs_server *server1,
> if (sap1->sa_family != sap2->sa_family)
> return 0;
>
> + if (!net_eq(server1->nfs_client->cl_net, server2->nfs_client->cl_net))
> + return 0;
> +
> switch (sap1->sa_family) {
> case AF_INET: {
> struct sockaddr_in *sin1 = (struct sockaddr_in *)sap1;
> @@ -2478,6 +2491,8 @@ static int nfs4_validate_mount_data(void *options,
> if (data == NULL)
> goto out_no_data;
>
> + args->net = &init_net;
> +
> switch (data->version) {
> case 1:
> if (data->host_addrlen > sizeof(args->nfs_server.address))
> diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
> index 216cea5..45286dc 100644
> --- a/include/linux/nfs_fs_sb.h
> +++ b/include/linux/nfs_fs_sb.h
> @@ -33,6 +33,7 @@ struct nfs_client {
> #define NFS_CS_STOP_RENEW 4 /* no more state to renew */
> #define NFS_CS_CHECK_LEASE_TIME 5 /* need to check lease time */
> struct sockaddr_storage cl_addr; /* server identifier */
> + struct net * cl_net; /* network context */
> size_t cl_addrlen;
> char * cl_hostname; /* hostname of server */
> struct list_head cl_share_link; /* link in global client list */
> _______________________________________________
> Containers mailing list
> Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx
> https://lists.linux-foundation.org/mailman/listinfo/containers
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/