diff --git a/minix/drivers/system/gpio/gpio.c b/minix/drivers/system/gpio/gpio.c index 9ddc19292..e6c2928fb 100644 --- a/minix/drivers/system/gpio/gpio.c +++ b/minix/drivers/system/gpio/gpio.c @@ -283,8 +283,8 @@ main(int argc, char **argv) root_stat.size = 0; root_stat.dev = NO_DEV; - /* limit the number of indexed entries */ - start_vtreefs(&hooks, 30, &root_stat, 0, DATA_SIZE); + /* run VTreeFS */ + run_vtreefs(&hooks, 30, 0, &root_stat, 0, DATA_SIZE); return EXIT_SUCCESS; } diff --git a/minix/fs/procfs/main.c b/minix/fs/procfs/main.c index 9e31fb588..3e416d494 100644 --- a/minix/fs/procfs/main.c +++ b/minix/fs/procfs/main.c @@ -87,8 +87,9 @@ int main(void) stat.size = 0; stat.dev = NO_DEV; - /* Start VTreeFS. */ - start_vtreefs(&hooks, NR_INODES, &stat, NR_PROCS + NR_TASKS, BUF_SIZE); + /* Run VTreeFS. */ + run_vtreefs(&hooks, NR_INODES, 0, &stat, NR_PROCS + NR_TASKS, + BUF_SIZE); return 0; } diff --git a/minix/include/minix/vtreefs.h b/minix/include/minix/vtreefs.h index 91c340f84..00e6db0d3 100644 --- a/minix/include/minix/vtreefs.h +++ b/minix/include/minix/vtreefs.h @@ -44,7 +44,7 @@ struct fs_hooks { extern struct inode *add_inode(struct inode *parent, const char *name, 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 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 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 void *get_inode_extra(const struct inode *inode); extern struct inode *get_root_inode(void); 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 set_inode_stat(struct inode *inode, struct inode_stat *stat); -extern void start_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes, - struct inode_stat *stat, index_t nr_indexed_entries, size_t buf_size); +extern void run_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes, + size_t inode_extra, struct inode_stat *stat, index_t nr_indexed_slots, + size_t buf_size); #endif /* _MINIX_VTREEFS_H */ diff --git a/minix/lib/libvtreefs/Makefile b/minix/lib/libvtreefs/Makefile index 181b053c0..d533fdb5d 100644 --- a/minix/lib/libvtreefs/Makefile +++ b/minix/lib/libvtreefs/Makefile @@ -7,6 +7,7 @@ CPPFLAGS+= -D_MINIX_SYSTEM LIB= vtreefs SRCS= \ + extra.c \ file.c \ inode.c \ link.c \ diff --git a/minix/lib/libvtreefs/extra.c b/minix/lib/libvtreefs/extra.c new file mode 100644 index 000000000..f283bfdd1 --- /dev/null +++ b/minix/lib/libvtreefs/extra.c @@ -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]; +} diff --git a/minix/lib/libvtreefs/inode.c b/minix/lib/libvtreefs/inode.c index 0363dc595..59328d9b9 100644 --- a/minix/lib/libvtreefs/inode.c +++ b/minix/lib/libvtreefs/inode.c @@ -19,6 +19,7 @@ static LIST_HEAD(index_head, inode) *parent_index_head; #define CHECK_INODE(node) \ do { \ 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 || \ (node->i_flags & I_DELETED)); \ } 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. */ for (i = 1; i < nr_inodes; i++) { node = &inode[i]; - + node->i_num = i; node->i_parent = NULL; node->i_count = 0; TAILQ_INIT(&node->i_children); @@ -83,6 +84,7 @@ init_inodes(unsigned int inodes, struct inode_stat * stat, /* Initialize the root inode. */ node = &inode[0]; + node->i_num = 0; node->i_parent = NULL; node->i_count = 0; TAILQ_INIT(&node->i_children); @@ -114,15 +116,13 @@ cleanup_inodes(void) static int parent_name_hash(const struct inode * parent, const char *name) { - unsigned int name_hash, parent_hash; - - /* The parent hash is a simple array entry; find its index. */ - parent_hash = (unsigned int)(parent - &inode[0]); + unsigned int name_hash; /* Use the sdbm algorithm to hash the 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) { - 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; 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. */ 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 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. */ @@ -342,7 +357,7 @@ get_inode_number(const struct inode * node) CHECK_INODE(node); - return (int)(node - &inode[0]) + 1; + return node->i_num + 1; } /* diff --git a/minix/lib/libvtreefs/inode.h b/minix/lib/libvtreefs/inode.h index a1788ecd7..01716edd8 100644 --- a/minix/lib/libvtreefs/inode.h +++ b/minix/lib/libvtreefs/inode.h @@ -16,6 +16,10 @@ * unused inodes. */ 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 */ struct inode_stat i_stat; /* POSIX attributes */ char i_name[PNAME_MAX + 1]; /* name of the inode in the parent */ diff --git a/minix/lib/libvtreefs/proto.h b/minix/lib/libvtreefs/proto.h index acead73cb..c6d2d8881 100644 --- a/minix/lib/libvtreefs/proto.h +++ b/minix/lib/libvtreefs/proto.h @@ -1,6 +1,10 @@ #ifndef _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 */ int init_buf(size_t size); void cleanup_buf(void); diff --git a/minix/lib/libvtreefs/vtreefs.c b/minix/lib/libvtreefs/vtreefs.c index f63d1064a..dc5fbe80a 100644 --- a/minix/lib/libvtreefs/vtreefs.c +++ b/minix/lib/libvtreefs/vtreefs.c @@ -6,6 +6,7 @@ static unsigned int inodes; static struct inode_stat *root_stat; static index_t root_entries; static size_t buf_size; +static size_t extra_size; /* * 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) 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. */ if ((r = init_buf(buf_size)) != OK) 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. */ void -start_vtreefs(struct fs_hooks * hooks, unsigned int nr_inodes, - struct inode_stat * stat, index_t nr_indexed_entries, size_t bufsize) +run_vtreefs(struct fs_hooks * hooks, unsigned int nr_inodes, + 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; inodes = nr_inodes; + extra_size = inode_extra; root_stat = stat; root_entries = nr_indexed_entries; buf_size = bufsize; diff --git a/minix/servers/devman/main.c b/minix/servers/devman/main.c index 924d6fb70..09e683adc 100644 --- a/minix/servers/devman/main.c +++ b/minix/servers/devman/main.c @@ -85,8 +85,9 @@ int main (int argc, char* argv[]) root_stat.size = 0; root_stat.dev = NO_DEV; - /* limit the number of indexed entries */ - start_vtreefs(&hooks, 1024, &root_stat, 0, BUF_SIZE); + /* run VTreeFS */ + run_vtreefs(&hooks, 1024, 0, &root_stat, 0, BUF_SIZE); + return 0; }