Implemented the new attribute open/close/... FS hooks. The mapping to the
old interface is completely done in userland ATM. It becomes more and more obvious that we probably need to provide the kernel add-on with a bit more information about what the client FS interface supports in the first place, so we can save unnecessary trips to the userland. Opening/closing attributes for a FS using the old style interface could be handled completely in the kernel add-on, for instance (even if we lose a bit of accuracy wrt to open modes etc.). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20258 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -122,6 +122,14 @@ enum {
|
||||
REWIND_ATTR_DIR_REPLY,
|
||||
|
||||
// attributes
|
||||
CREATE_ATTR_REQUEST,
|
||||
CREATE_ATTR_REPLY,
|
||||
OPEN_ATTR_REQUEST,
|
||||
OPEN_ATTR_REPLY,
|
||||
CLOSE_ATTR_REQUEST,
|
||||
CLOSE_ATTR_REPLY,
|
||||
FREE_ATTR_COOKIE_REQUEST,
|
||||
FREE_ATTR_COOKIE_REPLY,
|
||||
READ_ATTR_REQUEST,
|
||||
READ_ATTR_REPLY,
|
||||
WRITE_ATTR_REQUEST,
|
||||
@@ -960,6 +968,67 @@ public:
|
||||
// #pragma mark - attributes
|
||||
|
||||
|
||||
// CreateAttrRequest
|
||||
class CreateAttrRequest : public NodeRequest {
|
||||
public:
|
||||
CreateAttrRequest() : NodeRequest(CREATE_ATTR_REQUEST) {}
|
||||
status_t GetAddressInfos(AddressInfo* infos, int32* count);
|
||||
|
||||
Address name;
|
||||
uint32 type;
|
||||
int openMode;
|
||||
};
|
||||
|
||||
// CreateAttrReply
|
||||
class CreateAttrReply : public ReplyRequest {
|
||||
public:
|
||||
CreateAttrReply() : ReplyRequest(CREATE_ATTR_REPLY) {}
|
||||
|
||||
fs_cookie attrCookie;
|
||||
};
|
||||
|
||||
// OpenAttrRequest
|
||||
class OpenAttrRequest : public NodeRequest {
|
||||
public:
|
||||
OpenAttrRequest() : NodeRequest(OPEN_ATTR_REQUEST) {}
|
||||
status_t GetAddressInfos(AddressInfo* infos, int32* count);
|
||||
|
||||
Address name;
|
||||
int openMode;
|
||||
};
|
||||
|
||||
// OpenAttrReply
|
||||
class OpenAttrReply : public ReplyRequest {
|
||||
public:
|
||||
OpenAttrReply() : ReplyRequest(OPEN_ATTR_REPLY) {}
|
||||
|
||||
fs_cookie attrCookie;
|
||||
};
|
||||
|
||||
// CloseAttrRequest
|
||||
class CloseAttrRequest : public AttributeRequest {
|
||||
public:
|
||||
CloseAttrRequest() : AttributeRequest(CLOSE_ATTR_REQUEST) {}
|
||||
};
|
||||
|
||||
// CloseAttrReply
|
||||
class CloseAttrReply : public ReplyRequest {
|
||||
public:
|
||||
CloseAttrReply() : ReplyRequest(CLOSE_ATTR_REPLY) {}
|
||||
};
|
||||
|
||||
// FreeAttrCookieRequest
|
||||
class FreeAttrCookieRequest : public AttributeRequest {
|
||||
public:
|
||||
FreeAttrCookieRequest() : AttributeRequest(FREE_ATTR_COOKIE_REQUEST) {}
|
||||
};
|
||||
|
||||
// FreeAttrCookieReply
|
||||
class FreeAttrCookieReply : public ReplyRequest {
|
||||
public:
|
||||
FreeAttrCookieReply() : ReplyRequest(FREE_ATTR_COOKIE_REPLY) {}
|
||||
};
|
||||
|
||||
// ReadAttrRequest
|
||||
class ReadAttrRequest : public AttributeRequest {
|
||||
public:
|
||||
@@ -1605,6 +1674,22 @@ do_for_request(Request* request, Task& task)
|
||||
case REWIND_ATTR_DIR_REPLY:
|
||||
return task((RewindAttrDirReply*)request);
|
||||
// attributes
|
||||
case CREATE_ATTR_REQUEST:
|
||||
return task((CreateAttrRequest*)request);
|
||||
case CREATE_ATTR_REPLY:
|
||||
return task((CreateAttrReply*)request);
|
||||
case OPEN_ATTR_REQUEST:
|
||||
return task((OpenAttrRequest*)request);
|
||||
case OPEN_ATTR_REPLY:
|
||||
return task((OpenAttrReply*)request);
|
||||
case CLOSE_ATTR_REQUEST:
|
||||
return task((CloseAttrRequest*)request);
|
||||
case CLOSE_ATTR_REPLY:
|
||||
return task((CloseAttrReply*)request);
|
||||
case FREE_ATTR_COOKIE_REQUEST:
|
||||
return task((FreeAttrCookieRequest*)request);
|
||||
case FREE_ATTR_COOKIE_REPLY:
|
||||
return task((FreeAttrCookieReply*)request);
|
||||
case READ_ATTR_REQUEST:
|
||||
return task((ReadAttrRequest*)request);
|
||||
case READ_ATTR_REPLY:
|
||||
@@ -1834,6 +1919,14 @@ using UserlandFSUtil::ReadAttrDirReply;
|
||||
using UserlandFSUtil::RewindAttrDirRequest;
|
||||
using UserlandFSUtil::RewindAttrDirReply;
|
||||
// attributes
|
||||
using UserlandFSUtil::CreateAttrRequest;
|
||||
using UserlandFSUtil::CreateAttrReply;
|
||||
using UserlandFSUtil::OpenAttrRequest;
|
||||
using UserlandFSUtil::OpenAttrReply;
|
||||
using UserlandFSUtil::CloseAttrRequest;
|
||||
using UserlandFSUtil::CloseAttrReply;
|
||||
using UserlandFSUtil::FreeAttrCookieRequest;
|
||||
using UserlandFSUtil::FreeAttrCookieReply;
|
||||
using UserlandFSUtil::ReadAttrRequest;
|
||||
using UserlandFSUtil::ReadAttrReply;
|
||||
using UserlandFSUtil::WriteAttrRequest;
|
||||
|
||||
@@ -32,6 +32,7 @@ enum {
|
||||
USERLAND_IOCTL_OPEN_FILES,
|
||||
USERLAND_IOCTL_OPEN_DIRECTORIES,
|
||||
USERLAND_IOCTL_OPEN_ATTRIBUTE_DIRECTORIES,
|
||||
USERLAND_IOCTL_OPEN_ATTRIBUTES,
|
||||
USERLAND_IOCTL_OPEN_INDEX_DIRECTORIES,
|
||||
USERLAND_IOCTL_OPEN_QUERIES,
|
||||
};
|
||||
|
||||
@@ -74,6 +74,7 @@ Volume::Volume(FileSystem* fileSystem, mount_id id)
|
||||
fOpenFiles(0),
|
||||
fOpenDirectories(0),
|
||||
fOpenAttributeDirectories(0),
|
||||
fOpenAttributes(0),
|
||||
fOpenIndexDirectories(0),
|
||||
fOpenQueries(0),
|
||||
fVNodeCountMap(NULL),
|
||||
@@ -1097,6 +1098,7 @@ Volume::Create(fs_vnode dir, const char* name, int openMode, int mode,
|
||||
if (!port)
|
||||
return B_ERROR;
|
||||
PortReleaser _(fFileSystem->GetPortPool(), port);
|
||||
AutoIncrementer incrementer(&fOpenFiles);
|
||||
|
||||
// prepare the request
|
||||
RequestAllocator allocator(port->GetPort());
|
||||
@@ -1124,6 +1126,7 @@ Volume::Create(fs_vnode dir, const char* name, int openMode, int mode,
|
||||
// process the reply
|
||||
if (reply->error != B_OK)
|
||||
return reply->error;
|
||||
incrementer.Keep();
|
||||
*vnid = reply->vnid;
|
||||
*cookie = reply->fileCookie;
|
||||
// The VFS will balance the new_vnode() call for the FS.
|
||||
@@ -1197,6 +1200,7 @@ Volume::FreeCookie(fs_vnode node, fs_cookie cookie)
|
||||
error = B_OK;
|
||||
disconnected = true;
|
||||
}
|
||||
|
||||
int32 openFiles = atomic_add(&fOpenFiles, -1);
|
||||
if (openFiles <= 1 && disconnected)
|
||||
_PutAllPendingVNodes();
|
||||
@@ -1710,6 +1714,126 @@ Volume::RewindAttrDir(fs_vnode node, fs_cookie cookie)
|
||||
|
||||
// #pragma mark - attributes
|
||||
|
||||
// CreateAttr
|
||||
status_t
|
||||
Volume::CreateAttr(fs_vnode node, const char* name, uint32 type, int openMode,
|
||||
fs_cookie* cookie)
|
||||
{
|
||||
// get a free port
|
||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||
if (!port)
|
||||
return B_ERROR;
|
||||
PortReleaser _(fFileSystem->GetPortPool(), port);
|
||||
AutoIncrementer incrementer(&fOpenAttributes);
|
||||
|
||||
// prepare the request
|
||||
RequestAllocator allocator(port->GetPort());
|
||||
CreateAttrRequest* request;
|
||||
status_t error = AllocateRequest(allocator, &request);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
request->volume = fUserlandVolume;
|
||||
request->node = node;
|
||||
error = allocator.AllocateString(request->name, name);
|
||||
request->type = type;
|
||||
request->openMode = openMode;
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// send the request
|
||||
KernelRequestHandler handler(this, CREATE_ATTR_REPLY);
|
||||
CreateAttrReply* reply;
|
||||
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
RequestReleaser requestReleaser(port, reply);
|
||||
|
||||
// process the reply
|
||||
if (reply->error != B_OK)
|
||||
return reply->error;
|
||||
incrementer.Keep();
|
||||
*cookie = reply->attrCookie;
|
||||
return error;
|
||||
}
|
||||
|
||||
// OpenAttr
|
||||
status_t
|
||||
Volume::OpenAttr(fs_vnode node, const char* name, int openMode,
|
||||
fs_cookie* cookie)
|
||||
{
|
||||
// get a free port
|
||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||
if (!port)
|
||||
return B_ERROR;
|
||||
PortReleaser _(fFileSystem->GetPortPool(), port);
|
||||
AutoIncrementer incrementer(&fOpenAttributes);
|
||||
|
||||
// prepare the request
|
||||
RequestAllocator allocator(port->GetPort());
|
||||
OpenAttrRequest* request;
|
||||
status_t error = AllocateRequest(allocator, &request);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
request->volume = fUserlandVolume;
|
||||
request->node = node;
|
||||
error = allocator.AllocateString(request->name, name);
|
||||
request->openMode = openMode;
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// send the request
|
||||
KernelRequestHandler handler(this, OPEN_ATTR_REPLY);
|
||||
OpenAttrReply* reply;
|
||||
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
RequestReleaser requestReleaser(port, reply);
|
||||
|
||||
// process the reply
|
||||
if (reply->error != B_OK)
|
||||
return reply->error;
|
||||
incrementer.Keep();
|
||||
*cookie = reply->attrCookie;
|
||||
return error;
|
||||
}
|
||||
|
||||
// CloseAttr
|
||||
status_t
|
||||
Volume::CloseAttr(fs_vnode node, fs_cookie cookie)
|
||||
{
|
||||
status_t error = _CloseAttr(node, cookie);
|
||||
if (error != B_OK && fFileSystem->GetPortPool()->IsDisconnected()) {
|
||||
// This isn't really necessary, as the return value is irrelevant to
|
||||
// the VFS. OBOS ignores it completely. The fsshell returns it to the
|
||||
// userland, but considers the node closed anyway.
|
||||
WARN(("Volume::CloseAttr(): connection lost, forcing close attr\n"));
|
||||
return B_OK;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// FreeAttrCookie
|
||||
status_t
|
||||
Volume::FreeAttrCookie(fs_vnode node, fs_cookie cookie)
|
||||
{
|
||||
status_t error = _FreeAttrCookie(node, cookie);
|
||||
bool disconnected = false;
|
||||
if (error != B_OK && fFileSystem->GetPortPool()->IsDisconnected()) {
|
||||
// This isn't really necessary, as the return value is irrelevant to
|
||||
// the VFS. It's completely ignored by OBOS as well as by the fsshell.
|
||||
WARN(("Volume::FreeAttrCookie(): connection lost, forcing free attr "
|
||||
"cookie\n"));
|
||||
error = B_OK;
|
||||
disconnected = true;
|
||||
}
|
||||
|
||||
int32 openAttributes = atomic_add(&fOpenAttributes, -1);
|
||||
if (openAttributes <= 1 && disconnected)
|
||||
_PutAllPendingVNodes();
|
||||
return error;
|
||||
}
|
||||
|
||||
// ReadAttr
|
||||
status_t
|
||||
@@ -2708,6 +2832,76 @@ Volume::_FreeAttrDirCookie(fs_vnode node, fs_cookie cookie)
|
||||
return error;
|
||||
}
|
||||
|
||||
// _CloseAttr
|
||||
status_t
|
||||
Volume::_CloseAttr(fs_vnode node, fs_cookie cookie)
|
||||
{
|
||||
// get a free port
|
||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||
if (!port)
|
||||
return B_ERROR;
|
||||
PortReleaser _(fFileSystem->GetPortPool(), port);
|
||||
|
||||
// prepare the request
|
||||
RequestAllocator allocator(port->GetPort());
|
||||
CloseAttrRequest* request;
|
||||
status_t error = AllocateRequest(allocator, &request);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
request->volume = fUserlandVolume;
|
||||
request->node = node;
|
||||
request->attrCookie = cookie;
|
||||
|
||||
// send the request
|
||||
KernelRequestHandler handler(this, CLOSE_ATTR_REPLY);
|
||||
CloseAttrReply* reply;
|
||||
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
RequestReleaser requestReleaser(port, reply);
|
||||
|
||||
// process the reply
|
||||
if (reply->error != B_OK)
|
||||
return reply->error;
|
||||
return error;
|
||||
}
|
||||
|
||||
// _FreeAttrCookie
|
||||
status_t
|
||||
Volume::_FreeAttrCookie(fs_vnode node, fs_cookie cookie)
|
||||
{
|
||||
// get a free port
|
||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||
if (!port)
|
||||
return B_ERROR;
|
||||
PortReleaser _(fFileSystem->GetPortPool(), port);
|
||||
|
||||
// prepare the request
|
||||
RequestAllocator allocator(port->GetPort());
|
||||
FreeAttrCookieRequest* request;
|
||||
status_t error = AllocateRequest(allocator, &request);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
request->volume = fUserlandVolume;
|
||||
request->node = node;
|
||||
request->attrCookie = cookie;
|
||||
|
||||
// send the request
|
||||
KernelRequestHandler handler(this, FREE_ATTR_COOKIE_REPLY);
|
||||
FreeAttrCookieReply* reply;
|
||||
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
RequestReleaser requestReleaser(port, reply);
|
||||
|
||||
// process the reply
|
||||
if (reply->error != B_OK)
|
||||
return reply->error;
|
||||
return error;
|
||||
}
|
||||
|
||||
// _CloseIndexDir
|
||||
status_t
|
||||
Volume::_CloseIndexDir(fs_cookie cookie)
|
||||
@@ -2982,6 +3176,10 @@ PRINT(("Volume::_PutAllPendingVNodes()\n"));
|
||||
PRINT(("Volume::_PutAllPendingVNodes() failed: open attr dirs\n"));
|
||||
return USERLAND_IOCTL_OPEN_ATTRIBUTE_DIRECTORIES;
|
||||
}
|
||||
if (fOpenAttributes > 0) {
|
||||
PRINT(("Volume::_PutAllPendingVNodes() failed: open attributes\n"));
|
||||
return USERLAND_IOCTL_OPEN_ATTRIBUTES;
|
||||
}
|
||||
if (fOpenIndexDirectories > 0) {
|
||||
PRINT(("Volume::_PutAllPendingVNodes() failed: open index dirs\n"));
|
||||
return USERLAND_IOCTL_OPEN_INDEX_DIRECTORIES;
|
||||
|
||||
@@ -125,6 +125,13 @@ public:
|
||||
status_t RewindAttrDir(fs_vnode node, fs_cookie cookie);
|
||||
|
||||
// attributes
|
||||
status_t CreateAttr(fs_vnode node, const char* name,
|
||||
uint32 type, int openMode,
|
||||
fs_cookie* cookie);
|
||||
status_t OpenAttr(fs_vnode node, const char* name,
|
||||
int openMode, fs_cookie* cookie);
|
||||
status_t CloseAttr(fs_vnode node, fs_cookie cookie);
|
||||
status_t FreeAttrCookie(fs_vnode node, fs_cookie cookie);
|
||||
status_t ReadAttr(fs_vnode node, fs_cookie cookie,
|
||||
off_t pos, void* buffer, size_t bufferSize,
|
||||
size_t* bytesRead);
|
||||
@@ -176,6 +183,9 @@ private:
|
||||
status_t _CloseAttrDir(fs_vnode node, fs_cookie cookie);
|
||||
status_t _FreeAttrDirCookie(fs_vnode node,
|
||||
fs_cookie cookie);
|
||||
status_t _CloseAttr(fs_vnode node, fs_cookie cookie);
|
||||
status_t _FreeAttrCookie(fs_vnode node,
|
||||
fs_cookie cookie);
|
||||
status_t _CloseIndexDir(fs_cookie cookie);
|
||||
status_t _FreeIndexDirCookie(fs_cookie cookie);
|
||||
status_t _CloseQuery(fs_cookie cookie);
|
||||
@@ -208,6 +218,7 @@ private:
|
||||
vint32 fOpenFiles;
|
||||
vint32 fOpenDirectories;
|
||||
vint32 fOpenAttributeDirectories;
|
||||
vint32 fOpenAttributes;
|
||||
vint32 fOpenIndexDirectories;
|
||||
vint32 fOpenQueries;
|
||||
VNodeCountMap* fVNodeCountMap;
|
||||
|
||||
@@ -629,10 +629,53 @@ userlandfs_rewind_attr_dir(fs_volume fs, fs_vnode node, fs_cookie cookie)
|
||||
// #pragma mark - attributes
|
||||
|
||||
|
||||
// TODO: create_attr()
|
||||
// TODO: open_attr()
|
||||
// TODO: close_attr()
|
||||
// TODO: free_attr_cookie()
|
||||
// userlandfs_create_attr
|
||||
status_t
|
||||
userlandfs_create_attr(fs_volume fs, fs_vnode node, const char *name,
|
||||
uint32 type, int openMode, fs_cookie *cookie)
|
||||
{
|
||||
Volume* volume = (Volume*)fs;
|
||||
PRINT(("userlandfs_create_attr(%p, %p, \"%s\", 0x%lx, %d, %p)\n", fs, node,
|
||||
name, type, openMode, cookie));
|
||||
status_t error = volume->CreateAttr(node, name, type, openMode, cookie);
|
||||
PRINT(("userlandfs_create_attr() done: (%lx, %p)\n", error, *cookie));
|
||||
return error;
|
||||
}
|
||||
|
||||
// userlandfs_open_attr
|
||||
status_t
|
||||
userlandfs_open_attr(fs_volume fs, fs_vnode node, const char *name,
|
||||
int openMode, fs_cookie *cookie)
|
||||
{
|
||||
Volume* volume = (Volume*)fs;
|
||||
PRINT(("userlandfs_open_attr(%p, %p, \"%s\", %d, %p)\n", fs, node, name,
|
||||
openMode, cookie));
|
||||
status_t error = volume->OpenAttr(node, name, openMode, cookie);
|
||||
PRINT(("userlandfs_open_attr() done: (%lx, %p)\n", error, *cookie));
|
||||
return error;
|
||||
}
|
||||
|
||||
// userlandfs_close_attr
|
||||
status_t
|
||||
userlandfs_close_attr(fs_volume fs, fs_vnode node, fs_cookie cookie)
|
||||
{
|
||||
Volume* volume = (Volume*)fs;
|
||||
PRINT(("userlandfs_close_attr(%p, %p, %p)\n", fs, node, cookie));
|
||||
status_t error = volume->CloseAttr(node, cookie);
|
||||
PRINT(("userlandfs_close_attr() done: %lx\n", error));
|
||||
return error;
|
||||
}
|
||||
|
||||
// userlandfs_free_attr_cookie
|
||||
status_t
|
||||
userlandfs_free_attr_cookie(fs_volume fs, fs_vnode node, fs_cookie cookie)
|
||||
{
|
||||
Volume* volume = (Volume*)fs;
|
||||
PRINT(("userlandfs_close_attr(%p, %p, %p)\n", fs, node, cookie));
|
||||
status_t error = volume->FreeAttrCookie(node, cookie);
|
||||
PRINT(("userlandfs_close_attr() done: %lx\n", error));
|
||||
return error;
|
||||
}
|
||||
|
||||
// userlandfs_read_attr
|
||||
static status_t
|
||||
@@ -1016,10 +1059,10 @@ static file_system_module_info sUserlandFSModuleInfo = {
|
||||
&userlandfs_rewind_attr_dir,
|
||||
|
||||
/* attribute operations */
|
||||
NULL, // &userlandfs_create_attr,
|
||||
NULL, // &userlandfs_open_attr,
|
||||
NULL, // &userlandfs_close_attr,
|
||||
NULL, // &userlandfs_free_attr_cookie,
|
||||
&userlandfs_create_attr,
|
||||
&userlandfs_open_attr,
|
||||
&userlandfs_close_attr,
|
||||
&userlandfs_free_attr_cookie,
|
||||
&userlandfs_read_attr,
|
||||
&userlandfs_write_attr,
|
||||
|
||||
|
||||
@@ -175,6 +175,22 @@ ReadAttrDirReply::GetAddressInfos(AddressInfo* infos, int32* count)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// CreateAttrRequest
|
||||
status_t
|
||||
CreateAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
|
||||
{
|
||||
ADD_NON_NULL_STRING(name);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// OpenAttrRequest
|
||||
status_t
|
||||
OpenAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
|
||||
{
|
||||
ADD_NON_NULL_STRING(name);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// ReadAttrReply
|
||||
status_t
|
||||
ReadAttrReply::GetAddressInfos(AddressInfo* infos, int32* count)
|
||||
@@ -563,12 +579,21 @@ UserlandFSUtil::is_kernel_request(uint32 type)
|
||||
case REWIND_ATTR_DIR_REPLY:
|
||||
return false;
|
||||
// attributes
|
||||
case CREATE_ATTR_REQUEST:
|
||||
case OPEN_ATTR_REQUEST:
|
||||
case CLOSE_ATTR_REQUEST:
|
||||
case FREE_ATTR_COOKIE_REQUEST:
|
||||
case READ_ATTR_REQUEST:
|
||||
case WRITE_ATTR_REQUEST:
|
||||
case READ_ATTR_STAT_REQUEST:
|
||||
case RENAME_ATTR_REQUEST:
|
||||
case REMOVE_ATTR_REQUEST:
|
||||
return true;
|
||||
case CREATE_ATTR_REPLY:
|
||||
case OPEN_ATTR_REPLY:
|
||||
case CLOSE_ATTR_REPLY:
|
||||
case FREE_ATTR_COOKIE_REPLY:
|
||||
|
||||
case READ_ATTR_REPLY:
|
||||
case WRITE_ATTR_REPLY:
|
||||
case READ_ATTR_STAT_REPLY:
|
||||
@@ -753,12 +778,20 @@ UserlandFSUtil::is_userland_request(uint32 type)
|
||||
case REWIND_ATTR_DIR_REPLY:
|
||||
return true;
|
||||
// attributes
|
||||
case CREATE_ATTR_REQUEST:
|
||||
case OPEN_ATTR_REQUEST:
|
||||
case CLOSE_ATTR_REQUEST:
|
||||
case FREE_ATTR_COOKIE_REQUEST:
|
||||
case READ_ATTR_REQUEST:
|
||||
case WRITE_ATTR_REQUEST:
|
||||
case RENAME_ATTR_REQUEST:
|
||||
case READ_ATTR_STAT_REQUEST:
|
||||
case REMOVE_ATTR_REQUEST:
|
||||
return false;
|
||||
case CREATE_ATTR_REPLY:
|
||||
case OPEN_ATTR_REPLY:
|
||||
case CLOSE_ATTR_REPLY:
|
||||
case FREE_ATTR_COOKIE_REPLY:
|
||||
case READ_ATTR_REPLY:
|
||||
case WRITE_ATTR_REPLY:
|
||||
case READ_ATTR_STAT_REPLY:
|
||||
|
||||
@@ -2,9 +2,41 @@
|
||||
|
||||
#include "BeOSKernelVolume.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "beos_fs_interface.h"
|
||||
#include "kernel_emu.h"
|
||||
|
||||
|
||||
using std::nothrow;
|
||||
|
||||
static int open_mode_to_access(int openMode);
|
||||
|
||||
|
||||
// AttributeCookie
|
||||
class BeOSKernelVolume::AttributeCookie {
|
||||
public:
|
||||
AttributeCookie(const char* name, uint32 type, int openMode, bool exists,
|
||||
bool create)
|
||||
: fType(type),
|
||||
fOpenMode(openMode),
|
||||
fExists(exists),
|
||||
fCreate(create)
|
||||
{
|
||||
strcpy(fName, name);
|
||||
}
|
||||
|
||||
char fName[B_ATTR_NAME_LENGTH];
|
||||
uint32 fType;
|
||||
int fOpenMode;
|
||||
bool fExists;
|
||||
bool fCreate;
|
||||
};
|
||||
|
||||
|
||||
// constructor
|
||||
BeOSKernelVolume::BeOSKernelVolume(FileSystem* fileSystem, mount_id id,
|
||||
beos_vnode_ops* fsOps)
|
||||
@@ -503,43 +535,106 @@ BeOSKernelVolume::RewindAttrDir(fs_vnode node, fs_cookie cookie)
|
||||
// #pragma mark - attributes
|
||||
|
||||
|
||||
// CreateAttr
|
||||
status_t
|
||||
BeOSKernelVolume::CreateAttr(fs_vnode node, const char* name, uint32 type,
|
||||
int openMode, fs_cookie* cookie)
|
||||
{
|
||||
return _OpenAttr(node, name, type, openMode, true, cookie);
|
||||
}
|
||||
|
||||
// OpenAttr
|
||||
status_t
|
||||
BeOSKernelVolume::OpenAttr(fs_vnode node, const char* name, int openMode,
|
||||
fs_cookie* cookie)
|
||||
{
|
||||
return _OpenAttr(node, name, 0, openMode, false, cookie);
|
||||
}
|
||||
|
||||
// CloseAttr
|
||||
status_t
|
||||
BeOSKernelVolume::CloseAttr(fs_vnode node, fs_cookie cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// FreeAttrCookie
|
||||
status_t
|
||||
BeOSKernelVolume::FreeAttrCookie(fs_vnode node, fs_cookie _cookie)
|
||||
{
|
||||
AttributeCookie* cookie = (AttributeCookie*)_cookie;
|
||||
|
||||
// If the attribute doesn't exist yet and it was opened with
|
||||
// CreateAttr(), we could create it now. We have a race condition here
|
||||
// though, since someone else could have created it in the meantime.
|
||||
|
||||
delete cookie;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// ReadAttr
|
||||
status_t
|
||||
BeOSKernelVolume::ReadAttr(fs_vnode node, fs_cookie cookie, off_t pos,
|
||||
BeOSKernelVolume::ReadAttr(fs_vnode node, fs_cookie _cookie, off_t pos,
|
||||
void* buffer, size_t bufferSize, size_t* bytesRead)
|
||||
{
|
||||
// TODO: Implement!
|
||||
return B_BAD_VALUE;
|
||||
// if (!fFSOps->read_attr)
|
||||
// return B_BAD_VALUE;
|
||||
// *bytesRead = bufferSize;
|
||||
// return fFSOps->read_attr(fVolumeCookie, node, name, type, buffer, bytesRead,
|
||||
// pos);
|
||||
AttributeCookie* cookie = (AttributeCookie*)_cookie;
|
||||
|
||||
// check, if open mode allows reading
|
||||
if ((open_mode_to_access(cookie->fOpenMode) | R_OK) == 0)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
// read
|
||||
if (!fFSOps->read_attr)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
*bytesRead = bufferSize;
|
||||
return fFSOps->read_attr(fVolumeCookie, node, cookie->fName, cookie->fType,
|
||||
buffer, bytesRead, pos);
|
||||
}
|
||||
|
||||
// WriteAttr
|
||||
status_t
|
||||
BeOSKernelVolume::WriteAttr(fs_vnode node, fs_cookie cookie, off_t pos,
|
||||
BeOSKernelVolume::WriteAttr(fs_vnode node, fs_cookie _cookie, off_t pos,
|
||||
const void* buffer, size_t bufferSize, size_t* bytesWritten)
|
||||
{
|
||||
// TODO: Implement!
|
||||
return B_BAD_VALUE;
|
||||
// if (!fFSOps->write_attr)
|
||||
// return B_BAD_VALUE;
|
||||
// *bytesWritten = bufferSize;
|
||||
// return fFSOps->write_attr(fVolumeCookie, node, name, type, buffer,
|
||||
// bytesWritten, pos);
|
||||
AttributeCookie* cookie = (AttributeCookie*)_cookie;
|
||||
|
||||
// check, if open mode allows writing
|
||||
if ((open_mode_to_access(cookie->fOpenMode) | W_OK) == 0)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
// write
|
||||
if (!fFSOps->write_attr)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
*bytesWritten = bufferSize;
|
||||
return fFSOps->write_attr(fVolumeCookie, node, cookie->fName, cookie->fType,
|
||||
buffer, bytesWritten, pos);
|
||||
}
|
||||
|
||||
// ReadAttrStat
|
||||
status_t
|
||||
BeOSKernelVolume::ReadAttrStat(fs_vnode node, fs_cookie cookie, struct stat *st)
|
||||
BeOSKernelVolume::ReadAttrStat(fs_vnode node, fs_cookie _cookie,
|
||||
struct stat *st)
|
||||
{
|
||||
// TODO: Implement!
|
||||
return B_BAD_VALUE;
|
||||
// if (!fFSOps->stat_attr)
|
||||
// return B_BAD_VALUE;
|
||||
// return fFSOps->stat_attr(fVolumeCookie, node, name, attrInfo);
|
||||
AttributeCookie* cookie = (AttributeCookie*)_cookie;
|
||||
|
||||
// get the stats
|
||||
beos_attr_info attrInfo;
|
||||
if (!fFSOps->stat_attr)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t error = fFSOps->stat_attr(fVolumeCookie, node, cookie->fName,
|
||||
&attrInfo);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// translate to struct stat
|
||||
st->st_size = attrInfo.size;
|
||||
st->st_type = attrInfo.type;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// RenameAttr
|
||||
@@ -708,3 +803,65 @@ BeOSKernelVolume::ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize,
|
||||
(struct beos_dirent*)buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Private
|
||||
|
||||
|
||||
// _OpenAttr
|
||||
status_t
|
||||
BeOSKernelVolume::_OpenAttr(fs_vnode node, const char* name, uint32 type,
|
||||
int openMode, bool create, fs_cookie* _cookie)
|
||||
{
|
||||
// check permissions first
|
||||
int accessMode = open_mode_to_access(openMode) | (create ? W_OK : 0);
|
||||
status_t error = Access(node, accessMode);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// check whether the attribute already exists
|
||||
beos_attr_info attrInfo;
|
||||
if (!fFSOps->stat_attr)
|
||||
return B_BAD_VALUE;
|
||||
bool exists
|
||||
= (fFSOps->stat_attr(fVolumeCookie, node, name, &attrInfo) == B_OK);
|
||||
|
||||
if (create) {
|
||||
// create: fail, if attribute exists and non-existence was required
|
||||
if (exists && (openMode & O_EXCL))
|
||||
return B_FILE_EXISTS;
|
||||
} else {
|
||||
// open: fail, if attribute doesn't exist
|
||||
if (!exists)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
// keep the attribute type
|
||||
type = attrInfo.type;
|
||||
}
|
||||
|
||||
// create an attribute cookie
|
||||
AttributeCookie* cookie = new(nothrow) AttributeCookie(name, type,
|
||||
openMode, exists, create);
|
||||
if (!cookie)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// TODO: If we want to support O_TRUNC, we should do that here.
|
||||
|
||||
*_cookie = cookie;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// open_mode_to_access
|
||||
static int
|
||||
open_mode_to_access(int openMode)
|
||||
{
|
||||
switch (openMode & O_RWMASK) {
|
||||
case O_RDONLY:
|
||||
return R_OK;
|
||||
case O_WRONLY:
|
||||
return W_OK;
|
||||
case O_RDWR:
|
||||
default:
|
||||
return W_OK | R_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,13 @@ public:
|
||||
virtual status_t RewindAttrDir(fs_vnode node, fs_cookie cookie);
|
||||
|
||||
// attributes
|
||||
virtual status_t CreateAttr(fs_vnode node, const char *name,
|
||||
uint32 type, int openMode,
|
||||
fs_cookie *cookie);
|
||||
virtual status_t OpenAttr(fs_vnode node, const char *name,
|
||||
int openMode, fs_cookie *cookie);
|
||||
virtual status_t CloseAttr(fs_vnode node, fs_cookie cookie);
|
||||
virtual status_t FreeAttrCookie(fs_vnode node, fs_cookie cookie);
|
||||
virtual status_t ReadAttr(fs_vnode node, fs_cookie cookie,
|
||||
off_t pos, void* buffer, size_t bufferSize,
|
||||
size_t* bytesRead);
|
||||
@@ -135,6 +142,14 @@ public:
|
||||
size_t bufferSize, uint32 count,
|
||||
uint32* countRead);
|
||||
|
||||
private:
|
||||
class AttributeCookie;
|
||||
|
||||
private:
|
||||
status_t _OpenAttr(fs_vnode node, const char* name,
|
||||
uint32 type, int openMode, bool create,
|
||||
fs_cookie* cookie);
|
||||
|
||||
private:
|
||||
beos_vnode_ops* fFSOps;
|
||||
void* fVolumeCookie;
|
||||
|
||||
@@ -138,6 +138,14 @@ UserlandRequestHandler::HandleRequest(Request* request)
|
||||
return _HandleRequest((RewindAttrDirRequest*)request);
|
||||
|
||||
// attributes
|
||||
case CREATE_ATTR_REQUEST:
|
||||
return _HandleRequest((CreateAttrRequest*)request);
|
||||
case OPEN_ATTR_REQUEST:
|
||||
return _HandleRequest((OpenAttrRequest*)request);
|
||||
case CLOSE_ATTR_REQUEST:
|
||||
return _HandleRequest((CloseAttrRequest*)request);
|
||||
case FREE_ATTR_COOKIE_REQUEST:
|
||||
return _HandleRequest((FreeAttrCookieRequest*)request);
|
||||
case READ_ATTR_REQUEST:
|
||||
return _HandleRequest((ReadAttrRequest*)request);
|
||||
case WRITE_ATTR_REQUEST:
|
||||
@@ -1493,6 +1501,126 @@ UserlandRequestHandler::_HandleRequest(RewindAttrDirRequest* request)
|
||||
// #pragma mark - attributes
|
||||
|
||||
|
||||
// _HandleRequest
|
||||
status_t
|
||||
UserlandRequestHandler::_HandleRequest(CreateAttrRequest* request)
|
||||
{
|
||||
// check and execute the request
|
||||
status_t result = B_OK;
|
||||
Volume* volume = (Volume*)request->volume;
|
||||
if (!volume)
|
||||
result = B_BAD_VALUE;
|
||||
|
||||
fs_cookie attrCookie;
|
||||
if (result == B_OK) {
|
||||
RequestThreadContext context(volume);
|
||||
result = volume->CreateAttr(request->node,
|
||||
(const char*)request->name.GetData(), request->type,
|
||||
request->openMode, &attrCookie);
|
||||
}
|
||||
|
||||
// prepare the reply
|
||||
RequestAllocator allocator(fPort->GetPort());
|
||||
CreateAttrReply* reply;
|
||||
status_t error = AllocateRequest(allocator, &reply);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
reply->error = result;
|
||||
reply->attrCookie = attrCookie;
|
||||
|
||||
// send the reply
|
||||
return _SendReply(allocator, false);
|
||||
}
|
||||
|
||||
// _HandleRequest
|
||||
status_t
|
||||
UserlandRequestHandler::_HandleRequest(OpenAttrRequest* request)
|
||||
{
|
||||
// check and execute the request
|
||||
status_t result = B_OK;
|
||||
Volume* volume = (Volume*)request->volume;
|
||||
if (!volume)
|
||||
result = B_BAD_VALUE;
|
||||
|
||||
fs_cookie attrCookie;
|
||||
if (result == B_OK) {
|
||||
RequestThreadContext context(volume);
|
||||
result = volume->OpenAttr(request->node,
|
||||
(const char*)request->name.GetData(), request->openMode,
|
||||
&attrCookie);
|
||||
}
|
||||
|
||||
// prepare the reply
|
||||
RequestAllocator allocator(fPort->GetPort());
|
||||
OpenAttrReply* reply;
|
||||
status_t error = AllocateRequest(allocator, &reply);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
reply->error = result;
|
||||
reply->attrCookie = attrCookie;
|
||||
|
||||
// send the reply
|
||||
return _SendReply(allocator, false);
|
||||
}
|
||||
|
||||
// _HandleRequest
|
||||
status_t
|
||||
UserlandRequestHandler::_HandleRequest(CloseAttrRequest* request)
|
||||
{
|
||||
// check and execute the request
|
||||
status_t result = B_OK;
|
||||
Volume* volume = (Volume*)request->volume;
|
||||
if (!volume)
|
||||
result = B_BAD_VALUE;
|
||||
|
||||
if (result == B_OK) {
|
||||
RequestThreadContext context(volume);
|
||||
result = volume->CloseAttr(request->node, request->attrCookie);
|
||||
}
|
||||
|
||||
// prepare the reply
|
||||
RequestAllocator allocator(fPort->GetPort());
|
||||
CloseAttrReply* reply;
|
||||
status_t error = AllocateRequest(allocator, &reply);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
reply->error = result;
|
||||
|
||||
// send the reply
|
||||
return _SendReply(allocator, false);
|
||||
}
|
||||
|
||||
// _HandleRequest
|
||||
status_t
|
||||
UserlandRequestHandler::_HandleRequest(FreeAttrCookieRequest* request)
|
||||
{
|
||||
// check and execute the request
|
||||
status_t result = B_OK;
|
||||
Volume* volume = (Volume*)request->volume;
|
||||
if (!volume)
|
||||
result = B_BAD_VALUE;
|
||||
|
||||
if (result == B_OK) {
|
||||
RequestThreadContext context(volume);
|
||||
result = volume->FreeAttrCookie(request->node, request->attrCookie);
|
||||
}
|
||||
|
||||
// prepare the reply
|
||||
RequestAllocator allocator(fPort->GetPort());
|
||||
FreeAttrCookieReply* reply;
|
||||
status_t error = AllocateRequest(allocator, &reply);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
reply->error = result;
|
||||
|
||||
// send the reply
|
||||
return _SendReply(allocator, false);
|
||||
}
|
||||
|
||||
// _HandleRequest
|
||||
status_t
|
||||
UserlandRequestHandler::_HandleRequest(ReadAttrRequest* request)
|
||||
|
||||
@@ -54,6 +54,10 @@ class FreeAttrDirCookieRequest;
|
||||
class ReadAttrDirRequest;
|
||||
class RewindAttrDirRequest;
|
||||
// attributes
|
||||
class CreateAttrRequest;
|
||||
class OpenAttrRequest;
|
||||
class CloseAttrRequest;
|
||||
class FreeAttrCookieRequest;
|
||||
class ReadAttrRequest;
|
||||
class WriteAttrRequest;
|
||||
class ReadAttrStatRequest;
|
||||
@@ -148,6 +152,10 @@ private:
|
||||
status_t _HandleRequest(RewindAttrDirRequest* request);
|
||||
|
||||
// attributes
|
||||
status_t _HandleRequest(CreateAttrRequest* request);
|
||||
status_t _HandleRequest(OpenAttrRequest* request);
|
||||
status_t _HandleRequest(CloseAttrRequest* request);
|
||||
status_t _HandleRequest(FreeAttrCookieRequest* request);
|
||||
status_t _HandleRequest(ReadAttrRequest* request);
|
||||
status_t _HandleRequest(WriteAttrRequest* request);
|
||||
status_t _HandleRequest(ReadAttrStatRequest* request);
|
||||
|
||||
@@ -347,6 +347,36 @@ Volume::RewindAttrDir(fs_vnode node, fs_cookie cookie)
|
||||
// #pragma mark - attributes
|
||||
|
||||
|
||||
// CreateAttr
|
||||
status_t
|
||||
Volume::CreateAttr(fs_vnode node, const char* name, uint32 type, int openMode,
|
||||
fs_cookie* cookie)
|
||||
{
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// OpenAttr
|
||||
status_t
|
||||
Volume::OpenAttr(fs_vnode node, const char* name, int openMode,
|
||||
fs_cookie* cookie)
|
||||
{
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// CloseAttr
|
||||
status_t
|
||||
Volume::CloseAttr(fs_vnode node, fs_cookie cookie)
|
||||
{
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// FreeAttrCookie
|
||||
status_t
|
||||
Volume::FreeAttrCookie(fs_vnode node, fs_cookie cookie)
|
||||
{
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// ReadAttr
|
||||
status_t
|
||||
Volume::ReadAttr(fs_vnode node, fs_cookie cookie, off_t pos, void* buffer,
|
||||
|
||||
@@ -101,6 +101,13 @@ public:
|
||||
virtual status_t RewindAttrDir(fs_vnode node, fs_cookie cookie);
|
||||
|
||||
// attributes
|
||||
virtual status_t CreateAttr(fs_vnode node, const char* name,
|
||||
uint32 type, int openMode,
|
||||
fs_cookie* cookie);
|
||||
virtual status_t OpenAttr(fs_vnode node, const char* name,
|
||||
int openMode, fs_cookie* cookie);
|
||||
virtual status_t CloseAttr(fs_vnode node, fs_cookie cookie);
|
||||
virtual status_t FreeAttrCookie(fs_vnode node, fs_cookie cookie);
|
||||
virtual status_t ReadAttr(fs_vnode node, fs_cookie cookie,
|
||||
off_t pos, void* buffer, size_t bufferSize,
|
||||
size_t* bytesRead);
|
||||
|
||||
Reference in New Issue
Block a user