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