anatol/smart.go

LBA for SATA

Artist50S opened this issue · 6 comments

Hello. Faced the problem of obtaining data on the size of the logical and physical sectors. In the structure AtaIdentifyDevice.
LogicalPerPhisicalSectors uint16 // Word 106, Physical sector size / logical sector size
my code

   disk:= "sda"
   sd, err := smart.OpenSata("/dev/" + disk)
	if err != nil {
		s.logger.Error("open SATA "+disk, "error", err)
	}
   defer sd.Close()
   identify, err := sd.Identify()
	if err != nil {
		s.logger.Error("identify SATA "+disk, "error", err)
        }
  fmt.Println("sector size: " + fmt.Sprint(identify.LogicalPerPhisicalSectors))
  //sector size: 16384

Why is it outputting the number 16384, what is that number?

smartctl -a /dev/sda
=== START OF INFORMATION SECTION ===
Model Family:     Phison Driven SSDs
Device Model:     KINGSTON SEDC500R480G
Serial Number:    50026B7281111111
LU WWN Device Id: 5 0026b7 28281dfaa
Firmware Version: SCEKJ2.7
User Capacity:    480,103,981,056 bytes [480 GB]
Sector Size:      512 bytes logical/physical
Rotation Rate:    Solid State Device
Form Factor:      2.5 inches
Device is:        In smartctl database [for details use: -P show]
ATA Version is:   ACS-3 (minor revision not indicated)
SATA Version is:  SATA 3.1, 6.0 Gb/s (current: 6.0 Gb/s)
Local Time is:    Mon Jan 16 10:33:13 2023 UTC
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

Tell me what could be wrong?

Could you please also provide output of fmt.Printf("%+v\n", identify)?

&{GeneralConfig:64 _:[0 0 0 0 0 0 0 0 0] SerialNumberRaw:[48 53 50 48 66 54 50 55 50 56 49 56 70 68 65 65 32 32 32 32] _:[0 0 0] FirmwareRevisionRaw:[67 83 75 69 50 74 55 46] ModelNumberRaw:[73 75 71 78 84 83 78 79 83 32 68 69 53 67 48 48 52 82 48 56 32 71 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32] _:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] QueueDepth:31 SATACap:58638 SATACapAddl:6 FeaturesSupported:76 FeaturesEnabled:68 MajorVersion:2040 MinorVersion:0 CommandsSupported1:29803 CommandsSupported2:32009 CommandsSupported3:16739 CommandsEnabled1:29801 CommandsEnabled2:48137 CommandsEnabled3:16739 DMAModes:16511 _:[0 0 0 0] ResetResults:0 _:[0 0 0 0 0 0 0 0 0 0 0 0] LogicalPerPhisicalSectors:16384 InterSeekDelay:0 WWNRaw:[20482 27506 33409 57258] _:[0 0 0 0 0 0 0] CommandsSupported4:16409 CommandsEnabled4:16409 _:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] RotationRate:1 _:[0 0 0 0] TransportMajor:4223 _:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]}

Thank you!

I think I see what is going here. Per specification this field is a bitfield and defined as:

Physical sector size / logical sector size (see 7.12.7.56)
15 Shall be cleared to zero
14 Shall be set to one
13 Device has multiple logical sectors per physical sector.
12 Device Logical Sector longer than 256 words
11:4 Reserved
3:0 2^X logical sectors per physical sector

to compute the number of sectors you need to get 4 lower bits of the field and then compute 2^x, in your case 2^0 i.e. the drive has 1 logical sector per physical one.

Thank you.

It is surprisingly challenging to calculate capacity/sector sizes at SATA devices.

I just added a convenience function to access such functionality. Its use is sectors, capacity, logicalSectorSize, physicalSectorSize, logicalSectorOffset := i.Capacity(). Please try it and let me know if it works for you.

Yes, everything worked. Thanks a lot.
937703088 480103981056 512 512 0