/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
/* Reiserfs block (de)allocator, bitmap-based. */
#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_bits + 3);
/* Within that bitmap block it is located at bit offset *offset. */
*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;
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;
}
get_bit_address(s, block, &bmap, &offset);
/* Old format filesystem? Unlikely, but the bitmaps are all up front so
* we need to account for it. */
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));
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));
return 0;
}
}
if (bmap >= SB_BMAP_NR(s)) {
reiserfs_war