我购买了一个新的(2017 年)4 TB 硬盘,因此我预计它的物理扇区大小为 4096。的确,
$ hdparm -I /dev/sdh
...
Logical Sector size: 512 bytes
Physical Sector size: 4096 bytes
Logical Sector-0 offset: 0 bytes
device size with M = 1000*1000: 4000787 MBytes (4000 GB)
然而,当我尝试使用 对其进行分区时parted
,我得到的物理块大小为 512:
$ parted /dev/sdh print
Model: (scsi)
Disk /dev/sdh: 4001GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
152d:0561
该驱动器位于 USB 桥接器( JMicron JMS55 芯片组)后面的扩展坞 (iTec) 的 USB 3 端口上。
块层的大小似乎也错误:
$ cat /sys/block/sdh/queue/physical_block_size
512
$ cat /sys/block/sdh/queue/minimum_io_size
512
SCSI命令READ CAPACITY (16)
也会报告错误的大小:
$ sudo sg_readcap --16 /dev/sdh
Read Capacity results:
Protection: prot_en=0, p_type=0, p_i_exponent=0
Logical block provisioning: lbpme=0, lbprz=0
Last logical block address=7814037167 (0x1d1c0beaf),
Number of logical blocks=7814037168
Logical block length=512 bytes
Logical blocks per physical block exponent=0
Lowest aligned logical block address=0
而不是(来自另一个驱动器)
Logical blocks per physical block exponent=3 [so physical block length=4096 bytes]
另一方面,blockdev
报道称
$ blockdev --report /dev/sdh
RO RA SSZ BSZ StartSec Size Device
rw 256 512 4096 0 4000787030016 /dev/sdh
谷歌搜索发现有关USB桥的模糊信息,这些桥进行“4k/512扇区模拟,以允许大型硬盘具有MBR分区表”,但如果我理解正确的话,那么这些桥的逻辑扇区大小应该是4096,这不是我的桥梁就是这样。
那么究竟发生了什么?我该如何修复它,即让内核相信该驱动器具有 4096 字节大小的物理块?和physical_block_size
属性minimum_io_size
不可写。
一种可能的解释是桥接器的固件中存在错误,它只是复制READ CAPACITY (16)
响应的前 12 个字节,将字节 13 中的指数清零。但在这种情况下,我仍然想解决该错误不知何故。
编辑
我现在在另一个(旧的)USB 外壳中对其进行了测试。连接 eSATA,一切按预期工作,并READ CAPACITY (16)
报告 4096 字节物理扇区大小。通过 USB 连接 ( 04fc:0c25
Sunplus SATALink SPIF225A) 抱怨READ CAPACITY (16)
不支持(因此没有物理扇区大小),但READ CAPACITY (10)
确实支持。
这证实了至少对于Sunplus桥接器来说,SCSI命令不是任意转发的,并且使得JMicron USB桥接器的固件中更有可能存在错误,从而将响应归零READ CAPACITY (16)
。
但我仍然需要知道如何解决该错误。
答案1
man blockdev
--setbsz bytes
Set blocksize. Note that the block size is specific to the cur‐
rent file descriptor opening the block device, so the change of
block size only persists for as long as blockdev has the device
open, and is lost once blockdev exits.
case BLKBSZGET: /* get block device soft block size (cf. BLKSSZGET) */
return put_int(arg, block_size(bdev));
case BLKSSZGET: /* get block device logical block size */
return put_int(arg, bdev_logical_block_size(bdev));
case BLKPBSZGET: /* get block device physical block size */
return put_uint(arg, bdev_physical_block_size(bdev));
因此 BSZ 报告的blockdev
既不是逻辑块大小也不是物理块大小。它是“软块大小”。
查看此代码,有关特定于文件描述符的软块大小的部分似乎没有意义。blockdev
考虑到没有以块形式记录其他选项(仅固定大小的 512 字节扇区),也不想使用 来设置它。
在我自己的测试中,实际发生的情况是 BSZ 会保留很长时间任何进程保持块设备打开。看起来它在最后一次 close() 时被重置。
保护那个。 BLKBSZGET 是内核选择的用于访问设备的块大小(对于普通磁盘,这是 1k,对于 ata_ram,这是 4k),这不是底层磁盘的逻辑块大小。 :-( 因此,我们可能需要另一个 ioctl() 来从内核获取正确的值,并且 BLKSSZGET 可能最终成为磁盘的逻辑块大小,而新的 ioctl() 则导出磁盘的物理扇区大小。呃。
2003 年 4 月 9 日星期三下午 06:53:17 +0200,Rob van Nieuwkerk 写道:
我在系统(RH 2.4.18-27.7.x 内核)上的几个未安装分区上使用 BLKBSZGET 得到 4096。有些给出 1024 ..也许是因为我先安装了它们,然后为了测试而卸载了它们?
这将是最有可能的答案。当您卸载时,我不相信文件系统会打扰 set_blocksize(get_hardsect_size(dev)) 。