]> git.proxmox.com Git - mirror_zfs.git/blobdiff - include/sys/vdev_raidz.h
RAID-Z expansion feature
[mirror_zfs.git] / include / sys / vdev_raidz.h
index e34b6e4b158e10b9be8e5f38fa8eaca211b9601f..a34bc00ca4df8b7762a7f8cee5c8d15eb7d38213 100644 (file)
@@ -26,6 +26,7 @@
 #define        _SYS_VDEV_RAIDZ_H
 
 #include <sys/types.h>
+#include <sys/zfs_rlock.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -35,6 +36,8 @@ struct zio;
 struct raidz_col;
 struct raidz_row;
 struct raidz_map;
+struct vdev_raidz;
+struct uberblock;
 #if !defined(_KERNEL)
 struct kernel_param {};
 #endif
@@ -44,13 +47,19 @@ struct kernel_param {};
  */
 struct raidz_map *vdev_raidz_map_alloc(struct zio *, uint64_t, uint64_t,
     uint64_t);
+struct raidz_map *vdev_raidz_map_alloc_expanded(struct zio *,
+    uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, boolean_t);
 void vdev_raidz_map_free(struct raidz_map *);
+void vdev_raidz_free(struct vdev_raidz *);
 void vdev_raidz_generate_parity_row(struct raidz_map *, struct raidz_row *);
 void vdev_raidz_generate_parity(struct raidz_map *);
 void vdev_raidz_reconstruct(struct raidz_map *, const int *, int);
 void vdev_raidz_child_done(zio_t *);
 void vdev_raidz_io_done(zio_t *);
 void vdev_raidz_checksum_error(zio_t *, struct raidz_col *, abd_t *);
+struct raidz_row *vdev_raidz_row_alloc(int);
+void vdev_raidz_reflow_copy_scratch(spa_t *);
+void raidz_dtl_reassessed(vdev_t *);
 
 extern const zio_vsd_ops_t vdev_raidz_vsd_ops;
 
@@ -65,11 +74,101 @@ int vdev_raidz_math_reconstruct(struct raidz_map *, struct raidz_row *,
     const int *, const int *, const int);
 int vdev_raidz_impl_set(const char *);
 
+typedef struct vdev_raidz_expand {
+       uint64_t vre_vdev_id;
+
+       kmutex_t vre_lock;
+       kcondvar_t vre_cv;
+
+       /*
+        * How much i/o is outstanding (issued and not completed).
+        */
+       uint64_t vre_outstanding_bytes;
+
+       /*
+        * Next offset to issue i/o for.
+        */
+       uint64_t vre_offset;
+
+       /*
+        * Lowest offset of a failed expansion i/o.  The expansion will retry
+        * from here.  Once the expansion thread notices the failure and exits,
+        * vre_failed_offset is reset back to UINT64_MAX, and
+        * vre_waiting_for_resilver will be set.
+        */
+       uint64_t vre_failed_offset;
+       boolean_t vre_waiting_for_resilver;
+
+       /*
+        * Offset that is completing each txg
+        */
+       uint64_t vre_offset_pertxg[TXG_SIZE];
+
+       /*
+        * Bytes copied in each txg.
+        */
+       uint64_t vre_bytes_copied_pertxg[TXG_SIZE];
+
+       /*
+        * The rangelock prevents normal read/write zio's from happening while
+        * there are expansion (reflow) i/os in progress to the same offsets.
+        */
+       zfs_rangelock_t vre_rangelock;
+
+       /*
+        * These fields are stored on-disk in the vdev_top_zap:
+        */
+       dsl_scan_state_t vre_state;
+       uint64_t vre_start_time;
+       uint64_t vre_end_time;
+       uint64_t vre_bytes_copied;
+} vdev_raidz_expand_t;
+
 typedef struct vdev_raidz {
-       int vd_logical_width;
+       /*
+        * Number of child vdevs when this raidz vdev was created (i.e. before
+        * any raidz expansions).
+        */
+       int vd_original_width;
+
+       /*
+        * The current number of child vdevs, which may be more than the
+        * original width if an expansion is in progress or has completed.
+        */
+       int vd_physical_width;
+
        int vd_nparity;
+
+       /*
+        * Tree of reflow_node_t's.  The lock protects the avl tree only.
+        * The reflow_node_t's describe completed expansions, and are used
+        * to determine the logical width given a block's birth time.
+        */
+       avl_tree_t vd_expand_txgs;
+       kmutex_t vd_expand_lock;
+
+       /*
+        * If this vdev is being expanded, spa_raidz_expand is set to this
+        */
+       vdev_raidz_expand_t vn_vre;
 } vdev_raidz_t;
 
+extern int vdev_raidz_attach_check(vdev_t *);
+extern void vdev_raidz_attach_sync(void *, dmu_tx_t *);
+extern void spa_start_raidz_expansion_thread(spa_t *);
+extern int spa_raidz_expand_get_stats(spa_t *, pool_raidz_expand_stat_t *);
+extern int vdev_raidz_load(vdev_t *);
+
+/* RAIDZ scratch area pause points (for testing) */
+#define        RAIDZ_EXPAND_PAUSE_NONE 0
+#define        RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_1 1
+#define        RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_2 2
+#define        RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_3 3
+#define        RAIDZ_EXPAND_PAUSE_SCRATCH_VALID 4
+#define        RAIDZ_EXPAND_PAUSE_SCRATCH_REFLOWED 5
+#define        RAIDZ_EXPAND_PAUSE_SCRATCH_POST_REFLOW_1 6
+#define        RAIDZ_EXPAND_PAUSE_SCRATCH_POST_REFLOW_2 7
+
 #ifdef __cplusplus
 }
 #endif