libvtreefs: dynamically allocate long inode names
Extended by David van Moolenbroek to continue using static buffers for short inode names, so as to prevent important file system services such as procfs from running out of memory at runtime. Change-Id: I6f841741ee9944fc87dbdb78b5cdaa2abee9da76
This commit is contained in:
parent
5a7def9a94
commit
c21aa858e2
5 changed files with 30 additions and 8 deletions
|
@ -7,8 +7,9 @@ typedef void *cbdata_t;
|
|||
|
||||
#define NO_INDEX ((index_t) -1)
|
||||
|
||||
/* Maximum file name length, excluding terminating null character. It is set
|
||||
* to a low value to limit memory usage, but can be changed to any value.
|
||||
/* Maximum file name length, excluding terminating null character, for which
|
||||
* the name will be allocated statically. Longer names will be allocated
|
||||
* dynamically, and should not be used for system-critical file systems.
|
||||
*/
|
||||
#define PNAME_MAX 24
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ init_inodes(unsigned int inodes, struct inode_stat * stat,
|
|||
for (i = 1; i < nr_inodes; i++) {
|
||||
node = &inode[i];
|
||||
node->i_num = i;
|
||||
node->i_name = NULL;
|
||||
node->i_parent = NULL;
|
||||
node->i_count = 0;
|
||||
TAILQ_INIT(&node->i_children);
|
||||
|
@ -186,12 +187,13 @@ add_inode(struct inode * parent, const char * name, index_t index,
|
|||
cbdata_t cbdata)
|
||||
{
|
||||
struct inode *newnode;
|
||||
char *newname;
|
||||
int slot;
|
||||
|
||||
CHECK_INODE(parent);
|
||||
assert(S_ISDIR(parent->i_stat.mode));
|
||||
assert(!(parent->i_flags & I_DELETED));
|
||||
assert(strlen(name) <= PNAME_MAX);
|
||||
assert(strlen(name) <= NAME_MAX);
|
||||
assert(index >= 0 || index == NO_INDEX);
|
||||
assert(stat != NULL);
|
||||
assert(nr_indexed_entries >= 0);
|
||||
|
@ -204,18 +206,28 @@ add_inode(struct inode * parent, const char * name, index_t index,
|
|||
assert(!TAILQ_EMPTY(&unused_inodes));
|
||||
|
||||
newnode = TAILQ_FIRST(&unused_inodes);
|
||||
|
||||
/* Use the static name buffer if the name is short enough. Otherwise,
|
||||
* allocate heap memory for the name.
|
||||
*/
|
||||
newname = newnode->i_namebuf;
|
||||
if (strlen(name) > PNAME_MAX &&
|
||||
(newname = malloc(strlen(name) + 1)) == NULL)
|
||||
return NULL;
|
||||
|
||||
TAILQ_REMOVE(&unused_inodes, newnode, i_unused);
|
||||
|
||||
assert(newnode->i_count == 0);
|
||||
|
||||
/* Copy the relevant data to the inode. */
|
||||
newnode->i_parent = parent;
|
||||
newnode->i_name = newname;
|
||||
newnode->i_flags = 0;
|
||||
newnode->i_index = index;
|
||||
newnode->i_stat = *stat;
|
||||
newnode->i_indexed = nr_indexed_entries;
|
||||
newnode->i_cbdata = cbdata;
|
||||
strlcpy(newnode->i_name, name, sizeof(newnode->i_name));
|
||||
strcpy(newnode->i_name, name);
|
||||
|
||||
/* Clear the extra data for this inode, if present. */
|
||||
clear_inode_extra(newnode);
|
||||
|
@ -255,6 +267,8 @@ get_inode_name(const struct inode * node)
|
|||
{
|
||||
|
||||
CHECK_INODE(node);
|
||||
assert(!(node->i_flags & I_DELETED));
|
||||
assert(node->i_name != NULL);
|
||||
|
||||
return node->i_name;
|
||||
}
|
||||
|
@ -394,7 +408,7 @@ get_inode_by_name(const struct inode * parent, const char * name)
|
|||
int slot;
|
||||
|
||||
CHECK_INODE(parent);
|
||||
assert(strlen(name) <= PNAME_MAX);
|
||||
assert(strlen(name) <= NAME_MAX);
|
||||
assert(S_ISDIR(parent->i_stat.mode));
|
||||
|
||||
/* Get the hash value, and search for the inode. */
|
||||
|
@ -547,6 +561,12 @@ delete_inode(struct inode * node)
|
|||
if (node->i_index != NO_INDEX)
|
||||
LIST_REMOVE(node, i_hindex);
|
||||
|
||||
/* Free the name if allocated dynamically. */
|
||||
assert(node->i_name != NULL);
|
||||
if (node->i_name != node->i_namebuf)
|
||||
free(node->i_name);
|
||||
node->i_name = NULL;
|
||||
|
||||
node->i_flags |= I_DELETED;
|
||||
|
||||
/*
|
||||
|
|
|
@ -22,7 +22,8 @@ struct inode {
|
|||
|
||||
/* Inode metadata */
|
||||
struct inode_stat i_stat; /* POSIX attributes */
|
||||
char i_name[PNAME_MAX + 1]; /* name of the inode in the parent */
|
||||
char i_namebuf[PNAME_MAX + 1]; /* buffer for static (short) names */
|
||||
char *i_name; /* name of the inode in the parent */
|
||||
unsigned int i_count; /* reference count */
|
||||
index_t i_index; /* index number in parent / NO_INDEX */
|
||||
int i_indexed; /* number of indexed entries */
|
||||
|
|
|
@ -18,7 +18,7 @@ fs_lookup(ino_t dir_nr, char * name, struct fsdriver_node * node_details,
|
|||
if (!S_ISDIR(node->i_stat.mode))
|
||||
return ENOTDIR;
|
||||
|
||||
if (strlen(name) > PNAME_MAX)
|
||||
if (strlen(name) > NAME_MAX)
|
||||
return ENAMETOOLONG;
|
||||
|
||||
if (!strcmp(name, ".")) {
|
||||
|
|
|
@ -116,7 +116,7 @@ fs_statvfs(struct statvfs * buf)
|
|||
{
|
||||
|
||||
buf->f_flag = ST_NOTRUNC;
|
||||
buf->f_namemax = PNAME_MAX;
|
||||
buf->f_namemax = NAME_MAX;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue