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
|