From 87166dff2586aa5d844c86945a80b098861b2b23 Mon Sep 17 00:00:00 2001 From: Charles Manning Date: Sun, 25 Mar 2012 19:22:27 +1300 Subject: [PATCH] Fix resizing of large files. Chunk prunign was using an integer argument. That could damage a large file being resized down. Signed-off-by: Charles Manning --- direct/basic-test/dtest.c | 24 +++++++++++++++++++++--- yaffs_guts.c | 19 ++++++++++++++----- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/direct/basic-test/dtest.c b/direct/basic-test/dtest.c index d3c9ba5..3739aca 100644 --- a/direct/basic-test/dtest.c +++ b/direct/basic-test/dtest.c @@ -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"); diff --git a/yaffs_guts.c b/yaffs_guts.c index ae37c3f..6ad45fc 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -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. -- 2.30.2