/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
/* Reiserfs block (de)allocator, bitmap-based. */
#include <linux/config.h>
#include <linux/time.h>
#include <linux/reiserfs_fs.h>
#include <linux/errno.h>
#include <linux/buffer_head.h>
#include <linux/kernel.h>
#include <linux/pagemap.h>
#include <linux/reiserfs_fs_sb.h>
#include <linux/reiserfs_fs_i.h>
#include <linux/quotaops.h>
#define PREALLOCATION_SIZE 9
/* different reiserfs block allocator options */
#define SB_ALLOC_OPTS(s) (REISERFS_SB(s)->s_alloc_options.bits)
#define _ALLOC_concentrating_formatted_nodes 0
#define _ALLOC_displacing_large_files 1
#define _ALLOC_displacing_new_packing_localities 2
#define _ALLOC_old_hashed_relocation 3
#define _ALLOC_new_hashed_relocation 4
#define _ALLOC_skip_busy 5
#define _ALLOC_displace_based_on_dirid 6
#define _ALLOC_hashed_formatted_nodes 7
#define _ALLOC_old_way 8
#define _ALLOC_hundredth_slices 9
#define _ALLOC_dirid_groups 10
#define _ALLOC_oid_groups 11
#define _ALLOC_packing_groups 12
#define concentrating_formatted_nodes(s) test_bit(_ALLOC_concentrating_formatted_nodes, &SB_ALLOC_OPTS(s))
#define displacing_large_files(s) test_bit(_ALLOC_displacing_large_files, &SB_ALLOC_OPTS(s))
#define displacing_new_packing_localities(s) test_bit(_ALLOC_displacing_new_packing_localities, &SB_ALLOC_OPTS(s))
#define SET_OPTION(optname) \
do { \
reiserfs_warning(s, "reiserfs: 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)
{
/* It is in the bitmap block number equal to the block
* number divided by the number of bits in a block. */
*bmap_nr = block / (s->s_blocksize << 3);
/* Within that bitmap block it is located at bit offset *offset. */
*offset = block & ((s->s_blocksize << 3) - 1 );
return;
}
#ifdef CONFIG_REISERFS_CHECK
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 (s, "vs-4010: is_reusable: block number is out of range %lu (%u)",
block, SB_BLOCK_COUNT (s));
return 0;
}
/* 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 (s, "vs: 4020: is_reusable: "
"bitmap block %lu(%u) can't be freed or reused",
block, SB_BMAP_NR (s));
return 0;
}
get_bit_address (s, block, &i, &j);
if (i >= SB_BMAP_NR (s)) {
reiserfs_warning (s, "vs-4030: is_reusable: there is no so many bitmap blocks: "
"block=%lu, bitmap_nr=%d", block, i);
return 0;
}
if ((bit_value == 0 &&
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 (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 (s, "vs-4050: is_reusable: 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