[stgt] [PATCH] Add support for SBC GET_LBA_STATUS opcode

FUJITA Tomonori fujita.tomonori at lab.ntt.co.jp
Wed May 30 01:01:44 CEST 2012


On Tue, 29 May 2012 21:43:12 +1000
ronnie sahlberg <ronniesahlberg at gmail.com> 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 at gmail.com>
> Date: Tue, 29 May 2012 21:16:37 +1000
> Subject: [PATCH] SBC: Add GET_LBA_STATUS support
> 
> Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>
> ---
>  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 at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the stgt mailing list