* 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:
parent
c8530759dd
commit
00405f2286
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
1097
src/system/kernel/fs/overlay.cpp
Normal file
1097
src/system/kernel/fs/overlay.cpp
Normal file
File diff suppressed because it is too large
Load Diff
16
src/system/kernel/fs/overlay.h
Normal file
16
src/system/kernel/fs/overlay.h
Normal 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
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user