Exemple #1
0
static inline void displace_large_file(reiserfs_blocknr_hint_t *hint)
{
    if ( TEST_OPTION(displace_based_on_dirid, hint->th->t_super))
        hint->search_start = hint->beg + keyed_hash((char *)(&INODE_PKEY(hint->inode)->k_dir_id), 4) % (hint->end - hint->beg);
    else
        hint->search_start = hint->beg + keyed_hash((char *)(&INODE_PKEY(hint->inode)->k_objectid), 4) % (hint->end - hint->beg);
}
Exemple #2
0
static inline void hash_formatted_node(reiserfs_blocknr_hint_t *hint)
{
    char * hash_in;

    if (!hint->inode)
        hash_in = (char*)&hint->key.k_dir_id;
    else if ( TEST_OPTION(displace_based_on_dirid, hint->th->t_super))
        hash_in = (char *)(&INODE_PKEY(hint->inode)->k_dir_id);
    else
        hash_in = (char *)(&INODE_PKEY(hint->inode)->k_objectid);

    hint->search_start = hint->beg + keyed_hash(hash_in, 4) % (hint->end - hint->beg);
}
Exemple #3
0
/*
 * the packing is returned in disk byte order
 */
u32 reiserfs_choose_packing(struct inode *dir) {
    u32 packing;
    if (TEST_OPTION(packing_groups, dir->i_sb)) {
        u32 parent_dir = le32_to_cpu(INODE_PKEY(dir)->k_dir_id);
        /*
         * some versions of reiserfsck expect packing locality 1 to be
         * special
         */
        if (parent_dir == 1 || block_group_used(dir->i_sb,parent_dir))
            packing = INODE_PKEY(dir)->k_objectid;
        else
            packing = INODE_PKEY(dir)->k_dir_id;
    } else
        packing = INODE_PKEY(dir)->k_objectid;
    return packing;
}
Exemple #4
0
static void inline new_hashed_relocation (reiserfs_blocknr_hint_t * hint)
{
    char * hash_in;
    if (hint->formatted_node) {
        hash_in = (char*)&hint->key.k_dir_id;
    } else {
        if (!hint->inode) {
            //hint->search_start = hint->beg;
            hash_in = (char*)&hint->key.k_dir_id;
        } else if ( TEST_OPTION(displace_based_on_dirid, hint->th->t_super))
            hash_in = (char *)(&INODE_PKEY(hint->inode)->k_dir_id);
        else
            hash_in = (char *)(&INODE_PKEY(hint->inode)->k_objectid);
    }

    hint->search_start = hint->beg + keyed_hash(hash_in, 4) % (hint->end - hint->beg);
}
Exemple #5
0
/* Tries to find contiguous zero bit window (given size) in given region of
 * bitmap and place new blocks there. Returns number of allocated blocks. */
static int scan_bitmap (struct reiserfs_transaction_handle *th,
                        unsigned long *start, unsigned long finish,
                        int min, int max, int unfm, unsigned long 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;

    PROC_INFO_INC( s, scan_bitmap.call );
    if ( SB_FREE_BLOCKS(s) <= 0)
        return 0; // No point in looking for more free blocks

    get_bit_address (s, *start, &bm, &off);
    get_bit_address (s, finish, &end_bm, &end_off);

    // With this option set first we try to find a bitmap that is at least 10%
    // free, and if that fails, then we fall back to old whole bitmap scanning
    if ( TEST_OPTION(skip_busy, s) && SB_FREE_BLOCKS(s) > SB_BLOCK_COUNT(s)/20 ) {
        for (; bm < end_bm; bm++, off = 0) {
            if ( ( off && (!unfm || (file_block != 0))) || SB_AP_BITMAP(s)[bm].free_count > (s->s_blocksize << 3) / 10 )
                nr_allocated = scan_bitmap_block(th, bm, &off, off_max, min, max, unfm);
            if (nr_allocated)
                goto ret;
        }
        get_bit_address (s, *start, &bm, &off);
    }

    for (; bm < end_bm; bm++, off = 0) {
        nr_allocated = scan_bitmap_block(th, bm, &off, off_max, min, max, unfm);
        if (nr_allocated)
            goto ret;
    }

    nr_allocated = scan_bitmap_block(th, bm, &off, end_off + 1, min, max, unfm);

ret:
    *start = bm * off_max + off;
    return nr_allocated;

}
Exemple #6
0
static void determine_search_start(reiserfs_blocknr_hint_t *hint,
                                   int amount_needed)
{
    struct super_block *s = hint->th->t_super;
    int unfm_hint;

    hint->beg = 0;
    hint->end = SB_BLOCK_COUNT(s) - 1;

    /* This is former border algorithm. Now with tunable border offset */
    if (concentrating_formatted_nodes(s))
        set_border_in_hint(s, hint);

#ifdef DISPLACE_NEW_PACKING_LOCALITIES
    /* whenever we create a new directory, we displace it.  At first we will
       hash for location, later we might look for a moderately empty place for
       it */
    if (displacing_new_packing_localities(s)
            && hint->th->displace_new_blocks) {
        displace_new_packing_locality(hint);

        /* we do not continue determine_search_start,
         * if new packing locality is being displaced */
        return;
    }
#endif

    /* all persons should feel encouraged to add more special cases here and
     * test them */

    if (displacing_large_files(s) && !hint->formatted_node
            && this_blocknr_allocation_would_make_it_a_large_file(hint)) {
        displace_large_file(hint);
        return;
    }

    /* if none of our special cases is relevant, use the left neighbor in the
       tree order of the new node we are allocating for */
    if (hint->formatted_node && TEST_OPTION(hashed_formatted_nodes,s)) {
        hash_formatted_node(hint);
        return;
    }

    unfm_hint = get_left_neighbor(hint);

    /* Mimic old block allocator behaviour, that is if VFS allowed for preallocation,
       new blocks are displaced based on directory ID. Also, if suggested search_start
       is less than last preallocated block, we start searching from it, assuming that
       HDD dataflow is faster in forward direction */
    if ( TEST_OPTION(old_way, s)) {
        if (!hint->formatted_node) {
            if ( !reiserfs_hashed_relocation(s))
                old_way(hint);
            else if (!reiserfs_no_unhashed_relocation(s))
                old_hashed_relocation(hint);

            if ( hint->inode && hint->search_start < REISERFS_I(hint->inode)->i_prealloc_block)
                hint->search_start = REISERFS_I(hint->inode)->i_prealloc_block;
        }
        return;
    }

    /* This is an approach proposed by Hans */
    if ( TEST_OPTION(hundredth_slices, s) && ! (displacing_large_files(s) && !hint->formatted_node)) {
        hundredth_slices(hint);
        return;
    }

    /* old_hashed_relocation only works on unformatted */
    if (!unfm_hint && !hint->formatted_node &&
            TEST_OPTION(old_hashed_relocation, s))
    {
        old_hashed_relocation(hint);
    }
    /* new_hashed_relocation works with both formatted/unformatted nodes */
    if ((!unfm_hint || hint->formatted_node) &&
            TEST_OPTION(new_hashed_relocation, s))
    {
        new_hashed_relocation(hint);
    }
    /* dirid grouping works only on unformatted nodes */
    if (!unfm_hint && !hint->formatted_node && TEST_OPTION(dirid_groups,s))
    {
        dirid_groups(hint);
    }

#ifdef DISPLACE_NEW_PACKING_LOCALITIES
    if (hint->formatted_node && TEST_OPTION(dirid_groups,s))
    {
        dirid_groups(hint);
    }
#endif

    /* oid grouping works only on unformatted nodes */
    if (!unfm_hint && !hint->formatted_node && TEST_OPTION(oid_groups,s))
    {
        oid_groups(hint);
    }
    return;
}
Exemple #7
0
/* Tries to find contiguous zero bit window (given size) in given region of
 * 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 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;

    BUG_ON (!th->t_trans_id);

    PROC_INFO_INC( s, scan_bitmap.call );
    if ( SB_FREE_BLOCKS(s) <= 0)
        return 0; // No point in looking for more free blocks

    get_bit_address (s, *start, &bm, &off);
    get_bit_address (s, finish, &end_bm, &end_off);
    if (bm > SB_BMAP_NR(s))
        return 0;
    if (end_bm > SB_BMAP_NR(s))
        end_bm = SB_BMAP_NR(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
     * bitmap are allowed. Once we pass 80% full, this restriction
     * is lifted.
     *
     * We do this so that files that grow later still have space close to
     * their original allocation. This improves locality, and presumably
     * performance as a result.
     *
     * This is only an allocation policy and does not make up for getting a
     * bad hint. Decent hinting must be implemented for this to work well.
     */
    if ( TEST_OPTION(skip_busy, s) && SB_FREE_BLOCKS(s) > SB_BLOCK_COUNT(s)/20 ) {
        for (; bm < end_bm; bm++, off = 0) {
            if ( ( off && (!unfm || (file_block != 0))) || SB_AP_BITMAP(s)[bm].free_count > (s->s_blocksize << 3) / 10 )
                nr_allocated = scan_bitmap_block(th, bm, &off, off_max, min, max, unfm);
            if (nr_allocated)
                goto ret;
        }
        /* we know from above that start is a reasonable number */
        get_bit_address (s, *start, &bm, &off);
    }

    for (; bm < end_bm; bm++, off = 0) {
        nr_allocated = scan_bitmap_block(th, bm, &off, off_max, min, max, unfm);
        if (nr_allocated)
            goto ret;
    }

    nr_allocated = scan_bitmap_block(th, bm, &off, end_off + 1, min, max, unfm);

ret:
    *start = bm * off_max + off;
    return nr_allocated;

}