* Ensure the zap is flushed then inform the VFS of the capacity change.
*/
static int
-zvol_update_volsize(zvol_state_t *zv, uint64_t volsize)
+zvol_update_volsize(zvol_state_t *zv, uint64_t volsize, objset_t *os)
{
struct block_device *bdev;
dmu_tx_t *tx;
ASSERT(MUTEX_HELD(&zvol_state_lock));
- tx = dmu_tx_create(zv->zv_objset);
+ tx = dmu_tx_create(os);
dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
return (error);
}
- error = zap_update(zv->zv_objset, ZVOL_ZAP_OBJ, "size", 8, 1,
+ error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1,
&volsize, tx);
dmu_tx_commit(tx);
if (error)
return (error);
- error = dmu_free_long_range(zv->zv_objset,
+ error = dmu_free_long_range(os,
ZVOL_OBJ, volsize, DMU_OBJECT_END);
if (error)
return (error);
- zv->zv_volsize = volsize;
- zv->zv_changed = 1;
-
bdev = bdget_disk(zv->zv_disk, 0);
if (!bdev)
- return EIO;
+ return (EIO);
+/*
+ * 2.6.28 API change
+ * Added check_disk_size_change() helper function.
+ */
+#ifdef HAVE_CHECK_DISK_SIZE_CHANGE
+ set_capacity(zv->zv_disk, volsize >> 9);
+ zv->zv_volsize = volsize;
+ check_disk_size_change(zv->zv_disk, bdev);
+#else
+ zv->zv_volsize = volsize;
+ zv->zv_changed = 1;
+ (void) check_disk_change(bdev);
+#endif /* HAVE_CHECK_DISK_SIZE_CHANGE */
- error = check_disk_change(bdev);
- ASSERT3U(error, !=, 0);
bdput(bdev);
return (0);
goto out_doi;
}
- error = zvol_update_volsize(zv, volsize);
+ error = zvol_update_volsize(zv, volsize, os);
out_doi:
kmem_free(doi, sizeof(dmu_object_info_t));
out:
dmu_tx_t *tx;
rl_t *rl;
+ if (req->cmd_flags & VDEV_REQ_FLUSH)
+ zil_commit(zv->zv_zilog, ZVOL_OBJ);
+
+ /*
+ * Some requests are just for flush and nothing else.
+ */
+ if (size == 0) {
+ blk_end_request(req, 0, size);
+ return;
+ }
+
rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_WRITER);
tx = dmu_tx_create(zv->zv_objset);
error = dmu_write_req(zv->zv_objset, ZVOL_OBJ, req, tx);
if (error == 0)
- zvol_log_write(zv, tx, offset, size, rq_is_sync(req));
+ zvol_log_write(zv, tx, offset, size,
+ req->cmd_flags & VDEV_REQ_FUA);
dmu_tx_commit(tx);
zfs_range_unlock(rl);
- if (rq_is_sync(req))
+ if ((req->cmd_flags & VDEV_REQ_FUA) ||
+ zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zv->zv_zilog, ZVOL_OBJ);
blk_end_request(req, -error, size);
int error;
rl_t *rl;
+ if (size == 0) {
+ blk_end_request(req, 0, size);
+ return;
+ }
+
rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_READER);
error = dmu_read_req(zv->zv_objset, ZVOL_OBJ, req);
while ((req = blk_fetch_request(q)) != NULL) {
size = blk_rq_bytes(req);
- if (blk_rq_pos(req) + blk_rq_sectors(req) >
+ if (size != 0 && blk_rq_pos(req) + blk_rq_sectors(req) >
get_capacity(zv->zv_disk)) {
printk(KERN_INFO
"%s: bad access: block=%llu, count=%lu\n",
if (zv->zv_queue == NULL)
goto out_kmem;
+#ifdef HAVE_BLK_QUEUE_FLUSH
+ blk_queue_flush(zv->zv_queue, VDEV_REQ_FLUSH | VDEV_REQ_FUA);
+#else
+ blk_queue_ordered(zv->zv_queue, QUEUE_ORDERED_DRAIN, NULL);
+#endif /* HAVE_BLK_QUEUE_FLUSH */
+
zv->zv_disk = alloc_disk(ZVOL_MINORS);
if (zv->zv_disk == NULL)
goto out_queue;
list_destroy(&zvol_state_list);
}
-module_param(zvol_major, uint, 0);
+module_param(zvol_major, uint, 0444);
MODULE_PARM_DESC(zvol_major, "Major number for zvol device");
-module_param(zvol_threads, uint, 0);
+module_param(zvol_threads, uint, 0444);
MODULE_PARM_DESC(zvol_threads, "Number of threads for zvol device");