Please use this patch instead. It uses lseek64(). Resending since the previous reply did not go to the list. On Wed, May 30, 2012 at 9:01 AM, FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx> wrote: > On Tue, 29 May 2012 21:43:12 +1000 > ronnie sahlberg <ronniesahlberg@xxxxxxxxx> wrote: > >> Tomo, >> >> Please find attached a patch that adds support for the opcode >> GET_LBA_STATUS for thin-provisioned luns. >> >> >> This patch uses the new lseek() SEEK_DATA/SEEK_HOLE to find what is >> mapped and what is not on a sparse backend file. >> These two new features are very new and only available on very recent >> linux kernels and select filesystems. >> >> >> Linux 3.2 and BTRFS (mint13 for example) support these two new seek types. >> If SEEK_DATA/SEEK_HOLE is not available we emulate these as always >> returning that the specified offset is mapped, and that the next >> "hole" is at end-of-file, i.e. as if the file was not sparse at all. >> >>>From abd7df828a2b7ac6146a2e315138719a7f9f193f Mon Sep 17 00:00:00 2001 >> From: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx> >> Date: Tue, 29 May 2012 21:16:37 +1000 >> Subject: [PATCH] SBC: Add GET_LBA_STATUS support >> >> Signed-off-by: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx> >> --- >> usr/sbc.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++---------- >> usr/scsi.h | 1 + >> 2 files changed, 90 insertions(+), 19 deletions(-) >> >> diff --git a/usr/sbc.c b/usr/sbc.c >> index cf2b609..b7eaab0 100644 >> --- a/usr/sbc.c >> +++ b/usr/sbc.c >> @@ -23,6 +23,9 @@ >> * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA >> * 02110-1301 USA >> */ >> +#define _FILE_OFFSET_BITS 64 >> +#define __USE_GNU >> + >> #include <errno.h> >> #include <stdio.h> >> #include <stdlib.h> >> @@ -30,6 +33,7 @@ >> #include <stdint.h> >> #include <unistd.h> >> #include <linux/fs.h> >> +#include <sys/types.h> >> >> #include "list.h" >> #include "util.h" >> @@ -45,6 +49,23 @@ >> >> static unsigned int blk_shift = DEFAULT_BLK_SHIFT; >> >> +static off_t find_next_data(struct scsi_lu *dev, off_t offset) >> +{ >> +#ifdef SEEK_DATA >> + return lseek(dev->fd, offset, SEEK_DATA); >> +#else > > Why not use lseek64 like other places in tgt? > >> + return offset; >> +#endif >> +} >> +static off_t find_next_hole(struct scsi_lu *dev, off_t offset) >> +{ >> +#ifdef SEEK_HOLE >> + return lseek(dev->fd, offset, SEEK_HOLE); >> +#else >> + return dev->size; >> +#endif >> +} >> + >> static int sbc_mode_page_update(struct scsi_cmd *cmd, uint8_t *data, int *changed) >> { >> uint8_t pcode = data[0] & 0x3f; >> @@ -437,27 +458,76 @@ static int sbc_service_action(int host_no, struct scsi_cmd *cmd) >> goto sense; >> } >> >> - if (cmd->scb[1] != SAI_READ_CAPACITY_16) >> - goto sense; >> + if (cmd->scb[1] == SAI_READ_CAPACITY_16) { >> + if (scsi_get_in_length(cmd) < 12) >> + goto overflow; >> >> - if (scsi_get_in_length(cmd) < 12) >> - goto overflow; >> + len = min_t(int, len, scsi_get_in_length(cmd)); >> >> - len = min_t(int, len, scsi_get_in_length(cmd)); >> - >> - data = scsi_get_in_buffer(cmd); >> - memset(data, 0, len); >> - >> - bshift = cmd->dev->blk_shift; >> - size = cmd->dev->size >> bshift; >> - >> - *((uint64_t *)(data)) = __cpu_to_be64(size - 1); >> - data[2] = __cpu_to_be32(1UL << bshift); >> - >> - val = (cmd->dev->attrs.lbppbe << 16) | cmd->dev->attrs.la_lba; >> - if (cmd->dev->attrs.thinprovisioning) >> - val |= (3 << 14); /* set LBPME and LBPRZ */ >> - data[3] = __cpu_to_be32(val); >> + data = scsi_get_in_buffer(cmd); >> + memset(data, 0, len); >> + >> + bshift = cmd->dev->blk_shift; >> + size = cmd->dev->size >> bshift; >> + >> + *((uint64_t *)(data)) = __cpu_to_be64(size - 1); >> + data[2] = __cpu_to_be32(1UL << bshift); >> + >> + val = (cmd->dev->attrs.lbppbe << 16) | cmd->dev->attrs.la_lba; >> + if (cmd->dev->attrs.thinprovisioning) >> + val |= (3 << 14); /* set LBPME and LBPRZ */ >> + data[3] = __cpu_to_be32(val); >> + } else if (cmd->scb[1] == SAI_GET_LBA_STATUS) { >> + uint64_t offset; >> + uint32_t pdl; >> + int type; >> + char *buf; >> + >> + if (scsi_get_in_length(cmd) < 24) >> + goto overflow; >> + >> + len = scsi_get_in_length(cmd); >> + buf = scsi_get_in_buffer(cmd); >> + memset(buf, 0, len); >> + >> + offset = __be64_to_cpu(*(uint64_t *)&cmd->scb[2]) >> + << cmd->dev->blk_shift; >> + pdl = 4; >> + *(uint32_t *)&buf[0] = __cpu_to_be32(pdl); >> + >> + type = 0; >> + while (len >= 4 + pdl + 16) { >> + off_t next_offset; >> + >> + *(uint32_t *)&buf[0] = __cpu_to_be32(pdl + 16); >> + >> + if (offset >= cmd->dev->size) >> + break; >> + >> + next_offset = (type == 0) ? >> + find_next_hole(cmd->dev, offset) : >> + find_next_data(cmd->dev, offset); >> + if (next_offset == offset) { >> + type = 1 - type; >> + continue; >> + } >> + >> + *(uint64_t *)&buf[4 + pdl + 0] = >> + __cpu_to_be64(offset >> + >> cmd->dev->blk_shift); >> + *(uint64_t *)&buf[4 + pdl + 8] = >> + __cpu_to_be32((next_offset - offset) >> + >> cmd->dev->blk_shift); >> + buf[4 + pdl + 12] = type; >> + >> + pdl += 16; >> + type = 1 - type; >> + offset = next_offset; >> + } >> + len = 4 + pdl; >> + } else { >> + goto sense; >> + } >> >> overflow: >> scsi_set_in_resid_by_actual(cmd, len); >> diff --git a/usr/scsi.h b/usr/scsi.h >> index 0a02c36..2b994f9 100644 >> --- a/usr/scsi.h >> +++ b/usr/scsi.h >> @@ -80,6 +80,7 @@ >> #define WRITE_SAME_16 0x93 >> #define SERVICE_ACTION_IN 0x9e >> #define SAI_READ_CAPACITY_16 0x10 >> +#define SAI_GET_LBA_STATUS 0x12 >> #define REPORT_LUNS 0xa0 >> #define MOVE_MEDIUM 0xa5 >> #define EXCHANGE_MEDIUM 0xa6 >> -- >> 1.7.3.1
Attachment:
0001-SBC-Add-support-for-GET_LBA_STATUS-command.patch.gz
Description: GNU Zip compressed data
Attachment:
0001-SBC-Add-support-for-GET_LBA_STATUS-command.patch
Description: Binary data