]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/stropts.c
proper merge
[nfs-utils.git] / utils / mount / stropts.c
index c5c4ba157f9ec9d4ff0f5d7e7f644a1b9c226b63..e09aa7c3b470e5322e5b5ebf3115f73eeed947fd 100644 (file)
@@ -16,8 +16,8 @@
  *
  * You should have received a copy of the GNU General Public
  * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
  *
  */
 
 #include "parse_dev.h"
 #include "conffile.h"
 
-#ifndef HAVE_DECL_AI_ADDRCONFIG
-#define AI_ADDRCONFIG  0
-#endif
-
 #ifndef NFS_PROGRAM
 #define NFS_PROGRAM    (100003)
 #endif
@@ -114,7 +110,7 @@ static void nfs_default_version(struct nfsmount_info *mi)
        }
 }
 #else
-inline void nfs_default_version(struct nfsmount_info *mi) {}
+inline void nfs_default_version(__attribute__ ((unused)) struct nfsmount_info *mi) {}
 #endif /* MOUNT_CONFIG */
 
 /*
@@ -123,10 +119,12 @@ inline void nfs_default_version(struct nfsmount_info *mi) {}
  * Returns a time_t timeout timestamp, in seconds.
  */
 static time_t nfs_parse_retry_option(struct mount_options *options,
-                                    unsigned int timeout_minutes)
+                                    const time_t default_timeout)
 {
+       time_t timeout_minutes;
        long tmp;
 
+       timeout_minutes = default_timeout;
        switch (po_get_numeric(options, "retry", &tmp)) {
        case PO_NOT_FOUND:
                break;
@@ -135,6 +133,7 @@ static time_t nfs_parse_retry_option(struct mount_options *options,
                        timeout_minutes = tmp;
                        break;
                }
+               /*FALLTHROUGH*/
        case PO_BAD_VALUE:
                if (verbose)
                        nfs_error(_("%s: invalid retry timeout was specified; "
@@ -142,7 +141,7 @@ static time_t nfs_parse_retry_option(struct mount_options *options,
                break;
        }
 
-       return time(NULL) + (time_t)(timeout_minutes * 60);
+       return time(NULL) + (timeout_minutes * 60);
 }
 
 /*
@@ -343,7 +342,6 @@ static int nfs_validate_options(struct nfsmount_info *mi)
 {
        struct addrinfo hint = {
                .ai_protocol    = (int)IPPROTO_UDP,
-               .ai_flags       = AI_ADDRCONFIG,
        };
        sa_family_t family;
        int error;
@@ -439,8 +437,8 @@ static int nfs_construct_new_options(struct mount_options *options,
        if (po_append(options, new_option) == PO_FAILED)
                return 0;
 
-       po_remove_all(options, "port");
-       if (nfs_pmap->pm_port != NFS_PORT) {
+       if(po_remove_all(options, "port") == PO_FOUND ||
+          nfs_pmap->pm_port != NFS_PORT) {
                snprintf(new_option, sizeof(new_option) - 1,
                         "port=%lu", nfs_pmap->pm_port);
                if (po_append(options, new_option) == PO_FAILED)
@@ -540,6 +538,10 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options)
                errno = ESPIPE;
                if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED)
                        errno = EOPNOTSUPP;
+               else if (rpc_createerr.cf_stat == RPC_AUTHERROR)
+                       errno = EACCES;
+               else if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
+                       errno = ETIMEDOUT;
                else if (rpc_createerr.cf_error.re_errno != 0)
                        errno = rpc_createerr.cf_error.re_errno;
                return 0;
@@ -570,16 +572,18 @@ static int nfs_sys_mount(struct nfsmount_info *mi, struct mount_options *opts)
        char *options = NULL;
        int result;
 
+       if (mi->fake)
+               return 1;
+
        if (po_join(opts, &options) == PO_FAILED) {
                errno = EIO;
                return 0;
        }
 
-       if (mi->fake)
-               return 1;
-
        result = mount(mi->spec, mi->node, mi->type,
                        mi->flags & ~(MS_USER|MS_USERS), options);
+       free(options);
+
        if (verbose && result) {
                int save = errno;
                nfs_error(_("%s: mount(2): %s"), progname, strerror(save));
@@ -650,7 +654,7 @@ out_fail:
 static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
 {
        struct addrinfo *ai;
-       int ret;
+       int ret = 0;
 
        for (ai = mi->address; ai != NULL; ai = ai->ai_next) {
                ret = nfs_do_mount_v3v2(mi, ai->ai_addr, ai->ai_addrlen);
@@ -663,9 +667,10 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
                case EHOSTUNREACH:
                        continue;
                default:
-                       break;
+                       goto out;
                }
        }
+out:
        return ret;
 }
 
@@ -737,7 +742,7 @@ out_fail:
 static int nfs_try_mount_v4(struct nfsmount_info *mi)
 {
        struct addrinfo *ai;
-       int ret;
+       int ret = 0;
 
        for (ai = mi->address; ai != NULL; ai = ai->ai_next) {
                ret = nfs_do_mount_v4(mi, ai->ai_addr, ai->ai_addrlen);
@@ -749,9 +754,10 @@ static int nfs_try_mount_v4(struct nfsmount_info *mi)
                case EHOSTUNREACH:
                        continue;
                default:
-                       break;
+                       goto out;
                }
        }
+out:
        return ret;
 }
 
@@ -905,7 +911,8 @@ static int nfsmount_parent(struct nfsmount_info *mi)
        if (nfs_try_mount(mi))
                return EX_SUCCESS;
 
-       if (nfs_is_permanent_error(errno)) {
+       /* retry background mounts when the server is not up */
+       if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP) {
                mount_error(mi->spec, mi->node, errno);
                return EX_FAIL;
        }
@@ -940,7 +947,8 @@ static int nfsmount_child(struct nfsmount_info *mi)
                if (nfs_try_mount(mi))
                        return EX_SUCCESS;
 
-               if (nfs_is_permanent_error(errno))
+               /* retry background mounts when the server is not up */
+               if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP)
                        break;
 
                if (time(NULL) > timeout)
@@ -966,6 +974,26 @@ static int nfsmount_bg(struct nfsmount_info *mi)
                return nfsmount_child(mi);
 }
 
+/*
+ * Usually all that is needed for an NFS remount is to change
+ * generic mount options like "sync" or "ro".  These generic
+ * options are controlled by mi->flags, not by text-based
+ * options, and no contact with the server is needed.
+ *
+ * Take care with the /etc/mtab entry for this mount; just
+ * calling update_mtab() will change an "-t nfs -o vers=4"
+ * mount to an "-t nfs -o remount" mount, and that will
+ * confuse umount.nfs.
+ *
+ * Returns a valid mount command exit code.
+ */
+static int nfs_remount(struct nfsmount_info *mi)
+{
+       if (nfs_sys_mount(mi, mi->options))
+               return EX_SUCCESS;
+       return EX_FAIL;
+}
+
 /*
  * Process mount options and try a mount system call.
  *
@@ -982,6 +1010,12 @@ static int nfsmount_start(struct nfsmount_info *mi)
        if (!nfs_validate_options(mi))
                return EX_FAIL;
 
+       /*
+        * Avoid retry and negotiation logic when remounting
+        */
+       if (mi->flags & MS_REMOUNT)
+               return nfs_remount(mi);
+
        if (po_rightmost(mi->options, nfs_background_opttbl) == 0)
                return nfsmount_bg(mi);
        else
@@ -998,6 +1032,8 @@ static int nfsmount_start(struct nfsmount_info *mi)
  *             (input and output argument)
  * @fake: flag indicating whether to carry out the whole operation
  * @child: one if this is a mount daemon (bg)
+ *
+ * Returns a valid mount command exit code.
  */
 int nfsmount_string(const char *spec, const char *node, const char *type,
                    int flags, char **extra_opts, int fake, int child)