]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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 2007 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29
30 #pragma ident   "%Z%%M% %I%     %E% SMI"
31
32 /*
33  * ZFS volume emulation driver.
34  *
35  * Makes a DMU object look like a volume of arbitrary size, up to 2^64 bytes.
36  * Volumes are accessed through the symbolic links named:
37  *
38  * /dev/zvol/dsk/<pool_name>/<dataset_name>
39  * /dev/zvol/rdsk/<pool_name>/<dataset_name>
40  *
41  * These links are created by the ZFS-specific devfsadm link generator.
42  * Volumes are persistent through reboot.  No user command needs to be
43  * run before opening and using a device.
44  */
45
46 #include <sys/types.h>
47 #include <sys/param.h>
48 #include <sys/kernel.h>
49 #include <sys/errno.h>
50 #include <sys/uio.h>
51 #include <sys/bio.h>
52 #include <sys/buf.h>
53 #include <sys/kmem.h>
54 #include <sys/conf.h>
55 #include <sys/cmn_err.h>
56 #include <sys/stat.h>
57 #include <sys/zap.h>
58 #include <sys/spa.h>
59 #include <sys/zio.h>
60 #include <sys/dsl_prop.h>
61 #include <sys/dkio.h>
62 #include <sys/byteorder.h>
63 #include <sys/sunddi.h>
64 #include <sys/dirent.h>
65 #include <sys/policy.h>
66 #include <sys/fs/zfs.h>
67 #include <sys/zfs_ioctl.h>
68 #include <sys/zil.h>
69 #include <sys/refcount.h>
70 #include <sys/zfs_znode.h>
71 #include <sys/zfs_rlock.h>
72 #include <geom/geom.h>
73
74 #include "zfs_namecheck.h"
75
76 struct g_class zfs_zvol_class = {
77         .name = "ZFS::ZVOL",
78         .version = G_VERSION,
79 };
80
81 DECLARE_GEOM_CLASS(zfs_zvol_class, zfs_zvol);
82
83 #define ZVOL_OBJ                1ULL
84 #define ZVOL_ZAP_OBJ            2ULL
85
86 static uint32_t zvol_minors;
87
88 /*
89  * The in-core state of each volume.
90  */
91 typedef struct zvol_state {
92         char            zv_name[MAXPATHLEN]; /* pool/dd name */
93         uint64_t        zv_volsize;     /* amount of space we advertise */
94         uint64_t        zv_volblocksize; /* volume block size */
95         struct g_provider *zv_provider; /* GEOM provider */
96         uint8_t         zv_min_bs;      /* minimum addressable block shift */
97         uint8_t         zv_readonly;    /* hard readonly; like write-protect */
98         objset_t        *zv_objset;     /* objset handle */
99         uint32_t        zv_mode;        /* DS_MODE_* flags at open time */
100         uint32_t        zv_total_opens; /* total open count */
101         zilog_t         *zv_zilog;      /* ZIL handle */
102         uint64_t        zv_txg_assign;  /* txg to assign during ZIL replay */
103         znode_t         zv_znode;       /* for range locking */
104         int             zv_state;
105         struct bio_queue_head zv_queue;
106         struct mtx      zv_queue_mtx;   /* zv_queue mutex */
107 } zvol_state_t;
108
109 /*
110  * zvol maximum transfer in one DMU tx.
111  */
112 int zvol_maxphys = DMU_MAX_ACCESS/2;
113
114 static int zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio);
115
116 int
117 zvol_check_volsize(uint64_t volsize, uint64_t blocksize)
118 {
119         if (volsize == 0)
120                 return (EINVAL);
121
122         if (volsize % blocksize != 0)
123                 return (EINVAL);
124
125 #ifdef _ILP32
126         if (volsize - 1 > SPEC_MAXOFFSET_T)
127                 return (EOVERFLOW);
128 #endif
129         return (0);
130 }
131
132 int
133 zvol_check_volblocksize(uint64_t volblocksize)
134 {
135         if (volblocksize < SPA_MINBLOCKSIZE ||
136             volblocksize > SPA_MAXBLOCKSIZE ||
137             !ISP2(volblocksize))
138                 return (EDOM);
139
140         return (0);
141 }
142
143 static void
144 zvol_readonly_changed_cb(void *arg, uint64_t newval)
145 {
146         zvol_state_t *zv = arg;
147
148         zv->zv_readonly = (uint8_t)newval;
149 }
150
151 int
152 zvol_get_stats(objset_t *os, nvlist_t *nv)
153 {
154         int error;
155         dmu_object_info_t doi;
156         uint64_t val;
157
158
159         error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &val);
160         if (error)
161                 return (error);
162
163         dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLSIZE, val);
164
165         error = dmu_object_info(os, ZVOL_OBJ, &doi);
166
167         if (error == 0) {
168                 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLBLOCKSIZE,
169                     doi.doi_data_block_size);
170         }
171
172         return (error);
173 }
174
175 static zvol_state_t *
176 zvol_minor_lookup(const char *name)
177 {
178         struct g_provider *pp;
179         struct g_geom *gp;
180
181         g_topology_assert();
182
183         LIST_FOREACH(gp, &zfs_zvol_class.geom, geom) {
184                 LIST_FOREACH(pp, &gp->provider, provider) {
185                         if (strcmp(pp->name + sizeof(ZVOL_DEV_DIR), name) == 0)
186                                 return (pp->private);
187                 }
188         }
189
190         return (NULL);
191 }
192
193 static int
194 zvol_access(struct g_provider *pp, int acr, int acw, int ace)
195 {
196         zvol_state_t *zv;
197
198         g_topology_assert();
199
200         zv = pp->private;
201         if (zv == NULL) {
202                 if (acr <= 0 && acw <= 0 && ace <= 0)
203                         return (0);
204                 return (pp->error);
205         }
206
207         ASSERT(zv->zv_objset != NULL);
208
209         if (acw > 0 && (zv->zv_readonly || (zv->zv_mode & DS_MODE_READONLY)))
210                 return (EROFS);
211
212         zv->zv_total_opens += acr + acw + ace;
213
214         return (0);
215 }
216
217 /*
218  * zvol_log_write() handles synchronous writes using TX_WRITE ZIL transactions.
219  *
220  * We store data in the log buffers if it's small enough.
221  * Otherwise we will later flush the data out via dmu_sync().
222  */
223 ssize_t zvol_immediate_write_sz = 32768;
224
225 static void
226 zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, offset_t off, ssize_t len)
227 {
228         uint32_t blocksize = zv->zv_volblocksize;
229         lr_write_t *lr;
230
231         while (len) {
232                 ssize_t nbytes = MIN(len, blocksize - P2PHASE(off, blocksize));
233                 itx_t *itx = zil_itx_create(TX_WRITE, sizeof (*lr));
234
235                 itx->itx_wr_state =
236                     len > zvol_immediate_write_sz ?  WR_INDIRECT : WR_NEED_COPY;
237                 itx->itx_private = zv;
238                 lr = (lr_write_t *)&itx->itx_lr;
239                 lr->lr_foid = ZVOL_OBJ;
240                 lr->lr_offset = off;
241                 lr->lr_length = nbytes;
242                 lr->lr_blkoff = off - P2ALIGN_TYPED(off, blocksize, uint64_t);
243                 BP_ZERO(&lr->lr_blkptr);
244
245                 (void) zil_itx_assign(zv->zv_zilog, itx, tx);
246                 len -= nbytes;
247                 off += nbytes;
248         }
249 }
250
251 static void
252 zvol_start(struct bio *bp)
253 {
254         zvol_state_t *zv;
255
256         switch (bp->bio_cmd) {
257         case BIO_READ:
258         case BIO_WRITE:
259         case BIO_FLUSH:
260                 zv = bp->bio_to->private;
261                 ASSERT(zv != NULL);
262                 mtx_lock(&zv->zv_queue_mtx);
263                 bioq_insert_tail(&zv->zv_queue, bp);
264                 wakeup_one(&zv->zv_queue);
265                 mtx_unlock(&zv->zv_queue_mtx);
266                 break;
267         case BIO_DELETE:
268         case BIO_GETATTR:
269         default:
270                 g_io_deliver(bp, EOPNOTSUPP);
271                 break;
272         }
273 }
274
275 static void
276 zvol_serve_one(zvol_state_t *zv, struct bio *bp)
277 {
278         uint64_t off, volsize;
279         size_t size, resid;
280         char *addr;
281         objset_t *os;
282         rl_t *rl;
283         int error = 0;
284         boolean_t reading;
285
286         off = bp->bio_offset;
287         volsize = zv->zv_volsize;
288
289         os = zv->zv_objset;
290         ASSERT(os != NULL);
291
292         addr = bp->bio_data;
293         resid = bp->bio_length;
294
295         error = 0;
296
297         /*
298          * There must be no buffer changes when doing a dmu_sync() because
299          * we can't change the data whilst calculating the checksum.
300          * A better approach than a per zvol rwlock would be to lock ranges.
301          */
302         reading = (bp->bio_cmd == BIO_READ);
303         rl = zfs_range_lock(&zv->zv_znode, off, resid,
304             reading ? RL_READER : RL_WRITER);
305
306         while (resid != 0 && off < volsize) {
307
308                 size = MIN(resid, zvol_maxphys); /* zvol_maxphys per tx */
309
310                 if (size > volsize - off)       /* don't write past the end */
311                         size = volsize - off;
312
313                 if (reading) {
314                         error = dmu_read(os, ZVOL_OBJ, off, size, addr);
315                 } else {
316                         dmu_tx_t *tx = dmu_tx_create(os);
317                         dmu_tx_hold_write(tx, ZVOL_OBJ, off, size);
318                         error = dmu_tx_assign(tx, TXG_WAIT);
319                         if (error) {
320                                 dmu_tx_abort(tx);
321                         } else {
322                                 dmu_write(os, ZVOL_OBJ, off, size, addr, tx);
323                                 zvol_log_write(zv, tx, off, size);
324                                 dmu_tx_commit(tx);
325                         }
326                 }
327                 if (error)
328                         break;
329                 off += size;
330                 addr += size;
331                 resid -= size;
332         }
333         zfs_range_unlock(rl);
334
335         bp->bio_completed = bp->bio_length - resid;
336         if (bp->bio_completed < bp->bio_length)
337                 bp->bio_error = (off > volsize ? EINVAL : error);
338 }
339
340 static void
341 zvol_worker(void *arg)
342 {
343         zvol_state_t *zv;
344         struct bio *bp;
345
346         zv = arg;
347         for (;;) {
348                 mtx_lock(&zv->zv_queue_mtx);
349                 bp = bioq_takefirst(&zv->zv_queue);
350                 if (bp == NULL) {
351                         if (zv->zv_state == 1) {
352                                 zv->zv_state = 2;
353                                 wakeup(&zv->zv_state);
354                                 mtx_unlock(&zv->zv_queue_mtx);
355                                 kthread_exit(0);
356                         }
357                         msleep(&zv->zv_queue, &zv->zv_queue_mtx, PRIBIO | PDROP,
358                             "zvol:io", 0);
359                         continue;
360                 }
361                 mtx_unlock(&zv->zv_queue_mtx);
362                 switch (bp->bio_cmd) {
363                 case BIO_FLUSH:
364                         break;
365                 case BIO_READ:
366                 case BIO_WRITE:
367                         zvol_serve_one(zv, bp);
368                         break;
369                 }
370
371                 if (bp->bio_cmd != BIO_READ && !zil_disable)
372                         zil_commit(zv->zv_zilog, UINT64_MAX, ZVOL_OBJ);
373
374                 g_io_deliver(bp, bp->bio_error);
375         }
376 }
377
378 void
379 zvol_create_cb(objset_t *os, void *arg, dmu_tx_t *tx)
380 {
381         zfs_create_data_t *zc = arg;
382         int error;
383         uint64_t volblocksize, volsize;
384
385         VERIFY(nvlist_lookup_uint64(zc->zc_props,
386             zfs_prop_to_name(ZFS_PROP_VOLSIZE), &volsize) == 0);
387         if (nvlist_lookup_uint64(zc->zc_props,
388             zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), &volblocksize) != 0)
389                 volblocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
390
391         /*
392          * These properites must be removed from the list so the generic
393          * property setting step won't apply to them.
394          */
395         VERIFY(nvlist_remove_all(zc->zc_props,
396             zfs_prop_to_name(ZFS_PROP_VOLSIZE)) == 0);
397         (void) nvlist_remove_all(zc->zc_props,
398             zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE));
399
400         error = dmu_object_claim(os, ZVOL_OBJ, DMU_OT_ZVOL, volblocksize,
401             DMU_OT_NONE, 0, tx);
402         ASSERT(error == 0);
403
404         error = zap_create_claim(os, ZVOL_ZAP_OBJ, DMU_OT_ZVOL_PROP,
405             DMU_OT_NONE, 0, tx);
406         ASSERT(error == 0);
407
408         error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize, tx);
409         ASSERT(error == 0);
410 }
411
412 /*
413  * Replay a TX_WRITE ZIL transaction that didn't get committed
414  * after a system failure
415  */
416 static int
417 zvol_replay_write(zvol_state_t *zv, lr_write_t *lr, boolean_t byteswap)
418 {
419         objset_t *os = zv->zv_objset;
420         char *data = (char *)(lr + 1);  /* data follows lr_write_t */
421         uint64_t off = lr->lr_offset;
422         uint64_t len = lr->lr_length;
423         dmu_tx_t *tx;
424         int error;
425
426         if (byteswap)
427                 byteswap_uint64_array(lr, sizeof (*lr));
428
429         tx = dmu_tx_create(os);
430         dmu_tx_hold_write(tx, ZVOL_OBJ, off, len);
431         error = dmu_tx_assign(tx, zv->zv_txg_assign);
432         if (error) {
433                 dmu_tx_abort(tx);
434         } else {
435                 dmu_write(os, ZVOL_OBJ, off, len, data, tx);
436                 dmu_tx_commit(tx);
437         }
438
439         return (error);
440 }
441
442 /* ARGSUSED */
443 static int
444 zvol_replay_err(zvol_state_t *zv, lr_t *lr, boolean_t byteswap)
445 {
446         return (ENOTSUP);
447 }
448
449 /*
450  * Callback vectors for replaying records.
451  * Only TX_WRITE is needed for zvol.
452  */
453 zil_replay_func_t *zvol_replay_vector[TX_MAX_TYPE] = {
454         zvol_replay_err,        /* 0 no such transaction type */
455         zvol_replay_err,        /* TX_CREATE */
456         zvol_replay_err,        /* TX_MKDIR */
457         zvol_replay_err,        /* TX_MKXATTR */
458         zvol_replay_err,        /* TX_SYMLINK */
459         zvol_replay_err,        /* TX_REMOVE */
460         zvol_replay_err,        /* TX_RMDIR */
461         zvol_replay_err,        /* TX_LINK */
462         zvol_replay_err,        /* TX_RENAME */
463         zvol_replay_write,      /* TX_WRITE */
464         zvol_replay_err,        /* TX_TRUNCATE */
465         zvol_replay_err,        /* TX_SETATTR */
466         zvol_replay_err,        /* TX_ACL */
467 };
468
469 /*
470  * Create a minor node for the specified volume.
471  */
472 int
473 zvol_create_minor(const char *name, dev_t dev)
474 {
475         struct g_provider *pp;
476         struct g_geom *gp;
477         zvol_state_t *zv;
478         objset_t *os;
479         dmu_object_info_t doi;
480         uint64_t volsize;
481         int ds_mode = DS_MODE_PRIMARY;
482         int error;
483
484         DROP_GIANT();
485         g_topology_lock();
486
487         if ((zv = zvol_minor_lookup(name)) != NULL) {
488                 error = EEXIST;
489                 goto end;
490         }
491
492         if (strchr(name, '@') != 0)
493                 ds_mode |= DS_MODE_READONLY;
494
495         error = dmu_objset_open(name, DMU_OST_ZVOL, ds_mode, &os);
496         if (error)
497                 goto end;
498
499         g_topology_unlock();
500         PICKUP_GIANT();
501         error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
502         DROP_GIANT();
503         g_topology_lock();
504         if (error) {
505                 dmu_objset_close(os);
506                 goto end;
507         }
508
509         gp = g_new_geomf(&zfs_zvol_class, "zfs::zvol::%s", name);
510         gp->start = zvol_start;
511         gp->access = zvol_access;
512         pp = g_new_providerf(gp, "%s/%s", ZVOL_DEV_DIR, name);
513         pp->mediasize = volsize;
514         pp->sectorsize = DEV_BSIZE;
515
516         zv = kmem_zalloc(sizeof(*zv), KM_SLEEP);
517         (void) strcpy(zv->zv_name, name);
518         zv->zv_min_bs = DEV_BSHIFT;
519         zv->zv_provider = pp;
520         zv->zv_volsize = pp->mediasize;
521         zv->zv_objset = os;
522         zv->zv_mode = ds_mode;
523         zv->zv_zilog = zil_open(os, zvol_get_data);
524         mutex_init(&zv->zv_znode.z_range_lock, NULL, MUTEX_DEFAULT, NULL);
525         avl_create(&zv->zv_znode.z_range_avl, zfs_range_compare,
526             sizeof (rl_t), offsetof(rl_t, r_node));
527
528
529         /* get and cache the blocksize */
530         error = dmu_object_info(os, ZVOL_OBJ, &doi);
531         ASSERT(error == 0);
532         zv->zv_volblocksize = doi.doi_data_block_size;
533
534         zil_replay(os, zv, &zv->zv_txg_assign, zvol_replay_vector);
535
536         /* XXX this should handle the possible i/o error */
537         VERIFY(dsl_prop_register(dmu_objset_ds(zv->zv_objset),
538             "readonly", zvol_readonly_changed_cb, zv) == 0);
539
540         pp->private = zv;
541         g_error_provider(pp, 0);
542
543         bioq_init(&zv->zv_queue);
544         mtx_init(&zv->zv_queue_mtx, "zvol", NULL, MTX_DEF);
545         zv->zv_state = 0;
546         kthread_create(zvol_worker, zv, NULL, 0, 0, "zvol:worker %s", pp->name);
547
548         zvol_minors++;
549 end:
550         g_topology_unlock();
551         PICKUP_GIANT();
552
553         return (error);
554 }
555
556 /*
557  * Remove minor node for the specified volume.
558  */
559 int
560 zvol_remove_minor(const char *name)
561 {
562         struct g_provider *pp;
563         zvol_state_t *zv;
564         int error = 0;
565
566         DROP_GIANT();
567         g_topology_lock();
568
569         if ((zv = zvol_minor_lookup(name)) == NULL) {
570                 error = ENXIO;
571                 goto end;
572         }
573
574         if (zv->zv_total_opens != 0) {
575                 error = EBUSY;
576                 goto end;
577         }
578
579         VERIFY(dsl_prop_unregister(dmu_objset_ds(zv->zv_objset),
580             "readonly", zvol_readonly_changed_cb, zv) == 0);
581
582         mtx_lock(&zv->zv_queue_mtx);
583         zv->zv_state = 1;
584         wakeup_one(&zv->zv_queue);
585         while (zv->zv_state != 2)
586                 msleep(&zv->zv_state, &zv->zv_queue_mtx, 0, "zvol:w", 0);
587         mtx_unlock(&zv->zv_queue_mtx);
588         mtx_destroy(&zv->zv_queue_mtx);
589
590         pp = zv->zv_provider;
591         pp->private = NULL;
592         g_wither_geom(pp->geom, ENXIO);
593
594         zil_close(zv->zv_zilog);
595         zv->zv_zilog = NULL;
596         dmu_objset_close(zv->zv_objset);
597         zv->zv_objset = NULL;
598         avl_destroy(&zv->zv_znode.z_range_avl);
599         mutex_destroy(&zv->zv_znode.z_range_lock);
600
601         kmem_free(zv, sizeof(*zv));
602
603         zvol_minors--;
604 end:
605         g_topology_unlock();
606         PICKUP_GIANT();
607
608         return (error);
609 }
610
611 int
612 zvol_set_volsize(const char *name, dev_t dev, uint64_t volsize)
613 {
614         zvol_state_t *zv;
615         dmu_tx_t *tx;
616         int error;
617         dmu_object_info_t doi;
618
619         DROP_GIANT();
620         g_topology_lock();
621
622         if ((zv = zvol_minor_lookup(name)) == NULL) {
623                 error = ENXIO;
624                 goto end;
625         }
626
627         if ((error = dmu_object_info(zv->zv_objset, ZVOL_OBJ, &doi)) != 0 ||
628             (error = zvol_check_volsize(volsize,
629             doi.doi_data_block_size)) != 0) {
630                 goto end;
631         }
632
633         if (zv->zv_readonly || (zv->zv_mode & DS_MODE_READONLY)) {
634                 error = EROFS;
635                 goto end;
636         }
637
638         tx = dmu_tx_create(zv->zv_objset);
639         dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
640         dmu_tx_hold_free(tx, ZVOL_OBJ, volsize, DMU_OBJECT_END);
641         error = dmu_tx_assign(tx, TXG_WAIT);
642         if (error) {
643                 dmu_tx_abort(tx);
644                 goto end;
645         }
646
647         error = zap_update(zv->zv_objset, ZVOL_ZAP_OBJ, "size", 8, 1,
648             &volsize, tx);
649         if (error == 0) {
650                 error = dmu_free_range(zv->zv_objset, ZVOL_OBJ, volsize,
651                     DMU_OBJECT_END, tx);
652         }
653
654         dmu_tx_commit(tx);
655
656         if (error == 0) {
657                 zv->zv_volsize = volsize;
658                 zv->zv_provider->mediasize = volsize;   /* XXX: Not supported. */
659         }
660 end:
661         g_topology_unlock();
662         PICKUP_GIANT();
663
664         return (error);
665 }
666
667 int
668 zvol_set_volblocksize(const char *name, uint64_t volblocksize)
669 {
670         zvol_state_t *zv;
671         dmu_tx_t *tx;
672         int error;
673
674         DROP_GIANT();
675         g_topology_lock();
676
677         if ((zv = zvol_minor_lookup(name)) == NULL) {
678                 error = ENXIO;
679                 goto end;
680         }
681
682         if (zv->zv_readonly || (zv->zv_mode & DS_MODE_READONLY)) {
683                 error = EROFS;
684                 goto end;
685         }
686
687         tx = dmu_tx_create(zv->zv_objset);
688         dmu_tx_hold_bonus(tx, ZVOL_OBJ);
689         error = dmu_tx_assign(tx, TXG_WAIT);
690         if (error) {
691                 dmu_tx_abort(tx);
692         } else {
693                 error = dmu_object_set_blocksize(zv->zv_objset, ZVOL_OBJ,
694                     volblocksize, 0, tx);
695                 if (error == ENOTSUP)
696                         error = EBUSY;
697                 dmu_tx_commit(tx);
698                 /* XXX: Not supported. */
699 #if 0
700                 if (error == 0)
701                         zv->zv_provider->sectorsize = zc->zc_volblocksize;
702 #endif
703         }
704 end:
705         g_topology_unlock();
706         PICKUP_GIANT();
707
708         return (error);
709 }
710
711 void
712 zvol_get_done(dmu_buf_t *db, void *vzgd)
713 {
714         zgd_t *zgd = (zgd_t *)vzgd;
715         rl_t *rl = zgd->zgd_rl;
716
717         dmu_buf_rele(db, vzgd);
718         zfs_range_unlock(rl);
719         zil_add_vdev(zgd->zgd_zilog, DVA_GET_VDEV(BP_IDENTITY(zgd->zgd_bp)));
720         kmem_free(zgd, sizeof (zgd_t));
721 }
722
723 /*
724  * Get data to generate a TX_WRITE intent log record.
725  */
726 static int
727 zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
728 {
729         zvol_state_t *zv = arg;
730         objset_t *os = zv->zv_objset;
731         dmu_buf_t *db;
732         rl_t *rl;
733         zgd_t *zgd;
734         uint64_t boff;                  /* block starting offset */
735         int dlen = lr->lr_length;       /* length of user data */
736         int error;
737
738         ASSERT(zio);
739         ASSERT(dlen != 0);
740
741         /*
742          * Write records come in two flavors: immediate and indirect.
743          * For small writes it's cheaper to store the data with the
744          * log record (immediate); for large writes it's cheaper to
745          * sync the data and get a pointer to it (indirect) so that
746          * we don't have to write the data twice.
747          */
748         if (buf != NULL) /* immediate write */
749                 return (dmu_read(os, ZVOL_OBJ, lr->lr_offset, dlen, buf));
750
751         zgd = (zgd_t *)kmem_alloc(sizeof (zgd_t), KM_SLEEP);
752         zgd->zgd_zilog = zv->zv_zilog;
753         zgd->zgd_bp = &lr->lr_blkptr;
754
755         /*
756          * Lock the range of the block to ensure that when the data is
757          * written out and it's checksum is being calculated that no other
758          * thread can change the block.
759          */
760         boff = P2ALIGN_TYPED(lr->lr_offset, zv->zv_volblocksize, uint64_t);
761         rl = zfs_range_lock(&zv->zv_znode, boff, zv->zv_volblocksize,
762             RL_READER);
763         zgd->zgd_rl = rl;
764
765         VERIFY(0 == dmu_buf_hold(os, ZVOL_OBJ, lr->lr_offset, zgd, &db));
766         error = dmu_sync(zio, db, &lr->lr_blkptr,
767             lr->lr_common.lrc_txg, zvol_get_done, zgd);
768         if (error == 0)
769                 zil_add_vdev(zv->zv_zilog,
770                     DVA_GET_VDEV(BP_IDENTITY(&lr->lr_blkptr)));
771         /*
772          * If we get EINPROGRESS, then we need to wait for a
773          * write IO initiated by dmu_sync() to complete before
774          * we can release this dbuf.  We will finish everything
775          * up in the zvol_get_done() callback.
776          */
777         if (error == EINPROGRESS)
778                 return (0);
779         dmu_buf_rele(db, zgd);
780         zfs_range_unlock(rl);
781         kmem_free(zgd, sizeof (zgd_t));
782         return (error);
783 }
784
785 int
786 zvol_busy(void)
787 {
788         return (zvol_minors != 0);
789 }
790
791 void
792 zvol_init(void)
793 {
794         ZFS_LOG(1, "ZVOL Initialized.");
795 }
796
797 void
798 zvol_fini(void)
799 {
800         ZFS_LOG(1, "ZVOL Deinitialized.");
801 }