yaffs-direct: Fix object leak caused by defered free
authorCharles Manning <cdhmanning@gmail.com>
Tue, 4 Mar 2014 01:04:00 +0000 (14:04 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Tue, 4 Mar 2014 01:04:00 +0000 (14:04 +1300)
The change to dtest.c adds a test case that was leaking objects.
The change to yaffsfs.c fixes this.

This leak was triggered by sequences of the following form:

yaffs_open(file_name, ...); /* create obj */
...
yaffs_unlink(file_name);
yaffs_close(file_name);

When the file was closed, obj->my_inode was not NULL when yaffs_del_obj() is
called, therefore the object was not released properly.

The fix "unstitches" the object before the call to yaffs_del_obj(), so that
obj->my_inode is NULL and the object freeing is done correctly.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
direct/test-framework/basic-tests/dtest.c
direct/yaffsfs.c

index a6a8c9d6c10c986d57ba8167f92b36ea68c7e2c5..5db05beb79a57fd028b77f056a93c5550931a8fa 100644 (file)
@@ -3300,6 +3300,40 @@ void dir_fd_test(const char *mountpt)
 
 }
 
+
+
+void create_delete_many_files_test(const char *mountpt)
+{
+
+       char fn[100];
+       int i;
+       int fsize;
+       char buffer[1000];
+       int h;
+       int wrote;
+
+
+       yaffs_start_up();
+       yaffs_mount(mountpt);
+
+       for(i = 1; i < 2000; i++) {
+               sprintf(fn,"%s/f%d",mountpt, i);
+               fsize = (i%10) * 10000 + 20000;
+               h = yaffs_open(fn, O_CREAT | O_TRUNC | O_RDWR, 0666);
+               while (fsize > 0) {
+                       wrote = yaffs_write(h, buffer, sizeof(buffer));
+                       if (wrote != sizeof(buffer)) {
+                               printf("Writing file %s, only wrote %d bytes\n", fn, wrote);
+                               break;
+                       }
+                       fsize -= wrote;
+               }
+               yaffs_unlink(fn);
+               yaffs_close(h);
+       }
+
+}
+
 int random_seed;
 int simulate_power_failure;
 
@@ -3385,8 +3419,8 @@ int main(int argc, char *argv[])
 
        //dir_fd_test("/nand");
 
-       format_test("/nand");
-
+       //format_test("/nand");
+       create_delete_many_files_test("/nand");
         return 0;
 
 }
index 331590bfa4bff7db4d7f4f507579f5e109aed50f..6cffbc86ebc04705b59ae7b846022034a530e4f0 100644 (file)
@@ -247,13 +247,11 @@ static void yaffsfs_ReleaseInode(struct yaffsfs_Inode *in)
        struct yaffs_obj *obj;
 
        obj = in->iObj;
-
-       if (obj->unlinked)
-               yaffs_del_obj(obj);
-
        obj->my_inode = NULL;
        in->iObj = NULL;
 
+       if (obj->unlinked)
+               yaffs_del_obj(obj);
 }
 
 static void yaffsfs_PutInode(int inodeId)