X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Freiserfs%2Fbitmap.c;h=86639019d49e257022032c74f1dfb9ce996289c0;hb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;hp=0550e20ecc52ceae202d6e44cedb6ce04adc9eb7;hpb=c449269f45c2cdf53af08c8d0af37472f66539d9;p=linux-2.6.git diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index 0550e20ec..86639019d 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -12,6 +12,7 @@ #include #include #include +#include #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;