Add volume ops to the overlay filesystem and prepare it to be a standalone module.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29200 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2009-02-14 20:32:10 +00:00
parent a26c243920
commit 3c1b330b3b
2 changed files with 288 additions and 38 deletions

View File

@ -12,6 +12,8 @@
#include <dirent.h>
#include <fs_info.h>
#include <debug.h>
#include <KernelExport.h>
#include <NodeMonitor.h>
@ -22,9 +24,11 @@
//#define TRACE_OVERLAY
#ifdef TRACE_OVERLAY
#define TRACE(x...) dprintf("overlay: " x)
#define TRACE_VOLUME(x...) dprintf("overlay: " x)
#define TRACE_ALWAYS(x...) dprintf("overlay: " x)
#else
#define TRACE(x...) /* nothing */
#define TRACE_VOLUME(x...) /* nothing */
#define TRACE_ALWAYS(x...) dprintf("overlay: " x)
#endif
@ -43,12 +47,13 @@ public:
status_t InitCheck();
fs_volume * SuperVolume() { return fSuperVolume; }
fs_vnode * SuperVnode() { return &fSuperVnode; }
AttributeFile * GetAttributeFile();
private:
fs_volume fSuperVolume;
fs_volume * fSuperVolume;
fs_vnode fSuperVnode;
AttributeFile * fAttributeFile;
};
@ -129,7 +134,7 @@ private:
OverlayInode::OverlayInode(fs_volume *superVolume, fs_vnode *superVnode)
: fSuperVolume(*superVolume),
: fSuperVolume(superVolume),
fSuperVnode(*superVnode),
fAttributeFile(NULL)
{
@ -155,7 +160,7 @@ AttributeFile *
OverlayInode::GetAttributeFile()
{
if (fAttributeFile == NULL) {
fAttributeFile = new(std::nothrow) AttributeFile(&fSuperVolume,
fAttributeFile = new(std::nothrow) AttributeFile(fSuperVolume,
&fSuperVnode);
if (fAttributeFile == NULL) {
TRACE_ALWAYS("no memory to allocate attribute file\n");
@ -472,7 +477,15 @@ AttributeEntry::ReadStat(struct stat *stat)
}
// #pragma mark -
// #pragma mark - VNode ops
#define OVERLAY_CALL(op, params...) \
TRACE("relaying op: " #op "\n"); \
OverlayInode *node = (OverlayInode *)vnode->private_node; \
fs_vnode *superVnode = node->SuperVnode(); \
if (superVnode->ops->op != NULL) \
return superVnode->ops->op(volume->super_volume, superVnode, params);
static status_t
@ -482,8 +495,10 @@ overlay_put_vnode(fs_volume *volume, fs_vnode *vnode, bool reenter)
fs_vnode *superVnode = node->SuperVnode();
status_t result = B_OK;
if (superVnode->ops->put_vnode != NULL)
result = superVnode->ops->put_vnode(volume, superVnode, reenter);
if (superVnode->ops->put_vnode != NULL) {
result = superVnode->ops->put_vnode(volume->super_volume, superVnode,
reenter);
}
delete node;
return result;
@ -497,8 +512,10 @@ overlay_remove_vnode(fs_volume *volume, fs_vnode *vnode, bool reenter)
fs_vnode *superVnode = node->SuperVnode();
status_t result = B_OK;
if (superVnode->ops->remove_vnode != NULL)
result = superVnode->ops->remove_vnode(volume, superVnode, reenter);
if (superVnode->ops->remove_vnode != NULL) {
result = superVnode->ops->remove_vnode(volume->super_volume, superVnode,
reenter);
}
delete node;
return result;
@ -513,8 +530,8 @@ overlay_get_super_vnode(fs_volume *volume, fs_vnode *vnode,
fs_vnode *superVnode = node->SuperVnode();
if (superVnode->ops->get_super_vnode != NULL) {
return superVnode->ops->get_super_vnode(volume, superVnode, superVolume,
_superVnode);
return superVnode->ops->get_super_vnode(volume->super_volume,
superVnode, superVolume, _superVnode);
}
*_superVnode = *superVnode;
@ -522,17 +539,6 @@ overlay_get_super_vnode(fs_volume *volume, fs_vnode *vnode,
}
// #pragma mark -
#define OVERLAY_CALL(op, params...) \
TRACE("relaying op: " #op "\n"); \
OverlayInode *node = (OverlayInode *)vnode->private_node; \
fs_vnode *superVnode = node->SuperVnode(); \
if (superVnode->ops->op != NULL) \
return superVnode->ops->op(volume, superVnode, params);
static status_t
overlay_lookup(fs_volume *volume, fs_vnode *vnode, const char *name, ino_t *id)
{
@ -648,7 +654,7 @@ overlay_fsync(fs_volume *volume, fs_vnode *vnode)
fs_vnode *superVnode = node->SuperVnode();
if (superVnode->ops->fsync != NULL)
return superVnode->ops->fsync(volume, superVnode);
return superVnode->ops->fsync(volume->super_volume, superVnode);
return B_OK;
}
@ -819,18 +825,19 @@ static status_t
overlay_read_dir(fs_volume *volume, fs_vnode *vnode, void *cookie,
struct dirent *buffer, size_t bufferSize, uint32 *num)
{
TRACE("relaying op: read_dir\n");
OverlayInode *node = (OverlayInode *)vnode->private_node;
fs_vnode *superVnode = node->SuperVnode();
if (superVnode->ops->read_dir != NULL) {
status_t result = superVnode->ops->read_dir(volume, superVnode, cookie,
buffer, bufferSize, num);
status_t result = superVnode->ops->read_dir(volume->super_volume,
superVnode, cookie, buffer, bufferSize, num);
// TODO: handle multiple records
if (result == B_OK && strcmp(buffer->d_name,
if (result == B_OK && *num == 1 && strcmp(buffer->d_name,
ATTRIBUTE_OVERLAY_ATTRIBUTE_DIR_NAME) == 0) {
// skip over the attribute directory
return superVnode->ops->read_dir(volume, superVnode, cookie,
buffer, bufferSize, num);
return superVnode->ops->read_dir(volume->super_volume, superVnode,
cookie, buffer, bufferSize, num);
}
return result;
@ -1005,9 +1012,6 @@ overlay_create_special_node(fs_volume *volume, fs_vnode *vnode,
}
// #pragma mark -
static fs_vnode_ops sOverlayVnodeOps = {
&overlay_lookup,
&overlay_get_vnode_name,
@ -1086,18 +1090,209 @@ static fs_vnode_ops sOverlayVnodeOps = {
};
} // namespace _overlay
using namespace overlay;
// #pragma mark - Volume Ops
// #pragma mark -
#define OVERLAY_VOLUME_CALL(op, params...) \
TRACE_VOLUME("relaying volume op: " #op "\n"); \
if (volume->super_volume->ops->op != NULL) \
return volume->super_volume->ops->op(volume->super_volume, params);
status_t
create_overlay_vnode(fs_volume *superVolume, fs_vnode *vnode)
static status_t
overlay_unmount(fs_volume *volume)
{
OverlayInode *node = new(std::nothrow) OverlayInode(superVolume, vnode);
TRACE_VOLUME("relaying volume op: unmount\n");
if (volume->super_volume->ops->unmount != NULL)
return volume->super_volume->ops->unmount(volume->super_volume);
return B_UNSUPPORTED;
}
static status_t
overlay_read_fs_info(fs_volume *volume, struct fs_info *info)
{
TRACE_VOLUME("relaying volume op: read_fs_info\n");
status_t result = B_UNSUPPORTED;
if (volume->super_volume->ops->read_fs_info != NULL) {
result = volume->super_volume->ops->read_fs_info(volume->super_volume,
info);
if (result != B_OK)
return result;
info->flags |= B_FS_HAS_MIME | B_FS_HAS_ATTR | B_FS_HAS_QUERY;
return B_OK;
}
return B_UNSUPPORTED;
}
static status_t
overlay_write_fs_info(fs_volume *volume, const struct fs_info *info,
uint32 mask)
{
OVERLAY_VOLUME_CALL(write_fs_info, info, mask)
return B_UNSUPPORTED;
}
static status_t
overlay_sync(fs_volume *volume)
{
TRACE_VOLUME("relaying volume op: sync\n");
if (volume->super_volume->ops->sync != NULL)
return volume->super_volume->ops->sync(volume->super_volume);
return B_UNSUPPORTED;
}
static status_t
overlay_get_vnode(fs_volume *volume, ino_t id, fs_vnode *vnode, int *_type,
uint32 *_flags, bool reenter)
{
TRACE_VOLUME("relaying volume op: get_vnode\n");
if (volume->super_volume->ops->get_vnode != NULL) {
status_t status = volume->super_volume->ops->get_vnode(
volume->super_volume, id, vnode, _type, _flags, reenter);
if (status != B_OK)
return status;
OverlayInode *node = new(std::nothrow) OverlayInode(
volume->super_volume, vnode);
if (node == NULL) {
vnode->ops->put_vnode(volume->super_volume, vnode, reenter);
return B_NO_MEMORY;
}
status = node->InitCheck();
if (status != B_OK) {
delete node;
return status;
}
vnode->private_node = node;
vnode->ops = &sOverlayVnodeOps;
return B_OK;
}
return B_UNSUPPORTED;
}
static status_t
overlay_open_index_dir(fs_volume *volume, void **cookie)
{
OVERLAY_VOLUME_CALL(open_index_dir, cookie)
return B_UNSUPPORTED;
}
static status_t
overlay_close_index_dir(fs_volume *volume, void *cookie)
{
OVERLAY_VOLUME_CALL(close_index_dir, cookie)
return B_UNSUPPORTED;
}
static status_t
overlay_free_index_dir_cookie(fs_volume *volume, void *cookie)
{
OVERLAY_VOLUME_CALL(free_index_dir_cookie, cookie)
return B_UNSUPPORTED;
}
static status_t
overlay_read_index_dir(fs_volume *volume, void *cookie, struct dirent *buffer,
size_t bufferSize, uint32 *_num)
{
OVERLAY_VOLUME_CALL(read_index_dir, cookie, buffer, bufferSize, _num)
return B_UNSUPPORTED;
}
static status_t
overlay_rewind_index_dir(fs_volume *volume, void *cookie)
{
OVERLAY_VOLUME_CALL(rewind_index_dir, cookie)
return B_UNSUPPORTED;
}
static status_t
overlay_create_index(fs_volume *volume, const char *name, uint32 type,
uint32 flags)
{
OVERLAY_VOLUME_CALL(create_index, name, type, flags)
return B_UNSUPPORTED;
}
static status_t
overlay_remove_index(fs_volume *volume, const char *name)
{
OVERLAY_VOLUME_CALL(remove_index, name)
return B_UNSUPPORTED;
}
static status_t
overlay_read_index_stat(fs_volume *volume, const char *name, struct stat *stat)
{
OVERLAY_VOLUME_CALL(read_index_stat, name, stat)
return B_UNSUPPORTED;
}
static status_t
overlay_open_query(fs_volume *volume, const char *query, uint32 flags,
port_id port, uint32 token, void **_cookie)
{
OVERLAY_VOLUME_CALL(open_query, query, flags, port, token, _cookie)
return B_UNSUPPORTED;
}
static status_t
overlay_close_query(fs_volume *volume, void *cookie)
{
OVERLAY_VOLUME_CALL(close_query, cookie)
return B_UNSUPPORTED;
}
static status_t
overlay_free_query_cookie(fs_volume *volume, void *cookie)
{
OVERLAY_VOLUME_CALL(free_query_cookie, cookie)
return B_UNSUPPORTED;
}
static status_t
overlay_read_query(fs_volume *volume, void *cookie, struct dirent *buffer,
size_t bufferSize, uint32 *_num)
{
OVERLAY_VOLUME_CALL(read_query, cookie, buffer, bufferSize, _num)
return B_UNSUPPORTED;
}
static status_t
overlay_rewind_query(fs_volume *volume, void *cookie)
{
OVERLAY_VOLUME_CALL(rewind_query, cookie)
return B_UNSUPPORTED;
}
static status_t
overlay_create_sub_vnode(fs_volume *volume, ino_t id, fs_vnode *vnode)
{
OverlayInode *node = new(std::nothrow) OverlayInode(volume->super_volume,
vnode);
if (node == NULL)
return B_NO_MEMORY;
@ -1111,3 +1306,57 @@ create_overlay_vnode(fs_volume *superVolume, fs_vnode *vnode)
vnode->ops = &sOverlayVnodeOps;
return B_OK;
}
static status_t
overlay_delete_sub_vnode(fs_volume *volume, fs_vnode *vnode)
{
delete (OverlayInode *)vnode;
return B_OK;
}
static fs_volume_ops sOverlayVolumeOps = {
&overlay_unmount,
&overlay_read_fs_info,
&overlay_write_fs_info,
&overlay_sync,
&overlay_get_vnode,
&overlay_open_index_dir,
&overlay_close_index_dir,
&overlay_free_index_dir_cookie,
&overlay_read_index_dir,
&overlay_rewind_index_dir,
&overlay_create_index,
&overlay_remove_index,
&overlay_read_index_stat,
&overlay_open_query,
&overlay_close_query,
&overlay_free_query_cookie,
&overlay_read_query,
&overlay_rewind_query,
&overlay_create_sub_vnode,
&overlay_delete_sub_vnode
};
} // namespace _overlay
using namespace overlay;
// #pragma mark -
status_t
mount_overlay(fs_volume *volume, const char *device, uint32 flags,
const char *args, ino_t *rootID)
{
TRACE_VOLUME("mounting overlay\n");
volume->ops = &sOverlayVolumeOps;
return B_OK;
}

View File

@ -11,6 +11,7 @@
#include <fs_interface.h>
status_t create_overlay_vnode(fs_volume *superVolume, fs_vnode *vnode);
status_t mount_overlay(fs_volume *volume, const char *device, uint32 flags,
const char *args, ino_t *rootID);
#endif // _VFS_OVERLAY_H