Merge branch 'big-files': Merge in large file support
authorCharles Manning <cdhmanning@gmail.com>
Mon, 13 Feb 2012 02:47:12 +0000 (15:47 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Mon, 13 Feb 2012 02:47:12 +0000 (15:47 +1300)
Signed-off-by: Charles Manning <cdhmanning@gmail.com>
1  2 
direct/basic-test/dtest.c
direct/yaffsfs.c
yaffs_guts.h
yaffs_vfs_multi.c

index 35354232883e837e768f80378722f438731b3c65,0b67b7a1fd4092d15f7a5aafe3530fe0fdcc1513..4953830694c40290b699c8ef0244cb1cc9739bb6
@@@ -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);
  
  
  
         //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 37d6cae1d0cce812d4217f6444c06fbaf8360dd5,014bfc57020478d3b9a647cffae8741068b38616..b57084cb5805ca6b675d9a8287e4a69ece20ef75
@@@ -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)
  {
                        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;
        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;
                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;
        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;
  
  }
  
+ 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 b6d51299d87ffbc6ba8cac87a470b8872726249c,6e48d1361bfa5742955c669af5bed27bd8d983f8..b3bc574a51b29fe2b99159898e9ea27157a765bd
   */
  #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
  #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;
        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 fdb0137159aeb080809dd7501098d6119d054126,8f6e4b5fb9b198459d0048a82f1c1af6fdbbaf0a..db9f7376b4d43664c6c2b17112d39451e337ef76
  #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);
  
  
        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!!");
  
        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;
  
                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);
  
                        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;
  
        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);