We analyze a client FS's capabilities -- i.e. which hooks it provides or

can be emulated -- and pass this info to the kernel add-on. Thus we can
avoid passing requests to the userland that can't be serviced anyway.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20331 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2007-03-05 05:16:08 +00:00
parent cf4ccd6575
commit 4e0e80ed6c
13 changed files with 629 additions and 19 deletions

View File

@ -0,0 +1,191 @@
// FSCapabilities.h
#ifndef USERLAND_FS_FS_CAPABILITIES_H
#define USERLAND_FS_FS_CAPABILITIES_H
#include <string.h>
#include <stdio.h>
#include "Debug.h"
enum client_fs_type {
CLIENT_FS_BEOS_KERNEL = 0,
CLIENT_FS_HAIKU_KERNEL,
};
enum {
// FS operations
FS_CAPABILITY_MOUNT = 0,
FS_CAPABILITY_UNMOUNT,
FS_CAPABILITY_READ_FS_INFO,
FS_CAPABILITY_WRITE_FS_INFO,
FS_CAPABILITY_SYNC,
// vnode operations
FS_CAPABILITY_LOOKUP,
FS_CAPABILITY_GET_VNODE_NAME,
FS_CAPABILITY_GET_VNODE,
FS_CAPABILITY_PUT_VNODE,
FS_CAPABILITY_REMOVE_VNODE,
// VM file access
FS_CAPABILITY_CAN_PAGE,
FS_CAPABILITY_READ_PAGES,
FS_CAPABILITY_WRITE_PAGES,
// cache file access
FS_CAPABILITY_GET_FILE_MAP,
// common operations
FS_CAPABILITY_IOCTL,
FS_CAPABILITY_SET_FLAGS,
FS_CAPABILITY_SELECT,
FS_CAPABILITY_DESELECT,
FS_CAPABILITY_FSYNC,
FS_CAPABILITY_READ_SYMLINK,
FS_CAPABILITY_CREATE_SYMLINK,
FS_CAPABILITY_LINK,
FS_CAPABILITY_UNLINK,
FS_CAPABILITY_RENAME,
FS_CAPABILITY_ACCESS,
FS_CAPABILITY_READ_STAT,
FS_CAPABILITY_WRITE_STAT,
// file operations
FS_CAPABILITY_CREATE,
FS_CAPABILITY_OPEN,
FS_CAPABILITY_CLOSE,
FS_CAPABILITY_FREE_COOKIE,
FS_CAPABILITY_READ,
FS_CAPABILITY_WRITE,
// directory operations
FS_CAPABILITY_CREATE_DIR,
FS_CAPABILITY_REMOVE_DIR,
FS_CAPABILITY_OPEN_DIR,
FS_CAPABILITY_CLOSE_DIR,
FS_CAPABILITY_FREE_DIR_COOKIE,
FS_CAPABILITY_READ_DIR,
FS_CAPABILITY_REWIND_DIR,
// attribute directory operations
FS_CAPABILITY_OPEN_ATTR_DIR,
FS_CAPABILITY_CLOSE_ATTR_DIR,
FS_CAPABILITY_FREE_ATTR_DIR_COOKIE,
FS_CAPABILITY_READ_ATTR_DIR,
FS_CAPABILITY_REWIND_ATTR_DIR,
// attribute operations
FS_CAPABILITY_CREATE_ATTR,
FS_CAPABILITY_OPEN_ATTR,
FS_CAPABILITY_CLOSE_ATTR,
FS_CAPABILITY_FREE_ATTR_COOKIE,
FS_CAPABILITY_READ_ATTR,
FS_CAPABILITY_WRITE_ATTR,
FS_CAPABILITY_READ_ATTR_STAT,
FS_CAPABILITY_WRITE_ATTR_STAT,
FS_CAPABILITY_RENAME_ATTR,
FS_CAPABILITY_REMOVE_ATTR,
// index directory & index operations
FS_CAPABILITY_OPEN_INDEX_DIR,
FS_CAPABILITY_CLOSE_INDEX_DIR,
FS_CAPABILITY_FREE_INDEX_DIR_COOKIE,
FS_CAPABILITY_READ_INDEX_DIR,
FS_CAPABILITY_REWIND_INDEX_DIR,
FS_CAPABILITY_CREATE_INDEX,
FS_CAPABILITY_REMOVE_INDEX,
FS_CAPABILITY_READ_INDEX_STAT,
// query operations
FS_CAPABILITY_OPEN_QUERY,
FS_CAPABILITY_CLOSE_QUERY,
FS_CAPABILITY_FREE_QUERY_COOKIE,
FS_CAPABILITY_READ_QUERY,
FS_CAPABILITY_REWIND_QUERY,
FS_CAPABILITY_COUNT,
};
namespace UserlandFSUtil {
struct FSCapabilities {
client_fs_type clientFSType;
uint8 capabilities[(FS_CAPABILITY_COUNT + 7) / 8];
inline void ClearAll();
inline void Set(uint32 capability, bool set = true);
inline void Clear(uint32 capability);
inline bool Get(uint32 capability) const;
inline void Dump() const;
};
// ClearAll
inline void
FSCapabilities::ClearAll()
{
memset(capabilities, 0, sizeof(capabilities));
}
// Set
inline void
FSCapabilities::Set(uint32 capability, bool set)
{
if (capability >= FS_CAPABILITY_COUNT)
return;
uint8 flag = uint8(1 << (capability % 8));
if (set)
capabilities[capability / 8] |= flag;
else
capabilities[capability / 8] &= ~flag;
}
// Clear
inline void
FSCapabilities::Clear(uint32 capability)
{
Set(capability, false);
}
// Get
inline bool
FSCapabilities::Get(uint32 capability) const
{
if (capability >= FS_CAPABILITY_COUNT)
return false;
uint8 flag = uint8(1 << (capability % 8));
return (capabilities[capability / 8] & flag);
}
// Dump
inline void
FSCapabilities::Dump() const
{
D(
char buffer[128];
int byteCount = sizeof(capabilities);
for (int i = 0; i < byteCount; i++)
sprintf(buffer + 2 * i, "%02x", (int)capabilities[i]);
PRINT(("FSCapabilities[%d, %s]\n", clientFSType, buffer));
)
}
} // namespace UserlandFSUtil
using UserlandFSUtil::FSCapabilities;
#endif // USERLAND_FS_FS_CAPABILITIES_H

View File

@ -9,6 +9,7 @@
#include <fs_interface.h>
#include "Compatibility.h"
#include "FSCapabilities.h"
#include "Request.h"
@ -304,8 +305,9 @@ public:
FSConnectReply() : ReplyRequest(FS_CONNECT_REPLY) {}
status_t GetAddressInfos(AddressInfo* infos, int32* count);
Address portInfos;
int32 portInfoCount;
Address portInfos;
int32 portInfoCount;
FSCapabilities capabilities;
};

View File

@ -64,9 +64,11 @@ FileSystem::~FileSystem()
// Init
status_t
FileSystem::Init(const char* name, Port::Info* infos, int32 count)
FileSystem::Init(const char* name, Port::Info* infos, int32 count,
const FSCapabilities& capabilities)
{
PRINT(("FileSystem::Init(\"%s\", %p, %ld)\n", name, infos, infoCount));
PRINT(("FileSystem::Init(\"%s\", %p, %ld)\n", name, infos, count));
capabilities.Dump();
// check parameters
if (!name || !infos || count < 2)
@ -76,6 +78,8 @@ FileSystem::Init(const char* name, Port::Info* infos, int32 count)
if (!fName.SetTo(name))
return B_NO_MEMORY;
fCapabilities = capabilities;
// create the select sync entry map
fSelectSyncs = new(nothrow) SelectSyncMap;
if (!fSelectSyncs)
@ -159,6 +163,13 @@ FileSystem::GetName() const
return fName.GetString();
}
// GetCapabilities
const FSCapabilities&
FileSystem::GetCapabilities() const
{
return fCapabilities;
}
// GetPortPool
RequestPortPool*
FileSystem::GetPortPool()

View File

@ -5,6 +5,7 @@
#include <fs_interface.h>
#include "FSCapabilities.h"
#include "LazyInitializable.h"
#include "Locker.h"
#include "Referencable.h"
@ -24,10 +25,14 @@ public:
~FileSystem();
status_t Init(const char* name, Port::Info* infos,
int32 infoCount);
int32 infoCount,
const FSCapabilities& capabilities);
const char* GetName() const;
const FSCapabilities& GetCapabilities() const;
inline bool HasCapability(uint32 capability) const;
RequestPortPool* GetPortPool();
status_t Mount(mount_id id, const char* device,
@ -59,6 +64,7 @@ private:
Vector<Volume*> fVolumes;
Locker fVolumeLock;
String fName;
FSCapabilities fCapabilities;
RequestPort* fNotificationPort;
thread_id fNotificationThread;
RequestPortPool fPortPool;
@ -69,4 +75,12 @@ private:
volatile bool fTerminating;
};
// HasCapability
inline bool
FileSystem::HasCapability(uint32 capability) const
{
return fCapabilities.Get(capability);
}
#endif // USERLAND_FS_FILE_SYSTEM_H

View File

@ -68,7 +68,7 @@ FileSystemInitializer::FirstTimeInit()
if (!fFileSystem)
return B_NO_MEMORY;
error = fFileSystem->Init(fName, infos, count);
error = fFileSystem->Init(fName, infos, count, reply->capabilities);
if (error != B_OK)
return B_ERROR;

View File

@ -280,6 +280,10 @@ Volume::Unmount()
status_t
Volume::Sync()
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_SYNC))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -337,6 +341,10 @@ Volume::ReadFSInfo(fs_info* info)
status_t
Volume::WriteFSInfo(const struct fs_info *info, uint32 mask)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE_FS_INFO))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -574,6 +582,10 @@ Volume::IOCtl(fs_vnode node, fs_cookie cookie, uint32 command, void *buffer,
}
}
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_IOCTL))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -630,6 +642,10 @@ Volume::IOCtl(fs_vnode node, fs_cookie cookie, uint32 command, void *buffer,
status_t
Volume::SetFlags(fs_vnode node, fs_cookie cookie, int flags)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_SET_FLAGS))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -667,6 +683,12 @@ status_t
Volume::Select(fs_vnode node, fs_cookie cookie, uint8 event, uint32 ref,
selectsync* sync)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_SELECT)) {
notify_select_event(sync, ref, event);
return B_OK;
}
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -714,6 +736,10 @@ Volume::Select(fs_vnode node, fs_cookie cookie, uint8 event, uint32 ref,
status_t
Volume::Deselect(fs_vnode node, fs_cookie cookie, uint8 event, selectsync* sync)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_DESELECT))
return B_OK;
struct SyncRemover {
SyncRemover(FileSystem* fs, selectsync* sync)
: fs(fs), sync(sync) {}
@ -760,6 +786,10 @@ Volume::Deselect(fs_vnode node, fs_cookie cookie, uint8 event, selectsync* sync)
status_t
Volume::FSync(fs_vnode node)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FSYNC))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -796,6 +826,11 @@ Volume::ReadSymlink(fs_vnode node, char* buffer, size_t bufferSize,
size_t* bytesRead)
{
*bytesRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_SYMLINK))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -841,6 +876,10 @@ status_t
Volume::CreateSymlink(fs_vnode dir, const char* name, const char* target,
int mode)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE_SYMLINK))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -881,6 +920,10 @@ Volume::CreateSymlink(fs_vnode dir, const char* name, const char* target,
status_t
Volume::Link(fs_vnode dir, const char* name, fs_vnode node)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_LINK))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -919,6 +962,10 @@ Volume::Link(fs_vnode dir, const char* name, fs_vnode node)
status_t
Volume::Unlink(fs_vnode dir, const char* name)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_UNLINK))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -957,6 +1004,10 @@ status_t
Volume::Rename(fs_vnode oldDir, const char* oldName, fs_vnode newDir,
const char* newName)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_RENAME))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -997,6 +1048,10 @@ Volume::Rename(fs_vnode oldDir, const char* oldName, fs_vnode newDir,
status_t
Volume::Access(fs_vnode node, int mode)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_ACCESS))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1062,6 +1117,10 @@ Volume::ReadStat(fs_vnode node, struct stat* st)
status_t
Volume::WriteStat(fs_vnode node, const struct stat* st, uint32 mask)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE_STAT))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1102,6 +1161,10 @@ status_t
Volume::Create(fs_vnode dir, const char* name, int openMode, int mode,
void** cookie, vnode_id* vnid)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1148,6 +1211,10 @@ Volume::Create(fs_vnode dir, const char* name, int openMode, int mode,
status_t
Volume::Open(fs_vnode node, int openMode, fs_cookie* cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1223,6 +1290,10 @@ Volume::Read(fs_vnode node, fs_cookie cookie, off_t pos, void* buffer,
{
*bytesRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1272,6 +1343,10 @@ Volume::Write(fs_vnode node, fs_cookie cookie, off_t pos, const void* buffer,
{
*bytesWritten = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1315,6 +1390,10 @@ Volume::Write(fs_vnode node, fs_cookie cookie, off_t pos, const void* buffer,
status_t
Volume::CreateDir(fs_vnode dir, const char* name, int mode, vnode_id *newDir)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE_DIR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1354,6 +1433,10 @@ Volume::CreateDir(fs_vnode dir, const char* name, int mode, vnode_id *newDir)
status_t
Volume::RemoveDir(fs_vnode dir, const char* name)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_REMOVE_DIR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1391,6 +1474,10 @@ Volume::RemoveDir(fs_vnode dir, const char* name)
status_t
Volume::OpenDir(fs_vnode node, fs_cookie* cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_DIR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1466,6 +1553,10 @@ Volume::ReadDir(fs_vnode node, fs_vnode cookie, void* buffer, size_t bufferSize,
{
*countRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_DIR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1521,6 +1612,10 @@ reply->buffer.GetSize()));
status_t
Volume::RewindDir(fs_vnode node, fs_vnode cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_REWIND_DIR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1560,6 +1655,10 @@ Volume::RewindDir(fs_vnode node, fs_vnode cookie)
status_t
Volume::OpenAttrDir(fs_vnode node, fs_cookie *cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_ATTR_DIR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1635,6 +1734,10 @@ status_t
Volume::ReadAttrDir(fs_vnode node, fs_cookie cookie, void* buffer,
size_t bufferSize, uint32 count, uint32* countRead)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_ATTR_DIR))
return B_BAD_VALUE;
*countRead = 0;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
@ -1689,6 +1792,10 @@ Volume::ReadAttrDir(fs_vnode node, fs_cookie cookie, void* buffer,
status_t
Volume::RewindAttrDir(fs_vnode node, fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_REWIND_ATTR_DIR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1728,6 +1835,10 @@ status_t
Volume::CreateAttr(fs_vnode node, const char* name, uint32 type, int openMode,
fs_cookie* cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE_ATTR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1771,6 +1882,10 @@ status_t
Volume::OpenAttr(fs_vnode node, const char* name, int openMode,
fs_cookie* cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_ATTR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1851,6 +1966,10 @@ Volume::ReadAttr(fs_vnode node, fs_cookie cookie, off_t pos,
{
*bytesRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_ATTR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1900,6 +2019,10 @@ Volume::WriteAttr(fs_vnode node, fs_cookie cookie, off_t pos,
{
*bytesWritten = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE_ATTR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1940,6 +2063,10 @@ Volume::WriteAttr(fs_vnode node, fs_cookie cookie, off_t pos,
status_t
Volume::ReadAttrStat(fs_vnode node, fs_cookie cookie, struct stat *st)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_ATTR_STAT))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -1977,6 +2104,10 @@ status_t
Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode,
const char* newName)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_RENAME_ATTR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2017,6 +2148,10 @@ Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode,
status_t
Volume::RemoveAttr(fs_vnode node, const char* name)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_REMOVE_ATTR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2058,6 +2193,10 @@ Volume::RemoveAttr(fs_vnode node, const char* name)
status_t
Volume::OpenIndexDir(fs_cookie *cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_INDEX_DIR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2134,6 +2273,10 @@ Volume::ReadIndexDir(fs_cookie cookie, void* buffer, size_t bufferSize,
{
*countRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_INDEX_DIR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2186,6 +2329,10 @@ Volume::ReadIndexDir(fs_cookie cookie, void* buffer, size_t bufferSize,
status_t
Volume::RewindIndexDir(fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_REWIND_INDEX_DIR))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2220,6 +2367,10 @@ Volume::RewindIndexDir(fs_cookie cookie)
status_t
Volume::CreateIndex(const char* name, uint32 type, uint32 flags)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE_INDEX))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2258,6 +2409,10 @@ Volume::CreateIndex(const char* name, uint32 type, uint32 flags)
status_t
Volume::RemoveIndex(const char* name)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_REMOVE_INDEX))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2294,6 +2449,10 @@ Volume::RemoveIndex(const char* name)
status_t
Volume::ReadIndexStat(const char* name, struct stat *st)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_INDEX_STAT))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2336,6 +2495,10 @@ status_t
Volume::OpenQuery(const char* queryString, uint32 flags, port_id targetPort,
uint32 token, fs_cookie *cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_QUERY))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2417,6 +2580,10 @@ Volume::ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize,
{
*countRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_QUERY))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2560,6 +2727,10 @@ Volume::_Unmount()
status_t
Volume::_ReadFSInfo(fs_info* info)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_FS_INFO))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2669,6 +2840,10 @@ Volume::_WriteVNode(fs_vnode node, bool reenter)
status_t
Volume::_ReadStat(fs_vnode node, struct stat* st)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_STAT))
return B_BAD_VALUE;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2704,6 +2879,10 @@ Volume::_ReadStat(fs_vnode node, struct stat* st)
status_t
Volume::_Close(fs_vnode node, fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2739,6 +2918,10 @@ Volume::_Close(fs_vnode node, fs_cookie cookie)
status_t
Volume::_FreeCookie(fs_vnode node, fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_COOKIE))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2774,6 +2957,10 @@ Volume::_FreeCookie(fs_vnode node, fs_cookie cookie)
status_t
Volume::_CloseDir(fs_vnode node, fs_vnode cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_DIR))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2809,6 +2996,10 @@ Volume::_CloseDir(fs_vnode node, fs_vnode cookie)
status_t
Volume::_FreeDirCookie(fs_vnode node, fs_vnode cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_DIR_COOKIE))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2844,6 +3035,10 @@ Volume::_FreeDirCookie(fs_vnode node, fs_vnode cookie)
status_t
Volume::_CloseAttrDir(fs_vnode node, fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_ATTR_DIR))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2879,6 +3074,10 @@ Volume::_CloseAttrDir(fs_vnode node, fs_cookie cookie)
status_t
Volume::_FreeAttrDirCookie(fs_vnode node, fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_ATTR_DIR_COOKIE))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2914,6 +3113,10 @@ Volume::_FreeAttrDirCookie(fs_vnode node, fs_cookie cookie)
status_t
Volume::_CloseAttr(fs_vnode node, fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_ATTR))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2949,6 +3152,10 @@ Volume::_CloseAttr(fs_vnode node, fs_cookie cookie)
status_t
Volume::_FreeAttrCookie(fs_vnode node, fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_ATTR_COOKIE))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -2984,6 +3191,10 @@ Volume::_FreeAttrCookie(fs_vnode node, fs_cookie cookie)
status_t
Volume::_CloseIndexDir(fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_INDEX_DIR))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -3018,6 +3229,10 @@ Volume::_CloseIndexDir(fs_cookie cookie)
status_t
Volume::_FreeIndexDirCookie(fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_INDEX_DIR_COOKIE))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -3052,6 +3267,10 @@ Volume::_FreeIndexDirCookie(fs_cookie cookie)
status_t
Volume::_CloseQuery(fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_QUERY))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)
@ -3086,6 +3305,10 @@ Volume::_CloseQuery(fs_cookie cookie)
status_t
Volume::_FreeQueryCookie(fs_cookie cookie)
{
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_QUERY_COOKIE))
return B_OK;
// get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port)

View File

@ -4,6 +4,7 @@
#include <new>
#include "beos_fs_interface.h"
#include "BeOSKernelVolume.h"
using std::nothrow;
@ -13,6 +14,7 @@ BeOSKernelFileSystem::BeOSKernelFileSystem(beos_vnode_ops* fsOps)
: FileSystem(),
fFSOps(fsOps)
{
_InitCapabilities(fsOps);
}
// destructor
@ -45,3 +47,114 @@ BeOSKernelFileSystem::DeleteVolume(Volume* volume)
return B_OK;
}
// _InitCapabilities
void
BeOSKernelFileSystem::_InitCapabilities(beos_vnode_ops* fsOps)
{
fCapabilities.ClearAll();
// FS interface type
fCapabilities.clientFSType = CLIENT_FS_BEOS_KERNEL;
// FS operations
fCapabilities.Set(FS_CAPABILITY_MOUNT, fsOps->mount);
fCapabilities.Set(FS_CAPABILITY_UNMOUNT, fsOps->unmount);
fCapabilities.Set(FS_CAPABILITY_READ_FS_INFO, fsOps->rfsstat);
fCapabilities.Set(FS_CAPABILITY_WRITE_FS_INFO, fsOps->wfsstat);
fCapabilities.Set(FS_CAPABILITY_SYNC, fsOps->sync);
// vnode operations
fCapabilities.Set(FS_CAPABILITY_LOOKUP, fsOps->walk);
// missing: FS_CAPABILITY_GET_VNODE_NAME,
fCapabilities.Set(FS_CAPABILITY_GET_VNODE, fsOps->read_vnode);
fCapabilities.Set(FS_CAPABILITY_PUT_VNODE, fsOps->write_vnode);
fCapabilities.Set(FS_CAPABILITY_REMOVE_VNODE, fsOps->remove_vnode);
// VM file access
// missing: FS_CAPABILITY_CAN_PAGE,
// missing: FS_CAPABILITY_READ_PAGES,
// missing: FS_CAPABILITY_WRITE_PAGES,
// cache file access
// missing: FS_CAPABILITY_GET_FILE_MAP,
// common operations
fCapabilities.Set(FS_CAPABILITY_IOCTL, fsOps->ioctl);
fCapabilities.Set(FS_CAPABILITY_SET_FLAGS, fsOps->setflags);
fCapabilities.Set(FS_CAPABILITY_SELECT, fsOps->select);
fCapabilities.Set(FS_CAPABILITY_DESELECT, fsOps->deselect);
fCapabilities.Set(FS_CAPABILITY_FSYNC, fsOps->fsync);
fCapabilities.Set(FS_CAPABILITY_READ_SYMLINK, fsOps->readlink);
fCapabilities.Set(FS_CAPABILITY_CREATE_SYMLINK, fsOps->symlink);
fCapabilities.Set(FS_CAPABILITY_LINK, fsOps->link);
fCapabilities.Set(FS_CAPABILITY_UNLINK, fsOps->unlink);
fCapabilities.Set(FS_CAPABILITY_RENAME, fsOps->rename);
fCapabilities.Set(FS_CAPABILITY_ACCESS, fsOps->access);
fCapabilities.Set(FS_CAPABILITY_READ_STAT, fsOps->rstat);
fCapabilities.Set(FS_CAPABILITY_WRITE_STAT, fsOps->wstat);
// file operations
fCapabilities.Set(FS_CAPABILITY_CREATE, fsOps->create);
fCapabilities.Set(FS_CAPABILITY_OPEN, fsOps->open);
fCapabilities.Set(FS_CAPABILITY_CLOSE, fsOps->close);
fCapabilities.Set(FS_CAPABILITY_FREE_COOKIE, fsOps->free_cookie);
fCapabilities.Set(FS_CAPABILITY_READ, fsOps->read);
fCapabilities.Set(FS_CAPABILITY_WRITE, fsOps->write);
// directory operations
fCapabilities.Set(FS_CAPABILITY_CREATE_DIR, fsOps->mkdir);
fCapabilities.Set(FS_CAPABILITY_REMOVE_DIR, fsOps->rmdir);
fCapabilities.Set(FS_CAPABILITY_OPEN_DIR, fsOps->opendir);
fCapabilities.Set(FS_CAPABILITY_CLOSE_DIR, fsOps->closedir);
fCapabilities.Set(FS_CAPABILITY_FREE_DIR_COOKIE, fsOps->free_dircookie);
fCapabilities.Set(FS_CAPABILITY_READ_DIR, fsOps->readdir);
fCapabilities.Set(FS_CAPABILITY_REWIND_DIR, fsOps->rewinddir);
// attribute directory operations
fCapabilities.Set(FS_CAPABILITY_OPEN_ATTR_DIR, fsOps->open_attrdir);
fCapabilities.Set(FS_CAPABILITY_CLOSE_ATTR_DIR, fsOps->close_attrdir);
fCapabilities.Set(FS_CAPABILITY_FREE_ATTR_DIR_COOKIE,
fsOps->free_attrdircookie);
fCapabilities.Set(FS_CAPABILITY_READ_ATTR_DIR, fsOps->read_attrdir);
fCapabilities.Set(FS_CAPABILITY_REWIND_ATTR_DIR, fsOps->rewind_attrdir);
// attribute operations
// we emulate open_attr() and free_attr_dir_cookie() if either read_attr()
// or write_attr() is present
bool hasAttributes = (fsOps->read_attr || fsOps->write_attr);
fCapabilities.Set(FS_CAPABILITY_CREATE_ATTR, hasAttributes);
fCapabilities.Set(FS_CAPABILITY_OPEN_ATTR, hasAttributes);
fCapabilities.Set(FS_CAPABILITY_CLOSE_ATTR, false);
fCapabilities.Set(FS_CAPABILITY_FREE_ATTR_COOKIE, hasAttributes);
fCapabilities.Set(FS_CAPABILITY_READ_ATTR, fsOps->read_attr);
fCapabilities.Set(FS_CAPABILITY_WRITE_ATTR, fsOps->write_attr);
fCapabilities.Set(FS_CAPABILITY_READ_ATTR_STAT, fsOps->stat_attr);
// missing: FS_CAPABILITY_WRITE_ATTR_STAT
fCapabilities.Set(FS_CAPABILITY_RENAME_ATTR, fsOps->rename_attr);
fCapabilities.Set(FS_CAPABILITY_REMOVE_ATTR, fsOps->remove_attr);
// index directory & index operations
fCapabilities.Set(FS_CAPABILITY_OPEN_INDEX_DIR, fsOps->open_indexdir);
fCapabilities.Set(FS_CAPABILITY_CLOSE_INDEX_DIR, fsOps->close_indexdir);
fCapabilities.Set(FS_CAPABILITY_FREE_INDEX_DIR_COOKIE,
fsOps->free_indexdircookie);
fCapabilities.Set(FS_CAPABILITY_READ_INDEX_DIR, fsOps->read_indexdir);
fCapabilities.Set(FS_CAPABILITY_REWIND_INDEX_DIR, fsOps->rewind_indexdir);
fCapabilities.Set(FS_CAPABILITY_CREATE_INDEX, fsOps->create_index);
fCapabilities.Set(FS_CAPABILITY_REMOVE_INDEX, fsOps->remove_index);
fCapabilities.Set(FS_CAPABILITY_READ_INDEX_STAT, fsOps->stat_index);
// query operations
fCapabilities.Set(FS_CAPABILITY_OPEN_QUERY, fsOps->open_query);
fCapabilities.Set(FS_CAPABILITY_CLOSE_QUERY, fsOps->close_query);
fCapabilities.Set(FS_CAPABILITY_FREE_QUERY_COOKIE, fsOps->free_querycookie);
fCapabilities.Set(FS_CAPABILITY_READ_QUERY, fsOps->read_query);
// missing: FS_CAPABILITY_REWIND_QUERY,
}

View File

@ -17,6 +17,9 @@ public:
virtual status_t CreateVolume(Volume** volume, mount_id id);
virtual status_t DeleteVolume(Volume* volume);
private:
void _InitCapabilities(beos_vnode_ops* fsOps);
private:
beos_vnode_ops* fFSOps;
};

View File

@ -294,7 +294,7 @@ status_t
BeOSKernelVolume::Access(fs_vnode node, int mode)
{
if (!fFSOps->access)
return B_BAD_VALUE;
return B_OK;
return fFSOps->access(fVolumeCookie, node, mode);
}

View File

@ -9,6 +9,7 @@
#include <Message.h>
#include "FSCapabilities.h"
#include "Port.h"
#include "String.h"
@ -25,12 +26,13 @@ public:
{
}
FSInfo(const char* fsName, const Port::Info* infos, int32 count)
FSInfo(const char* fsName, const Port::Info* infos, int32 count,
const FSCapabilities& capabilities)
: fName(),
fInfos(NULL),
fCount(0)
{
SetTo(fsName, infos, count);
SetTo(fsName, infos, count, capabilities);
}
FSInfo(const BMessage* message)
@ -46,7 +48,7 @@ public:
fInfos(NULL),
fCount(0)
{
SetTo(other.GetName(), other.fInfos, other.fCount);
SetTo(other.GetName(), other.fInfos, other.fCount, other.fCapabilities);
}
~FSInfo()
@ -54,17 +56,24 @@ public:
Unset();
}
status_t SetTo(const char* fsName, const Port::Info* infos, int32 count)
status_t SetTo(const char* fsName, const Port::Info* infos, int32 count,
const FSCapabilities& capabilities)
{
Unset();
if (!fsName || !infos || count <= 0)
return B_BAD_VALUE;
if (!fName.SetTo(fsName))
return B_NO_MEMORY;
fInfos = new(nothrow) Port::Info[count];
if (!fInfos)
return B_NO_MEMORY;
memcpy(fInfos, infos, sizeof(Port::Info) * count);
fCapabilities = capabilities;
fCount = count;
return B_OK;
}
@ -72,17 +81,25 @@ public:
status_t SetTo(const BMessage* message)
{
Unset();
if (!message)
return B_BAD_VALUE;
const void* infos;
ssize_t size;
const char* fsName;
const void* capabilities;
ssize_t capabilitiesSize;
if (message->FindData("infos", B_RAW_TYPE, &infos, &size) != B_OK
|| size < 0 || message->FindString("fsName", &fsName) != B_OK) {
|| size < 0 || message->FindString("fsName", &fsName) != B_OK
|| message->FindData("capabilities", B_RAW_TYPE, &capabilities,
&capabilitiesSize) != B_OK
|| capabilitiesSize != sizeof(FSCapabilities)) {
return B_BAD_VALUE;
}
return SetTo(fsName, (const Port::Info*)infos,
size / sizeof(Port::Info));
size / sizeof(Port::Info), *(const FSCapabilities*)capabilities);
}
void Unset()
@ -108,26 +125,39 @@ public:
return fCount;
}
int32 GetSize() const
int32 GetInfosSize() const
{
return fCount * sizeof(Port::Info);
}
const FSCapabilities& GetCapabilities() const
{
return fCapabilities;
}
status_t Archive(BMessage* archive)
{
if (!fName.GetString() || !fInfos)
return B_NO_INIT;
status_t error = archive->AddString("fsName", fName.GetString());
if (error != B_OK)
return error;
return archive->AddData("infos", B_RAW_TYPE, fInfos,
error = archive->AddData("infos", B_RAW_TYPE, fInfos,
fCount * sizeof(Port::Info));
if (error != B_OK)
return error;
return archive->AddData("capabilities", B_RAW_TYPE, &fCapabilities,
sizeof(FSCapabilities));
}
private:
String fName;
Port::Info* fInfos;
int32 fCount;
FSCapabilities fCapabilities;
};
} // namespace UserlandFS

View File

@ -6,6 +6,8 @@
#include <fs_interface.h>
#include <SupportDefs.h>
#include "FSCapabilities.h"
namespace UserlandFS {
class Volume;
@ -17,6 +19,13 @@ public:
virtual status_t CreateVolume(Volume** volume, mount_id id) = 0;
virtual status_t DeleteVolume(Volume* volume) = 0;
void GetCapabilities(
FSCapabilities& capabilities) const
{ capabilities = fCapabilities; }
protected:
FSCapabilities fCapabilities;
};
} // namespace UserlandFS

View File

@ -319,6 +319,7 @@ UserlandFSDispatcher::_ProcessRequests()
if (error != B_OK)
RETURN_ERROR(error);
RequestReleaser _(fRequestPort, request);
// check the request type
if (request->GetType() == UFS_DISCONNECT_REQUEST)
return B_OK;
@ -326,6 +327,7 @@ UserlandFSDispatcher::_ProcessRequests()
RETURN_ERROR(B_BAD_VALUE);
PRINT(("UserlandFSDispatcher::_ProcessRequests(): received FS connect "
"request\n"));
// it's an FS connect request
FSConnectRequest* connectRequest = (FSConnectRequest*)request;
// get the FS name
@ -338,24 +340,27 @@ UserlandFSDispatcher::_ProcessRequests()
fsName.SetTo((const char*)connectRequest->fsName.GetData(), len);
if (result == B_OK && fsName.GetLength() == 0)
result = B_BAD_DATA;
// prepare the reply
RequestAllocator allocator(fRequestPort->GetPort());
FSConnectReply* reply;
error = AllocateRequest(allocator, &reply);
if (error != B_OK)
RETURN_ERROR(error);
FileSystem* fileSystem = NULL;
if (result == B_OK)
result = _GetFileSystem(fsName.GetString(), &fileSystem);
if (result == B_OK) {
const FSInfo* info = fileSystem->GetInfo();
result = allocator.AllocateData(reply->portInfos,
info->GetInfos(), info->GetSize(), sizeof(Port::Info));
if (result == B_OK)
reply->portInfoCount = info->CountInfos();
info->GetInfos(), info->GetInfosSize(), sizeof(Port::Info));
reply->portInfoCount = info->CountInfos();
reply->capabilities = info->GetCapabilities();
_PutFileSystem(fileSystem);
}
reply->error = result;
// send it
error = fRequestPort->SendRequest(&allocator);
if (error != B_OK)

View File

@ -183,20 +183,29 @@ UserlandFSServer::_RegisterWithDispatcher(const char* fsName)
ERROR(("Failed to lock the clipboard.\n"));
return B_ERROR;
}
// get the port infos
Port::Info infos[kRequestThreadCount + 1];
infos[0] = *fNotificationRequestPort->GetPortInfo();
for (int32 i = 0; i < kRequestThreadCount; i++)
infos[i + 1] = *fRequestThreads[i].GetPortInfo();
// FS capabilities
FSCapabilities capabilities;
fFileSystem->GetCapabilities(capabilities);
// init an FS info
FSInfo info;
status_t error = info.SetTo(fsName, infos, kRequestThreadCount + 1);
status_t error = info.SetTo(fsName, infos, kRequestThreadCount + 1,
capabilities);
// prepare the message
BMessage message(UFS_REGISTER_FS);
if (error == B_OK)
error = message.AddInt32("team", Team());
if (error == B_OK)
error = info.Archive(&message);
// send the message
BMessage reply;
error = messenger.SendMessage(&message, &reply);