X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmount%2Fnfsumount.c;fp=utils%2Fmount%2Fnfsumount.c;h=02d40ff9d2bcb32457f1414b073cbec16cb4f0b9;hp=b1927de92f156186b3099385ad383c3bfe2b2fad;hb=dc08c702a6c7f824f317af561f491635ee898a71;hpb=17962b82afb68ca8e6b0d3f432d36c6c7c4980ea diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c index b1927de..02d40ff 100644 --- a/utils/mount/nfsumount.c +++ b/utils/mount/nfsumount.c @@ -38,6 +38,9 @@ #include "parse_opt.h" #include "parse_dev.h" +#define MOUNTSFILE "/proc/mounts" +#define LINELEN (4096) + #if !defined(MNT_FORCE) /* dare not try to include -- lots of errors */ #define MNT_FORCE 1 @@ -242,6 +245,91 @@ static int nfs_umount23(const char *devname, char *string) return result; } +/* + * Detect NFSv4 mounts. + * + * Consult /proc/mounts to determine if the mount point + * is an NFSv4 mount. The kernel is authoritative about + * what type of mount this is. + * + * Returns 1 if "mc" is an NFSv4 mount, zero if not, and + * -1 if some error occurred. + */ +static int nfs_umount_is_vers4(const struct mntentchn *mc) +{ + char buffer[LINELEN], *next; + int retval; + FILE *f; + + if ((f = fopen(MOUNTSFILE, "r")) == NULL) { + fprintf(stderr, "%s: %s\n", + MOUNTSFILE, strerror(errno)); + return -1; + } + + retval = -1; + while (fgets(buffer, sizeof(buffer), f) != NULL) { + char *device, *mntdir, *type, *flags; + struct mount_options *options; + char *line = buffer; + + next = strchr(line, '\n'); + if (next != NULL) + *next = '\0'; + + device = strtok(line, " \t"); + if (device == NULL) + continue; + mntdir = strtok(NULL, " \t"); + if (mntdir == NULL) + continue; + if (strcmp(device, mc->m.mnt_fsname) != 0 && + strcmp(mntdir, mc->m.mnt_dir) != 0) + continue; + + type = strtok(NULL, " \t"); + if (type == NULL) + continue; + if (strcmp(type, "nfs4") == 0) + goto out_nfs4; + + flags = strtok(NULL, " \t"); + if (flags == NULL) + continue; + options = po_split(flags); + if (options != NULL) { + unsigned long version; + int rc; + + rc = nfs_nfs_version(options, &version); + po_destroy(options); + if (rc && version == 4) + goto out_nfs4; + } + + goto out_nfs; + } + if (retval == -1) + fprintf(stderr, "%s was not found in %s\n", + mc->m.mnt_dir, MOUNTSFILE); + +out: + fclose(f); + return retval; + +out_nfs4: + if (verbose) + fprintf(stderr, "NFSv4 mount point detected\n"); + retval = 1; + goto out; + +out_nfs: + if (verbose) + fprintf(stderr, "Legacy NFS mount point detected\n"); + retval = 0; + goto out; +} + static struct option umount_longopts[] = { { "force", 0, 0, 'f' }, @@ -365,13 +453,22 @@ int nfsumount(int argc, char *argv[]) ret = EX_SUCCESS; if (mc) { - if (!lazy && strcmp(mc->m.mnt_type, "nfs4") != 0) - /* We ignore the error from nfs_umount23. - * If the actual umount succeeds (in del_mtab), - * we don't want to signal an error, as that - * could cause /sbin/mount to retry! - */ - nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts); + if (!lazy) { + switch (nfs_umount_is_vers4(mc)) { + case 0: + /* We ignore the error from nfs_umount23. + * If the actual umount succeeds (in del_mtab), + * we don't want to signal an error, as that + * could cause /sbin/mount to retry! + */ + nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts); + break; + case 1: + break; + default: + return EX_FAIL; + } + } ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir); } else if (*spec != '/') { if (!lazy)