From cc0bac7f51fdecf0ff21b55cf75c793177a7fc3b Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Fri, 2 Mar 2007 07:09:18 +0000 Subject: [PATCH] We fake read_stat() on the root node and read_fs_info() when the connection to the server is lost. The former is required by our mount command (it stat()s the mount point for some reason unknown to me). The latter is just to be a good citizen. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20300 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../userlandfs/kernel_add_on/Volume.cpp | 159 ++++++++++++------ .../userlandfs/kernel_add_on/Volume.h | 2 + 2 files changed, 109 insertions(+), 52 deletions(-) diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp index e5b786b53d..11049e4c56 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "AutoLocker.h" #include "Compatibility.h" @@ -178,7 +179,7 @@ PRINT(("new_vnode(%ld, %lld)\n", fID, vnid)); status_t Volume::PublishVNode(vnode_id vnid, fs_vnode node) { -PRINT(("publish_vnode(%ld, %lld)\n", fID, vnid)); +PRINT(("publish_vnode(%ld, %lld, %p)\n", fID, vnid, node)); status_t error = publish_vnode(fID, vnid, node); if (error == B_OK) { if (IsMounting()) { @@ -312,33 +313,23 @@ Volume::Sync() status_t Volume::ReadFSInfo(fs_info* info) { - // get a free port - RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); - if (!port) - return B_ERROR; - PortReleaser _(fFileSystem->GetPortPool(), port); + // When the connection to the userland server is lost, we serve + // read_fs_info() requests manually. + status_t error = _ReadFSInfo(info); + if (error != B_OK && fFileSystem->GetPortPool()->IsDisconnected()) { + WARN(("Volume::Lookup(): connection lost, emulating lookup `.'\n")); - // prepare the request - RequestAllocator allocator(port->GetPort()); - ReadFSInfoRequest* request; - status_t error = AllocateRequest(allocator, &request); - if (error != B_OK) - return error; + info->flags = B_FS_IS_PERSISTENT | B_FS_IS_READONLY; + info->block_size = 512; + info->io_size = 512; + info->total_blocks = 0; + info->free_blocks = 0; + strlcpy(info->volume_name, fFileSystem->GetName(), + sizeof(info->volume_name)); + strlcat(info->volume_name, ":disconnected", sizeof(info->volume_name)); - request->volume = fUserlandVolume; - - // send the request - KernelRequestHandler handler(this, READ_FS_INFO_REPLY); - ReadFSInfoReply* 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; - *info = reply->info; + error = B_OK; + } return error; } @@ -1041,34 +1032,29 @@ Volume::Access(fs_vnode node, int mode) status_t Volume::ReadStat(fs_vnode node, struct stat* st) { - // get a free port - RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); - if (!port) - return B_ERROR; - PortReleaser _(fFileSystem->GetPortPool(), port); + // When the connection to the userland server is lost, we serve + // read_stat(fRootNode) requests manually to allow clean unmounting. + status_t error = _ReadStat(node, st); + if (error != B_OK && fFileSystem->GetPortPool()->IsDisconnected() + && node == fRootNode) { + WARN(("Volume::ReadStat(): connection lost, emulating stat for the " + "root node\n")); - // prepare the request - RequestAllocator allocator(port->GetPort()); - ReadStatRequest* request; - status_t error = AllocateRequest(allocator, &request); - if (error != B_OK) - return error; + st->st_dev = fID; + st->st_ino = fRootID; + st->st_mode = ACCESSPERMS; + st->st_nlink = 1; + st->st_uid = 0; + st->st_gid = 0; + st->st_size = 512; + st->st_blksize = 512; + st->st_atime = 0; + st->st_mtime = 0; + st->st_ctime = 0; + st->st_crtime = 0; - request->volume = fUserlandVolume; - request->node = node; - - // send the request - KernelRequestHandler handler(this, READ_STAT_REPLY); - ReadStatReply* 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; - *st = reply->st; + error = B_OK; + } return error; } @@ -2570,6 +2556,40 @@ Volume::_Unmount() return error; } +// _ReadFSInfo +status_t +Volume::_ReadFSInfo(fs_info* info) +{ + // 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()); + ReadFSInfoRequest* request; + status_t error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->volume = fUserlandVolume; + + // send the request + KernelRequestHandler handler(this, READ_FS_INFO_REPLY); + ReadFSInfoReply* 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; + *info = reply->info; + return error; +} + // _Lookup status_t Volume::_Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, int* type) @@ -2645,6 +2665,41 @@ Volume::_WriteVNode(fs_vnode node, bool reenter) return error; } +// _ReadStat +status_t +Volume::_ReadStat(fs_vnode node, struct stat* st) +{ + // 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()); + ReadStatRequest* request; + status_t error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->volume = fUserlandVolume; + request->node = node; + + // send the request + KernelRequestHandler handler(this, READ_STAT_REPLY); + ReadStatReply* 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; + *st = reply->st; + return error; +} + // _Close status_t Volume::_Close(fs_vnode node, fs_cookie cookie) diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h index bc86cf6d3e..27bc3d75c2 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h @@ -174,9 +174,11 @@ private: status_t _Mount(const char* device, uint32 flags, const char* parameters); status_t _Unmount(); + status_t _ReadFSInfo(fs_info* info); status_t _Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, int* type); status_t _WriteVNode(fs_vnode node, bool reenter); + status_t _ReadStat(fs_vnode node, struct stat* st); status_t _Close(fs_vnode node, fs_cookie cookie); status_t _FreeCookie(fs_vnode node, fs_cookie cookie); status_t _CloseDir(fs_vnode node, fs_vnode cookie);