Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / fs / reiserfs / file.c
index 2230aff..0eea8b4 100644 (file)
@@ -2,7 +2,6 @@
  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  */
 
-
 #include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_acl.h>
 ** We use reiserfs_truncate_file to pack the tail, since it already has
 ** all the conditions coded.  
 */
-static int reiserfs_file_release (struct inode * inode, struct file * filp)
+static int reiserfs_file_release(struct inode *inode, struct file *filp)
 {
 
-    struct reiserfs_transaction_handle th ;
-    int err;
-    int jbegin_failure = 0;
+       struct reiserfs_transaction_handle th;
+       int err;
+       int jbegin_failure = 0;
 
-    if (!S_ISREG (inode->i_mode))
-       BUG ();
+       if (!S_ISREG(inode->i_mode))
+               BUG();
 
-    /* fast out for when nothing needs to be done */
-    if ((atomic_read(&inode->i_count) > 1 ||
-       !(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) || 
-         !tail_has_to_be_packed(inode))       && 
-       REISERFS_I(inode)->i_prealloc_count <= 0) {
-       return 0;
-    }    
-    
-    reiserfs_write_lock(inode->i_sb);
-    down (&inode->i_sem); 
-    /* freeing preallocation only involves relogging blocks that
-     * are already in the current transaction.  preallocation gets
-     * freed at the end of each transaction, so it is impossible for
-     * us to log any additional blocks (including quota blocks)
-     */
-    err = journal_begin(&th, inode->i_sb, 1);
-    if (err) {
-       /* uh oh, we can't allow the inode to go away while there
-        * is still preallocation blocks pending.  Try to join the
-        * aborted transaction
-        */
-       jbegin_failure = err;
-       err = journal_join_abort(&th, inode->i_sb, 1);
+       /* fast out for when nothing needs to be done */
+       if ((atomic_read(&inode->i_count) > 1 ||
+            !(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) ||
+            !tail_has_to_be_packed(inode)) &&
+           REISERFS_I(inode)->i_prealloc_count <= 0) {
+               return 0;
+       }
 
+       reiserfs_write_lock(inode->i_sb);
+       mutex_lock(&inode->i_mutex);
+       /* freeing preallocation only involves relogging blocks that
+        * are already in the current transaction.  preallocation gets
+        * freed at the end of each transaction, so it is impossible for
+        * us to log any additional blocks (including quota blocks)
+        */
+       err = journal_begin(&th, inode->i_sb, 1);
        if (err) {
-           /* hmpf, our choices here aren't good.  We can pin the inode
-            * which will disallow unmount from every happening, we can
-            * do nothing, which will corrupt random memory on unmount,
-            * or we can forcibly remove the file from the preallocation
-            * list, which will leak blocks on disk.  Lets pin the inode
-            * and let the admin know what is going on.
-            */
-           igrab(inode);
-           reiserfs_warning(inode->i_sb, "pinning inode %lu because the "
-                            "preallocation can't be freed");
-           goto out;
+               /* uh oh, we can't allow the inode to go away while there
+                * is still preallocation blocks pending.  Try to join the
+                * aborted transaction
+                */
+               jbegin_failure = err;
+               err = journal_join_abort(&th, inode->i_sb, 1);
+
+               if (err) {
+                       /* hmpf, our choices here aren't good.  We can pin the inode
+                        * which will disallow unmount from every happening, we can
+                        * do nothing, which will corrupt random memory on unmount,
+                        * or we can forcibly remove the file from the preallocation
+                        * list, which will leak blocks on disk.  Lets pin the inode
+                        * and let the admin know what is going on.
+                        */
+                       igrab(inode);
+                       reiserfs_warning(inode->i_sb,
+                                        "pinning inode %lu because the "
+                                        "preallocation can't be freed");
+                       goto out;
+               }
        }
-    }
-    reiserfs_update_inode_transaction(inode) ;
+       reiserfs_update_inode_transaction(inode);
 
 #ifdef REISERFS_PREALLOCATE
-    reiserfs_discard_prealloc (&th, inode);
+       reiserfs_discard_prealloc(&th, inode);
 #endif
-    err = journal_end(&th, inode->i_sb, 1);
-
-    /* copy back the error code from journal_begin */
-    if (!err)
-        err = jbegin_failure;
-
-    if (!err && atomic_read(&inode->i_count) <= 1 &&
-       (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) &&
-        tail_has_to_be_packed (inode)) {
-       /* if regular file is released by last holder and it has been
-          appended (we append by unformatted node only) or its direct
-          item(s) had to be converted, then it may have to be
-          indirect2direct converted */
-       err = reiserfs_truncate_file(inode, 0) ;
-    }
-out:
-    up (&inode->i_sem); 
-    reiserfs_write_unlock(inode->i_sb);
-    return err;
+       err = journal_end(&th, inode->i_sb, 1);
+
+       /* copy back the error code from journal_begin */
+       if (!err)
+               err = jbegin_failure;
+
+       if (!err && atomic_read(&inode->i_count) <= 1 &&
+           (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) &&
+           tail_has_to_be_packed(inode)) {
+               /* if regular file is released by last holder and it has been
+                  appended (we append by unformatted node only) or its direct
+                  item(s) had to be converted, then it may have to be
+                  indirect2direct converted */
+               err = reiserfs_truncate_file(inode, 0);
+       }
+      out:
+       mutex_unlock(&inode->i_mutex);
+       reiserfs_write_unlock(inode->i_sb);
+       return err;
 }
 
-static void reiserfs_vfs_truncate_file(struct inode *inode) {
-    reiserfs_truncate_file(inode, 1) ;
+static void reiserfs_vfs_truncate_file(struct inode *inode)
+{
+       reiserfs_truncate_file(inode, 1);
 }
 
 /* Sync a reiserfs file. */
@@ -116,26 +117,24 @@ static void reiserfs_vfs_truncate_file(struct inode *inode) {
  * be removed...
  */
 
-static int reiserfs_sync_file(
-                             struct file   * p_s_filp,
-                             struct dentry * p_s_dentry,
-                             int datasync
-                             ) {
-  struct inode * p_s_inode = p_s_dentry->d_inode;
-  int n_err;
-  int barrier_done;
-
-  if (!S_ISREG(p_s_inode->i_mode))
-      BUG ();
-  n_err = sync_mapping_buffers(p_s_inode->i_mapping) ;
-  reiserfs_write_lock(p_s_inode->i_sb);
-  barrier_done = reiserfs_commit_for_inode(p_s_inode);
-  reiserfs_write_unlock(p_s_inode->i_sb);
-  if (barrier_done != 1)
-      blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL);
-  if (barrier_done < 0)
-    return barrier_done;
-  return ( n_err < 0 ) ? -EIO : 0;
+static int reiserfs_sync_file(struct file *p_s_filp,
+                             struct dentry *p_s_dentry, int datasync)
+{
+       struct inode *p_s_inode = p_s_dentry->d_inode;
+       int n_err;
+       int barrier_done;
+
+       if (!S_ISREG(p_s_inode->i_mode))
+               BUG();
+       n_err = sync_mapping_buffers(p_s_inode->i_mapping);
+       reiserfs_write_lock(p_s_inode->i_sb);
+       barrier_done = reiserfs_commit_for_inode(p_s_inode);
+       reiserfs_write_unlock(p_s_inode->i_sb);
+       if (barrier_done != 1)
+               blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL);
+       if (barrier_done < 0)
+               return barrier_done;
+       return (n_err < 0) ? -EIO : 0;
 }
 
 /* I really do not want to play with memory shortage right now, so
@@ -147,700 +146,800 @@ static int reiserfs_sync_file(
 /* Allocates blocks for a file to fulfil write request.
    Maps all unmapped but prepared pages from the list.
    Updates metadata with newly allocated blocknumbers as needed */
-static int reiserfs_allocate_blocks_for_region(
-                               struct reiserfs_transaction_handle *th,
-                               struct inode *inode, /* Inode we work with */
-                               loff_t pos, /* Writing position */
-                               int num_pages, /* number of pages write going
-                                                 to touch */
-                               int write_bytes, /* amount of bytes to write */
-                               struct page **prepared_pages, /* array of
-                                                                prepared pages
-                                                              */
-                               int blocks_to_allocate /* Amount of blocks we
-                                                         need to allocate to
-                                                         fit the data into file
-                                                        */
-                               )
+static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handle *th, struct inode *inode,    /* Inode we work with */
+                                              loff_t pos,      /* Writing position */
+                                              int num_pages,   /* number of pages write going
+                                                                  to touch */
+                                              int write_bytes, /* amount of bytes to write */
+                                              struct page **prepared_pages,    /* array of
+                                                                                  prepared pages
+                                                                                */
+                                              int blocks_to_allocate   /* Amount of blocks we
+                                                                          need to allocate to
+                                                                          fit the data into file
+                                                                        */
+    )
 {
-    struct cpu_key key; // cpu key of item that we are going to deal with
-    struct item_head *ih; // pointer to item head that we are going to deal with
-    struct buffer_head *bh; // Buffer head that contains items that we are going to deal with
-    __le32 * item; // pointer to item we are going to deal with
-    INITIALIZE_PATH(path); // path to item, that we are going to deal with.
-    b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored.
-    reiserfs_blocknr_hint_t hint; // hint structure for block allocator.
-    size_t res; // return value of various functions that we call.
-    int curr_block; // current block used to keep track of unmapped blocks.
-    int i; // loop counter
-    int itempos; // position in item
-    unsigned int from = (pos & (PAGE_CACHE_SIZE - 1)); // writing position in
-                                                      // first page
-    unsigned int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1; /* last modified byte offset in last page */
-    __u64 hole_size ; // amount of blocks for a file hole, if it needed to be created.
-    int modifying_this_item = 0; // Flag for items traversal code to keep track
-                                // of the fact that we already prepared
-                                // current block for journal
-    int will_prealloc = 0;
-    RFALSE(!blocks_to_allocate, "green-9004: tried to allocate zero blocks?");
-
-    /* only preallocate if this is a small write */
-    if (REISERFS_I(inode)->i_prealloc_count ||
-       (!(write_bytes & (inode->i_sb->s_blocksize -1)) &&
-        blocks_to_allocate <
-        REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize))
-        will_prealloc = REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize;
-
-    allocated_blocks = kmalloc((blocks_to_allocate + will_prealloc) *
-                                       sizeof(b_blocknr_t), GFP_NOFS);
-
-    /* First we compose a key to point at the writing position, we want to do
-       that outside of any locking region. */
-    make_cpu_key (&key, inode, pos+1, TYPE_ANY, 3/*key length*/);
-
-    /* If we came here, it means we absolutely need to open a transaction,
-       since we need to allocate some blocks */
-    reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that.
-    res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS); // Wish I know if this number enough
-    if (res)
-        goto error_exit;
-    reiserfs_update_inode_transaction(inode) ;
-
-    /* Look for the in-tree position of our write, need path for block allocator */
-    res = search_for_position_by_key(inode->i_sb, &key, &path);
-    if ( res == IO_ERROR ) {
-       res = -EIO;
-       goto error_exit;
-    }
-   
-    /* Allocate blocks */
-    /* First fill in "hint" structure for block allocator */
-    hint.th = th; // transaction handle.
-    hint.path = &path; // Path, so that block allocator can determine packing locality or whatever it needs to determine.
-    hint.inode = inode; // Inode is needed by block allocator too.
-    hint.search_start = 0; // We have no hint on where to search free blocks for block allocator.
-    hint.key = key.on_disk_key; // on disk key of file.
-    hint.block = inode->i_blocks>>(inode->i_sb->s_blocksize_bits-9); // Number of disk blocks this file occupies already.
-    hint.formatted_node = 0; // We are allocating blocks for unformatted node.
-    hint.preallocate = will_prealloc;
-
-    /* Call block allocator to allocate blocks */
-    res = reiserfs_allocate_blocknrs(&hint, allocated_blocks, blocks_to_allocate, blocks_to_allocate);
-    if ( res != CARRY_ON ) {
-       if ( res == NO_DISK_SPACE ) {
-           /* We flush the transaction in case of no space. This way some
-              blocks might become free */
-           SB_JOURNAL(inode->i_sb)->j_must_wait = 1;
-           res = restart_transaction(th, inode, &path);
-            if (res)
-                goto error_exit;
-
-           /* We might have scheduled, so search again */
-           res = search_for_position_by_key(inode->i_sb, &key, &path);
-           if ( res == IO_ERROR ) {
-               res = -EIO;
+       struct cpu_key key;     // cpu key of item that we are going to deal with
+       struct item_head *ih;   // pointer to item head that we are going to deal with
+       struct buffer_head *bh; // Buffer head that contains items that we are going to deal with
+       __le32 *item;           // pointer to item we are going to deal with
+       INITIALIZE_PATH(path);  // path to item, that we are going to deal with.
+       b_blocknr_t *allocated_blocks;  // Pointer to a place where allocated blocknumbers would be stored.
+       reiserfs_blocknr_hint_t hint;   // hint structure for block allocator.
+       size_t res;             // return value of various functions that we call.
+       int curr_block;         // current block used to keep track of unmapped blocks.
+       int i;                  // loop counter
+       int itempos;            // position in item
+       unsigned int from = (pos & (PAGE_CACHE_SIZE - 1));      // writing position in
+       // first page
+       unsigned int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1;        /* last modified byte offset in last page */
+       __u64 hole_size;        // amount of blocks for a file hole, if it needed to be created.
+       int modifying_this_item = 0;    // Flag for items traversal code to keep track
+       // of the fact that we already prepared
+       // current block for journal
+       int will_prealloc = 0;
+       RFALSE(!blocks_to_allocate,
+              "green-9004: tried to allocate zero blocks?");
+
+       /* only preallocate if this is a small write */
+       if (REISERFS_I(inode)->i_prealloc_count ||
+           (!(write_bytes & (inode->i_sb->s_blocksize - 1)) &&
+            blocks_to_allocate <
+            REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize))
+               will_prealloc =
+                   REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize;
+
+       allocated_blocks = kmalloc((blocks_to_allocate + will_prealloc) *
+                                  sizeof(b_blocknr_t), GFP_NOFS);
+       if (!allocated_blocks)
+               return -ENOMEM;
+
+       /* First we compose a key to point at the writing position, we want to do
+          that outside of any locking region. */
+       make_cpu_key(&key, inode, pos + 1, TYPE_ANY, 3 /*key length */ );
+
+       /* If we came here, it means we absolutely need to open a transaction,
+          since we need to allocate some blocks */
+       reiserfs_write_lock(inode->i_sb);       // Journaling stuff and we need that.
+       res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb));   // Wish I know if this number enough
+       if (res)
                goto error_exit;
-           }
+       reiserfs_update_inode_transaction(inode);
 
-           /* update changed info for hint structure. */
-           res = reiserfs_allocate_blocknrs(&hint, allocated_blocks, blocks_to_allocate, blocks_to_allocate);
-           if ( res != CARRY_ON ) {
-               res = -ENOSPC; 
-               pathrelse(&path);
+       /* Look for the in-tree position of our write, need path for block allocator */
+       res = search_for_position_by_key(inode->i_sb, &key, &path);
+       if (res == IO_ERROR) {
+               res = -EIO;
                goto error_exit;
-           }
-       } else {
-           res = -ENOSPC;
-           pathrelse(&path);
-           goto error_exit;
        }
-    }
 
-#ifdef __BIG_ENDIAN
-        // Too bad, I have not found any way to convert a given region from
-        // cpu format to little endian format
-    {
-        int i;
-        for ( i = 0; i < blocks_to_allocate ; i++)
-            allocated_blocks[i]=cpu_to_le32(allocated_blocks[i]);
-    }
-#endif
-
-    /* Blocks allocating well might have scheduled and tree might have changed,
-       let's search the tree again */
-    /* find where in the tree our write should go */
-    res = search_for_position_by_key(inode->i_sb, &key, &path);
-    if ( res == IO_ERROR ) {
-       res = -EIO;
-       goto error_exit_free_blocks;
-    }
-
-    bh = get_last_bh( &path ); // Get a bufferhead for last element in path.
-    ih = get_ih( &path );      // Get a pointer to last item head in path.
-    item = get_item( &path );  // Get a pointer to last item in path
-
-    /* Let's see what we have found */
-    if ( res != POSITION_FOUND ) { /* position not found, this means that we
-                                     might need to append file with holes
-                                     first */
-       // Since we are writing past the file's end, we need to find out if
-       // there is a hole that needs to be inserted before our writing
-       // position, and how many blocks it is going to cover (we need to
-       //  populate pointers to file blocks representing the hole with zeros)
+       /* Allocate blocks */
+       /* First fill in "hint" structure for block allocator */
+       hint.th = th;           // transaction handle.
+       hint.path = &path;      // Path, so that block allocator can determine packing locality or whatever it needs to determine.
+       hint.inode = inode;     // Inode is needed by block allocator too.
+       hint.search_start = 0;  // We have no hint on where to search free blocks for block allocator.
+       hint.key = key.on_disk_key;     // on disk key of file.
+       hint.block = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9);    // Number of disk blocks this file occupies already.
+       hint.formatted_node = 0;        // We are allocating blocks for unformatted node.
+       hint.preallocate = will_prealloc;
+
+       /* Call block allocator to allocate blocks */
+       res =
+           reiserfs_allocate_blocknrs(&hint, allocated_blocks,
+                                      blocks_to_allocate, blocks_to_allocate);
+       if (res != CARRY_ON) {
+               if (res == NO_DISK_SPACE) {
+                       /* We flush the transaction in case of no space. This way some
+                          blocks might become free */
+                       SB_JOURNAL(inode->i_sb)->j_must_wait = 1;
+                       res = restart_transaction(th, inode, &path);
+                       if (res)
+                               goto error_exit;
+
+                       /* We might have scheduled, so search again */
+                       res =
+                           search_for_position_by_key(inode->i_sb, &key,
+                                                      &path);
+                       if (res == IO_ERROR) {
+                               res = -EIO;
+                               goto error_exit;
+                       }
 
+                       /* update changed info for hint structure. */
+                       res =
+                           reiserfs_allocate_blocknrs(&hint, allocated_blocks,
+                                                      blocks_to_allocate,
+                                                      blocks_to_allocate);
+                       if (res != CARRY_ON) {
+                               res = res == QUOTA_EXCEEDED ? -EDQUOT : -ENOSPC;
+                               pathrelse(&path);
+                               goto error_exit;
+                       }
+               } else {
+                       res = res == QUOTA_EXCEEDED ? -EDQUOT : -ENOSPC;
+                       pathrelse(&path);
+                       goto error_exit;
+               }
+       }
+#ifdef __BIG_ENDIAN
+       // Too bad, I have not found any way to convert a given region from
+       // cpu format to little endian format
        {
-           int item_offset = 1;
-           /*
-            * if ih is stat data, its offset is 0 and we don't want to
-            * add 1 to pos in the hole_size calculation
-            */
-           if (is_statdata_le_ih(ih))
-               item_offset = 0;
-           hole_size = (pos + item_offset -
-                   (le_key_k_offset( get_inode_item_key_version(inode),
-                   &(ih->ih_key)) +
-                   op_bytes_number(ih, inode->i_sb->s_blocksize))) >>
-                   inode->i_sb->s_blocksize_bits;
+               int i;
+               for (i = 0; i < blocks_to_allocate; i++)
+                       allocated_blocks[i] = cpu_to_le32(allocated_blocks[i]);
        }
+#endif
 
-       if ( hole_size > 0 ) {
-           int to_paste = min_t(__u64, hole_size, MAX_ITEM_LEN(inode->i_sb->s_blocksize)/UNFM_P_SIZE ); // How much data to insert first time.
-           /* area filled with zeroes, to supply as list of zero blocknumbers
-              We allocate it outside of loop just in case loop would spin for
-              several iterations. */
-           char *zeros = kmalloc(to_paste*UNFM_P_SIZE, GFP_ATOMIC); // We cannot insert more than MAX_ITEM_LEN bytes anyway.
-           if ( !zeros ) {
-               res = -ENOMEM;
+       /* Blocks allocating well might have scheduled and tree might have changed,
+          let's search the tree again */
+       /* find where in the tree our write should go */
+       res = search_for_position_by_key(inode->i_sb, &key, &path);
+       if (res == IO_ERROR) {
+               res = -EIO;
                goto error_exit_free_blocks;
-           }
-           memset ( zeros, 0, to_paste*UNFM_P_SIZE);
-           do {
-               to_paste = min_t(__u64, hole_size, MAX_ITEM_LEN(inode->i_sb->s_blocksize)/UNFM_P_SIZE );
-               if ( is_indirect_le_ih(ih) ) {
-                   /* Ok, there is existing indirect item already. Need to append it */
-                   /* Calculate position past inserted item */
-                   make_cpu_key( &key, inode, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize), TYPE_INDIRECT, 3);
-                   res = reiserfs_paste_into_item( th, &path, &key, inode, (char *)zeros, UNFM_P_SIZE*to_paste);
-                   if ( res ) {
-                       kfree(zeros);
-                       goto error_exit_free_blocks;
-                   }
-               } else if ( is_statdata_le_ih(ih) ) {
-                   /* No existing item, create it */
-                   /* item head for new item */
-                   struct item_head ins_ih;
-
-                   /* create a key for our new item */
-                   make_cpu_key( &key, inode, 1, TYPE_INDIRECT, 3);
-
-                   /* Create new item head for our new item */
-                   make_le_item_head (&ins_ih, &key, key.version, 1,
-                                      TYPE_INDIRECT, to_paste*UNFM_P_SIZE,
-                                      0 /* free space */);
-
-                   /* Find where such item should live in the tree */
-                   res = search_item (inode->i_sb, &key, &path);
-                   if ( res != ITEM_NOT_FOUND ) {
-                       /* item should not exist, otherwise we have error */
-                       if ( res != -ENOSPC ) {
-                           reiserfs_warning (inode->i_sb,
-                               "green-9008: search_by_key (%K) returned %d",
-                                             &key, res);
+       }
+
+       bh = get_last_bh(&path);        // Get a bufferhead for last element in path.
+       ih = get_ih(&path);     // Get a pointer to last item head in path.
+       item = get_item(&path); // Get a pointer to last item in path
+
+       /* Let's see what we have found */
+       if (res != POSITION_FOUND) {    /* position not found, this means that we
+                                          might need to append file with holes
+                                          first */
+               // Since we are writing past the file's end, we need to find out if
+               // there is a hole that needs to be inserted before our writing
+               // position, and how many blocks it is going to cover (we need to
+               //  populate pointers to file blocks representing the hole with zeros)
+
+               {
+                       int item_offset = 1;
+                       /*
+                        * if ih is stat data, its offset is 0 and we don't want to
+                        * add 1 to pos in the hole_size calculation
+                        */
+                       if (is_statdata_le_ih(ih))
+                               item_offset = 0;
+                       hole_size = (pos + item_offset -
+                                    (le_key_k_offset
+                                     (get_inode_item_key_version(inode),
+                                      &(ih->ih_key)) + op_bytes_number(ih,
+                                                                       inode->
+                                                                       i_sb->
+                                                                       s_blocksize)))
+                           >> inode->i_sb->s_blocksize_bits;
+               }
+
+               if (hole_size > 0) {
+                       int to_paste = min_t(__u64, hole_size, MAX_ITEM_LEN(inode->i_sb->s_blocksize) / UNFM_P_SIZE);   // How much data to insert first time.
+                       /* area filled with zeroes, to supply as list of zero blocknumbers
+                          We allocate it outside of loop just in case loop would spin for
+                          several iterations. */
+                       char *zeros = kmalloc(to_paste * UNFM_P_SIZE, GFP_ATOMIC);      // We cannot insert more than MAX_ITEM_LEN bytes anyway.
+                       if (!zeros) {
+                               res = -ENOMEM;
+                               goto error_exit_free_blocks;
                        }
-                       res = -EIO;
-                       kfree(zeros);
-                       goto error_exit_free_blocks;
-                   }
-                   res = reiserfs_insert_item( th, &path, &key, &ins_ih, inode, (char *)zeros);
-               } else {
-                   reiserfs_panic(inode->i_sb, "green-9011: Unexpected key type %K\n", &key);
+                       memset(zeros, 0, to_paste * UNFM_P_SIZE);
+                       do {
+                               to_paste =
+                                   min_t(__u64, hole_size,
+                                         MAX_ITEM_LEN(inode->i_sb->
+                                                      s_blocksize) /
+                                         UNFM_P_SIZE);
+                               if (is_indirect_le_ih(ih)) {
+                                       /* Ok, there is existing indirect item already. Need to append it */
+                                       /* Calculate position past inserted item */
+                                       make_cpu_key(&key, inode,
+                                                    le_key_k_offset
+                                                    (get_inode_item_key_version
+                                                     (inode),
+                                                     &(ih->ih_key)) +
+                                                    op_bytes_number(ih,
+                                                                    inode->
+                                                                    i_sb->
+                                                                    s_blocksize),
+                                                    TYPE_INDIRECT, 3);
+                                       res =
+                                           reiserfs_paste_into_item(th, &path,
+                                                                    &key,
+                                                                    inode,
+                                                                    (char *)
+                                                                    zeros,
+                                                                    UNFM_P_SIZE
+                                                                    *
+                                                                    to_paste);
+                                       if (res) {
+                                               kfree(zeros);
+                                               goto error_exit_free_blocks;
+                                       }
+                               } else if (is_statdata_le_ih(ih)) {
+                                       /* No existing item, create it */
+                                       /* item head for new item */
+                                       struct item_head ins_ih;
+
+                                       /* create a key for our new item */
+                                       make_cpu_key(&key, inode, 1,
+                                                    TYPE_INDIRECT, 3);
+
+                                       /* Create new item head for our new item */
+                                       make_le_item_head(&ins_ih, &key,
+                                                         key.version, 1,
+                                                         TYPE_INDIRECT,
+                                                         to_paste *
+                                                         UNFM_P_SIZE,
+                                                         0 /* free space */ );
+
+                                       /* Find where such item should live in the tree */
+                                       res =
+                                           search_item(inode->i_sb, &key,
+                                                       &path);
+                                       if (res != ITEM_NOT_FOUND) {
+                                               /* item should not exist, otherwise we have error */
+                                               if (res != -ENOSPC) {
+                                                       reiserfs_warning(inode->
+                                                                        i_sb,
+                                                                        "green-9008: search_by_key (%K) returned %d",
+                                                                        &key,
+                                                                        res);
+                                               }
+                                               res = -EIO;
+                                               kfree(zeros);
+                                               goto error_exit_free_blocks;
+                                       }
+                                       res =
+                                           reiserfs_insert_item(th, &path,
+                                                                &key, &ins_ih,
+                                                                inode,
+                                                                (char *)zeros);
+                               } else {
+                                       reiserfs_panic(inode->i_sb,
+                                                      "green-9011: Unexpected key type %K\n",
+                                                      &key);
+                               }
+                               if (res) {
+                                       kfree(zeros);
+                                       goto error_exit_free_blocks;
+                               }
+                               /* Now we want to check if transaction is too full, and if it is
+                                  we restart it. This will also free the path. */
+                               if (journal_transaction_should_end
+                                   (th, th->t_blocks_allocated)) {
+                                       res =
+                                           restart_transaction(th, inode,
+                                                               &path);
+                                       if (res) {
+                                               pathrelse(&path);
+                                               kfree(zeros);
+                                               goto error_exit;
+                                       }
+                               }
+
+                               /* Well, need to recalculate path and stuff */
+                               set_cpu_key_k_offset(&key,
+                                                    cpu_key_k_offset(&key) +
+                                                    (to_paste << inode->
+                                                     i_blkbits));
+                               res =
+                                   search_for_position_by_key(inode->i_sb,
+                                                              &key, &path);
+                               if (res == IO_ERROR) {
+                                       res = -EIO;
+                                       kfree(zeros);
+                                       goto error_exit_free_blocks;
+                               }
+                               bh = get_last_bh(&path);
+                               ih = get_ih(&path);
+                               item = get_item(&path);
+                               hole_size -= to_paste;
+                       } while (hole_size);
+                       kfree(zeros);
                }
-               if ( res ) {
-                   kfree(zeros);
-                   goto error_exit_free_blocks;
+       }
+       // Go through existing indirect items first
+       // replace all zeroes with blocknumbers from list
+       // Note that if no corresponding item was found, by previous search,
+       // it means there are no existing in-tree representation for file area
+       // we are going to overwrite, so there is nothing to scan through for holes.
+       for (curr_block = 0, itempos = path.pos_in_item;
+            curr_block < blocks_to_allocate && res == POSITION_FOUND;) {
+             retry:
+
+               if (itempos >= ih_item_len(ih) / UNFM_P_SIZE) {
+                       /* We run out of data in this indirect item, let's look for another
+                          one. */
+                       /* First if we are already modifying current item, log it */
+                       if (modifying_this_item) {
+                               journal_mark_dirty(th, inode->i_sb, bh);
+                               modifying_this_item = 0;
+                       }
+                       /* Then set the key to look for a new indirect item (offset of old
+                          item is added to old item length */
+                       set_cpu_key_k_offset(&key,
+                                            le_key_k_offset
+                                            (get_inode_item_key_version(inode),
+                                             &(ih->ih_key)) +
+                                            op_bytes_number(ih,
+                                                            inode->i_sb->
+                                                            s_blocksize));
+                       /* Search ofor position of new key in the tree. */
+                       res =
+                           search_for_position_by_key(inode->i_sb, &key,
+                                                      &path);
+                       if (res == IO_ERROR) {
+                               res = -EIO;
+                               goto error_exit_free_blocks;
+                       }
+                       bh = get_last_bh(&path);
+                       ih = get_ih(&path);
+                       item = get_item(&path);
+                       itempos = path.pos_in_item;
+                       continue;       // loop to check all kinds of conditions and so on.
                }
-               /* Now we want to check if transaction is too full, and if it is
-                  we restart it. This will also free the path. */
-               if (journal_transaction_should_end(th, th->t_blocks_allocated)) {
-                   res = restart_transaction(th, inode, &path);
-                    if (res) {
-                        pathrelse (&path);
-                        kfree(zeros);
-                        goto error_exit;
-                    }
-                }
-
-               /* Well, need to recalculate path and stuff */
-               set_cpu_key_k_offset( &key, cpu_key_k_offset(&key) + (to_paste << inode->i_blkbits));
-               res = search_for_position_by_key(inode->i_sb, &key, &path);
-               if ( res == IO_ERROR ) {
-                   res = -EIO;
-                   kfree(zeros);
-                   goto error_exit_free_blocks;
+               /* Ok, we have correct position in item now, so let's see if it is
+                  representing file hole (blocknumber is zero) and fill it if needed */
+               if (!item[itempos]) {
+                       /* Ok, a hole. Now we need to check if we already prepared this
+                          block to be journaled */
+                       while (!modifying_this_item) {  // loop until succeed
+                               /* Well, this item is not journaled yet, so we must prepare
+                                  it for journal first, before we can change it */
+                               struct item_head tmp_ih;        // We copy item head of found item,
+                               // here to detect if fs changed under
+                               // us while we were preparing for
+                               // journal.
+                               int fs_gen;     // We store fs generation here to find if someone
+                               // changes fs under our feet
+
+                               copy_item_head(&tmp_ih, ih);    // Remember itemhead
+                               fs_gen = get_generation(inode->i_sb);   // remember fs generation
+                               reiserfs_prepare_for_journal(inode->i_sb, bh, 1);       // Prepare a buffer within which indirect item is stored for changing.
+                               if (fs_changed(fs_gen, inode->i_sb)
+                                   && item_moved(&tmp_ih, &path)) {
+                                       // Sigh, fs was changed under us, we need to look for new
+                                       // location of item we are working with
+
+                                       /* unmark prepaerd area as journaled and search for it's
+                                          new position */
+                                       reiserfs_restore_prepared_buffer(inode->
+                                                                        i_sb,
+                                                                        bh);
+                                       res =
+                                           search_for_position_by_key(inode->
+                                                                      i_sb,
+                                                                      &key,
+                                                                      &path);
+                                       if (res == IO_ERROR) {
+                                               res = -EIO;
+                                               goto error_exit_free_blocks;
+                                       }
+                                       bh = get_last_bh(&path);
+                                       ih = get_ih(&path);
+                                       item = get_item(&path);
+                                       itempos = path.pos_in_item;
+                                       goto retry;
+                               }
+                               modifying_this_item = 1;
+                       }
+                       item[itempos] = allocated_blocks[curr_block];   // Assign new block
+                       curr_block++;
                }
-               bh=get_last_bh(&path);
-               ih=get_ih(&path);
-               item = get_item(&path);
-               hole_size -= to_paste;
-           } while ( hole_size );
-           kfree(zeros);
+               itempos++;
        }
-    }
-
-    // Go through existing indirect items first
-    // replace all zeroes with blocknumbers from list
-    // Note that if no corresponding item was found, by previous search,
-    // it means there are no existing in-tree representation for file area
-    // we are going to overwrite, so there is nothing to scan through for holes.
-    for ( curr_block = 0, itempos = path.pos_in_item ; curr_block < blocks_to_allocate && res == POSITION_FOUND ; ) {
-retry:
-
-       if ( itempos >= ih_item_len(ih)/UNFM_P_SIZE ) {
-           /* We run out of data in this indirect item, let's look for another
-              one. */
-           /* First if we are already modifying current item, log it */
-           if ( modifying_this_item ) {
-               journal_mark_dirty (th, inode->i_sb, bh);
-               modifying_this_item = 0;
-           }
-           /* Then set the key to look for a new indirect item (offset of old
-              item is added to old item length */
-           set_cpu_key_k_offset( &key, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize));
-           /* Search ofor position of new key in the tree. */
-           res = search_for_position_by_key(inode->i_sb, &key, &path);
-           if ( res == IO_ERROR) {
-               res = -EIO;
-               goto error_exit_free_blocks;
-           }
-           bh=get_last_bh(&path);
-           ih=get_ih(&path);
-           item = get_item(&path);
-           itempos = path.pos_in_item;
-           continue; // loop to check all kinds of conditions and so on.
+
+       if (modifying_this_item) {      // We need to log last-accessed block, if it
+               // was modified, but not logged yet.
+               journal_mark_dirty(th, inode->i_sb, bh);
        }
-       /* Ok, we have correct position in item now, so let's see if it is
-          representing file hole (blocknumber is zero) and fill it if needed */
-       if ( !item[itempos] ) {
-           /* Ok, a hole. Now we need to check if we already prepared this
-              block to be journaled */
-           while ( !modifying_this_item ) { // loop until succeed
-               /* Well, this item is not journaled yet, so we must prepare
-                  it for journal first, before we can change it */
-               struct item_head tmp_ih; // We copy item head of found item,
-                                        // here to detect if fs changed under
-                                        // us while we were preparing for
-                                        // journal.
-               int fs_gen; // We store fs generation here to find if someone
-                           // changes fs under our feet
-
-               copy_item_head (&tmp_ih, ih); // Remember itemhead
-               fs_gen = get_generation (inode->i_sb); // remember fs generation
-               reiserfs_prepare_for_journal(inode->i_sb, bh, 1); // Prepare a buffer within which indirect item is stored for changing.
-               if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {
-                   // Sigh, fs was changed under us, we need to look for new
-                   // location of item we are working with
-
-                   /* unmark prepaerd area as journaled and search for it's
-                      new position */
-                   reiserfs_restore_prepared_buffer(inode->i_sb, bh);
-                   res = search_for_position_by_key(inode->i_sb, &key, &path);
-                   if ( res == IO_ERROR) {
-                       res = -EIO;
-                       goto error_exit_free_blocks;
-                   }
-                   bh=get_last_bh(&path);
-                   ih=get_ih(&path);
-                   item = get_item(&path);
-                   itempos = path.pos_in_item;
-                   goto retry;
+
+       if (curr_block < blocks_to_allocate) {
+               // Oh, well need to append to indirect item, or to create indirect item
+               // if there weren't any
+               if (is_indirect_le_ih(ih)) {
+                       // Existing indirect item - append. First calculate key for append
+                       // position. We do not need to recalculate path as it should
+                       // already point to correct place.
+                       make_cpu_key(&key, inode,
+                                    le_key_k_offset(get_inode_item_key_version
+                                                    (inode),
+                                                    &(ih->ih_key)) +
+                                    op_bytes_number(ih,
+                                                    inode->i_sb->s_blocksize),
+                                    TYPE_INDIRECT, 3);
+                       res =
+                           reiserfs_paste_into_item(th, &path, &key, inode,
+                                                    (char *)(allocated_blocks +
+                                                             curr_block),
+                                                    UNFM_P_SIZE *
+                                                    (blocks_to_allocate -
+                                                     curr_block));
+                       if (res) {
+                               goto error_exit_free_blocks;
+                       }
+               } else if (is_statdata_le_ih(ih)) {
+                       // Last found item was statdata. That means we need to create indirect item.
+                       struct item_head ins_ih;        /* itemhead for new item */
+
+                       /* create a key for our new item */
+                       make_cpu_key(&key, inode, 1, TYPE_INDIRECT, 3); // Position one,
+                       // because that's
+                       // where first
+                       // indirect item
+                       // begins
+                       /* Create new item head for our new item */
+                       make_le_item_head(&ins_ih, &key, key.version, 1,
+                                         TYPE_INDIRECT,
+                                         (blocks_to_allocate -
+                                          curr_block) * UNFM_P_SIZE,
+                                         0 /* free space */ );
+                       /* Find where such item should live in the tree */
+                       res = search_item(inode->i_sb, &key, &path);
+                       if (res != ITEM_NOT_FOUND) {
+                               /* Well, if we have found such item already, or some error
+                                  occured, we need to warn user and return error */
+                               if (res != -ENOSPC) {
+                                       reiserfs_warning(inode->i_sb,
+                                                        "green-9009: search_by_key (%K) "
+                                                        "returned %d", &key,
+                                                        res);
+                               }
+                               res = -EIO;
+                               goto error_exit_free_blocks;
+                       }
+                       /* Insert item into the tree with the data as its body */
+                       res =
+                           reiserfs_insert_item(th, &path, &key, &ins_ih,
+                                                inode,
+                                                (char *)(allocated_blocks +
+                                                         curr_block));
+               } else {
+                       reiserfs_panic(inode->i_sb,
+                                      "green-9010: unexpected item type for key %K\n",
+                                      &key);
                }
-               modifying_this_item = 1;
-           }
-           item[itempos] = allocated_blocks[curr_block]; // Assign new block
-           curr_block++;
        }
-       itempos++;
-    }
-
-    if ( modifying_this_item ) { // We need to log last-accessed block, if it
-                                // was modified, but not logged yet.
-       journal_mark_dirty (th, inode->i_sb, bh);
-    }
-
-    if ( curr_block < blocks_to_allocate ) {
-       // Oh, well need to append to indirect item, or to create indirect item
-       // if there weren't any
-       if ( is_indirect_le_ih(ih) ) {
-           // Existing indirect item - append. First calculate key for append
-           // position. We do not need to recalculate path as it should
-           // already point to correct place.
-           make_cpu_key( &key, inode, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize), TYPE_INDIRECT, 3);
-           res = reiserfs_paste_into_item( th, &path, &key, inode, (char *)(allocated_blocks+curr_block), UNFM_P_SIZE*(blocks_to_allocate-curr_block));
-           if ( res ) {
-               goto error_exit_free_blocks;
-           }
-       } else if (is_statdata_le_ih(ih) ) {
-           // Last found item was statdata. That means we need to create indirect item.
-           struct item_head ins_ih; /* itemhead for new item */
-
-           /* create a key for our new item */
-           make_cpu_key( &key, inode, 1, TYPE_INDIRECT, 3); // Position one,
-                                                           // because that's
-                                                           // where first
-                                                           // indirect item
-                                                           // begins
-           /* Create new item head for our new item */
-           make_le_item_head (&ins_ih, &key, key.version, 1, TYPE_INDIRECT,
-                              (blocks_to_allocate-curr_block)*UNFM_P_SIZE,
-                              0 /* free space */);
-           /* Find where such item should live in the tree */
-           res = search_item (inode->i_sb, &key, &path);
-           if ( res != ITEM_NOT_FOUND ) {
-               /* Well, if we have found such item already, or some error
-                  occured, we need to warn user and return error */
-               if ( res != -ENOSPC ) {
-                   reiserfs_warning (inode->i_sb,
-                                     "green-9009: search_by_key (%K) "
-                                     "returned %d", &key, res);
+       // the caller is responsible for closing the transaction
+       // unless we return an error, they are also responsible for logging
+       // the inode.
+       //
+       pathrelse(&path);
+       /*
+        * cleanup prellocation from previous writes
+        * if this is a partial block write
+        */
+       if (write_bytes & (inode->i_sb->s_blocksize - 1))
+               reiserfs_discard_prealloc(th, inode);
+       reiserfs_write_unlock(inode->i_sb);
+
+       // go through all the pages/buffers and map the buffers to newly allocated
+       // blocks (so that system knows where to write these pages later).
+       curr_block = 0;
+       for (i = 0; i < num_pages; i++) {
+               struct page *page = prepared_pages[i];  //current page
+               struct buffer_head *head = page_buffers(page);  // first buffer for a page
+               int block_start, block_end;     // in-page offsets for buffers.
+
+               if (!page_buffers(page))
+                       reiserfs_panic(inode->i_sb,
+                                      "green-9005: No buffers for prepared page???");
+
+               /* For each buffer in page */
+               for (bh = head, block_start = 0; bh != head || !block_start;
+                    block_start = block_end, bh = bh->b_this_page) {
+                       if (!bh)
+                               reiserfs_panic(inode->i_sb,
+                                              "green-9006: Allocated but absent buffer for a page?");
+                       block_end = block_start + inode->i_sb->s_blocksize;
+                       if (i == 0 && block_end <= from)
+                               /* if this buffer is before requested data to map, skip it */
+                               continue;
+                       if (i == num_pages - 1 && block_start >= to)
+                               /* If this buffer is after requested data to map, abort
+                                  processing of current page */
+                               break;
+
+                       if (!buffer_mapped(bh)) {       // Ok, unmapped buffer, need to map it
+                               map_bh(bh, inode->i_sb,
+                                      le32_to_cpu(allocated_blocks
+                                                  [curr_block]));
+                               curr_block++;
+                               set_buffer_new(bh);
+                       }
                }
-               res = -EIO;
-               goto error_exit_free_blocks;
-           }
-           /* Insert item into the tree with the data as its body */
-           res = reiserfs_insert_item( th, &path, &key, &ins_ih, inode, (char *)(allocated_blocks+curr_block));
-       } else {
-           reiserfs_panic(inode->i_sb, "green-9010: unexpected item type for key %K\n",&key);
-       }
-    }
-
-    // the caller is responsible for closing the transaction
-    // unless we return an error, they are also responsible for logging
-    // the inode.
-    //
-    pathrelse(&path);
-    /*
-     * cleanup prellocation from previous writes
-     * if this is a partial block write
-     */
-    if (write_bytes & (inode->i_sb->s_blocksize -1))
-        reiserfs_discard_prealloc(th, inode);
-    reiserfs_write_unlock(inode->i_sb);
-
-    // go through all the pages/buffers and map the buffers to newly allocated
-    // blocks (so that system knows where to write these pages later).
-    curr_block = 0;
-    for ( i = 0; i < num_pages ; i++ ) {
-       struct page *page=prepared_pages[i]; //current page
-       struct buffer_head *head = page_buffers(page);// first buffer for a page
-       int block_start, block_end; // in-page offsets for buffers.
-
-       if (!page_buffers(page))
-           reiserfs_panic(inode->i_sb, "green-9005: No buffers for prepared page???");
-
-       /* For each buffer in page */
-       for(bh = head, block_start = 0; bh != head || !block_start;
-           block_start=block_end, bh = bh->b_this_page) {
-           if (!bh)
-               reiserfs_panic(inode->i_sb, "green-9006: Allocated but absent buffer for a page?");
-           block_end = block_start+inode->i_sb->s_blocksize;
-           if (i == 0 && block_end <= from )
-               /* if this buffer is before requested data to map, skip it */
-               continue;
-           if (i == num_pages - 1 && block_start >= to)
-               /* If this buffer is after requested data to map, abort
-                  processing of current page */
-               break;
-
-           if ( !buffer_mapped(bh) ) { // Ok, unmapped buffer, need to map it
-               map_bh( bh, inode->i_sb, le32_to_cpu(allocated_blocks[curr_block]));
-               curr_block++;
-               set_buffer_new(bh);
-           }
        }
-    }
 
-    RFALSE( curr_block > blocks_to_allocate, "green-9007: Used too many blocks? weird");
+       RFALSE(curr_block > blocks_to_allocate,
+              "green-9007: Used too many blocks? weird");
 
-    kfree(allocated_blocks);
-    return 0;
+       kfree(allocated_blocks);
+       return 0;
 
 // Need to deal with transaction here.
-error_exit_free_blocks:
-    pathrelse(&path);
-    // free blocks
-    for( i = 0; i < blocks_to_allocate; i++ )
-       reiserfs_free_block(th, inode, le32_to_cpu(allocated_blocks[i]), 1);
-
-error_exit:
-    if (th->t_trans_id) {
-        int err;
-        // update any changes we made to blk count
-        reiserfs_update_sd(th, inode);
-        err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS);
-        if (err)
-            res = err;
-    }
-    reiserfs_write_unlock(inode->i_sb);
-    kfree(allocated_blocks);
-
-    return res;
+      error_exit_free_blocks:
+       pathrelse(&path);
+       // free blocks
+       for (i = 0; i < blocks_to_allocate; i++)
+               reiserfs_free_block(th, inode, le32_to_cpu(allocated_blocks[i]),
+                                   1);
+
+      error_exit:
+       if (th->t_trans_id) {
+               int err;
+               // update any changes we made to blk count
+               mark_inode_dirty(inode);
+               err =
+                   journal_end(th, inode->i_sb,
+                               JOURNAL_PER_BALANCE_CNT * 3 + 1 +
+                               2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb));
+               if (err)
+                       res = err;
+       }
+       reiserfs_write_unlock(inode->i_sb);
+       kfree(allocated_blocks);
+
+       return res;
 }
 
 /* Unlock pages prepared by reiserfs_prepare_file_region_for_write */
-static void reiserfs_unprepare_pages(struct page **prepared_pages, /* list of locked pages */
-                             size_t num_pages /* amount of pages */) {
-    int i; // loop counter
+static void reiserfs_unprepare_pages(struct page **prepared_pages,     /* list of locked pages */
+                                    size_t num_pages /* amount of pages */ )
+{
+       int i;                  // loop counter
 
-    for (i=0; i < num_pages ; i++) {
-       struct page *page = prepared_pages[i];
+       for (i = 0; i < num_pages; i++) {
+               struct page *page = prepared_pages[i];
 
-       try_to_free_buffers(page);
-       unlock_page(page);
-       page_cache_release(page);
-    }
+               try_to_free_buffers(page);
+               unlock_page(page);
+               page_cache_release(page);
+       }
 }
 
 /* This function will copy data from userspace to specified pages within
    supplied byte range */
-static int reiserfs_copy_from_user_to_file_region(
-                               loff_t pos, /* In-file position */
-                               int num_pages, /* Number of pages affected */
-                               int write_bytes, /* Amount of bytes to write */
-                               struct page **prepared_pages, /* pointer to 
-                                                                array to
-                                                                prepared pages
-                                                               */
-                               const char __user *buf /* Pointer to user-supplied
-                                                  data*/
-                               )
+static int reiserfs_copy_from_user_to_file_region(loff_t pos,  /* In-file position */
+                                                 int num_pages,        /* Number of pages affected */
+                                                 int write_bytes,      /* Amount of bytes to write */
+                                                 struct page **prepared_pages, /* pointer to 
+                                                                                  array to
+                                                                                  prepared pages
+                                                                                */
+                                                 const char __user * buf       /* Pointer to user-supplied
+                                                                                  data */
+    )
 {
-    long page_fault=0; // status of copy_from_user.
-    int i; // loop counter.
-    int offset; // offset in page
-
-    for ( i = 0, offset = (pos & (PAGE_CACHE_SIZE-1)); i < num_pages ; i++,offset=0) {
-       size_t count = min_t(size_t,PAGE_CACHE_SIZE-offset,write_bytes); // How much of bytes to write to this page
-       struct page *page=prepared_pages[i]; // Current page we process.
-
-       fault_in_pages_readable( buf, count);
-
-       /* Copy data from userspace to the current page */
-       kmap(page);
-       page_fault = __copy_from_user(page_address(page)+offset, buf, count); // Copy the data.
-       /* Flush processor's dcache for this page */
-       flush_dcache_page(page);
-       kunmap(page);
-       buf+=count;
-       write_bytes-=count;
-
-       if (page_fault)
-           break; // Was there a fault? abort.
-    }
-
-    return page_fault?-EFAULT:0;
+       long page_fault = 0;    // status of copy_from_user.
+       int i;                  // loop counter.
+       int offset;             // offset in page
+
+       for (i = 0, offset = (pos & (PAGE_CACHE_SIZE - 1)); i < num_pages;
+            i++, offset = 0) {
+               size_t count = min_t(size_t, PAGE_CACHE_SIZE - offset, write_bytes);    // How much of bytes to write to this page
+               struct page *page = prepared_pages[i];  // Current page we process.
+
+               fault_in_pages_readable(buf, count);
+
+               /* Copy data from userspace to the current page */
+               kmap(page);
+               page_fault = __copy_from_user(page_address(page) + offset, buf, count); // Copy the data.
+               /* Flush processor's dcache for this page */
+               flush_dcache_page(page);
+               kunmap(page);
+               buf += count;
+               write_bytes -= count;
+
+               if (page_fault)
+                       break;  // Was there a fault? abort.
+       }
+
+       return page_fault ? -EFAULT : 0;
 }
 
 /* taken fs/buffer.c:__block_commit_write */
 int reiserfs_commit_page(struct inode *inode, struct page *page,
-               unsigned from, unsigned to)
+                        unsigned from, unsigned to)
 {
-    unsigned block_start, block_end;
-    int partial = 0;
-    unsigned blocksize;
-    struct buffer_head *bh, *head;
-    unsigned long i_size_index = inode->i_size >> PAGE_CACHE_SHIFT;
-    int new;
-    int logit = reiserfs_file_data_log(inode);
-    struct super_block *s = inode->i_sb;
-    int bh_per_page = PAGE_CACHE_SIZE / s->s_blocksize;
-    struct reiserfs_transaction_handle th;
-    int ret = 0;
-
-    th.t_trans_id = 0;
-    blocksize = 1 << inode->i_blkbits;
-
-    if (logit) {
-       reiserfs_write_lock(s);
-       ret = journal_begin(&th, s, bh_per_page + 1);
-       if (ret)
-           goto drop_write_lock;
-       reiserfs_update_inode_transaction(inode);
-    }
-    for(bh = head = page_buffers(page), block_start = 0;
-        bh != head || !block_start;
-       block_start=block_end, bh = bh->b_this_page)
-    {
-
-       new = buffer_new(bh);
-       clear_buffer_new(bh);
-       block_end = block_start + blocksize;
-       if (block_end <= from || block_start >= to) {
-           if (!buffer_uptodate(bh))
-                   partial = 1;
-       } else {
-           set_buffer_uptodate(bh);
-           if (logit) {
-               reiserfs_prepare_for_journal(s, bh, 1);
-               journal_mark_dirty(&th, s, bh);
-           } else if (!buffer_dirty(bh)) {
-               mark_buffer_dirty(bh);
-               /* do data=ordered on any page past the end
-                * of file and any buffer marked BH_New.
-                */
-               if (reiserfs_data_ordered(inode->i_sb) &&
-                   (new || page->index >= i_size_index)) {
-                   reiserfs_add_ordered_list(inode, bh);
-               }
-           }
+       unsigned block_start, block_end;
+       int partial = 0;
+       unsigned blocksize;
+       struct buffer_head *bh, *head;
+       unsigned long i_size_index = inode->i_size >> PAGE_CACHE_SHIFT;
+       int new;
+       int logit = reiserfs_file_data_log(inode);
+       struct super_block *s = inode->i_sb;
+       int bh_per_page = PAGE_CACHE_SIZE / s->s_blocksize;
+       struct reiserfs_transaction_handle th;
+       int ret = 0;
+
+       th.t_trans_id = 0;
+       blocksize = 1 << inode->i_blkbits;
+
+       if (logit) {
+               reiserfs_write_lock(s);
+               ret = journal_begin(&th, s, bh_per_page + 1);
+               if (ret)
+                       goto drop_write_lock;
+               reiserfs_update_inode_transaction(inode);
+       }
+       for (bh = head = page_buffers(page), block_start = 0;
+            bh != head || !block_start;
+            block_start = block_end, bh = bh->b_this_page) {
+
+               new = buffer_new(bh);
+               clear_buffer_new(bh);
+               block_end = block_start + blocksize;
+               if (block_end <= from || block_start >= to) {
+                       if (!buffer_uptodate(bh))
+                               partial = 1;
+               } else {
+                       set_buffer_uptodate(bh);
+                       if (logit) {
+                               reiserfs_prepare_for_journal(s, bh, 1);
+                               journal_mark_dirty(&th, s, bh);
+                       } else if (!buffer_dirty(bh)) {
+                               mark_buffer_dirty(bh);
+                               /* do data=ordered on any page past the end
+                                * of file and any buffer marked BH_New.
+                                */
+                               if (reiserfs_data_ordered(inode->i_sb) &&
+                                   (new || page->index >= i_size_index)) {
+                                       reiserfs_add_ordered_list(inode, bh);
+                               }
+                       }
+               }
        }
-    }
-    if (logit) {
-       ret = journal_end(&th, s, bh_per_page + 1);
-drop_write_lock:
-       reiserfs_write_unlock(s);
-    }
-    /*
-     * If this is a partial write which happened to make all buffers
-     * uptodate then we can optimize away a bogus readpage() for
-     * the next read(). Here we 'discover' whether the page went
-     * uptodate as a result of this (potentially partial) write.
-     */
-    if (!partial)
-       SetPageUptodate(page);
-    return ret;
+       if (logit) {
+               ret = journal_end(&th, s, bh_per_page + 1);
+             drop_write_lock:
+               reiserfs_write_unlock(s);
+       }
+       /*
+        * If this is a partial write which happened to make all buffers
+        * uptodate then we can optimize away a bogus readpage() for
+        * the next read(). Here we 'discover' whether the page went
+        * uptodate as a result of this (potentially partial) write.
+        */
+       if (!partial)
+               SetPageUptodate(page);
+       return ret;
 }
 
-
 /* Submit pages for write. This was separated from actual file copying
    because we might want to allocate block numbers in-between.
    This function assumes that caller will adjust file size to correct value. */
-static int reiserfs_submit_file_region_for_write(
-                               struct reiserfs_transaction_handle *th,
-                               struct inode *inode,
-                               loff_t pos, /* Writing position offset */
-                               size_t num_pages, /* Number of pages to write */
-                               size_t write_bytes, /* number of bytes to write */
-                               struct page **prepared_pages /* list of pages */
-                               )
+static int reiserfs_submit_file_region_for_write(struct reiserfs_transaction_handle *th, struct inode *inode, loff_t pos,      /* Writing position offset */
+                                                size_t num_pages,      /* Number of pages to write */
+                                                size_t write_bytes,    /* number of bytes to write */
+                                                struct page **prepared_pages   /* list of pages */
+    )
 {
-    int status; // return status of block_commit_write.
-    int retval = 0; // Return value we are going to return.
-    int i; // loop counter
-    int offset; // Writing offset in page.
-    int orig_write_bytes = write_bytes;
-    int sd_update = 0;
-
-    for ( i = 0, offset = (pos & (PAGE_CACHE_SIZE-1)); i < num_pages ; i++,offset=0) {
-       int count = min_t(int,PAGE_CACHE_SIZE-offset,write_bytes); // How much of bytes to write to this page
-       struct page *page=prepared_pages[i]; // Current page we process.
-
-       status = reiserfs_commit_page(inode, page, offset, offset+count);
-       if ( status )
-           retval = status; // To not overcomplicate matters We are going to
-                            // submit all the pages even if there was error.
-                            // we only remember error status to report it on
-                            // exit.
-       write_bytes-=count;
-    }
-    /* now that we've gotten all the ordered buffers marked dirty,
-     * we can safely update i_size and close any running transaction
-     */
-    if ( pos + orig_write_bytes > inode->i_size) {
-       inode->i_size = pos + orig_write_bytes; // Set new size
-       /* If the file have grown so much that tail packing is no
-        * longer possible, reset "need to pack" flag */
-       if ( (have_large_tails (inode->i_sb) &&
-             inode->i_size > i_block_size (inode)*4) ||
-            (have_small_tails (inode->i_sb) &&
-            inode->i_size > i_block_size(inode)) )
-           REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask ;
-        else if ( (have_large_tails (inode->i_sb) &&
-                 inode->i_size < i_block_size (inode)*4) ||
-                 (have_small_tails (inode->i_sb) &&
-                 inode->i_size < i_block_size(inode)) )
-           REISERFS_I(inode)->i_flags |= i_pack_on_close_mask ;
-
+       int status;             // return status of block_commit_write.
+       int retval = 0;         // Return value we are going to return.
+       int i;                  // loop counter
+       int offset;             // Writing offset in page.
+       int orig_write_bytes = write_bytes;
+       int sd_update = 0;
+
+       for (i = 0, offset = (pos & (PAGE_CACHE_SIZE - 1)); i < num_pages;
+            i++, offset = 0) {
+               int count = min_t(int, PAGE_CACHE_SIZE - offset, write_bytes);  // How much of bytes to write to this page
+               struct page *page = prepared_pages[i];  // Current page we process.
+
+               status =
+                   reiserfs_commit_page(inode, page, offset, offset + count);
+               if (status)
+                       retval = status;        // To not overcomplicate matters We are going to
+               // submit all the pages even if there was error.
+               // we only remember error status to report it on
+               // exit.
+               write_bytes -= count;
+       }
+       /* now that we've gotten all the ordered buffers marked dirty,
+        * we can safely update i_size and close any running transaction
+        */
+       if (pos + orig_write_bytes > inode->i_size) {
+               inode->i_size = pos + orig_write_bytes; // Set new size
+               /* If the file have grown so much that tail packing is no
+                * longer possible, reset "need to pack" flag */
+               if ((have_large_tails(inode->i_sb) &&
+                    inode->i_size > i_block_size(inode) * 4) ||
+                   (have_small_tails(inode->i_sb) &&
+                    inode->i_size > i_block_size(inode)))
+                       REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
+               else if ((have_large_tails(inode->i_sb) &&
+                         inode->i_size < i_block_size(inode) * 4) ||
+                        (have_small_tails(inode->i_sb) &&
+                         inode->i_size < i_block_size(inode)))
+                       REISERFS_I(inode)->i_flags |= i_pack_on_close_mask;
+
+               if (th->t_trans_id) {
+                       reiserfs_write_lock(inode->i_sb);
+                       // this sets the proper flags for O_SYNC to trigger a commit
+                       mark_inode_dirty(inode);
+                       reiserfs_write_unlock(inode->i_sb);
+               } else
+                       mark_inode_dirty(inode);
+
+               sd_update = 1;
+       }
        if (th->t_trans_id) {
-           reiserfs_write_lock(inode->i_sb);
-           reiserfs_update_sd(th, inode); // And update on-disk metadata
-           reiserfs_write_unlock(inode->i_sb);
-       } else
-           inode->i_sb->s_op->dirty_inode(inode);
+               reiserfs_write_lock(inode->i_sb);
+               if (!sd_update)
+                       mark_inode_dirty(inode);
+               status = journal_end(th, th->t_super, th->t_blocks_allocated);
+               if (status)
+                       retval = status;
+               reiserfs_write_unlock(inode->i_sb);
+       }
+       th->t_trans_id = 0;
 
-        sd_update = 1;
-    }
-    if (th->t_trans_id) {
-       reiserfs_write_lock(inode->i_sb);
-       if (!sd_update)
-           reiserfs_update_sd(th, inode);
-       status = journal_end(th, th->t_super, th->t_blocks_allocated);
-        if (status)
-            retval = status;
-       reiserfs_write_unlock(inode->i_sb);
-    }
-    th->t_trans_id = 0;
-
-    /* 
-     * we have to unlock the pages after updating i_size, otherwise
-     * we race with writepage
-     */
-    for ( i = 0; i < num_pages ; i++) {
-       struct page *page=prepared_pages[i];
-       unlock_page(page); 
-       mark_page_accessed(page);
-       page_cache_release(page);
-    }
-    return retval;
+       /* 
+        * we have to unlock the pages after updating i_size, otherwise
+        * we race with writepage
+        */
+       for (i = 0; i < num_pages; i++) {
+               struct page *page = prepared_pages[i];
+               unlock_page(page);
+               mark_page_accessed(page);
+               page_cache_release(page);
+       }
+       return retval;
 }
 
 /* Look if passed writing region is going to touch file's tail
    (if it is present). And if it is, convert the tail to unformatted node */
-static int reiserfs_check_for_tail_and_convert( struct inode *inode, /* inode to deal with */
-                                        loff_t pos, /* Writing position */
-                                        int write_bytes /* amount of bytes to write */
-                                       )
+static int reiserfs_check_for_tail_and_convert(struct inode *inode,    /* inode to deal with */
+                                              loff_t pos,      /* Writing position */
+                                              int write_bytes  /* amount of bytes to write */
+    )
 {
-    INITIALIZE_PATH(path); // needed for search_for_position
-    struct cpu_key key; // Key that would represent last touched writing byte.
-    struct item_head *ih; // item header of found block;
-    int res; // Return value of various functions we call.
-    int cont_expand_offset; // We will put offset for generic_cont_expand here
-                           // This can be int just because tails are created
-                           // only for small files.
+       INITIALIZE_PATH(path);  // needed for search_for_position
+       struct cpu_key key;     // Key that would represent last touched writing byte.
+       struct item_head *ih;   // item header of found block;
+       int res;                // Return value of various functions we call.
+       int cont_expand_offset; // We will put offset for generic_cont_expand here
+       // This can be int just because tails are created
+       // only for small files.
+
 /* this embodies a dependency on a particular tail policy */
-    if ( inode->i_size >= inode->i_sb->s_blocksize*4 ) {
-       /* such a big files do not have tails, so we won't bother ourselves
-          to look for tails, simply return */
-       return 0;
-    }
-
-    reiserfs_write_lock(inode->i_sb);
-    /* find the item containing the last byte to be written, or if
-     * writing past the end of the file then the last item of the
-     * file (and then we check its type). */
-    make_cpu_key (&key, inode, pos+write_bytes+1, TYPE_ANY, 3/*key length*/);
-    res = search_for_position_by_key(inode->i_sb, &key, &path);
-    if ( res == IO_ERROR ) {
-        reiserfs_write_unlock(inode->i_sb);
-       return -EIO;
-    }
-    ih = get_ih(&path);
-    res = 0;
-    if ( is_direct_le_ih(ih) ) {
-       /* Ok, closest item is file tail (tails are stored in "direct"
-        * items), so we need to unpack it. */
-       /* To not overcomplicate matters, we just call generic_cont_expand
-          which will in turn call other stuff and finally will boil down to
-           reiserfs_get_block() that would do necessary conversion. */
-       cont_expand_offset = le_key_k_offset(get_inode_item_key_version(inode), &(ih->ih_key));
-       pathrelse(&path);
-       res = generic_cont_expand( inode, cont_expand_offset);
-    } else
-       pathrelse(&path);
+       if (inode->i_size >= inode->i_sb->s_blocksize * 4) {
+               /* such a big files do not have tails, so we won't bother ourselves
+                  to look for tails, simply return */
+               return 0;
+       }
 
-    reiserfs_write_unlock(inode->i_sb);
-    return res;
+       reiserfs_write_lock(inode->i_sb);
+       /* find the item containing the last byte to be written, or if
+        * writing past the end of the file then the last item of the
+        * file (and then we check its type). */
+       make_cpu_key(&key, inode, pos + write_bytes + 1, TYPE_ANY,
+                    3 /*key length */ );
+       res = search_for_position_by_key(inode->i_sb, &key, &path);
+       if (res == IO_ERROR) {
+               reiserfs_write_unlock(inode->i_sb);
+               return -EIO;
+       }
+       ih = get_ih(&path);
+       res = 0;
+       if (is_direct_le_ih(ih)) {
+               /* Ok, closest item is file tail (tails are stored in "direct"
+                * items), so we need to unpack it. */
+               /* To not overcomplicate matters, we just call generic_cont_expand
+                  which will in turn call other stuff and finally will boil down to
+                  reiserfs_get_block() that would do necessary conversion. */
+               cont_expand_offset =
+                   le_key_k_offset(get_inode_item_key_version(inode),
+                                   &(ih->ih_key));
+               pathrelse(&path);
+               res = generic_cont_expand(inode, cont_expand_offset);
+       } else
+               pathrelse(&path);
+
+       reiserfs_write_unlock(inode->i_sb);
+       return res;
 }
 
 /* This function locks pages starting from @pos for @inode.
@@ -851,275 +950,296 @@ static int reiserfs_check_for_tail_and_convert( struct inode *inode, /* inode to
    append), it is zeroed, then. 
    Returns number of unallocated blocks that should be allocated to cover
    new file data.*/
-static int reiserfs_prepare_file_region_for_write(
-                               struct inode *inode /* Inode of the file */,
-                               loff_t pos, /* position in the file */
-                               size_t num_pages, /* number of pages to
-                                                 prepare */
-                               size_t write_bytes, /* Amount of bytes to be
-                                                   overwritten from
-                                                   @pos */
-                               struct page **prepared_pages /* pointer to array
-                                                              where to store
-                                                              prepared pages */
-                                          )
+static int reiserfs_prepare_file_region_for_write(struct inode *inode
+                                                 /* Inode of the file */ ,
+                                                 loff_t pos,   /* position in the file */
+                                                 size_t num_pages,     /* number of pages to
+                                                                          prepare */
+                                                 size_t write_bytes,   /* Amount of bytes to be
+                                                                          overwritten from
+                                                                          @pos */
+                                                 struct page **prepared_pages  /* pointer to array
+                                                                                  where to store
+                                                                                  prepared pages */
+    )
 {
-    int res=0; // Return values of different functions we call.
-    unsigned long index = pos >> PAGE_CACHE_SHIFT; // Offset in file in pages.
-    int from = (pos & (PAGE_CACHE_SIZE - 1)); // Writing offset in first page
-    int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1;
-                                        /* offset of last modified byte in last
-                                           page */
-    struct address_space *mapping = inode->i_mapping; // Pages are mapped here.
-    int i; // Simple counter
-    int blocks = 0; /* Return value (blocks that should be allocated) */
-    struct buffer_head *bh, *head; // Current bufferhead and first bufferhead
-                                  // of a page.
-    unsigned block_start, block_end; // Starting and ending offsets of current
-                                    // buffer in the page.
-    struct buffer_head *wait[2], **wait_bh=wait; // Buffers for page, if
-                                                // Page appeared to be not up
-                                                // to date. Note how we have
-                                                // at most 2 buffers, this is
-                                                // because we at most may
-                                                // partially overwrite two
-                                                // buffers for one page. One at                                                 // the beginning of write area
-                                                // and one at the end.
-                                                // Everything inthe middle gets                                                 // overwritten totally.
-
-    struct cpu_key key; // cpu key of item that we are going to deal with
-    struct item_head *ih = NULL; // pointer to item head that we are going to deal with
-    struct buffer_head *itembuf=NULL; // Buffer head that contains items that we are going to deal with
-    INITIALIZE_PATH(path); // path to item, that we are going to deal with.
-    __le32 * item=NULL; // pointer to item we are going to deal with
-    int item_pos=-1; /* Position in indirect item */
-
-
-    if ( num_pages < 1 ) {
-       reiserfs_warning (inode->i_sb,
-                         "green-9001: reiserfs_prepare_file_region_for_write "
-                         "called with zero number of pages to process");
-       return -EFAULT;
-    }
-
-    /* We have 2 loops for pages. In first loop we grab and lock the pages, so
-       that nobody would touch these until we release the pages. Then
-       we'd start to deal with mapping buffers to blocks. */
-    for ( i = 0; i < num_pages; i++) {
-       prepared_pages[i] = grab_cache_page(mapping, index + i); // locks the page
-       if ( !prepared_pages[i]) {
-           res = -ENOMEM;
-           goto failed_page_grabbing;
-       }
-       if (!page_has_buffers(prepared_pages[i]))
-           create_empty_buffers(prepared_pages[i], inode->i_sb->s_blocksize, 0);
-    }
-
-    /* Let's count amount of blocks for a case where all the blocks
-       overwritten are new (we will substract already allocated blocks later)*/
-    if ( num_pages > 2 )
-       /* These are full-overwritten pages so we count all the blocks in
-          these pages are counted as needed to be allocated */
-       blocks = (num_pages - 2) << (PAGE_CACHE_SHIFT - inode->i_blkbits);
-
-    /* count blocks needed for first page (possibly partially written) */
-    blocks += ((PAGE_CACHE_SIZE - from) >> inode->i_blkbits) +
-          !!(from & (inode->i_sb->s_blocksize-1)); /* roundup */
-
-    /* Now we account for last page. If last page == first page (we
-       overwrite only one page), we substract all the blocks past the
-       last writing position in a page out of already calculated number
-       of blocks */
-    blocks += ((num_pages > 1) << (PAGE_CACHE_SHIFT-inode->i_blkbits)) -
-          ((PAGE_CACHE_SIZE - to) >> inode->i_blkbits);
-          /* Note how we do not roundup here since partial blocks still
-                  should be allocated */
-
-    /* Now if all the write area lies past the file end, no point in
-       maping blocks, since there is none, so we just zero out remaining
-       parts of first and last pages in write area (if needed) */
-    if ( (pos & ~((loff_t)PAGE_CACHE_SIZE - 1)) > inode->i_size ) {
-       if ( from != 0 ) {/* First page needs to be partially zeroed */
-           char *kaddr = kmap_atomic(prepared_pages[0], KM_USER0);
-           memset(kaddr, 0, from);
-           kunmap_atomic( kaddr, KM_USER0);
-       }
-       if ( to != PAGE_CACHE_SIZE ) { /* Last page needs to be partially zeroed */
-           char *kaddr = kmap_atomic(prepared_pages[num_pages-1], KM_USER0);
-           memset(kaddr+to, 0, PAGE_CACHE_SIZE - to);
-           kunmap_atomic( kaddr, KM_USER0);
+       int res = 0;            // Return values of different functions we call.
+       unsigned long index = pos >> PAGE_CACHE_SHIFT;  // Offset in file in pages.
+       int from = (pos & (PAGE_CACHE_SIZE - 1));       // Writing offset in first page
+       int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1;
+       /* offset of last modified byte in last
+          page */
+       struct address_space *mapping = inode->i_mapping;       // Pages are mapped here.
+       int i;                  // Simple counter
+       int blocks = 0;         /* Return value (blocks that should be allocated) */
+       struct buffer_head *bh, *head;  // Current bufferhead and first bufferhead
+       // of a page.
+       unsigned block_start, block_end;        // Starting and ending offsets of current
+       // buffer in the page.
+       struct buffer_head *wait[2], **wait_bh = wait;  // Buffers for page, if
+       // Page appeared to be not up
+       // to date. Note how we have
+       // at most 2 buffers, this is
+       // because we at most may
+       // partially overwrite two
+       // buffers for one page. One at                                                 // the beginning of write area
+       // and one at the end.
+       // Everything inthe middle gets                                                 // overwritten totally.
+
+       struct cpu_key key;     // cpu key of item that we are going to deal with
+       struct item_head *ih = NULL;    // pointer to item head that we are going to deal with
+       struct buffer_head *itembuf = NULL;     // Buffer head that contains items that we are going to deal with
+       INITIALIZE_PATH(path);  // path to item, that we are going to deal with.
+       __le32 *item = NULL;    // pointer to item we are going to deal with
+       int item_pos = -1;      /* Position in indirect item */
+
+       if (num_pages < 1) {
+               reiserfs_warning(inode->i_sb,
+                                "green-9001: reiserfs_prepare_file_region_for_write "
+                                "called with zero number of pages to process");
+               return -EFAULT;
        }
 
-       /* Since all blocks are new - use already calculated value */
-       return blocks;
-    }
-
-    /* Well, since we write somewhere into the middle of a file, there is
-       possibility we are writing over some already allocated blocks, so
-       let's map these blocks and substract number of such blocks out of blocks
-       we need to allocate (calculated above) */
-    /* Mask write position to start on blocksize, we do it out of the
-       loop for performance reasons */
-    pos &= ~((loff_t) inode->i_sb->s_blocksize - 1);
-    /* Set cpu key to the starting position in a file (on left block boundary)*/
-    make_cpu_key (&key, inode, 1 + ((pos) & ~((loff_t) inode->i_sb->s_blocksize - 1)), TYPE_ANY, 3/*key length*/);
-
-    reiserfs_write_lock(inode->i_sb); // We need that for at least search_by_key()
-    for ( i = 0; i < num_pages ; i++ ) { 
-
-       head = page_buffers(prepared_pages[i]);
-       /* For each buffer in the page */
-       for(bh = head, block_start = 0; bh != head || !block_start;
-           block_start=block_end, bh = bh->b_this_page) {
-               if (!bh)
-                   reiserfs_panic(inode->i_sb, "green-9002: Allocated but absent buffer for a page?");
-               /* Find where this buffer ends */
-               block_end = block_start+inode->i_sb->s_blocksize;
-               if (i == 0 && block_end <= from )
-                   /* if this buffer is before requested data to map, skip it*/
-                   continue;
-
-               if (i == num_pages - 1 && block_start >= to) {
-                   /* If this buffer is after requested data to map, abort
-                      processing of current page */
-                   break;
+       /* We have 2 loops for pages. In first loop we grab and lock the pages, so
+          that nobody would touch these until we release the pages. Then
+          we'd start to deal with mapping buffers to blocks. */
+       for (i = 0; i < num_pages; i++) {
+               prepared_pages[i] = grab_cache_page(mapping, index + i);        // locks the page
+               if (!prepared_pages[i]) {
+                       res = -ENOMEM;
+                       goto failed_page_grabbing;
                }
+               if (!page_has_buffers(prepared_pages[i]))
+                       create_empty_buffers(prepared_pages[i],
+                                            inode->i_sb->s_blocksize, 0);
+       }
 
-               if ( buffer_mapped(bh) && bh->b_blocknr !=0 ) {
-                   /* This is optimisation for a case where buffer is mapped
-                      and have blocknumber assigned. In case significant amount
-                      of such buffers are present, we may avoid some amount
-                      of search_by_key calls.
-                      Probably it would be possible to move parts of this code
-                      out of BKL, but I afraid that would overcomplicate code
-                      without any noticeable benefit.
-                   */
-                   item_pos++;
-                   /* Update the key */
-                   set_cpu_key_k_offset( &key, cpu_key_k_offset(&key) + inode->i_sb->s_blocksize);
-                   blocks--; // Decrease the amount of blocks that need to be
-                             // allocated
-                   continue; // Go to the next buffer
+       /* Let's count amount of blocks for a case where all the blocks
+          overwritten are new (we will substract already allocated blocks later) */
+       if (num_pages > 2)
+               /* These are full-overwritten pages so we count all the blocks in
+                  these pages are counted as needed to be allocated */
+               blocks =
+                   (num_pages - 2) << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+
+       /* count blocks needed for first page (possibly partially written) */
+       blocks += ((PAGE_CACHE_SIZE - from) >> inode->i_blkbits) + !!(from & (inode->i_sb->s_blocksize - 1));   /* roundup */
+
+       /* Now we account for last page. If last page == first page (we
+          overwrite only one page), we substract all the blocks past the
+          last writing position in a page out of already calculated number
+          of blocks */
+       blocks += ((num_pages > 1) << (PAGE_CACHE_SHIFT - inode->i_blkbits)) -
+           ((PAGE_CACHE_SIZE - to) >> inode->i_blkbits);
+       /* Note how we do not roundup here since partial blocks still
+          should be allocated */
+
+       /* Now if all the write area lies past the file end, no point in
+          maping blocks, since there is none, so we just zero out remaining
+          parts of first and last pages in write area (if needed) */
+       if ((pos & ~((loff_t) PAGE_CACHE_SIZE - 1)) > inode->i_size) {
+               if (from != 0) {        /* First page needs to be partially zeroed */
+                       char *kaddr = kmap_atomic(prepared_pages[0], KM_USER0);
+                       memset(kaddr, 0, from);
+                       kunmap_atomic(kaddr, KM_USER0);
+               }
+               if (to != PAGE_CACHE_SIZE) {    /* Last page needs to be partially zeroed */
+                       char *kaddr =
+                           kmap_atomic(prepared_pages[num_pages - 1],
+                                       KM_USER0);
+                       memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
+                       kunmap_atomic(kaddr, KM_USER0);
                }
 
-               if ( !itembuf || /* if first iteration */
-                    item_pos >= ih_item_len(ih)/UNFM_P_SIZE)
-                                            { /* or if we progressed past the
-                                                 current unformatted_item */
-                       /* Try to find next item */
-                       res = search_for_position_by_key(inode->i_sb, &key, &path);
-                       /* Abort if no more items */
-                       if ( res != POSITION_FOUND ) {
-                           /* make sure later loops don't use this item */
-                           itembuf = NULL;
-                           item = NULL;
-                           break;
+               /* Since all blocks are new - use already calculated value */
+               return blocks;
+       }
+
+       /* Well, since we write somewhere into the middle of a file, there is
+          possibility we are writing over some already allocated blocks, so
+          let's map these blocks and substract number of such blocks out of blocks
+          we need to allocate (calculated above) */
+       /* Mask write position to start on blocksize, we do it out of the
+          loop for performance reasons */
+       pos &= ~((loff_t) inode->i_sb->s_blocksize - 1);
+       /* Set cpu key to the starting position in a file (on left block boundary) */
+       make_cpu_key(&key, inode,
+                    1 + ((pos) & ~((loff_t) inode->i_sb->s_blocksize - 1)),
+                    TYPE_ANY, 3 /*key length */ );
+
+       reiserfs_write_lock(inode->i_sb);       // We need that for at least search_by_key()
+       for (i = 0; i < num_pages; i++) {
+
+               head = page_buffers(prepared_pages[i]);
+               /* For each buffer in the page */
+               for (bh = head, block_start = 0; bh != head || !block_start;
+                    block_start = block_end, bh = bh->b_this_page) {
+                       if (!bh)
+                               reiserfs_panic(inode->i_sb,
+                                              "green-9002: Allocated but absent buffer for a page?");
+                       /* Find where this buffer ends */
+                       block_end = block_start + inode->i_sb->s_blocksize;
+                       if (i == 0 && block_end <= from)
+                               /* if this buffer is before requested data to map, skip it */
+                               continue;
+
+                       if (i == num_pages - 1 && block_start >= to) {
+                               /* If this buffer is after requested data to map, abort
+                                  processing of current page */
+                               break;
                        }
 
-                       /* Update information about current indirect item */
-                       itembuf = get_last_bh( &path );
-                       ih = get_ih( &path );
-                       item = get_item( &path );
-                       item_pos = path.pos_in_item;
+                       if (buffer_mapped(bh) && bh->b_blocknr != 0) {
+                               /* This is optimisation for a case where buffer is mapped
+                                  and have blocknumber assigned. In case significant amount
+                                  of such buffers are present, we may avoid some amount
+                                  of search_by_key calls.
+                                  Probably it would be possible to move parts of this code
+                                  out of BKL, but I afraid that would overcomplicate code
+                                  without any noticeable benefit.
+                                */
+                               item_pos++;
+                               /* Update the key */
+                               set_cpu_key_k_offset(&key,
+                                                    cpu_key_k_offset(&key) +
+                                                    inode->i_sb->s_blocksize);
+                               blocks--;       // Decrease the amount of blocks that need to be
+                               // allocated
+                               continue;       // Go to the next buffer
+                       }
 
-                       RFALSE( !is_indirect_le_ih (ih), "green-9003: indirect item expected");
-               }
+                       if (!itembuf || /* if first iteration */
+                           item_pos >= ih_item_len(ih) / UNFM_P_SIZE) {        /* or if we progressed past the
+                                                                                  current unformatted_item */
+                               /* Try to find next item */
+                               res =
+                                   search_for_position_by_key(inode->i_sb,
+                                                              &key, &path);
+                               /* Abort if no more items */
+                               if (res != POSITION_FOUND) {
+                                       /* make sure later loops don't use this item */
+                                       itembuf = NULL;
+                                       item = NULL;
+                                       break;
+                               }
+
+                               /* Update information about current indirect item */
+                               itembuf = get_last_bh(&path);
+                               ih = get_ih(&path);
+                               item = get_item(&path);
+                               item_pos = path.pos_in_item;
+
+                               RFALSE(!is_indirect_le_ih(ih),
+                                      "green-9003: indirect item expected");
+                       }
 
-               /* See if there is some block associated with the file
-                  at that position, map the buffer to this block */
-               if ( get_block_num(item,item_pos) ) {
-                   map_bh(bh, inode->i_sb, get_block_num(item,item_pos));
-                   blocks--; // Decrease the amount of blocks that need to be
-                             // allocated
+                       /* See if there is some block associated with the file
+                          at that position, map the buffer to this block */
+                       if (get_block_num(item, item_pos)) {
+                               map_bh(bh, inode->i_sb,
+                                      get_block_num(item, item_pos));
+                               blocks--;       // Decrease the amount of blocks that need to be
+                               // allocated
+                       }
+                       item_pos++;
+                       /* Update the key */
+                       set_cpu_key_k_offset(&key,
+                                            cpu_key_k_offset(&key) +
+                                            inode->i_sb->s_blocksize);
                }
-               item_pos++;
-               /* Update the key */
-               set_cpu_key_k_offset( &key, cpu_key_k_offset(&key) + inode->i_sb->s_blocksize);
        }
-    }
-    pathrelse(&path); // Free the path
-    reiserfs_write_unlock(inode->i_sb);
+       pathrelse(&path);       // Free the path
+       reiserfs_write_unlock(inode->i_sb);
 
        /* Now zero out unmappend buffers for the first and last pages of
           write area or issue read requests if page is mapped. */
        /* First page, see if it is not uptodate */
-       if ( !PageUptodate(prepared_pages[0]) ) {
-           head = page_buffers(prepared_pages[0]);
-
-           /* For each buffer in page */
-           for(bh = head, block_start = 0; bh != head || !block_start;
-               block_start=block_end, bh = bh->b_this_page) {
-
-               if (!bh)
-                   reiserfs_panic(inode->i_sb, "green-9002: Allocated but absent buffer for a page?");
-               /* Find where this buffer ends */
-               block_end = block_start+inode->i_sb->s_blocksize;
-               if ( block_end <= from )
-                   /* if this buffer is before requested data to map, skip it*/
-                   continue;
-               if ( block_start < from ) { /* Aha, our partial buffer */
-                   if ( buffer_mapped(bh) ) { /* If it is mapped, we need to
-                                                 issue READ request for it to
-                                                 not loose data */
-                       ll_rw_block(READ, 1, &bh);
-                       *wait_bh++=bh;
-                   } else { /* Not mapped, zero it */
-                       char *kaddr = kmap_atomic(prepared_pages[0], KM_USER0);
-                       memset(kaddr+block_start, 0, from-block_start);
-                       kunmap_atomic( kaddr, KM_USER0);
-                       set_buffer_uptodate(bh);
-                   }
+       if (!PageUptodate(prepared_pages[0])) {
+               head = page_buffers(prepared_pages[0]);
+
+               /* For each buffer in page */
+               for (bh = head, block_start = 0; bh != head || !block_start;
+                    block_start = block_end, bh = bh->b_this_page) {
+
+                       if (!bh)
+                               reiserfs_panic(inode->i_sb,
+                                              "green-9002: Allocated but absent buffer for a page?");
+                       /* Find where this buffer ends */
+                       block_end = block_start + inode->i_sb->s_blocksize;
+                       if (block_end <= from)
+                               /* if this buffer is before requested data to map, skip it */
+                               continue;
+                       if (block_start < from) {       /* Aha, our partial buffer */
+                               if (buffer_mapped(bh)) {        /* If it is mapped, we need to
+                                                                  issue READ request for it to
+                                                                  not loose data */
+                                       ll_rw_block(READ, 1, &bh);
+                                       *wait_bh++ = bh;
+                               } else {        /* Not mapped, zero it */
+                                       char *kaddr =
+                                           kmap_atomic(prepared_pages[0],
+                                                       KM_USER0);
+                                       memset(kaddr + block_start, 0,
+                                              from - block_start);
+                                       kunmap_atomic(kaddr, KM_USER0);
+                                       set_buffer_uptodate(bh);
+                               }
+                       }
                }
-           }
        }
 
        /* Last page, see if it is not uptodate, or if the last page is past the end of the file. */
-       if ( !PageUptodate(prepared_pages[num_pages-1]) || 
-           ((pos+write_bytes)>>PAGE_CACHE_SHIFT) > (inode->i_size>>PAGE_CACHE_SHIFT) ) {
-           head = page_buffers(prepared_pages[num_pages-1]);
-
-           /* for each buffer in page */
-           for(bh = head, block_start = 0; bh != head || !block_start;
-               block_start=block_end, bh = bh->b_this_page) {
-
-               if (!bh)
-                   reiserfs_panic(inode->i_sb, "green-9002: Allocated but absent buffer for a page?");
-               /* Find where this buffer ends */
-               block_end = block_start+inode->i_sb->s_blocksize;
-               if ( block_start >= to )
-                   /* if this buffer is after requested data to map, skip it*/
-                   break;
-               if ( block_end > to ) { /* Aha, our partial buffer */
-                   if ( buffer_mapped(bh) ) { /* If it is mapped, we need to
-                                                 issue READ request for it to
-                                                 not loose data */
-                       ll_rw_block(READ, 1, &bh);
-                       *wait_bh++=bh;
-                   } else { /* Not mapped, zero it */
-                       char *kaddr = kmap_atomic(prepared_pages[num_pages-1], KM_USER0);
-                       memset(kaddr+to, 0, block_end-to);
-                       kunmap_atomic( kaddr, KM_USER0);
-                       set_buffer_uptodate(bh);
-                   }
+       if (!PageUptodate(prepared_pages[num_pages - 1]) ||
+           ((pos + write_bytes) >> PAGE_CACHE_SHIFT) >
+           (inode->i_size >> PAGE_CACHE_SHIFT)) {
+               head = page_buffers(prepared_pages[num_pages - 1]);
+
+               /* for each buffer in page */
+               for (bh = head, block_start = 0; bh != head || !block_start;
+                    block_start = block_end, bh = bh->b_this_page) {
+
+                       if (!bh)
+                               reiserfs_panic(inode->i_sb,
+                                              "green-9002: Allocated but absent buffer for a page?");
+                       /* Find where this buffer ends */
+                       block_end = block_start + inode->i_sb->s_blocksize;
+                       if (block_start >= to)
+                               /* if this buffer is after requested data to map, skip it */
+                               break;
+                       if (block_end > to) {   /* Aha, our partial buffer */
+                               if (buffer_mapped(bh)) {        /* If it is mapped, we need to
+                                                                  issue READ request for it to
+                                                                  not loose data */
+                                       ll_rw_block(READ, 1, &bh);
+                                       *wait_bh++ = bh;
+                               } else {        /* Not mapped, zero it */
+                                       char *kaddr =
+                                           kmap_atomic(prepared_pages
+                                                       [num_pages - 1],
+                                                       KM_USER0);
+                                       memset(kaddr + to, 0, block_end - to);
+                                       kunmap_atomic(kaddr, KM_USER0);
+                                       set_buffer_uptodate(bh);
+                               }
+                       }
                }
-           }
        }
 
-    /* Wait for read requests we made to happen, if necessary */
-    while(wait_bh > wait) {
-       wait_on_buffer(*--wait_bh);
-       if (!buffer_uptodate(*wait_bh)) {
-           res = -EIO;
-           goto failed_read;
+       /* Wait for read requests we made to happen, if necessary */
+       while (wait_bh > wait) {
+               wait_on_buffer(*--wait_bh);
+               if (!buffer_uptodate(*wait_bh)) {
+                       res = -EIO;
+                       goto failed_read;
+               }
        }
-    }
-
-    return blocks;
-failed_page_grabbing:
-    num_pages = i;
-failed_read:
-    reiserfs_unprepare_pages(prepared_pages, num_pages);
-    return res;
+
+       return blocks;
+      failed_page_grabbing:
+       num_pages = i;
+      failed_read:
+       reiserfs_unprepare_pages(prepared_pages, num_pages);
+       return res;
 }
 
 /* Write @count bytes at position @ppos in a file indicated by @file
@@ -1148,262 +1268,325 @@ failed_read:
    Future Features: providing search_by_key with hints.
 
 */
-static ssize_t reiserfs_file_write( struct file *file, /* the file we are going to write into */
-                             const char __user *buf, /*  pointer to user supplied data
-(in userspace) */
-                             size_t count, /* amount of bytes to write */
-                             loff_t *ppos /* pointer to position in file that we start writing at. Should be updated to
-                                           * new current position before returning. */ )
+static ssize_t reiserfs_file_write(struct file *file,  /* the file we are going to write into */
+                                  const char __user * buf,     /*  pointer to user supplied data
+                                                                  (in userspace) */
+                                  size_t count,        /* amount of bytes to write */
+                                  loff_t * ppos        /* pointer to position in file that we start writing at. Should be updated to
+                                                        * new current position before returning. */
+                                  )
 {
-    size_t already_written = 0; // Number of bytes already written to the file.
-    loff_t pos; // Current position in the file.
-    ssize_t res; // return value of various functions that we call.
-    int err = 0;
-    struct inode *inode = file->f_dentry->d_inode; // Inode of the file that we are writing to.
-                               /* To simplify coding at this time, we store
-                                  locked pages in array for now */
-    struct page * prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME];
-    struct reiserfs_transaction_handle th;
-    th.t_trans_id = 0;
-
-    if ( file->f_flags & O_DIRECT) { // Direct IO needs treatment
-       ssize_t result, after_file_end = 0;
-       if ( (*ppos + count >= inode->i_size) || (file->f_flags & O_APPEND) ) {
-           /* If we are appending a file, we need to put this savelink in here.
-              If we will crash while doing direct io, finish_unfinished will
-              cut the garbage from the file end. */
-           reiserfs_write_lock(inode->i_sb);
-           err = journal_begin(&th, inode->i_sb,  JOURNAL_PER_BALANCE_CNT );
-            if (err) {
-               reiserfs_write_unlock (inode->i_sb);
-               return err;
-           }
-           reiserfs_update_inode_transaction(inode);
-           add_save_link (&th, inode, 1 /* Truncate */);
-           after_file_end = 1;
-           err = journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT );
-            reiserfs_write_unlock(inode->i_sb);
-           if (err)
-               return err;
-       }
-       result = generic_file_write(file, buf, count, ppos);
-
-       if ( after_file_end ) { /* Now update i_size and remove the savelink */
-           struct reiserfs_transaction_handle th;
-           reiserfs_write_lock(inode->i_sb);
-           err = journal_begin(&th, inode->i_sb, 1);
-            if (err) {
-                reiserfs_write_unlock (inode->i_sb);
-                return err;
-            }
-           reiserfs_update_inode_transaction(inode);
-           reiserfs_update_sd(&th, inode);
-           err = journal_end(&th, inode->i_sb, 1);
-            if (err) {
-                reiserfs_write_unlock (inode->i_sb);
-                return err;
-            }
-           err = remove_save_link (inode, 1/* truncate */);
-           reiserfs_write_unlock(inode->i_sb);
-            if (err)
-                return err;
+       size_t already_written = 0;     // Number of bytes already written to the file.
+       loff_t pos;             // Current position in the file.
+       ssize_t res;            // return value of various functions that we call.
+       int err = 0;
+       struct inode *inode = file->f_dentry->d_inode;  // Inode of the file that we are writing to.
+       /* To simplify coding at this time, we store
+          locked pages in array for now */
+       struct page *prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME];
+       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;
        }
 
-       return result;
-    }
-
-    if ( unlikely((ssize_t) count < 0 ))
-        return -EINVAL;
-
-    if (unlikely(!access_ok(VERIFY_READ, buf, count)))
-        return -EFAULT;
-
-    down(&inode->i_sem); // locks the entire file for just us
-
-    pos = *ppos;
-
-    /* Check if we can write to specified region of file, file
-       is not overly big and this kind of stuff. Adjust pos and
-       count, if needed */
-    res = generic_write_checks(file, &pos, &count, 0);
-    if (res)
-       goto out;
-
-    if ( count == 0 )
-       goto out;
-
-    res = remove_suid(file->f_dentry);
-    if (res)
-       goto out;
-
-    inode_update_time(inode, 1); /* Both mtime and ctime */
-
-    // Ok, we are done with all the checks.
+       if (file->f_flags & O_DIRECT) { // Direct IO needs treatment
+               ssize_t result, after_file_end = 0;
+               if ((*ppos + count >= inode->i_size)
+                   || (file->f_flags & O_APPEND)) {
+                       /* If we are appending a file, we need to put this savelink in here.
+                          If we will crash while doing direct io, finish_unfinished will
+                          cut the garbage from the file end. */
+                       reiserfs_write_lock(inode->i_sb);
+                       err =
+                           journal_begin(&th, inode->i_sb,
+                                         JOURNAL_PER_BALANCE_CNT);
+                       if (err) {
+                               reiserfs_write_unlock(inode->i_sb);
+                               return err;
+                       }
+                       reiserfs_update_inode_transaction(inode);
+                       add_save_link(&th, inode, 1 /* Truncate */ );
+                       after_file_end = 1;
+                       err =
+                           journal_end(&th, inode->i_sb,
+                                       JOURNAL_PER_BALANCE_CNT);
+                       reiserfs_write_unlock(inode->i_sb);
+                       if (err)
+                               return err;
+               }
+               result = generic_file_write(file, buf, count, ppos);
+
+               if (after_file_end) {   /* Now update i_size and remove the savelink */
+                       struct reiserfs_transaction_handle th;
+                       reiserfs_write_lock(inode->i_sb);
+                       err = journal_begin(&th, inode->i_sb, 1);
+                       if (err) {
+                               reiserfs_write_unlock(inode->i_sb);
+                               return err;
+                       }
+                       reiserfs_update_inode_transaction(inode);
+                       mark_inode_dirty(inode);
+                       err = journal_end(&th, inode->i_sb, 1);
+                       if (err) {
+                               reiserfs_write_unlock(inode->i_sb);
+                               return err;
+                       }
+                       err = remove_save_link(inode, 1 /* truncate */ );
+                       reiserfs_write_unlock(inode->i_sb);
+                       if (err)
+                               return err;
+               }
 
-    // Now we should start real work
+               return result;
+       }
 
-    /* If we are going to write past the file's packed tail or if we are going
-       to overwrite part of the tail, we need that tail to be converted into
-       unformatted node */
-    res = reiserfs_check_for_tail_and_convert( inode, pos, count);
-    if (res)
-       goto out;
+       if (unlikely((ssize_t) count < 0))
+               return -EINVAL;
+
+       if (unlikely(!access_ok(VERIFY_READ, buf, count)))
+               return -EFAULT;
+
+       mutex_lock(&inode->i_mutex);    // locks the entire file for just us
+
+       pos = *ppos;
+
+       /* Check if we can write to specified region of file, file
+          is not overly big and this kind of stuff. Adjust pos and
+          count, if needed */
+       res = generic_write_checks(file, &pos, &count, 0);
+       if (res)
+               goto out;
+
+       if (count == 0)
+               goto out;
+
+       res = remove_suid(file->f_dentry);
+       if (res)
+               goto out;
+
+       file_update_time(file);
+
+       // Ok, we are done with all the checks.
+
+       // Now we should start real work
+
+       /* If we are going to write past the file's packed tail or if we are going
+          to overwrite part of the tail, we need that tail to be converted into
+          unformatted node */
+       res = reiserfs_check_for_tail_and_convert(inode, pos, count);
+       if (res)
+               goto out;
+
+       while (count > 0) {
+               /* This is the main loop in which we running until some error occures
+                  or until we write all of the data. */
+               size_t num_pages;       /* amount of pages we are going to write this iteration */
+               size_t write_bytes;     /* amount of bytes to write during this iteration */
+               size_t blocks_to_allocate;      /* how much blocks we need to allocate for this iteration */
+
+               /*  (pos & (PAGE_CACHE_SIZE-1)) is an idiom for offset into a page of pos */
+               num_pages = !!((pos + count) & (PAGE_CACHE_SIZE - 1)) + /* round up partial
+                                                                          pages */
+                   ((count +
+                     (pos & (PAGE_CACHE_SIZE - 1))) >> PAGE_CACHE_SHIFT);
+               /* convert size to amount of
+                  pages */
+               reiserfs_write_lock(inode->i_sb);
+               if (num_pages > REISERFS_WRITE_PAGES_AT_A_TIME
+                   || num_pages > reiserfs_can_fit_pages(inode->i_sb)) {
+                       /* If we were asked to write more data than we want to or if there
+                          is not that much space, then we shorten amount of data to write
+                          for this iteration. */
+                       num_pages =
+                           min_t(size_t, REISERFS_WRITE_PAGES_AT_A_TIME,
+                                 reiserfs_can_fit_pages(inode->i_sb));
+                       /* Also we should not forget to set size in bytes accordingly */
+                       write_bytes = (num_pages << PAGE_CACHE_SHIFT) -
+                           (pos & (PAGE_CACHE_SIZE - 1));
+                       /* If position is not on the
+                          start of the page, we need
+                          to substract the offset
+                          within page */
+               } else
+                       write_bytes = count;
+
+               /* reserve the blocks to be allocated later, so that later on
+                  we still have the space to write the blocks to */
+               reiserfs_claim_blocks_to_be_allocated(inode->i_sb,
+                                                     num_pages <<
+                                                     (PAGE_CACHE_SHIFT -
+                                                      inode->i_blkbits));
+               reiserfs_write_unlock(inode->i_sb);
+
+               if (!num_pages) {       /* If we do not have enough space even for a single page... */
+                       if (pos >
+                           inode->i_size + inode->i_sb->s_blocksize -
+                           (pos & (inode->i_sb->s_blocksize - 1))) {
+                               res = -ENOSPC;
+                               break;  // In case we are writing past the end of the last file block, break.
+                       }
+                       // Otherwise we are possibly overwriting the file, so
+                       // let's set write size to be equal or less than blocksize.
+                       // This way we get it correctly for file holes.
+                       // But overwriting files on absolutelly full volumes would not
+                       // be very efficient. Well, people are not supposed to fill
+                       // 100% of disk space anyway.
+                       write_bytes =
+                           min_t(size_t, count,
+                                 inode->i_sb->s_blocksize -
+                                 (pos & (inode->i_sb->s_blocksize - 1)));
+                       num_pages = 1;
+                       // No blocks were claimed before, so do it now.
+                       reiserfs_claim_blocks_to_be_allocated(inode->i_sb,
+                                                             1 <<
+                                                             (PAGE_CACHE_SHIFT
+                                                              -
+                                                              inode->
+                                                              i_blkbits));
+               }
 
-    while ( count > 0) {
-       /* This is the main loop in which we running until some error occures
-          or until we write all of the data. */
-       size_t num_pages;/* amount of pages we are going to write this iteration */
-       size_t write_bytes; /* amount of bytes to write during this iteration */
-       size_t blocks_to_allocate; /* how much blocks we need to allocate for this iteration */
-        
-        /*  (pos & (PAGE_CACHE_SIZE-1)) is an idiom for offset into a page of pos*/
-       num_pages = !!((pos+count) & (PAGE_CACHE_SIZE - 1)) + /* round up partial
-                                                         pages */
-                   ((count + (pos & (PAGE_CACHE_SIZE-1))) >> PAGE_CACHE_SHIFT); 
-                                               /* convert size to amount of
-                                                  pages */
-       reiserfs_write_lock(inode->i_sb);
-       if ( num_pages > REISERFS_WRITE_PAGES_AT_A_TIME 
-               || num_pages > reiserfs_can_fit_pages(inode->i_sb) ) {
-           /* If we were asked to write more data than we want to or if there
-              is not that much space, then we shorten amount of data to write
-              for this iteration. */
-           num_pages = min_t(size_t, REISERFS_WRITE_PAGES_AT_A_TIME, reiserfs_can_fit_pages(inode->i_sb));
-           /* Also we should not forget to set size in bytes accordingly */
-           write_bytes = (num_pages << PAGE_CACHE_SHIFT) - 
-                           (pos & (PAGE_CACHE_SIZE-1));
-                                        /* If position is not on the
-                                           start of the page, we need
-                                           to substract the offset
-                                           within page */
-       } else
-           write_bytes = count;
+               /* Prepare for writing into the region, read in all the
+                  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. */
+               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 -
+                                                        inode->i_blkbits));
+                       break;
+               }
 
-       /* reserve the blocks to be allocated later, so that later on
-          we still have the space to write the blocks to */
-       reiserfs_claim_blocks_to_be_allocated(inode->i_sb, num_pages << (PAGE_CACHE_SHIFT - inode->i_blkbits));
-       reiserfs_write_unlock(inode->i_sb);
+               blocks_to_allocate = res;
+
+               /* First we correct our estimate of how many blocks we need */
+               reiserfs_release_claimed_blocks(inode->i_sb,
+                                               (num_pages <<
+                                                (PAGE_CACHE_SHIFT -
+                                                 inode->i_sb->
+                                                 s_blocksize_bits)) -
+                                               blocks_to_allocate);
+
+               if (blocks_to_allocate > 0) {   /*We only allocate blocks if we need to */
+                       /* Fill in all the possible holes and append the file if needed */
+                       res =
+                           reiserfs_allocate_blocks_for_region(&th, inode, pos,
+                                                               num_pages,
+                                                               write_bytes,
+                                                               prepared_pages,
+                                                               blocks_to_allocate);
+               }
 
-       if ( !num_pages ) { /* If we do not have enough space even for a single page... */
-           if ( pos > inode->i_size+inode->i_sb->s_blocksize-(pos & (inode->i_sb->s_blocksize-1))) {
-               res = -ENOSPC;
-               break; // In case we are writing past the end of the last file block, break.
-           }
-           // Otherwise we are possibly overwriting the file, so
-           // let's set write size to be equal or less than blocksize.
-           // This way we get it correctly for file holes.
-           // But overwriting files on absolutelly full volumes would not
-           // be very efficient. Well, people are not supposed to fill
-           // 100% of disk space anyway.
-           write_bytes = min_t(size_t, count, inode->i_sb->s_blocksize - (pos & (inode->i_sb->s_blocksize - 1)));
-           num_pages = 1;
-           // No blocks were claimed before, so do it now.
-           reiserfs_claim_blocks_to_be_allocated(inode->i_sb, 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits));
-       }
+               /* well, we have allocated the blocks, so it is time to free
+                  the reservation we made earlier. */
+               reiserfs_release_claimed_blocks(inode->i_sb,
+                                               blocks_to_allocate);
+               if (res) {
+                       reiserfs_unprepare_pages(prepared_pages, num_pages);
+                       break;
+               }
 
-       /* Prepare for writing into the region, read in all the
-          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;
-           reiserfs_release_claimed_blocks(inode->i_sb, num_pages << (PAGE_CACHE_SHIFT - inode->i_blkbits));
-           break;
-       }
+/* NOTE that allocating blocks and filling blocks can be done in reverse order
+   and probably we would do that just to get rid of garbage in files after a
+   crash */
 
-       /* First we correct our estimate of how many blocks we need */
-       reiserfs_release_claimed_blocks(inode->i_sb, (num_pages << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits)) - blocks_to_allocate );
+               /* Copy data from user-supplied buffer to file's pages */
+               res =
+                   reiserfs_copy_from_user_to_file_region(pos, num_pages,
+                                                          write_bytes,
+                                                          prepared_pages, buf);
+               if (res) {
+                       reiserfs_unprepare_pages(prepared_pages, num_pages);
+                       break;
+               }
 
-       if ( blocks_to_allocate > 0) {/*We only allocate blocks if we need to*/
-           /* Fill in all the possible holes and append the file if needed */
-           res = reiserfs_allocate_blocks_for_region(&th, inode, pos, num_pages, write_bytes, prepared_pages, blocks_to_allocate);
+               /* Send the pages to disk and unlock them. */
+               res =
+                   reiserfs_submit_file_region_for_write(&th, inode, pos,
+                                                         num_pages,
+                                                         write_bytes,
+                                                         prepared_pages);
+               if (res)
+                       break;
+
+               already_written += write_bytes;
+               buf += write_bytes;
+               *ppos = pos += write_bytes;
+               count -= write_bytes;
+               balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages);
        }
 
-       /* well, we have allocated the blocks, so it is time to free
-          the reservation we made earlier. */
-       reiserfs_release_claimed_blocks(inode->i_sb, blocks_to_allocate);
-       if ( res ) {
-           reiserfs_unprepare_pages(prepared_pages, num_pages);
-           break;
+       /* this is only true on error */
+       if (th.t_trans_id) {
+               reiserfs_write_lock(inode->i_sb);
+               err = journal_end(&th, th.t_super, th.t_blocks_allocated);
+               reiserfs_write_unlock(inode->i_sb);
+               if (err) {
+                       res = err;
+                       goto out;
+               }
        }
 
-/* NOTE that allocating blocks and filling blocks can be done in reverse order
-   and probably we would do that just to get rid of garbage in files after a
-   crash */
+       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);
 
-       /* Copy data from user-supplied buffer to file's pages */
-       res = reiserfs_copy_from_user_to_file_region(pos, num_pages, write_bytes, prepared_pages, buf);
-       if ( res ) {
-           reiserfs_unprepare_pages(prepared_pages, num_pages);
-           break;
-       }
+       mutex_unlock(&inode->i_mutex);
+       reiserfs_async_progress_wait(inode->i_sb);
+       return (already_written != 0) ? already_written : res;
 
-       /* Send the pages to disk and unlock them. */
-       res = reiserfs_submit_file_region_for_write(&th, inode, pos, num_pages,
-                                                   write_bytes,prepared_pages);
-       if ( res )
-           break;
-
-       already_written += write_bytes;
-       buf += write_bytes;
-       *ppos = pos += write_bytes;
-       count -= write_bytes;
-       balance_dirty_pages_ratelimited(inode->i_mapping);
-    }
-
-    /* this is only true on error */
-    if (th.t_trans_id) {
-        reiserfs_write_lock(inode->i_sb);
-        err = journal_end(&th, th.t_super, th.t_blocks_allocated);
-        reiserfs_write_unlock(inode->i_sb);
-        if (err) {
-            res = err;
-            goto out;
-        }
-    }
-
-    if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
-       res = generic_osync_inode(inode, file->f_mapping, OSYNC_METADATA|OSYNC_DATA);
-
-    up(&inode->i_sem);
-    reiserfs_async_progress_wait(inode->i_sb);
-    return (already_written != 0)?already_written:res;
-
-out:
-    up(&inode->i_sem); // unlock the file on exit.
-    return res;
+      out:
+       mutex_unlock(&inode->i_mutex);  // unlock the file on exit.
+       return res;
 }
 
-static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user *buf,
-                              size_t count, loff_t pos)
+static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf,
+                                 size_t count, loff_t pos)
 {
-    return generic_file_aio_write(iocb, buf, count, pos);
+       return generic_file_aio_write(iocb, buf, count, pos);
 }
 
-
-
-struct file_operations reiserfs_file_operations = {
-    .read      = generic_file_read,
-    .write     = reiserfs_file_write,
-    .ioctl     = reiserfs_ioctl,
-    .mmap      = generic_file_mmap,
-    .release   = reiserfs_file_release,
-    .fsync     = reiserfs_sync_file,
-    .sendfile  = generic_file_sendfile,
-    .aio_read   = generic_file_aio_read,
-    .aio_write  = reiserfs_aio_write,
+const struct file_operations reiserfs_file_operations = {
+       .read = generic_file_read,
+       .write = reiserfs_file_write,
+       .ioctl = reiserfs_ioctl,
+       .mmap = generic_file_mmap,
+       .release = reiserfs_file_release,
+       .fsync = reiserfs_sync_file,
+       .sendfile = generic_file_sendfile,
+       .aio_read = generic_file_aio_read,
+       .aio_write = reiserfs_aio_write,
+       .splice_read = generic_file_splice_read,
+       .splice_write = generic_file_splice_write,
 };
 
-
-struct  inode_operations reiserfs_file_inode_operations = {
-    .truncate  = reiserfs_vfs_truncate_file,
-    .setattr    = reiserfs_setattr,
-    .setxattr   = reiserfs_setxattr,
-    .getxattr   = reiserfs_getxattr,
-    .listxattr  = reiserfs_listxattr,
-    .removexattr = reiserfs_removexattr,
-    .permission = reiserfs_permission,
+struct inode_operations reiserfs_file_inode_operations = {
+       .truncate = reiserfs_vfs_truncate_file,
+       .setattr = reiserfs_setattr,
+       .setxattr = reiserfs_setxattr,
+       .getxattr = reiserfs_getxattr,
+       .listxattr = reiserfs_listxattr,
+       .removexattr = reiserfs_removexattr,
+       .permission = reiserfs_permission,
+       .sync_flags = reiserfs_sync_flags,
 };
-
-