Add serial number support for virtio_blk
Subsystems (4)
PATCH 2/2 Add serial number support for virtio_blk
Signature · 2 lines
-- [email protected]
drivers/block/virtio_blk.c | 36 +++++++++++++++++++++++++++++++++--- include/linux/virtio_blk.h | 10 ++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-)
=================================================================
include/linux/virtio_blk.h +10 -0
@@ -14,7 +14,16 @@#define VIRTIO_BLK_F_GEOMETRY 4/* Legacy geometry available */ #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_SN 7/* serial number supported */ +/* ioctl cmd to retrieve serial# +*/ +#define VBLK_GET_SN ((unsigned int)('V' << 24 | 'B' << 16 | 'L' << 8 | 'K')) + +#define BLOCK_SERIAL_STRLEN 20 + +/* mapped into pci i/o region 0 +*/ struct virtio_blk_config {/* The capacity (in 512-byte sectors). */
@@ -31,6 +40,7 @@ struct virtio_blk_config } geometry;/* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ __u32 blk_size; +__u8 serial[BLOCK_SERIAL_STRLEN ]; } __attribute__((packed));/* These two define direction. */
=================================================================
drivers/block/virtio_blk.c +33 -3
@@ -146,12 +146,41 @@ static void do_virtblk_request(struct re vblk->vq->vq_ops->kick (vblk->vq); } +/* user passes the address of a char[] for serial# return, and has set char[0] +* to the array size. copy serial# to this char[] and return number of +* characters copied excluding any trailing '\0' pad chars in buffer. +*/ +#define _min (a,b) ((a) < (b) ? (a) : (b)) +static int get_virtblk_sn (struct block_device *bdev,void *buf) +{ +struct virtio_blk *vblk = bdev->bd_disk->private_data; +unsigned char serial[BLOCK_SERIAL_STRLEN ]; +unsigned char snlen; +int rv; + +if (copy_from_user (&snlen, buf,sizeof (snlen))) + rv = -EFAULT ; +else if ((rv =virtio_config_val (vblk->vdev,VIRTIO_BLK_F_SN , + offsetof(struct virtio_blk_config , serial), &serial))) + ; +else if (copy_to_user (buf, serial, + snlen =min (snlen, (unsigned char )sizeof (serial)))) + rv = -EFAULT ; +else +for (rv =0 ; rv < snlen; ++rv) +if (!serial[rv]) +break ; +return (rv); +} +static int virtblk_ioctl (struct block_device *bdev,fmode_t mode,unsigned cmd,unsigned long data) { -return scsi_cmd_ioctl (bdev->bd_disk->queue, - bdev->bd_disk, mode, cmd, - (void __user *)data); +if (cmd ==VBLK_GET_SN ) +return (get_virtblk_sn (bdev, (void __user *)data)); +else +return scsi_cmd_ioctl (bdev->bd_disk->queue, bdev->bd_disk, + mode, cmd, (void __user *)data); }/* We provide getgeo only to please some old bootloader/partitioning tools */
@@ -339,6 +368,7 @@ static struct virtio_device_id id_table[static unsigned int features[] = {VIRTIO_BLK_F_BARRIER ,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_SN };static struct virtio_driver virtio_blk = {
PATCH 2/2 Add serial number support for virtio_blk, V2
Signature · 2 lines
-- [email protected]
drivers/block/virtio_blk.c | 35 ++++++++++++++++++++++++++++++++--- include/linux/virtio_blk.h | 10 ++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-)
=================================================================
drivers/block/virtio_blk.c +32 -3
@@ -146,12 +146,40 @@ static void do_virtblk_request(struct re vblk->vq->vq_ops->kick (vblk->vq); } +/* user passes the address of a char[] for serial# return, and has set char[0] +* to the array size. copy serial# to this char[] and return number of +* characters copied excluding any trailing '\0' pad chars in buffer. +*/ +static int get_virtblk_sn (struct block_device *bdev,void *buf) +{ +struct virtio_blk *vblk = bdev->bd_disk->private_data; +unsigned char serial[BLOCK_SERIAL_STRLEN ]; +unsigned char snlen; +int rv; + +if (copy_from_user (&snlen, buf,sizeof (snlen))) + rv = -EFAULT ; +else if ((rv =virtio_config_val (vblk->vdev,VIRTIO_BLK_F_SN , + offsetof(struct virtio_blk_config , serial), &serial))) + ; +else if (copy_to_user (buf, serial, + snlen =min (snlen, (unsigned char )sizeof (serial)))) + rv = -EFAULT ; +else +for (rv =0 ; rv < snlen; ++rv) +if (!serial[rv]) +break ; +return (rv); +} +static int virtblk_ioctl (struct block_device *bdev,fmode_t mode,unsigned cmd,unsigned long data) { -return scsi_cmd_ioctl (bdev->bd_disk->queue, - bdev->bd_disk, mode, cmd, - (void __user *)data); +if (cmd ==VBLK_GET_SN ) +return (get_virtblk_sn (bdev, (void __user *)data)); +else +return scsi_cmd_ioctl (bdev->bd_disk->queue, bdev->bd_disk, + mode, cmd, (void __user *)data); }/* We provide getgeo only to please some old bootloader/partitioning tools */
@@ -356,6 +384,7 @@ static struct virtio_device_id id_table[static unsigned int features[] = {VIRTIO_BLK_F_BARRIER ,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_SN };static struct virtio_driver virtio_blk = {
=================================================================
include/linux/virtio_blk.h +10 -0
@@ -15,7 +15,16 @@#define VIRTIO_BLK_F_GEOMETRY 4/* Legacy geometry available */ #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_SN 8/* serial number supported */ +/* ioctl cmd to retrieve serial# +*/ +#define VBLK_GET_SN ((unsigned int)('V' << 24 | 'B' << 16 | 'L' << 8 | 'K')) + +#define BLOCK_SERIAL_STRLEN 20 + +/* mapped into pci i/o region 0 +*/ struct virtio_blk_config {/* The capacity (in 512-byte sectors). */
@@ -32,6 +41,7 @@ struct virtio_blk_config } geometry;/* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ __u32 blk_size; +__u8 serial[BLOCK_SERIAL_STRLEN ]; } __attribute__((packed));/* These two define direction. */