Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 114398
b: refs/heads/master
c: 1187c96
h: refs/heads/master
v: v3
  • Loading branch information
Joel Becker authored and Mark Fasheh committed Oct 13, 2008
1 parent dc72f62 commit c524349
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 08413899db89d8d636c2a2d4ba5c356ab587d7ef
refs/heads/master: 1187c968852e3c668f3b9376083851f81f6eee22
55 changes: 55 additions & 0 deletions trunk/fs/ocfs2/localalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,46 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb,
return status;
}

/* Check to see if the local alloc window is within ac->ac_max_block */
static int ocfs2_local_alloc_in_range(struct inode *inode,
struct ocfs2_alloc_context *ac,
u32 bits_wanted)
{
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_dinode *alloc;
struct ocfs2_local_alloc *la;
int start;
u64 block_off;

if (!ac->ac_max_block)
return 1;

alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
la = OCFS2_LOCAL_ALLOC(alloc);

start = ocfs2_local_alloc_find_clear_bits(osb, alloc, bits_wanted);
if (start == -1) {
mlog_errno(-ENOSPC);
return 0;
}

/*
* Converting (bm_off + start + bits_wanted) to blocks gives us
* the blkno just past our actual allocation. This is perfect
* to compare with ac_max_block.
*/
block_off = ocfs2_clusters_to_blocks(inode->i_sb,
le32_to_cpu(la->la_bm_off) +
start + bits_wanted);
mlog(0, "Checking %llu against %llu\n",
(unsigned long long)block_off,
(unsigned long long)ac->ac_max_block);
if (block_off > ac->ac_max_block)
return 0;

return 1;
}

/*
* make sure we've got at least bits_wanted contiguous bits in the
* local alloc. You lose them when you drop i_mutex.
Expand Down Expand Up @@ -658,6 +698,21 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
goto bail;
}

if (ac->ac_max_block)
mlog(0, "Calling in_range for max block %llu\n",
(unsigned long long)ac->ac_max_block);

if (!ocfs2_local_alloc_in_range(local_alloc_inode, ac,
bits_wanted)) {
/*
* The window is outside ac->ac_max_block.
* This errno tells the caller to keep localalloc enabled
* but to get the allocation from the main bitmap.
*/
status = -EFBIG;
goto bail;
}

ac->ac_inode = local_alloc_inode;
/* We should never use localalloc from another slot */
ac->ac_alloc_slot = osb->slot_num;
Expand Down
83 changes: 68 additions & 15 deletions trunk/fs/ocfs2/suballoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,18 @@ static int ocfs2_block_group_fill(handle_t *handle,
struct ocfs2_chain_list *cl);
static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
struct inode *alloc_inode,
struct buffer_head *bh);
struct buffer_head *bh,
u64 max_block);

static int ocfs2_cluster_group_search(struct inode *inode,
struct buffer_head *group_bh,
u32 bits_wanted, u32 min_bits,
u64 max_block,
u16 *bit_off, u16 *bits_found);
static int ocfs2_block_group_search(struct inode *inode,
struct buffer_head *group_bh,
u32 bits_wanted, u32 min_bits,
u64 max_block,
u16 *bit_off, u16 *bits_found);
static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
struct ocfs2_alloc_context *ac,
Expand Down Expand Up @@ -110,6 +113,9 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
u64 data_blkno,
u64 *bg_blkno,
u16 *bg_bit_off);
static int ocfs2_reserve_clusters_with_limit(struct ocfs2_super *osb,
u32 bits_wanted, u64 max_block,
struct ocfs2_alloc_context **ac);

void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
{
Expand Down Expand Up @@ -276,7 +282,8 @@ static inline u16 ocfs2_find_smallest_chain(struct ocfs2_chain_list *cl)
*/
static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
struct inode *alloc_inode,
struct buffer_head *bh)
struct buffer_head *bh,
u64 max_block)
{
int status, credits;
struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data;
Expand All @@ -294,9 +301,9 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
mlog_entry_void();

cl = &fe->id2.i_chain;
status = ocfs2_reserve_clusters(osb,
le16_to_cpu(cl->cl_cpg),
&ac);
status = ocfs2_reserve_clusters_with_limit(osb,
le16_to_cpu(cl->cl_cpg),
max_block, &ac);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
Expand Down Expand Up @@ -469,7 +476,8 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
goto bail;
}

status = ocfs2_block_group_alloc(osb, alloc_inode, bh);
status = ocfs2_block_group_alloc(osb, alloc_inode, bh,
ac->ac_max_block);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
Expand Down Expand Up @@ -590,6 +598,13 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,

(*ac)->ac_group_search = ocfs2_block_group_search;

/*
* stat(2) can't handle i_ino > 32bits, so we tell the
* lower levels not to allocate us a block group past that
* limit.
*/
(*ac)->ac_max_block = (u32)~0U;

/*
* slot is set when we successfully steal inode from other nodes.
* It is reset in 3 places:
Expand Down Expand Up @@ -670,9 +685,9 @@ int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb,
/* Callers don't need to care which bitmap (local alloc or main) to
* use so we figure it out for them, but unfortunately this clutters
* things a bit. */
int ocfs2_reserve_clusters(struct ocfs2_super *osb,
u32 bits_wanted,
struct ocfs2_alloc_context **ac)
static int ocfs2_reserve_clusters_with_limit(struct ocfs2_super *osb,
u32 bits_wanted, u64 max_block,
struct ocfs2_alloc_context **ac)
{
int status;

Expand All @@ -686,13 +701,18 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
}

(*ac)->ac_bits_wanted = bits_wanted;
(*ac)->ac_max_block = max_block;

status = -ENOSPC;
if (ocfs2_alloc_should_use_local(osb, bits_wanted)) {
status = ocfs2_reserve_local_alloc_bits(osb,
bits_wanted,
*ac);
if ((status < 0) && (status != -ENOSPC)) {
if (status == -EFBIG) {
/* The local alloc window is outside ac_max_block.
* use the main bitmap. */
status = -ENOSPC;
} else if ((status < 0) && (status != -ENOSPC)) {
mlog_errno(status);
goto bail;
}
Expand All @@ -718,6 +738,13 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
return status;
}

int ocfs2_reserve_clusters(struct ocfs2_super *osb,
u32 bits_wanted,
struct ocfs2_alloc_context **ac)
{
return ocfs2_reserve_clusters_with_limit(osb, bits_wanted, 0, ac);
}

/*
* More or less lifted from ext3. I'll leave their description below:
*
Expand Down Expand Up @@ -1000,10 +1027,12 @@ static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg
static int ocfs2_cluster_group_search(struct inode *inode,
struct buffer_head *group_bh,
u32 bits_wanted, u32 min_bits,
u64 max_block,
u16 *bit_off, u16 *bits_found)
{
int search = -ENOSPC;
int ret;
u64 blkoff;
struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
u16 tmp_off, tmp_found;
Expand Down Expand Up @@ -1038,6 +1067,17 @@ static int ocfs2_cluster_group_search(struct inode *inode,
if (ret)
return ret;

if (max_block) {
blkoff = ocfs2_clusters_to_blocks(inode->i_sb,
gd_cluster_off +
tmp_off + tmp_found);
mlog(0, "Checking %llu against %llu\n",
(unsigned long long)blkoff,
(unsigned long long)max_block);
if (blkoff > max_block)
return -ENOSPC;
}

/* ocfs2_block_group_find_clear_bits() might
* return success, but we still want to return
* -ENOSPC unless it found the minimum number
Expand All @@ -1061,19 +1101,31 @@ static int ocfs2_cluster_group_search(struct inode *inode,
static int ocfs2_block_group_search(struct inode *inode,
struct buffer_head *group_bh,
u32 bits_wanted, u32 min_bits,
u64 max_block,
u16 *bit_off, u16 *bits_found)
{
int ret = -ENOSPC;
u64 blkoff;
struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) group_bh->b_data;

BUG_ON(min_bits != 1);
BUG_ON(ocfs2_is_cluster_bitmap(inode));

if (bg->bg_free_bits_count)
if (bg->bg_free_bits_count) {
ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
group_bh, bits_wanted,
le16_to_cpu(bg->bg_bits),
bit_off, bits_found);
if (!ret && max_block) {
blkoff = le64_to_cpu(bg->bg_blkno) + *bit_off +
*bits_found;
mlog(0, "Checking %llu against %llu\n",
(unsigned long long)blkoff,
(unsigned long long)max_block);
if (blkoff > max_block)
ret = -ENOSPC;
}
}

return ret;
}
Expand Down Expand Up @@ -1138,7 +1190,7 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
}

ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits,
bit_off, &found);
ac->ac_max_block, bit_off, &found);
if (ret < 0) {
if (ret != -ENOSPC)
mlog_errno(ret);
Expand Down Expand Up @@ -1210,11 +1262,12 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
status = -ENOSPC;
/* for now, the chain search is a bit simplistic. We just use
* the 1st group with any empty bits. */
while ((status = ac->ac_group_search(alloc_inode, group_bh, bits_wanted,
min_bits, bit_off, &tmp_bits)) == -ENOSPC) {
while ((status = ac->ac_group_search(alloc_inode, group_bh,
bits_wanted, min_bits,
ac->ac_max_block, bit_off,
&tmp_bits)) == -ENOSPC) {
if (!bg->bg_next_group)
break;

if (prev_group_bh) {
brelse(prev_group_bh);
prev_group_bh = NULL;
Expand Down
11 changes: 7 additions & 4 deletions trunk/fs/ocfs2/suballoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@

typedef int (group_search_t)(struct inode *,
struct buffer_head *,
u32,
u32,
u16 *,
u16 *);
u32, /* bits_wanted */
u32, /* min_bits */
u64, /* max_block */
u16 *, /* *bit_off */
u16 *); /* *bits_found */

struct ocfs2_alloc_context {
struct inode *ac_inode; /* which bitmap are we allocating from? */
Expand All @@ -51,6 +52,8 @@ struct ocfs2_alloc_context {
group_search_t *ac_group_search;

u64 ac_last_group;
u64 ac_max_block; /* Highest block number to allocate. 0 is
is the same as ~0 - unlimited */
};

void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac);
Expand Down

0 comments on commit c524349

Please sign in to comment.