From: Charles Manning Date: Tue, 20 Dec 2011 02:58:11 +0000 (+1300) Subject: WIP large file support X-Git-Tag: pre-driver-refactoring~34^2~5 X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=20de150d680c2a84c4a2e0d5f0f354274c7ff9ab WIP large file support Signed-off-by: Charles Manning --- diff --git a/linux-tests/Makefile b/linux-tests/Makefile new file mode 100644 index 0000000..1f1d56e --- /dev/null +++ b/linux-tests/Makefile @@ -0,0 +1,15 @@ +CFLAGS += -Wall -D_FILE_OFFSET_BITS=64 + +TARGETS = xattrtest writebigsparse +all: $(TARGETS) + +xattrtest: xattrtest.c + gcc $(CFLAGS) -o $@ $< + +writebigsparse: writebigsparse.c + gcc $(CFLAGS) -o $@ $< + + +.PHONEY: clean +clean: + rm -f $(TARGETS) diff --git a/linux-tests/writebigsparse.c b/linux-tests/writebigsparse.c new file mode 100644 index 0000000..0d70128 --- /dev/null +++ b/linux-tests/writebigsparse.c @@ -0,0 +1,80 @@ +#define _LARGEFILE64_SOURCE +#include +#include +#include +#include +#include +#include + +int handle; + +#define N_WRITES 8000 +#define STRIDE 1000 + +#define BUFFER_N 2000 +unsigned buffer[BUFFER_N]; + + +void set_buffer(int n) +{ + int i; + for(i = 0; i < BUFFER_N; i++) + buffer[i] = i + n; +} + +void write_big_sparse_file(int h) +{ + int i; + off64_t offset = 0; + off64_t pos; + int n = sizeof(buffer); + int wrote; + + for(i = 0; i < 4000; i++) { + set_buffer(i); + pos = lseek64(h, offset, SEEK_SET); + if(pos != offset) { + printf("mismatched seek pos %lld offset %lld\n", + pos, offset); + exit(1); + } + wrote = write(h, buffer, n); + + if(wrote != n) { + printf("mismatched write wrote %d n %d\n", wrote, n); + exit(1); + } + + offset += (STRIDE * sizeof(buffer)); + } +} + + + + +void verify_big_sparse_file(int h) +{ +} + +int main(int argc, char *argv[]) +{ + + if(argc < 2) { + printf("Gimme a file name!\n"); + exit(1); + } + + handle = open(argv[1], O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE); + + if(handle < 0) { + perror("opening file"); + exit(1); + } + + write_big_sparse_file(handle); + system("sudo echo 3 > /proc/sys/vm/drop_caches"); + verify_big_sparse_file(handle); + + printf("Job done\n"); + return 0; +} diff --git a/linux-tests/xattrtest.c b/linux-tests/xattrtest.c index 4e92dfc..3a6931b 100644 --- a/linux-tests/xattrtest.c +++ b/linux-tests/xattrtest.c @@ -19,7 +19,8 @@ #include #include #include - +#include +#include static void print_xattrib_val(const char *path, const char *name) { @@ -66,8 +67,6 @@ void basic_xattr_test(const char *mountpt) int h; int result; int val1; - int valread; - strcpy(name,mountpt); strcat(name,"/"); @@ -115,4 +114,5 @@ int simulate_power_failure; int main(int argc, char *argv[]) { basic_xattr_test("/mnt/"); + return 0; } diff --git a/yaffs_guts.c b/yaffs_guts.c index 146fb2b..79a7988 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -44,8 +44,8 @@ static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk, /* Function to calculate chunk and offset */ -static inline void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr, - int *chunk_out, u32 *offset_out) +void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr, + int *chunk_out, u32 *offset_out) { int chunk; u32 offset; @@ -5001,7 +5001,13 @@ void yaffs_oh_size_load(struct yaffs_obj_hdr *oh, loff_t fsize) loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh) { - loff_t retval = (((loff_t) oh->file_size_high) << 32) | + loff_t retval; + + if(~(oh->file_size_high)) + retval = (((loff_t) oh->file_size_high) << 32) | (((loff_t) oh->file_size_low) & 0xFFFFFFFF); + else + retval = (loff_t) oh->file_size_low; + return retval; } diff --git a/yaffs_guts.h b/yaffs_guts.h index 9380966..a063776 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -949,7 +949,9 @@ u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn, int yaffs_is_non_empty_dir(struct yaffs_obj *obj); -/*\ +void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr, + int *chunk_out, u32 *offset_out); +/* * Marshalling functions to get loff_t file sizes into aand out of * object headers. */ diff --git a/yaffs_verify.c b/yaffs_verify.c index b3e540d..db48e56 100644 --- a/yaffs_verify.c +++ b/yaffs_verify.c @@ -222,11 +222,13 @@ void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh, void yaffs_verify_file(struct yaffs_obj *obj) { + u32 x; int required_depth; int actual_depth; - u32 last_chunk; + int last_chunk; + u32 offset_in_chunk; u32 the_chunk; - u32 x; + u32 i; struct yaffs_dev *dev; struct yaffs_ext_tags tags; @@ -242,9 +244,11 @@ void yaffs_verify_file(struct yaffs_obj *obj) dev = obj->my_dev; obj_id = obj->obj_id; + /* Check file size is consistent with tnode depth */ - last_chunk = - obj->variant.file_variant.file_size / dev->data_bytes_per_chunk + 1; + yaffs_addr_to_chunk(dev, obj->variant.file_variant.file_size, + &last_chunk, &offset_in_chunk); + last_chunk++; x = last_chunk >> YAFFS_TNODES_LEVEL0_BITS; required_depth = 0; while (x > 0) { diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c index b8e5124..8773b76 100644 --- a/yaffs_vfs_multi.c +++ b/yaffs_vfs_multi.c @@ -1068,9 +1068,9 @@ static int yaffs_writepage(struct page *page) if (page->index > end_index || !n_bytes) { yaffs_trace(YAFFS_TRACE_OS, - "yaffs_writepage at %08x, inode size = %08x!!", - (unsigned)(page->index << PAGE_CACHE_SHIFT), - (unsigned)inode->i_size); + "yaffs_writepage at %lld, inode size = %lld!!", + ((loff_t)page->index) << PAGE_CACHE_SHIFT, + inode->i_size); yaffs_trace(YAFFS_TRACE_OS, " -> don't care!!"); @@ -1094,11 +1094,11 @@ static int yaffs_writepage(struct page *page) yaffs_gross_lock(dev); yaffs_trace(YAFFS_TRACE_OS, - "yaffs_writepage at %08x, size %08x", - (unsigned)(page->index << PAGE_CACHE_SHIFT), n_bytes); + "yaffs_writepage at %lld, size %08x", + ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes); yaffs_trace(YAFFS_TRACE_OS, - "writepag0: obj = %05x, ino = %05x", - (int)obj->variant.file_variant.file_size, (int)inode->i_size); + "writepag0: obj = %lld, ino = %lld", + obj->variant.file_variant.file_size, inode->i_size); n_written = yaffs_wr_file(obj, buffer, page->index << PAGE_CACHE_SHIFT, n_bytes, 0); @@ -1106,8 +1106,8 @@ static int yaffs_writepage(struct page *page) yaffs_touch_super(dev); yaffs_trace(YAFFS_TRACE_OS, - "writepag1: obj = %05x, ino = %05x", - (int)obj->variant.file_variant.file_size, (int)inode->i_size); + "writepag1: obj = %lld, ino = %lld", + obj->variant.file_variant.file_size, inode->i_size); yaffs_gross_unlock(dev); @@ -1206,8 +1206,8 @@ static int yaffs_write_end(struct file *filp, struct address_space *mapping, addr = kva + offset_into_page; yaffs_trace(YAFFS_TRACE_OS, - "yaffs_write_end addr %p pos %x n_bytes %d", - addr, (unsigned)pos, copied); + "yaffs_write_end addr %p pos %lld n_bytes %d", + addr, pos, copied); ret = yaffs_file_write(filp, addr, copied, &pos); @@ -1236,17 +1236,12 @@ static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, int n_bytes = to - offset; int n_written; - unsigned spos = pos; - unsigned saddr; - kva = kmap(pg); addr = kva + offset; - saddr = (unsigned)addr; - yaffs_trace(YAFFS_TRACE_OS, - "yaffs_commit_write addr %x pos %x n_bytes %d", - saddr, spos, n_bytes); + "yaffs_commit_write addr %p pos %lld n_bytes %d", + addr, pos, n_bytes); n_written = yaffs_file_write(f, addr, n_bytes, &pos); @@ -1333,9 +1328,9 @@ static void yaffs_fill_inode_from_obj(struct inode *inode, inode->i_nlink = yaffs_get_obj_link_count(obj); yaffs_trace(YAFFS_TRACE_OS, - "yaffs_fill_inode mode %x uid %d gid %d size %d count %d", + "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d", inode->i_mode, inode->i_uid, inode->i_gid, - (int)inode->i_size, atomic_read(&inode->i_count)); + inode->i_size, atomic_read(&inode->i_count)); switch (obj->yst_mode & S_IFMT) { default: /* fifo, device or socket */ @@ -1410,7 +1405,8 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t * pos) { struct yaffs_obj *obj; - int n_written, ipos; + int n_written; + loff_t ipos; struct inode *inode; struct yaffs_dev *dev; @@ -1434,8 +1430,8 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, ipos = *pos; yaffs_trace(YAFFS_TRACE_OS, - "yaffs_file_write about to write writing %u(%x) bytes to object %d at %d(%x)", - (unsigned)n, (unsigned)n, obj->obj_id, ipos, ipos); + "yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld", + (unsigned)n, (unsigned)n, obj->obj_id, ipos); n_written = yaffs_wr_file(obj, buf, ipos, n, 0); @@ -1453,7 +1449,7 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, inode->i_blocks = (ipos + 511) >> 9; yaffs_trace(YAFFS_TRACE_OS, - "yaffs_file_write size updated to %d bytes, %d blocks", + "yaffs_file_write size updated to %lld bytes, %d blocks", ipos, (int)(inode->i_blocks)); } @@ -1920,10 +1916,11 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) yaffs_trace(YAFFS_TRACE_OS, "yaffs_setattr of object %d", yaffs_inode_to_obj(inode)->obj_id); - +#if 0 /* Fail if a requested resize >= 2GB */ if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31)) error = -EINVAL; +#endif if (error == 0) error = inode_change_ok(inode, attr);