X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fzvol.c;h=5d4802560201cb839ac662a8927d6380f8958b0c;hb=d3aa3ea96e02547166563bbd60bc8581567a140a;hp=5668e1dc0c32c4e1346c54f74fd7de7ff700b928;hpb=04434775b7f3aa55fbbcf2064cfb9f5f5c436e64;p=zfs.git diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index 5668e1d..5d48025 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -597,8 +597,8 @@ zvol_discard(void *arg) struct request *req = (struct request *)arg; struct request_queue *q = req->q; zvol_state_t *zv = q->queuedata; - uint64_t offset = blk_rq_pos(req) << 9; - uint64_t size = blk_rq_bytes(req); + uint64_t start = blk_rq_pos(req) << 9; + uint64_t end = start + blk_rq_bytes(req); int error; rl_t *rl; @@ -610,19 +610,28 @@ zvol_discard(void *arg) ASSERT(!(current->flags & PF_NOFS)); current->flags |= PF_NOFS; - if (offset + size > zv->zv_volsize) { - blk_end_request(req, -EIO, size); + if (end > zv->zv_volsize) { + blk_end_request(req, -EIO, blk_rq_bytes(req)); goto out; } - if (size == 0) { - blk_end_request(req, 0, size); + /* + * Align the request to volume block boundaries. If we don't, + * then this will force dnode_free_range() to zero out the + * unaligned parts, which is slow (read-modify-write) and + * useless since we are not freeing any space by doing so. + */ + start = P2ROUNDUP(start, zv->zv_volblocksize); + end = P2ALIGN(end, zv->zv_volblocksize); + + if (start >= end) { + blk_end_request(req, 0, blk_rq_bytes(req)); goto out; } - rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_WRITER); + rl = zfs_range_lock(&zv->zv_znode, start, end - start, RL_WRITER); - error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset, size); + error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, start, end - start); /* * TODO: maybe we should add the operation to the log. @@ -630,7 +639,7 @@ zvol_discard(void *arg) zfs_range_unlock(rl); - blk_end_request(req, -error, size); + blk_end_request(req, -error, blk_rq_bytes(req)); out: current->flags &= ~PF_NOFS; } @@ -1150,6 +1159,7 @@ static zvol_state_t * zvol_alloc(dev_t dev, const char *name) { zvol_state_t *zv; + int error = 0; zv = kmem_zalloc(sizeof (zvol_state_t), KM_SLEEP); if (zv == NULL) @@ -1159,6 +1169,15 @@ zvol_alloc(dev_t dev, const char *name) if (zv->zv_queue == NULL) goto out_kmem; +#ifdef HAVE_ELEVATOR_CHANGE + error = elevator_change(zv->zv_queue, "noop"); +#endif /* HAVE_ELEVATOR_CHANGE */ + if (error) { + printk("ZFS: Unable to set \"%s\" scheduler for zvol %s: %d\n", + "noop", name, error); + goto out_queue; + } + #ifdef HAVE_BLK_QUEUE_FLUSH blk_queue_flush(zv->zv_queue, VDEV_REQ_FLUSH | VDEV_REQ_FUA); #else @@ -1287,9 +1306,9 @@ __zvol_create_minor(const char *name) else zil_replay(os, zv, zvol_replay_vector); + zv->zv_objset = NULL; out_dmu_objset_disown: dmu_objset_disown(os, zvol_tag); - zv->zv_objset = NULL; out_doi: kmem_free(doi, sizeof(dmu_object_info_t)); out: