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;
}
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;
}
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,
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);
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 */
LIB= vtreefs
SRCS= \
+ extra.c \
file.c \
inode.c \
link.c \
--- /dev/null
+/* 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];
+}
#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);
/* 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);
/* Initialize the root inode. */
node = &inode[0];
+ node->i_num = 0;
node->i_parent = NULL;
node->i_count = 0;
TAILQ_INIT(&node->i_children);
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;
}
/*
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;
}
/*
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);
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.
*/
CHECK_INODE(node);
- return (int)(node - &inode[0]) + 1;
+ return node->i_num + 1;
}
/*
* 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 */
#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);
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
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);
* 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)
{
/*
*/
vtreefs_hooks = hooks;
inodes = nr_inodes;
+ extra_size = inode_extra;
root_stat = stat;
root_entries = nr_indexed_entries;
buf_size = bufsize;
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;
}