]> granicus.if.org Git - zfs/blobdiff - cmd/ztest/ztest.c
OpenZFS 9166 - zfs storage pool checkpoint
[zfs] / cmd / ztest / ztest.c
index 83a8b4f3ccef30c0e8d31be5478190d066f14271..78ad7e8de0a06a7833cddd8a7b52435dc9ab4dd3 100644 (file)
@@ -345,6 +345,7 @@ ztest_func_t ztest_reguid;
 ztest_func_t ztest_spa_upgrade;
 ztest_func_t ztest_device_removal;
 ztest_func_t ztest_remap_blocks;
+ztest_func_t ztest_spa_checkpoint_create_discard;
 ztest_func_t ztest_fletcher;
 ztest_func_t ztest_fletcher_incr;
 ztest_func_t ztest_verify_dnode_bt;
@@ -397,6 +398,7 @@ ztest_info_t ztest_info[] = {
        ZTI_INIT(ztest_vdev_aux_add_remove, 1, &ztest_opts.zo_vdevtime),
        ZTI_INIT(ztest_device_removal, 1, &zopt_sometimes),
        ZTI_INIT(ztest_remap_blocks, 1, &zopt_sometimes),
+       ZTI_INIT(ztest_spa_checkpoint_create_discard, 1, &zopt_rarely),
        ZTI_INIT(ztest_fletcher, 1, &zopt_rarely),
        ZTI_INIT(ztest_fletcher_incr, 1, &zopt_rarely),
        ZTI_INIT(ztest_verify_dnode_bt, 1, &zopt_sometimes),
@@ -446,6 +448,7 @@ static ztest_ds_t *ztest_ds;
 
 static kmutex_t ztest_vdev_lock;
 static boolean_t ztest_device_removal_active = B_FALSE;
+static kmutex_t ztest_checkpoint_lock;
 
 /*
  * The ztest_name_lock protects the pool and dataset namespace used by
@@ -2864,6 +2867,62 @@ ztest_spa_upgrade(ztest_ds_t *zd, uint64_t id)
        mutex_exit(&ztest_vdev_lock);
 }
 
+static void
+ztest_spa_checkpoint(spa_t *spa)
+{
+       ASSERT(MUTEX_HELD(&ztest_checkpoint_lock));
+
+       int error = spa_checkpoint(spa->spa_name);
+
+       switch (error) {
+       case 0:
+       case ZFS_ERR_DEVRM_IN_PROGRESS:
+       case ZFS_ERR_DISCARDING_CHECKPOINT:
+       case ZFS_ERR_CHECKPOINT_EXISTS:
+               break;
+       case ENOSPC:
+               ztest_record_enospc(FTAG);
+               break;
+       default:
+               fatal(0, "spa_checkpoint(%s) = %d", spa->spa_name, error);
+       }
+}
+
+static void
+ztest_spa_discard_checkpoint(spa_t *spa)
+{
+       ASSERT(MUTEX_HELD(&ztest_checkpoint_lock));
+
+       int error = spa_checkpoint_discard(spa->spa_name);
+
+       switch (error) {
+       case 0:
+       case ZFS_ERR_DISCARDING_CHECKPOINT:
+       case ZFS_ERR_NO_CHECKPOINT:
+               break;
+       default:
+               fatal(0, "spa_discard_checkpoint(%s) = %d",
+                   spa->spa_name, error);
+       }
+
+}
+
+/* ARGSUSED */
+void
+ztest_spa_checkpoint_create_discard(ztest_ds_t *zd, uint64_t id)
+{
+       spa_t *spa = ztest_spa;
+
+       mutex_enter(&ztest_checkpoint_lock);
+       if (ztest_random(2) == 0) {
+               ztest_spa_checkpoint(spa);
+       } else {
+               ztest_spa_discard_checkpoint(spa);
+       }
+       mutex_exit(&ztest_checkpoint_lock);
+}
+
+
 static vdev_t *
 vdev_lookup_by_path(vdev_t *vd, const char *path)
 {
@@ -2953,6 +3012,8 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
                case EEXIST:    /* Generic zil_reset() error */
                case EBUSY:     /* Replay required */
                case EACCES:    /* Crypto key not loaded */
+               case ZFS_ERR_CHECKPOINT_EXISTS:
+               case ZFS_ERR_DISCARDING_CHECKPOINT:
                        break;
                default:
                        fatal(0, "spa_vdev_remove() = %d", error);
@@ -2971,10 +3032,15 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
                error = spa_vdev_add(spa, nvroot);
                nvlist_free(nvroot);
 
-               if (error == ENOSPC)
+               switch (error) {
+               case 0:
+                       break;
+               case ENOSPC:
                        ztest_record_enospc("spa_vdev_add");
-               else if (error != 0)
+                       break;
+               default:
                        fatal(0, "spa_vdev_add() = %d", error);
+               }
        }
 
        mutex_exit(&ztest_vdev_lock);
@@ -3048,8 +3114,13 @@ ztest_vdev_aux_add_remove(ztest_ds_t *zd, uint64_t id)
                nvlist_t *nvroot = make_vdev_root(NULL, aux, NULL,
                    (ztest_opts.zo_vdev_size * 5) / 4, 0, 0, 0, 0, 1);
                error = spa_vdev_add(spa, nvroot);
-               if (error != 0)
+
+               switch (error) {
+               case 0:
+                       break;
+               default:
                        fatal(0, "spa_vdev_add(%p) = %d", nvroot, error);
+               }
                nvlist_free(nvroot);
        } else {
                /*
@@ -3061,8 +3132,16 @@ ztest_vdev_aux_add_remove(ztest_ds_t *zd, uint64_t id)
                        (void) vdev_online(spa, guid, 0, NULL);
 
                error = spa_vdev_remove(spa, guid, B_FALSE);
-               if (error != 0 && error != EBUSY)
+
+               switch (error) {
+               case 0:
+               case EBUSY:
+               case ZFS_ERR_CHECKPOINT_EXISTS:
+               case ZFS_ERR_DISCARDING_CHECKPOINT:
+                       break;
+               default:
                        fatal(0, "spa_vdev_remove(%llu) = %d", guid, error);
+               }
        }
 
        mutex_exit(&ztest_vdev_lock);
@@ -3166,7 +3245,6 @@ ztest_split_pool(ztest_ds_t *zd, uint64_t id)
                --zs->zs_mirrors;
        }
        mutex_exit(&ztest_vdev_lock);
-
 }
 
 /*
@@ -3271,7 +3349,8 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
                spa_config_exit(spa, SCL_ALL, FTAG);
                error = spa_vdev_detach(spa, oldguid, pguid, B_FALSE);
                if (error != 0 && error != ENODEV && error != EBUSY &&
-                   error != ENOTSUP)
+                   error != ENOTSUP && error != ZFS_ERR_CHECKPOINT_EXISTS &&
+                   error != ZFS_ERR_DISCARDING_CHECKPOINT)
                        fatal(0, "detach (%s) returned %d", oldpath, error);
                goto out;
        }
@@ -3362,6 +3441,10 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
        if (error == EOVERFLOW || error == EBUSY)
                expected_error = error;
 
+       if (error == ZFS_ERR_CHECKPOINT_EXISTS ||
+           error == ZFS_ERR_DISCARDING_CHECKPOINT)
+               expected_error = error;
+
        /* XXX workaround 6690467 */
        if (error != expected_error && expected_error != EBUSY) {
                fatal(0, "attach (%s %llu, %s %llu, %d) "
@@ -3556,6 +3639,7 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
        uint64_t top;
        uint64_t old_class_space, new_class_space, old_ms_count, new_ms_count;
 
+       mutex_enter(&ztest_checkpoint_lock);
        mutex_enter(&ztest_vdev_lock);
        spa_config_enter(spa, SCL_STATE, spa, RW_READER);
 
@@ -3566,8 +3650,9 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
         * when the device removal completes).
         */
        if (ztest_device_removal_active) {
-               spa_config_exit(spa, SCL_STATE, FTAG);
+               spa_config_exit(spa, SCL_STATE, spa);
                mutex_exit(&ztest_vdev_lock);
+               mutex_exit(&ztest_checkpoint_lock);
                return;
        }
 
@@ -3597,6 +3682,7 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
            psize == 0 || psize >= 4 * ztest_opts.zo_vdev_size) {
                spa_config_exit(spa, SCL_STATE, spa);
                mutex_exit(&ztest_vdev_lock);
+               mutex_exit(&ztest_checkpoint_lock);
                return;
        }
        ASSERT(psize > 0);
@@ -3622,6 +3708,7 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
                }
                spa_config_exit(spa, SCL_STATE, spa);
                mutex_exit(&ztest_vdev_lock);
+               mutex_exit(&ztest_checkpoint_lock);
                return;
        }
 
@@ -3656,6 +3743,7 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
                }
                spa_config_exit(spa, SCL_STATE, spa);
                mutex_exit(&ztest_vdev_lock);
+               mutex_exit(&ztest_checkpoint_lock);
                return;
        }
 
@@ -3686,6 +3774,7 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
 
        spa_config_exit(spa, SCL_STATE, spa);
        mutex_exit(&ztest_vdev_lock);
+       mutex_exit(&ztest_checkpoint_lock);
 }
 
 /*
@@ -5722,7 +5811,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
         */
        fd = open(pathrand, O_RDWR);
 
-       if (fd == -1)   /* we hit a gap in the device namespace */
+       if (fd == -1) /* we hit a gap in the device namespace */
                goto out;
 
        fsize = lseek(fd, 0, SEEK_END);
@@ -6645,6 +6734,7 @@ ztest_run(ztest_shared_t *zs)
         * Initialize parent/child shared state.
         */
        mutex_init(&ztest_vdev_lock, NULL, MUTEX_DEFAULT, NULL);
+       mutex_init(&ztest_checkpoint_lock, NULL, MUTEX_DEFAULT, NULL);
        VERIFY0(pthread_rwlock_init(&ztest_name_lock, NULL));
 
        zs->zs_thread_start = gethrtime();
@@ -6696,7 +6786,7 @@ ztest_run(ztest_shared_t *zs)
        spa->spa_deadman_failmode = ZIO_FAILURE_MODE_PANIC;
 
        /*
-        * Verify that we can safely inquire about about any object,
+        * Verify that we can safely inquire about any object,
         * whether it's allocated or not.  To make it interesting,
         * we probe a 5-wide window around each power of two.
         * This hits all edge cases, including zero and the max.
@@ -6804,6 +6894,7 @@ ztest_run(ztest_shared_t *zs)
        mutex_destroy(&zcl.zcl_callbacks_lock);
        (void) pthread_rwlock_destroy(&ztest_name_lock);
        mutex_destroy(&ztest_vdev_lock);
+       mutex_destroy(&ztest_checkpoint_lock);
 }
 
 static void
@@ -6953,6 +7044,7 @@ ztest_import(ztest_shared_t *zs)
        int error;
 
        mutex_init(&ztest_vdev_lock, NULL, MUTEX_DEFAULT, NULL);
+       mutex_init(&ztest_checkpoint_lock, NULL, MUTEX_DEFAULT, NULL);
        VERIFY0(pthread_rwlock_init(&ztest_name_lock, NULL));
 
        kernel_init(FREAD | FWRITE);
@@ -6984,6 +7076,7 @@ ztest_import(ztest_shared_t *zs)
 
        (void) pthread_rwlock_destroy(&ztest_name_lock);
        mutex_destroy(&ztest_vdev_lock);
+       mutex_destroy(&ztest_checkpoint_lock);
 }
 
 /*
@@ -6998,6 +7091,7 @@ ztest_init(ztest_shared_t *zs)
        int i;
 
        mutex_init(&ztest_vdev_lock, NULL, MUTEX_DEFAULT, NULL);
+       mutex_init(&ztest_checkpoint_lock, NULL, MUTEX_DEFAULT, NULL);
        VERIFY0(pthread_rwlock_init(&ztest_name_lock, NULL));
 
        kernel_init(FREAD | FWRITE);
@@ -7049,6 +7143,7 @@ ztest_init(ztest_shared_t *zs)
 
        (void) pthread_rwlock_destroy(&ztest_name_lock);
        mutex_destroy(&ztest_vdev_lock);
+       mutex_destroy(&ztest_checkpoint_lock);
 }
 
 static void