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