* Renamed _ForceUnmount() to _SuggestForceUnmount() to clarify what it does.

* Factored an _UnmountAndEjectVolume() method that takes a partition and mount
  path out of the method with the same name that gets a BMessage.
* Remove the mount point only if it's in rootfs.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26604 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-07-24 11:25:16 +00:00
parent 93706b7208
commit 489075a3b4
2 changed files with 141 additions and 128 deletions

View File

@ -138,7 +138,8 @@ AutoMounter::_MountVolumes(mount_mode normal, mount_mode removable,
BPath path; BPath path;
if (partition->GetPath(&path) != B_OK if (partition->GetPath(&path) != B_OK
|| partition->ContentName() == NULL || partition->ContentName() == NULL
|| fPrevious.FindString(path.Path(), &volumeName) != B_OK || fPrevious.FindString(path.Path(), &volumeName)
!= B_OK
|| strcmp(volumeName, partition->ContentName())) || strcmp(volumeName, partition->ContentName()))
return false; return false;
} else if (mode == kOnlyBFSVolumes) { } else if (mode == kOnlyBFSVolumes) {
@ -196,7 +197,7 @@ AutoMounter::_MountVolume(BMessage *message)
bool bool
AutoMounter::_ForceUnmount(const char* name, status_t error) AutoMounter::_SuggestForceUnmount(const char* name, status_t error)
{ {
BString text; BString text;
text << "Could not unmount disk \"" << name << "\":\n\t" << strerror(error); text << "Could not unmount disk \"" << name << "\":\n\t" << strerror(error);
@ -204,8 +205,8 @@ AutoMounter::_ForceUnmount(const char* name, status_t error)
"Note: if an application is currently writing to the volume, unmounting" "Note: if an application is currently writing to the volume, unmounting"
" it now might result in loss of data.\n"; " it now might result in loss of data.\n";
int32 choice = (new BAlert("", text.String(), "Cancel", "Force Unmount", NULL, int32 choice = (new BAlert("", text.String(), "Cancel", "Force Unmount",
B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go();
return choice == 1; return choice == 1;
} }
@ -223,7 +224,40 @@ AutoMounter::_ReportUnmountError(const char* name, status_t error)
void void
AutoMounter::_UnmountAndEjectVolume(BMessage *message) AutoMounter::_UnmountAndEjectVolume(BPartition* partition, BPath& mountPoint,
const char* name)
{
status_t status;
if (partition != NULL)
status = partition->Unmount();
else
status = fs_unmount_volume(mountPoint.Path(), 0);
if (status < B_OK) {
if (!_SuggestForceUnmount(name, status))
return;
if (partition != NULL)
status = partition->Unmount(B_FORCE_UNMOUNT);
else
status = fs_unmount_volume(mountPoint.Path(), B_FORCE_UNMOUNT);
}
if (status < B_OK) {
_ReportUnmountError(partition->ContentName(), status);
return;
}
// TODO: eject!
// remove the directory if it's a directory in rootfs
if (dev_for_path(mountPoint.Path()) == dev_for_path("/"))
rmdir(mountPoint.Path());
}
void
AutoMounter::_UnmountAndEjectVolume(BMessage* message)
{ {
int32 id; int32 id;
if (message->FindInt32("id", &id) == B_OK) { if (message->FindInt32("id", &id) == B_OK) {
@ -232,63 +266,37 @@ AutoMounter::_UnmountAndEjectVolume(BMessage *message)
BDiskDevice device; BDiskDevice device;
if (roster.GetPartitionWithID(id, &device, &partition) != B_OK) if (roster.GetPartitionWithID(id, &device, &partition) != B_OK)
return; return;
BPath path; BPath path;
if (partition->GetMountPoint(&path) == B_OK) if (partition->GetMountPoint(&path) == B_OK)
{ _UnmountAndEjectVolume(partition, path, partition->ContentName());
status_t status = partition->Unmount(); } else {
if (status < B_OK) { // see if we got a dev_t
if (!_ForceUnmount(partition->ContentName(), status))
return;
status = partition->Unmount(B_FORCE_UNMOUNT); dev_t device;
} if (message->FindInt32("device_id", &device) != B_OK)
return;
if (status < B_OK) BVolume volume(device);
_ReportUnmountError(partition->ContentName(), status); status_t status = volume.InitCheck();
else
rmdir(path.Path());
}
return;
}
// see if we got a dev_t char name[B_FILE_NAME_LENGTH];
dev_t device;
if (message->FindInt32("device_id", &device) != B_OK)
return;
BVolume volume(device);
status_t status = volume.InitCheck();
char name[B_FILE_NAME_LENGTH];
if (status == B_OK)
status = volume.GetName(name);
if (status < B_OK)
snprintf(name, sizeof(name), "device:%ld", device);
BPath path;
if (status == B_OK) {
BDirectory mountPoint;
status = volume.GetRootDirectory(&mountPoint);
if (status == B_OK) if (status == B_OK)
status = path.SetTo(&mountPoint, "."); status = volume.GetName(name);
} if (status < B_OK)
snprintf(name, sizeof(name), "device:%ld", device);
if (status == B_OK) { BPath path;
status = fs_unmount_volume(path.Path(), 0); if (status == B_OK) {
if (status < B_OK) { BDirectory mountPoint;
if (!_ForceUnmount(name, status)) status = volume.GetRootDirectory(&mountPoint);
return; if (status == B_OK)
status = path.SetTo(&mountPoint, ".");
status = fs_unmount_volume(path.Path(), B_FORCE_UNMOUNT);
} }
if (status == B_OK)
_UnmountAndEjectVolume(NULL, path, name);
} }
if (status == B_OK)
rmdir(path.Path());
if (status < B_OK)
_ReportUnmountError(name, status);
} }
@ -628,32 +636,32 @@ DumpPartition(Partition *partition, void*)
#endif #endif
/** Sets the Tracker Shell's AutoMounter to monitor a node. /*! Sets the Tracker Shell's AutoMounter to monitor a node.
* n.b. Get's the one AutoMounter and uses Tracker's _special_ WatchNode. n.b. Get's the one AutoMounter and uses Tracker's _special_ WatchNode.
*
* @param nodeToWatch (node_ref const * const) The Node to monitor.
* @param flags (uint32) watch_node flags from NodeMonitor.
* @return (status_t) watch_node status or B_BAD_TYPE if not a TTracker app.
*/
@param nodeToWatch (node_ref const * const) The Node to monitor.
@param flags (uint32) watch_node flags from NodeMonitor.
@return (status_t) watch_node status or B_BAD_TYPE if not a TTracker app.
*/
static status_t static status_t
AutoMounterWatchNode(const node_ref *nodeRef, uint32 flags) AutoMounterWatchNode(const node_ref *nodeRef, uint32 flags)
{ {
ASSERT(nodeRef != NULL); ASSERT(nodeRef != NULL);
TTracker *tracker = dynamic_cast<TTracker *>(be_app); TTracker *tracker = dynamic_cast<TTracker *>(be_app);
if (tracker != NULL) if (tracker != NULL) {
return TTracker::WatchNode(nodeRef, flags, BMessenger(0, tracker->AutoMounterLoop())); return TTracker::WatchNode(nodeRef, flags,
BMessenger(0, tracker->AutoMounterLoop()));
}
return B_BAD_TYPE; return B_BAD_TYPE;
} }
/** Tries to mount the partition and if it can it watches mount point. /*! Tries to mount the partition and if it can it watches mount point.
*
* @param partition (Partition * const) The partition to mount.
*/
@param partition (Partition * const) The partition to mount.
*/
static status_t static status_t
MountAndWatch(Partition *partition) MountAndWatch(Partition *partition)
{ {

View File

@ -41,6 +41,9 @@ All rights reserved.
#ifndef __HAIKU__ #ifndef __HAIKU__
# include "DeviceMap.h" # include "DeviceMap.h"
#else
class BPartition;
class BPath;
#endif #endif
namespace BPrivate { namespace BPrivate {
@ -73,8 +76,10 @@ class AutoMounter : public BLooper {
void _MountVolumes(mount_mode normal, mount_mode removable, void _MountVolumes(mount_mode normal, mount_mode removable,
bool initialRescan); bool initialRescan);
void _MountVolume(BMessage* message); void _MountVolume(BMessage* message);
bool _ForceUnmount(const char* name, status_t error); bool _SuggestForceUnmount(const char* name, status_t error);
void _ReportUnmountError(const char* name, status_t error); void _ReportUnmountError(const char* name, status_t error);
void _UnmountAndEjectVolume(BPartition* partition, BPath& mountPoint,
const char* name);
void _UnmountAndEjectVolume(BMessage* message); void _UnmountAndEjectVolume(BMessage* message);
void _FromMode(mount_mode mode, bool& all, bool& bfs, bool& restore); void _FromMode(mount_mode mode, bool& all, bool& bfs, bool& restore);