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 -- To unsubscribe from this list: send the line "unsubscribe stgt" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html