[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#690181: Backgrounding mount broken with NFS versions <4



Package: nfs-common
Version: 1:1.2.2-4squeeze2
Tags: patch

Assume the following:

An NFS server supports only NFS version <4.
This server is unreachable at a certain time.
A Debian client boots and tries to mount a directory on the server with
the 'bg' option, but without the 'nfsvers' option.
Later, the NFS server comes up.

Result: The client does _not_ mount the directory and the background
mount is silently terminated.  This typically breaks cross-mounted
server scenarios.

[Note that specifying 'nfsvers=3' is NOT a workaround, because then
 failing to connect the portmapper already terminates the mount.nfs
 process and no backgrounding happens at all.  This is a separate
 bug IMHO.]

Analysis:  When first trying an NFSv4 mount, 'vers=4' is appended
to the extra_options string in the mount options.  Then, the next
(background) attempt also happens with vers=4 and consequently,
nfs_try_mount_v3v2() is never called.  The mount fails, even though
the V3 server would now be reachable.

Fix appended.  It looks like this bug is also present in current
Debian nfs-utils git.

Regards,
Wolfram.

--- nfs-utils-1.2.2/utils/mount/stropts.c	2012-10-10 23:12:14.000000000 +0200
+++ nfs-utils-1.2.2wg/utils/mount/stropts.c	2012-10-10 23:12:26.000000000 +0200
@@ -659,6 +659,7 @@
 {
 	struct mount_options *options = po_dup(mi->options);
 	int result = 0;
+	char *extra_opts = NULL;
 
 	if (!options) {
 		errno = ENOMEM;
@@ -694,20 +695,26 @@
 		goto out_fail;
 	}
 
-	/*
-	 * Update option string to be recorded in /etc/mtab.
-	 */
-	if (po_join(options, mi->extra_opts) == PO_FAILED) {
+	if (po_join(options, &extra_opts) == PO_FAILED) {
 		errno = ENOMEM;
 		goto out_fail;
 	}
 
 	if (verbose)
 		printf(_("%s: trying text-based options '%s'\n"),
-			progname, *mi->extra_opts);
+			progname, extra_opts);
 
 	result = nfs_sys_mount(mi, options);
 
+	/*
+	 * If success, update option string to be recorded in /etc/mtab.
+	 */
+	if (result) {
+	    free(*mi->extra_opts);
+	    *mi->extra_opts = extra_opts;
+	} else
+	    free(extra_opts);
+
 out_fail:
 	po_destroy(options);
 	return result;


Reply to: