Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1459225 > unrolled thread
| Started by | Shaun Tancheff <shaun@tancheff.com> |
|---|---|
| First post | 2016-08-10 03:10 +0200 |
| Last post | 2016-08-10 21:40 +0200 |
| Articles | 4 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH v5 0/2] Add support for SCT Write Same Shaun Tancheff <shaun@tancheff.com> - 2016-08-10 03:10 +0200
[PATCH v5 1/2] Use kmap_atomic when rewriting attached page Shaun Tancheff <shaun@tancheff.com> - 2016-08-10 03:10 +0200
Re: [PATCH v5 1/2] Use kmap_atomic when rewriting attached page Shaun Tancheff <shaun.tancheff@seagate.com> - 2016-08-10 20:10 +0200
Re: [PATCH v5 1/2] Use kmap_atomic when rewriting attached page Tom Yan <tom.ty89@gmail.com> - 2016-08-10 21:40 +0200
| From | Shaun Tancheff <shaun@tancheff.com> |
|---|---|
| Date | 2016-08-10 03:10 +0200 |
| Subject | [PATCH v5 0/2] Add support for SCT Write Same |
| Message-ID | <s4qbT-6NI-5@gated-at.bofh.it> |
At some point the method of issuing Write Same for ATA drives changed. Currently write same is commonly available via SCT so expose the SCT capabilities and use SCT Write Same when it is available. This is useful for zoned based media that prefers to support discard with lbprz set, aka discard zeroes data by mapping discard operations to reset write pointer operations. Conventional zones that do not support reset write pointer can still honor the discard zeroes data by issuing a write same over the zone. It may also be nice to know if various controllers that currently disable WRITE SAME will work with the SCT Write Same code path: aacraid, arcmsr, megaraid, 3w-9xxx, 3w-sas, 3w-xxxx, gdth, hpsa, ips, megaraid, pmcraid, storvsc_drv This patch against v4.8-rc1 is also at https://github.com/stancheff/linux/tree/v4.8-rc1+ws.v5 git@github.com:stancheff/linux.git v4.8-rc1+ws.v5 Shaun Tancheff (2): Use kmap_atomic when rewriting attached page Add support for SCT Write Same drivers/ata/libata-scsi.c | 240 ++++++++++++++++++++++++++++++++++++++++------ include/linux/ata.h | 69 ++++++++----- 2 files changed, 252 insertions(+), 57 deletions(-) -- 2.8.1
[toc] | [next] | [standalone]
| From | Shaun Tancheff <shaun@tancheff.com> |
|---|---|
| Date | 2016-08-10 03:10 +0200 |
| Subject | [PATCH v5 1/2] Use kmap_atomic when rewriting attached page |
| Message-ID | <s4qbT-6NI-15@gated-at.bofh.it> |
| In reply to | #1459225 |
The current SATL for WRITE_SAME does not protect against misaligned
pages. Additionally the associated page should also kmap'd when
being modified.
Signed-off-by: Shaun Tancheff <shaun.tancheff@seagate.com>
---
v5: Added prep patch to work with non-page aligned scatterlist pages
and use kmap_atomic() to lock page during modification.
drivers/ata/libata-scsi.c | 53 ++++++++++++++++++++++++++++++++++++++++++-----
include/linux/ata.h | 26 -----------------------
2 files changed, 48 insertions(+), 31 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index e207b33..a71067a 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3282,16 +3282,60 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
return 1;
}
+/**
+ * ata_format_dsm_trim_descr() - SATL Write Same to DSM Trim
+ * @sg: Scatter / Gather list attached to command.
+ * @num: Maximum number of entries (nominally 64).
+ * @sector: Starting sector
+ * @count: Total Range of request
+ *
+ * Rewrite the WRITE SAME descriptor to be a DSM TRIM little-endian formatted
+ * descriptor.
+ *
+ * Upto 64 entries of the format:
+ * 63:48 Range Length
+ * 47:0 LBA
+ *
+ * Range Length of 0 is ignored.
+ * LBA's should be sorted order and not overlap.
+ *
+ * NOTE: this is the same format as ADD LBA(S) TO NV CACHE PINNED SET
+ */
+static unsigned int ata_format_dsm_trim_descr(struct scatterlist *sg, u32 num,
+ u64 sector, u32 count)
+{
+ void *ptr = kmap_atomic(sg_page(sg));
+ __le64 *buffer = ptr + sg->offset;
+ u32 i = 0, used_bytes;
+
+ while (i < num) {
+ u64 entry = sector |
+ ((u64)(count > 0xffff ? 0xffff : count) << 48);
+ buffer[i++] = __cpu_to_le64(entry);
+ if (count <= 0xffff)
+ break;
+ count -= 0xffff;
+ sector += 0xffff;
+ }
+
+ used_bytes = ALIGN(i * 8, 512);
+ memset(buffer + i, 0, used_bytes - i * 8);
+
+ kunmap_atomic(ptr);
+ return used_bytes;
+}
+
static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
{
struct ata_taskfile *tf = &qc->tf;
struct scsi_cmnd *scmd = qc->scsicmd;
struct ata_device *dev = qc->dev;
const u8 *cdb = scmd->cmnd;
+ struct scatterlist *sg;
u64 block;
u32 n_block;
+ const u32 trmax = ATA_MAX_TRIM_RNUM;
u32 size;
- void *buf;
u16 fp;
u8 bp = 0xff;
@@ -3319,10 +3363,9 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
if (!scsi_sg_count(scmd))
goto invalid_param_len;
- buf = page_address(sg_page(scsi_sglist(scmd)));
-
- if (n_block <= 65535 * ATA_MAX_TRIM_RNUM) {
- size = ata_set_lba_range_entries(buf, ATA_MAX_TRIM_RNUM, block, n_block);
+ sg = scsi_sglist(scmd);
+ if (n_block <= 0xffff * cmax) {
+ size = ata_format_dsm_trim_descr(sg, trmax, block, n_block);
} else {
fp = 2;
goto invalid_fld;
diff --git a/include/linux/ata.h b/include/linux/ata.h
index adbc812..45a1d71 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -1071,32 +1071,6 @@ static inline void ata_id_to_hd_driveid(u16 *id)
#endif
}
-/*
- * Write LBA Range Entries to the buffer that will cover the extent from
- * sector to sector + count. This is used for TRIM and for ADD LBA(S)
- * TO NV CACHE PINNED SET.
- */
-static inline unsigned ata_set_lba_range_entries(void *_buffer,
- unsigned num, u64 sector, unsigned long count)
-{
- __le64 *buffer = _buffer;
- unsigned i = 0, used_bytes;
-
- while (i < num) {
- u64 entry = sector |
- ((u64)(count > 0xffff ? 0xffff : count) << 48);
- buffer[i++] = __cpu_to_le64(entry);
- if (count <= 0xffff)
- break;
- count -= 0xffff;
- sector += 0xffff;
- }
-
- used_bytes = ALIGN(i * 8, 512);
- memset(buffer + i, 0, used_bytes - i * 8);
- return used_bytes;
-}
-
static inline bool ata_ok(u8 status)
{
return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
--
2.8.1
[toc] | [prev] | [next] | [standalone]
| From | Shaun Tancheff <shaun.tancheff@seagate.com> |
|---|---|
| Date | 2016-08-10 20:10 +0200 |
| Subject | Re: [PATCH v5 1/2] Use kmap_atomic when rewriting attached page |
| Message-ID | <s4G71-8uN-93@gated-at.bofh.it> |
| In reply to | #1459227 |
On Wed, Aug 10, 2016 at 5:56 AM, Tom Yan <tom.ty89@gmail.com> wrote:
> On 10 August 2016 at 09:00, Shaun Tancheff <shaun@tancheff.com> wrote:
>> static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
>> {
>> struct ata_taskfile *tf = &qc->tf;
>> struct scsi_cmnd *scmd = qc->scsicmd;
>> struct ata_device *dev = qc->dev;
>> const u8 *cdb = scmd->cmnd;
>> + struct scatterlist *sg;
>> u64 block;
>> u32 n_block;
>> + const u32 trmax = ATA_MAX_TRIM_RNUM;
>> u32 size;
>> - void *buf;
>> u16 fp;
>> u8 bp = 0xff;
>>
>> @@ -3319,10 +3363,9 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
>> if (!scsi_sg_count(scmd))
>> goto invalid_param_len;
>>
>> - buf = page_address(sg_page(scsi_sglist(scmd)));
>> -
>> - if (n_block <= 65535 * ATA_MAX_TRIM_RNUM) {
>> - size = ata_set_lba_range_entries(buf, ATA_MAX_TRIM_RNUM, block, n_block);
>> + sg = scsi_sglist(scmd);
>> + if (n_block <= 0xffff * cmax) {
>
> Although this got moved and corrected in the next patch, but perhaps
> you should still correct the `cmax` here, which should be `trmax`.
You are correct. I will fix this up. Thanks!
>> + size = ata_format_dsm_trim_descr(sg, trmax, block, n_block);
>> } else {
>> fp = 2;
>> goto invalid_fld;
--
Shaun Tancheff
[toc] | [prev] | [next] | [standalone]
| From | Tom Yan <tom.ty89@gmail.com> |
|---|---|
| Date | 2016-08-10 21:40 +0200 |
| Subject | Re: [PATCH v5 1/2] Use kmap_atomic when rewriting attached page |
| Message-ID | <s4G71-8uN-95@gated-at.bofh.it> |
| In reply to | #1459227 |
On 10 August 2016 at 09:00, Shaun Tancheff <shaun@tancheff.com> wrote:
> static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
> {
> struct ata_taskfile *tf = &qc->tf;
> struct scsi_cmnd *scmd = qc->scsicmd;
> struct ata_device *dev = qc->dev;
> const u8 *cdb = scmd->cmnd;
> + struct scatterlist *sg;
> u64 block;
> u32 n_block;
> + const u32 trmax = ATA_MAX_TRIM_RNUM;
> u32 size;
> - void *buf;
> u16 fp;
> u8 bp = 0xff;
>
> @@ -3319,10 +3363,9 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
> if (!scsi_sg_count(scmd))
> goto invalid_param_len;
>
> - buf = page_address(sg_page(scsi_sglist(scmd)));
> -
> - if (n_block <= 65535 * ATA_MAX_TRIM_RNUM) {
> - size = ata_set_lba_range_entries(buf, ATA_MAX_TRIM_RNUM, block, n_block);
> + sg = scsi_sglist(scmd);
> + if (n_block <= 0xffff * cmax) {
Although this got moved and corrected in the next patch, but perhaps
you should still correct the `cmax` here, which should be `trmax`.
> + size = ata_format_dsm_trim_descr(sg, trmax, block, n_block);
> } else {
> fp = 2;
> goto invalid_fld;
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web