Fix resizing of large files.
authorCharles Manning <cdhmanning@gmail.com>
Sun, 25 Mar 2012 06:22:27 +0000 (19:22 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Sun, 25 Mar 2012 06:22:27 +0000 (19:22 +1300)
Chunk prunign was using an integer argument. That could damage
a large file being resized down.

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

index d3c9ba5..3739aca 100644 (file)
@@ -2976,8 +2976,11 @@ void verify_big_sparse_file(int h)
 
 void large_file_test(const char *mountpt)
 {
+       char xx_buffer[1000];
+       int i;
        int handle;
        char fullname[100];
+       loff_t file_end;
 
        yaffs_trace_mask = 0;
 
@@ -3021,6 +3024,21 @@ void large_file_test(const char *mountpt)
        verify_big_sparse_file(handle);
        yaffs_unmount(mountpt);
 
+       /* Check resize by adding to the end, resizing back and verifying. */
+       yaffs_mount_common(mountpt, 0, 1);
+       printf("checking resize\n");
+        dumpDir(mountpt);
+       handle = yaffs_open(fullname, O_RDWR, 0);
+
+       file_end = yaffs_lseek(handle, 0, SEEK_END);
+       printf("file_end %lld\n", file_end);
+       for(i = 0; i < 10000; i++)
+               yaffs_write(handle, xx_buffer, sizeof(xx_buffer));
+       yaffs_ftruncate(handle, file_end);
+
+       verify_big_sparse_file(handle);
+       yaffs_unmount(mountpt);
+
 }
 
 
@@ -3092,10 +3110,10 @@ int main(int argc, char *argv[])
         //basic_utime_test("/yaffs2");
 
         //max_files_test("/yaffs2");
-        
-        start_twice("/yaffs2");
 
-        //large_file_test("/yaffs2");
+        //start_twice("/yaffs2");
+
+        large_file_test("/yaffs2");
 
         //basic_utime_test("/yaffs2");
         //case_insensitive_test("/yaffs2");
index ae37c3f..6ad45fc 100644 (file)
@@ -3687,17 +3687,26 @@ int yaffs_wr_file(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
 
 /* ---------------------- File resizing stuff ------------------ */
 
-static void yaffs_prune_chunks(struct yaffs_obj *in, int new_size)
+static void yaffs_prune_chunks(struct yaffs_obj *in, loff_t new_size)
 {
 
        struct yaffs_dev *dev = in->my_dev;
-       int old_size = in->variant.file_variant.file_size;
+       loff_t old_size = in->variant.file_variant.file_size;
        int i;
        int chunk_id;
-       int last_del = 1 + (old_size - 1) / dev->data_bytes_per_chunk;
-       int start_del = 1 + (new_size + dev->data_bytes_per_chunk - 1) /
-           dev->data_bytes_per_chunk;
+       u32 dummy;
+       int last_del;
+       int start_del;
+
+       if(old_size > 0)
+               yaffs_addr_to_chunk(dev, old_size - 1, &last_del, &dummy);
+       else
+               last_del = 0;
 
+       yaffs_addr_to_chunk(dev, new_size + dev->data_bytes_per_chunk - 1,
+                               &start_del, &dummy);
+       last_del++;
+       start_del++;
 
        /* Delete backwards so that we don't end up with holes if
         * power is lost part-way through the operation.