X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fzvol.c;h=0aaa268faa2a4793f59fd5013ad5560943a24090;hb=b18019d2d810585185493c62e9567fa85e51692c;hp=6e929429252a269179a4eae150f981d3c90371f1;hpb=60101509ee73c6e61e50c0a4079097f31bb39f4b;p=zfs.git diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index 6e92942..0aaa268 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -44,6 +44,7 @@ #include #include #include +#include unsigned int zvol_major = ZVOL_MAJOR; unsigned int zvol_threads = 0; @@ -57,7 +58,7 @@ static char *zvol_tag = "zvol_tag"; * The in-core state of each volume. */ typedef struct zvol_state { - char zv_name[DISK_NAME_LEN]; /* name */ + char zv_name[MAXNAMELEN]; /* name */ uint64_t zv_volsize; /* advertised space */ uint64_t zv_volblocksize;/* volume block size */ objset_t *zv_objset; /* objset handle */ @@ -131,7 +132,7 @@ zvol_find_by_name(const char *name) ASSERT(MUTEX_HELD(&zvol_state_lock)); for (zv = list_head(&zvol_state_list); zv != NULL; zv = list_next(&zvol_state_list, zv)) { - if (!strncmp(zv->zv_name, name, DISK_NAME_LEN)) + if (!strncmp(zv->zv_name, name, MAXNAMELEN)) return zv; } @@ -227,7 +228,7 @@ zvol_check_volsize(uint64_t volsize, uint64_t blocksize) * 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; @@ -235,7 +236,7 @@ zvol_update_volsize(zvol_state_t *zv, uint64_t volsize) 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) { @@ -243,27 +244,35 @@ zvol_update_volsize(zvol_state_t *zv, uint64_t volsize) 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); @@ -310,7 +319,7 @@ zvol_set_volsize(const char *name, uint64_t volsize) 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: @@ -525,6 +534,17 @@ zvol_write(void *arg) 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); @@ -541,12 +561,14 @@ zvol_write(void *arg) 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); @@ -569,6 +591,11 @@ zvol_read(void *arg) 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); @@ -618,7 +645,7 @@ zvol_request(struct request_queue *q) 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", @@ -894,6 +921,9 @@ zvol_ioctl(struct block_device *bdev, fmode_t mode, case BLKFLSBUF: zil_commit(zv->zv_zilog, ZVOL_OBJ); break; + case BLKZNAME: + error = copy_to_user((void *)arg, zv->zv_name, MAXNAMELEN); + break; default: error = -ENOTTY; @@ -1002,6 +1032,8 @@ static int zvol_ioctl_by_inode(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + if (file == NULL || inode == NULL) + return -EINVAL; return zvol_ioctl(inode->i_bdev, file->f_mode, cmd, arg); } @@ -1010,6 +1042,8 @@ static long zvol_compat_ioctl_by_inode(struct file *file, unsigned int cmd, unsigned long arg) { + if (file == NULL) + return -EINVAL; return zvol_compat_ioctl(file->f_dentry->d_inode->i_bdev, file->f_mode, cmd, arg); } @@ -1046,6 +1080,12 @@ zvol_alloc(dev_t dev, const char *name) 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; @@ -1053,11 +1093,13 @@ zvol_alloc(dev_t dev, const char *name) zv->zv_queue->queuedata = zv; zv->zv_dev = dev; zv->zv_open_count = 0; - strlcpy(zv->zv_name, name, DISK_NAME_LEN); + strlcpy(zv->zv_name, name, MAXNAMELEN); mutex_init(&zv->zv_znode.z_range_lock, NULL, MUTEX_DEFAULT, NULL); avl_create(&zv->zv_znode.z_range_avl, zfs_range_compare, sizeof (rl_t), offsetof(rl_t, r_node)); + zv->zv_znode.z_is_zvol = TRUE; + spin_lock_init(&zv->zv_lock); list_link_init(&zv->zv_next); @@ -1066,7 +1108,8 @@ zvol_alloc(dev_t dev, const char *name) zv->zv_disk->fops = &zvol_ops; zv->zv_disk->private_data = zv; zv->zv_disk->queue = zv->zv_queue; - snprintf(zv->zv_disk->disk_name, DISK_NAME_LEN, "%s", name); + snprintf(zv->zv_disk->disk_name, DISK_NAME_LEN, "%s%d", + ZVOL_DEV_NAME, (dev & MINORMASK)); return zv; @@ -1224,7 +1267,8 @@ zvol_create_minors_cb(spa_t *spa, uint64_t dsobj, if (strchr(dsname, '/') == NULL) return 0; - return __zvol_create_minor(dsname); + (void) __zvol_create_minor(dsname); + return (0); } /* @@ -1266,7 +1310,7 @@ zvol_remove_minors(const char *pool) zvol_state_t *zv, *zv_next; char *str; - str = kmem_zalloc(DISK_NAME_LEN, KM_SLEEP); + str = kmem_zalloc(MAXNAMELEN, KM_SLEEP); if (pool) { (void) strncpy(str, pool, strlen(pool)); (void) strcat(str, "/"); @@ -1282,7 +1326,7 @@ zvol_remove_minors(const char *pool) } } mutex_exit(&zvol_state_lock); - kmem_free(str, DISK_NAME_LEN); + kmem_free(str, MAXNAMELEN); } int @@ -1330,8 +1374,8 @@ zvol_fini(void) 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");