The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/zcommon/zfeature_common.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 
   22 /*
   23  * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
   24  * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
   25  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
   26  * Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved.
   27  * Copyright (c) 2017, Intel Corporation.
   28  * Copyright (c) 2019, Klara Inc.
   29  * Copyright (c) 2019, Allan Jude
   30  */
   31 
   32 #ifndef _KERNEL
   33 #include <errno.h>
   34 #include <string.h>
   35 #include <dirent.h>
   36 #include <search.h>
   37 #include <sys/stat.h>
   38 #endif
   39 #include <sys/debug.h>
   40 #include <sys/fs/zfs.h>
   41 #include <sys/inttypes.h>
   42 #include <sys/types.h>
   43 #include <sys/param.h>
   44 #include <sys/zfs_sysfs.h>
   45 #include "zfeature_common.h"
   46 
   47 /*
   48  * Set to disable all feature checks while opening pools, allowing pools with
   49  * unsupported features to be opened. Set for testing only.
   50  */
   51 boolean_t zfeature_checks_disable = B_FALSE;
   52 
   53 zfeature_info_t spa_feature_table[SPA_FEATURES];
   54 
   55 /*
   56  * Valid characters for feature guids. This list is mainly for aesthetic
   57  * purposes and could be expanded in the future. There are different allowed
   58  * characters in the guids reverse dns portion (before the colon) and its
   59  * short name (after the colon).
   60  */
   61 static int
   62 valid_char(char c, boolean_t after_colon)
   63 {
   64         return ((c >= 'a' && c <= 'z') ||
   65             (c >= '' && c <= '9') ||
   66             (after_colon && c == '_') ||
   67             (!after_colon && (c == '.' || c == '-')));
   68 }
   69 
   70 /*
   71  * Every feature guid must contain exactly one colon which separates a reverse
   72  * dns organization name from the feature's "short" name (e.g.
   73  * "com.company:feature_name").
   74  */
   75 boolean_t
   76 zfeature_is_valid_guid(const char *name)
   77 {
   78         int i;
   79         boolean_t has_colon = B_FALSE;
   80 
   81         i = 0;
   82         while (name[i] != '\0') {
   83                 char c = name[i++];
   84                 if (c == ':') {
   85                         if (has_colon)
   86                                 return (B_FALSE);
   87                         has_colon = B_TRUE;
   88                         continue;
   89                 }
   90                 if (!valid_char(c, has_colon))
   91                         return (B_FALSE);
   92         }
   93 
   94         return (has_colon);
   95 }
   96 
   97 boolean_t
   98 zfeature_is_supported(const char *guid)
   99 {
  100         if (zfeature_checks_disable)
  101                 return (B_TRUE);
  102 
  103         for (spa_feature_t i = 0; i < SPA_FEATURES; i++) {
  104                 zfeature_info_t *feature = &spa_feature_table[i];
  105                 if (!feature->fi_zfs_mod_supported)
  106                         continue;
  107                 if (strcmp(guid, feature->fi_guid) == 0)
  108                         return (B_TRUE);
  109         }
  110         return (B_FALSE);
  111 }
  112 
  113 int
  114 zfeature_lookup_guid(const char *guid, spa_feature_t *res)
  115 {
  116         for (spa_feature_t i = 0; i < SPA_FEATURES; i++) {
  117                 zfeature_info_t *feature = &spa_feature_table[i];
  118                 if (!feature->fi_zfs_mod_supported)
  119                         continue;
  120                 if (strcmp(guid, feature->fi_guid) == 0) {
  121                         if (res != NULL)
  122                                 *res = i;
  123                         return (0);
  124                 }
  125         }
  126 
  127         return (ENOENT);
  128 }
  129 
  130 int
  131 zfeature_lookup_name(const char *name, spa_feature_t *res)
  132 {
  133         for (spa_feature_t i = 0; i < SPA_FEATURES; i++) {
  134                 zfeature_info_t *feature = &spa_feature_table[i];
  135                 if (!feature->fi_zfs_mod_supported)
  136                         continue;
  137                 if (strcmp(name, feature->fi_uname) == 0) {
  138                         if (res != NULL)
  139                                 *res = i;
  140                         return (0);
  141                 }
  142         }
  143 
  144         return (ENOENT);
  145 }
  146 
  147 boolean_t
  148 zfeature_depends_on(spa_feature_t fid, spa_feature_t check)
  149 {
  150         zfeature_info_t *feature = &spa_feature_table[fid];
  151 
  152         for (int i = 0; feature->fi_depends[i] != SPA_FEATURE_NONE; i++) {
  153                 if (feature->fi_depends[i] == check)
  154                         return (B_TRUE);
  155         }
  156         return (B_FALSE);
  157 }
  158 
  159 static boolean_t
  160 deps_contains_feature(const spa_feature_t *deps, const spa_feature_t feature)
  161 {
  162         for (int i = 0; deps[i] != SPA_FEATURE_NONE; i++)
  163                 if (deps[i] == feature)
  164                         return (B_TRUE);
  165 
  166         return (B_FALSE);
  167 }
  168 
  169 #define STRCMP ((int(*)(const void *, const void *))&strcmp)
  170 struct zfs_mod_supported_features {
  171         void *tree;
  172         boolean_t all_features;
  173 };
  174 
  175 struct zfs_mod_supported_features *
  176 zfs_mod_list_supported(const char *scope)
  177 {
  178 #if defined(__FreeBSD__) || defined(_KERNEL) || defined(LIB_ZPOOL_BUILD)
  179         (void) scope;
  180         return (NULL);
  181 #else
  182         struct zfs_mod_supported_features *ret = calloc(1, sizeof (*ret));
  183         if (ret == NULL)
  184                 return (NULL);
  185 
  186         DIR *sysfs_dir = NULL;
  187         char path[128];
  188 
  189         if (snprintf(path, sizeof (path), "%s/%s",
  190             ZFS_SYSFS_DIR, scope) < sizeof (path))
  191                 sysfs_dir = opendir(path);
  192         if (sysfs_dir == NULL && errno == ENOENT) {
  193                 if (snprintf(path, sizeof (path), "%s/%s",
  194                     ZFS_SYSFS_ALT_DIR, scope) < sizeof (path))
  195                         sysfs_dir = opendir(path);
  196         }
  197         if (sysfs_dir == NULL) {
  198                 ret->all_features = errno == ENOENT &&
  199                     (access(ZFS_SYSFS_DIR, F_OK) == 0 ||
  200                     access(ZFS_SYSFS_ALT_DIR, F_OK) == 0);
  201                 return (ret);
  202         }
  203 
  204         struct dirent *node;
  205         while ((node = readdir(sysfs_dir)) != NULL) {
  206                 if (strcmp(node->d_name, ".") == 0 ||
  207                     strcmp(node->d_name, "..") == 0)
  208                         continue;
  209 
  210                 char *name = strdup(node->d_name);
  211                 if (name == NULL) {
  212                         goto nomem;
  213                 }
  214 
  215                 if (tsearch(name, &ret->tree, STRCMP) == NULL) {
  216                         /*
  217                          * Don't bother checking for duplicate entries:
  218                          * we're iterating a single directory.
  219                          */
  220                         free(name);
  221                         goto nomem;
  222                 }
  223         }
  224 
  225 end:
  226         closedir(sysfs_dir);
  227         return (ret);
  228 
  229 nomem:
  230         zfs_mod_list_supported_free(ret);
  231         ret = NULL;
  232         goto end;
  233 #endif
  234 }
  235 
  236 void
  237 zfs_mod_list_supported_free(struct zfs_mod_supported_features *list)
  238 {
  239 #if !defined(__FreeBSD__) && !defined(_KERNEL) && !defined(LIB_ZPOOL_BUILD)
  240         if (list) {
  241                 tdestroy(list->tree, free);
  242                 free(list);
  243         }
  244 #else
  245         (void) list;
  246 #endif
  247 }
  248 
  249 #if !defined(_KERNEL) && !defined(LIB_ZPOOL_BUILD)
  250 static boolean_t
  251 zfs_mod_supported_impl(const char *scope, const char *name, const char *sysfs)
  252 {
  253         char path[128];
  254         if (snprintf(path, sizeof (path), "%s%s%s%s%s", sysfs,
  255             scope == NULL ? "" : "/", scope ?: "",
  256             name == NULL ? "" : "/", name ?: "") < sizeof (path))
  257                 return (access(path, F_OK) == 0);
  258         else
  259                 return (B_FALSE);
  260 }
  261 
  262 boolean_t
  263 zfs_mod_supported(const char *scope, const char *name,
  264     const struct zfs_mod_supported_features *sfeatures)
  265 {
  266         boolean_t supported;
  267 
  268         if (sfeatures != NULL)
  269                 return (sfeatures->all_features ||
  270                     tfind(name, &sfeatures->tree, STRCMP));
  271 
  272         /*
  273          * Check both the primary and alternate sysfs locations to determine
  274          * if the required functionality is supported.
  275          */
  276         supported = (zfs_mod_supported_impl(scope, name, ZFS_SYSFS_DIR) ||
  277             zfs_mod_supported_impl(scope, name, ZFS_SYSFS_ALT_DIR));
  278 
  279         /*
  280          * For backwards compatibility with kernel modules that predate
  281          * supported feature/property checking.  Report the feature/property
  282          * as supported if the kernel module is loaded but the requested
  283          * scope directory does not exist.
  284          */
  285         if (supported == B_FALSE) {
  286                 if ((access(ZFS_SYSFS_DIR, F_OK) == 0 &&
  287                     !zfs_mod_supported_impl(scope, NULL, ZFS_SYSFS_DIR)) ||
  288                     (access(ZFS_SYSFS_ALT_DIR, F_OK) == 0 &&
  289                     !zfs_mod_supported_impl(scope, NULL, ZFS_SYSFS_ALT_DIR))) {
  290                         supported = B_TRUE;
  291                 }
  292         }
  293 
  294         return (supported);
  295 }
  296 #endif
  297 
  298 static boolean_t
  299 zfs_mod_supported_feature(const char *name,
  300     const struct zfs_mod_supported_features *sfeatures)
  301 {
  302         /*
  303          * The zfs module spa_feature_table[], whether in-kernel or in
  304          * libzpool, always supports all the features. libzfs needs to
  305          * query the running module, via sysfs, to determine which
  306          * features are supported.
  307          *
  308          * The equivalent _can_ be done on FreeBSD by way of the sysctl
  309          * tree, but this has not been done yet.  Therefore, we return
  310          * that all features are supported.
  311          */
  312 
  313 #if defined(_KERNEL) || defined(LIB_ZPOOL_BUILD) || defined(__FreeBSD__)
  314         (void) name, (void) sfeatures;
  315         return (B_TRUE);
  316 #else
  317         return (zfs_mod_supported(ZFS_SYSFS_POOL_FEATURES, name, sfeatures));
  318 #endif
  319 }
  320 
  321 static void
  322 zfeature_register(spa_feature_t fid, const char *guid, const char *name,
  323     const char *desc, zfeature_flags_t flags, zfeature_type_t type,
  324     const spa_feature_t *deps,
  325     const struct zfs_mod_supported_features *sfeatures)
  326 {
  327         zfeature_info_t *feature = &spa_feature_table[fid];
  328         static const spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
  329 
  330         ASSERT(name != NULL);
  331         ASSERT(desc != NULL);
  332         ASSERT((flags & ZFEATURE_FLAG_READONLY_COMPAT) == 0 ||
  333             (flags & ZFEATURE_FLAG_MOS) == 0);
  334         ASSERT3U(fid, <, SPA_FEATURES);
  335         ASSERT(zfeature_is_valid_guid(guid));
  336 
  337         if (deps == NULL)
  338                 deps = nodeps;
  339 
  340         VERIFY(((flags & ZFEATURE_FLAG_PER_DATASET) == 0) ||
  341             (deps_contains_feature(deps, SPA_FEATURE_EXTENSIBLE_DATASET)));
  342 
  343         feature->fi_feature = fid;
  344         feature->fi_guid = guid;
  345         feature->fi_uname = name;
  346         feature->fi_desc = desc;
  347         feature->fi_flags = flags;
  348         feature->fi_type = type;
  349         feature->fi_depends = deps;
  350         feature->fi_zfs_mod_supported =
  351             zfs_mod_supported_feature(guid, sfeatures);
  352 }
  353 
  354 /*
  355  * Every feature has a GUID of the form com.example:feature_name.  The
  356  * reversed DNS name ensures that the feature's GUID is unique across all ZFS
  357  * implementations.  This allows companies to independently develop and
  358  * release features.  Examples include org.delphix and org.datto.  Previously,
  359  * features developed on one implementation have used that implementation's
  360  * domain name (e.g. org.illumos and org.zfsonlinux).  Use of the org.openzfs
  361  * domain name is recommended for new features which are developed by the
  362  * OpenZFS community and its platforms.  This domain may optionally be used by
  363  * companies developing features for initial release through an OpenZFS
  364  * implementation.  Use of the org.openzfs domain requires reserving the
  365  * feature name in advance with the OpenZFS project.
  366  */
  367 void
  368 zpool_feature_init(void)
  369 {
  370         struct zfs_mod_supported_features *sfeatures =
  371             zfs_mod_list_supported(ZFS_SYSFS_POOL_FEATURES);
  372 
  373         zfeature_register(SPA_FEATURE_ASYNC_DESTROY,
  374             "com.delphix:async_destroy", "async_destroy",
  375             "Destroy filesystems asynchronously.",
  376             ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL,
  377             sfeatures);
  378 
  379         zfeature_register(SPA_FEATURE_EMPTY_BPOBJ,
  380             "com.delphix:empty_bpobj", "empty_bpobj",
  381             "Snapshots use less space.",
  382             ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL,
  383             sfeatures);
  384 
  385         zfeature_register(SPA_FEATURE_LZ4_COMPRESS,
  386             "org.illumos:lz4_compress", "lz4_compress",
  387             "LZ4 compression algorithm support.",
  388             ZFEATURE_FLAG_ACTIVATE_ON_ENABLE, ZFEATURE_TYPE_BOOLEAN, NULL,
  389             sfeatures);
  390 
  391         zfeature_register(SPA_FEATURE_MULTI_VDEV_CRASH_DUMP,
  392             "com.joyent:multi_vdev_crash_dump", "multi_vdev_crash_dump",
  393             "Crash dumps to multiple vdev pools.",
  394             0, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures);
  395 
  396         zfeature_register(SPA_FEATURE_SPACEMAP_HISTOGRAM,
  397             "com.delphix:spacemap_histogram", "spacemap_histogram",
  398             "Spacemaps maintain space histograms.",
  399             ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL,
  400             sfeatures);
  401 
  402         zfeature_register(SPA_FEATURE_ENABLED_TXG,
  403             "com.delphix:enabled_txg", "enabled_txg",
  404             "Record txg at which a feature is enabled",
  405             ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL,
  406             sfeatures);
  407 
  408         {
  409                 static const spa_feature_t hole_birth_deps[] = {
  410                         SPA_FEATURE_ENABLED_TXG,
  411                         SPA_FEATURE_NONE
  412                 };
  413                 zfeature_register(SPA_FEATURE_HOLE_BIRTH,
  414                     "com.delphix:hole_birth", "hole_birth",
  415                     "Retain hole birth txg for more precise zfs send",
  416                     ZFEATURE_FLAG_MOS | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE,
  417                     ZFEATURE_TYPE_BOOLEAN, hole_birth_deps, sfeatures);
  418         }
  419 
  420         zfeature_register(SPA_FEATURE_POOL_CHECKPOINT,
  421             "com.delphix:zpool_checkpoint", "zpool_checkpoint",
  422             "Pool state can be checkpointed, allowing rewind later.",
  423             ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL,
  424             sfeatures);
  425 
  426         zfeature_register(SPA_FEATURE_SPACEMAP_V2,
  427             "com.delphix:spacemap_v2", "spacemap_v2",
  428             "Space maps representing large segments are more efficient.",
  429             ZFEATURE_FLAG_READONLY_COMPAT | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE,
  430             ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures);
  431 
  432         zfeature_register(SPA_FEATURE_EXTENSIBLE_DATASET,
  433             "com.delphix:extensible_dataset", "extensible_dataset",
  434             "Enhanced dataset functionality, used by other features.",
  435             0, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures);
  436 
  437         {
  438                 static const spa_feature_t bookmarks_deps[] = {
  439                         SPA_FEATURE_EXTENSIBLE_DATASET,
  440                         SPA_FEATURE_NONE
  441                 };
  442 
  443                 zfeature_register(SPA_FEATURE_BOOKMARKS,
  444                     "com.delphix:bookmarks", "bookmarks",
  445                     "\"zfs bookmark\" command",
  446                     ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN,
  447                     bookmarks_deps, sfeatures);
  448         }
  449 
  450         {
  451                 static const spa_feature_t filesystem_limits_deps[] = {
  452                         SPA_FEATURE_EXTENSIBLE_DATASET,
  453                         SPA_FEATURE_NONE
  454                 };
  455                 zfeature_register(SPA_FEATURE_FS_SS_LIMIT,
  456                     "com.joyent:filesystem_limits", "filesystem_limits",
  457                     "Filesystem and snapshot limits.",
  458                     ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN,
  459                     filesystem_limits_deps, sfeatures);
  460         }
  461 
  462         zfeature_register(SPA_FEATURE_EMBEDDED_DATA,
  463             "com.delphix:embedded_data", "embedded_data",
  464             "Blocks which compress very well use even less space.",
  465             ZFEATURE_FLAG_MOS | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE,
  466             ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures);
  467 
  468         {
  469                 static const spa_feature_t livelist_deps[] = {
  470                         SPA_FEATURE_EXTENSIBLE_DATASET,
  471                         SPA_FEATURE_NONE
  472                 };
  473                 zfeature_register(SPA_FEATURE_LIVELIST,
  474                     "com.delphix:livelist", "livelist",
  475                     "Improved clone deletion performance.",
  476                     ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN,
  477                     livelist_deps, sfeatures);
  478         }
  479 
  480         {
  481                 static const spa_feature_t log_spacemap_deps[] = {
  482                         SPA_FEATURE_SPACEMAP_V2,
  483                         SPA_FEATURE_NONE
  484                 };
  485                 zfeature_register(SPA_FEATURE_LOG_SPACEMAP,
  486                     "com.delphix:log_spacemap", "log_spacemap",
  487                     "Log metaslab changes on a single spacemap and "
  488                     "flush them periodically.",
  489                     ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN,
  490                     log_spacemap_deps, sfeatures);
  491         }
  492 
  493         {
  494                 static const spa_feature_t large_blocks_deps[] = {
  495                         SPA_FEATURE_EXTENSIBLE_DATASET,
  496                         SPA_FEATURE_NONE
  497                 };
  498                 zfeature_register(SPA_FEATURE_LARGE_BLOCKS,
  499                     "org.open-zfs:large_blocks", "large_blocks",
  500                     "Support for blocks larger than 128KB.",
  501                     ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN,
  502                     large_blocks_deps, sfeatures);
  503         }
  504 
  505         {
  506                 static const spa_feature_t large_dnode_deps[] = {
  507                         SPA_FEATURE_EXTENSIBLE_DATASET,
  508                         SPA_FEATURE_NONE
  509                 };
  510                 zfeature_register(SPA_FEATURE_LARGE_DNODE,
  511                     "org.zfsonlinux:large_dnode", "large_dnode",
  512                     "Variable on-disk size of dnodes.",
  513                     ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN,
  514                     large_dnode_deps, sfeatures);
  515         }
  516 
  517         {
  518                 static const spa_feature_t sha512_deps[] = {
  519                         SPA_FEATURE_EXTENSIBLE_DATASET,
  520                         SPA_FEATURE_NONE
  521                 };
  522                 zfeature_register(SPA_FEATURE_SHA512,
  523                     "org.illumos:sha512", "sha512",
  524                     "SHA-512/256 hash algorithm.",
  525                     ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN,
  526                     sha512_deps, sfeatures);
  527         }
  528 
  529         {
  530                 static const spa_feature_t skein_deps[] = {
  531                         SPA_FEATURE_EXTENSIBLE_DATASET,
  532                         SPA_FEATURE_NONE
  533                 };
  534                 zfeature_register(SPA_FEATURE_SKEIN,
  535                     "org.illumos:skein", "skein",
  536                     "Skein hash algorithm.",
  537                     ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN,
  538                     skein_deps, sfeatures);
  539         }
  540 
  541         {
  542                 static const spa_feature_t edonr_deps[] = {
  543                         SPA_FEATURE_EXTENSIBLE_DATASET,
  544                         SPA_FEATURE_NONE
  545                 };
  546                 zfeature_register(SPA_FEATURE_EDONR,
  547                     "org.illumos:edonr", "edonr",
  548                     "Edon-R hash algorithm.",
  549                     ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN,
  550                     edonr_deps, sfeatures);
  551         }
  552 
  553         {
  554                 static const spa_feature_t redact_books_deps[] = {
  555                         SPA_FEATURE_BOOKMARK_V2,
  556                         SPA_FEATURE_EXTENSIBLE_DATASET,
  557                         SPA_FEATURE_BOOKMARKS,
  558                         SPA_FEATURE_NONE
  559                 };
  560                 zfeature_register(SPA_FEATURE_REDACTION_BOOKMARKS,
  561                     "com.delphix:redaction_bookmarks", "redaction_bookmarks",
  562                     "Support for bookmarks which store redaction lists for zfs "
  563                     "redacted send/recv.", 0, ZFEATURE_TYPE_BOOLEAN,
  564                     redact_books_deps, sfeatures);
  565         }
  566 
  567         {
  568                 static const spa_feature_t redact_datasets_deps[] = {
  569                         SPA_FEATURE_EXTENSIBLE_DATASET,
  570                         SPA_FEATURE_NONE
  571                 };
  572                 zfeature_register(SPA_FEATURE_REDACTED_DATASETS,
  573                     "com.delphix:redacted_datasets", "redacted_datasets",
  574                     "Support for redacted datasets, produced by receiving "
  575                     "a redacted zfs send stream.",
  576                     ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_UINT64_ARRAY,
  577                     redact_datasets_deps, sfeatures);
  578         }
  579 
  580         {
  581                 static const spa_feature_t bookmark_written_deps[] = {
  582                         SPA_FEATURE_BOOKMARK_V2,
  583                         SPA_FEATURE_EXTENSIBLE_DATASET,
  584                         SPA_FEATURE_BOOKMARKS,
  585                         SPA_FEATURE_NONE
  586                 };
  587                 zfeature_register(SPA_FEATURE_BOOKMARK_WRITTEN,
  588                     "com.delphix:bookmark_written", "bookmark_written",
  589                     "Additional accounting, enabling the written#<bookmark> "
  590                     "property (space written since a bookmark), "
  591                     "and estimates of send stream sizes for incrementals from "
  592                     "bookmarks.",
  593                     0, ZFEATURE_TYPE_BOOLEAN, bookmark_written_deps, sfeatures);
  594         }
  595 
  596         zfeature_register(SPA_FEATURE_DEVICE_REMOVAL,
  597             "com.delphix:device_removal", "device_removal",
  598             "Top-level vdevs can be removed, reducing logical pool size.",
  599             ZFEATURE_FLAG_MOS, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures);
  600 
  601         {
  602                 static const spa_feature_t obsolete_counts_deps[] = {
  603                         SPA_FEATURE_EXTENSIBLE_DATASET,
  604                         SPA_FEATURE_DEVICE_REMOVAL,
  605                         SPA_FEATURE_NONE
  606                 };
  607                 zfeature_register(SPA_FEATURE_OBSOLETE_COUNTS,
  608                     "com.delphix:obsolete_counts", "obsolete_counts",
  609                     "Reduce memory used by removed devices when their blocks "
  610                     "are freed or remapped.",
  611                     ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN,
  612                     obsolete_counts_deps, sfeatures);
  613         }
  614 
  615         {
  616                 static const spa_feature_t userobj_accounting_deps[] = {
  617                         SPA_FEATURE_EXTENSIBLE_DATASET,
  618                         SPA_FEATURE_NONE
  619                 };
  620                 zfeature_register(SPA_FEATURE_USEROBJ_ACCOUNTING,
  621                     "org.zfsonlinux:userobj_accounting", "userobj_accounting",
  622                     "User/Group object accounting.",
  623                     ZFEATURE_FLAG_READONLY_COMPAT | ZFEATURE_FLAG_PER_DATASET,
  624                     ZFEATURE_TYPE_BOOLEAN, userobj_accounting_deps, sfeatures);
  625         }
  626 
  627         {
  628                 static const spa_feature_t bookmark_v2_deps[] = {
  629                         SPA_FEATURE_EXTENSIBLE_DATASET,
  630                         SPA_FEATURE_BOOKMARKS,
  631                         SPA_FEATURE_NONE
  632                 };
  633                 zfeature_register(SPA_FEATURE_BOOKMARK_V2,
  634                     "com.datto:bookmark_v2", "bookmark_v2",
  635                     "Support for larger bookmarks",
  636                     0, ZFEATURE_TYPE_BOOLEAN, bookmark_v2_deps, sfeatures);
  637         }
  638 
  639         {
  640                 static const spa_feature_t encryption_deps[] = {
  641                         SPA_FEATURE_EXTENSIBLE_DATASET,
  642                         SPA_FEATURE_BOOKMARK_V2,
  643                         SPA_FEATURE_NONE
  644                 };
  645                 zfeature_register(SPA_FEATURE_ENCRYPTION,
  646                     "com.datto:encryption", "encryption",
  647                     "Support for dataset level encryption",
  648                     ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN,
  649                     encryption_deps, sfeatures);
  650         }
  651 
  652         {
  653                 static const spa_feature_t project_quota_deps[] = {
  654                         SPA_FEATURE_EXTENSIBLE_DATASET,
  655                         SPA_FEATURE_NONE
  656                 };
  657                 zfeature_register(SPA_FEATURE_PROJECT_QUOTA,
  658                     "org.zfsonlinux:project_quota", "project_quota",
  659                     "space/object accounting based on project ID.",
  660                     ZFEATURE_FLAG_READONLY_COMPAT | ZFEATURE_FLAG_PER_DATASET,
  661                     ZFEATURE_TYPE_BOOLEAN, project_quota_deps, sfeatures);
  662         }
  663 
  664         zfeature_register(SPA_FEATURE_ALLOCATION_CLASSES,
  665             "org.zfsonlinux:allocation_classes", "allocation_classes",
  666             "Support for separate allocation classes.",
  667             ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL,
  668             sfeatures);
  669 
  670         zfeature_register(SPA_FEATURE_RESILVER_DEFER,
  671             "com.datto:resilver_defer", "resilver_defer",
  672             "Support for deferring new resilvers when one is already running.",
  673             ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL,
  674             sfeatures);
  675 
  676         zfeature_register(SPA_FEATURE_DEVICE_REBUILD,
  677             "org.openzfs:device_rebuild", "device_rebuild",
  678             "Support for sequential mirror/dRAID device rebuilds",
  679             ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL,
  680             sfeatures);
  681 
  682         {
  683                 static const spa_feature_t zstd_deps[] = {
  684                         SPA_FEATURE_EXTENSIBLE_DATASET,
  685                         SPA_FEATURE_NONE
  686                 };
  687                 zfeature_register(SPA_FEATURE_ZSTD_COMPRESS,
  688                     "org.freebsd:zstd_compress", "zstd_compress",
  689                     "zstd compression algorithm support.",
  690                     ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, zstd_deps,
  691                     sfeatures);
  692         }
  693 
  694         zfeature_register(SPA_FEATURE_DRAID,
  695             "org.openzfs:draid", "draid", "Support for distributed spare RAID",
  696             ZFEATURE_FLAG_MOS, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures);
  697 
  698         {
  699                 static const spa_feature_t zilsaxattr_deps[] = {
  700                         SPA_FEATURE_EXTENSIBLE_DATASET,
  701                         SPA_FEATURE_NONE
  702                 };
  703                 zfeature_register(SPA_FEATURE_ZILSAXATTR,
  704                     "org.openzfs:zilsaxattr", "zilsaxattr",
  705                     "Support for xattr=sa extended attribute logging in ZIL.",
  706                     ZFEATURE_FLAG_PER_DATASET | ZFEATURE_FLAG_READONLY_COMPAT,
  707                     ZFEATURE_TYPE_BOOLEAN, zilsaxattr_deps, sfeatures);
  708         }
  709 
  710         zfeature_register(SPA_FEATURE_HEAD_ERRLOG,
  711             "com.delphix:head_errlog", "head_errlog",
  712             "Support for per-dataset on-disk error logs.",
  713             ZFEATURE_FLAG_ACTIVATE_ON_ENABLE, ZFEATURE_TYPE_BOOLEAN, NULL,
  714             sfeatures);
  715 
  716         {
  717                 static const spa_feature_t blake3_deps[] = {
  718                         SPA_FEATURE_EXTENSIBLE_DATASET,
  719                         SPA_FEATURE_NONE
  720                 };
  721                 zfeature_register(SPA_FEATURE_BLAKE3,
  722                     "org.openzfs:blake3", "blake3",
  723                     "BLAKE3 hash algorithm.",
  724                     ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN,
  725                     blake3_deps, sfeatures);
  726         }
  727 
  728         zfs_mod_list_supported_free(sfeatures);
  729 }
  730 
  731 #if defined(_KERNEL)
  732 EXPORT_SYMBOL(zfeature_lookup_guid);
  733 EXPORT_SYMBOL(zfeature_lookup_name);
  734 EXPORT_SYMBOL(zfeature_is_supported);
  735 EXPORT_SYMBOL(zfeature_is_valid_guid);
  736 EXPORT_SYMBOL(zfeature_depends_on);
  737 EXPORT_SYMBOL(zpool_feature_init);
  738 EXPORT_SYMBOL(spa_feature_table);
  739 #endif

Cache object: d59a2f2433e70b83ff1ccc8f584af676


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.