[PATCH] SUNRPC: set desired file system root before connecting local transports

Subsystems: filesystems (vfs and infrastructure), kernel nfsd, sunrpc, and lockd servers, networking [general], nfs, sunrpc, and lockd clients, the rest

STALE5272d

6 messages, 2 authors, 2012-03-07 · open the first message on its own page

[PATCH] SUNRPC: set desired file system root before connecting local transports

From: Stanislav Kinsbursky <hidden>
Date: 2012-02-29 14:59:35

Today, there is a problem in connecting of local SUNRPC thansports. These
transports uses UNIX sockets and connection itself is done by rpciod workqueue.
But UNIX sockets lookup is done in context of process file system root. I.e.
all local thunsports are connecting in rpciod context.
This works nice until we will try to mount NFS from process with other root -
for example in container. This container can have it's own (nested) root and
rcpbind process, listening on it's own unix sockets. But NFS mount attempt in
this container will register new service (Lockd for example) in global rpcbind
- not containers's one.
This patch solves the problem by switching rpciod kernel thread's file system
root to right one (stored on transport) while connecting of local transports.

Signed-off-by: Stanislav Kinsbursky <redacted>

---
 fs/fs_struct.c        |    1 +
 net/sunrpc/xprtsock.c |   32 ++++++++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index 78b519c..0f984c3 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -36,6 +36,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
 	if (old_root.dentry)
 		path_put_longterm(&old_root);
 }
+EXPORT_SYMBOL_GPL(set_fs_root);
 
 /*
  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 4c8281d..c94c181 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -37,6 +37,7 @@
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/xprtsock.h>
 #include <linux/file.h>
+#include <linux/fs_struct.h>
 #ifdef CONFIG_SUNRPC_BACKCHANNEL
 #include <linux/sunrpc/bc_xprt.h>
 #endif
@@ -255,6 +256,11 @@ struct sock_xprt {
 	void			(*old_state_change)(struct sock *);
 	void			(*old_write_space)(struct sock *);
 	void			(*old_error_report)(struct sock *);
+
+	/*
+	 * Saved transport creator root. Required for local transports only.
+	 */
+	struct path		root;
 };
 
 /*
@@ -1891,6 +1897,7 @@ static void xs_local_setup_socket(struct work_struct *work)
 	struct rpc_xprt *xprt = &transport->xprt;
 	struct socket *sock;
 	int status = -EIO;
+	struct path root;
 
 	if (xprt->shutdown)
 		goto out;
@@ -1908,7 +1915,14 @@ static void xs_local_setup_socket(struct work_struct *work)
 	dprintk("RPC:       worker connecting xprt %p via AF_LOCAL to %s\n",
 			xprt, xprt->address_strings[RPC_DISPLAY_ADDR]);
 
+	get_fs_root(current->fs, &root);
+	set_fs_root(current->fs, &transport->root);
+
 	status = xs_local_finish_connecting(xprt, sock);
+
+	set_fs_root(current->fs, &root);
+	path_put(&root);
+
 	switch (status) {
 	case 0:
 		dprintk("RPC:       xprt %p connected to %s\n",
@@ -2213,6 +2227,18 @@ static void xs_connect(struct rpc_task *task)
 	}
 }
 
+static void xs_local_destroy(struct rpc_xprt *xprt)
+{
+	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+	struct path root = transport->root;
+
+	dprintk("RPC:       xs_local_destroy xprt %p\n", xprt);
+
+	xs_destroy(xprt);
+
+	path_put(&root);
+}
+
 /**
  * xs_local_print_stats - display AF_LOCAL socket-specifc stats
  * @xprt: rpc_xprt struct containing statistics
@@ -2431,7 +2457,7 @@ static struct rpc_xprt_ops xs_local_ops = {
 	.send_request		= xs_local_send_request,
 	.set_retrans_timeout	= xprt_set_retrans_timeout_def,
 	.close			= xs_close,
-	.destroy		= xs_destroy,
+	.destroy		= xs_local_destroy,
 	.print_stats		= xs_local_print_stats,
 };
 
@@ -2606,8 +2632,10 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
 	dprintk("RPC:       set up xprt to %s via AF_LOCAL\n",
 			xprt->address_strings[RPC_DISPLAY_ADDR]);
 
-	if (try_module_get(THIS_MODULE))
+	if (try_module_get(THIS_MODULE)) {
+		get_fs_root(current->fs, &transport->root);
 		return xprt;
+	}
 	ret = ERR_PTR(-EINVAL);
 out_err:
 	xprt_free(xprt);

Re: [PATCH] SUNRPC: set desired file system root before connecting local transports

From: Myklebust, Trond <hidden>
Date: 2012-03-07 00:19:53

T24gV2VkLCAyMDEyLTAyLTI5IGF0IDE4OjU5ICswNDAwLCBTdGFuaXNsYXYgS2luc2J1cnNreSB3cm90ZToNCj4gVG9kYXksIHRoZXJlIGlzIGEgcHJvYmxlbSBpbiBjb25uZWN0aW5nIG9mIGxvY2FsIFNVTlJQQyB0aGFuc3BvcnRzLiBUaGVzZQ0KPiB0cmFuc3BvcnRzIHVzZXMgVU5JWCBzb2NrZXRzIGFuZCBjb25uZWN0aW9uIGl0c2VsZiBpcyBkb25lIGJ5IHJwY2lvZCB3b3JrcXVldWUuDQo+IEJ1dCBVTklYIHNvY2tldHMgbG9va3VwIGlzIGRvbmUgaW4gY29udGV4dCBvZiBwcm9jZXNzIGZpbGUgc3lzdGVtIHJvb3QuIEkuZS4NCj4gYWxsIGxvY2FsIHRodW5zcG9ydHMgYXJlIGNvbm5lY3RpbmcgaW4gcnBjaW9kIGNvbnRleHQuDQo+IFRoaXMgd29ya3MgbmljZSB1bnRpbCB3ZSB3aWxsIHRyeSB0byBtb3VudCBORlMgZnJvbSBwcm9jZXNzIHdpdGggb3RoZXIgcm9vdCAtDQo+IGZvciBleGFtcGxlIGluIGNvbnRhaW5lci4gVGhpcyBjb250YWluZXIgY2FuIGhhdmUgaXQncyBvd24gKG5lc3RlZCkgcm9vdCBhbmQNCj4gcmNwYmluZCBwcm9jZXNzLCBsaXN0ZW5pbmcgb24gaXQncyBvd24gdW5peCBzb2NrZXRzLiBCdXQgTkZTIG1vdW50IGF0dGVtcHQgaW4NCj4gdGhpcyBjb250YWluZXIgd2lsbCByZWdpc3RlciBuZXcgc2VydmljZSAoTG9ja2QgZm9yIGV4YW1wbGUpIGluIGdsb2JhbCBycGNiaW5kDQo+IC0gbm90IGNvbnRhaW5lcnMncyBvbmUuDQo+IFRoaXMgcGF0Y2ggc29sdmVzIHRoZSBwcm9ibGVtIGJ5IHN3aXRjaGluZyBycGNpb2Qga2VybmVsIHRocmVhZCdzIGZpbGUgc3lzdGVtDQo+IHJvb3QgdG8gcmlnaHQgb25lIChzdG9yZWQgb24gdHJhbnNwb3J0KSB3aGlsZSBjb25uZWN0aW5nIG9mIGxvY2FsIHRyYW5zcG9ydHMuDQo+IA0KPiBTaWduZWQtb2ZmLWJ5OiBTdGFuaXNsYXYgS2luc2J1cnNreSA8c2tpbnNidXJza3lAcGFyYWxsZWxzLmNvbT4NCj4gDQo+IC0tLQ0KPiAgZnMvZnNfc3RydWN0LmMgICAgICAgIHwgICAgMSArDQo+ICBuZXQvc3VucnBjL3hwcnRzb2NrLmMgfCAgIDMyICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKy0tDQo+ICAyIGZpbGVzIGNoYW5nZWQsIDMxIGluc2VydGlvbnMoKyksIDIgZGVsZXRpb25zKC0pDQo+IA0KPiBkaWZmIC0tZ2l0IGEvZnMvZnNfc3RydWN0LmMgYi9mcy9mc19zdHJ1Y3QuYw0KPiBpbmRleCA3OGI1MTljLi4wZjk4NGMzIDEwMDY0NA0KPiAtLS0gYS9mcy9mc19zdHJ1Y3QuYw0KPiArKysgYi9mcy9mc19zdHJ1Y3QuYw0KPiBAQCAtMzYsNiArMzYsNyBAQCB2b2lkIHNldF9mc19yb290KHN0cnVjdCBmc19zdHJ1Y3QgKmZzLCBzdHJ1Y3QgcGF0aCAqcGF0aCkNCj4gIAlpZiAob2xkX3Jvb3QuZGVudHJ5KQ0KPiAgCQlwYXRoX3B1dF9sb25ndGVybSgmb2xkX3Jvb3QpOw0KPiAgfQ0KPiArRVhQT1JUX1NZTUJPTF9HUEwoc2V0X2ZzX3Jvb3QpOw0KPiAgDQo+ICAvKg0KPiAgICogUmVwbGFjZSB0aGUgZnMtPntwd2RtbnQscHdkfSB3aXRoIHttbnQsZGVudHJ5fS4gUHV0IHRoZSBvbGQgdmFsdWVzLg0KPiBkaWZmIC0tZ2l0IGEvbmV0L3N1bnJwYy94cHJ0c29jay5jIGIvbmV0L3N1bnJwYy94cHJ0c29jay5jDQo+IGluZGV4IDRjODI4MWQuLmM5NGMxODEgMTAwNjQ0DQo+IC0tLSBhL25ldC9zdW5ycGMveHBydHNvY2suYw0KPiArKysgYi9uZXQvc3VucnBjL3hwcnRzb2NrLmMNCj4gQEAgLTM3LDYgKzM3LDcgQEANCj4gICNpbmNsdWRlIDxsaW51eC9zdW5ycGMvc3Zjc29jay5oPg0KPiAgI2luY2x1ZGUgPGxpbnV4L3N1bnJwYy94cHJ0c29jay5oPg0KPiAgI2luY2x1ZGUgPGxpbnV4L2ZpbGUuaD4NCj4gKyNpbmNsdWRlIDxsaW51eC9mc19zdHJ1Y3QuaD4NCj4gICNpZmRlZiBDT05GSUdfU1VOUlBDX0JBQ0tDSEFOTkVMDQo+ICAjaW5jbHVkZSA8bGludXgvc3VucnBjL2JjX3hwcnQuaD4NCj4gICNlbmRpZg0KPiBAQCAtMjU1LDYgKzI1NiwxMSBAQCBzdHJ1Y3Qgc29ja194cHJ0IHsNCj4gIAl2b2lkCQkJKCpvbGRfc3RhdGVfY2hhbmdlKShzdHJ1Y3Qgc29jayAqKTsNCj4gIAl2b2lkCQkJKCpvbGRfd3JpdGVfc3BhY2UpKHN0cnVjdCBzb2NrICopOw0KPiAgCXZvaWQJCQkoKm9sZF9lcnJvcl9yZXBvcnQpKHN0cnVjdCBzb2NrICopOw0KPiArDQo+ICsJLyoNCj4gKwkgKiBTYXZlZCB0cmFuc3BvcnQgY3JlYXRvciByb290LiBSZXF1aXJlZCBmb3IgbG9jYWwgdHJhbnNwb3J0cyBvbmx5Lg0KPiArCSAqLw0KPiArCXN0cnVjdCBwYXRoCQlyb290Ow0KPiAgfTsNCj4gIA0KPiAgLyoNCj4gQEAgLTE4OTEsNiArMTg5Nyw3IEBAIHN0YXRpYyB2b2lkIHhzX2xvY2FsX3NldHVwX3NvY2tldChzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspDQo+ICAJc3RydWN0IHJwY194cHJ0ICp4cHJ0ID0gJnRyYW5zcG9ydC0+eHBydDsNCj4gIAlzdHJ1Y3Qgc29ja2V0ICpzb2NrOw0KPiAgCWludCBzdGF0dXMgPSAtRUlPOw0KPiArCXN0cnVjdCBwYXRoIHJvb3Q7DQo+ICANCj4gIAlpZiAoeHBydC0+c2h1dGRvd24pDQo+ICAJCWdvdG8gb3V0Ow0KPiBAQCAtMTkwOCw3ICsxOTE1LDE0IEBAIHN0YXRpYyB2b2lkIHhzX2xvY2FsX3NldHVwX3NvY2tldChzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspDQo+ICAJZHByaW50aygiUlBDOiAgICAgICB3b3JrZXIgY29ubmVjdGluZyB4cHJ0ICVwIHZpYSBBRl9MT0NBTCB0byAlc1xuIiwNCj4gIAkJCXhwcnQsIHhwcnQtPmFkZHJlc3Nfc3RyaW5nc1tSUENfRElTUExBWV9BRERSXSk7DQo+ICANCj4gKwlnZXRfZnNfcm9vdChjdXJyZW50LT5mcywgJnJvb3QpOw0KPiArCXNldF9mc19yb290KGN1cnJlbnQtPmZzLCAmdHJhbnNwb3J0LT5yb290KTsNCj4gKw0KPiAgCXN0YXR1cyA9IHhzX2xvY2FsX2ZpbmlzaF9jb25uZWN0aW5nKHhwcnQsIHNvY2spOw0KPiArDQo+ICsJc2V0X2ZzX3Jvb3QoY3VycmVudC0+ZnMsICZyb290KTsNCj4gKwlwYXRoX3B1dCgmcm9vdCk7DQo+ICsNCj4gIAlzd2l0Y2ggKHN0YXR1cykgew0KPiAgCWNhc2UgMDoNCg0KSGkgU3RhbmlzbGF2LA0KDQpXaGF0IGhhcHBlbnMgaGVyZSBpZiB0aGUgbW91bnQgbmFtZXNwYWNlIG9mIHRoZSBwcm9jZXNzIHRoYXQgb3JpZ2luYWxseQ0KY3JlYXRlZCB0aGUgc29ja194cHJ0IG5vIGxvbmdlciBleGlzdHM/IFNob3VsZCB3ZSBjYXJlIGFib3V0IHRoYXQgY2FzZT8NCg0KQ2hlZXJzDQogIFRyb25kDQoNCi0tIA0KVHJvbmQgTXlrbGVidXN0DQpMaW51eCBORlMgY2xpZW50IG1haW50YWluZXINCg0KTmV0QXBwDQpUcm9uZC5NeWtsZWJ1c3RAbmV0YXBwLmNvbQ0Kd3d3Lm5ldGFwcC5jb20NCg0K--To unsubscribe from this list: send the line "unsubscribe linux-nfs" inthe body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.orgMore majordomo info at  http://vger.kernel.org/majordomo-info.html

Re: [PATCH] SUNRPC: set desired file system root before connecting local transports

From: Myklebust, Trond <hidden>
Date: 2012-03-07 00:21:51

On Wed, 2012-03-07 at 00:19 +0000, Myklebust, Trond wrote:
On Wed, 2012-02-29 at 18:59 +0400, Stanislav Kinsbursky wrote:
quoted
Today, there is a problem in connecting of local SUNRPC thansports. These
transports uses UNIX sockets and connection itself is done by rpciod workqueue.
But UNIX sockets lookup is done in context of process file system root. I.e.
all local thunsports are connecting in rpciod context.
This works nice until we will try to mount NFS from process with other root -
for example in container. This container can have it's own (nested) root and
rcpbind process, listening on it's own unix sockets. But NFS mount attempt in
this container will register new service (Lockd for example) in global rpcbind
- not containers's one.
This patch solves the problem by switching rpciod kernel thread's file system
root to right one (stored on transport) while connecting of local transports.

Signed-off-by: Stanislav Kinsbursky <redacted>

---
 fs/fs_struct.c        |    1 +
 net/sunrpc/xprtsock.c |   32 ++++++++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index 78b519c..0f984c3 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -36,6 +36,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
 	if (old_root.dentry)
 		path_put_longterm(&old_root);
 }
+EXPORT_SYMBOL_GPL(set_fs_root);
 
 /*
  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 4c8281d..c94c181 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -37,6 +37,7 @@
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/xprtsock.h>
 #include <linux/file.h>
+#include <linux/fs_struct.h>
 #ifdef CONFIG_SUNRPC_BACKCHANNEL
 #include <linux/sunrpc/bc_xprt.h>
 #endif
@@ -255,6 +256,11 @@ struct sock_xprt {
 	void			(*old_state_change)(struct sock *);
 	void			(*old_write_space)(struct sock *);
 	void			(*old_error_report)(struct sock *);
+
+	/*
+	 * Saved transport creator root. Required for local transports only.
+	 */
+	struct path		root;
 };
 
 /*
@@ -1891,6 +1897,7 @@ static void xs_local_setup_socket(struct work_struct *work)
 	struct rpc_xprt *xprt = &transport->xprt;
 	struct socket *sock;
 	int status = -EIO;
+	struct path root;
 
 	if (xprt->shutdown)
 		goto out;
@@ -1908,7 +1915,14 @@ static void xs_local_setup_socket(struct work_struct *work)
 	dprintk("RPC:       worker connecting xprt %p via AF_LOCAL to %s\n",
 			xprt, xprt->address_strings[RPC_DISPLAY_ADDR]);
 
+	get_fs_root(current->fs, &root);
+	set_fs_root(current->fs, &transport->root);
+
 	status = xs_local_finish_connecting(xprt, sock);
+
+	set_fs_root(current->fs, &root);
+	path_put(&root);
+
 	switch (status) {
 	case 0:
Hi Stanislav,

What happens here if the mount namespace of the process that originally
created the sock_xprt no longer exists? Should we care about that case?

Cheers
  Trond
BTW: We will in any case need Al Viro and Christoph's ACK in order to
export the set_fs_root() function.

-- 
Trond Myklebust
Linux NFS client maintainer

NetApp
Trond.Myklebust@netapp.com
www.netapp.com

Re: [PATCH] SUNRPC: set desired file system root before connecting local transports

From: Stanislav Kinsbursky <hidden>
Date: 2012-03-07 08:34:40

07.03.2012 04:19, Myklebust, Trond пишет:
On Wed, 2012-02-29 at 18:59 +0400, Stanislav Kinsbursky wrote:
quoted
Today, there is a problem in connecting of local SUNRPC thansports. These
transports uses UNIX sockets and connection itself is done by rpciod workqueue.
But UNIX sockets lookup is done in context of process file system root. I.e.
all local thunsports are connecting in rpciod context.
This works nice until we will try to mount NFS from process with other root -
for example in container. This container can have it's own (nested) root and
rcpbind process, listening on it's own unix sockets. But NFS mount attempt in
this container will register new service (Lockd for example) in global rpcbind
- not containers's one.
This patch solves the problem by switching rpciod kernel thread's file system
root to right one (stored on transport) while connecting of local transports.

Signed-off-by: Stanislav Kinsbursky<redacted>

---
  fs/fs_struct.c        |    1 +
  net/sunrpc/xprtsock.c |   32 ++++++++++++++++++++++++++++++--
  2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index 78b519c..0f984c3 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -36,6 +36,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
  	if (old_root.dentry)
  		path_put_longterm(&old_root);
  }
+EXPORT_SYMBOL_GPL(set_fs_root);

  /*
   * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 4c8281d..c94c181 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -37,6 +37,7 @@
  #include<linux/sunrpc/svcsock.h>
  #include<linux/sunrpc/xprtsock.h>
  #include<linux/file.h>
+#include<linux/fs_struct.h>
  #ifdef CONFIG_SUNRPC_BACKCHANNEL
  #include<linux/sunrpc/bc_xprt.h>
  #endif
@@ -255,6 +256,11 @@ struct sock_xprt {
  	void			(*old_state_change)(struct sock *);
  	void			(*old_write_space)(struct sock *);
  	void			(*old_error_report)(struct sock *);
+
+	/*
+	 * Saved transport creator root. Required for local transports only.
+	 */
+	struct path		root;
  };

  /*
@@ -1891,6 +1897,7 @@ static void xs_local_setup_socket(struct work_struct *work)
  	struct rpc_xprt *xprt =&transport->xprt;
  	struct socket *sock;
  	int status = -EIO;
+	struct path root;

  	if (xprt->shutdown)
  		goto out;
@@ -1908,7 +1915,14 @@ static void xs_local_setup_socket(struct work_struct *work)
  	dprintk("RPC:       worker connecting xprt %p via AF_LOCAL to %s\n",
  			xprt, xprt->address_strings[RPC_DISPLAY_ADDR]);

+	get_fs_root(current->fs,&root);
+	set_fs_root(current->fs,&transport->root);
+
  	status = xs_local_finish_connecting(xprt, sock);
+
+	set_fs_root(current->fs,&root);
+	path_put(&root);
+
  	switch (status) {
  	case 0:
Hi Stanislav,

What happens here if the mount namespace of the process that originally
created the sock_xprt no longer exists? Should we care about that case?
Hi, Trond.
Looks like this is not a problem, because process fs->root->mnt usage counter 
was increased on transport creation.
IOW, transport holds current root and thus mount namespace can't disappear.

-- 
Best regards,
Stanislav Kinsbursky

Re: [PATCH] SUNRPC: set desired file system root before connecting local transports

From: Stanislav Kinsbursky <hidden>
Date: 2012-03-07 08:36:55

07.03.2012 04:21, Myklebust, Trond пишет:
BTW: We will in any case need Al Viro and Christoph's ACK in order to
export the set_fs_root() function.
Yep, you right.
Is it better to add them into recipients on a reply to the patch or send the 
patch once more?

-- 
Best regards,
Stanislav Kinsbursky

Re: [PATCH] SUNRPC: set desired file system root before connecting local transports

From: Myklebust, Trond <hidden>
Date: 2012-03-07 13:21:31

On Wed, 2012-03-07 at 12:34 +0400, Stanislav Kinsbursky wrote:
07.03.2012 04:19, Myklebust, Trond пишет:
quoted
On Wed, 2012-02-29 at 18:59 +0400, Stanislav Kinsbursky wrote:
quoted
Today, there is a problem in connecting of local SUNRPC thansports. These
transports uses UNIX sockets and connection itself is done by rpciod workqueue.
But UNIX sockets lookup is done in context of process file system root. I.e.
all local thunsports are connecting in rpciod context.
This works nice until we will try to mount NFS from process with other root -
for example in container. This container can have it's own (nested) root and
rcpbind process, listening on it's own unix sockets. But NFS mount attempt in
this container will register new service (Lockd for example) in global rpcbind
- not containers's one.
This patch solves the problem by switching rpciod kernel thread's file system
root to right one (stored on transport) while connecting of local transports.

Signed-off-by: Stanislav Kinsbursky<redacted>

---
  fs/fs_struct.c        |    1 +
  net/sunrpc/xprtsock.c |   32 ++++++++++++++++++++++++++++++--
  2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index 78b519c..0f984c3 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -36,6 +36,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
  	if (old_root.dentry)
  		path_put_longterm(&old_root);
  }
+EXPORT_SYMBOL_GPL(set_fs_root);

  /*
   * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 4c8281d..c94c181 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -37,6 +37,7 @@
  #include<linux/sunrpc/svcsock.h>
  #include<linux/sunrpc/xprtsock.h>
  #include<linux/file.h>
+#include<linux/fs_struct.h>
  #ifdef CONFIG_SUNRPC_BACKCHANNEL
  #include<linux/sunrpc/bc_xprt.h>
  #endif
@@ -255,6 +256,11 @@ struct sock_xprt {
  	void			(*old_state_change)(struct sock *);
  	void			(*old_write_space)(struct sock *);
  	void			(*old_error_report)(struct sock *);
+
+	/*
+	 * Saved transport creator root. Required for local transports only.
+	 */
+	struct path		root;
  };

  /*
@@ -1891,6 +1897,7 @@ static void xs_local_setup_socket(struct work_struct *work)
  	struct rpc_xprt *xprt =&transport->xprt;
  	struct socket *sock;
  	int status = -EIO;
+	struct path root;

  	if (xprt->shutdown)
  		goto out;
@@ -1908,7 +1915,14 @@ static void xs_local_setup_socket(struct work_struct *work)
  	dprintk("RPC:       worker connecting xprt %p via AF_LOCAL to %s\n",
  			xprt, xprt->address_strings[RPC_DISPLAY_ADDR]);

+	get_fs_root(current->fs,&root);
+	set_fs_root(current->fs,&transport->root);
+
  	status = xs_local_finish_connecting(xprt, sock);
+
+	set_fs_root(current->fs,&root);
+	path_put(&root);
+
  	switch (status) {
  	case 0:
Hi Stanislav,

What happens here if the mount namespace of the process that originally
created the sock_xprt no longer exists? Should we care about that case?
Hi, Trond.
Looks like this is not a problem, because process fs->root->mnt usage counter 
was increased on transport creation.
IOW, transport holds current root and thus mount namespace can't disappear.
That pins the root struct vfsmount, but it doesn't pin the actual
process mount namespace. If the process is dead, then it is quite
possible that the struct mnt_namespace is gone, in which case while you
are pinning the root (i.e. '/'), submounts such as '/var' may be gone.

OTOH, I suppose that you can argue that if the mnt_namespace is gone,
then rpcbind can't be listening on /var/run/rpcbind.sock and so you are
screwed anyway...

OK.... Please just resend the patch, Ccing Al Viro and Christoph so that
we can get their opinion.

-- 
Trond Myklebust
Linux NFS client maintainer

NetApp
Trond.Myklebust@netapp.com
www.netapp.com

��칻
�&�~�&���+-��ݶ��w��˛���m�b��g~ȧ���ܨ}���Ơz�&j:+v����n�r��6;靫3��\
nnX��f�z��2�ޙ���&�)ߡ�a����
�G���h��j:+v���w�٥
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help