Release 4.10 fs/ocfs2/suballoc.c
/* -*- mode: c; c-basic-offset: 8; -*-
* vim: noexpandtab sw=8 ts=8 sts=0:
*
* suballoc.c
*
* metadata alloc and free
* Inspired by ext3 block groups.
*
* Copyright (C) 2002, 2004 Oracle. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <cluster/masklog.h>
#include "ocfs2.h"
#include "alloc.h"
#include "blockcheck.h"
#include "dlmglue.h"
#include "inode.h"
#include "journal.h"
#include "localalloc.h"
#include "suballoc.h"
#include "super.h"
#include "sysfile.h"
#include "uptodate.h"
#include "ocfs2_trace.h"
#include "buffer_head_io.h"
#define NOT_ALLOC_NEW_GROUP 0
#define ALLOC_NEW_GROUP 0x1
#define ALLOC_GROUPS_FROM_GLOBAL 0x2
#define OCFS2_MAX_TO_STEAL 1024
struct ocfs2_suballoc_result {
u64 sr_bg_blkno; /* The bg we allocated from. Set
to 0 when a block group is
contiguous. */
u64 sr_bg_stable_blkno; /*
* Doesn't change, always
* set to target block
* group descriptor
* block.
*/
u64 sr_blkno; /* The first allocated block */
unsigned int sr_bit_offset; /* The bit in the bg */
unsigned int sr_bits; /* How many bits we claimed */
};
static u64 ocfs2_group_from_res(struct ocfs2_suballoc_result *res)
{
if (res->sr_blkno == 0)
return 0;
if (res->sr_bg_blkno)
return res->sr_bg_blkno;
return ocfs2_which_suballoc_group(res->sr_blkno, res->sr_bit_offset);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
mark fasheh | mark fasheh | 45 | 100.00% | 1 | 100.00% |
| Total | 45 | 100.00% | 1 | 100.00% |
static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg);
static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe);
static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl);
static int ocfs2_block_group_fill(handle_t *handle,
struct inode *alloc_inode,
struct buffer_head *bg_bh,
u64 group_blkno,
unsigned int group_clusters,
u16 my_chain,
struct ocfs2_chain_list *cl);
static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
struct inode *alloc_inode,
struct buffer_head *bh,
u64 max_block,
u64 *last_alloc_group,
int flags);
static int ocfs2_cluster_group_search(struct inode *inode,
struct buffer_head *group_bh,
u32 bits_wanted, u32 min_bits,
u64 max_block,
struct ocfs2_suballoc_result *res);
static int ocfs2_block_group_search(struct inode *inode,
struct buffer_head *group_bh,
u32 bits_wanted, u32 min_bits,
u64 max_block,
struct ocfs2_suballoc_result *res);
static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
handle_t *handle,
u32 bits_wanted,
u32 min_bits,
struct ocfs2_suballoc_result *res);
static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
int nr);
static int ocfs2_relink_block_group(handle_t *handle,
struct inode *alloc_inode,
struct buffer_head *fe_bh,
struct buffer_head *bg_bh,
struct buffer_head *prev_bg_bh,
u16 chain);
static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,
u32 wanted);
static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
u64 bg_blkno,
u16 bg_bit_off);
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,
int flags,
struct ocfs2_alloc_context **ac);
void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
{
struct inode *inode = ac->ac_inode;
if (inode) {
if (ac->ac_which != OCFS2_AC_USE_LOCAL)
ocfs2_inode_unlock(inode, 1);
inode_unlock(inode);
iput(inode);
ac->ac_inode = NULL;
}
brelse(ac->ac_bh);
ac->ac_bh = NULL;
ac->ac_resv = NULL;
kfree(ac->ac_find_loc_priv);
ac->ac_find_loc_priv = NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
mark fasheh | mark fasheh | 74 | 84.09% | 6 | 75.00% |
tao ma | tao ma | 13 | 14.77% | 1 | 12.50% |
al viro | al viro | 1 | 1.14% | 1 | 12.50% |
| Total | 88 | 100.00% | 8 | 100.00% |
void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
{
ocfs2_free_ac_resource(ac);
kfree(ac);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tao ma | tao ma | 14 | 70.00% | 1 | 50.00% |
mark fasheh | mark fasheh | 6 | 30.00% | 1 | 50.00% |
| Total | 20 | 100.00% | 2 | 100.00% |
static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
{
return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
mark fasheh | mark fasheh | 32 | 100.00% | 1 | 100.00% |
| Total | 32 | 100.00% | 1 | 100.00% |
#define do_error(fmt, ...) \
do { \
if (resize) \
mlog(ML_ERROR, fmt, ##__VA_ARGS__); \
else \
return ocfs2_error(sb, fmt, ##__VA_ARGS__); \
} while (0)
static int ocfs2_validate_gd_self(struct super_block *sb,
struct buffer_head *bh,
int resize)
{
struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
do_error("Group descriptor #%llu has bad signature %.*s\n",
(unsigned long long)bh->b_blocknr, 7,
gd->bg_signature);
}
if (le64_to_cpu(gd->bg_blkno) != bh->b_blocknr) {
do_error("Group descriptor #%llu has an invalid bg_blkno of %llu\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)le64_to_cpu(gd->bg_blkno));
}
if (le32_to_cpu(gd->bg_generation) != OCFS2_SB(sb)->fs_generation) {
do_error("Group descriptor #%llu has an invalid fs_generation of #%u\n",
(unsigned long long)bh->b_blocknr,
le32_to_cpu(gd->bg_generation));
}
if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) {
do_error("Group descriptor #%llu has bit count %u but claims that %u are free\n",
(unsigned long long)bh->b_blocknr,
le16_to_cpu(gd->bg_bits),
le16_to_cpu(gd->bg_free_bits_count));
}
if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) {
do_error("Group descriptor #%llu has bit count %u but max bitmap bits of %u\n",
(unsigned long long)bh->b_blocknr,
le16_to_cpu(gd->bg_bits),
8 * le16_to_cpu(gd->bg_size));
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 210 | 86.07% | 3 | 50.00% |
mark fasheh | mark fasheh | 28 | 11.48% | 1 | 16.67% |
joe perches | joe perches | 5 | 2.05% | 1 | 16.67% |
tao ma | tao ma | 1 | 0.41% | 1 | 16.67% |
| Total | 244 | 100.00% | 6 | 100.00% |
static int ocfs2_validate_gd_parent(struct super_block *sb,
struct ocfs2_dinode *di,
struct buffer_head *bh,
int resize)
{
unsigned int max_bits;
struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
if (di->i_blkno != gd->bg_parent_dinode) {
do_error("Group descriptor #%llu has bad parent pointer (%llu, expected %llu)\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)le64_to_cpu(gd->bg_parent_dinode),
(unsigned long long)le64_to_cpu(di->i_blkno));
}
max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) * le16_to_cpu(di->id2.i_chain.cl_bpc);
if (le16_to_cpu(gd->bg_bits) > max_bits) {
do_error("Group descriptor #%llu has bit count of %u\n",
(unsigned long long)bh->b_blocknr,
le16_to_cpu(gd->bg_bits));
}
/* In resize, we may meet the case bg_chain == cl_next_free_rec. */
if ((le16_to_cpu(gd->bg_chain) >
le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) ||
((le16_to_cpu(gd->bg_chain) ==
le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) && !resize)) {
do_error("Group descriptor #%llu has bad chain %u\n",
(unsigned long long)bh->b_blocknr,
le16_to_cpu(gd->bg_chain));
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
mark fasheh | mark fasheh | 136 | 60.71% | 1 | 16.67% |
joel becker | joel becker | 55 | 24.55% | 3 | 50.00% |
tao ma | tao ma | 30 | 13.39% | 1 | 16.67% |
joe perches | joe perches | 3 | 1.34% | 1 | 16.67% |
| Total | 224 | 100.00% | 6 | 100.00% |
#undef do_error
/*
* This version only prints errors. It does not fail the filesystem, and
* exists only for resize.
*/
int ocfs2_check_group_descriptor(struct super_block *sb,
struct ocfs2_dinode *di,
struct buffer_head *bh)
{
int rc;
struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
BUG_ON(!buffer_uptodate(bh));
/*
* If the ecc fails, we return the error but otherwise
* leave the filesystem running. We know any error is
* local to this block.
*/
rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &gd->bg_check);
if (rc) {
mlog(ML_ERROR,
"Checksum failed for group descriptor %llu\n",
(unsigned long long)bh->b_blocknr);
} else
rc = ocfs2_validate_gd_self(sb, bh, 1);
if (!rc)
rc = ocfs2_validate_gd_parent(sb, di, bh, 1);
return rc;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 108 | 91.53% | 4 | 80.00% |
mark fasheh | mark fasheh | 10 | 8.47% | 1 | 20.00% |
| Total | 118 | 100.00% | 5 | 100.00% |
static int ocfs2_validate_group_descriptor(struct super_block *sb,
struct buffer_head *bh)
{
int rc;
struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
trace_ocfs2_validate_group_descriptor(
(unsigned long long)bh->b_blocknr);
BUG_ON(!buffer_uptodate(bh));
/*
* If the ecc fails, we return the error but otherwise
* leave the filesystem running. We know any error is
* local to this block.
*/
rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &gd->bg_check);
if (rc)
return rc;
/*
* Errors after here are fatal.
*/
return ocfs2_validate_gd_self(sb, bh, 0);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 74 | 83.15% | 3 | 50.00% |
mark fasheh | mark fasheh | 14 | 15.73% | 2 | 33.33% |
tao ma | tao ma | 1 | 1.12% | 1 | 16.67% |
| Total | 89 | 100.00% | 6 | 100.00% |
int ocfs2_read_group_descriptor(struct inode *inode, struct ocfs2_dinode *di,
u64 gd_blkno, struct buffer_head **bh)
{
int rc;
struct buffer_head *tmp = *bh;
rc = ocfs2_read_block(INODE_CACHE(inode), gd_blkno, &tmp,
ocfs2_validate_group_descriptor);
if (rc)
goto out;
rc = ocfs2_validate_gd_parent(inode->i_sb, di, tmp, 0);
if (rc) {
brelse(tmp);
goto out;
}
/* If ocfs2_read_block() got us a new bh, pass it up. */
if (!*bh)
*bh = tmp;
out:
return rc;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 105 | 100.00% | 3 | 100.00% |
| Total | 105 | 100.00% | 3 | 100.00% |
static void ocfs2_bg_discontig_add_extent(struct ocfs2_super *osb,
struct ocfs2_group_desc *bg,
struct ocfs2_chain_list *cl,
u64 p_blkno, unsigned int clusters)
{
struct ocfs2_extent_list *el = &bg->bg_list;
struct ocfs2_extent_rec *rec;
BUG_ON(!ocfs2_supports_discontig_bg(osb));
if (!el->l_next_free_rec)
el->l_count = cpu_to_le16(ocfs2_extent_recs_per_gd(osb->sb));
rec = &el->l_recs[le16_to_cpu(el->l_next_free_rec)];
rec->e_blkno = cpu_to_le64(p_blkno);
rec->e_cpos = cpu_to_le32(le16_to_cpu(bg->bg_bits) /
le16_to_cpu(cl->cl_bpc));
rec->e_leaf_clusters = cpu_to_le16(clusters);
le16_add_cpu(&bg->bg_bits, clusters * le16_to_cpu(cl->cl_bpc));
le16_add_cpu(&bg->bg_free_bits_count,
clusters * le16_to_cpu(cl->cl_bpc));
le16_add_cpu(&el->l_next_free_rec, 1);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 147 | 85.96% | 1 | 33.33% |
tao ma | tao ma | 24 | 14.04% | 2 | 66.67% |
| Total | 171 | 100.00% | 3 | 100.00% |
static int ocfs2_block_group_fill(handle_t *handle,
struct inode *alloc_inode,
struct buffer_head *bg_bh,
u64 group_blkno,
unsigned int group_clusters,
u16 my_chain,
struct ocfs2_chain_list *cl)
{
int status = 0;
struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb);
struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
struct super_block * sb = alloc_inode->i_sb;
if (((unsigned long long) bg_bh->b_blocknr) != group_blkno) {
status = ocfs2_error(alloc_inode->i_sb,
"group block (%llu) != b_blocknr (%llu)\n",
(unsigned long long)group_blkno,
(unsigned long long) bg_bh->b_blocknr);
goto bail;
}
status = ocfs2_journal_access_gd(handle,
INODE_CACHE(alloc_inode),
bg_bh,
OCFS2_JOURNAL_ACCESS_CREATE);
if (status < 0) {
mlog_errno(status);
goto bail;
}
memset(bg, 0, sb->s_blocksize);
strcpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE);
bg->bg_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb, 1,
osb->s_feature_incompat));
bg->bg_chain = cpu_to_le16(my_chain);
bg->bg_next_group = cl->cl_recs[my_chain].c_blkno;
bg->bg_parent_dinode = cpu_to_le64(OCFS2_I(alloc_inode)->ip_blkno);
bg->bg_blkno = cpu_to_le64(group_blkno);
if (group_clusters == le16_to_cpu(cl->cl_cpg))
bg->bg_bits = cpu_to_le16(ocfs2_bits_per_group(cl));
else
ocfs2_bg_discontig_add_extent(osb, bg, cl, group_blkno,
group_clusters);
/* set the 1st bit in the bitmap to account for the descriptor block */
ocfs2_set_bit(0, (unsigned long *)bg->bg_bitmap);
bg->bg_free_bits_count = cpu_to_le16(le16_to_cpu(bg->bg_bits) - 1);
ocfs2_journal_dirty(handle, bg_bh);
/* There is no need to zero out or otherwise initialize the
* other blocks in a group - All valid FS metadata in a block
* group stores the superblock fs_generation value at
* allocation time. */
bail:
if (status)
mlog_errno(status);
return status;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
mark fasheh | mark fasheh | 270 | 79.18% | 3 | 25.00% |
joel becker | joel becker | 58 | 17.01% | 4 | 33.33% |
tao ma | tao ma | 10 | 2.93% | 3 | 25.00% |
goldwyn rodrigues | goldwyn rodrigues | 2 | 0.59% | 1 | 8.33% |
joe perches | joe perches | 1 | 0.29% | 1 | 8.33% |
| Total | 341 | 100.00% | 12 | 100.00% |
static inline u16 ocfs2_find_smallest_chain(struct ocfs2_chain_list *cl)
{
u16 curr, best;
best = curr = 0;
while (curr < le16_to_cpu(cl->cl_count)) {
if (le32_to_cpu(cl->cl_recs[best].c_total) >
le32_to_cpu(cl->cl_recs[curr].c_total))
best = curr;
curr++;
}
return best;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
mark fasheh | mark fasheh | 72 | 100.00% | 1 | 100.00% |
| Total | 72 | 100.00% | 1 | 100.00% |
static struct buffer_head *
ocfs2_block_group_alloc_contig(struct ocfs2_super *osb, handle_t *handle,
struct inode *alloc_inode,
struct ocfs2_alloc_context *ac,
struct ocfs2_chain_list *cl)
{
int status;
u32 bit_off, num_bits;
u64 bg_blkno;
struct buffer_head *bg_bh;
unsigned int alloc_rec = ocfs2_find_smallest_chain(cl);
status = ocfs2_claim_clusters(handle, ac,
le16_to_cpu(cl->cl_cpg), &bit_off,
&num_bits);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
goto bail;
}
/* setup the group */
bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off);
trace_ocfs2_block_group_alloc_contig(
(unsigned long long)bg_blkno, alloc_rec);
bg_bh = sb_getblk(osb->sb, bg_blkno);
if (!bg_bh) {
status = -ENOMEM;
mlog_errno(status);
goto bail;
}
ocfs2_set_new_buffer_uptodate(INODE_CACHE(alloc_inode), bg_bh);
status = ocfs2_block_group_fill(handle, alloc_inode, bg_bh,
bg_blkno, num_bits, alloc_rec, cl);
if (status < 0) {
brelse(bg_bh);
mlog_errno(status);
}
bail:
return status ? ERR_PTR(status) : bg_bh;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 178 | 82.41% | 1 | 16.67% |
mark fasheh | mark fasheh | 32 | 14.81% | 1 | 16.67% |
tao ma | tao ma | 5 | 2.31% | 3 | 50.00% |
rui xiang | rui xiang | 1 | 0.46% | 1 | 16.67% |
| Total | 216 | 100.00% | 6 | 100.00% |
static int ocfs2_block_group_claim_bits(struct ocfs2_super *osb,
handle_t *handle,
struct ocfs2_alloc_context *ac,
unsigned int min_bits,
u32 *bit_off, u32 *num_bits)
{
int status = 0;
while (min_bits) {
status = ocfs2_claim_clusters(handle, ac, min_bits,
bit_off, num_bits);
if (status != -ENOSPC)
break;
min_bits >>= 1;
}
return status;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 73 | 100.00% | 2 | 100.00% |
| Total | 73 | 100.00% | 2 | 100.00% |
static int ocfs2_block_group_grow_discontig(handle_t *handle,
struct inode *alloc_inode,
struct buffer_head *bg_bh,
struct ocfs2_alloc_context *ac,
struct ocfs2_chain_list *cl,
unsigned int min_bits)
{
int status;
struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb);
struct ocfs2_group_desc *bg =
(struct ocfs2_group_desc *)bg_bh->b_data;
unsigned int needed = le16_to_cpu(cl->cl_cpg) -
le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc);
u32 p_cpos, clusters;
u64 p_blkno;
struct ocfs2_extent_list *el = &bg->bg_list;
status = ocfs2_journal_access_gd(handle,
INODE_CACHE(alloc_inode),
bg_bh,
OCFS2_JOURNAL_ACCESS_CREATE);
if (status < 0) {
mlog_errno(status);
goto bail;
}
while ((needed > 0) && (le16_to_cpu(el->l_next_free_rec) <
le16_to_cpu(el->l_count))) {
if (min_bits > needed)
min_bits = needed;
status = ocfs2_block_group_claim_bits(osb, handle, ac,
min_bits, &p_cpos,
&clusters);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
goto bail;
}
p_blkno = ocfs2_clusters_to_blocks(osb->sb, p_cpos);
ocfs2_bg_discontig_add_extent(osb, bg, cl, p_blkno,
clusters);
min_bits = clusters;
needed = le16_to_cpu(cl->cl_cpg) -
le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc);
}
if (needed > 0) {
/*
* We have used up all the extent rec but can't fill up
* the cpg. So bail out.
*/
status = -ENOSPC;
goto bail;
}
ocfs2_journal_dirty(handle, bg_bh);
bail:
return status;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 265 | 89.53% | 1 | 50.00% |
tao ma | tao ma | 31 | 10.47% | 1 | 50.00% |
| Total | 296 | 100.00% | 2 | 100.00% |
static void ocfs2_bg_alloc_cleanup(handle_t *handle,
struct ocfs2_alloc_context *cluster_ac,
struct inode *alloc_inode,
struct buffer_head *bg_bh)
{
int i, ret;
struct ocfs2_group_desc *bg;
struct ocfs2_extent_list *el;
struct ocfs2_extent_rec *rec;
if (!bg_bh)
return;
bg = (struct ocfs2_group_desc *)bg_bh->b_data;
el = &bg->bg_list;
for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
rec = &el->l_recs[i];
ret = ocfs2_free_clusters(handle, cluster_ac->ac_inode,
cluster_ac->ac_bh,
le64_to_cpu(rec->e_blkno),
le16_to_cpu(rec->e_leaf_clusters));
if (ret)
mlog_errno(ret);
/* Try all the clusters to free */
}
ocfs2_remove_from_cache(INODE_CACHE(alloc_inode), bg_bh);
brelse(bg_bh);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 152 | 99.35% | 2 | 66.67% |
al viro | al viro | 1 | 0.65% | 1 | 33.33% |
| Total | 153 | 100.00% | 3 | 100.00% |
static struct buffer_head *
ocfs2_block_group_alloc_discontig(handle_t *handle,
struct inode *alloc_inode,
struct ocfs2_alloc_context *ac,
struct ocfs2_chain_list *cl)
{
int status;
u32 bit_off, num_bits;
u64 bg_blkno;
unsigned int min_bits = le16_to_cpu(cl->cl_cpg) >> 1;
struct buffer_head *bg_bh = NULL;
unsigned int alloc_rec = ocfs2_find_smallest_chain(cl);
struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb);
if (!ocfs2_supports_discontig_bg(osb)) {
status = -ENOSPC;
goto bail;
}
status = ocfs2_extend_trans(handle,
ocfs2_calc_bg_discontig_credits(osb->sb));
if (status) {
mlog_errno(status);
goto bail;
}
/*
* We're going to be grabbing from multiple cluster groups.
* We don't have enough credits to relink them all, and the
* cluster groups will be staying in cache for the duration of
* this operation.
*/
ac->ac_disable_chain_relink = 1;
/* Claim the first region */
status = ocfs2_block_group_claim_bits(osb, handle, ac, min_bits,
&bit_off, &num_bits);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
goto bail;
}
min_bits = num_bits;
/* setup the group */
bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off);
trace_ocfs2_block_group_alloc_discontig(
(unsigned long long)bg_blkno, alloc_rec);
bg_bh = sb_getblk(osb->sb, bg_blkno);
if (!bg_bh) {
status =