Print this page
4171 clean up spa_feature_*() interfaces
4172 implement extensible_dataset feature for use by other zpool features
Reviewed by: Max Grossman <max.grossman@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/zhack/zhack.c
          +++ new/usr/src/cmd/zhack/zhack.c
↓ open down ↓ 275 lines elided ↑ open up ↑
 276  276  
 277  277          dump_obj(os, spa->spa_feat_for_read_obj, "for_read");
 278  278          dump_obj(os, spa->spa_feat_for_write_obj, "for_write");
 279  279          dump_obj(os, spa->spa_feat_desc_obj, "descriptions");
 280  280          dump_mos(spa);
 281  281  
 282  282          spa_close(spa, FTAG);
 283  283  }
 284  284  
 285  285  static void
 286      -feature_enable_sync(void *arg, dmu_tx_t *tx)
      286 +zhack_feature_enable_sync(void *arg, dmu_tx_t *tx)
 287  287  {
 288  288          spa_t *spa = dmu_tx_pool(tx)->dp_spa;
 289  289          zfeature_info_t *feature = arg;
 290  290  
 291      -        spa_feature_enable(spa, feature, tx);
      291 +        feature_enable_sync(spa, feature, tx);
      292 +
 292  293          spa_history_log_internal(spa, "zhack enable feature", tx,
 293  294              "guid=%s can_readonly=%u",
 294  295              feature->fi_guid, feature->fi_can_readonly);
 295  296  }
 296  297  
 297  298  static void
 298  299  zhack_do_feature_enable(int argc, char **argv)
 299  300  {
 300  301          char c;
 301  302          char *desc, *target;
 302  303          spa_t *spa;
 303  304          objset_t *mos;
 304  305          zfeature_info_t feature;
 305      -        zfeature_info_t *nodeps[] = { NULL };
      306 +        spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
 306  307  
 307  308          /*
 308  309           * Features are not added to the pool's label until their refcounts
 309  310           * are incremented, so fi_mos can just be left as false for now.
 310  311           */
 311  312          desc = NULL;
 312  313          feature.fi_uname = "zhack";
 313  314          feature.fi_mos = B_FALSE;
 314  315          feature.fi_can_readonly = B_FALSE;
 315  316          feature.fi_depends = nodeps;
↓ open down ↓ 26 lines elided ↑ open up ↑
 342  343          }
 343  344          target = argv[0];
 344  345          feature.fi_guid = argv[1];
 345  346  
 346  347          if (!zfeature_is_valid_guid(feature.fi_guid))
 347  348                  fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid);
 348  349  
 349  350          zhack_spa_open(target, B_FALSE, FTAG, &spa);
 350  351          mos = spa->spa_meta_objset;
 351  352  
 352      -        if (0 == zfeature_lookup_guid(feature.fi_guid, NULL))
      353 +        if (zfeature_is_supported(feature.fi_guid))
 353  354                  fatal(spa, FTAG, "'%s' is a real feature, will not enable");
 354  355          if (0 == zap_contains(mos, spa->spa_feat_desc_obj, feature.fi_guid))
 355  356                  fatal(spa, FTAG, "feature already enabled: %s",
 356  357                      feature.fi_guid);
 357  358  
 358  359          VERIFY0(dsl_sync_task(spa_name(spa), NULL,
 359      -            feature_enable_sync, &feature, 5));
      360 +            zhack_feature_enable_sync, &feature, 5));
 360  361  
 361  362          spa_close(spa, FTAG);
 362  363  
 363  364          free(desc);
 364  365  }
 365  366  
 366  367  static void
 367  368  feature_incr_sync(void *arg, dmu_tx_t *tx)
 368  369  {
 369  370          spa_t *spa = dmu_tx_pool(tx)->dp_spa;
 370  371          zfeature_info_t *feature = arg;
      372 +        uint64_t refcount;
 371  373  
 372      -        spa_feature_incr(spa, feature, tx);
      374 +        VERIFY0(feature_get_refcount(spa, feature, &refcount));
      375 +        feature_sync(spa, feature, refcount + 1, tx);
 373  376          spa_history_log_internal(spa, "zhack feature incr", tx,
 374  377              "guid=%s", feature->fi_guid);
 375  378  }
 376  379  
 377  380  static void
 378  381  feature_decr_sync(void *arg, dmu_tx_t *tx)
 379  382  {
 380  383          spa_t *spa = dmu_tx_pool(tx)->dp_spa;
 381  384          zfeature_info_t *feature = arg;
      385 +        uint64_t refcount;
 382  386  
 383      -        spa_feature_decr(spa, feature, tx);
      387 +        VERIFY0(feature_get_refcount(spa, feature, &refcount));
      388 +        feature_sync(spa, feature, refcount - 1, tx);
 384  389          spa_history_log_internal(spa, "zhack feature decr", tx,
 385  390              "guid=%s", feature->fi_guid);
 386  391  }
 387  392  
 388  393  static void
 389  394  zhack_do_feature_ref(int argc, char **argv)
 390  395  {
 391  396          char c;
 392  397          char *target;
 393  398          boolean_t decr = B_FALSE;
 394  399          spa_t *spa;
 395  400          objset_t *mos;
 396  401          zfeature_info_t feature;
 397      -        zfeature_info_t *nodeps[] = { NULL };
      402 +        spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
 398  403  
 399  404          /*
 400  405           * fi_desc does not matter here because it was written to disk
 401  406           * when the feature was enabled, but we need to properly set the
 402  407           * feature for read or write based on the information we read off
 403  408           * disk later.
 404  409           */
 405  410          feature.fi_uname = "zhack";
 406  411          feature.fi_mos = B_FALSE;
 407  412          feature.fi_desc = NULL;
↓ open down ↓ 22 lines elided ↑ open up ↑
 430  435          }
 431  436          target = argv[0];
 432  437          feature.fi_guid = argv[1];
 433  438  
 434  439          if (!zfeature_is_valid_guid(feature.fi_guid))
 435  440                  fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid);
 436  441  
 437  442          zhack_spa_open(target, B_FALSE, FTAG, &spa);
 438  443          mos = spa->spa_meta_objset;
 439  444  
 440      -        if (0 == zfeature_lookup_guid(feature.fi_guid, NULL))
 441      -                fatal(spa, FTAG, "'%s' is a real feature, will not change "
 442      -                    "refcount");
      445 +        if (zfeature_is_supported(feature.fi_guid)) {
      446 +                fatal(spa, FTAG,
      447 +                    "'%s' is a real feature, will not change refcount");
      448 +        }
 443  449  
 444  450          if (0 == zap_contains(mos, spa->spa_feat_for_read_obj,
 445  451              feature.fi_guid)) {
 446  452                  feature.fi_can_readonly = B_FALSE;
 447  453          } else if (0 == zap_contains(mos, spa->spa_feat_for_write_obj,
 448  454              feature.fi_guid)) {
 449  455                  feature.fi_can_readonly = B_TRUE;
 450  456          } else {
 451  457                  fatal(spa, FTAG, "feature is not enabled: %s", feature.fi_guid);
 452  458          }
 453  459  
 454      -        if (decr && !spa_feature_is_active(spa, &feature))
 455      -                fatal(spa, FTAG, "feature refcount already 0: %s",
 456      -                    feature.fi_guid);
      460 +        if (decr) {
      461 +                uint64_t count;
      462 +                if (feature_get_refcount(spa, &feature, &count) == 0 &&
      463 +                    count != 0) {
      464 +                        fatal(spa, FTAG, "feature refcount already 0: %s",
      465 +                            feature.fi_guid);
      466 +                }
      467 +        }
 457  468  
 458  469          VERIFY0(dsl_sync_task(spa_name(spa), NULL,
 459  470              decr ? feature_decr_sync : feature_incr_sync, &feature, 5));
 460  471  
 461  472          spa_close(spa, FTAG);
 462  473  }
 463  474  
 464  475  static int
 465  476  zhack_do_feature(int argc, char **argv)
 466  477  {
↓ open down ↓ 87 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX