]> git.proxmox.com Git - mirror_zfs-debian.git/blobdiff - module/zfs/zvol.c
Imported Upstream version 0.6.4.2
[mirror_zfs-debian.git] / module / zfs / zvol.c
index fa5c7eb4e2c88a8cd0e484ad63db0c31005a15dc..d180b5b5b76f468ba67aa6b71e5f35d094727c11 100644 (file)
@@ -577,20 +577,13 @@ zvol_write(void *arg)
        struct request *req = (struct request *)arg;
        struct request_queue *q = req->q;
        zvol_state_t *zv = q->queuedata;
+       fstrans_cookie_t cookie = spl_fstrans_mark();
        uint64_t offset = blk_rq_pos(req) << 9;
        uint64_t size = blk_rq_bytes(req);
        int error = 0;
        dmu_tx_t *tx;
        rl_t *rl;
 
-       /*
-        * Annotate this call path with a flag that indicates that it is
-        * unsafe to use KM_SLEEP during memory allocations due to the
-        * potential for a deadlock.  KM_PUSHPAGE should be used instead.
-        */
-       ASSERT(!(current->flags & PF_NOFS));
-       current->flags |= PF_NOFS;
-
        if (req->cmd_flags & VDEV_REQ_FLUSH)
                zil_commit(zv->zv_zilog, ZVOL_OBJ);
 
@@ -598,7 +591,7 @@ zvol_write(void *arg)
         * Some requests are just for flush and nothing else.
         */
        if (size == 0) {
-               blk_end_request(req, 0, size);
+               error = 0;
                goto out;
        }
 
@@ -612,7 +605,6 @@ zvol_write(void *arg)
        if (error) {
                dmu_tx_abort(tx);
                zfs_range_unlock(rl);
-               blk_end_request(req, -error, size);
                goto out;
        }
 
@@ -628,9 +620,9 @@ zvol_write(void *arg)
            zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zv->zv_zilog, ZVOL_OBJ);
 
-       blk_end_request(req, -error, size);
 out:
-       current->flags &= ~PF_NOFS;
+       blk_end_request(req, -error, size);
+       spl_fstrans_unmark(cookie);
 }
 
 #ifdef HAVE_BLK_QUEUE_DISCARD
@@ -640,21 +632,14 @@ zvol_discard(void *arg)
        struct request *req = (struct request *)arg;
        struct request_queue *q = req->q;
        zvol_state_t *zv = q->queuedata;
+       fstrans_cookie_t cookie = spl_fstrans_mark();
        uint64_t start = blk_rq_pos(req) << 9;
        uint64_t end = start + blk_rq_bytes(req);
        int error;
        rl_t *rl;
 
-       /*
-        * Annotate this call path with a flag that indicates that it is
-        * unsafe to use KM_SLEEP during memory allocations due to the
-        * potential for a deadlock.  KM_PUSHPAGE should be used instead.
-        */
-       ASSERT(!(current->flags & PF_NOFS));
-       current->flags |= PF_NOFS;
-
        if (end > zv->zv_volsize) {
-               blk_end_request(req, -EIO, blk_rq_bytes(req));
+               error = EIO;
                goto out;
        }
 
@@ -668,7 +653,7 @@ zvol_discard(void *arg)
        end = P2ALIGN(end, zv->zv_volblocksize);
 
        if (start >= end) {
-               blk_end_request(req, 0, blk_rq_bytes(req));
+               error = 0;
                goto out;
        }
 
@@ -681,10 +666,9 @@ zvol_discard(void *arg)
         */
 
        zfs_range_unlock(rl);
-
-       blk_end_request(req, -error, blk_rq_bytes(req));
 out:
-       current->flags &= ~PF_NOFS;
+       blk_end_request(req, -error, blk_rq_bytes(req));
+       spl_fstrans_unmark(cookie);
 }
 #endif /* HAVE_BLK_QUEUE_DISCARD */
 
@@ -700,14 +684,15 @@ zvol_read(void *arg)
        struct request *req = (struct request *)arg;
        struct request_queue *q = req->q;
        zvol_state_t *zv = q->queuedata;
+       fstrans_cookie_t cookie = spl_fstrans_mark();
        uint64_t offset = blk_rq_pos(req) << 9;
        uint64_t size = blk_rq_bytes(req);
        int error;
        rl_t *rl;
 
        if (size == 0) {
-               blk_end_request(req, 0, size);
-               return;
+               error = 0;
+               goto out;
        }
 
        rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_READER);
@@ -720,7 +705,9 @@ zvol_read(void *arg)
        if (error == ECKSUM)
                error = SET_ERROR(EIO);
 
+out:
        blk_end_request(req, -error, size);
+       spl_fstrans_unmark(cookie);
 }
 
 /*
@@ -838,7 +825,7 @@ zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
        ASSERT(zio != NULL);
        ASSERT(size != 0);
 
-       zgd = (zgd_t *)kmem_zalloc(sizeof (zgd_t), KM_PUSHPAGE);
+       zgd = (zgd_t *)kmem_zalloc(sizeof (zgd_t), KM_SLEEP);
        zgd->zgd_zilog = zv->zv_zilog;
        zgd->zgd_rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_READER);
 
@@ -945,6 +932,10 @@ zvol_first_open(zvol_state_t *zv)
                        return (-SET_ERROR(ERESTARTSYS));
        }
 
+       error = dsl_prop_get_integer(zv->zv_name, "readonly", &ro, NULL);
+       if (error)
+               goto out_mutex;
+
        /* lie and say we're read-only */
        error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, 1, zvol_tag, &os);
        if (error)
@@ -967,7 +958,6 @@ zvol_first_open(zvol_state_t *zv)
        zv->zv_volsize = volsize;
        zv->zv_zilog = zil_open(os, zvol_get_data);
 
-       VERIFY(dsl_prop_get_integer(zv->zv_name, "readonly", &ro, NULL) == 0);
        if (ro || dmu_objset_is_snapshot(os) ||
            !spa_writeable(dmu_objset_spa(os))) {
                set_disk_ro(zv->zv_disk, 1);
@@ -1065,11 +1055,11 @@ zvol_release(struct gendisk *disk, fmode_t mode)
                drop_mutex = 1;
        }
 
-       ASSERT3P(zv, !=, NULL);
-       ASSERT3U(zv->zv_open_count, >, 0);
-       zv->zv_open_count--;
-       if (zv->zv_open_count == 0)
-               zvol_last_close(zv);
+       if (zv->zv_open_count > 0) {
+               zv->zv_open_count--;
+               if (zv->zv_open_count == 0)
+                       zvol_last_close(zv);
+       }
 
        if (drop_mutex)
                mutex_exit(&zvol_state_lock);
@@ -1247,7 +1237,7 @@ zvol_alloc(dev_t dev, const char *name)
        zvol_state_t *zv;
        int error = 0;
 
-       zv = kmem_zalloc(sizeof (zvol_state_t), KM_PUSHPAGE);
+       zv = kmem_zalloc(sizeof (zvol_state_t), KM_SLEEP);
 
        spin_lock_init(&zv->zv_lock);
        list_link_init(&zv->zv_next);
@@ -1327,7 +1317,7 @@ __zvol_snapdev_hidden(const char *name)
        char *atp;
        int error = 0;
 
-       parent = kmem_alloc(MAXPATHLEN, KM_PUSHPAGE);
+       parent = kmem_alloc(MAXPATHLEN, KM_SLEEP);
        (void) strlcpy(parent, name, MAXPATHLEN);
 
        if ((atp = strrchr(parent, '@')) != NULL) {
@@ -1366,7 +1356,7 @@ __zvol_create_minor(const char *name, boolean_t ignore_snapdev)
                        goto out;
        }
 
-       doi = kmem_alloc(sizeof (dmu_object_info_t), KM_PUSHPAGE);
+       doi = kmem_alloc(sizeof (dmu_object_info_t), KM_SLEEP);
 
        error = dmu_objset_own(name, DMU_OST_ZVOL, B_TRUE, zvol_tag, &os);
        if (error)
@@ -1399,7 +1389,7 @@ __zvol_create_minor(const char *name, boolean_t ignore_snapdev)
 
        set_capacity(zv->zv_disk, zv->zv_volsize >> 9);
 
-       blk_queue_max_hw_sectors(zv->zv_queue, UINT_MAX);
+       blk_queue_max_hw_sectors(zv->zv_queue, DMU_MAX_ACCESS / 512);
        blk_queue_max_segments(zv->zv_queue, UINT16_MAX);
        blk_queue_max_segment_size(zv->zv_queue, UINT_MAX);
        blk_queue_physical_block_size(zv->zv_queue, zv->zv_volblocksize);
@@ -1578,7 +1568,7 @@ zvol_rename_minors(const char *oldname, const char *newname)
 
        oldnamelen = strlen(oldname);
        newnamelen = strlen(newname);
-       name = kmem_alloc(MAXNAMELEN, KM_PUSHPAGE);
+       name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 
        mutex_enter(&zvol_state_lock);