dm: Move targets specific structs to .c files These don't need to be defined and exposed in dm.h.diff -r1.36 -r1.37 src/sys/dev/dm/dm.h
(tkusumi)
--- src/sys/dev/dm/dm.h 2019/12/08 10:35:53 1.36
+++ src/sys/dev/dm/dm.h 2019/12/08 10:50:21 1.37
@@ -1,337 +1,298 @@ | @@ -1,337 +1,298 @@ | |||
1 | /* $NetBSD: dm.h,v 1.36 2019/12/08 10:35:53 tkusumi Exp $ */ | 1 | /* $NetBSD: dm.h,v 1.37 2019/12/08 10:50:21 tkusumi Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Adam Hamsik. | 8 | * by Adam Hamsik. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #ifndef _DM_DEV_H_ | 32 | #ifndef _DM_DEV_H_ | |
33 | #define _DM_DEV_H_ | 33 | #define _DM_DEV_H_ | |
34 | 34 | |||
35 | 35 | |||
36 | #ifdef _KERNEL | 36 | #ifdef _KERNEL | |
37 | 37 | |||
38 | #include <sys/errno.h> | 38 | #include <sys/errno.h> | |
39 | 39 | |||
40 | #include <sys/atomic.h> | 40 | #include <sys/atomic.h> | |
41 | #include <sys/fcntl.h> | 41 | #include <sys/fcntl.h> | |
42 | #include <sys/condvar.h> | 42 | #include <sys/condvar.h> | |
43 | #include <sys/kauth.h> | 43 | #include <sys/kauth.h> | |
44 | #include <sys/mutex.h> | 44 | #include <sys/mutex.h> | |
45 | #include <sys/rwlock.h> | 45 | #include <sys/rwlock.h> | |
46 | #include <sys/queue.h> | 46 | #include <sys/queue.h> | |
47 | #include <sys/vnode.h> | 47 | #include <sys/vnode.h> | |
48 | 48 | |||
49 | #include <sys/device.h> | 49 | #include <sys/device.h> | |
50 | #include <sys/disk.h> | 50 | #include <sys/disk.h> | |
51 | #include <sys/disklabel.h> | 51 | #include <sys/disklabel.h> | |
52 | 52 | |||
53 | #include <miscfs/specfs/specdev.h> /* for v_rdev */ | 53 | #include <miscfs/specfs/specdev.h> /* for v_rdev */ | |
54 | 54 | |||
55 | #include <prop/proplib.h> | 55 | #include <prop/proplib.h> | |
56 | 56 | |||
57 | #define DM_MAX_TYPE_NAME 16 | 57 | #define DM_MAX_TYPE_NAME 16 | |
58 | #define DM_NAME_LEN 128 | 58 | #define DM_NAME_LEN 128 | |
59 | #define DM_UUID_LEN 129 | 59 | #define DM_UUID_LEN 129 | |
60 | 60 | |||
61 | #define DM_VERSION_MAJOR 4 | 61 | #define DM_VERSION_MAJOR 4 | |
62 | #define DM_VERSION_MINOR 16 | 62 | #define DM_VERSION_MINOR 16 | |
63 | 63 | |||
64 | #define DM_VERSION_PATCHLEVEL 0 | 64 | #define DM_VERSION_PATCHLEVEL 0 | |
65 | 65 | |||
66 | /*** Internal device-mapper structures ***/ | 66 | /*** Internal device-mapper structures ***/ | |
67 | 67 | |||
68 | /* | 68 | /* | |
69 | * A device mapper table is a list of physical ranges plus the mapping target | 69 | * A device mapper table is a list of physical ranges plus the mapping target | |
70 | * applied to them. | 70 | * applied to them. | |
71 | */ | 71 | */ | |
72 | 72 | |||
73 | typedef struct dm_table_entry { | 73 | typedef struct dm_table_entry { | |
74 | struct dm_dev *dm_dev; /* backlink */ | 74 | struct dm_dev *dm_dev; /* backlink */ | |
75 | uint64_t start; | 75 | uint64_t start; | |
76 | uint64_t length; | 76 | uint64_t length; | |
77 | 77 | |||
78 | struct dm_target *target; /* Link to table target. */ | 78 | struct dm_target *target; /* Link to table target. */ | |
79 | void *target_config; /* Target specific data. */ | 79 | void *target_config; /* Target specific data. */ | |
80 | SLIST_ENTRY(dm_table_entry) next; | 80 | SLIST_ENTRY(dm_table_entry) next; | |
81 | } dm_table_entry_t; | 81 | } dm_table_entry_t; | |
82 | 82 | |||
83 | SLIST_HEAD(dm_table, dm_table_entry); | 83 | SLIST_HEAD(dm_table, dm_table_entry); | |
84 | 84 | |||
85 | typedef struct dm_table dm_table_t; | 85 | typedef struct dm_table dm_table_t; | |
86 | 86 | |||
87 | typedef struct dm_table_head { | 87 | typedef struct dm_table_head { | |
88 | /* Current active table is selected with this. */ | 88 | /* Current active table is selected with this. */ | |
89 | int cur_active_table; | 89 | int cur_active_table; | |
90 | struct dm_table tables[2]; | 90 | struct dm_table tables[2]; | |
91 | 91 | |||
92 | kmutex_t table_mtx; | 92 | kmutex_t table_mtx; | |
93 | kcondvar_t table_cv; /*IO waiting cv */ | 93 | kcondvar_t table_cv; /*IO waiting cv */ | |
94 | 94 | |||
95 | uint32_t io_cnt; | 95 | uint32_t io_cnt; | |
96 | } dm_table_head_t; | 96 | } dm_table_head_t; | |
97 | 97 | |||
98 | #define MAX_DEV_NAME 32 | 98 | #define MAX_DEV_NAME 32 | |
99 | 99 | |||
100 | /* | 100 | /* | |
101 | * This structure is used to store opened vnodes for disk with name. | 101 | * This structure is used to store opened vnodes for disk with name. | |
102 | * I need this because devices can be opened only once, but I can | 102 | * I need this because devices can be opened only once, but I can | |
103 | * have more than one device on one partition. | 103 | * have more than one device on one partition. | |
104 | */ | 104 | */ | |
105 | 105 | |||
106 | typedef struct dm_pdev { | 106 | typedef struct dm_pdev { | |
107 | char name[MAX_DEV_NAME]; | 107 | char name[MAX_DEV_NAME]; | |
108 | 108 | |||
109 | struct vnode *pdev_vnode; | 109 | struct vnode *pdev_vnode; | |
110 | uint64_t pdev_numsec; | 110 | uint64_t pdev_numsec; | |
111 | unsigned pdev_secsize; | 111 | unsigned pdev_secsize; | |
112 | int ref_cnt; /* reference counter for users ofthis pdev */ | 112 | int ref_cnt; /* reference counter for users ofthis pdev */ | |
113 | 113 | |||
114 | SLIST_ENTRY(dm_pdev) next_pdev; | 114 | SLIST_ENTRY(dm_pdev) next_pdev; | |
115 | } dm_pdev_t; | 115 | } dm_pdev_t; | |
116 | 116 | |||
117 | /* | 117 | /* | |
118 | * This structure is called for every device-mapper device. | 118 | * This structure is called for every device-mapper device. | |
119 | * It points to SLIST of device tables and mirrored, snapshoted etc. devices. | 119 | * It points to SLIST of device tables and mirrored, snapshoted etc. devices. | |
120 | */ | 120 | */ | |
121 | TAILQ_HEAD(dm_dev_head, dm_dev); | 121 | TAILQ_HEAD(dm_dev_head, dm_dev); | |
122 | //extern struct dm_dev_head dm_devs; | 122 | //extern struct dm_dev_head dm_devs; | |
123 | 123 | |||
124 | typedef struct dm_dev { | 124 | typedef struct dm_dev { | |
125 | char name[DM_NAME_LEN]; | 125 | char name[DM_NAME_LEN]; | |
126 | char uuid[DM_UUID_LEN]; | 126 | char uuid[DM_UUID_LEN]; | |
127 | 127 | |||
128 | device_t devt; /* pointer to autoconf device_t structure */ | 128 | device_t devt; /* pointer to autoconf device_t structure */ | |
129 | uint64_t minor; /* Device minor number */ | 129 | uint64_t minor; /* Device minor number */ | |
130 | uint32_t flags; /* store communication protocol flags */ | 130 | uint32_t flags; /* store communication protocol flags */ | |
131 | 131 | |||
132 | kmutex_t dev_mtx; /* mutex for generall device lock */ | 132 | kmutex_t dev_mtx; /* mutex for generall device lock */ | |
133 | kcondvar_t dev_cv; /* cv for between ioctl synchronisation */ | 133 | kcondvar_t dev_cv; /* cv for between ioctl synchronisation */ | |
134 | 134 | |||
135 | uint32_t event_nr; | 135 | uint32_t event_nr; | |
136 | uint32_t ref_cnt; | 136 | uint32_t ref_cnt; | |
137 | 137 | |||
138 | dm_table_head_t table_head; | 138 | dm_table_head_t table_head; | |
139 | 139 | |||
140 | //struct dm_dev_head upcalls; | 140 | //struct dm_dev_head upcalls; | |
141 | 141 | |||
142 | struct disk *diskp; | 142 | struct disk *diskp; | |
143 | kmutex_t diskp_mtx; | 143 | kmutex_t diskp_mtx; | |
144 | 144 | |||
145 | //TAILQ_ENTRY(dm_dev) next_upcall; /* LIST of mirrored, snapshoted devices. */ | 145 | //TAILQ_ENTRY(dm_dev) next_upcall; /* LIST of mirrored, snapshoted devices. */ | |
146 | 146 | |||
147 | TAILQ_ENTRY(dm_dev) next_devlist; /* Major device list. */ | 147 | TAILQ_ENTRY(dm_dev) next_devlist; /* Major device list. */ | |
148 | } dm_dev_t; | 148 | } dm_dev_t; | |
149 | 149 | |||
150 | /* for zero, error : dm_target->target_config == NULL */ | 150 | /* for zero, error : dm_target->target_config == NULL */ | |
151 | 151 | |||
152 | /* | 152 | /* | |
153 | * Target config is initiated with target_init function. | 153 | * Target config is initiated with target_init function. | |
154 | */ | 154 | */ | |
155 | 155 | |||
156 | /* for linear : */ | 156 | /* for linear : */ | |
157 | typedef struct target_linear_config { | 157 | typedef struct target_linear_config { | |
158 | dm_pdev_t *pdev; | 158 | dm_pdev_t *pdev; | |
159 | uint64_t offset; | 159 | uint64_t offset; | |
160 | TAILQ_ENTRY(target_linear_config) entries; | 160 | TAILQ_ENTRY(target_linear_config) entries; | |
161 | } dm_target_linear_config_t; | 161 | } dm_target_linear_config_t; | |
162 | 162 | |||
163 | /* | 163 | /* | |
164 | * Striping devices are stored in a linked list, this might be inefficient | 164 | * Striping devices are stored in a linked list, this might be inefficient | |
165 | * for more than 8 striping devices and can be changed to something more | 165 | * for more than 8 striping devices and can be changed to something more | |
166 | * scalable. | 166 | * scalable. | |
167 | * TODO: look for other options than linked list. | 167 | * TODO: look for other options than linked list. | |
168 | */ | 168 | */ | |
169 | TAILQ_HEAD(target_linear_devs, target_linear_config); | 169 | TAILQ_HEAD(target_linear_devs, target_linear_config); | |
170 | 170 | |||
171 | typedef struct target_linear_devs dm_target_linear_devs_t; | 171 | typedef struct target_linear_devs dm_target_linear_devs_t; | |
172 | 172 | |||
173 | /* for stripe : */ | |||
174 | typedef struct target_stripe_config { | |||
175 | #define DM_STRIPE_DEV_OFFSET 2 | |||
176 | struct target_linear_devs stripe_devs; | |||
177 | uint8_t stripe_num; | |||
178 | uint64_t stripe_chunksize; | |||
179 | size_t params_len; | |||
180 | } dm_target_stripe_config_t; | |||
181 | ||||
182 | /* for mirror : */ | |||
183 | typedef struct target_mirror_config { | |||
184 | #define MAX_MIRROR_COPIES 4 | |||
185 | dm_pdev_t *orig; | |||
186 | dm_pdev_t *copies[MAX_MIRROR_COPIES]; | |||
187 | ||||
188 | /* copied blocks bitmaps administration etc*/ | |||
189 | dm_pdev_t *log_pdev; /* for administration */ | |||
190 | uint64_t log_regionsize; /* blocksize of mirror */ | |||
191 | ||||
192 | /* list of parts that still need copied etc.; run length encoded? */ | |||
193 | } dm_target_mirror_config_t; | |||
194 | ||||
195 | ||||
196 | /* for snapshot : */ | |||
197 | typedef struct target_snapshot_config { | |||
198 | dm_pdev_t *tsc_snap_dev; | |||
199 | /* cow dev is set only for persistent snapshot devices */ | |||
200 | dm_pdev_t *tsc_cow_dev; | |||
201 | ||||
202 | uint64_t tsc_chunk_size; | |||
203 | uint32_t tsc_persistent_dev; | |||
204 | } dm_target_snapshot_config_t; | |||
205 | ||||
206 | /* for snapshot-origin devices */ | |||
207 | typedef struct target_snapshot_origin_config { | |||
208 | dm_pdev_t *tsoc_real_dev; | |||
209 | /* list of snapshots ? */ | |||
210 | } dm_target_snapshot_origin_config_t; | |||
211 | ||||
212 | /* constant dm_target structures for error, zero, linear, stripes etc. */ | 173 | /* constant dm_target structures for error, zero, linear, stripes etc. */ | |
213 | typedef struct dm_target { | 174 | typedef struct dm_target { | |
214 | char name[DM_MAX_TYPE_NAME]; | 175 | char name[DM_MAX_TYPE_NAME]; | |
215 | /* Initialize target_config area */ | 176 | /* Initialize target_config area */ | |
216 | int (*init)(dm_table_entry_t *, char *); | 177 | int (*init)(dm_table_entry_t *, char *); | |
217 | 178 | |||
218 | /* Destroy target_config area */ | 179 | /* Destroy target_config area */ | |
219 | int (*destroy)(dm_table_entry_t *); | 180 | int (*destroy)(dm_table_entry_t *); | |
220 | 181 | |||
221 | int (*deps) (dm_table_entry_t *, prop_array_t); | 182 | int (*deps) (dm_table_entry_t *, prop_array_t); | |
222 | /* | 183 | /* | |
223 | * Status routine is called to get params string, which is target | 184 | * Status routine is called to get params string, which is target | |
224 | * specific. When dm_table_status_ioctl is called with flag | 185 | * specific. When dm_table_status_ioctl is called with flag | |
225 | * DM_STATUS_TABLE_FLAG I have to sent params string back. | 186 | * DM_STATUS_TABLE_FLAG I have to sent params string back. | |
226 | */ | 187 | */ | |
227 | char * (*status)(void *); | 188 | char * (*status)(void *); | |
228 | int (*strategy)(dm_table_entry_t *, struct buf *); | 189 | int (*strategy)(dm_table_entry_t *, struct buf *); | |
229 | int (*sync)(dm_table_entry_t *); | 190 | int (*sync)(dm_table_entry_t *); | |
230 | int (*upcall)(dm_table_entry_t *, struct buf *); | 191 | int (*upcall)(dm_table_entry_t *, struct buf *); | |
231 | int (*secsize)(dm_table_entry_t *, unsigned *); | 192 | int (*secsize)(dm_table_entry_t *, unsigned *); | |
232 | 193 | |||
233 | uint32_t version[3]; | 194 | uint32_t version[3]; | |
234 | uint32_t ref_cnt; | 195 | uint32_t ref_cnt; | |
235 | 196 | |||
236 | TAILQ_ENTRY(dm_target) dm_target_next; | 197 | TAILQ_ENTRY(dm_target) dm_target_next; | |
237 | } dm_target_t; | 198 | } dm_target_t; | |
238 | 199 | |||
239 | /* Interface structures */ | 200 | /* Interface structures */ | |
240 | 201 | |||
241 | /* device-mapper */ | 202 | /* device-mapper */ | |
242 | void dmgetproperties(struct disk *, dm_table_head_t *); | 203 | void dmgetproperties(struct disk *, dm_table_head_t *); | |
243 | 204 | |||
244 | /* dm_ioctl.c */ | 205 | /* dm_ioctl.c */ | |
245 | int dm_dev_create_ioctl(prop_dictionary_t); | 206 | int dm_dev_create_ioctl(prop_dictionary_t); | |
246 | int dm_dev_list_ioctl(prop_dictionary_t); | 207 | int dm_dev_list_ioctl(prop_dictionary_t); | |
247 | int dm_dev_remove_ioctl(prop_dictionary_t); | 208 | int dm_dev_remove_ioctl(prop_dictionary_t); | |
248 | int dm_dev_rename_ioctl(prop_dictionary_t); | 209 | int dm_dev_rename_ioctl(prop_dictionary_t); | |
249 | int dm_dev_resume_ioctl(prop_dictionary_t); | 210 | int dm_dev_resume_ioctl(prop_dictionary_t); | |
250 | int dm_dev_status_ioctl(prop_dictionary_t); | 211 | int dm_dev_status_ioctl(prop_dictionary_t); | |
251 | int dm_dev_suspend_ioctl(prop_dictionary_t); | 212 | int dm_dev_suspend_ioctl(prop_dictionary_t); | |
252 | 213 | |||
253 | int dm_check_version(prop_dictionary_t); | 214 | int dm_check_version(prop_dictionary_t); | |
254 | int dm_list_versions_ioctl(prop_dictionary_t); | 215 | int dm_list_versions_ioctl(prop_dictionary_t); | |
255 | 216 | |||
256 | int dm_table_clear_ioctl(prop_dictionary_t); | 217 | int dm_table_clear_ioctl(prop_dictionary_t); | |
257 | int dm_table_deps_ioctl(prop_dictionary_t); | 218 | int dm_table_deps_ioctl(prop_dictionary_t); | |
258 | int dm_table_load_ioctl(prop_dictionary_t); | 219 | int dm_table_load_ioctl(prop_dictionary_t); | |
259 | int dm_table_status_ioctl(prop_dictionary_t); | 220 | int dm_table_status_ioctl(prop_dictionary_t); | |
260 | 221 | |||
261 | /* dm_target.c */ | 222 | /* dm_target.c */ | |
262 | dm_target_t* dm_target_alloc(const char *); | 223 | dm_target_t* dm_target_alloc(const char *); | |
263 | dm_target_t* dm_target_autoload(const char *); | 224 | dm_target_t* dm_target_autoload(const char *); | |
264 | int dm_target_destroy(void); | 225 | int dm_target_destroy(void); | |
265 | int dm_target_insert(dm_target_t *); | 226 | int dm_target_insert(dm_target_t *); | |
266 | prop_array_t dm_target_prop_list(void); | 227 | prop_array_t dm_target_prop_list(void); | |
267 | dm_target_t* dm_target_lookup(const char *); | 228 | dm_target_t* dm_target_lookup(const char *); | |
268 | int dm_target_rem(const char *); | 229 | int dm_target_rem(const char *); | |
269 | void dm_target_unbusy(dm_target_t *); | 230 | void dm_target_unbusy(dm_target_t *); | |
270 | void dm_target_busy(dm_target_t *); | 231 | void dm_target_busy(dm_target_t *); | |
271 | 232 | |||
272 | /* XXX temporally add */ | 233 | /* XXX temporally add */ | |
273 | int dm_target_init(void); | 234 | int dm_target_init(void); | |
274 | 235 | |||
275 | #define DM_MAX_PARAMS_SIZE 1024 | 236 | #define DM_MAX_PARAMS_SIZE 1024 | |
276 | 237 | |||
277 | /* dm_target_linear.c */ | 238 | /* dm_target_linear.c */ | |
278 | int dm_target_linear_init(dm_table_entry_t *, char *); | 239 | int dm_target_linear_init(dm_table_entry_t *, char *); | |
279 | char *dm_target_linear_status(void *); | 240 | char *dm_target_linear_status(void *); | |
280 | int dm_target_linear_strategy(dm_table_entry_t *, struct buf *); | 241 | int dm_target_linear_strategy(dm_table_entry_t *, struct buf *); | |
281 | int dm_target_linear_sync(dm_table_entry_t *); | 242 | int dm_target_linear_sync(dm_table_entry_t *); | |
282 | int dm_target_linear_deps(dm_table_entry_t *, prop_array_t); | 243 | int dm_target_linear_deps(dm_table_entry_t *, prop_array_t); | |
283 | int dm_target_linear_destroy(dm_table_entry_t *); | 244 | int dm_target_linear_destroy(dm_table_entry_t *); | |
284 | int dm_target_linear_upcall(dm_table_entry_t *, struct buf *); | 245 | int dm_target_linear_upcall(dm_table_entry_t *, struct buf *); | |
285 | int dm_target_linear_secsize(dm_table_entry_t *, unsigned *); | 246 | int dm_target_linear_secsize(dm_table_entry_t *, unsigned *); | |
286 | 247 | |||
287 | /* Generic function used to convert char to string */ | 248 | /* Generic function used to convert char to string */ | |
288 | uint64_t atoi(const char *); | 249 | uint64_t atoi(const char *); | |
289 | 250 | |||
290 | /* dm_target_stripe.c */ | 251 | /* dm_target_stripe.c */ | |
291 | int dm_target_stripe_init(dm_table_entry_t *, char *); | 252 | int dm_target_stripe_init(dm_table_entry_t *, char *); | |
292 | char *dm_target_stripe_status(void *); | 253 | char *dm_target_stripe_status(void *); | |
293 | int dm_target_stripe_strategy(dm_table_entry_t *, struct buf *); | 254 | int dm_target_stripe_strategy(dm_table_entry_t *, struct buf *); | |
294 | int dm_target_stripe_sync(dm_table_entry_t *); | 255 | int dm_target_stripe_sync(dm_table_entry_t *); | |
295 | int dm_target_stripe_deps(dm_table_entry_t *, prop_array_t); | 256 | int dm_target_stripe_deps(dm_table_entry_t *, prop_array_t); | |
296 | int dm_target_stripe_destroy(dm_table_entry_t *); | 257 | int dm_target_stripe_destroy(dm_table_entry_t *); | |
297 | int dm_target_stripe_upcall(dm_table_entry_t *, struct buf *); | 258 | int dm_target_stripe_upcall(dm_table_entry_t *, struct buf *); | |
298 | int dm_target_stripe_secsize(dm_table_entry_t *, unsigned *); | 259 | int dm_target_stripe_secsize(dm_table_entry_t *, unsigned *); | |
299 | 260 | |||
300 | /* dm_table.c */ | 261 | /* dm_table.c */ | |
301 | #define DM_TABLE_ACTIVE 0 | 262 | #define DM_TABLE_ACTIVE 0 | |
302 | #define DM_TABLE_INACTIVE 1 | 263 | #define DM_TABLE_INACTIVE 1 | |
303 | 264 | |||
304 | int dm_table_destroy(dm_table_head_t *, uint8_t); | 265 | int dm_table_destroy(dm_table_head_t *, uint8_t); | |
305 | uint64_t dm_table_size(dm_table_head_t *); | 266 | uint64_t dm_table_size(dm_table_head_t *); | |
306 | uint64_t dm_inactive_table_size(dm_table_head_t *); | 267 | uint64_t dm_inactive_table_size(dm_table_head_t *); | |
307 | void dm_table_disksize(dm_table_head_t *, uint64_t *, unsigned *); | 268 | void dm_table_disksize(dm_table_head_t *, uint64_t *, unsigned *); | |
308 | dm_table_t *dm_table_get_entry(dm_table_head_t *, uint8_t); | 269 | dm_table_t *dm_table_get_entry(dm_table_head_t *, uint8_t); | |
309 | int dm_table_get_target_count(dm_table_head_t *, uint8_t); | 270 | int dm_table_get_target_count(dm_table_head_t *, uint8_t); | |
310 | void dm_table_release(dm_table_head_t *, uint8_t s); | 271 | void dm_table_release(dm_table_head_t *, uint8_t s); | |
311 | void dm_table_switch_tables(dm_table_head_t *); | 272 | void dm_table_switch_tables(dm_table_head_t *); | |
312 | void dm_table_head_init(dm_table_head_t *); | 273 | void dm_table_head_init(dm_table_head_t *); | |
313 | void dm_table_head_destroy(dm_table_head_t *); | 274 | void dm_table_head_destroy(dm_table_head_t *); | |
314 | 275 | |||
315 | /* dm_dev.c */ | 276 | /* dm_dev.c */ | |
316 | dm_dev_t* dm_dev_alloc(void); | 277 | dm_dev_t* dm_dev_alloc(void); | |
317 | void dm_dev_busy(dm_dev_t *); | 278 | void dm_dev_busy(dm_dev_t *); | |
318 | int dm_dev_destroy(void); | 279 | int dm_dev_destroy(void); | |
319 | dm_dev_t* dm_dev_detach(device_t); | 280 | dm_dev_t* dm_dev_detach(device_t); | |
320 | int dm_dev_free(dm_dev_t *); | 281 | int dm_dev_free(dm_dev_t *); | |
321 | int dm_dev_init(void); | 282 | int dm_dev_init(void); | |
322 | int dm_dev_insert(dm_dev_t *); | 283 | int dm_dev_insert(dm_dev_t *); | |
323 | dm_dev_t* dm_dev_lookup(const char *, const char *, int); | 284 | dm_dev_t* dm_dev_lookup(const char *, const char *, int); | |
324 | prop_array_t dm_dev_prop_list(void); | 285 | prop_array_t dm_dev_prop_list(void); | |
325 | dm_dev_t* dm_dev_rem(const char *, const char *, int); | 286 | dm_dev_t* dm_dev_rem(const char *, const char *, int); | |
326 | /*int dm_dev_test_minor(int);*/ | 287 | /*int dm_dev_test_minor(int);*/ | |
327 | void dm_dev_unbusy(dm_dev_t *); | 288 | void dm_dev_unbusy(dm_dev_t *); | |
328 | 289 | |||
329 | /* dm_pdev.c */ | 290 | /* dm_pdev.c */ | |
330 | int dm_pdev_decr(dm_pdev_t *); | 291 | int dm_pdev_decr(dm_pdev_t *); | |
331 | int dm_pdev_destroy(void); | 292 | int dm_pdev_destroy(void); | |
332 | int dm_pdev_init(void); | 293 | int dm_pdev_init(void); | |
333 | dm_pdev_t* dm_pdev_insert(const char *); | 294 | dm_pdev_t* dm_pdev_insert(const char *); | |
334 | 295 | |||
335 | #endif /*_KERNEL*/ | 296 | #endif /*_KERNEL*/ | |
336 | 297 | |||
337 | #endif /*_DM_DEV_H_*/ | 298 | #endif /*_DM_DEV_H_*/ |
--- src/sys/dev/dm/dm_target_mirror.c 2019/12/08 04:41:02 1.15
+++ src/sys/dev/dm/dm_target_mirror.c 2019/12/08 10:50:21 1.16
@@ -1,179 +1,191 @@ | @@ -1,179 +1,191 @@ | |||
1 | /*$NetBSD: dm_target_mirror.c,v 1.15 2019/12/08 04:41:02 tkusumi Exp $*/ | 1 | /*$NetBSD: dm_target_mirror.c,v 1.16 2019/12/08 10:50:21 tkusumi Exp $*/ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2009 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Adam Hamsik. | 8 | * by Adam Hamsik. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | #include <sys/cdefs.h> | 31 | #include <sys/cdefs.h> | |
32 | __KERNEL_RCSID(0, "$NetBSD: dm_target_mirror.c,v 1.15 2019/12/08 04:41:02 tkusumi Exp $"); | 32 | __KERNEL_RCSID(0, "$NetBSD: dm_target_mirror.c,v 1.16 2019/12/08 10:50:21 tkusumi Exp $"); | |
33 | 33 | |||
34 | /* | 34 | /* | |
35 | * This file implements initial version of device-mapper mirror target. | 35 | * This file implements initial version of device-mapper mirror target. | |
36 | */ | 36 | */ | |
37 | #include <sys/types.h> | 37 | #include <sys/types.h> | |
38 | #include <sys/param.h> | 38 | #include <sys/param.h> | |
39 | 39 | |||
40 | #include <sys/buf.h> | 40 | #include <sys/buf.h> | |
41 | 41 | |||
42 | #include "dm.h" | 42 | #include "dm.h" | |
43 | 43 | |||
44 | /* dm_target_mirror.c */ | 44 | /* dm_target_mirror.c */ | |
45 | int dm_target_mirror_init(dm_table_entry_t *, char *); | 45 | int dm_target_mirror_init(dm_table_entry_t *, char *); | |
46 | char *dm_target_mirror_status(void *); | 46 | char *dm_target_mirror_status(void *); | |
47 | int dm_target_mirror_strategy(dm_table_entry_t *, struct buf *); | 47 | int dm_target_mirror_strategy(dm_table_entry_t *, struct buf *); | |
48 | int dm_target_mirror_sync(dm_table_entry_t *); | 48 | int dm_target_mirror_sync(dm_table_entry_t *); | |
49 | int dm_target_mirror_deps(dm_table_entry_t *, prop_array_t); | 49 | int dm_target_mirror_deps(dm_table_entry_t *, prop_array_t); | |
50 | int dm_target_mirror_destroy(dm_table_entry_t *); | 50 | int dm_target_mirror_destroy(dm_table_entry_t *); | |
51 | int dm_target_mirror_upcall(dm_table_entry_t *, struct buf *); | 51 | int dm_target_mirror_upcall(dm_table_entry_t *, struct buf *); | |
52 | 52 | |||
53 | typedef struct target_mirror_config { | |||
54 | #define MAX_MIRROR_COPIES 4 | |||
55 | dm_pdev_t *orig; | |||
56 | dm_pdev_t *copies[MAX_MIRROR_COPIES]; | |||
57 | ||||
58 | /* copied blocks bitmaps administration etc*/ | |||
59 | dm_pdev_t *log_pdev; /* for administration */ | |||
60 | uint64_t log_regionsize; /* blocksize of mirror */ | |||
61 | ||||
62 | /* list of parts that still need copied etc.; run length encoded? */ | |||
63 | } dm_target_mirror_config_t; | |||
64 | ||||
53 | #ifdef DM_TARGET_MODULE | 65 | #ifdef DM_TARGET_MODULE | |
54 | /* | 66 | /* | |
55 | * Every target can be compiled directly to dm driver or as a | 67 | * Every target can be compiled directly to dm driver or as a | |
56 | * separate module this part of target is used for loading targets | 68 | * separate module this part of target is used for loading targets | |
57 | * to dm driver. | 69 | * to dm driver. | |
58 | * Target can be unloaded from kernel only if there are no users of | 70 | * Target can be unloaded from kernel only if there are no users of | |
59 | * it e.g. there are no devices which uses that target. | 71 | * it e.g. there are no devices which uses that target. | |
60 | */ | 72 | */ | |
61 | #include <sys/kernel.h> | 73 | #include <sys/kernel.h> | |
62 | #include <sys/module.h> | 74 | #include <sys/module.h> | |
63 | 75 | |||
64 | MODULE(MODULE_CLASS_MISC, dm_target_mirror, "dm"); | 76 | MODULE(MODULE_CLASS_MISC, dm_target_mirror, "dm"); | |
65 | 77 | |||
66 | static int | 78 | static int | |
67 | dm_target_mirror_modcmd(modcmd_t cmd, void *arg) | 79 | dm_target_mirror_modcmd(modcmd_t cmd, void *arg) | |
68 | { | 80 | { | |
69 | dm_target_t *dmt; | 81 | dm_target_t *dmt; | |
70 | int r; | 82 | int r; | |
71 | dmt = NULL; | 83 | dmt = NULL; | |
72 | 84 | |||
73 | switch (cmd) { | 85 | switch (cmd) { | |
74 | case MODULE_CMD_INIT: | 86 | case MODULE_CMD_INIT: | |
75 | if ((dmt = dm_target_lookup("mirror")) != NULL) { | 87 | if ((dmt = dm_target_lookup("mirror")) != NULL) { | |
76 | dm_target_unbusy(dmt); | 88 | dm_target_unbusy(dmt); | |
77 | return EEXIST; | 89 | return EEXIST; | |
78 | } | 90 | } | |
79 | dmt = dm_target_alloc("mirror"); | 91 | dmt = dm_target_alloc("mirror"); | |
80 | 92 | |||
81 | dmt->version[0] = 1; | 93 | dmt->version[0] = 1; | |
82 | dmt->version[1] = 0; | 94 | dmt->version[1] = 0; | |
83 | dmt->version[2] = 0; | 95 | dmt->version[2] = 0; | |
84 | dmt->init = &dm_target_mirror_init; | 96 | dmt->init = &dm_target_mirror_init; | |
85 | dmt->status = &dm_target_mirror_status; | 97 | dmt->status = &dm_target_mirror_status; | |
86 | dmt->strategy = &dm_target_mirror_strategy; | 98 | dmt->strategy = &dm_target_mirror_strategy; | |
87 | dmt->sync = &dm_target_mirror_sync; | 99 | dmt->sync = &dm_target_mirror_sync; | |
88 | dmt->deps = &dm_target_mirror_deps; | 100 | dmt->deps = &dm_target_mirror_deps; | |
89 | dmt->destroy = &dm_target_mirror_destroy; | 101 | dmt->destroy = &dm_target_mirror_destroy; | |
90 | dmt->upcall = &dm_target_mirror_upcall; | 102 | dmt->upcall = &dm_target_mirror_upcall; | |
91 | 103 | |||
92 | r = dm_target_insert(dmt); | 104 | r = dm_target_insert(dmt); | |
93 | 105 | |||
94 | break; | 106 | break; | |
95 | 107 | |||
96 | case MODULE_CMD_FINI: | 108 | case MODULE_CMD_FINI: | |
97 | r = dm_target_rem("mirror"); | 109 | r = dm_target_rem("mirror"); | |
98 | break; | 110 | break; | |
99 | 111 | |||
100 | case MODULE_CMD_STAT: | 112 | case MODULE_CMD_STAT: | |
101 | return ENOTTY; | 113 | return ENOTTY; | |
102 | 114 | |||
103 | default: | 115 | default: | |
104 | return ENOTTY; | 116 | return ENOTTY; | |
105 | } | 117 | } | |
106 | 118 | |||
107 | return r; | 119 | return r; | |
108 | } | 120 | } | |
109 | #endif | 121 | #endif | |
110 | 122 | |||
111 | /* | 123 | /* | |
112 | * Init function called from dm_table_load_ioctl. | 124 | * Init function called from dm_table_load_ioctl. | |
113 | * start length mirror log_type #logargs logarg1 ... logargN #devs device1 offset1 ... deviceN offsetN | 125 | * start length mirror log_type #logargs logarg1 ... logargN #devs device1 offset1 ... deviceN offsetN | |
114 | * 0 52428800 mirror clustered_disk 4 253:2 1024 UUID block_on_error 3 253:3 0 253:4 0 253:5 0 | 126 | * 0 52428800 mirror clustered_disk 4 253:2 1024 UUID block_on_error 3 253:3 0 253:4 0 253:5 0 | |
115 | */ | 127 | */ | |
116 | int | 128 | int | |
117 | dm_target_mirror_init(dm_table_entry_t *table_en, char *params) | 129 | dm_target_mirror_init(dm_table_entry_t *table_en, char *params) | |
118 | { | 130 | { | |
119 | 131 | |||
120 | printf("Mirror target init function called!!\n"); | 132 | printf("Mirror target init function called!!\n"); | |
121 | 133 | |||
122 | table_en->target_config = NULL; | 134 | table_en->target_config = NULL; | |
123 | 135 | |||
124 | return ENOSYS; | 136 | return ENOSYS; | |
125 | } | 137 | } | |
126 | 138 | |||
127 | /* Status routine called to get params string. */ | 139 | /* Status routine called to get params string. */ | |
128 | char * | 140 | char * | |
129 | dm_target_mirror_status(void *target_config) | 141 | dm_target_mirror_status(void *target_config) | |
130 | { | 142 | { | |
131 | return NULL; | 143 | return NULL; | |
132 | } | 144 | } | |
133 | 145 | |||
134 | /* Strategy routine called from dm_strategy. */ | 146 | /* Strategy routine called from dm_strategy. */ | |
135 | int | 147 | int | |
136 | dm_target_mirror_strategy(dm_table_entry_t *table_en, struct buf *bp) | 148 | dm_target_mirror_strategy(dm_table_entry_t *table_en, struct buf *bp) | |
137 | { | 149 | { | |
138 | 150 | |||
139 | printf("Mirror target read function called!!\n"); | 151 | printf("Mirror target read function called!!\n"); | |
140 | 152 | |||
141 | bp->b_error = EIO; | 153 | bp->b_error = EIO; | |
142 | bp->b_resid = 0; | 154 | bp->b_resid = 0; | |
143 | 155 | |||
144 | biodone(bp); | 156 | biodone(bp); | |
145 | 157 | |||
146 | return 0; | 158 | return 0; | |
147 | } | 159 | } | |
148 | 160 | |||
149 | /* Sync underlying disk caches. */ | 161 | /* Sync underlying disk caches. */ | |
150 | int | 162 | int | |
151 | dm_target_mirror_sync(dm_table_entry_t *table_en) | 163 | dm_target_mirror_sync(dm_table_entry_t *table_en) | |
152 | { | 164 | { | |
153 | 165 | |||
154 | return 0; | 166 | return 0; | |
155 | } | 167 | } | |
156 | 168 | |||
157 | /* Doesn't do anything here. */ | 169 | /* Doesn't do anything here. */ | |
158 | int | 170 | int | |
159 | dm_target_mirror_destroy(dm_table_entry_t *table_en) | 171 | dm_target_mirror_destroy(dm_table_entry_t *table_en) | |
160 | { | 172 | { | |
161 | /* Unbusy target so we can unload it */ | 173 | /* Unbusy target so we can unload it */ | |
162 | dm_target_unbusy(table_en->target); | 174 | dm_target_unbusy(table_en->target); | |
163 | 175 | |||
164 | return 0; | 176 | return 0; | |
165 | } | 177 | } | |
166 | 178 | |||
167 | /* Doesn't not need to do anything here. */ | 179 | /* Doesn't not need to do anything here. */ | |
168 | int | 180 | int | |
169 | dm_target_mirror_deps(dm_table_entry_t *table_en, prop_array_t prop_array) | 181 | dm_target_mirror_deps(dm_table_entry_t *table_en, prop_array_t prop_array) | |
170 | { | 182 | { | |
171 | return 0; | 183 | return 0; | |
172 | } | 184 | } | |
173 | 185 | |||
174 | /* Unsupported for this target. */ | 186 | /* Unsupported for this target. */ | |
175 | int | 187 | int | |
176 | dm_target_mirror_upcall(dm_table_entry_t *table_en, struct buf *bp) | 188 | dm_target_mirror_upcall(dm_table_entry_t *table_en, struct buf *bp) | |
177 | { | 189 | { | |
178 | return 0; | 190 | return 0; | |
179 | } | 191 | } |
--- src/sys/dev/dm/dm_target_snapshot.c 2019/12/08 10:35:53 1.27
+++ src/sys/dev/dm/dm_target_snapshot.c 2019/12/08 10:50:21 1.28
@@ -1,535 +1,549 @@ | @@ -1,535 +1,549 @@ | |||
1 | /* $NetBSD: dm_target_snapshot.c,v 1.27 2019/12/08 10:35:53 tkusumi Exp $ */ | 1 | /* $NetBSD: dm_target_snapshot.c,v 1.28 2019/12/08 10:50:21 tkusumi Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Adam Hamsik. | 8 | * by Adam Hamsik. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | #include <sys/cdefs.h> | 31 | #include <sys/cdefs.h> | |
32 | __KERNEL_RCSID(0, "$NetBSD: dm_target_snapshot.c,v 1.27 2019/12/08 10:35:53 tkusumi Exp $"); | 32 | __KERNEL_RCSID(0, "$NetBSD: dm_target_snapshot.c,v 1.28 2019/12/08 10:50:21 tkusumi Exp $"); | |
33 | 33 | |||
34 | /* | 34 | /* | |
35 | * 1. Suspend my_data to temporarily stop any I/O while the snapshot is being | 35 | * 1. Suspend my_data to temporarily stop any I/O while the snapshot is being | |
36 | * activated. | 36 | * activated. | |
37 | * dmsetup suspend my_data | 37 | * dmsetup suspend my_data | |
38 | * | 38 | * | |
39 | * 2. Create the snapshot-origin device with no table. | 39 | * 2. Create the snapshot-origin device with no table. | |
40 | * dmsetup create my_data_org | 40 | * dmsetup create my_data_org | |
41 | * | 41 | * | |
42 | * 3. Read the table from my_data and load it into my_data_org. | 42 | * 3. Read the table from my_data and load it into my_data_org. | |
43 | * dmsetup table my_data | dmsetup load my_data_org | 43 | * dmsetup table my_data | dmsetup load my_data_org | |
44 | * | 44 | * | |
45 | * 4. Resume this new table. | 45 | * 4. Resume this new table. | |
46 | * dmsetup resume my_data_org | 46 | * dmsetup resume my_data_org | |
47 | * | 47 | * | |
48 | * 5. Create the snapshot device with no table. | 48 | * 5. Create the snapshot device with no table. | |
49 | * dmsetup create my_data_snap | 49 | * dmsetup create my_data_snap | |
50 | * | 50 | * | |
51 | * 6. Load the table into my_data_snap. This uses /dev/hdd1 as the COW device and | 51 | * 6. Load the table into my_data_snap. This uses /dev/hdd1 as the COW device and | |
52 | * uses a 32kB chunk-size. | 52 | * uses a 32kB chunk-size. | |
53 | * echo "0 `blockdev --getsize /dev/mapper/my_data` snapshot \ | 53 | * echo "0 `blockdev --getsize /dev/mapper/my_data` snapshot \ | |
54 | * /dev/mapper/my_data_org /dev/hdd1 p 64" | dmsetup load my_data_snap | 54 | * /dev/mapper/my_data_org /dev/hdd1 p 64" | dmsetup load my_data_snap | |
55 | * | 55 | * | |
56 | * 7. Reload my_data as a snapshot-origin device that points to my_data_org. | 56 | * 7. Reload my_data as a snapshot-origin device that points to my_data_org. | |
57 | * echo "0 `blockdev --getsize /dev/mapper/my_data` snapshot-origin \ | 57 | * echo "0 `blockdev --getsize /dev/mapper/my_data` snapshot-origin \ | |
58 | * /dev/mapper/my_data_org" | dmsetup load my_data | 58 | * /dev/mapper/my_data_org" | dmsetup load my_data | |
59 | * | 59 | * | |
60 | * 8. Resume the snapshot and origin devices. | 60 | * 8. Resume the snapshot and origin devices. | |
61 | * dmsetup resume my_data_snap | 61 | * dmsetup resume my_data_snap | |
62 | * dmsetup resume my_data | 62 | * dmsetup resume my_data | |
63 | * | 63 | * | |
64 | * Before snapshot creation | 64 | * Before snapshot creation | |
65 | * dev_name; dev table | 65 | * dev_name; dev table | |
66 | * | my_data; 0 1024 linear /dev/sd1a 384| | 66 | * | my_data; 0 1024 linear /dev/sd1a 384| | |
67 | * | 67 | * | |
68 | * After snapshot creation | 68 | * After snapshot creation | |
69 | * |my_data_org;0 1024 linear /dev/sd1a 384| | 69 | * |my_data_org;0 1024 linear /dev/sd1a 384| | |
70 | * / | 70 | * / | |
71 | * |my_data; 0 1024 snapshot-origin /dev/vg00/my_data_org| | 71 | * |my_data; 0 1024 snapshot-origin /dev/vg00/my_data_org| | |
72 | * / | 72 | * / | |
73 | * |my_data_snap; 0 1024 snapshot /dev/vg00/my_data /dev/mapper/my_data_cow P 8 | 73 | * |my_data_snap; 0 1024 snapshot /dev/vg00/my_data /dev/mapper/my_data_cow P 8 | |
74 | * \ | 74 | * \ | |
75 | * |my_data_cow; 0 256 linear /dev/sd1a 1408| | 75 | * |my_data_cow; 0 256 linear /dev/sd1a 1408| | |
76 | */ | 76 | */ | |
77 | 77 | |||
78 | /* | 78 | /* | |
79 | * This file implements initial version of device-mapper snapshot target. | 79 | * This file implements initial version of device-mapper snapshot target. | |
80 | */ | 80 | */ | |
81 | #include <sys/types.h> | 81 | #include <sys/types.h> | |
82 | #include <sys/param.h> | 82 | #include <sys/param.h> | |
83 | 83 | |||
84 | #include <sys/buf.h> | 84 | #include <sys/buf.h> | |
85 | #include <sys/kmem.h> | 85 | #include <sys/kmem.h> | |
86 | 86 | |||
87 | #include "dm.h" | 87 | #include "dm.h" | |
88 | 88 | |||
89 | /* dm_target_snapshot.c */ | 89 | /* dm_target_snapshot.c */ | |
90 | int dm_target_snapshot_init(dm_table_entry_t *, char *); | 90 | int dm_target_snapshot_init(dm_table_entry_t *, char *); | |
91 | char *dm_target_snapshot_status(void *); | 91 | char *dm_target_snapshot_status(void *); | |
92 | int dm_target_snapshot_strategy(dm_table_entry_t *, struct buf *); | 92 | int dm_target_snapshot_strategy(dm_table_entry_t *, struct buf *); | |
93 | int dm_target_snapshot_deps(dm_table_entry_t *, prop_array_t); | 93 | int dm_target_snapshot_deps(dm_table_entry_t *, prop_array_t); | |
94 | int dm_target_snapshot_destroy(dm_table_entry_t *); | 94 | int dm_target_snapshot_destroy(dm_table_entry_t *); | |
95 | int dm_target_snapshot_upcall(dm_table_entry_t *, struct buf *); | 95 | int dm_target_snapshot_upcall(dm_table_entry_t *, struct buf *); | |
96 | 96 | |||
97 | /* dm snapshot origin driver */ | 97 | /* dm snapshot origin driver */ | |
98 | int dm_target_snapshot_orig_init(dm_table_entry_t *, char *); | 98 | int dm_target_snapshot_orig_init(dm_table_entry_t *, char *); | |
99 | char *dm_target_snapshot_orig_status(void *); | 99 | char *dm_target_snapshot_orig_status(void *); | |
100 | int dm_target_snapshot_orig_strategy(dm_table_entry_t *, struct buf *); | 100 | int dm_target_snapshot_orig_strategy(dm_table_entry_t *, struct buf *); | |
101 | int dm_target_snapshot_orig_sync(dm_table_entry_t *); | 101 | int dm_target_snapshot_orig_sync(dm_table_entry_t *); | |
102 | int dm_target_snapshot_orig_deps(dm_table_entry_t *, prop_array_t); | 102 | int dm_target_snapshot_orig_deps(dm_table_entry_t *, prop_array_t); | |
103 | int dm_target_snapshot_orig_destroy(dm_table_entry_t *); | 103 | int dm_target_snapshot_orig_destroy(dm_table_entry_t *); | |
104 | int dm_target_snapshot_orig_upcall(dm_table_entry_t *, struct buf *); | 104 | int dm_target_snapshot_orig_upcall(dm_table_entry_t *, struct buf *); | |
105 | 105 | |||
106 | typedef struct target_snapshot_config { | |||
107 | dm_pdev_t *tsc_snap_dev; | |||
108 | /* cow dev is set only for persistent snapshot devices */ | |||
109 | dm_pdev_t *tsc_cow_dev; | |||
110 | ||||
111 | uint64_t tsc_chunk_size; | |||
112 | uint32_t tsc_persistent_dev; | |||
113 | } dm_target_snapshot_config_t; | |||
114 | ||||
115 | typedef struct target_snapshot_origin_config { | |||
116 | dm_pdev_t *tsoc_real_dev; | |||
117 | /* list of snapshots ? */ | |||
118 | } dm_target_snapshot_origin_config_t; | |||
119 | ||||
106 | #ifdef DM_TARGET_MODULE | 120 | #ifdef DM_TARGET_MODULE | |
107 | /* | 121 | /* | |
108 | * Every target can be compiled directly to dm driver or as a | 122 | * Every target can be compiled directly to dm driver or as a | |
109 | * separate module this part of target is used for loading targets | 123 | * separate module this part of target is used for loading targets | |
110 | * to dm driver. | 124 | * to dm driver. | |
111 | * Target can be unloaded from kernel only if there are no users of | 125 | * Target can be unloaded from kernel only if there are no users of | |
112 | * it e.g. there are no devices which uses that target. | 126 | * it e.g. there are no devices which uses that target. | |
113 | */ | 127 | */ | |
114 | #include <sys/kernel.h> | 128 | #include <sys/kernel.h> | |
115 | #include <sys/module.h> | 129 | #include <sys/module.h> | |
116 | 130 | |||
117 | MODULE(MODULE_CLASS_MISC, dm_target_snapshot, "dm"); | 131 | MODULE(MODULE_CLASS_MISC, dm_target_snapshot, "dm"); | |
118 | 132 | |||
119 | static int | 133 | static int | |
120 | dm_target_snapshot_modcmd(modcmd_t cmd, void *arg) | 134 | dm_target_snapshot_modcmd(modcmd_t cmd, void *arg) | |
121 | { | 135 | { | |
122 | dm_target_t *dmt, *dmt1; | 136 | dm_target_t *dmt, *dmt1; | |
123 | int r; | 137 | int r; | |
124 | 138 | |||
125 | dmt = NULL; | 139 | dmt = NULL; | |
126 | dmt1 = NULL; | 140 | dmt1 = NULL; | |
127 | 141 | |||
128 | switch (cmd) { | 142 | switch (cmd) { | |
129 | case MODULE_CMD_INIT: | 143 | case MODULE_CMD_INIT: | |
130 | if (((dmt = dm_target_lookup("snapshot")) != NULL)) { | 144 | if (((dmt = dm_target_lookup("snapshot")) != NULL)) { | |
131 | dm_target_unbusy(dmt); | 145 | dm_target_unbusy(dmt); | |
132 | return EEXIST; | 146 | return EEXIST; | |
133 | } | 147 | } | |
134 | if (((dmt = dm_target_lookup("snapshot-origin")) != NULL)) { | 148 | if (((dmt = dm_target_lookup("snapshot-origin")) != NULL)) { | |
135 | dm_target_unbusy(dmt); | 149 | dm_target_unbusy(dmt); | |
136 | return EEXIST; | 150 | return EEXIST; | |
137 | } | 151 | } | |
138 | dmt = dm_target_alloc("snapshot"); | 152 | dmt = dm_target_alloc("snapshot"); | |
139 | dmt1 = dm_target_alloc("snapshot-origin"); | 153 | dmt1 = dm_target_alloc("snapshot-origin"); | |
140 | 154 | |||
141 | dmt->version[0] = 1; | 155 | dmt->version[0] = 1; | |
142 | dmt->version[1] = 0; | 156 | dmt->version[1] = 0; | |
143 | dmt->version[2] = 5; | 157 | dmt->version[2] = 5; | |
144 | dmt->init = &dm_target_snapshot_init; | 158 | dmt->init = &dm_target_snapshot_init; | |
145 | dmt->status = &dm_target_snapshot_status; | 159 | dmt->status = &dm_target_snapshot_status; | |
146 | dmt->strategy = &dm_target_snapshot_strategy; | 160 | dmt->strategy = &dm_target_snapshot_strategy; | |
147 | dmt->deps = &dm_target_snapshot_deps; | 161 | dmt->deps = &dm_target_snapshot_deps; | |
148 | dmt->destroy = &dm_target_snapshot_destroy; | 162 | dmt->destroy = &dm_target_snapshot_destroy; | |
149 | dmt->upcall = &dm_target_snapshot_upcall; | 163 | dmt->upcall = &dm_target_snapshot_upcall; | |
150 | 164 | |||
151 | r = dm_target_insert(dmt); | 165 | r = dm_target_insert(dmt); | |
152 | 166 | |||
153 | dmt1->version[0] = 1; | 167 | dmt1->version[0] = 1; | |
154 | dmt1->version[1] = 0; | 168 | dmt1->version[1] = 0; | |
155 | dmt1->version[2] = 5; | 169 | dmt1->version[2] = 5; | |
156 | dmt1->init = &dm_target_snapshot_orig_init; | 170 | dmt1->init = &dm_target_snapshot_orig_init; | |
157 | dmt1->status = &dm_target_snapshot_orig_status; | 171 | dmt1->status = &dm_target_snapshot_orig_status; | |
158 | dmt1->strategy = &dm_target_snapshot_orig_strategy; | 172 | dmt1->strategy = &dm_target_snapshot_orig_strategy; | |
159 | dmt1->sync = &dm_target_snapshot_orig_sync; | 173 | dmt1->sync = &dm_target_snapshot_orig_sync; | |
160 | dmt1->deps = &dm_target_snapshot_orig_deps; | 174 | dmt1->deps = &dm_target_snapshot_orig_deps; | |
161 | dmt1->destroy = &dm_target_snapshot_orig_destroy; | 175 | dmt1->destroy = &dm_target_snapshot_orig_destroy; | |
162 | dmt1->upcall = &dm_target_snapshot_orig_upcall; | 176 | dmt1->upcall = &dm_target_snapshot_orig_upcall; | |
163 | 177 | |||
164 | r = dm_target_insert(dmt1); | 178 | r = dm_target_insert(dmt1); | |
165 | break; | 179 | break; | |
166 | 180 | |||
167 | case MODULE_CMD_FINI: | 181 | case MODULE_CMD_FINI: | |
168 | /* | 182 | /* | |
169 | * Try to remove snapshot target if it works remove snap-origin | 183 | * Try to remove snapshot target if it works remove snap-origin | |
170 | * it is not possible to remove snapshot and do not remove | 184 | * it is not possible to remove snapshot and do not remove | |
171 | * snap-origin because they are used together. | 185 | * snap-origin because they are used together. | |
172 | */ | 186 | */ | |
173 | if ((r = dm_target_rem("snapshot")) == 0) | 187 | if ((r = dm_target_rem("snapshot")) == 0) | |
174 | r = dm_target_rem("snapshot-origin"); | 188 | r = dm_target_rem("snapshot-origin"); | |
175 | 189 | |||
176 | break; | 190 | break; | |
177 | 191 | |||
178 | case MODULE_CMD_STAT: | 192 | case MODULE_CMD_STAT: | |
179 | return ENOTTY; | 193 | return ENOTTY; | |
180 | 194 | |||
181 | default: | 195 | default: | |
182 | return ENOTTY; | 196 | return ENOTTY; | |
183 | } | 197 | } | |
184 | 198 | |||
185 | return r; | 199 | return r; | |
186 | } | 200 | } | |
187 | #endif | 201 | #endif | |
188 | 202 | |||
189 | /* | 203 | /* | |
190 | * Init function called from dm_table_load_ioctl. | 204 | * Init function called from dm_table_load_ioctl. | |
191 | * argv: /dev/mapper/my_data_org /dev/mapper/tsc_cow_dev p 64 | 205 | * argv: /dev/mapper/my_data_org /dev/mapper/tsc_cow_dev p 64 | |
192 | * snapshot_origin device, cow device, persistent flag, chunk size | 206 | * snapshot_origin device, cow device, persistent flag, chunk size | |
193 | */ | 207 | */ | |
194 | int | 208 | int | |
195 | dm_target_snapshot_init(dm_table_entry_t *table_en, char *params) | 209 | dm_target_snapshot_init(dm_table_entry_t *table_en, char *params) | |
196 | { | 210 | { | |
197 | dm_target_snapshot_config_t *tsc; | 211 | dm_target_snapshot_config_t *tsc; | |
198 | dm_pdev_t *dmp_snap, *dmp_cow; | 212 | dm_pdev_t *dmp_snap, *dmp_cow; | |
199 | char **ap, *argv[5]; | 213 | char **ap, *argv[5]; | |
200 | 214 | |||
201 | dmp_cow = NULL; | 215 | dmp_cow = NULL; | |
202 | 216 | |||
203 | if (params == NULL) | 217 | if (params == NULL) | |
204 | return EINVAL; | 218 | return EINVAL; | |
205 | /* | 219 | /* | |
206 | * Parse a string, containing tokens delimited by white space, | 220 | * Parse a string, containing tokens delimited by white space, | |
207 | * into an argument vector | 221 | * into an argument vector | |
208 | */ | 222 | */ | |
209 | for (ap = argv; ap < &argv[4] && | 223 | for (ap = argv; ap < &argv[4] && | |
210 | (*ap = strsep(¶ms, " \t")) != NULL;) { | 224 | (*ap = strsep(¶ms, " \t")) != NULL;) { | |
211 | if (**ap != '\0') | 225 | if (**ap != '\0') | |
212 | ap++; | 226 | ap++; | |
213 | } | 227 | } | |
214 | 228 | |||
215 | printf("Snapshot target init function called!!\n"); | 229 | printf("Snapshot target init function called!!\n"); | |
216 | printf("Snapshotted device: %s, cow device %s,\n\t persistent flag: %s, " | 230 | printf("Snapshotted device: %s, cow device %s,\n\t persistent flag: %s, " | |
217 | "chunk size: %s\n", argv[0], argv[1], argv[2], argv[3]); | 231 | "chunk size: %s\n", argv[0], argv[1], argv[2], argv[3]); | |
218 | 232 | |||
219 | /* Insert snap device to global pdev list */ | 233 | /* Insert snap device to global pdev list */ | |
220 | if ((dmp_snap = dm_pdev_insert(argv[0])) == NULL) | 234 | if ((dmp_snap = dm_pdev_insert(argv[0])) == NULL) | |
221 | return ENOENT; | 235 | return ENOENT; | |
222 | 236 | |||
223 | tsc = kmem_alloc(sizeof(*tsc), KM_SLEEP); | 237 | tsc = kmem_alloc(sizeof(*tsc), KM_SLEEP); | |
224 | tsc->tsc_persistent_dev = 0; | 238 | tsc->tsc_persistent_dev = 0; | |
225 | 239 | |||
226 | /* There is now cow device for nonpersistent snapshot devices */ | 240 | /* There is now cow device for nonpersistent snapshot devices */ | |
227 | if (strcmp(argv[2], "p") == 0) { | 241 | if (strcmp(argv[2], "p") == 0) { | |
228 | tsc->tsc_persistent_dev = 1; | 242 | tsc->tsc_persistent_dev = 1; | |
229 | 243 | |||
230 | /* Insert cow device to global pdev list */ | 244 | /* Insert cow device to global pdev list */ | |
231 | if ((dmp_cow = dm_pdev_insert(argv[1])) == NULL) { | 245 | if ((dmp_cow = dm_pdev_insert(argv[1])) == NULL) { | |
232 | kmem_free(tsc, sizeof(*tsc)); | 246 | kmem_free(tsc, sizeof(*tsc)); | |
233 | return ENOENT; | 247 | return ENOENT; | |
234 | } | 248 | } | |
235 | } | 249 | } | |
236 | tsc->tsc_chunk_size = atoi(argv[3]); | 250 | tsc->tsc_chunk_size = atoi(argv[3]); | |
237 | 251 | |||
238 | tsc->tsc_snap_dev = dmp_snap; | 252 | tsc->tsc_snap_dev = dmp_snap; | |
239 | tsc->tsc_cow_dev = dmp_cow; | 253 | tsc->tsc_cow_dev = dmp_cow; | |
240 | 254 | |||
241 | table_en->target_config = tsc; | 255 | table_en->target_config = tsc; | |
242 | 256 | |||
243 | return 0; | 257 | return 0; | |
244 | } | 258 | } | |
245 | 259 | |||
246 | /* | 260 | /* | |
247 | * Status routine is called to get params string, which is target | 261 | * Status routine is called to get params string, which is target | |
248 | * specific. When dm_table_status_ioctl is called with flag | 262 | * specific. When dm_table_status_ioctl is called with flag | |
249 | * DM_STATUS_TABLE_FLAG I have to sent params string back. | 263 | * DM_STATUS_TABLE_FLAG I have to sent params string back. | |
250 | */ | 264 | */ | |
251 | char * | 265 | char * | |
252 | dm_target_snapshot_status(void *target_config) | 266 | dm_target_snapshot_status(void *target_config) | |
253 | { | 267 | { | |
254 | dm_target_snapshot_config_t *tsc; | 268 | dm_target_snapshot_config_t *tsc; | |
255 | 269 | |||
256 | uint32_t i; | 270 | uint32_t i; | |
257 | uint32_t count; | 271 | uint32_t count; | |
258 | size_t prm_len, cow_len; | 272 | size_t prm_len, cow_len; | |
259 | char *params; | 273 | char *params; | |
260 | 274 | |||
261 | tsc = target_config; | 275 | tsc = target_config; | |
262 | 276 | |||
263 | prm_len = 0; | 277 | prm_len = 0; | |
264 | cow_len = 0; | 278 | cow_len = 0; | |
265 | count = 0; | 279 | count = 0; | |
266 | 280 | |||
267 | printf("Snapshot target status function called\n"); | 281 | printf("Snapshot target status function called\n"); | |
268 | 282 | |||
269 | /* count number of chars in offset */ | 283 | /* count number of chars in offset */ | |
270 | for (i = tsc->tsc_chunk_size; i != 0; i /= 10) | 284 | for (i = tsc->tsc_chunk_size; i != 0; i /= 10) | |
271 | count++; | 285 | count++; | |
272 | 286 | |||
273 | if (tsc->tsc_persistent_dev) | 287 | if (tsc->tsc_persistent_dev) | |
274 | cow_len = strlen(tsc->tsc_cow_dev->name); | 288 | cow_len = strlen(tsc->tsc_cow_dev->name); | |
275 | 289 | |||
276 | /* length of names + count of chars + spaces and null char */ | 290 | /* length of names + count of chars + spaces and null char */ | |
277 | prm_len = strlen(tsc->tsc_snap_dev->name) + cow_len + count + 5; | 291 | prm_len = strlen(tsc->tsc_snap_dev->name) + cow_len + count + 5; | |
278 | 292 | |||
279 | params = kmem_alloc(prm_len, KM_SLEEP); | 293 | params = kmem_alloc(prm_len, KM_SLEEP); | |
280 | 294 | |||
281 | printf("%s %s %s %" PRIu64 "\n", tsc->tsc_snap_dev->name, | 295 | printf("%s %s %s %" PRIu64 "\n", tsc->tsc_snap_dev->name, | |
282 | tsc->tsc_cow_dev->name, tsc->tsc_persistent_dev ? "p" : "n", | 296 | tsc->tsc_cow_dev->name, tsc->tsc_persistent_dev ? "p" : "n", | |
283 | tsc->tsc_chunk_size); | 297 | tsc->tsc_chunk_size); | |
284 | 298 | |||
285 | snprintf(params, prm_len, "%s %s %s %" PRIu64, tsc->tsc_snap_dev->name, | 299 | snprintf(params, prm_len, "%s %s %s %" PRIu64, tsc->tsc_snap_dev->name, | |
286 | tsc->tsc_persistent_dev ? tsc->tsc_cow_dev->name : "", | 300 | tsc->tsc_persistent_dev ? tsc->tsc_cow_dev->name : "", | |
287 | tsc->tsc_persistent_dev ? "p" : "n", | 301 | tsc->tsc_persistent_dev ? "p" : "n", | |
288 | tsc->tsc_chunk_size); | 302 | tsc->tsc_chunk_size); | |
289 | 303 | |||
290 | return params; | 304 | return params; | |
291 | } | 305 | } | |
292 | 306 | |||
293 | /* Strategy routine called from dm_strategy. */ | 307 | /* Strategy routine called from dm_strategy. */ | |
294 | int | 308 | int | |
295 | dm_target_snapshot_strategy(dm_table_entry_t *table_en, struct buf *bp) | 309 | dm_target_snapshot_strategy(dm_table_entry_t *table_en, struct buf *bp) | |
296 | { | 310 | { | |
297 | 311 | |||
298 | printf("Snapshot target read function called!!\n"); | 312 | printf("Snapshot target read function called!!\n"); | |
299 | 313 | |||
300 | bp->b_error = EIO; | 314 | bp->b_error = EIO; | |
301 | bp->b_resid = 0; | 315 | bp->b_resid = 0; | |
302 | 316 | |||
303 | biodone(bp); | 317 | biodone(bp); | |
304 | 318 | |||
305 | return 0; | 319 | return 0; | |
306 | } | 320 | } | |
307 | 321 | |||
308 | /* Doesn't do anything here. */ | 322 | /* Doesn't do anything here. */ | |
309 | int | 323 | int | |
310 | dm_target_snapshot_destroy(dm_table_entry_t *table_en) | 324 | dm_target_snapshot_destroy(dm_table_entry_t *table_en) | |
311 | { | 325 | { | |
312 | 326 | |||
313 | /* | 327 | /* | |
314 | * Destroy function is called for every target even if it | 328 | * Destroy function is called for every target even if it | |
315 | * doesn't have target_config. | 329 | * doesn't have target_config. | |
316 | */ | 330 | */ | |
317 | if (table_en->target_config == NULL) | 331 | if (table_en->target_config == NULL) | |
318 | goto out; | 332 | goto out; | |
319 | 333 | |||
320 | printf("Snapshot target destroy function called\n"); | 334 | printf("Snapshot target destroy function called\n"); | |
321 | 335 | |||
322 | dm_target_snapshot_config_t *tsc = table_en->target_config; | 336 | dm_target_snapshot_config_t *tsc = table_en->target_config; | |
323 | 337 | |||
324 | /* Decrement pdev ref counter if 0 remove it */ | 338 | /* Decrement pdev ref counter if 0 remove it */ | |
325 | dm_pdev_decr(tsc->tsc_snap_dev); | 339 | dm_pdev_decr(tsc->tsc_snap_dev); | |
326 | if (tsc->tsc_persistent_dev) | 340 | if (tsc->tsc_persistent_dev) | |
327 | dm_pdev_decr(tsc->tsc_cow_dev); | 341 | dm_pdev_decr(tsc->tsc_cow_dev); | |
328 | 342 | |||
329 | kmem_free(tsc, sizeof(*tsc)); | 343 | kmem_free(tsc, sizeof(*tsc)); | |
330 | out: | 344 | out: | |
331 | /* Unbusy target so we can unload it */ | 345 | /* Unbusy target so we can unload it */ | |
332 | dm_target_unbusy(table_en->target); | 346 | dm_target_unbusy(table_en->target); | |
333 | 347 | |||
334 | return 0; | 348 | return 0; | |
335 | } | 349 | } | |
336 | 350 | |||
337 | /* Add this target dependencies to prop_array_t */ | 351 | /* Add this target dependencies to prop_array_t */ | |
338 | int | 352 | int | |
339 | dm_target_snapshot_deps(dm_table_entry_t *table_en, prop_array_t prop_array) | 353 | dm_target_snapshot_deps(dm_table_entry_t *table_en, prop_array_t prop_array) | |
340 | { | 354 | { | |
341 | dm_target_snapshot_config_t *tsc; | 355 | dm_target_snapshot_config_t *tsc; | |
342 | 356 | |||
343 | if (table_en->target_config == NULL) | 357 | if (table_en->target_config == NULL) | |
344 | return 0; | 358 | return 0; | |
345 | 359 | |||
346 | tsc = table_en->target_config; | 360 | tsc = table_en->target_config; | |
347 | 361 | |||
348 | prop_array_add_uint64(prop_array, | 362 | prop_array_add_uint64(prop_array, | |
349 | (uint64_t) tsc->tsc_snap_dev->pdev_vnode->v_rdev); | 363 | (uint64_t) tsc->tsc_snap_dev->pdev_vnode->v_rdev); | |
350 | 364 | |||
351 | if (tsc->tsc_persistent_dev) { | 365 | if (tsc->tsc_persistent_dev) { | |
352 | prop_array_add_uint64(prop_array, | 366 | prop_array_add_uint64(prop_array, | |
353 | (uint64_t) tsc->tsc_cow_dev->pdev_vnode->v_rdev); | 367 | (uint64_t) tsc->tsc_cow_dev->pdev_vnode->v_rdev); | |
354 | 368 | |||
355 | } | 369 | } | |
356 | return 0; | 370 | return 0; | |
357 | } | 371 | } | |
358 | 372 | |||
359 | /* Upcall is used to inform other depended devices about IO. */ | 373 | /* Upcall is used to inform other depended devices about IO. */ | |
360 | int | 374 | int | |
361 | dm_target_snapshot_upcall(dm_table_entry_t *table_en, struct buf *bp) | 375 | dm_target_snapshot_upcall(dm_table_entry_t *table_en, struct buf *bp) | |
362 | { | 376 | { | |
363 | printf("dm_target_snapshot_upcall called\n"); | 377 | printf("dm_target_snapshot_upcall called\n"); | |
364 | 378 | |||
365 | printf("upcall buf flags %s %s\n", | 379 | printf("upcall buf flags %s %s\n", | |
366 | (bp->b_flags & B_WRITE) ? "B_WRITE" : "", | 380 | (bp->b_flags & B_WRITE) ? "B_WRITE" : "", | |
367 | (bp->b_flags & B_READ) ? "B_READ" : ""); | 381 | (bp->b_flags & B_READ) ? "B_READ" : ""); | |
368 | 382 | |||
369 | return 0; | 383 | return 0; | |
370 | } | 384 | } | |
371 | 385 | |||
372 | /* | 386 | /* | |
373 | * dm target snapshot origin routines. | 387 | * dm target snapshot origin routines. | |
374 | * | 388 | * | |
375 | * Keep for compatibility with linux lvm2tools. They use two targets | 389 | * Keep for compatibility with linux lvm2tools. They use two targets | |
376 | * to implement snapshots. Snapshot target will implement exception | 390 | * to implement snapshots. Snapshot target will implement exception | |
377 | * store and snapshot origin will implement device which calls every | 391 | * store and snapshot origin will implement device which calls every | |
378 | * snapshot device when write is done on master device. | 392 | * snapshot device when write is done on master device. | |
379 | */ | 393 | */ | |
380 | 394 | |||
381 | /* | 395 | /* | |
382 | * Init function called from dm_table_load_ioctl. | 396 | * Init function called from dm_table_load_ioctl. | |
383 | * | 397 | * | |
384 | * argv: /dev/mapper/my_data_real | 398 | * argv: /dev/mapper/my_data_real | |
385 | */ | 399 | */ | |
386 | int | 400 | int | |
387 | dm_target_snapshot_orig_init(dm_table_entry_t *table_en, char *params) | 401 | dm_target_snapshot_orig_init(dm_table_entry_t *table_en, char *params) | |
388 | { | 402 | { | |
389 | dm_target_snapshot_origin_config_t *tsoc; | 403 | dm_target_snapshot_origin_config_t *tsoc; | |
390 | dm_pdev_t *dmp_real; | 404 | dm_pdev_t *dmp_real; | |
391 | 405 | |||
392 | if (params == NULL) | 406 | if (params == NULL) | |
393 | return EINVAL; | 407 | return EINVAL; | |
394 | 408 | |||
395 | printf("Snapshot origin target init function called!!\n"); | 409 | printf("Snapshot origin target init function called!!\n"); | |
396 | printf("Parent device: %s\n", params); | 410 | printf("Parent device: %s\n", params); | |
397 | 411 | |||
398 | /* Insert snap device to global pdev list */ | 412 | /* Insert snap device to global pdev list */ | |
399 | if ((dmp_real = dm_pdev_insert(params)) == NULL) | 413 | if ((dmp_real = dm_pdev_insert(params)) == NULL) | |
400 | return ENOENT; | 414 | return ENOENT; | |
401 | 415 | |||
402 | tsoc = kmem_alloc(sizeof(dm_target_snapshot_origin_config_t), KM_SLEEP); | 416 | tsoc = kmem_alloc(sizeof(dm_target_snapshot_origin_config_t), KM_SLEEP); | |
403 | tsoc->tsoc_real_dev = dmp_real; | 417 | tsoc->tsoc_real_dev = dmp_real; | |
404 | 418 | |||
405 | table_en->target_config = tsoc; | 419 | table_en->target_config = tsoc; | |
406 | 420 | |||
407 | return 0; | 421 | return 0; | |
408 | } | 422 | } | |
409 | 423 | |||
410 | /* | 424 | /* | |
411 | * Status routine is called to get params string, which is target | 425 | * Status routine is called to get params string, which is target | |
412 | * specific. When dm_table_status_ioctl is called with flag | 426 | * specific. When dm_table_status_ioctl is called with flag | |
413 | * DM_STATUS_TABLE_FLAG I have to sent params string back. | 427 | * DM_STATUS_TABLE_FLAG I have to sent params string back. | |
414 | */ | 428 | */ | |
415 | char * | 429 | char * | |
416 | dm_target_snapshot_orig_status(void *target_config) | 430 | dm_target_snapshot_orig_status(void *target_config) | |
417 | { | 431 | { | |
418 | dm_target_snapshot_origin_config_t *tsoc; | 432 | dm_target_snapshot_origin_config_t *tsoc; | |
419 | 433 | |||
420 | size_t prm_len; | 434 | size_t prm_len; | |
421 | char *params; | 435 | char *params; | |
422 | 436 | |||
423 | tsoc = target_config; | 437 | tsoc = target_config; | |
424 | 438 | |||
425 | prm_len = 0; | 439 | prm_len = 0; | |
426 | 440 | |||
427 | printf("Snapshot origin target status function called\n"); | 441 | printf("Snapshot origin target status function called\n"); | |
428 | 442 | |||
429 | /* length of names + count of chars + spaces and null char */ | 443 | /* length of names + count of chars + spaces and null char */ | |
430 | prm_len = strlen(tsoc->tsoc_real_dev->name) + 1; | 444 | prm_len = strlen(tsoc->tsoc_real_dev->name) + 1; | |
431 | 445 | |||
432 | printf("real_dev name %s\n", tsoc->tsoc_real_dev->name); | 446 | printf("real_dev name %s\n", tsoc->tsoc_real_dev->name); | |
433 | 447 | |||
434 | params = kmem_alloc(prm_len, KM_SLEEP); | 448 | params = kmem_alloc(prm_len, KM_SLEEP); | |
435 | 449 | |||
436 | printf("%s\n", tsoc->tsoc_real_dev->name); | 450 | printf("%s\n", tsoc->tsoc_real_dev->name); | |
437 | 451 | |||
438 | snprintf(params, prm_len, "%s", tsoc->tsoc_real_dev->name); | 452 | snprintf(params, prm_len, "%s", tsoc->tsoc_real_dev->name); | |
439 | 453 | |||
440 | return params; | 454 | return params; | |
441 | } | 455 | } | |
442 | 456 | |||
443 | /* Strategy routine called from dm_strategy. */ | 457 | /* Strategy routine called from dm_strategy. */ | |
444 | int | 458 | int | |
445 | dm_target_snapshot_orig_strategy(dm_table_entry_t *table_en, struct buf *bp) | 459 | dm_target_snapshot_orig_strategy(dm_table_entry_t *table_en, struct buf *bp) | |
446 | { | 460 | { | |
447 | 461 | |||
448 | printf("Snapshot_Orig target read function called!!\n"); | 462 | printf("Snapshot_Orig target read function called!!\n"); | |
449 | 463 | |||
450 | bp->b_error = EIO; | 464 | bp->b_error = EIO; | |
451 | bp->b_resid = 0; | 465 | bp->b_resid = 0; | |
452 | 466 | |||
453 | biodone(bp); | 467 | biodone(bp); | |
454 | 468 | |||
455 | return 0; | 469 | return 0; | |
456 | } | 470 | } | |
457 | 471 | |||
458 | /* | 472 | /* | |
459 | * Sync underlying disk caches. | 473 | * Sync underlying disk caches. | |
460 | */ | 474 | */ | |
461 | int | 475 | int | |
462 | dm_target_snapshot_orig_sync(dm_table_entry_t *table_en) | 476 | dm_target_snapshot_orig_sync(dm_table_entry_t *table_en) | |
463 | { | 477 | { | |
464 | int cmd; | 478 | int cmd; | |
465 | dm_target_snapshot_origin_config_t *tsoc; | 479 | dm_target_snapshot_origin_config_t *tsoc; | |
466 | 480 | |||
467 | tsoc = table_en->target_config; | 481 | tsoc = table_en->target_config; | |
468 | 482 | |||
469 | cmd = 1; | 483 | cmd = 1; | |
470 | 484 | |||
471 | return VOP_IOCTL(tsoc->tsoc_real_dev->pdev_vnode, DIOCCACHESYNC, | 485 | return VOP_IOCTL(tsoc->tsoc_real_dev->pdev_vnode, DIOCCACHESYNC, | |
472 | &cmd, FREAD|FWRITE, kauth_cred_get()); | 486 | &cmd, FREAD|FWRITE, kauth_cred_get()); | |
473 | } | 487 | } | |
474 | 488 | |||
475 | /* Decrement pdev and free allocated space. */ | 489 | /* Decrement pdev and free allocated space. */ | |
476 | int | 490 | int | |
477 | dm_target_snapshot_orig_destroy(dm_table_entry_t *table_en) | 491 | dm_target_snapshot_orig_destroy(dm_table_entry_t *table_en) | |
478 | { | 492 | { | |
479 | 493 | |||
480 | /* | 494 | /* | |
481 | * Destroy function is called for every target even if it | 495 | * Destroy function is called for every target even if it | |
482 | * doesn't have target_config. | 496 | * doesn't have target_config. | |
483 | */ | 497 | */ | |
484 | 498 | |||
485 | if (table_en->target_config == NULL) | 499 | if (table_en->target_config == NULL) | |
486 | goto out; | 500 | goto out; | |
487 | 501 | |||
488 | dm_target_snapshot_origin_config_t *tsoc = table_en->target_config; | 502 | dm_target_snapshot_origin_config_t *tsoc = table_en->target_config; | |
489 | 503 | |||
490 | /* Decrement pdev ref counter if 0 remove it */ | 504 | /* Decrement pdev ref counter if 0 remove it */ | |
491 | dm_pdev_decr(tsoc->tsoc_real_dev); | 505 | dm_pdev_decr(tsoc->tsoc_real_dev); | |
492 | 506 | |||
493 | kmem_free(tsoc, sizeof(*tsoc)); | 507 | kmem_free(tsoc, sizeof(*tsoc)); | |
494 | out: | 508 | out: | |
495 | /* Unbusy target so we can unload it */ | 509 | /* Unbusy target so we can unload it */ | |
496 | dm_target_unbusy(table_en->target); | 510 | dm_target_unbusy(table_en->target); | |
497 | 511 | |||
498 | return 0; | 512 | return 0; | |
499 | } | 513 | } | |
500 | 514 | |||
501 | /* | 515 | /* | |
502 | * Get target deps and add them to prop_array_t. | 516 | * Get target deps and add them to prop_array_t. | |
503 | */ | 517 | */ | |
504 | int | 518 | int | |
505 | dm_target_snapshot_orig_deps(dm_table_entry_t *table_en, | 519 | dm_target_snapshot_orig_deps(dm_table_entry_t *table_en, | |
506 | prop_array_t prop_array) | 520 | prop_array_t prop_array) | |
507 | { | 521 | { | |
508 | dm_target_snapshot_origin_config_t *tsoc; | 522 | dm_target_snapshot_origin_config_t *tsoc; | |
509 | struct vattr va; | 523 | struct vattr va; | |
510 | 524 | |||
511 | int error; | 525 | int error; | |
512 | 526 | |||
513 | if (table_en->target_config == NULL) | 527 | if (table_en->target_config == NULL) | |
514 | return 0; | 528 | return 0; | |
515 | 529 | |||
516 | tsoc = table_en->target_config; | 530 | tsoc = table_en->target_config; | |
517 | 531 | |||
518 | vn_lock(tsoc->tsoc_real_dev->pdev_vnode, LK_SHARED | LK_RETRY); | 532 | vn_lock(tsoc->tsoc_real_dev->pdev_vnode, LK_SHARED | LK_RETRY); | |
519 | error = VOP_GETATTR(tsoc->tsoc_real_dev->pdev_vnode, &va, | 533 | error = VOP_GETATTR(tsoc->tsoc_real_dev->pdev_vnode, &va, | |
520 | curlwp->l_cred); | 534 | curlwp->l_cred); | |
521 | VOP_UNLOCK(tsoc->tsoc_real_dev->pdev_vnode); | 535 | VOP_UNLOCK(tsoc->tsoc_real_dev->pdev_vnode); | |
522 | if (error != 0) | 536 | if (error != 0) | |
523 | return error; | 537 | return error; | |
524 | 538 | |||
525 | prop_array_add_uint64(prop_array, (uint64_t) va.va_rdev); | 539 | prop_array_add_uint64(prop_array, (uint64_t) va.va_rdev); | |
526 | 540 | |||
527 | return 0; | 541 | return 0; | |
528 | } | 542 | } | |
529 | 543 | |||
530 | /* Unsupported for this target. */ | 544 | /* Unsupported for this target. */ | |
531 | int | 545 | int | |
532 | dm_target_snapshot_orig_upcall(dm_table_entry_t *table_en, struct buf *bp) | 546 | dm_target_snapshot_orig_upcall(dm_table_entry_t *table_en, struct buf *bp) | |
533 | { | 547 | { | |
534 | return 0; | 548 | return 0; | |
535 | } | 549 | } |
--- src/sys/dev/dm/dm_target_stripe.c 2019/12/08 04:41:02 1.31
+++ src/sys/dev/dm/dm_target_stripe.c 2019/12/08 10:50:21 1.32
@@ -1,372 +1,380 @@ | @@ -1,372 +1,380 @@ | |||
1 | /*$NetBSD: dm_target_stripe.c,v 1.31 2019/12/08 04:41:02 tkusumi Exp $*/ | 1 | /*$NetBSD: dm_target_stripe.c,v 1.32 2019/12/08 10:50:21 tkusumi Exp $*/ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2009 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Adam Hamsik. | 8 | * by Adam Hamsik. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | #include <sys/cdefs.h> | 31 | #include <sys/cdefs.h> | |
32 | __KERNEL_RCSID(0, "$NetBSD: dm_target_stripe.c,v 1.31 2019/12/08 04:41:02 tkusumi Exp $"); | 32 | __KERNEL_RCSID(0, "$NetBSD: dm_target_stripe.c,v 1.32 2019/12/08 10:50:21 tkusumi Exp $"); | |
33 | 33 | |||
34 | /* | 34 | /* | |
35 | * This file implements initial version of device-mapper stripe target. | 35 | * This file implements initial version of device-mapper stripe target. | |
36 | */ | 36 | */ | |
37 | #include <sys/types.h> | 37 | #include <sys/types.h> | |
38 | #include <sys/param.h> | 38 | #include <sys/param.h> | |
39 | 39 | |||
40 | #include <sys/buf.h> | 40 | #include <sys/buf.h> | |
41 | #include <sys/kmem.h> | 41 | #include <sys/kmem.h> | |
42 | #include <sys/lwp.h> | 42 | #include <sys/lwp.h> | |
43 | 43 | |||
44 | #include "dm.h" | 44 | #include "dm.h" | |
45 | 45 | |||
46 | typedef struct target_stripe_config { | |||
47 | #define DM_STRIPE_DEV_OFFSET 2 | |||
48 | struct target_linear_devs stripe_devs; | |||
49 | uint8_t stripe_num; | |||
50 | uint64_t stripe_chunksize; | |||
51 | size_t params_len; | |||
52 | } dm_target_stripe_config_t; | |||
53 | ||||
46 | #ifdef DM_TARGET_MODULE | 54 | #ifdef DM_TARGET_MODULE | |
47 | /* | 55 | /* | |
48 | * Every target can be compiled directly to dm driver or as a | 56 | * Every target can be compiled directly to dm driver or as a | |
49 | * separate module this part of target is used for loading targets | 57 | * separate module this part of target is used for loading targets | |
50 | * to dm driver. | 58 | * to dm driver. | |
51 | * Target can be unloaded from kernel only if there are no users of | 59 | * Target can be unloaded from kernel only if there are no users of | |
52 | * it e.g. there are no devices which uses that target. | 60 | * it e.g. there are no devices which uses that target. | |
53 | */ | 61 | */ | |
54 | #include <sys/kernel.h> | 62 | #include <sys/kernel.h> | |
55 | #include <sys/module.h> | 63 | #include <sys/module.h> | |
56 | 64 | |||
57 | MODULE(MODULE_CLASS_MISC, dm_target_stripe, NULL); | 65 | MODULE(MODULE_CLASS_MISC, dm_target_stripe, NULL); | |
58 | 66 | |||
59 | static int | 67 | static int | |
60 | dm_target_stripe_modcmd(modcmd_t cmd, void *arg) | 68 | dm_target_stripe_modcmd(modcmd_t cmd, void *arg) | |
61 | { | 69 | { | |
62 | dm_target_t *dmt; | 70 | dm_target_t *dmt; | |
63 | int r; | 71 | int r; | |
64 | dmt = NULL; | 72 | dmt = NULL; | |
65 | 73 | |||
66 | switch (cmd) { | 74 | switch (cmd) { | |
67 | case MODULE_CMD_INIT: | 75 | case MODULE_CMD_INIT: | |
68 | if ((dmt = dm_target_lookup("stripe")) != NULL) { | 76 | if ((dmt = dm_target_lookup("stripe")) != NULL) { | |
69 | dm_target_unbusy(dmt); | 77 | dm_target_unbusy(dmt); | |
70 | return EEXIST; | 78 | return EEXIST; | |
71 | } | 79 | } | |
72 | dmt = dm_target_alloc("stripe"); | 80 | dmt = dm_target_alloc("stripe"); | |
73 | 81 | |||
74 | dmt->version[0] = 1; | 82 | dmt->version[0] = 1; | |
75 | dmt->version[1] = 0; | 83 | dmt->version[1] = 0; | |
76 | dmt->version[2] = 0; | 84 | dmt->version[2] = 0; | |
77 | dmt->init = &dm_target_stripe_init; | 85 | dmt->init = &dm_target_stripe_init; | |
78 | dmt->status = &dm_target_stripe_status; | 86 | dmt->status = &dm_target_stripe_status; | |
79 | dmt->strategy = &dm_target_stripe_strategy; | 87 | dmt->strategy = &dm_target_stripe_strategy; | |
80 | dmt->sync = &dm_target_stripe_sync; | 88 | dmt->sync = &dm_target_stripe_sync; | |
81 | dmt->deps = &dm_target_stripe_deps; | 89 | dmt->deps = &dm_target_stripe_deps; | |
82 | dmt->destroy = &dm_target_stripe_destroy; | 90 | dmt->destroy = &dm_target_stripe_destroy; | |
83 | dmt->upcall = &dm_target_stripe_upcall; | 91 | dmt->upcall = &dm_target_stripe_upcall; | |
84 | dmt->secsize = &dm_target_stripe_secsize; | 92 | dmt->secsize = &dm_target_stripe_secsize; | |
85 | 93 | |||
86 | r = dm_target_insert(dmt); | 94 | r = dm_target_insert(dmt); | |
87 | 95 | |||
88 | break; | 96 | break; | |
89 | 97 | |||
90 | case MODULE_CMD_FINI: | 98 | case MODULE_CMD_FINI: | |
91 | r = dm_target_rem("stripe"); | 99 | r = dm_target_rem("stripe"); | |
92 | break; | 100 | break; | |
93 | 101 | |||
94 | case MODULE_CMD_STAT: | 102 | case MODULE_CMD_STAT: | |
95 | return ENOTTY; | 103 | return ENOTTY; | |
96 | 104 | |||
97 | default: | 105 | default: | |
98 | return ENOTTY; | 106 | return ENOTTY; | |
99 | } | 107 | } | |
100 | 108 | |||
101 | return r; | 109 | return r; | |
102 | } | 110 | } | |
103 | #endif | 111 | #endif | |
104 | 112 | |||
105 | static void | 113 | static void | |
106 | dm_target_stripe_fini(dm_target_stripe_config_t *tsc) | 114 | dm_target_stripe_fini(dm_target_stripe_config_t *tsc) | |
107 | { | 115 | { | |
108 | dm_target_linear_config_t *tlc; | 116 | dm_target_linear_config_t *tlc; | |
109 | 117 | |||
110 | if (tsc == NULL) | 118 | if (tsc == NULL) | |
111 | return; | 119 | return; | |
112 | 120 | |||
113 | while ((tlc = TAILQ_FIRST(&tsc->stripe_devs)) != NULL) { | 121 | while ((tlc = TAILQ_FIRST(&tsc->stripe_devs)) != NULL) { | |
114 | TAILQ_REMOVE(&tsc->stripe_devs, tlc, entries); | 122 | TAILQ_REMOVE(&tsc->stripe_devs, tlc, entries); | |
115 | dm_pdev_decr(tlc->pdev); | 123 | dm_pdev_decr(tlc->pdev); | |
116 | kmem_free(tlc, sizeof(*tlc)); | 124 | kmem_free(tlc, sizeof(*tlc)); | |
117 | } | 125 | } | |
118 | 126 | |||
119 | kmem_free(tsc, sizeof(*tsc)); | 127 | kmem_free(tsc, sizeof(*tsc)); | |
120 | } | 128 | } | |
121 | 129 | |||
122 | /* | 130 | /* | |
123 | * Init function called from dm_table_load_ioctl. | 131 | * Init function called from dm_table_load_ioctl. | |
124 | * DM_STRIPE_DEV_OFFSET should always hold the index of the first device-offset | 132 | * DM_STRIPE_DEV_OFFSET should always hold the index of the first device-offset | |
125 | * pair in the parameters. | 133 | * pair in the parameters. | |
126 | * Example line sent to dm from lvm tools when using striped target. | 134 | * Example line sent to dm from lvm tools when using striped target. | |
127 | * start length striped #stripes chunk_size device1 offset1 ... deviceN offsetN | 135 | * start length striped #stripes chunk_size device1 offset1 ... deviceN offsetN | |
128 | * 0 65536 striped 2 512 /dev/hda 0 /dev/hdb 0 | 136 | * 0 65536 striped 2 512 /dev/hda 0 /dev/hdb 0 | |
129 | */ | 137 | */ | |
130 | int | 138 | int | |
131 | dm_target_stripe_init(dm_table_entry_t *table_en, char *params) | 139 | dm_target_stripe_init(dm_table_entry_t *table_en, char *params) | |
132 | { | 140 | { | |
133 | dm_target_linear_config_t *tlc; | 141 | dm_target_linear_config_t *tlc; | |
134 | dm_target_stripe_config_t *tsc; | 142 | dm_target_stripe_config_t *tsc; | |
135 | size_t len; | 143 | size_t len; | |
136 | char **ap, *argv[10]; | 144 | char **ap, *argv[10]; | |
137 | int strpc, strpi; | 145 | int strpc, strpi; | |
138 | 146 | |||
139 | if (params == NULL) | 147 | if (params == NULL) | |
140 | return EINVAL; | 148 | return EINVAL; | |
141 | 149 | |||
142 | len = strlen(params) + 1; | 150 | len = strlen(params) + 1; | |
143 | 151 | |||
144 | /* | 152 | /* | |
145 | * Parse a string, containing tokens delimited by white space, | 153 | * Parse a string, containing tokens delimited by white space, | |
146 | * into an argument vector | 154 | * into an argument vector | |
147 | */ | 155 | */ | |
148 | for (ap = argv; ap <= &argv[9] && | 156 | for (ap = argv; ap <= &argv[9] && | |
149 | (*ap = strsep(¶ms, " \t")) != NULL;) { | 157 | (*ap = strsep(¶ms, " \t")) != NULL;) { | |
150 | if (**ap != '\0') | 158 | if (**ap != '\0') | |
151 | ap++; | 159 | ap++; | |
152 | } | 160 | } | |
153 | 161 | |||
154 | printf("Stripe target init function called!!\n"); | 162 | printf("Stripe target init function called!!\n"); | |
155 | 163 | |||
156 | printf("Stripe target chunk size %s number of stripes %s\n", | 164 | printf("Stripe target chunk size %s number of stripes %s\n", | |
157 | argv[1], argv[0]); | 165 | argv[1], argv[0]); | |
158 | 166 | |||
159 | tsc = kmem_alloc(sizeof(*tsc), KM_SLEEP); | 167 | tsc = kmem_alloc(sizeof(*tsc), KM_SLEEP); | |
160 | 168 | |||
161 | /* Initialize linked list for striping devices */ | 169 | /* Initialize linked list for striping devices */ | |
162 | TAILQ_INIT(&tsc->stripe_devs); | 170 | TAILQ_INIT(&tsc->stripe_devs); | |
163 | 171 | |||
164 | /* Save length of param string */ | 172 | /* Save length of param string */ | |
165 | tsc->params_len = len; | 173 | tsc->params_len = len; | |
166 | tsc->stripe_chunksize = atoi(argv[1]); | 174 | tsc->stripe_chunksize = atoi(argv[1]); | |
167 | tsc->stripe_num = (uint8_t) atoi(argv[0]); | 175 | tsc->stripe_num = (uint8_t) atoi(argv[0]); | |
168 | 176 | |||
169 | strpc = DM_STRIPE_DEV_OFFSET + (tsc->stripe_num * 2); | 177 | strpc = DM_STRIPE_DEV_OFFSET + (tsc->stripe_num * 2); | |
170 | for (strpi = DM_STRIPE_DEV_OFFSET; strpi < strpc; strpi += 2) { | 178 | for (strpi = DM_STRIPE_DEV_OFFSET; strpi < strpc; strpi += 2) { | |
171 | printf("Stripe target device name %s -- offset %s\n", | 179 | printf("Stripe target device name %s -- offset %s\n", | |
172 | argv[strpi], argv[strpi+1]); | 180 | argv[strpi], argv[strpi+1]); | |
173 | 181 | |||
174 | tlc = kmem_alloc(sizeof(*tlc), KM_SLEEP); | 182 | tlc = kmem_alloc(sizeof(*tlc), KM_SLEEP); | |
175 | if ((tlc->pdev = dm_pdev_insert(argv[strpi])) == NULL) { | 183 | if ((tlc->pdev = dm_pdev_insert(argv[strpi])) == NULL) { | |
176 | kmem_free(tlc, sizeof(*tlc)); | 184 | kmem_free(tlc, sizeof(*tlc)); | |
177 | dm_target_stripe_fini(tsc); | 185 | dm_target_stripe_fini(tsc); | |
178 | return ENOENT; | 186 | return ENOENT; | |
179 | } | 187 | } | |
180 | tlc->offset = atoi(argv[strpi+1]); | 188 | tlc->offset = atoi(argv[strpi+1]); | |
181 | 189 | |||
182 | /* Insert striping device to linked list. */ | 190 | /* Insert striping device to linked list. */ | |
183 | TAILQ_INSERT_TAIL(&tsc->stripe_devs, tlc, entries); | 191 | TAILQ_INSERT_TAIL(&tsc->stripe_devs, tlc, entries); | |
184 | } | 192 | } | |
185 | 193 | |||
186 | table_en->target_config = tsc; | 194 | table_en->target_config = tsc; | |
187 | 195 | |||
188 | return 0; | 196 | return 0; | |
189 | } | 197 | } | |
190 | 198 | |||
191 | /* Status routine called to get params string. */ | 199 | /* Status routine called to get params string. */ | |
192 | char * | 200 | char * | |
193 | dm_target_stripe_status(void *target_config) | 201 | dm_target_stripe_status(void *target_config) | |
194 | { | 202 | { | |
195 | dm_target_linear_config_t *tlc; | 203 | dm_target_linear_config_t *tlc; | |
196 | dm_target_stripe_config_t *tsc; | 204 | dm_target_stripe_config_t *tsc; | |
197 | char *params, *tmp; | 205 | char *params, *tmp; | |
198 | 206 | |||
199 | tsc = target_config; | 207 | tsc = target_config; | |
200 | 208 | |||
201 | params = kmem_alloc(DM_MAX_PARAMS_SIZE, KM_SLEEP); | 209 | params = kmem_alloc(DM_MAX_PARAMS_SIZE, KM_SLEEP); | |
202 | tmp = kmem_alloc(DM_MAX_PARAMS_SIZE, KM_SLEEP); | 210 | tmp = kmem_alloc(DM_MAX_PARAMS_SIZE, KM_SLEEP); | |
203 | 211 | |||
204 | snprintf(params, DM_MAX_PARAMS_SIZE, "%d %" PRIu64, | 212 | snprintf(params, DM_MAX_PARAMS_SIZE, "%d %" PRIu64, | |
205 | tsc->stripe_num, tsc->stripe_chunksize); | 213 | tsc->stripe_num, tsc->stripe_chunksize); | |
206 | 214 | |||
207 | TAILQ_FOREACH(tlc, &tsc->stripe_devs, entries) { | 215 | TAILQ_FOREACH(tlc, &tsc->stripe_devs, entries) { | |
208 | snprintf(tmp, DM_MAX_PARAMS_SIZE, " %s %" PRIu64, | 216 | snprintf(tmp, DM_MAX_PARAMS_SIZE, " %s %" PRIu64, | |
209 | tlc->pdev->name, tlc->offset); | 217 | tlc->pdev->name, tlc->offset); | |
210 | strcat(params, tmp); | 218 | strcat(params, tmp); | |
211 | } | 219 | } | |
212 | 220 | |||
213 | kmem_free(tmp, DM_MAX_PARAMS_SIZE); | 221 | kmem_free(tmp, DM_MAX_PARAMS_SIZE); | |
214 | 222 | |||
215 | return params; | 223 | return params; | |
216 | } | 224 | } | |
217 | 225 | |||
218 | /* Strategy routine called from dm_strategy. */ | 226 | /* Strategy routine called from dm_strategy. */ | |
219 | int | 227 | int | |
220 | dm_target_stripe_strategy(dm_table_entry_t *table_en, struct buf *bp) | 228 | dm_target_stripe_strategy(dm_table_entry_t *table_en, struct buf *bp) | |
221 | { | 229 | { | |
222 | dm_target_linear_config_t *tlc; | 230 | dm_target_linear_config_t *tlc; | |
223 | dm_target_stripe_config_t *tsc; | 231 | dm_target_stripe_config_t *tsc; | |
224 | struct buf *nestbuf; | 232 | struct buf *nestbuf; | |
225 | uint64_t blkno, blkoff; | 233 | uint64_t blkno, blkoff; | |
226 | uint64_t stripe, stripe_blknr; | 234 | uint64_t stripe, stripe_blknr; | |
227 | uint32_t stripe_off, stripe_rest, num_blks, issue_blks; | 235 | uint32_t stripe_off, stripe_rest, num_blks, issue_blks; | |
228 | int i, stripe_devnr; | 236 | int i, stripe_devnr; | |
229 | 237 | |||
230 | tsc = table_en->target_config; | 238 | tsc = table_en->target_config; | |
231 | if (tsc == NULL) | 239 | if (tsc == NULL) | |
232 | return 0; | 240 | return 0; | |
233 | 241 | |||
234 | /* printf("Stripe target read function called %" PRIu64 "!!\n", | 242 | /* printf("Stripe target read function called %" PRIu64 "!!\n", | |
235 | tlc->offset);*/ | 243 | tlc->offset);*/ | |
236 | 244 | |||
237 | /* calculate extent of request */ | 245 | /* calculate extent of request */ | |
238 | KASSERT(bp->b_resid % DEV_BSIZE == 0); | 246 | KASSERT(bp->b_resid % DEV_BSIZE == 0); | |
239 | 247 | |||
240 | blkno = bp->b_blkno; | 248 | blkno = bp->b_blkno; | |
241 | blkoff = 0; | 249 | blkoff = 0; | |
242 | num_blks = bp->b_resid / DEV_BSIZE; | 250 | num_blks = bp->b_resid / DEV_BSIZE; | |
243 | for (;;) { | 251 | for (;;) { | |
244 | /* blockno to stripe piece nr */ | 252 | /* blockno to stripe piece nr */ | |
245 | stripe = blkno / tsc->stripe_chunksize; | 253 | stripe = blkno / tsc->stripe_chunksize; | |
246 | stripe_off = blkno % tsc->stripe_chunksize; | 254 | stripe_off = blkno % tsc->stripe_chunksize; | |
247 | 255 | |||
248 | /* where we are inside the stripe */ | 256 | /* where we are inside the stripe */ | |
249 | stripe_devnr = stripe % tsc->stripe_num; | 257 | stripe_devnr = stripe % tsc->stripe_num; | |
250 | stripe_blknr = stripe / tsc->stripe_num; | 258 | stripe_blknr = stripe / tsc->stripe_num; | |
251 | 259 | |||
252 | /* how much is left before we hit a boundary */ | 260 | /* how much is left before we hit a boundary */ | |
253 | stripe_rest = tsc->stripe_chunksize - stripe_off; | 261 | stripe_rest = tsc->stripe_chunksize - stripe_off; | |
254 | 262 | |||
255 | /* issue this piece on stripe `stripe' */ | 263 | /* issue this piece on stripe `stripe' */ | |
256 | issue_blks = MIN(stripe_rest, num_blks); | 264 | issue_blks = MIN(stripe_rest, num_blks); | |
257 | nestbuf = getiobuf(NULL, true); | 265 | nestbuf = getiobuf(NULL, true); | |
258 | 266 | |||
259 | nestiobuf_setup(bp, nestbuf, blkoff, issue_blks * DEV_BSIZE); | 267 | nestiobuf_setup(bp, nestbuf, blkoff, issue_blks * DEV_BSIZE); | |
260 | nestbuf->b_blkno = stripe_blknr * tsc->stripe_chunksize + stripe_off; | 268 | nestbuf->b_blkno = stripe_blknr * tsc->stripe_chunksize + stripe_off; | |
261 | 269 | |||
262 | tlc = TAILQ_FIRST(&tsc->stripe_devs); | 270 | tlc = TAILQ_FIRST(&tsc->stripe_devs); | |
263 | for (i = 0; i < stripe_devnr && tlc != NULL; i++) | 271 | for (i = 0; i < stripe_devnr && tlc != NULL; i++) | |
264 | tlc = TAILQ_NEXT(tlc, entries); | 272 | tlc = TAILQ_NEXT(tlc, entries); | |
265 | 273 | |||
266 | /* by this point we should have an tlc */ | 274 | /* by this point we should have an tlc */ | |
267 | KASSERT(tlc != NULL); | 275 | KASSERT(tlc != NULL); | |
268 | 276 | |||
269 | nestbuf->b_blkno += tlc->offset; | 277 | nestbuf->b_blkno += tlc->offset; | |
270 | 278 | |||
271 | VOP_STRATEGY(tlc->pdev->pdev_vnode, nestbuf); | 279 | VOP_STRATEGY(tlc->pdev->pdev_vnode, nestbuf); | |
272 | 280 | |||
273 | blkno += issue_blks; | 281 | blkno += issue_blks; | |
274 | blkoff += issue_blks * DEV_BSIZE; | 282 | blkoff += issue_blks * DEV_BSIZE; | |
275 | num_blks -= issue_blks; | 283 | num_blks -= issue_blks; | |
276 | 284 | |||
277 | if (num_blks <= 0) | 285 | if (num_blks <= 0) | |
278 | break; | 286 | break; | |
279 | } | 287 | } | |
280 | 288 | |||
281 | return 0; | 289 | return 0; | |
282 | } | 290 | } | |
283 | 291 | |||
284 | /* Sync underlying disk caches. */ | 292 | /* Sync underlying disk caches. */ | |
285 | int | 293 | int | |
286 | dm_target_stripe_sync(dm_table_entry_t *table_en) | 294 | dm_target_stripe_sync(dm_table_entry_t *table_en) | |
287 | { | 295 | { | |
288 | int cmd, err; | 296 | int cmd, err; | |
289 | dm_target_stripe_config_t *tsc; | 297 | dm_target_stripe_config_t *tsc; | |
290 | dm_target_linear_config_t *tlc; | 298 | dm_target_linear_config_t *tlc; | |
291 | 299 | |||
292 | tsc = table_en->target_config; | 300 | tsc = table_en->target_config; | |
293 | 301 | |||
294 | err = 0; | 302 | err = 0; | |
295 | cmd = 1; | 303 | cmd = 1; | |
296 | 304 | |||
297 | TAILQ_FOREACH(tlc, &tsc->stripe_devs, entries) { | 305 | TAILQ_FOREACH(tlc, &tsc->stripe_devs, entries) { | |
298 | if ((err = VOP_IOCTL(tlc->pdev->pdev_vnode, DIOCCACHESYNC, | 306 | if ((err = VOP_IOCTL(tlc->pdev->pdev_vnode, DIOCCACHESYNC, | |
299 | &cmd, FREAD|FWRITE, kauth_cred_get())) != 0) | 307 | &cmd, FREAD|FWRITE, kauth_cred_get())) != 0) | |
300 | return err; | 308 | return err; | |
301 | } | 309 | } | |
302 | 310 | |||
303 | return err; | 311 | return err; | |
304 | 312 | |||
305 | } | 313 | } | |
306 | 314 | |||
307 | /* Destroy target specific data. */ | 315 | /* Destroy target specific data. */ | |
308 | int | 316 | int | |
309 | dm_target_stripe_destroy(dm_table_entry_t *table_en) | 317 | dm_target_stripe_destroy(dm_table_entry_t *table_en) | |
310 | { | 318 | { | |
311 | dm_target_stripe_fini(table_en->target_config); | 319 | dm_target_stripe_fini(table_en->target_config); | |
312 | 320 | |||
313 | /* Unbusy target so we can unload it */ | 321 | /* Unbusy target so we can unload it */ | |
314 | dm_target_unbusy(table_en->target); | 322 | dm_target_unbusy(table_en->target); | |
315 | 323 | |||
316 | return 0; | 324 | return 0; | |
317 | } | 325 | } | |
318 | 326 | |||
319 | /* Doesn't not need to do anything here. */ | 327 | /* Doesn't not need to do anything here. */ | |
320 | int | 328 | int | |
321 | dm_target_stripe_deps(dm_table_entry_t *table_en, prop_array_t prop_array) | 329 | dm_target_stripe_deps(dm_table_entry_t *table_en, prop_array_t prop_array) | |
322 | { | 330 | { | |
323 | dm_target_stripe_config_t *tsc; | 331 | dm_target_stripe_config_t *tsc; | |
324 | dm_target_linear_config_t *tlc; | 332 | dm_target_linear_config_t *tlc; | |
325 | 333 | |||
326 | if (table_en->target_config == NULL) | 334 | if (table_en->target_config == NULL) | |
327 | return ENOENT; | 335 | return ENOENT; | |
328 | 336 | |||
329 | tsc = table_en->target_config; | 337 | tsc = table_en->target_config; | |
330 | 338 | |||
331 | TAILQ_FOREACH(tlc, &tsc->stripe_devs, entries) { | 339 | TAILQ_FOREACH(tlc, &tsc->stripe_devs, entries) { | |
332 | prop_array_add_uint64(prop_array, | 340 | prop_array_add_uint64(prop_array, | |
333 | (uint64_t) tlc->pdev->pdev_vnode->v_rdev); | 341 | (uint64_t) tlc->pdev->pdev_vnode->v_rdev); | |
334 | } | 342 | } | |
335 | 343 | |||
336 | return 0; | 344 | return 0; | |
337 | } | 345 | } | |
338 | 346 | |||
339 | /* Unsupported for this target. */ | 347 | /* Unsupported for this target. */ | |
340 | int | 348 | int | |
341 | dm_target_stripe_upcall(dm_table_entry_t *table_en, struct buf *bp) | 349 | dm_target_stripe_upcall(dm_table_entry_t *table_en, struct buf *bp) | |
342 | { | 350 | { | |
343 | return 0; | 351 | return 0; | |
344 | } | 352 | } | |
345 | 353 | |||
346 | /* | 354 | /* | |
347 | * Compute physical block size | 355 | * Compute physical block size | |
348 | * For a stripe target we chose the maximum sector size of all | 356 | * For a stripe target we chose the maximum sector size of all | |
349 | * stripe devices. For the supported power-of-2 sizes this is equivalent | 357 | * stripe devices. For the supported power-of-2 sizes this is equivalent | |
350 | * to the least common multiple. | 358 | * to the least common multiple. | |
351 | */ | 359 | */ | |
352 | int | 360 | int | |
353 | dm_target_stripe_secsize(dm_table_entry_t *table_en, unsigned *secsizep) | 361 | dm_target_stripe_secsize(dm_table_entry_t *table_en, unsigned *secsizep) | |
354 | { | 362 | { | |
355 | dm_target_linear_config_t *tlc; | 363 | dm_target_linear_config_t *tlc; | |
356 | dm_target_stripe_config_t *tsc; | 364 | dm_target_stripe_config_t *tsc; | |
357 | unsigned secsize; | 365 | unsigned secsize; | |
358 | 366 | |||
359 | secsize = 0; | 367 | secsize = 0; | |
360 | 368 | |||
361 | tsc = table_en->target_config; | 369 | tsc = table_en->target_config; | |
362 | if (tsc != NULL) { | 370 | if (tsc != NULL) { | |
363 | TAILQ_FOREACH(tlc, &tsc->stripe_devs, entries) { | 371 | TAILQ_FOREACH(tlc, &tsc->stripe_devs, entries) { | |
364 | if (secsize < tlc->pdev->pdev_secsize) | 372 | if (secsize < tlc->pdev->pdev_secsize) | |
365 | secsize = tlc->pdev->pdev_secsize; | 373 | secsize = tlc->pdev->pdev_secsize; | |
366 | } | 374 | } | |
367 | } | 375 | } | |
368 | 376 | |||
369 | *secsizep = secsize; | 377 | *secsizep = secsize; | |
370 | 378 | |||
371 | return 0; | 379 | return 0; | |
372 | } | 380 | } |