Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 319822
b: refs/heads/master
c: cd5d503
h: refs/heads/master
v: v3
  • Loading branch information
Paolo Bonzini authored and Rusty Russell committed Jul 30, 2012
1 parent 7640560 commit d35bd85
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2c95a3290919541b846bee3e0fbaa75860929f53
refs/heads/master: cd5d503862b0d0d927c56ef2e34d3ededac88039
90 changes: 87 additions & 3 deletions trunk/drivers/block/virtio_blk.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,83 @@ static int virtblk_name_format(char *prefix, int index, char *buf, int buflen)
return 0;
}

static int virtblk_get_cache_mode(struct virtio_device *vdev)
{
u8 writeback;
int err;

err = virtio_config_val(vdev, VIRTIO_BLK_F_CONFIG_WCE,
offsetof(struct virtio_blk_config, wce),
&writeback);
if (err)
writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE);

return writeback;
}

static void virtblk_update_cache_mode(struct virtio_device *vdev)
{
u8 writeback = virtblk_get_cache_mode(vdev);
struct virtio_blk *vblk = vdev->priv;

if (writeback)
blk_queue_flush(vblk->disk->queue, REQ_FLUSH);
else
blk_queue_flush(vblk->disk->queue, 0);

revalidate_disk(vblk->disk);
}

static const char *const virtblk_cache_types[] = {
"write through", "write back"
};

static ssize_t
virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct gendisk *disk = dev_to_disk(dev);
struct virtio_blk *vblk = disk->private_data;
struct virtio_device *vdev = vblk->vdev;
int i;
u8 writeback;

BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE));
for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; )
if (sysfs_streq(buf, virtblk_cache_types[i]))
break;

if (i < 0)
return -EINVAL;

writeback = i;
vdev->config->set(vdev,
offsetof(struct virtio_blk_config, wce),
&writeback, sizeof(writeback));

virtblk_update_cache_mode(vdev);
return count;
}

static ssize_t
virtblk_cache_type_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct gendisk *disk = dev_to_disk(dev);
struct virtio_blk *vblk = disk->private_data;
u8 writeback = virtblk_get_cache_mode(vblk->vdev);

BUG_ON(writeback >= ARRAY_SIZE(virtblk_cache_types));
return snprintf(buf, 40, "%s\n", virtblk_cache_types[writeback]);
}

static const struct device_attribute dev_attr_cache_type_ro =
__ATTR(cache_type, S_IRUGO,
virtblk_cache_type_show, NULL);
static const struct device_attribute dev_attr_cache_type_rw =
__ATTR(cache_type, S_IRUGO|S_IWUSR,
virtblk_cache_type_show, virtblk_cache_type_store);

static int __devinit virtblk_probe(struct virtio_device *vdev)
{
struct virtio_blk *vblk;
Expand Down Expand Up @@ -471,8 +548,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
vblk->index = index;

/* configure queue flush support */
if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH))
blk_queue_flush(q, REQ_FLUSH);
virtblk_update_cache_mode(vdev);

/* If disk is read-only in the host, the guest should obey */
if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
Expand Down Expand Up @@ -550,6 +626,14 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
if (err)
goto out_del_disk;

if (virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE))
err = device_create_file(disk_to_dev(vblk->disk),
&dev_attr_cache_type_rw);
else
err = device_create_file(disk_to_dev(vblk->disk),
&dev_attr_cache_type_ro);
if (err)
goto out_del_disk;
return 0;

out_del_disk:
Expand Down Expand Up @@ -642,7 +726,7 @@ static const struct virtio_device_id id_table[] = {
static unsigned int features[] = {
VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI,
VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY
VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE
};

/*
Expand Down
5 changes: 4 additions & 1 deletion trunk/include/linux/virtio_blk.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/
#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
#define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command support */
#define VIRTIO_BLK_F_WCE 9 /* Writeback mode enabled after reset */
#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */
#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */

#define VIRTIO_BLK_ID_BYTES 20 /* ID string length */

Expand Down Expand Up @@ -69,6 +70,8 @@ struct virtio_blk_config {
/* optimal sustained I/O size in logical blocks. */
__u32 opt_io_size;

/* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */
__u8 wce;
} __attribute__((packed));

/*
Expand Down

0 comments on commit d35bd85

Please sign in to comment.