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();
|
||||
|
||||
private:
|
||||
static void _CheckMediaStatusDaemon(void* self, int iteration);
|
||||
void _CheckMediaStatus();
|
||||
static status_t _CheckMediaStatusDaemon(void* self);
|
||||
status_t _CheckMediaStatus();
|
||||
|
||||
status_t _RescanDiskSystems(bool fileSystems);
|
||||
|
||||
@ -127,6 +127,8 @@ private:
|
||||
PartitionMap *fPartitions;
|
||||
DiskSystemMap *fDiskSystems;
|
||||
PartitionSet *fObsoletePartitions;
|
||||
thread_id fMediaChecker;
|
||||
volatile bool fTerminating;
|
||||
|
||||
static KDiskDeviceManager *sDefaultManager;
|
||||
};
|
||||
|
@ -54,6 +54,7 @@ public:
|
||||
bool IsBusy() const;
|
||||
bool IsBusy(bool includeDescendants);
|
||||
bool CheckAndMarkBusy(bool includeDescendants);
|
||||
void MarkBusy(bool includeDescendants);
|
||||
void UnmarkBusy(bool includeDescendants);
|
||||
|
||||
void SetOffset(off_t offset);
|
||||
|
@ -103,15 +103,19 @@ KDiskDeviceManager::KDiskDeviceManager()
|
||||
fDevices(new(nothrow) DeviceMap),
|
||||
fPartitions(new(nothrow) PartitionMap),
|
||||
fDiskSystems(new(nothrow) DiskSystemMap),
|
||||
fObsoletePartitions(new(nothrow) PartitionSet)
|
||||
fObsoletePartitions(new(nothrow) PartitionSet),
|
||||
fMediaChecker(-1),
|
||||
fTerminating(false)
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return;
|
||||
|
||||
RescanDiskSystems();
|
||||
|
||||
register_kernel_daemon(&_CheckMediaStatusDaemon, this, 10);
|
||||
// once every second
|
||||
fMediaChecker = spawn_kernel_thread(_CheckMediaStatusDaemon,
|
||||
"media checker", B_NORMAL_PRIORITY, this);
|
||||
if (fMediaChecker >= 0)
|
||||
resume_thread(fMediaChecker);
|
||||
|
||||
DBG(OUT("number of disk systems: %ld\n", CountDiskSystems()));
|
||||
// TODO: Watch the disk systems and the relevant directories.
|
||||
@ -120,9 +124,11 @@ 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
|
||||
for (int32 cookie = 0; KDiskDevice *device = NextDevice(&cookie);) {
|
||||
PartitionRegistrar _(device);
|
||||
@ -1127,35 +1133,45 @@ KDiskDeviceManager::_ScanPartition(KPartition *partition)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
status_t
|
||||
KDiskDeviceManager::_CheckMediaStatus()
|
||||
{
|
||||
if (fLock.LockWithTimeout(0) != B_OK)
|
||||
return;
|
||||
|
||||
int32 cookie = 0;
|
||||
while (true) {
|
||||
KDiskDevice* device = NextDevice(&cookie);
|
||||
if (device == NULL)
|
||||
break;
|
||||
int32 cookie = 0;
|
||||
while (KDiskDevice* device = RegisterNextDevice(&cookie)) {
|
||||
DeviceWriteLocker locker(device);
|
||||
|
||||
bool hadMedia = device->HasMedia();
|
||||
device->UpdateMediaStatusIfNeeded();
|
||||
if (device->IsBusy(true))
|
||||
continue;
|
||||
|
||||
// TODO: propagate changes!
|
||||
if (device->MediaChanged()) {
|
||||
bool hadMedia = device->HasMedia();
|
||||
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());
|
||||
} else if (!device->HasMedia() && hadMedia) {
|
||||
dprintf("Media removed from %s\n", device->Path());
|
||||
_ScanPartition(device, false);
|
||||
} else if (!device->HasMedia() && hadMedia) {
|
||||
dprintf("Media removed from %s\n", device->Path());
|
||||
}
|
||||
|
||||
device->UnmarkBusy(true);
|
||||
}
|
||||
|
||||
snooze(1000000);
|
||||
}
|
||||
|
||||
fLock.Unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KDiskDeviceManager::_CheckMediaStatusDaemon(void* self, int iteration)
|
||||
status_t
|
||||
KDiskDeviceManager::_CheckMediaStatusDaemon(void* self)
|
||||
{
|
||||
((KDiskDeviceManager*)self)->_CheckMediaStatus();
|
||||
return ((KDiskDeviceManager*)self)->_CheckMediaStatus();
|
||||
}
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <KFileDiskDevice.h>
|
||||
#include <KPath.h>
|
||||
|
||||
#include "virtualdrive.h"
|
||||
|
||||
// debugging
|
||||
//#define DBG(x)
|
||||
@ -166,7 +165,6 @@ KFileDiskDevice::GetGeometry(device_geometry *geometry)
|
||||
geometry->write_once = false;
|
||||
|
||||
return B_OK;
|
||||
|
||||
}
|
||||
|
||||
// _RegisterDevice
|
||||
@ -175,48 +173,6 @@ KFileDiskDevice::_RegisterDevice(const char *file, const char *device)
|
||||
{
|
||||
return devfs_publish_file_device(device + 5, file);
|
||||
// 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
|
||||
@ -225,29 +181,6 @@ KFileDiskDevice::_UnregisterDevice(const char *_device)
|
||||
{
|
||||
return devfs_unpublish_file_device(_device + 5);
|
||||
// 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
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <KernelExport.h>
|
||||
#include <Drivers.h>
|
||||
#include <Errors.h>
|
||||
#include <fs_volume.h>
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
#include <ddm_userland_interface.h>
|
||||
@ -22,6 +23,7 @@
|
||||
#include <KPartitionVisitor.h>
|
||||
#include <KPath.h>
|
||||
#include <VectorSet.h>
|
||||
#include <vfs.h>
|
||||
|
||||
#include "UserDataWriter.h"
|
||||
|
||||
@ -272,6 +274,16 @@ KPartition::CheckAndMarkBusy(bool includeDescendants)
|
||||
if (IsBusy(includeDescendants))
|
||||
return false;
|
||||
|
||||
MarkBusy(includeDescendants);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// MarkBusy
|
||||
void
|
||||
KPartition::MarkBusy(bool includeDescendants)
|
||||
{
|
||||
if (includeDescendants) {
|
||||
struct MarkBusyVisitor : KPartitionVisitor {
|
||||
virtual bool VisitPre(KPartition* partition)
|
||||
@ -284,8 +296,6 @@ KPartition::CheckAndMarkBusy(bool includeDescendants)
|
||||
VisitEachDescendant(&markVisitor);
|
||||
} else
|
||||
SetBusy(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -1039,7 +1049,13 @@ KPartition::UninitializeContents(bool logChanges)
|
||||
|
||||
// volume
|
||||
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);
|
||||
flags |= B_PARTITION_CHANGED_VOLUME;
|
||||
}
|
||||
|
@ -1225,7 +1225,7 @@ _user_uninitialize_partition(partition_id partitionID, int32* _changeCounter)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// check busy
|
||||
if (partition->IsBusy(true))
|
||||
if (!partition->CheckAndMarkBusy(true))
|
||||
return B_BUSY;
|
||||
|
||||
// TODO: We should also check, if any partition is mounted!
|
||||
|
Loading…
Reference in New Issue
Block a user