Add large file support changes to yaffs_vfs_single.c
[yaffs2.git] / yaffs_vfs_multi.c
index b8e51243051a27fc7a17c3b79dbbfd72555699b1..ce41d6c81d8150a0ad59a70fec185c2645d167c7 100644 (file)
 #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)
 {
@@ -970,13 +976,13 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg)
        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);
 
@@ -994,8 +1000,7 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg)
 
        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);
 
@@ -1068,9 +1073,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,20 +1099,20 @@ 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);
+                                 ((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);
 
@@ -1206,8 +1211,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 +1241,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);
 
@@ -1330,12 +1330,12 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
                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 */
@@ -1410,7 +1410,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 +1435,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 +1454,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));
                }
 
@@ -1744,10 +1745,9 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
        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;
        }
@@ -1779,7 +1779,7 @@ static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
                                   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,
@@ -1809,6 +1809,14 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
 
        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,
@@ -1897,10 +1905,8 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        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)
@@ -1920,10 +1926,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);
@@ -2818,6 +2825,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        sb->u.generic_sbp = dev;
 #endif
 
+
        dev->driver_context = mtd;
        param->name = mtd->name;
 
@@ -2939,6 +2947,8 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        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);
 
@@ -3115,6 +3125,8 @@ static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
 
 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);