xref: /freebsd/sys/contrib/openzfs/include/sys/vdev_raidz.h (revision 22649d4dba730d46244fd2dff4fd174903c8379f)
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