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:
Ingo Weinhold 2007-11-12 18:41:36 +00:00
parent 5b1f301a11
commit b3a5629b9e
6 changed files with 64 additions and 96 deletions

View File

@ -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;
};

View File

@ -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);

View File

@ -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();
}

View File

@ -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

View File

@ -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;
}

View File

@ -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!