* Haiku kernel interface emulation: Retrieve the capabilities for each vnode.
We do some caching using a hash table indexed by the operations vector. * Pass the vnode capabilities to the kernel module. * In the kernel tailor the operation vectors for volumes and vnodes passed to the VFS according to the respective capabilities. This way those vectors look pretty much like those from the client FS. This saves unnecessary calls when hooks are not implemented and should also fix compatibility problems in cases where not implementing a hook and returning an error don't mean the same to the VFS. * Inlined some of the kernel module Volume class getters. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29572 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -509,9 +509,10 @@ class ReadVNodeReply : public ReplyRequest {
|
|||||||
public:
|
public:
|
||||||
ReadVNodeReply() : ReplyRequest(READ_VNODE_REPLY) {}
|
ReadVNodeReply() : ReplyRequest(READ_VNODE_REPLY) {}
|
||||||
|
|
||||||
void* node;
|
void* node;
|
||||||
int type;
|
int type;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
|
FSVNodeCapabilities capabilities;
|
||||||
};
|
};
|
||||||
|
|
||||||
// WriteVNodeRequest
|
// WriteVNodeRequest
|
||||||
@@ -1604,9 +1605,10 @@ class NewVNodeRequest : public Request {
|
|||||||
public:
|
public:
|
||||||
NewVNodeRequest() : Request(NEW_VNODE_REQUEST) {}
|
NewVNodeRequest() : Request(NEW_VNODE_REQUEST) {}
|
||||||
|
|
||||||
dev_t nsid;
|
dev_t nsid;
|
||||||
ino_t vnid;
|
ino_t vnid;
|
||||||
void* node;
|
void* node;
|
||||||
|
FSVNodeCapabilities capabilities;
|
||||||
};
|
};
|
||||||
|
|
||||||
// NewVNodeReply
|
// NewVNodeReply
|
||||||
@@ -1620,11 +1622,12 @@ class PublishVNodeRequest : public Request {
|
|||||||
public:
|
public:
|
||||||
PublishVNodeRequest() : Request(PUBLISH_VNODE_REQUEST) {}
|
PublishVNodeRequest() : Request(PUBLISH_VNODE_REQUEST) {}
|
||||||
|
|
||||||
dev_t nsid;
|
dev_t nsid;
|
||||||
ino_t vnid;
|
ino_t vnid;
|
||||||
void* node;
|
void* node;
|
||||||
int type;
|
int type;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
|
FSVNodeCapabilities capabilities;
|
||||||
};
|
};
|
||||||
|
|
||||||
// PublishVNodeReply
|
// PublishVNodeReply
|
||||||
|
|||||||
@@ -3,18 +3,22 @@
|
|||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "Volume.h"
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
#include "AutoLocker.h"
|
#include "AutoLocker.h"
|
||||||
#include "Compatibility.h"
|
#include "Compatibility.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include "HashMap.h"
|
#include "HashMap.h"
|
||||||
|
#include "kernel_interface.h"
|
||||||
#include "KernelRequestHandler.h"
|
#include "KernelRequestHandler.h"
|
||||||
#include "PortReleaser.h"
|
#include "PortReleaser.h"
|
||||||
#include "RequestAllocator.h"
|
#include "RequestAllocator.h"
|
||||||
#include "Requests.h"
|
#include "Requests.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "SingleReplyRequestHandler.h"
|
#include "SingleReplyRequestHandler.h"
|
||||||
#include "Volume.h"
|
|
||||||
|
|
||||||
// The time after which the notification thread times out at the port and
|
// The time after which the notification thread times out at the port and
|
||||||
// restarts the loop. Of interest only when the FS is deleted. It is the
|
// restarts the loop. Of interest only when the FS is deleted. It is the
|
||||||
@@ -30,7 +34,6 @@ struct FileSystem::SelectSyncMap
|
|||||||
FileSystem::FileSystem()
|
FileSystem::FileSystem()
|
||||||
:
|
:
|
||||||
fVolumes(),
|
fVolumes(),
|
||||||
fVolumeLock(),
|
|
||||||
fName(),
|
fName(),
|
||||||
fTeam(-1),
|
fTeam(-1),
|
||||||
fNotificationPort(NULL),
|
fNotificationPort(NULL),
|
||||||
@@ -42,6 +45,8 @@ FileSystem::FileSystem()
|
|||||||
fInitialized(false),
|
fInitialized(false),
|
||||||
fTerminating(false)
|
fTerminating(false)
|
||||||
{
|
{
|
||||||
|
mutex_init(&fVolumeLock, "userlandfs volumes");
|
||||||
|
mutex_init(&fVNodeOpsLock, "userlandfs vnode ops");
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
@@ -65,6 +70,18 @@ FileSystem::~FileSystem()
|
|||||||
delete fSelectSyncs;
|
delete fSelectSyncs;
|
||||||
}
|
}
|
||||||
delete fSettings;
|
delete fSettings;
|
||||||
|
|
||||||
|
// delete vnode ops vectors -- there shouldn't be any left, though
|
||||||
|
VNodeOps* ops = fVNodeOps.Clear();
|
||||||
|
int32 count = 0;
|
||||||
|
while (ops != NULL) {
|
||||||
|
count++;
|
||||||
|
VNodeOps* next = ops->fNext;
|
||||||
|
free(ops);
|
||||||
|
ops = next;
|
||||||
|
}
|
||||||
|
if (count > 0)
|
||||||
|
WARN(("Deleted %ld vnode ops vectors!\n", count));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
@@ -83,6 +100,11 @@ FileSystem::Init(const char* name, team_id team, Port::Info* infos, int32 count,
|
|||||||
if (!fName.SetTo(name))
|
if (!fName.SetTo(name))
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// init VNodeOps map
|
||||||
|
status_t error = fVNodeOps.Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
fTeam = team;
|
fTeam = team;
|
||||||
fCapabilities = capabilities;
|
fCapabilities = capabilities;
|
||||||
|
|
||||||
@@ -96,7 +118,7 @@ FileSystem::Init(const char* name, team_id team, Port::Info* infos, int32 count,
|
|||||||
fNotificationPort = new(nothrow) RequestPort(infos);
|
fNotificationPort = new(nothrow) RequestPort(infos);
|
||||||
if (!fNotificationPort)
|
if (!fNotificationPort)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
status_t error = fNotificationPort->InitCheck();
|
error = fNotificationPort->InitCheck();
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -198,18 +220,18 @@ FileSystem::Mount(fs_volume* fsVolume, const char* device, uint32 flags,
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
// add volume to the volume list
|
// add volume to the volume list
|
||||||
fVolumeLock.Lock();
|
MutexLocker locker(fVolumeLock);
|
||||||
status_t error = fVolumes.PushBack(volume);
|
status_t error = fVolumes.PushBack(volume);
|
||||||
fVolumeLock.Unlock();
|
locker.Unlock();
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
// mount volume
|
// mount volume
|
||||||
error = volume->Mount(device, flags, parameters);
|
error = volume->Mount(device, flags, parameters);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
fVolumeLock.Lock();
|
MutexLocker locker(fVolumeLock);
|
||||||
fVolumes.Remove(volume);
|
fVolumes.Remove(volume);
|
||||||
fVolumeLock.Unlock();
|
locker.Unlock();
|
||||||
volume->RemoveReference();
|
volume->RemoveReference();
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -256,16 +278,15 @@ FileSystem::Initialize(const char* deviceName, const char* parameters,
|
|||||||
void
|
void
|
||||||
FileSystem::VolumeUnmounted(Volume* volume)
|
FileSystem::VolumeUnmounted(Volume* volume)
|
||||||
{
|
{
|
||||||
fVolumeLock.Lock();
|
MutexLocker locker(fVolumeLock);
|
||||||
fVolumes.Remove(volume);
|
fVolumes.Remove(volume);
|
||||||
fVolumeLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetVolume
|
// GetVolume
|
||||||
Volume*
|
Volume*
|
||||||
FileSystem::GetVolume(dev_t id)
|
FileSystem::GetVolume(dev_t id)
|
||||||
{
|
{
|
||||||
AutoLocker<Locker> _(fVolumeLock);
|
MutexLocker _(fVolumeLock);
|
||||||
for (Vector<Volume*>::Iterator it = fVolumes.Begin();
|
for (Vector<Volume*>::Iterator it = fVolumes.Begin();
|
||||||
it != fVolumes.End();
|
it != fVolumes.End();
|
||||||
it++) {
|
it++) {
|
||||||
@@ -318,6 +339,7 @@ FileSystem::RemoveSelectSyncEntry(selectsync* sync)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// KnowsSelectSyncEntry
|
// KnowsSelectSyncEntry
|
||||||
bool
|
bool
|
||||||
FileSystem::KnowsSelectSyncEntry(selectsync* sync)
|
FileSystem::KnowsSelectSyncEntry(selectsync* sync)
|
||||||
@@ -325,6 +347,54 @@ FileSystem::KnowsSelectSyncEntry(selectsync* sync)
|
|||||||
return fSelectSyncs->ContainsKey(sync);
|
return fSelectSyncs->ContainsKey(sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// GetVNodeOps
|
||||||
|
VNodeOps*
|
||||||
|
FileSystem::GetVNodeOps(const FSVNodeCapabilities& capabilities)
|
||||||
|
{
|
||||||
|
MutexLocker locker(fVNodeOpsLock);
|
||||||
|
|
||||||
|
// do we already have ops for those capabilities
|
||||||
|
VNodeOps* ops = fVNodeOps.Lookup(capabilities);
|
||||||
|
if (ops != NULL) {
|
||||||
|
ops->refCount++;
|
||||||
|
return ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no, create a new object
|
||||||
|
fs_vnode_ops* opsVector = new(std::nothrow) fs_vnode_ops;
|
||||||
|
if (opsVector == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// set the operations
|
||||||
|
_InitVNodeOpsVector(opsVector, capabilities);
|
||||||
|
|
||||||
|
// create the VNodeOps object
|
||||||
|
ops = new(std::nothrow) VNodeOps(capabilities, opsVector);
|
||||||
|
if (ops == NULL) {
|
||||||
|
delete opsVector;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fVNodeOps.Insert(ops);
|
||||||
|
|
||||||
|
return ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PutVNodeOps
|
||||||
|
void
|
||||||
|
FileSystem::PutVNodeOps(VNodeOps* ops)
|
||||||
|
{
|
||||||
|
MutexLocker locker(fVNodeOpsLock);
|
||||||
|
|
||||||
|
if (--ops->refCount == 0) {
|
||||||
|
fVNodeOps.Remove(ops);
|
||||||
|
delete ops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// IsUserlandServerThread
|
// IsUserlandServerThread
|
||||||
bool
|
bool
|
||||||
FileSystem::IsUserlandServerThread() const
|
FileSystem::IsUserlandServerThread() const
|
||||||
@@ -334,6 +404,108 @@ FileSystem::IsUserlandServerThread() const
|
|||||||
return (info.team == fUserlandServerTeam);
|
return (info.team == fUserlandServerTeam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// _InitVNodeOpsVector
|
||||||
|
void
|
||||||
|
FileSystem::_InitVNodeOpsVector(fs_vnode_ops* ops,
|
||||||
|
const FSVNodeCapabilities& capabilities)
|
||||||
|
{
|
||||||
|
memcpy(ops, &gUserlandFSVnodeOps, sizeof(fs_vnode_ops));
|
||||||
|
|
||||||
|
#undef CLEAR_UNSUPPORTED
|
||||||
|
#define CLEAR_UNSUPPORTED(capability, op) \
|
||||||
|
if (!capabilities.Get(capability)) \
|
||||||
|
ops->op = NULL
|
||||||
|
|
||||||
|
// vnode operations
|
||||||
|
// FS_VNODE_CAPABILITY_LOOKUP: lookup
|
||||||
|
// FS_VNODE_CAPABILITY_GET_VNODE_NAME: get_vnode_name
|
||||||
|
// emulated in userland
|
||||||
|
// FS_VNODE_CAPABILITY_PUT_VNODE: put_vnode
|
||||||
|
// FS_VNODE_CAPABILITY_REMOVE_VNODE: remove_vnode
|
||||||
|
// needed by Volume to clean up
|
||||||
|
|
||||||
|
// asynchronous I/O
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_IO, io);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_CANCEL_IO, cancel_io);
|
||||||
|
|
||||||
|
// cache file access
|
||||||
|
ops->get_file_map = NULL; // never used
|
||||||
|
|
||||||
|
// common operations
|
||||||
|
// FS_VNODE_CAPABILITY_IOCTL: ioctl
|
||||||
|
// needed by Volume
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_SET_FLAGS, set_flags);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_SELECT, select);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_DESELECT, deselect);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_FSYNC, fsync);
|
||||||
|
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_READ_SYMLINK, read_symlink);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_CREATE_SYMLINK, create_symlink);
|
||||||
|
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_LINK, link);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_UNLINK, unlink);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_RENAME, rename);
|
||||||
|
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_ACCESS, access);
|
||||||
|
// FS_VNODE_CAPABILITY_READ_STAT: read_stat
|
||||||
|
// needed by Volume
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_WRITE_STAT, write_stat);
|
||||||
|
|
||||||
|
// file operations
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_CREATE, create);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_OPEN, open);
|
||||||
|
// FS_VNODE_CAPABILITY_CLOSE: close
|
||||||
|
// needed by Volume
|
||||||
|
// FS_VNODE_CAPABILITY_FREE_COOKIE: free_cookie
|
||||||
|
// needed by Volume
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_READ, read);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_WRITE, write);
|
||||||
|
|
||||||
|
// directory operations
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_CREATE_DIR, create_dir);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_REMOVE_DIR, remove_dir);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_OPEN_DIR, open_dir);
|
||||||
|
// FS_VNODE_CAPABILITY_CLOSE_DIR: close_dir
|
||||||
|
// needed by Volume
|
||||||
|
// FS_VNODE_CAPABILITY_FREE_DIR_COOKIE: free_dir_cookie
|
||||||
|
// needed by Volume
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_READ_DIR, read_dir);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_REWIND_DIR, rewind_dir);
|
||||||
|
|
||||||
|
// attribute directory operations
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_OPEN_ATTR_DIR, open_attr_dir);
|
||||||
|
// FS_VNODE_CAPABILITY_CLOSE_ATTR_DIR: close_attr_dir
|
||||||
|
// needed by Volume
|
||||||
|
// FS_VNODE_CAPABILITY_FREE_ATTR_DIR_COOKIE: free_attr_dir_cookie
|
||||||
|
// needed by Volume
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_READ_ATTR_DIR, read_attr_dir);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_REWIND_ATTR_DIR, rewind_attr_dir);
|
||||||
|
|
||||||
|
// attribute operations
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_CREATE_ATTR, create_attr);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_OPEN_ATTR, open_attr);
|
||||||
|
// FS_VNODE_CAPABILITY_CLOSE_ATTR: close_attr
|
||||||
|
// needed by Volume
|
||||||
|
// FS_VNODE_CAPABILITY_FREE_ATTR_COOKIE: free_attr_cookie
|
||||||
|
// needed by Volume
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_READ_ATTR, read_attr);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_WRITE_ATTR, write_attr);
|
||||||
|
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_READ_ATTR_STAT, read_attr_stat);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_WRITE_ATTR_STAT, write_attr_stat);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_RENAME_ATTR, rename_attr);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_REMOVE_ATTR, remove_attr);
|
||||||
|
|
||||||
|
// support for node and FS layers
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_CREATE_SPECIAL_NODE,
|
||||||
|
create_special_node);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VNODE_CAPABILITY_GET_SUPER_VNODE, get_super_vnode);
|
||||||
|
|
||||||
|
#undef CLEAR_UNSUPPORTED
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// _NotificationThreadEntry
|
// _NotificationThreadEntry
|
||||||
int32
|
int32
|
||||||
FileSystem::_NotificationThreadEntry(void* data)
|
FileSystem::_NotificationThreadEntry(void* data)
|
||||||
@@ -341,6 +513,7 @@ FileSystem::_NotificationThreadEntry(void* data)
|
|||||||
return ((FileSystem*)data)->_NotificationThread();
|
return ((FileSystem*)data)->_NotificationThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// _NotificationThread
|
// _NotificationThread
|
||||||
int32
|
int32
|
||||||
FileSystem::_NotificationThread()
|
FileSystem::_NotificationThread()
|
||||||
|
|||||||
@@ -7,6 +7,10 @@
|
|||||||
|
|
||||||
#include <fs_interface.h>
|
#include <fs_interface.h>
|
||||||
|
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
#include <lock.h>
|
||||||
|
|
||||||
#include "FSCapabilities.h"
|
#include "FSCapabilities.h"
|
||||||
#include "LazyInitializable.h"
|
#include "LazyInitializable.h"
|
||||||
#include "Locker.h"
|
#include "Locker.h"
|
||||||
@@ -20,6 +24,42 @@ struct IOCtlInfo;
|
|||||||
class Settings;
|
class Settings;
|
||||||
class Volume;
|
class Volume;
|
||||||
|
|
||||||
|
|
||||||
|
struct VNodeOps : HashTableLink<VNodeOps> {
|
||||||
|
int32 refCount;
|
||||||
|
FSVNodeCapabilities capabilities;
|
||||||
|
fs_vnode_ops* ops;
|
||||||
|
|
||||||
|
VNodeOps(const FSVNodeCapabilities& capabilities, fs_vnode_ops* ops)
|
||||||
|
:
|
||||||
|
refCount(1),
|
||||||
|
capabilities(capabilities),
|
||||||
|
ops(ops)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~VNodeOps()
|
||||||
|
{
|
||||||
|
delete ops;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct VNodeOpsHashDefinition {
|
||||||
|
typedef FSVNodeCapabilities KeyType;
|
||||||
|
typedef VNodeOps ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(const FSVNodeCapabilities& key) const
|
||||||
|
{ return key.GetHashCode(); }
|
||||||
|
size_t Hash(const VNodeOps* value) const
|
||||||
|
{ return HashKey(value->capabilities); }
|
||||||
|
bool Compare(const FSVNodeCapabilities& key, const VNodeOps* value) const
|
||||||
|
{ return value->capabilities == key; }
|
||||||
|
HashTableLink<VNodeOps>* GetLink(VNodeOps* value) const
|
||||||
|
{ return value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class FileSystem {
|
class FileSystem {
|
||||||
public:
|
public:
|
||||||
FileSystem();
|
FileSystem();
|
||||||
@@ -52,9 +92,16 @@ public:
|
|||||||
void RemoveSelectSyncEntry(selectsync* sync);
|
void RemoveSelectSyncEntry(selectsync* sync);
|
||||||
bool KnowsSelectSyncEntry(selectsync* sync);
|
bool KnowsSelectSyncEntry(selectsync* sync);
|
||||||
|
|
||||||
|
VNodeOps* GetVNodeOps(
|
||||||
|
const FSVNodeCapabilities& capabilities);
|
||||||
|
void PutVNodeOps(VNodeOps* ops);
|
||||||
|
|
||||||
bool IsUserlandServerThread() const;
|
bool IsUserlandServerThread() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _InitVNodeOpsVector(fs_vnode_ops* ops,
|
||||||
|
const FSVNodeCapabilities& capabilities);
|
||||||
|
|
||||||
static int32 _NotificationThreadEntry(void* data);
|
static int32 _NotificationThreadEntry(void* data);
|
||||||
int32 _NotificationThread();
|
int32 _NotificationThread();
|
||||||
|
|
||||||
@@ -62,9 +109,12 @@ private:
|
|||||||
friend class KernelDebug;
|
friend class KernelDebug;
|
||||||
struct SelectSyncEntry;
|
struct SelectSyncEntry;
|
||||||
struct SelectSyncMap;
|
struct SelectSyncMap;
|
||||||
|
typedef OpenHashTable<VNodeOpsHashDefinition> VNodeOpsMap;
|
||||||
|
|
||||||
Vector<Volume*> fVolumes;
|
Vector<Volume*> fVolumes;
|
||||||
Locker fVolumeLock;
|
mutex fVolumeLock;
|
||||||
|
VNodeOpsMap fVNodeOps;
|
||||||
|
mutex fVNodeOpsLock;
|
||||||
String fName;
|
String fName;
|
||||||
team_id fTeam;
|
team_id fTeam;
|
||||||
FSCapabilities fCapabilities;
|
FSCapabilities fCapabilities;
|
||||||
|
|||||||
@@ -403,8 +403,11 @@ KernelRequestHandler::_HandleRequest(NewVNodeRequest* request)
|
|||||||
Volume* volume = NULL;
|
Volume* volume = NULL;
|
||||||
status_t result = _GetVolume(request->nsid, &volume);
|
status_t result = _GetVolume(request->nsid, &volume);
|
||||||
VolumePutter _(volume);
|
VolumePutter _(volume);
|
||||||
if (result == B_OK)
|
if (result == B_OK) {
|
||||||
result = volume->NewVNode(request->vnid, request->node);
|
result = volume->NewVNode(request->vnid, request->node,
|
||||||
|
request->capabilities);
|
||||||
|
}
|
||||||
|
|
||||||
// prepare the reply
|
// prepare the reply
|
||||||
RequestAllocator allocator(fPort->GetPort());
|
RequestAllocator allocator(fPort->GetPort());
|
||||||
NewVNodeReply* reply;
|
NewVNodeReply* reply;
|
||||||
@@ -412,6 +415,7 @@ KernelRequestHandler::_HandleRequest(NewVNodeRequest* request)
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
reply->error = result;
|
reply->error = result;
|
||||||
|
|
||||||
// send the reply
|
// send the reply
|
||||||
return fPort->SendRequest(&allocator);
|
return fPort->SendRequest(&allocator);
|
||||||
}
|
}
|
||||||
@@ -426,7 +430,7 @@ KernelRequestHandler::_HandleRequest(PublishVNodeRequest* request)
|
|||||||
VolumePutter _(volume);
|
VolumePutter _(volume);
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
result = volume->PublishVNode(request->vnid, request->node,
|
result = volume->PublishVNode(request->vnid, request->node,
|
||||||
request->type, request->flags);
|
request->type, request->flags, request->capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare the reply
|
// prepare the reply
|
||||||
|
|||||||
@@ -47,22 +47,32 @@ static const bigtime_t kUserlandServerlandPortTimeout = 10000000; // 10s
|
|||||||
|
|
||||||
// VNode
|
// VNode
|
||||||
struct Volume::VNode : HashTableLink<VNode> {
|
struct Volume::VNode : HashTableLink<VNode> {
|
||||||
ino_t id;
|
ino_t id;
|
||||||
void* clientNode;
|
void* clientNode;
|
||||||
void* fileCache;
|
void* fileCache;
|
||||||
int32 useCount;
|
VNodeOps* ops;
|
||||||
bool valid;
|
int32 useCount;
|
||||||
|
bool valid;
|
||||||
|
|
||||||
VNode(ino_t id, void* clientNode)
|
VNode(ino_t id, void* clientNode, VNodeOps* ops)
|
||||||
:
|
:
|
||||||
id(id),
|
id(id),
|
||||||
clientNode(clientNode),
|
clientNode(clientNode),
|
||||||
fileCache(NULL),
|
fileCache(NULL),
|
||||||
|
ops(ops),
|
||||||
useCount(0),
|
useCount(0),
|
||||||
valid(true)
|
valid(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Delete(Volume* volume)
|
||||||
|
{
|
||||||
|
if (ops != NULL)
|
||||||
|
volume->GetFileSystem()->PutVNodeOps(ops);
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected: // should be private, but gcc 2.95.3 issues a warning
|
||||||
~VNode()
|
~VNode()
|
||||||
{
|
{
|
||||||
if (fileCache != NULL)
|
if (fileCache != NULL)
|
||||||
@@ -278,27 +288,6 @@ Volume::~Volume()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// GetFileSystem
|
|
||||||
FileSystem*
|
|
||||||
Volume::GetFileSystem() const
|
|
||||||
{
|
|
||||||
return fFileSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserlandVolume
|
|
||||||
void*
|
|
||||||
Volume::GetUserlandVolume() const
|
|
||||||
{
|
|
||||||
return fUserlandVolume;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRootID
|
|
||||||
ino_t
|
|
||||||
Volume::GetRootID() const
|
|
||||||
{
|
|
||||||
return fRootID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// #pragma mark - client methods
|
// #pragma mark - client methods
|
||||||
|
|
||||||
// GetVNode
|
// GetVNode
|
||||||
@@ -342,7 +331,8 @@ PRINT(("acquire_vnode(%ld, %lld)\n", GetID(), vnid));
|
|||||||
|
|
||||||
// NewVNode
|
// NewVNode
|
||||||
status_t
|
status_t
|
||||||
Volume::NewVNode(ino_t vnid, void* clientNode)
|
Volume::NewVNode(ino_t vnid, void* clientNode,
|
||||||
|
const FSVNodeCapabilities& capabilities)
|
||||||
{
|
{
|
||||||
PRINT(("new_vnode(%ld, %lld)\n", GetID(), vnid));
|
PRINT(("new_vnode(%ld, %lld)\n", GetID(), vnid));
|
||||||
// lookup the node
|
// lookup the node
|
||||||
@@ -353,17 +343,24 @@ PRINT(("new_vnode(%ld, %lld)\n", GetID(), vnid));
|
|||||||
RETURN_ERROR(B_BAD_VALUE);
|
RETURN_ERROR(B_BAD_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the node
|
// get the ops vector for the node
|
||||||
node = new(std::nothrow) VNode(vnid, clientNode);
|
VNodeOps* ops = fFileSystem->GetVNodeOps(capabilities);
|
||||||
if (node == NULL)
|
if (ops == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
// create the node
|
||||||
|
node = new(std::nothrow) VNode(vnid, clientNode, ops);
|
||||||
|
if (node == NULL) {
|
||||||
|
fFileSystem->PutVNodeOps(ops);
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
// tell the VFS
|
// tell the VFS
|
||||||
status_t error = new_vnode(fFSVolume, vnid, node, &gUserlandFSVnodeOps);
|
status_t error = new_vnode(fFSVolume, vnid, node, node->ops->ops);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
delete node;
|
node->Delete(this);
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,7 +373,8 @@ PRINT(("new_vnode(%ld, %lld)\n", GetID(), vnid));
|
|||||||
|
|
||||||
// PublishVNode
|
// PublishVNode
|
||||||
status_t
|
status_t
|
||||||
Volume::PublishVNode(ino_t vnid, void* clientNode, int type, uint32 flags)
|
Volume::PublishVNode(ino_t vnid, void* clientNode, int type, uint32 flags,
|
||||||
|
const FSVNodeCapabilities& capabilities)
|
||||||
{
|
{
|
||||||
PRINT(("publish_vnode(%ld, %lld, %p)\n", GetID(), vnid, clientNode));
|
PRINT(("publish_vnode(%ld, %lld, %p)\n", GetID(), vnid, clientNode));
|
||||||
// lookup the node
|
// lookup the node
|
||||||
@@ -386,21 +384,30 @@ PRINT(("publish_vnode(%ld, %lld, %p)\n", GetID(), vnid, clientNode));
|
|||||||
|
|
||||||
if (!nodeKnown) {
|
if (!nodeKnown) {
|
||||||
// The node is not yet known -- create it.
|
// The node is not yet known -- create it.
|
||||||
node = new(std::nothrow) VNode(vnid, clientNode);
|
|
||||||
if (node == NULL)
|
// get the ops vector for the node
|
||||||
|
VNodeOps* ops = fFileSystem->GetVNodeOps(capabilities);
|
||||||
|
if (ops == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
// create the node
|
||||||
|
node = new(std::nothrow) VNode(vnid, clientNode, ops);
|
||||||
|
if (node == NULL) {
|
||||||
|
fFileSystem->PutVNodeOps(ops);
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
// tell the VFS
|
// tell the VFS
|
||||||
status_t error = publish_vnode(fFSVolume, vnid, node, &gUserlandFSVnodeOps,
|
status_t error = publish_vnode(fFSVolume, vnid, node, node->ops->ops,
|
||||||
type, flags);
|
type, flags);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
// TODO: We should note whether the node was made known via new_vnode(). If so,
|
// TODO: We should note whether the node was made known via new_vnode(). If so,
|
||||||
// we should remove and delete it here!
|
// we should remove and delete it here!
|
||||||
if (!nodeKnown)
|
if (!nodeKnown)
|
||||||
delete node;
|
node->Delete(this);
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,29 +697,33 @@ Volume::Mount(const char* device, uint32 flags, const char* parameters)
|
|||||||
|
|
||||||
// mount
|
// mount
|
||||||
status_t error = _Mount(device, flags, parameters);
|
status_t error = _Mount(device, flags, parameters);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
if (error == B_OK) {
|
MutexLocker locker(fLock);
|
||||||
MutexLocker locker(fLock);
|
// fetch the root node, so that we can serve Walk() requests on it,
|
||||||
// fetch the root node, so that we can serve Walk() requests on it,
|
// after the connection to the userland server is gone
|
||||||
// after the connection to the userland server is gone
|
fRootNode = fVNodes->Lookup(fRootID);
|
||||||
fRootNode = fVNodes->Lookup(fRootID);
|
if (fRootNode == NULL) {
|
||||||
if (fRootNode == NULL) {
|
// The root node was not added while mounting. That's a serious
|
||||||
// The root node was not added while mounting. That's a serious
|
// problem -- not only because we don't have it, but also because
|
||||||
// problem -- not only because we don't have it, but also because
|
// the VFS requires publish_vnode() to be invoked for the root node.
|
||||||
// the VFS requires publish_vnode() to be invoked for the root node.
|
ERROR(("Volume::Mount(): new_vnode() was not called for root node! "
|
||||||
ERROR(("Volume::Mount(): new_vnode() was not called for root node! "
|
"Unmounting...\n"));
|
||||||
"Unmounting...\n"));
|
locker.Unlock();
|
||||||
locker.Unlock();
|
Unmount();
|
||||||
Unmount();
|
return B_ERROR;
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrement the root node use count. The publish_vnode() the client FS
|
|
||||||
// did will be balanced by the VFS.
|
|
||||||
if (fVNodeCountingEnabled)
|
|
||||||
fRootNode->useCount--;
|
|
||||||
}
|
}
|
||||||
return error;
|
|
||||||
|
// Decrement the root node use count. The publish_vnode() the client FS
|
||||||
|
// did will be balanced by the VFS.
|
||||||
|
if (fVNodeCountingEnabled)
|
||||||
|
fRootNode->useCount--;
|
||||||
|
|
||||||
|
// init the volume ops vector we'll give the VFS
|
||||||
|
_InitVolumeOps();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmount
|
// Unmount
|
||||||
@@ -729,7 +740,7 @@ Volume::Unmount()
|
|||||||
VNode* node = fVNodes->Clear(true);
|
VNode* node = fVNodes->Clear(true);
|
||||||
while (node != NULL) {
|
while (node != NULL) {
|
||||||
VNode* nextNode = node->fNext;
|
VNode* nextNode = node->fNext;
|
||||||
delete node;
|
node->Delete(this);
|
||||||
node = nextNode;
|
node = nextNode;
|
||||||
}
|
}
|
||||||
delete fVNodes;
|
delete fVNodes;
|
||||||
@@ -937,8 +948,8 @@ Volume::GetVNodeName(void* _node, char* buffer, size_t bufferSize)
|
|||||||
|
|
||||||
// ReadVNode
|
// ReadVNode
|
||||||
status_t
|
status_t
|
||||||
Volume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
Volume::ReadVNode(ino_t vnid, bool reenter, void** _node, fs_vnode_ops** _ops,
|
||||||
uint32* flags)
|
int* type, uint32* flags)
|
||||||
{
|
{
|
||||||
// get a free port
|
// get a free port
|
||||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||||
@@ -958,7 +969,7 @@ Volume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
|||||||
request->reenter = reenter;
|
request->reenter = reenter;
|
||||||
|
|
||||||
// add the uninitialized node to our map
|
// add the uninitialized node to our map
|
||||||
VNode* vnode = new(std::nothrow) VNode(vnid, NULL);
|
VNode* vnode = new(std::nothrow) VNode(vnid, NULL, NULL);
|
||||||
if (vnode == NULL)
|
if (vnode == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
vnode->valid = false;
|
vnode->valid = false;
|
||||||
@@ -983,14 +994,23 @@ Volume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
|||||||
return reply->error;
|
return reply->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the ops vector for the node
|
||||||
|
VNodeOps* ops = fFileSystem->GetVNodeOps(reply->capabilities);
|
||||||
|
if (ops == NULL) {
|
||||||
|
_RemoveInvalidVNode(vnid);
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
// everything went fine -- mark the node valid
|
// everything went fine -- mark the node valid
|
||||||
locker.Lock();
|
locker.Lock();
|
||||||
vnode->clientNode = reply->node;
|
vnode->clientNode = reply->node;
|
||||||
|
vnode->ops = ops;
|
||||||
vnode->valid = true;
|
vnode->valid = true;
|
||||||
|
|
||||||
*_node = vnode;
|
*_node = vnode;
|
||||||
*type = reply->type;
|
*type = reply->type;
|
||||||
*flags = reply->flags;
|
*flags = reply->flags;
|
||||||
|
*_ops = ops->ops;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1021,7 +1041,7 @@ Volume::RemoveVNode(void* _node, bool reenter)
|
|||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
void* clientNode = vnode->clientNode;
|
void* clientNode = vnode->clientNode;
|
||||||
delete vnode;
|
vnode->Delete(this);
|
||||||
|
|
||||||
// get a free port
|
// get a free port
|
||||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||||
@@ -3461,6 +3481,60 @@ Volume::RewindQuery(void* cookie)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
// #pragma mark ----- private implementations -----
|
// #pragma mark ----- private implementations -----
|
||||||
|
|
||||||
|
|
||||||
|
// _InitVolumeOps
|
||||||
|
void
|
||||||
|
Volume::_InitVolumeOps()
|
||||||
|
{
|
||||||
|
memcpy(&fVolumeOps, &gUserlandFSVolumeOps, sizeof(fs_volume_ops));
|
||||||
|
|
||||||
|
#undef CLEAR_UNSUPPORTED
|
||||||
|
#define CLEAR_UNSUPPORTED(capability, op) \
|
||||||
|
if (!fCapabilities.Get(capability)) \
|
||||||
|
fVolumeOps.op = NULL
|
||||||
|
|
||||||
|
// FS operations
|
||||||
|
// FS_VOLUME_CAPABILITY_UNMOUNT: unmount
|
||||||
|
// always needed
|
||||||
|
|
||||||
|
// FS_VOLUME_CAPABILITY_READ_FS_INFO: read_fs_info
|
||||||
|
// always needed
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_WRITE_FS_INFO, write_fs_info);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_SYNC, sync);
|
||||||
|
|
||||||
|
// vnode operations
|
||||||
|
// FS_VOLUME_CAPABILITY_GET_VNODE: get_vnode
|
||||||
|
// always needed
|
||||||
|
|
||||||
|
// index directory & index operations
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_OPEN_INDEX_DIR, open_index_dir);
|
||||||
|
// FS_VOLUME_CAPABILITY_CLOSE_INDEX_DIR: close_index_dir
|
||||||
|
// always needed
|
||||||
|
// FS_VOLUME_CAPABILITY_FREE_INDEX_DIR_COOKIE: free_index_dir_cookie
|
||||||
|
// always needed
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_READ_INDEX_DIR, read_index_dir);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_REWIND_INDEX_DIR, rewind_index_dir);
|
||||||
|
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_CREATE_INDEX, create_index);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_REMOVE_INDEX, remove_index);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_READ_INDEX_STAT, read_index_stat);
|
||||||
|
|
||||||
|
// query operations
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_OPEN_QUERY, open_query);
|
||||||
|
// FS_VOLUME_CAPABILITY_CLOSE_QUERY: close_query
|
||||||
|
// always needed
|
||||||
|
// FS_VOLUME_CAPABILITY_FREE_QUERY_COOKIE: free_query_cookie
|
||||||
|
// always needed
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_READ_QUERY, read_query);
|
||||||
|
CLEAR_UNSUPPORTED(FS_VOLUME_CAPABILITY_REWIND_QUERY, rewind_query);
|
||||||
|
|
||||||
|
#undef CLEAR_UNSUPPORTED
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
// _Mount
|
// _Mount
|
||||||
status_t
|
status_t
|
||||||
Volume::_Mount(const char* device, uint32 flags, const char* parameters)
|
Volume::_Mount(const char* device, uint32 flags, const char* parameters)
|
||||||
@@ -3636,7 +3710,7 @@ Volume::_WriteVNode(void* _node, bool reenter)
|
|||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
void* clientNode = vnode->clientNode;
|
void* clientNode = vnode->clientNode;
|
||||||
delete vnode;
|
vnode->Delete(this);
|
||||||
|
|
||||||
// get a free port
|
// get a free port
|
||||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||||
@@ -4280,7 +4354,7 @@ Volume::_RemoveInvalidVNode(ino_t vnid)
|
|||||||
for (; vnode->useCount > 0; vnode->useCount--)
|
for (; vnode->useCount > 0; vnode->useCount--)
|
||||||
put_vnode(fFSVolume, vnid);
|
put_vnode(fFSVolume, vnid);
|
||||||
|
|
||||||
delete vnode;
|
vnode->Delete(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,21 +38,24 @@ public:
|
|||||||
fs_volume* fsVolume);
|
fs_volume* fsVolume);
|
||||||
~Volume();
|
~Volume();
|
||||||
|
|
||||||
FileSystem* GetFileSystem() const;
|
inline FileSystem* GetFileSystem() const;
|
||||||
inline dev_t GetID() const;
|
inline dev_t GetID() const;
|
||||||
|
|
||||||
|
inline fs_volume_ops* GetVolumeOps() { return &fVolumeOps; }
|
||||||
inline bool HasCapability(int capability) const;
|
inline bool HasCapability(int capability) const;
|
||||||
|
|
||||||
void* GetUserlandVolume() const;
|
inline void* GetUserlandVolume() const;
|
||||||
ino_t GetRootID() const;
|
inline ino_t GetRootID() const;
|
||||||
|
|
||||||
// client methods
|
// client methods
|
||||||
status_t GetVNode(ino_t vnid, void** node);
|
status_t GetVNode(ino_t vnid, void** node);
|
||||||
status_t PutVNode(ino_t vnid);
|
status_t PutVNode(ino_t vnid);
|
||||||
status_t AcquireVNode(ino_t vnid);
|
status_t AcquireVNode(ino_t vnid);
|
||||||
status_t NewVNode(ino_t vnid, void* node);
|
status_t NewVNode(ino_t vnid, void* node,
|
||||||
|
const FSVNodeCapabilities& capabilities);
|
||||||
status_t PublishVNode(ino_t vnid, void* node,
|
status_t PublishVNode(ino_t vnid, void* node,
|
||||||
int type, uint32 flags);
|
int type, uint32 flags,
|
||||||
|
const FSVNodeCapabilities& capabilities);
|
||||||
status_t RemoveVNode(ino_t vnid);
|
status_t RemoveVNode(ino_t vnid);
|
||||||
status_t UnremoveVNode(ino_t vnid);
|
status_t UnremoveVNode(ino_t vnid);
|
||||||
status_t GetVNodeRemoved(ino_t vnid, bool* removed);
|
status_t GetVNodeRemoved(ino_t vnid, bool* removed);
|
||||||
@@ -88,7 +91,8 @@ public:
|
|||||||
status_t GetVNodeName(void* node, char* buffer,
|
status_t GetVNodeName(void* node, char* buffer,
|
||||||
size_t bufferSize);
|
size_t bufferSize);
|
||||||
status_t ReadVNode(ino_t vnid, bool reenter,
|
status_t ReadVNode(ino_t vnid, bool reenter,
|
||||||
void** node, int* type, uint32* flags);
|
void** node, fs_vnode_ops** _ops, int* type,
|
||||||
|
uint32* flags);
|
||||||
status_t WriteVNode(void* node, bool reenter);
|
status_t WriteVNode(void* node, bool reenter);
|
||||||
status_t RemoveVNode(void* node, bool reenter);
|
status_t RemoveVNode(void* node, bool reenter);
|
||||||
|
|
||||||
@@ -227,6 +231,8 @@ private:
|
|||||||
friend class IORequestRemover;
|
friend class IORequestRemover;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _InitVolumeOps();
|
||||||
|
|
||||||
status_t _Mount(const char* device, uint32 flags,
|
status_t _Mount(const char* device, uint32 flags,
|
||||||
const char* parameters);
|
const char* parameters);
|
||||||
status_t _Unmount();
|
status_t _Unmount();
|
||||||
@@ -289,6 +295,7 @@ private:
|
|||||||
FileSystem* fFileSystem;
|
FileSystem* fFileSystem;
|
||||||
fs_volume* fFSVolume;
|
fs_volume* fFSVolume;
|
||||||
FSVolumeCapabilities fCapabilities;
|
FSVolumeCapabilities fCapabilities;
|
||||||
|
fs_volume_ops fVolumeOps;
|
||||||
void* fUserlandVolume;
|
void* fUserlandVolume;
|
||||||
ino_t fRootID;
|
ino_t fRootID;
|
||||||
VNode* fRootNode;
|
VNode* fRootNode;
|
||||||
@@ -314,6 +321,15 @@ Volume::GetID() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// GetFileSystem
|
||||||
|
inline FileSystem*
|
||||||
|
Volume::GetFileSystem() const
|
||||||
|
{
|
||||||
|
return fFileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HasCapability
|
||||||
inline bool
|
inline bool
|
||||||
Volume::HasCapability(int capability) const
|
Volume::HasCapability(int capability) const
|
||||||
{
|
{
|
||||||
@@ -321,6 +337,22 @@ Volume::HasCapability(int capability) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// GetUserlandVolume
|
||||||
|
inline void*
|
||||||
|
Volume::GetUserlandVolume() const
|
||||||
|
{
|
||||||
|
return fUserlandVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// GetRootID
|
||||||
|
inline ino_t
|
||||||
|
Volume::GetRootID() const
|
||||||
|
{
|
||||||
|
return fRootID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
Volume::HasVNodeCapability(VNode* vnode, int capability) const
|
Volume::HasVNodeCapability(VNode* vnode, int capability) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ userlandfs_mount(fs_volume* fsVolume, const char* device, uint32 flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fsVolume->private_volume = volume;
|
fsVolume->private_volume = volume;
|
||||||
fsVolume->ops = &gUserlandFSVolumeOps;
|
fsVolume->ops = volume->GetVolumeOps();
|
||||||
*rootVnodeID = volume->GetRootID();
|
*rootVnodeID = volume->GetRootID();
|
||||||
|
|
||||||
PRINT(("userlandfs_mount() done: %p, %lld\n", fsVolume->private_volume,
|
PRINT(("userlandfs_mount() done: %p, %lld\n", fsVolume->private_volume,
|
||||||
@@ -207,10 +207,12 @@ userlandfs_get_vnode(fs_volume* fsVolume, ino_t vnid, fs_vnode* fsNode,
|
|||||||
PRINT(("userlandfs_get_vnode(%p, %lld, %p, %d)\n", volume, vnid,
|
PRINT(("userlandfs_get_vnode(%p, %lld, %p, %d)\n", volume, vnid,
|
||||||
fsNode->private_node, reenter));
|
fsNode->private_node, reenter));
|
||||||
void* node;
|
void* node;
|
||||||
status_t error = volume->ReadVNode(vnid, reenter, &node, _type, _flags);
|
fs_vnode_ops* ops;
|
||||||
|
status_t error = volume->ReadVNode(vnid, reenter, &node, &ops, _type,
|
||||||
|
_flags);
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
fsNode->private_node = node;
|
fsNode->private_node = node;
|
||||||
fsNode->ops = &gUserlandFSVnodeOps;
|
fsNode->ops = ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINT(("userlandfs_get_vnode() done: (%lx, %p)\n", error, node));
|
PRINT(("userlandfs_get_vnode() done: (%lx, %p)\n", error, node));
|
||||||
|
|||||||
@@ -466,10 +466,11 @@ UserlandRequestHandler::_HandleRequest(ReadVNodeRequest* request)
|
|||||||
void* node;
|
void* node;
|
||||||
int type;
|
int type;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
|
FSVNodeCapabilities capabilities;
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
RequestThreadContext context(volume);
|
RequestThreadContext context(volume);
|
||||||
result = volume->ReadVNode(request->vnid, request->reenter, &node,
|
result = volume->ReadVNode(request->vnid, request->reenter, &node,
|
||||||
&type, &flags);
|
&type, &flags, &capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare the reply
|
// prepare the reply
|
||||||
@@ -483,6 +484,7 @@ UserlandRequestHandler::_HandleRequest(ReadVNodeRequest* request)
|
|||||||
reply->node = node;
|
reply->node = node;
|
||||||
reply->type = type;
|
reply->type = type;
|
||||||
reply->flags = flags;
|
reply->flags = flags;
|
||||||
|
reply->capabilities = capabilities;
|
||||||
|
|
||||||
// send the reply
|
// send the reply
|
||||||
return _SendReply(allocator, false);
|
return _SendReply(allocator, false);
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
// Volume.cpp
|
/*
|
||||||
|
* Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
@@ -169,7 +172,7 @@ Volume::GetVNodeName(void* node, char* buffer, size_t bufferSize)
|
|||||||
// ReadVNode
|
// ReadVNode
|
||||||
status_t
|
status_t
|
||||||
Volume::ReadVNode(ino_t vnid, bool reenter, void** node, int* type,
|
Volume::ReadVNode(ino_t vnid, bool reenter, void** node, int* type,
|
||||||
uint32* flags)
|
uint32* flags, FSVNodeCapabilities* _capabilities)
|
||||||
{
|
{
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// Volume.h
|
/*
|
||||||
|
* Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
#ifndef USERLAND_FS_VOLUME_H
|
#ifndef USERLAND_FS_VOLUME_H
|
||||||
#define USERLAND_FS_VOLUME_H
|
#define USERLAND_FS_VOLUME_H
|
||||||
|
|
||||||
@@ -49,7 +51,8 @@ public:
|
|||||||
virtual status_t GetVNodeName(void* node, char* buffer,
|
virtual status_t GetVNodeName(void* node, char* buffer,
|
||||||
size_t bufferSize);
|
size_t bufferSize);
|
||||||
virtual status_t ReadVNode(ino_t vnid, bool reenter,
|
virtual status_t ReadVNode(ino_t vnid, bool reenter,
|
||||||
void** node, int* type, uint32* flags);
|
void** node, int* type, uint32* flags,
|
||||||
|
FSVNodeCapabilities* _capabilities);
|
||||||
virtual status_t WriteVNode(void* node, bool reenter);
|
virtual status_t WriteVNode(void* node, bool reenter);
|
||||||
virtual status_t RemoveVNode(void* node, bool reenter);
|
virtual status_t RemoveVNode(void* node, bool reenter);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
#include "beos_kernel_emu.h"
|
||||||
#include "BeOSKernelVolume.h"
|
#include "BeOSKernelVolume.h"
|
||||||
#include "fs_cache.h"
|
#include "fs_cache.h"
|
||||||
#include "fs_interface.h"
|
#include "fs_interface.h"
|
||||||
@@ -76,6 +77,8 @@ void
|
|||||||
BeOSKernelFileSystem::_InitCapabilities()
|
BeOSKernelFileSystem::_InitCapabilities()
|
||||||
{
|
{
|
||||||
fCapabilities.ClearAll();
|
fCapabilities.ClearAll();
|
||||||
|
fVolumeCapabilities.ClearAll();
|
||||||
|
fNodeCapabilities.ClearAll();
|
||||||
|
|
||||||
// FS interface type
|
// FS interface type
|
||||||
fClientFSType = CLIENT_FS_BEOS_KERNEL;
|
fClientFSType = CLIENT_FS_BEOS_KERNEL;
|
||||||
@@ -207,6 +210,21 @@ BeOSKernelFileSystem::_InitCapabilities()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
// get_beos_file_system_node_capabilities
|
||||||
|
//
|
||||||
|
// Service function for beos_kernel_emu.cpp. Declared in beos_kernel_emu.h.
|
||||||
|
void
|
||||||
|
get_beos_file_system_node_capabilities(FSVNodeCapabilities& capabilities)
|
||||||
|
{
|
||||||
|
BeOSKernelFileSystem* fileSystem
|
||||||
|
= static_cast<BeOSKernelFileSystem*>(FileSystem::GetInstance());
|
||||||
|
fileSystem->GetNodeCapabilities(capabilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - bootstrapping
|
// #pragma mark - bootstrapping
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
// BeOSKernelVolume.cpp
|
/*
|
||||||
|
* Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "BeOSKernelVolume.h"
|
#include "BeOSKernelVolume.h"
|
||||||
|
|
||||||
@@ -11,6 +14,7 @@
|
|||||||
|
|
||||||
#include "../kernel_emu.h"
|
#include "../kernel_emu.h"
|
||||||
|
|
||||||
|
#include "BeOSKernelFileSystem.h"
|
||||||
#include "fs_interface.h"
|
#include "fs_interface.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -40,6 +44,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// _FileSystem
|
||||||
|
inline BeOSKernelFileSystem*
|
||||||
|
BeOSKernelVolume::_FileSystem() const
|
||||||
|
{
|
||||||
|
return static_cast<BeOSKernelFileSystem*>(fFileSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
BeOSKernelVolume::BeOSKernelVolume(FileSystem* fileSystem, dev_t id,
|
BeOSKernelVolume::BeOSKernelVolume(FileSystem* fileSystem, dev_t id,
|
||||||
beos_vnode_ops* fsOps, const FSVolumeCapabilities& capabilities)
|
beos_vnode_ops* fsOps, const FSVolumeCapabilities& capabilities)
|
||||||
@@ -165,7 +177,7 @@ BeOSKernelVolume::GetVNodeType(void* node, int* type)
|
|||||||
// ReadVNode
|
// ReadVNode
|
||||||
status_t
|
status_t
|
||||||
BeOSKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** node, int* type,
|
BeOSKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** node, int* type,
|
||||||
uint32* flags)
|
uint32* flags, FSVNodeCapabilities* _capabilities)
|
||||||
{
|
{
|
||||||
if (!fFSOps->read_vnode)
|
if (!fFSOps->read_vnode)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -186,6 +198,7 @@ BeOSKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** node, int* type,
|
|||||||
|
|
||||||
*type = (st.st_mode & S_IFMT);
|
*type = (st.st_mode & S_IFMT);
|
||||||
*flags = 0;
|
*flags = 0;
|
||||||
|
_FileSystem()->GetNodeCapabilities(*_capabilities);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// BeOSKernelVolume.h
|
/*
|
||||||
|
* Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
#ifndef USERLAND_FS_BEOS_KERNEL_VOLUME_H
|
#ifndef USERLAND_FS_BEOS_KERNEL_VOLUME_H
|
||||||
#define USERLAND_FS_BEOS_KERNEL_VOLUME_H
|
#define USERLAND_FS_BEOS_KERNEL_VOLUME_H
|
||||||
|
|
||||||
@@ -9,6 +11,9 @@ struct beos_vnode_ops;
|
|||||||
|
|
||||||
namespace UserlandFS {
|
namespace UserlandFS {
|
||||||
|
|
||||||
|
class BeOSKernelFileSystem;
|
||||||
|
|
||||||
|
|
||||||
class BeOSKernelVolume : public Volume {
|
class BeOSKernelVolume : public Volume {
|
||||||
public:
|
public:
|
||||||
BeOSKernelVolume(FileSystem* fileSystem,
|
BeOSKernelVolume(FileSystem* fileSystem,
|
||||||
@@ -33,7 +38,8 @@ public:
|
|||||||
// the three parameters publish_vnode() is
|
// the three parameters publish_vnode() is
|
||||||
// used.
|
// used.
|
||||||
virtual status_t ReadVNode(ino_t vnid, bool reenter,
|
virtual status_t ReadVNode(ino_t vnid, bool reenter,
|
||||||
void** node, int* type, uint32* flags);
|
void** node, int* type, uint32* flags,
|
||||||
|
FSVNodeCapabilities* _capabilities);
|
||||||
virtual status_t WriteVNode(void* node, bool reenter);
|
virtual status_t WriteVNode(void* node, bool reenter);
|
||||||
virtual status_t RemoveVNode(void* node, bool reenter);
|
virtual status_t RemoveVNode(void* node, bool reenter);
|
||||||
|
|
||||||
@@ -154,6 +160,7 @@ private:
|
|||||||
status_t _OpenAttr(void* node, const char* name,
|
status_t _OpenAttr(void* node, const char* name,
|
||||||
uint32 type, int openMode, bool create,
|
uint32 type, int openMode, bool create,
|
||||||
void** cookie);
|
void** cookie);
|
||||||
|
inline BeOSKernelFileSystem* _FileSystem() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
beos_vnode_ops* fFSOps;
|
beos_vnode_ops* fFSOps;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// beos_kernel_emu.cpp
|
// beos_kernel_emu.cpp
|
||||||
|
|
||||||
|
#include "beos_kernel_emu.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -145,9 +147,14 @@ put_vnode(nspace_id nsid, ino_t vnid)
|
|||||||
int
|
int
|
||||||
new_vnode(nspace_id nsid, ino_t vnid, void *data)
|
new_vnode(nspace_id nsid, ino_t vnid, void *data)
|
||||||
{
|
{
|
||||||
|
// get the node capabilities
|
||||||
|
FSVNodeCapabilities capabilities;
|
||||||
|
get_beos_file_system_node_capabilities(capabilities);
|
||||||
|
|
||||||
// The semantics of new_vnode() has changed. The new publish_vnode()
|
// The semantics of new_vnode() has changed. The new publish_vnode()
|
||||||
// should work like the former new_vnode().
|
// should work like the former new_vnode().
|
||||||
return UserlandFS::KernelEmu::publish_vnode(nsid, vnid, data);
|
return UserlandFS::KernelEmu::publish_vnode(nsid, vnid, data,
|
||||||
|
capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove_vnode
|
// remove_vnode
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
// HaikuKernelFileSystem.cpp
|
/*
|
||||||
|
* Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "HaikuKernelFileSystem.h"
|
#include "HaikuKernelFileSystem.h"
|
||||||
|
|
||||||
@@ -37,6 +40,40 @@ struct HaikuKernelFileSystem::IORequestHashDefinition {
|
|||||||
// IORequestTable
|
// IORequestTable
|
||||||
struct HaikuKernelFileSystem::IORequestTable
|
struct HaikuKernelFileSystem::IORequestTable
|
||||||
: public OpenHashTable<IORequestHashDefinition> {
|
: public OpenHashTable<IORequestHashDefinition> {
|
||||||
|
typedef int32 KeyType;
|
||||||
|
typedef HaikuKernelIORequest ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(int32 key) const
|
||||||
|
{ return key; }
|
||||||
|
size_t Hash(const HaikuKernelIORequest* value) const
|
||||||
|
{ return value->id; }
|
||||||
|
bool Compare(int32 key, const HaikuKernelIORequest* value) const
|
||||||
|
{ return value->id == key; }
|
||||||
|
HashTableLink<HaikuKernelIORequest>*
|
||||||
|
GetLink(HaikuKernelIORequest* value) const
|
||||||
|
{ return value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// NodeCapabilitiesHashDefinition
|
||||||
|
struct HaikuKernelFileSystem::NodeCapabilitiesHashDefinition {
|
||||||
|
typedef fs_vnode_ops* KeyType;
|
||||||
|
typedef HaikuKernelNode::Capabilities ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(fs_vnode_ops* key) const
|
||||||
|
{ return (size_t)(addr_t)key; }
|
||||||
|
size_t Hash(const ValueType* value) const
|
||||||
|
{ return HashKey(value->ops); }
|
||||||
|
bool Compare(fs_vnode_ops* key, const ValueType* value) const
|
||||||
|
{ return value->ops == key; }
|
||||||
|
HashTableLink<ValueType>* GetLink(ValueType* value) const
|
||||||
|
{ return value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// NodeCapabilitiesTable
|
||||||
|
struct HaikuKernelFileSystem::NodeCapabilitiesTable
|
||||||
|
: public OpenHashTable<NodeCapabilitiesHashDefinition> {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -46,6 +83,7 @@ HaikuKernelFileSystem::HaikuKernelFileSystem(file_system_module_info* fsModule)
|
|||||||
FileSystem(),
|
FileSystem(),
|
||||||
fFSModule(fsModule),
|
fFSModule(fsModule),
|
||||||
fIORequests(NULL),
|
fIORequests(NULL),
|
||||||
|
fNodeCapabilities(NULL),
|
||||||
fLock("HaikuKernelFileSystem")
|
fLock("HaikuKernelFileSystem")
|
||||||
{
|
{
|
||||||
_InitCapabilities();
|
_InitCapabilities();
|
||||||
@@ -60,6 +98,7 @@ HaikuKernelFileSystem::~HaikuKernelFileSystem()
|
|||||||
fFSModule->info.std_ops(B_MODULE_UNINIT);
|
fFSModule->info.std_ops(B_MODULE_UNINIT);
|
||||||
|
|
||||||
delete fIORequests;
|
delete fIORequests;
|
||||||
|
delete fNodeCapabilities;
|
||||||
|
|
||||||
// TODO: Call the cleanup methods (condition vars, block cache)!
|
// TODO: Call the cleanup methods (condition vars, block cache)!
|
||||||
}
|
}
|
||||||
@@ -91,6 +130,15 @@ HaikuKernelFileSystem::Init()
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// create the node capabilites map
|
||||||
|
fNodeCapabilities = new(std::nothrow) NodeCapabilitiesTable;
|
||||||
|
if (fNodeCapabilities == NULL)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
error = fNodeCapabilities->Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
// call the kernel module initialization (if any)
|
// call the kernel module initialization (if any)
|
||||||
if (!fFSModule->info.std_ops)
|
if (!fFSModule->info.std_ops)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -183,6 +231,50 @@ HaikuKernelFileSystem::PutIORequest(HaikuKernelIORequest* request,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// GetVNodeCapabilities
|
||||||
|
HaikuKernelNode::Capabilities*
|
||||||
|
HaikuKernelFileSystem::GetNodeCapabilities(fs_vnode_ops* ops)
|
||||||
|
{
|
||||||
|
AutoLocker<Locker> locker(fLock);
|
||||||
|
|
||||||
|
// check whether the ops are already known
|
||||||
|
HaikuKernelNode::Capabilities* capabilities
|
||||||
|
= fNodeCapabilities->Lookup(ops);
|
||||||
|
if (capabilities != NULL) {
|
||||||
|
capabilities->refCount++;
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the capabilities implied by the ops vector
|
||||||
|
FSVNodeCapabilities nodeCapabilities;
|
||||||
|
_InitNodeCapabilities(ops, nodeCapabilities);
|
||||||
|
|
||||||
|
// create a new object
|
||||||
|
capabilities = new(std::nothrow) HaikuKernelNode::Capabilities(ops,
|
||||||
|
nodeCapabilities);
|
||||||
|
if (capabilities == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fNodeCapabilities->Insert(capabilities);
|
||||||
|
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PutVNodeCapabilities
|
||||||
|
void
|
||||||
|
HaikuKernelFileSystem::PutNodeCapabilities(
|
||||||
|
HaikuKernelNode::Capabilities* capabilities)
|
||||||
|
{
|
||||||
|
AutoLocker<Locker> locker(fLock);
|
||||||
|
|
||||||
|
if (--capabilities->refCount == 0) {
|
||||||
|
fNodeCapabilities->Remove(capabilities);
|
||||||
|
delete capabilities;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// _InitCapabilities
|
// _InitCapabilities
|
||||||
void
|
void
|
||||||
HaikuKernelFileSystem::_InitCapabilities()
|
HaikuKernelFileSystem::_InitCapabilities()
|
||||||
@@ -197,6 +289,90 @@ HaikuKernelFileSystem::_InitCapabilities()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ void
|
||||||
|
HaikuKernelFileSystem::_InitNodeCapabilities(fs_vnode_ops* ops,
|
||||||
|
FSVNodeCapabilities& capabilities)
|
||||||
|
{
|
||||||
|
capabilities.ClearAll();
|
||||||
|
|
||||||
|
// vnode operations
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_LOOKUP, ops->lookup);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_GET_VNODE_NAME, ops->get_vnode_name);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_PUT_VNODE, ops->put_vnode);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_REMOVE_VNODE, ops->remove_vnode);
|
||||||
|
|
||||||
|
// asynchronous I/O
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_IO, ops->io);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_CANCEL_IO, ops->cancel_io);
|
||||||
|
|
||||||
|
// cache file access
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_GET_FILE_MAP, ops->get_file_map);
|
||||||
|
|
||||||
|
// common operations
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_IOCTL, ops->ioctl);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_SET_FLAGS, ops->set_flags);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_SELECT, ops->select);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_DESELECT, ops->deselect);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_FSYNC, ops->fsync);
|
||||||
|
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_READ_SYMLINK, ops->read_symlink);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_CREATE_SYMLINK, ops->create_symlink);
|
||||||
|
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_LINK, ops->link);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_UNLINK, ops->unlink);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_RENAME, ops->rename);
|
||||||
|
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_ACCESS, ops->access);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_READ_STAT, ops->read_stat);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_WRITE_STAT, ops->write_stat);
|
||||||
|
|
||||||
|
// file operations
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_CREATE, ops->create);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_OPEN, ops->open);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_CLOSE, ops->close);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_FREE_COOKIE, ops->free_cookie);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_READ, ops->read);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_WRITE, ops->write);
|
||||||
|
|
||||||
|
// directory operations
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_CREATE_DIR, ops->create_dir);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_REMOVE_DIR, ops->remove_dir);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_OPEN_DIR, ops->open_dir);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_CLOSE_DIR, ops->close_dir);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_FREE_DIR_COOKIE, ops->free_dir_cookie);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_READ_DIR, ops->read_dir);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_REWIND_DIR, ops->rewind_dir);
|
||||||
|
|
||||||
|
// attribute directory operations
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_OPEN_ATTR_DIR, ops->open_attr_dir);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_CLOSE_ATTR_DIR, ops->close_attr_dir);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_FREE_ATTR_DIR_COOKIE,
|
||||||
|
ops->free_attr_dir_cookie);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_DIR, ops->read_attr_dir);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_REWIND_ATTR_DIR, ops->rewind_attr_dir);
|
||||||
|
|
||||||
|
// attribute operations
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_CREATE_ATTR, ops->create_attr);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_OPEN_ATTR, ops->open_attr);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_CLOSE_ATTR, ops->close_attr);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_FREE_ATTR_COOKIE,
|
||||||
|
ops->free_attr_cookie);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR, ops->read_attr);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_WRITE_ATTR, ops->write_attr);
|
||||||
|
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_STAT, ops->read_attr_stat);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_WRITE_ATTR_STAT,
|
||||||
|
ops->write_attr_stat);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_RENAME_ATTR, ops->rename_attr);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_REMOVE_ATTR, ops->remove_attr);
|
||||||
|
|
||||||
|
// support for node and FS layers
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_CREATE_SPECIAL_NODE,
|
||||||
|
ops->create_special_node);
|
||||||
|
capabilities.Set(FS_VNODE_CAPABILITY_GET_SUPER_VNODE, ops->get_super_vnode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - bootstrapping
|
// #pragma mark - bootstrapping
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
// HaikuKernelFileSystem.h
|
/*
|
||||||
|
* Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
#ifndef USERLAND_FS_HAIKU_KERNEL_FILE_SYSTEM_H
|
#ifndef USERLAND_FS_HAIKU_KERNEL_FILE_SYSTEM_H
|
||||||
#define USERLAND_FS_HAIKU_KERNEL_FILE_SYSTEM_H
|
#define USERLAND_FS_HAIKU_KERNEL_FILE_SYSTEM_H
|
||||||
|
|
||||||
#include "Locker.h"
|
#include "Locker.h"
|
||||||
|
|
||||||
|
#include "HaikuKernelNode.h"
|
||||||
|
|
||||||
#include "../FileSystem.h"
|
#include "../FileSystem.h"
|
||||||
|
|
||||||
|
|
||||||
struct file_system_module_info;
|
struct file_system_module_info;
|
||||||
|
|
||||||
|
|
||||||
namespace UserlandFS {
|
namespace UserlandFS {
|
||||||
|
|
||||||
struct HaikuKernelIORequest;
|
struct HaikuKernelIORequest;
|
||||||
@@ -29,16 +35,27 @@ public:
|
|||||||
void PutIORequest(HaikuKernelIORequest* request,
|
void PutIORequest(HaikuKernelIORequest* request,
|
||||||
int32 refCount = 1);
|
int32 refCount = 1);
|
||||||
|
|
||||||
|
HaikuKernelNode::Capabilities* GetNodeCapabilities(
|
||||||
|
fs_vnode_ops* ops);
|
||||||
|
void PutNodeCapabilities(
|
||||||
|
HaikuKernelNode::Capabilities*
|
||||||
|
capabilities);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class IORequestHashDefinition;
|
struct IORequestHashDefinition;
|
||||||
class IORequestTable;
|
struct IORequestTable;
|
||||||
|
struct NodeCapabilitiesHashDefinition;
|
||||||
|
struct NodeCapabilitiesTable;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _InitCapabilities();
|
void _InitCapabilities();
|
||||||
|
static void _InitNodeCapabilities(fs_vnode_ops* ops,
|
||||||
|
FSVNodeCapabilities& capabilities);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
file_system_module_info* fFSModule;
|
file_system_module_info* fFSModule;
|
||||||
IORequestTable* fIORequests;
|
IORequestTable* fIORequests;
|
||||||
|
NodeCapabilitiesTable* fNodeCapabilities;
|
||||||
Locker fLock;
|
Locker fLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,11 @@
|
|||||||
#include <fs_interface.h>
|
#include <fs_interface.h>
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
#include "FSCapabilities.h"
|
#include "FSCapabilities.h"
|
||||||
|
|
||||||
|
|
||||||
namespace UserlandFS {
|
namespace UserlandFS {
|
||||||
|
|
||||||
class HaikuKernelVolume;
|
class HaikuKernelVolume;
|
||||||
@@ -18,14 +21,19 @@ using UserlandFSUtil::FSVNodeCapabilities;
|
|||||||
|
|
||||||
|
|
||||||
struct HaikuKernelNode : fs_vnode {
|
struct HaikuKernelNode : fs_vnode {
|
||||||
|
struct Capabilities;
|
||||||
|
|
||||||
ino_t id;
|
ino_t id;
|
||||||
HaikuKernelVolume* volume;
|
HaikuKernelVolume* volume;
|
||||||
|
Capabilities* capabilities;
|
||||||
bool published;
|
bool published;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline HaikuKernelNode(HaikuKernelVolume* volume,
|
inline HaikuKernelNode(HaikuKernelVolume* volume,
|
||||||
ino_t vnodeID, void* privateNode,
|
ino_t vnodeID, void* privateNode,
|
||||||
fs_vnode_ops* ops);
|
fs_vnode_ops* ops,
|
||||||
|
Capabilities* capabilities);
|
||||||
|
~HaikuKernelNode();
|
||||||
|
|
||||||
static HaikuKernelNode* GetNode(fs_vnode* node);
|
static HaikuKernelNode* GetNode(fs_vnode* node);
|
||||||
|
|
||||||
@@ -33,11 +41,27 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct HaikuKernelNode::Capabilities : HashTableLink<Capabilities> {
|
||||||
|
int32 refCount;
|
||||||
|
fs_vnode_ops* ops;
|
||||||
|
FSVNodeCapabilities capabilities;
|
||||||
|
|
||||||
|
Capabilities(fs_vnode_ops* ops, FSVNodeCapabilities capabilities)
|
||||||
|
:
|
||||||
|
refCount(1),
|
||||||
|
ops(ops),
|
||||||
|
capabilities(capabilities)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
HaikuKernelNode::HaikuKernelNode(HaikuKernelVolume* volume, ino_t vnodeID,
|
HaikuKernelNode::HaikuKernelNode(HaikuKernelVolume* volume, ino_t vnodeID,
|
||||||
void* privateNode, fs_vnode_ops* ops)
|
void* privateNode, fs_vnode_ops* ops, Capabilities* capabilities)
|
||||||
:
|
:
|
||||||
id(vnodeID),
|
id(vnodeID),
|
||||||
volume(volume),
|
volume(volume),
|
||||||
|
capabilities(capabilities),
|
||||||
published(false)
|
published(false)
|
||||||
{
|
{
|
||||||
this->private_node = privateNode;
|
this->private_node = privateNode;
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
// HaikuKernelVolume.cpp
|
/*
|
||||||
|
* Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "HaikuKernelVolume.h"
|
#include "HaikuKernelVolume.h"
|
||||||
|
|
||||||
@@ -84,11 +87,20 @@ HaikuKernelVolume::NewVNode(ino_t vnodeID, void* privateNode, fs_vnode_ops* ops,
|
|||||||
if (node != NULL)
|
if (node != NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// create a new node
|
// get node capabilities
|
||||||
node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode, ops);
|
HaikuKernelNode::Capabilities* capabilities
|
||||||
if (node == NULL)
|
= _FileSystem()->GetNodeCapabilities(ops);
|
||||||
|
if (capabilities == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// create a new node
|
||||||
|
node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode, ops,
|
||||||
|
capabilities);
|
||||||
|
if (node == NULL) {
|
||||||
|
_FileSystem()->PutNodeCapabilities(capabilities);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
// add to map
|
// add to map
|
||||||
status_t error = fNodes->Put(vnodeID, node);
|
status_t error = fNodes->Put(vnodeID, node);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
@@ -115,11 +127,19 @@ HaikuKernelVolume::PublishVNode(ino_t vnodeID, void* privateNode,
|
|||||||
if (node->published)
|
if (node->published)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
} else {
|
} else {
|
||||||
|
// get node capabilities
|
||||||
|
HaikuKernelNode::Capabilities* capabilities
|
||||||
|
= _FileSystem()->GetNodeCapabilities(ops);
|
||||||
|
if (capabilities == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
// create a new node
|
// create a new node
|
||||||
node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode,
|
node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode,
|
||||||
ops);
|
ops, capabilities);
|
||||||
if (node == NULL)
|
if (node == NULL) {
|
||||||
|
_FileSystem()->PutNodeCapabilities(capabilities);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
// add to map
|
// add to map
|
||||||
status_t error = fNodes->Put(vnodeID, node);
|
status_t error = fNodes->Put(vnodeID, node);
|
||||||
@@ -271,14 +291,14 @@ HaikuKernelVolume::GetVNodeName(void* _node, char* buffer, size_t bufferSize)
|
|||||||
// ReadVNode
|
// ReadVNode
|
||||||
status_t
|
status_t
|
||||||
HaikuKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
HaikuKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
||||||
uint32* flags)
|
uint32* flags, FSVNodeCapabilities* _capabilities)
|
||||||
{
|
{
|
||||||
if (!fVolume.ops->get_vnode)
|
if (!fVolume.ops->get_vnode)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// create a new wrapper node and add it to the map
|
// create a new wrapper node and add it to the map
|
||||||
HaikuKernelNode* node = new(std::nothrow) HaikuKernelNode(this, vnid, NULL,
|
HaikuKernelNode* node = new(std::nothrow) HaikuKernelNode(this, vnid, NULL,
|
||||||
NULL);
|
NULL, NULL);
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
ObjectDeleter<HaikuKernelNode> nodeDeleter(node);
|
ObjectDeleter<HaikuKernelNode> nodeDeleter(node);
|
||||||
@@ -301,11 +321,23 @@ HaikuKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get node capabilities
|
||||||
|
HaikuKernelNode::Capabilities* capabilities
|
||||||
|
= _FileSystem()->GetNodeCapabilities(node->ops);
|
||||||
|
if (capabilities == NULL) {
|
||||||
|
node->ops->put_vnode(&fVolume, node, reenter);
|
||||||
|
locker.Lock();
|
||||||
|
fNodes->Remove(vnid);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
locker.Lock();
|
locker.Lock();
|
||||||
|
node->capabilities = capabilities;
|
||||||
node->published = true;
|
node->published = true;
|
||||||
nodeDeleter.Detach();
|
nodeDeleter.Detach();
|
||||||
|
|
||||||
*_node = node;
|
*_node = node;
|
||||||
|
*_capabilities = capabilities->capabilities;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -1166,81 +1198,4 @@ HaikuKernelVolume::_InitCapabilities()
|
|||||||
fCapabilities.Set(FS_VOLUME_CAPABILITY_READ_QUERY, fVolume.ops->read_query);
|
fCapabilities.Set(FS_VOLUME_CAPABILITY_READ_QUERY, fVolume.ops->read_query);
|
||||||
fCapabilities.Set(FS_VOLUME_CAPABILITY_REWIND_QUERY,
|
fCapabilities.Set(FS_VOLUME_CAPABILITY_REWIND_QUERY,
|
||||||
fVolume.ops->rewind_query);
|
fVolume.ops->rewind_query);
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// vnode operations
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_LOOKUP, fFSModule->lookup);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_GET_VNODE_NAME, fFSModule->get_vnode_name);
|
|
||||||
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_GET_VNODE, fFSModule->get_vnode);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_PUT_VNODE, fFSModule->put_vnode);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_REMOVE_VNODE, fFSModule->remove_vnode);
|
|
||||||
|
|
||||||
// VM file access
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_CAN_PAGE, fFSModule->can_page);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_READ_PAGES, fFSModule->read_pages);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_PAGES, fFSModule->write_pages);
|
|
||||||
|
|
||||||
// cache file access
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_GET_FILE_MAP, fFSModule->get_file_map);
|
|
||||||
|
|
||||||
// common operations
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_IOCTL, fFSModule->ioctl);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_SET_FLAGS, fFSModule->set_flags);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_SELECT, fFSModule->select);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_DESELECT, fFSModule->deselect);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_FSYNC, fFSModule->fsync);
|
|
||||||
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_READ_SYMLINK, fFSModule->read_symlink);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_CREATE_SYMLINK, fFSModule->create_symlink);
|
|
||||||
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_LINK, fFSModule->link);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_UNLINK, fFSModule->unlink);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_RENAME, fFSModule->rename);
|
|
||||||
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_ACCESS, fFSModule->access);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_READ_STAT, fFSModule->read_stat);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_STAT, fFSModule->write_stat);
|
|
||||||
|
|
||||||
// file operations
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_CREATE, fFSModule->create);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_OPEN, fFSModule->open);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE, fFSModule->close);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_FREE_COOKIE, fFSModule->free_cookie);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_READ, fFSModule->read);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_WRITE, fFSModule->write);
|
|
||||||
|
|
||||||
// directory operations
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_CREATE_DIR, fFSModule->create_dir);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_REMOVE_DIR, fFSModule->remove_dir);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_OPEN_DIR, fFSModule->open_dir);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE_DIR, fFSModule->close_dir);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_FREE_DIR_COOKIE, fFSModule->free_dir_cookie);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_READ_DIR, fFSModule->read_dir);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_REWIND_DIR, fFSModule->rewind_dir);
|
|
||||||
|
|
||||||
// attribute directory operations
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_OPEN_ATTR_DIR, fFSModule->open_attr_dir);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE_ATTR_DIR, fFSModule->close_attr_dir);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_FREE_ATTR_DIR_COOKIE,
|
|
||||||
fFSModule->free_attr_dir_cookie);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_DIR, fFSModule->read_attr_dir);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_REWIND_ATTR_DIR, fFSModule->rewind_attr_dir);
|
|
||||||
|
|
||||||
// attribute operations
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_CREATE_ATTR, fFSModule->create_attr);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_OPEN_ATTR, fFSModule->open_attr);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_CLOSE_ATTR, fFSModule->close_attr);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_FREE_ATTR_COOKIE,
|
|
||||||
fFSModule->free_attr_cookie);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR, fFSModule->read_attr);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_ATTR, fFSModule->write_attr);
|
|
||||||
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_READ_ATTR_STAT, fFSModule->read_attr_stat);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_ATTR_STAT,
|
|
||||||
fFSModule->write_attr_stat);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_RENAME_ATTR, fFSModule->rename_attr);
|
|
||||||
fCapabilities.Set(FS_VNODE_CAPABILITY_REMOVE_ATTR, fFSModule->remove_attr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// HaikuKernelVolume.h
|
/*
|
||||||
|
* Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
#ifndef USERLAND_FS_HAIKU_KERNEL_VOLUME_H
|
#ifndef USERLAND_FS_HAIKU_KERNEL_VOLUME_H
|
||||||
#define USERLAND_FS_HAIKU_KERNEL_VOLUME_H
|
#define USERLAND_FS_HAIKU_KERNEL_VOLUME_H
|
||||||
|
|
||||||
@@ -56,7 +58,8 @@ public:
|
|||||||
virtual status_t GetVNodeName(void* node, char* buffer,
|
virtual status_t GetVNodeName(void* node, char* buffer,
|
||||||
size_t bufferSize);
|
size_t bufferSize);
|
||||||
virtual status_t ReadVNode(ino_t vnid, bool reenter,
|
virtual status_t ReadVNode(ino_t vnid, bool reenter,
|
||||||
void** node, int* type, uint32* flags);
|
void** node, int* type, uint32* flags,
|
||||||
|
FSVNodeCapabilities* _capabilities);
|
||||||
virtual status_t WriteVNode(void* node, bool reenter);
|
virtual status_t WriteVNode(void* node, bool reenter);
|
||||||
virtual status_t RemoveVNode(void* node, bool reenter);
|
virtual status_t RemoveVNode(void* node, bool reenter);
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ SharedLibrary libuserlandfs_haiku_kernel.so
|
|||||||
|
|
||||||
# UserlandFS server interface
|
# UserlandFS server interface
|
||||||
HaikuKernelFileSystem.cpp
|
HaikuKernelFileSystem.cpp
|
||||||
|
HaikuKernelNode.cpp
|
||||||
HaikuKernelVolume.cpp
|
HaikuKernelVolume.cpp
|
||||||
|
|
||||||
:
|
:
|
||||||
|
|||||||
@@ -136,7 +136,8 @@ new_vnode(fs_volume *_volume, ino_t vnodeID, void *privateNode,
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
// announce the new node
|
// announce the new node
|
||||||
error = UserlandFS::KernelEmu::new_vnode(volume->GetID(), vnodeID, node);
|
error = UserlandFS::KernelEmu::new_vnode(volume->GetID(), vnodeID, node,
|
||||||
|
node->capabilities->capabilities);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
volume->UndoNewVNode(node);
|
volume->UndoNewVNode(node);
|
||||||
|
|
||||||
@@ -159,7 +160,7 @@ publish_vnode(fs_volume *_volume, ino_t vnodeID, void *privateNode,
|
|||||||
|
|
||||||
// publish the new node
|
// publish the new node
|
||||||
error = UserlandFS::KernelEmu::publish_vnode(volume->GetID(), vnodeID, node,
|
error = UserlandFS::KernelEmu::publish_vnode(volume->GetID(), vnodeID, node,
|
||||||
type, flags);
|
type, flags, node->capabilities->capabilities);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
volume->UndoPublishVNode(node);
|
volume->UndoPublishVNode(node);
|
||||||
|
|
||||||
|
|||||||
@@ -365,7 +365,8 @@ UserlandFS::KernelEmu::acquire_vnode(dev_t nsid, ino_t vnid)
|
|||||||
|
|
||||||
// new_vnode
|
// new_vnode
|
||||||
status_t
|
status_t
|
||||||
UserlandFS::KernelEmu::new_vnode(dev_t nsid, ino_t vnid, void* data)
|
UserlandFS::KernelEmu::new_vnode(dev_t nsid, ino_t vnid, void* data,
|
||||||
|
const FSVNodeCapabilities& capabilities)
|
||||||
{
|
{
|
||||||
// get the request port and the file system
|
// get the request port and the file system
|
||||||
RequestPort* port;
|
RequestPort* port;
|
||||||
@@ -384,6 +385,7 @@ UserlandFS::KernelEmu::new_vnode(dev_t nsid, ino_t vnid, void* data)
|
|||||||
request->nsid = nsid;
|
request->nsid = nsid;
|
||||||
request->vnid = vnid;
|
request->vnid = vnid;
|
||||||
request->node = data;
|
request->node = data;
|
||||||
|
request->capabilities = capabilities;
|
||||||
|
|
||||||
// send the request
|
// send the request
|
||||||
UserlandRequestHandler handler(fileSystem, NEW_VNODE_REPLY);
|
UserlandRequestHandler handler(fileSystem, NEW_VNODE_REPLY);
|
||||||
@@ -402,7 +404,7 @@ UserlandFS::KernelEmu::new_vnode(dev_t nsid, ino_t vnid, void* data)
|
|||||||
// publish_vnode
|
// publish_vnode
|
||||||
status_t
|
status_t
|
||||||
UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data,
|
UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data,
|
||||||
int type, uint32 flags)
|
int type, uint32 flags, const FSVNodeCapabilities& capabilities)
|
||||||
{
|
{
|
||||||
// get the request port and the file system
|
// get the request port and the file system
|
||||||
RequestPort* port;
|
RequestPort* port;
|
||||||
@@ -423,6 +425,7 @@ UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data,
|
|||||||
request->node = data;
|
request->node = data;
|
||||||
request->type = type;
|
request->type = type;
|
||||||
request->flags = flags;
|
request->flags = flags;
|
||||||
|
request->capabilities = capabilities;
|
||||||
|
|
||||||
// send the request
|
// send the request
|
||||||
UserlandRequestHandler handler(fileSystem, PUBLISH_VNODE_REPLY);
|
UserlandRequestHandler handler(fileSystem, PUBLISH_VNODE_REPLY);
|
||||||
@@ -441,7 +444,8 @@ UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data,
|
|||||||
|
|
||||||
// publish_vnode
|
// publish_vnode
|
||||||
status_t
|
status_t
|
||||||
UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data)
|
UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data,
|
||||||
|
const FSVNodeCapabilities& capabilities)
|
||||||
{
|
{
|
||||||
// get the volume
|
// get the volume
|
||||||
Volume* volume = FileSystem::GetInstance()->VolumeWithID(nsid);
|
Volume* volume = FileSystem::GetInstance()->VolumeWithID(nsid);
|
||||||
@@ -455,7 +459,8 @@ UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data)
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
// publish the node
|
// publish the node
|
||||||
return UserlandFS::KernelEmu::publish_vnode(nsid, vnid, data, type, 0);
|
return UserlandFS::KernelEmu::publish_vnode(nsid, vnid, data, type, 0,
|
||||||
|
capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include "FSCapabilities.h"
|
||||||
|
|
||||||
|
|
||||||
struct selectsync;
|
struct selectsync;
|
||||||
struct file_io_vec;
|
struct file_io_vec;
|
||||||
|
|
||||||
@@ -24,10 +27,12 @@ status_t notify_query(port_id port, int32 token, int32 operation,
|
|||||||
status_t get_vnode(dev_t nsid, ino_t vnid, void** node);
|
status_t get_vnode(dev_t nsid, ino_t vnid, void** node);
|
||||||
status_t put_vnode(dev_t nsid, ino_t vnid);
|
status_t put_vnode(dev_t nsid, ino_t vnid);
|
||||||
status_t acquire_vnode(dev_t nsid, ino_t vnodeID);
|
status_t acquire_vnode(dev_t nsid, ino_t vnodeID);
|
||||||
status_t new_vnode(dev_t nsid, ino_t vnid, void* data);
|
status_t new_vnode(dev_t nsid, ino_t vnid, void* data,
|
||||||
|
const FSVNodeCapabilities& capabilities);
|
||||||
status_t publish_vnode(dev_t nsid, ino_t vnid, void* data, int type,
|
status_t publish_vnode(dev_t nsid, ino_t vnid, void* data, int type,
|
||||||
uint32 flags);
|
uint32 flags, const FSVNodeCapabilities& capabilities);
|
||||||
status_t publish_vnode(dev_t nsid, ino_t vnid, void* data);
|
status_t publish_vnode(dev_t nsid, ino_t vnid, void* data,
|
||||||
|
const FSVNodeCapabilities& capabilities);
|
||||||
status_t remove_vnode(dev_t nsid, ino_t vnid);
|
status_t remove_vnode(dev_t nsid, ino_t vnid);
|
||||||
status_t unremove_vnode(dev_t nsid, ino_t vnid);
|
status_t unremove_vnode(dev_t nsid, ino_t vnid);
|
||||||
status_t get_vnode_removed(dev_t nsid, ino_t vnid, bool* removed);
|
status_t get_vnode_removed(dev_t nsid, ino_t vnid, bool* removed);
|
||||||
|
|||||||
Reference in New Issue
Block a user