]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / sys / cddl / contrib / opensolaris / uts / common / fs / zfs / zvol.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
23  * All rights reserved.
24  */
25 /*
26  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29
30 /*
31  * ZFS volume emulation driver.
32  *
33  * Makes a DMU object look like a volume of arbitrary size, up to 2^64 bytes.
34  * Volumes are accessed through the symbolic links named:
35  *
36  * /dev/zvol/dsk/<pool_name>/<dataset_name>
37  * /dev/zvol/rdsk/<pool_name>/<dataset_name>
38  *
39  * These links are created by the ZFS-specific devfsadm link generator.
40  * Volumes are persistent through reboot.  No user command needs to be
41  * run before opening and using a device.
42  */
43
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/kernel.h>
47 #include <sys/errno.h>
48 #include <sys/uio.h>
49 #include <sys/bio.h>
50 #include <sys/buf.h>
51 #include <sys/kmem.h>
52 #include <sys/conf.h>
53 #include <sys/cmn_err.h>
54 #include <sys/stat.h>
55 #include <sys/zap.h>
56 #include <sys/spa.h>
57 #include <sys/zio.h>
58 #include <sys/dmu_traverse.h>
59 #include <sys/dnode.h>
60 #include <sys/dsl_dataset.h>
61 #include <sys/dsl_prop.h>
62 #include <sys/dkio.h>
63 #include <sys/byteorder.h>
64 #include <sys/sunddi.h>
65 #include <sys/dirent.h>
66 #include <sys/policy.h>
67 #include <sys/fs/zfs.h>
68 #include <sys/zfs_ioctl.h>
69 #include <sys/zil.h>
70 #include <sys/refcount.h>
71 #include <sys/zfs_znode.h>
72 #include <sys/zfs_rlock.h>
73 #include <sys/vdev_impl.h>
74 #include <sys/zvol.h>
75 #include <geom/geom.h>
76
77 #include "zfs_namecheck.h"
78
79 #define ZVOL_DUMPSIZE   "dumpsize"
80
81 struct g_class zfs_zvol_class = {
82         .name = "ZFS::ZVOL",
83         .version = G_VERSION,
84 };
85
86 DECLARE_GEOM_CLASS(zfs_zvol_class, zfs_zvol);
87
88 /*
89  * This lock protects the zvol_state structure from being modified
90  * while it's being used, e.g. an open that comes in before a create
91  * finishes.  It also protects temporary opens of the dataset so that,
92  * e.g., an open doesn't get a spurious EBUSY.
93  */
94 static kmutex_t zvol_state_lock;
95 static uint32_t zvol_minors;
96
97 #define NUM_EXTENTS     ((SPA_MAXBLOCKSIZE) / sizeof (zvol_extent_t))
98
99 typedef struct zvol_extent {
100         dva_t           ze_dva;         /* dva associated with this extent */
101         uint64_t        ze_stride;      /* extent stride */
102         uint64_t        ze_size;        /* number of blocks in extent */
103 } zvol_extent_t;
104
105 /*
106  * The list of extents associated with the dump device
107  */
108 typedef struct zvol_ext_list {
109         zvol_extent_t           zl_extents[NUM_EXTENTS];
110         struct zvol_ext_list    *zl_next;
111 } zvol_ext_list_t;
112
113 /*
114  * The in-core state of each volume.
115  */
116 typedef struct zvol_state {
117         char            zv_name[MAXPATHLEN]; /* pool/dd name */
118         uint64_t        zv_volsize;     /* amount of space we advertise */
119         uint64_t        zv_volblocksize; /* volume block size */
120         struct g_provider *zv_provider; /* GEOM provider */
121         uint8_t         zv_min_bs;      /* minimum addressable block shift */
122         uint8_t         zv_flags;       /* readonly; dumpified */
123         objset_t        *zv_objset;     /* objset handle */
124         uint32_t        zv_mode;        /* DS_MODE_* flags at open time */
125         uint32_t        zv_total_opens; /* total open count */
126         zilog_t         *zv_zilog;      /* ZIL handle */
127         zvol_ext_list_t *zv_list;       /* List of extents for dump */
128         uint64_t        zv_txg_assign;  /* txg to assign during ZIL replay */
129         znode_t         zv_znode;       /* for range locking */
130         int             zv_state;
131         struct bio_queue_head zv_queue;
132         struct mtx      zv_queue_mtx;   /* zv_queue mutex */
133 } zvol_state_t;
134
135 /*
136  * zvol specific flags
137  */
138 #define ZVOL_RDONLY     0x1
139 #define ZVOL_DUMPIFIED  0x2
140 #define ZVOL_EXCL       0x4
141
142 /*
143  * zvol maximum transfer in one DMU tx.
144  */
145 int zvol_maxphys = DMU_MAX_ACCESS/2;
146
147 extern int zfs_set_prop_nvlist(const char *, nvlist_t *);
148 static int zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio);
149 static int zvol_dumpify(zvol_state_t *zv);
150 static int zvol_dump_fini(zvol_state_t *zv);
151 static int zvol_dump_init(zvol_state_t *zv, boolean_t resize);
152
153 static void
154 zvol_size_changed(zvol_state_t *zv, major_t maj)
155 {
156         struct g_provider *pp;
157
158         g_topology_assert();
159
160         pp = zv->zv_provider;
161         if (pp == NULL)
162                 return;
163         if (zv->zv_volsize == pp->mediasize)
164                 return;
165         /*
166          * Changing provider size is not really supported by GEOM, but it
167          * should be safe when provider is closed.
168          */
169         if (zv->zv_total_opens > 0)
170                 return;
171         pp->mediasize = zv->zv_volsize;
172 }
173
174 int
175 zvol_check_volsize(uint64_t volsize, uint64_t blocksize)
176 {
177         if (volsize == 0)
178                 return (EINVAL);
179
180         if (volsize % blocksize != 0)
181                 return (EINVAL);
182
183 #ifdef _ILP32
184         if (volsize - 1 > SPEC_MAXOFFSET_T)
185                 return (EOVERFLOW);
186 #endif
187         return (0);
188 }
189
190 int
191 zvol_check_volblocksize(uint64_t volblocksize)
192 {
193         if (volblocksize < SPA_MINBLOCKSIZE ||
194             volblocksize > SPA_MAXBLOCKSIZE ||
195             !ISP2(volblocksize))
196                 return (EDOM);
197
198         return (0);
199 }
200
201 static void
202 zvol_readonly_changed_cb(void *arg, uint64_t newval)
203 {
204         zvol_state_t *zv = arg;
205
206         if (newval)
207                 zv->zv_flags |= ZVOL_RDONLY;
208         else
209                 zv->zv_flags &= ~ZVOL_RDONLY;
210 }
211
212 int
213 zvol_get_stats(objset_t *os, nvlist_t *nv)
214 {
215         int error;
216         dmu_object_info_t doi;
217         uint64_t val;
218
219
220         error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &val);
221         if (error)
222                 return (error);
223
224         dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLSIZE, val);
225
226         error = dmu_object_info(os, ZVOL_OBJ, &doi);
227
228         if (error == 0) {
229                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLBLOCKSIZE,
230                     doi.doi_data_block_size);
231         }
232
233         return (error);
234 }
235
236 static zvol_state_t *
237 zvol_minor_lookup(const char *name)
238 {
239         struct g_provider *pp;
240         struct g_geom *gp;
241
242         g_topology_assert();
243         ASSERT(MUTEX_HELD(&zvol_state_lock));
244
245         LIST_FOREACH(gp, &zfs_zvol_class.geom, geom) {
246                 LIST_FOREACH(pp, &gp->provider, provider) {
247                         if (strcmp(pp->name + sizeof(ZVOL_DEV_DIR), name) == 0)
248                                 return (pp->private);
249                 }
250         }
251
252         return (NULL);
253 }
254
255 static int
256 zvol_access(struct g_provider *pp, int acr, int acw, int ace)
257 {
258         zvol_state_t *zv;
259
260         g_topology_assert();
261         mutex_enter(&zvol_state_lock);
262
263         zv = pp->private;
264         if (zv == NULL) {
265                 if (acr <= 0 && acw <= 0 && ace <= 0)
266                         return (0);
267                 mutex_exit(&zvol_state_lock);
268                 return (pp->error);
269         }
270
271         ASSERT(zv->zv_objset != NULL);
272
273         if (acw > 0 &&
274             ((zv->zv_flags & ZVOL_RDONLY) ||
275              (zv->zv_mode & DS_MODE_READONLY))) {
276                 mutex_exit(&zvol_state_lock);
277                 return (EROFS);
278         }
279
280         zv->zv_total_opens += acr + acw + ace;
281         zvol_size_changed(zv, 0);
282
283         mutex_exit(&zvol_state_lock);
284
285         return (0);
286 }
287
288 /*
289  * zvol_log_write() handles synchronous writes using TX_WRITE ZIL transactions.
290  *
291  * We store data in the log buffers if it's small enough.
292  * Otherwise we will later flush the data out via dmu_sync().
293  */
294 ssize_t zvol_immediate_write_sz = 32768;
295
296 static void
297 zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, offset_t off, ssize_t len)
298 {
299         uint32_t blocksize = zv->zv_volblocksize;
300         lr_write_t *lr;
301
302         while (len) {
303                 ssize_t nbytes = MIN(len, blocksize - P2PHASE(off, blocksize));
304                 itx_t *itx = zil_itx_create(TX_WRITE, sizeof (*lr));
305
306                 itx->itx_wr_state =
307                     len > zvol_immediate_write_sz ?  WR_INDIRECT : WR_NEED_COPY;
308                 itx->itx_private = zv;
309                 lr = (lr_write_t *)&itx->itx_lr;
310                 lr->lr_foid = ZVOL_OBJ;
311                 lr->lr_offset = off;
312                 lr->lr_length = nbytes;
313                 lr->lr_blkoff = off - P2ALIGN_TYPED(off, blocksize, uint64_t);
314                 BP_ZERO(&lr->lr_blkptr);
315
316                 (void) zil_itx_assign(zv->zv_zilog, itx, tx);
317                 len -= nbytes;
318                 off += nbytes;
319         }
320 }
321
322 static void
323 zvol_start(struct bio *bp)
324 {
325         zvol_state_t *zv;
326
327         switch (bp->bio_cmd) {
328         case BIO_READ:
329         case BIO_WRITE:
330         case BIO_FLUSH:
331                 zv = bp->bio_to->private;
332                 ASSERT(zv != NULL);
333                 mtx_lock(&zv->zv_queue_mtx);
334                 bioq_insert_tail(&zv->zv_queue, bp);
335                 wakeup_one(&zv->zv_queue);
336                 mtx_unlock(&zv->zv_queue_mtx);
337                 break;
338         case BIO_DELETE:
339         case BIO_GETATTR:
340         default:
341                 g_io_deliver(bp, EOPNOTSUPP);
342                 break;
343         }
344 }
345
346 static void
347 zvol_serve_one(zvol_state_t *zv, struct bio *bp)
348 {
349         uint64_t off, volsize;
350         size_t size, resid;
351         char *addr;
352         objset_t *os;
353         rl_t *rl;
354         int error = 0;
355         boolean_t reading;
356
357         off = bp->bio_offset;
358         volsize = zv->zv_volsize;
359
360         os = zv->zv_objset;
361         ASSERT(os != NULL);
362
363         addr = bp->bio_data;
364         resid = bp->bio_length;
365
366         error = 0;
367
368         /*
369          * There must be no buffer changes when doing a dmu_sync() because
370          * we can't change the data whilst calculating the checksum.
371          * A better approach than a per zvol rwlock would be to lock ranges.
372          */
373         reading = (bp->bio_cmd == BIO_READ);
374         rl = zfs_range_lock(&zv->zv_znode, off, resid,
375             reading ? RL_READER : RL_WRITER);
376
377         while (resid != 0 && off < volsize) {
378
379                 size = MIN(resid, zvol_maxphys); /* zvol_maxphys per tx */
380
381                 if (size > volsize - off)       /* don't write past the end */
382                         size = volsize - off;
383
384                 if (reading) {
385                         error = dmu_read(os, ZVOL_OBJ, off, size, addr);
386                 } else {
387                         dmu_tx_t *tx = dmu_tx_create(os);
388                         dmu_tx_hold_write(tx, ZVOL_OBJ, off, size);
389                         error = dmu_tx_assign(tx, TXG_WAIT);
390                         if (error) {
391                                 dmu_tx_abort(tx);
392                         } else {
393                                 dmu_write(os, ZVOL_OBJ, off, size, addr, tx);
394                                 zvol_log_write(zv, tx, off, size);
395                                 dmu_tx_commit(tx);
396                         }
397                 }
398                 if (error) {
399                         /* convert checksum errors into IO errors */
400                         if (error == ECKSUM)
401                                 error = EIO;
402                         break;
403                 }
404                 off += size;
405                 addr += size;
406                 resid -= size;
407         }
408         zfs_range_unlock(rl);
409
410         bp->bio_completed = bp->bio_length - resid;
411         if (bp->bio_completed < bp->bio_length)
412                 bp->bio_error = (off > volsize ? EINVAL : error);
413 }
414
415 static void
416 zvol_worker(void *arg)
417 {
418         zvol_state_t *zv;
419         struct bio *bp;
420
421         thread_lock(curthread);
422         sched_prio(curthread, PRIBIO);
423         thread_unlock(curthread);
424
425         zv = arg;
426         for (;;) {
427                 mtx_lock(&zv->zv_queue_mtx);
428                 bp = bioq_takefirst(&zv->zv_queue);
429                 if (bp == NULL) {
430                         if (zv->zv_state == 1) {
431                                 zv->zv_state = 2;
432                                 wakeup(&zv->zv_state);
433                                 mtx_unlock(&zv->zv_queue_mtx);
434                                 kthread_exit();
435                         }
436                         msleep(&zv->zv_queue, &zv->zv_queue_mtx, PRIBIO | PDROP,
437                             "zvol:io", 0);
438                         continue;
439                 }
440                 mtx_unlock(&zv->zv_queue_mtx);
441                 switch (bp->bio_cmd) {
442                 case BIO_FLUSH:
443                         break;
444                 case BIO_READ:
445                 case BIO_WRITE:
446                         zvol_serve_one(zv, bp);
447                         break;
448                 }
449
450                 if (bp->bio_cmd == BIO_FLUSH && !zil_disable)
451                         zil_commit(zv->zv_zilog, UINT64_MAX, ZVOL_OBJ);
452
453                 g_io_deliver(bp, bp->bio_error);
454         }
455 }
456
457 void
458 zvol_init_extent(zvol_extent_t *ze, blkptr_t *bp)
459 {
460         ze->ze_dva = bp->blk_dva[0];    /* structure assignment */
461         ze->ze_stride = 0;
462         ze->ze_size = 1;
463 }
464
465 /* extent mapping arg */
466 struct maparg {
467         zvol_ext_list_t *ma_list;
468         zvol_extent_t   *ma_extent;
469         int             ma_gang;
470 };
471
472 /*ARGSUSED*/
473 static int
474 zvol_map_block(traverse_blk_cache_t *bc, spa_t *spa, void *arg)
475 {
476         zbookmark_t *zb = &bc->bc_bookmark;
477         blkptr_t *bp = &bc->bc_blkptr;
478         void *data = bc->bc_data;
479         dnode_phys_t *dnp = bc->bc_dnode;
480         struct maparg *ma = (struct maparg *)arg;
481         uint64_t stride;
482
483         /* If there is an error, then keep trying to make progress */
484         if (bc->bc_errno)
485                 return (ERESTART);
486
487 #ifdef ZFS_DEBUG
488         if (zb->zb_level == -1) {
489                 ASSERT3U(BP_GET_TYPE(bp), ==, DMU_OT_OBJSET);
490                 ASSERT3U(BP_GET_LEVEL(bp), ==, 0);
491         } else {
492                 ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type);
493                 ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level);
494         }
495
496         if (zb->zb_level > 0) {
497                 uint64_t fill = 0;
498                 blkptr_t *bpx, *bpend;
499
500                 for (bpx = data, bpend = bpx + BP_GET_LSIZE(bp) / sizeof (*bpx);
501                     bpx < bpend; bpx++) {
502                         if (bpx->blk_birth != 0) {
503                                 fill += bpx->blk_fill;
504                         } else {
505                                 ASSERT(bpx->blk_fill == 0);
506                         }
507                 }
508                 ASSERT3U(fill, ==, bp->blk_fill);
509         }
510
511         if (zb->zb_level == 0 && dnp->dn_type == DMU_OT_DNODE) {
512                 uint64_t fill = 0;
513                 dnode_phys_t *dnx, *dnend;
514
515                 for (dnx = data, dnend = dnx + (BP_GET_LSIZE(bp)>>DNODE_SHIFT);
516                     dnx < dnend; dnx++) {
517                         if (dnx->dn_type != DMU_OT_NONE)
518                                 fill++;
519                 }
520                 ASSERT3U(fill, ==, bp->blk_fill);
521         }
522 #endif
523
524         if (zb->zb_level || dnp->dn_type == DMU_OT_DNODE)
525                 return (0);
526
527         /* Abort immediately if we have encountered gang blocks */
528         if (BP_IS_GANG(bp)) {
529                 ma->ma_gang++;
530                 return (EINTR);
531         }
532
533         /* first time? */
534         if (ma->ma_extent->ze_size == 0) {
535                 zvol_init_extent(ma->ma_extent, bp);
536                 return (0);
537         }
538
539         stride = (DVA_GET_OFFSET(&bp->blk_dva[0])) -
540             ((DVA_GET_OFFSET(&ma->ma_extent->ze_dva)) +
541             (ma->ma_extent->ze_size - 1) * (ma->ma_extent->ze_stride));
542         if (DVA_GET_VDEV(BP_IDENTITY(bp)) ==
543             DVA_GET_VDEV(&ma->ma_extent->ze_dva)) {
544                 if (ma->ma_extent->ze_stride == 0) {
545                         /* second block in this extent */
546                         ma->ma_extent->ze_stride = stride;
547                         ma->ma_extent->ze_size++;
548                         return (0);
549                 } else if (ma->ma_extent->ze_stride == stride) {
550                         /*
551                          * the block we allocated has the same
552                          * stride
553                          */
554                         ma->ma_extent->ze_size++;
555                         return (0);
556                 }
557         }
558
559         /*
560          * dtrace -n 'zfs-dprintf
561          * /stringof(arg0) == "zvol.c"/
562          * {
563          *      printf("%s: %s", stringof(arg1), stringof(arg3))
564          * } '
565          */
566         dprintf("ma_extent 0x%lx mrstride 0x%lx stride %lx\n",
567             ma->ma_extent->ze_size, ma->ma_extent->ze_stride, stride);
568         dprintf_bp(bp, "%s", "next blkptr:");
569         /* start a new extent */
570         if (ma->ma_extent == &ma->ma_list->zl_extents[NUM_EXTENTS - 1]) {
571                 ma->ma_list->zl_next = kmem_zalloc(sizeof (zvol_ext_list_t),
572                     KM_SLEEP);
573                 ma->ma_list = ma->ma_list->zl_next;
574                 ma->ma_extent = &ma->ma_list->zl_extents[0];
575         } else {
576                 ma->ma_extent++;
577         }
578         zvol_init_extent(ma->ma_extent, bp);
579         return (0);
580 }
581
582 /* ARGSUSED */
583 void
584 zvol_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx)
585 {
586         zfs_creat_t *zct = arg;
587         nvlist_t *nvprops = zct->zct_props;
588         int error;
589         uint64_t volblocksize, volsize;
590
591         VERIFY(nvlist_lookup_uint64(nvprops,
592             zfs_prop_to_name(ZFS_PROP_VOLSIZE), &volsize) == 0);
593         if (nvlist_lookup_uint64(nvprops,
594             zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), &volblocksize) != 0)
595                 volblocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
596
597         /*
598          * These properties must be removed from the list so the generic
599          * property setting step won't apply to them.
600          */
601         VERIFY(nvlist_remove_all(nvprops,
602             zfs_prop_to_name(ZFS_PROP_VOLSIZE)) == 0);
603         (void) nvlist_remove_all(nvprops,
604             zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE));
605
606         error = dmu_object_claim(os, ZVOL_OBJ, DMU_OT_ZVOL, volblocksize,
607             DMU_OT_NONE, 0, tx);
608         ASSERT(error == 0);
609
610         error = zap_create_claim(os, ZVOL_ZAP_OBJ, DMU_OT_ZVOL_PROP,
611             DMU_OT_NONE, 0, tx);
612         ASSERT(error == 0);
613
614         error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize, tx);
615         ASSERT(error == 0);
616 }
617
618 /*
619  * Replay a TX_WRITE ZIL transaction that didn't get committed
620  * after a system failure
621  */
622 static int
623 zvol_replay_write(zvol_state_t *zv, lr_write_t *lr, boolean_t byteswap)
624 {
625         objset_t *os = zv->zv_objset;
626         char *data = (char *)(lr + 1);  /* data follows lr_write_t */
627         uint64_t off = lr->lr_offset;
628         uint64_t len = lr->lr_length;
629         dmu_tx_t *tx;
630         int error;
631
632         if (byteswap)
633                 byteswap_uint64_array(lr, sizeof (*lr));
634
635         tx = dmu_tx_create(os);
636         dmu_tx_hold_write(tx, ZVOL_OBJ, off, len);
637         error = dmu_tx_assign(tx, zv->zv_txg_assign);
638         if (error) {
639                 dmu_tx_abort(tx);
640         } else {
641                 dmu_write(os, ZVOL_OBJ, off, len, data, tx);
642                 dmu_tx_commit(tx);
643         }
644
645         return (error);
646 }
647
648 /* ARGSUSED */
649 static int
650 zvol_replay_err(zvol_state_t *zv, lr_t *lr, boolean_t byteswap)
651 {
652         return (ENOTSUP);
653 }
654
655 /*
656  * Callback vectors for replaying records.
657  * Only TX_WRITE is needed for zvol.
658  */
659 zil_replay_func_t *zvol_replay_vector[TX_MAX_TYPE] = {
660         zvol_replay_err,        /* 0 no such transaction type */
661         zvol_replay_err,        /* TX_CREATE */
662         zvol_replay_err,        /* TX_MKDIR */
663         zvol_replay_err,        /* TX_MKXATTR */
664         zvol_replay_err,        /* TX_SYMLINK */
665         zvol_replay_err,        /* TX_REMOVE */
666         zvol_replay_err,        /* TX_RMDIR */
667         zvol_replay_err,        /* TX_LINK */
668         zvol_replay_err,        /* TX_RENAME */
669         zvol_replay_write,      /* TX_WRITE */
670         zvol_replay_err,        /* TX_TRUNCATE */
671         zvol_replay_err,        /* TX_SETATTR */
672         zvol_replay_err,        /* TX_ACL */
673 };
674
675 /*
676  * reconstruct dva that gets us to the desired offset (offset
677  * is in bytes)
678  */
679 int
680 zvol_get_dva(zvol_state_t *zv, uint64_t offset, dva_t *dva)
681 {
682         zvol_ext_list_t *zl;
683         zvol_extent_t   *ze;
684         int             idx;
685         uint64_t        tmp;
686
687         if ((zl = zv->zv_list) == NULL)
688                 return (EIO);
689         idx = 0;
690         ze =  &zl->zl_extents[0];
691         while (offset >= ze->ze_size * zv->zv_volblocksize) {
692                 offset -= ze->ze_size * zv->zv_volblocksize;
693
694                 if (idx == NUM_EXTENTS - 1) {
695                         /* we've reached the end of this array */
696                         ASSERT(zl->zl_next != NULL);
697                         if (zl->zl_next == NULL)
698                                 return (-1);
699                         zl = zl->zl_next;
700                         ze = &zl->zl_extents[0];
701                         idx = 0;
702                 } else {
703                         ze++;
704                         idx++;
705                 }
706         }
707         DVA_SET_VDEV(dva, DVA_GET_VDEV(&ze->ze_dva));
708         tmp = DVA_GET_OFFSET((&ze->ze_dva));
709         tmp += (ze->ze_stride * (offset / zv->zv_volblocksize));
710         DVA_SET_OFFSET(dva, tmp);
711         return (0);
712 }
713
714 static void
715 zvol_free_extents(zvol_state_t *zv)
716 {
717         zvol_ext_list_t *zl;
718         zvol_ext_list_t *tmp;
719
720         if (zv->zv_list != NULL) {
721                 zl = zv->zv_list;
722                 while (zl != NULL) {
723                         tmp = zl->zl_next;
724                         kmem_free(zl, sizeof (zvol_ext_list_t));
725                         zl = tmp;
726                 }
727                 zv->zv_list = NULL;
728         }
729 }
730
731 int
732 zvol_get_lbas(zvol_state_t *zv)
733 {
734         struct maparg   ma;
735         zvol_ext_list_t *zl;
736         zvol_extent_t   *ze;
737         uint64_t        blocks = 0;
738         int             err;
739
740         ma.ma_list = zl = kmem_zalloc(sizeof (zvol_ext_list_t), KM_SLEEP);
741         ma.ma_extent = &ma.ma_list->zl_extents[0];
742         ma.ma_gang = 0;
743         zv->zv_list = ma.ma_list;
744
745         err = traverse_zvol(zv->zv_objset, ADVANCE_PRE, zvol_map_block, &ma);
746         if (err == EINTR && ma.ma_gang) {
747                 /*
748                  * We currently don't support dump devices when the pool
749                  * is so fragmented that our allocation has resulted in
750                  * gang blocks.
751                  */
752                 zvol_free_extents(zv);
753                 return (EFRAGS);
754         }
755         ASSERT3U(err, ==, 0);
756
757         ze = &zl->zl_extents[0];
758         while (ze) {
759                 blocks += ze->ze_size;
760                 if (ze == &zl->zl_extents[NUM_EXTENTS - 1]) {
761                         zl = zl->zl_next;
762                         ze = &zl->zl_extents[0];
763                 } else {
764                         ze++;
765                 }
766         }
767         if (blocks != (zv->zv_volsize / zv->zv_volblocksize)) {
768                 zvol_free_extents(zv);
769                 return (EIO);
770         }
771
772         return (0);
773 }
774
775 /*
776  * Create a minor node (plus a whole lot more) for the specified volume.
777  */
778 int
779 zvol_create_minor(const char *name, major_t maj)
780 {
781         struct g_provider *pp;
782         struct g_geom *gp;
783         zvol_state_t *zv;
784         objset_t *os;
785         dmu_object_info_t doi;
786         uint64_t volsize;
787         int ds_mode = DS_MODE_OWNER;
788         int error;
789
790         DROP_GIANT();
791         g_topology_lock();
792         mutex_enter(&zvol_state_lock);
793
794         if ((zv = zvol_minor_lookup(name)) != NULL) {
795                 error = EEXIST;
796                 goto end;
797         }
798
799         if (strchr(name, '@') != 0)
800                 ds_mode |= DS_MODE_READONLY;
801
802         error = dmu_objset_open(name, DMU_OST_ZVOL, ds_mode, &os);
803         if (error)
804                 goto end;
805
806         error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
807         if (error) {
808                 dmu_objset_close(os);
809                 goto end;
810         }
811
812         gp = g_new_geomf(&zfs_zvol_class, "zfs::zvol::%s", name);
813         gp->start = zvol_start;
814         gp->access = zvol_access;
815         pp = g_new_providerf(gp, "%s/%s", ZVOL_DEV_DIR, name);
816         pp->mediasize = volsize;
817         pp->sectorsize = DEV_BSIZE;
818
819         zv = kmem_zalloc(sizeof(*zv), KM_SLEEP);
820         (void) strcpy(zv->zv_name, name);
821         zv->zv_min_bs = DEV_BSHIFT;
822         zv->zv_provider = pp;
823         zv->zv_volsize = pp->mediasize;
824         zv->zv_objset = os;
825         zv->zv_mode = ds_mode;
826         zv->zv_zilog = zil_open(os, zvol_get_data);
827         mutex_init(&zv->zv_znode.z_range_lock, NULL, MUTEX_DEFAULT, NULL);
828         avl_create(&zv->zv_znode.z_range_avl, zfs_range_compare,
829             sizeof (rl_t), offsetof(rl_t, r_node));
830         /* get and cache the blocksize */
831         error = dmu_object_info(os, ZVOL_OBJ, &doi);
832         ASSERT(error == 0);
833         zv->zv_volblocksize = doi.doi_data_block_size;
834
835         zil_replay(os, zv, &zv->zv_txg_assign, zvol_replay_vector, NULL);
836
837         /* XXX this should handle the possible i/o error */
838         VERIFY(dsl_prop_register(dmu_objset_ds(zv->zv_objset),
839             "readonly", zvol_readonly_changed_cb, zv) == 0);
840
841         pp->private = zv;
842         g_error_provider(pp, 0);
843
844         bioq_init(&zv->zv_queue);
845         mtx_init(&zv->zv_queue_mtx, "zvol", NULL, MTX_DEF);
846         zv->zv_state = 0;
847         kproc_kthread_add(zvol_worker, zv, &zfsproc, NULL, 0, 0, "zfskern",
848             "zvol %s", pp->name + strlen(ZVOL_DEV_DIR) + 1);
849
850         zvol_minors++;
851 end:
852         mutex_exit(&zvol_state_lock);
853         g_topology_unlock();
854         PICKUP_GIANT();
855
856         return (error);
857 }
858
859 /*
860  * Remove minor node for the specified volume.
861  */
862 int
863 zvol_remove_minor(const char *name)
864 {
865         struct g_provider *pp;
866         zvol_state_t *zv;
867         int error = 0;
868
869         DROP_GIANT();
870         g_topology_lock();
871         mutex_enter(&zvol_state_lock);
872
873         if ((zv = zvol_minor_lookup(name)) == NULL) {
874                 error = ENXIO;
875                 goto end;
876         }
877
878         if (zv->zv_total_opens != 0) {
879                 error = EBUSY;
880                 goto end;
881         }
882
883         VERIFY(dsl_prop_unregister(dmu_objset_ds(zv->zv_objset),
884             "readonly", zvol_readonly_changed_cb, zv) == 0);
885
886         mtx_lock(&zv->zv_queue_mtx);
887         zv->zv_state = 1;
888         wakeup_one(&zv->zv_queue);
889         while (zv->zv_state != 2)
890                 msleep(&zv->zv_state, &zv->zv_queue_mtx, 0, "zvol:w", 0);
891         mtx_unlock(&zv->zv_queue_mtx);
892         mtx_destroy(&zv->zv_queue_mtx);
893
894         pp = zv->zv_provider;
895         pp->private = NULL;
896         g_wither_geom(pp->geom, ENXIO);
897
898         zil_close(zv->zv_zilog);
899         zv->zv_zilog = NULL;
900         dmu_objset_close(zv->zv_objset);
901         zv->zv_objset = NULL;
902         avl_destroy(&zv->zv_znode.z_range_avl);
903         mutex_destroy(&zv->zv_znode.z_range_lock);
904
905         kmem_free(zv, sizeof(*zv));
906
907         zvol_minors--;
908 end:
909         mutex_exit(&zvol_state_lock);
910         g_topology_unlock();
911         PICKUP_GIANT();
912
913         return (error);
914 }
915
916 int
917 zvol_prealloc(zvol_state_t *zv)
918 {
919         objset_t *os = zv->zv_objset;
920         dmu_tx_t *tx;
921         void *data;
922         uint64_t refd, avail, usedobjs, availobjs;
923         uint64_t resid = zv->zv_volsize;
924         uint64_t off = 0;
925
926         /* Check the space usage before attempting to allocate the space */
927         dmu_objset_space(os, &refd, &avail, &usedobjs, &availobjs);
928         if (avail < zv->zv_volsize)
929                 return (ENOSPC);
930
931         /* Free old extents if they exist */
932         zvol_free_extents(zv);
933
934         /* allocate the blocks by writing each one */
935         data = kmem_zalloc(SPA_MAXBLOCKSIZE, KM_SLEEP);
936
937         while (resid != 0) {
938                 int error;
939                 uint64_t bytes = MIN(resid, SPA_MAXBLOCKSIZE);
940
941                 tx = dmu_tx_create(os);
942                 dmu_tx_hold_write(tx, ZVOL_OBJ, off, bytes);
943                 error = dmu_tx_assign(tx, TXG_WAIT);
944                 if (error) {
945                         dmu_tx_abort(tx);
946                         kmem_free(data, SPA_MAXBLOCKSIZE);
947                         (void) dmu_free_long_range(os, ZVOL_OBJ, 0, off);
948                         return (error);
949                 }
950                 dmu_write(os, ZVOL_OBJ, off, bytes, data, tx);
951                 dmu_tx_commit(tx);
952                 off += bytes;
953                 resid -= bytes;
954         }
955         kmem_free(data, SPA_MAXBLOCKSIZE);
956         txg_wait_synced(dmu_objset_pool(os), 0);
957
958         return (0);
959 }
960
961 int
962 zvol_update_volsize(zvol_state_t *zv, major_t maj, uint64_t volsize)
963 {
964         dmu_tx_t *tx;
965         int error;
966
967         ASSERT(MUTEX_HELD(&zvol_state_lock));
968
969         tx = dmu_tx_create(zv->zv_objset);
970         dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
971         error = dmu_tx_assign(tx, TXG_WAIT);
972         if (error) {
973                 dmu_tx_abort(tx);
974                 return (error);
975         }
976
977         error = zap_update(zv->zv_objset, ZVOL_ZAP_OBJ, "size", 8, 1,
978             &volsize, tx);
979         dmu_tx_commit(tx);
980
981         if (error == 0)
982                 error = dmu_free_long_range(zv->zv_objset,
983                     ZVOL_OBJ, volsize, DMU_OBJECT_END);
984
985         /*
986          * If we are using a faked-up state (zv_provider == NULL) then don't
987          * try to update the in-core zvol state.
988          */
989         if (error == 0 && zv->zv_provider) {
990                 zv->zv_volsize = volsize;
991                 zvol_size_changed(zv, maj);
992         }
993         return (error);
994 }
995
996 int
997 zvol_set_volsize(const char *name, major_t maj, uint64_t volsize)
998 {
999         zvol_state_t *zv;
1000         int error;
1001         dmu_object_info_t doi;
1002         uint64_t old_volsize = 0ULL;
1003         zvol_state_t state = { 0 };
1004
1005         DROP_GIANT();
1006         g_topology_lock();
1007         mutex_enter(&zvol_state_lock);
1008
1009         if ((zv = zvol_minor_lookup(name)) == NULL) {
1010                 /*
1011                  * If we are doing a "zfs clone -o volsize=", then the
1012                  * minor node won't exist yet.
1013                  */
1014                 error = dmu_objset_open(name, DMU_OST_ZVOL, DS_MODE_OWNER,
1015                     &state.zv_objset);
1016                 if (error != 0)
1017                         goto out;
1018                 zv = &state;
1019         }
1020         old_volsize = zv->zv_volsize;
1021
1022         if ((error = dmu_object_info(zv->zv_objset, ZVOL_OBJ, &doi)) != 0 ||
1023             (error = zvol_check_volsize(volsize,
1024             doi.doi_data_block_size)) != 0)
1025                 goto out;
1026
1027         if (zv->zv_flags & ZVOL_RDONLY || (zv->zv_mode & DS_MODE_READONLY)) {
1028                 error = EROFS;
1029                 goto out;
1030         }
1031
1032         error = zvol_update_volsize(zv, maj, volsize);
1033
1034 #if 0
1035         /*
1036          * Reinitialize the dump area to the new size. If we
1037          * failed to resize the dump area then restore the it back to
1038          * it's original size.
1039          */
1040         if (error == 0 && zv->zv_flags & ZVOL_DUMPIFIED) {
1041                 if ((error = zvol_dumpify(zv)) != 0 ||
1042                     (error = dumpvp_resize()) != 0) {
1043                         (void) zvol_update_volsize(zv, maj, old_volsize);
1044                         error = zvol_dumpify(zv);
1045                 }
1046         }
1047 #endif
1048
1049 out:
1050         if (state.zv_objset)
1051                 dmu_objset_close(state.zv_objset);
1052
1053         mutex_exit(&zvol_state_lock);
1054         g_topology_unlock();
1055         PICKUP_GIANT();
1056
1057         return (error);
1058 }
1059
1060 int
1061 zvol_set_volblocksize(const char *name, uint64_t volblocksize)
1062 {
1063         zvol_state_t *zv;
1064         dmu_tx_t *tx;
1065         int error;
1066
1067         DROP_GIANT();
1068         g_topology_lock();
1069         mutex_enter(&zvol_state_lock);
1070
1071         if ((zv = zvol_minor_lookup(name)) == NULL) {
1072                 error = ENXIO;
1073                 goto end;
1074         }
1075         if (zv->zv_flags & ZVOL_RDONLY || (zv->zv_mode & DS_MODE_READONLY)) {
1076                 error = EROFS;
1077                 goto end;
1078         }
1079
1080         tx = dmu_tx_create(zv->zv_objset);
1081         dmu_tx_hold_bonus(tx, ZVOL_OBJ);
1082         error = dmu_tx_assign(tx, TXG_WAIT);
1083         if (error) {
1084                 dmu_tx_abort(tx);
1085         } else {
1086                 error = dmu_object_set_blocksize(zv->zv_objset, ZVOL_OBJ,
1087                     volblocksize, 0, tx);
1088                 if (error == ENOTSUP)
1089                         error = EBUSY;
1090                 dmu_tx_commit(tx);
1091         }
1092 end:
1093         mutex_exit(&zvol_state_lock);
1094         g_topology_unlock();
1095         PICKUP_GIANT();
1096
1097         return (error);
1098 }
1099
1100 void
1101 zvol_get_done(dmu_buf_t *db, void *vzgd)
1102 {
1103         zgd_t *zgd = (zgd_t *)vzgd;
1104         rl_t *rl = zgd->zgd_rl;
1105
1106         dmu_buf_rele(db, vzgd);
1107         zfs_range_unlock(rl);
1108         zil_add_block(zgd->zgd_zilog, zgd->zgd_bp);
1109         kmem_free(zgd, sizeof (zgd_t));
1110 }
1111
1112 /*
1113  * Get data to generate a TX_WRITE intent log record.
1114  */
1115 static int
1116 zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
1117 {
1118         zvol_state_t *zv = arg;
1119         objset_t *os = zv->zv_objset;
1120         dmu_buf_t *db;
1121         rl_t *rl;
1122         zgd_t *zgd;
1123         uint64_t boff;                  /* block starting offset */
1124         int dlen = lr->lr_length;       /* length of user data */
1125         int error;
1126
1127         ASSERT(zio);
1128         ASSERT(dlen != 0);
1129
1130         /*
1131          * Write records come in two flavors: immediate and indirect.
1132          * For small writes it's cheaper to store the data with the
1133          * log record (immediate); for large writes it's cheaper to
1134          * sync the data and get a pointer to it (indirect) so that
1135          * we don't have to write the data twice.
1136          */
1137         if (buf != NULL) /* immediate write */
1138                 return (dmu_read(os, ZVOL_OBJ, lr->lr_offset, dlen, buf));
1139
1140         zgd = (zgd_t *)kmem_alloc(sizeof (zgd_t), KM_SLEEP);
1141         zgd->zgd_zilog = zv->zv_zilog;
1142         zgd->zgd_bp = &lr->lr_blkptr;
1143
1144         /*
1145          * Lock the range of the block to ensure that when the data is
1146          * written out and its checksum is being calculated that no other
1147          * thread can change the block.
1148          */
1149         boff = P2ALIGN_TYPED(lr->lr_offset, zv->zv_volblocksize, uint64_t);
1150         rl = zfs_range_lock(&zv->zv_znode, boff, zv->zv_volblocksize,
1151             RL_READER);
1152         zgd->zgd_rl = rl;
1153
1154         VERIFY(0 == dmu_buf_hold(os, ZVOL_OBJ, lr->lr_offset, zgd, &db));
1155         error = dmu_sync(zio, db, &lr->lr_blkptr,
1156             lr->lr_common.lrc_txg, zvol_get_done, zgd);
1157         if (error == 0)
1158                 zil_add_block(zv->zv_zilog, &lr->lr_blkptr);
1159         /*
1160          * If we get EINPROGRESS, then we need to wait for a
1161          * write IO initiated by dmu_sync() to complete before
1162          * we can release this dbuf.  We will finish everything
1163          * up in the zvol_get_done() callback.
1164          */
1165         if (error == EINPROGRESS)
1166                 return (0);
1167         dmu_buf_rele(db, zgd);
1168         zfs_range_unlock(rl);
1169         kmem_free(zgd, sizeof (zgd_t));
1170         return (error);
1171 }
1172
1173 int
1174 zvol_busy(void)
1175 {
1176         return (zvol_minors != 0);
1177 }
1178
1179 void
1180 zvol_init(void)
1181 {
1182         mutex_init(&zvol_state_lock, NULL, MUTEX_DEFAULT, NULL);
1183         ZFS_LOG(1, "ZVOL Initialized.");
1184 }
1185
1186 void
1187 zvol_fini(void)
1188 {
1189         mutex_destroy(&zvol_state_lock);
1190         ZFS_LOG(1, "ZVOL Deinitialized.");
1191 }
1192
1193 static boolean_t
1194 zvol_is_swap(zvol_state_t *zv)
1195 {
1196         vnode_t *vp;
1197         boolean_t ret = B_FALSE;
1198         char *devpath;
1199         size_t devpathlen;
1200         int error;
1201
1202 #if 0
1203         devpathlen = strlen(ZVOL_FULL_DEV_DIR) + strlen(zv->zv_name) + 1;
1204         devpath = kmem_alloc(devpathlen, KM_SLEEP);
1205         (void) sprintf(devpath, "%s%s", ZVOL_FULL_DEV_DIR, zv->zv_name);
1206         error = lookupname(devpath, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp);
1207         kmem_free(devpath, devpathlen);
1208
1209         ret = !error && IS_SWAPVP(common_specvp(vp));
1210
1211         if (vp != NULL)
1212                 VN_RELE(vp);
1213 #endif
1214
1215         return (ret);
1216 }
1217
1218 static int
1219 zvol_dump_init(zvol_state_t *zv, boolean_t resize)
1220 {
1221         dmu_tx_t *tx;
1222         int error = 0;
1223         objset_t *os = zv->zv_objset;
1224         nvlist_t *nv = NULL;
1225         uint64_t checksum, compress, refresrv;
1226
1227         ASSERT(MUTEX_HELD(&zvol_state_lock));
1228
1229         tx = dmu_tx_create(os);
1230         dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
1231         error = dmu_tx_assign(tx, TXG_WAIT);
1232         if (error) {
1233                 dmu_tx_abort(tx);
1234                 return (error);
1235         }
1236
1237         /*
1238          * If we are resizing the dump device then we only need to
1239          * update the refreservation to match the newly updated
1240          * zvolsize. Otherwise, we save off the original state of the
1241          * zvol so that we can restore them if the zvol is ever undumpified.
1242          */
1243         if (resize) {
1244                 error = zap_update(os, ZVOL_ZAP_OBJ,
1245                     zfs_prop_to_name(ZFS_PROP_REFRESERVATION), 8, 1,
1246                     &zv->zv_volsize, tx);
1247         } else {
1248                 error = dsl_prop_get_integer(zv->zv_name,
1249                     zfs_prop_to_name(ZFS_PROP_COMPRESSION), &compress, NULL);
1250                 error = error ? error : dsl_prop_get_integer(zv->zv_name,
1251                     zfs_prop_to_name(ZFS_PROP_CHECKSUM), &checksum, NULL);
1252                 error = error ? error : dsl_prop_get_integer(zv->zv_name,
1253                     zfs_prop_to_name(ZFS_PROP_REFRESERVATION), &refresrv, NULL);
1254
1255                 error = error ? error : zap_update(os, ZVOL_ZAP_OBJ,
1256                     zfs_prop_to_name(ZFS_PROP_COMPRESSION), 8, 1,
1257                     &compress, tx);
1258                 error = error ? error : zap_update(os, ZVOL_ZAP_OBJ,
1259                     zfs_prop_to_name(ZFS_PROP_CHECKSUM), 8, 1, &checksum, tx);
1260                 error = error ? error : zap_update(os, ZVOL_ZAP_OBJ,
1261                     zfs_prop_to_name(ZFS_PROP_REFRESERVATION), 8, 1,
1262                     &refresrv, tx);
1263         }
1264         dmu_tx_commit(tx);
1265
1266         /* Truncate the file */
1267         if (!error)
1268                 error = dmu_free_long_range(zv->zv_objset,
1269                     ZVOL_OBJ, 0, DMU_OBJECT_END);
1270
1271         if (error)
1272                 return (error);
1273
1274         /*
1275          * We only need update the zvol's property if we are initializing
1276          * the dump area for the first time.
1277          */
1278         if (!resize) {
1279                 VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1280                 VERIFY(nvlist_add_uint64(nv,
1281                     zfs_prop_to_name(ZFS_PROP_REFRESERVATION), 0) == 0);
1282                 VERIFY(nvlist_add_uint64(nv,
1283                     zfs_prop_to_name(ZFS_PROP_COMPRESSION),
1284                     ZIO_COMPRESS_OFF) == 0);
1285                 VERIFY(nvlist_add_uint64(nv,
1286                     zfs_prop_to_name(ZFS_PROP_CHECKSUM),
1287                     ZIO_CHECKSUM_OFF) == 0);
1288
1289                 error = zfs_set_prop_nvlist(zv->zv_name, nv);
1290                 nvlist_free(nv);
1291
1292                 if (error)
1293                         return (error);
1294         }
1295
1296         /* Allocate the space for the dump */
1297         error = zvol_prealloc(zv);
1298         return (error);
1299 }
1300
1301 static int
1302 zvol_dumpify(zvol_state_t *zv)
1303 {
1304         int error = 0;
1305         uint64_t dumpsize = 0;
1306         dmu_tx_t *tx;
1307         objset_t *os = zv->zv_objset;
1308
1309         if (zv->zv_flags & ZVOL_RDONLY || (zv->zv_mode & DS_MODE_READONLY))
1310                 return (EROFS);
1311
1312         /*
1313          * We do not support swap devices acting as dump devices.
1314          */
1315         if (zvol_is_swap(zv))
1316                 return (ENOTSUP);
1317
1318         if (zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ, ZVOL_DUMPSIZE,
1319             8, 1, &dumpsize) != 0 || dumpsize != zv->zv_volsize) {
1320                 boolean_t resize = (dumpsize > 0) ? B_TRUE : B_FALSE;
1321
1322                 if ((error = zvol_dump_init(zv, resize)) != 0) {
1323                         (void) zvol_dump_fini(zv);
1324                         return (error);
1325                 }
1326         }
1327
1328         /*
1329          * Build up our lba mapping.
1330          */
1331         error = zvol_get_lbas(zv);
1332         if (error) {
1333                 (void) zvol_dump_fini(zv);
1334                 return (error);
1335         }
1336
1337         tx = dmu_tx_create(os);
1338         dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
1339         error = dmu_tx_assign(tx, TXG_WAIT);
1340         if (error) {
1341                 dmu_tx_abort(tx);
1342                 (void) zvol_dump_fini(zv);
1343                 return (error);
1344         }
1345
1346         zv->zv_flags |= ZVOL_DUMPIFIED;
1347         error = zap_update(os, ZVOL_ZAP_OBJ, ZVOL_DUMPSIZE, 8, 1,
1348             &zv->zv_volsize, tx);
1349         dmu_tx_commit(tx);
1350
1351         if (error) {
1352                 (void) zvol_dump_fini(zv);
1353                 return (error);
1354         }
1355
1356         txg_wait_synced(dmu_objset_pool(os), 0);
1357         return (0);
1358 }
1359
1360 static int
1361 zvol_dump_fini(zvol_state_t *zv)
1362 {
1363         dmu_tx_t *tx;
1364         objset_t *os = zv->zv_objset;
1365         nvlist_t *nv;
1366         int error = 0;
1367         uint64_t checksum, compress, refresrv;
1368
1369         /*
1370          * Attempt to restore the zvol back to its pre-dumpified state.
1371          * This is a best-effort attempt as it's possible that not all
1372          * of these properties were initialized during the dumpify process
1373          * (i.e. error during zvol_dump_init).
1374          */
1375
1376         tx = dmu_tx_create(os);
1377         dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
1378         error = dmu_tx_assign(tx, TXG_WAIT);
1379         if (error) {
1380                 dmu_tx_abort(tx);
1381                 return (error);
1382         }
1383         (void) zap_remove(os, ZVOL_ZAP_OBJ, ZVOL_DUMPSIZE, tx);
1384         dmu_tx_commit(tx);
1385
1386         (void) zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ,
1387             zfs_prop_to_name(ZFS_PROP_CHECKSUM), 8, 1, &checksum);
1388         (void) zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ,
1389             zfs_prop_to_name(ZFS_PROP_COMPRESSION), 8, 1, &compress);
1390         (void) zap_lookup(zv->zv_objset, ZVOL_ZAP_OBJ,
1391             zfs_prop_to_name(ZFS_PROP_REFRESERVATION), 8, 1, &refresrv);
1392
1393         VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1394         (void) nvlist_add_uint64(nv,
1395             zfs_prop_to_name(ZFS_PROP_CHECKSUM), checksum);
1396         (void) nvlist_add_uint64(nv,
1397             zfs_prop_to_name(ZFS_PROP_COMPRESSION), compress);
1398         (void) nvlist_add_uint64(nv,
1399             zfs_prop_to_name(ZFS_PROP_REFRESERVATION), refresrv);
1400         (void) zfs_set_prop_nvlist(zv->zv_name, nv);
1401         nvlist_free(nv);
1402
1403         zvol_free_extents(zv);
1404         zv->zv_flags &= ~ZVOL_DUMPIFIED;
1405         (void) dmu_free_long_range(os, ZVOL_OBJ, 0, DMU_OBJECT_END);
1406
1407         return (0);
1408 }