axeld + bonefish:
* Unmount when uninitializing a partition. * Finished the media checker implementation, i.e. we rescan when a media was inserted and uninitialize when ejected. * Turned the disk device media checker from a kernel daemon into a thread. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22909 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5b1f301a11
commit
b3a5629b9e
@ -99,8 +99,8 @@ public:
|
|||||||
status_t RescanDiskSystems();
|
status_t RescanDiskSystems();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void _CheckMediaStatusDaemon(void* self, int iteration);
|
static status_t _CheckMediaStatusDaemon(void* self);
|
||||||
void _CheckMediaStatus();
|
status_t _CheckMediaStatus();
|
||||||
|
|
||||||
status_t _RescanDiskSystems(bool fileSystems);
|
status_t _RescanDiskSystems(bool fileSystems);
|
||||||
|
|
||||||
@ -127,6 +127,8 @@ private:
|
|||||||
PartitionMap *fPartitions;
|
PartitionMap *fPartitions;
|
||||||
DiskSystemMap *fDiskSystems;
|
DiskSystemMap *fDiskSystems;
|
||||||
PartitionSet *fObsoletePartitions;
|
PartitionSet *fObsoletePartitions;
|
||||||
|
thread_id fMediaChecker;
|
||||||
|
volatile bool fTerminating;
|
||||||
|
|
||||||
static KDiskDeviceManager *sDefaultManager;
|
static KDiskDeviceManager *sDefaultManager;
|
||||||
};
|
};
|
||||||
|
@ -54,6 +54,7 @@ public:
|
|||||||
bool IsBusy() const;
|
bool IsBusy() const;
|
||||||
bool IsBusy(bool includeDescendants);
|
bool IsBusy(bool includeDescendants);
|
||||||
bool CheckAndMarkBusy(bool includeDescendants);
|
bool CheckAndMarkBusy(bool includeDescendants);
|
||||||
|
void MarkBusy(bool includeDescendants);
|
||||||
void UnmarkBusy(bool includeDescendants);
|
void UnmarkBusy(bool includeDescendants);
|
||||||
|
|
||||||
void SetOffset(off_t offset);
|
void SetOffset(off_t offset);
|
||||||
|
@ -103,15 +103,19 @@ KDiskDeviceManager::KDiskDeviceManager()
|
|||||||
fDevices(new(nothrow) DeviceMap),
|
fDevices(new(nothrow) DeviceMap),
|
||||||
fPartitions(new(nothrow) PartitionMap),
|
fPartitions(new(nothrow) PartitionMap),
|
||||||
fDiskSystems(new(nothrow) DiskSystemMap),
|
fDiskSystems(new(nothrow) DiskSystemMap),
|
||||||
fObsoletePartitions(new(nothrow) PartitionSet)
|
fObsoletePartitions(new(nothrow) PartitionSet),
|
||||||
|
fMediaChecker(-1),
|
||||||
|
fTerminating(false)
|
||||||
{
|
{
|
||||||
if (InitCheck() != B_OK)
|
if (InitCheck() != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RescanDiskSystems();
|
RescanDiskSystems();
|
||||||
|
|
||||||
register_kernel_daemon(&_CheckMediaStatusDaemon, this, 10);
|
fMediaChecker = spawn_kernel_thread(_CheckMediaStatusDaemon,
|
||||||
// once every second
|
"media checker", B_NORMAL_PRIORITY, this);
|
||||||
|
if (fMediaChecker >= 0)
|
||||||
|
resume_thread(fMediaChecker);
|
||||||
|
|
||||||
DBG(OUT("number of disk systems: %ld\n", CountDiskSystems()));
|
DBG(OUT("number of disk systems: %ld\n", CountDiskSystems()));
|
||||||
// TODO: Watch the disk systems and the relevant directories.
|
// TODO: Watch the disk systems and the relevant directories.
|
||||||
@ -120,9 +124,11 @@ KDiskDeviceManager::KDiskDeviceManager()
|
|||||||
|
|
||||||
KDiskDeviceManager::~KDiskDeviceManager()
|
KDiskDeviceManager::~KDiskDeviceManager()
|
||||||
{
|
{
|
||||||
unregister_kernel_daemon(&_CheckMediaStatusDaemon, this);
|
fTerminating = true;
|
||||||
|
|
||||||
|
status_t result;
|
||||||
|
wait_for_thread(fMediaChecker, &result);
|
||||||
|
|
||||||
// TODO: terminate and remove all jobs
|
|
||||||
// remove all devices
|
// remove all devices
|
||||||
for (int32 cookie = 0; KDiskDevice *device = NextDevice(&cookie);) {
|
for (int32 cookie = 0; KDiskDevice *device = NextDevice(&cookie);) {
|
||||||
PartitionRegistrar _(device);
|
PartitionRegistrar _(device);
|
||||||
@ -1127,35 +1133,45 @@ KDiskDeviceManager::_ScanPartition(KPartition *partition)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
KDiskDeviceManager::_CheckMediaStatus()
|
KDiskDeviceManager::_CheckMediaStatus()
|
||||||
{
|
{
|
||||||
if (fLock.LockWithTimeout(0) != B_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int32 cookie = 0;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
KDiskDevice* device = NextDevice(&cookie);
|
int32 cookie = 0;
|
||||||
if (device == NULL)
|
while (KDiskDevice* device = RegisterNextDevice(&cookie)) {
|
||||||
break;
|
DeviceWriteLocker locker(device);
|
||||||
|
|
||||||
bool hadMedia = device->HasMedia();
|
if (device->IsBusy(true))
|
||||||
device->UpdateMediaStatusIfNeeded();
|
continue;
|
||||||
|
|
||||||
// TODO: propagate changes!
|
bool hadMedia = device->HasMedia();
|
||||||
if (device->MediaChanged()) {
|
device->UpdateMediaStatusIfNeeded();
|
||||||
|
|
||||||
|
if (!device->MediaChanged() && (device->HasMedia() || !hadMedia))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
device->MarkBusy(true);
|
||||||
|
device->UninitializeContents(true);
|
||||||
|
|
||||||
|
if (device->MediaChanged()) {
|
||||||
dprintf("Media changed from %s\n", device->Path());
|
dprintf("Media changed from %s\n", device->Path());
|
||||||
} else if (!device->HasMedia() && hadMedia) {
|
_ScanPartition(device, false);
|
||||||
dprintf("Media removed from %s\n", device->Path());
|
} else if (!device->HasMedia() && hadMedia) {
|
||||||
|
dprintf("Media removed from %s\n", device->Path());
|
||||||
|
}
|
||||||
|
|
||||||
|
device->UnmarkBusy(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snooze(1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
fLock.Unlock();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
KDiskDeviceManager::_CheckMediaStatusDaemon(void* self, int iteration)
|
KDiskDeviceManager::_CheckMediaStatusDaemon(void* self)
|
||||||
{
|
{
|
||||||
((KDiskDeviceManager*)self)->_CheckMediaStatus();
|
return ((KDiskDeviceManager*)self)->_CheckMediaStatus();
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include <KFileDiskDevice.h>
|
#include <KFileDiskDevice.h>
|
||||||
#include <KPath.h>
|
#include <KPath.h>
|
||||||
|
|
||||||
#include "virtualdrive.h"
|
|
||||||
|
|
||||||
// debugging
|
// debugging
|
||||||
//#define DBG(x)
|
//#define DBG(x)
|
||||||
@ -166,7 +165,6 @@ KFileDiskDevice::GetGeometry(device_geometry *geometry)
|
|||||||
geometry->write_once = false;
|
geometry->write_once = false;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// _RegisterDevice
|
// _RegisterDevice
|
||||||
@ -175,48 +173,6 @@ KFileDiskDevice::_RegisterDevice(const char *file, const char *device)
|
|||||||
{
|
{
|
||||||
return devfs_publish_file_device(device + 5, file);
|
return devfs_publish_file_device(device + 5, file);
|
||||||
// we need to remove the "/dev/" part from the path
|
// we need to remove the "/dev/" part from the path
|
||||||
|
|
||||||
// TODO: For now we use the virtualdrive driver to register a file
|
|
||||||
// as a device and then simply symlink the assigned device to the
|
|
||||||
// desired device location. Replace that with the
|
|
||||||
// respective kernel magic for the OBOS kernel!
|
|
||||||
// -> Well, we could simply symlink the file there. Doesn't work for R5,
|
|
||||||
// but we should be able to deal with it properly.
|
|
||||||
//
|
|
||||||
// // open the virtualdrive control device
|
|
||||||
// int fd = open(VIRTUAL_DRIVE_CONTROL_DEVICE, O_RDONLY);
|
|
||||||
// if (fd < 0) {
|
|
||||||
// DBG(OUT("Failed to open virtualdrive control device: %s\n",
|
|
||||||
// strerror(errno)));
|
|
||||||
// return errno;
|
|
||||||
// }
|
|
||||||
// // set up the info
|
|
||||||
// virtual_drive_info info;
|
|
||||||
// strcpy(info.file_name, file);
|
|
||||||
// info.use_geometry = false;
|
|
||||||
// status_t error = B_OK;
|
|
||||||
// if (ioctl(fd, VIRTUAL_DRIVE_REGISTER_FILE, &info) != 0) {
|
|
||||||
// error = errno;
|
|
||||||
// DBG(OUT("Failed to install file device: %s\n", strerror(error)));
|
|
||||||
// }
|
|
||||||
// // close the control device
|
|
||||||
// close(fd);
|
|
||||||
// // create a symlink
|
|
||||||
// if (error == B_OK) {
|
|
||||||
// if (symlink(info.device_name, device) != 0) {
|
|
||||||
// DBG(OUT("Failed to create file device symlink: %s\n",
|
|
||||||
// strerror(error)));
|
|
||||||
// error = errno;
|
|
||||||
// // unregister the file device
|
|
||||||
// // open the device
|
|
||||||
// int deviceFD = open(info.device_name, O_RDONLY);
|
|
||||||
// if (deviceFD >= 0) {
|
|
||||||
// ioctl(deviceFD, VIRTUAL_DRIVE_UNREGISTER_FILE);
|
|
||||||
// close(deviceFD);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// _UnregisterDevice
|
// _UnregisterDevice
|
||||||
@ -225,29 +181,6 @@ KFileDiskDevice::_UnregisterDevice(const char *_device)
|
|||||||
{
|
{
|
||||||
return devfs_unpublish_file_device(_device + 5);
|
return devfs_unpublish_file_device(_device + 5);
|
||||||
// we need to remove the "/dev/" part from the path
|
// we need to remove the "/dev/" part from the path
|
||||||
|
|
||||||
// // read the symlink to get the path of the virtualdrive device
|
|
||||||
// char device[B_PATH_NAME_LENGTH];
|
|
||||||
// ssize_t bytesRead = readlink(_device, device, sizeof(device) - 1);
|
|
||||||
// if (bytesRead < 0)
|
|
||||||
// return errno;
|
|
||||||
// device[bytesRead] = '\0';
|
|
||||||
// // open the device
|
|
||||||
// int fd = open(device, O_RDONLY);
|
|
||||||
// if (fd < 0)
|
|
||||||
// return errno;
|
|
||||||
// // issue the ioctl
|
|
||||||
// status_t error = B_OK;
|
|
||||||
// if (ioctl(fd, VIRTUAL_DRIVE_UNREGISTER_FILE) != 0)
|
|
||||||
// error = errno;
|
|
||||||
// // close the control device
|
|
||||||
// close(fd);
|
|
||||||
// // remove the symlink
|
|
||||||
// if (error == B_OK) {
|
|
||||||
// if (remove(_device) < 0)
|
|
||||||
// error = errno;
|
|
||||||
// }
|
|
||||||
// return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// _GetDirectoryPath
|
// _GetDirectoryPath
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <Drivers.h>
|
#include <Drivers.h>
|
||||||
#include <Errors.h>
|
#include <Errors.h>
|
||||||
|
#include <fs_volume.h>
|
||||||
#include <util/kernel_cpp.h>
|
#include <util/kernel_cpp.h>
|
||||||
|
|
||||||
#include <ddm_userland_interface.h>
|
#include <ddm_userland_interface.h>
|
||||||
@ -22,6 +23,7 @@
|
|||||||
#include <KPartitionVisitor.h>
|
#include <KPartitionVisitor.h>
|
||||||
#include <KPath.h>
|
#include <KPath.h>
|
||||||
#include <VectorSet.h>
|
#include <VectorSet.h>
|
||||||
|
#include <vfs.h>
|
||||||
|
|
||||||
#include "UserDataWriter.h"
|
#include "UserDataWriter.h"
|
||||||
|
|
||||||
@ -272,6 +274,16 @@ KPartition::CheckAndMarkBusy(bool includeDescendants)
|
|||||||
if (IsBusy(includeDescendants))
|
if (IsBusy(includeDescendants))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
MarkBusy(includeDescendants);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MarkBusy
|
||||||
|
void
|
||||||
|
KPartition::MarkBusy(bool includeDescendants)
|
||||||
|
{
|
||||||
if (includeDescendants) {
|
if (includeDescendants) {
|
||||||
struct MarkBusyVisitor : KPartitionVisitor {
|
struct MarkBusyVisitor : KPartitionVisitor {
|
||||||
virtual bool VisitPre(KPartition* partition)
|
virtual bool VisitPre(KPartition* partition)
|
||||||
@ -284,8 +296,6 @@ KPartition::CheckAndMarkBusy(bool includeDescendants)
|
|||||||
VisitEachDescendant(&markVisitor);
|
VisitEachDescendant(&markVisitor);
|
||||||
} else
|
} else
|
||||||
SetBusy(true);
|
SetBusy(true);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1039,7 +1049,13 @@ KPartition::UninitializeContents(bool logChanges)
|
|||||||
|
|
||||||
// volume
|
// volume
|
||||||
if (VolumeID() >= 0) {
|
if (VolumeID() >= 0) {
|
||||||
// TODO: Unmount?
|
status_t error = vfs_unmount(VolumeID(),
|
||||||
|
B_FORCE_UNMOUNT | B_UNMOUNT_BUSY_PARTITION);
|
||||||
|
if (error != B_OK) {
|
||||||
|
dprintf("KPartition::UninitializeContents(): Failed to unmount "
|
||||||
|
"device %ld: %s\n", VolumeID(), strerror(error));
|
||||||
|
}
|
||||||
|
|
||||||
SetVolumeID(-1);
|
SetVolumeID(-1);
|
||||||
flags |= B_PARTITION_CHANGED_VOLUME;
|
flags |= B_PARTITION_CHANGED_VOLUME;
|
||||||
}
|
}
|
||||||
|
@ -1225,7 +1225,7 @@ _user_uninitialize_partition(partition_id partitionID, int32* _changeCounter)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// check busy
|
// check busy
|
||||||
if (partition->IsBusy(true))
|
if (!partition->CheckAndMarkBusy(true))
|
||||||
return B_BUSY;
|
return B_BUSY;
|
||||||
|
|
||||||
// TODO: We should also check, if any partition is mounted!
|
// TODO: We should also check, if any partition is mounted!
|
||||||
|
Loading…
Reference in New Issue
Block a user