Print this page




  60 static int zfs_do_clone(int argc, char **argv);
  61 static int zfs_do_create(int argc, char **argv);
  62 static int zfs_do_destroy(int argc, char **argv);
  63 static int zfs_do_get(int argc, char **argv);
  64 static int zfs_do_inherit(int argc, char **argv);
  65 static int zfs_do_list(int argc, char **argv);
  66 static int zfs_do_mount(int argc, char **argv);
  67 static int zfs_do_rename(int argc, char **argv);
  68 static int zfs_do_rollback(int argc, char **argv);
  69 static int zfs_do_set(int argc, char **argv);
  70 static int zfs_do_upgrade(int argc, char **argv);
  71 static int zfs_do_snapshot(int argc, char **argv);
  72 static int zfs_do_unmount(int argc, char **argv);
  73 static int zfs_do_share(int argc, char **argv);
  74 static int zfs_do_unshare(int argc, char **argv);
  75 static int zfs_do_send(int argc, char **argv);
  76 static int zfs_do_receive(int argc, char **argv);
  77 static int zfs_do_promote(int argc, char **argv);
  78 static int zfs_do_allow(int argc, char **argv);
  79 static int zfs_do_unallow(int argc, char **argv);

  80 
  81 /*
  82  * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
  83  */
  84 
  85 #ifdef DEBUG
  86 const char *
  87 _umem_debug_init(void)
  88 {
  89         return ("default,verbose"); /* $UMEM_DEBUG setting */
  90 }
  91 
  92 const char *
  93 _umem_logging_init(void)
  94 {
  95         return ("fail,contents"); /* $UMEM_LOGGING setting */
  96 }
  97 #endif
  98 
  99 typedef enum {
 100         HELP_CLONE,
 101         HELP_CREATE,
 102         HELP_DESTROY,
 103         HELP_GET,
 104         HELP_INHERIT,
 105         HELP_UPGRADE,
 106         HELP_LIST,
 107         HELP_MOUNT,
 108         HELP_PROMOTE,
 109         HELP_RECEIVE,
 110         HELP_RENAME,
 111         HELP_ROLLBACK,
 112         HELP_SEND,
 113         HELP_SET,
 114         HELP_SHARE,
 115         HELP_SNAPSHOT,
 116         HELP_UNMOUNT,
 117         HELP_UNSHARE,
 118         HELP_ALLOW,
 119         HELP_UNALLOW

 120 } zfs_help_t;
 121 
 122 typedef struct zfs_command {
 123         const char      *name;
 124         int             (*func)(int argc, char **argv);
 125         zfs_help_t      usage;
 126 } zfs_command_t;
 127 
 128 /*
 129  * Master command table.  Each ZFS command has a name, associated function, and
 130  * usage message.  The usage messages need to be internationalized, so we have
 131  * to have a function to return the usage message based on a command index.
 132  *
 133  * These commands are organized according to how they are displayed in the usage
 134  * message.  An empty command (one with a NULL name) indicates an empty line in
 135  * the generic usage message.
 136  */
 137 static zfs_command_t command_table[] = {
 138         { "create",     zfs_do_create,          HELP_CREATE             },
 139         { "destroy",    zfs_do_destroy,         HELP_DESTROY            },


 145         { "rename",     zfs_do_rename,          HELP_RENAME             },
 146         { NULL },
 147         { "list",       zfs_do_list,            HELP_LIST               },
 148         { NULL },
 149         { "set",        zfs_do_set,             HELP_SET                },
 150         { "get",        zfs_do_get,             HELP_GET                },
 151         { "inherit",    zfs_do_inherit,         HELP_INHERIT            },
 152         { "upgrade",    zfs_do_upgrade,         HELP_UPGRADE            },
 153         { NULL },
 154         { "mount",      zfs_do_mount,           HELP_MOUNT              },
 155         { "unmount",    zfs_do_unmount,         HELP_UNMOUNT            },
 156         { "share",      zfs_do_share,           HELP_SHARE              },
 157         { "unshare",    zfs_do_unshare,         HELP_UNSHARE            },
 158         { NULL },
 159         { "send",       zfs_do_send,            HELP_SEND               },
 160         { "receive",    zfs_do_receive,         HELP_RECEIVE            },
 161         { NULL },
 162         { "allow",      zfs_do_allow,           HELP_ALLOW              },
 163         { NULL },
 164         { "unallow",    zfs_do_unallow,         HELP_UNALLOW            },


 165 };
 166 
 167 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 168 
 169 zfs_command_t *current_command;
 170 
 171 static const char *
 172 get_usage(zfs_help_t idx)
 173 {
 174         switch (idx) {
 175         case HELP_CLONE:
 176                 return (gettext("\tclone [-p] [-o property=value] ... "
 177                     "<snapshot> <filesystem|volume>\n"));
 178         case HELP_CREATE:
 179                 return (gettext("\tcreate [-p] [-o property=value] ... "
 180                     "<filesystem>\n"
 181                     "\tcreate [-ps] [-b blocksize] [-o property=value] ... "
 182                     "-V <size> <volume>\n"));
 183         case HELP_DESTROY:
 184                 return (gettext("\tdestroy [-rRf] "


 233                     "<-a | filesystem|mountpoint>\n"));
 234         case HELP_ALLOW:
 235                 return (gettext("\tallow [-ldug] "
 236                     "<\"everyone\"|user|group>[,...] <perm|@setname>[,...]\n"
 237                     "\t    <filesystem|volume>\n"
 238                     "\tallow [-ld] -e <perm|@setname>[,...] "
 239                     "<filesystem|volume>\n"
 240                     "\tallow -c <perm|@setname>[,...] <filesystem|volume>\n"
 241                     "\tallow -s @setname <perm|@setname>[,...] "
 242                     "<filesystem|volume>\n"));
 243         case HELP_UNALLOW:
 244                 return (gettext("\tunallow [-rldug] "
 245                     "<\"everyone\"|user|group>[,...]\n"
 246                     "\t    [<perm|@setname>[,...]] <filesystem|volume>\n"
 247                     "\tunallow [-rld] -e [<perm|@setname>[,...]] "
 248                     "<filesystem|volume>\n"
 249                     "\tunallow [-r] -c [<perm|@setname>[,...]] "
 250                     "<filesystem|volume>\n"
 251                     "\tunallow [-r] -s @setname [<perm|@setname>[,...]] "
 252                     "<filesystem|volume>\n"));



 253         }
 254 
 255         abort();
 256         /* NOTREACHED */
 257 }
 258 
 259 /*
 260  * Utility function to guarantee malloc() success.
 261  */
 262 void *
 263 safe_malloc(size_t size)
 264 {
 265         void *data;
 266 
 267         if ((data = calloc(1, size)) == NULL) {
 268                 (void) fprintf(stderr, "internal error: out of memory\n");
 269                 exit(1);
 270         }
 271 
 272         return (data);


3044                                 return (0);
3045 
3046                         (void) fprintf(stderr, gettext("cannot %s '%s': "
3047                             "dataset is exported to a local zone\n"), cmdname,
3048                             zfs_get_name(zhp));
3049                         return (1);
3050 
3051                 } else if (!zoned && getzoneid() != GLOBAL_ZONEID) {
3052                         if (!explicit)
3053                                 return (0);
3054 
3055                         (void) fprintf(stderr, gettext("cannot %s '%s': "
3056                             "permission denied\n"), cmdname,
3057                             zfs_get_name(zhp));
3058                         return (1);
3059                 }
3060 
3061                 /*
3062                  * Ignore any filesystems which don't apply to us. This
3063                  * includes those with a legacy mountpoint, or those with
3064                  * legacy share options.


3065                  */
3066                 verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
3067                     sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
3068                 verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts,
3069                     sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0);
3070                 verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB, smbshareopts,
3071                     sizeof (smbshareopts), NULL, NULL, 0, B_FALSE) == 0);
3072 
3073                 if (op == OP_SHARE && strcmp(shareopts, "off") == 0 &&
3074                     strcmp(smbshareopts, "off") == 0) {
3075                         if (!explicit)
3076                                 return (0);
3077 
3078                         (void) fprintf(stderr, gettext("cannot share '%s': "
3079                             "legacy share\n"), zfs_get_name(zhp));
3080                         (void) fprintf(stderr, gettext("use share(1M) to "
3081                             "share this filesystem, or set "
3082                             "sharenfs property on\n"));
3083                         return (1);
3084                 }


3113                  * on           no              pass through
3114                  * on           yes             pass through
3115                  * off          no              return 0
3116                  * off          yes             display error, return 1
3117                  * noauto       no              return 0
3118                  * noauto       yes             pass through
3119                  */
3120                 canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
3121                 if (canmount == ZFS_CANMOUNT_OFF) {
3122                         if (!explicit)
3123                                 return (0);
3124 
3125                         (void) fprintf(stderr, gettext("cannot %s '%s': "
3126                             "'canmount' property is set to 'off'\n"), cmdname,
3127                             zfs_get_name(zhp));
3128                         return (1);
3129                 } else if (canmount == ZFS_CANMOUNT_NOAUTO && !explicit) {
3130                         return (0);
3131                 }
3132 

3133                 /*















3134                  * At this point, we have verified that the mountpoint and/or
3135                  * shareopts are appropriate for auto management. If the
3136                  * filesystem is already mounted or shared, return (failing
3137                  * for explicit requests); otherwise mount or share the
3138                  * filesystem.
3139                  */
3140                 switch (op) {
3141                 case OP_SHARE:
3142 
3143                         shared_nfs = zfs_is_shared_nfs(zhp, NULL);
3144                         shared_smb = zfs_is_shared_smb(zhp, NULL);
3145 
3146                         if (shared_nfs && shared_smb ||
3147                             (shared_nfs && strcmp(shareopts, "on") == 0 &&
3148                             strcmp(smbshareopts, "off") == 0) ||
3149                             (shared_smb && strcmp(smbshareopts, "on") == 0 &&
3150                             strcmp(shareopts, "off") == 0)) {
3151                                 if (!explicit)
3152                                         return (0);
3153 


3333                 case ':':
3334                         (void) fprintf(stderr, gettext("missing argument for "
3335                             "'%c' option\n"), optopt);
3336                         usage(B_FALSE);
3337                         break;
3338                 case '?':
3339                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3340                             optopt);
3341                         usage(B_FALSE);
3342                 }
3343         }
3344 
3345         argc -= optind;
3346         argv += optind;
3347 
3348         /* check number of arguments */
3349         if (do_all) {
3350                 zfs_handle_t **dslist = NULL;
3351                 size_t i, count = 0;
3352                 char *protocol = NULL;

3353 

3354                 if (op == OP_MOUNT) {
3355                         types = ZFS_TYPE_FILESYSTEM;
3356                 } else if (argc > 0) {
3357                         if (strcmp(argv[0], "nfs") == 0 ||
3358                             strcmp(argv[0], "smb") == 0) {
3359                                 types = ZFS_TYPE_FILESYSTEM;
3360                         } else if (strcmp(argv[0], "iscsi") == 0) {
3361                                 types = ZFS_TYPE_VOLUME;
3362                         } else {
3363                                 (void) fprintf(stderr, gettext("share type "
3364                                     "must be 'nfs', 'smb' or 'iscsi'\n"));
3365                                 usage(B_FALSE);
3366                         }
3367                         protocol = argv[0];
3368                         argc--;
3369                         argv++;
3370                 } else {
3371                         types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
3372                 }
3373 
3374                 if (argc != 0) {
3375                         (void) fprintf(stderr, gettext("too many arguments\n"));
3376                         usage(B_FALSE);
3377                 }
3378 
3379                 get_all_datasets(types, &dslist, &count, verbose);
3380 
3381                 if (count == 0)
3382                         return (0);
3383 
3384                 qsort(dslist, count, sizeof (void *), dataset_cmp);
3385 
3386                 for (i = 0; i < count; i++) {

3387                         if (verbose)
3388                                 report_mount_progress(i, count);
3389 
3390                         if (share_mount_one(dslist[i], op, flags, protocol,
3391                             B_FALSE, options) != 0)

























3392                                 ret = 1;



3393                         zfs_close(dslist[i]);
3394                 }
3395 
3396                 free(dslist);
3397         } else if (argc == 0) {
3398                 struct mnttab entry;
3399 
3400                 if ((op == OP_SHARE) || (options != NULL)) {
3401                         (void) fprintf(stderr, gettext("missing filesystem "
3402                             "argument (specify -a for all)\n"));
3403                         usage(B_FALSE);
3404                 }
3405 
3406                 /*
3407                  * When mount is given no arguments, go through /etc/mnttab and
3408                  * display any active ZFS mounts.  We hide any snapshots, since
3409                  * they are controlled automatically.
3410                  */
3411                 rewind(mnttab_file);
3412                 while (getmntent(mnttab_file, &entry) == 0) {


4062                 }
4063         }
4064 
4065         argc -= optind;
4066         argv += optind;
4067 
4068         /* check arguments */
4069         if (argc != 1) {
4070                 if (argc == 0)
4071                         (void) fprintf(stderr, gettext("missing path "
4072                             "argument\n"));
4073                 else
4074                         (void) fprintf(stderr, gettext("too many arguments\n"));
4075                 (void) fprintf(stderr, gettext("usage: unmount [-f] <path>\n"));
4076                 return (2);
4077         }
4078 
4079         return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE));
4080 }
4081 





































































































































































































4082 static int
4083 volcheck(zpool_handle_t *zhp, void *data)
4084 {
4085         boolean_t isinit = *((boolean_t *)data);
4086 
4087         if (isinit)
4088                 return (zpool_create_zvol_links(zhp));
4089         else
4090                 return (zpool_remove_zvol_links(zhp));
4091 }
4092 
4093 /*
4094  * Iterate over all pools in the system and either create or destroy /dev/zvol
4095  * links, depending on the value of 'isinit'.
4096  */
4097 static int
4098 do_volcheck(boolean_t isinit)
4099 {
4100         return (zpool_iter(g_zfs, volcheck, &isinit) ? 1 : 0);
4101 }




  60 static int zfs_do_clone(int argc, char **argv);
  61 static int zfs_do_create(int argc, char **argv);
  62 static int zfs_do_destroy(int argc, char **argv);
  63 static int zfs_do_get(int argc, char **argv);
  64 static int zfs_do_inherit(int argc, char **argv);
  65 static int zfs_do_list(int argc, char **argv);
  66 static int zfs_do_mount(int argc, char **argv);
  67 static int zfs_do_rename(int argc, char **argv);
  68 static int zfs_do_rollback(int argc, char **argv);
  69 static int zfs_do_set(int argc, char **argv);
  70 static int zfs_do_upgrade(int argc, char **argv);
  71 static int zfs_do_snapshot(int argc, char **argv);
  72 static int zfs_do_unmount(int argc, char **argv);
  73 static int zfs_do_share(int argc, char **argv);
  74 static int zfs_do_unshare(int argc, char **argv);
  75 static int zfs_do_send(int argc, char **argv);
  76 static int zfs_do_receive(int argc, char **argv);
  77 static int zfs_do_promote(int argc, char **argv);
  78 static int zfs_do_allow(int argc, char **argv);
  79 static int zfs_do_unallow(int argc, char **argv);
  80 static int zfs_do_key(int argc, char **argv);
  81 
  82 /*
  83  * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
  84  */
  85 
  86 #ifdef DEBUG
  87 const char *
  88 _umem_debug_init(void)
  89 {
  90         return ("default,verbose"); /* $UMEM_DEBUG setting */
  91 }
  92 
  93 const char *
  94 _umem_logging_init(void)
  95 {
  96         return ("fail,contents"); /* $UMEM_LOGGING setting */
  97 }
  98 #endif
  99 
 100 typedef enum {
 101         HELP_CLONE,
 102         HELP_CREATE,
 103         HELP_DESTROY,
 104         HELP_GET,
 105         HELP_INHERIT,
 106         HELP_UPGRADE,
 107         HELP_LIST,
 108         HELP_MOUNT,
 109         HELP_PROMOTE,
 110         HELP_RECEIVE,
 111         HELP_RENAME,
 112         HELP_ROLLBACK,
 113         HELP_SEND,
 114         HELP_SET,
 115         HELP_SHARE,
 116         HELP_SNAPSHOT,
 117         HELP_UNMOUNT,
 118         HELP_UNSHARE,
 119         HELP_ALLOW,
 120         HELP_UNALLOW,
 121         HELP_KEY
 122 } zfs_help_t;
 123 
 124 typedef struct zfs_command {
 125         const char      *name;
 126         int             (*func)(int argc, char **argv);
 127         zfs_help_t      usage;
 128 } zfs_command_t;
 129 
 130 /*
 131  * Master command table.  Each ZFS command has a name, associated function, and
 132  * usage message.  The usage messages need to be internationalized, so we have
 133  * to have a function to return the usage message based on a command index.
 134  *
 135  * These commands are organized according to how they are displayed in the usage
 136  * message.  An empty command (one with a NULL name) indicates an empty line in
 137  * the generic usage message.
 138  */
 139 static zfs_command_t command_table[] = {
 140         { "create",     zfs_do_create,          HELP_CREATE             },
 141         { "destroy",    zfs_do_destroy,         HELP_DESTROY            },


 147         { "rename",     zfs_do_rename,          HELP_RENAME             },
 148         { NULL },
 149         { "list",       zfs_do_list,            HELP_LIST               },
 150         { NULL },
 151         { "set",        zfs_do_set,             HELP_SET                },
 152         { "get",        zfs_do_get,             HELP_GET                },
 153         { "inherit",    zfs_do_inherit,         HELP_INHERIT            },
 154         { "upgrade",    zfs_do_upgrade,         HELP_UPGRADE            },
 155         { NULL },
 156         { "mount",      zfs_do_mount,           HELP_MOUNT              },
 157         { "unmount",    zfs_do_unmount,         HELP_UNMOUNT            },
 158         { "share",      zfs_do_share,           HELP_SHARE              },
 159         { "unshare",    zfs_do_unshare,         HELP_UNSHARE            },
 160         { NULL },
 161         { "send",       zfs_do_send,            HELP_SEND               },
 162         { "receive",    zfs_do_receive,         HELP_RECEIVE            },
 163         { NULL },
 164         { "allow",      zfs_do_allow,           HELP_ALLOW              },
 165         { NULL },
 166         { "unallow",    zfs_do_unallow,         HELP_UNALLOW            },
 167         { NULL },
 168         { "key",        zfs_do_key,             HELP_KEY                },
 169 };
 170 
 171 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 172 
 173 zfs_command_t *current_command;
 174 
 175 static const char *
 176 get_usage(zfs_help_t idx)
 177 {
 178         switch (idx) {
 179         case HELP_CLONE:
 180                 return (gettext("\tclone [-p] [-o property=value] ... "
 181                     "<snapshot> <filesystem|volume>\n"));
 182         case HELP_CREATE:
 183                 return (gettext("\tcreate [-p] [-o property=value] ... "
 184                     "<filesystem>\n"
 185                     "\tcreate [-ps] [-b blocksize] [-o property=value] ... "
 186                     "-V <size> <volume>\n"));
 187         case HELP_DESTROY:
 188                 return (gettext("\tdestroy [-rRf] "


 237                     "<-a | filesystem|mountpoint>\n"));
 238         case HELP_ALLOW:
 239                 return (gettext("\tallow [-ldug] "
 240                     "<\"everyone\"|user|group>[,...] <perm|@setname>[,...]\n"
 241                     "\t    <filesystem|volume>\n"
 242                     "\tallow [-ld] -e <perm|@setname>[,...] "
 243                     "<filesystem|volume>\n"
 244                     "\tallow -c <perm|@setname>[,...] <filesystem|volume>\n"
 245                     "\tallow -s @setname <perm|@setname>[,...] "
 246                     "<filesystem|volume>\n"));
 247         case HELP_UNALLOW:
 248                 return (gettext("\tunallow [-rldug] "
 249                     "<\"everyone\"|user|group>[,...]\n"
 250                     "\t    [<perm|@setname>[,...]] <filesystem|volume>\n"
 251                     "\tunallow [-rld] -e [<perm|@setname>[,...]] "
 252                     "<filesystem|volume>\n"
 253                     "\tunallow [-r] -c [<perm|@setname>[,...]] "
 254                     "<filesystem|volume>\n"
 255                     "\tunallow [-r] -s @setname [<perm|@setname>[,...]] "
 256                     "<filesystem|volume>\n"));
 257         case HELP_KEY:
 258                 return (gettext("\tkey <-l | -u | -c [ -o <property=value>]> "
 259                     "<-a | filesystem>\n"));
 260         }
 261 
 262         abort();
 263         /* NOTREACHED */
 264 }
 265 
 266 /*
 267  * Utility function to guarantee malloc() success.
 268  */
 269 void *
 270 safe_malloc(size_t size)
 271 {
 272         void *data;
 273 
 274         if ((data = calloc(1, size)) == NULL) {
 275                 (void) fprintf(stderr, "internal error: out of memory\n");
 276                 exit(1);
 277         }
 278 
 279         return (data);


3051                                 return (0);
3052 
3053                         (void) fprintf(stderr, gettext("cannot %s '%s': "
3054                             "dataset is exported to a local zone\n"), cmdname,
3055                             zfs_get_name(zhp));
3056                         return (1);
3057 
3058                 } else if (!zoned && getzoneid() != GLOBAL_ZONEID) {
3059                         if (!explicit)
3060                                 return (0);
3061 
3062                         (void) fprintf(stderr, gettext("cannot %s '%s': "
3063                             "permission denied\n"), cmdname,
3064                             zfs_get_name(zhp));
3065                         return (1);
3066                 }
3067 
3068                 /*
3069                  * Ignore any filesystems which don't apply to us. This
3070                  * includes those with a legacy mountpoint, or those with
3071                  * legacy share options.  We also have to ignore those
3072                  * that are encrypted that don't currently have their
3073                  * key available.
3074                  */
3075                 verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
3076                     sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
3077                 verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts,
3078                     sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0);
3079                 verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB, smbshareopts,
3080                     sizeof (smbshareopts), NULL, NULL, 0, B_FALSE) == 0);
3081 
3082                 if (op == OP_SHARE && strcmp(shareopts, "off") == 0 &&
3083                     strcmp(smbshareopts, "off") == 0) {
3084                         if (!explicit)
3085                                 return (0);
3086 
3087                         (void) fprintf(stderr, gettext("cannot share '%s': "
3088                             "legacy share\n"), zfs_get_name(zhp));
3089                         (void) fprintf(stderr, gettext("use share(1M) to "
3090                             "share this filesystem, or set "
3091                             "sharenfs property on\n"));
3092                         return (1);
3093                 }


3122                  * on           no              pass through
3123                  * on           yes             pass through
3124                  * off          no              return 0
3125                  * off          yes             display error, return 1
3126                  * noauto       no              return 0
3127                  * noauto       yes             pass through
3128                  */
3129                 canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
3130                 if (canmount == ZFS_CANMOUNT_OFF) {
3131                         if (!explicit)
3132                                 return (0);
3133 
3134                         (void) fprintf(stderr, gettext("cannot %s '%s': "
3135                             "'canmount' property is set to 'off'\n"), cmdname,
3136                             zfs_get_name(zhp));
3137                         return (1);
3138                 } else if (canmount == ZFS_CANMOUNT_NOAUTO && !explicit) {
3139                         return (0);
3140                 }
3141 
3142 
3143                 /*
3144                  * Only need to check for ZFS_CRYPT_KEY_UNAVAILABLE since
3145                  * datasets that aren't encrypted have a keystatus of
3146                  * ZFS_CRYPT_KEY_UNDEFINED.
3147                  */
3148                 if (zfs_mount_crypto_check(zhp) != 0) {
3149                         if (!explicit)
3150                                 return (0);
3151 
3152                         (void) fprintf(stderr, gettext("cannot %s '%s': "
3153                             "encryption key unavailable\n"), cmdname,
3154                             zfs_get_name(zhp));
3155                         return (1);
3156                 }
3157 
3158                 /*
3159                  * At this point, we have verified that the mountpoint and/or
3160                  * shareopts are appropriate for auto management. If the
3161                  * filesystem is already mounted or shared, return (failing
3162                  * for explicit requests); otherwise mount or share the
3163                  * filesystem.
3164                  */
3165                 switch (op) {
3166                 case OP_SHARE:
3167 
3168                         shared_nfs = zfs_is_shared_nfs(zhp, NULL);
3169                         shared_smb = zfs_is_shared_smb(zhp, NULL);
3170 
3171                         if (shared_nfs && shared_smb ||
3172                             (shared_nfs && strcmp(shareopts, "on") == 0 &&
3173                             strcmp(smbshareopts, "off") == 0) ||
3174                             (shared_smb && strcmp(smbshareopts, "on") == 0 &&
3175                             strcmp(shareopts, "off") == 0)) {
3176                                 if (!explicit)
3177                                         return (0);
3178 


3358                 case ':':
3359                         (void) fprintf(stderr, gettext("missing argument for "
3360                             "'%c' option\n"), optopt);
3361                         usage(B_FALSE);
3362                         break;
3363                 case '?':
3364                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3365                             optopt);
3366                         usage(B_FALSE);
3367                 }
3368         }
3369 
3370         argc -= optind;
3371         argv += optind;
3372 
3373         /* check number of arguments */
3374         if (do_all) {
3375                 zfs_handle_t **dslist = NULL;
3376                 size_t i, count = 0;
3377                 char *protocol = NULL;
3378                 char bypass[ZPOOL_MAXPROPLEN] = { 0 };
3379 
3380 
3381                 if (op == OP_MOUNT) {
3382                         types = ZFS_TYPE_FILESYSTEM;
3383                 } else if (argc > 0) {
3384                         if (strcmp(argv[0], "nfs") == 0 ||
3385                             strcmp(argv[0], "smb") == 0) {
3386                                 types = ZFS_TYPE_FILESYSTEM;
3387                         } else if (strcmp(argv[0], "iscsi") == 0) {
3388                                 types = ZFS_TYPE_VOLUME;
3389                         } else {
3390                                 (void) fprintf(stderr, gettext("share type "
3391                                     "must be 'nfs', 'smb' or 'iscsi'\n"));
3392                                 usage(B_FALSE);
3393                         }
3394                         protocol = argv[0];
3395                         argc--;
3396                         argv++;
3397                 } else {
3398                         types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
3399                 }
3400 
3401                 if (argc != 0) {
3402                         (void) fprintf(stderr, gettext("too many arguments\n"));
3403                         usage(B_FALSE);
3404                 }
3405 
3406                 get_all_datasets(types, &dslist, &count, verbose);
3407 
3408                 if (count == 0)
3409                         return (0);
3410 
3411                 qsort(dslist, count, sizeof (void *), dataset_cmp);
3412 
3413                 for (i = 0; i < count; i++) {
3414 
3415                         if (verbose)
3416                                 report_mount_progress(i, count);
3417 
3418                         /*
3419                          * If bypass has a dataset value, then we need to skip
3420                          * any datasets that are underneath it.
3421                          */
3422                         if (bypass[0] != NULL) {
3423                                 int len = strlen(bypass);
3424                                 char *ds_name = (char *)zfs_get_name(dslist[i]);
3425 
3426                                 if (strncmp(bypass, ds_name, len) == 0 &&
3427                                     (strlen(ds_name) > len) &&
3428                                     ds_name[len] == '/') {
3429                                         zfs_close(dslist[i]);
3430                                         continue;
3431                                 } else
3432                                         bypass[0] = '\0';
3433                         }
3434 
3435                         /*
3436                          * Check if the dataset has a key before loading, if
3437                          * no, then store it in 'bypass'.
3438                          */
3439                         if (zfs_mount_crypto_check(dslist[i])) {
3440                                 (void) strlcpy(bypass, zfs_get_name(dslist[i]),
3441                                     ZPOOL_MAXPROPLEN);
3442                         } else {
3443                                 if (share_mount_one(dslist[i], op, flags,
3444                                     protocol, B_FALSE, options) != 0) {
3445                                         ret = 1;
3446                                 }
3447                         }
3448 
3449                         zfs_close(dslist[i]);
3450                 }
3451 
3452                 free(dslist);
3453         } else if (argc == 0) {
3454                 struct mnttab entry;
3455 
3456                 if ((op == OP_SHARE) || (options != NULL)) {
3457                         (void) fprintf(stderr, gettext("missing filesystem "
3458                             "argument (specify -a for all)\n"));
3459                         usage(B_FALSE);
3460                 }
3461 
3462                 /*
3463                  * When mount is given no arguments, go through /etc/mnttab and
3464                  * display any active ZFS mounts.  We hide any snapshots, since
3465                  * they are controlled automatically.
3466                  */
3467                 rewind(mnttab_file);
3468                 while (getmntent(mnttab_file, &entry) == 0) {


4118                 }
4119         }
4120 
4121         argc -= optind;
4122         argv += optind;
4123 
4124         /* check arguments */
4125         if (argc != 1) {
4126                 if (argc == 0)
4127                         (void) fprintf(stderr, gettext("missing path "
4128                             "argument\n"));
4129                 else
4130                         (void) fprintf(stderr, gettext("too many arguments\n"));
4131                 (void) fprintf(stderr, gettext("usage: unmount [-f] <path>\n"));
4132                 return (2);
4133         }
4134 
4135         return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE));
4136 }
4137 
4138 int
4139 zfs_do_key(int argc, char **argv)
4140 {
4141         int error = 1, options = 0;
4142         nvlist_t *props = NULL;
4143         char c, *propname, *propval = NULL;
4144         boolean_t load = B_FALSE, unload = B_FALSE, change = B_FALSE;
4145         boolean_t do_all = B_FALSE;
4146         char *strval;
4147         zfs_handle_t **dslist = NULL, *zhp = NULL;
4148         uint_t count;
4149         zfs_prop_t zprop;
4150 
4151         while ((c = getopt(argc, argv, "aluco:")) != -1) {
4152                 switch (c) {
4153                 case 'a':
4154                         do_all = B_TRUE;
4155                         break;
4156 
4157                 case 'l':
4158                         load = B_TRUE;
4159                         break;
4160 
4161                 case 'u':
4162                         unload = B_TRUE;
4163                         break;
4164 
4165                 case 'c':
4166                         change = B_TRUE;
4167                         break;
4168 
4169                 case 'o':
4170                         /* Key change is the only command that allows options */
4171                         if (change != B_TRUE) {
4172                                 (void) fprintf(stderr, gettext("Property "
4173                                     "options only allowed during key "
4174                                     "change.\n"));
4175                                 usage(B_FALSE);
4176                                 goto error;
4177                         }
4178 
4179                         propname = optarg;
4180                         if ((propval = strchr(optarg, '=')) == NULL) {
4181                                 (void) fprintf(stderr, gettext("missing "
4182                                     "'=' for -o option\n"));
4183                                 goto error;
4184                         }
4185 
4186                         *propval = '\0';
4187                         propval++;
4188 
4189                         zprop = zfs_name_to_prop(propname);
4190                         switch (zprop) {
4191                         case ZFS_PROP_KEYSOURCE:
4192                         case ZFS_PROP_KEYSCOPE:
4193                                 break;
4194 
4195                         default:
4196                                 (void) fprintf(stderr, gettext("Invalid "
4197                                     "property for key operation: '%s'\n"),
4198                                     propname);
4199                                 goto error;
4200                         };
4201 
4202                         if (props == NULL &&
4203                             nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
4204                                 (void) fprintf(stderr, gettext("internal "
4205                                     "error: out of memory\n"));
4206                                 goto error;
4207                         }
4208 
4209                         if (nvlist_lookup_string(props, propname,
4210                             &strval) == 0) {
4211                                 (void) fprintf(stderr, gettext("property '%s' "
4212                                     "specified multiple times\n"), propname);
4213                                 goto error;
4214                         }
4215                         if (nvlist_add_string(props, propname, propval) != 0) {
4216                                 (void) fprintf(stderr, gettext("internal "
4217                                     "error: out of memory\n"));
4218                                 goto error;
4219                         }
4220 
4221                         options += 2;
4222                         break;
4223 
4224                 case '?':
4225                 default:
4226                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4227                             optopt);
4228                         usage(B_FALSE);
4229 
4230                 }
4231         }
4232 
4233         if (!change && props != NULL)
4234                 (void) fprintf(stderr, gettext("Properties are not allowed to "
4235                     "be used in this command.\n"));
4236 
4237         if (((load || unload) && (argc > 3)) ||
4238             (change && ((argc - options) > 3))) {
4239                         (void) fprintf(stderr,
4240                             gettext("too many arguments\n"));
4241                         usage(B_FALSE);
4242                         goto error;
4243         } else if ((load || unload) && (argc < 3)) {
4244                         (void) fprintf(stderr, gettext("missing dataset "
4245                             "argument (specify -a for all)\n"));
4246                         usage(B_FALSE);
4247                         goto error;
4248         } else if (change && ((argc - options) < 3)) {
4249                         (void) fprintf(stderr, gettext("missing dataset "
4250                             "argument\n"));
4251                         usage(B_FALSE);
4252                         goto error;
4253         }
4254 
4255         if (do_all == B_FALSE) {
4256                 zhp = zfs_open(g_zfs, argv[argc - 1],
4257                     ZFS_TYPE_FILESYSTEM|ZFS_TYPE_VOLUME);
4258                 if (zhp == NULL)
4259                         goto error;
4260 
4261         } else if (change) {
4262                 /* We don't support do_all in a change operation */
4263 
4264                 (void) fprintf(stderr, gettext("cannot use '-a' with "
4265                     "change operation.\n"));
4266                 usage(B_FALSE);
4267                 goto error;
4268 
4269         } else {
4270                 get_all_datasets(ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
4271                     &dslist, &count, B_FALSE);
4272                 if (count == 0)
4273                         return (0);
4274 
4275                 qsort(dslist, count, sizeof (void *), dataset_cmp);
4276         }
4277 
4278         if (load) {
4279                 if (do_all) {
4280                         int i;
4281                         zfs_crypt_t *cry = NULL;
4282 
4283                         cry = calloc(1, sizeof (zfs_crypt_t));
4284                         for (i = 0; i < count; i++) {
4285                                 if (zfs_is_encrypted(dslist[i])) {
4286                                         zfs_set_libzfs_cry(dslist[i], cry);
4287                                         (void) zfs_load_key(dslist[i]);
4288                                         bzero(cry, sizeof (zfs_crypt_t));
4289                                 }
4290                                 zfs_close(dslist[i]);
4291                         }
4292 
4293                         free(cry);
4294                         free(dslist);
4295                         error = 0;
4296 
4297                 } else
4298                         error = zfs_cmd_key_load(zhp);
4299 
4300         } else if (unload) {
4301                 if (do_all) {
4302                         int i;
4303 
4304                         /* Do in reverse order so we can unmount easily */
4305                         for (i = count - 1; i > 0; i--) {
4306                                 if (zfs_is_encrypted(dslist[i]))
4307                                         (void) zfs_unload_key(dslist[i]);
4308 
4309                                 zfs_close(dslist[i]);
4310                         }
4311 
4312                         free(dslist);
4313                         error = 0;
4314 
4315                 } else
4316                         error = zfs_cmd_key_unload(zhp);
4317 
4318         } else if (change) {
4319                 error = zfs_cmd_key_change(zhp, props);
4320 
4321         } else
4322                 usage(B_FALSE);
4323 
4324         if (zhp != NULL)
4325                 zfs_close(zhp);
4326 
4327 error:
4328         if (props != NULL) {
4329                 nvlist_free(props);
4330         }
4331         return (error);
4332 }
4333 
4334 
4335 static int
4336 volcheck(zpool_handle_t *zhp, void *data)
4337 {
4338         boolean_t isinit = *((boolean_t *)data);
4339 
4340         if (isinit)
4341                 return (zpool_create_zvol_links(zhp));
4342         else
4343                 return (zpool_remove_zvol_links(zhp));
4344 }
4345 
4346 /*
4347  * Iterate over all pools in the system and either create or destroy /dev/zvol
4348  * links, depending on the value of 'isinit'.
4349  */
4350 static int
4351 do_volcheck(boolean_t isinit)
4352 {
4353         return (zpool_iter(g_zfs, volcheck, &isinit) ? 1 : 0);
4354 }