- if (verbose)
- printf(_("%s: text-based options: '%s'\n"),
- progname, *extra_opts);
-
- if (!fake) {
- if (mount(spec, node, "nfs",
- flags & ~(MS_USER|MS_USERS), *extra_opts)) {
- mount_error(spec, node, errno);
- return EX_FAIL;
+ result = nfs_sys_mount(mi, options);
+
+out_fail:
+ po_destroy(options);
+ return result;
+}
+
+/*
+ * For "-t nfs -o vers=4" or "-t nfs4" mounts.
+ */
+static int nfs_try_mount_v4(struct nfsmount_info *mi)
+{
+ struct sockaddr *sap = &mi->address.sa;
+ struct mount_options *options = po_dup(mi->options);
+ int result = 0;
+
+ if (!options) {
+ errno = ENOMEM;
+ return result;
+ }
+
+ if (mi->version == 0) {
+ if (po_contains(options, "mounthost") ||
+ po_contains(options, "mountaddr") ||
+ po_contains(options, "mountvers") ||
+ po_contains(options, "mountproto")) {
+ /*
+ * Since these mountd options are set assume version 3
+ * is wanted so error out with EPROTONOSUPPORT so the
+ * protocol negation starts with v3.
+ */
+ errno = EPROTONOSUPPORT;
+ goto out_fail;
+ }
+ if (po_append(options, "vers=4") == PO_FAILED) {
+ errno = EINVAL;
+ goto out_fail;
+ }
+ }
+
+ if (!nfs_append_clientaddr_option(sap, mi->salen, options)) {
+ errno = EINVAL;
+ goto out_fail;
+ }
+
+ /*
+ * Update option string to be recorded in /etc/mtab.
+ */
+ if (po_join(options, mi->extra_opts) == PO_FAILED) {
+ errno = ENOMEM;
+ goto out_fail;
+ }
+
+ result = nfs_sys_mount(mi, options);
+
+out_fail:
+ po_destroy(options);
+ return result;
+}
+
+/*
+ * This is a single pass through the fg/bg loop.
+ *
+ * Returns TRUE if successful, otherwise FALSE.
+ * "errno" is set to reflect the individual error.
+ */
+static int nfs_try_mount(struct nfsmount_info *mi)
+{
+ int result = 0;
+
+ switch (mi->version) {
+ case 0:
+ if (linux_version_code() > MAKE_VERSION(2, 6, 31)) {
+ errno = 0;
+ result = nfs_try_mount_v4(mi);
+ if (errno != EPROTONOSUPPORT) {
+ /*
+ * To deal with legacy Linux servers that don't
+ * automatically export a pseudo root, retry
+ * ENOENT errors using version 3. And for
+ * Linux servers prior to 2.6.25, retry EPERM
+ */
+ if (errno != ENOENT && errno != EPERM)
+ break;
+ }