add physical_block_size field where applicable

only scsi_disk checks the actual value, other drivers take the logical block size.

This change reports the physical block size from the disk rather than the block
size used by IDE/SATA/SCSI commands. On typical modern SATA disks, the SATA
commands will use 512 byte blocks, but the disk will actually read and write
4K blocks internally. This is only of importance for partition alignment for DriveSetup,
and is independant of file systems or partitioning systems. This could also influence
the recommended block size for some file systems.

Change-Id: Id0f2e22659e89fcef64c1f8d04f81cd68995e01f
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5667
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
This commit is contained in:
Jérôme Duval 2022-09-15 18:04:53 +02:00 committed by Adrien Destugues
parent 285fe6257a
commit 688acf41a3
25 changed files with 114 additions and 45 deletions

View File

@ -144,6 +144,7 @@ typedef struct {
bool removable; /* non-zero if removable */
bool read_only; /* non-zero if read only */
bool write_once; /* non-zero if write-once */
uint32 bytes_per_physical_sector; /* physical sector size in bytes */
} device_geometry;
@ -174,6 +175,7 @@ typedef struct {
off_t offset; /* offset (in bytes) */
off_t size; /* size (in bytes) */
int32 logical_block_size; /* logical block size of partition */
int32 physical_block_size; /* physical block size of partition */
int32 session; /* id of session */
int32 partition; /* id of partition */
char device[256]; /* path to the physical device */

View File

@ -130,6 +130,7 @@ typedef struct {
bool removable; /* non-zero if removable */
bool read_only; /* non-zero if read only */
bool write_once; /* non-zero if write-once */
uint32 bytes_per_physical_sector; /* physical sector size in bytes */
} device_geometry;
enum {
@ -151,6 +152,7 @@ typedef struct {
off_t offset; /* offset (in bytes) */
off_t size; /* size (in bytes) */
int32 logical_block_size; /* logical block size of partition */
int32 physical_block_size; /* physical block size of partition */
int32 session; /* id of session */
int32 partition; /* id of partition */
char device[256]; /* path to the physical device */

View File

@ -25,6 +25,7 @@ typedef struct partition_data {
off_t size;
off_t content_size;
uint32 block_size;
uint32 physical_block_size;
int32 child_count;
int32 index; // [sys]
uint32 status;

View File

@ -63,7 +63,7 @@ typedef struct scsi_periph_callbacks {
// informs of new size of medium
// (set to NULL if not a block device)
void (*set_capacity)(periph_device_cookie cookie, uint64 capacity,
uint32 blockSize);
uint32 blockSize, uint32 physicalBlockSize);
// *** removable devices
// called when media got changed (can be NULL if medium is not changable)

View File

@ -70,6 +70,9 @@ public:
void SetBlockSize(uint32 blockSize);
uint32 BlockSize() const;
void SetPhysicalBlockSize(uint32 blockSize);
uint32 PhysicalBlockSize() const;
void SetIndex(int32 index);
int32 Index() const; // 0 for devices

View File

@ -38,6 +38,7 @@ public:
off_t Size() const;
off_t ContentSize() const; // 0 if uninitialized
uint32 BlockSize() const;
uint32 PhysicalBlockSize() const;
int32 Index() const; // 0 for devices
uint32 Status() const;

View File

@ -22,6 +22,7 @@ struct user_partition_data {
off_t size;
off_t content_size;
uint32 block_size;
uint32 physical_block_size;
uint32 status;
uint32 flags;
dev_t volume;

View File

@ -608,7 +608,7 @@ mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
case B_GET_GEOMETRY:
{
if (buffer == NULL || length < sizeof(device_geometry))
if (buffer == NULL || length > sizeof(device_geometry))
return B_BAD_VALUE;
if (info->geometry.bytes_per_sector == 0) {
@ -619,8 +619,7 @@ mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
}
}
return user_memcpy(buffer, &info->geometry,
sizeof(device_geometry));
return user_memcpy(buffer, &info->geometry, length);
}
case B_GET_ICON_NAME:

View File

@ -116,6 +116,7 @@ get_geometry(nvme_disk_handle* handle, device_geometry* geometry)
nvme_disk_driver_info* info = handle->info;
devfs_compute_geometry_size(geometry, info->capacity, info->block_size);
geometry->bytes_per_physical_sector = info->block_size;
geometry->device_type = B_DISK;
geometry->removable = false;
@ -950,7 +951,7 @@ nvme_disk_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
case B_GET_GEOMETRY:
{
if (buffer == NULL /*|| length != sizeof(device_geometry)*/)
if (buffer == NULL || length > sizeof(device_geometry))
return B_BAD_VALUE;
device_geometry geometry;
@ -958,7 +959,7 @@ nvme_disk_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
if (status != B_OK)
return status;
return user_memcpy(buffer, &geometry, sizeof(device_geometry));
return user_memcpy(buffer, &geometry, length);
}
case B_GET_ICON_NAME:

View File

@ -131,7 +131,7 @@ test_capacity(cd_driver_info *info)
PAGE_STATE_WIRED | VM_PAGE_ALLOC_BUSY);
entries[numEntries].address = page->physical_page_number * B_PAGE_SIZE;
entries[numEntries].size = bytes;;
entries[numEntries].size = bytes;
left -= bytes;
}
@ -207,6 +207,7 @@ get_geometry(cd_handle *handle, device_geometry *geometry)
return B_DEV_MEDIA_CHANGED;
devfs_compute_geometry_size(geometry, info->capacity, info->block_size);
geometry->bytes_per_physical_sector = info->physical_block_size;
geometry->device_type = info->device_type;
geometry->removable = info->removable;
@ -843,7 +844,7 @@ cd_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
case B_GET_GEOMETRY:
{
if (buffer == NULL /*|| length != sizeof(device_geometry)*/)
if (buffer == NULL || length > sizeof(device_geometry))
return B_BAD_VALUE;
device_geometry geometry;
@ -851,7 +852,7 @@ cd_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
if (status != B_OK)
return status;
return user_memcpy(buffer, &geometry, sizeof(device_geometry));
return user_memcpy(buffer, &geometry, length);
}
case B_GET_ICON_NAME:
@ -955,7 +956,7 @@ cd_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
static void
cd_set_capacity(cd_driver_info* info, uint64 capacity, uint32 blockSize)
cd_set_capacity(cd_driver_info* info, uint64 capacity, uint32 blockSize, uint32 physicalBlockSize)
{
TRACE("cd_set_capacity(info = %p, capacity = %Ld, blockSize = %ld)\n",
info, capacity, blockSize);
@ -1006,6 +1007,7 @@ cd_set_capacity(cd_driver_info* info, uint64 capacity, uint32 blockSize)
info->io_scheduler->SetCallback(do_io, info);
info->block_size = blockSize;
info->physical_block_size = physicalBlockSize;
}
if (info->original_capacity != capacity && info->io_scheduler != NULL) {
@ -1036,7 +1038,7 @@ cd_media_changed(cd_driver_info* info, scsi_ccb* request)
scsi_periph_callbacks callbacks = {
(void (*)(periph_device_cookie, uint64, uint32))cd_set_capacity,
(void (*)(periph_device_cookie, uint64, uint32, uint32))cd_set_capacity,
(void (*)(periph_device_cookie, scsi_ccb *))cd_media_changed
};

View File

@ -34,6 +34,7 @@ struct cd_driver_info {
uint64 capacity;
uint64 original_capacity;
uint32 block_size;
uint32 physical_block_size;
bool removable;
uint8 device_type;

View File

@ -99,6 +99,7 @@ get_geometry(das_handle* handle, device_geometry* geometry)
return status;
devfs_compute_geometry_size(geometry, info->capacity, info->block_size);
geometry->bytes_per_physical_sector = info->physical_block_size;
geometry->device_type = B_DISK;
geometry->removable = info->removable;
@ -112,10 +113,11 @@ get_geometry(das_handle* handle, device_geometry* geometry)
geometry->write_once = false;
TRACE("scsi_disk: get_geometry(): %" B_PRId32 ", %" B_PRId32 ", %" B_PRId32
", %" B_PRId32 ", %d, %d, %d, %d\n", geometry->bytes_per_sector,
", %" B_PRId32 ", %d, %d, %d, %d, %" B_PRId32 "\n", geometry->bytes_per_sector,
geometry->sectors_per_track, geometry->cylinder_count,
geometry->head_count, geometry->device_type,
geometry->removable, geometry->read_only, geometry->write_once);
geometry->removable, geometry->read_only, geometry->write_once,
geometry->bytes_per_physical_sector);
return B_OK;
}
@ -403,7 +405,7 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
case B_GET_GEOMETRY:
{
if (buffer == NULL /*|| length != sizeof(device_geometry)*/)
if (buffer == NULL || length > sizeof(device_geometry))
return B_BAD_VALUE;
device_geometry geometry;
@ -411,7 +413,7 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
if (status != B_OK)
return status;
return user_memcpy(buffer, &geometry, sizeof(device_geometry));
return user_memcpy(buffer, &geometry, length);
}
case B_GET_ICON_NAME:
@ -468,7 +470,7 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
static void
das_set_capacity(das_driver_info* info, uint64 capacity, uint32 blockSize)
das_set_capacity(das_driver_info* info, uint64 capacity, uint32 blockSize, uint32 physicalBlockSize)
{
TRACE("das_set_capacity(device = %p, capacity = %" B_PRIu64
", blockSize = %" B_PRIu32 ")\n", info, capacity, blockSize);
@ -508,6 +510,7 @@ das_set_capacity(das_driver_info* info, uint64 capacity, uint32 blockSize)
}
info->block_size = blockSize;
info->physical_block_size = physicalBlockSize;
}
@ -521,7 +524,7 @@ das_media_changed(das_driver_info *device, scsi_ccb *request)
scsi_periph_callbacks callbacks = {
(void (*)(periph_device_cookie, uint64, uint32))das_set_capacity,
(void (*)(periph_device_cookie, uint64, uint32, uint32))das_set_capacity,
(void (*)(periph_device_cookie, scsi_ccb *))das_media_changed
};

View File

@ -30,6 +30,7 @@ struct das_driver_info {
uint64 capacity;
uint32 block_size;
uint32 physical_block_size;
bool removable;
};

View File

@ -1196,6 +1196,7 @@ usb_disk_update_capacity_16(device_lun *lun)
lun->media_present = true;
lun->media_changed = false;
lun->block_size = B_BENDIAN_TO_HOST_INT32(parameter.logical_block_length);
lun->physical_block_size = lun->block_size;
lun->block_count =
B_BENDIAN_TO_HOST_INT64(parameter.last_logical_block_address) + 1;
return B_OK;
@ -1248,6 +1249,7 @@ usb_disk_update_capacity(device_lun *lun)
lun->media_present = true;
lun->media_changed = false;
lun->block_size = B_BENDIAN_TO_HOST_INT32(parameter.logical_block_length);
lun->physical_block_size = lun->block_size;
lun->block_count =
B_BENDIAN_TO_HOST_INT32(parameter.last_logical_block_address) + 1;
if (lun->block_count == 0) {
@ -1910,6 +1912,8 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
case B_GET_GEOMETRY:
{
if (buffer == NULL || length > sizeof(device_geometry))
return B_BAD_VALUE;
if (lun->media_changed) {
status_t result = usb_disk_update_capacity(lun);
if (result != B_OK)
@ -1919,6 +1923,7 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
device_geometry geometry;
devfs_compute_geometry_size(&geometry, lun->block_count,
lun->block_size);
geometry.bytes_per_physical_sector = lun->physical_block_size;
geometry.device_type = lun->device_type;
geometry.removable = lun->removable;
@ -1927,7 +1932,7 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
TRACE("B_GET_GEOMETRY: %" B_PRId32 " sectors at %" B_PRId32
" bytes per sector\n", geometry.cylinder_count,
geometry.bytes_per_sector);
return user_memcpy(buffer, &geometry, sizeof(device_geometry));
return user_memcpy(buffer, &geometry, length);
}
case B_FLUSH_DRIVE_CACHE:

View File

@ -70,6 +70,7 @@ struct device_lun_s {
bool media_changed;
uint64 block_count;
uint32 block_size;
uint32 physical_block_size;
uint8 device_type;
bool removable;
bool write_protected;

View File

@ -588,17 +588,18 @@ status_t nbd_control(cookie_t *cookie, uint32 op, void *data, size_t len) {
return EINVAL;
case B_GET_GEOMETRY:
case B_GET_BIOS_GEOMETRY:
if (data) {
device_geometry *geom = (device_geometry *)data;
geom->bytes_per_sector = BLKSIZE;
geom->sectors_per_track = 1;
geom->cylinder_count = cookie->dev->size / BLKSIZE;
geom->head_count = 1;
geom->device_type = B_DISK;
geom->removable = false;
geom->read_only = cookie->dev->readonly;
geom->write_once = false;
return B_OK;
if (data != NULL && len <= sizeof(device_geometry)) {
device_geometry geometry;
geometry.bytes_per_sector = BLKSIZE;
geometry.sectors_per_track = 1;
geometry.cylinder_count = cookie->dev->size / BLKSIZE;
geometry.head_count = 1;
geometry.device_type = B_DISK;
geometry.removable = false;
geometry.read_only = cookie->dev->readonly;
geometry.write_once = false;
geometry.bytes_per_physical_sector = BLKSIZE;
return user_memcpy(data, &geometry, len);
}
return EINVAL;
case B_GET_MEDIA_STATUS:

View File

@ -1435,6 +1435,9 @@ ram_disk_raw_device_control(void* _cookie, uint32 op, void* buffer,
case B_GET_GEOMETRY:
case B_GET_BIOS_GEOMETRY:
{
if (buffer == NULL || length > sizeof(device_geometry))
return B_BAD_VALUE;
device_geometry geometry;
geometry.bytes_per_sector = B_PAGE_SIZE;
geometry.sectors_per_track = 1;
@ -1446,8 +1449,9 @@ ram_disk_raw_device_control(void* _cookie, uint32 op, void* buffer,
geometry.removable = true;
geometry.read_only = false;
geometry.write_once = false;
geometry.bytes_per_physical_sector = B_PAGE_SIZE;
return user_memcpy(buffer, &geometry, sizeof(device_geometry));
return user_memcpy(buffer, &geometry, length);
}
case B_GET_MEDIA_STATUS:

View File

@ -100,6 +100,7 @@ struct RemoteDiskDevice : recursive_lock {
geometry->removable = true;
geometry->read_only = remoteDisk->IsReadOnly();
geometry->write_once = false;
geometry->bytes_per_physical_sector = REMOTE_DISK_BLOCK_SIZE;
}
};
@ -247,17 +248,15 @@ remote_disk_control(void* cookie, uint32 op, void* arg, size_t len)
return B_BAD_VALUE;
}
case B_GET_GEOMETRY:
TRACE(("remote_disk: B_GET_GEOMETRY\n"));
device->GetGeometry((device_geometry*)arg, false);
return B_OK;
case B_GET_BIOS_GEOMETRY:
{
TRACE(("remote_disk: B_GET_BIOS_GEOMETRY\n"));
device->GetGeometry((device_geometry*)arg, true);
return B_OK;
}
case B_GET_GEOMETRY:
TRACE(("remote_disk: %s\n",
op == B_GET_BIOS_GEOMETRY ? "B_GET_BIOS_GEOMETRY" : "B_GET_GEOMETRY"));
if (buffer == NULL || length > sizeof(device_geometry))
return B_BAD_VALUE;
device_geometry geometry;
device->GetGeometry(&geometry, op == B_GET_BIOS_GEOMETRY);
return user_memcpy(buffer, &geometry, length);
case B_GET_MEDIA_STATUS:
TRACE(("remote_disk: B_GET_MEDIA_STATUS\n"));

View File

@ -130,6 +130,7 @@ get_geometry(virtio_block_handle* handle, device_geometry* geometry)
virtio_block_driver_info* info = handle->info;
devfs_compute_geometry_size(geometry, info->capacity, info->block_size);
geometry->bytes_per_physical_sector = info->block_size;
geometry->device_type = B_DISK;
geometry->removable = false;
@ -435,7 +436,7 @@ virtio_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
case B_GET_GEOMETRY:
{
if (buffer == NULL /*|| length != sizeof(device_geometry)*/)
if (buffer == NULL || length > sizeof(device_geometry))
return B_BAD_VALUE;
device_geometry geometry;
@ -443,7 +444,7 @@ virtio_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
if (status != B_OK)
return status;
return user_memcpy(buffer, &geometry, sizeof(device_geometry));
return user_memcpy(buffer, &geometry, length);
}
case B_GET_ICON_NAME:

View File

@ -38,8 +38,9 @@ struct CapacityInfo {
bool capacityFilled;
uint64 lastLba;
uint32 blockSize;
uint32 physicalBlockSize;
// Provisioining info from READ CAPACITY
// Provisioning info from READ CAPACITY
bool provisioningFilled;
bool lbpme;
bool lbprz;
@ -135,6 +136,7 @@ read_capacity_10(scsi_periph_device_info* device, scsi_ccb* request,
= (uint32)B_BENDIAN_TO_HOST_INT32(capacityResult.lba);
capacityInfo->blockSize
= B_BENDIAN_TO_HOST_INT32(capacityResult.block_size);
capacityInfo->physicalBlockSize = capacityInfo->blockSize;
}
return res;
@ -177,6 +179,8 @@ read_capacity_16(scsi_periph_device_info* device, scsi_ccb* request,
= B_BENDIAN_TO_HOST_INT64(capacityLongResult.lba);
capacityInfo->blockSize
= B_BENDIAN_TO_HOST_INT32(capacityLongResult.block_size);
capacityInfo->physicalBlockSize = capacityInfo->blockSize
* (1 << capacityLongResult.logical_blocks_per_physical_block_exponent);
}
if (res == B_OK && request->data_resid
@ -359,14 +363,16 @@ periph_check_capacity(scsi_periph_device_info* device, scsi_ccb* request)
}
uint64 capacity;
uint32 blockSize;
uint32 blockSize, physicalBlockSize;
if (capacityInfo.capacityFilled) {
capacity = capacityInfo.lastLba + 1;
blockSize = capacityInfo.blockSize;
physicalBlockSize = capacityInfo.physicalBlockSize;
} else {
capacity = 0;
blockSize = 0;
physicalBlockSize = 0;
}
enum trim_command unmapCommand = TRIM_NONE;
@ -435,9 +441,10 @@ periph_check_capacity(scsi_periph_device_info* device, scsi_ccb* request)
device->max_unmap_descriptor_count = maxDescriptorCount;
device->block_size = blockSize;
device->physical_block_size = physicalBlockSize;
device->callbacks->set_capacity(device->periph_device,
capacity, blockSize);
capacity, blockSize, physicalBlockSize);
/* device->byte2blk_shift = log2( device->block_size );
if( device->byte2blk_shift < 0 ) {

View File

@ -41,6 +41,7 @@ typedef struct scsi_periph_device_info {
uint32 max_unmap_descriptor_count; // max. number of ranges in one command
uint32 block_size;
uint32 physical_block_size;
int32 preferred_ccb_size;
int32 rw10_enabled; // 10 byte r/w commands supported; access must be atomic
int32 next_tag_action; // queuing flag for next r/w command; access must be atomic

View File

@ -583,6 +583,7 @@ BMutablePartition::Init(const user_partition_data* partitionData,
fData->size = partitionData->size;
fData->content_size = partitionData->content_size;
fData->block_size = partitionData->block_size;
fData->physical_block_size = partitionData->physical_block_size;
fData->status = partitionData->status;
fData->flags = partitionData->flags;
fData->volume = partitionData->volume;

View File

@ -141,6 +141,16 @@ BPartition::BlockSize() const
}
/*! \brief Returns the physical block size of the device.
\return The physical block size of the device in bytes.
*/
uint32
BPartition::PhysicalBlockSize() const
{
return _PartitionData()->physical_block_size;
}
/*! \brief Returns the index of the partition in its session's list of
partitions.
\return The index of the partition in its session's list of partitions.
@ -1353,6 +1363,7 @@ BPartition::_Update(user_partition_data* data, bool* updated)
if (data->offset != oldData->offset
|| data->size != oldData->size
|| data->block_size != oldData->block_size
|| data->physical_block_size != oldData->physical_block_size
|| data->status != oldData->status
|| data->flags != oldData->flags
|| data->volume != oldData->volume

View File

@ -391,6 +391,7 @@ KDiskDevice::_InitPartitionData()
{
fDeviceData.id = fPartitionData.id;
fPartitionData.block_size = fDeviceData.geometry.bytes_per_sector;
fPartitionData.physical_block_size = fDeviceData.geometry.bytes_per_physical_sector;
fPartitionData.offset = 0;
fPartitionData.size = (off_t)fPartitionData.block_size
* fDeviceData.geometry.sectors_per_track

View File

@ -73,6 +73,7 @@ KPartition::KPartition(partition_id id)
fPartitionData.size = 0;
fPartitionData.content_size = 0;
fPartitionData.block_size = 0;
fPartitionData.physical_block_size = 0;
fPartitionData.child_count = 0;
fPartitionData.index = -1;
fPartitionData.status = B_PARTITION_UNRECOGNIZED;
@ -202,6 +203,7 @@ KPartition::PublishDevice()
info.offset = Offset();
info.size = Size();
info.logical_block_size = BlockSize();
info.physical_block_size = PhysicalBlockSize();
info.session = 0;
info.partition = ID();
if (strlcpy(info.device, Device()->Path(), sizeof(info.device))
@ -453,6 +455,21 @@ KPartition::BlockSize() const
}
uint32
KPartition::PhysicalBlockSize() const
{
return fPartitionData.physical_block_size;
}
void
KPartition::SetPhysicalBlockSize(uint32 blockSize)
{
if (fPartitionData.physical_block_size != blockSize)
fPartitionData.physical_block_size = blockSize;
}
void
KPartition::SetIndex(int32 index)
{
@ -870,6 +887,7 @@ KPartition::AddChild(KPartition* partition, int32 index)
partition->SetParent(this);
partition->SetDevice(Device());
partition->SetPhysicalBlockSize(PhysicalBlockSize());
// publish to devfs
partition->PublishDevice();
@ -1271,6 +1289,7 @@ KPartition::WriteUserData(UserDataWriter& writer, user_partition_data* data)
data->size = Size();
data->content_size = ContentSize();
data->block_size = BlockSize();
data->physical_block_size = PhysicalBlockSize();
data->status = Status();
data->flags = Flags();
data->volume = VolumeID();
@ -1322,6 +1341,7 @@ KPartition::Dump(bool deep, int32 level)
Size() / (1024.0*1024));
OUT("%s content size: %" B_PRIdOFF "\n", prefix, ContentSize());
OUT("%s block size: %" B_PRIu32 "\n", prefix, BlockSize());
OUT("%s physical block size: %" B_PRIu32 "\n", prefix, PhysicalBlockSize());
OUT("%s child count: %" B_PRId32 "\n", prefix, CountChildren());
OUT("%s index: %" B_PRId32 "\n", prefix, Index());
OUT("%s status: %" B_PRIu32 "\n", prefix, Status());