The question came up about how to mount an nfs server with toybox. I
remembered from my contract with parallels in 2010 that I used to do
that: http://landley.livejournal.com/49382.html

So I gave it a go, and found out that the kernel guys broke the text
parsing, and I needed the attached patch (tested on linux-4.4) to fix
it.

Background: behind the scenes the mount -o options filter out a bunch
of flag values (which get passed to the mount syscall as an integer of
various MS_BLAH values or-ed together) and the rest of the values are
passed through as a comma separated text string.

I.E. for every filesystem EXCEPT nfs, options is a text string.

But for NFS it can can either be a text string or a binary blob with
the first digit being a low-ascii value indicating the version number.
If the first digit ISN'T a low-ascii value, it's treated as text and
parsed as text, and since there's nothing the binary blob can do that
the text string _can't_, there's NO REASON to ever use the binary
blob. It's there for historical reasons, and it has versions because
every time they added a new option they had to extend the structure
with more fields at the end, where string parsing just goes
",fruitbasket=42" and you're good.

I.E. NFS was historically stupid, but had a way not to be.

Naturally, the util-linux mount special cases NFS and produces a
binary blob, and so does busybox. Toybox doesn't because it's STUPID,
and so we're using the generic codepath which has been there
forever... and bit-rotted because nobody was testing it.
<the-aristocrats>NFS!</the-aristocrats>

Anyway, with that patch to the kernel and current toybox-git, I built
http://unfs3.sf.net and ran this on the host:

  $ echo "/home/landley (no_root_squash,insecure)" > blah.cfg
  $ ./unfsd -d -s -p -e $PWD/blah.cfg -l 127.0.0.1 -m 9999 -n 9999

And then in qemu:

  $ mount -t nfs -o ro,port=9999,mountport=9999,nolock,v3,udp \
    10.0.2.2:/home/landley /mnt

And it worked.

(The reason for specifying all that -m9999 stuff is telling it to use
a high port number so I don't have to run the nfs server as root on
the host. I'm aware there's a built-in kernel NFS server. I'm also
aware there used to be a built-in kernel httpd, and they're equally
bad ideas. No really, http://www.linuxjournal.com/article/4132 and it
died because it was a BAD IDEA. There aren't built-in kernel SMB or
DNS servers, v9fs doesn't have an in-kernel server, it's REALLY STUPID
that NFS does and I'm not messing with it. Hence testing against
unfs3.)

If somebody wants to send the kernel patch to linux-kernel, feel free
to add my signed-off-by. I'm still under the weather and really not up
to dealing with... them... right now.

Rob
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index f126828..2e0af1c 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2126,11 +2126,23 @@ static int nfs_validate_text_mount_data(void *options,
 	int port = 0;
 	int max_namelen = PAGE_SIZE;
 	int max_pathlen = NFS_MAXPATHLEN;
+	int rc;
 	struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
 
 	if (nfs_parse_mount_options((char *)options, args) == 0)
 		return -EINVAL;
 
+	rc = nfs_parse_devname(dev_name,
+				   &args->nfs_server.hostname,
+				   max_namelen,
+				   &args->nfs_server.export_path,
+				   max_pathlen);
+
+	args->nfs_server.addrlen = rpc_pton(args->net,
+			args->nfs_server.hostname,
+			strlen(args->nfs_server.hostname),
+			sap, sizeof(args->nfs_server.address));
+
 	if (!nfs_verify_server_address(sap))
 		goto out_no_address;
 
@@ -2151,11 +2163,7 @@ static int nfs_validate_text_mount_data(void *options,
 
 	nfs_set_port(sap, &args->nfs_server.port, port);
 
-	return nfs_parse_devname(dev_name,
-				   &args->nfs_server.hostname,
-				   max_namelen,
-				   &args->nfs_server.export_path,
-				   max_pathlen);
+	return rc;
 
 #if !IS_ENABLED(CONFIG_NFS_V4)
 out_v4_not_compiled:
_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to