#define SET_OPTION(optname) \
do { \
- reiserfs_warning(s, "reiserfs: option \"%s\" is set", #optname); \
- set_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s)); \
+ reiserfs_info(s, "block allocator option \"%s\" is set", #optname); \
+ set_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s)); \
} while(0)
#define TEST_OPTION(optname, s) \
test_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s))
static inline void get_bit_address(struct super_block *s,
- b_blocknr_t block, int *bmap_nr, int *offset)
+ b_blocknr_t block,
+ unsigned int *bmap_nr,
+ unsigned int *offset)
{
/* It is in the bitmap block number equal to the block
* number divided by the number of bits in a block. */
*offset = block & ((s->s_blocksize << 3) - 1);
}
-#ifdef CONFIG_REISERFS_CHECK
int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
{
- int bmap, offset;
- struct buffer_head *bh;
+ unsigned int bmap, offset;
+ unsigned int bmap_count = reiserfs_bmap_count(s);
if (block == 0 || block >= SB_BLOCK_COUNT(s)) {
- reiserfs_warning(s,
- "vs-4010: is_reusable: block number is out of range %lu (%u)",
- block, SB_BLOCK_COUNT(s));
+ reiserfs_error(s, "vs-4010",
+ "block number is out of range %lu (%u)",
+ block, SB_BLOCK_COUNT(s));
return 0;
}
if (unlikely(test_bit(REISERFS_OLD_FORMAT,
&(REISERFS_SB(s)->s_properties)))) {
b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1;
- if (block >= bmap1 && block <= bmap1 + SB_BMAP_NR(s)) {
- reiserfs_warning(s, "vs: 4019: is_reusable: "
- "bitmap block %lu(%u) can't be freed or reused",
- block, SB_BMAP_NR(s));
+ if (block >= bmap1 &&
+ block <= bmap1 + bmap_count) {
+ reiserfs_error(s, "vs-4019", "bitmap block %lu(%u) "
+ "can't be freed or reused",
+ block, bmap_count);
return 0;
}
} else {
if (offset == 0) {
- reiserfs_warning(s, "vs: 4020: is_reusable: "
- "bitmap block %lu(%u) can't be freed or reused",
- block, SB_BMAP_NR(s));
+ reiserfs_error(s, "vs-4020", "bitmap block %lu(%u) "
+ "can't be freed or reused",
+ block, bmap_count);
return 0;
}
}
- if (bmap >= SB_BMAP_NR(s)) {
- reiserfs_warning(s,
- "vs-4030: is_reusable: there is no so many bitmap blocks: "
- "block=%lu, bitmap_nr=%d", block, bmap);
- return 0;
- }
-
- bh = SB_AP_BITMAP(s)[bmap].bh;
- get_bh(bh);
-
- if ((bit_value == 0 && reiserfs_test_le_bit(offset, bh->b_data)) ||
- (bit_value == 1 && reiserfs_test_le_bit(offset, bh->b_data) == 0)) {
- reiserfs_warning(s,
- "vs-4040: is_reusable: corresponding bit of block %lu does not "
- "match required value (bmap==%d, offset==%d) test_bit==%d",
- block, bmap, offset,
- reiserfs_test_le_bit(offset, bh->b_data));
-
- brelse(bh);
+ if (bmap >= bmap_count) {
+ reiserfs_error(s, "vs-4030", "bitmap for requested block "
+ "is out of range: block=%lu, bitmap_nr=%u",
+ block, bmap);
return 0;
}
- brelse(bh);
if (bit_value == 0 && block == SB_ROOT_BLOCK(s)) {
- reiserfs_warning(s,
- "vs-4050: is_reusable: this is root block (%u), "
- "it must be busy", SB_ROOT_BLOCK(s));
+ reiserfs_error(s, "vs-4050", "this is root block (%u), "
+ "it must be busy", SB_ROOT_BLOCK(s));
return 0;
}
return 1;
}
-#endif /* CONFIG_REISERFS_CHECK */
/* searches in journal structures for a given block number (bmap, off). If block
is found in reiserfs journal it suggests next free block candidate to test. */
-static inline int is_block_in_journal(struct super_block *s, int bmap, int
- off, int *next)
+static inline int is_block_in_journal(struct super_block *s, unsigned int bmap,
+ int off, int *next)
{
b_blocknr_t tmp;
/* it searches for a window of zero bits with given minimum and maximum lengths in one bitmap
* block; */
static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
- int bmap_n, int *beg, int boundary, int min,
- int max, int unfm)
+ unsigned int bmap_n, int *beg, int boundary,
+ int min, int max, int unfm)
{
struct super_block *s = th->t_super;
struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n];
BUG_ON(!th->t_trans_id);
- RFALSE(bmap_n >= SB_BMAP_NR(s), "Bitmap %d is out of range (0..%d)",
- bmap_n, SB_BMAP_NR(s) - 1);
+ RFALSE(bmap_n >= reiserfs_bmap_count(s), "Bitmap %u is out of "
+ "range (0..%u)", bmap_n, reiserfs_bmap_count(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
/* - I mean `a window of zero bits' as in description of this function - Zam. */
if (!bi) {
- reiserfs_warning(s, "NULL bitmap info pointer for bitmap %d",
- bmap_n);
+ reiserfs_error(s, "jdm-4055", "NULL bitmap info pointer "
+ "for bitmap %d", bmap_n);
return 0;
}
- bh = bi->bh;
- get_bh(bh);
- if (buffer_locked(bh)) {
- PROC_INFO_INC(s, scan_bitmap.wait);
- __wait_on_buffer(bh);
- }
+ bh = reiserfs_read_bitmap_block(s, bmap_n);
+ if (bh == NULL)
+ return 0;
while (1) {
cont:
} else {
hash_in = (char *)(&id);
hash = keyed_hash(hash_in, 4);
- bm = hash % SB_BMAP_NR(s);
+ bm = hash % reiserfs_bmap_count(s);
if (!bm)
bm = 1;
}
/* this can only be true when SB_BMAP_NR = 1 */
- if (bm >= SB_BMAP_NR(s))
+ if (bm >= reiserfs_bmap_count(s))
bm = 0;
return bm;
}
*/
static inline int block_group_used(struct super_block *s, u32 id)
{
- int bm;
- bm = bmap_hash_id(s, id);
- if (SB_AP_BITMAP(s)[bm].free_count > ((s->s_blocksize << 3) * 60 / 100)) {
+ int bm = bmap_hash_id(s, id);
+ struct reiserfs_bitmap_info *info = &SB_AP_BITMAP(s)[bm];
+
+ /* If we don't have cached information on this bitmap block, we're
+ * going to have to load it later anyway. Loading it here allows us
+ * to make a better decision. This favors long-term performance gain
+ * with a better on-disk layout vs. a short term gain of skipping the
+ * read and potentially having a bad placement. */
+ if (info->free_count == UINT_MAX) {
+ struct buffer_head *bh = reiserfs_read_bitmap_block(s, bm);
+ brelse(bh);
+ }
+
+ if (info->free_count > ((s->s_blocksize << 3) * 60 / 100)) {
return 0;
}
return 1;
* bitmap and place new blocks there. Returns number of allocated blocks. */
static int scan_bitmap(struct reiserfs_transaction_handle *th,
b_blocknr_t * start, b_blocknr_t finish,
- int min, int max, int unfm, unsigned long file_block)
+ int min, int max, int unfm, sector_t file_block)
{
int nr_allocated = 0;
struct super_block *s = th->t_super;
/* find every bm and bmap and bmap_nr in this file, and change them all to bitmap_blocknr
* - Hans, it is not a block number - Zam. */
- int bm, off;
- int end_bm, end_off;
- int off_max = s->s_blocksize << 3;
+ unsigned int bm, off;
+ unsigned int end_bm, end_off;
+ unsigned int off_max = s->s_blocksize << 3;
BUG_ON(!th->t_trans_id);
get_bit_address(s, *start, &bm, &off);
get_bit_address(s, finish, &end_bm, &end_off);
- if (bm > SB_BMAP_NR(s))
+ if (bm > reiserfs_bmap_count(s))
return 0;
- if (end_bm > SB_BMAP_NR(s))
- end_bm = SB_BMAP_NR(s);
+ if (end_bm > reiserfs_bmap_count(s))
+ end_bm = reiserfs_bmap_count(s);
/* When the bitmap is more than 10% free, anyone can allocate.
* When it's less than 10% free, only files that already use the
struct reiserfs_super_block *rs;
struct buffer_head *sbh, *bmbh;
struct reiserfs_bitmap_info *apbi;
- int nr, offset;
+ unsigned int nr, offset;
BUG_ON(!th->t_trans_id);
get_bit_address(s, block, &nr, &offset);
- if (nr >= sb_bmap_nr(rs)) {
- reiserfs_warning(s, "vs-4075: reiserfs_free_block: "
- "block %lu is out of range on %s",
- block, reiserfs_bdevname(s));
+ if (nr >= reiserfs_bmap_count(s)) {
+ reiserfs_error(s, "vs-4075", "block %lu is out of range",
+ block);
return;
}
- bmbh = apbi[nr].bh;
- get_bh(bmbh);
+ bmbh = reiserfs_read_bitmap_block(s, nr);
+ if (!bmbh)
+ return;
reiserfs_prepare_for_journal(s, bmbh, 1);
/* clear bit for the given block in bit map */
if (!reiserfs_test_and_clear_le_bit(offset, bmbh->b_data)) {
- reiserfs_warning(s, "vs-4080: reiserfs_free_block: "
- "free_block (%s:%lu)[dev:blocknr]: bit already cleared",
- reiserfs_bdevname(s), block);
+ reiserfs_error(s, "vs-4080",
+ "block %lu: bit already cleared", block);
}
apbi[nr].free_count++;
journal_mark_dirty(th, s, bmbh);
journal_mark_dirty(th, s, sbh);
if (for_unformatted)
- DQUOT_FREE_BLOCK_NODIRTY(inode, 1);
+ vfs_dq_free_block_nodirty(inode, 1);
}
void reiserfs_free_block(struct reiserfs_transaction_handle *th,
int for_unformatted)
{
struct super_block *s = th->t_super;
-
BUG_ON(!th->t_trans_id);
RFALSE(!s, "vs-4061: trying to free block on nonexistent device");
- RFALSE(is_reusable(s, block, 1) == 0,
- "vs-4071: can not free such block");
+ if (!is_reusable(s, block, 1))
+ return;
+
+ if (block > sb_block_count(REISERFS_SB(s)->s_rs)) {
+ reiserfs_error(th->t_super, "bitmap-4072",
+ "Trying to free block outside file system "
+ "boundaries (%lu > %lu)",
+ block, sb_block_count(REISERFS_SB(s)->s_rs));
+ return;
+ }
/* mark it before we clear it, just in case */
journal_mark_freed(th, s, block);
_reiserfs_free_block(th, inode, block, for_unformatted);
static void reiserfs_free_prealloc_block(struct reiserfs_transaction_handle *th,
struct inode *inode, b_blocknr_t block)
{
+ BUG_ON(!th->t_trans_id);
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");
- BUG_ON(!th->t_trans_id);
+ if (!is_reusable(th->t_super, block, 1))
+ return;
_reiserfs_free_block(th, inode, block, 1);
}
BUG_ON(!th->t_trans_id);
#ifdef CONFIG_REISERFS_CHECK
if (ei->i_prealloc_count < 0)
- reiserfs_warning(th->t_super,
- "zam-4001:%s: inode has negative prealloc blocks count.",
- __FUNCTION__);
+ reiserfs_error(th->t_super, "zam-4001",
+ "inode has negative prealloc blocks count.");
#endif
while (ei->i_prealloc_count > 0) {
reiserfs_free_prealloc_block(th, inode, ei->i_prealloc_block);
i_prealloc_list);
#ifdef CONFIG_REISERFS_CHECK
if (!ei->i_prealloc_count) {
- reiserfs_warning(th->t_super,
- "zam-4001:%s: inode is in prealloc list but has no preallocated blocks.",
- __FUNCTION__);
+ reiserfs_error(th->t_super, "zam-4001",
+ "inode is in prealloc list but has "
+ "no preallocated blocks.");
}
#endif
__discard_prealloc(th, ei);
continue;
}
- reiserfs_warning(s, "zam-4001: %s : unknown option - %s",
- __FUNCTION__, this_char);
+ reiserfs_warning(s, "zam-4001", "unknown option - %s",
+ this_char);
return 1;
}
- reiserfs_warning(s, "allocator options = [%08x]\n", SB_ALLOC_OPTS(s));
+ reiserfs_info(s, "allocator options = [%08x]\n", SB_ALLOC_OPTS(s));
return 0;
}
/*
* Relocation based on dirid, hashing them into a given bitmap block
- * files. Formatted nodes are unaffected, a seperate policy covers them
+ * files. Formatted nodes are unaffected, a separate policy covers them
*/
static void dirid_groups(reiserfs_blocknr_hint_t * hint)
{
/*
* Relocation based on oid, hashing them into a given bitmap block
- * files. Formatted nodes are unaffected, a seperate policy covers them
+ * files. Formatted nodes are unaffected, a separate policy covers them
*/
static void oid_groups(reiserfs_blocknr_hint_t * hint)
{
*/
static int get_left_neighbor(reiserfs_blocknr_hint_t * hint)
{
- struct path *path;
+ struct treepath *path;
struct buffer_head *bh;
struct item_head *ih;
int pos_in_item;
b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1;
int passno = 0;
int nr_allocated = 0;
- int bigalloc = 0;
determine_prealloc_size(hint);
if (!hint->formatted_node) {
amount_needed, hint->inode->i_uid);
#endif
quota_ret =
- DQUOT_ALLOC_BLOCK_NODIRTY(hint->inode, amount_needed);
+ vfs_dq_alloc_block_nodirty(hint->inode, amount_needed);
if (quota_ret) /* Quota exceeded? */
return QUOTA_EXCEEDED;
if (hint->preallocate && hint->prealloc_size) {
"reiserquota: allocating (prealloc) %d blocks id=%u",
hint->prealloc_size, hint->inode->i_uid);
#endif
- quota_ret =
- DQUOT_PREALLOC_BLOCK_NODIRTY(hint->inode,
+ quota_ret = vfs_dq_prealloc_block_nodirty(hint->inode,
hint->prealloc_size);
if (quota_ret)
hint->preallocate = hint->prealloc_size = 0;
}
/* for unformatted nodes, force large allocations */
- bigalloc = amount_needed;
}
do {
- /* in bigalloc mode, nr_allocated should stay zero until
- * the entire allocation is filled
- */
- if (unlikely(bigalloc && nr_allocated)) {
- reiserfs_warning(s, "bigalloc is %d, nr_allocated %d\n",
- bigalloc, nr_allocated);
- /* reset things to a sane value */
- bigalloc = amount_needed - nr_allocated;
- }
- /*
- * try pass 0 and pass 1 looking for a nice big
- * contiguous allocation. Then reset and look
- * for anything you can find.
- */
- if (passno == 2 && bigalloc) {
- passno = 0;
- bigalloc = 0;
- }
switch (passno++) {
case 0: /* Search from hint->search_start to end of disk */
start = hint->search_start;
nr_allocated,
hint->inode->i_uid);
#endif
- DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed + hint->prealloc_size - nr_allocated); /* Free not allocated blocks */
+ /* Free not allocated blocks */
+ vfs_dq_free_block_nodirty(hint->inode,
+ amount_needed + hint->prealloc_size -
+ nr_allocated);
}
while (nr_allocated--)
reiserfs_free_block(hint->th, hint->inode,
new_blocknrs +
nr_allocated,
start, finish,
- bigalloc ?
- bigalloc : 1,
+ 1,
amount_needed -
nr_allocated,
hint->
REISERFS_I(hint->inode)->i_prealloc_count,
hint->inode->i_uid);
#endif
- DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed +
+ vfs_dq_free_block_nodirty(hint->inode, amount_needed +
hint->prealloc_size - nr_allocated -
REISERFS_I(hint->inode)->
i_prealloc_count);
return ret;
}
-/* These 2 functions are here to provide blocks reservation to the rest of kernel */
-/* Reserve @blocks amount of blocks in fs pointed by @sb. Caller must make sure
- there are actually this much blocks on the FS available */
-void reiserfs_claim_blocks_to_be_allocated(struct super_block *sb, /* super block of
- filesystem where
- blocks should be
- reserved */
- int blocks /* How much to reserve */
- )
-{
-
- /* Fast case, if reservation is zero - exit immediately. */
- if (!blocks)
- return;
-
- spin_lock(&REISERFS_SB(sb)->bitmap_lock);
- REISERFS_SB(sb)->reserved_blocks += blocks;
- spin_unlock(&REISERFS_SB(sb)->bitmap_lock);
-}
-
-/* Unreserve @blocks amount of blocks in fs pointed by @sb */
-void reiserfs_release_claimed_blocks(struct super_block *sb, /* super block of
- filesystem where
- blocks should be
- reserved */
- int blocks /* How much to unreserve */
- )
-{
-
- /* Fast case, if unreservation is zero - exit immediately. */
- if (!blocks)
- return;
-
- spin_lock(&REISERFS_SB(sb)->bitmap_lock);
- REISERFS_SB(sb)->reserved_blocks -= blocks;
- spin_unlock(&REISERFS_SB(sb)->bitmap_lock);
- RFALSE(REISERFS_SB(sb)->reserved_blocks < 0,
- "amount of blocks reserved became zero?");
-}
-
-/* This function estimates how much pages we will be able to write to FS
- used for reiserfs_file_write() purposes for now. */
-int reiserfs_can_fit_pages(struct super_block *sb /* superblock of filesystem
- to estimate space */ )
-{
- int space;
-
- spin_lock(&REISERFS_SB(sb)->bitmap_lock);
- space =
- (SB_FREE_BLOCKS(sb) -
- REISERFS_SB(sb)->reserved_blocks) >> (PAGE_CACHE_SHIFT -
- sb->s_blocksize_bits);
- spin_unlock(&REISERFS_SB(sb)->bitmap_lock);
-
- return space > 0 ? space : 0;
-}
-
void reiserfs_cache_bitmap_metadata(struct super_block *sb,
struct buffer_head *bh,
struct reiserfs_bitmap_info *info)
{
unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size);
- info->first_zero_hint = 1 << (sb->s_blocksize_bits + 3);
+ /* The first bit must ALWAYS be 1 */
+ if (!reiserfs_test_le_bit(0, (unsigned long *)bh->b_data))
+ reiserfs_error(sb, "reiserfs-2025", "bitmap block %lu is "
+ "corrupted: first bit must be 1", bh->b_blocknr);
+
+ info->free_count = 0;
while (--cur >= (unsigned long *)bh->b_data) {
- int base = ((char *)cur - bh->b_data) << 3;
+ int i;
/* 0 and ~0 are special, we can optimize for them */
- if (*cur == 0) {
- info->first_zero_hint = base;
+ if (*cur == 0)
info->free_count += BITS_PER_LONG;
- } else if (*cur != ~0L) { /* A mix, investigate */
- int b;
- for (b = BITS_PER_LONG - 1; b >= 0; b--) {
- if (!reiserfs_test_le_bit(b, cur)) {
- info->first_zero_hint = base + b;
+ else if (*cur != ~0L) /* A mix, investigate */
+ for (i = BITS_PER_LONG - 1; i >= 0; i--)
+ if (!reiserfs_test_le_bit(i, cur))
info->free_count++;
- }
- }
- }
}
- /* The first bit must ALWAYS be 1 */
- BUG_ON(info->first_zero_hint == 0);
}
struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
unsigned int bitmap)
{
b_blocknr_t block = (sb->s_blocksize << 3) * bitmap;
+ struct reiserfs_bitmap_info *info = SB_AP_BITMAP(sb) + bitmap;
struct buffer_head *bh;
/* Way old format filesystems had the bitmaps packed up front.
else if (bitmap == 0)
block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1;
- bh = sb_getblk(sb, block);
- if (!buffer_uptodate(bh))
- ll_rw_block(READ, 1, &bh);
+ bh = sb_bread(sb, block);
+ if (bh == NULL)
+ reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) "
+ "reading failed", __func__, block);
+ else {
+ if (buffer_locked(bh)) {
+ PROC_INFO_INC(sb, scan_bitmap.wait);
+ __wait_on_buffer(bh);
+ }
+ BUG_ON(!buffer_uptodate(bh));
+ BUG_ON(atomic_read(&bh->b_count) == 0);
+
+ if (info->free_count == UINT_MAX)
+ reiserfs_cache_bitmap_metadata(sb, bh, info);
+ }
return bh;
}
int reiserfs_init_bitmap_cache(struct super_block *sb)
{
struct reiserfs_bitmap_info *bitmap;
- int i;
+ unsigned int bmap_nr = reiserfs_bmap_count(sb);
- bitmap = vmalloc(sizeof (*bitmap) * SB_BMAP_NR(sb));
+ bitmap = vmalloc(sizeof(*bitmap) * bmap_nr);
if (bitmap == NULL)
return -ENOMEM;
- memset(bitmap, 0, sizeof (*bitmap) * SB_BMAP_NR(sb));
-
- for (i = 0; i < SB_BMAP_NR(sb); i++)
- bitmap[i].bh = reiserfs_read_bitmap_block(sb, i);
-
- /* make sure we have them all */
- for (i = 0; i < SB_BMAP_NR(sb); i++) {
- wait_on_buffer(bitmap[i].bh);
- if (!buffer_uptodate(bitmap[i].bh)) {
- reiserfs_warning(sb, "sh-2029: %s: "
- "bitmap block (#%lu) reading failed",
- __FUNCTION__, bitmap[i].bh->b_blocknr);
- for (i = 0; i < SB_BMAP_NR(sb); i++)
- brelse(bitmap[i].bh);
- vfree(bitmap);
- return -EIO;
- }
- }
-
- /* Cache the info on the bitmaps before we get rolling */
- for (i = 0; i < SB_BMAP_NR(sb); i++)
- reiserfs_cache_bitmap_metadata(sb, bitmap[i].bh, &bitmap[i]);
+ memset(bitmap, 0xff, sizeof(*bitmap) * bmap_nr);
SB_AP_BITMAP(sb) = bitmap;
return 0;
}
+
+void reiserfs_free_bitmap_cache(struct super_block *sb)
+{
+ if (SB_AP_BITMAP(sb)) {
+ vfree(SB_AP_BITMAP(sb));
+ SB_AP_BITMAP(sb) = NULL;
+ }
+}