Print this page
10570 Need workaround to EFI boot on AMI BIOS
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/zfs/zvol.c
+++ new/usr/src/uts/common/fs/zfs/zvol.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
20 20 */
21 21 /*
22 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 *
24 24 * Portions Copyright 2010 Robert Milkowski
25 25 *
26 26 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
27 27 * Copyright (c) 2012, 2017 by Delphix. All rights reserved.
28 28 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
29 29 * Copyright (c) 2014 Integros [integros.com]
30 + * Copyright (c) 2019, Joyent, Inc.
30 31 */
31 32
32 33 /*
33 34 * ZFS volume emulation driver.
34 35 *
35 36 * Makes a DMU object look like a volume of arbitrary size, up to 2^64 bytes.
36 37 * Volumes are accessed through the symbolic links named:
37 38 *
38 39 * /dev/zvol/dsk/<pool_name>/<dataset_name>
39 40 * /dev/zvol/rdsk/<pool_name>/<dataset_name>
40 41 *
41 42 * These links are created by the /dev filesystem (sdev_zvolops.c).
42 43 * Volumes are persistent through reboot. No user command needs to be
43 44 * run before opening and using a device.
44 45 */
45 46
46 47 #include <sys/types.h>
47 48 #include <sys/param.h>
48 49 #include <sys/errno.h>
49 50 #include <sys/uio.h>
50 51 #include <sys/buf.h>
51 52 #include <sys/modctl.h>
52 53 #include <sys/open.h>
53 54 #include <sys/kmem.h>
54 55 #include <sys/conf.h>
55 56 #include <sys/cmn_err.h>
56 57 #include <sys/stat.h>
57 58 #include <sys/zap.h>
58 59 #include <sys/spa.h>
59 60 #include <sys/spa_impl.h>
60 61 #include <sys/zio.h>
61 62 #include <sys/dmu_traverse.h>
62 63 #include <sys/dnode.h>
63 64 #include <sys/dsl_dataset.h>
64 65 #include <sys/dsl_prop.h>
65 66 #include <sys/dkio.h>
66 67 #include <sys/efi_partition.h>
67 68 #include <sys/byteorder.h>
68 69 #include <sys/pathname.h>
69 70 #include <sys/ddi.h>
70 71 #include <sys/sunddi.h>
71 72 #include <sys/crc32.h>
72 73 #include <sys/dirent.h>
73 74 #include <sys/policy.h>
74 75 #include <sys/fs/zfs.h>
75 76 #include <sys/zfs_ioctl.h>
76 77 #include <sys/mkdev.h>
77 78 #include <sys/zil.h>
78 79 #include <sys/refcount.h>
79 80 #include <sys/zfs_znode.h>
80 81 #include <sys/zfs_rlock.h>
81 82 #include <sys/vdev_disk.h>
82 83 #include <sys/vdev_impl.h>
83 84 #include <sys/vdev_raidz.h>
84 85 #include <sys/zvol.h>
85 86 #include <sys/dumphdr.h>
86 87 #include <sys/zil_impl.h>
87 88 #include <sys/dbuf.h>
88 89 #include <sys/dmu_tx.h>
89 90 #include <sys/zfeature.h>
90 91 #include <sys/zio_checksum.h>
91 92 #include <sys/zil_impl.h>
92 93 #include <sys/dkioc_free_util.h>
93 94 #include <sys/zfs_rlock.h>
94 95
95 96 #include "zfs_namecheck.h"
96 97
97 98 void *zfsdev_state;
98 99 static char *zvol_tag = "zvol_tag";
99 100
100 101 #define ZVOL_DUMPSIZE "dumpsize"
101 102
102 103 /*
103 104 * This lock protects the zfsdev_state structure from being modified
104 105 * while it's being used, e.g. an open that comes in before a create
105 106 * finishes. It also protects temporary opens of the dataset so that,
106 107 * e.g., an open doesn't get a spurious EBUSY.
107 108 */
108 109 kmutex_t zfsdev_state_lock;
109 110 static uint32_t zvol_minors;
110 111
111 112 typedef struct zvol_extent {
112 113 list_node_t ze_node;
113 114 dva_t ze_dva; /* dva associated with this extent */
114 115 uint64_t ze_nblks; /* number of blocks in extent */
115 116 } zvol_extent_t;
116 117
117 118 /*
118 119 * The in-core state of each volume.
119 120 */
120 121 typedef struct zvol_state {
121 122 char zv_name[MAXPATHLEN]; /* pool/dd name */
122 123 uint64_t zv_volsize; /* amount of space we advertise */
123 124 uint64_t zv_volblocksize; /* volume block size */
124 125 minor_t zv_minor; /* minor number */
125 126 uint8_t zv_min_bs; /* minimum addressable block shift */
126 127 uint8_t zv_flags; /* readonly, dumpified, etc. */
127 128 objset_t *zv_objset; /* objset handle */
128 129 uint32_t zv_open_count[OTYPCNT]; /* open counts */
129 130 uint32_t zv_total_opens; /* total open count */
130 131 zilog_t *zv_zilog; /* ZIL handle */
131 132 list_t zv_extents; /* List of extents for dump */
132 133 rangelock_t zv_rangelock;
133 134 dnode_t *zv_dn; /* dnode hold */
134 135 } zvol_state_t;
135 136
136 137 /*
137 138 * zvol specific flags
138 139 */
139 140 #define ZVOL_RDONLY 0x1
140 141 #define ZVOL_DUMPIFIED 0x2
141 142 #define ZVOL_EXCL 0x4
142 143 #define ZVOL_WCE 0x8
143 144
144 145 /*
145 146 * zvol maximum transfer in one DMU tx.
146 147 */
147 148 int zvol_maxphys = DMU_MAX_ACCESS/2;
148 149
149 150 /*
150 151 * Toggle unmap functionality.
151 152 */
152 153 boolean_t zvol_unmap_enabled = B_TRUE;
153 154
154 155 /*
155 156 * If true, unmaps requested as synchronous are executed synchronously,
156 157 * otherwise all unmaps are asynchronous.
157 158 */
158 159 boolean_t zvol_unmap_sync_enabled = B_FALSE;
159 160
160 161 extern int zfs_set_prop_nvlist(const char *, zprop_source_t,
161 162 nvlist_t *, nvlist_t *);
162 163 static int zvol_remove_zv(zvol_state_t *);
163 164 static int zvol_get_data(void *arg, lr_write_t *lr, char *buf,
164 165 struct lwb *lwb, zio_t *zio);
165 166 static int zvol_dumpify(zvol_state_t *zv);
166 167 static int zvol_dump_fini(zvol_state_t *zv);
167 168 static int zvol_dump_init(zvol_state_t *zv, boolean_t resize);
168 169
169 170 static void
170 171 zvol_size_changed(zvol_state_t *zv, uint64_t volsize)
171 172 {
172 173 dev_t dev = makedevice(ddi_driver_major(zfs_dip), zv->zv_minor);
173 174
174 175 zv->zv_volsize = volsize;
175 176 VERIFY(ddi_prop_update_int64(dev, zfs_dip,
176 177 "Size", volsize) == DDI_SUCCESS);
177 178 VERIFY(ddi_prop_update_int64(dev, zfs_dip,
178 179 "Nblocks", lbtodb(volsize)) == DDI_SUCCESS);
179 180
180 181 /* Notify specfs to invalidate the cached size */
181 182 spec_size_invalidate(dev, VBLK);
182 183 spec_size_invalidate(dev, VCHR);
183 184 }
184 185
185 186 int
186 187 zvol_check_volsize(uint64_t volsize, uint64_t blocksize)
187 188 {
188 189 if (volsize == 0)
189 190 return (SET_ERROR(EINVAL));
190 191
191 192 if (volsize % blocksize != 0)
192 193 return (SET_ERROR(EINVAL));
193 194
194 195 #ifdef _ILP32
195 196 if (volsize - 1 > SPEC_MAXOFFSET_T)
196 197 return (SET_ERROR(EOVERFLOW));
197 198 #endif
198 199 return (0);
199 200 }
200 201
201 202 int
202 203 zvol_check_volblocksize(uint64_t volblocksize)
203 204 {
204 205 if (volblocksize < SPA_MINBLOCKSIZE ||
205 206 volblocksize > SPA_OLD_MAXBLOCKSIZE ||
206 207 !ISP2(volblocksize))
207 208 return (SET_ERROR(EDOM));
208 209
209 210 return (0);
210 211 }
211 212
212 213 int
213 214 zvol_get_stats(objset_t *os, nvlist_t *nv)
214 215 {
215 216 int error;
216 217 dmu_object_info_t doi;
217 218 uint64_t val;
218 219
219 220 error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &val);
220 221 if (error)
221 222 return (error);
222 223
223 224 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLSIZE, val);
224 225
225 226 error = dmu_object_info(os, ZVOL_OBJ, &doi);
226 227
227 228 if (error == 0) {
228 229 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLBLOCKSIZE,
229 230 doi.doi_data_block_size);
230 231 }
231 232
232 233 return (error);
233 234 }
234 235
235 236 static zvol_state_t *
236 237 zvol_minor_lookup(const char *name)
237 238 {
238 239 minor_t minor;
239 240 zvol_state_t *zv;
240 241
241 242 ASSERT(MUTEX_HELD(&zfsdev_state_lock));
242 243
243 244 for (minor = 1; minor <= ZFSDEV_MAX_MINOR; minor++) {
244 245 zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
245 246 if (zv == NULL)
246 247 continue;
247 248 if (strcmp(zv->zv_name, name) == 0)
248 249 return (zv);
249 250 }
250 251
251 252 return (NULL);
252 253 }
253 254
254 255 /* extent mapping arg */
255 256 struct maparg {
256 257 zvol_state_t *ma_zv;
257 258 uint64_t ma_blks;
258 259 };
259 260
260 261 /*ARGSUSED*/
261 262 static int
262 263 zvol_map_block(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
263 264 const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
264 265 {
265 266 struct maparg *ma = arg;
266 267 zvol_extent_t *ze;
267 268 int bs = ma->ma_zv->zv_volblocksize;
268 269
269 270 if (bp == NULL || BP_IS_HOLE(bp) ||
270 271 zb->zb_object != ZVOL_OBJ || zb->zb_level != 0)
271 272 return (0);
272 273
273 274 VERIFY(!BP_IS_EMBEDDED(bp));
274 275
275 276 VERIFY3U(ma->ma_blks, ==, zb->zb_blkid);
276 277 ma->ma_blks++;
277 278
278 279 /* Abort immediately if we have encountered gang blocks */
279 280 if (BP_IS_GANG(bp))
280 281 return (SET_ERROR(EFRAGS));
281 282
282 283 /*
283 284 * See if the block is at the end of the previous extent.
284 285 */
285 286 ze = list_tail(&ma->ma_zv->zv_extents);
286 287 if (ze &&
287 288 DVA_GET_VDEV(BP_IDENTITY(bp)) == DVA_GET_VDEV(&ze->ze_dva) &&
288 289 DVA_GET_OFFSET(BP_IDENTITY(bp)) ==
289 290 DVA_GET_OFFSET(&ze->ze_dva) + ze->ze_nblks * bs) {
290 291 ze->ze_nblks++;
291 292 return (0);
292 293 }
293 294
294 295 dprintf_bp(bp, "%s", "next blkptr:");
295 296
296 297 /* start a new extent */
297 298 ze = kmem_zalloc(sizeof (zvol_extent_t), KM_SLEEP);
298 299 ze->ze_dva = bp->blk_dva[0]; /* structure assignment */
299 300 ze->ze_nblks = 1;
300 301 list_insert_tail(&ma->ma_zv->zv_extents, ze);
301 302 return (0);
302 303 }
303 304
304 305 static void
305 306 zvol_free_extents(zvol_state_t *zv)
306 307 {
307 308 zvol_extent_t *ze;
308 309
309 310 while (ze = list_head(&zv->zv_extents)) {
310 311 list_remove(&zv->zv_extents, ze);
311 312 kmem_free(ze, sizeof (zvol_extent_t));
312 313 }
313 314 }
314 315
315 316 static int
316 317 zvol_get_lbas(zvol_state_t *zv)
317 318 {
318 319 objset_t *os = zv->zv_objset;
319 320 struct maparg ma;
320 321 int err;
321 322
322 323 ma.ma_zv = zv;
323 324 ma.ma_blks = 0;
324 325 zvol_free_extents(zv);
325 326
326 327 /* commit any in-flight changes before traversing the dataset */
327 328 txg_wait_synced(dmu_objset_pool(os), 0);
328 329 err = traverse_dataset(dmu_objset_ds(os), 0,
329 330 TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA, zvol_map_block, &ma);
330 331 if (err || ma.ma_blks != (zv->zv_volsize / zv->zv_volblocksize)) {
331 332 zvol_free_extents(zv);
332 333 return (err ? err : EIO);
333 334 }
334 335
335 336 return (0);
336 337 }
337 338
338 339 /* ARGSUSED */
339 340 void
340 341 zvol_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx)
341 342 {
342 343 zfs_creat_t *zct = arg;
343 344 nvlist_t *nvprops = zct->zct_props;
344 345 int error;
345 346 uint64_t volblocksize, volsize;
346 347
347 348 VERIFY(nvlist_lookup_uint64(nvprops,
348 349 zfs_prop_to_name(ZFS_PROP_VOLSIZE), &volsize) == 0);
349 350 if (nvlist_lookup_uint64(nvprops,
350 351 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), &volblocksize) != 0)
351 352 volblocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
352 353
353 354 /*
354 355 * These properties must be removed from the list so the generic
355 356 * property setting step won't apply to them.
356 357 */
357 358 VERIFY(nvlist_remove_all(nvprops,
358 359 zfs_prop_to_name(ZFS_PROP_VOLSIZE)) == 0);
359 360 (void) nvlist_remove_all(nvprops,
360 361 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE));
361 362
362 363 error = dmu_object_claim(os, ZVOL_OBJ, DMU_OT_ZVOL, volblocksize,
363 364 DMU_OT_NONE, 0, tx);
364 365 ASSERT(error == 0);
365 366
366 367 error = zap_create_claim(os, ZVOL_ZAP_OBJ, DMU_OT_ZVOL_PROP,
367 368 DMU_OT_NONE, 0, tx);
368 369 ASSERT(error == 0);
369 370
370 371 error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize, tx);
371 372 ASSERT(error == 0);
372 373 }
373 374
374 375 /*
375 376 * Replay a TX_TRUNCATE ZIL transaction if asked. TX_TRUNCATE is how we
376 377 * implement DKIOCFREE/free-long-range.
377 378 */
378 379 static int
379 380 zvol_replay_truncate(void *arg1, void *arg2, boolean_t byteswap)
380 381 {
381 382 zvol_state_t *zv = arg1;
382 383 lr_truncate_t *lr = arg2;
383 384 uint64_t offset, length;
384 385
385 386 if (byteswap)
386 387 byteswap_uint64_array(lr, sizeof (*lr));
387 388
388 389 offset = lr->lr_offset;
389 390 length = lr->lr_length;
390 391
391 392 return (dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset, length));
392 393 }
393 394
394 395 /*
395 396 * Replay a TX_WRITE ZIL transaction that didn't get committed
396 397 * after a system failure
397 398 */
398 399 static int
399 400 zvol_replay_write(void *arg1, void *arg2, boolean_t byteswap)
400 401 {
401 402 zvol_state_t *zv = arg1;
402 403 lr_write_t *lr = arg2;
403 404 objset_t *os = zv->zv_objset;
404 405 char *data = (char *)(lr + 1); /* data follows lr_write_t */
405 406 uint64_t offset, length;
406 407 dmu_tx_t *tx;
407 408 int error;
408 409
409 410 if (byteswap)
410 411 byteswap_uint64_array(lr, sizeof (*lr));
411 412
412 413 offset = lr->lr_offset;
413 414 length = lr->lr_length;
414 415
415 416 /* If it's a dmu_sync() block, write the whole block */
416 417 if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
417 418 uint64_t blocksize = BP_GET_LSIZE(&lr->lr_blkptr);
418 419 if (length < blocksize) {
419 420 offset -= offset % blocksize;
420 421 length = blocksize;
421 422 }
422 423 }
423 424
424 425 tx = dmu_tx_create(os);
425 426 dmu_tx_hold_write(tx, ZVOL_OBJ, offset, length);
426 427 error = dmu_tx_assign(tx, TXG_WAIT);
427 428 if (error) {
428 429 dmu_tx_abort(tx);
429 430 } else {
430 431 dmu_write(os, ZVOL_OBJ, offset, length, data, tx);
431 432 dmu_tx_commit(tx);
432 433 }
433 434
434 435 return (error);
435 436 }
436 437
437 438 /* ARGSUSED */
438 439 static int
439 440 zvol_replay_err(void *arg1, void *arg2, boolean_t byteswap)
440 441 {
441 442 return (SET_ERROR(ENOTSUP));
442 443 }
443 444
444 445 /*
445 446 * Callback vectors for replaying records.
446 447 * Only TX_WRITE and TX_TRUNCATE are needed for zvol.
447 448 */
448 449 zil_replay_func_t *zvol_replay_vector[TX_MAX_TYPE] = {
449 450 zvol_replay_err, /* 0 no such transaction type */
450 451 zvol_replay_err, /* TX_CREATE */
451 452 zvol_replay_err, /* TX_MKDIR */
452 453 zvol_replay_err, /* TX_MKXATTR */
453 454 zvol_replay_err, /* TX_SYMLINK */
454 455 zvol_replay_err, /* TX_REMOVE */
455 456 zvol_replay_err, /* TX_RMDIR */
456 457 zvol_replay_err, /* TX_LINK */
457 458 zvol_replay_err, /* TX_RENAME */
458 459 zvol_replay_write, /* TX_WRITE */
459 460 zvol_replay_truncate, /* TX_TRUNCATE */
460 461 zvol_replay_err, /* TX_SETATTR */
461 462 zvol_replay_err, /* TX_ACL */
462 463 zvol_replay_err, /* TX_CREATE_ACL */
463 464 zvol_replay_err, /* TX_CREATE_ATTR */
464 465 zvol_replay_err, /* TX_CREATE_ACL_ATTR */
465 466 zvol_replay_err, /* TX_MKDIR_ACL */
466 467 zvol_replay_err, /* TX_MKDIR_ATTR */
467 468 zvol_replay_err, /* TX_MKDIR_ACL_ATTR */
468 469 zvol_replay_err, /* TX_WRITE2 */
469 470 };
470 471
471 472 int
472 473 zvol_name2minor(const char *name, minor_t *minor)
473 474 {
474 475 zvol_state_t *zv;
475 476
476 477 mutex_enter(&zfsdev_state_lock);
477 478 zv = zvol_minor_lookup(name);
478 479 if (minor && zv)
479 480 *minor = zv->zv_minor;
480 481 mutex_exit(&zfsdev_state_lock);
481 482 return (zv ? 0 : -1);
482 483 }
483 484
484 485 /*
485 486 * Create a minor node (plus a whole lot more) for the specified volume.
486 487 */
487 488 int
488 489 zvol_create_minor(const char *name)
489 490 {
490 491 zfs_soft_state_t *zs;
491 492 zvol_state_t *zv;
492 493 objset_t *os;
493 494 dmu_object_info_t doi;
494 495 minor_t minor = 0;
495 496 char chrbuf[30], blkbuf[30];
496 497 int error;
497 498
498 499 mutex_enter(&zfsdev_state_lock);
499 500
500 501 if (zvol_minor_lookup(name) != NULL) {
501 502 mutex_exit(&zfsdev_state_lock);
502 503 return (SET_ERROR(EEXIST));
503 504 }
504 505
505 506 /* lie and say we're read-only */
506 507 error = dmu_objset_own(name, DMU_OST_ZVOL, B_TRUE, FTAG, &os);
507 508
508 509 if (error) {
509 510 mutex_exit(&zfsdev_state_lock);
510 511 return (error);
511 512 }
512 513
513 514 if ((minor = zfsdev_minor_alloc()) == 0) {
514 515 dmu_objset_disown(os, FTAG);
515 516 mutex_exit(&zfsdev_state_lock);
516 517 return (SET_ERROR(ENXIO));
517 518 }
518 519
519 520 if (ddi_soft_state_zalloc(zfsdev_state, minor) != DDI_SUCCESS) {
520 521 dmu_objset_disown(os, FTAG);
521 522 mutex_exit(&zfsdev_state_lock);
522 523 return (SET_ERROR(EAGAIN));
523 524 }
524 525 (void) ddi_prop_update_string(minor, zfs_dip, ZVOL_PROP_NAME,
525 526 (char *)name);
526 527
527 528 (void) snprintf(chrbuf, sizeof (chrbuf), "%u,raw", minor);
528 529
529 530 if (ddi_create_minor_node(zfs_dip, chrbuf, S_IFCHR,
530 531 minor, DDI_PSEUDO, 0) == DDI_FAILURE) {
531 532 ddi_soft_state_free(zfsdev_state, minor);
532 533 dmu_objset_disown(os, FTAG);
533 534 mutex_exit(&zfsdev_state_lock);
534 535 return (SET_ERROR(EAGAIN));
535 536 }
536 537
537 538 (void) snprintf(blkbuf, sizeof (blkbuf), "%u", minor);
538 539
539 540 if (ddi_create_minor_node(zfs_dip, blkbuf, S_IFBLK,
540 541 minor, DDI_PSEUDO, 0) == DDI_FAILURE) {
541 542 ddi_remove_minor_node(zfs_dip, chrbuf);
542 543 ddi_soft_state_free(zfsdev_state, minor);
543 544 dmu_objset_disown(os, FTAG);
544 545 mutex_exit(&zfsdev_state_lock);
545 546 return (SET_ERROR(EAGAIN));
546 547 }
547 548
548 549 zs = ddi_get_soft_state(zfsdev_state, minor);
549 550 zs->zss_type = ZSST_ZVOL;
550 551 zv = zs->zss_data = kmem_zalloc(sizeof (zvol_state_t), KM_SLEEP);
551 552 (void) strlcpy(zv->zv_name, name, MAXPATHLEN);
552 553 zv->zv_min_bs = DEV_BSHIFT;
553 554 zv->zv_minor = minor;
554 555 zv->zv_objset = os;
555 556 if (dmu_objset_is_snapshot(os) || !spa_writeable(dmu_objset_spa(os)))
556 557 zv->zv_flags |= ZVOL_RDONLY;
557 558 rangelock_init(&zv->zv_rangelock, NULL, NULL);
558 559 list_create(&zv->zv_extents, sizeof (zvol_extent_t),
559 560 offsetof(zvol_extent_t, ze_node));
560 561 /* get and cache the blocksize */
561 562 error = dmu_object_info(os, ZVOL_OBJ, &doi);
562 563 ASSERT(error == 0);
563 564 zv->zv_volblocksize = doi.doi_data_block_size;
564 565
565 566 if (spa_writeable(dmu_objset_spa(os))) {
566 567 if (zil_replay_disable)
567 568 zil_destroy(dmu_objset_zil(os), B_FALSE);
568 569 else
569 570 zil_replay(os, zv, zvol_replay_vector);
570 571 }
571 572 dmu_objset_disown(os, FTAG);
572 573 zv->zv_objset = NULL;
573 574
574 575 zvol_minors++;
575 576
576 577 mutex_exit(&zfsdev_state_lock);
577 578
578 579 return (0);
579 580 }
580 581
581 582 /*
582 583 * Remove minor node for the specified volume.
583 584 */
584 585 static int
585 586 zvol_remove_zv(zvol_state_t *zv)
586 587 {
587 588 char nmbuf[20];
588 589 minor_t minor = zv->zv_minor;
589 590
590 591 ASSERT(MUTEX_HELD(&zfsdev_state_lock));
591 592 if (zv->zv_total_opens != 0)
592 593 return (SET_ERROR(EBUSY));
593 594
594 595 (void) snprintf(nmbuf, sizeof (nmbuf), "%u,raw", minor);
595 596 ddi_remove_minor_node(zfs_dip, nmbuf);
596 597
597 598 (void) snprintf(nmbuf, sizeof (nmbuf), "%u", minor);
598 599 ddi_remove_minor_node(zfs_dip, nmbuf);
599 600
600 601 rangelock_fini(&zv->zv_rangelock);
601 602
602 603 kmem_free(zv, sizeof (zvol_state_t));
603 604
604 605 ddi_soft_state_free(zfsdev_state, minor);
605 606
606 607 zvol_minors--;
607 608 return (0);
608 609 }
609 610
610 611 int
611 612 zvol_remove_minor(const char *name)
612 613 {
613 614 zvol_state_t *zv;
614 615 int rc;
615 616
616 617 mutex_enter(&zfsdev_state_lock);
617 618 if ((zv = zvol_minor_lookup(name)) == NULL) {
618 619 mutex_exit(&zfsdev_state_lock);
619 620 return (SET_ERROR(ENXIO));
620 621 }
621 622 rc = zvol_remove_zv(zv);
622 623 mutex_exit(&zfsdev_state_lock);
623 624 return (rc);
624 625 }
625 626
626 627 int
627 628 zvol_first_open(zvol_state_t *zv)
628 629 {
629 630 objset_t *os;
630 631 uint64_t volsize;
631 632 int error;
632 633 uint64_t readonly;
633 634
634 635 /* lie and say we're read-only */
635 636 error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, B_TRUE,
636 637 zvol_tag, &os);
637 638 if (error)
638 639 return (error);
639 640
640 641 zv->zv_objset = os;
641 642 error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
642 643 if (error) {
643 644 ASSERT(error == 0);
644 645 dmu_objset_disown(os, zvol_tag);
645 646 return (error);
646 647 }
647 648
648 649 error = dnode_hold(os, ZVOL_OBJ, zvol_tag, &zv->zv_dn);
649 650 if (error) {
650 651 dmu_objset_disown(os, zvol_tag);
651 652 return (error);
652 653 }
653 654
654 655 zvol_size_changed(zv, volsize);
655 656 zv->zv_zilog = zil_open(os, zvol_get_data);
656 657
657 658 VERIFY(dsl_prop_get_integer(zv->zv_name, "readonly", &readonly,
658 659 NULL) == 0);
659 660 if (readonly || dmu_objset_is_snapshot(os) ||
660 661 !spa_writeable(dmu_objset_spa(os)))
661 662 zv->zv_flags |= ZVOL_RDONLY;
662 663 else
663 664 zv->zv_flags &= ~ZVOL_RDONLY;
664 665 return (error);
665 666 }
666 667
667 668 void
668 669 zvol_last_close(zvol_state_t *zv)
669 670 {
670 671 zil_close(zv->zv_zilog);
671 672 zv->zv_zilog = NULL;
672 673
673 674 dnode_rele(zv->zv_dn, zvol_tag);
674 675 zv->zv_dn = NULL;
675 676
676 677 /*
677 678 * Evict cached data
678 679 */
679 680 if (dsl_dataset_is_dirty(dmu_objset_ds(zv->zv_objset)) &&
680 681 !(zv->zv_flags & ZVOL_RDONLY))
681 682 txg_wait_synced(dmu_objset_pool(zv->zv_objset), 0);
682 683 dmu_objset_evict_dbufs(zv->zv_objset);
683 684
684 685 dmu_objset_disown(zv->zv_objset, zvol_tag);
685 686 zv->zv_objset = NULL;
686 687 }
687 688
688 689 int
689 690 zvol_prealloc(zvol_state_t *zv)
690 691 {
691 692 objset_t *os = zv->zv_objset;
692 693 dmu_tx_t *tx;
693 694 uint64_t refd, avail, usedobjs, availobjs;
694 695 uint64_t resid = zv->zv_volsize;
695 696 uint64_t off = 0;
696 697
697 698 /* Check the space usage before attempting to allocate the space */
698 699 dmu_objset_space(os, &refd, &avail, &usedobjs, &availobjs);
699 700 if (avail < zv->zv_volsize)
700 701 return (SET_ERROR(ENOSPC));
701 702
702 703 /* Free old extents if they exist */
703 704 zvol_free_extents(zv);
704 705
705 706 while (resid != 0) {
706 707 int error;
707 708 uint64_t bytes = MIN(resid, SPA_OLD_MAXBLOCKSIZE);
708 709
709 710 tx = dmu_tx_create(os);
710 711 dmu_tx_hold_write(tx, ZVOL_OBJ, off, bytes);
711 712 error = dmu_tx_assign(tx, TXG_WAIT);
712 713 if (error) {
713 714 dmu_tx_abort(tx);
714 715 (void) dmu_free_long_range(os, ZVOL_OBJ, 0, off);
715 716 return (error);
716 717 }
717 718 dmu_prealloc(os, ZVOL_OBJ, off, bytes, tx);
718 719 dmu_tx_commit(tx);
719 720 off += bytes;
720 721 resid -= bytes;
721 722 }
722 723 txg_wait_synced(dmu_objset_pool(os), 0);
723 724
724 725 return (0);
725 726 }
726 727
727 728 static int
728 729 zvol_update_volsize(objset_t *os, uint64_t volsize)
729 730 {
730 731 dmu_tx_t *tx;
731 732 int error;
732 733
733 734 ASSERT(MUTEX_HELD(&zfsdev_state_lock));
734 735
735 736 tx = dmu_tx_create(os);
736 737 dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
737 738 dmu_tx_mark_netfree(tx);
738 739 error = dmu_tx_assign(tx, TXG_WAIT);
739 740 if (error) {
740 741 dmu_tx_abort(tx);
741 742 return (error);
742 743 }
743 744
744 745 error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1,
745 746 &volsize, tx);
746 747 dmu_tx_commit(tx);
747 748
748 749 if (error == 0)
749 750 error = dmu_free_long_range(os,
750 751 ZVOL_OBJ, volsize, DMU_OBJECT_END);
751 752 return (error);
752 753 }
753 754
754 755 void
755 756 zvol_remove_minors(const char *name)
756 757 {
757 758 zvol_state_t *zv;
758 759 char *namebuf;
759 760 minor_t minor;
760 761
761 762 namebuf = kmem_zalloc(strlen(name) + 2, KM_SLEEP);
762 763 (void) strncpy(namebuf, name, strlen(name));
763 764 (void) strcat(namebuf, "/");
764 765 mutex_enter(&zfsdev_state_lock);
765 766 for (minor = 1; minor <= ZFSDEV_MAX_MINOR; minor++) {
766 767
767 768 zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
768 769 if (zv == NULL)
769 770 continue;
770 771 if (strncmp(namebuf, zv->zv_name, strlen(namebuf)) == 0)
771 772 (void) zvol_remove_zv(zv);
772 773 }
773 774 kmem_free(namebuf, strlen(name) + 2);
774 775
775 776 mutex_exit(&zfsdev_state_lock);
776 777 }
777 778
778 779 static int
779 780 zvol_update_live_volsize(zvol_state_t *zv, uint64_t volsize)
780 781 {
781 782 uint64_t old_volsize = 0ULL;
782 783 int error = 0;
783 784
784 785 ASSERT(MUTEX_HELD(&zfsdev_state_lock));
785 786
786 787 /*
787 788 * Reinitialize the dump area to the new size. If we
788 789 * failed to resize the dump area then restore it back to
789 790 * its original size. We must set the new volsize prior
790 791 * to calling dumpvp_resize() to ensure that the devices'
791 792 * size(9P) is not visible by the dump subsystem.
792 793 */
793 794 old_volsize = zv->zv_volsize;
794 795 zvol_size_changed(zv, volsize);
795 796
796 797 if (zv->zv_flags & ZVOL_DUMPIFIED) {
797 798 if ((error = zvol_dumpify(zv)) != 0 ||
798 799 (error = dumpvp_resize()) != 0) {
799 800 int dumpify_error;
800 801
801 802 (void) zvol_update_volsize(zv->zv_objset, old_volsize);
802 803 zvol_size_changed(zv, old_volsize);
803 804 dumpify_error = zvol_dumpify(zv);
804 805 error = dumpify_error ? dumpify_error : error;
805 806 }
806 807 }
807 808
808 809 /*
809 810 * Generate a LUN expansion event.
810 811 */
811 812 if (error == 0) {
812 813 sysevent_id_t eid;
813 814 nvlist_t *attr;
814 815 char *physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
815 816
816 817 (void) snprintf(physpath, MAXPATHLEN, "%s%u", ZVOL_PSEUDO_DEV,
817 818 zv->zv_minor);
818 819
819 820 VERIFY(nvlist_alloc(&attr, NV_UNIQUE_NAME, KM_SLEEP) == 0);
820 821 VERIFY(nvlist_add_string(attr, DEV_PHYS_PATH, physpath) == 0);
821 822
822 823 (void) ddi_log_sysevent(zfs_dip, SUNW_VENDOR, EC_DEV_STATUS,
823 824 ESC_DEV_DLE, attr, &eid, DDI_SLEEP);
824 825
825 826 nvlist_free(attr);
826 827 kmem_free(physpath, MAXPATHLEN);
827 828 }
828 829 return (error);
829 830 }
830 831
831 832 int
832 833 zvol_set_volsize(const char *name, uint64_t volsize)
833 834 {
834 835 zvol_state_t *zv = NULL;
835 836 objset_t *os;
836 837 int error;
837 838 dmu_object_info_t doi;
838 839 uint64_t readonly;
839 840 boolean_t owned = B_FALSE;
840 841
841 842 error = dsl_prop_get_integer(name,
842 843 zfs_prop_to_name(ZFS_PROP_READONLY), &readonly, NULL);
843 844 if (error != 0)
844 845 return (error);
845 846 if (readonly)
846 847 return (SET_ERROR(EROFS));
847 848
848 849 mutex_enter(&zfsdev_state_lock);
849 850 zv = zvol_minor_lookup(name);
850 851
851 852 if (zv == NULL || zv->zv_objset == NULL) {
852 853 if ((error = dmu_objset_own(name, DMU_OST_ZVOL, B_FALSE,
853 854 FTAG, &os)) != 0) {
854 855 mutex_exit(&zfsdev_state_lock);
855 856 return (error);
856 857 }
857 858 owned = B_TRUE;
858 859 if (zv != NULL)
859 860 zv->zv_objset = os;
860 861 } else {
861 862 os = zv->zv_objset;
862 863 }
863 864
864 865 if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 ||
865 866 (error = zvol_check_volsize(volsize, doi.doi_data_block_size)) != 0)
866 867 goto out;
867 868
868 869 error = zvol_update_volsize(os, volsize);
869 870
870 871 if (error == 0 && zv != NULL)
871 872 error = zvol_update_live_volsize(zv, volsize);
872 873 out:
873 874 if (owned) {
874 875 dmu_objset_disown(os, FTAG);
875 876 if (zv != NULL)
876 877 zv->zv_objset = NULL;
877 878 }
878 879 mutex_exit(&zfsdev_state_lock);
879 880 return (error);
880 881 }
881 882
882 883 /*ARGSUSED*/
883 884 int
884 885 zvol_open(dev_t *devp, int flag, int otyp, cred_t *cr)
885 886 {
886 887 zvol_state_t *zv;
887 888 int err = 0;
888 889
889 890 mutex_enter(&zfsdev_state_lock);
890 891
891 892 zv = zfsdev_get_soft_state(getminor(*devp), ZSST_ZVOL);
892 893 if (zv == NULL) {
893 894 mutex_exit(&zfsdev_state_lock);
894 895 return (SET_ERROR(ENXIO));
895 896 }
896 897
897 898 if (zv->zv_total_opens == 0)
898 899 err = zvol_first_open(zv);
899 900 if (err) {
900 901 mutex_exit(&zfsdev_state_lock);
901 902 return (err);
902 903 }
903 904 if ((flag & FWRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
904 905 err = SET_ERROR(EROFS);
905 906 goto out;
906 907 }
907 908 if (zv->zv_flags & ZVOL_EXCL) {
908 909 err = SET_ERROR(EBUSY);
909 910 goto out;
910 911 }
911 912 if (flag & FEXCL) {
912 913 if (zv->zv_total_opens != 0) {
913 914 err = SET_ERROR(EBUSY);
914 915 goto out;
915 916 }
916 917 zv->zv_flags |= ZVOL_EXCL;
917 918 }
918 919
919 920 if (zv->zv_open_count[otyp] == 0 || otyp == OTYP_LYR) {
920 921 zv->zv_open_count[otyp]++;
921 922 zv->zv_total_opens++;
922 923 }
923 924 mutex_exit(&zfsdev_state_lock);
924 925
925 926 return (err);
926 927 out:
927 928 if (zv->zv_total_opens == 0)
928 929 zvol_last_close(zv);
929 930 mutex_exit(&zfsdev_state_lock);
930 931 return (err);
931 932 }
932 933
933 934 /*ARGSUSED*/
934 935 int
935 936 zvol_close(dev_t dev, int flag, int otyp, cred_t *cr)
936 937 {
937 938 minor_t minor = getminor(dev);
938 939 zvol_state_t *zv;
939 940 int error = 0;
940 941
941 942 mutex_enter(&zfsdev_state_lock);
942 943
943 944 zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
944 945 if (zv == NULL) {
945 946 mutex_exit(&zfsdev_state_lock);
946 947 return (SET_ERROR(ENXIO));
947 948 }
948 949
949 950 if (zv->zv_flags & ZVOL_EXCL) {
950 951 ASSERT(zv->zv_total_opens == 1);
951 952 zv->zv_flags &= ~ZVOL_EXCL;
952 953 }
953 954
954 955 /*
955 956 * If the open count is zero, this is a spurious close.
956 957 * That indicates a bug in the kernel / DDI framework.
957 958 */
958 959 ASSERT(zv->zv_open_count[otyp] != 0);
959 960 ASSERT(zv->zv_total_opens != 0);
960 961
961 962 /*
962 963 * You may get multiple opens, but only one close.
963 964 */
964 965 zv->zv_open_count[otyp]--;
965 966 zv->zv_total_opens--;
966 967
967 968 if (zv->zv_total_opens == 0)
968 969 zvol_last_close(zv);
969 970
970 971 mutex_exit(&zfsdev_state_lock);
971 972 return (error);
972 973 }
973 974
974 975 /* ARGSUSED */
975 976 static void
976 977 zvol_get_done(zgd_t *zgd, int error)
977 978 {
978 979 if (zgd->zgd_db)
979 980 dmu_buf_rele(zgd->zgd_db, zgd);
980 981
981 982 rangelock_exit(zgd->zgd_lr);
982 983
983 984 kmem_free(zgd, sizeof (zgd_t));
984 985 }
985 986
986 987 /*
987 988 * Get data to generate a TX_WRITE intent log record.
988 989 */
989 990 static int
990 991 zvol_get_data(void *arg, lr_write_t *lr, char *buf, struct lwb *lwb, zio_t *zio)
991 992 {
992 993 zvol_state_t *zv = arg;
993 994 uint64_t offset = lr->lr_offset;
994 995 uint64_t size = lr->lr_length; /* length of user data */
995 996 dmu_buf_t *db;
996 997 zgd_t *zgd;
997 998 int error;
998 999
999 1000 ASSERT3P(lwb, !=, NULL);
1000 1001 ASSERT3P(zio, !=, NULL);
1001 1002 ASSERT3U(size, !=, 0);
1002 1003
1003 1004 zgd = kmem_zalloc(sizeof (zgd_t), KM_SLEEP);
1004 1005 zgd->zgd_lwb = lwb;
1005 1006
1006 1007 /*
1007 1008 * Write records come in two flavors: immediate and indirect.
1008 1009 * For small writes it's cheaper to store the data with the
1009 1010 * log record (immediate); for large writes it's cheaper to
1010 1011 * sync the data and get a pointer to it (indirect) so that
1011 1012 * we don't have to write the data twice.
1012 1013 */
1013 1014 if (buf != NULL) { /* immediate write */
1014 1015 zgd->zgd_lr = rangelock_enter(&zv->zv_rangelock, offset, size,
1015 1016 RL_READER);
1016 1017 error = dmu_read_by_dnode(zv->zv_dn, offset, size, buf,
1017 1018 DMU_READ_NO_PREFETCH);
1018 1019 } else { /* indirect write */
1019 1020 /*
1020 1021 * Have to lock the whole block to ensure when it's written out
1021 1022 * and its checksum is being calculated that no one can change
1022 1023 * the data. Contrarily to zfs_get_data we need not re-check
1023 1024 * blocksize after we get the lock because it cannot be changed.
1024 1025 */
1025 1026 size = zv->zv_volblocksize;
1026 1027 offset = P2ALIGN(offset, size);
1027 1028 zgd->zgd_lr = rangelock_enter(&zv->zv_rangelock, offset, size,
1028 1029 RL_READER);
1029 1030 error = dmu_buf_hold_by_dnode(zv->zv_dn, offset, zgd, &db,
1030 1031 DMU_READ_NO_PREFETCH);
1031 1032 if (error == 0) {
1032 1033 blkptr_t *bp = &lr->lr_blkptr;
1033 1034
1034 1035 zgd->zgd_db = db;
1035 1036 zgd->zgd_bp = bp;
1036 1037
1037 1038 ASSERT(db->db_offset == offset);
1038 1039 ASSERT(db->db_size == size);
1039 1040
1040 1041 error = dmu_sync(zio, lr->lr_common.lrc_txg,
1041 1042 zvol_get_done, zgd);
1042 1043
1043 1044 if (error == 0)
1044 1045 return (0);
1045 1046 }
1046 1047 }
1047 1048
1048 1049 zvol_get_done(zgd, error);
1049 1050
1050 1051 return (error);
1051 1052 }
1052 1053
1053 1054 /*
1054 1055 * zvol_log_write() handles synchronous writes using TX_WRITE ZIL transactions.
1055 1056 *
1056 1057 * We store data in the log buffers if it's small enough.
1057 1058 * Otherwise we will later flush the data out via dmu_sync().
1058 1059 */
1059 1060 ssize_t zvol_immediate_write_sz = 32768;
1060 1061
1061 1062 static void
1062 1063 zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, offset_t off, ssize_t resid,
1063 1064 boolean_t sync)
1064 1065 {
1065 1066 uint32_t blocksize = zv->zv_volblocksize;
1066 1067 zilog_t *zilog = zv->zv_zilog;
1067 1068 itx_wr_state_t write_state;
1068 1069
1069 1070 if (zil_replaying(zilog, tx))
1070 1071 return;
1071 1072
1072 1073 if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT)
1073 1074 write_state = WR_INDIRECT;
1074 1075 else if (!spa_has_slogs(zilog->zl_spa) &&
1075 1076 resid >= blocksize && blocksize > zvol_immediate_write_sz)
1076 1077 write_state = WR_INDIRECT;
1077 1078 else if (sync)
1078 1079 write_state = WR_COPIED;
1079 1080 else
1080 1081 write_state = WR_NEED_COPY;
1081 1082
1082 1083 while (resid) {
1083 1084 itx_t *itx;
1084 1085 lr_write_t *lr;
1085 1086 itx_wr_state_t wr_state = write_state;
1086 1087 ssize_t len = resid;
1087 1088
1088 1089 if (wr_state == WR_COPIED && resid > ZIL_MAX_COPIED_DATA)
1089 1090 wr_state = WR_NEED_COPY;
1090 1091 else if (wr_state == WR_INDIRECT)
1091 1092 len = MIN(blocksize - P2PHASE(off, blocksize), resid);
1092 1093
1093 1094 itx = zil_itx_create(TX_WRITE, sizeof (*lr) +
1094 1095 (wr_state == WR_COPIED ? len : 0));
1095 1096 lr = (lr_write_t *)&itx->itx_lr;
1096 1097 if (wr_state == WR_COPIED && dmu_read_by_dnode(zv->zv_dn,
1097 1098 off, len, lr + 1, DMU_READ_NO_PREFETCH) != 0) {
1098 1099 zil_itx_destroy(itx);
1099 1100 itx = zil_itx_create(TX_WRITE, sizeof (*lr));
1100 1101 lr = (lr_write_t *)&itx->itx_lr;
1101 1102 wr_state = WR_NEED_COPY;
1102 1103 }
1103 1104
1104 1105 itx->itx_wr_state = wr_state;
1105 1106 lr->lr_foid = ZVOL_OBJ;
1106 1107 lr->lr_offset = off;
1107 1108 lr->lr_length = len;
1108 1109 lr->lr_blkoff = 0;
1109 1110 BP_ZERO(&lr->lr_blkptr);
1110 1111
1111 1112 itx->itx_private = zv;
1112 1113 itx->itx_sync = sync;
1113 1114
1114 1115 zil_itx_assign(zilog, itx, tx);
1115 1116
1116 1117 off += len;
1117 1118 resid -= len;
1118 1119 }
1119 1120 }
1120 1121
1121 1122 static int
1122 1123 zvol_dumpio_vdev(vdev_t *vd, void *addr, uint64_t offset, uint64_t origoffset,
1123 1124 uint64_t size, boolean_t doread, boolean_t isdump)
1124 1125 {
1125 1126 vdev_disk_t *dvd;
1126 1127 int c;
1127 1128 int numerrors = 0;
1128 1129
1129 1130 if (vd->vdev_ops == &vdev_mirror_ops ||
1130 1131 vd->vdev_ops == &vdev_replacing_ops ||
1131 1132 vd->vdev_ops == &vdev_spare_ops) {
1132 1133 for (c = 0; c < vd->vdev_children; c++) {
1133 1134 int err = zvol_dumpio_vdev(vd->vdev_child[c],
1134 1135 addr, offset, origoffset, size, doread, isdump);
1135 1136 if (err != 0) {
1136 1137 numerrors++;
1137 1138 } else if (doread) {
1138 1139 break;
1139 1140 }
1140 1141 }
1141 1142 }
1142 1143
1143 1144 if (!vd->vdev_ops->vdev_op_leaf && vd->vdev_ops != &vdev_raidz_ops)
1144 1145 return (numerrors < vd->vdev_children ? 0 : EIO);
1145 1146
1146 1147 if (doread && !vdev_readable(vd))
1147 1148 return (SET_ERROR(EIO));
1148 1149 else if (!doread && !vdev_writeable(vd))
1149 1150 return (SET_ERROR(EIO));
1150 1151
1151 1152 if (vd->vdev_ops == &vdev_raidz_ops) {
1152 1153 return (vdev_raidz_physio(vd,
1153 1154 addr, size, offset, origoffset, doread, isdump));
1154 1155 }
1155 1156
1156 1157 offset += VDEV_LABEL_START_SIZE;
1157 1158
1158 1159 if (ddi_in_panic() || isdump) {
1159 1160 ASSERT(!doread);
1160 1161 if (doread)
1161 1162 return (SET_ERROR(EIO));
1162 1163 dvd = vd->vdev_tsd;
1163 1164 ASSERT3P(dvd, !=, NULL);
1164 1165 return (ldi_dump(dvd->vd_lh, addr, lbtodb(offset),
1165 1166 lbtodb(size)));
1166 1167 } else {
1167 1168 dvd = vd->vdev_tsd;
1168 1169 ASSERT3P(dvd, !=, NULL);
1169 1170 return (vdev_disk_ldi_physio(dvd->vd_lh, addr, size,
1170 1171 offset, doread ? B_READ : B_WRITE));
1171 1172 }
1172 1173 }
1173 1174
1174 1175 static int
1175 1176 zvol_dumpio(zvol_state_t *zv, void *addr, uint64_t offset, uint64_t size,
1176 1177 boolean_t doread, boolean_t isdump)
1177 1178 {
1178 1179 vdev_t *vd;
1179 1180 int error;
1180 1181 zvol_extent_t *ze;
1181 1182 spa_t *spa = dmu_objset_spa(zv->zv_objset);
1182 1183
1183 1184 /* Must be sector aligned, and not stradle a block boundary. */
1184 1185 if (P2PHASE(offset, DEV_BSIZE) || P2PHASE(size, DEV_BSIZE) ||
1185 1186 P2BOUNDARY(offset, size, zv->zv_volblocksize)) {
1186 1187 return (SET_ERROR(EINVAL));
1187 1188 }
1188 1189 ASSERT(size <= zv->zv_volblocksize);
1189 1190
1190 1191 /* Locate the extent this belongs to */
1191 1192 ze = list_head(&zv->zv_extents);
1192 1193 while (offset >= ze->ze_nblks * zv->zv_volblocksize) {
1193 1194 offset -= ze->ze_nblks * zv->zv_volblocksize;
1194 1195 ze = list_next(&zv->zv_extents, ze);
1195 1196 }
1196 1197
1197 1198 if (ze == NULL)
1198 1199 return (SET_ERROR(EINVAL));
1199 1200
1200 1201 if (!ddi_in_panic())
1201 1202 spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
1202 1203
1203 1204 vd = vdev_lookup_top(spa, DVA_GET_VDEV(&ze->ze_dva));
1204 1205 offset += DVA_GET_OFFSET(&ze->ze_dva);
1205 1206 error = zvol_dumpio_vdev(vd, addr, offset, DVA_GET_OFFSET(&ze->ze_dva),
1206 1207 size, doread, isdump);
1207 1208
1208 1209 if (!ddi_in_panic())
1209 1210 spa_config_exit(spa, SCL_STATE, FTAG);
1210 1211
1211 1212 return (error);
1212 1213 }
1213 1214
1214 1215 int
1215 1216 zvol_strategy(buf_t *bp)
1216 1217 {
1217 1218 zfs_soft_state_t *zs = NULL;
1218 1219 zvol_state_t *zv;
1219 1220 uint64_t off, volsize;
1220 1221 size_t resid;
1221 1222 char *addr;
1222 1223 objset_t *os;
1223 1224 int error = 0;
1224 1225 boolean_t doread = bp->b_flags & B_READ;
1225 1226 boolean_t is_dumpified;
1226 1227 boolean_t sync;
1227 1228
1228 1229 if (getminor(bp->b_edev) == 0) {
1229 1230 error = SET_ERROR(EINVAL);
1230 1231 } else {
1231 1232 zs = ddi_get_soft_state(zfsdev_state, getminor(bp->b_edev));
1232 1233 if (zs == NULL)
1233 1234 error = SET_ERROR(ENXIO);
1234 1235 else if (zs->zss_type != ZSST_ZVOL)
1235 1236 error = SET_ERROR(EINVAL);
1236 1237 }
1237 1238
1238 1239 if (error) {
1239 1240 bioerror(bp, error);
1240 1241 biodone(bp);
1241 1242 return (0);
1242 1243 }
1243 1244
1244 1245 zv = zs->zss_data;
1245 1246
1246 1247 if (!(bp->b_flags & B_READ) && (zv->zv_flags & ZVOL_RDONLY)) {
1247 1248 bioerror(bp, EROFS);
1248 1249 biodone(bp);
1249 1250 return (0);
1250 1251 }
1251 1252
1252 1253 off = ldbtob(bp->b_blkno);
1253 1254 volsize = zv->zv_volsize;
1254 1255
1255 1256 os = zv->zv_objset;
1256 1257 ASSERT(os != NULL);
1257 1258
1258 1259 bp_mapin(bp);
1259 1260 addr = bp->b_un.b_addr;
1260 1261 resid = bp->b_bcount;
1261 1262
1262 1263 if (resid > 0 && (off < 0 || off >= volsize)) {
1263 1264 bioerror(bp, EIO);
1264 1265 biodone(bp);
1265 1266 return (0);
1266 1267 }
1267 1268
1268 1269 is_dumpified = zv->zv_flags & ZVOL_DUMPIFIED;
1269 1270 sync = ((!(bp->b_flags & B_ASYNC) &&
1270 1271 !(zv->zv_flags & ZVOL_WCE)) ||
1271 1272 (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS)) &&
1272 1273 !doread && !is_dumpified;
1273 1274
1274 1275 /*
1275 1276 * There must be no buffer changes when doing a dmu_sync() because
1276 1277 * we can't change the data whilst calculating the checksum.
1277 1278 */
1278 1279 locked_range_t *lr = rangelock_enter(&zv->zv_rangelock, off, resid,
1279 1280 doread ? RL_READER : RL_WRITER);
1280 1281
1281 1282 while (resid != 0 && off < volsize) {
1282 1283 size_t size = MIN(resid, zvol_maxphys);
1283 1284 if (is_dumpified) {
1284 1285 size = MIN(size, P2END(off, zv->zv_volblocksize) - off);
1285 1286 error = zvol_dumpio(zv, addr, off, size,
1286 1287 doread, B_FALSE);
1287 1288 } else if (doread) {
1288 1289 error = dmu_read(os, ZVOL_OBJ, off, size, addr,
1289 1290 DMU_READ_PREFETCH);
1290 1291 } else {
1291 1292 dmu_tx_t *tx = dmu_tx_create(os);
1292 1293 dmu_tx_hold_write(tx, ZVOL_OBJ, off, size);
1293 1294 error = dmu_tx_assign(tx, TXG_WAIT);
1294 1295 if (error) {
1295 1296 dmu_tx_abort(tx);
1296 1297 } else {
1297 1298 dmu_write(os, ZVOL_OBJ, off, size, addr, tx);
1298 1299 zvol_log_write(zv, tx, off, size, sync);
1299 1300 dmu_tx_commit(tx);
1300 1301 }
1301 1302 }
1302 1303 if (error) {
1303 1304 /* convert checksum errors into IO errors */
1304 1305 if (error == ECKSUM)
1305 1306 error = SET_ERROR(EIO);
1306 1307 break;
1307 1308 }
1308 1309 off += size;
1309 1310 addr += size;
1310 1311 resid -= size;
1311 1312 }
1312 1313 rangelock_exit(lr);
1313 1314
1314 1315 if ((bp->b_resid = resid) == bp->b_bcount)
1315 1316 bioerror(bp, off > volsize ? EINVAL : error);
1316 1317
1317 1318 if (sync)
1318 1319 zil_commit(zv->zv_zilog, ZVOL_OBJ);
1319 1320 biodone(bp);
1320 1321
1321 1322 return (0);
1322 1323 }
1323 1324
1324 1325 /*
1325 1326 * Set the buffer count to the zvol maximum transfer.
1326 1327 * Using our own routine instead of the default minphys()
1327 1328 * means that for larger writes we write bigger buffers on X86
1328 1329 * (128K instead of 56K) and flush the disk write cache less often
1329 1330 * (every zvol_maxphys - currently 1MB) instead of minphys (currently
1330 1331 * 56K on X86 and 128K on sparc).
1331 1332 */
1332 1333 void
1333 1334 zvol_minphys(struct buf *bp)
1334 1335 {
1335 1336 if (bp->b_bcount > zvol_maxphys)
1336 1337 bp->b_bcount = zvol_maxphys;
1337 1338 }
1338 1339
1339 1340 int
1340 1341 zvol_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblocks)
1341 1342 {
1342 1343 minor_t minor = getminor(dev);
1343 1344 zvol_state_t *zv;
1344 1345 int error = 0;
1345 1346 uint64_t size;
1346 1347 uint64_t boff;
1347 1348 uint64_t resid;
1348 1349
1349 1350 zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
1350 1351 if (zv == NULL)
1351 1352 return (SET_ERROR(ENXIO));
1352 1353
1353 1354 if ((zv->zv_flags & ZVOL_DUMPIFIED) == 0)
1354 1355 return (SET_ERROR(EINVAL));
1355 1356
1356 1357 boff = ldbtob(blkno);
1357 1358 resid = ldbtob(nblocks);
1358 1359
1359 1360 VERIFY3U(boff + resid, <=, zv->zv_volsize);
1360 1361
1361 1362 while (resid) {
1362 1363 size = MIN(resid, P2END(boff, zv->zv_volblocksize) - boff);
1363 1364 error = zvol_dumpio(zv, addr, boff, size, B_FALSE, B_TRUE);
1364 1365 if (error)
1365 1366 break;
1366 1367 boff += size;
1367 1368 addr += size;
1368 1369 resid -= size;
1369 1370 }
1370 1371
1371 1372 return (error);
1372 1373 }
1373 1374
1374 1375 /*ARGSUSED*/
1375 1376 int
1376 1377 zvol_read(dev_t dev, uio_t *uio, cred_t *cr)
1377 1378 {
1378 1379 minor_t minor = getminor(dev);
1379 1380 zvol_state_t *zv;
1380 1381 uint64_t volsize;
1381 1382 int error = 0;
1382 1383
1383 1384 zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
1384 1385 if (zv == NULL)
1385 1386 return (SET_ERROR(ENXIO));
1386 1387
1387 1388 volsize = zv->zv_volsize;
1388 1389 if (uio->uio_resid > 0 &&
1389 1390 (uio->uio_loffset < 0 || uio->uio_loffset >= volsize))
1390 1391 return (SET_ERROR(EIO));
1391 1392
1392 1393 if (zv->zv_flags & ZVOL_DUMPIFIED) {
1393 1394 error = physio(zvol_strategy, NULL, dev, B_READ,
1394 1395 zvol_minphys, uio);
1395 1396 return (error);
1396 1397 }
1397 1398
1398 1399 locked_range_t *lr = rangelock_enter(&zv->zv_rangelock,
1399 1400 uio->uio_loffset, uio->uio_resid, RL_READER);
1400 1401 while (uio->uio_resid > 0 && uio->uio_loffset < volsize) {
1401 1402 uint64_t bytes = MIN(uio->uio_resid, DMU_MAX_ACCESS >> 1);
1402 1403
1403 1404 /* don't read past the end */
1404 1405 if (bytes > volsize - uio->uio_loffset)
1405 1406 bytes = volsize - uio->uio_loffset;
1406 1407
1407 1408 error = dmu_read_uio(zv->zv_objset, ZVOL_OBJ, uio, bytes);
1408 1409 if (error) {
1409 1410 /* convert checksum errors into IO errors */
1410 1411 if (error == ECKSUM)
1411 1412 error = SET_ERROR(EIO);
1412 1413 break;
1413 1414 }
1414 1415 }
1415 1416 rangelock_exit(lr);
1416 1417
1417 1418 return (error);
1418 1419 }
1419 1420
1420 1421 /*ARGSUSED*/
1421 1422 int
1422 1423 zvol_write(dev_t dev, uio_t *uio, cred_t *cr)
1423 1424 {
1424 1425 minor_t minor = getminor(dev);
1425 1426 zvol_state_t *zv;
1426 1427 uint64_t volsize;
1427 1428 int error = 0;
1428 1429 boolean_t sync;
1429 1430
1430 1431 zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
1431 1432 if (zv == NULL)
1432 1433 return (SET_ERROR(ENXIO));
1433 1434
1434 1435 volsize = zv->zv_volsize;
1435 1436 if (uio->uio_resid > 0 &&
1436 1437 (uio->uio_loffset < 0 || uio->uio_loffset >= volsize))
1437 1438 return (SET_ERROR(EIO));
1438 1439
1439 1440 if (zv->zv_flags & ZVOL_DUMPIFIED) {
1440 1441 error = physio(zvol_strategy, NULL, dev, B_WRITE,
1441 1442 zvol_minphys, uio);
1442 1443 return (error);
1443 1444 }
1444 1445
1445 1446 sync = !(zv->zv_flags & ZVOL_WCE) ||
1446 1447 (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS);
1447 1448
1448 1449 locked_range_t *lr = rangelock_enter(&zv->zv_rangelock,
1449 1450 uio->uio_loffset, uio->uio_resid, RL_WRITER);
1450 1451 while (uio->uio_resid > 0 && uio->uio_loffset < volsize) {
1451 1452 uint64_t bytes = MIN(uio->uio_resid, DMU_MAX_ACCESS >> 1);
1452 1453 uint64_t off = uio->uio_loffset;
1453 1454 dmu_tx_t *tx = dmu_tx_create(zv->zv_objset);
1454 1455
1455 1456 if (bytes > volsize - off) /* don't write past the end */
1456 1457 bytes = volsize - off;
1457 1458
1458 1459 dmu_tx_hold_write(tx, ZVOL_OBJ, off, bytes);
1459 1460 error = dmu_tx_assign(tx, TXG_WAIT);
1460 1461 if (error) {
1461 1462 dmu_tx_abort(tx);
1462 1463 break;
1463 1464 }
1464 1465 error = dmu_write_uio_dnode(zv->zv_dn, uio, bytes, tx);
1465 1466 if (error == 0)
1466 1467 zvol_log_write(zv, tx, off, bytes, sync);
1467 1468 dmu_tx_commit(tx);
1468 1469
1469 1470 if (error)
1470 1471 break;
1471 1472 }
1472 1473 rangelock_exit(lr);
1473 1474
1474 1475 if (sync)
1475 1476 zil_commit(zv->zv_zilog, ZVOL_OBJ);
1476 1477 return (error);
1477 1478 }
1478 1479
1479 1480 int
1480 1481 zvol_getefi(void *arg, int flag, uint64_t vs, uint8_t bs)
1481 1482 {
1482 1483 struct uuid uuid = EFI_RESERVED;
1483 1484 efi_gpe_t gpe = { 0 };
1484 1485 uint32_t crc;
1485 1486 dk_efi_t efi;
1486 1487 int length;
1487 1488 char *ptr;
1488 1489
1489 1490 if (ddi_copyin(arg, &efi, sizeof (dk_efi_t), flag))
1490 1491 return (SET_ERROR(EFAULT));
1491 1492 ptr = (char *)(uintptr_t)efi.dki_data_64;
1492 1493 length = efi.dki_length;
1493 1494 /*
1494 1495 * Some clients may attempt to request a PMBR for the
1495 1496 * zvol. Currently this interface will return EINVAL to
1496 1497 * such requests. These requests could be supported by
1497 1498 * adding a check for lba == 0 and consing up an appropriate
1498 1499 * PMBR.
1499 1500 */
1500 1501 if (efi.dki_lba < 1 || efi.dki_lba > 2 || length <= 0)
1501 1502 return (SET_ERROR(EINVAL));
↓ open down ↓ |
1462 lines elided |
↑ open up ↑ |
1502 1503
1503 1504 gpe.efi_gpe_StartingLBA = LE_64(34ULL);
1504 1505 gpe.efi_gpe_EndingLBA = LE_64((vs >> bs) - 1);
1505 1506 UUID_LE_CONVERT(gpe.efi_gpe_PartitionTypeGUID, uuid);
1506 1507
1507 1508 if (efi.dki_lba == 1) {
1508 1509 efi_gpt_t gpt = { 0 };
1509 1510
1510 1511 gpt.efi_gpt_Signature = LE_64(EFI_SIGNATURE);
1511 1512 gpt.efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT);
1512 - gpt.efi_gpt_HeaderSize = LE_32(sizeof (gpt));
1513 + gpt.efi_gpt_HeaderSize = LE_32(EFI_HEADER_SIZE);
1513 1514 gpt.efi_gpt_MyLBA = LE_64(1ULL);
1514 1515 gpt.efi_gpt_FirstUsableLBA = LE_64(34ULL);
1515 1516 gpt.efi_gpt_LastUsableLBA = LE_64((vs >> bs) - 1);
1516 1517 gpt.efi_gpt_PartitionEntryLBA = LE_64(2ULL);
1517 1518 gpt.efi_gpt_NumberOfPartitionEntries = LE_32(1);
1518 1519 gpt.efi_gpt_SizeOfPartitionEntry =
1519 1520 LE_32(sizeof (efi_gpe_t));
1520 1521 CRC32(crc, &gpe, sizeof (gpe), -1U, crc32_table);
1521 1522 gpt.efi_gpt_PartitionEntryArrayCRC32 = LE_32(~crc);
1522 - CRC32(crc, &gpt, sizeof (gpt), -1U, crc32_table);
1523 + CRC32(crc, &gpt, EFI_HEADER_SIZE, -1U, crc32_table);
1523 1524 gpt.efi_gpt_HeaderCRC32 = LE_32(~crc);
1524 1525 if (ddi_copyout(&gpt, ptr, MIN(sizeof (gpt), length),
1525 1526 flag))
1526 1527 return (SET_ERROR(EFAULT));
1527 1528 ptr += sizeof (gpt);
1528 1529 length -= sizeof (gpt);
1529 1530 }
1530 1531 if (length > 0 && ddi_copyout(&gpe, ptr, MIN(sizeof (gpe),
1531 1532 length), flag))
1532 1533 return (SET_ERROR(EFAULT));
1533 1534 return (0);
1534 1535 }
1535 1536
1536 1537 /*
1537 1538 * BEGIN entry points to allow external callers access to the volume.
1538 1539 */
1539 1540 /*
1540 1541 * Return the volume parameters needed for access from an external caller.
1541 1542 * These values are invariant as long as the volume is held open.
1542 1543 */
1543 1544 int
1544 1545 zvol_get_volume_params(minor_t minor, uint64_t *blksize,
1545 1546 uint64_t *max_xfer_len, void **minor_hdl, void **objset_hdl, void **zil_hdl,
1546 1547 void **rl_hdl, void **dnode_hdl)
1547 1548 {
1548 1549 zvol_state_t *zv;
1549 1550
1550 1551 zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
1551 1552 if (zv == NULL)
1552 1553 return (SET_ERROR(ENXIO));
1553 1554 if (zv->zv_flags & ZVOL_DUMPIFIED)
1554 1555 return (SET_ERROR(ENXIO));
1555 1556
1556 1557 ASSERT(blksize && max_xfer_len && minor_hdl &&
1557 1558 objset_hdl && zil_hdl && rl_hdl && dnode_hdl);
1558 1559
1559 1560 *blksize = zv->zv_volblocksize;
1560 1561 *max_xfer_len = (uint64_t)zvol_maxphys;
1561 1562 *minor_hdl = zv;
1562 1563 *objset_hdl = zv->zv_objset;
1563 1564 *zil_hdl = zv->zv_zilog;
1564 1565 *rl_hdl = &zv->zv_rangelock;
1565 1566 *dnode_hdl = zv->zv_dn;
1566 1567 return (0);
1567 1568 }
1568 1569
1569 1570 /*
1570 1571 * Return the current volume size to an external caller.
1571 1572 * The size can change while the volume is open.
1572 1573 */
1573 1574 uint64_t
1574 1575 zvol_get_volume_size(void *minor_hdl)
1575 1576 {
1576 1577 zvol_state_t *zv = minor_hdl;
1577 1578
1578 1579 return (zv->zv_volsize);
1579 1580 }
1580 1581
1581 1582 /*
1582 1583 * Return the current WCE setting to an external caller.
1583 1584 * The WCE setting can change while the volume is open.
1584 1585 */
1585 1586 int
1586 1587 zvol_get_volume_wce(void *minor_hdl)
1587 1588 {
1588 1589 zvol_state_t *zv = minor_hdl;
1589 1590
1590 1591 return ((zv->zv_flags & ZVOL_WCE) ? 1 : 0);
1591 1592 }
1592 1593
1593 1594 /*
1594 1595 * Entry point for external callers to zvol_log_write
1595 1596 */
1596 1597 void
1597 1598 zvol_log_write_minor(void *minor_hdl, dmu_tx_t *tx, offset_t off, ssize_t resid,
1598 1599 boolean_t sync)
1599 1600 {
1600 1601 zvol_state_t *zv = minor_hdl;
1601 1602
1602 1603 zvol_log_write(zv, tx, off, resid, sync);
1603 1604 }
1604 1605 /*
1605 1606 * END entry points to allow external callers access to the volume.
1606 1607 */
1607 1608
1608 1609 /*
1609 1610 * Log a DKIOCFREE/free-long-range to the ZIL with TX_TRUNCATE.
1610 1611 */
1611 1612 static void
1612 1613 zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off, uint64_t len,
1613 1614 boolean_t sync)
1614 1615 {
1615 1616 itx_t *itx;
1616 1617 lr_truncate_t *lr;
1617 1618 zilog_t *zilog = zv->zv_zilog;
1618 1619
1619 1620 if (zil_replaying(zilog, tx))
1620 1621 return;
1621 1622
1622 1623 itx = zil_itx_create(TX_TRUNCATE, sizeof (*lr));
1623 1624 lr = (lr_truncate_t *)&itx->itx_lr;
1624 1625 lr->lr_foid = ZVOL_OBJ;
1625 1626 lr->lr_offset = off;
1626 1627 lr->lr_length = len;
1627 1628
1628 1629 itx->itx_sync = sync;
1629 1630 zil_itx_assign(zilog, itx, tx);
1630 1631 }
1631 1632
1632 1633 /*
1633 1634 * Dirtbag ioctls to support mkfs(1M) for UFS filesystems. See dkio(7I).
1634 1635 * Also a dirtbag dkio ioctl for unmap/free-block functionality.
1635 1636 */
1636 1637 /*ARGSUSED*/
1637 1638 int
1638 1639 zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
1639 1640 {
1640 1641 zvol_state_t *zv;
1641 1642 struct dk_callback *dkc;
1642 1643 int error = 0;
1643 1644 locked_range_t *lr;
1644 1645
1645 1646 mutex_enter(&zfsdev_state_lock);
1646 1647
1647 1648 zv = zfsdev_get_soft_state(getminor(dev), ZSST_ZVOL);
1648 1649
1649 1650 if (zv == NULL) {
1650 1651 mutex_exit(&zfsdev_state_lock);
1651 1652 return (SET_ERROR(ENXIO));
1652 1653 }
1653 1654 ASSERT(zv->zv_total_opens > 0);
1654 1655
1655 1656 switch (cmd) {
1656 1657
1657 1658 case DKIOCINFO:
1658 1659 {
1659 1660 struct dk_cinfo dki;
1660 1661
1661 1662 bzero(&dki, sizeof (dki));
1662 1663 (void) strcpy(dki.dki_cname, "zvol");
1663 1664 (void) strcpy(dki.dki_dname, "zvol");
1664 1665 dki.dki_ctype = DKC_UNKNOWN;
1665 1666 dki.dki_unit = getminor(dev);
1666 1667 dki.dki_maxtransfer =
1667 1668 1 << (SPA_OLD_MAXBLOCKSHIFT - zv->zv_min_bs);
1668 1669 mutex_exit(&zfsdev_state_lock);
1669 1670 if (ddi_copyout(&dki, (void *)arg, sizeof (dki), flag))
1670 1671 error = SET_ERROR(EFAULT);
1671 1672 return (error);
1672 1673 }
1673 1674
1674 1675 case DKIOCGMEDIAINFO:
1675 1676 {
1676 1677 struct dk_minfo dkm;
1677 1678
1678 1679 bzero(&dkm, sizeof (dkm));
1679 1680 dkm.dki_lbsize = 1U << zv->zv_min_bs;
1680 1681 dkm.dki_capacity = zv->zv_volsize >> zv->zv_min_bs;
1681 1682 dkm.dki_media_type = DK_UNKNOWN;
1682 1683 mutex_exit(&zfsdev_state_lock);
1683 1684 if (ddi_copyout(&dkm, (void *)arg, sizeof (dkm), flag))
1684 1685 error = SET_ERROR(EFAULT);
1685 1686 return (error);
1686 1687 }
1687 1688
1688 1689 case DKIOCGMEDIAINFOEXT:
1689 1690 {
1690 1691 struct dk_minfo_ext dkmext;
1691 1692
1692 1693 bzero(&dkmext, sizeof (dkmext));
1693 1694 dkmext.dki_lbsize = 1U << zv->zv_min_bs;
1694 1695 dkmext.dki_pbsize = zv->zv_volblocksize;
1695 1696 dkmext.dki_capacity = zv->zv_volsize >> zv->zv_min_bs;
1696 1697 dkmext.dki_media_type = DK_UNKNOWN;
1697 1698 mutex_exit(&zfsdev_state_lock);
1698 1699 if (ddi_copyout(&dkmext, (void *)arg, sizeof (dkmext), flag))
1699 1700 error = SET_ERROR(EFAULT);
1700 1701 return (error);
1701 1702 }
1702 1703
1703 1704 case DKIOCGETEFI:
1704 1705 {
1705 1706 uint64_t vs = zv->zv_volsize;
1706 1707 uint8_t bs = zv->zv_min_bs;
1707 1708
1708 1709 mutex_exit(&zfsdev_state_lock);
1709 1710 error = zvol_getefi((void *)arg, flag, vs, bs);
1710 1711 return (error);
1711 1712 }
1712 1713
1713 1714 case DKIOCFLUSHWRITECACHE:
1714 1715 dkc = (struct dk_callback *)arg;
1715 1716 mutex_exit(&zfsdev_state_lock);
1716 1717 zil_commit(zv->zv_zilog, ZVOL_OBJ);
1717 1718 if ((flag & FKIOCTL) && dkc != NULL && dkc->dkc_callback) {
1718 1719 (*dkc->dkc_callback)(dkc->dkc_cookie, error);
1719 1720 error = 0;
1720 1721 }
1721 1722 return (error);
1722 1723
1723 1724 case DKIOCGETWCE:
1724 1725 {
1725 1726 int wce = (zv->zv_flags & ZVOL_WCE) ? 1 : 0;
1726 1727 if (ddi_copyout(&wce, (void *)arg, sizeof (int),
1727 1728 flag))
1728 1729 error = SET_ERROR(EFAULT);
1729 1730 break;
1730 1731 }
1731 1732 case DKIOCSETWCE:
1732 1733 {
1733 1734 int wce;
1734 1735 if (ddi_copyin((void *)arg, &wce, sizeof (int),
1735 1736 flag)) {
1736 1737 error = SET_ERROR(EFAULT);
1737 1738 break;
1738 1739 }
1739 1740 if (wce) {
1740 1741 zv->zv_flags |= ZVOL_WCE;
1741 1742 mutex_exit(&zfsdev_state_lock);
1742 1743 } else {
1743 1744 zv->zv_flags &= ~ZVOL_WCE;
1744 1745 mutex_exit(&zfsdev_state_lock);
1745 1746 zil_commit(zv->zv_zilog, ZVOL_OBJ);
1746 1747 }
1747 1748 return (0);
1748 1749 }
1749 1750
1750 1751 case DKIOCGGEOM:
1751 1752 case DKIOCGVTOC:
1752 1753 /*
1753 1754 * commands using these (like prtvtoc) expect ENOTSUP
1754 1755 * since we're emulating an EFI label
1755 1756 */
1756 1757 error = SET_ERROR(ENOTSUP);
1757 1758 break;
1758 1759
1759 1760 case DKIOCDUMPINIT:
1760 1761 lr = rangelock_enter(&zv->zv_rangelock, 0, zv->zv_volsize,
1761 1762 RL_WRITER);
1762 1763 error = zvol_dumpify(zv);
1763 1764 rangelock_exit(lr);
1764 1765 break;
1765 1766
1766 1767 case DKIOCDUMPFINI:
1767 1768 if (!(zv->zv_flags & ZVOL_DUMPIFIED))
1768 1769 break;
1769 1770 lr = rangelock_enter(&zv->zv_rangelock, 0, zv->zv_volsize,
1770 1771 RL_WRITER);
1771 1772 error = zvol_dump_fini(zv);
1772 1773 rangelock_exit(lr);
1773 1774 break;
1774 1775
1775 1776 case DKIOCFREE:
1776 1777 {
1777 1778 dkioc_free_list_t *dfl;
1778 1779 dmu_tx_t *tx;
1779 1780
1780 1781 if (!zvol_unmap_enabled)
1781 1782 break;
1782 1783
1783 1784 if (!(flag & FKIOCTL)) {
1784 1785 error = dfl_copyin((void *)arg, &dfl, flag, KM_SLEEP);
1785 1786 if (error != 0)
1786 1787 break;
1787 1788 } else {
1788 1789 dfl = (dkioc_free_list_t *)arg;
1789 1790 ASSERT3U(dfl->dfl_num_exts, <=, DFL_COPYIN_MAX_EXTS);
1790 1791 if (dfl->dfl_num_exts > DFL_COPYIN_MAX_EXTS) {
1791 1792 error = SET_ERROR(EINVAL);
1792 1793 break;
1793 1794 }
1794 1795 }
1795 1796
1796 1797 mutex_exit(&zfsdev_state_lock);
1797 1798
1798 1799 for (int i = 0; i < dfl->dfl_num_exts; i++) {
1799 1800 uint64_t start = dfl->dfl_exts[i].dfle_start,
1800 1801 length = dfl->dfl_exts[i].dfle_length,
1801 1802 end = start + length;
1802 1803
1803 1804 /*
1804 1805 * Apply Postel's Law to length-checking. If they
1805 1806 * overshoot, just blank out until the end, if there's
1806 1807 * a need to blank out anything.
1807 1808 */
1808 1809 if (start >= zv->zv_volsize)
1809 1810 continue; /* No need to do anything... */
1810 1811 if (end > zv->zv_volsize) {
1811 1812 end = DMU_OBJECT_END;
1812 1813 length = end - start;
1813 1814 }
1814 1815
1815 1816 lr = rangelock_enter(&zv->zv_rangelock, start, length,
1816 1817 RL_WRITER);
1817 1818 tx = dmu_tx_create(zv->zv_objset);
1818 1819 error = dmu_tx_assign(tx, TXG_WAIT);
1819 1820 if (error != 0) {
1820 1821 dmu_tx_abort(tx);
1821 1822 } else {
1822 1823 zvol_log_truncate(zv, tx, start, length,
1823 1824 B_TRUE);
1824 1825 dmu_tx_commit(tx);
1825 1826 error = dmu_free_long_range(zv->zv_objset,
1826 1827 ZVOL_OBJ, start, length);
1827 1828 }
1828 1829
1829 1830 rangelock_exit(lr);
1830 1831
1831 1832 if (error != 0)
1832 1833 break;
1833 1834 }
1834 1835
1835 1836 /*
1836 1837 * If the write-cache is disabled, 'sync' property
1837 1838 * is set to 'always', or if the caller is asking for
1838 1839 * a synchronous free, commit this operation to the zil.
1839 1840 * This will sync any previous uncommitted writes to the
1840 1841 * zvol object.
1841 1842 * Can be overridden by the zvol_unmap_sync_enabled tunable.
1842 1843 */
1843 1844 if ((error == 0) && zvol_unmap_sync_enabled &&
1844 1845 (!(zv->zv_flags & ZVOL_WCE) ||
1845 1846 (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS) ||
1846 1847 (dfl->dfl_flags & DF_WAIT_SYNC))) {
1847 1848 zil_commit(zv->zv_zilog, ZVOL_OBJ);
1848 1849 }
1849 1850
1850 1851 if (!(flag & FKIOCTL))
1851 1852 dfl_free(dfl);
1852 1853
1853 1854 return (error);
1854 1855 }
1855 1856
1856 1857 default:
1857 1858 error = SET_ERROR(ENOTTY);
1858 1859 break;
1859 1860
1860 1861 }
1861 1862 mutex_exit(&zfsdev_state_lock);
1862 1863 return (error);
1863 1864 }
1864 1865
1865 1866 int
1866 1867 zvol_busy(void)
1867 1868 {
1868 1869 return (zvol_minors != 0);
1869 1870 }
1870 1871
1871 1872 void
1872 1873 zvol_init(void)
1873 1874 {
1874 1875 VERIFY(ddi_soft_state_init(&zfsdev_state, sizeof (zfs_soft_state_t),
1875 1876 1) == 0);
1876 1877 mutex_init(&zfsdev_state_lock, NULL, MUTEX_DEFAULT, NULL);
1877 1878 }
1878 1879
1879 1880 void
1880 1881 zvol_fini(void)
1881 1882 {
1882 1883 mutex_destroy(&zfsdev_state_lock);
1883 1884 ddi_soft_state_fini(&zfsdev_state);
1884 1885 }
1885 1886
1886 1887 /*ARGSUSED*/
1887 1888 static int
1888 1889 zfs_mvdev_dump_feature_check(void *arg, dmu_tx_t *tx)
1889 1890 {
1890 1891 spa_t *spa = dmu_tx_pool(tx)->dp_spa;
1891 1892
1892 1893 if (spa_feature_is_active(spa, SPA_FEATURE_MULTI_VDEV_CRASH_DUMP))
1893 1894 return (1);
1894 1895 return (0);
1895 1896 }
1896 1897
1897 1898 /*ARGSUSED*/
1898 1899 static void
1899 1900 zfs_mvdev_dump_activate_feature_sync(void *arg, dmu_tx_t *tx)
1900 1901 {
1901 1902 spa_t *spa = dmu_tx_pool(tx)->dp_spa;
1902 1903
1903 1904 spa_feature_incr(spa, SPA_FEATURE_MULTI_VDEV_CRASH_DUMP, tx);
1904 1905 }
1905 1906
1906 1907 static int
1907 1908 zvol_dump_init(zvol_state_t *zv, boolean_t resize)
1908 1909 {
1909 1910 dmu_tx_t *tx;
1910 1911 int error;
1911 1912 objset_t *os = zv->zv_objset;
1912 1913 spa_t *spa = dmu_objset_spa(os);
1913 1914 vdev_t *vd = spa->spa_root_vdev;
1914 1915 nvlist_t *nv = NULL;
1915 1916 uint64_t version = spa_version(spa);
1916 1917 uint64_t checksum, compress, refresrv, vbs, dedup;
1917 1918
1918 1919 ASSERT(MUTEX_HELD(&zfsdev_state_lock));
1919 1920 ASSERT(vd->vdev_ops == &vdev_root_ops);
1920 1921
1921 1922 error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, 0,
1922 1923 DMU_OBJECT_END);
1923 1924 if (error != 0)
1924 1925 return (error);
1925 1926 /* wait for dmu_free_long_range to actually free the blocks */
1926 1927 txg_wait_synced(dmu_objset_pool(zv->zv_objset), 0);
1927 1928
1928 1929 /*
1929 1930 * If the pool on which the dump device is being initialized has more
1930 1931 * than one child vdev, check that the MULTI_VDEV_CRASH_DUMP feature is
1931 1932 * enabled. If so, bump that feature's counter to indicate that the
1932 1933 * feature is active. We also check the vdev type to handle the
1933 1934 * following case:
1934 1935 * # zpool create test raidz disk1 disk2 disk3
1935 1936 * Now have spa_root_vdev->vdev_children == 1 (the raidz vdev),
1936 1937 * the raidz vdev itself has 3 children.
1937 1938 */
1938 1939 if (vd->vdev_children > 1 || vd->vdev_ops == &vdev_raidz_ops) {
1939 1940 if (!spa_feature_is_enabled(spa,
1940 1941 SPA_FEATURE_MULTI_VDEV_CRASH_DUMP))
1941 1942 return (SET_ERROR(ENOTSUP));
1942 1943 (void) dsl_sync_task(spa_name(spa),
1943 1944 zfs_mvdev_dump_feature_check,
1944 1945 zfs_mvdev_dump_activate_feature_sync, NULL,
1945 1946 2, ZFS_SPACE_CHECK_RESERVED);
1946 1947 }
1947 1948
1948 1949 if (!resize) {
1949 1950 error = dsl_prop_get_integer(zv->zv_name,
1950 1951 zfs_prop_to_name(ZFS_PROP_COMPRESSION), &compress, NULL);
1951 1952 if (error == 0) {
1952 1953 error = dsl_prop_get_integer(zv->zv_name,
1953 1954 zfs_prop_to_name(ZFS_PROP_CHECKSUM), &checksum,
1954 1955 NULL);
1955 1956 }
1956 1957 if (error == 0) {
1957 1958 error = dsl_prop_get_integer(zv->zv_name,
1958 1959 zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
1959 1960 &refresrv, NULL);
1960 1961 }
1961 1962 if (error == 0) {
1962 1963 error = dsl_prop_get_integer(zv->zv_name,
1963 1964 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), &vbs,
1964 1965 NULL);
1965 1966 }
1966 1967 if (version >= SPA_VERSION_DEDUP && error == 0) {
1967 1968 error = dsl_prop_get_integer(zv->zv_name,
1968 1969 zfs_prop_to_name(ZFS_PROP_DEDUP), &dedup, NULL);
1969 1970 }
1970 1971 }
1971 1972 if (error != 0)
1972 1973 return (error);
1973 1974
1974 1975 tx = dmu_tx_create(os);
1975 1976 dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
1976 1977 dmu_tx_hold_bonus(tx, ZVOL_OBJ);
1977 1978 error = dmu_tx_assign(tx, TXG_WAIT);
1978 1979 if (error != 0) {
1979 1980 dmu_tx_abort(tx);
1980 1981 return (error);
1981 1982 }
1982 1983
1983 1984 /*
1984 1985 * If we are resizing the dump device then we only need to
1985 1986 * update the refreservation to match the newly updated
1986 1987 * zvolsize. Otherwise, we save off the original state of the
1987 1988 * zvol so that we can restore them if the zvol is ever undumpified.
1988 1989 */
1989 1990 if (resize) {
1990 1991 error = zap_update(os, ZVOL_ZAP_OBJ,
1991 1992 zfs_prop_to_name(ZFS_PROP_REFRESERVATION), 8, 1,
1992 1993 &zv->zv_volsize, tx);
1993 1994 } else {
1994 1995 error = zap_update(os, ZVOL_ZAP_OBJ,
1995 1996 zfs_prop_to_name(ZFS_PROP_COMPRESSION), 8, 1,
1996 1997 &compress, tx);
1997 1998 if (error == 0) {
1998 1999 error = zap_update(os, ZVOL_ZAP_OBJ,
1999 2000 zfs_prop_to_name(ZFS_PROP_CHECKSUM), 8, 1,
2000 2001 &checksum, tx);
2001 2002 }
2002 2003 if (error == 0) {
2003 2004 error = zap_update(os, ZVOL_ZAP_OBJ,
2004 2005 zfs_prop_to_name(ZFS_PROP_REFRESERVATION), 8, 1,
2005 2006 &refresrv, tx);
2006 2007 }
2007 2008 if (error == 0) {
2008 2009 error = zap_update(os, ZVOL_ZAP_OBJ,
2009 2010 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 8, 1,
2010 2011 &vbs, tx);
2011 2012 }
2012 2013 if (error == 0) {
2013 2014 error = dmu_object_set_blocksize(
2014 2015 os, ZVOL_OBJ, SPA_OLD_MAXBLOCKSIZE, 0, tx);
2015 2016 }
2016 2017 if (version >= SPA_VERSION_DEDUP && error == 0) {
2017 2018 error = zap_update(os, ZVOL_ZAP_OBJ,
2018 2019 zfs_prop_to_name(ZFS_PROP_DEDUP), 8, 1,
2019 2020 &dedup, tx);
2020 2021 }
2021 2022 if (error == 0)
2022 2023 zv->zv_volblocksize = SPA_OLD_MAXBLOCKSIZE;
2023 2024 }
2024 2025 dmu_tx_commit(tx);
2025 2026
2026 2027 /*
2027 2028 * We only need update the zvol's property if we are initializing
2028 2029 * the dump area for the first time.
2029 2030 */
2030 2031 if (error == 0 && !resize) {
2031 2032 /*
2032 2033 * If MULTI_VDEV_CRASH_DUMP is active, use the NOPARITY checksum
2033 2034 * function. Otherwise, use the old default -- OFF.
2034 2035 */
2035 2036 checksum = spa_feature_is_active(spa,
2036 2037 SPA_FEATURE_MULTI_VDEV_CRASH_DUMP) ? ZIO_CHECKSUM_NOPARITY :
2037 2038 ZIO_CHECKSUM_OFF;
2038 2039
2039 2040 VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0);
2040 2041 VERIFY(nvlist_add_uint64(nv,
2041 2042 zfs_prop_to_name(ZFS_PROP_REFRESERVATION), 0) == 0);
2042 2043 VERIFY(nvlist_add_uint64(nv,
2043 2044 zfs_prop_to_name(ZFS_PROP_COMPRESSION),
2044 2045 ZIO_COMPRESS_OFF) == 0);
2045 2046 VERIFY(nvlist_add_uint64(nv,
2046 2047 zfs_prop_to_name(ZFS_PROP_CHECKSUM),
2047 2048 checksum) == 0);
2048 2049 if (version >= SPA_VERSION_DEDUP) {
2049 2050 VERIFY(nvlist_add_uint64(nv,
2050 2051 zfs_prop_to_name(ZFS_PROP_DEDUP),
2051 2052 ZIO_CHECKSUM_OFF) == 0);
2052 2053 }
2053 2054
2054 2055 error = zfs_set_prop_nvlist(zv->zv_name, ZPROP_SRC_LOCAL,
2055 2056 nv, NULL);
2056 2057 nvlist_free(nv);
2057 2058 }
2058 2059
2059 2060 /* Allocate the space for the dump */
2060 2061 if (error == 0)
2061 2062 error = zvol_prealloc(zv);
2062 2063 return (error);
2063 2064 }
2064 2065
2065 2066 static int
2066 2067 zvol_dumpify(zvol_state_t *zv)
2067 2068 {
2068 2069 int error = 0;
2069 2070 uint64_t dumpsize = 0;
2070 2071 dmu_tx_t *tx;
2071 2072 objset_t *os = zv->zv_objset;
2072 2073
2073 2074 if (zv->zv_flags & ZVOL_RDONLY)
2074 2075 return (SET_ERROR(EROFS));
2075 2076
2076 2077 if (zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ, ZVOL_DUMPSIZE,
2077 2078 8, 1, &dumpsize) != 0 || dumpsize != zv->zv_volsize) {
2078 2079 boolean_t resize = (dumpsize > 0);
2079 2080
2080 2081 if ((error = zvol_dump_init(zv, resize)) != 0) {
2081 2082 (void) zvol_dump_fini(zv);
2082 2083 return (error);
2083 2084 }
2084 2085 }
2085 2086
2086 2087 /*
2087 2088 * Build up our lba mapping.
2088 2089 */
2089 2090 error = zvol_get_lbas(zv);
2090 2091 if (error) {
2091 2092 (void) zvol_dump_fini(zv);
2092 2093 return (error);
2093 2094 }
2094 2095
2095 2096 tx = dmu_tx_create(os);
2096 2097 dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
2097 2098 error = dmu_tx_assign(tx, TXG_WAIT);
2098 2099 if (error) {
2099 2100 dmu_tx_abort(tx);
2100 2101 (void) zvol_dump_fini(zv);
2101 2102 return (error);
2102 2103 }
2103 2104
2104 2105 zv->zv_flags |= ZVOL_DUMPIFIED;
2105 2106 error = zap_update(os, ZVOL_ZAP_OBJ, ZVOL_DUMPSIZE, 8, 1,
2106 2107 &zv->zv_volsize, tx);
2107 2108 dmu_tx_commit(tx);
2108 2109
2109 2110 if (error) {
2110 2111 (void) zvol_dump_fini(zv);
2111 2112 return (error);
2112 2113 }
2113 2114
2114 2115 txg_wait_synced(dmu_objset_pool(os), 0);
2115 2116 return (0);
2116 2117 }
2117 2118
2118 2119 static int
2119 2120 zvol_dump_fini(zvol_state_t *zv)
2120 2121 {
2121 2122 dmu_tx_t *tx;
2122 2123 objset_t *os = zv->zv_objset;
2123 2124 nvlist_t *nv;
2124 2125 int error = 0;
2125 2126 uint64_t checksum, compress, refresrv, vbs, dedup;
2126 2127 uint64_t version = spa_version(dmu_objset_spa(zv->zv_objset));
2127 2128
2128 2129 /*
2129 2130 * Attempt to restore the zvol back to its pre-dumpified state.
2130 2131 * This is a best-effort attempt as it's possible that not all
2131 2132 * of these properties were initialized during the dumpify process
2132 2133 * (i.e. error during zvol_dump_init).
2133 2134 */
2134 2135
2135 2136 tx = dmu_tx_create(os);
2136 2137 dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
2137 2138 error = dmu_tx_assign(tx, TXG_WAIT);
2138 2139 if (error) {
2139 2140 dmu_tx_abort(tx);
2140 2141 return (error);
2141 2142 }
2142 2143 (void) zap_remove(os, ZVOL_ZAP_OBJ, ZVOL_DUMPSIZE, tx);
2143 2144 dmu_tx_commit(tx);
2144 2145
2145 2146 (void) zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ,
2146 2147 zfs_prop_to_name(ZFS_PROP_CHECKSUM), 8, 1, &checksum);
2147 2148 (void) zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ,
2148 2149 zfs_prop_to_name(ZFS_PROP_COMPRESSION), 8, 1, &compress);
2149 2150 (void) zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ,
2150 2151 zfs_prop_to_name(ZFS_PROP_REFRESERVATION), 8, 1, &refresrv);
2151 2152 (void) zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ,
2152 2153 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 8, 1, &vbs);
2153 2154
2154 2155 VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0);
2155 2156 (void) nvlist_add_uint64(nv,
2156 2157 zfs_prop_to_name(ZFS_PROP_CHECKSUM), checksum);
2157 2158 (void) nvlist_add_uint64(nv,
2158 2159 zfs_prop_to_name(ZFS_PROP_COMPRESSION), compress);
2159 2160 (void) nvlist_add_uint64(nv,
2160 2161 zfs_prop_to_name(ZFS_PROP_REFRESERVATION), refresrv);
2161 2162 if (version >= SPA_VERSION_DEDUP &&
2162 2163 zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ,
2163 2164 zfs_prop_to_name(ZFS_PROP_DEDUP), 8, 1, &dedup) == 0) {
2164 2165 (void) nvlist_add_uint64(nv,
2165 2166 zfs_prop_to_name(ZFS_PROP_DEDUP), dedup);
2166 2167 }
2167 2168 (void) zfs_set_prop_nvlist(zv->zv_name, ZPROP_SRC_LOCAL,
2168 2169 nv, NULL);
2169 2170 nvlist_free(nv);
2170 2171
2171 2172 zvol_free_extents(zv);
2172 2173 zv->zv_flags &= ~ZVOL_DUMPIFIED;
2173 2174 (void) dmu_free_long_range(os, ZVOL_OBJ, 0, DMU_OBJECT_END);
2174 2175 /* wait for dmu_free_long_range to actually free the blocks */
2175 2176 txg_wait_synced(dmu_objset_pool(zv->zv_objset), 0);
2176 2177 tx = dmu_tx_create(os);
2177 2178 dmu_tx_hold_bonus(tx, ZVOL_OBJ);
2178 2179 error = dmu_tx_assign(tx, TXG_WAIT);
2179 2180 if (error) {
2180 2181 dmu_tx_abort(tx);
2181 2182 return (error);
2182 2183 }
2183 2184 if (dmu_object_set_blocksize(os, ZVOL_OBJ, vbs, 0, tx) == 0)
2184 2185 zv->zv_volblocksize = vbs;
2185 2186 dmu_tx_commit(tx);
2186 2187
2187 2188 return (0);
2188 2189 }
↓ open down ↓ |
656 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX