From: Charles Manning Date: Mon, 13 Feb 2012 02:47:12 +0000 (+1300) Subject: Merge branch 'big-files': Merge in large file support X-Git-Tag: pre-driver-refactoring~34 X-Git-Url: https://yaffs.net/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=ce0a5fb9849b6dc0d1347709b28d3a34eefec662;hp=-c Merge branch 'big-files': Merge in large file support Signed-off-by: Charles Manning --- ce0a5fb9849b6dc0d1347709b28d3a34eefec662 diff --combined direct/basic-test/dtest.c index 3535423,0b67b7a..4953830 --- a/direct/basic-test/dtest.c +++ b/direct/basic-test/dtest.c @@@ -533,7 -533,7 +533,7 @@@ void dumpDirFollow(const char *dname yaffs_lstat(str,&s); - printf("%s ino %d length %d mode %X ",de->d_name,(int)s.st_ino,(int)s.st_size,s.st_mode); + printf("%s ino %lld length %d mode %X ",de->d_name,(int)s.st_ino,s.st_size,s.st_mode); switch(s.st_mode & S_IFMT) { case S_IFREG: printf("data file"); break; @@@ -580,7 -580,8 +580,8 @@@ void dump_directory_tree_worker(const c yaffs_lstat(str,&s); - printf("%s inode %d obj %x length %d mode %X ",str,s.st_ino,de->d_dont_use,(int)s.st_size,s.st_mode); + printf("%s inode %d obj %x length %lld mode %X ", + str,s.st_ino,de->d_dont_use, s.st_size,s.st_mode); switch(s.st_mode & S_IFMT) { case S_IFREG: printf("data file"); break; @@@ -2755,60 -2756,170 +2756,223 @@@ void link_follow_test(const char *mount } +void max_files_test(const char *mountpt) +{ + char fn[100]; + char sn[100]; + char hn[100]; + int result; + int h; + int i; + + yaffs_trace_mask = 0; + + yaffs_start_up(); + + yaffs_mount(mountpt); + + for(i = 0; i < 5000; i++) { + sprintf(fn,"%s/file%d", mountpt, i); + yaffs_unlink(fn); + h = yaffs_open(fn,O_CREAT| O_RDWR, S_IREAD | S_IWRITE); + if(h < 0) + printf("File %s not created\n", fn); + yaffs_write(h,fn,100); + result = yaffs_close(h); + } + for(i = 0; i < 5; i++){ + sprintf(fn,"%s/file%d",mountpt, i); + yaffs_unlink(fn); + } + + for(i = 1000; i < 1010; i++){ + sprintf(fn,"%s/file%d",mountpt, i); + h = yaffs_open(fn,O_CREAT| O_RDWR, S_IREAD | S_IWRITE); + yaffs_write(h,fn,100); + if(h < 0) + printf("File %s not created\n", fn); + result = yaffs_close(h); + } + + h =yaffs_open(hn,O_RDWR,0); + +} + +void start_twice(const char *mountpt) +{ + printf("About to do first yaffs_start\n"); + yaffs_start_up(); + printf("started\n"); + printf("First mount returns %d\n", yaffs_mount(mountpt)); + printf("About to do second yaffs_start\n"); + yaffs_start_up(); + printf("started\n"); + printf("Second mount returns %d\n", yaffs_mount(mountpt)); +} + #define N_WRITES 2000 + #define STRIDE 2000 + + #define BUFFER_N 1100 + unsigned xxbuffer[BUFFER_N]; + + + void set_buffer(int n) + { + int i; + for(i = 0; i < BUFFER_N; i++) + xxbuffer[i] = i + n; + } + + void write_big_sparse_file(int h) + { + int i; + loff_t offset = 0; + loff_t pos; + int n = sizeof(xxbuffer); + int wrote; + + for(i = 0; i < N_WRITES; i++) { + printf("writing at %lld\n", offset); + set_buffer(i); + pos = yaffs_lseek(h, offset, SEEK_SET); + if(pos != offset) { + printf("mismatched seek pos %lld offset %lld\n", + pos, offset); + perror("lseek64"); + exit(1); + } + wrote = yaffs_write(h, xxbuffer, n); + + if(wrote != n) { + printf("mismatched write wrote %d n %d\n", wrote, n); + exit(1); + } + + offset += (STRIDE * sizeof(xxbuffer)); + } + + yaffs_ftruncate(h, offset); + + } + + + + + void verify_big_sparse_file(int h) + { + unsigned check_buffer[BUFFER_N]; + int i; + loff_t offset = 0; + loff_t pos; + int n = sizeof(check_buffer); + int result; + const char * check_type; + int checks_failed = 0; + int checks_passed = 0; + + for(i = 0; i < N_WRITES * STRIDE; i++) { + if(i % STRIDE) { + check_type = "zero"; + memset(xxbuffer,0, n); + } else { + check_type = "buffer"; + set_buffer(i/STRIDE); + } + //printf("%s checking %lld\n", check_type, offset); + pos = yaffs_lseek(h, offset, SEEK_SET); + if(pos != offset) { + printf("mismatched seek pos %lld offset %lld\n", + pos, offset); + perror("lseek64"); + exit(1); + } + result = yaffs_read(h, check_buffer, n); + + if(result != n) { + printf("mismatched read result %d n %d\n", result, n); + exit(1); + } + + + + + if(memcmp(xxbuffer, check_buffer, n)) { + int j; + + printf("buffer at %lld mismatches\n", pos); + printf("xxbuffer "); + for(j = 0; j < 20; j++) + printf(" %d",xxbuffer[j]); + printf("\n"); + printf("check_buffer "); + for(j = 0; j < 20; j++) + printf(" %d",check_buffer[j]); + printf("\n"); + + checks_failed++; + } else { + checks_passed++; + } + + offset += sizeof(xxbuffer); + } + + printf("%d checks passed, %d checks failed\n", checks_passed, checks_failed); + + } + + + void large_file_test(const char *mountpt) + { + int handle; + char fullname[100]; + + yaffs_trace_mask = 0; + + yaffs_start_up(); + + yaffs_mount(mountpt); + printf("mounted\n"); + dumpDir(mountpt); + + sprintf(fullname, "%s/%s", mountpt, "big-test-file"); + + handle = yaffs_open(fullname, O_RDONLY, 0); + + handle = yaffs_open(fullname, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE); + + if(handle < 0) { + perror("opening file"); + exit(1); + } + + write_big_sparse_file(handle); + verify_big_sparse_file(handle); + + yaffs_close(handle); + + printf("Job done\n"); + yaffs_unmount(mountpt); + + yaffs_mount(mountpt); + printf("mounted again\n"); + dumpDir(mountpt); + handle = yaffs_open(fullname, O_RDONLY, 0); + verify_big_sparse_file(handle); + yaffs_unmount(mountpt); + + + yaffs_mount_common(mountpt, 0, 1); + printf("mounted with no checkpt\n"); + dumpDir(mountpt); + handle = yaffs_open(fullname, O_RDONLY, 0); + verify_big_sparse_file(handle); + yaffs_unmount(mountpt); + + } + + int random_seed; int simulate_power_failure; @@@ -2845,7 -2956,7 +3009,7 @@@ int main(int argc, char *argv[] //checkpoint_upgrade_test("/flash/flash",20); //small_overwrite_test("/flash/flash",1000); //checkpoint_fill_test("/flash/flash",20); - // random_small_file_test("/flash/flash",10000); + //random_small_file_test("/flash/flash",10000); // huge_array_test("/flash/flash",10); @@@ -2874,12 -2985,10 +3038,15 @@@ //test_flash_traffic("yaffs2"); // link_follow_test("/yaffs2"); + //basic_utime_test("/yaffs2"); + + //max_files_test("/yaffs2"); + + start_twice("/yaffs2"); - large_file_test("/yaffs2"); ++ //large_file_test("/yaffs2"); + + //basic_utime_test("/yaffs2"); return 0; diff --combined direct/yaffsfs.c index 37d6cae,014bfc5..b57084c --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@@ -75,7 -75,7 +75,7 @@@ typedef struct u8 shareWrite:1; int inodeId:12; /* Index to corresponding yaffsfs_Inode */ int handleCount:10; /* Number of handles for this fd */ - u32 position; /* current position in file */ + loff_t position; /* current position in file */ }yaffsfs_FileDes; typedef struct { @@@ -124,7 -124,7 +124,7 @@@ static void yaffsfs_InitHandles(void static yaffsfs_Handle *yaffsfs_HandleToPointer(int h) { - if(h >= 0 && h <= YAFFSFS_N_HANDLES) + if(h >= 0 && h < YAFFSFS_N_HANDLES) return &yaffsfs_handle[h]; return NULL; } @@@ -743,15 -743,7 +743,15 @@@ int yaffs_dup(int handle } +static int yaffsfs_TooManyObjects(struct yaffs_dev *dev) +{ + int current_objects = dev->n_obj - dev->n_deleted_files; + if(dev->param.max_objects && current_objects > dev->param.max_objects) + return 1; + else + return 0; +} int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int sharing) { @@@ -923,9 -915,6 +923,9 @@@ if(dir->my_dev->read_only){ yaffsfs_SetError(-EROFS); errorReported = 1; + } else if(yaffsfs_TooManyObjects(dir->my_dev)) { + yaffsfs_SetError(-ENFILE); + errorReported = 1; } else obj = yaffs_create_file(dir,name,mode,0,0); @@@ -1048,17 -1037,17 +1048,17 @@@ int yaffs_close(int handle - int yaffsfs_do_read(int handle, void *vbuf, unsigned int nbyte, int isPread, int offset) + int yaffsfs_do_read(int handle, void *vbuf, unsigned int nbyte, int isPread, loff_t offset) { yaffsfs_FileDes *fd = NULL; struct yaffs_obj *obj = NULL; - int pos = 0; - int startPos = 0; - int endPos = 0; + loff_t pos = 0; + loff_t startPos = 0; + loff_t endPos = 0; int nRead = 0; int nToRead = 0; int totalRead = 0; - unsigned int maxRead; + loff_t maxRead; u8 *buf = (u8 *)vbuf; if(!vbuf){ @@@ -1165,18 -1154,18 +1165,18 @@@ int yaffs_read(int handle, void *buf, u return yaffsfs_do_read(handle, buf, nbyte, 0, 0); } - int yaffs_pread(int handle, void *buf, unsigned int nbyte, unsigned int offset) + int yaffs_pread(int handle, void *buf, unsigned int nbyte, loff_t offset) { return yaffsfs_do_read(handle, buf, nbyte, 1, offset); } - int yaffsfs_do_write(int handle, const void *vbuf, unsigned int nbyte, int isPwrite, int offset) + int yaffsfs_do_write(int handle, const void *vbuf, unsigned int nbyte, int isPwrite, loff_t offset) { yaffsfs_FileDes *fd = NULL; struct yaffs_obj *obj = NULL; - int pos = 0; - int startPos = 0; - int endPos; + loff_t pos = 0; + loff_t startPos = 0; + loff_t endPos; int nWritten = 0; int totalWritten = 0; int write_trhrough = 0; @@@ -1279,13 -1268,13 +1279,13 @@@ int yaffs_write(int fd, const void *buf return yaffsfs_do_write(fd, buf, nbyte, 0, 0); } - int yaffs_pwrite(int fd, const void *buf, unsigned int nbyte, unsigned int offset) + int yaffs_pwrite(int fd, const void *buf, unsigned int nbyte, loff_t offset) { return yaffsfs_do_write(fd, buf, nbyte, 1, offset); } - int yaffs_truncate(const YCHAR *path,off_t new_size) + int yaffs_truncate(const YCHAR *path,loff_t new_size) { struct yaffs_obj *obj = NULL; struct yaffs_obj *dir = NULL; @@@ -1323,14 -1312,14 +1323,14 @@@ else if(new_size < 0 || new_size > YAFFS_MAX_FILE_SIZE) yaffsfs_SetError(-EINVAL); else - result = yaffs_resize_file(obj,new_size); + result = yaffs_resize_file(obj, new_size); yaffsfs_Unlock(); return (result) ? 0 : -1; } - int yaffs_ftruncate(int handle, off_t new_size) + int yaffs_ftruncate(int handle, loff_t new_size) { yaffsfs_FileDes *fd = NULL; struct yaffs_obj *obj = NULL; @@@ -1351,19 -1340,19 +1351,19 @@@ yaffsfs_SetError(-EINVAL); else /* resize the file */ - result = yaffs_resize_file(obj,new_size); + result = yaffs_resize_file(obj, new_size); yaffsfs_Unlock(); return (result) ? 0 : -1; } - off_t yaffs_lseek(int handle, off_t offset, int whence) + loff_t yaffs_lseek(int handle, loff_t offset, int whence) { yaffsfs_FileDes *fd = NULL; struct yaffs_obj *obj = NULL; - int pos = -1; - int fSize = -1; + loff_t pos = -1; + loff_t fSize = -1; yaffsfs_Lock(); fd = yaffsfs_HandleToFileDes(handle); @@@ -2377,8 -2366,6 +2377,8 @@@ int yaffs_mkdir(const YCHAR *path, mode yaffsfs_SetError(-ELOOP); else if(!parent) yaffsfs_SetError(-ENOENT); + else if(yaffsfs_TooManyObjects(parent->my_dev)) + yaffsfs_SetError(-ENFILE); else if(strnlen(name,5) == 0){ /* Trying to make the root itself */ yaffsfs_SetError(-EEXIST); @@@ -2438,7 -2425,7 +2438,7 @@@ void * yaffs_getdev(const YCHAR *path return (void *)dev; } - int yaffs_mount2(const YCHAR *path,int read_only) + int yaffs_mount_common(const YCHAR *path,int read_only, int skip_checkpt) { int retVal=-1; int result=YAFFS_FAIL; @@@ -2464,7 -2451,15 +2464,15 @@@ if(dev){ if(!dev->is_mounted){ dev->read_only = read_only ? 1 : 0; - result = yaffs_guts_initialise(dev); + if(skip_checkpt) { + u8 skip = dev->param.skip_checkpt_rd; + dev->param.skip_checkpt_rd = 1; + result = yaffs_guts_initialise(dev); + dev->param.skip_checkpt_rd = skip; + } else { + result = yaffs_guts_initialise(dev); + } + if(result == YAFFS_FAIL) yaffsfs_SetError(-ENOMEM); retVal = result ? 0 : -1; @@@ -2480,9 -2475,13 +2488,13 @@@ } + int yaffs_mount2(const YCHAR *path, int readonly) + { + return yaffs_mount_common(path, readonly, 0); + } int yaffs_mount(const YCHAR *path) { - return yaffs_mount2(path,0); + return yaffs_mount_common(path, 0, 0); } int yaffs_sync(const YCHAR *path) @@@ -2720,14 -2719,6 +2732,14 @@@ int yaffs_inodecount(const YCHAR *path void yaffs_add_device(struct yaffs_dev *dev) { + struct list_head *cfg; + /* First check that the device is not in the list. */ + + list_for_each(cfg, &yaffsfs_deviceList){ + if(dev == list_entry(cfg, struct yaffs_dev, dev_list)) + return; + } + dev->is_mounted = 0; dev->param.remove_obj_fn = yaffsfs_RemoveObjectCallback; @@@ -2985,8 -2976,6 +2997,8 @@@ int yaffs_symlink(const YCHAR *oldpath yaffsfs_SetError(-ELOOP); else if( !parent || strnlen(name,5) < 1) yaffsfs_SetError(-ENOENT); + else if(yaffsfs_TooManyObjects(parent->my_dev)) + yaffsfs_SetError(-ENFILE); else if(parent->my_dev->read_only) yaffsfs_SetError(-EROFS); else if(parent){ @@@ -3079,8 -3068,6 +3091,8 @@@ int yaffs_link(const YCHAR *oldpath, co yaffsfs_SetError(-ENOENT); else if(obj->my_dev->read_only) yaffsfs_SetError(-EROFS); + else if(yaffsfs_TooManyObjects(obj->my_dev)) + yaffsfs_SetError(-ENFILE); else if(lnk) yaffsfs_SetError(-EEXIST); else if(lnk_dir->my_dev != obj->my_dev) diff --combined yaffs_guts.h index b6d5129,6e48d13..b3bc574 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@@ -29,6 -29,18 +29,18 @@@ */ #define YAFFS_MAGIC 0x5941ff53 + /* + * Tnodes form a tree with the tnodes in "levels" + * Levels greater than 0 hold 8 slots which point to other tnodes. + * Those at level 0 hold 16 slots which point to chunks in NAND. + * + * A maximum level of 8 thust supports files of size up to: + * + * 2^(3*MAX_LEVEL+4) + * + * Thus a max level of 8 supports files with up to 2^^28 chunks which gives + * a maximum file size of arounf 51Gbytees with 2k chunks. + */ #define YAFFS_NTNODES_LEVEL0 16 #define YAFFS_TNODES_LEVEL0_BITS 4 #define YAFFS_TNODES_LEVEL0_MASK 0xf @@@ -36,8 -48,11 +48,11 @@@ #define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2) #define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1) #define YAFFS_TNODES_INTERNAL_MASK 0x7 - #define YAFFS_TNODES_MAX_LEVEL 6 - + #define YAFFS_TNODES_MAX_LEVEL 8 + #define YAFFS_TNODES_MAX_BITS (YAFFS_TNODES_LEVEL0_BITS + \ + YAFFS_TNODES_INTERNAL_BITS * \ + YAFFS_TNODES_MAX_LEVEL) + #define YAFFS_MAX_CHUNK_ID ((1 << YAFFS_TNODES_MAX_BITS) - 1) /* Constants for YAFFS1 mode */ #define YAFFS_BYTES_PER_SPARE 16 @@@ -49,7 -64,7 +64,7 @@@ #define YAFFS_MIN_YAFFS2_CHUNK_SIZE 1024 #define YAFFS_MIN_YAFFS2_SPARE_SIZE 32 - #define YAFFS_MAX_CHUNK_ID 0x000fffff + #define YAFFS_ALLOCATION_NOBJECTS 100 #define YAFFS_ALLOCATION_NTNODES 100 @@@ -60,7 -75,7 +75,7 @@@ #define YAFFS_OBJECT_SPACE 0x40000 #define YAFFS_MAX_OBJECT_ID (YAFFS_OBJECT_SPACE - 1) - #define YAFFS_CHECKPOINT_VERSION 4 + #define YAFFS_CHECKPOINT_VERSION 5 #ifdef CONFIG_YAFFS_UNICODE #define YAFFS_MAX_NAME_LENGTH 127 @@@ -185,7 -200,7 +200,7 @@@ struct yaffs_ext_tags enum yaffs_obj_type extra_obj_type; /* What object type? */ - unsigned extra_length; /* Length if it is a file */ + loff_t extra_file_size; /* Length if it is a file */ unsigned extra_equiv_id; /* Equivalent object for a hard link */ }; @@@ -308,7 -323,7 +323,7 @@@ struct yaffs_obj_hdr u32 yst_ctime; /* File size applies to files only */ - int file_size; + u32 file_size_low; /* Equivalent object id applies to hard links only. */ int equiv_id; @@@ -325,7 -340,8 +340,8 @@@ u32 inband_shadowed_obj_id; u32 inband_is_shrink; - u32 reserved[2]; + u32 file_size_high; + u32 reserved[1]; int shadows_obj; /* This object header shadows the specified object if > 0 */ @@@ -349,9 -365,9 +365,9 @@@ struct yaffs_tnode */ struct yaffs_file_var { - u32 file_size; - u32 scanned_size; - u32 shrink_size; + loff_t file_size; + loff_t scanned_size; + loff_t shrink_size; int top_level; struct yaffs_tnode *top; }; @@@ -479,7 -495,7 +495,7 @@@ struct yaffs_checkpt_obj u8 unlink_allowed:1; u8 serial; int n_data_chunks; - u32 size_or_equiv_obj; + loff_t size_or_equiv_obj; }; /*--------------------- Temporary buffers ---------------- @@@ -587,11 -603,6 +603,11 @@@ struct yaffs_param int always_check_erased; /* Force chunk erased check always on */ int disable_summary; + + int max_objects; /* + * Set to limit the number of objects created. + * 0 = no limit. + */ }; struct yaffs_dev { @@@ -821,7 -832,7 +837,7 @@@ int yaffs_unlinker(struct yaffs_obj *di int yaffs_del_obj(struct yaffs_obj *obj); int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size); - int yaffs_get_obj_length(struct yaffs_obj *obj); + loff_t yaffs_get_obj_length(struct yaffs_obj *obj); int yaffs_get_obj_inode(struct yaffs_obj *obj); unsigned yaffs_get_obj_type(struct yaffs_obj *obj); int yaffs_get_obj_link_count(struct yaffs_obj *obj); @@@ -940,4 -951,16 +956,16 @@@ u32 yaffs_get_group_base(struct yaffs_d unsigned pos); 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. + */ + 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 yaffs_max_file_size(struct yaffs_dev *dev); + + #endif diff --combined yaffs_vfs_multi.c index fdb0137,8f6e4b5..db9f737 --- a/yaffs_vfs_multi.c +++ b/yaffs_vfs_multi.c @@@ -148,12 -148,6 +148,12 @@@ #define YAFFS_USE_WRITE_BEGIN_END 0 #endif + + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) +#define set_nlink(inode, count) do { (inode)->i_nlink = (count); } while(0) +#endif + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28)) static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) { @@@ -976,13 -970,14 +976,14 @@@ static int yaffs_readpage_nolock(struc struct yaffs_obj *obj; unsigned char *pg_buf; int ret; + loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT; struct yaffs_dev *dev; yaffs_trace(YAFFS_TRACE_OS, - "yaffs_readpage_nolock at %08x, size %08x", - (unsigned)(pg->index << PAGE_CACHE_SHIFT), - (unsigned)PAGE_CACHE_SIZE); + "yaffs_readpage_nolock at %lld, size %08x", + (long long)pos, + (unsigned)PAGE_CACHE_SIZE); obj = yaffs_dentry_to_obj(f->f_dentry); @@@ -1000,8 -995,7 +1001,7 @@@ yaffs_gross_lock(dev); - ret = yaffs_file_rd(obj, pg_buf, - pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE); + ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE); yaffs_gross_unlock(dev); @@@ -1074,9 -1068,9 +1074,9 @@@ static int yaffs_writepage(struct 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!!"); @@@ -1100,20 -1094,20 +1100,20 @@@ 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); + ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes, 0); 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); @@@ -1212,8 -1206,8 +1212,8 @@@ static int yaffs_write_end(struct file 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); @@@ -1242,17 -1236,12 +1242,12 @@@ static int yaffs_commit_write(struct fi 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); @@@ -1336,12 -1325,12 +1331,12 @@@ static void yaffs_fill_inode_from_obj(s inode->i_size = yaffs_get_obj_length(obj); inode->i_blocks = (inode->i_size + 511) >> 9; - inode->i_nlink = yaffs_get_obj_link_count(obj); + set_nlink(inode, 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 */ @@@ -1416,7 -1405,8 +1411,8 @@@ static ssize_t yaffs_file_write(struct loff_t * pos) { struct yaffs_obj *obj; - int n_written, ipos; + int n_written; + loff_t ipos; struct inode *inode; struct yaffs_dev *dev; @@@ -1440,8 -1430,8 +1436,8 @@@ 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); @@@ -1459,7 -1449,7 +1455,7 @@@ 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)); } @@@ -1750,9 -1740,10 +1746,9 @@@ static int yaffs_unlink(struct inode *d ret_val = yaffs_unlinker(obj, dentry->d_name.name); if (ret_val == YAFFS_OK) { - dentry->d_inode->i_nlink--; + inode_dec_link_count(dentry->d_inode); dir->i_version++; yaffs_gross_unlock(dev); - mark_inode_dirty(dentry->d_inode); update_dir_time(dir); return 0; } @@@ -1784,7 -1775,7 +1780,7 @@@ static int yaffs_link(struct dentry *ol obj); if (link) { - old_dentry->d_inode->i_nlink = yaffs_get_obj_link_count(obj); + set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj)); d_instantiate(dentry, old_dentry->d_inode); atomic_inc(&old_dentry->d_inode->i_count); yaffs_trace(YAFFS_TRACE_OS, @@@ -1814,14 -1805,6 +1810,14 @@@ static int yaffs_symlink(struct inode * yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink"); + if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) > + YAFFS_MAX_NAME_LENGTH) + return -ENAMETOOLONG; + + if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) > + YAFFS_MAX_ALIAS_LENGTH) + return -ENAMETOOLONG; + dev = yaffs_inode_to_obj(dir)->my_dev; yaffs_gross_lock(dev); obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name, @@@ -1910,8 -1893,10 +1906,8 @@@ static int yaffs_rename(struct inode *o yaffs_gross_unlock(dev); if (ret_val == YAFFS_OK) { - if (target) { - new_dentry->d_inode->i_nlink--; - mark_inode_dirty(new_dentry->d_inode); - } + if (target) + inode_dec_link_count(new_dentry->d_inode); update_dir_time(old_dir); if (old_dir != new_dir) @@@ -1931,10 -1916,11 +1927,11 @@@ static int yaffs_setattr(struct dentry 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); @@@ -2829,6 -2815,7 +2826,7 @@@ static struct super_block *yaffs_intern sb->u.generic_sbp = dev; #endif + dev->driver_context = mtd; param->name = mtd->name; @@@ -2950,6 -2937,8 +2948,8 @@@ if (!context->bg_thread) param->defered_dir_update = 0; + sb->s_maxbytes = yaffs_max_file_size(dev); + /* Release lock before yaffs_get_inode() */ yaffs_gross_unlock(dev); @@@ -3126,6 -3115,8 +3126,8 @@@ static char *yaffs_dump_dev_part0(char static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev) { + buf += sprintf(buf, "max file size....... %lld\n", + (long long) yaffs_max_file_size(dev)); buf += sprintf(buf, "data_bytes_per_chunk. %d\n", dev->data_bytes_per_chunk); buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits);