Skip to content

Commit 43717c7

Browse files
chuckleverTrond Myklebust
authored and
Trond Myklebust
committed
NFS: Retry mounting NFSROOT
Lukas Razik <[email protected]> reports that on his SPARC system, booting with an NFS root file system stopped working after commit 56463e5 "NFS: Use super.c for NFSROOT mount option parsing." We found that the network switch to which Lukas' client was attached was delaying access to the LAN after the client's NIC driver reported that its link was up. The delay was longer than the timeouts used in the NFS client during mounting. NFSROOT worked for Lukas before commit 56463e5 because in those kernels, the client's first operation was an rpcbind request to determine which port the NFS server was listening on. When that request failed after a long timeout, the client simply selected the default NFS port (2049). By that time the switch was allowing access to the LAN, and the mount succeeded. Neither of these client behaviors is desirable, so reverting 56463e5 is really not a choice. Instead, introduce a mechanism that retries the NFSROOT mount request several times. This is the same tactic that normal user space NFS mounts employ to overcome server and network delays. Signed-off-by: Lukas Razik <[email protected]> [ cel: match kernel coding style, add proper patch description ] [ cel: add exponential back-off ] Signed-off-by: Chuck Lever <[email protected]> Tested-by: Lukas Razik <[email protected]> Cc: [email protected] # > 2.6.38 Signed-off-by: Trond Myklebust <[email protected]>
1 parent 68c9715 commit 43717c7

File tree

1 file changed

+31
-4
lines changed

1 file changed

+31
-4
lines changed

init/do_mounts.c

+31-4
Original file line numberDiff line numberDiff line change
@@ -398,15 +398,42 @@ void __init mount_block_root(char *name, int flags)
398398
}
399399

400400
#ifdef CONFIG_ROOT_NFS
401+
402+
#define NFSROOT_TIMEOUT_MIN 5
403+
#define NFSROOT_TIMEOUT_MAX 30
404+
#define NFSROOT_RETRY_MAX 5
405+
401406
static int __init mount_nfs_root(void)
402407
{
403408
char *root_dev, *root_data;
409+
unsigned int timeout;
410+
int try, err;
404411

405-
if (nfs_root_data(&root_dev, &root_data) != 0)
406-
return 0;
407-
if (do_mount_root(root_dev, "nfs", root_mountflags, root_data) != 0)
412+
err = nfs_root_data(&root_dev, &root_data);
413+
if (err != 0)
408414
return 0;
409-
return 1;
415+
416+
/*
417+
* The server or network may not be ready, so try several
418+
* times. Stop after a few tries in case the client wants
419+
* to fall back to other boot methods.
420+
*/
421+
timeout = NFSROOT_TIMEOUT_MIN;
422+
for (try = 1; ; try++) {
423+
err = do_mount_root(root_dev, "nfs",
424+
root_mountflags, root_data);
425+
if (err == 0)
426+
return 1;
427+
if (try > NFSROOT_RETRY_MAX)
428+
break;
429+
430+
/* Wait, in case the server refused us immediately */
431+
ssleep(timeout);
432+
timeout <<= 1;
433+
if (timeout > NFSROOT_TIMEOUT_MAX)
434+
timeout = NFSROOT_TIMEOUT_MAX;
435+
}
436+
return 0;
410437
}
411438
#endif
412439

0 commit comments

Comments
 (0)