* Add an additional argument to get_vnode() that gets the fs_vnode_ops of the

node. That is needed for a layered filesystem to be able to construct a full
  fs_vnode out of a volume/inode pair.
* Adapt places where get_vnode is used. Sadly this is a C API and we can't just
  use a default NULL for that argument.
* Introduce a flag B_VNODE_WANTS_OVERLAY_SUB_NODE that can be returned in the
  flags field of a fs get_vnode call. A filesystem can use this flag to indicate
  that it doesn't support the full set of fs features (attributes, write support)
  and it'd like to have unsupported calls emulated by an overlay sub node.
* Add a perliminary overlay filesystem that emulates file attributes using files
  on a filesystem where attributes aren't supported. It does currently only
  support reading attributes/attribute directories though. All other calls are
  just passed through to the super filesystem.
* Adjust places where a HAS_FS_CALL() is taken as a guarantee that the operation
  is supported. For the overlay filesystem we may later return a B_UNSUPPORTED,
  so make sure that in that case proper fallback options are taken.
* Make the iso9660 filesystem request overlay sub nodes. This can be fine tuned
  later to only trigger where there are features on a CD that need emulation
  at all.

If you happened to know the attribute file format and location you could build
an iso with read-only attribute support now. Note that this won't be enough to
get a bootable iso-only image as the query and index support is yet missing.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29177 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2009-02-09 23:06:31 +00:00
parent c8530759dd
commit 00405f2286
21 changed files with 1186 additions and 46 deletions

View File

@ -43,6 +43,7 @@ struct file_io_vec {
// flags for publish_vnode() and fs_volume_ops::get_vnode() // flags for publish_vnode() and fs_volume_ops::get_vnode()
#define B_VNODE_PUBLISH_REMOVED 0x01 #define B_VNODE_PUBLISH_REMOVED 0x01
#define B_VNODE_DONT_CREATE_SPECIAL_SUB_NODE 0x02 #define B_VNODE_DONT_CREATE_SPECIAL_SUB_NODE 0x02
#define B_VNODE_WANTS_OVERLAY_SUB_NODE 0x04
#ifdef __cplusplus #ifdef __cplusplus
@ -307,7 +308,7 @@ extern status_t publish_vnode(fs_volume *volume, ino_t vnodeID,
void *privateNode, fs_vnode_ops *ops, int type, void *privateNode, fs_vnode_ops *ops, int type,
uint32 flags); uint32 flags);
extern status_t get_vnode(fs_volume *volume, ino_t vnodeID, extern status_t get_vnode(fs_volume *volume, ino_t vnodeID,
void **_privateNode); void **_privateNode, fs_vnode_ops **_vnodeOps);
extern status_t put_vnode(fs_volume *volume, ino_t vnodeID); extern status_t put_vnode(fs_volume *volume, ino_t vnodeID);
extern status_t acquire_vnode(fs_volume *volume, ino_t vnodeID); extern status_t acquire_vnode(fs_volume *volume, ino_t vnodeID);
extern status_t remove_vnode(fs_volume *volume, ino_t vnodeID); extern status_t remove_vnode(fs_volume *volume, ino_t vnodeID);

View File

@ -344,7 +344,8 @@ extern fssh_status_t fssh_publish_vnode(fssh_fs_volume *volume,
fssh_vnode_id vnodeID, void *privateNode, fssh_vnode_id vnodeID, void *privateNode,
fssh_fs_vnode_ops *ops, int type, uint32_t flags); fssh_fs_vnode_ops *ops, int type, uint32_t flags);
extern fssh_status_t fssh_get_vnode(fssh_fs_volume *volume, extern fssh_status_t fssh_get_vnode(fssh_fs_volume *volume,
fssh_vnode_id vnodeID, void **_privateNode); fssh_vnode_id vnodeID, void **_privateNode,
fssh_fs_vnode_ops **_vnodeOps);
extern fssh_status_t fssh_put_vnode(fssh_fs_volume *volume, extern fssh_status_t fssh_put_vnode(fssh_fs_volume *volume,
fssh_vnode_id vnodeID); fssh_vnode_id vnodeID);
extern fssh_status_t fssh_acquire_vnode(fssh_fs_volume *volume, extern fssh_status_t fssh_acquire_vnode(fssh_fs_volume *volume,

View File

@ -2701,7 +2701,7 @@ AttributeIterator::GetNext(char* name, size_t* _length, uint32* _type,
// if you haven't yet access to the attributes directory, get it // if you haven't yet access to the attributes directory, get it
if (fAttributes == NULL) { if (fAttributes == NULL) {
if (get_vnode(volume->FSVolume(), volume->ToVnode(fInode->Attributes()), if (get_vnode(volume->FSVolume(), volume->ToVnode(fInode->Attributes()),
(void**)&fAttributes) != B_OK) { (void**)&fAttributes, NULL) != B_OK) {
FATAL(("get_vnode() failed in AttributeIterator::GetNext(ino_t" FATAL(("get_vnode() failed in AttributeIterator::GetNext(ino_t"
" = %Ld,name = \"%s\")\n", fInode->ID(), name)); " = %Ld,name = \"%s\")\n", fInode->ID(), name));
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;

View File

@ -354,7 +354,8 @@ public:
{ {
Unset(); Unset();
return fStatus = get_vnode(volume->FSVolume(), id, (void**)&fInode); return fStatus = get_vnode(volume->FSVolume(), id, (void**)&fInode,
NULL);
} }
status_t SetTo(Volume* volume, block_run run) status_t SetTo(Volume* volume, block_run run)

View File

@ -556,7 +556,7 @@ bfs_lookup(fs_volume* _volume, fs_vnode* _directory, const char* file,
locker.Unlock(); locker.Unlock();
Inode* inode; Inode* inode;
status = get_vnode(volume->FSVolume(), *_vnodeID, (void**)&inode); status = get_vnode(volume->FSVolume(), *_vnodeID, (void**)&inode, NULL);
if (status != B_OK) { if (status != B_OK) {
REPORT_ERROR(status); REPORT_ERROR(status);
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;

View File

@ -1493,7 +1493,7 @@ cdda_lookup(fs_volume* _volume, fs_vnode* _dir, const char* name, ino_t* _id)
if (inode == NULL) if (inode == NULL)
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
status = get_vnode(volume->FSVolume(), inode->ID(), NULL); status = get_vnode(volume->FSVolume(), inode->ID(), NULL, NULL);
if (status < B_OK) if (status < B_OK)
return status; return status;

View File

@ -310,7 +310,7 @@ Volume::Mount(const char* deviceName, uint32 flags)
if ((fBlockCache = opener.InitCache(NumBlocks(), fBlockSize)) == NULL) if ((fBlockCache = opener.InitCache(NumBlocks(), fBlockSize)) == NULL)
return B_ERROR; return B_ERROR;
status = get_vnode(fFSVolume, EXT2_ROOT_NODE, (void**)&fRootNode); status = get_vnode(fFSVolume, EXT2_ROOT_NODE, (void**)&fRootNode, NULL);
if (status != B_OK) { if (status != B_OK) {
TRACE("could not create root node: get_vnode() failed!\n"); TRACE("could not create root node: get_vnode() failed!\n");
return status; return status;

View File

@ -319,7 +319,7 @@ ext2_lookup(fs_volume* _volume, fs_vnode* _directory, const char* name,
break; break;
} }
return get_vnode(volume->FSVolume(), *_vnodeID, NULL); return get_vnode(volume->FSVolume(), *_vnodeID, NULL, NULL);
} }

View File

@ -433,7 +433,7 @@ findfile(nspace *vol, vnode *dir, const char *file, ino_t *vnid,
if (vnid) if (vnid)
*vnid = found_vnid; *vnid = found_vnid;
if (node) if (node)
result = get_vnode(vol->volume, found_vnid, (void **)node); result = get_vnode(vol->volume, found_vnid, (void **)node, NULL);
result = B_OK; result = B_OK;
} else { } else {
result = ENOENT; result = ENOENT;

View File

@ -890,7 +890,7 @@ dosfs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode,
*vnid = dummy.vnid; *vnid = dummy.vnid;
dummy.magic = ~VNODE_MAGIC; dummy.magic = ~VNODE_MAGIC;
result = get_vnode(_vol, *vnid, (void **)&file); result = get_vnode(_vol, *vnid, (void **)&file, NULL);
if (result < B_OK) { if (result < B_OK) {
if (vol->fs_flags & FS_FLAGS_OP_SYNC) if (vol->fs_flags & FS_FLAGS_OP_SYNC)
_dosfs_sync(vol); _dosfs_sync(vol);
@ -1155,7 +1155,7 @@ dosfs_rename(fs_volume *_vol, fs_vnode *_odir, const char *oldname,
if (vnid == vol->root_vnode.vnid) if (vnid == vol->root_vnode.vnid)
break; break;
result = get_vnode(_vol, vnid, (void **)&dir); result = get_vnode(_vol, vnid, (void **)&dir, NULL);
if (result < B_OK) if (result < B_OK)
goto bi1; goto bi1;
parent = dir->dir_vnid; parent = dir->dir_vnid;

View File

@ -224,12 +224,12 @@ fs_walk(fs_volume *_vol, fs_vnode *_base, const char *file, ino_t *_vnodeID)
// base directory // base directory
TRACE(("fs_walk - found \".\" file.\n")); TRACE(("fs_walk - found \".\" file.\n"));
*_vnodeID = baseNode->id; *_vnodeID = baseNode->id;
return get_vnode(_vol, *_vnodeID, (void **)&newNode); return get_vnode(_vol, *_vnodeID, NULL, NULL);
} else if (strcmp(file, "..") == 0) { } else if (strcmp(file, "..") == 0) {
// parent directory // parent directory
TRACE(("fs_walk - found \"..\" file.\n")); TRACE(("fs_walk - found \"..\" file.\n"));
*_vnodeID = baseNode->parID; *_vnodeID = baseNode->parID;
return get_vnode(_vol, *_vnodeID, (void **)&newNode); return get_vnode(_vol, *_vnodeID, NULL, NULL);
} }
// look up file in the directory // look up file in the directory
@ -272,7 +272,7 @@ fs_walk(fs_volume *_vol, fs_vnode *_base, const char *file, ino_t *_vnodeID)
TRACE(("fs_walk - New vnode id is %Ld\n", *_vnodeID)); TRACE(("fs_walk - New vnode id is %Ld\n", *_vnodeID));
result = get_vnode(_vol, *_vnodeID, result = get_vnode(_vol, *_vnodeID,
(void **)&newNode); (void **)&newNode, NULL);
if (result == B_OK) { if (result == B_OK) {
newNode->parID = baseNode->id; newNode->parID = baseNode->id;
done = true; done = true;
@ -349,7 +349,7 @@ fs_read_vnode(fs_volume *_vol, ino_t vnodeID, fs_vnode *_node,
_node->private_node = newNode; _node->private_node = newNode;
_node->ops = &gISO9660VnodeOps; _node->ops = &gISO9660VnodeOps;
*_type = newNode->attr.stat[FS_DATA_FORMAT].st_mode & ~(S_IWUSR | S_IWGRP | S_IWOTH); *_type = newNode->attr.stat[FS_DATA_FORMAT].st_mode & ~(S_IWUSR | S_IWGRP | S_IWOTH);
*_flags = 0; *_flags = B_VNODE_WANTS_OVERLAY_SUB_NODE;
if ((newNode->flags & ISO_ISDIR) == 0) { if ((newNode->flags & ISO_ISDIR) == 0) {
newNode->cache = file_cache_create(ns->id, vnodeID, newNode->cache = file_cache_create(ns->id, vnodeID,

View File

@ -898,7 +898,7 @@ fs_walk(fs_volume *_volume, fs_vnode *_base, const char *file, ino_t *vnid)
isLink=S_ISLNK(st.st_mode); isLink=S_ISLNK(st.st_mode);
} }
if ((result=get_vnode (_volume,*vnid,(void **)&dummy))<B_OK) if ((result=get_vnode (_volume,*vnid,(void **)&dummy,NULL))<B_OK)
return result; return result;
return B_OK; return B_OK;
@ -1755,7 +1755,7 @@ fs_create(fs_volume *_volume, fs_vnode *_dir, const char *name, int omode, int p
*vnid=st.st_ino; *vnid=st.st_ino;
if ((result=get_vnode(_volume,*vnid,&dummy))<B_OK) if ((result=get_vnode(_volume,*vnid,&dummy,NULL))<B_OK)
return result; return result;
if (S_ISDIR(st.st_mode)) if (S_ISDIR(st.st_mode))
@ -1901,7 +1901,7 @@ fs_unlink(fs_volume *_volume, fs_vnode *_dir, const char *name)
insert_node (ns,newNode); insert_node (ns,newNode);
if ((result=get_vnode(_volume,st.st_ino,(void **)&dummy))<B_OK) if ((result=get_vnode(_volume,st.st_ino,(void **)&dummy,NULL))<B_OK)
{ {
XDRInPacketDestroy (&reply); XDRInPacketDestroy (&reply);
XDROutPacketDestroy (&call); XDROutPacketDestroy (&call);
@ -2195,7 +2195,7 @@ fs_rmdir(fs_volume *_volume, fs_vnode *_dir, const char *name)
insert_node (ns,newNode); insert_node (ns,newNode);
if ((result=get_vnode(_volume,st.st_ino,(void **)&dummy))<B_OK) if ((result=get_vnode(_volume,st.st_ino,(void **)&dummy,NULL))<B_OK)
{ {
XDRInPacketDestroy(&reply); XDRInPacketDestroy(&reply);
XDROutPacketDestroy(&call); XDROutPacketDestroy(&call);
@ -2341,7 +2341,7 @@ fs_symlink(fs_volume *_volume, fs_vnode *_dir, const char *name, const char *pat
if (result==B_OK) if (result==B_OK)
{ {
void *dummy; void *dummy;
if ((result=get_vnode(_volume,st.st_ino,&dummy))<B_OK) if ((result=get_vnode(_volume,st.st_ino,&dummy,NULL))<B_OK)
return result; return result;
XDRInPacketDestroy (&reply); XDRInPacketDestroy (&reply);

View File

@ -294,7 +294,7 @@ Volume::GetKeyOffsetForName(const char *name, int len, uint64 *result)
status_t status_t
Volume::GetVNode(ino_t id, VNode **node) Volume::GetVNode(ino_t id, VNode **node)
{ {
return get_vnode(GetFSVolume(), id, (void**)node); return get_vnode(GetFSVolume(), id, (void**)node, NULL);
} }
// PutVNode // PutVNode

View File

@ -407,7 +407,8 @@ add_partition(struct devfs* fs, struct devfs_vnode* device, const char* name,
// increase reference count of raw device - // increase reference count of raw device -
// the partition device really needs it // the partition device really needs it
status = get_vnode(fs->volume, device->id, (void**)&partition->raw_device); status = get_vnode(fs->volume, device->id, (void**)&partition->raw_device,
NULL);
if (status < B_OK) if (status < B_OK)
goto err1; goto err1;
@ -937,7 +938,7 @@ devfs_lookup(fs_volume *_volume, fs_vnode *_dir, const char *name, ino_t *_id)
{ {
struct devfs *fs = (struct devfs *)_volume->private_volume; struct devfs *fs = (struct devfs *)_volume->private_volume;
struct devfs_vnode *dir = (struct devfs_vnode *)_dir->private_node; struct devfs_vnode *dir = (struct devfs_vnode *)_dir->private_node;
struct devfs_vnode *vnode, *vdummy; struct devfs_vnode *vnode;
status_t status; status_t status;
TRACE(("devfs_lookup: entry dir %p, name '%s'\n", dir, name)); TRACE(("devfs_lookup: entry dir %p, name '%s'\n", dir, name));
@ -958,7 +959,7 @@ devfs_lookup(fs_volume *_volume, fs_vnode *_dir, const char *name, ino_t *_id)
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
} }
status = get_vnode(fs->volume, vnode->id, (void**)&vdummy); status = get_vnode(fs->volume, vnode->id, NULL, NULL);
if (status < B_OK) if (status < B_OK)
return status; return status;
@ -1062,7 +1063,7 @@ devfs_create(fs_volume* _volume, fs_vnode* _dir, const char* name, int openMode,
if (openMode & O_EXCL) if (openMode & O_EXCL)
return B_FILE_EXISTS; return B_FILE_EXISTS;
status = get_vnode(fs->volume, vnode->id, NULL); status = get_vnode(fs->volume, vnode->id, NULL, NULL);
if (status < B_OK) if (status < B_OK)
return status; return status;
@ -2091,7 +2092,7 @@ devfs_unpublish_device(BaseDevice* device, bool disconnect)
{ {
devfs_vnode* node; devfs_vnode* node;
status_t status = get_vnode(sDeviceFileSystem->volume, device->ID(), status_t status = get_vnode(sDeviceFileSystem->volume, device->ID(),
(void**)&node); (void**)&node, NULL);
if (status != B_OK) if (status != B_OK)
return status; return status;

View File

@ -12,6 +12,7 @@ KernelMergeObject kernel_fs.o :
fifo.cpp fifo.cpp
KPath.cpp KPath.cpp
node_monitor.cpp node_monitor.cpp
overlay.cpp
rootfs.cpp rootfs.cpp
socket.cpp socket.cpp
vfs.cpp vfs.cpp

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
/*
* Copyright 2009, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#ifndef _VFS_OVERLAY_H
#define _VFS_OVERLAY_H
#include <fs_interface.h>
status_t create_overlay_vnode(fs_volume *superVolume, fs_vnode *vnode);
#endif // _VFS_OVERLAY_H

View File

@ -284,8 +284,7 @@ remove_node(struct rootfs *fs, struct rootfs_vnode *directory,
{ {
// schedule this vnode to be removed when it's ref goes to zero // schedule this vnode to be removed when it's ref goes to zero
void* dummy; bool gotNode = (get_vnode(fs->volume, vnode->id, NULL, NULL) == B_OK);
bool gotNode = (get_vnode(fs->volume, vnode->id, &dummy) == B_OK);
status_t status = B_OK; status_t status = B_OK;
if (gotNode) if (gotNode)
@ -432,7 +431,7 @@ rootfs_lookup(fs_volume *_volume, fs_vnode *_dir, const char *name, ino_t *_id)
{ {
struct rootfs *fs = (struct rootfs *)_volume->private_volume; struct rootfs *fs = (struct rootfs *)_volume->private_volume;
struct rootfs_vnode *dir = (struct rootfs_vnode *)_dir->private_node; struct rootfs_vnode *dir = (struct rootfs_vnode *)_dir->private_node;
struct rootfs_vnode *vnode,*vdummy; struct rootfs_vnode *vnode;
status_t status; status_t status;
TRACE(("rootfs_lookup: entry dir %p, name '%s'\n", dir, name)); TRACE(("rootfs_lookup: entry dir %p, name '%s'\n", dir, name));
@ -448,7 +447,7 @@ rootfs_lookup(fs_volume *_volume, fs_vnode *_dir, const char *name, ino_t *_id)
goto err; goto err;
} }
status = get_vnode(fs->volume, vnode->id, (void**)&vdummy); status = get_vnode(fs->volume, vnode->id, NULL, NULL);
if (status < B_OK) if (status < B_OK)
goto err; goto err;

View File

@ -54,6 +54,7 @@
#include "fifo.h" #include "fifo.h"
#include "io_requests.h" #include "io_requests.h"
#include "overlay.h"
//#define TRACE_VFS //#define TRACE_VFS
@ -1180,6 +1181,9 @@ create_special_sub_node(struct vnode* vnode, uint32 flags)
if (S_ISFIFO(vnode->type)) if (S_ISFIFO(vnode->type))
return create_fifo_vnode(vnode->mount->volume, vnode); return create_fifo_vnode(vnode->mount->volume, vnode);
if ((flags & B_VNODE_WANTS_OVERLAY_SUB_NODE) != 0)
return create_overlay_vnode(vnode->mount->volume, vnode);
return B_BAD_VALUE; return B_BAD_VALUE;
} }
@ -1253,7 +1257,8 @@ restart:
bool publishSpecialSubNode = false; bool publishSpecialSubNode = false;
if (gotNode) { if (gotNode) {
vnode->type = type; vnode->type = type;
publishSpecialSubNode = is_special_node_type(type) publishSpecialSubNode = (is_special_node_type(type)
|| (flags & B_VNODE_WANTS_OVERLAY_SUB_NODE) != 0)
&& (flags & B_VNODE_DONT_CREATE_SPECIAL_SUB_NODE) == 0; && (flags & B_VNODE_DONT_CREATE_SPECIAL_SUB_NODE) == 0;
} }
@ -2485,8 +2490,9 @@ get_vnode_name(struct vnode *vnode, struct vnode *parent, struct dirent *buffer,
if (HAS_FS_CALL(vnode, get_vnode_name)) { if (HAS_FS_CALL(vnode, get_vnode_name)) {
// The FS supports getting the name of a vnode. // The FS supports getting the name of a vnode.
return FS_CALL(vnode, get_vnode_name, buffer->d_name, if (FS_CALL(vnode, get_vnode_name, buffer->d_name,
(char*)buffer + bufferSize - buffer->d_name); (char*)buffer + bufferSize - buffer->d_name) == B_OK)
return B_OK;
} }
// The FS doesn't support getting the name of a vnode. So we search the // The FS doesn't support getting the name of a vnode. So we search the
@ -3584,7 +3590,8 @@ publish_vnode(fs_volume *volume, ino_t vnodeID, void *privateNode,
extern "C" status_t extern "C" status_t
get_vnode(fs_volume *volume, ino_t vnodeID, void **_fsNode) get_vnode(fs_volume *volume, ino_t vnodeID, void **_privateNode,
fs_vnode_ops **_vnodeOps)
{ {
struct vnode *vnode; struct vnode *vnode;
@ -3608,10 +3615,16 @@ get_vnode(fs_volume *volume, ino_t vnodeID, void **_fsNode)
return status; return status;
} }
if (_fsNode != NULL) if (_privateNode != NULL)
*_fsNode = resolvedNode.private_node; *_privateNode = resolvedNode.private_node;
} else if (_fsNode != NULL) if (_vnodeOps != NULL)
*_fsNode = vnode->private_node; *_vnodeOps = resolvedNode.ops;
} else {
if (_privateNode != NULL)
*_privateNode = vnode->private_node;
if (_vnodeOps != NULL)
*_vnodeOps = vnode->ops;
}
return B_OK; return B_OK;
} }
@ -4005,7 +4018,7 @@ vfs_get_fs_node_from_path(fs_volume *volume, const char *path, bool kernel,
} }
// Use get_vnode() to resolve the cookie for the right layer. // Use get_vnode() to resolve the cookie for the right layer.
status = get_vnode(volume, vnode->id, _node); status = get_vnode(volume, vnode->id, _node, NULL);
put_vnode(vnode); put_vnode(vnode);
return status; return status;

View File

@ -401,14 +401,16 @@ synchronous_io(io_request* request, DoIO& io)
status_t status_t
vfs_vnode_io(struct vnode* vnode, void* cookie, io_request* request) vfs_vnode_io(struct vnode* vnode, void* cookie, io_request* request)
{ {
if (!HAS_FS_CALL(vnode, io)) { status_t result = B_ERROR;
if (!HAS_FS_CALL(vnode, io)
|| (result = FS_CALL(vnode, io, cookie, request)) == B_UNSUPPORTED) {
// no io() call -- fall back to synchronous I/O // no io() call -- fall back to synchronous I/O
IOBuffer* buffer = request->Buffer(); IOBuffer* buffer = request->Buffer();
VnodeIO io(request->IsWrite(), buffer->IsPhysical(), vnode, cookie); VnodeIO io(request->IsWrite(), buffer->IsPhysical(), vnode, cookie);
return synchronous_io(request, io); return synchronous_io(request, io);
} }
return FS_CALL(vnode, io, cookie, request); return result;
} }

View File

@ -1985,7 +1985,8 @@ fssh_publish_vnode(fssh_fs_volume *volume, fssh_vnode_id vnodeID,
extern "C" fssh_status_t extern "C" fssh_status_t
fssh_get_vnode(fssh_fs_volume *volume, fssh_vnode_id vnodeID, void **fsNode) fssh_get_vnode(fssh_fs_volume *volume, fssh_vnode_id vnodeID,
void **privateNode, fssh_fs_vnode_ops **vnodeOps)
{ {
struct vnode *vnode; struct vnode *vnode;
@ -2009,9 +2010,16 @@ fssh_get_vnode(fssh_fs_volume *volume, fssh_vnode_id vnodeID, void **fsNode)
return status; return status;
} }
*fsNode = resolvedNode.private_node; if (privateNode != NULL)
} else *privateNode = resolvedNode.private_node;
*fsNode = vnode->private_node; if (vnodeOps != NULL)
*vnodeOps = resolvedNode.ops;
} else {
if (privateNode != NULL)
*privateNode = vnode->private_node;
if (vnodeOps != NULL)
*vnodeOps = vnode->ops;
}
return FSSH_B_OK; return FSSH_B_OK;
} }
@ -2443,7 +2451,7 @@ vfs_get_fs_node_from_path(fssh_fs_volume *volume, const char *path, bool kernel,
} }
// Use get_vnode() to resolve the cookie for the right layer. // Use get_vnode() to resolve the cookie for the right layer.
status = ::fssh_get_vnode(volume, vnode->id, _node); status = ::fssh_get_vnode(volume, vnode->id, _node, NULL);
put_vnode(vnode); put_vnode(vnode);
return FSSH_B_OK; return FSSH_B_OK;