nfsd4: use list_move in move_to_confirmed
[safe/jmp/linux-2.6] / fs / reiserfs / inode.c
index 50a73e7..dc2c65e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <linux/buffer_head.h>
@@ -31,11 +32,15 @@ void reiserfs_delete_inode(struct inode *inode)
            JOURNAL_PER_BALANCE_CNT * 2 +
            2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
        struct reiserfs_transaction_handle th;
+       int depth;
        int err;
 
+       if (!is_bad_inode(inode))
+               dquot_initialize(inode);
+
        truncate_inode_pages(&inode->i_data, 0);
 
-       reiserfs_write_lock(inode->i_sb);
+       depth = reiserfs_write_lock_once(inode->i_sb);
 
        /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
        if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) {  /* also handles bad_inode case */
@@ -53,7 +58,7 @@ void reiserfs_delete_inode(struct inode *inode)
                 * after delete_object so that quota updates go into the same transaction as
                 * stat data deletion */
                if (!err) 
-                       DQUOT_FREE_INODE(inode);
+                       dquot_free_inode(inode);
 
                if (journal_end(&th, inode->i_sb, jbegin_count))
                        goto out;
@@ -74,7 +79,7 @@ void reiserfs_delete_inode(struct inode *inode)
       out:
        clear_inode(inode);     /* note this must go after the journal_end to prevent deadlock */
        inode->i_blocks = 0;
-       reiserfs_write_unlock(inode->i_sb);
+       reiserfs_write_unlock_once(inode->i_sb, depth);
 }
 
 static void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid,
@@ -251,7 +256,6 @@ static int _get_block_create_0(struct inode *inode, sector_t block,
        struct cpu_key key;
        struct buffer_head *bh;
        struct item_head *ih, tmp_ih;
-       int fs_gen;
        b_blocknr_t blocknr;
        char *p = NULL;
        int chars;
@@ -265,7 +269,6 @@ static int _get_block_create_0(struct inode *inode, sector_t block,
                     (loff_t) block * inode->i_sb->s_blocksize + 1, TYPE_ANY,
                     3);
 
-      research:
        result = search_for_position_by_key(inode->i_sb, &key, &path);
        if (result != POSITION_FOUND) {
                pathrelse(&path);
@@ -340,7 +343,6 @@ static int _get_block_create_0(struct inode *inode, sector_t block,
        }
        // read file tail into part of page
        offset = (cpu_key_k_offset(&key) - 1) & (PAGE_CACHE_SIZE - 1);
-       fs_gen = get_generation(inode->i_sb);
        copy_item_head(&tmp_ih, ih);
 
        /* we only want to kmap if we are reading the tail into the page.
@@ -348,13 +350,9 @@ static int _get_block_create_0(struct inode *inode, sector_t block,
         ** sure we need to.  But, this means the item might move if
         ** kmap schedules
         */
-       if (!p) {
+       if (!p)
                p = (char *)kmap(bh_result->b_page);
-               if (fs_changed(fs_gen, inode->i_sb)
-                   && item_moved(&tmp_ih, &path)) {
-                       goto research;
-               }
-       }
+
        p += offset;
        memset(p, 0, inode->i_sb->s_blocksize);
        do {
@@ -363,7 +361,7 @@ static int _get_block_create_0(struct inode *inode, sector_t block,
                }
                /* make sure we don't read more bytes than actually exist in
                 ** the file.  This can happen in odd cases where i_size isn't
-                ** correct, and when direct item padding results in a few 
+                ** correct, and when direct item padding results in a few
                 ** extra bytes at the end of the direct item
                 */
                if ((le_ih_k_offset(ih) + path.pos_in_item) > inode->i_size)
@@ -438,15 +436,15 @@ static int reiserfs_bmap(struct inode *inode, sector_t block,
 ** -ENOENT instead of a valid buffer.  block_prepare_write expects to
 ** be able to do i/o on the buffers returned, unless an error value
 ** is also returned.
-** 
+**
 ** So, this allows block_prepare_write to be used for reading a single block
 ** in a page.  Where it does not produce a valid page for holes, or past the
 ** end of the file.  This turns out to be exactly what we need for reading
 ** tails for conversion.
 **
 ** The point of the wrapper is forcing a certain value for create, even
-** though the VFS layer is calling this function with create==1.  If you 
-** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block, 
+** though the VFS layer is calling this function with create==1.  If you
+** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block,
 ** don't use this function.
 */
 static int reiserfs_get_block_create_0(struct inode *inode, sector_t block,
@@ -489,10 +487,14 @@ static int reiserfs_get_blocks_direct_io(struct inode *inode,
           disappeared */
        if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) {
                int err;
-               lock_kernel();
+
+               reiserfs_write_lock(inode->i_sb);
+
                err = reiserfs_commit_for_inode(inode);
                REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
-               unlock_kernel();
+
+               reiserfs_write_unlock(inode->i_sb);
+
                if (err < 0)
                        ret = err;
        }
@@ -601,8 +603,9 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
        __le32 *item;
        int done;
        int fs_gen;
+       int lock_depth;
        struct reiserfs_transaction_handle *th = NULL;
-       /* space reserved in transaction batch: 
+       /* space reserved in transaction batch:
           . 3 balancings in direct->indirect conversion
           . 1 block involved into reiserfs_update_sd()
           XXX in practically impossible worst case direct2indirect()
@@ -616,12 +619,11 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
        loff_t new_offset =
            (((loff_t) block) << inode->i_sb->s_blocksize_bits) + 1;
 
-       /* bad.... */
-       reiserfs_write_lock(inode->i_sb);
+       lock_depth = reiserfs_write_lock_once(inode->i_sb);
        version = get_inode_item_key_version(inode);
 
        if (!file_capable(inode, block)) {
-               reiserfs_write_unlock(inode->i_sb);
+               reiserfs_write_unlock_once(inode->i_sb, lock_depth);
                return -EFBIG;
        }
 
@@ -633,7 +635,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                /* find number of block-th logical block of the file */
                ret = _get_block_create_0(inode, block, bh_result,
                                          create | GET_BLOCK_READ_DIRECT);
-               reiserfs_write_unlock(inode->i_sb);
+               reiserfs_write_unlock_once(inode->i_sb, lock_depth);
                return ret;
        }
        /*
@@ -751,10 +753,10 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                if (!dangle && th)
                        retval = reiserfs_end_persistent_transaction(th);
 
-               reiserfs_write_unlock(inode->i_sb);
+               reiserfs_write_unlock_once(inode->i_sb, lock_depth);
 
                /* the item was found, so new blocks were not added to the file
-                ** there is no need to make sure the inode is updated with this 
+                ** there is no need to make sure the inode is updated with this
                 ** transaction
                 */
                return retval;
@@ -935,7 +937,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                        if (blocks_needed == 1) {
                                un = &unf_single;
                        } else {
-                               un = kzalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_ATOMIC);      // We need to avoid scheduling.
+                               un = kzalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_NOFS);
                                if (!un) {
                                        un = &unf_single;
                                        blocks_needed = 1;
@@ -986,7 +988,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
 
                /* this loop could log more blocks than we had originally asked
                 ** for.  So, we have to allow the transaction to end if it is
-                ** too big or too full.  Update the inode so things are 
+                ** too big or too full.  Update the inode so things are
                 ** consistent if we crash before the function returns
                 **
                 ** release the path so that anybody waiting on the path before
@@ -997,10 +999,16 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                        if (retval)
                                goto failure;
                }
-               /* inserting indirect pointers for a hole can take a 
-                ** long time.  reschedule if needed
+               /*
+                * inserting indirect pointers for a hole can take a
+                * long time.  reschedule if needed and also release the write
+                * lock for others.
                 */
-               cond_resched();
+               if (need_resched()) {
+                       reiserfs_write_unlock_once(inode->i_sb, lock_depth);
+                       schedule();
+                       lock_depth = reiserfs_write_lock_once(inode->i_sb);
+               }
 
                retval = search_for_position_by_key(inode->i_sb, &key, &path);
                if (retval == IO_ERROR) {
@@ -1035,7 +1043,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
                        retval = err;
        }
 
-       reiserfs_write_unlock(inode->i_sb);
+       reiserfs_write_unlock_once(inode->i_sb, lock_depth);
        reiserfs_check_path(&path);
        return retval;
 }
@@ -1131,8 +1139,6 @@ static void init_inode(struct inode *inode, struct treepath *path)
        REISERFS_I(inode)->i_trans_id = 0;
        REISERFS_I(inode)->i_jl = NULL;
        mutex_init(&(REISERFS_I(inode)->i_mmap));
-       reiserfs_init_acl_access(inode);
-       reiserfs_init_acl_default(inode);
        reiserfs_init_xattr_rwsem(inode);
 
        if (stat_data_v1(ih)) {
@@ -1444,7 +1450,7 @@ void reiserfs_read_locked_inode(struct inode *inode,
           update sd on unlink all that is required is to check for nlink
           here. This bug was first found by Sizif when debugging
           SquidNG/Butterfly, forgotten, and found again after Philippe
-          Gramoulle <philippe.gramoulle@mmania.com> reproduced it. 
+          Gramoulle <philippe.gramoulle@mmania.com> reproduced it.
 
           More logical fix would require changes in fs/inode.c:iput() to
           remove inode from hash-table _after_ fs cleaned disk stuff up and
@@ -1495,9 +1501,11 @@ struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key)
 
        args.objectid = key->on_disk_key.k_objectid;
        args.dirid = key->on_disk_key.k_dir_id;
+       reiserfs_write_unlock(s);
        inode = iget5_locked(s, key->on_disk_key.k_objectid,
                             reiserfs_find_actor, reiserfs_init_locked_inode,
                             (void *)(&args));
+       reiserfs_write_lock(s);
        if (!inode)
                return ERR_PTR(-ENOMEM);
 
@@ -1611,7 +1619,7 @@ int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp,
 ** to properly mark inodes for datasync and such, but only actually
 ** does something when called for a synchronous update.
 */
-int reiserfs_write_inode(struct inode *inode, int do_sync)
+int reiserfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
        struct reiserfs_transaction_handle th;
        int jbegin_count = 1;
@@ -1619,11 +1627,11 @@ int reiserfs_write_inode(struct inode *inode, int do_sync)
        if (inode->i_sb->s_flags & MS_RDONLY)
                return -EROFS;
        /* memory pressure can sometimes initiate write_inode calls with sync == 1,
-        ** these cases are just when the system needs ram, not when the 
+        ** these cases are just when the system needs ram, not when the
         ** inode needs to reach disk for safety, and they can safely be
         ** ignored because the altered inode has already been logged.
         */
-       if (do_sync && !(current->flags & PF_MEMALLOC)) {
+       if (wbc->sync_mode == WB_SYNC_ALL && !(current->flags & PF_MEMALLOC)) {
                reiserfs_write_lock(inode->i_sb);
                if (!journal_begin(&th, inode->i_sb, jbegin_count)) {
                        reiserfs_update_sd(&th, inode);
@@ -1736,7 +1744,7 @@ static int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, struct i
 /* inserts the stat data into the tree, and then calls
    reiserfs_new_directory (to insert ".", ".." item if new object is
    directory) or reiserfs_new_symlink (to insert symlink body if new
-   object is symlink) or nothing (if new object is regular file) 
+   object is symlink) or nothing (if new object is regular file)
 
    NOTE! uid and gid must already be set in the inode.  If we return
    non-zero due to an error, we have to drop the quota previously allocated
@@ -1744,10 +1752,11 @@ static int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, struct i
    if we return non-zero, we also end the transaction.  */
 int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
                       struct inode *dir, int mode, const char *symname,
-                      /* 0 for regular, EMTRY_DIR_SIZE for dirs, 
+                      /* 0 for regular, EMTRY_DIR_SIZE for dirs,
                          strlen (symname) for symlinks) */
                       loff_t i_size, struct dentry *dentry,
-                      struct inode *inode)
+                      struct inode *inode,
+                      struct reiserfs_security_handle *security)
 {
        struct super_block *sb;
        struct reiserfs_iget_args args;
@@ -1760,10 +1769,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 
        BUG_ON(!th->t_trans_id);
 
-       if (DQUOT_ALLOC_INODE(inode)) {
-               err = -EDQUOT;
+       dquot_initialize(inode);
+       err = dquot_alloc_inode(inode);
+       if (err)
                goto out_end_trans;
-       }
        if (!dir->i_nlink) {
                err = -EPERM;
                goto out_bad_inode;
@@ -1793,7 +1802,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
                goto out_bad_inode;
        }
        if (old_format_only(sb))
-               /* not a perfect generation count, as object ids can be reused, but 
+               /* not a perfect generation count, as object ids can be reused, but
                 ** this is as good as reiserfs can do right now.
                 ** note that the private part of inode isn't filled in yet, we have
                 ** to use the directory.
@@ -1833,8 +1842,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
            REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
        sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode);
        mutex_init(&(REISERFS_I(inode)->i_mmap));
-       reiserfs_init_acl_access(inode);
-       reiserfs_init_acl_default(inode);
        reiserfs_init_xattr_rwsem(inode);
 
        /* key to search for correct place for new stat data */
@@ -1914,9 +1921,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
                goto out_inserted_sd;
        }
 
-       /* XXX CHECK THIS */
        if (reiserfs_posixacl(inode->i_sb)) {
-               retval = reiserfs_inherit_default_acl(dir, dentry, inode);
+               retval = reiserfs_inherit_default_acl(th, dir, dentry, inode);
                if (retval) {
                        err = retval;
                        reiserfs_check_path(&path_to_key);
@@ -1930,6 +1936,19 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
        } else if (IS_PRIVATE(dir))
                inode->i_flags |= S_PRIVATE;
 
+       if (security->name) {
+               retval = reiserfs_security_write(th, inode, security);
+               if (retval) {
+                       err = retval;
+                       reiserfs_check_path(&path_to_key);
+                       retval = journal_end(th, th->t_super,
+                                            th->t_blocks_allocated);
+                       if (retval)
+                               err = retval;
+                       goto out_inserted_sd;
+               }
+       }
+
        reiserfs_update_sd(th, inode);
        reiserfs_check_path(&path_to_key);
 
@@ -1944,12 +1963,12 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
        INODE_PKEY(inode)->k_objectid = 0;
 
        /* Quota change must be inside a transaction for journaling */
-       DQUOT_FREE_INODE(inode);
+       dquot_free_inode(inode);
 
       out_end_trans:
        journal_end(th, th->t_super, th->t_blocks_allocated);
        /* Drop can be outside and it needs more credits so it's better to have it outside */
-       DQUOT_DROP(inode);
+       dquot_drop(inode);
        inode->i_flags |= S_NOQUOTA;
        make_bad_inode(inode);
 
@@ -1974,7 +1993,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 **
 ** on failure, nonzero is returned, page_result and bh_result are untouched.
 */
-static int grab_tail_page(struct inode *p_s_inode,
+static int grab_tail_page(struct inode *inode,
                          struct page **page_result,
                          struct buffer_head **bh_result)
 {
@@ -1982,11 +2001,11 @@ static int grab_tail_page(struct inode *p_s_inode,
        /* we want the page with the last byte in the file,
         ** not the page that will hold the next byte for appending
         */
-       unsigned long index = (p_s_inode->i_size - 1) >> PAGE_CACHE_SHIFT;
+       unsigned long index = (inode->i_size - 1) >> PAGE_CACHE_SHIFT;
        unsigned long pos = 0;
        unsigned long start = 0;
-       unsigned long blocksize = p_s_inode->i_sb->s_blocksize;
-       unsigned long offset = (p_s_inode->i_size) & (PAGE_CACHE_SIZE - 1);
+       unsigned long blocksize = inode->i_sb->s_blocksize;
+       unsigned long offset = (inode->i_size) & (PAGE_CACHE_SIZE - 1);
        struct buffer_head *bh;
        struct buffer_head *head;
        struct page *page;
@@ -2000,7 +2019,7 @@ static int grab_tail_page(struct inode *p_s_inode,
        if ((offset & (blocksize - 1)) == 0) {
                return -ENOENT;
        }
-       page = grab_cache_page(p_s_inode->i_mapping, index);
+       page = grab_cache_page(inode->i_mapping, index);
        error = -ENOMEM;
        if (!page) {
                goto out;
@@ -2029,7 +2048,7 @@ static int grab_tail_page(struct inode *p_s_inode,
                 ** I've screwed up the code to find the buffer, or the code to
                 ** call prepare_write
                 */
-               reiserfs_error(p_s_inode->i_sb, "clm-6000",
+               reiserfs_error(inode->i_sb, "clm-6000",
                               "error reading block %lu", bh->b_blocknr);
                error = -EIO;
                goto unlock;
@@ -2052,27 +2071,29 @@ static int grab_tail_page(struct inode *p_s_inode,
 **
 ** some code taken from block_truncate_page
 */
-int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
+int reiserfs_truncate_file(struct inode *inode, int update_timestamps)
 {
        struct reiserfs_transaction_handle th;
        /* we want the offset for the first byte after the end of the file */
-       unsigned long offset = p_s_inode->i_size & (PAGE_CACHE_SIZE - 1);
-       unsigned blocksize = p_s_inode->i_sb->s_blocksize;
+       unsigned long offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
+       unsigned blocksize = inode->i_sb->s_blocksize;
        unsigned length;
        struct page *page = NULL;
        int error;
        struct buffer_head *bh = NULL;
        int err2;
+       int lock_depth;
 
-       reiserfs_write_lock(p_s_inode->i_sb);
+       lock_depth = reiserfs_write_lock_once(inode->i_sb);
 
-       if (p_s_inode->i_size > 0) {
-               if ((error = grab_tail_page(p_s_inode, &page, &bh))) {
-                       // -ENOENT means we truncated past the end of the file, 
+       if (inode->i_size > 0) {
+               error = grab_tail_page(inode, &page, &bh);
+               if (error) {
+                       // -ENOENT means we truncated past the end of the file,
                        // and get_block_create_0 could not find a block to read in,
                        // which is ok.
                        if (error != -ENOENT)
-                               reiserfs_error(p_s_inode->i_sb, "clm-6001",
+                               reiserfs_error(inode->i_sb, "clm-6001",
                                               "grab_tail_page failed %d",
                                               error);
                        page = NULL;
@@ -2080,29 +2101,29 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
                }
        }
 
-       /* so, if page != NULL, we have a buffer head for the offset at 
-        ** the end of the file. if the bh is mapped, and bh->b_blocknr != 0, 
-        ** then we have an unformatted node.  Otherwise, we have a direct item, 
-        ** and no zeroing is required on disk.  We zero after the truncate, 
-        ** because the truncate might pack the item anyway 
+       /* so, if page != NULL, we have a buffer head for the offset at
+        ** the end of the file. if the bh is mapped, and bh->b_blocknr != 0,
+        ** then we have an unformatted node.  Otherwise, we have a direct item,
+        ** and no zeroing is required on disk.  We zero after the truncate,
+        ** because the truncate might pack the item anyway
         ** (it will unmap bh if it packs).
         */
        /* it is enough to reserve space in transaction for 2 balancings:
           one for "save" link adding and another for the first
           cut_from_item. 1 is for update_sd */
-       error = journal_begin(&th, p_s_inode->i_sb,
+       error = journal_begin(&th, inode->i_sb,
                              JOURNAL_PER_BALANCE_CNT * 2 + 1);
        if (error)
                goto out;
-       reiserfs_update_inode_transaction(p_s_inode);
+       reiserfs_update_inode_transaction(inode);
        if (update_timestamps)
                /* we are doing real truncate: if the system crashes before the last
                   transaction of truncating gets committed - on reboot the file
                   either appears truncated properly or not truncated at all */
-               add_save_link(&th, p_s_inode, 1);
-       err2 = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);
+               add_save_link(&th, inode, 1);
+       err2 = reiserfs_do_truncate(&th, inode, page, update_timestamps);
        error =
-           journal_end(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
+           journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
        if (error)
                goto out;
 
@@ -2113,7 +2134,7 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
        }
        
        if (update_timestamps) {
-               error = remove_save_link(p_s_inode, 1 /* truncate */ );
+               error = remove_save_link(inode, 1 /* truncate */);
                if (error)
                        goto out;
        }
@@ -2132,14 +2153,17 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
                page_cache_release(page);
        }
 
-       reiserfs_write_unlock(p_s_inode->i_sb);
+       reiserfs_write_unlock_once(inode->i_sb, lock_depth);
+
        return 0;
       out:
        if (page) {
                unlock_page(page);
                page_cache_release(page);
        }
-       reiserfs_write_unlock(p_s_inode->i_sb);
+
+       reiserfs_write_unlock_once(inode->i_sb, lock_depth);
+
        return error;
 }
 
@@ -2293,8 +2317,8 @@ static int map_block_for_writepage(struct inode *inode,
        return retval;
 }
 
-/* 
- * mason@suse.com: updated in 2.5.54 to follow the same general io 
+/*
+ * mason@suse.com: updated in 2.5.54 to follow the same general io
  * start/recovery path as __block_write_full_page, along with special
  * code to handle reiserfs tails.
  */
@@ -2434,7 +2458,7 @@ static int reiserfs_write_full_page(struct page *page,
        unlock_page(page);
 
        /*
-        * since any buffer might be the only dirty buffer on the page, 
+        * since any buffer might be the only dirty buffer on the page,
         * the first submit_bh can bring the page out of writeback.
         * be careful with the buffers.
         */
@@ -2453,8 +2477,8 @@ static int reiserfs_write_full_page(struct page *page,
        if (nr == 0) {
                /*
                 * if this page only had a direct item, it is very possible for
-                * no io to be required without there being an error.  Or, 
-                * someone else could have locked them and sent them down the 
+                * no io to be required without there being an error.  Or,
+                * someone else could have locked them and sent them down the
                 * pipe without locking the page
                 */
                bh = head;
@@ -2473,7 +2497,7 @@ static int reiserfs_write_full_page(struct page *page,
 
       fail:
        /* catches various errors, we need to make sure any valid dirty blocks
-        * get to the media.  The page is currently locked and not marked for 
+        * get to the media.  The page is currently locked and not marked for
         * writeback
         */
        ClearPageUptodate(page);
@@ -2521,6 +2545,12 @@ static int reiserfs_writepage(struct page *page, struct writeback_control *wbc)
        return reiserfs_write_full_page(page, wbc);
 }
 
+static void reiserfs_truncate_failed_write(struct inode *inode)
+{
+       truncate_inode_pages(inode->i_mapping, inode->i_size);
+       reiserfs_truncate_file(inode, 0);
+}
+
 static int reiserfs_write_begin(struct file *file,
                                struct address_space *mapping,
                                loff_t pos, unsigned len, unsigned flags,
@@ -2587,6 +2617,8 @@ static int reiserfs_write_begin(struct file *file,
        if (ret) {
                unlock_page(page);
                page_cache_release(page);
+               /* Truncate allocated blocks */
+               reiserfs_truncate_failed_write(inode);
        }
        return ret;
 }
@@ -2598,7 +2630,10 @@ int reiserfs_prepare_write(struct file *f, struct page *page,
        int ret;
        int old_ref = 0;
 
+       reiserfs_write_unlock(inode->i_sb);
        reiserfs_wait_on_write_block(inode->i_sb);
+       reiserfs_write_lock(inode->i_sb);
+
        fix_tail_page_for_writing(page);
        if (reiserfs_transaction_running(inode->i_sb)) {
                struct reiserfs_transaction_handle *th;
@@ -2654,6 +2689,8 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
        int update_sd = 0;
        struct reiserfs_transaction_handle *th;
        unsigned start;
+       int lock_depth = 0;
+       bool locked = false;
 
        if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND)
                pos ++;
@@ -2679,10 +2716,10 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
         ** transaction tracking stuff when the size changes.  So, we have
         ** to do the i_size updates here.
         */
-       pos += copied;
-       if (pos > inode->i_size) {
+       if (pos + copied > inode->i_size) {
                struct reiserfs_transaction_handle myth;
-               reiserfs_write_lock(inode->i_sb);
+               lock_depth = reiserfs_write_lock_once(inode->i_sb);
+               locked = true;
                /* If the file have grown beyond the border where it
                   can have a tail, unmark it as needing a tail
                   packing */
@@ -2693,12 +2730,11 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
                        REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
 
                ret = journal_begin(&myth, inode->i_sb, 1);
-               if (ret) {
-                       reiserfs_write_unlock(inode->i_sb);
+               if (ret)
                        goto journal_error;
-               }
+
                reiserfs_update_inode_transaction(inode);
-               inode->i_size = pos;
+               inode->i_size = pos + copied;
                /*
                 * this will just nest into our transaction.  It's important
                 * to use mark_inode_dirty so the inode gets pushed around on the
@@ -2708,34 +2744,40 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
                reiserfs_update_sd(&myth, inode);
                update_sd = 1;
                ret = journal_end(&myth, inode->i_sb, 1);
-               reiserfs_write_unlock(inode->i_sb);
                if (ret)
                        goto journal_error;
        }
        if (th) {
-               reiserfs_write_lock(inode->i_sb);
+               if (!locked) {
+                       lock_depth = reiserfs_write_lock_once(inode->i_sb);
+                       locked = true;
+               }
                if (!update_sd)
                        mark_inode_dirty(inode);
                ret = reiserfs_end_persistent_transaction(th);
-               reiserfs_write_unlock(inode->i_sb);
                if (ret)
                        goto out;
        }
 
       out:
+       if (locked)
+               reiserfs_write_unlock_once(inode->i_sb, lock_depth);
        unlock_page(page);
        page_cache_release(page);
+
+       if (pos + len > inode->i_size)
+               reiserfs_truncate_failed_write(inode);
+
        return ret == 0 ? copied : ret;
 
       journal_error:
+       reiserfs_write_unlock_once(inode->i_sb, lock_depth);
+       locked = false;
        if (th) {
-               reiserfs_write_lock(inode->i_sb);
                if (!update_sd)
                        reiserfs_update_sd(th, inode);
                ret = reiserfs_end_persistent_transaction(th);
-               reiserfs_write_unlock(inode->i_sb);
        }
-
        goto out;
 }
 
@@ -2748,7 +2790,10 @@ int reiserfs_commit_write(struct file *f, struct page *page,
        int update_sd = 0;
        struct reiserfs_transaction_handle *th = NULL;
 
+       reiserfs_write_unlock(inode->i_sb);
        reiserfs_wait_on_write_block(inode->i_sb);
+       reiserfs_write_lock(inode->i_sb);
+
        if (reiserfs_transaction_running(inode->i_sb)) {
                th = current->journal_info;
        }
@@ -2760,7 +2805,6 @@ int reiserfs_commit_write(struct file *f, struct page *page,
         */
        if (pos > inode->i_size) {
                struct reiserfs_transaction_handle myth;
-               reiserfs_write_lock(inode->i_sb);
                /* If the file have grown beyond the border where it
                   can have a tail, unmark it as needing a tail
                   packing */
@@ -2771,10 +2815,9 @@ int reiserfs_commit_write(struct file *f, struct page *page,
                        REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
 
                ret = journal_begin(&myth, inode->i_sb, 1);
-               if (ret) {
-                       reiserfs_write_unlock(inode->i_sb);
+               if (ret)
                        goto journal_error;
-               }
+
                reiserfs_update_inode_transaction(inode);
                inode->i_size = pos;
                /*
@@ -2786,16 +2829,13 @@ int reiserfs_commit_write(struct file *f, struct page *page,
                reiserfs_update_sd(&myth, inode);
                update_sd = 1;
                ret = journal_end(&myth, inode->i_sb, 1);
-               reiserfs_write_unlock(inode->i_sb);
                if (ret)
                        goto journal_error;
        }
        if (th) {
-               reiserfs_write_lock(inode->i_sb);
                if (!update_sd)
                        mark_inode_dirty(inode);
                ret = reiserfs_end_persistent_transaction(th);
-               reiserfs_write_unlock(inode->i_sb);
                if (ret)
                        goto out;
        }
@@ -2805,11 +2845,9 @@ int reiserfs_commit_write(struct file *f, struct page *page,
 
       journal_error:
        if (th) {
-               reiserfs_write_lock(inode->i_sb);
                if (!update_sd)
                        reiserfs_update_sd(th, inode);
                ret = reiserfs_end_persistent_transaction(th);
-               reiserfs_write_unlock(inode->i_sb);
        }
 
        return ret;
@@ -3030,14 +3068,17 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb,
 int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
-       int error;
        unsigned int ia_valid;
+       int depth;
+       int error;
 
        /* must be turned off for recursive notify_change calls */
        ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
 
-       reiserfs_write_lock(inode->i_sb);
+       depth = reiserfs_write_lock_once(inode->i_sb);
        if (attr->ia_valid & ATTR_SIZE) {
+               dquot_initialize(inode);
+
                /* version 2 items will be caught by the s_maxbytes check
                 ** done for us in vmtruncate
                 */
@@ -3099,8 +3140,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                                                  jbegin_count);
                                if (error)
                                        goto out;
-                               error =
-                                   DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
+                               error = dquot_transfer(inode, attr);
                                if (error) {
                                        journal_end(&th, inode->i_sb,
                                                    jbegin_count);
@@ -3117,8 +3157,17 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                                    journal_end(&th, inode->i_sb, jbegin_count);
                        }
                }
-               if (!error)
+               if (!error) {
+                       /*
+                        * Relax the lock here, as it might truncate the
+                        * inode pages and wait for inode pages locks.
+                        * To release such page lock, the owner needs the
+                        * reiserfs lock
+                        */
+                       reiserfs_write_unlock_once(inode->i_sb, depth);
                        error = inode_setattr(inode, attr);
+                       depth = reiserfs_write_lock_once(inode->i_sb);
+               }
        }
 
        if (!error && reiserfs_posixacl(inode->i_sb)) {
@@ -3127,7 +3176,8 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
       out:
-       reiserfs_write_unlock(inode->i_sb);
+       reiserfs_write_unlock_once(inode->i_sb, depth);
+
        return error;
 }