Consolidated and fixed device_geometry computation.

* The only implementation that would accept more than 2 TB was the one in
  scsi_disk. But even that one was limited to 63 TB.
* Now there is a new utility function devfs_compute_geometry_size() which
  does it correctly for sizes up to 2^64 which should be good enough for
  quite some time :-)
* This fixes bug #8992.
This commit is contained in:
Axel Dörfler
2012-10-08 13:59:16 +02:00
parent cff0983994
commit 9b9cb227c7
5 changed files with 61 additions and 45 deletions
+4 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2002-2012, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@@ -29,6 +29,9 @@ status_t devfs_publish_device(const char *path, device_hooks *calls);
status_t devfs_publish_directory(const char *path);
status_t devfs_rescan_driver(const char *driverName);
void devfs_compute_geometry_size(device_geometry* geometry, uint64 blockCount,
uint32 blockSize);
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010, Haiku, Inc. All rights reserved.
* Copyright 2004-2012, Haiku, Inc. All rights reserved.
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
@@ -21,6 +21,7 @@
#include <algorithm>
#include <fs/devfs.h>
#include <io_requests.h>
#include <vm/vm_page.h>
@@ -205,10 +206,8 @@ get_geometry(cd_handle *handle, device_geometry *geometry)
if (status == B_DEV_MEDIA_CHANGED)
return B_DEV_MEDIA_CHANGED;
geometry->bytes_per_sector = info->block_size;
geometry->sectors_per_track = 1;
geometry->cylinder_count = info->capacity;
geometry->head_count = 1;
devfs_compute_geometry_size(geometry, info->capacity, info->block_size);
geometry->device_type = info->device_type;
geometry->removable = info->removable;
@@ -1,5 +1,5 @@
/*
* Copyright 2008, Axel Dörfler, [email protected].
* Copyright 2008-2012, Axel Dörfler, [email protected].
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
* Distributed under the terms of the MIT License.
*/
@@ -20,6 +20,8 @@
#include <string.h>
#include <stdlib.h>
#include <fs/devfs.h>
#include "dma_resources.h"
#include "IORequest.h"
#include "IOSchedulerSimple.h"
@@ -65,7 +67,7 @@ static device_manager_info* sDeviceManager;
static status_t
update_capacity(das_driver_info *device)
update_capacity(das_driver_info* device)
{
TRACE("update_capacity()\n");
@@ -88,20 +90,12 @@ get_geometry(das_handle* handle, device_geometry* geometry)
das_driver_info* info = handle->info;
status_t status = update_capacity(info);
if (status < B_OK)
if (status != B_OK)
return status;
geometry->bytes_per_sector = info->block_size;
if (info->capacity > UINT_MAX) {
// TODO this doesn't work for capacity greater than 35TB
geometry->sectors_per_track = 256;
geometry->cylinder_count = info->capacity / (256 * 32);
geometry->head_count = 32;
} else {
geometry->sectors_per_track = 1;
geometry->cylinder_count = info->capacity;
geometry->head_count = 1;
}
devfs_compute_geometry_size(geometry, info->capacity, info->block_size);
geometry->device_type = B_DISK;
geometry->removable = info->removable;
@@ -1,18 +1,23 @@
/*
* Copyright 2008-2010, Haiku Inc. All rights reserved.
* Copyright 2008-2012, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <[email protected]>
*/
#include <ByteOrder.h>
#include <KernelExport.h>
#include <Drivers.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include "usb_disk.h"
#include <ByteOrder.h>
#include <Drivers.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fs/devfs.h>
#include "usb_disk_scsi.h"
@@ -463,7 +468,7 @@ usb_disk_request_sense(device_lun *lun)
TRACE_ALWAYS("request_sense: media changed\n");
lun->media_changed = true;
lun->media_present = true;
return B_DEV_MEDIA_CHANGED;
}
// fall through
@@ -1058,17 +1063,17 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
break;
}
device_geometry *geometry = (device_geometry *)buffer;
geometry->bytes_per_sector = lun->block_size;
geometry->cylinder_count = lun->block_count;
geometry->sectors_per_track = geometry->head_count = 1;
geometry->device_type = lun->device_type;
geometry->removable = lun->removable;
geometry->read_only = lun->write_protected;
geometry->write_once = (lun->device_type == B_WORM);
device_geometry geometry;
devfs_compute_geometry_size(&geometry, lun->block_count,
lun->block_size);
geometry.device_type = lun->device_type;
geometry.removable = lun->removable;
geometry.read_only = lun->write_protected;
geometry.write_once = lun->device_type == B_WORM;
TRACE("B_GET_GEOMETRY: %ld sectors at %ld bytes per sector\n",
geometry->cylinder_count, geometry->bytes_per_sector);
result = B_OK;
geometry.cylinder_count, geometry.bytes_per_sector);
result = user_memcpy(buffer, &geometry, sizeof(device_geometry));
break;
}
+22 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2002-2012, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@@ -26,6 +26,7 @@
#include <debug.h>
#include <elf.h>
#include <FindDirectory.h>
#include <fs/devfs.h>
#include <fs/KPath.h>
#include <fs/node_monitor.h>
#include <kdevice_manager.h>
@@ -1498,17 +1499,16 @@ devfs_ioctl(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, uint32 op,
device_geometry geometry;
status_t status = vnode->stream.u.dev.device->Control(
cookie->device_cookie, op, &geometry, length);
if (status < B_OK)
if (status != B_OK)
return status;
// patch values to match partition size
geometry.sectors_per_track = 0;
if (geometry.bytes_per_sector == 0)
geometry.bytes_per_sector = 512;
geometry.sectors_per_track = partition->info.size
/ geometry.bytes_per_sector;
geometry.head_count = 1;
geometry.cylinder_count = 1;
devfs_compute_geometry_size(&geometry,
partition->info.size / geometry.bytes_per_sector,
geometry.bytes_per_sector);
return user_memcpy(buffer, &geometry, sizeof(device_geometry));
}
@@ -2207,6 +2207,21 @@ devfs_unpublish_device(BaseDevice* device, bool disconnect)
}
void
devfs_compute_geometry_size(device_geometry* geometry, uint64 blockCount,
uint32 blockSize)
{
if (blockCount > UINT32_MAX)
geometry->head_count = (blockCount + UINT32_MAX - 1) / UINT32_MAX;
else
geometry->head_count = 1;
geometry->cylinder_count = 1;
geometry->sectors_per_track = blockCount / geometry->head_count;
geometry->bytes_per_sector = blockSize;
}
// #pragma mark - support API for legacy drivers