patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / reiserfs / stree.c
index 0d4f5f5..ab1c01d 100644 (file)
@@ -60,6 +60,7 @@
 #include <linux/reiserfs_fs.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/quotaops.h>
 
 /* Does the buffer contain a disk block which is in the tree. */
 inline int B_IS_IN_TREE (const struct buffer_head * p_s_bh)
@@ -71,9 +72,6 @@ inline int B_IS_IN_TREE (const struct buffer_head * p_s_bh)
   return ( B_LEVEL (p_s_bh) != FREE_LEVEL );
 }
 
-
-
-
 inline void copy_short_key (void * to, const void * from)
 {
     memcpy (to, from, SHORT_KEY_SIZE);
@@ -166,7 +164,7 @@ inline int comp_cpu_keys (const struct cpu_key * key1,
     if (cpu_key_k_offset (key1) > cpu_key_k_offset (key2))
        return 1;
 
-    reiserfs_warning ("comp_cpu_keys: type are compared for %K and %K\n",
+    reiserfs_warning (NULL, "comp_cpu_keys: type are compared for %K and %K",
                      key1, key2);
 
     if (cpu_key_k_type (key1) < cpu_key_k_type (key2))
@@ -499,21 +497,21 @@ static int is_leaf (char * buf, int blocksize, struct buffer_head * bh)
 
     blkh = (struct block_head *)buf;
     if ( blkh_level(blkh) != DISK_LEAF_NODE_LEVEL) {
-       printk ("is_leaf: this should be caught earlier\n");
+       reiserfs_warning (NULL, "is_leaf: this should be caught earlier");
        return 0;
     }
 
     nr = blkh_nr_item(blkh);
     if (nr < 1 || nr > ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN))) {
        /* item number is too big or too small */
-       reiserfs_warning ("is_leaf: nr_item seems wrong: %z\n", bh);
+       reiserfs_warning (NULL, "is_leaf: nr_item seems wrong: %z", bh);
        return 0;
     }
     ih = (struct item_head *)(buf + BLKH_SIZE) + nr - 1;
     used_space = BLKH_SIZE + IH_SIZE * nr + (blocksize - ih_location (ih));
     if (used_space != blocksize - blkh_free_space(blkh)) {
        /* free space does not match to calculated amount of use space */
-       reiserfs_warning ("is_leaf: free space seems wrong: %z\n", bh);
+       reiserfs_warning (NULL, "is_leaf: free space seems wrong: %z", bh);
        return 0;
     }
 
@@ -525,19 +523,19 @@ static int is_leaf (char * buf, int blocksize, struct buffer_head * bh)
     prev_location = blocksize;
     for (i = 0; i < nr; i ++, ih ++) {
        if ( le_ih_k_type(ih) == TYPE_ANY) {
-           reiserfs_warning ("is_leaf: wrong item type for item %h\n",ih);
+           reiserfs_warning (NULL, "is_leaf: wrong item type for item %h",ih);
            return 0;
        }
        if (ih_location (ih) >= blocksize || ih_location (ih) < IH_SIZE * nr) {
-           reiserfs_warning ("is_leaf: item location seems wrong: %h\n", ih);
+           reiserfs_warning (NULL, "is_leaf: item location seems wrong: %h", ih);
            return 0;
        }
        if (ih_item_len (ih) < 1 || ih_item_len (ih) > MAX_ITEM_LEN (blocksize)) {
-           reiserfs_warning ("is_leaf: item length seems wrong: %h\n", ih);
+           reiserfs_warning (NULL, "is_leaf: item length seems wrong: %h", ih);
            return 0;
        }
        if (prev_location - ih_location (ih) != ih_item_len (ih)) {
-           reiserfs_warning ("is_leaf: item location seems wrong (second one): %h\n", ih);
+           reiserfs_warning (NULL, "is_leaf: item location seems wrong (second one): %h", ih);
            return 0;
        }
        prev_location = ih_location (ih);
@@ -559,20 +557,20 @@ static int is_internal (char * buf, int blocksize, struct buffer_head * bh)
     nr = blkh_level(blkh);
     if (nr <= DISK_LEAF_NODE_LEVEL || nr > MAX_HEIGHT) {
        /* this level is not possible for internal nodes */
-       printk ("is_internal: this should be caught earlier\n");
+       reiserfs_warning (NULL, "is_internal: this should be caught earlier");
        return 0;
     }
     
     nr = blkh_nr_item(blkh);
     if (nr > (blocksize - BLKH_SIZE - DC_SIZE) / (KEY_SIZE + DC_SIZE)) {
        /* for internal which is not root we might check min number of keys */
-       reiserfs_warning ("is_internal: number of key seems wrong: %z\n", bh);
+       reiserfs_warning (NULL, "is_internal: number of key seems wrong: %z", bh);
        return 0;
     }
 
     used_space = BLKH_SIZE + KEY_SIZE * nr + DC_SIZE * (nr + 1);
     if (used_space != blocksize - blkh_free_space(blkh)) {
-       reiserfs_warning ("is_internal: free space seems wrong: %z\n", bh);
+       reiserfs_warning (NULL, "is_internal: free space seems wrong: %z", bh);
        return 0;
     }
 
@@ -586,7 +584,7 @@ static int is_internal (char * buf, int blocksize, struct buffer_head * bh)
 static int is_tree_node (struct buffer_head * bh, int level)
 {
     if (B_LEVEL (bh) != level) {
-       printk ("is_tree_node: node level %d does not match to the expected one %d\n",
+       reiserfs_warning (NULL, "is_tree_node: node level %d does not match to the expected one %d",
                B_LEVEL (bh), level);
        return 0;
     }
@@ -683,9 +681,9 @@ int search_by_key (struct super_block * p_s_sb,
 
 #ifdef CONFIG_REISERFS_CHECK
        if ( !(++n_repeat_counter % 50000) )
-           reiserfs_warning ("PAP-5100: search_by_key: %s:"
+           reiserfs_warning (p_s_sb, "PAP-5100: search_by_key: %s:"
                              "there were %d iterations of while loop "
-                             "looking for key %K\n",
+                             "looking for key %K",
                              current->comm, n_repeat_counter, p_s_key);
 #endif
 
@@ -748,8 +746,8 @@ int search_by_key (struct super_block * p_s_sb,
        // make sure, that the node contents look like a node of
        // certain level
        if (!is_tree_node (p_s_bh, expected_level)) {
-           reiserfs_warning ("vs-5150: search_by_key: "
-                             "invalid format found in block %ld. Fsck?\n", 
+           reiserfs_warning (p_s_sb, "vs-5150: search_by_key: "
+                             "invalid format found in block %ld. Fsck?",
                              p_s_bh->b_blocknr);
            pathrelse (p_s_search_path);
            return IO_ERROR;
@@ -1125,8 +1123,7 @@ static char  prepare_for_delete_or_cut(
                tmp = get_block_num(p_n_unfm_pointer,0);
                put_block_num(p_n_unfm_pointer, 0, 0);
                journal_mark_dirty (th, p_s_sb, p_s_bh);
-               inode->i_blocks -= p_s_sb->s_blocksize / 512;
-               reiserfs_free_block(th, tmp);
+               reiserfs_free_block(th, inode, tmp, 1);
                if ( item_moved (&s_ih, p_s_path) )  {
                        need_research = 1;
                        break ;
@@ -1155,8 +1152,7 @@ static char  prepare_for_delete_or_cut(
     }
 }
 
-
-/* Calculate bytes number which will be deleted or cutted in the balance. */
+/* Calculate number of bytes which will be deleted or cut during balance */
 int calc_deleted_bytes_number(
     struct  tree_balance  * p_s_tb,
     char                    c_mode
@@ -1167,14 +1163,14 @@ int calc_deleted_bytes_number(
     if ( is_statdata_le_ih (p_le_ih) )
        return 0;
 
+    n_del_size = ( c_mode == M_DELETE ) ? ih_item_len(p_le_ih) : -p_s_tb->insert_size[0];
     if ( is_direntry_le_ih (p_le_ih) ) {
        // return EMPTY_DIR_SIZE; /* We delete emty directoris only. */
        // we can't use EMPTY_DIR_SIZE, as old format dirs have a different
        // empty size.  ick. FIXME, is this right?
        //
-       return ih_item_len(p_le_ih);
+       return n_del_size ;
     }
-    n_del_size = ( c_mode == M_DELETE ) ? ih_item_len(p_le_ih) : -p_s_tb->insert_size[0];
 
     if ( is_indirect_le_ih (p_le_ih) )
        n_del_size = (n_del_size/UNFM_P_SIZE)*
@@ -1208,17 +1204,46 @@ void padd_item (char * item, int total_length, int length)
        item [--i] = 0;
 }
 
+#ifdef REISERQUOTA_DEBUG
+char key2type(struct key *ih)
+{
+  if (is_direntry_le_key(2, ih))
+    return 'd';
+  if (is_direct_le_key(2, ih))
+    return 'D';
+  if (is_indirect_le_key(2, ih))
+    return 'i';
+  if (is_statdata_le_key(2, ih))
+    return 's';
+  return 'u';
+}
+
+char head2type(struct item_head *ih)
+{
+  if (is_direntry_le_ih(ih))
+    return 'd';
+  if (is_direct_le_ih(ih))
+    return 'D';
+  if (is_indirect_le_ih(ih))
+    return 'i';
+  if (is_statdata_le_ih(ih))
+    return 's';
+  return 'u';
+}
+#endif
 
 /* Delete object item. */
 int reiserfs_delete_item (struct reiserfs_transaction_handle *th, 
                          struct path * p_s_path, /* Path to the deleted item. */
                          const struct cpu_key * p_s_item_key, /* Key to search for the deleted item.  */
-                         struct inode * p_s_inode,/* inode is here just to update i_blocks */
+                         struct inode * p_s_inode,/* inode is here just to update i_blocks and quotas */
                          struct buffer_head  * p_s_un_bh)    /* NULL or unformatted node pointer.    */
 {
     struct super_block * p_s_sb = p_s_inode->i_sb;
     struct tree_balance   s_del_balance;
     struct item_head      s_ih;
+    struct item_head      *q_ih;
+    int                          quota_cut_bytes;
     int                   n_ret_value,
        n_del_size,
        n_removed;
@@ -1255,8 +1280,8 @@ int reiserfs_delete_item (struct reiserfs_transaction_handle *th,
        if (n_ret_value == IO_ERROR)
            break;
        if (n_ret_value == FILE_NOT_FOUND) {
-           reiserfs_warning ("vs-5340: reiserfs_delete_item: "
-                             "no items of the file %K found\n", p_s_item_key);
+           reiserfs_warning (p_s_sb, "vs-5340: reiserfs_delete_item: "
+                             "no items of the file %K found", p_s_item_key);
            break;
        }
     } /* while (1) */
@@ -1268,6 +1293,22 @@ int reiserfs_delete_item (struct reiserfs_transaction_handle *th,
 
     // reiserfs_delete_item returns item length when success
     n_ret_value = calc_deleted_bytes_number(&s_del_balance, M_DELETE);
+    q_ih = get_ih(p_s_path) ;
+    quota_cut_bytes = ih_item_len(q_ih) ;
+
+    /* hack so the quota code doesn't have to guess if the file
+    ** has a tail.  On tail insert, we allocate quota for 1 unformatted node.
+    ** We test the offset because the tail might have been
+    ** split into multiple items, and we only want to decrement for
+    ** the unfm node once
+    */
+    if (!S_ISLNK (p_s_inode->i_mode) && is_direct_le_ih(q_ih)) {
+        if ((le_ih_k_offset(q_ih) & (p_s_sb->s_blocksize - 1)) == 1) {
+            quota_cut_bytes = p_s_sb->s_blocksize + UNFM_P_SIZE;
+        } else {
+           quota_cut_bytes = 0 ;
+       }
+    }
 
     if ( p_s_un_bh )  {
        int off;
@@ -1299,10 +1340,14 @@ int reiserfs_delete_item (struct reiserfs_transaction_handle *th,
               B_I_PITEM(PATH_PLAST_BUFFER(p_s_path), &s_ih), n_ret_value);
        kunmap_atomic(data, KM_USER0);
     }
-
     /* Perform balancing after all resources have been collected at once. */ 
     do_balance(&s_del_balance, NULL, NULL, M_DELETE);
 
+#ifdef REISERQUOTA_DEBUG
+    reiserfs_debug (p_s_sb, "reiserquota delete_item(): freeing %u, id=%u type=%c", quota_cut_bytes, p_s_inode->i_uid, head2type(&s_ih));
+#endif
+    DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes);
+
     /* Return deleted body length */
     return n_ret_value;
 }
@@ -1327,22 +1372,26 @@ int reiserfs_delete_item (struct reiserfs_transaction_handle *th,
 
 /* this deletes item which never gets split */
 void reiserfs_delete_solid_item (struct reiserfs_transaction_handle *th,
+                                struct inode *inode,
                                 struct key * key)
 {
     struct tree_balance tb;
     INITIALIZE_PATH (path);
-    int item_len;
+    int item_len = 0;
     int tb_init = 0 ;
     struct cpu_key cpu_key;
     int retval;
+    int quota_cut_bytes = 0;
     
     le_key2cpu_key (&cpu_key, key);
     
     while (1) {
        retval = search_item (th->t_super, &cpu_key, &path);
        if (retval == IO_ERROR) {
-           reiserfs_warning ("vs-5350: reiserfs_delete_solid_item: "
-                             "i/o failure occurred trying to delete %K\n", &cpu_key);
+           reiserfs_warning (th->t_super,
+                             "vs-5350: reiserfs_delete_solid_item: "
+                             "i/o failure occurred trying to delete %K",
+                             &cpu_key);
            break;
        }
        if (retval != ITEM_FOUND) {
@@ -1350,7 +1399,7 @@ void reiserfs_delete_solid_item (struct reiserfs_transaction_handle *th,
            // No need for a warning, if there is just no free space to insert '..' item into the newly-created subdir
            if ( !( (unsigned long long) GET_HASH_VALUE (le_key_k_offset (le_key_version (key), key)) == 0 && \
                 (unsigned long long) GET_GENERATION_NUMBER (le_key_k_offset (le_key_version (key), key)) == 1 ) )
-               reiserfs_warning ("vs-5355: reiserfs_delete_solid_item: %k not found", key);
+               reiserfs_warning (th->t_super, "vs-5355: reiserfs_delete_solid_item: %k not found", key);
            break;
        }
        if (!tb_init) {
@@ -1358,6 +1407,7 @@ void reiserfs_delete_solid_item (struct reiserfs_transaction_handle *th,
            item_len = ih_item_len( PATH_PITEM_HEAD(&path) );
            init_tb_struct (th, &tb, th->t_super, &path, - (IH_SIZE + item_len));
        }
+       quota_cut_bytes = ih_item_len(PATH_PITEM_HEAD(&path)) ;
 
        retval = fix_nodes (M_DELETE, &tb, NULL, 0);
        if (retval == REPEAT_SEARCH) {
@@ -1367,12 +1417,18 @@ void reiserfs_delete_solid_item (struct reiserfs_transaction_handle *th,
 
        if (retval == CARRY_ON) {
            do_balance (&tb, 0, 0, M_DELETE);
+           if (inode) {        /* Should we count quota for item? (we don't count quotas for save-links) */
+#ifdef REISERQUOTA_DEBUG
+               reiserfs_debug (th->t_super, "reiserquota delete_solid_item(): freeing %u id=%u type=%c", quota_cut_bytes, inode->i_uid, key2type(key));
+#endif
+               DQUOT_FREE_SPACE_NODIRTY(inode, quota_cut_bytes);
+           }
            break;
        }
 
        // IO_ERROR, NO_DISK_SPACE, etc
-       reiserfs_warning ("vs-5360: reiserfs_delete_solid_item: "
-                         "could not delete %K due to fix_nodes failure\n", &cpu_key);
+       reiserfs_warning (th->t_super, "vs-5360: reiserfs_delete_solid_item: "
+                         "could not delete %K due to fix_nodes failure", &cpu_key);
        unfix_nodes (&tb);
        break;
     }
@@ -1399,7 +1455,7 @@ void reiserfs_delete_object (struct reiserfs_transaction_handle *th, struct inod
       }
 /* USE_INODE_GENERATION_COUNTER */
 #endif
-    reiserfs_delete_solid_item (th, INODE_PKEY (inode));
+    reiserfs_delete_solid_item (th, inode, INODE_PKEY (inode));
 }
 
 
@@ -1466,7 +1522,7 @@ static void indirect_to_direct_roll_back (struct reiserfs_transaction_handle *th
        tail_len -= removed;
        set_cpu_key_k_offset (&tail_key, cpu_key_k_offset (&tail_key) - removed);
     }
-    printk ("indirect_to_direct_roll_back: indirect_to_direct conversion has been rolled back due to lack of disk space\n");
+    reiserfs_warning (inode->i_sb, "indirect_to_direct_roll_back: indirect_to_direct conversion has been rolled back due to lack of disk space");
     //mark_file_without_tail (inode);
     mark_inode_dirty (inode);
 }
@@ -1486,12 +1542,14 @@ int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
        structure by using the init_tb_struct and fix_nodes functions.
        After that we can make tree balancing. */
     struct tree_balance s_cut_balance;
+    struct item_head *p_le_ih;
     int n_cut_size = 0,        /* Amount to be cut. */
        n_ret_value = CARRY_ON,
        n_removed = 0,     /* Number of the removed unformatted nodes. */
        n_is_inode_locked = 0;
     char                c_mode;            /* Mode of the balance. */
     int retval2 = -1;
+    int quota_cut_bytes;
     
     
     init_tb_struct(th, &s_cut_balance, p_s_inode->i_sb, p_s_path, n_cut_size);
@@ -1556,7 +1614,7 @@ int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
        if (n_ret_value == POSITION_FOUND)
            continue;
 
-       reiserfs_warning ("PAP-5610: reiserfs_cut_from_item: item %K not found\n", p_s_item_key);
+       reiserfs_warning (p_s_sb, "PAP-5610: reiserfs_cut_from_item: item %K not found", p_s_item_key);
        unfix_nodes (&s_cut_balance);
        return (n_ret_value == IO_ERROR) ? -EIO : -ENOENT;
     } /* while */
@@ -1569,7 +1627,7 @@ int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
            indirect_to_direct_roll_back (th, p_s_inode, p_s_path);
        }
        if (n_ret_value == NO_DISK_SPACE)
-           reiserfs_warning ("NO_DISK_SPACE");
+           reiserfs_warning (p_s_sb, "NO_DISK_SPACE");
        unfix_nodes (&s_cut_balance);
        return -EIO;
     }
@@ -1579,23 +1637,27 @@ int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
     RFALSE( c_mode == M_PASTE || c_mode == M_INSERT, "invalid mode");
 
     /* Calculate number of bytes that need to be cut from the item. */
+    quota_cut_bytes = ( c_mode == M_DELETE ) ? ih_item_len(get_ih(p_s_path)) : -s_cut_balance.insert_size[0];
     if (retval2 == -1)
        n_ret_value = calc_deleted_bytes_number(&s_cut_balance, c_mode);
     else
        n_ret_value = retval2;
-    
-    if ( c_mode == M_DELETE ) {
-       struct item_head * p_le_ih = PATH_PITEM_HEAD (s_cut_balance.tb_path);
-       
-       if ( is_direct_le_ih (p_le_ih) && (le_ih_k_offset (p_le_ih) & (p_s_sb->s_blocksize - 1)) == 1 ) {
-           /* we delete first part of tail which was stored in direct
-               item(s) */
+
+
+    /* For direct items, we only change the quota when deleting the last
+    ** item.
+    */
+    p_le_ih = PATH_PITEM_HEAD (s_cut_balance.tb_path);
+    if (!S_ISLNK (p_s_inode->i_mode) && is_direct_le_ih(p_le_ih)) {
+        if (c_mode == M_DELETE &&
+          (le_ih_k_offset (p_le_ih) & (p_s_sb->s_blocksize - 1)) == 1 ) {
            // FIXME: this is to keep 3.5 happy
            REISERFS_I(p_s_inode)->i_first_direct_byte = U32_MAX;
-           p_s_inode->i_blocks -= p_s_sb->s_blocksize / 512;
+           quota_cut_bytes = p_s_sb->s_blocksize + UNFM_P_SIZE ;
+        } else {
+           quota_cut_bytes = 0 ;
        }
     }
-
 #ifdef CONFIG_REISERFS_CHECK
     if (n_is_inode_locked) {
        struct item_head * le_ih = PATH_PITEM_HEAD (s_cut_balance.tb_path);
@@ -1630,19 +1692,23 @@ int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
        */
        REISERFS_I(p_s_inode)->i_flags &= ~i_pack_on_close_mask ;
     }
+#ifdef REISERQUOTA_DEBUG
+    reiserfs_debug (p_s_inode->i_sb, "reiserquota cut_from_item(): freeing %u id=%u type=%c", quota_cut_bytes, p_s_inode->i_uid, '?');
+#endif
+    DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes);
     return n_ret_value;
 }
 
-
 static void truncate_directory (struct reiserfs_transaction_handle *th, struct inode * inode)
 {
     if (inode->i_nlink)
-       reiserfs_warning ("vs-5655: truncate_directory: link count != 0\n");
+       reiserfs_warning (inode->i_sb,
+                         "vs-5655: truncate_directory: link count != 0");
 
     set_le_key_k_offset (KEY_FORMAT_3_5, INODE_PKEY (inode), DOT_OFFSET);
     set_le_key_k_type (KEY_FORMAT_3_5, INODE_PKEY (inode), TYPE_DIRENTRY);
-    reiserfs_delete_solid_item (th, INODE_PKEY (inode));
-
+    reiserfs_delete_solid_item (th, inode, INODE_PKEY (inode));
+    reiserfs_update_sd(th, inode) ;
     set_le_key_k_offset (KEY_FORMAT_3_5, INODE_PKEY (inode), SD_OFFSET);
     set_le_key_k_type (KEY_FORMAT_3_5, INODE_PKEY (inode), TYPE_STAT_DATA);    
 }
@@ -1686,14 +1752,14 @@ void reiserfs_do_truncate (struct reiserfs_transaction_handle *th,
 
     retval = search_for_position_by_key(p_s_inode->i_sb, &s_item_key, &s_search_path);
     if (retval == IO_ERROR) {
-       reiserfs_warning ("vs-5657: reiserfs_do_truncate: "
-                         "i/o failure occurred trying to truncate %K\n", &s_item_key);
+       reiserfs_warning (p_s_inode->i_sb, "vs-5657: reiserfs_do_truncate: "
+                         "i/o failure occurred trying to truncate %K", &s_item_key);
        return;
     }
     if (retval == POSITION_FOUND || retval == FILE_NOT_FOUND) {
        pathrelse (&s_search_path);
-       reiserfs_warning ("PAP-5660: reiserfs_do_truncate: "
-                         "wrong result %d of search for %K\n", retval, &s_item_key);
+       reiserfs_warning (p_s_inode->i_sb, "PAP-5660: reiserfs_do_truncate: "
+                         "wrong result %d of search for %K", retval, &s_item_key);
        return;
     }
 
@@ -1724,7 +1790,7 @@ void reiserfs_do_truncate (struct reiserfs_transaction_handle *th,
        /* Cut or delete file item. */
        n_deleted = reiserfs_cut_from_item(th, &s_search_path, &s_item_key, p_s_inode,  page, n_new_file_size);
        if (n_deleted < 0) {
-           reiserfs_warning ("vs-5665: reiserfs_do_truncate: reiserfs_cut_from_item failed");
+           reiserfs_warning (p_s_inode->i_sb, "vs-5665: reiserfs_do_truncate: reiserfs_cut_from_item failed");
            reiserfs_check_path(&s_search_path) ;
            return;
        }
@@ -1764,7 +1830,7 @@ void reiserfs_do_truncate (struct reiserfs_transaction_handle *th,
              search_for_position_by_key(p_s_inode->i_sb, &s_item_key, &s_search_path) == POSITION_FOUND )  ;
 
     RFALSE( n_file_size > ROUND_UP (n_new_file_size),
-           "PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d\n",
+           "PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d",
            n_new_file_size, n_file_size, s_item_key.on_disk_key.k_objectid);
 
 update_and_out:
@@ -1809,18 +1875,37 @@ static void check_research_for_paste (struct path * path,
 int reiserfs_paste_into_item (struct reiserfs_transaction_handle *th, 
                              struct path         * p_s_search_path,    /* Path to the pasted item.          */
                              const struct cpu_key      * p_s_key,              /* Key to search for the needed item.*/
+                             struct inode        * inode,              /* Inode item belongs to */
                              const char          * p_c_body,           /* Pointer to the bytes to paste.    */
                              int                   n_pasted_size)      /* Size of pasted bytes.             */
 {
     struct tree_balance s_paste_balance;
     int                 retval;
+    int                        fs_gen;
+
+    fs_gen = get_generation(inode->i_sb) ;
 
+#ifdef REISERQUOTA_DEBUG
+    reiserfs_debug (inode->i_sb, "reiserquota paste_into_item(): allocating %u id=%u type=%c", n_pasted_size, inode->i_uid, key2type(&(p_s_key->on_disk_key)));
+#endif
+
+    if (DQUOT_ALLOC_SPACE_NODIRTY(inode, n_pasted_size)) {
+       pathrelse(p_s_search_path);
+       return -EDQUOT;
+    }
     init_tb_struct(th, &s_paste_balance, th->t_super, p_s_search_path, n_pasted_size);
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
     s_paste_balance.key = p_s_key->on_disk_key;
 #endif
-    
-    while ( (retval = fix_nodes(M_PASTE, &s_paste_balance, NULL, p_c_body)) == REPEAT_SEARCH ) {
+
+    /* DQUOT_* can schedule, must check before the fix_nodes */
+    if (fs_changed(fs_gen, inode->i_sb)) {
+       goto search_again;
+    }
+
+    while ((retval = fix_nodes(M_PASTE, &s_paste_balance, NULL, p_c_body)) ==
+REPEAT_SEARCH ) {
+search_again:
        /* file system changed while we were in the fix_nodes */
        PROC_INFO_INC( th -> t_super, paste_into_item_restarted );
        retval = search_for_position_by_key (th->t_super, p_s_key, p_s_search_path);
@@ -1829,7 +1914,7 @@ int reiserfs_paste_into_item (struct reiserfs_transaction_handle *th,
            goto error_out ;
        }
        if (retval == POSITION_FOUND) {
-           reiserfs_warning ("PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists\n", p_s_key);
+           reiserfs_warning (inode->i_sb, "PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists", p_s_key);
            retval = -EEXIST ;
            goto error_out ;
        }
@@ -1849,6 +1934,10 @@ int reiserfs_paste_into_item (struct reiserfs_transaction_handle *th,
 error_out:
     /* this also releases the path */
     unfix_nodes(&s_paste_balance);
+#ifdef REISERQUOTA_DEBUG
+    reiserfs_debug (inode->i_sb, "reiserquota paste_into_item(): freeing %u id=%u type=%c", n_pasted_size, inode->i_uid, key2type(&(p_s_key->on_disk_key)));
+#endif
+    DQUOT_FREE_SPACE_NODIRTY(inode, n_pasted_size);
     return retval ;
 }
 
@@ -1858,23 +1947,45 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
                         struct path         *  p_s_path,         /* Path to the inserteded item.         */
                         const struct cpu_key      * key,
                         struct item_head    *  p_s_ih,           /* Pointer to the item header to insert.*/
+                        struct inode        * inode,
                         const char          *  p_c_body)         /* Pointer to the bytes to insert.      */
 {
     struct tree_balance s_ins_balance;
     int                 retval;
-
+    int fs_gen = 0 ;
+    int quota_bytes = 0 ;
+
+    if (inode) {      /* Do we count quotas for item? */
+       fs_gen = get_generation(inode->i_sb);
+       quota_bytes = ih_item_len(p_s_ih);
+
+       /* hack so the quota code doesn't have to guess if the file has
+        ** a tail, links are always tails, so there's no guessing needed
+        */
+       if (!S_ISLNK (inode->i_mode) && is_direct_le_ih(p_s_ih)) {
+           quota_bytes = inode->i_sb->s_blocksize + UNFM_P_SIZE ;
+       }
+#ifdef REISERQUOTA_DEBUG
+       reiserfs_debug (inode->i_sb, "reiserquota insert_item(): allocating %u id=%u type=%c", quota_bytes, inode->i_uid, head2type(p_s_ih));
+#endif
+       /* We can't dirty inode here. It would be immediately written but
+        * appropriate stat item isn't inserted yet... */
+       if (DQUOT_ALLOC_SPACE_NODIRTY(inode, quota_bytes)) {
+           pathrelse(p_s_path);
+           return -EDQUOT;
+       }
+    }
     init_tb_struct(th, &s_ins_balance, th->t_super, p_s_path, IH_SIZE + ih_item_len(p_s_ih));
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
     s_ins_balance.key = key->on_disk_key;
 #endif
-
-    /*
-    if (p_c_body == 0)
-      n_zeros_num = ih_item_len(p_s_ih);
-    */
-    //    le_key2cpu_key (&key, &(p_s_ih->ih_key));
+    /* DQUOT_* can schedule, must check to be sure calling fix_nodes is safe */
+    if (inode && fs_changed(fs_gen, inode->i_sb)) {
+       goto search_again;
+    }
 
     while ( (retval = fix_nodes(M_INSERT, &s_ins_balance, p_s_ih, p_c_body)) == REPEAT_SEARCH) {
+search_again:
        /* file system changed while we were in the fix_nodes */
        PROC_INFO_INC( th -> t_super, insert_item_restarted );
        retval = search_item (th->t_super, key, p_s_path);
@@ -1883,8 +1994,8 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
            goto error_out ;
        }
        if (retval == ITEM_FOUND) {
-           reiserfs_warning ("PAP-5760: reiserfs_insert_item: "
-                             "key %K already exists in the tree\n", key);
+           reiserfs_warning (th->t_super, "PAP-5760: reiserfs_insert_item: "
+                             "key %K already exists in the tree", key);
            retval = -EEXIST ;
            goto error_out; 
        }
@@ -1900,6 +2011,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
 error_out:
     /* also releases the path */
     unfix_nodes(&s_ins_balance);
+#ifdef REISERQUOTA_DEBUG
+    reiserfs_debug (th->t_super, "reiserquota insert_item(): freeing %u id=%u type=%c", quota_bytes, inode->i_uid, head2type(p_s_ih));
+#endif
+    if (inode)
+       DQUOT_FREE_SPACE_NODIRTY(inode, quota_bytes) ;
     return retval; 
 }