libvtreefs: API changes/extensions, part 2
- rename start_vtreefs to run_vtreefs, since the function returns upon termination these days; - add get_inode_slots function to retrieve the number of indexed slots; - add support for extra per-inode data for arbitrary storage. Change-Id: If2d365d7b478a1cecc9e20fb2b3e70c1a1cf7243
This commit is contained in:
parent
5eefd0fec2
commit
52be5c0afb
10 changed files with 111 additions and 19 deletions
|
@ -283,8 +283,8 @@ main(int argc, char **argv)
|
||||||
root_stat.size = 0;
|
root_stat.size = 0;
|
||||||
root_stat.dev = NO_DEV;
|
root_stat.dev = NO_DEV;
|
||||||
|
|
||||||
/* limit the number of indexed entries */
|
/* run VTreeFS */
|
||||||
start_vtreefs(&hooks, 30, &root_stat, 0, DATA_SIZE);
|
run_vtreefs(&hooks, 30, 0, &root_stat, 0, DATA_SIZE);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,8 +87,9 @@ int main(void)
|
||||||
stat.size = 0;
|
stat.size = 0;
|
||||||
stat.dev = NO_DEV;
|
stat.dev = NO_DEV;
|
||||||
|
|
||||||
/* Start VTreeFS. */
|
/* Run VTreeFS. */
|
||||||
start_vtreefs(&hooks, NR_INODES, &stat, NR_PROCS + NR_TASKS, BUF_SIZE);
|
run_vtreefs(&hooks, NR_INODES, 0, &stat, NR_PROCS + NR_TASKS,
|
||||||
|
BUF_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ struct fs_hooks {
|
||||||
|
|
||||||
extern struct inode *add_inode(struct inode *parent, const char *name,
|
extern struct inode *add_inode(struct inode *parent, const char *name,
|
||||||
index_t index, const struct inode_stat *stat,
|
index_t index, const struct inode_stat *stat,
|
||||||
index_t nr_indexed_entries, cbdata_t cbdata);
|
index_t nr_indexed_slots, cbdata_t cbdata);
|
||||||
extern void delete_inode(struct inode *inode);
|
extern void delete_inode(struct inode *inode);
|
||||||
|
|
||||||
extern struct inode *get_inode_by_name(const struct inode *parent,
|
extern struct inode *get_inode_by_name(const struct inode *parent,
|
||||||
|
@ -54,7 +54,9 @@ extern struct inode *get_inode_by_index(const struct inode *parent,
|
||||||
|
|
||||||
extern const char *get_inode_name(const struct inode *inode);
|
extern const char *get_inode_name(const struct inode *inode);
|
||||||
extern index_t get_inode_index(const struct inode *inode);
|
extern index_t get_inode_index(const struct inode *inode);
|
||||||
|
extern index_t get_inode_slots(const struct inode *inode);
|
||||||
extern cbdata_t get_inode_cbdata(const struct inode *inode);
|
extern cbdata_t get_inode_cbdata(const struct inode *inode);
|
||||||
|
extern void *get_inode_extra(const struct inode *inode);
|
||||||
|
|
||||||
extern struct inode *get_root_inode(void);
|
extern struct inode *get_root_inode(void);
|
||||||
extern struct inode *get_parent_inode(const struct inode *inode);
|
extern struct inode *get_parent_inode(const struct inode *inode);
|
||||||
|
@ -64,7 +66,8 @@ extern struct inode *get_next_inode(const struct inode *previous);
|
||||||
extern void get_inode_stat(const struct inode *inode, struct inode_stat *stat);
|
extern void get_inode_stat(const struct inode *inode, struct inode_stat *stat);
|
||||||
extern void set_inode_stat(struct inode *inode, struct inode_stat *stat);
|
extern void set_inode_stat(struct inode *inode, struct inode_stat *stat);
|
||||||
|
|
||||||
extern void start_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes,
|
extern void run_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes,
|
||||||
struct inode_stat *stat, index_t nr_indexed_entries, size_t buf_size);
|
size_t inode_extra, struct inode_stat *stat, index_t nr_indexed_slots,
|
||||||
|
size_t buf_size);
|
||||||
|
|
||||||
#endif /* _MINIX_VTREEFS_H */
|
#endif /* _MINIX_VTREEFS_H */
|
||||||
|
|
|
@ -7,6 +7,7 @@ CPPFLAGS+= -D_MINIX_SYSTEM
|
||||||
LIB= vtreefs
|
LIB= vtreefs
|
||||||
|
|
||||||
SRCS= \
|
SRCS= \
|
||||||
|
extra.c \
|
||||||
file.c \
|
file.c \
|
||||||
inode.c \
|
inode.c \
|
||||||
link.c \
|
link.c \
|
||||||
|
|
56
minix/lib/libvtreefs/extra.c
Normal file
56
minix/lib/libvtreefs/extra.c
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/* VTreeFS - extra.c - per-inode storage of arbitrary extra data */
|
||||||
|
|
||||||
|
#include "inc.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Right now, we maintain the extra data (if requested) as a separate buffer,
|
||||||
|
* so that we don't have to make the inode structure variable in size. Later,
|
||||||
|
* if for example the maximum node name length becomes a runtime setting, we
|
||||||
|
* could reconsider this.
|
||||||
|
*/
|
||||||
|
static char *extra_ptr = NULL;
|
||||||
|
static size_t extra_size = 0; /* per inode */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize memory to store extra data.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
init_extra(unsigned int nr_inodes, size_t inode_extra)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (extra_size == 0)
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
if ((extra_ptr = malloc(nr_inodes * inode_extra)) == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
extra_size = inode_extra;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the extra data for the given inode to zero.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clear_inode_extra(struct inode * node)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (extra_size == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(&extra_ptr[node->i_num * extra_size], 0, extra_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve a pointer to the extra data for the given inode.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
get_inode_extra(const struct inode * node)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (extra_size == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (void *)&extra_ptr[node->i_num * extra_size];
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ static LIST_HEAD(index_head, inode) *parent_index_head;
|
||||||
#define CHECK_INODE(node) \
|
#define CHECK_INODE(node) \
|
||||||
do { \
|
do { \
|
||||||
assert(node >= &inode[0] && node < &inode[nr_inodes]); \
|
assert(node >= &inode[0] && node < &inode[nr_inodes]); \
|
||||||
|
assert((unsigned int)(node - &inode[0]) == node->i_num);\
|
||||||
assert(node == &inode[0] || node->i_parent != NULL || \
|
assert(node == &inode[0] || node->i_parent != NULL || \
|
||||||
(node->i_flags & I_DELETED)); \
|
(node->i_flags & I_DELETED)); \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
@ -68,7 +69,7 @@ init_inodes(unsigned int inodes, struct inode_stat * stat,
|
||||||
/* Add free inodes to the unused/free list. Skip the root inode. */
|
/* Add free inodes to the unused/free list. Skip the root inode. */
|
||||||
for (i = 1; i < nr_inodes; i++) {
|
for (i = 1; i < nr_inodes; i++) {
|
||||||
node = &inode[i];
|
node = &inode[i];
|
||||||
|
node->i_num = i;
|
||||||
node->i_parent = NULL;
|
node->i_parent = NULL;
|
||||||
node->i_count = 0;
|
node->i_count = 0;
|
||||||
TAILQ_INIT(&node->i_children);
|
TAILQ_INIT(&node->i_children);
|
||||||
|
@ -83,6 +84,7 @@ init_inodes(unsigned int inodes, struct inode_stat * stat,
|
||||||
|
|
||||||
/* Initialize the root inode. */
|
/* Initialize the root inode. */
|
||||||
node = &inode[0];
|
node = &inode[0];
|
||||||
|
node->i_num = 0;
|
||||||
node->i_parent = NULL;
|
node->i_parent = NULL;
|
||||||
node->i_count = 0;
|
node->i_count = 0;
|
||||||
TAILQ_INIT(&node->i_children);
|
TAILQ_INIT(&node->i_children);
|
||||||
|
@ -114,15 +116,13 @@ cleanup_inodes(void)
|
||||||
static int
|
static int
|
||||||
parent_name_hash(const struct inode * parent, const char *name)
|
parent_name_hash(const struct inode * parent, const char *name)
|
||||||
{
|
{
|
||||||
unsigned int name_hash, parent_hash;
|
unsigned int name_hash;
|
||||||
|
|
||||||
/* The parent hash is a simple array entry; find its index. */
|
|
||||||
parent_hash = (unsigned int)(parent - &inode[0]);
|
|
||||||
|
|
||||||
/* Use the sdbm algorithm to hash the name. */
|
/* Use the sdbm algorithm to hash the name. */
|
||||||
name_hash = sdbm_hash(name, strlen(name));
|
name_hash = sdbm_hash(name, strlen(name));
|
||||||
|
|
||||||
return (parent_hash ^ name_hash) % nr_inodes;
|
/* The parent hash is a simple array entry. */
|
||||||
|
return (parent->i_num ^ name_hash) % nr_inodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -132,7 +132,7 @@ static int
|
||||||
parent_index_hash(const struct inode * parent, index_t index)
|
parent_index_hash(const struct inode * parent, index_t index)
|
||||||
{
|
{
|
||||||
|
|
||||||
return ((int)(parent - &inode[0]) ^ index) % nr_inodes;
|
return (parent->i_num ^ index) % nr_inodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -217,6 +217,9 @@ add_inode(struct inode * parent, const char * name, index_t index,
|
||||||
newnode->i_cbdata = cbdata;
|
newnode->i_cbdata = cbdata;
|
||||||
strlcpy(newnode->i_name, name, sizeof(newnode->i_name));
|
strlcpy(newnode->i_name, name, sizeof(newnode->i_name));
|
||||||
|
|
||||||
|
/* Clear the extra data for this inode, if present. */
|
||||||
|
clear_inode_extra(newnode);
|
||||||
|
|
||||||
/* Add the inode to the list of children inodes of the parent. */
|
/* Add the inode to the list of children inodes of the parent. */
|
||||||
TAILQ_INSERT_HEAD(&parent->i_children, newnode, i_siblings);
|
TAILQ_INSERT_HEAD(&parent->i_children, newnode, i_siblings);
|
||||||
|
|
||||||
|
@ -268,6 +271,18 @@ get_inode_index(const struct inode * node)
|
||||||
return node->i_index;
|
return node->i_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the number of indexed slots for the given (directory) inode.
|
||||||
|
*/
|
||||||
|
index_t
|
||||||
|
get_inode_slots(const struct inode * node)
|
||||||
|
{
|
||||||
|
|
||||||
|
CHECK_INODE(node);
|
||||||
|
|
||||||
|
return node->i_indexed;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the callback data associated with the given inode.
|
* Return the callback data associated with the given inode.
|
||||||
*/
|
*/
|
||||||
|
@ -342,7 +357,7 @@ get_inode_number(const struct inode * node)
|
||||||
|
|
||||||
CHECK_INODE(node);
|
CHECK_INODE(node);
|
||||||
|
|
||||||
return (int)(node - &inode[0]) + 1;
|
return node->i_num + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
* unused inodes.
|
* unused inodes.
|
||||||
*/
|
*/
|
||||||
struct inode {
|
struct inode {
|
||||||
|
/* Inode identity */
|
||||||
|
unsigned int i_num; /* index number into the inode array */
|
||||||
|
/* Note that the actual inode number (of type ino_t) is (i_num + 1). */
|
||||||
|
|
||||||
/* Inode metadata */
|
/* Inode metadata */
|
||||||
struct inode_stat i_stat; /* POSIX attributes */
|
struct inode_stat i_stat; /* POSIX attributes */
|
||||||
char i_name[PNAME_MAX + 1]; /* name of the inode in the parent */
|
char i_name[PNAME_MAX + 1]; /* name of the inode in the parent */
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#ifndef _VTREEFS_PROTO_H
|
#ifndef _VTREEFS_PROTO_H
|
||||||
#define _VTREEFS_PROTO_H
|
#define _VTREEFS_PROTO_H
|
||||||
|
|
||||||
|
/* extra.c */
|
||||||
|
int init_extra(unsigned int inodes, size_t inode_extra);
|
||||||
|
void clear_inode_extra(struct inode *node);
|
||||||
|
|
||||||
/* file.c */
|
/* file.c */
|
||||||
int init_buf(size_t size);
|
int init_buf(size_t size);
|
||||||
void cleanup_buf(void);
|
void cleanup_buf(void);
|
||||||
|
|
|
@ -6,6 +6,7 @@ static unsigned int inodes;
|
||||||
static struct inode_stat *root_stat;
|
static struct inode_stat *root_stat;
|
||||||
static index_t root_entries;
|
static index_t root_entries;
|
||||||
static size_t buf_size;
|
static size_t buf_size;
|
||||||
|
static size_t extra_size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize internal state. This is the only place where dynamic memory
|
* Initialize internal state. This is the only place where dynamic memory
|
||||||
|
@ -20,6 +21,10 @@ init_server(int __unused type, sef_init_info_t * __unused info)
|
||||||
if ((r = init_inodes(inodes, root_stat, root_entries)) != OK)
|
if ((r = init_inodes(inodes, root_stat, root_entries)) != OK)
|
||||||
panic("init_inodes failed: %d", r);
|
panic("init_inodes failed: %d", r);
|
||||||
|
|
||||||
|
/* Initialize extra data. */
|
||||||
|
if ((r = init_extra(inodes, extra_size)) != OK)
|
||||||
|
panic("init_extra failed: %d", r);
|
||||||
|
|
||||||
/* Initialize the I/O buffer. */
|
/* Initialize the I/O buffer. */
|
||||||
if ((r = init_buf(buf_size)) != OK)
|
if ((r = init_buf(buf_size)) != OK)
|
||||||
panic("init_buf failed: %d", r);
|
panic("init_buf failed: %d", r);
|
||||||
|
@ -83,8 +88,9 @@ fs_other(const message * m_ptr, int ipc_status)
|
||||||
* unmounted and the process is signaled to exit.
|
* unmounted and the process is signaled to exit.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
start_vtreefs(struct fs_hooks * hooks, unsigned int nr_inodes,
|
run_vtreefs(struct fs_hooks * hooks, unsigned int nr_inodes,
|
||||||
struct inode_stat * stat, index_t nr_indexed_entries, size_t bufsize)
|
size_t inode_extra, struct inode_stat * stat,
|
||||||
|
index_t nr_indexed_entries, size_t bufsize)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -93,6 +99,7 @@ start_vtreefs(struct fs_hooks * hooks, unsigned int nr_inodes,
|
||||||
*/
|
*/
|
||||||
vtreefs_hooks = hooks;
|
vtreefs_hooks = hooks;
|
||||||
inodes = nr_inodes;
|
inodes = nr_inodes;
|
||||||
|
extra_size = inode_extra;
|
||||||
root_stat = stat;
|
root_stat = stat;
|
||||||
root_entries = nr_indexed_entries;
|
root_entries = nr_indexed_entries;
|
||||||
buf_size = bufsize;
|
buf_size = bufsize;
|
||||||
|
|
|
@ -85,8 +85,9 @@ int main (int argc, char* argv[])
|
||||||
root_stat.size = 0;
|
root_stat.size = 0;
|
||||||
root_stat.dev = NO_DEV;
|
root_stat.dev = NO_DEV;
|
||||||
|
|
||||||
/* limit the number of indexed entries */
|
/* run VTreeFS */
|
||||||
start_vtreefs(&hooks, 1024, &root_stat, 0, BUF_SIZE);
|
run_vtreefs(&hooks, 1024, 0, &root_stat, 0, BUF_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue