Wed Dec 4 16:55:30 2019 UTC ()
dm: Minor fixes/cleanups


(tkusumi)
diff -r1.43 -r1.44 src/sys/dev/dm/device-mapper.c
diff -r1.14 -r1.15 src/sys/dev/dm/dm_pdev.c

cvs diff -r1.43 -r1.44 src/sys/dev/dm/device-mapper.c (switch to unified diff)

--- src/sys/dev/dm/device-mapper.c 2019/12/04 15:31:12 1.43
+++ src/sys/dev/dm/device-mapper.c 2019/12/04 16:55:30 1.44
@@ -1,723 +1,723 @@ @@ -1,723 +1,723 @@
1/* $NetBSD: device-mapper.c,v 1.43 2019/12/04 15:31:12 tkusumi Exp $ */ 1/* $NetBSD: device-mapper.c,v 1.44 2019/12/04 16:55:30 tkusumi Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 4 * Copyright (c) 2010 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/* 32/*
33 * I want to say thank you to all people who helped me with this project. 33 * I want to say thank you to all people who helped me with this project.
34 */ 34 */
35 35
36#include <sys/types.h> 36#include <sys/types.h>
37#include <sys/param.h> 37#include <sys/param.h>
38 38
39#include <sys/buf.h> 39#include <sys/buf.h>
40#include <sys/conf.h> 40#include <sys/conf.h>
41#include <sys/device.h> 41#include <sys/device.h>
42#include <sys/dkio.h> 42#include <sys/dkio.h>
43#include <sys/disk.h> 43#include <sys/disk.h>
44#include <sys/disklabel.h> 44#include <sys/disklabel.h>
45#include <sys/ioctl.h> 45#include <sys/ioctl.h>
46#include <sys/ioccom.h> 46#include <sys/ioccom.h>
47#include <sys/kmem.h> 47#include <sys/kmem.h>
48#include <sys/kauth.h> 48#include <sys/kauth.h>
49 49
50#include "netbsd-dm.h" 50#include "netbsd-dm.h"
51#include "dm.h" 51#include "dm.h"
52#include "ioconf.h" 52#include "ioconf.h"
53 53
54static dev_type_open(dmopen); 54static dev_type_open(dmopen);
55static dev_type_close(dmclose); 55static dev_type_close(dmclose);
56static dev_type_read(dmread); 56static dev_type_read(dmread);
57static dev_type_write(dmwrite); 57static dev_type_write(dmwrite);
58static dev_type_ioctl(dmioctl); 58static dev_type_ioctl(dmioctl);
59static dev_type_strategy(dmstrategy); 59static dev_type_strategy(dmstrategy);
60static dev_type_size(dmsize); 60static dev_type_size(dmsize);
61 61
62/* attach and detach routines */ 62/* attach and detach routines */
63#ifdef _MODULE 63#ifdef _MODULE
64static int dmdestroy(void); 64static int dmdestroy(void);
65#endif 65#endif
66 66
67static void dm_doinit(void); 67static void dm_doinit(void);
68 68
69static int dm_cmd_to_fun(prop_dictionary_t); 69static int dm_cmd_to_fun(prop_dictionary_t);
70static int disk_ioctl_switch(dev_t, u_long, void *); 70static int disk_ioctl_switch(dev_t, u_long, void *);
71static int dm_ioctl_switch(u_long); 71static int dm_ioctl_switch(u_long);
72static void dmminphys(struct buf *); 72static void dmminphys(struct buf *);
73 73
74/* CF attach/detach functions used for power management */ 74/* CF attach/detach functions used for power management */
75static int dm_detach(device_t, int); 75static int dm_detach(device_t, int);
76static void dm_attach(device_t, device_t, void *); 76static void dm_attach(device_t, device_t, void *);
77static int dm_match(device_t, cfdata_t, void *); 77static int dm_match(device_t, cfdata_t, void *);
78 78
79/* ***Variable-definitions*** */ 79/* ***Variable-definitions*** */
80const struct bdevsw dm_bdevsw = { 80const struct bdevsw dm_bdevsw = {
81 .d_open = dmopen, 81 .d_open = dmopen,
82 .d_close = dmclose, 82 .d_close = dmclose,
83 .d_strategy = dmstrategy, 83 .d_strategy = dmstrategy,
84 .d_ioctl = dmioctl, 84 .d_ioctl = dmioctl,
85 .d_dump = nodump, 85 .d_dump = nodump,
86 .d_psize = dmsize, 86 .d_psize = dmsize,
87 .d_discard = nodiscard, 87 .d_discard = nodiscard,
88 .d_flag = D_DISK | D_MPSAFE 88 .d_flag = D_DISK | D_MPSAFE
89}; 89};
90 90
91const struct cdevsw dm_cdevsw = { 91const struct cdevsw dm_cdevsw = {
92 .d_open = dmopen, 92 .d_open = dmopen,
93 .d_close = dmclose, 93 .d_close = dmclose,
94 .d_read = dmread, 94 .d_read = dmread,
95 .d_write = dmwrite, 95 .d_write = dmwrite,
96 .d_ioctl = dmioctl, 96 .d_ioctl = dmioctl,
97 .d_stop = nostop, 97 .d_stop = nostop,
98 .d_tty = notty, 98 .d_tty = notty,
99 .d_poll = nopoll, 99 .d_poll = nopoll,
100 .d_mmap = nommap, 100 .d_mmap = nommap,
101 .d_kqfilter = nokqfilter, 101 .d_kqfilter = nokqfilter,
102 .d_discard = nodiscard, 102 .d_discard = nodiscard,
103 .d_flag = D_DISK | D_MPSAFE 103 .d_flag = D_DISK | D_MPSAFE
104}; 104};
105 105
106const struct dkdriver dmdkdriver = { 106const struct dkdriver dmdkdriver = {
107 .d_strategy = dmstrategy 107 .d_strategy = dmstrategy
108}; 108};
109 109
110CFATTACH_DECL3_NEW(dm, 0, 110CFATTACH_DECL3_NEW(dm, 0,
111 dm_match, dm_attach, dm_detach, NULL, NULL, NULL, 111 dm_match, dm_attach, dm_detach, NULL, NULL, NULL,
112 DVF_DETACH_SHUTDOWN); 112 DVF_DETACH_SHUTDOWN);
113 113
114extern uint32_t dm_dev_counter; 114extern uint32_t dm_dev_counter;
115 115
116/* 116/*
117 * This structure is used to translate command sent to kernel driver in 117 * This structure is used to translate command sent to kernel driver in
118 * <key>command</key> 118 * <key>command</key>
119 * <value></value> 119 * <value></value>
120 * to function which I can call, and if the command is allowed for 120 * to function which I can call, and if the command is allowed for
121 * non-superusers. 121 * non-superusers.
122 */ 122 */
123/* 123/*
124 * This array is used to translate cmd to function pointer. 124 * This array is used to translate cmd to function pointer.
125 * 125 *
126 * Interface between libdevmapper and lvm2tools uses different 126 * Interface between libdevmapper and lvm2tools uses different
127 * names for one IOCTL call because libdevmapper do another thing 127 * names for one IOCTL call because libdevmapper do another thing
128 * then. When I run "info" or "mknodes" libdevmapper will send same 128 * then. When I run "info" or "mknodes" libdevmapper will send same
129 * ioctl to kernel but will do another things in userspace. 129 * ioctl to kernel but will do another things in userspace.
130 * 130 *
131 */ 131 */
132static const struct cmd_function { 132static const struct cmd_function {
133 const char *cmd; 133 const char *cmd;
134 int (*fn)(prop_dictionary_t); 134 int (*fn)(prop_dictionary_t);
135 int allowed; 135 int allowed;
136} cmd_fn[] = { 136} cmd_fn[] = {
137 { .cmd = "version", .fn = dm_get_version_ioctl, .allowed = 1 }, 137 { .cmd = "version", .fn = dm_get_version_ioctl, .allowed = 1 },
138 { .cmd = "targets", .fn = dm_list_versions_ioctl, .allowed = 1 }, 138 { .cmd = "targets", .fn = dm_list_versions_ioctl, .allowed = 1 },
139 { .cmd = "create", .fn = dm_dev_create_ioctl, .allowed = 0 }, 139 { .cmd = "create", .fn = dm_dev_create_ioctl, .allowed = 0 },
140 { .cmd = "info", .fn = dm_dev_status_ioctl, .allowed = 1 }, 140 { .cmd = "info", .fn = dm_dev_status_ioctl, .allowed = 1 },
141 { .cmd = "mknodes", .fn = dm_dev_status_ioctl, .allowed = 1 }, 141 { .cmd = "mknodes", .fn = dm_dev_status_ioctl, .allowed = 1 },
142 { .cmd = "names", .fn = dm_dev_list_ioctl, .allowed = 1 }, 142 { .cmd = "names", .fn = dm_dev_list_ioctl, .allowed = 1 },
143 { .cmd = "suspend", .fn = dm_dev_suspend_ioctl, .allowed = 0 }, 143 { .cmd = "suspend", .fn = dm_dev_suspend_ioctl, .allowed = 0 },
144 { .cmd = "remove", .fn = dm_dev_remove_ioctl, .allowed = 0 }, 144 { .cmd = "remove", .fn = dm_dev_remove_ioctl, .allowed = 0 },
145 { .cmd = "rename", .fn = dm_dev_rename_ioctl, .allowed = 0 }, 145 { .cmd = "rename", .fn = dm_dev_rename_ioctl, .allowed = 0 },
146 { .cmd = "resume", .fn = dm_dev_resume_ioctl, .allowed = 0 }, 146 { .cmd = "resume", .fn = dm_dev_resume_ioctl, .allowed = 0 },
147 { .cmd = "clear", .fn = dm_table_clear_ioctl, .allowed = 0 }, 147 { .cmd = "clear", .fn = dm_table_clear_ioctl, .allowed = 0 },
148 { .cmd = "deps", .fn = dm_table_deps_ioctl, .allowed = 1 }, 148 { .cmd = "deps", .fn = dm_table_deps_ioctl, .allowed = 1 },
149 { .cmd = "reload", .fn = dm_table_load_ioctl, .allowed = 0 }, 149 { .cmd = "reload", .fn = dm_table_load_ioctl, .allowed = 0 },
150 { .cmd = "status", .fn = dm_table_status_ioctl, .allowed = 1 }, 150 { .cmd = "status", .fn = dm_table_status_ioctl, .allowed = 1 },
151 { .cmd = "table", .fn = dm_table_status_ioctl, .allowed = 1 }, 151 { .cmd = "table", .fn = dm_table_status_ioctl, .allowed = 1 },
152 { .cmd = NULL, .fn = NULL, .allowed = 0 } 152 { .cmd = NULL, .fn = NULL, .allowed = 0 }
153}; 153};
154 154
155#ifdef _MODULE 155#ifdef _MODULE
156#include <sys/module.h> 156#include <sys/module.h>
157 157
158/* Autoconf defines */ 158/* Autoconf defines */
159CFDRIVER_DECL(dm, DV_DISK, NULL); 159CFDRIVER_DECL(dm, DV_DISK, NULL);
160 160
161MODULE(MODULE_CLASS_DRIVER, dm, "dk_subr"); 161MODULE(MODULE_CLASS_DRIVER, dm, "dk_subr");
162 162
163/* New module handle routine */ 163/* New module handle routine */
164static int 164static int
165dm_modcmd(modcmd_t cmd, void *arg) 165dm_modcmd(modcmd_t cmd, void *arg)
166{ 166{
167#ifdef _MODULE 167#ifdef _MODULE
168 int error; 168 int error;
169 devmajor_t bmajor, cmajor; 169 devmajor_t bmajor, cmajor;
170 170
171 error = 0; 171 error = 0;
172 bmajor = -1; 172 bmajor = -1;
173 cmajor = -1; 173 cmajor = -1;
174 174
175 switch (cmd) { 175 switch (cmd) {
176 case MODULE_CMD_INIT: 176 case MODULE_CMD_INIT:
177 error = config_cfdriver_attach(&dm_cd); 177 error = config_cfdriver_attach(&dm_cd);
178 if (error) 178 if (error)
179 break; 179 break;
180 180
181 error = config_cfattach_attach(dm_cd.cd_name, &dm_ca); 181 error = config_cfattach_attach(dm_cd.cd_name, &dm_ca);
182 if (error) { 182 if (error) {
183 aprint_error("%s: unable to register cfattach\n", 183 aprint_error("%s: unable to register cfattach\n",
184 dm_cd.cd_name); 184 dm_cd.cd_name);
185 return error; 185 return error;
186 } 186 }
187 187
188 error = devsw_attach(dm_cd.cd_name, &dm_bdevsw, &bmajor, 188 error = devsw_attach(dm_cd.cd_name, &dm_bdevsw, &bmajor,
189 &dm_cdevsw, &cmajor); 189 &dm_cdevsw, &cmajor);
190 if (error == EEXIST) 190 if (error == EEXIST)
191 error = 0; 191 error = 0;
192 if (error) { 192 if (error) {
193 config_cfattach_detach(dm_cd.cd_name, &dm_ca); 193 config_cfattach_detach(dm_cd.cd_name, &dm_ca);
194 config_cfdriver_detach(&dm_cd); 194 config_cfdriver_detach(&dm_cd);
195 break; 195 break;
196 } 196 }
197 dm_doinit(); 197 dm_doinit();
198 break; 198 break;
199 case MODULE_CMD_FINI: 199 case MODULE_CMD_FINI:
200 /* 200 /*
201 * Disable unloading of dm module if there are any devices 201 * Disable unloading of dm module if there are any devices
202 * defined in driver. This is probably too strong we need 202 * defined in driver. This is probably too strong we need
203 * to disable auto-unload only if there is mounted dm device 203 * to disable auto-unload only if there is mounted dm device
204 * present. 204 * present.
205 */ 205 */
206 if (dm_dev_counter > 0) 206 if (dm_dev_counter > 0)
207 return EBUSY; 207 return EBUSY;
208 /* race window here */ 208 /* race window here */
209 209
210 error = dmdestroy(); 210 error = dmdestroy();
211 if (error) 211 if (error)
212 break; 212 break;
213 213
214 config_cfdriver_detach(&dm_cd); 214 config_cfdriver_detach(&dm_cd);
215 215
216 devsw_detach(&dm_bdevsw, &dm_cdevsw); 216 devsw_detach(&dm_bdevsw, &dm_cdevsw);
217 break; 217 break;
218 case MODULE_CMD_STAT: 218 case MODULE_CMD_STAT:
219 return ENOTTY; 219 return ENOTTY;
220 default: 220 default:
221 return ENOTTY; 221 return ENOTTY;
222 } 222 }
223 223
224 return error; 224 return error;
225#else 225#else
226 return ENOTTY; 226 return ENOTTY;
227#endif 227#endif
228} 228}
229#endif /* _MODULE */ 229#endif /* _MODULE */
230 230
231/* 231/*
232 * dm_match: 232 * dm_match:
233 * 233 *
234 * Autoconfiguration match function for pseudo-device glue. 234 * Autoconfiguration match function for pseudo-device glue.
235 */ 235 */
236static int 236static int
237dm_match(device_t parent, cfdata_t match, void *aux) 237dm_match(device_t parent, cfdata_t match, void *aux)
238{ 238{
239 239
240 /* Pseudo-device; always present. */ 240 /* Pseudo-device; always present. */
241 return (1); 241 return (1);
242} 242}
243 243
244/* 244/*
245 * dm_attach: 245 * dm_attach:
246 * 246 *
247 * Autoconfiguration attach function for pseudo-device glue. 247 * Autoconfiguration attach function for pseudo-device glue.
248 */ 248 */
249static void 249static void
250dm_attach(device_t parent, device_t self, void *aux) 250dm_attach(device_t parent, device_t self, void *aux)
251{ 251{
252 return; 252 return;
253} 253}
254 254
255 255
256/* 256/*
257 * dm_detach: 257 * dm_detach:
258 * 258 *
259 * Autoconfiguration detach function for pseudo-device glue. 259 * Autoconfiguration detach function for pseudo-device glue.
260 * This routine is called by dm_ioctl::dm_dev_remove_ioctl and by autoconf to 260 * This routine is called by dm_ioctl::dm_dev_remove_ioctl and by autoconf to
261 * remove devices created in device-mapper. 261 * remove devices created in device-mapper.
262 */ 262 */
263static int 263static int
264dm_detach(device_t self, int flags) 264dm_detach(device_t self, int flags)
265{ 265{
266 dm_dev_t *dmv; 266 dm_dev_t *dmv;
267 267
268 /* Detach device from global device list */ 268 /* Detach device from global device list */
269 if ((dmv = dm_dev_detach(self)) == NULL) 269 if ((dmv = dm_dev_detach(self)) == NULL)
270 return ENOENT; 270 return ENOENT;
271 271
272 /* Destroy active table first. */ 272 /* Destroy active table first. */
273 dm_table_destroy(&dmv->table_head, DM_TABLE_ACTIVE); 273 dm_table_destroy(&dmv->table_head, DM_TABLE_ACTIVE);
274 274
275 /* Destroy inactive table if exits, too. */ 275 /* Destroy inactive table if exits, too. */
276 dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE); 276 dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE);
277 277
278 dm_table_head_destroy(&dmv->table_head); 278 dm_table_head_destroy(&dmv->table_head);
279 279
280 /* Destroy disk device structure */ 280 /* Destroy disk device structure */
281 disk_detach(dmv->diskp); 281 disk_detach(dmv->diskp);
282 disk_destroy(dmv->diskp); 282 disk_destroy(dmv->diskp);
283 283
284 /* Destroy device */ 284 /* Destroy device */
285 (void)dm_dev_free(dmv); 285 (void)dm_dev_free(dmv);
286 286
287 /* Decrement device counter After removing device */ 287 /* Decrement device counter After removing device */
288 atomic_dec_32(&dm_dev_counter); 288 atomic_dec_32(&dm_dev_counter);
289 289
290 return 0; 290 return 0;
291} 291}
292 292
293static void 293static void
294dm_doinit(void) 294dm_doinit(void)
295{ 295{
296 dm_target_init(); 296 dm_target_init();
297 dm_dev_init(); 297 dm_dev_init();
298 dm_pdev_init(); 298 dm_pdev_init();
299} 299}
300 300
301/* attach routine */ 301/* attach routine */
302void 302void
303dmattach(int n) 303dmattach(int n)
304{ 304{
305 int error; 305 int error;
306 306
307 error = config_cfattach_attach(dm_cd.cd_name, &dm_ca); 307 error = config_cfattach_attach(dm_cd.cd_name, &dm_ca);
308 if (error) { 308 if (error) {
309 aprint_error("%s: unable to register cfattach\n", 309 aprint_error("%s: unable to register cfattach\n",
310 dm_cd.cd_name); 310 dm_cd.cd_name);
311 } else { 311 } else {
312 dm_doinit(); 312 dm_doinit();
313 } 313 }
314} 314}
315 315
316#ifdef _MODULE 316#ifdef _MODULE
317/* Destroy routine */ 317/* Destroy routine */
318static int 318static int
319dmdestroy(void) 319dmdestroy(void)
320{ 320{
321 int error; 321 int error;
322 322
323 error = config_cfattach_detach(dm_cd.cd_name, &dm_ca); 323 error = config_cfattach_detach(dm_cd.cd_name, &dm_ca);
324 if (error) 324 if (error)
325 return error; 325 return error;
326 326
327 dm_dev_destroy(); 327 dm_dev_destroy();
328 dm_pdev_destroy(); 328 dm_pdev_destroy();
329 dm_target_destroy(); 329 dm_target_destroy();
330 330
331 return 0; 331 return 0;
332} 332}
333#endif /* _MODULE */ 333#endif /* _MODULE */
334 334
335static int 335static int
336dmopen(dev_t dev, int flags, int mode, struct lwp *l) 336dmopen(dev_t dev, int flags, int mode, struct lwp *l)
337{ 337{
338 338
339 aprint_debug("dm open routine called %" PRIu32 "\n", minor(dev)); 339 aprint_debug("dm open routine called %" PRIu32 "\n", minor(dev));
340 return 0; 340 return 0;
341} 341}
342 342
343static int 343static int
344dmclose(dev_t dev, int flags, int mode, struct lwp *l) 344dmclose(dev_t dev, int flags, int mode, struct lwp *l)
345{ 345{
346 346
347 aprint_debug("dm close routine called %" PRIu32 "\n", minor(dev)); 347 aprint_debug("dm close routine called %" PRIu32 "\n", minor(dev));
348 return 0; 348 return 0;
349} 349}
350 350
351 351
352static int 352static int
353dmioctl(dev_t dev, const u_long cmd, void *data, int flag, struct lwp *l) 353dmioctl(dev_t dev, const u_long cmd, void *data, int flag, struct lwp *l)
354{ 354{
355 int r; 355 int r;
356 prop_dictionary_t dm_dict_in; 356 prop_dictionary_t dm_dict_in;
357 357
358 r = 0; 358 r = 0;
359 359
360 aprint_debug("dmioctl called\n"); 360 aprint_debug("dmioctl called\n");
361 KASSERT(data != NULL); 361 KASSERT(data != NULL);
362 362
363 if ((r = disk_ioctl_switch(dev, cmd, data)) == ENOTTY) { 363 if ((r = disk_ioctl_switch(dev, cmd, data)) == ENOTTY) {
364 struct plistref *pref = (struct plistref *) data; 364 struct plistref *pref = (struct plistref *) data;
365 365
366 /* Check if we were called with NETBSD_DM_IOCTL ioctl 366 /* Check if we were called with NETBSD_DM_IOCTL ioctl
367 otherwise quit. */ 367 otherwise quit. */
368 if ((r = dm_ioctl_switch(cmd)) != 0) 368 if ((r = dm_ioctl_switch(cmd)) != 0)
369 return r; 369 return r;
370 370
371 if((r = prop_dictionary_copyin_ioctl(pref, cmd, &dm_dict_in)) 371 if((r = prop_dictionary_copyin_ioctl(pref, cmd, &dm_dict_in))
372 != 0) 372 != 0)
373 return r; 373 return r;
374 374
375 if ((r = dm_check_version(dm_dict_in)) != 0) 375 if ((r = dm_check_version(dm_dict_in)) != 0)
376 goto cleanup_exit; 376 goto cleanup_exit;
377 377
378 /* run ioctl routine */ 378 /* run ioctl routine */
379 if ((r = dm_cmd_to_fun(dm_dict_in)) != 0) 379 if ((r = dm_cmd_to_fun(dm_dict_in)) != 0)
380 goto cleanup_exit; 380 goto cleanup_exit;
381 381
382cleanup_exit: 382cleanup_exit:
383 r = prop_dictionary_copyout_ioctl(pref, cmd, dm_dict_in); 383 r = prop_dictionary_copyout_ioctl(pref, cmd, dm_dict_in);
384 prop_object_release(dm_dict_in); 384 prop_object_release(dm_dict_in);
385 } 385 }
386 386
387 return r; 387 return r;
388} 388}
389 389
390/* 390/*
391 * Translate command sent from libdevmapper to func. 391 * Translate command sent from libdevmapper to func.
392 */ 392 */
393static int 393static int
394dm_cmd_to_fun(prop_dictionary_t dm_dict) 394dm_cmd_to_fun(prop_dictionary_t dm_dict)
395 { 395 {
396 int i, r; 396 int i, r;
397 prop_string_t command; 397 prop_string_t command;
398 398
399 r = 0; 399 r = 0;
400 400
401 if ((command = prop_dictionary_get(dm_dict, DM_IOCTL_COMMAND)) == NULL) 401 if ((command = prop_dictionary_get(dm_dict, DM_IOCTL_COMMAND)) == NULL)
402 return EINVAL; 402 return EINVAL;
403 403
404 for(i = 0; cmd_fn[i].cmd != NULL; i++) 404 for(i = 0; cmd_fn[i].cmd != NULL; i++)
405 if (prop_string_equals_cstring(command, cmd_fn[i].cmd)) 405 if (prop_string_equals_cstring(command, cmd_fn[i].cmd))
406 break; 406 break;
407 407
408 if (!cmd_fn[i].allowed && 408 if (!cmd_fn[i].allowed &&
409 (r = kauth_authorize_system(kauth_cred_get(), 409 (r = kauth_authorize_system(kauth_cred_get(),
410 KAUTH_SYSTEM_DEVMAPPER, 0, NULL, NULL, NULL)) != 0) 410 KAUTH_SYSTEM_DEVMAPPER, 0, NULL, NULL, NULL)) != 0)
411 return r; 411 return r;
412 412
413 if (cmd_fn[i].cmd == NULL) 413 if (cmd_fn[i].cmd == NULL)
414 return EINVAL; 414 return EINVAL;
415 415
416 aprint_debug("ioctl %s called\n", cmd_fn[i].cmd); 416 aprint_debug("ioctl %s called\n", cmd_fn[i].cmd);
417 r = cmd_fn[i].fn(dm_dict); 417 r = cmd_fn[i].fn(dm_dict);
418 418
419 return r; 419 return r;
420} 420}
421 421
422/* Call apropriate ioctl handler function. */ 422/* Call apropriate ioctl handler function. */
423static int 423static int
424dm_ioctl_switch(u_long cmd) 424dm_ioctl_switch(u_long cmd)
425{ 425{
426 426
427 switch(cmd) { 427 switch(cmd) {
428 case NETBSD_DM_IOCTL: 428 case NETBSD_DM_IOCTL:
429 aprint_debug("dm NetBSD_DM_IOCTL called\n"); 429 aprint_debug("dm NetBSD_DM_IOCTL called\n");
430 break; 430 break;
431 default: 431 default:
432 aprint_debug("dm unknown ioctl called\n"); 432 aprint_debug("dm unknown ioctl called\n");
433 return ENOTTY; 433 return ENOTTY;
434 break; /* NOT REACHED */ 434 break; /* NOT REACHED */
435 } 435 }
436 436
437 return 0; 437 return 0;
438} 438}
439 439
440 /* 440 /*
441 * Check for disk specific ioctls. 441 * Check for disk specific ioctls.
442 */ 442 */
443 443
444static int 444static int
445disk_ioctl_switch(dev_t dev, u_long cmd, void *data) 445disk_ioctl_switch(dev_t dev, u_long cmd, void *data)
446{ 446{
447 dm_dev_t *dmv; 447 dm_dev_t *dmv;
448 448
449 /* disk ioctls make sense only on block devices */ 449 /* disk ioctls make sense only on block devices */
450 if (minor(dev) == 0) 450 if (minor(dev) == 0)
451 return ENOTTY; 451 return ENOTTY;
452 452
453 switch(cmd) { 453 switch(cmd) {
454 case DIOCGWEDGEINFO: 454 case DIOCGWEDGEINFO:
455 { 455 {
456 struct dkwedge_info *dkw = (void *) data; 456 struct dkwedge_info *dkw = (void *) data;
457 unsigned secsize; 457 unsigned secsize;
458 458
459 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL) 459 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL)
460 return ENODEV; 460 return ENODEV;
461 461
462 aprint_debug("DIOCGWEDGEINFO ioctl called\n"); 462 aprint_debug("DIOCGWEDGEINFO ioctl called\n");
463 463
464 strlcpy(dkw->dkw_devname, dmv->name, 16); 464 strlcpy(dkw->dkw_devname, dmv->name, 16);
465 strlcpy(dkw->dkw_wname, dmv->name, DM_NAME_LEN); 465 strlcpy(dkw->dkw_wname, dmv->name, DM_NAME_LEN);
466 strlcpy(dkw->dkw_parent, dmv->name, 16); 466 strlcpy(dkw->dkw_parent, dmv->name, 16);
467 467
468 dkw->dkw_offset = 0; 468 dkw->dkw_offset = 0;
469 dm_table_disksize(&dmv->table_head, &dkw->dkw_size, &secsize); 469 dm_table_disksize(&dmv->table_head, &dkw->dkw_size, &secsize);
470 strcpy(dkw->dkw_ptype, DKW_PTYPE_FFS); 470 strcpy(dkw->dkw_ptype, DKW_PTYPE_FFS);
471 471
472 dm_dev_unbusy(dmv); 472 dm_dev_unbusy(dmv);
473 break; 473 break;
474 } 474 }
475 475
476 case DIOCGDISKINFO: 476 case DIOCGDISKINFO:
477 { 477 {
478 struct plistref *pref = (struct plistref *) data; 478 struct plistref *pref = (struct plistref *) data;
479 479
480 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL) 480 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL)
481 return ENODEV; 481 return ENODEV;
482 482
483 if (dmv->diskp->dk_info == NULL) { 483 if (dmv->diskp->dk_info == NULL) {
484 dm_dev_unbusy(dmv); 484 dm_dev_unbusy(dmv);
485 return ENOTSUP; 485 return ENOTSUP;
486 } else 486 } else
487 prop_dictionary_copyout_ioctl(pref, cmd, 487 prop_dictionary_copyout_ioctl(pref, cmd,
488 dmv->diskp->dk_info); 488 dmv->diskp->dk_info);
489 489
490 dm_dev_unbusy(dmv); 490 dm_dev_unbusy(dmv);
491 break; 491 break;
492 } 492 }
493 493
494 case DIOCCACHESYNC: 494 case DIOCCACHESYNC:
495 { 495 {
496 dm_table_entry_t *table_en; 496 dm_table_entry_t *table_en;
497 dm_table_t *tbl; 497 dm_table_t *tbl;
498 498
499 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL) 499 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL)
500 return ENODEV; 500 return ENODEV;
501 501
502 /* Select active table */ 502 /* Select active table */
503 tbl = dm_table_get_entry(&dmv->table_head, DM_TABLE_ACTIVE); 503 tbl = dm_table_get_entry(&dmv->table_head, DM_TABLE_ACTIVE);
504 504
505 /* 505 /*
506 * Call sync target routine for all table entries. Target sync 506 * Call sync target routine for all table entries. Target sync
507 * routine basically call DIOCCACHESYNC on underlying devices. 507 * routine basically call DIOCCACHESYNC on underlying devices.
508 */ 508 */
509 SLIST_FOREACH(table_en, tbl, next) { 509 SLIST_FOREACH(table_en, tbl, next) {
510 (void)table_en->target->sync(table_en); 510 (void)table_en->target->sync(table_en);
511 } 511 }
512 dm_table_release(&dmv->table_head, DM_TABLE_ACTIVE); 512 dm_table_release(&dmv->table_head, DM_TABLE_ACTIVE);
513 dm_dev_unbusy(dmv); 513 dm_dev_unbusy(dmv);
514 break; 514 break;
515 } 515 }
516 516
517 case DIOCGSECTORSIZE: 517 case DIOCGSECTORSIZE:
518 { 518 {
519 u_int *valp = data; 519 u_int *valp = data;
520 uint64_t numsec; 520 uint64_t numsec;
521 unsigned int secsize; 521 unsigned int secsize;
522 522
523 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL) 523 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL)
524 return ENODEV; 524 return ENODEV;
525 525
526 aprint_debug("DIOCGSECTORSIZE ioctl called\n"); 526 aprint_debug("DIOCGSECTORSIZE ioctl called\n");
527 527
528 dm_table_disksize(&dmv->table_head, &numsec, &secsize); 528 dm_table_disksize(&dmv->table_head, &numsec, &secsize);
529 *valp = secsize; 529 *valp = secsize;
530 530
531 dm_dev_unbusy(dmv); 531 dm_dev_unbusy(dmv);
532 break; 532 break;
533 } 533 }
534 534
535 case DIOCGMEDIASIZE: 535 case DIOCGMEDIASIZE:
536 { 536 {
537 off_t *valp = data; 537 off_t *valp = data;
538 uint64_t numsec; 538 uint64_t numsec;
539 unsigned int secsize; 539 unsigned int secsize;
540 540
541 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL) 541 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL)
542 return ENODEV; 542 return ENODEV;
543 543
544 aprint_debug("DIOCGMEDIASIZE ioctl called\n"); 544 aprint_debug("DIOCGMEDIASIZE ioctl called\n");
545 545
546 dm_table_disksize(&dmv->table_head, &numsec, &secsize); 546 dm_table_disksize(&dmv->table_head, &numsec, &secsize);
547 *valp = numsec; 547 *valp = numsec;
548 548
549 dm_dev_unbusy(dmv); 549 dm_dev_unbusy(dmv);
550 break; 550 break;
551 } 551 }
552 552
553 default: 553 default:
554 aprint_debug("unknown disk_ioctl called\n"); 554 aprint_debug("unknown disk_ioctl called\n");
555 return ENOTTY; 555 return ENOTTY;
556 break; /* NOT REACHED */ 556 break; /* NOT REACHED */
557 } 557 }
558 558
559 return 0; 559 return 0;
560} 560}
561 561
562/* 562/*
563 * Do all IO operations on dm logical devices. 563 * Do all IO operations on dm logical devices.
564 */ 564 */
565static void 565static void
566dmstrategy(struct buf *bp) 566dmstrategy(struct buf *bp)
567{ 567{
568 dm_dev_t *dmv; 568 dm_dev_t *dmv;
569 dm_table_t *tbl; 569 dm_table_t *tbl;
570 dm_table_entry_t *table_en; 570 dm_table_entry_t *table_en;
571 struct buf *nestbuf; 571 struct buf *nestbuf;
572 572
573 uint64_t buf_start, buf_len, issued_len; 573 uint64_t buf_start, buf_len, issued_len;
574 uint64_t table_start, table_end; 574 uint64_t table_start, table_end;
575 uint64_t start, end; 575 uint64_t start, end;
576 576
577 buf_start = bp->b_blkno * DEV_BSIZE; 577 buf_start = bp->b_blkno * DEV_BSIZE;
578 buf_len = bp->b_bcount; 578 buf_len = bp->b_bcount;
579 579
580 tbl = NULL; 580 tbl = NULL;
581 581
582 table_end = 0; 582 table_end = 0;
583 issued_len = 0; 583 issued_len = 0;
584 584
585 if ((dmv = dm_dev_lookup(NULL, NULL, minor(bp->b_dev))) == NULL) { 585 if ((dmv = dm_dev_lookup(NULL, NULL, minor(bp->b_dev))) == NULL) {
586 bp->b_error = EIO; 586 bp->b_error = EIO;
587 bp->b_resid = bp->b_bcount; 587 bp->b_resid = bp->b_bcount;
588 biodone(bp); 588 biodone(bp);
589 return; 589 return;
590 } 590 }
591 591
592 if (bounds_check_with_mediasize(bp, DEV_BSIZE, 592 if (bounds_check_with_mediasize(bp, DEV_BSIZE,
593 dm_table_size(&dmv->table_head)) <= 0) { 593 dm_table_size(&dmv->table_head)) <= 0) {
594 dm_dev_unbusy(dmv); 594 dm_dev_unbusy(dmv);
595 bp->b_resid = bp->b_bcount; 595 bp->b_resid = bp->b_bcount;
596 biodone(bp); 596 biodone(bp);
597 return; 597 return;
598 } 598 }
599 599
600 /* 600 /*
601 * disk(9) is part of device structure and it can't be used without 601 * disk(9) is part of device structure and it can't be used without
602 * mutual exclusion, use diskp_mtx until it will be fixed. 602 * mutual exclusion, use diskp_mtx until it will be fixed.
603 */ 603 */
604 mutex_enter(&dmv->diskp_mtx); 604 mutex_enter(&dmv->diskp_mtx);
605 disk_busy(dmv->diskp); 605 disk_busy(dmv->diskp);
606 mutex_exit(&dmv->diskp_mtx); 606 mutex_exit(&dmv->diskp_mtx);
607 607
608 /* Select active table */ 608 /* Select active table */
609 tbl = dm_table_get_entry(&dmv->table_head, DM_TABLE_ACTIVE); 609 tbl = dm_table_get_entry(&dmv->table_head, DM_TABLE_ACTIVE);
610 610
611 /* Nested buffers count down to zero therefore I have 611 /* Nested buffers count down to zero therefore I have
612 to set bp->b_resid to maximal value. */ 612 to set bp->b_resid to maximal value. */
613 bp->b_resid = bp->b_bcount; 613 bp->b_resid = bp->b_bcount;
614 614
615 /* 615 /*
616 * Find out what tables I want to select. 616 * Find out what tables I want to select.
617 */ 617 */
618 SLIST_FOREACH(table_en, tbl, next) { 618 SLIST_FOREACH(table_en, tbl, next) {
619 /* I need need number of bytes not blocks. */ 619 /* I need number of bytes not blocks. */
620 table_start = table_en->start * DEV_BSIZE; 620 table_start = table_en->start * DEV_BSIZE;
621 /* 621 /*
622 * I have to sub 1 from table_en->length to prevent 622 * I have to sub 1 from table_en->length to prevent
623 * off by one error 623 * off by one error
624 */ 624 */
625 table_end = table_start + (table_en->length)* DEV_BSIZE; 625 table_end = table_start + table_en->length * DEV_BSIZE;
626 626
627 start = MAX(table_start, buf_start); 627 start = MAX(table_start, buf_start);
628 628
629 end = MIN(table_end, buf_start + buf_len); 629 end = MIN(table_end, buf_start + buf_len);
630 630
631 aprint_debug("----------------------------------------\n"); 631 aprint_debug("----------------------------------------\n");
632 aprint_debug("table_start %010" PRIu64", table_end %010" 632 aprint_debug("table_start %010" PRIu64", table_end %010"
633 PRIu64 "\n", table_start, table_end); 633 PRIu64 "\n", table_start, table_end);
634 aprint_debug("buf_start %010" PRIu64", buf_len %010" 634 aprint_debug("buf_start %010" PRIu64", buf_len %010"
635 PRIu64"\n", buf_start, buf_len); 635 PRIu64"\n", buf_start, buf_len);
636 aprint_debug("start-buf_start %010"PRIu64", end %010" 636 aprint_debug("start-buf_start %010"PRIu64", end %010"
637 PRIu64"\n", start - buf_start, end); 637 PRIu64"\n", start - buf_start, end);
638 aprint_debug("start %010" PRIu64" , end %010" 638 aprint_debug("start %010" PRIu64" , end %010"
639 PRIu64"\n", start, end); 639 PRIu64"\n", start, end);
640 aprint_debug("\n----------------------------------------\n"); 640 aprint_debug("\n----------------------------------------\n");
641 641
642 if (start < end) { 642 if (start < end) {
643 /* create nested buffer */ 643 /* create nested buffer */
644 nestbuf = getiobuf(NULL, true); 644 nestbuf = getiobuf(NULL, true);
645 645
646 nestiobuf_setup(bp, nestbuf, start - buf_start, 646 nestiobuf_setup(bp, nestbuf, start - buf_start,
647 (end - start)); 647 (end - start));
648 648
649 issued_len += end - start; 649 issued_len += end - start;
650 650
651 /* I need number of blocks. */ 651 /* I need number of blocks. */
652 nestbuf->b_blkno = (start - table_start) / DEV_BSIZE; 652 nestbuf->b_blkno = (start - table_start) / DEV_BSIZE;
653 653
654 table_en->target->strategy(table_en, nestbuf); 654 table_en->target->strategy(table_en, nestbuf);
655 } 655 }
656 } 656 }
657 657
658 if (issued_len < buf_len) 658 if (issued_len < buf_len)
659 nestiobuf_done(bp, buf_len - issued_len, EINVAL); 659 nestiobuf_done(bp, buf_len - issued_len, EINVAL);
660 660
661 mutex_enter(&dmv->diskp_mtx); 661 mutex_enter(&dmv->diskp_mtx);
662 disk_unbusy(dmv->diskp, buf_len, bp != NULL ? bp->b_flags & B_READ : 0); 662 disk_unbusy(dmv->diskp, buf_len, bp != NULL ? bp->b_flags & B_READ : 0);
663 mutex_exit(&dmv->diskp_mtx); 663 mutex_exit(&dmv->diskp_mtx);
664 664
665 dm_table_release(&dmv->table_head, DM_TABLE_ACTIVE); 665 dm_table_release(&dmv->table_head, DM_TABLE_ACTIVE);
666 dm_dev_unbusy(dmv); 666 dm_dev_unbusy(dmv);
667} 667}
668 668
669 669
670static int 670static int
671dmread(dev_t dev, struct uio *uio, int flag) 671dmread(dev_t dev, struct uio *uio, int flag)
672{ 672{
673 673
674 return (physio(dmstrategy, NULL, dev, B_READ, dmminphys, uio)); 674 return (physio(dmstrategy, NULL, dev, B_READ, dmminphys, uio));
675} 675}
676 676
677static int 677static int
678dmwrite(dev_t dev, struct uio *uio, int flag) 678dmwrite(dev_t dev, struct uio *uio, int flag)
679{ 679{
680 680
681 return (physio(dmstrategy, NULL, dev, B_WRITE, dmminphys, uio)); 681 return (physio(dmstrategy, NULL, dev, B_WRITE, dmminphys, uio));
682} 682}
683 683
684static int 684static int
685dmsize(dev_t dev) 685dmsize(dev_t dev)
686{ 686{
687 dm_dev_t *dmv; 687 dm_dev_t *dmv;
688 uint64_t size; 688 uint64_t size;
689 689
690 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL) 690 if ((dmv = dm_dev_lookup(NULL, NULL, minor(dev))) == NULL)
691 return -ENOENT; 691 return -ENOENT;
692 692
693 size = dm_table_size(&dmv->table_head); 693 size = dm_table_size(&dmv->table_head);
694 dm_dev_unbusy(dmv); 694 dm_dev_unbusy(dmv);
695 695
696 return size; 696 return size;
697} 697}
698 698
699static void 699static void
700dmminphys(struct buf *bp) 700dmminphys(struct buf *bp)
701{ 701{
702 702
703 bp->b_bcount = MIN(bp->b_bcount, MAXPHYS); 703 bp->b_bcount = MIN(bp->b_bcount, MAXPHYS);
704} 704}
705 705
706void 706void
707dmgetproperties(struct disk *disk, dm_table_head_t *head) 707dmgetproperties(struct disk *disk, dm_table_head_t *head)
708{ 708{
709 uint64_t numsec; 709 uint64_t numsec;
710 unsigned secsize; 710 unsigned secsize;
711 711
712 dm_table_disksize(head, &numsec, &secsize); 712 dm_table_disksize(head, &numsec, &secsize);
713 713
714 struct disk_geom *dg = &disk->dk_geom; 714 struct disk_geom *dg = &disk->dk_geom;
715 715
716 memset(dg, 0, sizeof(*dg)); 716 memset(dg, 0, sizeof(*dg));
717 dg->dg_secperunit = numsec; 717 dg->dg_secperunit = numsec;
718 dg->dg_secsize = secsize; 718 dg->dg_secsize = secsize;
719 dg->dg_nsectors = 32; 719 dg->dg_nsectors = 32;
720 dg->dg_ntracks = 64; 720 dg->dg_ntracks = 64;
721 721
722 disk_set_info(NULL, disk, "ESDI"); 722 disk_set_info(NULL, disk, "ESDI");
723} 723}

cvs diff -r1.14 -r1.15 src/sys/dev/dm/dm_pdev.c (switch to unified diff)

--- src/sys/dev/dm/dm_pdev.c 2019/12/04 15:31:12 1.14
+++ src/sys/dev/dm/dm_pdev.c 2019/12/04 16:55:30 1.15
@@ -1,254 +1,254 @@ @@ -1,254 +1,254 @@
1/* $NetBSD: dm_pdev.c,v 1.14 2019/12/04 15:31:12 tkusumi Exp $ */ 1/* $NetBSD: dm_pdev.c,v 1.15 2019/12/04 16:55:30 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_pdev.c,v 1.14 2019/12/04 15:31:12 tkusumi Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: dm_pdev.c,v 1.15 2019/12/04 16:55:30 tkusumi Exp $");
33 33
34#include <sys/types.h> 34#include <sys/types.h>
35#include <sys/param.h> 35#include <sys/param.h>
36 36
37#include <sys/disk.h> 37#include <sys/disk.h>
38#include <sys/fcntl.h> 38#include <sys/fcntl.h>
39#include <sys/kmem.h> 39#include <sys/kmem.h>
40#include <sys/namei.h> 40#include <sys/namei.h>
41 41
42#include <dev/dkvar.h> 42#include <dev/dkvar.h>
43 43
44#include "dm.h" 44#include "dm.h"
45 45
46SLIST_HEAD(dm_pdevs, dm_pdev) dm_pdev_list; 46static SLIST_HEAD(dm_pdevs, dm_pdev) dm_pdev_list;
47 47
48static kmutex_t dm_pdev_mutex; 48static kmutex_t dm_pdev_mutex;
49 49
50static dm_pdev_t *dm_pdev_alloc(const char *); 50static dm_pdev_t *dm_pdev_alloc(const char *);
51static int dm_pdev_rem(dm_pdev_t *); 51static int dm_pdev_rem(dm_pdev_t *);
52static dm_pdev_t *dm_pdev_lookup_name(const char *); 52static dm_pdev_t *dm_pdev_lookup_name(const char *);
53 53
54/* 54/*
55* Find used pdev with name == dm_pdev_name. 55* Find used pdev with name == dm_pdev_name.
56*/ 56*/
57dm_pdev_t * 57dm_pdev_t *
58dm_pdev_lookup_name(const char *dm_pdev_name) 58dm_pdev_lookup_name(const char *dm_pdev_name)
59{ 59{
60 dm_pdev_t *dm_pdev; 60 dm_pdev_t *dm_pdev;
61 size_t dlen; 61 size_t dlen;
62 size_t slen; 62 size_t slen;
63 63
64 KASSERT(dm_pdev_name != NULL); 64 KASSERT(dm_pdev_name != NULL);
65 65
66 slen = strlen(dm_pdev_name); 66 slen = strlen(dm_pdev_name);
67 67
68 SLIST_FOREACH(dm_pdev, &dm_pdev_list, next_pdev) { 68 SLIST_FOREACH(dm_pdev, &dm_pdev_list, next_pdev) {
69 dlen = strlen(dm_pdev->name); 69 dlen = strlen(dm_pdev->name);
70 70
71 if (slen != dlen) 71 if (slen != dlen)
72 continue; 72 continue;
73 73
74 if (strncmp(dm_pdev_name, dm_pdev->name, slen) == 0) 74 if (strncmp(dm_pdev_name, dm_pdev->name, slen) == 0)
75 return dm_pdev; 75 return dm_pdev;
76 } 76 }
77 77
78 return NULL; 78 return NULL;
79} 79}
80 80
81/* 81/*
82 * Create entry for device with name dev_name and open vnode for it. 82 * Create entry for device with name dev_name and open vnode for it.
83 * If entry already exists in global SLIST I will only increment 83 * If entry already exists in global SLIST I will only increment
84 * reference counter. 84 * reference counter.
85 */ 85 */
86dm_pdev_t * 86dm_pdev_t *
87dm_pdev_insert(const char *dev_name) 87dm_pdev_insert(const char *dev_name)
88{ 88{
89 struct pathbuf *dev_pb; 89 struct pathbuf *dev_pb;
90 dm_pdev_t *dmp; 90 dm_pdev_t *dmp;
91 int error; 91 int error;
92 92
93 KASSERT(dev_name != NULL); 93 KASSERT(dev_name != NULL);
94 94
95 mutex_enter(&dm_pdev_mutex); 95 mutex_enter(&dm_pdev_mutex);
96 dmp = dm_pdev_lookup_name(dev_name); 96 dmp = dm_pdev_lookup_name(dev_name);
97 97
98 if (dmp != NULL) { 98 if (dmp != NULL) {
99 dmp->ref_cnt++; 99 dmp->ref_cnt++;
100 aprint_debug("%s: pdev %s already in tree\n", 100 aprint_debug("%s: pdev %s already in tree\n",
101 __func__, dev_name); 101 __func__, dev_name);
102 mutex_exit(&dm_pdev_mutex); 102 mutex_exit(&dm_pdev_mutex);
103 return dmp; 103 return dmp;
104 } 104 }
105 105
106 if ((dmp = dm_pdev_alloc(dev_name)) == NULL) { 106 if ((dmp = dm_pdev_alloc(dev_name)) == NULL) {
107 mutex_exit(&dm_pdev_mutex); 107 mutex_exit(&dm_pdev_mutex);
108 return NULL; 108 return NULL;
109 } 109 }
110 110
111 dev_pb = pathbuf_create(dev_name); 111 dev_pb = pathbuf_create(dev_name);
112 if (dev_pb == NULL) { 112 if (dev_pb == NULL) {
113 aprint_debug("%s: pathbuf_create on device: %s failed!\n", 113 aprint_debug("%s: pathbuf_create on device: %s failed!\n",
114 __func__, dev_name); 114 __func__, dev_name);
115 mutex_exit(&dm_pdev_mutex); 115 mutex_exit(&dm_pdev_mutex);
116 kmem_free(dmp, sizeof(dm_pdev_t)); 116 kmem_free(dmp, sizeof(dm_pdev_t));
117 return NULL; 117 return NULL;
118 } 118 }
119 error = dk_lookup(dev_pb, curlwp, &dmp->pdev_vnode); 119 error = dk_lookup(dev_pb, curlwp, &dmp->pdev_vnode);
120 pathbuf_destroy(dev_pb); 120 pathbuf_destroy(dev_pb);
121 if (error) { 121 if (error) {
122 aprint_debug("%s: dk_lookup on device: %s (error %d)\n", 122 aprint_debug("%s: dk_lookup on device: %s (error %d)\n",
123 __func__, dev_name, error); 123 __func__, dev_name, error);
124 mutex_exit(&dm_pdev_mutex); 124 mutex_exit(&dm_pdev_mutex);
125 kmem_free(dmp, sizeof(dm_pdev_t)); 125 kmem_free(dmp, sizeof(dm_pdev_t));
126 return NULL; 126 return NULL;
127 } 127 }
128 getdisksize(dmp->pdev_vnode, &dmp->pdev_numsec, &dmp->pdev_secsize); 128 getdisksize(dmp->pdev_vnode, &dmp->pdev_numsec, &dmp->pdev_secsize);
129 dmp->ref_cnt = 1; 129 dmp->ref_cnt = 1;
130 130
131 SLIST_INSERT_HEAD(&dm_pdev_list, dmp, next_pdev); 131 SLIST_INSERT_HEAD(&dm_pdev_list, dmp, next_pdev);
132 mutex_exit(&dm_pdev_mutex); 132 mutex_exit(&dm_pdev_mutex);
133 133
134 return dmp; 134 return dmp;
135} 135}
136 136
137/* 137/*
138 * Initialize pdev subsystem. 138 * Initialize pdev subsystem.
139 */ 139 */
140int 140int
141dm_pdev_init(void) 141dm_pdev_init(void)
142{ 142{
143 SLIST_INIT(&dm_pdev_list); /* initialize global pdev list */ 143 SLIST_INIT(&dm_pdev_list); /* initialize global pdev list */
144 mutex_init(&dm_pdev_mutex, MUTEX_DEFAULT, IPL_NONE); 144 mutex_init(&dm_pdev_mutex, MUTEX_DEFAULT, IPL_NONE);
145 145
146 return 0; 146 return 0;
147} 147}
148 148
149/* 149/*
150 * Allocat new pdev structure if is not already present and 150 * Allocat new pdev structure if is not already present and
151 * set name. 151 * set name.
152 */ 152 */
153static dm_pdev_t * 153static dm_pdev_t *
154dm_pdev_alloc(const char *name) 154dm_pdev_alloc(const char *name)
155{ 155{
156 dm_pdev_t *dmp; 156 dm_pdev_t *dmp;
157 157
158 dmp = kmem_zalloc(sizeof(*dmp), KM_SLEEP); 158 dmp = kmem_zalloc(sizeof(*dmp), KM_SLEEP);
159 strlcpy(dmp->name, name, sizeof(dmp->name)); 159 strlcpy(dmp->name, name, sizeof(dmp->name));
160 dmp->ref_cnt = 0; 160 dmp->ref_cnt = 0;
161 dmp->pdev_vnode = NULL; 161 dmp->pdev_vnode = NULL;
162 162
163 return dmp; 163 return dmp;
164} 164}
165 165
166/* 166/*
167 * Destroy allocated dm_pdev. 167 * Destroy allocated dm_pdev.
168 */ 168 */
169static int 169static int
170dm_pdev_rem(dm_pdev_t * dmp) 170dm_pdev_rem(dm_pdev_t * dmp)
171{ 171{
172 172
173 KASSERT(dmp != NULL); 173 KASSERT(dmp != NULL);
174 174
175 if (dmp->pdev_vnode != NULL) { 175 if (dmp->pdev_vnode != NULL) {
176 int error = vn_close(dmp->pdev_vnode, FREAD | FWRITE, FSCRED); 176 int error = vn_close(dmp->pdev_vnode, FREAD | FWRITE, FSCRED);
177 if (error != 0) 177 if (error != 0)
178 return error; 178 return error;
179 } 179 }
180 kmem_free(dmp, sizeof(*dmp)); 180 kmem_free(dmp, sizeof(*dmp));
181 181
182 return 0; 182 return 0;
183} 183}
184 184
185/* 185/*
186 * Destroy all existing pdev's in device-mapper. 186 * Destroy all existing pdev's in device-mapper.
187 */ 187 */
188int 188int
189dm_pdev_destroy(void) 189dm_pdev_destroy(void)
190{ 190{
191 dm_pdev_t *dm_pdev; 191 dm_pdev_t *dm_pdev;
192 192
193 mutex_enter(&dm_pdev_mutex); 193 mutex_enter(&dm_pdev_mutex);
194 while (!SLIST_EMPTY(&dm_pdev_list)) { /* List Deletion. */ 194 while (!SLIST_EMPTY(&dm_pdev_list)) { /* List Deletion. */
195 dm_pdev = SLIST_FIRST(&dm_pdev_list); 195 dm_pdev = SLIST_FIRST(&dm_pdev_list);
196 196
197 SLIST_REMOVE_HEAD(&dm_pdev_list, next_pdev); 197 SLIST_REMOVE_HEAD(&dm_pdev_list, next_pdev);
198 198
199 dm_pdev_rem(dm_pdev); 199 dm_pdev_rem(dm_pdev);
200 } 200 }
201 mutex_exit(&dm_pdev_mutex); 201 mutex_exit(&dm_pdev_mutex);
202 202
203 mutex_destroy(&dm_pdev_mutex); 203 mutex_destroy(&dm_pdev_mutex);
204 return 0; 204 return 0;
205} 205}
206 206
207/* 207/*
208 * This funcion is called from dm_dev_remove_ioctl. 208 * This funcion is called from dm_dev_remove_ioctl.
209 * When I'm removing device from list, I have to decrement 209 * When I'm removing device from list, I have to decrement
210 * reference counter. If reference counter is 0 I will remove 210 * reference counter. If reference counter is 0 I will remove
211 * dmp from global list and from device list to. And I will CLOSE 211 * dmp from global list and from device list to. And I will CLOSE
212 * dmp vnode too. 212 * dmp vnode too.
213 */ 213 */
214 214
215/* 215/*
216 * Decrement pdev reference counter if 0 remove it. 216 * Decrement pdev reference counter if 0 remove it.
217 */ 217 */
218int 218int
219dm_pdev_decr(dm_pdev_t * dmp) 219dm_pdev_decr(dm_pdev_t * dmp)
220{ 220{
221 KASSERT(dmp != NULL); 221 KASSERT(dmp != NULL);
222 /* 222 /*
223 * If this was last reference remove dmp from 223 * If this was last reference remove dmp from
224 * global list also. 224 * global list also.
225 */ 225 */
226 mutex_enter(&dm_pdev_mutex); 226 mutex_enter(&dm_pdev_mutex);
227 227
228 if (--dmp->ref_cnt == 0) { 228 if (--dmp->ref_cnt == 0) {
229 SLIST_REMOVE(&dm_pdev_list, dmp, dm_pdev, next_pdev); 229 SLIST_REMOVE(&dm_pdev_list, dmp, dm_pdev, next_pdev);
230 mutex_exit(&dm_pdev_mutex); 230 mutex_exit(&dm_pdev_mutex);
231 dm_pdev_rem(dmp); 231 dm_pdev_rem(dmp);
232 return 0; 232 return 0;
233 } 233 }
234 mutex_exit(&dm_pdev_mutex); 234 mutex_exit(&dm_pdev_mutex);
235 return 0; 235 return 0;
236} 236}
237 237
238#if 0 238#if 0
239static int 239static int
240dm_pdev_dump_list(void) 240dm_pdev_dump_list(void)
241{ 241{
242 dm_pdev_t *dmp; 242 dm_pdev_t *dmp;
243  243
244 aprint_verbose("Dumping dm_pdev_list\n"); 244 aprint_verbose("Dumping dm_pdev_list\n");
245  245
246 SLIST_FOREACH(dmp, &dm_pdev_list, next_pdev) { 246 SLIST_FOREACH(dmp, &dm_pdev_list, next_pdev) {
247 aprint_verbose("dm_pdev_name %s ref_cnt %d list_rf_cnt %d\n", 247 aprint_verbose("dm_pdev_name %s ref_cnt %d list_rf_cnt %d\n",
248 dmp->name, dmp->ref_cnt, dmp->list_ref_cnt); 248 dmp->name, dmp->ref_cnt, dmp->list_ref_cnt);
249 } 249 }
250  250
251 return 0; 251 return 0;
252  252
253} 253}
254#endif 254#endif