Print this page
%B

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/zfs_ioctl.c
          +++ new/usr/src/uts/common/fs/zfs/zfs_ioctl.c
↓ open down ↓ 17 lines elided ↑ open up ↑
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Portions Copyright 2011 Martin Matuska
  25   25   * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  26   26   * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  27   27   * Copyright (c) 2012 by Delphix. All rights reserved.
       28 + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
  28   29   */
  29   30  
  30   31  /*
  31   32   * ZFS ioctls.
  32   33   *
  33   34   * This file handles the ioctls to /dev/zfs, used for configuring ZFS storage
  34   35   * pools and filesystems, e.g. with /sbin/zfs and /sbin/zpool.
  35   36   *
  36   37   * There are two ways that we handle ioctls: the legacy way where almost
  37   38   * all of the logic is in the ioctl callback, and the new way where most
↓ open down ↓ 127 lines elided ↑ open up ↑
 165  166  #include <sys/mount.h>
 166  167  #include <sys/sdt.h>
 167  168  #include <sys/fs/zfs.h>
 168  169  #include <sys/zfs_ctldir.h>
 169  170  #include <sys/zfs_dir.h>
 170  171  #include <sys/zfs_onexit.h>
 171  172  #include <sys/zvol.h>
 172  173  #include <sys/dsl_scan.h>
 173  174  #include <sharefs/share.h>
 174  175  #include <sys/dmu_objset.h>
      176 +#include <sys/zfeature.h>
 175  177  
 176  178  #include "zfs_namecheck.h"
 177  179  #include "zfs_prop.h"
 178  180  #include "zfs_deleg.h"
 179  181  #include "zfs_comutil.h"
 180  182  
 181  183  extern struct modlfs zfs_modlfs;
 182  184  
 183  185  extern void zfs_init(void);
 184  186  extern void zfs_fini(void);
↓ open down ↓ 43 lines elided ↑ open up ↑
 228  230  static int zfs_ioc_userspace_upgrade(zfs_cmd_t *zc);
 229  231  static int zfs_check_settable(const char *name, nvpair_t *property,
 230  232      cred_t *cr);
 231  233  static int zfs_check_clearable(char *dataset, nvlist_t *props,
 232  234      nvlist_t **errors);
 233  235  static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *,
 234  236      boolean_t *);
 235  237  int zfs_set_prop_nvlist(const char *, zprop_source_t, nvlist_t *, nvlist_t *);
 236  238  static int get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp);
 237  239  
      240 +static int zfs_prop_activate_feature(dsl_pool_t *dp, zfeature_info_t *feature);
      241 +static int zfs_prop_activate_feature_check(void *arg1, void *arg2,
      242 +    dmu_tx_t *tx);
      243 +static void zfs_prop_activate_feature_sync(void *arg1, void *arg2,
      244 +    dmu_tx_t *tx);
      245 +
 238  246  /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */
 239  247  void
 240  248  __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
 241  249  {
 242  250          const char *newfile;
 243  251          char buf[512];
 244  252          va_list adx;
 245  253  
 246  254          /*
 247  255           * Get rid of annoying "../common/" prefix to filename.
↓ open down ↓ 2128 lines elided ↑ open up ↑
2376 2384                  if (err == 0 && intval >= ZPL_VERSION_USERSPACE) {
2377 2385                          zfs_cmd_t *zc;
2378 2386  
2379 2387                          zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
2380 2388                          (void) strcpy(zc->zc_name, dsname);
2381 2389                          (void) zfs_ioc_userspace_upgrade(zc);
2382 2390                          kmem_free(zc, sizeof (zfs_cmd_t));
2383 2391                  }
2384 2392                  break;
2385 2393          }
     2394 +        case ZFS_PROP_COMPRESSION:
     2395 +        {
     2396 +                if (intval == ZIO_COMPRESS_LZ4 ||
     2397 +                    intval == ZIO_COMPRESS_LZ4HC) {
     2398 +                        zfeature_info_t *feature =
     2399 +                            &spa_feature_table[SPA_FEATURE_LZ4_COMPRESS];
     2400 +                        spa_t *spa;
     2401 +                        dsl_pool_t *dp;
2386 2402  
     2403 +                        if ((err = spa_open(dsname, &spa, FTAG)) != 0)
     2404 +                                return (err);
     2405 +
     2406 +                        dp = spa->spa_dsl_pool;
     2407 +
     2408 +                        /*
     2409 +                         * Setting the LZ4 compression algorithm activates
     2410 +                         * the feature.
     2411 +                         */
     2412 +                        if (!spa_feature_is_active(spa, feature)) {
     2413 +                                if ((err = zfs_prop_activate_feature(dp,
     2414 +                                    feature)) != 0) {
     2415 +                                        spa_close(spa, FTAG);
     2416 +                                        return (err);
     2417 +                                }
     2418 +                        }
     2419 +
     2420 +                        spa_close(spa, FTAG);
     2421 +                }
     2422 +                /*
     2423 +                 * We still want the default set action to be performed in the
     2424 +                 * caller, we only performed zfeature settings here.
     2425 +                 */
     2426 +                err = -1;
     2427 +                break;
     2428 +        }
     2429 +
2387 2430          default:
2388 2431                  err = -1;
2389 2432          }
2390 2433  
2391 2434          return (err);
2392 2435  }
2393 2436  
2394 2437  /*
2395 2438   * This function is best effort. If it fails to set any of the given properties,
2396 2439   * it continues to set as many as it can and returns the last error
↓ open down ↓ 1223 lines elided ↑ open up ↑
3620 3663                              zfs_earlier_version(dsname,
3621 3664                              SPA_VERSION_GZIP_COMPRESSION)) {
3622 3665                                  return (ENOTSUP);
3623 3666                          }
3624 3667  
3625 3668                          if (intval == ZIO_COMPRESS_ZLE &&
3626 3669                              zfs_earlier_version(dsname,
3627 3670                              SPA_VERSION_ZLE_COMPRESSION))
3628 3671                                  return (ENOTSUP);
3629 3672  
     3673 +                        if (intval == ZIO_COMPRESS_LZ4 ||
     3674 +                            intval == ZIO_COMPRESS_LZ4HC) {
     3675 +                                zfeature_info_t *feature =
     3676 +                                    &spa_feature_table[
     3677 +                                    SPA_FEATURE_LZ4_COMPRESS];
     3678 +                                spa_t *spa;
     3679 +
     3680 +                                if ((err = spa_open(dsname, &spa, FTAG)) != 0)
     3681 +                                        return (err);
     3682 +
     3683 +                                if (!spa_feature_is_enabled(spa, feature)) {
     3684 +                                        spa_close(spa, FTAG);
     3685 +                                        return (ENOTSUP);
     3686 +                                }
     3687 +                                spa_close(spa, FTAG);
     3688 +                        }
     3689 +
3630 3690                          /*
3631 3691                           * If this is a bootable dataset then
3632 3692                           * verify that the compression algorithm
3633 3693                           * is supported for booting. We must return
3634 3694                           * something other than ENOTSUP since it
3635 3695                           * implies a downrev pool version.
3636 3696                           */
3637 3697                          if (zfs_is_bootfs(dsname) &&
3638 3698                              !BOOTFS_COMPRESS_VALID(intval)) {
3639 3699                                  return (ERANGE);
↓ open down ↓ 23 lines elided ↑ open up ↑
3663 3723                              zfs_earlier_version(dsname,
3664 3724                              SPA_VERSION_PASSTHROUGH_X))
3665 3725                                  return (ENOTSUP);
3666 3726                  }
3667 3727                  break;
3668 3728          }
3669 3729  
3670 3730          return (zfs_secpolicy_setprop(dsname, prop, pair, CRED()));
3671 3731  }
3672 3732  
     3733 +/*
     3734 + * Activates a feature on a pool in response to a property setting. This
     3735 + * creates a new sync task which modifies the pool to reflect the feature
     3736 + * as being active.
     3737 + */
     3738 +static int
     3739 +zfs_prop_activate_feature(dsl_pool_t *dp, zfeature_info_t *feature)
     3740 +{
     3741 +        int err;
     3742 +
     3743 +        /* EBUSY here indicates that the feature is already active */
     3744 +        err = dsl_sync_task_do(dp, zfs_prop_activate_feature_check,
     3745 +            zfs_prop_activate_feature_sync, dp->dp_spa, feature, 2);
     3746 +
     3747 +        if (err != 0 && err != EBUSY)
     3748 +                return (err);
     3749 +        else
     3750 +                return (0);
     3751 +}
     3752 +
     3753 +/*
     3754 + * Checks for a race condition to make sure we don't increment a feature flag
     3755 + * multiple times.
     3756 + */
     3757 +/*ARGSUSED*/
     3758 +static int
     3759 +zfs_prop_activate_feature_check(void *arg1, void *arg2, dmu_tx_t *tx)
     3760 +{
     3761 +        spa_t *spa = arg1;
     3762 +        zfeature_info_t *feature = arg2;
     3763 +
     3764 +        if (!spa_feature_is_active(spa, feature))
     3765 +                return (0);
     3766 +        else
     3767 +                return (EBUSY);
     3768 +}
     3769 +
     3770 +/*
     3771 + * The callback invoked on feature activation in the sync task caused by
     3772 + * zfs_prop_activate_feature.
     3773 + */
     3774 +static void
     3775 +zfs_prop_activate_feature_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     3776 +{
     3777 +        spa_t *spa = arg1;
     3778 +        zfeature_info_t *feature = arg2;
     3779 +
     3780 +        spa_feature_incr(spa, feature, tx);
     3781 +}
     3782 +
3673 3783  /*
3674 3784   * Removes properties from the given props list that fail permission checks
3675 3785   * needed to clear them and to restore them in case of a receive error. For each
3676 3786   * property, make sure we have both set and inherit permissions.
3677 3787   *
3678 3788   * Returns the first error encountered if any permission checks fail. If the
3679 3789   * caller provides a non-NULL errlist, it also gives the complete list of names
3680 3790   * of all the properties that failed a permission check along with the
3681 3791   * corresponding error numbers. The caller is responsible for freeing the
3682 3792   * returned errlist.
↓ open down ↓ 2234 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX