Print this page


Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/zfs/zfs_main.c
          +++ new/usr/src/cmd/zfs/zfs_main.c
↓ open down ↓ 69 lines elided ↑ open up ↑
  70   70  static int zfs_do_upgrade(int argc, char **argv);
  71   71  static int zfs_do_snapshot(int argc, char **argv);
  72   72  static int zfs_do_unmount(int argc, char **argv);
  73   73  static int zfs_do_share(int argc, char **argv);
  74   74  static int zfs_do_unshare(int argc, char **argv);
  75   75  static int zfs_do_send(int argc, char **argv);
  76   76  static int zfs_do_receive(int argc, char **argv);
  77   77  static int zfs_do_promote(int argc, char **argv);
  78   78  static int zfs_do_allow(int argc, char **argv);
  79   79  static int zfs_do_unallow(int argc, char **argv);
       80 +static int zfs_do_key(int argc, char **argv);
  80   81  
  81   82  /*
  82   83   * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
  83   84   */
  84   85  
  85   86  #ifdef DEBUG
  86   87  const char *
  87   88  _umem_debug_init(void)
  88   89  {
  89   90          return ("default,verbose"); /* $UMEM_DEBUG setting */
↓ open down ↓ 19 lines elided ↑ open up ↑
 109  110          HELP_RECEIVE,
 110  111          HELP_RENAME,
 111  112          HELP_ROLLBACK,
 112  113          HELP_SEND,
 113  114          HELP_SET,
 114  115          HELP_SHARE,
 115  116          HELP_SNAPSHOT,
 116  117          HELP_UNMOUNT,
 117  118          HELP_UNSHARE,
 118  119          HELP_ALLOW,
 119      -        HELP_UNALLOW
      120 +        HELP_UNALLOW,
      121 +        HELP_KEY
 120  122  } zfs_help_t;
 121  123  
 122  124  typedef struct zfs_command {
 123  125          const char      *name;
 124  126          int             (*func)(int argc, char **argv);
 125  127          zfs_help_t      usage;
 126  128  } zfs_command_t;
 127  129  
 128  130  /*
 129  131   * Master command table.  Each ZFS command has a name, associated function, and
↓ open down ↓ 25 lines elided ↑ open up ↑
 155  157          { "unmount",    zfs_do_unmount,         HELP_UNMOUNT            },
 156  158          { "share",      zfs_do_share,           HELP_SHARE              },
 157  159          { "unshare",    zfs_do_unshare,         HELP_UNSHARE            },
 158  160          { NULL },
 159  161          { "send",       zfs_do_send,            HELP_SEND               },
 160  162          { "receive",    zfs_do_receive,         HELP_RECEIVE            },
 161  163          { NULL },
 162  164          { "allow",      zfs_do_allow,           HELP_ALLOW              },
 163  165          { NULL },
 164  166          { "unallow",    zfs_do_unallow,         HELP_UNALLOW            },
      167 +        { NULL },
      168 +        { "key",        zfs_do_key,             HELP_KEY                },
 165  169  };
 166  170  
 167  171  #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 168  172  
 169  173  zfs_command_t *current_command;
 170  174  
 171  175  static const char *
 172  176  get_usage(zfs_help_t idx)
 173  177  {
 174  178          switch (idx) {
↓ open down ↓ 68 lines elided ↑ open up ↑
 243  247          case HELP_UNALLOW:
 244  248                  return (gettext("\tunallow [-rldug] "
 245  249                      "<\"everyone\"|user|group>[,...]\n"
 246  250                      "\t    [<perm|@setname>[,...]] <filesystem|volume>\n"
 247  251                      "\tunallow [-rld] -e [<perm|@setname>[,...]] "
 248  252                      "<filesystem|volume>\n"
 249  253                      "\tunallow [-r] -c [<perm|@setname>[,...]] "
 250  254                      "<filesystem|volume>\n"
 251  255                      "\tunallow [-r] -s @setname [<perm|@setname>[,...]] "
 252  256                      "<filesystem|volume>\n"));
      257 +        case HELP_KEY:
      258 +                return (gettext("\tkey <-l | -u | -c [ -o <property=value>]> "
      259 +                    "<-a | filesystem>\n"));
 253  260          }
 254  261  
 255  262          abort();
 256  263          /* NOTREACHED */
 257  264  }
 258  265  
 259  266  /*
 260  267   * Utility function to guarantee malloc() success.
 261  268   */
 262  269  void *
↓ open down ↓ 2791 lines elided ↑ open up ↑
3054 3061  
3055 3062                          (void) fprintf(stderr, gettext("cannot %s '%s': "
3056 3063                              "permission denied\n"), cmdname,
3057 3064                              zfs_get_name(zhp));
3058 3065                          return (1);
3059 3066                  }
3060 3067  
3061 3068                  /*
3062 3069                   * Ignore any filesystems which don't apply to us. This
3063 3070                   * includes those with a legacy mountpoint, or those with
3064      -                 * legacy share options.
     3071 +                 * legacy share options.  We also have to ignore those
     3072 +                 * that are encrypted that don't currently have their
     3073 +                 * key available.
3065 3074                   */
3066 3075                  verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
3067 3076                      sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
3068 3077                  verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts,
3069 3078                      sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0);
3070 3079                  verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB, smbshareopts,
3071 3080                      sizeof (smbshareopts), NULL, NULL, 0, B_FALSE) == 0);
3072 3081  
3073 3082                  if (op == OP_SHARE && strcmp(shareopts, "off") == 0 &&
3074 3083                      strcmp(smbshareopts, "off") == 0) {
↓ open down ↓ 48 lines elided ↑ open up ↑
3123 3132                                  return (0);
3124 3133  
3125 3134                          (void) fprintf(stderr, gettext("cannot %s '%s': "
3126 3135                              "'canmount' property is set to 'off'\n"), cmdname,
3127 3136                              zfs_get_name(zhp));
3128 3137                          return (1);
3129 3138                  } else if (canmount == ZFS_CANMOUNT_NOAUTO && !explicit) {
3130 3139                          return (0);
3131 3140                  }
3132 3141  
     3142 +
3133 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 +                /*
3134 3159                   * At this point, we have verified that the mountpoint and/or
3135 3160                   * shareopts are appropriate for auto management. If the
3136 3161                   * filesystem is already mounted or shared, return (failing
3137 3162                   * for explicit requests); otherwise mount or share the
3138 3163                   * filesystem.
3139 3164                   */
3140 3165                  switch (op) {
3141 3166                  case OP_SHARE:
3142 3167  
3143 3168                          shared_nfs = zfs_is_shared_nfs(zhp, NULL);
↓ open down ↓ 199 lines elided ↑ open up ↑
3343 3368          }
3344 3369  
3345 3370          argc -= optind;
3346 3371          argv += optind;
3347 3372  
3348 3373          /* check number of arguments */
3349 3374          if (do_all) {
3350 3375                  zfs_handle_t **dslist = NULL;
3351 3376                  size_t i, count = 0;
3352 3377                  char *protocol = NULL;
     3378 +                char bypass[ZPOOL_MAXPROPLEN] = { 0 };
3353 3379  
     3380 +
3354 3381                  if (op == OP_MOUNT) {
3355 3382                          types = ZFS_TYPE_FILESYSTEM;
3356 3383                  } else if (argc > 0) {
3357 3384                          if (strcmp(argv[0], "nfs") == 0 ||
3358 3385                              strcmp(argv[0], "smb") == 0) {
3359 3386                                  types = ZFS_TYPE_FILESYSTEM;
3360 3387                          } else if (strcmp(argv[0], "iscsi") == 0) {
3361 3388                                  types = ZFS_TYPE_VOLUME;
3362 3389                          } else {
3363 3390                                  (void) fprintf(stderr, gettext("share type "
↓ open down ↓ 13 lines elided ↑ open up ↑
3377 3404                  }
3378 3405  
3379 3406                  get_all_datasets(types, &dslist, &count, verbose);
3380 3407  
3381 3408                  if (count == 0)
3382 3409                          return (0);
3383 3410  
3384 3411                  qsort(dslist, count, sizeof (void *), dataset_cmp);
3385 3412  
3386 3413                  for (i = 0; i < count; i++) {
     3414 +
3387 3415                          if (verbose)
3388 3416                                  report_mount_progress(i, count);
3389 3417  
3390      -                        if (share_mount_one(dslist[i], op, flags, protocol,
3391      -                            B_FALSE, options) != 0)
3392      -                                ret = 1;
     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 +
3393 3449                          zfs_close(dslist[i]);
3394 3450                  }
3395 3451  
3396 3452                  free(dslist);
3397 3453          } else if (argc == 0) {
3398 3454                  struct mnttab entry;
3399 3455  
3400 3456                  if ((op == OP_SHARE) || (options != NULL)) {
3401 3457                          (void) fprintf(stderr, gettext("missing filesystem "
3402 3458                              "argument (specify -a for all)\n"));
↓ open down ↓ 669 lines elided ↑ open up ↑
4072 4128                              "argument\n"));
4073 4129                  else
4074 4130                          (void) fprintf(stderr, gettext("too many arguments\n"));
4075 4131                  (void) fprintf(stderr, gettext("usage: unmount [-f] <path>\n"));
4076 4132                  return (2);
4077 4133          }
4078 4134  
4079 4135          return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE));
4080 4136  }
4081 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 +
4082 4335  static int
4083 4336  volcheck(zpool_handle_t *zhp, void *data)
4084 4337  {
4085 4338          boolean_t isinit = *((boolean_t *)data);
4086 4339  
4087 4340          if (isinit)
4088 4341                  return (zpool_create_zvol_links(zhp));
4089 4342          else
4090 4343                  return (zpool_remove_zvol_links(zhp));
4091 4344  }
↓ open down ↓ 137 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX