예제 #1
0
static inline int blocknrs_and_prealloc_arrays_from_search_start
(reiserfs_blocknr_hint_t *hint, b_blocknr_t *new_blocknrs, int amount_needed)
{
    struct super_block *s = hint->th->t_super;
    b_blocknr_t start = hint->search_start;
    b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1;
    int second_pass = 0;
    int nr_allocated = 0;

    determine_prealloc_size(hint);
    while((nr_allocated
            += allocate_without_wrapping_disk(hint, new_blocknrs + nr_allocated, start, finish,
                    amount_needed - nr_allocated, hint->prealloc_size))
            < amount_needed) {

        /* not all blocks were successfully allocated yet*/
        if (second_pass) {	/* it was a second pass; we must free all blocks */
            while (nr_allocated --)
                reiserfs_free_block(hint->th, new_blocknrs[nr_allocated]);

            return NO_DISK_SPACE;
        } else {		/* refine search parameters for next pass */
            second_pass = 1;
            finish = start;
            start = 0;
            continue;
        }
    }
    return CARRY_ON;
}
예제 #2
0
static inline int blocknrs_and_prealloc_arrays_from_search_start
(reiserfs_blocknr_hint_t *hint, b_blocknr_t *new_blocknrs, int amount_needed)
{
    struct super_block *s = hint->th->t_super;
    b_blocknr_t start = hint->search_start;
    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) {
        int quota_ret;
#ifdef REISERQUOTA_DEBUG
        reiserfs_debug (s, REISERFS_DEBUG_CODE, "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, REISERFS_DEBUG_CODE, "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;
        }
        /* 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;
            finish = SB_BLOCK_COUNT(s) - 1;
            break;
        case 1: /* Search from hint->beg to hint->search_start */
            start = hint->beg;
            finish = hint->search_start;
            break;
        case 2: /* Last chance: Search from 0 to hint->beg */
            start = 0;
            finish = hint->beg;
            break;
        default: /* We've tried searching everywhere, not enough space */
            /* Free the blocks */
            if (!hint->formatted_node) {
#ifdef REISERQUOTA_DEBUG
                reiserfs_debug (s, REISERFS_DEBUG_CODE, "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, hint->inode, new_blocknrs[nr_allocated], !hint->formatted_node);

            return NO_DISK_SPACE;
        }
    } while ((nr_allocated += allocate_without_wrapping_disk (hint,
                              new_blocknrs + nr_allocated, start, finish,
                              bigalloc ? bigalloc : 1,
                              amount_needed - nr_allocated,
                              hint->prealloc_size))
             < amount_needed);
    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, REISERFS_DEBUG_CODE, "reiserquota: freeing (failed prealloc) %d blocks id=%u", amount_needed + hint->prealloc_size - nr_allocated - REISERFS_I(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;
}