From: Nicholas Bellinger <n...@linux-iscsi.org> This patch adds top level BSG support to QEMU-KVM block and adds the BDS_* prefixed defines for SG_IO and BSG.
It adds the BDS_SCSI_GENERIC and BDS_BSG assignments in block/raw-posix.c:hdev_open() using S_ISCHR() and major(st.st_rdev) in order to determine when we are dealing with scsi-generic or scsi-bsg backstores. Signed-off-by: Nicholas A. Bellinger <n...@linux-iscsi.org> --- block.c | 7 +++++- block.h | 1 + block/raw-posix.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++--- block_int.h | 6 +++++ 4 files changed, 74 insertions(+), 5 deletions(-) diff --git a/block.c b/block.c index 6b505fb..8faf25d 100644 --- a/block.c +++ b/block.c @@ -1340,7 +1340,12 @@ int bdrv_is_read_only(BlockDriverState *bs) int bdrv_is_sg(BlockDriverState *bs) { - return bs->sg; + return bs->sg == BDS_SCSI_GENERIC; +} + +int bdrv_is_bsg(BlockDriverState *bs) +{ + return bs->sg == BDS_BSG; } int bdrv_enable_write_cache(BlockDriverState *bs) diff --git a/block.h b/block.h index 78ecfac..5869c8c 100644 --- a/block.h +++ b/block.h @@ -174,6 +174,7 @@ void bdrv_set_removable(BlockDriverState *bs, int removable); int bdrv_is_removable(BlockDriverState *bs); int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_sg(BlockDriverState *bs); +int bdrv_is_bsg(BlockDriverState *bs); int bdrv_enable_write_cache(BlockDriverState *bs); int bdrv_is_inserted(BlockDriverState *bs); int bdrv_media_changed(BlockDriverState *bs); diff --git a/block/raw-posix.c b/block/raw-posix.c index bf89717..2802c97 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -53,6 +53,7 @@ #include <sys/param.h> #include <linux/cdrom.h> #include <linux/fd.h> +#include <linux/major.h> #endif #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) #include <signal.h> @@ -885,13 +886,69 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) s->type = FTYPE_FILE; #if defined(__linux__) { - char resolved_path[ MAXPATHLEN ], *temp; + struct stat st, st2; + FILE *file; + char major[8], dev[64], path[128], *p, *buf; + int ch, i; - temp = realpath(filename, resolved_path); - if (temp && strstart(temp, "/dev/sg", NULL)) { - bs->sg = 1; + if (stat(filename, &st) < 0) { + printf("stat() failed errno: %d\n", errno); + return -1; + } + + if (major(st.st_rdev) == SCSI_GENERIC_MAJOR) { + bs->sg = BDS_SCSI_GENERIC; + goto out; + } + + memset(major, 0, 8); + memset(dev, 0, 64); + memset(path, 0, 128); + + buf = strdup(filename); + if (!buf) + goto out; + /* + * Locate the device name from the path, we are interested + * in the last strsep() token.. + */ + while ((p = strsep(&buf, "/"))) + snprintf(dev, 64, "%s", p); + /* + * Check to sure the sysfs entry exists before calling open + */ + snprintf(path, 128, "/sys/class/bsg/%s/dev", dev); + if (stat(path, &st2) < 0) { + free(buf); + goto out; + } + + file = fopen(path, "r"); + if (!file) { + printf("fopen() failed for BSG sysfs path: %s\n", path); + free(buf); + goto out; + } + ch = fgetc(file); + for (i = 0; i < 7; i++) { + if (ch == ':') { + major[i] = '\0'; + break; + } + major[i] = ch; + ch = fgetc(file); } + fclose(file); + /* + * If the major returned by /sys/class/bsg/$H:C:T:L/dev matches + * stat(), then we signal BDS_BSG usage. + */ + if (major(st.st_rdev) == atoi(major)) + bs->sg = BDS_BSG; + + free(buf); } +out: #endif return raw_open_common(bs, filename, flags, 0); diff --git a/block_int.h b/block_int.h index 3c3adb5..8fdc816 100644 --- a/block_int.h +++ b/block_int.h @@ -40,6 +40,11 @@ #define BLOCK_OPT_CLUSTER_SIZE "cluster_size" #define BLOCK_OPT_PREALLOC "preallocation" +/* Used for BlockDriverState->sg */ +#define BDS_NONE 0 +#define BDS_SCSI_GENERIC 1 +#define BDS_BSG 2 + typedef struct AIOPool { void (*cancel)(BlockDriverAIOCB *acb); int aiocb_size; @@ -150,6 +155,7 @@ struct BlockDriverState { int encrypted; /* if true, the media is encrypted */ int valid_key; /* if true, a valid encryption key has been set */ int sg; /* if true, the device is a /dev/sg* */ + int fd; /* Used for BSG file descriptor */ /* event callback when inserting/removing */ void (*change_cb)(void *opaque); void *change_opaque; -- 1.5.6.5