Skip to content

Commit 5251ae2

Browse files
damien-lemoalfloatious
authored andcommitted
ata: libata-scsi: Return residual for emulated SCSI commands
The function ata_scsi_rbuf_fill() used to fill the reply buffer of emulated SCSI commands always copies the ATA reply buffer (ata_scsi_rbuf) up to the size of the SCSI command buffer (the transfer length for the command), even if the reply is shorter than the SCSI command buffer. This leads to issuers of the SCSI command to always get a result without any residual (resid is always 0) despite the potentially shorter reply for the command. Modify all fill actors used by ata_scsi_rbuf_fill() to return the number of bytes filled for the reply and 0 in case of error. Using this value, add a call to scsi_set_resid() in ata_scsi_rbuf_fill() to set the correct residual for the SCSI command when the reply length is shorter than the command buffer. Signed-off-by: Damien Le Moal <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Niklas Cassel <[email protected]>
1 parent 2365278 commit 5251ae2

File tree

1 file changed

+47
-34
lines changed

1 file changed

+47
-34
lines changed

drivers/ata/libata-scsi.c

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,17 +1792,19 @@ static void ata_scsi_rbuf_fill(struct ata_device *dev, struct scsi_cmnd *cmd,
17921792
unsigned int (*actor)(struct ata_device *dev,
17931793
struct scsi_cmnd *cmd, u8 *rbuf))
17941794
{
1795-
unsigned int rc;
17961795
unsigned long flags;
1796+
unsigned int len;
17971797

17981798
spin_lock_irqsave(&ata_scsi_rbuf_lock, flags);
17991799

18001800
memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
1801-
rc = actor(dev, cmd, ata_scsi_rbuf);
1802-
if (rc == 0) {
1801+
len = actor(dev, cmd, ata_scsi_rbuf);
1802+
if (len) {
18031803
sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
18041804
ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
18051805
cmd->result = SAM_STAT_GOOD;
1806+
if (scsi_bufflen(cmd) > len)
1807+
scsi_set_resid(cmd, scsi_bufflen(cmd) - len);
18061808
}
18071809

18081810
spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags);
@@ -1890,7 +1892,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_device *dev,
18901892
else
18911893
memcpy(rbuf + 58, versions, sizeof(versions));
18921894

1893-
return 0;
1895+
/*
1896+
* Include all 8 possible version descriptors, even if not all of
1897+
* them are popoulated.
1898+
*/
1899+
return 96;
18941900
}
18951901

18961902
/**
@@ -1928,7 +1934,8 @@ static unsigned int ata_scsiop_inq_00(struct ata_device *dev,
19281934
num_pages++;
19291935
}
19301936
rbuf[3] = num_pages; /* number of supported VPD pages */
1931-
return 0;
1937+
1938+
return get_unaligned_be16(&rbuf[2]) + 4;
19321939
}
19331940

19341941
/**
@@ -1955,7 +1962,8 @@ static unsigned int ata_scsiop_inq_80(struct ata_device *dev,
19551962
memcpy(rbuf, hdr, sizeof(hdr));
19561963
ata_id_string(dev->id, (unsigned char *) &rbuf[4],
19571964
ATA_ID_SERNO, ATA_ID_SERNO_LEN);
1958-
return 0;
1965+
1966+
return get_unaligned_be16(&rbuf[2]) + 4;
19591967
}
19601968

19611969
/**
@@ -2016,7 +2024,8 @@ static unsigned int ata_scsiop_inq_83(struct ata_device *dev,
20162024
num += ATA_ID_WWN_LEN;
20172025
}
20182026
rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */
2019-
return 0;
2027+
2028+
return get_unaligned_be16(&rbuf[2]) + 4;
20202029
}
20212030

20222031
/**
@@ -2053,7 +2062,8 @@ static unsigned int ata_scsiop_inq_89(struct ata_device *dev,
20532062
rbuf[56] = ATA_CMD_ID_ATA;
20542063

20552064
memcpy(&rbuf[60], &dev->id[0], 512);
2056-
return 0;
2065+
2066+
return get_unaligned_be16(&rbuf[2]) + 4;
20572067
}
20582068

20592069
/**
@@ -2104,7 +2114,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_device *dev,
21042114
put_unaligned_be32(1, &rbuf[28]);
21052115
}
21062116

2107-
return 0;
2117+
return get_unaligned_be16(&rbuf[2]) + 4;
21082118
}
21092119

21102120
/**
@@ -2134,7 +2144,7 @@ static unsigned int ata_scsiop_inq_b1(struct ata_device *dev,
21342144
if (zoned)
21352145
rbuf[8] = (zoned << 4);
21362146

2137-
return 0;
2147+
return get_unaligned_be16(&rbuf[2]) + 4;
21382148
}
21392149

21402150
/**
@@ -2157,7 +2167,7 @@ static unsigned int ata_scsiop_inq_b2(struct ata_device *dev,
21572167
rbuf[3] = 0x4;
21582168
rbuf[5] = 1 << 6; /* TPWS */
21592169

2160-
return 0;
2170+
return get_unaligned_be16(&rbuf[2]) + 4;
21612171
}
21622172

21632173
/**
@@ -2177,7 +2187,7 @@ static unsigned int ata_scsiop_inq_b6(struct ata_device *dev,
21772187
{
21782188
if (!(dev->flags & ATA_DFLAG_ZAC)) {
21792189
ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
2180-
return 1;
2190+
return 0;
21812191
}
21822192

21832193
/*
@@ -2195,7 +2205,7 @@ static unsigned int ata_scsiop_inq_b6(struct ata_device *dev,
21952205
put_unaligned_be32(dev->zac_zones_optimal_nonseq, &rbuf[12]);
21962206
put_unaligned_be32(dev->zac_zones_max_open, &rbuf[16]);
21972207

2198-
return 0;
2208+
return get_unaligned_be16(&rbuf[2]) + 4;
21992209
}
22002210

22012211
/**
@@ -2219,7 +2229,7 @@ static unsigned int ata_scsiop_inq_b9(struct ata_device *dev,
22192229

22202230
if (!cpr_log) {
22212231
ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
2222-
return 1;
2232+
return 0;
22232233
}
22242234

22252235
/* SCSI Concurrent Positioning Ranges VPD page: SBC-5 rev 1 or later */
@@ -2233,7 +2243,7 @@ static unsigned int ata_scsiop_inq_b9(struct ata_device *dev,
22332243
put_unaligned_be64(cpr_log->cpr[i].num_lbas, &desc[16]);
22342244
}
22352245

2236-
return 0;
2246+
return get_unaligned_be16(&rbuf[2]) + 4;
22372247
}
22382248

22392249
/**
@@ -2255,7 +2265,7 @@ static unsigned int ata_scsiop_inquiry(struct ata_device *dev,
22552265
/* is CmdDt set? */
22562266
if (scsicmd[1] & 2) {
22572267
ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
2258-
return 1;
2268+
return 0;
22592269
}
22602270

22612271
/* Is EVPD clear? */
@@ -2283,7 +2293,7 @@ static unsigned int ata_scsiop_inquiry(struct ata_device *dev,
22832293
return ata_scsiop_inq_b9(dev, cmd, rbuf);
22842294
default:
22852295
ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
2286-
return 1;
2296+
return 0;
22872297
}
22882298
}
22892299

@@ -2614,24 +2624,27 @@ static unsigned int ata_scsiop_mode_sense(struct ata_device *dev,
26142624
rbuf[3] = sizeof(sat_blk_desc);
26152625
memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc));
26162626
}
2617-
} else {
2618-
put_unaligned_be16(p - rbuf - 2, &rbuf[0]);
2619-
rbuf[3] |= dpofua;
2620-
if (ebd) {
2621-
rbuf[7] = sizeof(sat_blk_desc);
2622-
memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
2623-
}
2627+
2628+
return rbuf[0] + 1;
2629+
}
2630+
2631+
put_unaligned_be16(p - rbuf - 2, &rbuf[0]);
2632+
rbuf[3] |= dpofua;
2633+
if (ebd) {
2634+
rbuf[7] = sizeof(sat_blk_desc);
2635+
memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
26242636
}
2625-
return 0;
2637+
2638+
return get_unaligned_be16(&rbuf[0]) + 2;
26262639

26272640
invalid_fld:
26282641
ata_scsi_set_invalid_field(dev, cmd, fp, bp);
2629-
return 1;
2642+
return 0;
26302643

26312644
saving_not_supp:
26322645
ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x39, 0x0);
26332646
/* "Saving parameters not supported" */
2634-
return 1;
2647+
return 0;
26352648
}
26362649

26372650
/**
@@ -2674,7 +2687,7 @@ static unsigned int ata_scsiop_read_cap(struct ata_device *dev,
26742687
rbuf[6] = sector_size >> (8 * 1);
26752688
rbuf[7] = sector_size;
26762689

2677-
return 0;
2690+
return 8;
26782691
}
26792692

26802693
/*
@@ -2684,7 +2697,7 @@ static unsigned int ata_scsiop_read_cap(struct ata_device *dev,
26842697
if (scsicmd[0] != SERVICE_ACTION_IN_16 ||
26852698
(scsicmd[1] & 0x1f) != SAI_READ_CAPACITY_16) {
26862699
ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
2687-
return 1;
2700+
return 0;
26882701
}
26892702

26902703
/* sector count, 64-bit */
@@ -2719,7 +2732,7 @@ static unsigned int ata_scsiop_read_cap(struct ata_device *dev,
27192732
}
27202733
}
27212734

2722-
return 0;
2735+
return 16;
27232736
}
27242737

27252738
/**
@@ -2738,7 +2751,7 @@ static unsigned int ata_scsiop_report_luns(struct ata_device *dev,
27382751
{
27392752
rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */
27402753

2741-
return 0;
2754+
return 16;
27422755
}
27432756

27442757
/*
@@ -3463,13 +3476,13 @@ static unsigned int ata_scsiop_maint_in(struct ata_device *dev,
34633476

34643477
if ((cdb[1] & 0x1f) != MI_REPORT_SUPPORTED_OPERATION_CODES) {
34653478
ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
3466-
return 1;
3479+
return 0;
34673480
}
34683481

34693482
if (cdb[2] != 1 && cdb[2] != 3) {
34703483
ata_dev_warn(dev, "invalid command format %d\n", cdb[2]);
34713484
ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
3472-
return 1;
3485+
return 0;
34733486
}
34743487

34753488
switch (cdb[3]) {
@@ -3542,7 +3555,7 @@ static unsigned int ata_scsiop_maint_in(struct ata_device *dev,
35423555
rbuf[0] = rwcdlp;
35433556
rbuf[1] = cdlp | supported;
35443557

3545-
return 0;
3558+
return 4;
35463559
}
35473560

35483561
/**

0 commit comments

Comments
 (0)