* More debug output in the kernel module.

* Made publish_vnode() available in userland. For old style FS add-ons
  publish_vnode() is used when they request a new_vnode(). The semantics
  of new_vnode() changed considerably in Haiku, but publish_vnode()
  seems to do pretty much what the old new_vnode() did.
* The UserlandFS hosted RamFS begins to work under Haiku. It runs pretty
  soon out of memory though (under vmware with 256 MB) and node
  monitoring is broken ATM.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20264 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2007-03-01 04:56:08 +00:00
parent 32164a180c
commit 042eb16896
10 changed files with 213 additions and 12 deletions
@@ -185,6 +185,8 @@ enum {
PUT_VNODE_REPLY, PUT_VNODE_REPLY,
NEW_VNODE_REQUEST, NEW_VNODE_REQUEST,
NEW_VNODE_REPLY, NEW_VNODE_REPLY,
PUBLISH_VNODE_REQUEST,
PUBLISH_VNODE_REPLY,
REMOVE_VNODE_REQUEST, REMOVE_VNODE_REQUEST,
REMOVE_VNODE_REPLY, REMOVE_VNODE_REPLY,
UNREMOVE_VNODE_REQUEST, UNREMOVE_VNODE_REQUEST,
@@ -1425,6 +1427,22 @@ public:
NewVNodeReply() : ReplyRequest(NEW_VNODE_REPLY) {} NewVNodeReply() : ReplyRequest(NEW_VNODE_REPLY) {}
}; };
// PublishVNodeRequest
class PublishVNodeRequest : public Request {
public:
PublishVNodeRequest() : Request(PUBLISH_VNODE_REQUEST) {}
mount_id nsid;
vnode_id vnid;
fs_vnode node;
};
// PublishVNodeReply
class PublishVNodeReply : public ReplyRequest {
public:
PublishVNodeReply() : ReplyRequest(PUBLISH_VNODE_REPLY) {}
};
// RemoveVNodeRequest // RemoveVNodeRequest
class RemoveVNodeRequest : public Request { class RemoveVNodeRequest : public Request {
public: public:
@@ -1788,6 +1806,10 @@ do_for_request(Request* request, Task& task)
return task((NewVNodeRequest*)request); return task((NewVNodeRequest*)request);
case NEW_VNODE_REPLY: case NEW_VNODE_REPLY:
return task((NewVNodeReply*)request); return task((NewVNodeReply*)request);
case PUBLISH_VNODE_REQUEST:
return task((PublishVNodeRequest*)request);
case PUBLISH_VNODE_REPLY:
return task((PublishVNodeReply*)request);
case REMOVE_VNODE_REQUEST: case REMOVE_VNODE_REQUEST:
return task((RemoveVNodeRequest*)request); return task((RemoveVNodeRequest*)request);
case REMOVE_VNODE_REPLY: case REMOVE_VNODE_REPLY:
@@ -1979,6 +2001,8 @@ using UserlandFSUtil::PutVNodeRequest;
using UserlandFSUtil::PutVNodeReply; using UserlandFSUtil::PutVNodeReply;
using UserlandFSUtil::NewVNodeRequest; using UserlandFSUtil::NewVNodeRequest;
using UserlandFSUtil::NewVNodeReply; using UserlandFSUtil::NewVNodeReply;
using UserlandFSUtil::PublishVNodeRequest;
using UserlandFSUtil::PublishVNodeReply;
using UserlandFSUtil::RemoveVNodeRequest; using UserlandFSUtil::RemoveVNodeRequest;
using UserlandFSUtil::RemoveVNodeReply; using UserlandFSUtil::RemoveVNodeReply;
using UserlandFSUtil::UnremoveVNodeRequest; using UserlandFSUtil::UnremoveVNodeRequest;
@@ -71,6 +71,8 @@ KernelRequestHandler::HandleRequest(Request* request)
return _HandleRequest((PutVNodeRequest*)request); return _HandleRequest((PutVNodeRequest*)request);
case NEW_VNODE_REQUEST: case NEW_VNODE_REQUEST:
return _HandleRequest((NewVNodeRequest*)request); return _HandleRequest((NewVNodeRequest*)request);
case PUBLISH_VNODE_REQUEST:
return _HandleRequest((PublishVNodeRequest*)request);
case REMOVE_VNODE_REQUEST: case REMOVE_VNODE_REQUEST:
return _HandleRequest((RemoveVNodeRequest*)request); return _HandleRequest((RemoveVNodeRequest*)request);
case UNREMOVE_VNODE_REQUEST: case UNREMOVE_VNODE_REQUEST:
@@ -274,6 +276,30 @@ KernelRequestHandler::_HandleRequest(NewVNodeRequest* request)
return fPort->SendRequest(&allocator); return fPort->SendRequest(&allocator);
} }
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(PublishVNodeRequest* request)
{
// check and executed the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->PublishVNode(request->vnid, request->node);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
PublishVNodeReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest // _HandleRequest
status_t status_t
KernelRequestHandler::_HandleRequest(RemoveVNodeRequest* request) KernelRequestHandler::_HandleRequest(RemoveVNodeRequest* request)
@@ -14,6 +14,7 @@ class IsVNodeRemovedRequest;
class NewVNodeRequest; class NewVNodeRequest;
class NotifyListenerRequest; class NotifyListenerRequest;
class NotifySelectEventRequest; class NotifySelectEventRequest;
class PublishVNodeRequest;
class PutVNodeRequest; class PutVNodeRequest;
class RemoveVNodeRequest; class RemoveVNodeRequest;
class SendNotificationRequest; class SendNotificationRequest;
@@ -26,11 +27,11 @@ using UserlandFSUtil::IsVNodeRemovedRequest;
using UserlandFSUtil::NewVNodeRequest; using UserlandFSUtil::NewVNodeRequest;
using UserlandFSUtil::NotifyListenerRequest; using UserlandFSUtil::NotifyListenerRequest;
using UserlandFSUtil::NotifySelectEventRequest; using UserlandFSUtil::NotifySelectEventRequest;
using UserlandFSUtil::PublishVNodeRequest;
using UserlandFSUtil::PutVNodeRequest; using UserlandFSUtil::PutVNodeRequest;
using UserlandFSUtil::RemoveVNodeRequest; using UserlandFSUtil::RemoveVNodeRequest;
using UserlandFSUtil::SendNotificationRequest; using UserlandFSUtil::SendNotificationRequest;
using UserlandFSUtil::UnremoveVNodeRequest; using UserlandFSUtil::UnremoveVNodeRequest;
using UserlandFSUtil::GetVNodeRequest;
class Volume; class Volume;
@@ -55,6 +56,7 @@ private:
status_t _HandleRequest(GetVNodeRequest* request); status_t _HandleRequest(GetVNodeRequest* request);
status_t _HandleRequest(PutVNodeRequest* request); status_t _HandleRequest(PutVNodeRequest* request);
status_t _HandleRequest(NewVNodeRequest* request); status_t _HandleRequest(NewVNodeRequest* request);
status_t _HandleRequest(PublishVNodeRequest* request);
status_t _HandleRequest(RemoveVNodeRequest* request); status_t _HandleRequest(RemoveVNodeRequest* request);
status_t _HandleRequest(UnremoveVNodeRequest* request); status_t _HandleRequest(UnremoveVNodeRequest* request);
status_t _HandleRequest(IsVNodeRemovedRequest* request); status_t _HandleRequest(IsVNodeRemovedRequest* request);
@@ -163,6 +163,29 @@ PRINT(("new_vnode(%ld, %Ld)\n", fID, vnid));
if (error != B_OK) { if (error != B_OK) {
ERROR(("Volume::NewVNode(): Failed to add vnode to mount " ERROR(("Volume::NewVNode(): Failed to add vnode to mount "
"vnode map!\n")); "vnode map!\n"));
publish_vnode(fID, vnid, node);
put_vnode(fID, vnid);
return error;
}
}
// TODO: Check what need to do according to the new semantics.
// _IncrementVNodeCount(vnid);
}
return error;
}
// PublishVNode
status_t
Volume::PublishVNode(vnode_id vnid, fs_vnode node)
{
PRINT(("publish_vnode(%ld, %Ld)\n", fID, vnid));
status_t error = publish_vnode(fID, vnid, node);
if (error == B_OK) {
if (IsMounting()) {
error = fMountVNodes->Put(vnid, node);
if (error != B_OK) {
ERROR(("Volume::PublishVNode(): Failed to add vnode to mount "
"vnode map!\n"));
put_vnode(fID, vnid); put_vnode(fID, vnid);
return error; return error;
} }
@@ -35,9 +35,10 @@ public:
bool IsMounting() const; bool IsMounting() const;
// client methods // client methods
status_t GetVNode(vnode_id vnid, void** node); status_t GetVNode(vnode_id vnid, fs_vnode* node);
status_t PutVNode(vnode_id vnid); status_t PutVNode(vnode_id vnid);
status_t NewVNode(vnode_id vnid, void* node); status_t NewVNode(vnode_id vnid, fs_vnode node);
status_t PublishVNode(vnode_id vnid, fs_vnode node);
status_t RemoveVNode(vnode_id vnid); status_t RemoveVNode(vnode_id vnid);
status_t UnremoveVNode(vnode_id vnid); status_t UnremoveVNode(vnode_id vnid);
status_t IsVNodeRemoved(vnode_id vnid); status_t IsVNodeRemoved(vnode_id vnid);
@@ -67,6 +67,9 @@ static status_t
userlandfs_mount(mount_id id, const char *device, uint32 flags, userlandfs_mount(mount_id id, const char *device, uint32 flags,
const char *args, fs_volume *fsCookie, vnode_id *rootVnodeID) const char *args, fs_volume *fsCookie, vnode_id *rootVnodeID)
{ {
PRINT(("userlandfs_mount(%ld, %s, 0x%lx, %s, %p, %p)\n", id, device, flags,
args, fsCookie, rootVnodeID));
status_t error = B_OK; status_t error = B_OK;
// get the parameters // get the parameters
@@ -75,44 +78,50 @@ userlandfs_mount(mount_id id, const char *device, uint32 flags,
const char* fsParameters; const char* fsParameters;
error = parse_parameters(args, fsName, &fsParameters); error = parse_parameters(args, fsName, &fsParameters);
if (error != B_OK) if (error != B_OK)
return error; RETURN_ERROR(error);
// get the UserlandFS object // get the UserlandFS object
UserlandFS* userlandFS = UserlandFS::GetUserlandFS(); UserlandFS* userlandFS = UserlandFS::GetUserlandFS();
if (!userlandFS) if (!userlandFS)
return B_ERROR; RETURN_ERROR(B_ERROR);
// get the file system // get the file system
FileSystem* fileSystem = NULL; FileSystem* fileSystem = NULL;
error = userlandFS->RegisterFileSystem(fsName.GetString(), &fileSystem); error = userlandFS->RegisterFileSystem(fsName.GetString(), &fileSystem);
if (error != B_OK) if (error != B_OK)
return error; RETURN_ERROR(error);
// mount the volume // mount the volume
Volume* volume = NULL; Volume* volume = NULL;
error = fileSystem->Mount(id, device, flags, fsParameters, &volume); error = fileSystem->Mount(id, device, flags, fsParameters, &volume);
if (error != B_OK) { if (error != B_OK) {
userlandFS->UnregisterFileSystem(fileSystem); userlandFS->UnregisterFileSystem(fileSystem);
return error; RETURN_ERROR(error);
} }
*fsCookie = volume; *fsCookie = volume;
*rootVnodeID = volume->GetRootID(); *rootVnodeID = volume->GetRootID();
PRINT(("userlandfs_mount() done: %p, %lld\n", *fsCookie, *rootVnodeID));
return error; return error;
} }
// userlandfs_unmount // userlandfs_unmount
static status_t static status_t
userlandfs_unmount(fs_volume ns) userlandfs_unmount(fs_volume fs)
{ {
Volume* volume = (Volume*)ns; Volume* volume = (Volume*)fs;
PRINT(("userlandfs_unmount(%p)\n", fs));
FileSystem* fileSystem = volume->GetFileSystem(); FileSystem* fileSystem = volume->GetFileSystem();
status_t error = volume->Unmount(); status_t error = volume->Unmount();
// The error code the FS's unmount hook returns is completely irrelevant to // The error code the FS's unmount hook returns is completely irrelevant to
// the VFS. It considers the volume unmounted in any case. // the VFS. It considers the volume unmounted in any case.
volume->RemoveReference(); volume->RemoveReference();
UserlandFS::GetUserlandFS()->UnregisterFileSystem(fileSystem); UserlandFS::GetUserlandFS()->UnregisterFileSystem(fileSystem);
PRINT(("userlandfs_unmount() done: %lx\n", error));
return error; return error;
} }
@@ -960,6 +969,7 @@ userlandfs_std_ops(int32 op, ...)
case B_MODULE_INIT: case B_MODULE_INIT:
{ {
init_debugging(); init_debugging();
PRINT(("userlandfs_std_ops(): B_MODULE_INIT\n"));
// make sure there is a UserlandFS we can work with // make sure there is a UserlandFS we can work with
UserlandFS* userlandFS = NULL; UserlandFS* userlandFS = NULL;
@@ -973,6 +983,7 @@ userlandfs_std_ops(int32 op, ...)
} }
case B_MODULE_UNINIT: case B_MODULE_UNINIT:
PRINT(("userlandfs_std_ops(): B_MODULE_UNINIT\n"));
UserlandFS::UninitUserlandFS(); UserlandFS::UninitUserlandFS();
exit_debugging(); exit_debugging();
return B_OK; return B_OK;
@@ -645,6 +645,7 @@ UserlandFSUtil::is_kernel_request(uint32 type)
case GET_VNODE_REQUEST: case GET_VNODE_REQUEST:
case PUT_VNODE_REQUEST: case PUT_VNODE_REQUEST:
case NEW_VNODE_REQUEST: case NEW_VNODE_REQUEST:
case PUBLISH_VNODE_REQUEST:
case REMOVE_VNODE_REQUEST: case REMOVE_VNODE_REQUEST:
case UNREMOVE_VNODE_REQUEST: case UNREMOVE_VNODE_REQUEST:
case IS_VNODE_REMOVED_REQUEST: case IS_VNODE_REMOVED_REQUEST:
@@ -652,6 +653,7 @@ UserlandFSUtil::is_kernel_request(uint32 type)
case GET_VNODE_REPLY: case GET_VNODE_REPLY:
case PUT_VNODE_REPLY: case PUT_VNODE_REPLY:
case NEW_VNODE_REPLY: case NEW_VNODE_REPLY:
case PUBLISH_VNODE_REPLY:
case REMOVE_VNODE_REPLY: case REMOVE_VNODE_REPLY:
case UNREMOVE_VNODE_REPLY: case UNREMOVE_VNODE_REPLY:
case IS_VNODE_REMOVED_REPLY: case IS_VNODE_REMOVED_REPLY:
@@ -843,6 +845,7 @@ UserlandFSUtil::is_userland_request(uint32 type)
case GET_VNODE_REQUEST: case GET_VNODE_REQUEST:
case PUT_VNODE_REQUEST: case PUT_VNODE_REQUEST:
case NEW_VNODE_REQUEST: case NEW_VNODE_REQUEST:
case PUBLISH_VNODE_REQUEST:
case REMOVE_VNODE_REQUEST: case REMOVE_VNODE_REQUEST:
case UNREMOVE_VNODE_REQUEST: case UNREMOVE_VNODE_REQUEST:
case IS_VNODE_REMOVED_REQUEST: case IS_VNODE_REMOVED_REQUEST:
@@ -850,6 +853,7 @@ UserlandFSUtil::is_userland_request(uint32 type)
case GET_VNODE_REPLY: case GET_VNODE_REPLY:
case PUT_VNODE_REPLY: case PUT_VNODE_REPLY:
case NEW_VNODE_REPLY: case NEW_VNODE_REPLY:
case PUBLISH_VNODE_REPLY:
case REMOVE_VNODE_REPLY: case REMOVE_VNODE_REPLY:
case UNREMOVE_VNODE_REPLY: case UNREMOVE_VNODE_REPLY:
case IS_VNODE_REMOVED_REPLY: case IS_VNODE_REMOVED_REPLY:
@@ -83,7 +83,9 @@ put_vnode(nspace_id nsid, vnode_id vnid)
int int
new_vnode(nspace_id nsid, vnode_id vnid, void *data) new_vnode(nspace_id nsid, vnode_id vnid, void *data)
{ {
return UserlandFS::KernelEmu::new_vnode(nsid, vnid, data); // 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);
} }
// remove_vnode // remove_vnode
@@ -360,8 +360,36 @@ status_t
UserlandFS::KernelEmu::publish_vnode(mount_id nsid, vnode_id vnid, UserlandFS::KernelEmu::publish_vnode(mount_id nsid, vnode_id vnid,
fs_vnode data) fs_vnode data)
{ {
// TODO: Implement! // get the request port and the file system
return B_BAD_VALUE; RequestPort* port;
FileSystem* fileSystem;
status_t error = get_port_and_fs(&port, &fileSystem);
if (error != B_OK)
return error;
// prepare the request
RequestAllocator allocator(port->GetPort());
PublishVNodeRequest* request;
error = AllocateRequest(allocator, &request);
if (error != B_OK)
return error;
request->nsid = nsid;
request->vnid = vnid;
request->node = data;
// send the request
UserlandRequestHandler handler(fileSystem, PUBLISH_VNODE_REPLY);
PublishVNodeReply* reply;
error = port->SendRequest(&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;
} }
// remove_vnode // remove_vnode
@@ -0,0 +1,80 @@
# userlandfs settings
#
# Lives in /boot/home/config/settings/kernel/drivers/.
# OpenBFS
file_system obfs {
# BFS_IOCTL_VERSION
ioctl 14200 {
buffer_size 0
write_buffer_size 4
is_buffer true
}
# BFS_IOCTL_START_CHECKING
ioctl 14201 {
buffer_size 312
write_buffer_size 312
is_buffer true
}
# BFS_IOCTL_STOP_CHECKING
ioctl 14202 {
buffer_size 312
write_buffer_size 312
is_buffer true
}
# BFS_IOCTL_CHECK_NEXT_NODE
ioctl 14203 {
buffer_size 312
write_buffer_size 312
is_buffer true
}
# allocate and zero all free blocks
ioctl 56742 {
buffer_size 0
write_buffer_size 0
is_buffer false
}
# dump super block
ioctl 56743 {
buffer_size 0
write_buffer_size 0
is_buffer false
}
# dump inode
ioctl 56744 {
buffer_size 0
write_buffer_size 0
is_buffer false
}
# dump inode block
ioctl 56745 {
buffer_size 0
write_buffer_size 0
is_buffer false
}
}
# NetFS
file_system netfs {
# NET_FS_IOCTL_ADD_SERVER
ioctl 11000 {
buffer_size 256
write_buffer_size 0
is_buffer true
}
# NET_FS_IOCTL_REMOVE_SERVER
ioctl 11001 {
buffer_size 256
write_buffer_size 0
is_buffer true
}
}