1716fd348SMartin Matuska /* 2716fd348SMartin Matuska * CDDL HEADER START 3716fd348SMartin Matuska * 4716fd348SMartin Matuska * The contents of this file are subject to the terms of the 5716fd348SMartin Matuska * Common Development and Distribution License (the "License"). 6716fd348SMartin Matuska * You may not use this file except in compliance with the License. 7716fd348SMartin Matuska * 8716fd348SMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10716fd348SMartin Matuska * See the License for the specific language governing permissions 11716fd348SMartin Matuska * and limitations under the License. 12716fd348SMartin Matuska * 13716fd348SMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each 14716fd348SMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15716fd348SMartin Matuska * If applicable, add the following below this CDDL HEADER, with the 16716fd348SMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying 17716fd348SMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner] 18716fd348SMartin Matuska * 19716fd348SMartin Matuska * CDDL HEADER END 20716fd348SMartin Matuska */ 21716fd348SMartin Matuska 22716fd348SMartin Matuska /* 23716fd348SMartin Matuska * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24716fd348SMartin Matuska * Copyright (c) 2011 Lawrence Livermore National Security, LLC. 25716fd348SMartin Matuska */ 26716fd348SMartin Matuska 27716fd348SMartin Matuska #include <libintl.h> 28716fd348SMartin Matuska #include <unistd.h> 29716fd348SMartin Matuska #include <sys/file.h> 30716fd348SMartin Matuska #include <sys/mount.h> 31716fd348SMartin Matuska #include <sys/mntent.h> 32716fd348SMartin Matuska #include <sys/stat.h> 33716fd348SMartin Matuska #include <libzfs.h> 34716fd348SMartin Matuska #include <libzutil.h> 35716fd348SMartin Matuska #include <locale.h> 36716fd348SMartin Matuska #include <getopt.h> 37716fd348SMartin Matuska #include <fcntl.h> 38716fd348SMartin Matuska #include <errno.h> 39716fd348SMartin Matuska 40716fd348SMartin Matuska #define ZS_COMMENT 0x00000000 /* comment */ 41716fd348SMartin Matuska #define ZS_ZFSUTIL 0x00000001 /* caller is zfs(8) */ 42716fd348SMartin Matuska 43716fd348SMartin Matuska libzfs_handle_t *g_zfs; 44716fd348SMartin Matuska 45716fd348SMartin Matuska /* 46716fd348SMartin Matuska * Opportunistically convert a target string into a pool name. If the 47716fd348SMartin Matuska * string does not represent a block device with a valid zfs label 48716fd348SMartin Matuska * then it is passed through without modification. 49716fd348SMartin Matuska */ 50716fd348SMartin Matuska static void 51716fd348SMartin Matuska parse_dataset(const char *target, char **dataset) 52716fd348SMartin Matuska { 53716fd348SMartin Matuska /* 54716fd348SMartin Matuska * Prior to util-linux 2.36.2, if a file or directory in the 55716fd348SMartin Matuska * current working directory was named 'dataset' then mount(8) 56716fd348SMartin Matuska * would prepend the current working directory to the dataset. 57716fd348SMartin Matuska * Check for it and strip the prepended path when it is added. 58716fd348SMartin Matuska */ 59716fd348SMartin Matuska char cwd[PATH_MAX]; 60716fd348SMartin Matuska if (getcwd(cwd, PATH_MAX) == NULL) { 61716fd348SMartin Matuska perror("getcwd"); 62716fd348SMartin Matuska return; 63716fd348SMartin Matuska } 64716fd348SMartin Matuska int len = strlen(cwd); 65716fd348SMartin Matuska if (strncmp(cwd, target, len) == 0) 66716fd348SMartin Matuska target += len; 67716fd348SMartin Matuska 68716fd348SMartin Matuska /* Assume pool/dataset is more likely */ 69716fd348SMartin Matuska strlcpy(*dataset, target, PATH_MAX); 70716fd348SMartin Matuska 71716fd348SMartin Matuska int fd = open(target, O_RDONLY | O_CLOEXEC); 72716fd348SMartin Matuska if (fd < 0) 73716fd348SMartin Matuska return; 74716fd348SMartin Matuska 75716fd348SMartin Matuska nvlist_t *cfg = NULL; 76716fd348SMartin Matuska if (zpool_read_label(fd, &cfg, NULL) == 0) { 772a58b312SMartin Matuska const char *nm = NULL; 78716fd348SMartin Matuska if (!nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &nm)) 79716fd348SMartin Matuska strlcpy(*dataset, nm, PATH_MAX); 80716fd348SMartin Matuska nvlist_free(cfg); 81716fd348SMartin Matuska } 82716fd348SMartin Matuska 83716fd348SMartin Matuska if (close(fd)) 84716fd348SMartin Matuska perror("close"); 85716fd348SMartin Matuska } 86716fd348SMartin Matuska 87716fd348SMartin Matuska /* 88716fd348SMartin Matuska * Update the mtab_* code to use the libmount library when it is commonly 89716fd348SMartin Matuska * available otherwise fallback to legacy mode. The mount(8) utility will 90716fd348SMartin Matuska * manage the lock file for us to prevent racing updates to /etc/mtab. 91716fd348SMartin Matuska */ 92716fd348SMartin Matuska static int 93716fd348SMartin Matuska mtab_is_writeable(void) 94716fd348SMartin Matuska { 95716fd348SMartin Matuska struct stat st; 96716fd348SMartin Matuska int error, fd; 97716fd348SMartin Matuska 98716fd348SMartin Matuska error = lstat("/etc/mtab", &st); 99716fd348SMartin Matuska if (error || S_ISLNK(st.st_mode)) 100716fd348SMartin Matuska return (0); 101716fd348SMartin Matuska 102716fd348SMartin Matuska fd = open("/etc/mtab", O_RDWR | O_CREAT, 0644); 103716fd348SMartin Matuska if (fd < 0) 104716fd348SMartin Matuska return (0); 105716fd348SMartin Matuska 106716fd348SMartin Matuska close(fd); 107716fd348SMartin Matuska return (1); 108716fd348SMartin Matuska } 109716fd348SMartin Matuska 110716fd348SMartin Matuska static int 111a0b956f5SMartin Matuska mtab_update(const char *dataset, const char *mntpoint, const char *type, 112a0b956f5SMartin Matuska const char *mntopts) 113716fd348SMartin Matuska { 114716fd348SMartin Matuska struct mntent mnt; 115716fd348SMartin Matuska FILE *fp; 116716fd348SMartin Matuska int error; 117716fd348SMartin Matuska 118a0b956f5SMartin Matuska mnt.mnt_fsname = (char *)dataset; 119a0b956f5SMartin Matuska mnt.mnt_dir = (char *)mntpoint; 120a0b956f5SMartin Matuska mnt.mnt_type = (char *)type; 121a0b956f5SMartin Matuska mnt.mnt_opts = (char *)(mntopts ?: ""); 122716fd348SMartin Matuska mnt.mnt_freq = 0; 123716fd348SMartin Matuska mnt.mnt_passno = 0; 124716fd348SMartin Matuska 125a0b956f5SMartin Matuska fp = setmntent("/etc/mtab", "a+e"); 126716fd348SMartin Matuska if (!fp) { 127716fd348SMartin Matuska (void) fprintf(stderr, gettext( 128716fd348SMartin Matuska "filesystem '%s' was mounted, but /etc/mtab " 129716fd348SMartin Matuska "could not be opened due to error: %s\n"), 130716fd348SMartin Matuska dataset, strerror(errno)); 131716fd348SMartin Matuska return (MOUNT_FILEIO); 132716fd348SMartin Matuska } 133716fd348SMartin Matuska 134716fd348SMartin Matuska error = addmntent(fp, &mnt); 135716fd348SMartin Matuska if (error) { 136716fd348SMartin Matuska (void) fprintf(stderr, gettext( 137716fd348SMartin Matuska "filesystem '%s' was mounted, but /etc/mtab " 138716fd348SMartin Matuska "could not be updated due to error: %s\n"), 139716fd348SMartin Matuska dataset, strerror(errno)); 140716fd348SMartin Matuska return (MOUNT_FILEIO); 141716fd348SMartin Matuska } 142716fd348SMartin Matuska 143716fd348SMartin Matuska (void) endmntent(fp); 144716fd348SMartin Matuska 145716fd348SMartin Matuska return (MOUNT_SUCCESS); 146716fd348SMartin Matuska } 147716fd348SMartin Matuska 148716fd348SMartin Matuska int 149716fd348SMartin Matuska main(int argc, char **argv) 150716fd348SMartin Matuska { 151716fd348SMartin Matuska zfs_handle_t *zhp; 152716fd348SMartin Matuska char prop[ZFS_MAXPROPLEN]; 153716fd348SMartin Matuska uint64_t zfs_version = 0; 154716fd348SMartin Matuska char mntopts[MNT_LINE_MAX] = { '\0' }; 155716fd348SMartin Matuska char badopt[MNT_LINE_MAX] = { '\0' }; 156716fd348SMartin Matuska char mtabopt[MNT_LINE_MAX] = { '\0' }; 157716fd348SMartin Matuska char mntpoint[PATH_MAX]; 158716fd348SMartin Matuska char dataset[PATH_MAX], *pdataset = dataset; 159716fd348SMartin Matuska unsigned long mntflags = 0, zfsflags = 0, remount = 0; 160716fd348SMartin Matuska int sloppy = 0, fake = 0, verbose = 0, nomtab = 0, zfsutil = 0; 161716fd348SMartin Matuska int error, c; 162716fd348SMartin Matuska 163716fd348SMartin Matuska (void) setlocale(LC_ALL, ""); 164716fd348SMartin Matuska (void) setlocale(LC_NUMERIC, "C"); 165716fd348SMartin Matuska (void) textdomain(TEXT_DOMAIN); 166716fd348SMartin Matuska 167716fd348SMartin Matuska opterr = 0; 168716fd348SMartin Matuska 169716fd348SMartin Matuska /* check options */ 170716fd348SMartin Matuska while ((c = getopt_long(argc, argv, "sfnvo:h?", 0, 0)) != -1) { 171716fd348SMartin Matuska switch (c) { 172716fd348SMartin Matuska case 's': 173716fd348SMartin Matuska sloppy = 1; 174716fd348SMartin Matuska break; 175716fd348SMartin Matuska case 'f': 176716fd348SMartin Matuska fake = 1; 177716fd348SMartin Matuska break; 178716fd348SMartin Matuska case 'n': 179716fd348SMartin Matuska nomtab = 1; 180716fd348SMartin Matuska break; 181716fd348SMartin Matuska case 'v': 182716fd348SMartin Matuska verbose++; 183716fd348SMartin Matuska break; 184716fd348SMartin Matuska case 'o': 185716fd348SMartin Matuska (void) strlcpy(mntopts, optarg, sizeof (mntopts)); 186716fd348SMartin Matuska break; 187716fd348SMartin Matuska case 'h': 188716fd348SMartin Matuska case '?': 189716fd348SMartin Matuska if (optopt) 190716fd348SMartin Matuska (void) fprintf(stderr, 191716fd348SMartin Matuska gettext("Invalid option '%c'\n"), optopt); 192716fd348SMartin Matuska (void) fprintf(stderr, gettext("Usage: mount.zfs " 193716fd348SMartin Matuska "[-sfnvh] [-o options] <dataset> <mountpoint>\n")); 194716fd348SMartin Matuska return (MOUNT_USAGE); 195716fd348SMartin Matuska } 196716fd348SMartin Matuska } 197716fd348SMartin Matuska 198716fd348SMartin Matuska argc -= optind; 199716fd348SMartin Matuska argv += optind; 200716fd348SMartin Matuska 201716fd348SMartin Matuska /* check that we only have two arguments */ 202716fd348SMartin Matuska if (argc != 2) { 203716fd348SMartin Matuska if (argc == 0) 204716fd348SMartin Matuska (void) fprintf(stderr, gettext("missing dataset " 205716fd348SMartin Matuska "argument\n")); 206716fd348SMartin Matuska else if (argc == 1) 207716fd348SMartin Matuska (void) fprintf(stderr, 208716fd348SMartin Matuska gettext("missing mountpoint argument\n")); 209716fd348SMartin Matuska else 210716fd348SMartin Matuska (void) fprintf(stderr, gettext("too many arguments\n")); 211716fd348SMartin Matuska (void) fprintf(stderr, "usage: mount <dataset> <mountpoint>\n"); 212716fd348SMartin Matuska return (MOUNT_USAGE); 213716fd348SMartin Matuska } 214716fd348SMartin Matuska 215716fd348SMartin Matuska parse_dataset(argv[0], &pdataset); 216716fd348SMartin Matuska 217716fd348SMartin Matuska /* canonicalize the mount point */ 218716fd348SMartin Matuska if (realpath(argv[1], mntpoint) == NULL) { 219716fd348SMartin Matuska (void) fprintf(stderr, gettext("filesystem '%s' cannot be " 220716fd348SMartin Matuska "mounted at '%s' due to canonicalization error: %s\n"), 221716fd348SMartin Matuska dataset, argv[1], strerror(errno)); 222716fd348SMartin Matuska return (MOUNT_SYSERR); 223716fd348SMartin Matuska } 224716fd348SMartin Matuska 225716fd348SMartin Matuska /* validate mount options and set mntflags */ 226716fd348SMartin Matuska error = zfs_parse_mount_options(mntopts, &mntflags, &zfsflags, sloppy, 227716fd348SMartin Matuska badopt, mtabopt); 228716fd348SMartin Matuska if (error) { 229716fd348SMartin Matuska switch (error) { 230716fd348SMartin Matuska case ENOMEM: 231716fd348SMartin Matuska (void) fprintf(stderr, gettext("filesystem '%s' " 232716fd348SMartin Matuska "cannot be mounted due to a memory allocation " 233716fd348SMartin Matuska "failure.\n"), dataset); 234716fd348SMartin Matuska return (MOUNT_SYSERR); 235716fd348SMartin Matuska case ENOENT: 236716fd348SMartin Matuska (void) fprintf(stderr, gettext("filesystem '%s' " 237716fd348SMartin Matuska "cannot be mounted due to invalid option " 238716fd348SMartin Matuska "'%s'.\n"), dataset, badopt); 239716fd348SMartin Matuska (void) fprintf(stderr, gettext("Use the '-s' option " 240716fd348SMartin Matuska "to ignore the bad mount option.\n")); 241716fd348SMartin Matuska return (MOUNT_USAGE); 242716fd348SMartin Matuska default: 243716fd348SMartin Matuska (void) fprintf(stderr, gettext("filesystem '%s' " 244716fd348SMartin Matuska "cannot be mounted due to internal error %d.\n"), 245716fd348SMartin Matuska dataset, error); 246716fd348SMartin Matuska return (MOUNT_SOFTWARE); 247716fd348SMartin Matuska } 248716fd348SMartin Matuska } 249716fd348SMartin Matuska 250716fd348SMartin Matuska if (mntflags & MS_REMOUNT) { 251716fd348SMartin Matuska nomtab = 1; 252716fd348SMartin Matuska remount = 1; 253716fd348SMartin Matuska } 254716fd348SMartin Matuska 255716fd348SMartin Matuska if (zfsflags & ZS_ZFSUTIL) 256716fd348SMartin Matuska zfsutil = 1; 257716fd348SMartin Matuska 258716fd348SMartin Matuska if ((g_zfs = libzfs_init()) == NULL) { 259716fd348SMartin Matuska (void) fprintf(stderr, "%s\n", libzfs_error_init(errno)); 260716fd348SMartin Matuska return (MOUNT_SYSERR); 261716fd348SMartin Matuska } 262716fd348SMartin Matuska 263716fd348SMartin Matuska /* try to open the dataset to access the mount point */ 264716fd348SMartin Matuska if ((zhp = zfs_open(g_zfs, dataset, 265716fd348SMartin Matuska ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT)) == NULL) { 266716fd348SMartin Matuska (void) fprintf(stderr, gettext("filesystem '%s' cannot be " 267716fd348SMartin Matuska "mounted, unable to open the dataset\n"), dataset); 268716fd348SMartin Matuska libzfs_fini(g_zfs); 269716fd348SMartin Matuska return (MOUNT_USAGE); 270716fd348SMartin Matuska } 271716fd348SMartin Matuska 272*e2df9bb4SMartin Matuska if (sloppy || libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) { 273716fd348SMartin Matuska zfs_adjust_mount_options(zhp, mntpoint, mntopts, mtabopt); 274716fd348SMartin Matuska } 275716fd348SMartin Matuska 276716fd348SMartin Matuska /* treat all snapshots as legacy mount points */ 277716fd348SMartin Matuska if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) 278716fd348SMartin Matuska (void) strlcpy(prop, ZFS_MOUNTPOINT_LEGACY, ZFS_MAXPROPLEN); 279716fd348SMartin Matuska else 280716fd348SMartin Matuska (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop, 281716fd348SMartin Matuska sizeof (prop), NULL, NULL, 0, B_FALSE); 282716fd348SMartin Matuska 283716fd348SMartin Matuska /* 284716fd348SMartin Matuska * Fetch the max supported zfs version in case we get ENOTSUP 285716fd348SMartin Matuska * back from the mount command, since we need the zfs handle 286716fd348SMartin Matuska * to do so. 287716fd348SMartin Matuska */ 288716fd348SMartin Matuska zfs_version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION); 289716fd348SMartin Matuska if (zfs_version == 0) { 290716fd348SMartin Matuska fprintf(stderr, gettext("unable to fetch " 291716fd348SMartin Matuska "ZFS version for filesystem '%s'\n"), dataset); 292716fd348SMartin Matuska zfs_close(zhp); 293716fd348SMartin Matuska libzfs_fini(g_zfs); 294716fd348SMartin Matuska return (MOUNT_SYSERR); 295716fd348SMartin Matuska } 296716fd348SMartin Matuska 297716fd348SMartin Matuska /* 298716fd348SMartin Matuska * Legacy mount points may only be mounted using 'mount', never using 299716fd348SMartin Matuska * 'zfs mount'. However, since 'zfs mount' actually invokes 'mount' 300716fd348SMartin Matuska * we differentiate the two cases using the 'zfsutil' mount option. 301716fd348SMartin Matuska * This mount option should only be supplied by the 'zfs mount' util. 302716fd348SMartin Matuska * 303716fd348SMartin Matuska * The only exception to the above rule is '-o remount' which is 304716fd348SMartin Matuska * always allowed for non-legacy datasets. This is done because when 305716fd348SMartin Matuska * using zfs as your root file system both rc.sysinit/umountroot and 306716fd348SMartin Matuska * systemd depend on 'mount -o remount <mountpoint>' to work. 307716fd348SMartin Matuska */ 308716fd348SMartin Matuska if (zfsutil && (strcmp(prop, ZFS_MOUNTPOINT_LEGACY) == 0)) { 309716fd348SMartin Matuska (void) fprintf(stderr, gettext( 310716fd348SMartin Matuska "filesystem '%s' cannot be mounted using 'zfs mount'.\n" 311716fd348SMartin Matuska "Use 'zfs set mountpoint=%s' or 'mount -t zfs %s %s'.\n" 312716fd348SMartin Matuska "See zfs(8) for more information.\n"), 313716fd348SMartin Matuska dataset, mntpoint, dataset, mntpoint); 314716fd348SMartin Matuska zfs_close(zhp); 315716fd348SMartin Matuska libzfs_fini(g_zfs); 316716fd348SMartin Matuska return (MOUNT_USAGE); 317716fd348SMartin Matuska } 318716fd348SMartin Matuska 319716fd348SMartin Matuska if (!zfsutil && !(remount || fake) && 320716fd348SMartin Matuska strcmp(prop, ZFS_MOUNTPOINT_LEGACY)) { 321716fd348SMartin Matuska (void) fprintf(stderr, gettext( 322716fd348SMartin Matuska "filesystem '%s' cannot be mounted using 'mount'.\n" 323716fd348SMartin Matuska "Use 'zfs set mountpoint=%s' or 'zfs mount %s'.\n" 324716fd348SMartin Matuska "See zfs(8) for more information.\n"), 325716fd348SMartin Matuska dataset, "legacy", dataset); 326716fd348SMartin Matuska zfs_close(zhp); 327716fd348SMartin Matuska libzfs_fini(g_zfs); 328716fd348SMartin Matuska return (MOUNT_USAGE); 329716fd348SMartin Matuska } 330716fd348SMartin Matuska 331716fd348SMartin Matuska if (verbose) 332716fd348SMartin Matuska (void) fprintf(stdout, gettext("mount.zfs:\n" 333716fd348SMartin Matuska " dataset: \"%s\"\n mountpoint: \"%s\"\n" 334716fd348SMartin Matuska " mountflags: 0x%lx\n zfsflags: 0x%lx\n" 335716fd348SMartin Matuska " mountopts: \"%s\"\n mtabopts: \"%s\"\n"), 336716fd348SMartin Matuska dataset, mntpoint, mntflags, zfsflags, mntopts, mtabopt); 337716fd348SMartin Matuska 338716fd348SMartin Matuska if (!fake) { 339*e2df9bb4SMartin Matuska if (!remount && !sloppy && 340716fd348SMartin Matuska !libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) { 341716fd348SMartin Matuska error = zfs_mount_at(zhp, mntopts, mntflags, mntpoint); 342716fd348SMartin Matuska if (error) { 343716fd348SMartin Matuska (void) fprintf(stderr, "zfs_mount_at() failed: " 344716fd348SMartin Matuska "%s", libzfs_error_description(g_zfs)); 345716fd348SMartin Matuska zfs_close(zhp); 346716fd348SMartin Matuska libzfs_fini(g_zfs); 347716fd348SMartin Matuska return (MOUNT_SYSERR); 348716fd348SMartin Matuska } 349716fd348SMartin Matuska } else { 350716fd348SMartin Matuska error = mount(dataset, mntpoint, MNTTYPE_ZFS, 351716fd348SMartin Matuska mntflags, mntopts); 352716fd348SMartin Matuska } 353716fd348SMartin Matuska } 354716fd348SMartin Matuska 355716fd348SMartin Matuska zfs_close(zhp); 356716fd348SMartin Matuska libzfs_fini(g_zfs); 357716fd348SMartin Matuska 358716fd348SMartin Matuska if (error) { 359716fd348SMartin Matuska switch (errno) { 360716fd348SMartin Matuska case ENOENT: 361716fd348SMartin Matuska (void) fprintf(stderr, gettext("mount point " 362716fd348SMartin Matuska "'%s' does not exist\n"), mntpoint); 363716fd348SMartin Matuska return (MOUNT_SYSERR); 364716fd348SMartin Matuska case EBUSY: 365716fd348SMartin Matuska (void) fprintf(stderr, gettext("filesystem " 366716fd348SMartin Matuska "'%s' is already mounted\n"), dataset); 367716fd348SMartin Matuska return (MOUNT_BUSY); 368716fd348SMartin Matuska case ENOTSUP: 369716fd348SMartin Matuska if (zfs_version > ZPL_VERSION) { 370716fd348SMartin Matuska (void) fprintf(stderr, 371716fd348SMartin Matuska gettext("filesystem '%s' (v%d) is not " 372716fd348SMartin Matuska "supported by this implementation of " 373716fd348SMartin Matuska "ZFS (max v%d).\n"), dataset, 374716fd348SMartin Matuska (int)zfs_version, (int)ZPL_VERSION); 375716fd348SMartin Matuska } else { 376716fd348SMartin Matuska (void) fprintf(stderr, 377716fd348SMartin Matuska gettext("filesystem '%s' mount " 378716fd348SMartin Matuska "failed for unknown reason.\n"), dataset); 379716fd348SMartin Matuska } 380716fd348SMartin Matuska return (MOUNT_SYSERR); 381716fd348SMartin Matuska #ifdef MS_MANDLOCK 382716fd348SMartin Matuska case EPERM: 383716fd348SMartin Matuska if (mntflags & MS_MANDLOCK) { 384716fd348SMartin Matuska (void) fprintf(stderr, gettext("filesystem " 385716fd348SMartin Matuska "'%s' has the 'nbmand=on' property set, " 386716fd348SMartin Matuska "this mount\noption may be disabled in " 387716fd348SMartin Matuska "your kernel. Use 'zfs set nbmand=off'\n" 388716fd348SMartin Matuska "to disable this option and try to " 389716fd348SMartin Matuska "mount the filesystem again.\n"), dataset); 390716fd348SMartin Matuska return (MOUNT_SYSERR); 391716fd348SMartin Matuska } 392716fd348SMartin Matuska #endif 393716fd348SMartin Matuska zfs_fallthrough; 394716fd348SMartin Matuska default: 395716fd348SMartin Matuska (void) fprintf(stderr, gettext("filesystem " 396716fd348SMartin Matuska "'%s' can not be mounted: %s\n"), dataset, 397716fd348SMartin Matuska strerror(errno)); 398716fd348SMartin Matuska return (MOUNT_USAGE); 399716fd348SMartin Matuska } 400716fd348SMartin Matuska } 401716fd348SMartin Matuska 402716fd348SMartin Matuska if (!nomtab && mtab_is_writeable()) { 403716fd348SMartin Matuska error = mtab_update(dataset, mntpoint, MNTTYPE_ZFS, mtabopt); 404716fd348SMartin Matuska if (error) 405716fd348SMartin Matuska return (error); 406716fd348SMartin Matuska } 407716fd348SMartin Matuska 408716fd348SMartin Matuska return (MOUNT_SUCCESS); 409716fd348SMartin Matuska } 410