diff mbox

gnu: Allow nfs filesystems to be automatically mounted.

Message ID 1479842100-13226-1-git-send-email-jmd@gnu.org
State New
Headers show

Commit Message

John Darrington Nov. 22, 2016, 7:15 p.m. UTC
How about this, then?





* gnu/build/file-systems.scm (mount-file-system): Append target addr= when
mounting nfs filesystems.
---
 gnu/build/file-systems.scm | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

Comments

Ludovic Courtès Nov. 23, 2016, 10:07 p.m. UTC | #1
John Darrington <jmd@gnu.org> skribis:

> How about this, then?
>
>
>
>
>
> * gnu/build/file-systems.scm (mount-file-system): Append target addr= when
> mounting nfs filesystems.
> ---
>  gnu/build/file-systems.scm | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/gnu/build/file-systems.scm b/gnu/build/file-systems.scm
> index 0d55e91..c6fc784 100644
> --- a/gnu/build/file-systems.scm
> +++ b/gnu/build/file-systems.scm
> @@ -481,7 +481,21 @@ run a file system check."
>               (call-with-output-file mount-point (const #t)))
>             (mkdir-p mount-point))
>  
> -       (mount source mount-point type flags options)
> +       (mount source mount-point type flags
> +              (cond
> +               ((string-match "^nfs.*" type)
> +                (let* ((host (car (string-split source #\:)))
> +                       (aa (car (getaddrinfo host #f)))
> +                       (sa (addrinfo:addr aa))
> +                       (inet-addr (inet-ntop (sockaddr:fam sa)
> +                                             (sockaddr:addr sa))))
> +                  (string-append "addr="
> +                                 inet-addr
> +                                 (if options
> +                                     (string-append "," options)
> +                                     ""))))
> +               (else
> +                options)))

Looking at mount(8), it seems that the normal way is for ‘source’ to be
something like “knuth.cwi.nl:/dir”.  The kernel then takes care of
parsing that and doing name resolution somehow.

In that case, we don’t have anything to do, good for us.

mount(8) doesn’t mention ‘addr’.  Do you have documentation about it?

Thanks,
Ludo’.
John Darrington Nov. 23, 2016, 11:32 p.m. UTC | #2
On Wed, Nov 23, 2016 at 11:07:27PM +0100, Ludovic Court??s wrote:
     John Darrington <jmd@gnu.org> skribis:
     
     > * gnu/build/file-systems.scm (mount-file-system): Append target addr= when
     > mounting nfs filesystems.
     > ---
     >  gnu/build/file-systems.scm | 16 +++++++++++++++-
     >  1 file changed, 15 insertions(+), 1 deletion(-)
     >
     > diff --git a/gnu/build/file-systems.scm b/gnu/build/file-systems.scm
     > index 0d55e91..c6fc784 100644
     > --- a/gnu/build/file-systems.scm
     > +++ b/gnu/build/file-systems.scm
     > @@ -481,7 +481,21 @@ run a file system check."
     >               (call-with-output-file mount-point (const #t)))
     >             (mkdir-p mount-point))
     >  
     > -       (mount source mount-point type flags options)
     > +       (mount source mount-point type flags
     > +              (cond
     > +               ((string-match "^nfs.*" type)
     > +                (let* ((host (car (string-split source #\:)))
     > +                       (aa (car (getaddrinfo host #f)))
     > +                       (sa (addrinfo:addr aa))
     > +                       (inet-addr (inet-ntop (sockaddr:fam sa)
     > +                                             (sockaddr:addr sa))))
     > +                  (string-append "addr="
     > +                                 inet-addr
     > +                                 (if options
     > +                                     (string-append "," options)
     > +                                     ""))))
     > +               (else
     > +                options)))
     
     Looking at mount(8), it seems that the normal way is for ???source??? to be
     something like ???knuth.cwi.nl:/dir???.  The kernel then takes care of
     parsing that and doing name resolution somehow.
     
     In that case, we don???t have anything to do, good for us.

Unforunately that is not the case.  :(

Attempting to mount a NFS system by a direct system call will fail unless you
pass addr= as an option (try it if you don't believe me).  The mount.nfs
command when used with -v shows what actually goes on:

$ sudo  mount.nfs -v 192.168.0.125:/export/junk  /mnt
 mount.nfs: timeout set for Wed Nov 23 23:50:43 2016
 mount.nfs: trying text-based options 'vers=4.2,addr=192.168.0.125,clientaddr=192.168.0.22'
 mount.nfs: mount(2): Protocol not supported
 mount.nfs: trying text-based options 'vers=4.1,addr=192.168.0.125,clientaddr=192.168.0.22'
 mount.nfs: mount(2): No such file or directory
 mount.nfs: trying text-based options 'addr=192.168.0.125'
 mount.nfs: prog 100003, trying vers=3, prot=6
 mount.nfs: trying 192.168.0.125 prog 100003 vers 3 prot TCP port 2049
 mount.nfs: prog 100005, trying vers=3, prot=17
 mount.nfs: trying 192.168.0.125 prog 100005 vers 3 prot UDP port 45585
 192.168.0.125:/export/junk on /mnt type nfs

As you can see, it does a kind of crude protocol negotiation with the server.

It's also instructive to experiment a bit by running a command like:

 sudo strace mount -v :/export/junk  -o addr=192.168.0.125 /mnt
in which one can see the system call: 
mount(":/export/junk", "/mnt", "nfs", MS_MGC_VAL, "addr=192.168.0.125") = 0

However running the same command but dropping the option will result in:
 sudo strace mount -v :/export/junk  /mnt
mount(":/export/junk", "/mnt", "nfs", MS_MGC_VAL, NULL) = -1 EINVAL (Invalid argument)


So I think we really do need this patch or something similar to it.


     mount(8) doesn???t mention ???addr???.  Do you have documentation about it?

This aspect of NFS is poorly documented.  The best I found is a discussion at
http://stackoverflow.com/questions/28350912/nfs-mount-system-call-in-linux


     
J'
Ludovic Courtès Nov. 24, 2016, 4:08 p.m. UTC | #3
John Darrington <john@darrington.wattle.id.au> skribis:

> It's also instructive to experiment a bit by running a command like:
>
>  sudo strace mount -v :/export/junk  -o addr=192.168.0.125 /mnt
> in which one can see the system call: 
> mount(":/export/junk", "/mnt", "nfs", MS_MGC_VAL, "addr=192.168.0.125") = 0

Oooh, in that case the patch makes perfect sense.  Thanks for
explaining!

> diff --git a/gnu/build/file-systems.scm b/gnu/build/file-systems.scm
> index 0d55e91..c6fc784 100644
> --- a/gnu/build/file-systems.scm
> +++ b/gnu/build/file-systems.scm
> @@ -481,7 +481,21 @@ run a file system check."
>               (call-with-output-file mount-point (const #t)))
>             (mkdir-p mount-point))
>  
> -       (mount source mount-point type flags options)
> +       (mount source mount-point type flags
> +              (cond
> +               ((string-match "^nfs.*" type)
> +                (let* ((host (car (string-split source #\:)))
> +                       (aa (car (getaddrinfo host #f)))
> +                       (sa (addrinfo:addr aa))
> +                       (inet-addr (inet-ntop (sockaddr:fam sa)
> +                                             (sockaddr:addr sa))))
> +                  (string-append "addr="
> +                                 inet-addr
> +                                 (if options
> +                                     (string-append "," options)
> +                                     ""))))
> +               (else
> +                options)))

Could we write it as:

  (if (string-prefix? "nfs" type)
      (mount-nfs source mount-point type flags options)
      (mount source mount-point type flags options))

and have a separate:

  (define (mount-nfs source mount-point type flags options)
    …)

?

Also, the code above must be changed to use ‘match’ instead of ‘car’.

It should be (getaddrinfo host "nfs") instead of (getaddrinfo host #f).

I’m assuming the syntax for SOURCE doesn’t allow one to specify a TCP
port.  Is this correct?

Thanks,
Ludo’.
diff mbox

Patch

diff --git a/gnu/build/file-systems.scm b/gnu/build/file-systems.scm
index 0d55e91..c6fc784 100644
--- a/gnu/build/file-systems.scm
+++ b/gnu/build/file-systems.scm
@@ -481,7 +481,21 @@  run a file system check."
              (call-with-output-file mount-point (const #t)))
            (mkdir-p mount-point))
 
-       (mount source mount-point type flags options)
+       (mount source mount-point type flags
+              (cond
+               ((string-match "^nfs.*" type)
+                (let* ((host (car (string-split source #\:)))
+                       (aa (car (getaddrinfo host #f)))
+                       (sa (addrinfo:addr aa))
+                       (inet-addr (inet-ntop (sockaddr:fam sa)
+                                             (sockaddr:addr sa))))
+                  (string-append "addr="
+                                 inet-addr
+                                 (if options
+                                     (string-append "," options)
+                                     ""))))
+               (else
+                options)))
 
        ;; For read-only bind mounts, an extra remount is needed, as per
        ;; <http://lwn.net/Articles/281157/>, which still applies to Linux 4.0.