addr= hint for mount program
Subsystems (3)
PATCH 1/1 addr= hint for mount program
Here's my first stab at a patch for mount to make it treat the addr= option as a hint. I've done some very basic testing and it seems to do the right thing, but I need to dredge up a multi-homed NFS server here soon to verify that all is working. If anyone has one and wants to test this out for me, I'd be appreciative :-)
The patch is a little larger than I had originally anticipated, primarily because I had to move a chunk of code that happened before the option parsing to after.
Since the util-linux mailing list seems to be inactive, should I just submit this to the util-linux maintainer directly?
-- Jeff
mount/nfsmount.c +80 -43
@@ -195,7 +195,7 @@static char *prev_bg_host;char hostdir[1024 ];CLIENT *mclient; -char *hostname, *dirname, *old_opts, *mounthost =NULL ; +char *hostname, *dirname, *old_opts, *mounthost, *prefaddr_s =NULL ;char new_opts[1024 ];struct timeval total_timeout;enum clnt_stat clnt_stat;
@@ -207,6 +207,7 @@struct sockaddr_in server_addr;struct sockaddr_in mount_server_addr;struct pmap *pm_mnt; +struct in_addr prefaddr;int msock, fsock;struct timeval retry_timeout;union {
@@ -214,7 +215,7 @@struct mountres3 nfsv3; } status;struct stat statbuf; -char *s; +char *s =NULL ;int port, mountport, proto, bg, soft, intr;int posix, nocto, noac, nolock, broken_suid;int retry, tcp;
@@ -258,43 +259,6 @@ goto fail; } - server_addr.sin_family =AF_INET ; -#ifdef HAVE_inet_aton - if (!inet_aton(hostname, &server_addr.sin_addr)) -#endif - { -if ((hp =gethostbyname (hostname)) ==NULL ) { -fprintf (stderr,_ ("mount: can't get address for %s\n" ), - hostname); - goto fail; - }else { -if (hp->h_length >sizeof (struct in_addr )) { -fprintf (stderr, -_ ("mount: got bad hp->h_length\n" )); - hp->h_length =sizeof (struct in_addr ); - } -memcpy (&server_addr.sin_addr, - hp->h_addr, hp->h_length); - } - } - -memcpy (&mount_server_addr, &server_addr,sizeof (mount_server_addr)); - -/* add IP address to mtab options for use when unmounting */ - - s =inet_ntoa (server_addr.sin_addr); - old_opts = *extra_opts; -if (!old_opts) - old_opts ="" ; -if (strlen (old_opts) +strlen (s) +10 >=sizeof (new_opts)) { -fprintf (stderr,_ ("mount: " -"excessively long option argument\n" )); - goto fail; - } -sprintf (new_opts,"%s%saddr=%s" , - old_opts, *old_opts ?"," :"" , s); - *extra_opts =xstrdup (new_opts); -/* Set default options. * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to * let the kernel decide.
@@ -328,6 +292,7 @@ nfsvers =0 ;/* parse options */ + old_opts =xstrdup (*extra_opts);for (opt =strtok (old_opts,"," ); opt; opt =strtok (NULL ,"," )) {if ((opteq =strchr (opt,'=' ))) {
@@ -388,10 +353,10 @@#endif printf (_ ("Warning: Option namlen is not supported.\n" )); }else if (!strcmp (opt,"addr" )) { -/* ignore */ ; + prefaddr_s = opteq +1 ; }else {printf (_ ("unknown nfs mount parameter: " -"%s=%d\n" ), opt, val); +"%s=%s\n" ), opt, opteq+1 ); goto fail; } }else {
@@ -477,8 +442,8 @@ data.rsize, data.wsize, data.timeo, data.retrans);printf ("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n" , data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); -printf ("port = %d, bg = %d, retry = %d, flags = %.8x\n" , - port, bg, retry, data.flags); +printf ("port = %d, bg = %d, retry = %d, flags = %.8x, addr = %s\n" , + port, bg, retry, data.flags, prefaddr_s);printf ("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n" , mountprog, mountvers, nfsprog, nfsvers); printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
@@ -511,6 +476,78 @@return retval; } + s =NULL ; + server_addr.sin_family =AF_INET ; +#ifdef HAVE_inet_aton +if (!inet_aton (hostname, &server_addr.sin_addr)) +#endif + { +if ((hp =gethostbyname (hostname)) ==NULL ) { +fprintf (stderr,_ ("mount: can't get address for %s\n" ), + hostname); + goto fail; + }else { +if (hp->h_length >sizeof (struct in_addr )) { +fprintf (stderr, +_ ("mount: got bad hp->h_length\n" )); + hp->h_length =sizeof (struct in_addr ); + } + + val =0 ; + s =NULL ; + +#ifdef HAVE_inet_aton +/* if a preferred address is specified, then make sure +* it matches one of the host's addresses before using +* it. If it doesn't, just use first host in list. +*/ +if (prefaddr_s) { +inet_aton (prefaddr_s,&prefaddr); +while (hp->h_addr_list[val]) { +if (prefaddr.s_addr == *(ulong *) + (hp->h_addr_list[val])) { + s = hp->h_addr_list[val]; +break ; + } + ++val; + } + +if (!s) +fprintf (stderr,_ ("mount: specified address doesn't match hostname. Ignoring it.\n" )); + } +#endif /* HAVE_inet_aton */ + +if (s) { +memcpy (&server_addr.sin_addr, + s, hp->h_length); + }else { +memcpy (&server_addr.sin_addr, + hp->h_addr, hp->h_length); + } + } + } + +memcpy (&mount_server_addr, &server_addr,sizeof (mount_server_addr)); + +/* add IP address to mtab options for use when unmounting, if it +* wasn't specified or was ignored */ +if (!s) { + s =inet_ntoa (server_addr.sin_addr); + old_opts = *extra_opts; + +if (!old_opts) + old_opts ="" ; + +if (strlen (old_opts) +strlen (s) +10 >=sizeof (new_opts)) { +fprintf (stderr,_ ("mount: " +"excessively long option argument\n" )); + goto fail; + } +sprintf (new_opts,"%s%saddr=%s" , + old_opts, *old_opts ?"," :"" , s); + *extra_opts =xstrdup (new_opts); + } +/* create mount deamon client */ /* See if the nfs host = mount host. */ if (mounthost) {