~ubuntu-branches/ubuntu/precise/nfs-utils/precise-updates

« back to all changes in this revision

Viewing changes to utils/mount/stropts.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-07-23 17:54:36 UTC
  • mfrom: (14.1.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110723175436-mu7zaa6637prifpq
* Merge from Debian unstable (LP: #728586, LP: #789117), remaining
  changes:
  - debian/nfs-common.{statd,statd-mounting,gssd,idmapd}.upstart,
    debian/control, debian/nfs-common.{preinst,postinst,prerm,postrm},
    debian/rules: drop nfs-common init script in favor of upstart jobs,
    and build-depend on debhelper (>= 7.3.15ubuntu3) for correct upstart
    init handling.
  - Depend on rpcbind (>= 0.2.0-6ubuntu1) for upstart support.
  - debian/nfs-kernel-server.postinst: don't call "invoke-rc.d nfs-common"
    in the postinst, this is redundant anyway and the nfs-common init script
    is gone now.
  - nfs-kernel-server.default:  Add comment about how to disable nfs4.
  - debian/patches/multiarch-kerberos-paths: Search for kerberos libs
    in multiarch locations.
  - nfs-kernel-server.init: Unmount nfsd fs when init script stops
  - ubuntu-fix-kernel-version-handling: avoid segfaults from short kernel
    version numbers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
#include "parse_dev.h"
50
50
#include "conffile.h"
51
51
 
52
 
#ifndef HAVE_DECL_AI_ADDRCONFIG
53
 
#define AI_ADDRCONFIG   0
54
 
#endif
55
 
 
56
52
#ifndef NFS_PROGRAM
57
53
#define NFS_PROGRAM     (100003)
58
54
#endif
114
110
        }
115
111
}
116
112
#else
117
 
inline void nfs_default_version(struct nfsmount_info *mi) {}
 
113
inline void nfs_default_version(__attribute__ ((unused)) struct nfsmount_info *mi) {}
118
114
#endif /* MOUNT_CONFIG */
119
115
 
120
116
/*
123
119
 * Returns a time_t timeout timestamp, in seconds.
124
120
 */
125
121
static time_t nfs_parse_retry_option(struct mount_options *options,
126
 
                                     unsigned int timeout_minutes)
 
122
                                     const time_t default_timeout)
127
123
{
 
124
        time_t timeout_minutes;
128
125
        long tmp;
129
126
 
 
127
        timeout_minutes = default_timeout;
130
128
        switch (po_get_numeric(options, "retry", &tmp)) {
131
129
        case PO_NOT_FOUND:
132
130
                break;
135
133
                        timeout_minutes = tmp;
136
134
                        break;
137
135
                }
 
136
                /*FALLTHROUGH*/
138
137
        case PO_BAD_VALUE:
139
138
                if (verbose)
140
139
                        nfs_error(_("%s: invalid retry timeout was specified; "
142
141
                break;
143
142
        }
144
143
 
145
 
        return time(NULL) + (time_t)(timeout_minutes * 60);
 
144
        return time(NULL) + (timeout_minutes * 60);
146
145
}
147
146
 
148
147
/*
302
301
 
303
302
        if (strncmp(mi->type, "nfs4", 4) == 0)
304
303
                mi->version = 4;
305
 
        else {
306
 
                char *option = po_get(mi->options, "proto");
307
 
                if (option && strcmp(option, "rdma") == 0)
308
 
                        mi->version = 3;
309
 
        }
 
304
 
 
305
        /*
 
306
         * Before 2.6.32, the kernel NFS client didn't
 
307
         * support "-t nfs vers=4" mounts, so NFS version
 
308
         * 4 cannot be included when autonegotiating
 
309
         * while running on those kernels.
 
310
         */
 
311
        if (mi->version == 0 &&
 
312
            linux_version_code() <= MAKE_VERSION(2, 6, 31))
 
313
                mi->version = 3;
310
314
 
311
315
        /*
312
316
         * If we still don't know, check for version-specific
338
342
{
339
343
        struct addrinfo hint = {
340
344
                .ai_protocol    = (int)IPPROTO_UDP,
341
 
                .ai_flags       = AI_ADDRCONFIG,
342
345
        };
343
346
        sa_family_t family;
344
347
        int error;
490
493
        union nfs_sockaddr mnt_address;
491
494
        struct sockaddr *mnt_saddr = &mnt_address.sa;
492
495
        socklen_t mnt_salen = sizeof(mnt_address);
 
496
        unsigned long protocol;
493
497
        struct pmap mnt_pmap;
494
 
        char *option;
495
498
 
496
499
        /*
497
 
         * Skip option negotiation for proto=rdma mounts.
 
500
         * Version and transport negotiation is not required
 
501
         * and does not work for RDMA mounts.
498
502
         */
499
 
        option = po_get(options, "proto");
500
 
        if (option && strcmp(option, "rdma") == 0)
 
503
        if (!nfs_nfs_protocol(options, &protocol)) {
 
504
                errno = EINVAL;
 
505
                return 0;
 
506
        }
 
507
        if (protocol == NFSPROTO_RDMA)
501
508
                goto out;
502
509
 
503
510
        /*
538
545
 
539
546
        if (!nfs_construct_new_options(options, nfs_saddr, &nfs_pmap,
540
547
                                        mnt_saddr, &mnt_pmap)) {
541
 
                errno = EINVAL;
 
548
                if (rpc_createerr.cf_stat == RPC_UNKNOWNPROTO)
 
549
                        errno = EPROTONOSUPPORT;
 
550
                else
 
551
                        errno = EINVAL;
542
552
                return 0;
543
553
        }
544
554
 
558
568
        char *options = NULL;
559
569
        int result;
560
570
 
 
571
        if (mi->fake)
 
572
                return 1;
 
573
 
561
574
        if (po_join(opts, &options) == PO_FAILED) {
562
575
                errno = EIO;
563
576
                return 0;
564
577
        }
565
578
 
566
 
        if (mi->fake)
567
 
                return 1;
568
 
 
569
579
        result = mount(mi->spec, mi->node, mi->type,
570
580
                        mi->flags & ~(MS_USER|MS_USERS), options);
 
581
        free(options);
 
582
 
571
583
        if (verbose && result) {
572
584
                int save = errno;
573
585
                nfs_error(_("%s: mount(2): %s"), progname, strerror(save));
586
598
                errno = ENOMEM;
587
599
                return result;
588
600
        }
589
 
 
 
601
        errno = 0;
590
602
        if (!nfs_append_addr_option(sap, salen, options)) {
591
 
                errno = EINVAL;
 
603
                if (errno == 0)
 
604
                        errno = EINVAL;
592
605
                goto out_fail;
593
606
        }
594
607
 
595
608
        if (!nfs_fix_mounthost_option(options, mi->hostname)) {
596
 
                errno = EINVAL;
 
609
                if (errno == 0)
 
610
                        errno = EINVAL;
597
611
                goto out_fail;
598
612
        }
599
613
        if (!mi->fake && !nfs_verify_lock_option(options)) {
600
 
                errno = EINVAL;
 
614
                if (errno == 0)
 
615
                        errno = EINVAL;
601
616
                goto out_fail;
602
617
        }
603
618
 
635
650
static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
636
651
{
637
652
        struct addrinfo *ai;
638
 
        int ret;
 
653
        int ret = 0;
639
654
 
640
655
        for (ai = mi->address; ai != NULL; ai = ai->ai_next) {
641
656
                ret = nfs_do_mount_v3v2(mi, ai->ai_addr, ai->ai_addrlen);
722
737
static int nfs_try_mount_v4(struct nfsmount_info *mi)
723
738
{
724
739
        struct addrinfo *ai;
725
 
        int ret;
 
740
        int ret = 0;
726
741
 
727
742
        for (ai = mi->address; ai != NULL; ai = ai->ai_next) {
728
743
                ret = nfs_do_mount_v4(mi, ai->ai_addr, ai->ai_addrlen);
741
756
}
742
757
 
743
758
/*
 
759
 * Handle NFS version and transport protocol
 
760
 * autonegotiation.
 
761
 *
 
762
 * When no version or protocol is specified on the
 
763
 * command line, mount.nfs negotiates with the server
 
764
 * to determine appropriate settings for the new
 
765
 * mount point.
 
766
 *
 
767
 * Returns TRUE if successful, otherwise FALSE.
 
768
 * "errno" is set to reflect the individual error.
 
769
 */
 
770
static int nfs_autonegotiate(struct nfsmount_info *mi)
 
771
{
 
772
        int result;
 
773
 
 
774
        result = nfs_try_mount_v4(mi);
 
775
        if (result)
 
776
                return result;
 
777
                
 
778
        switch (errno) {
 
779
        case EPROTONOSUPPORT:
 
780
                /* A clear indication that the server or our
 
781
                 * client does not support NFS version 4. */
 
782
                goto fall_back;
 
783
        case ENOENT:
 
784
                /* Legacy Linux servers don't export an NFS
 
785
                 * version 4 pseudoroot. */
 
786
                goto fall_back;
 
787
        case EPERM:
 
788
                /* Linux servers prior to 2.6.25 may return
 
789
                 * EPERM when NFS version 4 is not supported. */
 
790
                goto fall_back;
 
791
        default:
 
792
                return result;
 
793
        }
 
794
 
 
795
fall_back:
 
796
        return nfs_try_mount_v3v2(mi);
 
797
}
 
798
 
 
799
/*
744
800
 * This is a single pass through the fg/bg loop.
745
801
 *
746
802
 * Returns TRUE if successful, otherwise FALSE.
752
808
 
753
809
        switch (mi->version) {
754
810
        case 0:
755
 
                if (linux_version_code() > MAKE_VERSION(2, 6, 31)) {
756
 
                        errno = 0;
757
 
                        result = nfs_try_mount_v4(mi);
758
 
                        if (errno != EPROTONOSUPPORT) {
759
 
                                /* 
760
 
                                 * To deal with legacy Linux servers that don't
761
 
                                 * automatically export a pseudo root, retry
762
 
                                 * ENOENT errors using version 3. And for
763
 
                                 * Linux servers prior to 2.6.25, retry EPERM
764
 
                                 */
765
 
                                if (errno != ENOENT && errno != EPERM)
766
 
                                        break;
767
 
                        }
768
 
                }
 
811
                result = nfs_autonegotiate(mi);
 
812
                break;
769
813
        case 2:
770
814
        case 3:
771
815
                result = nfs_try_mount_v3v2(mi);
799
843
        case ESTALE:
800
844
        case ETIMEDOUT:
801
845
        case ECONNREFUSED:
 
846
        case EHOSTUNREACH:
802
847
                return 0;       /* temporary */
803
848
        default:
804
849
                return 1;       /* permanent */
922
967
}
923
968
 
924
969
/*
 
970
 * Usually all that is needed for an NFS remount is to change
 
971
 * generic mount options like "sync" or "ro".  These generic
 
972
 * options are controlled by mi->flags, not by text-based
 
973
 * options, and no contact with the server is needed.
 
974
 *
 
975
 * Take care with the /etc/mtab entry for this mount; just
 
976
 * calling update_mtab() will change an "-t nfs -o vers=4"
 
977
 * mount to an "-t nfs -o remount" mount, and that will
 
978
 * confuse umount.nfs.
 
979
 *
 
980
 * Returns a valid mount command exit code.
 
981
 */
 
982
static int nfs_remount(struct nfsmount_info *mi)
 
983
{
 
984
        if (nfs_sys_mount(mi, mi->options))
 
985
                return EX_SUCCESS;
 
986
        return EX_FAIL;
 
987
}
 
988
 
 
989
/*
925
990
 * Process mount options and try a mount system call.
926
991
 *
927
992
 * Returns a valid mount command exit code.
937
1002
        if (!nfs_validate_options(mi))
938
1003
                return EX_FAIL;
939
1004
 
 
1005
        /*
 
1006
         * Avoid retry and negotiation logic when remounting
 
1007
         */
 
1008
        if (mi->flags & MS_REMOUNT)
 
1009
                return nfs_remount(mi);
 
1010
 
940
1011
        if (po_rightmost(mi->options, nfs_background_opttbl) == 0)
941
1012
                return nfsmount_bg(mi);
942
1013
        else
953
1024
 *              (input and output argument)
954
1025
 * @fake: flag indicating whether to carry out the whole operation
955
1026
 * @child: one if this is a mount daemon (bg)
 
1027
 *
 
1028
 * Returns a valid mount command exit code.
956
1029
 */
957
1030
int nfsmount_string(const char *spec, const char *node, const char *type,
958
1031
                    int flags, char **extra_opts, int fake, int child)