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>


 266         argv++;
 267 
 268         if (argc < 1) {
 269                 (void) fprintf(stderr, "error: missing pool name\n");
 270                 usage();
 271         }
 272         target = argv[0];
 273 
 274         zhack_spa_open(target, B_TRUE, FTAG, &spa);
 275         os = spa->spa_meta_objset;
 276 
 277         dump_obj(os, spa->spa_feat_for_read_obj, "for_read");
 278         dump_obj(os, spa->spa_feat_for_write_obj, "for_write");
 279         dump_obj(os, spa->spa_feat_desc_obj, "descriptions");
 280         dump_mos(spa);
 281 
 282         spa_close(spa, FTAG);
 283 }
 284 
 285 static void
 286 feature_enable_sync(void *arg, dmu_tx_t *tx)
 287 {
 288         spa_t *spa = dmu_tx_pool(tx)->dp_spa;
 289         zfeature_info_t *feature = arg;
 290 
 291         spa_feature_enable(spa, feature, tx);

 292         spa_history_log_internal(spa, "zhack enable feature", tx,
 293             "guid=%s can_readonly=%u",
 294             feature->fi_guid, feature->fi_can_readonly);
 295 }
 296 
 297 static void
 298 zhack_do_feature_enable(int argc, char **argv)
 299 {
 300         char c;
 301         char *desc, *target;
 302         spa_t *spa;
 303         objset_t *mos;
 304         zfeature_info_t feature;
 305         zfeature_info_t *nodeps[] = { NULL };
 306 
 307         /*
 308          * Features are not added to the pool's label until their refcounts
 309          * are incremented, so fi_mos can just be left as false for now.
 310          */
 311         desc = NULL;
 312         feature.fi_uname = "zhack";
 313         feature.fi_mos = B_FALSE;
 314         feature.fi_can_readonly = B_FALSE;
 315         feature.fi_depends = nodeps;
 316 
 317         optind = 1;
 318         while ((c = getopt(argc, argv, "rmd:")) != -1) {
 319                 switch (c) {
 320                 case 'r':
 321                         feature.fi_can_readonly = B_TRUE;
 322                         break;
 323                 case 'd':
 324                         desc = strdup(optarg);
 325                         break;


 332         if (desc == NULL)
 333                 desc = strdup("zhack injected");
 334         feature.fi_desc = desc;
 335 
 336         argc -= optind;
 337         argv += optind;
 338 
 339         if (argc < 2) {
 340                 (void) fprintf(stderr, "error: missing feature or pool name\n");
 341                 usage();
 342         }
 343         target = argv[0];
 344         feature.fi_guid = argv[1];
 345 
 346         if (!zfeature_is_valid_guid(feature.fi_guid))
 347                 fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid);
 348 
 349         zhack_spa_open(target, B_FALSE, FTAG, &spa);
 350         mos = spa->spa_meta_objset;
 351 
 352         if (0 == zfeature_lookup_guid(feature.fi_guid, NULL))
 353                 fatal(spa, FTAG, "'%s' is a real feature, will not enable");
 354         if (0 == zap_contains(mos, spa->spa_feat_desc_obj, feature.fi_guid))
 355                 fatal(spa, FTAG, "feature already enabled: %s",
 356                     feature.fi_guid);
 357 
 358         VERIFY0(dsl_sync_task(spa_name(spa), NULL,
 359             feature_enable_sync, &feature, 5));
 360 
 361         spa_close(spa, FTAG);
 362 
 363         free(desc);
 364 }
 365 
 366 static void
 367 feature_incr_sync(void *arg, dmu_tx_t *tx)
 368 {
 369         spa_t *spa = dmu_tx_pool(tx)->dp_spa;
 370         zfeature_info_t *feature = arg;

 371 
 372         spa_feature_incr(spa, feature, tx);

 373         spa_history_log_internal(spa, "zhack feature incr", tx,
 374             "guid=%s", feature->fi_guid);
 375 }
 376 
 377 static void
 378 feature_decr_sync(void *arg, dmu_tx_t *tx)
 379 {
 380         spa_t *spa = dmu_tx_pool(tx)->dp_spa;
 381         zfeature_info_t *feature = arg;

 382 
 383         spa_feature_decr(spa, feature, tx);

 384         spa_history_log_internal(spa, "zhack feature decr", tx,
 385             "guid=%s", feature->fi_guid);
 386 }
 387 
 388 static void
 389 zhack_do_feature_ref(int argc, char **argv)
 390 {
 391         char c;
 392         char *target;
 393         boolean_t decr = B_FALSE;
 394         spa_t *spa;
 395         objset_t *mos;
 396         zfeature_info_t feature;
 397         zfeature_info_t *nodeps[] = { NULL };
 398 
 399         /*
 400          * fi_desc does not matter here because it was written to disk
 401          * when the feature was enabled, but we need to properly set the
 402          * feature for read or write based on the information we read off
 403          * disk later.
 404          */
 405         feature.fi_uname = "zhack";
 406         feature.fi_mos = B_FALSE;
 407         feature.fi_desc = NULL;
 408         feature.fi_depends = nodeps;
 409 
 410         optind = 1;
 411         while ((c = getopt(argc, argv, "md")) != -1) {
 412                 switch (c) {
 413                 case 'm':
 414                         feature.fi_mos = B_TRUE;
 415                         break;
 416                 case 'd':
 417                         decr = B_TRUE;


 420                         usage();
 421                         break;
 422                 }
 423         }
 424         argc -= optind;
 425         argv += optind;
 426 
 427         if (argc < 2) {
 428                 (void) fprintf(stderr, "error: missing feature or pool name\n");
 429                 usage();
 430         }
 431         target = argv[0];
 432         feature.fi_guid = argv[1];
 433 
 434         if (!zfeature_is_valid_guid(feature.fi_guid))
 435                 fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid);
 436 
 437         zhack_spa_open(target, B_FALSE, FTAG, &spa);
 438         mos = spa->spa_meta_objset;
 439 
 440         if (0 == zfeature_lookup_guid(feature.fi_guid, NULL))
 441                 fatal(spa, FTAG, "'%s' is a real feature, will not change "
 442                     "refcount");

 443 
 444         if (0 == zap_contains(mos, spa->spa_feat_for_read_obj,
 445             feature.fi_guid)) {
 446                 feature.fi_can_readonly = B_FALSE;
 447         } else if (0 == zap_contains(mos, spa->spa_feat_for_write_obj,
 448             feature.fi_guid)) {
 449                 feature.fi_can_readonly = B_TRUE;
 450         } else {
 451                 fatal(spa, FTAG, "feature is not enabled: %s", feature.fi_guid);
 452         }
 453 
 454         if (decr && !spa_feature_is_active(spa, &feature))



 455                 fatal(spa, FTAG, "feature refcount already 0: %s",
 456                     feature.fi_guid);


 457 
 458         VERIFY0(dsl_sync_task(spa_name(spa), NULL,
 459             decr ? feature_decr_sync : feature_incr_sync, &feature, 5));
 460 
 461         spa_close(spa, FTAG);
 462 }
 463 
 464 static int
 465 zhack_do_feature(int argc, char **argv)
 466 {
 467         char *subcommand;
 468 
 469         argc--;
 470         argv++;
 471         if (argc == 0) {
 472                 (void) fprintf(stderr,
 473                     "error: no feature operation specified\n");
 474                 usage();
 475         }
 476 




 266         argv++;
 267 
 268         if (argc < 1) {
 269                 (void) fprintf(stderr, "error: missing pool name\n");
 270                 usage();
 271         }
 272         target = argv[0];
 273 
 274         zhack_spa_open(target, B_TRUE, FTAG, &spa);
 275         os = spa->spa_meta_objset;
 276 
 277         dump_obj(os, spa->spa_feat_for_read_obj, "for_read");
 278         dump_obj(os, spa->spa_feat_for_write_obj, "for_write");
 279         dump_obj(os, spa->spa_feat_desc_obj, "descriptions");
 280         dump_mos(spa);
 281 
 282         spa_close(spa, FTAG);
 283 }
 284 
 285 static void
 286 zhack_feature_enable_sync(void *arg, dmu_tx_t *tx)
 287 {
 288         spa_t *spa = dmu_tx_pool(tx)->dp_spa;
 289         zfeature_info_t *feature = arg;
 290 
 291         feature_enable_sync(spa, feature, tx);
 292 
 293         spa_history_log_internal(spa, "zhack enable feature", tx,
 294             "guid=%s can_readonly=%u",
 295             feature->fi_guid, feature->fi_can_readonly);
 296 }
 297 
 298 static void
 299 zhack_do_feature_enable(int argc, char **argv)
 300 {
 301         char c;
 302         char *desc, *target;
 303         spa_t *spa;
 304         objset_t *mos;
 305         zfeature_info_t feature;
 306         spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
 307 
 308         /*
 309          * Features are not added to the pool's label until their refcounts
 310          * are incremented, so fi_mos can just be left as false for now.
 311          */
 312         desc = NULL;
 313         feature.fi_uname = "zhack";
 314         feature.fi_mos = B_FALSE;
 315         feature.fi_can_readonly = B_FALSE;
 316         feature.fi_depends = nodeps;
 317 
 318         optind = 1;
 319         while ((c = getopt(argc, argv, "rmd:")) != -1) {
 320                 switch (c) {
 321                 case 'r':
 322                         feature.fi_can_readonly = B_TRUE;
 323                         break;
 324                 case 'd':
 325                         desc = strdup(optarg);
 326                         break;


 333         if (desc == NULL)
 334                 desc = strdup("zhack injected");
 335         feature.fi_desc = desc;
 336 
 337         argc -= optind;
 338         argv += optind;
 339 
 340         if (argc < 2) {
 341                 (void) fprintf(stderr, "error: missing feature or pool name\n");
 342                 usage();
 343         }
 344         target = argv[0];
 345         feature.fi_guid = argv[1];
 346 
 347         if (!zfeature_is_valid_guid(feature.fi_guid))
 348                 fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid);
 349 
 350         zhack_spa_open(target, B_FALSE, FTAG, &spa);
 351         mos = spa->spa_meta_objset;
 352 
 353         if (zfeature_is_supported(feature.fi_guid))
 354                 fatal(spa, FTAG, "'%s' is a real feature, will not enable");
 355         if (0 == zap_contains(mos, spa->spa_feat_desc_obj, feature.fi_guid))
 356                 fatal(spa, FTAG, "feature already enabled: %s",
 357                     feature.fi_guid);
 358 
 359         VERIFY0(dsl_sync_task(spa_name(spa), NULL,
 360             zhack_feature_enable_sync, &feature, 5));
 361 
 362         spa_close(spa, FTAG);
 363 
 364         free(desc);
 365 }
 366 
 367 static void
 368 feature_incr_sync(void *arg, dmu_tx_t *tx)
 369 {
 370         spa_t *spa = dmu_tx_pool(tx)->dp_spa;
 371         zfeature_info_t *feature = arg;
 372         uint64_t refcount;
 373 
 374         VERIFY0(feature_get_refcount(spa, feature, &refcount));
 375         feature_sync(spa, feature, refcount + 1, tx);
 376         spa_history_log_internal(spa, "zhack feature incr", tx,
 377             "guid=%s", feature->fi_guid);
 378 }
 379 
 380 static void
 381 feature_decr_sync(void *arg, dmu_tx_t *tx)
 382 {
 383         spa_t *spa = dmu_tx_pool(tx)->dp_spa;
 384         zfeature_info_t *feature = arg;
 385         uint64_t refcount;
 386 
 387         VERIFY0(feature_get_refcount(spa, feature, &refcount));
 388         feature_sync(spa, feature, refcount - 1, tx);
 389         spa_history_log_internal(spa, "zhack feature decr", tx,
 390             "guid=%s", feature->fi_guid);
 391 }
 392 
 393 static void
 394 zhack_do_feature_ref(int argc, char **argv)
 395 {
 396         char c;
 397         char *target;
 398         boolean_t decr = B_FALSE;
 399         spa_t *spa;
 400         objset_t *mos;
 401         zfeature_info_t feature;
 402         spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
 403 
 404         /*
 405          * fi_desc does not matter here because it was written to disk
 406          * when the feature was enabled, but we need to properly set the
 407          * feature for read or write based on the information we read off
 408          * disk later.
 409          */
 410         feature.fi_uname = "zhack";
 411         feature.fi_mos = B_FALSE;
 412         feature.fi_desc = NULL;
 413         feature.fi_depends = nodeps;
 414 
 415         optind = 1;
 416         while ((c = getopt(argc, argv, "md")) != -1) {
 417                 switch (c) {
 418                 case 'm':
 419                         feature.fi_mos = B_TRUE;
 420                         break;
 421                 case 'd':
 422                         decr = B_TRUE;


 425                         usage();
 426                         break;
 427                 }
 428         }
 429         argc -= optind;
 430         argv += optind;
 431 
 432         if (argc < 2) {
 433                 (void) fprintf(stderr, "error: missing feature or pool name\n");
 434                 usage();
 435         }
 436         target = argv[0];
 437         feature.fi_guid = argv[1];
 438 
 439         if (!zfeature_is_valid_guid(feature.fi_guid))
 440                 fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid);
 441 
 442         zhack_spa_open(target, B_FALSE, FTAG, &spa);
 443         mos = spa->spa_meta_objset;
 444 
 445         if (zfeature_is_supported(feature.fi_guid)) {
 446                 fatal(spa, FTAG,
 447                     "'%s' is a real feature, will not change refcount");
 448         }
 449 
 450         if (0 == zap_contains(mos, spa->spa_feat_for_read_obj,
 451             feature.fi_guid)) {
 452                 feature.fi_can_readonly = B_FALSE;
 453         } else if (0 == zap_contains(mos, spa->spa_feat_for_write_obj,
 454             feature.fi_guid)) {
 455                 feature.fi_can_readonly = B_TRUE;
 456         } else {
 457                 fatal(spa, FTAG, "feature is not enabled: %s", feature.fi_guid);
 458         }
 459 
 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         }
 468 
 469         VERIFY0(dsl_sync_task(spa_name(spa), NULL,
 470             decr ? feature_decr_sync : feature_incr_sync, &feature, 5));
 471 
 472         spa_close(spa, FTAG);
 473 }
 474 
 475 static int
 476 zhack_do_feature(int argc, char **argv)
 477 {
 478         char *subcommand;
 479 
 480         argc--;
 481         argv++;
 482         if (argc == 0) {
 483                 (void) fprintf(stderr,
 484                     "error: no feature operation specified\n");
 485                 usage();
 486         }
 487