1 // SPDX-License-Identifier: CDDL-1.0 2 /* 3 * This file and its contents are supplied under the terms of the 4 * Common Development and Distribution License ("CDDL"), version 1.0. 5 * You may only use this file in accordance with the terms of version 6 * 1.0 of the CDDL. 7 * 8 * A full copy of the text of the CDDL should have accompanied this 9 * source. A copy of the CDDL is also available via the Internet at 10 * https://opensource.org/license/CDDL-1.0. 11 */ 12 /* 13 * Copyright (C) 2016 Gvozden Neskovic <neskovic@compeng.uni-frankfurt.de>. 14 */ 15 16 #ifndef _SYS_VDEV_RAIDZ_H 17 #define _SYS_VDEV_RAIDZ_H 18 19 #include <sys/types.h> 20 #include <sys/zfs_rlock.h> 21 22 #ifdef __cplusplus 23 extern "C" { 24 #endif 25 26 struct zio; 27 struct raidz_col; 28 struct raidz_row; 29 struct raidz_map; 30 struct vdev_raidz; 31 struct uberblock; 32 #if !defined(_KERNEL) 33 struct kernel_param {}; 34 #endif 35 36 /* 37 * vdev_raidz interface 38 */ 39 struct raidz_map *vdev_raidz_map_alloc(struct zio *, uint64_t, uint64_t, 40 uint64_t); 41 struct raidz_map *vdev_raidz_map_alloc_expanded(struct zio *, 42 uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, boolean_t); 43 void vdev_raidz_map_free(struct raidz_map *); 44 void vdev_raidz_free(struct vdev_raidz *); 45 void vdev_raidz_generate_parity_row(struct raidz_map *, struct raidz_row *); 46 void vdev_raidz_generate_parity(struct raidz_map *); 47 void vdev_raidz_reconstruct(struct raidz_map *, const int *, int); 48 void vdev_raidz_child_done(zio_t *); 49 void vdev_raidz_io_done(zio_t *); 50 void vdev_raidz_checksum_error(zio_t *, struct raidz_col *, abd_t *); 51 struct raidz_row *vdev_raidz_row_alloc(int, zio_t *); 52 void vdev_raidz_reflow_copy_scratch(spa_t *); 53 void raidz_dtl_reassessed(vdev_t *); 54 boolean_t vdev_sit_out_reads(vdev_t *, zio_flag_t); 55 void vdev_raidz_sit_child(vdev_t *, uint64_t); 56 void vdev_raidz_unsit_child(vdev_t *); 57 58 extern const zio_vsd_ops_t vdev_raidz_vsd_ops; 59 60 /* 61 * vdev_raidz_math interface 62 */ 63 /* Required, but not used, by ZFS_MODULE_PARAM_CALL */ 64 extern uint32_t zfs_vdev_raidz_impl; 65 void vdev_raidz_math_init(void); 66 void vdev_raidz_math_fini(void); 67 const struct raidz_impl_ops *vdev_raidz_math_get_ops(void); 68 int vdev_raidz_math_generate(struct raidz_map *, struct raidz_row *); 69 int vdev_raidz_math_reconstruct(struct raidz_map *, struct raidz_row *, 70 const int *, const int *, const int); 71 int vdev_raidz_impl_set(const char *); 72 int vdev_raidz_impl_get(char *buffer, size_t size); 73 74 typedef struct vdev_raidz_expand { 75 uint64_t vre_vdev_id; 76 77 kmutex_t vre_lock; 78 kcondvar_t vre_cv; 79 80 /* 81 * How much i/o is outstanding (issued and not completed). 82 */ 83 uint64_t vre_outstanding_bytes; 84 85 /* 86 * Next offset to issue i/o for. 87 */ 88 uint64_t vre_offset; 89 90 /* 91 * Lowest offset of a failed expansion i/o. The expansion will retry 92 * from here. Once the expansion thread notices the failure and exits, 93 * vre_failed_offset is reset back to UINT64_MAX, and 94 * vre_waiting_for_resilver will be set. 95 */ 96 uint64_t vre_failed_offset; 97 boolean_t vre_waiting_for_resilver; 98 99 /* 100 * Offset that is completing each txg 101 */ 102 uint64_t vre_offset_pertxg[TXG_SIZE]; 103 104 /* 105 * Bytes copied in each txg. 106 */ 107 uint64_t vre_bytes_copied_pertxg[TXG_SIZE]; 108 109 /* 110 * The rangelock prevents normal read/write zio's from happening while 111 * there are expansion (reflow) i/os in progress to the same offsets. 112 */ 113 zfs_rangelock_t vre_rangelock; 114 115 /* 116 * These fields are stored on-disk in the vdev_top_zap: 117 */ 118 dsl_scan_state_t vre_state; 119 uint64_t vre_start_time; 120 uint64_t vre_end_time; 121 uint64_t vre_bytes_copied; 122 } vdev_raidz_expand_t; 123 124 typedef struct vdev_raidz { 125 /* 126 * Number of child vdevs when this raidz vdev was created (i.e. before 127 * any raidz expansions). 128 */ 129 int vd_original_width; 130 131 /* 132 * The current number of child vdevs, which may be more than the 133 * original width if an expansion is in progress or has completed. 134 */ 135 int vd_physical_width; 136 137 int vd_nparity; 138 139 /* 140 * Tree of reflow_node_t's. The lock protects the avl tree only. 141 * The reflow_node_t's describe completed expansions, and are used 142 * to determine the logical width given a block's birth time. 143 */ 144 avl_tree_t vd_expand_txgs; 145 kmutex_t vd_expand_lock; 146 147 /* 148 * If this vdev is being expanded, spa_raidz_expand is set to this 149 */ 150 vdev_raidz_expand_t vn_vre; 151 } vdev_raidz_t; 152 153 extern int vdev_raidz_attach_check(vdev_t *); 154 extern void vdev_raidz_attach_sync(void *, dmu_tx_t *); 155 extern void spa_start_raidz_expansion_thread(spa_t *); 156 extern int spa_raidz_expand_get_stats(spa_t *, pool_raidz_expand_stat_t *); 157 extern int vdev_raidz_load(vdev_t *); 158 159 /* RAIDZ scratch area pause points (for testing) */ 160 #define RAIDZ_EXPAND_PAUSE_NONE 0 161 #define RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_1 1 162 #define RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_2 2 163 #define RAIDZ_EXPAND_PAUSE_PRE_SCRATCH_3 3 164 #define RAIDZ_EXPAND_PAUSE_SCRATCH_VALID 4 165 #define RAIDZ_EXPAND_PAUSE_SCRATCH_REFLOWED 5 166 #define RAIDZ_EXPAND_PAUSE_SCRATCH_POST_REFLOW_1 6 167 #define RAIDZ_EXPAND_PAUSE_SCRATCH_POST_REFLOW_2 7 168 169 #ifdef __cplusplus 170 } 171 #endif 172 173 #endif /* _SYS_VDEV_RAIDZ_H */ 174