]> err.no Git - linux-2.6/blobdiff - fs/reiserfs/file.c
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[linux-2.6] / fs / reiserfs / file.c
index 1cad5d066a5c343705616c692fa2a9913588da38..d0c1e865963eac20acc606cc8f26089f20ad2ac1 100644 (file)
@@ -1287,6 +1287,23 @@ static ssize_t reiserfs_file_write(struct file *file,    /* the file we are going t
        struct reiserfs_transaction_handle th;
        th.t_trans_id = 0;
 
+       /* If a filesystem is converted from 3.5 to 3.6, we'll have v3.5 items
+       * lying around (most of the disk, in fact). Despite the filesystem
+       * now being a v3.6 format, the old items still can't support large
+       * file sizes. Catch this case here, as the rest of the VFS layer is
+       * oblivious to the different limitations between old and new items.
+       * reiserfs_setattr catches this for truncates. This chunk is lifted
+       * from generic_write_checks. */
+       if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 &&
+           *ppos + count > MAX_NON_LFS) {
+               if (*ppos >= MAX_NON_LFS) {
+                       send_sig(SIGXFSZ, current, 0);
+                       return -EFBIG;
+               }
+               if (count > MAX_NON_LFS - (unsigned long)*ppos)
+                       count = MAX_NON_LFS - (unsigned long)*ppos;
+       }
+
        if (file->f_flags & O_DIRECT) { // Direct IO needs treatment
                ssize_t result, after_file_end = 0;
                if ((*ppos + count >= inode->i_size)
@@ -1447,13 +1464,11 @@ static ssize_t reiserfs_file_write(struct file *file,   /* the file we are going t
                   partially overwritten pages, if needed. And lock the pages,
                   so that nobody else can access these until we are done.
                   We get number of actual blocks needed as a result. */
-               blocks_to_allocate =
-                   reiserfs_prepare_file_region_for_write(inode, pos,
-                                                          num_pages,
-                                                          write_bytes,
-                                                          prepared_pages);
-               if (blocks_to_allocate < 0) {
-                       res = blocks_to_allocate;
+               res = reiserfs_prepare_file_region_for_write(inode, pos,
+                                                            num_pages,
+                                                            write_bytes,
+                                                            prepared_pages);
+               if (res < 0) {
                        reiserfs_release_claimed_blocks(inode->i_sb,
                                                        num_pages <<
                                                        (PAGE_CACHE_SHIFT -
@@ -1461,6 +1476,8 @@ static ssize_t reiserfs_file_write(struct file *file,     /* the file we are going t
                        break;
                }
 
+               blocks_to_allocate = res;
+
                /* First we correct our estimate of how many blocks we need */
                reiserfs_release_claimed_blocks(inode->i_sb,
                                                (num_pages <<
@@ -1515,7 +1532,7 @@ static ssize_t reiserfs_file_write(struct file *file,     /* the file we are going t
                buf += write_bytes;
                *ppos = pos += write_bytes;
                count -= write_bytes;
-               balance_dirty_pages_ratelimited(inode->i_mapping);
+               balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages);
        }
 
        /* this is only true on error */
@@ -1529,10 +1546,10 @@ static ssize_t reiserfs_file_write(struct file *file,   /* the file we are going t
                }
        }
 
-       if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
-               res =
-                   generic_osync_inode(inode, file->f_mapping,
-                                       OSYNC_METADATA | OSYNC_DATA);
+       if (likely(res >= 0) &&
+           (unlikely((file->f_flags & O_SYNC) || IS_SYNC(inode))))
+               res = generic_osync_inode(inode, file->f_mapping,
+                                         OSYNC_METADATA | OSYNC_DATA);
 
        mutex_unlock(&inode->i_mutex);
        reiserfs_async_progress_wait(inode->i_sb);