* 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:
|
||||
ReadVNodeReply() : ReplyRequest(READ_VNODE_REPLY) {}
|
||||
|
||||
void* node;
|
||||
int type;
|
||||
uint32 flags;
|
||||
void* node;
|
||||
int type;
|
||||
uint32 flags;
|
||||
FSVNodeCapabilities capabilities;
|
||||
};
|
||||
|
||||
// WriteVNodeRequest
|
||||
@@ -1604,9 +1605,10 @@ class NewVNodeRequest : public Request {
|
||||
public:
|
||||
NewVNodeRequest() : Request(NEW_VNODE_REQUEST) {}
|
||||
|
||||
dev_t nsid;
|
||||
ino_t vnid;
|
||||
void* node;
|
||||
dev_t nsid;
|
||||
ino_t vnid;
|
||||
void* node;
|
||||
FSVNodeCapabilities capabilities;
|
||||
};
|
||||
|
||||
// NewVNodeReply
|
||||
@@ -1620,11 +1622,12 @@ class PublishVNodeRequest : public Request {
|
||||
public:
|
||||
PublishVNodeRequest() : Request(PUBLISH_VNODE_REQUEST) {}
|
||||
|
||||
dev_t nsid;
|
||||
ino_t vnid;
|
||||
void* node;
|
||||
int type;
|
||||
uint32 flags;
|
||||
dev_t nsid;
|
||||
ino_t vnid;
|
||||
void* node;
|
||||
int type;
|
||||
uint32 flags;
|
||||
FSVNodeCapabilities capabilities;
|
||||
};
|
||||
|
||||
// PublishVNodeReply
|
||||
|
||||
@@ -3,18 +3,22 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "Volume.h"
|
||||
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
#include "AutoLocker.h"
|
||||
#include "Compatibility.h"
|
||||
#include "Debug.h"
|
||||
#include "FileSystem.h"
|
||||
#include "HashMap.h"
|
||||
#include "kernel_interface.h"
|
||||
#include "KernelRequestHandler.h"
|
||||
#include "PortReleaser.h"
|
||||
#include "RequestAllocator.h"
|
||||
#include "Requests.h"
|
||||
#include "Settings.h"
|
||||
#include "SingleReplyRequestHandler.h"
|
||||
#include "Volume.h"
|
||||
|
||||
// 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
|
||||
@@ -30,7 +34,6 @@ struct FileSystem::SelectSyncMap
|
||||
FileSystem::FileSystem()
|
||||
:
|
||||
fVolumes(),
|
||||
fVolumeLock(),
|
||||
fName(),
|
||||
fTeam(-1),
|
||||
fNotificationPort(NULL),
|
||||
@@ -42,6 +45,8 @@ FileSystem::FileSystem()
|
||||
fInitialized(false),
|
||||
fTerminating(false)
|
||||
{
|
||||
mutex_init(&fVolumeLock, "userlandfs volumes");
|
||||
mutex_init(&fVNodeOpsLock, "userlandfs vnode ops");
|
||||
}
|
||||
|
||||
// destructor
|
||||
@@ -65,6 +70,18 @@ FileSystem::~FileSystem()
|
||||
delete fSelectSyncs;
|
||||
}
|
||||
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
|
||||
@@ -83,6 +100,11 @@ FileSystem::Init(const char* name, team_id team, Port::Info* infos, int32 count,
|
||||
if (!fName.SetTo(name))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// init VNodeOps map
|
||||
status_t error = fVNodeOps.Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
fTeam = team;
|
||||
fCapabilities = capabilities;
|
||||
|
||||
@@ -96,7 +118,7 @@ FileSystem::Init(const char* name, team_id team, Port::Info* infos, int32 count,
|
||||
fNotificationPort = new(nothrow) RequestPort(infos);
|
||||
if (!fNotificationPort)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
status_t error = fNotificationPort->InitCheck();
|
||||
error = fNotificationPort->InitCheck();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@@ -198,18 +220,18 @@ FileSystem::Mount(fs_volume* fsVolume, const char* device, uint32 flags,
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// add volume to the volume list
|
||||
fVolumeLock.Lock();
|
||||
MutexLocker locker(fVolumeLock);
|
||||
status_t error = fVolumes.PushBack(volume);
|
||||
fVolumeLock.Unlock();
|
||||
locker.Unlock();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// mount volume
|
||||
error = volume->Mount(device, flags, parameters);
|
||||
if (error != B_OK) {
|
||||
fVolumeLock.Lock();
|
||||
MutexLocker locker(fVolumeLock);
|
||||
fVolumes.Remove(volume);
|
||||
fVolumeLock.Unlock();
|
||||
locker.Unlock();
|
||||
volume->RemoveReference();
|
||||
return error;
|
||||
}
|
||||
@@ -256,16 +278,15 @@ FileSystem::Initialize(const char* deviceName, const char* parameters,
|
||||
void
|
||||
FileSystem::VolumeUnmounted(Volume* volume)
|
||||
{
|
||||
fVolumeLock.Lock();
|
||||
MutexLocker locker(fVolumeLock);
|
||||
fVolumes.Remove(volume);
|
||||
fVolumeLock.Unlock();
|
||||
}
|
||||
|
||||
// GetVolume
|
||||
Volume*
|
||||
FileSystem::GetVolume(dev_t id)
|
||||
{
|
||||
AutoLocker<Locker> _(fVolumeLock);
|
||||
MutexLocker _(fVolumeLock);
|
||||
for (Vector<Volume*>::Iterator it = fVolumes.Begin();
|
||||
it != fVolumes.End();
|
||||
it++) {
|
||||
@@ -318,6 +339,7 @@ FileSystem::RemoveSelectSyncEntry(selectsync* sync)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// KnowsSelectSyncEntry
|
||||
bool
|
||||
FileSystem::KnowsSelectSyncEntry(selectsync* sync)
|
||||
@@ -325,6 +347,54 @@ FileSystem::KnowsSelectSyncEntry(selectsync* 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
|
||||
bool
|
||||
FileSystem::IsUserlandServerThread() const
|
||||
@@ -334,6 +404,108 @@ FileSystem::IsUserlandServerThread() const
|
||||
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
|
||||
int32
|
||||
FileSystem::_NotificationThreadEntry(void* data)
|
||||
@@ -341,6 +513,7 @@ FileSystem::_NotificationThreadEntry(void* data)
|
||||
return ((FileSystem*)data)->_NotificationThread();
|
||||
}
|
||||
|
||||
|
||||
// _NotificationThread
|
||||
int32
|
||||
FileSystem::_NotificationThread()
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
|
||||
#include <fs_interface.h>
|
||||
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include <lock.h>
|
||||
|
||||
#include "FSCapabilities.h"
|
||||
#include "LazyInitializable.h"
|
||||
#include "Locker.h"
|
||||
@@ -20,6 +24,42 @@ struct IOCtlInfo;
|
||||
class Settings;
|
||||
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 {
|
||||
public:
|
||||
FileSystem();
|
||||
@@ -52,9 +92,16 @@ public:
|
||||
void RemoveSelectSyncEntry(selectsync* sync);
|
||||
bool KnowsSelectSyncEntry(selectsync* sync);
|
||||
|
||||
VNodeOps* GetVNodeOps(
|
||||
const FSVNodeCapabilities& capabilities);
|
||||
void PutVNodeOps(VNodeOps* ops);
|
||||
|
||||
bool IsUserlandServerThread() const;
|
||||
|
||||
private:
|
||||
void _InitVNodeOpsVector(fs_vnode_ops* ops,
|
||||
const FSVNodeCapabilities& capabilities);
|
||||
|
||||
static int32 _NotificationThreadEntry(void* data);
|
||||
int32 _NotificationThread();
|
||||
|
||||
@@ -62,9 +109,12 @@ private:
|
||||
friend class KernelDebug;
|
||||
struct SelectSyncEntry;
|
||||
struct SelectSyncMap;
|
||||
typedef OpenHashTable<VNodeOpsHashDefinition> VNodeOpsMap;
|
||||
|
||||
Vector<Volume*> fVolumes;
|
||||
Locker fVolumeLock;
|
||||
mutex fVolumeLock;
|
||||
VNodeOpsMap fVNodeOps;
|
||||
mutex fVNodeOpsLock;
|
||||
String fName;
|
||||
team_id fTeam;
|
||||
FSCapabilities fCapabilities;
|
||||
|
||||
@@ -403,8 +403,11 @@ KernelRequestHandler::_HandleRequest(NewVNodeRequest* request)
|
||||
Volume* volume = NULL;
|
||||
status_t result = _GetVolume(request->nsid, &volume);
|
||||
VolumePutter _(volume);
|
||||
if (result == B_OK)
|
||||
result = volume->NewVNode(request->vnid, request->node);
|
||||
if (result == B_OK) {
|
||||
result = volume->NewVNode(request->vnid, request->node,
|
||||
request->capabilities);
|
||||
}
|
||||
|
||||
// prepare the reply
|
||||
RequestAllocator allocator(fPort->GetPort());
|
||||
NewVNodeReply* reply;
|
||||
@@ -412,6 +415,7 @@ KernelRequestHandler::_HandleRequest(NewVNodeRequest* request)
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
reply->error = result;
|
||||
|
||||
// send the reply
|
||||
return fPort->SendRequest(&allocator);
|
||||
}
|
||||
@@ -426,7 +430,7 @@ KernelRequestHandler::_HandleRequest(PublishVNodeRequest* request)
|
||||
VolumePutter _(volume);
|
||||
if (result == B_OK) {
|
||||
result = volume->PublishVNode(request->vnid, request->node,
|
||||
request->type, request->flags);
|
||||
request->type, request->flags, request->capabilities);
|
||||
}
|
||||
|
||||
// prepare the reply
|
||||
|
||||
@@ -47,22 +47,32 @@ static const bigtime_t kUserlandServerlandPortTimeout = 10000000; // 10s
|
||||
|
||||
// VNode
|
||||
struct Volume::VNode : HashTableLink<VNode> {
|
||||
ino_t id;
|
||||
void* clientNode;
|
||||
void* fileCache;
|
||||
int32 useCount;
|
||||
bool valid;
|
||||
ino_t id;
|
||||
void* clientNode;
|
||||
void* fileCache;
|
||||
VNodeOps* ops;
|
||||
int32 useCount;
|
||||
bool valid;
|
||||
|
||||
VNode(ino_t id, void* clientNode)
|
||||
VNode(ino_t id, void* clientNode, VNodeOps* ops)
|
||||
:
|
||||
id(id),
|
||||
clientNode(clientNode),
|
||||
fileCache(NULL),
|
||||
ops(ops),
|
||||
useCount(0),
|
||||
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()
|
||||
{
|
||||
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
|
||||
|
||||
// GetVNode
|
||||
@@ -342,7 +331,8 @@ PRINT(("acquire_vnode(%ld, %lld)\n", GetID(), vnid));
|
||||
|
||||
// NewVNode
|
||||
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));
|
||||
// lookup the node
|
||||
@@ -353,17 +343,24 @@ PRINT(("new_vnode(%ld, %lld)\n", GetID(), vnid));
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
}
|
||||
|
||||
// create the node
|
||||
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);
|
||||
|
||||
// create the node
|
||||
node = new(std::nothrow) VNode(vnid, clientNode, ops);
|
||||
if (node == NULL) {
|
||||
fFileSystem->PutVNodeOps(ops);
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
}
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
// 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) {
|
||||
delete node;
|
||||
node->Delete(this);
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
@@ -376,7 +373,8 @@ PRINT(("new_vnode(%ld, %lld)\n", GetID(), vnid));
|
||||
|
||||
// PublishVNode
|
||||
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));
|
||||
// lookup the node
|
||||
@@ -386,21 +384,30 @@ PRINT(("publish_vnode(%ld, %lld, %p)\n", GetID(), vnid, clientNode));
|
||||
|
||||
if (!nodeKnown) {
|
||||
// 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);
|
||||
|
||||
// create the node
|
||||
node = new(std::nothrow) VNode(vnid, clientNode, ops);
|
||||
if (node == NULL) {
|
||||
fFileSystem->PutVNodeOps(ops);
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
// 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);
|
||||
if (error != B_OK) {
|
||||
// TODO: We should note whether the node was made known via new_vnode(). If so,
|
||||
// we should remove and delete it here!
|
||||
if (!nodeKnown)
|
||||
delete node;
|
||||
node->Delete(this);
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
@@ -690,29 +697,33 @@ Volume::Mount(const char* device, uint32 flags, const char* parameters)
|
||||
|
||||
// mount
|
||||
status_t error = _Mount(device, flags, parameters);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
if (error == B_OK) {
|
||||
MutexLocker locker(fLock);
|
||||
// fetch the root node, so that we can serve Walk() requests on it,
|
||||
// after the connection to the userland server is gone
|
||||
fRootNode = fVNodes->Lookup(fRootID);
|
||||
if (fRootNode == NULL) {
|
||||
// The root node was not added while mounting. That's a serious
|
||||
// problem -- not only because we don't have it, but also because
|
||||
// the VFS requires publish_vnode() to be invoked for the root node.
|
||||
ERROR(("Volume::Mount(): new_vnode() was not called for root node! "
|
||||
"Unmounting...\n"));
|
||||
locker.Unlock();
|
||||
Unmount();
|
||||
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--;
|
||||
MutexLocker locker(fLock);
|
||||
// fetch the root node, so that we can serve Walk() requests on it,
|
||||
// after the connection to the userland server is gone
|
||||
fRootNode = fVNodes->Lookup(fRootID);
|
||||
if (fRootNode == NULL) {
|
||||
// The root node was not added while mounting. That's a serious
|
||||
// problem -- not only because we don't have it, but also because
|
||||
// the VFS requires publish_vnode() to be invoked for the root node.
|
||||
ERROR(("Volume::Mount(): new_vnode() was not called for root node! "
|
||||
"Unmounting...\n"));
|
||||
locker.Unlock();
|
||||
Unmount();
|
||||
return B_ERROR;
|
||||
}
|
||||
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
|
||||
@@ -729,7 +740,7 @@ Volume::Unmount()
|
||||
VNode* node = fVNodes->Clear(true);
|
||||
while (node != NULL) {
|
||||
VNode* nextNode = node->fNext;
|
||||
delete node;
|
||||
node->Delete(this);
|
||||
node = nextNode;
|
||||
}
|
||||
delete fVNodes;
|
||||
@@ -937,8 +948,8 @@ Volume::GetVNodeName(void* _node, char* buffer, size_t bufferSize)
|
||||
|
||||
// ReadVNode
|
||||
status_t
|
||||
Volume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
||||
uint32* flags)
|
||||
Volume::ReadVNode(ino_t vnid, bool reenter, void** _node, fs_vnode_ops** _ops,
|
||||
int* type, uint32* flags)
|
||||
{
|
||||
// get a free port
|
||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||
@@ -958,7 +969,7 @@ Volume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
||||
request->reenter = reenter;
|
||||
|
||||
// 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)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
vnode->valid = false;
|
||||
@@ -983,14 +994,23 @@ Volume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
||||
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
|
||||
locker.Lock();
|
||||
vnode->clientNode = reply->node;
|
||||
vnode->ops = ops;
|
||||
vnode->valid = true;
|
||||
|
||||
*_node = vnode;
|
||||
*type = reply->type;
|
||||
*flags = reply->flags;
|
||||
*_ops = ops->ops;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -1021,7 +1041,7 @@ Volume::RemoveVNode(void* _node, bool reenter)
|
||||
locker.Unlock();
|
||||
|
||||
void* clientNode = vnode->clientNode;
|
||||
delete vnode;
|
||||
vnode->Delete(this);
|
||||
|
||||
// get a free port
|
||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||
@@ -3461,6 +3481,60 @@ Volume::RewindQuery(void* cookie)
|
||||
// #pragma mark -
|
||||
// #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
|
||||
status_t
|
||||
Volume::_Mount(const char* device, uint32 flags, const char* parameters)
|
||||
@@ -3636,7 +3710,7 @@ Volume::_WriteVNode(void* _node, bool reenter)
|
||||
locker.Unlock();
|
||||
|
||||
void* clientNode = vnode->clientNode;
|
||||
delete vnode;
|
||||
vnode->Delete(this);
|
||||
|
||||
// get a free port
|
||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||
@@ -4280,7 +4354,7 @@ Volume::_RemoveInvalidVNode(ino_t vnid)
|
||||
for (; vnode->useCount > 0; vnode->useCount--)
|
||||
put_vnode(fFSVolume, vnid);
|
||||
|
||||
delete vnode;
|
||||
vnode->Delete(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,21 +38,24 @@ public:
|
||||
fs_volume* fsVolume);
|
||||
~Volume();
|
||||
|
||||
FileSystem* GetFileSystem() const;
|
||||
inline FileSystem* GetFileSystem() const;
|
||||
inline dev_t GetID() const;
|
||||
|
||||
inline fs_volume_ops* GetVolumeOps() { return &fVolumeOps; }
|
||||
inline bool HasCapability(int capability) const;
|
||||
|
||||
void* GetUserlandVolume() const;
|
||||
ino_t GetRootID() const;
|
||||
inline void* GetUserlandVolume() const;
|
||||
inline ino_t GetRootID() const;
|
||||
|
||||
// client methods
|
||||
status_t GetVNode(ino_t vnid, void** node);
|
||||
status_t PutVNode(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,
|
||||
int type, uint32 flags);
|
||||
int type, uint32 flags,
|
||||
const FSVNodeCapabilities& capabilities);
|
||||
status_t RemoveVNode(ino_t vnid);
|
||||
status_t UnremoveVNode(ino_t vnid);
|
||||
status_t GetVNodeRemoved(ino_t vnid, bool* removed);
|
||||
@@ -88,7 +91,8 @@ public:
|
||||
status_t GetVNodeName(void* node, char* buffer,
|
||||
size_t bufferSize);
|
||||
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 RemoveVNode(void* node, bool reenter);
|
||||
|
||||
@@ -227,6 +231,8 @@ private:
|
||||
friend class IORequestRemover;
|
||||
|
||||
private:
|
||||
void _InitVolumeOps();
|
||||
|
||||
status_t _Mount(const char* device, uint32 flags,
|
||||
const char* parameters);
|
||||
status_t _Unmount();
|
||||
@@ -289,6 +295,7 @@ private:
|
||||
FileSystem* fFileSystem;
|
||||
fs_volume* fFSVolume;
|
||||
FSVolumeCapabilities fCapabilities;
|
||||
fs_volume_ops fVolumeOps;
|
||||
void* fUserlandVolume;
|
||||
ino_t fRootID;
|
||||
VNode* fRootNode;
|
||||
@@ -314,6 +321,15 @@ Volume::GetID() const
|
||||
}
|
||||
|
||||
|
||||
// GetFileSystem
|
||||
inline FileSystem*
|
||||
Volume::GetFileSystem() const
|
||||
{
|
||||
return fFileSystem;
|
||||
}
|
||||
|
||||
|
||||
// HasCapability
|
||||
inline bool
|
||||
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
|
||||
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->ops = &gUserlandFSVolumeOps;
|
||||
fsVolume->ops = volume->GetVolumeOps();
|
||||
*rootVnodeID = volume->GetRootID();
|
||||
|
||||
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,
|
||||
fsNode->private_node, reenter));
|
||||
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) {
|
||||
fsNode->private_node = node;
|
||||
fsNode->ops = &gUserlandFSVnodeOps;
|
||||
fsNode->ops = ops;
|
||||
}
|
||||
|
||||
PRINT(("userlandfs_get_vnode() done: (%lx, %p)\n", error, node));
|
||||
|
||||
@@ -466,10 +466,11 @@ UserlandRequestHandler::_HandleRequest(ReadVNodeRequest* request)
|
||||
void* node;
|
||||
int type;
|
||||
uint32 flags;
|
||||
FSVNodeCapabilities capabilities;
|
||||
if (result == B_OK) {
|
||||
RequestThreadContext context(volume);
|
||||
result = volume->ReadVNode(request->vnid, request->reenter, &node,
|
||||
&type, &flags);
|
||||
&type, &flags, &capabilities);
|
||||
}
|
||||
|
||||
// prepare the reply
|
||||
@@ -483,6 +484,7 @@ UserlandRequestHandler::_HandleRequest(ReadVNodeRequest* request)
|
||||
reply->node = node;
|
||||
reply->type = type;
|
||||
reply->flags = flags;
|
||||
reply->capabilities = capabilities;
|
||||
|
||||
// send the reply
|
||||
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"
|
||||
|
||||
@@ -169,7 +172,7 @@ Volume::GetVNodeName(void* node, char* buffer, size_t bufferSize)
|
||||
// ReadVNode
|
||||
status_t
|
||||
Volume::ReadVNode(ino_t vnid, bool reenter, void** node, int* type,
|
||||
uint32* flags)
|
||||
uint32* flags, FSVNodeCapabilities* _capabilities)
|
||||
{
|
||||
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
|
||||
#define USERLAND_FS_VOLUME_H
|
||||
|
||||
@@ -49,7 +51,8 @@ public:
|
||||
virtual status_t GetVNodeName(void* node, char* buffer,
|
||||
size_t bufferSize);
|
||||
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 RemoveVNode(void* node, bool reenter);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "beos_kernel_emu.h"
|
||||
#include "BeOSKernelVolume.h"
|
||||
#include "fs_cache.h"
|
||||
#include "fs_interface.h"
|
||||
@@ -76,6 +77,8 @@ void
|
||||
BeOSKernelFileSystem::_InitCapabilities()
|
||||
{
|
||||
fCapabilities.ClearAll();
|
||||
fVolumeCapabilities.ClearAll();
|
||||
fNodeCapabilities.ClearAll();
|
||||
|
||||
// FS interface type
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -11,6 +14,7 @@
|
||||
|
||||
#include "../kernel_emu.h"
|
||||
|
||||
#include "BeOSKernelFileSystem.h"
|
||||
#include "fs_interface.h"
|
||||
|
||||
|
||||
@@ -40,6 +44,14 @@ public:
|
||||
};
|
||||
|
||||
|
||||
// _FileSystem
|
||||
inline BeOSKernelFileSystem*
|
||||
BeOSKernelVolume::_FileSystem() const
|
||||
{
|
||||
return static_cast<BeOSKernelFileSystem*>(fFileSystem);
|
||||
}
|
||||
|
||||
|
||||
// constructor
|
||||
BeOSKernelVolume::BeOSKernelVolume(FileSystem* fileSystem, dev_t id,
|
||||
beos_vnode_ops* fsOps, const FSVolumeCapabilities& capabilities)
|
||||
@@ -165,7 +177,7 @@ BeOSKernelVolume::GetVNodeType(void* node, int* type)
|
||||
// ReadVNode
|
||||
status_t
|
||||
BeOSKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** node, int* type,
|
||||
uint32* flags)
|
||||
uint32* flags, FSVNodeCapabilities* _capabilities)
|
||||
{
|
||||
if (!fFSOps->read_vnode)
|
||||
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);
|
||||
*flags = 0;
|
||||
_FileSystem()->GetNodeCapabilities(*_capabilities);
|
||||
|
||||
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
|
||||
#define USERLAND_FS_BEOS_KERNEL_VOLUME_H
|
||||
|
||||
@@ -9,6 +11,9 @@ struct beos_vnode_ops;
|
||||
|
||||
namespace UserlandFS {
|
||||
|
||||
class BeOSKernelFileSystem;
|
||||
|
||||
|
||||
class BeOSKernelVolume : public Volume {
|
||||
public:
|
||||
BeOSKernelVolume(FileSystem* fileSystem,
|
||||
@@ -33,7 +38,8 @@ public:
|
||||
// the three parameters publish_vnode() is
|
||||
// used.
|
||||
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 RemoveVNode(void* node, bool reenter);
|
||||
|
||||
@@ -154,6 +160,7 @@ private:
|
||||
status_t _OpenAttr(void* node, const char* name,
|
||||
uint32 type, int openMode, bool create,
|
||||
void** cookie);
|
||||
inline BeOSKernelFileSystem* _FileSystem() const;
|
||||
|
||||
private:
|
||||
beos_vnode_ops* fFSOps;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// beos_kernel_emu.cpp
|
||||
|
||||
#include "beos_kernel_emu.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -145,9 +147,14 @@ put_vnode(nspace_id nsid, ino_t vnid)
|
||||
int
|
||||
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()
|
||||
// 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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -37,6 +40,40 @@ struct HaikuKernelFileSystem::IORequestHashDefinition {
|
||||
// IORequestTable
|
||||
struct HaikuKernelFileSystem::IORequestTable
|
||||
: 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(),
|
||||
fFSModule(fsModule),
|
||||
fIORequests(NULL),
|
||||
fNodeCapabilities(NULL),
|
||||
fLock("HaikuKernelFileSystem")
|
||||
{
|
||||
_InitCapabilities();
|
||||
@@ -60,6 +98,7 @@ HaikuKernelFileSystem::~HaikuKernelFileSystem()
|
||||
fFSModule->info.std_ops(B_MODULE_UNINIT);
|
||||
|
||||
delete fIORequests;
|
||||
delete fNodeCapabilities;
|
||||
|
||||
// TODO: Call the cleanup methods (condition vars, block cache)!
|
||||
}
|
||||
@@ -91,6 +130,15 @@ HaikuKernelFileSystem::Init()
|
||||
if (error != B_OK)
|
||||
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)
|
||||
if (!fFSModule->info.std_ops)
|
||||
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
|
||||
void
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
#define USERLAND_FS_HAIKU_KERNEL_FILE_SYSTEM_H
|
||||
|
||||
#include "Locker.h"
|
||||
|
||||
#include "HaikuKernelNode.h"
|
||||
|
||||
#include "../FileSystem.h"
|
||||
|
||||
|
||||
struct file_system_module_info;
|
||||
|
||||
|
||||
namespace UserlandFS {
|
||||
|
||||
struct HaikuKernelIORequest;
|
||||
@@ -29,16 +35,27 @@ public:
|
||||
void PutIORequest(HaikuKernelIORequest* request,
|
||||
int32 refCount = 1);
|
||||
|
||||
HaikuKernelNode::Capabilities* GetNodeCapabilities(
|
||||
fs_vnode_ops* ops);
|
||||
void PutNodeCapabilities(
|
||||
HaikuKernelNode::Capabilities*
|
||||
capabilities);
|
||||
|
||||
private:
|
||||
class IORequestHashDefinition;
|
||||
class IORequestTable;
|
||||
struct IORequestHashDefinition;
|
||||
struct IORequestTable;
|
||||
struct NodeCapabilitiesHashDefinition;
|
||||
struct NodeCapabilitiesTable;
|
||||
|
||||
private:
|
||||
void _InitCapabilities();
|
||||
static void _InitNodeCapabilities(fs_vnode_ops* ops,
|
||||
FSVNodeCapabilities& capabilities);
|
||||
|
||||
private:
|
||||
file_system_module_info* fFSModule;
|
||||
IORequestTable* fIORequests;
|
||||
NodeCapabilitiesTable* fNodeCapabilities;
|
||||
Locker fLock;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
#include <fs_interface.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include "FSCapabilities.h"
|
||||
|
||||
|
||||
namespace UserlandFS {
|
||||
|
||||
class HaikuKernelVolume;
|
||||
@@ -18,14 +21,19 @@ using UserlandFSUtil::FSVNodeCapabilities;
|
||||
|
||||
|
||||
struct HaikuKernelNode : fs_vnode {
|
||||
struct Capabilities;
|
||||
|
||||
ino_t id;
|
||||
HaikuKernelVolume* volume;
|
||||
Capabilities* capabilities;
|
||||
bool published;
|
||||
|
||||
public:
|
||||
inline HaikuKernelNode(HaikuKernelVolume* volume,
|
||||
ino_t vnodeID, void* privateNode,
|
||||
fs_vnode_ops* ops);
|
||||
fs_vnode_ops* ops,
|
||||
Capabilities* capabilities);
|
||||
~HaikuKernelNode();
|
||||
|
||||
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,
|
||||
void* privateNode, fs_vnode_ops* ops)
|
||||
void* privateNode, fs_vnode_ops* ops, Capabilities* capabilities)
|
||||
:
|
||||
id(vnodeID),
|
||||
volume(volume),
|
||||
capabilities(capabilities),
|
||||
published(false)
|
||||
{
|
||||
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"
|
||||
|
||||
@@ -84,11 +87,20 @@ HaikuKernelVolume::NewVNode(ino_t vnodeID, void* privateNode, fs_vnode_ops* ops,
|
||||
if (node != NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// create a new node
|
||||
node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode, ops);
|
||||
if (node == NULL)
|
||||
// get node capabilities
|
||||
HaikuKernelNode::Capabilities* capabilities
|
||||
= _FileSystem()->GetNodeCapabilities(ops);
|
||||
if (capabilities == NULL)
|
||||
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
|
||||
status_t error = fNodes->Put(vnodeID, node);
|
||||
if (error != B_OK) {
|
||||
@@ -115,11 +127,19 @@ HaikuKernelVolume::PublishVNode(ino_t vnodeID, void* privateNode,
|
||||
if (node->published)
|
||||
return B_BAD_VALUE;
|
||||
} else {
|
||||
// get node capabilities
|
||||
HaikuKernelNode::Capabilities* capabilities
|
||||
= _FileSystem()->GetNodeCapabilities(ops);
|
||||
if (capabilities == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// create a new node
|
||||
node = new(std::nothrow) HaikuKernelNode(this, vnodeID, privateNode,
|
||||
ops);
|
||||
if (node == NULL)
|
||||
ops, capabilities);
|
||||
if (node == NULL) {
|
||||
_FileSystem()->PutNodeCapabilities(capabilities);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
// add to map
|
||||
status_t error = fNodes->Put(vnodeID, node);
|
||||
@@ -271,14 +291,14 @@ HaikuKernelVolume::GetVNodeName(void* _node, char* buffer, size_t bufferSize)
|
||||
// ReadVNode
|
||||
status_t
|
||||
HaikuKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
||||
uint32* flags)
|
||||
uint32* flags, FSVNodeCapabilities* _capabilities)
|
||||
{
|
||||
if (!fVolume.ops->get_vnode)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// create a new wrapper node and add it to the map
|
||||
HaikuKernelNode* node = new(std::nothrow) HaikuKernelNode(this, vnid, NULL,
|
||||
NULL);
|
||||
NULL, NULL);
|
||||
if (node == NULL)
|
||||
return B_NO_MEMORY;
|
||||
ObjectDeleter<HaikuKernelNode> nodeDeleter(node);
|
||||
@@ -301,11 +321,23 @@ HaikuKernelVolume::ReadVNode(ino_t vnid, bool reenter, void** _node, int* type,
|
||||
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();
|
||||
node->capabilities = capabilities;
|
||||
node->published = true;
|
||||
nodeDeleter.Detach();
|
||||
|
||||
*_node = node;
|
||||
*_capabilities = capabilities->capabilities;
|
||||
|
||||
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_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
|
||||
#define USERLAND_FS_HAIKU_KERNEL_VOLUME_H
|
||||
|
||||
@@ -56,7 +58,8 @@ public:
|
||||
virtual status_t GetVNodeName(void* node, char* buffer,
|
||||
size_t bufferSize);
|
||||
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 RemoveVNode(void* node, bool reenter);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ SharedLibrary libuserlandfs_haiku_kernel.so
|
||||
|
||||
# UserlandFS server interface
|
||||
HaikuKernelFileSystem.cpp
|
||||
HaikuKernelNode.cpp
|
||||
HaikuKernelVolume.cpp
|
||||
|
||||
:
|
||||
|
||||
@@ -136,7 +136,8 @@ new_vnode(fs_volume *_volume, ino_t vnodeID, void *privateNode,
|
||||
return error;
|
||||
|
||||
// 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)
|
||||
volume->UndoNewVNode(node);
|
||||
|
||||
@@ -159,7 +160,7 @@ publish_vnode(fs_volume *_volume, ino_t vnodeID, void *privateNode,
|
||||
|
||||
// publish the new node
|
||||
error = UserlandFS::KernelEmu::publish_vnode(volume->GetID(), vnodeID, node,
|
||||
type, flags);
|
||||
type, flags, node->capabilities->capabilities);
|
||||
if (error != B_OK)
|
||||
volume->UndoPublishVNode(node);
|
||||
|
||||
|
||||
@@ -365,7 +365,8 @@ UserlandFS::KernelEmu::acquire_vnode(dev_t nsid, ino_t vnid)
|
||||
|
||||
// new_vnode
|
||||
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
|
||||
RequestPort* port;
|
||||
@@ -384,6 +385,7 @@ UserlandFS::KernelEmu::new_vnode(dev_t nsid, ino_t vnid, void* data)
|
||||
request->nsid = nsid;
|
||||
request->vnid = vnid;
|
||||
request->node = data;
|
||||
request->capabilities = capabilities;
|
||||
|
||||
// send the request
|
||||
UserlandRequestHandler handler(fileSystem, NEW_VNODE_REPLY);
|
||||
@@ -402,7 +404,7 @@ UserlandFS::KernelEmu::new_vnode(dev_t nsid, ino_t vnid, void* data)
|
||||
// publish_vnode
|
||||
status_t
|
||||
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
|
||||
RequestPort* port;
|
||||
@@ -423,6 +425,7 @@ UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data,
|
||||
request->node = data;
|
||||
request->type = type;
|
||||
request->flags = flags;
|
||||
request->capabilities = capabilities;
|
||||
|
||||
// send the request
|
||||
UserlandRequestHandler handler(fileSystem, PUBLISH_VNODE_REPLY);
|
||||
@@ -441,7 +444,8 @@ UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data,
|
||||
|
||||
// publish_vnode
|
||||
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
|
||||
Volume* volume = FileSystem::GetInstance()->VolumeWithID(nsid);
|
||||
@@ -455,7 +459,8 @@ UserlandFS::KernelEmu::publish_vnode(dev_t nsid, ino_t vnid, void* data)
|
||||
return error;
|
||||
|
||||
// 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 "FSCapabilities.h"
|
||||
|
||||
|
||||
struct selectsync;
|
||||
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 put_vnode(dev_t nsid, ino_t vnid);
|
||||
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,
|
||||
uint32 flags);
|
||||
status_t publish_vnode(dev_t nsid, ino_t vnid, void* data);
|
||||
uint32 flags, const FSVNodeCapabilities& capabilities);
|
||||
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 unremove_vnode(dev_t nsid, ino_t vnid);
|
||||
status_t get_vnode_removed(dev_t nsid, ino_t vnid, bool* removed);
|
||||
|
||||
Reference in New Issue
Block a user