Skip to content

Commit 8a9ebe7

Browse files
Mike ChristieNicholas Bellinger
authored andcommitted
target: Fix WRITE_SAME/DISCARD conversion to linux 512b sectors
In a couple places we are not converting to/from the Linux block layer 512 bytes sectors. 1. The request queue values and what we do are a mismatch of things: max_discard_sectors - This is in linux block layer 512 byte sectors. We are just copying this to max_unmap_lba_count. discard_granularity - This is in bytes. We are converting it to Linux block layer 512 byte sectors. discard_alignment - This is in bytes. We are just copying this over. The problem is that the core LIO code exports these values in spc_emulate_evpd_b0 and we use them to test request arguments in sbc_execute_unmap, but we never convert to the block size we export to the initiator. If we are not using 512 byte sectors then we are exporting the wrong values or are checks are off. And, for the discard_alignment/bytes case we are just plain messed up. 2. blkdev_issue_discard's start and number of sector arguments are supposed to be in linux block layer 512 byte sectors. We are currently passing in the values we get from the initiator which might be based on some other sector size. There is a similar problem in iblock_execute_write_same where the bio functions want values in 512 byte sectors but we are passing in what we got from the initiator. Signed-off-by: Mike Christie <mchristi@redhat.com> Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
1 parent 92e963f commit 8a9ebe7

File tree

4 files changed

+70
-64
lines changed

4 files changed

+70
-64
lines changed

drivers/target/target_core_device.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,50 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
828828
return dev;
829829
}
830830

831+
/*
832+
* Check if the underlying struct block_device request_queue supports
833+
* the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
834+
* in ATA and we need to set TPE=1
835+
*/
836+
bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
837+
struct request_queue *q, int block_size)
838+
{
839+
if (!blk_queue_discard(q))
840+
return false;
841+
842+
attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) /
843+
block_size;
844+
/*
845+
* Currently hardcoded to 1 in Linux/SCSI code..
846+
*/
847+
attrib->max_unmap_block_desc_count = 1;
848+
attrib->unmap_granularity = q->limits.discard_granularity / block_size;
849+
attrib->unmap_granularity_alignment = q->limits.discard_alignment /
850+
block_size;
851+
attrib->unmap_zeroes_data = q->limits.discard_zeroes_data;
852+
return true;
853+
}
854+
EXPORT_SYMBOL(target_configure_unmap_from_queue);
855+
856+
/*
857+
* Convert from blocksize advertised to the initiator to the 512 byte
858+
* units unconditionally used by the Linux block layer.
859+
*/
860+
sector_t target_to_linux_sector(struct se_device *dev, sector_t lb)
861+
{
862+
switch (dev->dev_attrib.block_size) {
863+
case 4096:
864+
return lb << 3;
865+
case 2048:
866+
return lb << 2;
867+
case 1024:
868+
return lb << 1;
869+
default:
870+
return lb;
871+
}
872+
}
873+
EXPORT_SYMBOL(target_to_linux_sector);
874+
831875
int target_configure_device(struct se_device *dev)
832876
{
833877
struct se_hba *hba = dev->se_hba;

drivers/target/target_core_file.c

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -160,25 +160,11 @@ static int fd_configure_device(struct se_device *dev)
160160
" block_device blocks: %llu logical_block_size: %d\n",
161161
dev_size, div_u64(dev_size, fd_dev->fd_block_size),
162162
fd_dev->fd_block_size);
163-
/*
164-
* Check if the underlying struct block_device request_queue supports
165-
* the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
166-
* in ATA and we need to set TPE=1
167-
*/
168-
if (blk_queue_discard(q)) {
169-
dev->dev_attrib.max_unmap_lba_count =
170-
q->limits.max_discard_sectors;
171-
/*
172-
* Currently hardcoded to 1 in Linux/SCSI code..
173-
*/
174-
dev->dev_attrib.max_unmap_block_desc_count = 1;
175-
dev->dev_attrib.unmap_granularity =
176-
q->limits.discard_granularity >> 9;
177-
dev->dev_attrib.unmap_granularity_alignment =
178-
q->limits.discard_alignment;
163+
164+
if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
165+
fd_dev->fd_block_size))
179166
pr_debug("IFILE: BLOCK Discard support available,"
180-
" disabled by default\n");
181-
}
167+
" disabled by default\n");
182168
/*
183169
* Enable write same emulation for IBLOCK and use 0xFFFF as
184170
* the smaller WRITE_SAME(10) only has a two-byte block count.
@@ -490,9 +476,12 @@ fd_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
490476
if (S_ISBLK(inode->i_mode)) {
491477
/* The backend is block device, use discard */
492478
struct block_device *bdev = inode->i_bdev;
479+
struct se_device *dev = cmd->se_dev;
493480

494-
ret = blkdev_issue_discard(bdev, lba,
495-
nolb, GFP_KERNEL, 0);
481+
ret = blkdev_issue_discard(bdev,
482+
target_to_linux_sector(dev, lba),
483+
target_to_linux_sector(dev, nolb),
484+
GFP_KERNEL, 0);
496485
if (ret < 0) {
497486
pr_warn("FILEIO: blkdev_issue_discard() failed: %d\n",
498487
ret);

drivers/target/target_core_iblock.c

Lines changed: 14 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -121,29 +121,11 @@ static int iblock_configure_device(struct se_device *dev)
121121
dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q);
122122
dev->dev_attrib.hw_queue_depth = q->nr_requests;
123123

124-
/*
125-
* Check if the underlying struct block_device request_queue supports
126-
* the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
127-
* in ATA and we need to set TPE=1
128-
*/
129-
if (blk_queue_discard(q)) {
130-
dev->dev_attrib.max_unmap_lba_count =
131-
q->limits.max_discard_sectors;
132-
133-
/*
134-
* Currently hardcoded to 1 in Linux/SCSI code..
135-
*/
136-
dev->dev_attrib.max_unmap_block_desc_count = 1;
137-
dev->dev_attrib.unmap_granularity =
138-
q->limits.discard_granularity >> 9;
139-
dev->dev_attrib.unmap_granularity_alignment =
140-
q->limits.discard_alignment;
141-
dev->dev_attrib.unmap_zeroes_data =
142-
q->limits.discard_zeroes_data;
143-
124+
if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
125+
dev->dev_attrib.hw_block_size))
144126
pr_debug("IBLOCK: BLOCK Discard support available,"
145-
" disabled by default\n");
146-
}
127+
" disabled by default\n");
128+
147129
/*
148130
* Enable write same emulation for IBLOCK and use 0xFFFF as
149131
* the smaller WRITE_SAME(10) only has a two-byte block count.
@@ -415,9 +397,13 @@ static sense_reason_t
415397
iblock_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
416398
{
417399
struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
400+
struct se_device *dev = cmd->se_dev;
418401
int ret;
419402

420-
ret = blkdev_issue_discard(bdev, lba, nolb, GFP_KERNEL, 0);
403+
ret = blkdev_issue_discard(bdev,
404+
target_to_linux_sector(dev, lba),
405+
target_to_linux_sector(dev, nolb),
406+
GFP_KERNEL, 0);
421407
if (ret < 0) {
422408
pr_err("blkdev_issue_discard() failed: %d\n", ret);
423409
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -433,8 +419,10 @@ iblock_execute_write_same(struct se_cmd *cmd)
433419
struct scatterlist *sg;
434420
struct bio *bio;
435421
struct bio_list list;
436-
sector_t block_lba = cmd->t_task_lba;
437-
sector_t sectors = sbc_get_write_same_sectors(cmd);
422+
struct se_device *dev = cmd->se_dev;
423+
sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba);
424+
sector_t sectors = target_to_linux_sector(dev,
425+
sbc_get_write_same_sectors(cmd));
438426

439427
if (cmd->prot_op) {
440428
pr_err("WRITE_SAME: Protection information with IBLOCK"
@@ -648,12 +636,12 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
648636
enum dma_data_direction data_direction)
649637
{
650638
struct se_device *dev = cmd->se_dev;
639+
sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba);
651640
struct iblock_req *ibr;
652641
struct bio *bio, *bio_start;
653642
struct bio_list list;
654643
struct scatterlist *sg;
655644
u32 sg_num = sgl_nents;
656-
sector_t block_lba;
657645
unsigned bio_cnt;
658646
int rw = 0;
659647
int i;
@@ -679,24 +667,6 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
679667
rw = READ;
680668
}
681669

682-
/*
683-
* Convert the blocksize advertised to the initiator to the 512 byte
684-
* units unconditionally used by the Linux block layer.
685-
*/
686-
if (dev->dev_attrib.block_size == 4096)
687-
block_lba = (cmd->t_task_lba << 3);
688-
else if (dev->dev_attrib.block_size == 2048)
689-
block_lba = (cmd->t_task_lba << 2);
690-
else if (dev->dev_attrib.block_size == 1024)
691-
block_lba = (cmd->t_task_lba << 1);
692-
else if (dev->dev_attrib.block_size == 512)
693-
block_lba = cmd->t_task_lba;
694-
else {
695-
pr_err("Unsupported SCSI -> BLOCK LBA conversion:"
696-
" %u\n", dev->dev_attrib.block_size);
697-
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
698-
}
699-
700670
ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
701671
if (!ibr)
702672
goto fail;

include/target/target_core_backend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,8 @@ sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd,
9494
sense_reason_t (*exec_cmd)(struct se_cmd *cmd));
9595

9696
bool target_sense_desc_format(struct se_device *dev);
97+
sector_t target_to_linux_sector(struct se_device *dev, sector_t lb);
98+
bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
99+
struct request_queue *q, int block_size);
97100

98101
#endif /* TARGET_CORE_BACKEND_H */

0 commit comments

Comments
 (0)