From 688acf41a377f25d4048dc6092edb86ac9179677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 15 Sep 2022 18:04:53 +0200 Subject: [PATCH] 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 Reviewed-by: Adrien Destugues --- headers/build/os/drivers/Drivers.h | 2 ++ headers/os/drivers/Drivers.h | 2 ++ headers/os/drivers/disk_device_manager.h | 1 + headers/private/drivers/scsi_periph.h | 2 +- .../kernel/disk_device_manager/KPartition.h | 3 +++ headers/private/storage/Partition.h | 1 + .../system/ddm_userland_interface_defs.h | 1 + .../kernel/drivers/disk/mmc/mmc_disk.cpp | 5 ++-- .../kernel/drivers/disk/nvme/nvme_disk.cpp | 5 ++-- .../drivers/disk/scsi/scsi_cd/scsi_cd.cpp | 12 ++++++---- .../drivers/disk/scsi/scsi_cd/scsi_cd.h | 1 + .../drivers/disk/scsi/scsi_disk/scsi_disk.cpp | 15 +++++++----- .../drivers/disk/scsi/scsi_disk/scsi_disk.h | 1 + .../drivers/disk/usb/usb_disk/usb_disk.cpp | 7 +++++- .../drivers/disk/usb/usb_disk/usb_disk.h | 1 + .../kernel/drivers/disk/virtual/nbd/nbd.c | 23 ++++++++++--------- .../disk/virtual/ram_disk/ram_disk.cpp | 6 ++++- .../disk/virtual/remote_disk/remote_disk.cpp | 19 ++++++++------- .../virtual/virtio_block/virtio_block.cpp | 5 ++-- .../kernel/generic/scsi_periph/block.cpp | 13 ++++++++--- .../generic/scsi_periph/scsi_periph_int.h | 1 + .../storage/disk_device/MutablePartition.cpp | 1 + src/kits/storage/disk_device/Partition.cpp | 11 +++++++++ .../disk_device_manager/KDiskDevice.cpp | 1 + .../kernel/disk_device_manager/KPartition.cpp | 20 ++++++++++++++++ 25 files changed, 114 insertions(+), 45 deletions(-) diff --git a/headers/build/os/drivers/Drivers.h b/headers/build/os/drivers/Drivers.h index 2093eac83c..fa506ea0b3 100644 --- a/headers/build/os/drivers/Drivers.h +++ b/headers/build/os/drivers/Drivers.h @@ -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 */ diff --git a/headers/os/drivers/Drivers.h b/headers/os/drivers/Drivers.h index a854305b38..ec7d7fd2bd 100644 --- a/headers/os/drivers/Drivers.h +++ b/headers/os/drivers/Drivers.h @@ -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 */ diff --git a/headers/os/drivers/disk_device_manager.h b/headers/os/drivers/disk_device_manager.h index 17c1b782c2..6d3508cff4 100644 --- a/headers/os/drivers/disk_device_manager.h +++ b/headers/os/drivers/disk_device_manager.h @@ -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; diff --git a/headers/private/drivers/scsi_periph.h b/headers/private/drivers/scsi_periph.h index a6e78f2a37..e2ad93cbd1 100644 --- a/headers/private/drivers/scsi_periph.h +++ b/headers/private/drivers/scsi_periph.h @@ -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) diff --git a/headers/private/kernel/disk_device_manager/KPartition.h b/headers/private/kernel/disk_device_manager/KPartition.h index 577d23a893..9b43d7f0db 100644 --- a/headers/private/kernel/disk_device_manager/KPartition.h +++ b/headers/private/kernel/disk_device_manager/KPartition.h @@ -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 diff --git a/headers/private/storage/Partition.h b/headers/private/storage/Partition.h index aff04da79c..8f49a0ccc9 100644 --- a/headers/private/storage/Partition.h +++ b/headers/private/storage/Partition.h @@ -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; diff --git a/headers/private/system/ddm_userland_interface_defs.h b/headers/private/system/ddm_userland_interface_defs.h index df6c5388a1..8bc493c3da 100644 --- a/headers/private/system/ddm_userland_interface_defs.h +++ b/headers/private/system/ddm_userland_interface_defs.h @@ -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; diff --git a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp index ae8fd000e3..8a043e7e26 100644 --- a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp @@ -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: diff --git a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp index 486ffd5ba1..4db54c91df 100644 --- a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp @@ -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: diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp index 60ad4e0e65..c1c265d9d1 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp @@ -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 }; diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h index 6ee0d26aee..2d0a6ac595 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h @@ -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; diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp index eba0d5ccf4..0245e6c54a 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp @@ -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 }; diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.h b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.h index be92f22019..b5c0c36275 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.h +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.h @@ -30,6 +30,7 @@ struct das_driver_info { uint64 capacity; uint32 block_size; + uint32 physical_block_size; bool removable; }; diff --git a/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp b/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp index f14f0ff57c..30d585c3a3 100644 --- a/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp @@ -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: diff --git a/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.h b/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.h index 4b2a78bafc..8a5495904f 100644 --- a/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.h +++ b/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.h @@ -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; diff --git a/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c b/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c index ad63193a41..60c853e42d 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c +++ b/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c @@ -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: diff --git a/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp b/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp index 0b09ecc510..ae9e38383c 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp @@ -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: diff --git a/src/add-ons/kernel/drivers/disk/virtual/remote_disk/remote_disk.cpp b/src/add-ons/kernel/drivers/disk/virtual/remote_disk/remote_disk.cpp index 193811c081..f7d1c96e6e 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/remote_disk/remote_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/virtual/remote_disk/remote_disk.cpp @@ -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")); diff --git a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp index 835694c0b8..0e7cdcdb10 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp +++ b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp @@ -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: diff --git a/src/add-ons/kernel/generic/scsi_periph/block.cpp b/src/add-ons/kernel/generic/scsi_periph/block.cpp index e9b4d2dc73..92cb1fad8e 100644 --- a/src/add-ons/kernel/generic/scsi_periph/block.cpp +++ b/src/add-ons/kernel/generic/scsi_periph/block.cpp @@ -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 ) { diff --git a/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h b/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h index 8a25e1f5b9..932f323567 100644 --- a/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h +++ b/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h @@ -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 diff --git a/src/kits/storage/disk_device/MutablePartition.cpp b/src/kits/storage/disk_device/MutablePartition.cpp index 3c2325cfe5..75d96f17d6 100644 --- a/src/kits/storage/disk_device/MutablePartition.cpp +++ b/src/kits/storage/disk_device/MutablePartition.cpp @@ -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; diff --git a/src/kits/storage/disk_device/Partition.cpp b/src/kits/storage/disk_device/Partition.cpp index a7158dba7a..c31be1c77d 100644 --- a/src/kits/storage/disk_device/Partition.cpp +++ b/src/kits/storage/disk_device/Partition.cpp @@ -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 diff --git a/src/system/kernel/disk_device_manager/KDiskDevice.cpp b/src/system/kernel/disk_device_manager/KDiskDevice.cpp index 1756026497..a2c71cb983 100644 --- a/src/system/kernel/disk_device_manager/KDiskDevice.cpp +++ b/src/system/kernel/disk_device_manager/KDiskDevice.cpp @@ -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 diff --git a/src/system/kernel/disk_device_manager/KPartition.cpp b/src/system/kernel/disk_device_manager/KPartition.cpp index cfe4263c3a..1679367d80 100644 --- a/src/system/kernel/disk_device_manager/KPartition.cpp +++ b/src/system/kernel/disk_device_manager/KPartition.cpp @@ -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());