From patchwork Fri Mar 25 16:39:12 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Landley X-Patchwork-Id: 662861 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p2PGdbsb013944 for ; Fri, 25 Mar 2011 16:39:42 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751263Ab1CYQjd (ORCPT ); Fri, 25 Mar 2011 12:39:33 -0400 Received: from mx2.parallels.com ([64.131.90.16]:57804 "EHLO mx2.parallels.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750820Ab1CYQjc (ORCPT ); Fri, 25 Mar 2011 12:39:32 -0400 Received: from [96.31.168.206] (helo=mail.parallels.com) by mx2.parallels.com with esmtps (TLSv1:AES128-SHA:128) (Exim 4.74) (envelope-from ) id 1Q3A2e-00012v-Ge; Fri, 25 Mar 2011 12:39:17 -0400 Received: from [192.168.2.108] (24.27.19.110) by mail.parallels.com (10.255.249.32) with Microsoft SMTP Server (TLS) id 14.1.218.12; Fri, 25 Mar 2011 09:39:14 -0700 Message-ID: <4D8CC530.9050107@parallels.com> Date: Fri, 25 Mar 2011 11:39:12 -0500 From: Rob Landley User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101208 Thunderbird/3.1.7 MIME-Version: 1.0 To: , , Tim Spriggs , Trond Myklebust , Pavel Emelyanov Subject: [PATCH] NFSv2/3 containerization: add network context to nfs_client X-Originating-IP: [24.27.19.110] Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 25 Mar 2011 16:40:39 +0000 (UTC) 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 #include #include +#include #include #include @@ -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 */