qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Use SCSI command to get size of SG device
@ 2012-10-09  9:42 Chen HanXiao
  2012-10-09 17:21 ` Christoph Hellwig
  0 siblings, 1 reply; 6+ messages in thread
From: Chen HanXiao @ 2012-10-09  9:42 UTC (permalink / raw)
  To: qemu-devel

When we use SCSI generic device as disk image, function lseek
could not get the size of this kind of device.
So try to use SCSI command Read Capacity(10) when lseek failed to get
the size of SCSI generic device.

Signed-off-by: Chen Hanxiao <chenhanxiao@cn.fujitsu.com>
---
 block/raw-posix.c |   46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/block/raw-posix.c b/block/raw-posix.c
index 28d439f..0be7db8 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -53,6 +53,7 @@
 #include <linux/cdrom.h>
 #include <linux/fd.h>
 #include <linux/fs.h>
+#include <scsi/sg.h>
 #endif
 #ifdef CONFIG_FIEMAP
 #include <linux/fiemap.h>
@@ -147,6 +148,7 @@ typedef struct BDRVRawReopenState {
 } BDRVRawReopenState;
 
 static int fd_open(BlockDriverState *bs);
+static int64_t raw_getlength_ioctl(int fd);
 static int64_t raw_getlength(BlockDriverState *bs);
 
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -653,13 +655,53 @@ static int64_t raw_getlength(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
     int ret;
-
+    int64_t len;
+    
     ret = fd_open(bs);
     if (ret < 0) {
         return ret;
     }
 
-    return lseek(s->fd, 0, SEEK_END);
+    len = lseek(s->fd, 0, SEEK_END);
+    if ( len >= 0) {
+        return len;
+    } else {
+        len = raw_getlength_ioctl(s->fd);
+        return len;
+    }
+}
+
+/* Use SCSI Read Capacity(10) Command to get length */
+static int64_t raw_getlength_ioctl(int fd)
+{
+    unsigned char CDB[10] =
+        {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    unsigned char sense_buffer[32];
+    unsigned char resp_buffer[32];
+    uint32_t block_size;
+    uint64_t last_blk_addr;
+    struct sg_io_hdr io_hdr;
+    int64_t ret;
+ 
+    memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
+    memset(sense_buffer, 0, sizeof(sense_buffer));
+    memset(sense_buffer, 0, sizeof(resp_buffer));
+    io_hdr.interface_id = 'S';
+    io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+    io_hdr.cmd_len = sizeof(CDB);
+    io_hdr.cmdp = CDB;
+    io_hdr.sbp = sense_buffer;
+    io_hdr.dxferp = resp_buffer;
+    io_hdr.dxfer_len = sizeof(resp_buffer);
+    if((ret = ioctl(fd, SG_IO, &io_hdr)) < 0)
+        return ret;
+
+    last_blk_addr = ((resp_buffer[0] << 24) | (resp_buffer[1] << 16) |
+        (resp_buffer[2] << 8) | resp_buffer[3]);
+    block_size = ((resp_buffer[4] << 24) | (resp_buffer[5] << 16) |
+        (resp_buffer[6] << 8) | resp_buffer[7]);
+    ret = (int64_t)((last_blk_addr + 1) * block_size);
+    return ret;
 }
 #endif
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-10-10  9:01 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-09  9:42 [Qemu-devel] [PATCH] Use SCSI command to get size of SG device Chen HanXiao
2012-10-09 17:21 ` Christoph Hellwig
2012-10-10  2:11   ` Chen HanXiao
2012-10-10  6:33     ` Paolo Bonzini
2012-10-10  8:33       ` Chen HanXiao
2012-10-10  9:01         ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).