]> Zhao Yanbai Git Server - minix.git/commitdiff
libvtreefs: dynamically allocate long inode names 13/3013/1
authorCristiano Giuffrida <giuffrida@cs.vu.nl>
Wed, 31 Dec 2014 01:15:44 +0000 (02:15 +0100)
committerDavid van Moolenbroek <david@minix3.org>
Mon, 29 Jun 2015 10:57:24 +0000 (10:57 +0000)
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

minix/include/minix/vtreefs.h
minix/lib/libvtreefs/inode.c
minix/lib/libvtreefs/inode.h
minix/lib/libvtreefs/path.c
minix/lib/libvtreefs/stadir.c

index 00e6db0d3e5cabf39cf6be1b441ce11b92168d2d..7c1d6ed2293378b05e19b584143b8a5d6c8b75c0 100644 (file)
@@ -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
 
index 3b40f8cb065009692d9fb255b6a954d37ffddc37..6ad4a4bee376de4651a4d7db1afb8701b7a7b02a 100644 (file)
@@ -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;
 
                /*
index 01716edd8d1713af8069f2c58d0c1ee8ca5823ac..3340cca322cb9c3dedbc8e2bf5e5eaf3e7da9cd7 100644 (file)
@@ -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 */
index 23b8d68c8c6d6284b3a670cd875ed5b57684864e..7d604306ac8e04bf79d682b7156d3359b4cdf82a 100644 (file)
@@ -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, ".")) {
index 5a4a5e5c8c6563d47c8ae386ab09727c8209f95e..bb15049db9686c6f4889ef7fa2c43648596a5141 100644 (file)
@@ -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;
 }