vserver 1.9.5.x5
[linux-2.6.git] / fs / reiserfs / inode.c
index 72abbaa..d44d122 100644 (file)
 
 extern int reiserfs_default_io_size; /* default io size devuned in super.c */
 
-/* args for the create parameter of reiserfs_get_block */
-#define GET_BLOCK_NO_CREATE 0 /* don't create new blocks or convert tails */
-#define GET_BLOCK_CREATE 1    /* add anything you need to find block */
-#define GET_BLOCK_NO_HOLE 2   /* return -ENOENT for file holes */
-#define GET_BLOCK_READ_DIRECT 4  /* read the tail if indirect item not found */
-#define GET_BLOCK_NO_ISEM     8 /* i_sem is not held, don't preallocate */
-#define GET_BLOCK_NO_DANGLE   16 /* don't leave any transactions running */
-
-static int reiserfs_get_block (struct inode * inode, sector_t block,
-                              struct buffer_head * bh_result, int create);
 static int reiserfs_commit_write(struct file *f, struct page *page,
                                  unsigned from, unsigned to);
+static int reiserfs_prepare_write(struct file *f, struct page *page,
+                                 unsigned from, unsigned to);
 
 void reiserfs_delete_inode (struct inode * inode)
 {
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2; 
+    /* We need blocks for transaction + (user+group) quota update (possibly delete) */
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS;
     struct reiserfs_transaction_handle th ;
   
     reiserfs_write_lock(inode->i_sb);
 
-    DQUOT_FREE_INODE(inode);
     /* 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 */
        down (&inode->i_sem); 
 
        reiserfs_delete_xattrs (inode);
 
-       journal_begin(&th, inode->i_sb, jbegin_count) ;
+       if (journal_begin(&th, inode->i_sb, jbegin_count)) {
+           up (&inode->i_sem);
+           goto out;
+       }
        reiserfs_update_inode_transaction(inode) ;
 
-       reiserfs_delete_object (&th, inode);
+       if (reiserfs_delete_object (&th, inode)) {
+           up (&inode->i_sem);
+           goto out;
+       }
+
+       /* Do quota update inside a transaction for journaled quotas. We must do that
+        * after delete_object so that quota updates go into the same transaction as
+        * stat data deletion */
+       DQUOT_FREE_INODE(inode);
 
-       journal_end(&th, inode->i_sb, jbegin_count) ;
+       if (journal_end(&th, inode->i_sb, jbegin_count)) {
+           up (&inode->i_sem);
+           goto out;
+       }
 
         up (&inode->i_sem);
 
         /* all items of file are deleted, so we can remove "save" link */
-       remove_save_link (inode, 0/* not truncate */);
+       remove_save_link (inode, 0/* not truncate */); /* we can't do anything
+                                                        * about an error here */
     } else {
        /* no object items are in the tree */
        ;
     }
+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);
@@ -202,20 +210,28 @@ static int file_capable (struct inode * inode, long block)
     return 0;
 }
 
-/*static*/ void restart_transaction(struct reiserfs_transaction_handle *th,
+/*static*/ int restart_transaction(struct reiserfs_transaction_handle *th,
                                struct inode *inode, struct path *path) {
   struct super_block *s = th->t_super ;
   int len = th->t_blocks_allocated ;
+  int err;
+
+  BUG_ON (!th->t_trans_id);
+  BUG_ON (!th->t_refcount);
 
   /* we cannot restart while nested */
   if (th->t_refcount > 1) {
-      return  ;
+      return  ;
   }
   pathrelse(path) ;
   reiserfs_update_sd(th, inode) ;
-  journal_end(th, s, len) ;
-  journal_begin(th, s, JOURNAL_PER_BALANCE_CNT * 6) ;
-  reiserfs_update_inode_transaction(inode) ;
+  err = journal_end(th, s, len) ;
+  if (!err) {
+      err = journal_begin(th, s, JOURNAL_PER_BALANCE_CNT * 6) ;
+      if (!err)
+        reiserfs_update_inode_transaction(inode) ;
+  }
+  return err;
 }
 
 // it is called by get_block when create == 0. Returns block number
@@ -390,8 +406,8 @@ finished:
 
 // this is called to create file map. So, _get_block_create_0 will not
 // read direct item
-int reiserfs_bmap (struct inode * inode, sector_t block,
-                  struct buffer_head * bh_result, int create)
+static int reiserfs_bmap (struct inode * inode, sector_t block,
+                         struct buffer_head * bh_result, int create)
 {
     if (!file_capable (inode, block))
        return -EFBIG;
@@ -444,9 +460,11 @@ static int reiserfs_get_blocks_direct_io(struct inode *inode,
 
     ret = reiserfs_get_block(inode, iblock, bh_result,
                              create | GET_BLOCK_NO_DANGLE) ;
+    if (ret)
+        goto out;
 
     /* don't allow direct io onto tail pages */
-    if (ret == 0 && buffer_mapped(bh_result) && bh_result->b_blocknr == 0) {
+    if (buffer_mapped(bh_result) && bh_result->b_blocknr == 0) {
         /* make sure future calls to the direct io funcs for this offset
         ** in the file fail by unmapping the buffer
         */
@@ -456,11 +474,15 @@ static int reiserfs_get_blocks_direct_io(struct inode *inode,
     /* Possible unpacked tail. Flush the data before pages have
        disappeared */
     if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) {
+        int err;
         lock_kernel();
-        reiserfs_commit_for_inode(inode);
+        err = reiserfs_commit_for_inode(inode);
         REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
         unlock_kernel();
+        if (err < 0)
+            ret = err;
     }
+out:
     return ret ;
 }
 
@@ -540,6 +562,7 @@ static inline int _allocate_block(struct reiserfs_transaction_handle *th,
                           b_blocknr_t *allocated_block_nr, 
                           struct path * path,
                           int flags) {
+    BUG_ON (!th->t_trans_id);
   
 #ifdef REISERFS_PREALLOCATE
     if (!(flags & GET_BLOCK_NO_ISEM)) {
@@ -552,7 +575,7 @@ static inline int _allocate_block(struct reiserfs_transaction_handle *th,
 int reiserfs_get_block (struct inode * inode, sector_t block,
                        struct buffer_head * bh_result, int create)
 {
-    int repeat, retval;
+    int repeat, retval = 0;
     b_blocknr_t allocated_block_nr = 0;// b_blocknr_t is (unsigned) 32 bit int
     INITIALIZE_PATH(path);
     int pos_in_item;
@@ -567,8 +590,9 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
         . 3 balancings in direct->indirect conversion
         . 1 block involved into reiserfs_update_sd()
        XXX in practically impossible worst case direct2indirect()
-       can incur (much) more that 3 balancings. */
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1;
+       can incur (much) more than 3 balancings.
+       quota update for user, group */
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS;
     int version;
     int dangle = 1;
     loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ;
@@ -656,7 +680,9 @@ start_trans:
            ** research if we succeed on the second try
            */
            SB_JOURNAL(inode->i_sb)->j_next_async_flush = 1;
-           restart_transaction(th, inode, &path) ;
+           retval = restart_transaction(th, inode, &path) ;
+            if (retval)
+                goto failure;
            repeat = _allocate_block(th, block, inode, &allocated_block_nr, NULL, create);
 
            if (repeat != NO_DISK_SPACE && repeat != QUOTA_EXCEEDED) {
@@ -697,8 +723,9 @@ start_trans:
        }
        set_block_dev_mapped(bh_result, unfm_ptr, inode);
        pathrelse (&path);
+        retval = 0;
        if (!dangle && th)
-           reiserfs_end_persistent_transaction(th);
+           retval = reiserfs_end_persistent_transaction(th);
 
        reiserfs_write_unlock(inode->i_sb);
         
@@ -706,7 +733,7 @@ start_trans:
        ** there is no need to make sure the inode is updated with this 
        ** transaction
        */
-       return 0;
+       return retval;
     }
 
     if (!th) {
@@ -767,9 +794,12 @@ start_trans:
                 * ugly, but we can only end the transaction if
                 * we aren't nested
                 */
+               BUG_ON (!th->t_refcount);
                if (th->t_refcount == 1) {
-                   reiserfs_end_persistent_transaction(th);
+                   retval = reiserfs_end_persistent_transaction(th);
                    th = NULL;
+                   if (retval)
+                       goto failure;
                }
 
                retval = convert_tail_for_hole(inode, bh_result, tail_offset) ;
@@ -899,7 +929,9 @@ start_trans:
        ** ending their transaction will be able to continue.
        */
        if (journal_transaction_should_end(th, th->t_blocks_allocated)) {
-         restart_transaction(th, inode, &path) ;
+         retval = restart_transaction(th, inode, &path) ;
+         if (retval)
+           goto failure;
        }
        /* inserting indirect pointers for a hole can take a 
        ** long time.  reschedule if needed
@@ -930,10 +962,15 @@ start_trans:
     retval = 0;
 
  failure:
-    if (th && !dangle) {
-      reiserfs_update_sd(th, inode) ;
-      reiserfs_end_persistent_transaction(th);
+    if (th && (!dangle || (retval && !th->t_trans_id))) {
+        int err;
+        if (th->t_trans_id)
+            reiserfs_update_sd(th, inode);
+        err = reiserfs_end_persistent_transaction(th);
+        if (err)
+            retval = err;
     }
+
     reiserfs_write_unlock(inode->i_sb);
     reiserfs_check_path(&path) ;
     return retval;
@@ -1225,6 +1262,8 @@ void reiserfs_update_sd_size (struct reiserfs_transaction_handle *th,
     struct item_head *ih, tmp_ih ;
     int retval;
 
+    BUG_ON (!th->t_trans_id);
+
     make_cpu_key (&key, inode, SD_OFFSET, TYPE_STAT_DATA, 3);//key type is unimportant
     
     for(;;) {
@@ -1418,12 +1457,14 @@ struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp)
     
     key.on_disk_key.k_objectid = data[0] ;
     key.on_disk_key.k_dir_id = data[1] ;
+    reiserfs_write_lock(sb);
     inode = reiserfs_iget(sb, &key) ;
     if (inode && !IS_ERR(inode) && data[2] != 0 &&
        data[2] != inode->i_generation) {
            iput(inode) ;
            inode = NULL ;
     }
+    reiserfs_write_unlock(sb);
     if (!inode)
            inode = ERR_PTR(-ESTALE);
     if (IS_ERR(inode))
@@ -1518,12 +1559,8 @@ int reiserfs_write_inode (struct inode * inode, int do_sync) {
     struct reiserfs_transaction_handle th ;
     int jbegin_count = 1 ;
 
-    if (inode->i_sb->s_flags & MS_RDONLY) {
-        reiserfs_warning (inode->i_sb,
-                         "clm-6005: writing inode %lu on readonly FS",
-                         inode->i_ino) ;
+    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 
     ** inode needs to reach disk for safety, and they can safely be
@@ -1531,24 +1568,15 @@ int reiserfs_write_inode (struct inode * inode, int do_sync) {
     */
     if (do_sync && !(current->flags & PF_MEMALLOC)) {
        reiserfs_write_lock(inode->i_sb);
-       journal_begin(&th, inode->i_sb, jbegin_count) ;
-       reiserfs_update_sd (&th, inode);
-       journal_end_sync(&th, inode->i_sb, jbegin_count) ;
+       if (!journal_begin(&th, inode->i_sb, jbegin_count)) {
+            reiserfs_update_sd (&th, inode);
+            journal_end_sync(&th, inode->i_sb, jbegin_count) ;
+        }
        reiserfs_write_unlock(inode->i_sb);
     }
     return 0;
 }
 
-/* FIXME: no need any more. right? */
-int reiserfs_sync_inode (struct reiserfs_transaction_handle *th, struct inode * inode)
-{
-  int err = 0;
-
-  reiserfs_update_sd (th, inode);
-  return err;
-}
-
-
 /* stat data of new object is inserted already, this inserts the item
    containing "." and ".." entries */
 static int reiserfs_new_directory (struct reiserfs_transaction_handle *th, 
@@ -1561,6 +1589,8 @@ static int reiserfs_new_directory (struct reiserfs_transaction_handle *th,
     char * body = empty_dir;
     struct cpu_key key;
     int retval;
+
+    BUG_ON (!th->t_trans_id);
     
     _make_cpu_key (&key, KEY_FORMAT_3_5, le32_to_cpu (ih->ih_key.k_dir_id),
                   le32_to_cpu (ih->ih_key.k_objectid), DOT_OFFSET, TYPE_DIRENTRY, 3/*key length*/);
@@ -1612,6 +1642,8 @@ static int reiserfs_new_symlink (struct reiserfs_transaction_handle *th,
     struct cpu_key key;
     int retval;
 
+    BUG_ON (!th->t_trans_id);
+
     _make_cpu_key (&key, KEY_FORMAT_3_5, 
                   le32_to_cpu (ih->ih_key.k_dir_id), 
                   le32_to_cpu (ih->ih_key.k_objectid),
@@ -1662,7 +1694,13 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
     struct stat_data sd;
     int retval;
     int err;
+
+    BUG_ON (!th->t_trans_id);
   
+    if (DQUOT_ALLOC_INODE(inode)) {
+       err = -EDQUOT;
+       goto out_end_trans;
+    }
     if (!dir || !dir->i_nlink) {
        err = -EPERM;
        goto out_bad_inode;
@@ -1700,7 +1738,8 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
     if( S_ISLNK( inode -> i_mode ) )
            inode -> i_flags &= ~ ( S_IMMUTABLE | S_APPEND );
 
-    inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+    inode->i_mtime = inode->i_atime = inode->i_ctime =
+           CURRENT_TIME_SEC;
     inode->i_size = i_size;
     inode->i_blocks = 0;
     inode->i_bytes = 0;
@@ -1830,9 +1869,12 @@ out_bad_inode:
     /* Invalidate the object, nothing was inserted yet */
     INODE_PKEY(inode)->k_objectid = 0;
 
-    /* dquot_drop must be done outside a transaction */
-    journal_end(th, th->t_super, th->t_blocks_allocated) ;
+    /* Quota change must be inside a transaction for journaling */
     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);
     inode->i_flags |= S_NOQUOTA;
     make_bad_inode(inode);
@@ -1936,7 +1978,7 @@ unlock:
 **
 ** some code taken from block_truncate_page
 */
-void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {
+int reiserfs_truncate_file(struct inode *p_s_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) ;
@@ -1972,18 +2014,28 @@ void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {
     /* 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 */
-    journal_begin(&th, p_s_inode->i_sb,  JOURNAL_PER_BALANCE_CNT * 2 + 1 ) ;
+    error = journal_begin (&th, p_s_inode->i_sb,
+                           JOURNAL_PER_BALANCE_CNT * 2 + 1);
+    if (error)
+        goto out;
     reiserfs_update_inode_transaction(p_s_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);
-    reiserfs_do_truncate (&th, p_s_inode, page, update_timestamps) ;
-    journal_end(&th, p_s_inode->i_sb,  JOURNAL_PER_BALANCE_CNT * 2 + 1 ) ;
+    error = reiserfs_do_truncate (&th, p_s_inode, page, update_timestamps) ;
+    if (error)
+        goto out;
+    error = journal_end (&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
+    if (error)
+        goto out;
 
-    if (update_timestamps)
-       remove_save_link (p_s_inode, 1/* truncate */);
+    if (update_timestamps) {
+       error = remove_save_link (p_s_inode, 1/* truncate */);
+        if (error)
+            goto out;
+    }
 
     if (page) {
         length = offset & (blocksize - 1) ;
@@ -2005,6 +2057,14 @@ void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {
     }
 
     reiserfs_write_unlock(p_s_inode->i_sb);
+    return 0;
+out:
+    if (page) {
+        unlock_page (page);
+        page_cache_release (page);
+    }
+    reiserfs_write_unlock(p_s_inode->i_sb);
+    return error;
 }
 
 static int map_block_for_writepage(struct inode *inode, 
@@ -2074,7 +2134,9 @@ research:
 
        if (!trans_running) {
            /* vs-3050 is gone, no need to drop the path */
-           journal_begin(&th, inode->i_sb, jbegin_count) ;
+           retval = journal_begin(&th, inode->i_sb, jbegin_count) ;
+            if (retval)
+                goto out;
            reiserfs_update_inode_transaction(inode) ;
            trans_running = 1;
            if (fs_changed(fs_gen, inode->i_sb) && item_moved(&tmp_ih, &path)) {
@@ -2114,7 +2176,9 @@ research:
 out:
     pathrelse(&path) ;
     if (trans_running) {
-       journal_end(&th, inode->i_sb, jbegin_count) ;
+        int err = journal_end(&th, inode->i_sb, jbegin_count) ;
+        if (err)
+            retval = err;
        trans_running = 0;
     }
     reiserfs_write_unlock(inode->i_sb);
@@ -2220,7 +2284,11 @@ static int reiserfs_write_full_page(struct page *page, struct writeback_control
     if (checked) {
        ClearPageChecked(page);
        reiserfs_write_lock(s);
-       journal_begin(&th, s, bh_per_page + 1);
+       error = journal_begin(&th, s, bh_per_page + 1);
+       if (error) {
+           reiserfs_write_unlock(s);
+           goto fail;
+       }
        reiserfs_update_inode_transaction(inode);
     }
     /* now go through and lock any dirty buffers on the page */
@@ -2255,8 +2323,10 @@ static int reiserfs_write_full_page(struct page *page, struct writeback_control
     } while((bh = bh->b_this_page) != head);
 
     if (checked) {
-       journal_end(&th, s, bh_per_page + 1);
+       error = journal_end(&th, s, bh_per_page + 1);
        reiserfs_write_unlock(s);
+       if (error)
+           goto fail;
     }
     BUG_ON(PageWriteback(page));
     set_page_writeback(page);
@@ -2352,7 +2422,7 @@ static int reiserfs_writepage (struct page * page, struct writeback_control *wbc
     return reiserfs_write_full_page(page, wbc) ;
 }
 
-int reiserfs_prepare_write(struct file *f, struct page *page, 
+static int reiserfs_prepare_write(struct file *f, struct page *page,
                           unsigned from, unsigned to) {
     struct inode *inode = page->mapping->host ;
     int ret;
@@ -2362,7 +2432,9 @@ int reiserfs_prepare_write(struct file *f, struct page *page,
     fix_tail_page_for_writing(page) ;
     if (reiserfs_transaction_running(inode->i_sb)) {
        struct reiserfs_transaction_handle *th;
-        th = (struct reiserfs_transaction_handle *)current->journal_info;
+       th = (struct reiserfs_transaction_handle *)current->journal_info;
+        BUG_ON (!th->t_refcount);
+        BUG_ON (!th->t_trans_id);
        old_ref = th->t_refcount;
        th->t_refcount++;
     }
@@ -2384,9 +2456,12 @@ int reiserfs_prepare_write(struct file *f, struct page *page,
            if (old_ref)
                th->t_refcount--;
            else {
+                int err;
                reiserfs_write_lock(inode->i_sb);
-               reiserfs_end_persistent_transaction(th);
+               err = reiserfs_end_persistent_transaction(th);
                reiserfs_write_unlock(inode->i_sb);
+                if (err)
+                    ret = err;
            }
        }
     }
@@ -2427,20 +2502,28 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
             (have_small_tails (inode->i_sb) && inode->i_size > i_block_size(inode)) )
            REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask ;
 
-       journal_begin(&myth, inode->i_sb, 1) ;
+       ret = journal_begin(&myth, inode->i_sb, 1) ;
+       if (ret) {
+           reiserfs_write_unlock(inode->i_sb);
+           goto journal_error;
+       }
        reiserfs_update_inode_transaction(inode) ;
        inode->i_size = pos ;
        reiserfs_update_sd(&myth, inode) ;
        update_sd = 1;
-       journal_end(&myth, inode->i_sb, 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)
            reiserfs_update_sd(th, inode) ;
-        reiserfs_end_persistent_transaction(th);
+       ret = reiserfs_end_persistent_transaction(th);
        reiserfs_write_unlock(inode->i_sb);
+       if (ret)
+           goto out;
     }
  
     /* we test for O_SYNC here so we can commit the transaction
@@ -2448,10 +2531,22 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
     */
     if (f && (f->f_flags & O_SYNC)) {
        reiserfs_write_lock(inode->i_sb);
-       reiserfs_commit_for_inode(inode) ;
+       ret = reiserfs_commit_for_inode(inode) ;
        reiserfs_write_unlock(inode->i_sb);
     }
+out:
     return ret ;
+
+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;
 }
 
 void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode )
@@ -2714,11 +2809,16 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
         if (attr->ia_size > inode->i_size) {
            error = generic_cont_expand(inode, attr->ia_size) ;
            if (REISERFS_I(inode)->i_prealloc_count > 0) {
+               int err;
                struct reiserfs_transaction_handle th ;
                /* we're changing at most 2 bitmaps, inode + super */
-               journal_begin(&th, inode->i_sb, 4) ;
-               reiserfs_discard_prealloc (&th, inode);
-               journal_end(&th, inode->i_sb, 4) ;
+               err = journal_begin(&th, inode->i_sb, 4) ;
+               if (!err) {
+                   reiserfs_discard_prealloc (&th, inode);
+                   err = journal_end(&th, inode->i_sb, 4) ;
+               }
+               if (err)
+                   error = err;
            }
            if (error)
                goto out;
@@ -2743,8 +2843,25 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
            (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
                 error = reiserfs_chown_xattrs (inode, attr);
 
-                if (!error)
+                if (!error) {
+                   struct reiserfs_transaction_handle th;
+
+                   /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
+                   journal_begin(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
                     error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
+                   if (error) {
+                       journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+                       goto out;
+                   }
+                   /* Update corresponding info in inode so that everything is in
+                    * one transaction */
+                   if (attr->ia_valid & ATTR_UID)
+                       inode->i_uid = attr->ia_uid;
+                   if (attr->ia_valid & ATTR_GID)
+                       inode->i_gid = attr->ia_gid;
+                   mark_inode_dirty(inode);
+                   journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+               }
         }
         if (!error)
             error = inode_setattr(inode, attr) ;