misc/187269: AF-4Kn SATA drives have mis-interpreted sector sizes
Ravi Pokala
rpokala at panasas.com
Wed Mar 5 04:20:01 UTC 2014
>Number: 187269
>Category: misc
>Synopsis: AF-4Kn SATA drives have mis-interpreted sector sizes
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Mar 05 04:20:00 UTC 2014
>Closed-Date:
>Last-Modified:
>Originator: Ravi Pokala
>Release: 10-STABLE r262757
>Organization:
Panasas, Inc.
>Environment:
FreeBSD mau-kennedy-1a 10.0-STABLE FreeBSD 10.0-STABLE #0 r262757M: Tue Mar 4 17:24:53 PST 2014 root at mau-kennedy-1a:/usr/obj/usr/src/sys/GENERIC amd64
>Description:
AF-4Kn SATA drives (4KB logical sector size, 4KB physical sector size) are being identified as having 2KB logical sectors and 512-byte physical sectors. This leads to data access timing out, the GPT being unreadable, and general uselessness.
The drive that I was using when I discovered this problem is an engineering sample under NDA, so I have obscured the model/firmware/serial/WWN; sorry about that. The label states that the capacity is 5.0TB and that there are 1220942646 LBAs.
/var/run/dmesg.boot (comments indented):
----------------------------------------------------------------
ada0 at ahcich0 bus 0 scbus0 target 0 lun 0
ada0: <DRIVE-MODEL DRIVE-FW> ATA-9 SATA 3.x device
ada0: Serial Number DRIVE-SERIAL-NUMBER
ada0: 600.000MB/s transfers (SATA 3.x, UDMA6, PIO 4096bytes)
ada0: Command Queueing enabled
ada0: 2384653MB (1220942646 2048 byte sectors: 16H 63S/T 16383C)
Incorrect capacity
Correct number of logical sectors, but incorrect sector size
ada0: Previously was known as ad4
(ada0:ahcich0:0:0:0): READ_DMA48. ACB: 25 00 f7 1a c6 40 48 00 00 00 04 00
(ada0:ahcich0:0:0:0): CAM status: CCB request was invalid
(ada0:ahcich0:0:0:0): Error 22, Unretryable error
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 01 34 1b c6 40 48 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: CCB request was invalid
(ada0:ahcich0:0:0:0): Error 22, Unretryable error
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 01 34 1b c6 40 48 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: CCB request was invalid
(ada0:ahcich0:0:0:0): Error 22, Unretryable error
GEOM: ada0: corrupt or invalid GPT detected.
GEOM: ada0: GPT rejected -- may not be recoverable.
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 20 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 20 00 00 00 00 00 00 00 00
5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 04 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 04 00 00 00 00 00 00 00 00
5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 00 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 00 00 00 00 00 00 00 00 00
5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 80 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 80 00 00 00 00 00 00 00 00
5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 20 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 20 00 00 00 00 00 00 00 00
5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 04 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 04 00 00 00 00 00 00 00 00
5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 00 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 00 00 00 00 00 00 00 00 00
5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 80 00 00 40 00 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 80 00 00 00 00 00 00 00 00
5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 04 f7 1a c6 40 48 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: ATA Status Error
(ada0:ahcich0:0:0:0): ATA status: 41 (DRDY ERR), error: 84 (ICRC ABRT )
(ada0:ahcich0:0:0:0): RES: 41 84 f7 1a c6 00 48 00 00 00 00
5 attempts
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 01 34 1b c6 40 48 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: CCB request was invalid
(ada0:ahcich0:0:0:0): Error 22, Unretryable error
(ada0:ahcich0:0:0:0): READ_FPDMA_QUEUED. ACB: 60 01 34 1b c6 40 48 00 00 00 00 00
(ada0:ahcich0:0:0:0): CAM status: CCB request was invalid
(ada0:ahcich0:0:0:0): Error 22, Unretryable error
----------------------------------------------------------------
`camcontrol identify ada0' (comments indented):
----------------------------------------------------------------
pass0: <DRIVE-MODEL DRIVE-FW> ATA-9 SATA 3.x device
pass0: 600.000MB/s transfers (SATA 3.x, UDMA6, PIO 4096bytes)
protocol ATA/ATAPI-9 SATA 3.x
device model DRIVE-MODEL
firmware revision DRIVE-FW
serial number DRIVE-SERIAL-NUMBER
WWN DRIVE-WWN
cylinders 16383
heads 16
sectors/track 63
sector size logical 2048, physical 512, offset 0
Incorrect sector sizes
LBA supported 268435455 sectors
LBA48 supported 1220942646 sectors
PIO supported PIO4
DMA supported WDMA2 UDMA6
media RPM 7200
Feature Support Enabled Value Vendor
read ahead yes yes
write cache yes yes
flush cache yes yes
overlap no
Tagged Command Queuing (TCQ) no no
Native Command Queuing (NCQ) yes 32 tags
SMART yes yes
microcode download yes yes
security yes no
power management yes yes
advanced power management yes yes 128/0x80
automatic acoustic management no no
media status notification no no
power-up in Standby yes no
write-read-verify no no
unload no no
free-fall no no
Data Set Management (DSM/TRIM) no
Host Protected Area (HPA) no
----------------------------------------------------------------
I looked at the code, and discovered two issues:
(1) sys/cam/ata/ata_all.c::ata_logical_sector_size()
The function returns the LSS in bytes. If IDENTIFY_DEVICE word 'pss' indicates that the LSS is larger than 512 bytes, it concatenates words 'lss_1' and 'lss_2' into a 'u_int32_t' and returns it. However, the ATA specs define that value as the number of *words* in a logical sector, not the number of bytes. Thus, it returns 2048 instead of 4096 as the LSS.
----------------------------------------------------------------
(2) sys/cam/ata/ata_all.c::ata_physical_sector_size()
The function returns the PSS in bytes. If IDENTIFY_DEVICE word 'pss' indicates that there are multiple logical sectors per physical sector, it extracts the scaling factor, multiplies it by the LSS, and returns the result; otherwise, it returns a PSS of 512 bytes. The problem here is that, if there is only one logical sector per physical sector, the logical sector size is completely ignored.
>How-To-Repeat:
Boot with an AF-4Kn SATA drive attached.
>Fix:
The attached patch fixes both of the problems (I also took the liberty of replacing a few magic constants (a bitmask and value used for validation) with '#define's.)
(1) sys/cam/ata/ata_all.c::ata_logical_sector_size()
After concatenating 'lss_1' and 'lss_2', convert from words to bytes by left-shifting one bit.
----------------------------------------------------------------
(2) sys/cam/ata/ata_all.c::ata_physical_sector_size()
If there is only a single logical sector per physical sector, then the physical sector size is equal to the logical sector size, so return that value.
----------------------------------------------------------------
/var/run/dmesg.boot (comments indented):
----------------------------------------------------------------
ada0 at ahcich0 bus 0 scbus0 target 0 lun 0
ada0: <DRIVE-MODEL DRIVE-FW> ATA-9 SATA 3.x device
ada0: Serial Number DRIVE-SERIAL-NUMBER
ada0: 600.000MB/s transfers (SATA 3.x, UDMA6, PIO 8192bytes)
ada0: Command Queueing enabled
ada0: 4769307MB (1220942646 4096 byte sectors: 16H 63S/T 16383C)
Correct capacity
Correct number of logical sectors, and correct sector size
ada0: Previously was known as ad4
No errors; GPT was read and parsed correctly
----------------------------------------------------------------
`gpart show ada0':
----------------------------------------------------------------
=> 6 1220942635 ada0 GPT (4.5T)
6 3969000 2 freebsd-ufs (15G)
3969006 1216973635 - free - (4.5T)
----------------------------------------------------------------
`camcontrol identify ada0' (comments indented):
----------------------------------------------------------------
pass0: <DRIVE-MODEL DRIVE-FW> ATA-9 SATA 3.x device
pass0: 600.000MB/s transfers (SATA 3.x, UDMA6, PIO 8192bytes)
protocol ATA/ATAPI-9 SATA 3.x
device model DRIVE-MODEL
firmware revision DRIVE-FW
serial number DRIVE-SERIAL-NUMBER
WWN DRIVE-WWN
cylinders 16383
heads 16
sectors/track 63
sector size logical 4096, physical 4096, offset 0
Correct sector sizes
LBA supported 268435455 sectors
LBA48 supported 1220942646 sectors
PIO supported PIO4
DMA supported WDMA2 UDMA6
media RPM 7200
Feature Support Enabled Value Vendor
read ahead yes yes
write cache yes yes
flush cache yes yes
overlap no
Tagged Command Queuing (TCQ) no no
Native Command Queuing (NCQ) yes 32 tags
SMART yes yes
microcode download yes yes
security yes no
power management yes yes
advanced power management yes yes 128/0x80
automatic acoustic management no no
media status notification no no
power-up in Standby yes no
write-read-verify no no
unload no no
free-fall no no
Data Set Management (DSM/TRIM) no
Host Protected Area (HPA) no
----------------------------------------------------------------
Patch attached with submission follows:
Index: sys/cam/ata/ata_all.c
===================================================================
--- sys/cam/ata/ata_all.c (revision 262757)
+++ sys/cam/ata/ata_all.c (working copy)
@@ -338,10 +338,10 @@
uint32_t
ata_logical_sector_size(struct ata_params *ident_data)
{
- if ((ident_data->pss & 0xc000) == 0x4000 &&
+ if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE &&
(ident_data->pss & ATA_PSS_LSSABOVE512)) {
- return ((u_int32_t)ident_data->lss_1 |
- ((u_int32_t)ident_data->lss_2 << 16));
+ return (u_int32_t) (((u_int32_t)ident_data->lss_1 |
+ ((u_int32_t)ident_data->lss_2 << 16)) << 1);
}
return (512);
}
@@ -349,10 +349,13 @@
uint64_t
ata_physical_sector_size(struct ata_params *ident_data)
{
- if ((ident_data->pss & 0xc000) == 0x4000 &&
- (ident_data->pss & ATA_PSS_MULTLS)) {
- return ((uint64_t)ata_logical_sector_size(ident_data) *
- (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+ if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE) {
+ if (ident_data->pss & ATA_PSS_MULTLS) {
+ return ((uint64_t)ata_logical_sector_size(ident_data) *
+ (1 << (ident_data->pss & ATA_PSS_LSPPS)));
+ } else {
+ return (uint64_t)ata_logical_sector_size(ident_data);
+ }
}
return (512);
}
Index: sys/sys/ata.h
===================================================================
--- sys/sys/ata.h (revision 262757)
+++ sys/sys/ata.h (working copy)
@@ -211,6 +211,8 @@
u_int16_t reserved104;
/*105*/ u_int16_t max_dsm_blocks;
/*106*/ u_int16_t pss;
+#define ATA_PSS_VALID_MASK 0xC000
+#define ATA_PSS_VALID_VALUE 0x4000
#define ATA_PSS_LSPPS 0x000F
#define ATA_PSS_LSSABOVE512 0x1000
#define ATA_PSS_MULTLS 0x2000
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list