* Moved partition scanning back to KDiskDeviceManager. ATM only

synchronous scanning is supported.
* Removed the disk device job support from the disk device manager.
* K{Disk,File,Partitioning}System:
  - Remove querying and validation methods.
  - Commented out the modification methods until their fate is decided.
* Removed obsolete _user_get_partitionable_spaces().


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22799 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2007-11-01 22:41:22 +00:00
parent c5e454a288
commit 327887959e
47 changed files with 162 additions and 5127 deletions
@@ -1,103 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic
*/
#ifndef _K_DISK_DEVICE_JOB_H
#define _K_DISK_DEVICE_JOB_H
#include "disk_device_manager.h"
#include <KPartitionVisitor.h>
struct user_disk_device_job_info;
namespace BPrivate {
namespace DiskDevice {
class KDiskDeviceJobQueue;
/**
* Represents some action executed on the disk device.
*/
class KDiskDeviceJob {
public:
KDiskDeviceJob(uint32 type, partition_id partitionID,
partition_id scopeID = -1);
virtual ~KDiskDeviceJob();
disk_job_id ID() const;
void SetJobQueue(KDiskDeviceJobQueue *queue);
KDiskDeviceJobQueue *JobQueue() const;
uint32 Type() const;
void SetStatus(uint32 status);
uint32 Status() const;
status_t SetDescription(const char *description);
const char *Description() const;
partition_id PartitionID() const;
partition_id ScopeID() const;
status_t SetErrorMessage(const char *message);
const char *ErrorMessage() const;
void SetTaskCount(int32 count);
int32 TaskCount() const;
void SetCompletedTasks(int32 count);
int32 CompletedTasks() const;
void SetInterruptProperties(uint32 properties);
uint32 InterruptProperties() const;
virtual void GetTaskDescription(char *description);
void UpdateProgress(float progress);
// may trigger a notification
void UpdateExtraProgress(const char *info);
// triggers a notification
float Progress() const;
status_t GetInfo(user_disk_device_job_info *info);
status_t GetProgressInfo(disk_device_job_progress_info *info);
virtual status_t Do() = 0;
private:
static disk_job_id _NextID();
disk_job_id fID;
KDiskDeviceJobQueue *fJobQueue;
uint32 fType;
uint32 fStatus;
partition_id fPartitionID;
partition_id fScopeID;
char *fDescription;
char *fErrorMessage;
int32 fTaskCount;
int32 fCompletedTasks;
uint32 fInterruptProperties;
float fProgress;
static disk_job_id fNextID;
protected:
// some stuff useful for all descendants
bool IsPartitionNotBusy(KPartition* partition);
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KDiskDeviceJob;
#endif // _DISK_DEVICE_JOB_H
@@ -1,59 +0,0 @@
// KDiskDeviceJobFactory.h
#ifndef _K_DISK_DEVICE_JOB_FACTORY_H
#define _K_DISK_DEVICE_JOB_FACTORY_H
#include "disk_device_manager.h"
namespace BPrivate {
namespace DiskDevice {
class KDiskDeviceJob;
class KDiskDeviceJobFactory {
public:
KDiskDeviceJobFactory();
~KDiskDeviceJobFactory();
KDiskDeviceJob *CreateDefragmentJob(partition_id partitionID);
KDiskDeviceJob *CreateRepairJob(partition_id partitionID, bool checkOnly);
KDiskDeviceJob *CreateResizeJob(partition_id parentID,
partition_id partitionID, off_t size);
KDiskDeviceJob *CreateMoveJob(partition_id parentID,
partition_id partitionID, off_t offset,
const partition_id *contentsToMove,
int32 contentsToMoveCount);
KDiskDeviceJob *CreateSetNameJob(partition_id parentID,
partition_id partitionID,
const char *name);
KDiskDeviceJob *CreateSetContentNameJob(partition_id partitionID,
const char *name);
KDiskDeviceJob *CreateSetTypeJob(partition_id parentID,
partition_id partitionID,
const char *type);
KDiskDeviceJob *CreateSetParametersJob(partition_id parentID,
partition_id partitionID,
const char *parameters);
KDiskDeviceJob *CreateSetContentParametersJob(partition_id partitionID,
const char *parameters);
KDiskDeviceJob *CreateInitializeJob(partition_id partitionID,
disk_system_id diskSystemID,
const char *name,
const char *parameters);
KDiskDeviceJob *CreateUninitializeJob(partition_id partitionID);
KDiskDeviceJob *CreateCreateChildJob(partition_id partitionID,
partition_id childID, off_t offset,
off_t size, const char *type,
const char *parameters);
KDiskDeviceJob *CreateDeleteChildJob(partition_id parentID,
partition_id partitionID);
KDiskDeviceJob *CreateScanPartitionJob(partition_id partitionID);
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KDiskDeviceJobFactory;
#endif // _K_DISK_DEVICE_JOB_FACTORY_H
@@ -1,72 +0,0 @@
// KDiskDeviceJobQueue.h
#ifndef _K_DISK_DEVICE_JOB_QUEUE_H
#define _K_DISK_DEVICE_JOB_QUEUE_H
#include <OS.h>
#include "disk_device_manager.h"
namespace BPrivate {
namespace DiskDevice {
class KDiskDevice;
class KDiskDeviceJob;
class KDiskDeviceJobQueue {
public:
KDiskDeviceJobQueue(KDiskDevice *device = NULL);
~KDiskDeviceJobQueue();
status_t InitCheck() const;
void SetDevice(KDiskDevice *device);
KDiskDevice *Device() const;
int32 ActiveJobIndex() const;
KDiskDeviceJob *ActiveJob() const;
// list of scheduled jobs
bool AddJob(KDiskDeviceJob *job);
KDiskDeviceJob *RemoveJob(int32 index);
bool RemoveJob(KDiskDeviceJob *job);
// Adding/removing is only possible before the queues is added to the
// manager.
KDiskDeviceJob *JobAt(int32 index) const;
int32 CountJobs() const;
status_t Execute();
// Called by the manager, when the queue is added to it.
// manager must be locked
status_t Cancel(bool reverse);
status_t Pause();
status_t Continue();
sem_id ReadyToPause();
// called only by the queue's thread from within a module hook
bool IsExecuting() const;
bool IsCanceled() const;
bool ShallReverse() const;
bool IsPaused() const;
bool IsPauseRequested() const;
private:
struct JobQueue;
int32 _ThreadLoop();
static int32 _ThreadEntry(void *data);
KDiskDevice *fDevice;
int32 fActiveJob;
JobQueue *fJobs;
uint32 fFlags;
thread_id fThread;
sem_id fSyncSemaphore;
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KDiskDeviceJobQueue;
#endif // _K_DISK_DEVICE_JOB_QUEUE_H
@@ -16,9 +16,6 @@ namespace BPrivate {
namespace DiskDevice {
class KDiskDevice;
class KDiskDeviceJob;
class KDiskDeviceJobFactory;
class KDiskDeviceJobQueue;
class KDiskSystem;
class KFileDiskDevice;
class KPartition;
@@ -66,10 +63,10 @@ public:
// Both the device and the partition is also registered and must be
// unregistered by the caller.
status_t ScanPartition(KPartition* partition, bool async);
status_t ScanPartition(KPartition* partition);
partition_id CreateFileDevice(const char *filePath,
bool *newlyCreated = NULL, bool async = true);
partition_id CreateFileDevice(const char* filePath,
bool* newlyCreated = NULL);
status_t DeleteFileDevice(const char *filePath);
status_t DeleteFileDevice(partition_id id);
@@ -81,29 +78,6 @@ public:
bool PartitionRemoved(KPartition *partition); //
bool DeletePartition(KPartition *partition); //
// Jobs
// manager must be locked
KDiskDeviceJob *FindJob(disk_job_id id);
int32 CountJobs();
KDiskDeviceJob *NextJob(int32 *cookie);
// manager must be locked
status_t AddJobQueue(KDiskDeviceJobQueue *jobQueue);
// the device must be write locked
status_t RemoveJobQueue(KDiskDeviceJobQueue *jobQueue);
status_t DeleteJobQueue(KDiskDeviceJobQueue *jobQueue);
// called when the execution is done
int32 CountJobQueues();
KDiskDeviceJobQueue *NextJobQueue(int32 *cookie);
KDiskDeviceJobFactory *JobFactory() const;
// manager must *not* be locked
status_t UpdateBusyPartitions(KDiskDevice *device);
status_t UpdateJobStatus(KDiskDeviceJob *job, uint32 status,
bool updateBusyPartitions);
// Disk Systems
// manager must be locked
@@ -137,20 +111,14 @@ private:
bool _AddDevice(KDiskDevice *device);
bool _RemoveDevice(KDiskDevice *device);
bool _RemoveJobQueue(KDiskDeviceJobQueue *jobQueue);
status_t _UpdateBusyPartitions(KDiskDevice *device);
status_t _UpdateJobStatus(KDiskDeviceJob *job, uint32 status,
bool updateBusyPartitions);
status_t _Scan(const char *path);
status_t _ScanPartition(KPartition *partition, bool async);
// the manager must be locked and the device write locked
status_t _ScanPartition(KPartition *partition);
// used by the other _ScanPartition() version only
struct DeviceMap;
struct DiskSystemMap;
struct JobMap;
struct JobQueueVector;
struct PartitionMap;
struct PartitionSet;
@@ -159,9 +127,6 @@ private:
PartitionMap *fPartitions;
DiskSystemMap *fDiskSystems;
PartitionSet *fObsoletePartitions;
JobMap *fJobs;
JobQueueVector *fJobQueues;
KDiskDeviceJobFactory *fJobFactory;
static KDiskDeviceManager *sDefaultManager;
};
@@ -15,7 +15,7 @@ struct user_disk_system_info;
namespace BPrivate {
namespace DiskDevice {
class KDiskDeviceJob;
//class KDiskDeviceJob;
class KPartition;
//! \brief Common ancestor for disk system add-on wrappers
@@ -51,60 +51,10 @@ public:
virtual void FreeCookie(KPartition *partition);
virtual void FreeContentCookie(KPartition *partition);
// Querying
// Device must be read locked.
virtual uint32 GetSupportedOperations(KPartition* partition, uint32 mask);
virtual uint32 GetSupportedChildOperations(KPartition* child, uint32 mask);
// for convenience
bool SupportsOperations(KPartition* partition, uint32 operations)
{ return (GetSupportedOperations(partition, operations) & operations)
== operations; }
bool SupportsChildOperations(KPartition* child, uint32 operations)
{ return (GetSupportedChildOperations(child, operations) & operations)
== operations; }
virtual bool SupportsInitializingChild(KPartition *child,
const char *diskSystem);
virtual bool IsSubSystemFor(KPartition *partition);
virtual bool ValidateResize(KPartition *partition, off_t *size);
virtual bool ValidateResizeChild(KPartition *child, off_t *size);
virtual bool ValidateMove(KPartition *partition, off_t *start);
virtual bool ValidateMoveChild(KPartition *child, off_t *start);
virtual bool ValidateSetName(KPartition *partition, char *name);
virtual bool ValidateSetContentName(KPartition *partition, char *name);
virtual bool ValidateSetType(KPartition *partition, const char *type);
virtual bool ValidateSetParameters(KPartition *partition,
const char *parameters);
virtual bool ValidateSetContentParameters(KPartition *parameters,
const char *parameters);
virtual bool ValidateInitialize(KPartition *partition, char *name,
const char *parameters);
virtual bool ValidateCreateChild(KPartition *partition, off_t *start,
off_t *size, const char *type,
const char *parameters, int32 *index);
virtual int32 CountPartitionableSpaces(KPartition *partition);
virtual status_t GetPartitionableSpaces(KPartition *partition,
partitionable_space_data *buffer,
int32 count,
int32 *actualCount = NULL);
virtual status_t GetNextSupportedType(KPartition *partition, int32 *cookie,
char *type);
virtual status_t GetTypeForContentType(const char *contentType,
char *type);
// Shadow partition modification
// Device must be write locked.
virtual status_t ShadowPartitionChanged(KPartition *partition,
KPartition *child, uint32 operation);
// Writing
// Device should not be locked.
#if 0
virtual status_t Defragment(KPartition *partition, KDiskDeviceJob *job);
virtual status_t Repair(KPartition *partition, bool checkOnly,
KDiskDeviceJob *job);
@@ -140,6 +90,7 @@ public:
// since the device will not be locked, when they are called. The KPartition
// is registered though, so that it is at least guaranteed that the object
// won't go away.
#endif // 0
protected:
virtual status_t LoadModule();
@@ -33,25 +33,9 @@ public:
virtual void FreeIdentifyCookie(KPartition *partition, void *cookie);
virtual void FreeContentCookie(KPartition *partition);
// Querying
virtual uint32 GetSupportedOperations(KPartition* partition, uint32 mask);
virtual bool ValidateResize(KPartition *partition, off_t *size);
virtual bool ValidateMove(KPartition *partition, off_t *start);
virtual bool ValidateSetContentName(KPartition *partition, char *name);
virtual bool ValidateSetContentParameters(KPartition *partition,
const char *parameters);
virtual bool ValidateInitialize(KPartition *partition, char *name,
const char *parameters);
// Shadow partition modification
virtual status_t ShadowPartitionChanged(KPartition *partition,
KPartition *child, uint32 operation);
// Writing
#if 0
virtual status_t Defragment(KPartition *partition, KDiskDeviceJob *job);
virtual status_t Repair(KPartition *partition, bool checkOnly,
KDiskDeviceJob *job);
@@ -66,6 +50,7 @@ public:
KDiskDeviceJob *job);
virtual status_t Initialize(KPartition *partition, const char *name,
const char *parameters, KDiskDeviceJob *job);
#endif // 0
protected:
virtual status_t LoadModule();
@@ -35,49 +35,9 @@ public:
virtual void FreeCookie(KPartition *partition);
virtual void FreeContentCookie(KPartition *partition);
// Querying
virtual uint32 GetSupportedOperations(KPartition* partition, uint32 mask);
virtual uint32 GetSupportedChildOperations(KPartition* child, uint32 mask);
virtual bool SupportsInitializingChild(KPartition *child,
const char *diskSystem);
virtual bool IsSubSystemFor(KPartition *partition);
virtual bool ValidateResize(KPartition *partition, off_t *size);
virtual bool ValidateResizeChild(KPartition *child, off_t *size);
virtual bool ValidateMove(KPartition *partition, off_t *start);
virtual bool ValidateMoveChild(KPartition *child, off_t *start);
virtual bool ValidateSetName(KPartition *partition, char *name);
virtual bool ValidateSetContentName(KPartition *partition, char *name);
virtual bool ValidateSetType(KPartition *partition, const char *type);
virtual bool ValidateSetParameters(KPartition *partition,
const char *parameters);
virtual bool ValidateSetContentParameters(KPartition *parameters,
const char *parameters);
virtual bool ValidateInitialize(KPartition *partition, char *name,
const char *parameters);
virtual bool ValidateCreateChild(KPartition *partition, off_t *start,
off_t *size, const char *type,
const char *parameters, int32 *index);
virtual int32 CountPartitionableSpaces(KPartition *partition);
virtual status_t GetPartitionableSpaces(KPartition *partition,
partitionable_space_data *buffer,
int32 count,
int32 *actualCount = NULL);
virtual status_t GetNextSupportedType(KPartition *partition, int32 *cookie,
char *type);
virtual status_t GetTypeForContentType(const char *contentType,
char *type);
// Shadow partition modification
virtual status_t ShadowPartitionChanged(KPartition *partition,
KPartition *child, uint32 operation);
// Writing
#if 0
virtual status_t Repair(KPartition *partition, bool checkOnly,
KDiskDeviceJob *job);
virtual status_t Resize(KPartition *partition, off_t size,
@@ -108,6 +68,7 @@ public:
virtual status_t DeleteChild(KPartition *child, KDiskDeviceJob *job);
virtual status_t Initialize(KPartition *partition, const char *name,
const char *parameters, KDiskDeviceJob *job);
#endif // 0
protected:
virtual status_t LoadModule();
@@ -13,14 +13,9 @@ UsePrivateHeaders shared ;
UsePrivateHeaders storage ;
KernelMergeObject kernel_disk_device_manager.o :
ddm_operation_validation.cpp
ddm_userland_interface.cpp
disk_device_manager.cpp
KDiskDevice.cpp
KDiskDeviceJob.cpp
KDiskDeviceJobFactory.cpp
KDiskDeviceJobGenerator.cpp
KDiskDeviceJobQueue.cpp
KDiskDeviceManager.cpp
KFileDiskDevice.cpp
KDiskSystem.cpp
@@ -33,20 +28,6 @@ KernelMergeObject kernel_disk_device_manager.o :
KShadowPartition.cpp
UserDataWriter.cpp
# jobs
KCreateChildJob.cpp
KDefragmentJob.cpp
KDeleteChildJob.cpp
KInitializeJob.cpp
KMoveJob.cpp
KRepairJob.cpp
KResizeJob.cpp
KScanPartitionJob.cpp
KSetNameJob.cpp
KSetParametersJob.cpp
KSetTypeJob.cpp
KUninitializeJob.cpp
# utilities
Locker.cpp
RWLocker.cpp
@@ -1,307 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#include <stdio.h>
#include "ddm_userland_interface.h"
#include <util/kernel_cpp.h>
#include <KDiskDeviceJob.h>
#include <KDiskDeviceUtils.h>
// debugging
//#define DBG(x)
#define DBG(x) x
#define OUT dprintf
// constructor
/**
Creates a new job
\param type actual type of the job (see DiskDeviceDefs.h for details)
\param partitionID the partition/device on which the action should be
executed
\param scopeID partition/device which is the highest in the hierarchy (i.e.
closest to the root) that can be affected by the action - every
descendant of this partition is marked busy and all ancestors are marked
descendant-busy
*/
KDiskDeviceJob::KDiskDeviceJob(uint32 type, partition_id partitionID,
partition_id scopeID)
: fID(_NextID()),
fJobQueue(NULL),
fType(type),
fStatus(B_DISK_DEVICE_JOB_UNINITIALIZED),
fPartitionID(partitionID),
fScopeID(scopeID),
fDescription(NULL),
fErrorMessage(NULL),
fTaskCount(1),
fCompletedTasks(0),
fInterruptProperties(0),
fProgress(0)
{
if (fScopeID < 0)
fScopeID = fPartitionID;
}
// destructor
KDiskDeviceJob::~KDiskDeviceJob()
{
if (fDescription)
free(fDescription);
}
// ID
disk_job_id
KDiskDeviceJob::ID() const
{
return fID;
}
// SetJobQueue
void
KDiskDeviceJob::SetJobQueue(KDiskDeviceJobQueue *queue)
{
fJobQueue = queue;
}
// JobQueue
BPrivate::DiskDevice::KDiskDeviceJobQueue *
KDiskDeviceJob::JobQueue() const
{
return fJobQueue;
}
// Type
uint32
KDiskDeviceJob::Type() const
{
return fType;
}
// SetStatus
void
KDiskDeviceJob::SetStatus(uint32 status)
{
fStatus = status;
}
// Status
uint32
KDiskDeviceJob::Status() const
{
return fStatus;
}
// SetDescription
status_t
KDiskDeviceJob::SetDescription(const char *description)
{
return set_string(fDescription, description);
}
// Description
const char *
KDiskDeviceJob::Description() const
{
return fDescription;
}
// PartitionID
partition_id
KDiskDeviceJob::PartitionID() const
{
return fPartitionID;
}
// ScopeID
partition_id
KDiskDeviceJob::ScopeID() const
{
return fScopeID;
}
// SetErrorMessage
status_t
KDiskDeviceJob::SetErrorMessage(const char *message)
{
return set_string(fErrorMessage, message);
}
// ErrorMessage
const char *
KDiskDeviceJob::ErrorMessage() const
{
return fErrorMessage;
}
// SetTaskCount
void
KDiskDeviceJob::SetTaskCount(int32 count)
{
fTaskCount = count;
}
// TaskCount
int32
KDiskDeviceJob::TaskCount() const
{
return fTaskCount;
}
// SetCompletedTasks
void
KDiskDeviceJob::SetCompletedTasks(int32 count)
{
fCompletedTasks = count;
}
// CompletedTasks
int32
KDiskDeviceJob::CompletedTasks() const
{
return fCompletedTasks;
}
// SetInterruptProperties
void
KDiskDeviceJob::SetInterruptProperties(uint32 properties)
{
fInterruptProperties = properties;
}
// InterruptProperties
uint32
KDiskDeviceJob::InterruptProperties() const
{
return fInterruptProperties;
}
// GetTaskDescription
void
KDiskDeviceJob::GetTaskDescription(char *description)
{
if (!description)
return;
if (fDescription)
strcpy(description, fDescription);
else
description[0] = '\0';
}
// UpdateProgress
void
KDiskDeviceJob::UpdateProgress(float progress)
{
if (fProgress == progress)
return;
fProgress = progress;
// TODO: notification
}
// UpdateExtraProgress
void
KDiskDeviceJob::UpdateExtraProgress(const char *info)
{
// TODO:...
}
// Progress
float
KDiskDeviceJob::Progress() const
{
return fProgress;
}
// GetInfo
status_t
KDiskDeviceJob::GetInfo(user_disk_device_job_info *info)
{
if (!info)
return B_BAD_VALUE;
info->id = ID();
info->type = Type();
info->partition = PartitionID();
if (Description())
strcpy(info->description, Description());
else
info->description[0] = '\0';
return B_OK;
}
// GetProgressInfo
status_t
KDiskDeviceJob::GetProgressInfo(disk_device_job_progress_info *info)
{
if (!info)
return B_BAD_VALUE;
info->status = Status();
info->interrupt_properties = InterruptProperties();
info->task_count = TaskCount();
info->completed_tasks = CompletedTasks();
info->current_task_progress = Progress();
GetTaskDescription(info->current_task_description);
return B_OK;
}
/** \fn status_t KDiskDevice::Do()
Do the actual work of the job.
- is supposed to be implemented in descendants
- doesn't have any parameter - every operation needs different ones
-> they're passed to the constructor
- the implementations will
- check the parameters given in constructor (e.g. if given partition
exists...)
- check whether the partition has needed disk system (its own or
parent - depends on the operation)
- using the disk system, validate the operation for given params
- finally execute the action
\return B_OK when everything went OK, some error otherwise
*/
// _NextID
disk_job_id
KDiskDeviceJob::_NextID()
{
return atomic_add(&fNextID, 1);
}
// fNextID
disk_job_id KDiskDeviceJob::fNextID = 0;
/**
Checks if there's any descendant which is not busy/descendant-busy.
- the condition of busy descendant is common for many disk device operations ->
many jobs can use this
\param partition the root of checked subtree of the whole partition
hierarchy
*/
bool
KDiskDeviceJob::IsPartitionNotBusy(KPartition* partition)
{
if( !partition ) {
return false;
}
struct IsNotBusyVisitor : KPartitionVisitor {
virtual bool VisitPre(KPartition* partition)
{
return !(partition->IsBusy() || partition->IsDescendantBusy());
}
};
IsNotBusyVisitor notBusyVisitor;
return partition->VisitEachDescendant(&notBusyVisitor);
}
@@ -1,154 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#include <util/kernel_cpp.h>
#include "KDiskDeviceJob.h"
#include "KDiskDeviceJobFactory.h"
#include "KCreateChildJob.h"
#include "KDefragmentJob.h"
#include "KDeleteChildJob.h"
#include "KInitializeJob.h"
#include "KMoveJob.h"
#include "KRepairJob.h"
#include "KResizeJob.h"
#include "KScanPartitionJob.h"
#include "KSetNameJob.h"
#include "KSetParametersJob.h"
#include "KSetTypeJob.h"
#include "KUninitializeJob.h"
using namespace std;
KDiskDeviceJobFactory::KDiskDeviceJobFactory()
{
}
KDiskDeviceJobFactory::~KDiskDeviceJobFactory()
{
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateDefragmentJob(partition_id partitionID)
{
return new(nothrow) KDefragmentJob(partitionID);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateRepairJob(partition_id partitionID,
bool checkOnly)
{
return new(nothrow) KRepairJob(partitionID, checkOnly);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateResizeJob(partition_id parentID,
partition_id partitionID, off_t size)
{
return new(nothrow) KResizeJob(parentID, partitionID, size);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateMoveJob(partition_id parentID,
partition_id partitionID, off_t offset, const partition_id *contentsToMove,
int32 contentsToMoveCount)
{
// TODO: this is wierd, what in hell are contentsToMove etc?
return new(nothrow) KMoveJob(parentID, partitionID, offset);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateSetNameJob(partition_id parentID,
partition_id partitionID, const char *name)
{
return new(nothrow) KSetNameJob(parentID, partitionID, name, 0);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateSetContentNameJob(partition_id partitionID,
const char *name)
{
return new(nothrow) KSetNameJob(0, partitionID, 0, name);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateSetTypeJob(partition_id parentID,
partition_id partitionID, const char *type)
{
return new(nothrow) KSetTypeJob(parentID, partitionID, type);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateSetParametersJob(partition_id parentID,
partition_id partitionID, const char *parameters)
{
return new(nothrow) KSetParametersJob(parentID, partitionID, parameters, 0);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateSetContentParametersJob(partition_id partitionID,
const char *parameters)
{
return new(nothrow) KSetParametersJob(0, partitionID, 0, parameters);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateInitializeJob(partition_id partitionID,
disk_system_id diskSystemID, const char *name, const char *parameters)
{
return new(nothrow) KInitializeJob(partitionID, diskSystemID, name,
parameters);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateUninitializeJob(partition_id partitionID)
{
return new(nothrow) KUninitializeJob(partitionID);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateCreateChildJob(partition_id partitionID,
partition_id childID, off_t offset, off_t size, const char *type,
const char *parameters)
{
return new(nothrow) KCreateChildJob(partitionID, childID, offset, size,
type, parameters);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateDeleteChildJob(partition_id parentID,
partition_id partitionID)
{
return new(nothrow) KDeleteChildJob(parentID, partitionID);
}
KDiskDeviceJob *
KDiskDeviceJobFactory::CreateScanPartitionJob(partition_id partitionID)
{
return new(nothrow) KScanPartitionJob(partitionID);
}
@@ -1,487 +0,0 @@
// KDiskDeviceJobGenerator.cpp
#include "KDiskDevice.h"
#include "KDiskDeviceJob.h"
#include "KDiskDeviceJobFactory.h"
#include "KDiskDeviceJobQueue.h"
#include "KDiskDeviceJobGenerator.h"
#include "KDiskDeviceUtils.h"
#include "KDiskSystem.h"
#include "KShadowPartition.h"
// move_info
struct KDiskDeviceJobGenerator::move_info {
KPartition *partition;
off_t position;
off_t target_position;
off_t size;
};
// constructor
KDiskDeviceJobGenerator::KDiskDeviceJobGenerator(
KDiskDeviceJobFactory *jobFactory, KDiskDevice *device,
KDiskDeviceJobQueue *jobQueue)
: fJobFactory(jobFactory),
fDevice(device),
fJobQueue(jobQueue),
fMoveInfos(NULL),
fMoveInfoCount(0),
fPartitionIDs(NULL),
fPartitionIDCount(0)
{
if (fDevice && !fJobQueue) {
fJobQueue = new(nothrow) KDiskDeviceJobQueue(fDevice);
if (fDevice->ShadowPartition()) {
fMoveInfoCount = max(fDevice->CountDescendants(),
fDevice->ShadowPartition()->CountDescendants());
}
fMoveInfos = new(nothrow) move_info[fMoveInfoCount];
fPartitionIDs = new(nothrow) partition_id[fMoveInfoCount];
}
}
// destructor
KDiskDeviceJobGenerator::~KDiskDeviceJobGenerator()
{
delete[] fMoveInfos;
delete[] fPartitionIDs;
delete fJobQueue;
}
// JobFactory
KDiskDeviceJobFactory *
KDiskDeviceJobGenerator::JobFactory() const
{
return fJobFactory;
}
// Device
KDiskDevice *
KDiskDeviceJobGenerator::Device() const
{
return fDevice;
}
// JobQueue
KDiskDeviceJobQueue *
KDiskDeviceJobGenerator::JobQueue() const
{
return fJobQueue;
}
// DetachJobQueue
KDiskDeviceJobQueue *
KDiskDeviceJobGenerator::DetachJobQueue()
{
KDiskDeviceJobQueue *jobQueue = fJobQueue;
fJobQueue = NULL;
return jobQueue;
}
// GenerateJobs
status_t
KDiskDeviceJobGenerator::GenerateJobs()
{
// check parameters
if (!fJobFactory || !fDevice || !fJobQueue || !fMoveInfos || !fPartitionIDs
|| fJobQueue->Device() != fDevice || !fDevice->ShadowPartition()) {
return B_BAD_VALUE;
}
// 1) Generate jobs for all physical partitions that don't have an
// associated shadow partition, i.e. those that shall be deleted.
// 2) Generate uninitialize jobs for all partition whose initialization
// changes, also those that shall be initialized with a disk system.
// This simplifies moving and resizing.
status_t error = _GenerateCleanupJobs(fDevice);
if (error != B_OK)
return error;
// Generate jobs that move and resize the remaining physical partitions
// to their final position/size.
error = _GeneratePlacementJobs(fDevice);
if (error != B_OK)
return error;
// Generate the remaining jobs in one run: initialization, creation of
// partitions, and changing of name, content name, type, parameters, and
// content parameters.
error = _GenerateRemainingJobs(NULL, fDevice->ShadowPartition());
if (error != B_OK)
return error;
return B_OK;
}
// _AddJob
status_t
KDiskDeviceJobGenerator::_AddJob(KDiskDeviceJob *job)
{
if (!job)
return B_NO_MEMORY;
if (!fJobQueue->AddJob(job)) {
delete job;
return B_NO_MEMORY;
}
return B_OK;
}
// _GenerateCleanupJobs
status_t
KDiskDeviceJobGenerator::_GenerateCleanupJobs(KPartition *partition)
{
// TODO: Depending on how this shall be handled, we might want to unmount
// all descendants of a partition to be uninitialized or removed.
if (KPartition *shadow = partition->ShadowPartition()) {
if (shadow->ChangeFlags() & B_PARTITION_CHANGED_INITIALIZATION) {
// partition changes initialization
status_t error = _AddJob(fJobFactory->CreateUninitializeJob(
partition->ID()));
if (error != B_OK)
return error;
} else {
// recurse
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) {
status_t error = _GenerateCleanupJobs(child);
if (error != B_OK)
return error;
}
}
} else if (KPartition *parent = partition->Parent()) {
// create job and add it to the queue
status_t error = _AddJob(fJobFactory->CreateDeleteChildJob(
parent->ID(), partition->ID()));
if (error != B_OK)
return error;
}
return B_OK;
}
// _GeneratePlacementJobs
status_t
KDiskDeviceJobGenerator::_GeneratePlacementJobs(KPartition *partition)
{
if (KPartition *shadow = partition->ShadowPartition()) {
// Don't resize/move partitions that have an unrecognized contents.
// They must have been uninitialized before.
if (shadow->Status() == B_PARTITION_UNRECOGNIZED
&& (shadow->Size() != partition->Size()
|| shadow->Offset() != partition->Offset())) {
return B_ERROR;
}
if (shadow->Size() > partition->Size()) {
// size grows: resize first
status_t error = _GenerateResizeJob(partition);
if (error != B_OK)
return error;
}
// place the children
status_t error = _GenerateChildPlacementJobs(partition);
if (error != B_OK)
return error;
if (shadow->Size() < partition->Size()) {
// size shrinks: resize now
status_t error = _GenerateResizeJob(partition);
if (error != B_OK)
return error;
}
}
return B_OK;
}
// _GenerateResizeJob
status_t
KDiskDeviceJobGenerator::_GenerateResizeJob(KPartition *partition)
{
KPartition *shadow = partition->ShadowPartition();
if (!shadow)
return B_BAD_VALUE;
if (!partition->Parent())
return B_ERROR;
return _AddJob(fJobFactory->CreateResizeJob(partition->Parent()->ID(),
partition->ID(),
shadow->Size()));
}
// _GenerateChildPlacementJobs
status_t
KDiskDeviceJobGenerator::_GenerateChildPlacementJobs(KPartition *partition)
{
KPartition *shadow = partition->ShadowPartition();
// nothing to do, if the partition contains no partitioning system or
// shall be re-initialized
if (!shadow->DiskSystem()
|| (shadow->ChangeFlags() & B_PARTITION_CHANGED_INITIALIZATION)) {
return B_OK;
}
// first resize all children that shall shrink and place their descendants
int32 childCount = 0;
int32 moveForth = 0;
int32 moveBack = 0;
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) {
if (KPartition *childShadow = child->ShadowPartition()) {
// add a move_info for the child
move_info &info = fMoveInfos[childCount];
childCount++;
info.partition = child;
info.position = child->Offset();
info.target_position = childShadow->Offset();
info.size = child->Size();
if (info.position < info.target_position)
moveForth++;
else if (info.position > info.target_position)
moveBack++;
// resize the child, if it shall shrink
if (childShadow->Size() < child->Size()) {
status_t error = _GeneratePlacementJobs(child);
if (error != B_OK)
return error;
info.size = childShadow->Size();
}
}
}
// sort the move infos
if (childCount > 0 && moveForth + moveBack > 0) {
qsort(fMoveInfos, childCount, sizeof(move_info),
_CompareMoveInfoPosition);
}
// move the children to their final positions
while (moveForth + moveBack > 0) {
int32 moved = 0;
if (moveForth < moveBack) {
// move children back
for (int32 i = 0; i < childCount; i++) {
move_info &info = fMoveInfos[i];
if (info.position > info.target_position) {
if (i == 0
|| info.target_position >= fMoveInfos[i - 1].position
+ fMoveInfos[i - 1].size) {
// check OK -- the partition wouldn't be moved before
// the end of the preceding one
status_t error = _GenerateMoveJob(info.partition);
if (error != B_OK)
return error;
info.position = info.target_position;
moved++;
moveBack--;
}
}
}
} else {
// move children forth
for (int32 i = childCount - 1; i >= 0; i--) {
move_info &info = fMoveInfos[i];
if (info.position > info.target_position) {
if (i == childCount - 1
|| info.target_position + info.size
<= fMoveInfos[i - 1].position) {
// check OK -- the partition wouldn't be moved before
// the end of the preceding one
status_t error = _GenerateMoveJob(info.partition);
if (error != B_OK)
return error;
info.position = info.target_position;
moved++;
moveForth--;
}
}
}
}
// terminate, if no partition could be moved
if (moved == 0)
return B_ERROR;
}
// now resize all children that shall grow/keep their size and place
// their descendants
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) {
if (KPartition *childShadow = child->ShadowPartition()) {
if (childShadow->Size() >= child->Size()) {
status_t error = _GeneratePlacementJobs(child);
if (error != B_OK)
return error;
}
}
}
return B_OK;
}
// _GenerateMoveJob
status_t
KDiskDeviceJobGenerator::_GenerateMoveJob(KPartition *partition)
{
KPartition *shadow = partition->ShadowPartition();
if (!shadow)
return B_BAD_VALUE;
if (!partition->Parent())
return B_ERROR;
// collect all descendants whose contents need to be moved
fPartitionIDCount = 0;;
status_t error = _CollectContentsToMove(partition);
if (error != B_OK)
return B_OK;
// add the job
return _AddJob(fJobFactory->CreateMoveJob(partition->Parent()->ID(),
partition->ID(),
shadow->Offset(), fPartitionIDs,
fPartitionIDCount));
}
// _CollectContentsToMove
status_t
KDiskDeviceJobGenerator::_CollectContentsToMove(KPartition *partition)
{
KPartition *shadow = partition->ShadowPartition();
if (!shadow)
return B_OK;
if (shadow->Status() == B_PARTITION_UNRECOGNIZED)
return B_ERROR;
// if the partition has contents, push its ID
if (shadow->DiskSystem()
&& !(shadow->ChangeFlags() & B_PARTITION_CHANGED_INITIALIZATION)) {
_PushPartitionID(partition->ID());
}
// recurse
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) {
status_t error = _CollectContentsToMove(child);
if (error != B_OK)
return error;
}
return B_OK;
}
// _GenerateRemainingJobs
status_t
KDiskDeviceJobGenerator::_GenerateRemainingJobs(KShadowPartition *parent,
KShadowPartition *partition)
{
KPhysicalPartition *physicalPartition = partition->PhysicalPartition();
// get correct ID of partition and parent partition
partition_id partitionID = (physicalPartition ? physicalPartition->ID()
: partition->ID());
partition_id parentID = -1;
if (parent) {
parentID = (parent->PhysicalPartition()
? parent->PhysicalPartition()->ID() : parent->ID());
}
// create the partition, if not existing yet
if (!physicalPartition) {
if (!parent)
return B_BAD_VALUE;
status_t error = _AddJob(fJobFactory->CreateCreateChildJob(
parentID, partitionID, partition->Offset(), partition->Size(),
partition->Type(), partition->Parameters()));
if (error != B_OK)
return error;
} else {
// partition already exists: set non-content properties
// name
if ((partition->ChangeFlags() & B_PARTITION_CHANGED_NAME)
|| compare_string(partition->Name(), physicalPartition->Name())) {
if (!parent)
return B_BAD_VALUE;
status_t error = _AddJob(fJobFactory->CreateSetNameJob(
parentID, partitionID, partition->Name()));
if (error != B_OK)
return error;
}
// type
if ((partition->ChangeFlags() & B_PARTITION_CHANGED_TYPE)
|| compare_string(partition->Type(), physicalPartition->Type())) {
if (!parent)
return B_BAD_VALUE;
status_t error = _AddJob(fJobFactory->CreateSetTypeJob(
parentID, partitionID, partition->Type()));
if (error != B_OK)
return error;
}
// parameters
if ((partition->ChangeFlags() & B_PARTITION_CHANGED_PARAMETERS)
|| compare_string(partition->Parameters(),
physicalPartition->Parameters())) {
if (!parent)
return B_BAD_VALUE;
status_t error = _AddJob(fJobFactory->CreateSetParametersJob(
parentID, partitionID, partition->Parameters()));
if (error != B_OK)
return error;
}
}
if (partition->DiskSystem()) {
// initialize the partition, if required
if (partition->ChangeFlags() & B_PARTITION_CHANGED_INITIALIZATION) {
status_t error = _AddJob(fJobFactory->CreateInitializeJob(
partitionID, partition->DiskSystem()->ID(),
partition->ContentName(), partition->ContentParameters()));
if (error != B_OK)
return error;
} else {
// partition not (re-)initialized, set content properties
// content name
if ((partition->ChangeFlags() & B_PARTITION_CHANGED_NAME)
|| compare_string(partition->ContentName(),
physicalPartition->ContentName())) {
status_t error = _AddJob(fJobFactory->CreateSetContentNameJob(
partitionID, partition->ContentName()));
if (error != B_OK)
return error;
}
// content parameters
if ((partition->ChangeFlags() & B_PARTITION_CHANGED_PARAMETERS)
|| compare_string(partition->ContentParameters(),
physicalPartition->ContentParameters())) {
status_t error = _AddJob(
fJobFactory->CreateSetContentParametersJob(
partitionID, partition->ContentParameters()));
if (error != B_OK)
return error;
}
// defragment
if (partition->ChangeFlags()
& B_PARTITION_CHANGED_DEFRAGMENTATION) {
status_t error = _AddJob(fJobFactory->CreateDefragmentJob(
partitionID));
if (error != B_OK)
return error;
}
// check / repair
bool repair = (partition->ChangeFlags()
& B_PARTITION_CHANGED_REPAIR);
if ((partition->ChangeFlags() & B_PARTITION_CHANGED_CHECK)
|| repair) {
status_t error = _AddJob(fJobFactory->CreateRepairJob(
partitionID, repair));
if (error != B_OK)
return error;
}
}
}
// recurse
for (int32 i = 0; KPartition *_child = partition->ChildAt(i); i++) {
// ToDo: was:
// KShadowPartition *child = dynamic_cast<KShadowPartition *>(_child);
KShadowPartition *child = static_cast<KShadowPartition *>(_child);
if (!child)
return B_BAD_VALUE;
status_t error = _GenerateRemainingJobs(partition, child);
if (error != B_OK)
return error;
}
return B_OK;
}
// _PushPartitionID
void
KDiskDeviceJobGenerator::_PushPartitionID(partition_id id)
{
fPartitionIDs[fPartitionIDCount++] = id;
}
// _CompareMoveInfoOffset
int
KDiskDeviceJobGenerator::_CompareMoveInfoPosition(const void *_a,
const void *_b)
{
const move_info *a = static_cast<const move_info *>(_a);
const move_info *b = static_cast<const move_info *>(_b);
if (a->position < b->position)
return -1;
if (a->position > b->position)
return 1;
return 0;
}
@@ -1,65 +0,0 @@
// KDiskDeviceJobGenerator.h
#ifndef _K_DISK_DEVICE_JOB_GENERATOR_H
#define _K_DISK_DEVICE_JOB_GENERATOR_H
#include "disk_device_manager.h"
namespace BPrivate {
namespace DiskDevice {
class KDiskDevice;
class KDiskDeviceJob;
class KDiskDeviceJobFactory;
class KDiskDeviceJobQueue;
class KPartition;
class KPhysicalPartition;
class KShadowPartition;
class KDiskDeviceJobGenerator {
public:
KDiskDeviceJobGenerator(KDiskDeviceJobFactory *jobFactory,
KDiskDevice *device,
KDiskDeviceJobQueue *jobQueue = NULL);
~KDiskDeviceJobGenerator();
KDiskDeviceJobFactory *JobFactory() const;
KDiskDevice *Device() const;
KDiskDeviceJobQueue *JobQueue() const;
KDiskDeviceJobQueue *DetachJobQueue();
status_t GenerateJobs();
private:
struct move_info;
status_t _AddJob(KDiskDeviceJob *job);
status_t _GenerateCleanupJobs(KPartition *partition);
status_t _GeneratePlacementJobs(KPartition *partition);
status_t _GenerateResizeJob(KPartition *partition);
status_t _GenerateChildPlacementJobs(KPartition *partition);
status_t _GenerateMoveJob(KPartition *partition);
status_t _CollectContentsToMove(KPartition *partition);
status_t _GenerateRemainingJobs(KShadowPartition *parent,
KShadowPartition *partition);
void _PushPartitionID(partition_id id);
static int _CompareMoveInfoPosition(const void *_a, const void *_b);
KDiskDeviceJobFactory *fJobFactory;
KDiskDevice *fDevice;
KDiskDeviceJobQueue *fJobQueue;
move_info *fMoveInfos;
int32 fMoveInfoCount;
partition_id *fPartitionIDs;
int32 fPartitionIDCount;
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KDiskDeviceJobGenerator;
#endif // _K_DISK_DEVICE_JOB_GENERATOR_H
@@ -1,361 +0,0 @@
// KDiskDeviceJobQueue.cpp
#include <stdio.h>
#include <string.h>
#include <Vector.h>
#include <KernelExport.h>
#include <util/kernel_cpp.h>
#include "KDiskDevice.h"
#include "KDiskDeviceJob.h"
#include "KDiskDeviceJobQueue.h"
#include "KDiskDeviceManager.h"
#include "KDiskDeviceUtils.h"
// debugging
//#define DBG(x)
#define DBG(x) x
#define OUT dprintf
using namespace std;
// flags
enum {
JOB_QUEUE_EXECUTING = 0x01,
JOB_QUEUE_CANCELED = 0x02,
JOB_QUEUE_REVERSE = 0x04,
JOB_QUEUE_PAUSED = 0x08,
JOB_QUEUE_PAUSE_REQUESTED = 0x10,
};
struct KDiskDeviceJobQueue::JobQueue : Vector<KDiskDeviceJob*> {};
// constructor
KDiskDeviceJobQueue::KDiskDeviceJobQueue(KDiskDevice *device)
: fDevice(NULL),
fActiveJob(0),
fJobs(NULL),
fFlags(0),
fThread(-1),
fSyncSemaphore(-1)
{
fJobs = new(nothrow) JobQueue;
SetDevice(device);
}
// destructor
KDiskDeviceJobQueue::~KDiskDeviceJobQueue()
{
// Delete the semaphore. This awakes our thread in case it is paused --
// that shouldn't happen, though.
if (fSyncSemaphore >= 0)
delete_sem(fSyncSemaphore);
// The thread should not run or is just deleting us via the manager
// method DeleteJobQueue(). At any rate, fThread should be unset.
if (fThread >= 0) {
// something's weird
DBG(OUT("WARNING: KDiskDeviceJobQueue::~KDiskDeviceJobQueue(): jobber "
" thread is still running!\n"));
}
// delete the jobs and the queue
if (fJobs) {
int32 count = fJobs->Count();
for (int32 i = 0; i < count; i++)
delete fJobs->ElementAt(i);
delete fJobs;
}
// unset the device
SetDevice(NULL);
}
// InitCheck
status_t
KDiskDeviceJobQueue::InitCheck() const
{
return (fJobs ? B_OK : B_NO_MEMORY);
}
// SetDevice
void
KDiskDeviceJobQueue::SetDevice(KDiskDevice *device)
{
// unset the old device
if (fDevice) {
fDevice->Unregister();
fDevice = NULL;
}
// set the new one
if (device) {
fDevice = device;
fDevice->Register();
}
}
// Device
BPrivate::DiskDevice::KDiskDevice *
KDiskDeviceJobQueue::Device() const
{
return fDevice;
}
// ActiveJobIndex
int32
KDiskDeviceJobQueue::ActiveJobIndex() const
{
return fActiveJob;
}
// ActiveJob
KDiskDeviceJob *
KDiskDeviceJobQueue::ActiveJob() const
{
return JobAt(fActiveJob);
}
// AddJob
bool
KDiskDeviceJobQueue::AddJob(KDiskDeviceJob *job)
{
if (InitCheck() != B_OK || IsExecuting() || !job || job->JobQueue())
return false;
status_t error = fJobs->PushBack(job);
if (error == B_OK)
job->SetJobQueue(this);
return (error == B_OK);
}
// RemoveJob
KDiskDeviceJob *
KDiskDeviceJobQueue::RemoveJob(int32 index)
{
if (InitCheck() != B_OK || IsExecuting() || index < 0
|| index >= fJobs->Count()) {
return NULL;
}
KDiskDeviceJob *job = fJobs->ElementAt(index);
fJobs->Erase(index);
job->SetJobQueue(NULL);
return job;
}
// RemoveJob
bool
KDiskDeviceJobQueue::RemoveJob(KDiskDeviceJob *job)
{
if (InitCheck() != B_OK || IsExecuting() || !job
|| job->JobQueue() != this) {
return false;
}
return RemoveJob(fJobs->IndexOf(job));
}
// JobAt
KDiskDeviceJob *
KDiskDeviceJobQueue::JobAt(int32 index) const
{
if (InitCheck() != B_OK || index < 0 || index >= fJobs->Count())
return NULL;
return fJobs->ElementAt(index);
}
// CountJobs
int32
KDiskDeviceJobQueue::CountJobs() const
{
if (InitCheck() != B_OK)
return 0;
return fJobs->Count();
}
// Execute
status_t
KDiskDeviceJobQueue::Execute()
{
if (InitCheck() != B_OK)
return InitCheck();
if (IsExecuting())
return B_BAD_VALUE;
// create a synchronization semaphore
fSyncSemaphore = create_sem(0, "disk device job queue sync");
if (fSyncSemaphore < 0)
return fSyncSemaphore;
// spawn a thread and run it
fThread = spawn_kernel_thread(_ThreadEntry, "disk device jobber",
B_NORMAL_PRIORITY, this);
if (fThread < 0) {
delete_sem(fSyncSemaphore);
fSyncSemaphore = -1;
return fThread;
}
fFlags |= JOB_QUEUE_EXECUTING;
resume_thread(fThread);
return B_OK;
}
// Cancel
status_t
KDiskDeviceJobQueue::Cancel(bool reverse)
{
if (InitCheck() != B_OK)
return InitCheck();
if (!IsExecuting() || IsCanceled())
return B_BAD_VALUE;
KDiskDeviceJob *job = ActiveJob();
if (!job)
return B_ERROR;
// check, if the active job allows canceling
if (!(job->InterruptProperties() & B_DISK_DEVICE_JOB_CAN_CANCEL))
return B_BAD_VALUE;
if (reverse && !(job->InterruptProperties()
& B_DISK_DEVICE_JOB_REVERSE_ON_CANCEL)) {
return B_BAD_VALUE;
}
// update the flags
fFlags |= JOB_QUEUE_CANCELED;
if (reverse)
fFlags |= JOB_QUEUE_REVERSE;
// let the thread continue, if paused
if (IsPaused() || IsPauseRequested())
Continue();
return B_OK;
}
// Pause
status_t
KDiskDeviceJobQueue::Pause()
{
if (InitCheck() != B_OK)
return InitCheck();
if (!IsExecuting() || IsCanceled() || IsPaused() || IsPauseRequested())
return B_BAD_VALUE;
fFlags |= JOB_QUEUE_PAUSE_REQUESTED;
return B_OK;
}
// Continue
status_t
KDiskDeviceJobQueue::Continue()
{
if (InitCheck() != B_OK)
return InitCheck();
if (!IsExecuting() || !(IsPaused() || IsPauseRequested()))
return B_BAD_VALUE;
if (IsPaused()) {
fFlags &= ~(uint32)JOB_QUEUE_PAUSED;
release_sem(fSyncSemaphore);
} else
fFlags &= ~(uint32)JOB_QUEUE_PAUSE_REQUESTED;
return B_OK;
}
// ReadyToPause
sem_id
KDiskDeviceJobQueue::ReadyToPause()
{
if (InitCheck() != B_OK)
return InitCheck();
if (!IsExecuting() || !IsPauseRequested())
return B_BAD_VALUE;
fFlags &= ~(uint32)JOB_QUEUE_PAUSE_REQUESTED;
fFlags |= JOB_QUEUE_PAUSED;
return fSyncSemaphore;
}
// IsExecuting
bool
KDiskDeviceJobQueue::IsExecuting() const
{
return (fFlags & JOB_QUEUE_EXECUTING);
}
// IsCanceled
bool
KDiskDeviceJobQueue::IsCanceled() const
{
return (fFlags & JOB_QUEUE_CANCELED);
}
// ShallReverse
bool
KDiskDeviceJobQueue::ShallReverse() const
{
return (fFlags & JOB_QUEUE_REVERSE);
}
// IsPaused
bool
KDiskDeviceJobQueue::IsPaused() const
{
return (fFlags & JOB_QUEUE_PAUSED);
}
// IsPauseRequested
bool
KDiskDeviceJobQueue::IsPauseRequested() const
{
return (fFlags & JOB_QUEUE_PAUSE_REQUESTED);
}
// _ThreadLoop
int32
KDiskDeviceJobQueue::_ThreadLoop()
{
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
// main loop: process all jobs
bool failed = false;
while (KDiskDeviceJob *activeJob = ActiveJob()) {
manager->UpdateJobStatus(activeJob, B_DISK_DEVICE_JOB_IN_PROGRESS,
true);
status_t error = activeJob->Do();
if (error == B_OK) {
if (ManagerLocker locker = manager) {
// if canceled, simply bail out -- this and all succeeding
// jobs will be canceled
if (IsCanceled())
break;
// if pause was requested ignore the request
if (IsPauseRequested())
Continue();
// go to the next job
fActiveJob++;
} else
break;
// mark the job succeeded
manager->UpdateJobStatus(activeJob, B_DISK_DEVICE_JOB_SUCCEEDED,
true);
} else {
DBG(OUT("job failed: %s\n", strerror(error)));
DBG(OUT(" message: %s\n", activeJob->ErrorMessage()));
// job failed: this and all succeeding jobs will be marked failed
failed = true;
break;
}
}
// All jobs that remain need to be marked failed or canceled.
bool updatePartitions = false;
for (int32 i = fActiveJob; KDiskDeviceJob *job = JobAt(i); i++) {
manager->UpdateJobStatus(job, (failed ? B_DISK_DEVICE_JOB_FAILED
: B_DISK_DEVICE_JOB_CANCELED),
false);
updatePartitions = true;
}
if (updatePartitions)
manager->UpdateBusyPartitions(Device());
// tell the manager, that we are done.
if (ManagerLocker locker = manager) {
fFlags &= ~(uint32)JOB_QUEUE_EXECUTING;
fThread = -1;
manager->DeleteJobQueue(this);
}
return 0;
}
// _ThreadEntry
int32
KDiskDeviceJobQueue::_ThreadEntry(void *data)
{
return static_cast<KDiskDeviceJobQueue*>(data)->_ThreadLoop();
}
@@ -7,9 +7,6 @@
#include "KDiskDevice.h"
#include "KDiskDeviceJob.h"
#include "KDiskDeviceJobFactory.h"
#include "KDiskDeviceJobQueue.h"
#include "KDiskDeviceManager.h"
#include "KDiskDeviceUtils.h"
#include "KDiskSystem.h"
@@ -66,13 +63,6 @@ struct GetDiskSystemID {
}
};
// GetJobID
struct GetJobID {
inline disk_job_id operator()(const KDiskDeviceJob *job) const
{
return job->ID();
}
};
// PartitionMap
struct KDiskDeviceManager::PartitionMap : VectorMap<partition_id, KPartition*,
@@ -97,15 +87,6 @@ struct KDiskDeviceManager::DiskSystemMap : VectorMap<disk_system_id,
struct KDiskDeviceManager::PartitionSet : VectorSet<KPartition*> {
};
// JobMap
struct KDiskDeviceManager::JobMap : VectorMap<disk_job_id, KDiskDeviceJob*,
VectorMapEntryStrategy::ImplicitKey<disk_job_id, KDiskDeviceJob*,
GetJobID> > {
};
// JobQueueVector
struct KDiskDeviceManager::JobQueueVector : Vector<KDiskDeviceJobQueue*> {};
static bool
is_active_job_status(uint32 status)
@@ -123,10 +104,7 @@ KDiskDeviceManager::KDiskDeviceManager()
fDevices(new(nothrow) DeviceMap),
fPartitions(new(nothrow) PartitionMap),
fDiskSystems(new(nothrow) DiskSystemMap),
fObsoletePartitions(new(nothrow) PartitionSet),
fJobs(new(nothrow) JobMap),
fJobQueues(new(nothrow) JobQueueVector),
fJobFactory(new(nothrow) KDiskDeviceJobFactory)
fObsoletePartitions(new(nothrow) PartitionSet)
{
if (InitCheck() != B_OK)
return;
@@ -184,19 +162,15 @@ KDiskDeviceManager::~KDiskDeviceManager()
delete fDevices;
delete fDiskSystems;
delete fObsoletePartitions;
delete fJobs;
delete fJobQueues;
delete fJobFactory;
}
// InitCheck
status_t
KDiskDeviceManager::InitCheck() const
{
if (!fPartitions || !fDevices || !fDiskSystems || !fObsoletePartitions
|| !fJobs || !fJobQueues || !fJobFactory) {
if (!fPartitions || !fDevices || !fDiskSystems || !fObsoletePartitions)
return B_NO_MEMORY;
}
return (fLock.Sem() >= 0 ? B_OK : fLock.Sem());
}
@@ -496,15 +470,15 @@ KDiskDeviceManager::WriteLockPartition(partition_id id)
// ScanPartition
status_t
KDiskDeviceManager::ScanPartition(KPartition* partition, bool async)
KDiskDeviceManager::ScanPartition(KPartition* partition)
{
// TODO: This won't do. Locking the DDM while scanning the partition is not a
// good idea. Even locking the device doesn't feels right. Marking the partition
// good idea. Even locking the device doesn't feel right. Marking the partition
// busy and passing the disk system a temporary clone of the partition_data
// should work as well.
if (DeviceWriteLocker deviceLocker = partition->Device()) {
if (ManagerLocker locker = this)
return _ScanPartition(partition, async);
return _ScanPartition(partition, false);
}
return B_ERROR;
@@ -513,8 +487,7 @@ KDiskDeviceManager::ScanPartition(KPartition* partition, bool async)
// CreateFileDevice
partition_id
KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated,
bool async)
KDiskDeviceManager::CreateFileDevice(const char *filePath, bool* newlyCreated)
{
if (!filePath)
return B_BAD_VALUE;
@@ -532,6 +505,7 @@ KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated,
if ((device = FindFileDevice(filePath))) {
if (newlyCreated)
*newlyCreated = false;
return device->ID();
}
@@ -553,10 +527,11 @@ KDiskDeviceManager::CreateFileDevice(const char *filePath, bool *newlyCreated,
// scan device
if (error == B_OK) {
_ScanPartition(device, async);
_ScanPartition(device, false);
if (newlyCreated)
*newlyCreated = true;
return device->ID();
}
@@ -655,160 +630,6 @@ KDiskDeviceManager::DeletePartition(KPartition *partition)
return false;
}
// FindJob
KDiskDeviceJob *
KDiskDeviceManager::FindJob(disk_job_id id)
{
JobMap::Iterator it = fJobs->Find(id);
if (it == fJobs->End())
return NULL;
return it->Value();
}
// CountJobs
int32
KDiskDeviceManager::CountJobs()
{
return fJobs->Count();
}
// NextJob
KDiskDeviceJob *
KDiskDeviceManager::NextJob(int32 *cookie)
{
if (!cookie)
return NULL;
JobMap::Iterator it = fJobs->FindClose(*cookie, false);
if (it != fJobs->End()) {
KDiskDeviceJob *job = it->Value();
*cookie = job->ID() + 1;
return job;
}
return NULL;
}
// AddJobQueue
/*!
The device must be write locked, the manager must be locked.
*/
status_t
KDiskDeviceManager::AddJobQueue(KDiskDeviceJobQueue *jobQueue)
{
// check the parameter
if (!jobQueue)
return B_BAD_VALUE;
if (jobQueue->InitCheck() != B_OK)
return jobQueue->InitCheck();
// add the queue
status_t error = fJobQueues->PushBack(jobQueue);
if (error != B_OK)
return error;
// add the queue's jobs
int32 count = jobQueue->CountJobs();
for (int32 i = 0; i < count; i++) {
KDiskDeviceJob *job = jobQueue->JobAt(i);
error = fJobs->Put(job->ID(), job);
if (error != B_OK) {
_RemoveJobQueue(jobQueue);
return error;
}
}
// mark the jobs scheduled
for (int32 i = 0; KDiskDeviceJob *job = jobQueue->JobAt(i); i++)
_UpdateJobStatus(job, B_DISK_DEVICE_JOB_SCHEDULED, false);
_UpdateBusyPartitions(jobQueue->Device());
// start the execution of the queue
error = jobQueue->Execute();
if (error != B_OK) {
// resuming the execution failed -- mark all jobs failed and
// remove the queue
for (int32 i = 0; KDiskDeviceJob *job = jobQueue->JobAt(i); i++)
_UpdateJobStatus(job, B_DISK_DEVICE_JOB_FAILED, false);
_RemoveJobQueue(jobQueue);
_UpdateBusyPartitions(jobQueue->Device());
}
return error;
}
// RemoveJobQueue
status_t
KDiskDeviceManager::RemoveJobQueue(KDiskDeviceJobQueue *jobQueue)
{
if (!jobQueue)
return B_BAD_VALUE;
if (jobQueue->InitCheck() != B_OK)
return jobQueue->InitCheck();
if (jobQueue->IsExecuting())
return B_BAD_VALUE;
return (_RemoveJobQueue(jobQueue)
? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND);
}
// DeleteJobQueue
status_t
KDiskDeviceManager::DeleteJobQueue(KDiskDeviceJobQueue *jobQueue)
{
status_t error = RemoveJobQueue(jobQueue);
if (error == B_OK)
delete jobQueue;
return error;
}
// CountJobQueues
int32
KDiskDeviceManager::CountJobQueues()
{
return fJobQueues->Count();
}
// NextJobQueue
KDiskDeviceJobQueue *
KDiskDeviceManager::NextJobQueue(int32 *cookie)
{
if (!cookie || *cookie < 0 || *cookie >= CountJobQueues())
return NULL;
return fJobQueues->ElementAt((*cookie)++);
}
// JobFactory
KDiskDeviceJobFactory *
KDiskDeviceManager::JobFactory() const
{
return fJobFactory;
}
// UpdateBusyPartitions
status_t
KDiskDeviceManager::UpdateBusyPartitions(KDiskDevice *device)
{
if (!device)
return B_BAD_VALUE;
if (DeviceWriteLocker deviceLocker = device) {
if (ManagerLocker locker = this)
return _UpdateBusyPartitions(device);
}
return B_ERROR;
}
// UpdateJobStatus
status_t
KDiskDeviceManager::UpdateJobStatus(KDiskDeviceJob *job, uint32 status,
bool updateBusyPartitions)
{
// check parameters
if (!job)
return B_BAD_VALUE;
KDiskDeviceJobQueue *jobQueue = job->JobQueue();
KDiskDevice *device = (jobQueue ? jobQueue->Device() : NULL);
if (!device)
return B_BAD_VALUE;
// lock device and manager
if (DeviceWriteLocker deviceLocker = device) {
if (ManagerLocker locker = this)
return _UpdateJobStatus(job, status, updateBusyPartitions);
}
return B_ERROR;
}
// FindDiskSystem
KDiskSystem *
@@ -1038,26 +859,8 @@ KDiskDeviceManager::_RemoveDevice(KDiskDevice *device)
&& PartitionRemoved(device));
}
// _RemoveJobQueue
bool
KDiskDeviceManager::_RemoveJobQueue(KDiskDeviceJobQueue *jobQueue)
{
if (!jobQueue)
return false;
// find the job queue
JobQueueVector::Iterator it = fJobQueues->Find(jobQueue);
if (it == fJobQueues->End())
return false;
// remove the queue's jobs
int32 count = jobQueue->CountJobs();
for (int32 i = 0; i < count; i++) {
KDiskDeviceJob *job = jobQueue->JobAt(i);
fJobs->Remove(job->ID());
}
fJobQueues->Erase(it);
return true;
}
#if 0
// _UpdateBusyPartitions
/*!
The device must be write locked, the manager must be locked.
@@ -1119,32 +922,8 @@ KDiskDeviceManager::_UpdateBusyPartitions(KDiskDevice *device)
device->VisitEachDescendant(&visitor2);
return B_OK;
}
#endif
// _UpdateJobStatus
status_t
KDiskDeviceManager::_UpdateJobStatus(KDiskDeviceJob *job, uint32 status,
bool updateBusyPartitions)
{
// check parameters
if (!job)
return B_BAD_VALUE;
KDiskDeviceJobQueue *jobQueue = job->JobQueue();
KDiskDevice *device = (jobQueue ? jobQueue->Device() : NULL);
if (!device)
return B_BAD_VALUE;
if (job->Status() == status)
return B_OK;
// check migration of a schedule/in progress to a terminal state
// or vice versa
updateBusyPartitions &= (is_active_job_status(job->Status())
!= is_active_job_status(status));
// set new state and update the partitions' busy flags
job->SetStatus(status);
if (updateBusyPartitions)
return _UpdateBusyPartitions(device);
// TODO: notifications
return B_OK;
}
// _Scan
status_t
@@ -1210,42 +989,148 @@ DBG(OUT(" found device: %s\n", path));
status_t
KDiskDeviceManager::_ScanPartition(KPartition *partition, bool async)
{
// TODO: There's no reason why the manager needs to be locked anymore.
if (!partition)
return B_BAD_VALUE;
// TODO: Reimplement asynchronous scanning, if we really need it.
#if 0
if (async) {
// create a new job queue for the device
KDiskDeviceJobQueue *jobQueue = new(nothrow) KDiskDeviceJobQueue;
if (!jobQueue)
return B_NO_MEMORY;
jobQueue->SetDevice(partition->Device());
// create a job for scanning the device and add it to the job queue
KDiskDeviceJob *job = fJobFactory->CreateScanPartitionJob(partition->ID());
if (!job) {
delete jobQueue;
return B_NO_MEMORY;
}
if (!jobQueue->AddJob(job)) {
delete jobQueue;
delete job;
return B_NO_MEMORY;
}
// add the job queue
status_t error = AddJobQueue(jobQueue);
if (error != B_OK)
delete jobQueue;
return error;
}
#endif
KDiskDeviceJob *job = fJobFactory->CreateScanPartitionJob(partition->ID());
if (job == NULL)
return B_NO_MEMORY;
// scan synchronously
status_t status = job->Do();
UpdateBusyPartitions(partition->Device());
if (!partition->Device()->HasMedia())
return B_OK;
delete job;
return status;
status_t error = _ScanPartition(partition);
// mark all partitions un-busy
// TODO: This is not quite correct here. Partitions are created marked "busy",
// hence the one creating it should be responsible for clearing the flag, not
// us.
struct UnmarkBusyVisitor : KPartitionVisitor {
virtual bool VisitPre(KPartition* partition)
{
partition->ClearFlags(B_PARTITION_BUSY
| B_PARTITION_DESCENDANT_BUSY);
return false;
}
} visitor;
partition->VisitEachDescendant(&visitor);
return error;
}
status_t
KDiskDeviceManager::_ScanPartition(KPartition *partition)
{
// the partition's device must be write-locked
if (!partition)
return B_BAD_VALUE;
if (partition->DiskSystem() != NULL) {
// TODO: this is more or less a hack to allow rescanning a partition
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++)
_ScanPartition(child);
return B_OK;
}
DBG(
KPath partitionPath;
partition->GetPath(&partitionPath);
OUT("KDiskDeviceManager::_ScanPartition(%s)\n", partitionPath.Path());
)
// publish the partition
status_t error = B_OK;
if (!partition->IsPublished()) {
error = partition->PublishDevice();
if (error != B_OK)
return error;
}
// find the disk system that returns the best priority for this partition
float bestPriority = -1;
KDiskSystem *bestDiskSystem = NULL;
void *bestCookie = NULL;
int32 itCookie = 0;
while (KDiskSystem *diskSystem = LoadNextDiskSystem(&itCookie)) {
DBG(OUT(" trying: %s\n", diskSystem->Name()));
void *cookie = NULL;
float priority = diskSystem->Identify(partition, &cookie);
DBG(OUT(" returned: %ld/1000\n", int32(1000 * priority)));
if (priority >= 0 && priority > bestPriority) {
// new best disk system
if (bestDiskSystem) {
bestDiskSystem->FreeIdentifyCookie(partition, bestCookie);
bestDiskSystem->Unload();
}
bestPriority = priority;
bestDiskSystem = diskSystem;
bestCookie = cookie;
} else {
// disk system doesn't identify the partition or worse than our
// current favorite
if (priority >= 0)
diskSystem->FreeIdentifyCookie(partition, cookie);
diskSystem->Unload();
}
}
// now, if we have found a disk system, let it scan the partition
if (bestDiskSystem) {
DBG(OUT(" scanning with: %s\n", bestDiskSystem->Name()));
error = bestDiskSystem->Scan(partition, bestCookie);
bestDiskSystem->FreeIdentifyCookie(partition, bestCookie);
if (error == B_OK) {
partition->SetDiskSystem(bestDiskSystem);
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++)
_ScanPartition(child);
} else {
// TODO: Handle the error.
DBG(OUT(" scanning failed: %s\n", strerror(error)));
}
// now we can safely unload the disk system -- it has been loaded by
// the partition(s) and thus will not really be unloaded
bestDiskSystem->Unload();
} else {
// contents not recognized
// nothing to be done -- partitions are created as unrecognized
}
return error;
}
@@ -190,195 +190,7 @@ KDiskSystem::FreeContentCookie(KPartition *partition)
}
// GetSupportedOperations
uint32
KDiskSystem::GetSupportedOperations(KPartition* partition, uint32 mask)
{
// to be implemented by derived classes
return 0;
}
// GetSupportedChildOperations
uint32
KDiskSystem::GetSupportedChildOperations(KPartition* child, uint32 mask)
{
// to be implemented by derived classes
return 0;
}
// SupportsInitializingChild
bool
KDiskSystem::SupportsInitializingChild(KPartition *child,
const char *diskSystem)
{
// to be implemented by derived classes
return false;
}
// IsSubSystemFor
bool
KDiskSystem::IsSubSystemFor(KPartition *partition)
{
// to be implemented by derived classes
return false;
}
// ValidateResize
bool
KDiskSystem::ValidateResize(KPartition *partition, off_t *size)
{
// to be implemented by derived classes
return false;
}
// ValidateResizeChild
bool
KDiskSystem::ValidateResizeChild(KPartition *child, off_t *size)
{
// to be implemented by derived classes
return false;
}
// ValidateMove
bool
KDiskSystem::ValidateMove(KPartition *partition, off_t *start)
{
// to be implemented by derived classes
return false;
}
// ValidateMoveChild
bool
KDiskSystem::ValidateMoveChild(KPartition *child, off_t *start)
{
// to be implemented by derived classes
return false;
}
// ValidateSetName
bool
KDiskSystem::ValidateSetName(KPartition *partition, char *name)
{
// to be implemented by derived classes
return false;
}
// ValidateSetContentName
bool
KDiskSystem::ValidateSetContentName(KPartition *partition, char *name)
{
// to be implemented by derived classes
return false;
}
// ValidateSetType
bool
KDiskSystem::ValidateSetType(KPartition *partition, const char *type)
{
// to be implemented by derived classes
return false;
}
// ValidateSetParameters
bool
KDiskSystem::ValidateSetParameters(KPartition *partition,
const char *parameters)
{
// to be implemented by derived classes
return false;
}
// ValidateSetContentParameters
bool
KDiskSystem::ValidateSetContentParameters(KPartition *partition,
const char *parameters)
{
// to be implemented by derived classes
return false;
}
// ValidateInitialize
bool
KDiskSystem::ValidateInitialize(KPartition *partition, char *name,
const char *parameters)
{
// to be implemented by derived classes
return false;
}
// ValidateCreateChild
bool
KDiskSystem::ValidateCreateChild(KPartition *partition, off_t *start,
off_t *size, const char *type,
const char *parameters, int32 *index)
{
// to be implemented by derived classes
return false;
}
// CountPartitionableSpaces
int32
KDiskSystem::CountPartitionableSpaces(KPartition *partition)
{
// to be implemented by derived classes
return 0;
}
// GetPartitionableSpaces
status_t
KDiskSystem::GetPartitionableSpaces(KPartition *partition,
partitionable_space_data *buffer,
int32 count, int32 *actualCount)
{
// to be implemented by derived classes
return B_ERROR;
}
// GetNextSupportedType
status_t
KDiskSystem::GetNextSupportedType(KPartition *partition, int32 *cookie,
char *type)
{
// to be implemented by derived classes
return B_ENTRY_NOT_FOUND;
}
// ShadowPartitionChanged
status_t
KDiskSystem::ShadowPartitionChanged(KPartition *partition, KPartition *child,
uint32 operation)
{
// to be implemented by derived classes
return B_ENTRY_NOT_FOUND;
}
// GetTypeForContentType
status_t
KDiskSystem::GetTypeForContentType(const char *contentType, char *type)
{
// to be implemented by derived classes
return B_ENTRY_NOT_FOUND;
}
#if 0
// Defragment
status_t
@@ -513,6 +325,8 @@ KDiskSystem::DeleteChild(KPartition *child, KDiskDeviceJob *job)
return B_ERROR;
}
#endif // 0
// LoadModule
status_t
@@ -7,7 +7,7 @@
#include <fs_interface.h>
#include "ddm_modules.h"
#include "KDiskDeviceJob.h"
//#include "KDiskDeviceJob.h"
#include "KDiskDeviceUtils.h"
#include "KFileSystem.h"
#include "KPartition.h"
@@ -97,97 +97,7 @@ KFileSystem::FreeContentCookie(KPartition *partition)
}
// GetSupportedOperations
uint32
KFileSystem::GetSupportedOperations(KPartition* partition, uint32 mask)
{
ASSERT(partition != NULL);
// Note, that for initialization, the partition's disk system does not
// need to be this disk system.
if (!fModule)
return 0;
if (!fModule->get_supported_operations)
return (Flags() & mask);
return fModule->get_supported_operations(partition->PartitionData(), mask)
& mask;
}
// ValidateResize
bool
KFileSystem::ValidateResize(KPartition *partition, off_t *size)
{
return (partition && size && partition->DiskSystem() == this && fModule
&& fModule->validate_resize
&& fModule->validate_resize(partition->PartitionData(), size));
}
// ValidateMove
bool
KFileSystem::ValidateMove(KPartition *partition, off_t *start)
{
return (partition && start && partition->DiskSystem() == this && fModule
&& fModule->validate_move
&& fModule->validate_move(partition->PartitionData(), start));
}
// ValidateSetContentName
bool
KFileSystem::ValidateSetContentName(KPartition *partition, char *name)
{
return (partition && name && partition->DiskSystem() == this
&& fModule && fModule->validate_set_content_name
&& fModule->validate_set_content_name(partition->PartitionData(),
name));
}
// ValidateSetContentParameters
bool
KFileSystem::ValidateSetContentParameters(KPartition *partition,
const char *parameters)
{
return (partition && partition->DiskSystem() == this && fModule
&& fModule->validate_set_content_parameters
&& fModule->validate_set_content_parameters(
partition->PartitionData(), parameters));
}
// ValidateInitialize
bool
KFileSystem::ValidateInitialize(KPartition *partition, char *name,
const char *parameters)
{
return (partition && fModule && fModule->validate_initialize
&& fModule->validate_initialize(partition->PartitionData(), name,
parameters));
}
// ShadowPartitionChanged
status_t
KFileSystem::ShadowPartitionChanged(KPartition *partition, KPartition *child,
uint32 operation)
{
if (!partition)
return B_BAD_VALUE;
if (!fModule)
return B_ERROR;
// If not implemented, we assume, that the file system doesn't have to
// make any additional changes.
if (!fModule->shadow_changed)
return B_OK;
return fModule->shadow_changed(partition->PartitionData(),
child ? child->PartitionData() : NULL, operation);
}
#if 0
// Defragment
status_t
@@ -277,6 +187,8 @@ KFileSystem::Initialize(KPartition *partition, const char *name,
return result;
}
#endif // 0
// LoadModule
status_t
@@ -18,7 +18,7 @@
#include <ddm_modules.h>
#include <KDiskDevice.h>
#include <KDiskDeviceJob.h>
//#include <KDiskDeviceJob.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KPartition.h>
@@ -127,301 +127,7 @@ KPartitioningSystem::FreeContentCookie(KPartition *partition)
}
// GetSupportedOperations
uint32
KPartitioningSystem::GetSupportedOperations(KPartition* partition, uint32 mask)
{
ASSERT(partition != NULL);
// Note, that for initialization, the partition's disk system does not
// need to be this disk system.
if (!fModule)
return 0;
if (!fModule->get_supported_operations)
return (Flags() & mask);
return fModule->get_supported_operations(partition->PartitionData(), mask)
& mask;
}
// GetSupportedChildOperations
uint32
KPartitioningSystem::GetSupportedChildOperations(KPartition* child, uint32 mask)
{
ASSERT(child != NULL);
ASSERT(child->Parent() != NULL);
ASSERT(child->Parent()->DiskSystem() == this);
if (!fModule)
return 0;
if (!fModule->get_supported_child_operations)
return (Flags() & mask);
return fModule->get_supported_child_operations(
child->Parent()->PartitionData(), child->PartitionData(), mask)
& mask;
}
// SupportsInitializingChild
/*! Check whether the child partition managed by this partitioning system can
be initialized with the given disk system.
*/
bool
KPartitioningSystem::SupportsInitializingChild(KPartition *child,
const char *diskSystem)
{
if (!child || child->ParentDiskSystem() != this || !diskSystem
|| !fModule)
return false;
// If the hook is not implemented, the parent disk system doesn't want a
// veto.
if (!fModule->supports_initializing_child)
return true;
return fModule->supports_initializing_child(child->PartitionData(),
diskSystem);
}
// IsSubSystemFor
//! Check whether the add-on is a subsystem for a given partition.
bool
KPartitioningSystem::IsSubSystemFor(KPartition *partition)
{
return (partition && fModule && fModule->is_sub_system_for
&& fModule->is_sub_system_for(partition->PartitionData()));
}
// ValidateResize
//! Validates parameters for resizing a partition
bool
KPartitioningSystem::ValidateResize(KPartition *partition, off_t *size)
{
return (partition && size && partition->DiskSystem() == this && fModule
&& fModule->validate_resize
&& fModule->validate_resize(partition->PartitionData(), size));
}
// ValidateResizeChild
//! Validates parameters for resizing a child partition
bool
KPartitioningSystem::ValidateResizeChild(KPartition *child, off_t *size)
{
return (child && size && child->Parent()
&& child->ParentDiskSystem() == this && fModule
&& fModule->validate_resize_child
&& fModule->validate_resize_child(child->Parent()->PartitionData(),
child->PartitionData(), size));
}
// ValidateMove
//! Validates parameters for moving a partition
bool
KPartitioningSystem::ValidateMove(KPartition *partition, off_t *start)
{
return (partition && start && partition->DiskSystem() == this && fModule
&& fModule->validate_move
&& fModule->validate_move(partition->PartitionData(), start));
}
// ValidateMoveChild
//! Validates parameters for moving a child partition
bool
KPartitioningSystem::ValidateMoveChild(KPartition *child, off_t *start)
{
return (child && start && child->Parent()
&& child->ParentDiskSystem() == this && fModule
&& fModule->validate_move_child
&& fModule->validate_move_child(child->Parent()->PartitionData(),
child->PartitionData(), start));
}
// ValidateSetName
//! Validates parameters for setting name of a partition
bool
KPartitioningSystem::ValidateSetName(KPartition *partition, char *name)
{
return (partition && name && partition->Parent()
&& partition->ParentDiskSystem() == this && fModule
&& fModule->validate_set_name
&& fModule->validate_set_name(partition->PartitionData(), name));
}
// ValidateSetContentName
//! Validates parameters for setting name of the content of a partition
bool
KPartitioningSystem::ValidateSetContentName(KPartition *partition, char *name)
{
return (partition && name && partition->DiskSystem() == this
&& fModule && fModule->validate_set_content_name
&& fModule->validate_set_content_name(partition->PartitionData(),
name));
}
// ValidateSetType
//! Validates parameters for setting type of a partition
bool
KPartitioningSystem::ValidateSetType(KPartition *partition, const char *type)
{
return (partition && type && partition->ParentDiskSystem() == this
&& fModule && fModule->validate_set_type
&& fModule->validate_set_type(partition->PartitionData(), type));
}
// ValidateSetParameters
//! Validates parameters for setting parameters of a partition
bool
KPartitioningSystem::ValidateSetParameters(KPartition *partition,
const char *parameters)
{
return (partition && partition->ParentDiskSystem() == this
&& fModule && fModule->validate_set_parameters
&& fModule->validate_set_parameters(partition->PartitionData(),
parameters));
}
// ValidateSetContentParameters
//! Validates parameters for setting parameters of the content of a partition
bool
KPartitioningSystem::ValidateSetContentParameters(KPartition *partition,
const char *parameters)
{
return (partition && partition->DiskSystem() == this && fModule
&& fModule->validate_set_content_parameters
&& fModule->validate_set_content_parameters(
partition->PartitionData(), parameters));
}
// ValidateInitialize
//! Validates parameters for initializing a partition
bool
KPartitioningSystem::ValidateInitialize(KPartition *partition, char *name,
const char *parameters)
{
return (partition && fModule && fModule->validate_initialize
&& fModule->validate_initialize(partition->PartitionData(), name,
parameters));
}
// ValidateCreateChild
//! Validates parameters for creating child of a partition
bool
KPartitioningSystem::ValidateCreateChild(KPartition *partition, off_t *start,
off_t *size, const char *type, const char *parameters, int32 *index)
{
int32 _index = 0;
if (!index)
index = &_index;
return (partition && start && size && type
&& partition->DiskSystem() == this && fModule
&& fModule->validate_create_child
&& fModule->validate_create_child(partition->PartitionData(), start,
size, type, parameters, index));
}
// CountPartitionableSpaces
//! Counts partitionable spaces on a partition
int32
KPartitioningSystem::CountPartitionableSpaces(KPartition *partition)
{
if (!partition || partition->DiskSystem() != this || !fModule)
return 0;
if (!fModule->get_partitionable_spaces) {
// TODO: Fallback algorithm.
return 0;
}
int32 count = 0;
status_t error = fModule->get_partitionable_spaces(
partition->PartitionData(), NULL, 0, &count);
return (error == B_OK || error == B_BUFFER_OVERFLOW ? count : 0);
}
// GetPartitionableSpaces
//! Retrieves a list of partitionable spaces on a partition
status_t
KPartitioningSystem::GetPartitionableSpaces(KPartition *partition,
partitionable_space_data *buffer, int32 count, int32 *actualCount)
{
if (!partition || partition->DiskSystem() != this || count > 0 && !buffer
|| !actualCount || !fModule) {
return B_BAD_VALUE;
}
if (!fModule->get_partitionable_spaces) {
// TODO: Fallback algorithm.
return B_ENTRY_NOT_FOUND;
}
return fModule->get_partitionable_spaces(partition->PartitionData(),
buffer, count, actualCount);
}
// GetNextSupportedType
//! Iterates through supported partition types
status_t
KPartitioningSystem::GetNextSupportedType(KPartition *partition, int32 *cookie,
char *type)
{
if (!partition || partition->DiskSystem() != this || !cookie || !type
|| !fModule) {
return B_BAD_VALUE;
}
if (!fModule->get_next_supported_type)
return B_ENTRY_NOT_FOUND;
return fModule->get_next_supported_type(partition->PartitionData(), cookie,
type);
}
// GetTypeForContentType
//! Translates the "pretty" content type to an internal type
status_t
KPartitioningSystem::GetTypeForContentType(const char *contentType, char *type)
{
if (!contentType || !type || !fModule)
return B_BAD_VALUE;
if (!fModule->get_type_for_content_type)
return B_ENTRY_NOT_FOUND;
return fModule->get_type_for_content_type(contentType, type);
}
// ShadowPartitionChanged
//! Calls for additional modifications when shadow partition is changed
status_t
KPartitioningSystem::ShadowPartitionChanged(KPartition *partition,
KPartition *child, uint32 operation)
{
if (!partition)
return B_BAD_VALUE;
if (!fModule)
return B_ERROR;
// If not implemented, we assume, that the partitioning system doesn't
// have to make any additional changes.
if (!fModule->shadow_changed)
return B_OK;
return fModule->shadow_changed(partition->PartitionData(),
child ? child->PartitionData() : NULL, operation);
}
#if 0
// Repair
//! Repairs a partition
@@ -877,6 +583,8 @@ KPartitioningSystem::DeleteChild(KPartition *child, KDiskDeviceJob *job)
return B_ERROR;
}
#endif // 0
// LoadModule
status_t
@@ -182,6 +182,7 @@ KPhysicalPartition::CreateShadowPartition()
return B_NO_MEMORY;
}
#if 0
// notify the disk systems
// parent disk system
status_t error;
@@ -204,6 +205,7 @@ KPhysicalPartition::CreateShadowPartition()
return error;
}
}
#endif // 0
}
// create shadows for children
@@ -1,492 +0,0 @@
// ddm_operation_validation.cpp
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KShadowPartition.h>
#include "ddm_operation_validation.h"
// static functions
namespace BPrivate {
namespace DiskDevice {
static status_t check_busy_partition(const KPartition *partition, bool shadow);
static status_t check_partition(const KPartition *partition,
int32 changeCounter, bool shadow);
} // namespace DiskDevice
} // namespace BPrivate
// get_current_team
team_id
BPrivate::DiskDevice::get_current_team()
{
// TODO: There must be a straighter way in kernelland.
thread_info info;
get_thread_info(find_thread(NULL), &info);
return info.team;
}
// check_shadow_partition
bool
BPrivate::DiskDevice::check_shadow_partition(const KPartition *partition,
int32 changeCounter,
bool requireShadow)
{
if (!partition || !partition->Device()
|| partition->IsShadowPartition() != requireShadow
|| changeCounter != partition->ChangeCounter()) {
return false;
}
if (!requireShadow)
return true;
return (partition->IsShadowPartition()
&& partition->Device()->ShadowOwner() == get_current_team());
}
// check_busy_partition
static
status_t
BPrivate::DiskDevice::check_busy_partition(const KPartition *partition,
bool shadow)
{
bool busy = (partition->IsBusy() || partition->IsDescendantBusy());
if (shadow) {
if (busy)
return B_BUSY;
} else {
if (!busy)
return B_BAD_VALUE;
}
return B_OK;
}
// check_partition
static
status_t
BPrivate::DiskDevice::check_partition(const KPartition *partition,
int32 changeCounter, bool shadow)
{
if (!check_shadow_partition(partition, changeCounter, shadow))
return B_BAD_VALUE;
bool busy = (partition->IsBusy() || partition->IsDescendantBusy());
if (shadow) {
if (busy)
return B_BUSY;
} else {
if (!busy)
return B_BAD_VALUE;
}
return B_OK;
}
// get_unmovable_descendants
bool
BPrivate::DiskDevice::get_unmovable_descendants(KPartition *partition,
partition_id *&unmovable, size_t &unmovableSize,
partition_id *&needUnmounting, size_t &needUnmountingSize,
bool requireShadow)
{
// check parameters
if (!partition || !unmovable || !needUnmounting || unmovableSize == 0
|| needUnmountingSize) {
return false;
}
// check partition
KDiskSystem *diskSystem = partition->DiskSystem();
bool supports = (diskSystem
&& diskSystem->SupportsOperations(partition,
B_DISK_SYSTEM_SUPPORTS_MOVING));
if (supports) {
unmovable[0] = partition->ID();
unmovableSize--;
}
if (supports && diskSystem->IsFileSystem()) {
needUnmounting[0] = partition->ID();
needUnmountingSize--;
}
// check child partitions
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) {
if (!get_unmovable_descendants(child, unmovable, unmovableSize,
needUnmounting, needUnmountingSize)) {
return false;
}
}
return true;
}
// validate_move_descendants
status_t
BPrivate::DiskDevice::validate_move_descendants(KPartition *partition,
off_t moveBy, bool markMovable, bool requireShadow)
{
if (!partition)
return B_BAD_VALUE;
// check partition
bool uninitialized = partition->IsUninitialized();
KDiskSystem *diskSystem = partition->DiskSystem();
bool movable = (uninitialized
|| diskSystem && diskSystem->SupportsOperations(partition,
B_DISK_SYSTEM_SUPPORTS_MOVING));
if (markMovable)
partition->SetAlgorithmData(movable);
// moving partition is supported in principle, now check the new offset
if (!uninitialized) {
if (movable) {
off_t offset = partition->Offset() + moveBy;
off_t newOffset = offset;
if (!diskSystem->ValidateMove(partition, &newOffset)
|| newOffset != offset) {
return B_ERROR;
}
} else
return B_ERROR;
// check children
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++) {
status_t error = validate_move_descendants(child, moveBy);
if (error != B_OK)
return error;
}
}
return B_OK;
}
// validate_defragment_partition
status_t
BPrivate::DiskDevice::validate_defragment_partition(KPartition *partition,
int32 changeCounter, bool *whileMounted, bool requireShadow)
{
status_t error = check_partition(partition, changeCounter, requireShadow);
if (error != B_OK)
return error;
// get the disk system and get the info
KDiskSystem *diskSystem = partition->DiskSystem();
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
uint32 operations = diskSystem->GetSupportedOperations(partition,
B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING
| B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING_WHILE_MOUNTED);
if (!(operations & B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING))
return B_ERROR;
if (whileMounted) {
*whileMounted = (operations
& B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING_WHILE_MOUNTED);
}
return B_OK;
}
// validate_repair_partition
status_t
BPrivate::DiskDevice::validate_repair_partition(KPartition *partition,
int32 changeCounter, bool checkOnly, bool *whileMounted,
bool requireShadow)
{
status_t error = check_partition(partition, changeCounter, requireShadow);
if (error != B_OK)
return error;
// get the disk system and get the info
KDiskSystem *diskSystem = partition->DiskSystem();
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
uint32 operations = diskSystem->GetSupportedOperations(partition,
B_DISK_SYSTEM_SUPPORTS_REPAIRING
| B_DISK_SYSTEM_SUPPORTS_REPAIRING_WHILE_MOUNTED);
if (!(operations & B_DISK_SYSTEM_SUPPORTS_REPAIRING))
return B_ERROR;
if (whileMounted) {
*whileMounted = (operations
& B_DISK_SYSTEM_SUPPORTS_REPAIRING_WHILE_MOUNTED);
}
return B_OK;
}
// validate_resize_partition
status_t
BPrivate::DiskDevice::validate_resize_partition(KPartition *partition,
int32 changeCounter, off_t *size, off_t *contentSize, bool requireShadow)
{
if (!partition || !size || !contentSize
|| !check_shadow_partition(partition, changeCounter, requireShadow)
|| !partition->Parent()) {
return B_BAD_VALUE;
}
status_t error = check_busy_partition(partition->Parent(), requireShadow);
if (error != B_OK)
return error;
// get the parent disk system and let it check the value
KDiskSystem *parentDiskSystem = partition->Parent()->DiskSystem();
if (!parentDiskSystem)
return B_ENTRY_NOT_FOUND;
if (!parentDiskSystem->ValidateResizeChild(partition, size))
return B_ERROR;
// if contents is uninitialized, then there's no need to check anything
// more
if (partition->IsUninitialized())
return B_OK;
// get the child disk system and let it check the value
KDiskSystem *childDiskSystem = partition->DiskSystem();
if (!childDiskSystem)
return B_ENTRY_NOT_FOUND;
*contentSize = *size;
// don't worry, if the content system desires to be smaller
if (!childDiskSystem->ValidateResize(partition, contentSize)
|| *contentSize > *size) {
return B_ERROR;
}
return B_OK;
}
// validate_move_partition
status_t
BPrivate::DiskDevice::validate_move_partition(KPartition *partition,
int32 changeCounter, off_t *newOffset, bool markMovable,
bool requireShadow)
{
if (!partition || !newOffset
|| !check_shadow_partition(partition, changeCounter, requireShadow)
|| !partition->Parent()) {
return B_BAD_VALUE;
}
status_t error = check_busy_partition(partition->Parent(), requireShadow);
if (error != B_OK)
return error;
// get the parent disk system and let it check the value
KDiskSystem *parentDiskSystem = partition->Parent()->DiskSystem();
if (!parentDiskSystem)
return B_ENTRY_NOT_FOUND;
if (!parentDiskSystem->ValidateMoveChild(partition, newOffset))
return B_ERROR;
// let the concerned content disk systems check the value
return validate_move_descendants(partition,
partition->Offset() - *newOffset, markMovable);
}
// validate_set_partition_name
status_t
BPrivate::DiskDevice::validate_set_partition_name(KPartition *partition,
int32 changeCounter, char *name, bool requireShadow)
{
if (!partition || !name)
return B_BAD_VALUE;
// truncate name to maximal size
name[B_OS_NAME_LENGTH] = '\0';
// check the partition
if (!check_shadow_partition(partition, changeCounter, requireShadow)
|| !partition->Parent()) {
return B_BAD_VALUE;
}
status_t error = check_busy_partition(partition->Parent(), requireShadow);
if (error != B_OK)
return error;
// get the disk system
KDiskSystem *diskSystem = partition->Parent()->DiskSystem();
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
// get the info
if (diskSystem->ValidateSetName(partition, name))
return B_OK;
return B_ERROR;
}
// validate_set_partition_content_name
status_t
BPrivate::DiskDevice::validate_set_partition_content_name(
KPartition *partition, int32 changeCounter, char *name, bool requireShadow)
{
if (!partition || !name)
return B_BAD_VALUE;
// truncate name to maximal size
name[B_OS_NAME_LENGTH] = '\0';
// check the partition
status_t error = check_partition(partition, changeCounter, requireShadow);
if (error != B_OK)
return error;
// get the disk system
KDiskSystem *diskSystem = partition->DiskSystem();
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
// get the info
if (diskSystem->ValidateSetContentName(partition, name))
return B_OK;
return B_ERROR;
}
// validate_set_partition_type
status_t
BPrivate::DiskDevice::validate_set_partition_type(KPartition *partition,
int32 changeCounter, const char *type, bool requireShadow)
{
if (!partition || !type)
return B_BAD_VALUE;
// check the partition
if (!check_shadow_partition(partition, changeCounter, requireShadow)
|| !partition->Parent()) {
return B_BAD_VALUE;
}
status_t error = check_busy_partition(partition->Parent(), requireShadow);
if (error != B_OK)
return error;
// get the disk system
KDiskSystem *diskSystem = partition->Parent()->DiskSystem();
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
// get the info
if (diskSystem->ValidateSetType(partition, type))
return B_OK;
return B_ERROR;
}
// validate_set_partition_parameters
status_t
BPrivate::DiskDevice::validate_set_partition_parameters(KPartition *partition,
int32 changeCounter, const char *parameters, bool requireShadow)
{
if (!partition || !parameters)
return B_BAD_VALUE;
// check the partition
if (!check_shadow_partition(partition, changeCounter, requireShadow)
|| !partition->Parent()) {
return B_BAD_VALUE;
}
status_t error = check_busy_partition(partition->Parent(), requireShadow);
if (error != B_OK)
return error;
// get the disk system
KDiskSystem *diskSystem = partition->Parent()->DiskSystem();
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
// get the info
if (diskSystem->ValidateSetParameters(partition, parameters))
return B_OK;
return B_ERROR;
}
// validate_set_partition_content_parameters
status_t
BPrivate::DiskDevice::validate_set_partition_content_parameters(
KPartition *partition, int32 changeCounter, const char *parameters,
bool requireShadow)
{
// check the partition
status_t error = check_partition(partition, changeCounter, requireShadow);
if (error != B_OK)
return error;
// get the disk system
KDiskSystem *diskSystem = partition->DiskSystem();
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
// get the info
if (diskSystem->ValidateSetContentParameters(partition, parameters))
return B_OK;
return B_ERROR;
}
// validate_initialize_partition
status_t
BPrivate::DiskDevice::validate_initialize_partition(KPartition *partition,
int32 changeCounter, const char *diskSystemName, char *name,
const char *parameters, bool requireShadow)
{
if (!partition || !diskSystemName)
return B_BAD_VALUE;
// truncate name to maximal size
if (name)
name[B_OS_NAME_LENGTH] = '\0';
// check the partition
status_t error = check_partition(partition, changeCounter, requireShadow);
if (error != B_OK)
return error;
// get the disk system
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemName);
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
DiskSystemLoader loader(diskSystem, true);
// get the info
if (diskSystem->ValidateInitialize(partition, name, parameters))
return B_OK;
return B_ERROR;
}
// validate_create_child_partition
status_t
BPrivate::DiskDevice::validate_create_child_partition(KPartition *partition,
int32 changeCounter, off_t *offset, off_t *size, const char *type,
const char *parameters, int32 *_index, bool requireShadow)
{
if (!partition || !offset || !size || !type)
return B_BAD_VALUE;
// check the partition
status_t error = check_partition(partition, changeCounter, requireShadow);
if (error != B_OK)
return error;
// get the disk system
KDiskSystem *diskSystem = partition->DiskSystem();
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
// get the info
int32 index;
if (diskSystem->ValidateCreateChild(partition, offset, size, type,
parameters, &index)) {
if (_index)
*_index = index;
return B_OK;
}
return B_ERROR;
}
// validate_delete_child_partition
status_t
BPrivate::DiskDevice::validate_delete_child_partition(KPartition *partition,
int32 changeCounter, bool requireShadow)
{
if (!partition)
return B_BAD_VALUE;
// check the partition
if (!check_shadow_partition(partition, changeCounter, requireShadow)
|| !partition->Parent()) {
return B_BAD_VALUE;
}
status_t error = check_busy_partition(partition->Parent(), requireShadow);
if (error != B_OK)
return error;
// get the disk system
KDiskSystem *diskSystem = partition->Parent()->DiskSystem();
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
// get the info
if (diskSystem->SupportsChildOperations(partition,
B_DISK_SYSTEM_SUPPORTS_DELETING_CHILD)) {
return B_OK;
}
return B_ERROR;
}
//} // namespace DiskDevice
//} // namespace BPrivate
@@ -1,74 +0,0 @@
// ddm_operation_validation.h
#ifndef _DISK_DEVICE_MANAGER_OPERATION_VALIDATION_H
#define _DISK_DEVICE_MANAGER_OPERATION_VALIDATION_H
#include <OS.h>
#include <disk_device_manager.h>
namespace BPrivate {
namespace DiskDevice {
class KPartition;
team_id get_current_team();
bool check_shadow_partition(const KPartition *partition, int32 changeCounter,
bool requireShadow = true);
bool get_unmovable_descendants(KPartition *partition, partition_id *&unmovable,
size_t &unmovableSize,
partition_id *&needUnmounting,
size_t &needUnmountingSize,
bool requireShadow = true);
status_t validate_move_descendants(KPartition *partition, off_t moveBy,
bool markMovable = false,
bool requireShadow = true);
status_t validate_defragment_partition(KPartition *partition,
int32 changeCounter,
bool *whileMounted = NULL,
bool requireShadow = true);
status_t validate_repair_partition(KPartition *partition, int32 changeCounter,
bool checkOnly, bool *whileMounted = NULL,
bool requireShadow = true);
status_t validate_resize_partition(KPartition *partition, int32 changeCounter,
off_t *size, off_t *contentSize,
bool requireShadow = true);
status_t validate_move_partition(KPartition *partition, int32 changeCounter,
off_t *newOffset, bool markMovable = false,
bool requireShadow = true);
status_t validate_set_partition_name(KPartition *partition,
int32 changeCounter, char *name,
bool requireShadow = true);
status_t validate_set_partition_content_name(KPartition *partition,
int32 changeCounter, char *name,
bool requireShadow = true);
status_t validate_set_partition_type(KPartition *partition,
int32 changeCounter, const char *type,
bool requireShadow = true);
status_t validate_set_partition_parameters(KPartition *partition,
int32 changeCounter,
const char *parameters,
bool requireShadow = true);
status_t validate_set_partition_content_parameters(KPartition *partition,
int32 changeCounter,
const char *parameters,
bool requireShadow = true);
status_t validate_initialize_partition(KPartition *partition,
int32 changeCounter,
const char *diskSystemName, char *name,
const char *parameters,
bool requireShadow = true);
status_t validate_create_child_partition(KPartition *partition,
int32 changeCounter, off_t *offset,
off_t *size, const char *type,
const char *parameters,
int32 *index = NULL,
bool requireShadow = true);
status_t validate_delete_child_partition(KPartition *partition,
int32 changeCounter,
bool requireShadow = true);
} // namespace DiskDevice
} // namespace BPrivate
#endif // _DISK_DEVICE_MANAGER_OPERATION_VALIDATION_H
@@ -8,8 +8,6 @@
#include <AutoDeleter.h>
#include <ddm_userland_interface.h>
#include <KDiskDevice.h>
#include <KDiskDeviceJob.h>
#include <KDiskDeviceJobQueue.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
@@ -17,8 +15,6 @@
#include <KShadowPartition.h>
#include <syscall_args.h>
#include "ddm_operation_validation.h"
#include "KDiskDeviceJobGenerator.h"
#include "UserDataWriter.h"
using namespace BPrivate::DiskDevice;
@@ -51,6 +47,7 @@ ddm_strlcpy(char *to, const char *from, size_t size,
}
#if 0
// move_descendants
static void
move_descendants(KPartition *partition, off_t moveBy)
@@ -86,6 +83,7 @@ move_descendants_contents(KPartition *partition)
}
return B_OK;
}
#endif // 0
// _user_get_next_disk_device_id
@@ -283,67 +281,6 @@ _user_get_disk_device_data(partition_id id, bool deviceOnly, bool shadow,
}
// _user_get_partitionable_spaces
status_t
_user_get_partitionable_spaces(partition_id partitionID, int32 changeCounter,
partitionable_space_data *_buffer, int32 count, int32 *_actualCount)
{
if (count > 0 && !_buffer)
return B_BAD_VALUE;
if (count > 0 && !IS_USER_ADDRESS(_buffer)
|| _actualCount && !IS_USER_ADDRESS(_actualCount)) {
return B_BAD_ADDRESS;
}
// allocate buffer
int32 bufferSize = count * sizeof(partitionable_space_data);
partitionable_space_data *buffer = NULL;
MemoryDeleter bufferDeleter;
if (count > 0) {
buffer = (partitionable_space_data*)malloc(bufferSize);
if (!buffer)
return B_NO_MEMORY;
bufferDeleter.SetTo(buffer);
}
status_t error = B_OK;
// get the partition
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
KPartition *partition = manager->ReadLockPartition(partitionID);
if (!partition)
return B_ENTRY_NOT_FOUND;
PartitionRegistrar registrar1(partition, true);
PartitionRegistrar registrar2(partition->Device(), true);
DeviceReadLocker locker(partition->Device(), true);
if (!check_shadow_partition(partition, changeCounter))
return B_BAD_VALUE;
// get the disk system
KDiskSystem *diskSystem = partition->DiskSystem();
if (!diskSystem)
return B_ENTRY_NOT_FOUND;
// get the info
int32 actualCount;
error = diskSystem->GetPartitionableSpaces(partition, buffer, count,
&actualCount);
// copy out
if (_actualCount)
user_memcpy(_actualCount, &actualCount, sizeof(actualCount));
// copy even on error
if (error == B_OK && buffer)
user_memcpy(_buffer, buffer, bufferSize);
return error;
}
// _user_register_file_device
partition_id
_user_register_file_device(const char *_filename)
@@ -5,8 +5,6 @@
#include "disk_device_manager.h"
#include "KDiskDevice.h"
#include "KDiskDeviceJob.h"
#include "KDiskDeviceJobQueue.h"
#include "KDiskDeviceManager.h"
#include "KDiskDeviceUtils.h"
#include "KDiskSystem.h"
@@ -232,7 +230,7 @@ scan_partition(partition_id partitionID)
PartitionRegistrar _(partition, true);
// scan it
return manager->ScanPartition(partition, false);
return manager->ScanPartition(partition);
}
@@ -253,6 +251,7 @@ find_disk_system(const char *name)
bool
update_disk_device_job_progress(disk_job_id jobID, float progress)
{
#if 0
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
if (ManagerLocker locker = manager) {
if (KDiskDeviceJob *job = manager->FindJob(jobID)) {
@@ -260,6 +259,7 @@ update_disk_device_job_progress(disk_job_id jobID, float progress)
return true;
}
}
#endif
return false;
}
@@ -268,6 +268,7 @@ update_disk_device_job_progress(disk_job_id jobID, float progress)
bool
update_disk_device_job_extra_progress(disk_job_id jobID, const char *info)
{
#if 0
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
if (ManagerLocker locker = manager) {
if (KDiskDeviceJob *job = manager->FindJob(jobID)) {
@@ -275,6 +276,7 @@ update_disk_device_job_extra_progress(disk_job_id jobID, const char *info)
return true;
}
}
#endif
return false;
}
@@ -283,6 +285,7 @@ update_disk_device_job_extra_progress(disk_job_id jobID, const char *info)
bool
set_disk_device_job_error_message(disk_job_id jobID, const char *message)
{
#if 0
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
if (ManagerLocker locker = manager) {
if (KDiskDeviceJob *job = manager->FindJob(jobID)) {
@@ -290,6 +293,7 @@ set_disk_device_job_error_message(disk_job_id jobID, const char *message)
return true;
}
}
#endif
return false;
}
@@ -299,6 +303,7 @@ uint32
update_disk_device_job_interrupt_properties(disk_job_id jobID,
uint32 interruptProperties)
{
#if 0
bool paused = false;
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
do {
@@ -329,6 +334,7 @@ update_disk_device_job_interrupt_properties(disk_job_id jobID,
pauseSemaphore = -1;
}
} while (paused);
#endif
return B_DISK_DEVICE_JOB_CONTINUE;
}
@@ -1,129 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#include "KCreateChildJob.h"
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KPartition.h>
#include <KPartitionVisitor.h>
#include <string.h>
#include "ddm_operation_validation.h"
/**
Creates the job.
\param partition whose children should we create
\param child new child ID
\param offset where the child should start
\param size size of the new child
\param parameters additional parameters for the operation
*/
KCreateChildJob::KCreateChildJob(partition_id partition, partition_id child,
off_t offset, off_t size, const char *type, const char *parameters)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_CREATE, partition, partition),
fChildID(child),
fOffset(offset),
fSize(size),
fType (!type ? NULL : strdup(type)),
fParameters(!parameters ? NULL : strdup(parameters))
{
SetDescription( "creating child of the partition" );
}
KCreateChildJob::~KCreateChildJob()
{
free(fType);
free(fParameters);
}
/**
* Do the actual creation
*
* \note in time of calling the \c KDiskSystem function for creating child, the partition is NOT locked
*/
status_t
KCreateChildJob::Do()
{
KDiskDeviceManager* manager = KDiskDeviceManager::Default();
KPartition* partition = manager->WriteLockPartition(PartitionID());
if (partition) {
PartitionRegistrar registrar(partition, true);
PartitionRegistrar deviceRegistrar(partition->Device(), true);
DeviceWriteLocker locker(partition->Device(), true);
if (!partition->DiskSystem()) {
SetErrorMessage("Partition has no disk system!");
return B_BAD_VALUE;
}
// all descendants should be marked busy/descendant busy
if (IsPartitionNotBusy(partition)) {
SetErrorMessage("Can't create child of non-busy partition!");
return B_ERROR;
}
KPartition* childPartition = manager->WriteLockPartition(fChildID);
if (!childPartition) {
// TODO
}
off_t newOffset = fOffset;
off_t newSize = fSize;
status_t validationResult = validate_create_child_partition(
partition, partition->ChangeCounter(),
&newOffset, &fSize, fType,
fParameters, NULL, false);
if (validationResult != B_OK) {
SetErrorMessage("Validating of creating new child failed!");
return validationResult;
}
if (newOffset != fOffset) {
SetErrorMessage("Requested offset is not valid.");
return B_ERROR;
}
if (newSize != fSize) {
SetErrorMessage("Requested size is not valid");
}
KDiskSystem *diskSystem = partition->DiskSystem();
DiskSystemLoader loader(diskSystem);
KPartition *newChild = 0;
locker.Unlock();
status_t createResult = diskSystem->CreateChild(partition, newOffset,
newSize, fType, fParameters, this, &newChild, fChildID);
if (createResult != B_OK) {
SetErrorMessage("Creating new partition child failed!");
return createResult;
}
return B_OK;
}
else {
SetErrorMessage("Couldn't find partition.");
return B_ENTRY_NOT_FOUND;
}
}
@@ -1,42 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#ifndef _K_DISK_DEVICE_CREATE_CHILD_JOB_H
#define _K_DISK_DEVICE_CREATE_CHILD_JOB_H
#include "KDiskDeviceJob.h"
namespace BPrivate {
namespace DiskDevice {
/**
* Create new child of given partition
*/
class KCreateChildJob : public KDiskDeviceJob {
public:
KCreateChildJob(partition_id partition, partition_id child, off_t offset,
off_t size, const char *type, const char *parameters);
virtual ~KCreateChildJob();
virtual status_t Do();
private:
partition_id fChildID;
off_t fOffset;
off_t fSize;
char* fType;
char* fParameters;
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KCreateChildJob;
#endif // _DISK_DEVICE_CREATE_CHILD_JOB_H
@@ -1,105 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#include "KDefragmentJob.h"
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KPartition.h>
#include <KPartitionVisitor.h>
#include <string.h>
#include "ddm_operation_validation.h"
/**
Creates the job
\param partition which device should we defragment
*/
KDefragmentJob::KDefragmentJob(partition_id partition)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_DEFRAGMENT, partition, partition)
{
SetDescription("defragmenting partition");
}
KDefragmentJob::~KDefragmentJob()
{
}
status_t
KDefragmentJob::Do()
{
KDiskDeviceManager* manager = KDiskDeviceManager::Default();
KPartition* partition = manager->WriteLockPartition(PartitionID());
if (partition) {
PartitionRegistrar registrar(partition, true);
PartitionRegistrar deviceRegistrar(partition->Device(), true);
DeviceWriteLocker locker(partition->Device(), true);
// some basic checks
if (!partition->DiskSystem()) {
SetErrorMessage("Partition has no disk system!");
return B_BAD_VALUE;
}
// all descendants should be marked busy/descendant busy
if (IsPartitionNotBusy(partition) ) {
SetErrorMessage("Can't defragment non-busy partition!");
return B_ERROR;
}
bool whileMounted;
// OK, seems alright, let's validate the job
status_t validationResult = validate_defragment_partition(
partition, partition->ChangeCounter(), &whileMounted, false);
if (validationResult != B_OK) {
SetErrorMessage("Validation of defragmenting partition failed.");
return validationResult;
}
if (!whileMounted && partition->IsMounted()) {
SetErrorMessage("This partition cannot be defragmented while "
"mounted." );
return B_ERROR;
}
// everything OK, let's do the job!
KDiskSystem *diskSystem = partition->DiskSystem();
DiskSystemLoader loader(diskSystem);
locker.Unlock();
status_t defragResult = diskSystem->Defragment(partition, this);
if (defragResult != B_OK) {
SetErrorMessage("Defragmenting partition failed!");
return defragResult;
}
return B_OK;
} else {
SetErrorMessage("Couldn't find partition!");
return B_ENTRY_NOT_FOUND;
}
}
@@ -1,33 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#ifndef _K_DISK_DEVICE_DEFRAGMENT_JOB_H
#define _K_DISK_DEVICE_DEFRAGMENT_JOB_H
#include "KDiskDeviceJob.h"
namespace BPrivate {
namespace DiskDevice {
/**
* Defragments the device
*/
class KDefragmentJob : public KDiskDeviceJob {
public:
KDefragmentJob(partition_id partition);
virtual ~KDefragmentJob();
virtual status_t Do();
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KDefragmentJob;
#endif // _DISK_DEVICE_DEFRAGMENT_JOB_H
@@ -1,94 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#include "KDeleteChildJob.h"
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KPartition.h>
#include <KPartitionVisitor.h>
#include <string.h>
#include "ddm_operation_validation.h"
/*!
Creates the job
\param parent device of the deleted partition
\param partition partition supposed to be removed
*/
KDeleteChildJob::KDeleteChildJob(partition_id parent, partition_id partition)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_DELETE, partition, parent)
{
SetDescription("deleting child of the partition");
}
KDeleteChildJob::~KDeleteChildJob()
{
}
status_t
KDeleteChildJob::Do()
{
KDiskDeviceManager* manager = KDiskDeviceManager::Default();
KPartition* partition = manager->WriteLockPartition(PartitionID());
if (partition) {
PartitionRegistrar registrar(partition, true);
PartitionRegistrar deviceRegistrar(partition->Device(), true);
DeviceWriteLocker locker(partition->Device(), true);
if (!partition->ParentDiskSystem()) {
SetErrorMessage("Partition has no parent disk system!");
return B_BAD_VALUE;
}
// all descendants should be marked busy/descendant busy
if (IsPartitionNotBusy( partition)) {
SetErrorMessage("Can't delete child of non-busy partition!");
return B_ERROR;
}
status_t validationResult = validate_delete_child_partition(
partition, partition->ChangeCounter(), false);
if (validationResult != B_OK) {
SetErrorMessage("Validation of deleting child failed!");
return validationResult;
}
// everything OK, let's do the job!
KDiskSystem *parentDiskSystem = partition->ParentDiskSystem();
DiskSystemLoader loader(parentDiskSystem );
locker.Unlock();
status_t deleteResult = parentDiskSystem->DeleteChild(partition, this);
if (deleteResult != B_OK) {
SetErrorMessage("Deleting child failed!");
return deleteResult;
}
return B_OK;
} else {
SetErrorMessage("Couldn't find partition!");
return B_ENTRY_NOT_FOUND;
}
}
@@ -1,33 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#ifndef _K_DISK_DEVICE_DELETE_CHILD_JOB_H
#define _K_DISK_DEVICE_DELETE_CHILD_JOB_H
#include "KDiskDeviceJob.h"
namespace BPrivate {
namespace DiskDevice {
/**
* Deletes specific child of a partition/device
*/
class KDeleteChildJob : public KDiskDeviceJob {
public:
KDeleteChildJob(partition_id parent, partition_id partition);
virtual ~KDeleteChildJob();
virtual status_t Do();
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KDeleteChildJob;
#endif // _DISK_DEVICE_DELETE_CHILD_JOB_H
@@ -1,138 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#include <stdio.h>
#include <string.h>
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KPartition.h>
#include <KPartitionVisitor.h>
#include <string.h>
#include "ddm_operation_validation.h"
#include "KInitializeJob.h"
// debugging
//#define DBG(x)
#define DBG(x) x
#define OUT dprintf
/*!
Creates the job.
\param partition the partition to initialize
\param diskSystemID which disk system the partition should be initialized with
\param parameters additional parameters for the operation
*/
KInitializeJob::KInitializeJob(partition_id partition,
disk_system_id diskSystemID, const char *name, const char *parameters)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_INITIALIZE, partition, partition),
fDiskSystemID(diskSystemID),
fName(!name ? NULL : strdup(name)),
fParameters(!parameters ? NULL : strdup(parameters))
{
SetDescription("initializing the partition with given disk system");
}
KInitializeJob::~KInitializeJob()
{
free(fName);
free(fParameters);
}
status_t
KInitializeJob::Do()
{
DBG(OUT("KInitializeJob::Do(%ld)\n", PartitionID()));
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
KPartition *partition = manager->WriteLockPartition(PartitionID());
if (!partition) {
SetErrorMessage("Couldn't find partition.");
return B_ENTRY_NOT_FOUND;
}
PartitionRegistrar registrar(partition, true);
PartitionRegistrar deviceRegistrar(partition->Device(), true);
DeviceWriteLocker locker(partition->Device(), true);
// basic checks
// all descendants should be marked busy/descendant busy
if (IsPartitionNotBusy(partition)) {
SetErrorMessage("Can't initialize non-busy partition!");
return B_ERROR;
}
if (partition->DiskSystem()) {
SetErrorMessage("Partition is already initialized.");
return B_BAD_VALUE;
}
// get the disk system
KDiskSystem *diskSystemToInit = manager->LoadDiskSystem(fDiskSystemID);
if (!diskSystemToInit) {
SetErrorMessage("Given DiskSystemID doesn't correspond to any "
"known DiskSystem.");
return B_BAD_VALUE;
}
DiskSystemLoader loader(diskSystemToInit, true);
// check the parameters
char name[B_DISK_DEVICE_NAME_LENGTH];
if (fName)
strlcpy(name, fName, sizeof(name));
status_t error = validate_initialize_partition(partition,
partition->ChangeCounter(), diskSystemToInit->Name(),
fName ? name : NULL, fParameters, false);
if (error != B_OK) {
SetErrorMessage("Validation of initializing partition failed.");
return error;
}
if (fName != NULL && strcmp(fName, name) != 0) {
SetErrorMessage("Requested name not valid.");
return B_BAD_VALUE;
}
// everything seems OK -> let's do the job
locker.Unlock();
error = diskSystemToInit->Initialize(partition, fName, fParameters, this);
if (error != B_OK) {
SetErrorMessage("Initialization of partition failed!");
return error;
}
locker.Lock();
if (partition->DiskSystem()) {
// The disk system might have triggered a rescan after initializing, in
// which case the disk system is already set. Just check, if it is the
// right one.
if (partition->DiskSystem() != diskSystemToInit) {
SetErrorMessage("Partition has wrong disk system after "
"initialization.");
return B_ERROR;
}
} else
partition->SetDiskSystem(diskSystemToInit);
return B_OK;
}
@@ -1,40 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#ifndef _K_DISK_DEVICE_INITIALIZE_JOB_H
#define _K_DISK_DEVICE_INITIALIZE_JOB_H
#include "KDiskDeviceJob.h"
namespace BPrivate {
namespace DiskDevice {
/**
* Initializes the device with given disk system (i.e. partitioning or file system)
*/
class KInitializeJob : public KDiskDeviceJob {
public:
KInitializeJob(partition_id partition, disk_system_id diskSystemID,
const char *name, const char *parameters);
virtual ~KInitializeJob();
virtual status_t Do();
private:
disk_system_id fDiskSystemID;
char * fName;
char * fParameters;
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KInitializeJob;
#endif // _DISK_DEVICE_INITIALIZE_JOB_H
@@ -1,117 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#include "KMoveJob.h"
#include <stdio.h>
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KPartition.h>
#include <KPartitionVisitor.h>
#include "ddm_operation_validation.h"
// debugging
//#define DBG(x)
#define DBG(x) x
#define OUT dprintf
/**
Creates the job.
\param parentID the device whose child should be moved
\param partitionID the child to move
\param offset where to move
*/
KMoveJob::KMoveJob(partition_id parentID, partition_id partitionID,
off_t offset)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_MOVE, partitionID, parentID),
fNewOffset(offset)
{
SetDescription("moving partition");
}
KMoveJob::~KMoveJob()
{
}
status_t
KMoveJob::Do()
{
DBG(OUT( "KMoveJob::Do(%ld)\n", PartitionID() ));
// get the partition
KDiskDeviceManager* manager = KDiskDeviceManager::Default();
KPartition *partition = manager->WriteLockPartition(PartitionID());
if (partition) {
// OK, we have the partition, do some checks
PartitionRegistrar registrar(partition, true);
PartitionRegistrar deviceRegistrar(partition->Device(), true);
DeviceWriteLocker locker(partition->Device(), true);
// basic checks
if (!partition->ParentDiskSystem()) {
SetErrorMessage("Partition has no parent disk system!");
return B_BAD_VALUE;
}
if (partition->Offset() == fNewOffset) {
// we are already on the right place -> nothing to do...
return B_OK;
}
off_t newOffset = fNewOffset;
status_t validateResult = validate_move_partition(partition,
partition->ChangeCounter(), &newOffset, true, false);
// TODO posledni 2 parametry????
// TODO: Huh?
if (validateResult != B_OK) {
SetErrorMessage("Validation of the new partition offset failed.");
return validateResult;
}
if (newOffset != fNewOffset) {
SetErrorMessage("Requested partition offset not valid.");
return B_ERROR;
}
// all descendants should be marked busy/descendant busy
if (IsPartitionNotBusy(partition)) {
SetErrorMessage("Can't move non-busy partition!");
return B_ERROR;
}
// get all necessary objects
KDiskSystem *parentDiskSystem = partition->ParentDiskSystem();
KDiskSystem *childDiskSystem = partition->DiskSystem();
locker.Unlock();
status_t moveResult = parentDiskSystem->Move(partition, fNewOffset,
this);
if (moveResult != B_OK) {
SetErrorMessage("Moving of partition failed.");
}
return moveResult;
} else {
SetErrorMessage("Couldn't find partition.");
return B_ENTRY_NOT_FOUND;
}
}
@@ -1,37 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#ifndef _K_DISK_DEVICE_MOVE_JOB_H
#define _K_DISK_DEVICE_MOVE_JOB_H
#include "KDiskDeviceJob.h"
namespace BPrivate {
namespace DiskDevice {
/**
* Moves given child of a partition/device
*/
class KMoveJob : public KDiskDeviceJob {
public:
KMoveJob(partition_id parentID, partition_id partitionID, off_t offset);
virtual ~KMoveJob();
virtual status_t Do();
private:
off_t fNewOffset;
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KMoveJob;
#endif // _DISK_DEVICE_MOVE_JOB_H
@@ -1,101 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#include "KRepairJob.h"
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KPartition.h>
#include <KPartitionVisitor.h>
#include <string.h>
#include "ddm_operation_validation.h"
/**
Creates the job.
\param partition the partition which should be repared
\param checkOnly when true, the partition is only checked, but no actual
repairs are proceeded
*/
KRepairJob::KRepairJob(partition_id partition, bool checkOnly)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_REPAIR, partition, partition),
fCheckOnly( checkOnly )
{
SetDescription("repairing partition");
}
KRepairJob::~KRepairJob()
{
}
status_t
KRepairJob::Do()
{
KDiskDeviceManager* manager = KDiskDeviceManager::Default();
KPartition* partition = manager->WriteLockPartition(PartitionID());
if (partition) {
PartitionRegistrar registrar(partition, true);
PartitionRegistrar deviceRegistrar(partition->Device(), true);
DeviceWriteLocker locker(partition->Device(), true);
// basic checks
if (!partition->DiskSystem()) {
SetErrorMessage("Partition has no disk system.");
return B_BAD_VALUE;
}
if (IsPartitionNotBusy(partition)) {
SetErrorMessage("Can't repair non-busy partition!");
return B_ERROR;
}
bool whileMounted;
status_t validationResult = validate_repair_partition(partition,
partition->ChangeCounter(), fCheckOnly, &whileMounted, false);
if (validationResult != B_OK) {
SetErrorMessage("Validation repairing partition failed!");
return validationResult;
}
// everything OK, let's do the job
KDiskSystem* diskSystem = partition->DiskSystem();
DiskSystemLoader loader(diskSystem);
locker.Unlock();
status_t repairResult = diskSystem->Repair(partition, fCheckOnly, this);
if (repairResult != B_OK) {
if (fCheckOnly) {
SetErrorMessage("Checking for repairing partition failed!");
} else {
SetErrorMessage("Repairing partition failed!");
}
return repairResult;
}
return B_OK;
} else {
SetErrorMessage("Couldn't find partition!");
return B_ENTRY_NOT_FOUND;
}
}
@@ -1,37 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#ifndef _K_DISK_DEVICE_REPAIR_JOB_H
#define _K_DISK_DEVICE_REPAIR_JOB_H
#include "KDiskDeviceJob.h"
namespace BPrivate {
namespace DiskDevice {
/**
* Repair partition (or check for repairs)
*/
class KRepairJob : public KDiskDeviceJob {
public:
KRepairJob(partition_id partition, bool checkOnly);
virtual ~KRepairJob();
virtual status_t Do();
private:
bool fCheckOnly;
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KRepairJob;
#endif // _DISK_DEVICE_REPAIR_JOB_H
@@ -1,145 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#include <stdio.h>
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KPartition.h>
#include <KPartitionVisitor.h>
#include "ddm_operation_validation.h"
#include "KResizeJob.h"
// debugging
//#define DBG(x)
#define DBG(x) x
#define OUT dprintf
// constructor
/**
Creates the job.
\param parentID the device whose child should be resized
\param partitionID the partition which should be resized
\param size new size for the partition
*/
KResizeJob::KResizeJob(partition_id parentID, partition_id partitionID,
off_t size)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_RESIZE, partitionID, parentID),
fSize(size)
{
SetDescription("resizing partition");
}
// destructor
KResizeJob::~KResizeJob()
{
}
// Do
status_t
KResizeJob::Do()
{
DBG(OUT("KResizeJob::Do(%ld)\n", PartitionID()));
// get the partition
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
KPartition *partition = manager->WriteLockPartition(PartitionID());
if (partition) {
PartitionRegistrar registrar(partition, true);
PartitionRegistrar deviceRegistrar(partition->Device(), true);
DeviceWriteLocker locker(partition->Device(), true);
// basic checks
if (!partition->ParentDiskSystem()) {
SetErrorMessage("Partition has no parent disk system!");
return B_BAD_VALUE;
}
// if size remains the same, then nothing's to do
if (partition->Size() == fSize)
return B_OK;
// check new size
off_t size = fSize;
off_t contentSize = fSize;
status_t error = validate_resize_partition(partition,
partition->ChangeCounter(), &size, &contentSize, false);
if (error != B_OK) {
SetErrorMessage("Validation of the new partition size failed.");
return error;
}
if (size != fSize) {
SetErrorMessage("Requested size is not valid.");
return B_ERROR;
}
// all descendants should be marked busy/descendant busy
struct IsNotBusyVisitor : KPartitionVisitor {
virtual bool VisitPre(KPartition *partition)
{
return !(partition->IsBusy() || partition->IsDescendantBusy());
}
} isNotBusyVisitor;
if (partition->VisitEachDescendant(&isNotBusyVisitor)) {
SetErrorMessage("Can't resize non-busy partition!");
return B_ERROR;
}
// things look good: get all infos needed for resizing
KDiskSystem *parentDiskSystem = partition->ParentDiskSystem();
KDiskSystem *childDiskSystem = partition->DiskSystem();
DiskSystemLoader loader1(parentDiskSystem);
DiskSystemLoader loader2(childDiskSystem);
off_t oldSize = partition->Size();
off_t oldContentSize = partition->ContentSize();
// unlock the device and resize the beast
locker.Unset();
// if growing, resize partition first
if (oldSize < fSize) {
status_t error = parentDiskSystem->ResizeChild(partition, fSize,
this);
if (error != B_OK)
return error;
}
// resize contents
if (childDiskSystem && oldContentSize != contentSize) {
status_t error = childDiskSystem->Resize(partition, contentSize,
this);
if (error != B_OK)
return error;
}
// if shrinking, resize partition last
if (oldSize > fSize) {
status_t error = parentDiskSystem->ResizeChild(partition, fSize,
this);
if (error != B_OK)
return error;
}
return B_OK;
} else {
SetErrorMessage("Couldn't find partition.");
return B_ENTRY_NOT_FOUND;
}
}
@@ -1,35 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#ifndef _K_DISK_DEVICE_RESIZE_JOB_H
#define _K_DISK_DEVICE_RESIZE_JOB_H
#include "KDiskDeviceJob.h"
namespace BPrivate {
namespace DiskDevice {
/**
* Resizes a partition.
*/
class KResizeJob : public KDiskDeviceJob {
public:
KResizeJob(partition_id parentID, partition_id partitionID, off_t size);
virtual ~KResizeJob();
virtual status_t Do();
private:
off_t fSize;
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KResizeJob;
#endif // _DISK_DEVICE_RESIZE_JOB_H
@@ -1,150 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#include <KernelExport.h>
#include <stdio.h>
#include <string.h>
#include "KDiskDevice.h"
#include "KDiskDeviceManager.h"
#include "KDiskDeviceUtils.h"
#include "KDiskSystem.h"
#include "KPartition.h"
#include "KPath.h"
#include "KScanPartitionJob.h"
// debugging
#define DBG(x)
#define OUT dprintf
/**
Creates the job.
\param partitionID the partition to scan
*/
KScanPartitionJob::KScanPartitionJob(partition_id partitionID)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_SCAN, partitionID)
{
SetDescription("scanning partition");
}
KScanPartitionJob::~KScanPartitionJob()
{
}
status_t
KScanPartitionJob::Do()
{
// get the partition
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
KPartition *partition = manager->WriteLockPartition(PartitionID());
if (!partition)
return B_ENTRY_NOT_FOUND;
KDiskDevice *device = partition->Device();
PartitionRegistrar registrar1(partition, true);
PartitionRegistrar registrar2(device, true);
DeviceWriteLocker locker(device, true);
// scan the partition
status_t error = B_OK;
if (device->HasMedia()) {
error = _ScanPartition(partition);
if (error != B_OK) {
// ...
error = B_OK;
}
}
return error;
}
status_t
KScanPartitionJob::_ScanPartition(KPartition *partition)
{
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
// the partition's device must be write-locked
if (!partition)
return B_BAD_VALUE;
if (partition->DiskSystem() != NULL) {
// TODO: this is more or less a hack to prevent rescanning a partition
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++)
_ScanPartition(child);
return B_OK;
}
DBG(
KPath partitionPath;
partition->GetPath(&partitionPath);
OUT("KDiskDeviceManager::_ScanPartition(%s)\n", partitionPath.Path());
)
// publish the partition
status_t error = B_OK;
if (!partition->IsPublished()) {
error = partition->PublishDevice();
if (error != B_OK)
return error;
}
// find the disk system that returns the best priority for this partition
float bestPriority = -1;
KDiskSystem *bestDiskSystem = NULL;
void *bestCookie = NULL;
int32 itCookie = 0;
while (KDiskSystem *diskSystem = manager->LoadNextDiskSystem(&itCookie)) {
DBG(OUT(" trying: %s\n", diskSystem->Name()));
void *cookie = NULL;
float priority = diskSystem->Identify(partition, &cookie);
DBG(OUT(" returned: %ld/1000\n", int32(1000 * priority)));
if (priority >= 0 && priority > bestPriority) {
// new best disk system
if (bestDiskSystem) {
bestDiskSystem->FreeIdentifyCookie(partition, bestCookie);
bestDiskSystem->Unload();
}
bestPriority = priority;
bestDiskSystem = diskSystem;
bestCookie = cookie;
} else {
// disk system doesn't identify the partition or worse than our
// current favorite
if (priority >= 0)
diskSystem->FreeIdentifyCookie(partition, cookie);
diskSystem->Unload();
}
}
// now, if we have found a disk system, let it scan the partition
if (bestDiskSystem) {
DBG(OUT(" scanning with: %s\n", bestDiskSystem->Name()));
error = bestDiskSystem->Scan(partition, bestCookie);
bestDiskSystem->FreeIdentifyCookie(partition, bestCookie);
if (error == B_OK) {
partition->SetDiskSystem(bestDiskSystem);
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++)
_ScanPartition(child);
} else {
// TODO: Handle the error.
DBG(OUT(" scanning failed: %s\n", strerror(error)));
}
// now we can safely unload the disk system -- it has been loaded by
// the partition(s) and thus will not really be unloaded
bestDiskSystem->Unload();
} else {
// contents not recognized
// nothing to be done -- partitions are created as unrecognized
}
return error;
}
@@ -1,37 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#ifndef _K_DISK_DEVICE_SCAN_PARTITION_JOB_H
#define _K_DISK_DEVICE_SCAN_PARTITION_JOB_H
#include "KDiskDeviceJob.h"
namespace BPrivate {
namespace DiskDevice {
class KPartition;
/**
* Scans partition and tries to find the most suitable disk system for it
*/
class KScanPartitionJob : public KDiskDeviceJob {
public:
KScanPartitionJob(partition_id partitionID);
virtual ~KScanPartitionJob();
virtual status_t Do();
private:
status_t _ScanPartition(KPartition *partition);
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KScanPartitionJob;
#endif // _DISK_DEVICE_SCAN_PARTITION_JOB_H
@@ -1,148 +0,0 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Lubos Kulic <[email protected]>
*/
#include "KSetNameJob.h"
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KPartition.h>
#include <KPartitionVisitor.h>
#include <string.h>
#include "ddm_operation_validation.h"
/**
Creates the job.
\param partitionID the partition/device whose name should be set
\param name the new name for \c partitionID
\param contentName the new name for the content of \c partitionID
*/
KSetNameJob::KSetNameJob(partition_id parentID, partition_id partitionID,
const char* name, const char* contentName)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_SET_NAME, partitionID, parentID),
fName(!name ? NULL : strdup(name)),
fContentName(!contentName ? NULL : strdup(contentName))
{
SetDescription("setting name for the partition or its content");
}
KSetNameJob::~KSetNameJob()
{
free(fName);
free(fContentName);
}
status_t
KSetNameJob::Do()
{
KDiskDeviceManager* manager = KDiskDeviceManager::Default();
KPartition* partition = manager->WriteLockPartition(PartitionID());
if (partition) {
if (!fName && !fContentName) {
SetErrorMessage("No name to set.");
return B_BAD_VALUE;
}
PartitionRegistrar registrar(partition, true);
PartitionRegistrar deviceRegistrar(partition->Device(), true);
// TODO is lock necessary?
DeviceWriteLocker locker(partition->Device(), true);
// basic checks
// all descendants should be marked busy/descendant busy
if (IsPartitionNotBusy(partition)) {
SetErrorMessage("Can't set name for non-busy partition!");
return B_ERROR;
}
if (fName) {
// set name of the partition
// setting name of this partition -> via our parent disk system
if (!partition->ParentDiskSystem()) {
SetErrorMessage("Partition has no parent disk system!");
return B_BAD_VALUE;
}
// TODO maybe give copy of name
// TODO: The parameters are already validated and should not be changed again!
status_t validationResult = validate_set_partition_name(
partition, partition->ChangeCounter(), fName, false);
if( validationResult != B_OK) {
SetErrorMessage( "Validation of setting partition name failed!" );
return validationResult;
}
// everything OK, let's do the job
KDiskSystem* parentDiskSystem = partition->ParentDiskSystem();
DiskSystemLoader loader(parentDiskSystem);
locker.Unlock();
status_t setNameResult = parentDiskSystem->SetName(partition, fName,
this);
if (setNameResult != B_OK) {
SetErrorMessage( "Setting name of the partition failed!" );
}
return setNameResult;
}
if (fContentName) {
// set name of the contents
// setting name of our contents -> via our disk system
if (!partition->DiskSystem()) {
SetErrorMessage( "Partition has no disk system!");
return B_BAD_VALUE;
}
// TODO: The parameters are already validated and should not be changed again!
status_t validationResult = validate_set_partition_content_name(
partition, partition->ChangeCounter(), fContentName, false);
if (validationResult != B_OK) {
SetErrorMessage("Validation of setting partition content name "
"failed!");
return validationResult;
}
// everything OK, let's do the job
KDiskSystem* diskSystem = partition->DiskSystem();
DiskSystemLoader loader(diskSystem);
locker.Unlock();
status_t result = diskSystem->SetContentName(partition,
fContentName, this);
if (result != B_OK) {
SetErrorMessage("Setting name of the partition's content "
"failed!" );
}
return result;
}
} else {
SetErrorMessage("Couldn't find partition!");
return B_ENTRY_NOT_FOUND;
}
return B_ERROR;
}
@@ -1,42 +0,0 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Lubos Kulic <[email protected]>
*/
#ifndef _K_DISK_DEVICE_SET_NAME_JOB_H
#define _K_DISK_DEVICE_SET_NAME_JOB_H
#include <KDiskDeviceJob.h>
namespace BPrivate {
namespace DiskDevice {
/**
* Sets the name for partition/device and/or its content
*
* - can set both name and content name for the partition - but
* it's possible to create it with only one of these name parameters and so
* set only one of the names
*/
class KSetNameJob : public KDiskDeviceJob {
public:
KSetNameJob(partition_id parentID, partition_id partitionID,
const char* name, const char* contentName);
virtual ~KSetNameJob();
virtual status_t Do();
private:
char* fName;
char* fContentName;
};
}
}
using BPrivate::DiskDevice::KSetNameJob;
#endif
@@ -1,145 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KPartition.h>
#include <KPartitionVisitor.h>
#include <string.h>
#include "KSetParametersJob.h"
#include "ddm_operation_validation.h"
/**
Creates the job.
\param partition the partition whose params (or content params) should be set
\param parameters the new parameters for the partition
\param contentParameters the new parameters for partition's content
*/
KSetParametersJob::KSetParametersJob(partition_id parent,
partition_id partition, const char *parameters,
const char *contentParameters)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_SET_TYPE, partition, parent),
fParams(!parameters ? NULL : strdup(parameters)),
fContentParams(!contentParameters ? NULL : strdup(contentParameters))
{
SetDescription("setting partition parameters&content parameters");
}
KSetParametersJob::~KSetParametersJob()
{
free(fParams);
free(fContentParams);
}
status_t
KSetParametersJob::Do()
{
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
KPartition *partition = manager->WriteLockPartition(PartitionID());
if (partition) {
if (!fParams && !fContentParams) {
SetErrorMessage("No parameter to set.");
return B_BAD_VALUE;
}
PartitionRegistrar registrar(partition, true);
PartitionRegistrar deviceRegistrar(partition->Device(), true);
// TODO is lock necessary?
DeviceWriteLocker locker(partition->Device(), true);
// all descendants should be marked busy/descendant busy
if (IsPartitionNotBusy(partition)) {
SetErrorMessage("Can't set parameters for non-busy partition!");
return B_ERROR;
}
// TODO unlock?
if (fParams) {
// basic checks
if (!partition->ParentDiskSystem()) {
SetErrorMessage("Partition has no parent disk system!");
return B_BAD_VALUE;
}
// TODO maybe give copy of parameters?
// we have some parameters to set
// TODO: The parameters are already validated and should not be changed again!
status_t validationResult = validate_set_partition_parameters(
partition, partition->ChangeCounter(), fParams, false);
KDiskSystem *parentDiskSystem = partition->ParentDiskSystem();
DiskSystemLoader loader(parentDiskSystem);
if (validationResult != B_OK) {
SetErrorMessage("Validation of setting partition parameters "
"failed.");
return validationResult;
}
locker.Unlock();
status_t setParametersResult = parentDiskSystem->SetParameters(
partition, fParams, this);
if (setParametersResult != B_OK) {
SetErrorMessage( "Setting partition parameters failed." );
}
}
if (fContentParams) {
// basic checks
if (!partition->DiskSystem()) {
SetErrorMessage("Partition has no disk system!");
return B_BAD_VALUE;
}
// TODO: The parameters are already validated and should not be changed again!
status_t validationResult
= validate_set_partition_content_parameters(partition,
partition->ChangeCounter(), fContentParams, false);
if (validationResult != B_OK) {
SetErrorMessage("Validation of setting partition content "
"parameters failed.");
return validationResult;
}
KDiskSystem *diskSystem = partition->DiskSystem();
DiskSystemLoader loader(diskSystem);
locker.Unlock();
status_t result = diskSystem->SetContentParameters(partition,
fContentParams, this);
if (result != B_OK) {
SetErrorMessage("Setting partition content parameters failed.");
}
}
// TODO: Check return values!
return B_OK;
} else {
SetErrorMessage( "Couldn't find partition" );
return B_ENTRY_NOT_FOUND;
}
}
@@ -1,42 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
* Lubos Kulic <[email protected]>
*/
#ifndef _K_DISK_DEVICE_SET_PARAMETERS_JOB_H
#define _K_DISK_DEVICE_SET_PARAMETERS_JOB_H
#include "KDiskDeviceJob.h"
namespace BPrivate {
namespace DiskDevice {
/**
* Sets the parameters for partition and/or for its content
*
* - can set both partition parameters and parameters for its content -
* but it's possible to create it with only one of these parameters
*/
class KSetParametersJob : public KDiskDeviceJob {
public:
KSetParametersJob(partition_id parent, partition_id partition,
const char *parameters, const char *contentParameters);
virtual ~KSetParametersJob();
virtual status_t Do();
private:
char * fParams, * fContentParams;
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KSetParametersJob;
#endif // _DISK_DEVICE_SET_PARAMETERS_JOB_H
@@ -1,96 +0,0 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Lubos Kulic <[email protected]>
*/
#include <KPartition.h>
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KDiskSystem.h>
#include <KPartitionVisitor.h>
#include <string.h>
#include "KSetTypeJob.h"
#include "ddm_operation_validation.h"
/**
Creates the job.
\param partitionID the partition whose type should be set
\param type the new type for the partition
*/
KSetTypeJob::KSetTypeJob(partition_id parentID, partition_id partitionID,
const char *type)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_SET_TYPE, partitionID, parentID),
fType(!type ? NULL : strdup(type))
{
SetDescription("setting partition type");
}
KSetTypeJob::~KSetTypeJob()
{
}
status_t
KSetTypeJob::Do()
{
KDiskDeviceManager* manager = KDiskDeviceManager::Default();
KPartition* partition = manager->WriteLockPartition(PartitionID());
if (partition) {
PartitionRegistrar registrar(partition, true);
PartitionRegistrar deviceRegistrar(partition->Device(), true);
// TODO is lock necessary?
DeviceWriteLocker locker(partition->Device(), true);
// basic checks
if (!partition->ParentDiskSystem()) {
SetErrorMessage("Partition has no parent disk system!");
return B_BAD_VALUE;
}
if (!fType) {
SetErrorMessage("No type to set!");
return B_BAD_VALUE;
}
// TODO: The parameters are already validated and should not be changed again!
status_t validationResult = validate_set_partition_type(
partition, partition->ChangeCounter(), fType, false);
if (validationResult != B_OK) {
SetErrorMessage("Validation of setting partition type failed!");
return validationResult;
}
// everything OK, let's do the job
KDiskSystem* parentDiskSystem = partition->ParentDiskSystem();
DiskSystemLoader loader(parentDiskSystem);
status_t setTypeResult = parentDiskSystem->SetType(partition, fType,
this);
if (setTypeResult != B_OK) {
SetErrorMessage("Setting partition type failed!");
return setTypeResult;
}
return B_OK;
} else {
SetErrorMessage("Couldn't find partition!");
return B_ENTRY_NOT_FOUND;
}
}
@@ -1,37 +0,0 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Lubos Kulic <[email protected]>
*/
#ifndef _K_DISK_DEVICE_SET_TYPE_JOB_H
#define _K_DISK_DEVICE_SET_TYPE_JOB_H
#include <KDiskDeviceJob.h>
namespace BPrivate {
namespace DiskDevice {
/**
* Sets type of the device/partition
*/
class KSetTypeJob : public KDiskDeviceJob
{
public:
KSetTypeJob(partition_id parentID, partition_id partitionID, const char *type);
virtual ~KSetTypeJob();
virtual status_t Do();
private:
char * fType;
};
}
}
using BPrivate::DiskDevice::KSetTypeJob;
#endif
@@ -1,83 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#include <stdio.h>
#include <KernelExport.h>
#include <DiskDeviceDefs.h>
#include <KDiskDevice.h>
#include <KDiskDeviceManager.h>
#include <KDiskDeviceUtils.h>
#include <KPartition.h>
#include <KPartitionVisitor.h>
#include "KUninitializeJob.h"
// debugging
//#define DBG(x)
#define DBG(x) x
#define OUT dprintf
// constructor
KUninitializeJob::KUninitializeJob(partition_id partitionID)
: KDiskDeviceJob(B_DISK_DEVICE_JOB_UNINITIALIZE, partitionID)
{
SetDescription("uninitializing partition");
}
// destructor
KUninitializeJob::~KUninitializeJob()
{
}
// Do
status_t
KUninitializeJob::Do()
{
DBG(OUT("KUninitializeJob::Do(%ld)\n", PartitionID()));
// get the partition
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
if (KPartition *partition = manager->WriteLockPartition(PartitionID())) {
PartitionRegistrar registrar1(partition, true);
PartitionRegistrar registrar2(partition->Device(), true);
DeviceWriteLocker locker(partition->Device(), true);
// the partition's descendants must not be mounted
struct IsMountedVisitor : KPartitionVisitor {
virtual bool VisitPre(KPartition *partition)
{
return partition->IsMounted();
}
} isMountedVisitor;
if (partition->VisitEachDescendant(&isMountedVisitor)) {
SetErrorMessage("Can't uninitialize mounted partition.");
return B_ERROR;
}
// all descendants should be marked busy/descendant busy
struct IsNotBusyVisitor : KPartitionVisitor {
virtual bool VisitPre(KPartition *partition)
{
return !(partition->IsBusy() || partition->IsDescendantBusy());
}
} isNotBusyVisitor;
if (partition->VisitEachDescendant(&isNotBusyVisitor)) {
SetErrorMessage("Can't uninitialize non-busy partition!");
return B_ERROR;
}
// things look good: uninitialize the thing
status_t error = partition->UninitializeContents();
if (error != B_OK)
SetErrorMessage("Failed to uninitialize partition contents!");
return error;
} else {
SetErrorMessage("Couldn't find partition.");
return B_ENTRY_NOT_FOUND;
}
// cannot come here
return B_ERROR;
}
@@ -1,32 +0,0 @@
/*
* Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#ifndef _K_DISK_DEVICE_UNINITIALIZE_JOB_H
#define _K_DISK_DEVICE_UNINITIALIZE_JOB_H
#include "KDiskDeviceJob.h"
namespace BPrivate {
namespace DiskDevice {
/**
* Uninitializes the partition/device
*/
class KUninitializeJob : public KDiskDeviceJob {
public:
KUninitializeJob(partition_id partitionID);
virtual ~KUninitializeJob();
virtual status_t Do();
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KUninitializeJob;
#endif // _K_DISK_DEVICE_UNINITIALIZE_JOB_H
+1 -1
View File
@@ -5350,7 +5350,7 @@ fs_mount(char *path, const char *device, const char *fsName, uint32 flags,
// an invalid path, or the path refers to an image file. We try
// to let the DDM create a file device for the path.
partition_id deviceID = ddm->CreateFileDevice(normalizedDevice.Path(),
&newlyCreatedFileDevice, false);
&newlyCreatedFileDevice);
if (deviceID >= 0) {
partition = ddm->RegisterPartition(deviceID, true);
if (newlyCreatedFileDevice)