patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / reiserfs / bitmap.c
index 0550e20..8663901 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/pagemap.h>
 #include <linux/reiserfs_fs_sb.h>
 #include <linux/reiserfs_fs_i.h>
+#include <linux/quotaops.h>
 
 #define PREALLOCATION_SIZE 9
 
@@ -36,7 +37,7 @@
 
 #define SET_OPTION(optname) \
    do { \
-        reiserfs_warning("reiserfs: option \"%s\" is set\n", #optname); \
+        reiserfs_warning(s, "reiserfs: option \"%s\" is set", #optname); \
         set_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s)); \
     } while(0)
 #define TEST_OPTION(optname, s) \
@@ -59,7 +60,7 @@ int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value)
     int i, j;
 
     if (block == 0 || block >= SB_BLOCK_COUNT (s)) {
-       reiserfs_warning ("vs-4010: is_reusable: block number is out of range %lu (%u)\n",
+       reiserfs_warning (s, "vs-4010: is_reusable: block number is out of range %lu (%u)",
                          block, SB_BLOCK_COUNT (s));
        return 0;
     }
@@ -67,8 +68,8 @@ int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value)
     /* it can't be one of the bitmap blocks */
     for (i = 0; i < SB_BMAP_NR (s); i ++)
        if (block == SB_AP_BITMAP (s)[i].bh->b_blocknr) {
-           reiserfs_warning ("vs: 4020: is_reusable: "
-                             "bitmap block %lu(%u) can't be freed or reused\n",
+           reiserfs_warning (s, "vs: 4020: is_reusable: "
+                             "bitmap block %lu(%u) can't be freed or reused",
                              block, SB_BMAP_NR (s));
            return 0;
        }
@@ -76,8 +77,8 @@ int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value)
     get_bit_address (s, block, &i, &j);
 
     if (i >= SB_BMAP_NR (s)) {
-       reiserfs_warning ("vs-4030: is_reusable: there is no so many bitmap blocks: "
-                         "block=%lu, bitmap_nr=%d\n", block, i);
+       reiserfs_warning (s, "vs-4030: is_reusable: there is no so many bitmap blocks: "
+                         "block=%lu, bitmap_nr=%d", block, i);
        return 0;
     }
 
@@ -85,16 +86,16 @@ int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value)
          reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data)) ||
        (bit_value == 1 && 
         reiserfs_test_le_bit(j, SB_AP_BITMAP (s)[i].bh->b_data) == 0)) {
-       reiserfs_warning ("vs-4040: is_reusable: corresponding bit of block %lu does not "
-                         "match required value (i==%d, j==%d) test_bit==%d\n",
+       reiserfs_warning (s, "vs-4040: is_reusable: corresponding bit of block %lu does not "
+                         "match required value (i==%d, j==%d) test_bit==%d",
                block, i, j, reiserfs_test_le_bit (j, SB_AP_BITMAP (s)[i].bh->b_data));
 
        return 0;
     }
 
     if (bit_value == 0 && block == SB_ROOT_BLOCK (s)) {
-       reiserfs_warning ("vs-4050: is_reusable: this is root block (%u), "
-                         "it must be busy\n", SB_ROOT_BLOCK (s));
+       reiserfs_warning (s, "vs-4050: is_reusable: this is root block (%u), "
+                         "it must be busy", SB_ROOT_BLOCK (s));
        return 0;
     }
 
@@ -133,7 +134,7 @@ static int scan_bitmap_block (struct reiserfs_transaction_handle *th,
     int end, next;
     int org = *beg;
 
-    RFALSE(bmap_n >= SB_BMAP_NR (s), "Bitmap %d is out of range (0..%d)\n",bmap_n, SB_BMAP_NR (s) - 1);
+    RFALSE(bmap_n >= SB_BMAP_NR (s), "Bitmap %d is out of range (0..%d)",bmap_n, SB_BMAP_NR (s) - 1);
     PROC_INFO_INC( s, scan_bitmap.bmap );
 /* this is unclear and lacks comments, explain how journal bitmaps
    work here for the reader.  Convey a sense of the design here. What
@@ -141,7 +142,7 @@ static int scan_bitmap_block (struct reiserfs_transaction_handle *th,
 /* - I mean `a window of zero bits' as in description of this function - Zam. */
   
     if ( !bi ) {
-       printk("Hey, bitmap info pointer is zero for bitmap %d!\n",bmap_n);
+       reiserfs_warning (s, "NULL bitmap info pointer for bitmap %d", bmap_n);
        return 0;
     }
     if (buffer_locked (bi->bh)) {
@@ -281,7 +282,8 @@ static int scan_bitmap (struct reiserfs_transaction_handle *th,
 }
 
 static void _reiserfs_free_block (struct reiserfs_transaction_handle *th,
-                                 b_blocknr_t block)
+                                 struct inode *inode, b_blocknr_t block,
+                                 int for_unformatted)
 {
     struct super_block * s = th->t_super;
     struct reiserfs_super_block * rs;
@@ -298,8 +300,8 @@ static void _reiserfs_free_block (struct reiserfs_transaction_handle *th,
     get_bit_address (s, block, &nr, &offset);
 
     if (nr >= sb_bmap_nr (rs)) {
-       reiserfs_warning ("vs-4075: reiserfs_free_block: "
-                         "block %lu is out of range on %s\n", 
+       reiserfs_warning (s, "vs-4075: reiserfs_free_block: "
+                         "block %lu is out of range on %s",
                          block, reiserfs_bdevname (s));
        return;
     }
@@ -308,8 +310,8 @@ static void _reiserfs_free_block (struct reiserfs_transaction_handle *th,
 
     /* clear bit for the given block in bit map */
     if (!reiserfs_test_and_clear_le_bit (offset, apbi[nr].bh->b_data)) {
-       reiserfs_warning ("vs-4080: reiserfs_free_block: "
-                         "free_block (%s:%lu)[dev:blocknr]: bit already cleared\n", 
+       reiserfs_warning (s, "vs-4080: reiserfs_free_block: "
+                         "free_block (%s:%lu)[dev:blocknr]: bit already cleared",
                          reiserfs_bdevname (s), block);
     }
     if (offset < apbi[nr].first_zero_hint) {
@@ -323,11 +325,13 @@ static void _reiserfs_free_block (struct reiserfs_transaction_handle *th,
     set_sb_free_blocks( rs, sb_free_blocks(rs) + 1 );
 
     journal_mark_dirty (th, s, sbh);
-  s->s_dirt = 1;
+    if (for_unformatted)
+        DQUOT_FREE_BLOCK_NODIRTY(inode, 1);
 }
 
 void reiserfs_free_block (struct reiserfs_transaction_handle *th, 
-                          b_blocknr_t block)
+                         struct inode *inode, b_blocknr_t block,
+                         int for_unformatted)
 {
     struct super_block * s = th->t_super;
 
@@ -335,42 +339,46 @@ void reiserfs_free_block (struct reiserfs_transaction_handle *th,
     RFALSE(is_reusable (s, block, 1) == 0, "vs-4071: can not free such block");
     /* mark it before we clear it, just in case */
     journal_mark_freed(th, s, block) ;
-    _reiserfs_free_block(th, block) ;
+    _reiserfs_free_block(th, inode, block, for_unformatted) ;
 }
 
 /* preallocated blocks don't need to be run through journal_mark_freed */
 void reiserfs_free_prealloc_block (struct reiserfs_transaction_handle *th, 
-                          b_blocknr_t block) {
+                         struct inode *inode, b_blocknr_t block) {
     RFALSE(!th->t_super, "vs-4060: trying to free block on nonexistent device");
     RFALSE(is_reusable (th->t_super, block, 1) == 0, "vs-4070: can not free such block");
-    _reiserfs_free_block(th, block) ;
+    _reiserfs_free_block(th, inode, block, 1) ;
 }
 
 static void __discard_prealloc (struct reiserfs_transaction_handle * th,
                                struct reiserfs_inode_info *ei)
 {
     unsigned long save = ei->i_prealloc_block ;
+    int dirty = 0;
+    struct inode *inode = &ei->vfs_inode;
 #ifdef CONFIG_REISERFS_CHECK
     if (ei->i_prealloc_count < 0)
-       reiserfs_warning("zam-4001:%s: inode has negative prealloc blocks count.\n", __FUNCTION__ );
+       reiserfs_warning (th->t_super, "zam-4001:%s: inode has negative prealloc blocks count.", __FUNCTION__ );
 #endif
     while (ei->i_prealloc_count > 0) {
-       reiserfs_free_prealloc_block(th,ei->i_prealloc_block);
+       reiserfs_free_prealloc_block(th, inode, ei->i_prealloc_block);
        ei->i_prealloc_block++;
        ei->i_prealloc_count --;
+       dirty = 1;
     }
+    if (dirty)
+       reiserfs_update_sd(th, inode);
     ei->i_prealloc_block = save;
     list_del_init(&(ei->i_prealloc_list));
 }
 
 /* FIXME: It should be inline function */
 void reiserfs_discard_prealloc (struct reiserfs_transaction_handle *th, 
-                               struct inode * inode)
+                               struct inode *inode)
 {
     struct reiserfs_inode_info *ei = REISERFS_I(inode);
-    if (ei->i_prealloc_count) {
+    if (ei->i_prealloc_count)
        __discard_prealloc(th, ei);
-    }
 }
 
 void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th)
@@ -382,7 +390,7 @@ void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th)
        ei = list_entry(plist->next, struct reiserfs_inode_info, i_prealloc_list);
 #ifdef CONFIG_REISERFS_CHECK
        if (!ei->i_prealloc_count) {
-           reiserfs_warning("zam-4001:%s: inode is in prealloc list but has no preallocated blocks.\n", __FUNCTION__);
+           reiserfs_warning (th->t_super, "zam-4001:%s: inode is in prealloc list but has no preallocated blocks.", __FUNCTION__);
        }
 #endif
        __discard_prealloc(th, ei);
@@ -468,7 +476,8 @@ int reiserfs_parse_alloc_options(struct super_block * s, char * options)
            continue;
        }
 
-       reiserfs_warning("zam-4001: %s : unknown option - %s\n", __FUNCTION__ , this_char);
+       reiserfs_warning (s, "zam-4001: %s : unknown option - %s",
+                         __FUNCTION__ , this_char);
        return 1;
       }
   
@@ -508,7 +517,7 @@ static inline void get_left_neighbor(reiserfs_blocknr_hint_t *hint)
 
     path = hint->path;
     bh = get_last_bh(path);
-    RFALSE( !bh, "green-4002: Illegal path specified to get_left_neighbor\n");
+    RFALSE( !bh, "green-4002: Illegal path specified to get_left_neighbor");
     ih = get_ih(path);
     pos_in_item = path->pos_in_item;
     item = get_item (path);
@@ -772,6 +781,24 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
     int nr_allocated = 0;
 
     determine_prealloc_size(hint);
+    if (!hint->formatted_node) {
+        int quota_ret;
+#ifdef REISERQUOTA_DEBUG
+       reiserfs_debug (s, "reiserquota: allocating %d blocks id=%u", amount_needed, hint->inode->i_uid);
+#endif
+       quota_ret = DQUOT_ALLOC_BLOCK_NODIRTY(hint->inode, amount_needed);
+       if (quota_ret)    /* Quota exceeded? */
+           return QUOTA_EXCEEDED;
+       if (hint->preallocate && hint->prealloc_size ) {
+#ifdef REISERQUOTA_DEBUG
+           reiserfs_debug (s, "reiserquota: allocating (prealloc) %d blocks id=%u", hint->prealloc_size, hint->inode->i_uid);
+#endif
+           quota_ret = DQUOT_PREALLOC_BLOCK_NODIRTY(hint->inode, hint->prealloc_size);
+           if (quota_ret)
+               hint->preallocate=hint->prealloc_size=0;
+       }
+    }
+
     while((nr_allocated
          += allocate_without_wrapping_disk(hint, new_blocknrs + nr_allocated, start, finish,
                                          amount_needed - nr_allocated, hint->prealloc_size))
@@ -779,8 +806,14 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
 
        /* not all blocks were successfully allocated yet*/
        if (second_pass) {      /* it was a second pass; we must free all blocks */
+           if (!hint->formatted_node) {
+#ifdef REISERQUOTA_DEBUG
+               reiserfs_debug (s, "reiserquota: freeing (nospace) %d blocks id=%u", amount_needed + hint->prealloc_size - nr_allocated, hint->inode->i_uid);
+#endif
+               DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed + hint->prealloc_size - nr_allocated);     /* Free not allocated blocks */
+           }
            while (nr_allocated --)
-               reiserfs_free_block(hint->th, new_blocknrs[nr_allocated]);
+               reiserfs_free_block(hint->th, hint->inode, new_blocknrs[nr_allocated], !hint->formatted_node);
 
            return NO_DISK_SPACE;
        } else {                /* refine search parameters for next pass */
@@ -789,7 +822,19 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
            start = 0;
            continue;
        }
-      }
+    }
+    if ( !hint->formatted_node &&
+         amount_needed + hint->prealloc_size >
+        nr_allocated + REISERFS_I(hint->inode)->i_prealloc_count) {
+    /* Some of preallocation blocks were not allocated */
+#ifdef REISERQUOTA_DEBUG
+       reiserfs_debug (s, "reiserquota: freeing (failed prealloc) %d blocks id=%u", amount_needed + hint->prealloc_size - nr_allocated - INODE_INFO(hint->inode)->i_prealloc_count, hint->inode->i_uid);
+#endif
+       DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed +
+                                hint->prealloc_size - nr_allocated -
+                                REISERFS_I(hint->inode)->i_prealloc_count);
+    }
+
     return CARRY_ON;
 }
 
@@ -858,7 +903,7 @@ int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *hint,
 
     if (ret != CARRY_ON) {
        while (amount_needed ++ < initial_amount_needed) {
-           reiserfs_free_block(hint->th, *(--new_blocknrs));
+           reiserfs_free_block(hint->th, hint->inode, *(--new_blocknrs), 1);
        }
     }
     return ret;