static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac, int type, u32 slot) { int status; u32 bits_wanted = ac->ac_bits_wanted; struct inode *alloc_inode; struct buffer_head *bh = NULL; struct ocfs2_dinode *fe; u32 free_bits; mlog_entry_void(); alloc_inode = ocfs2_get_system_file_inode(osb, type, slot); if (!alloc_inode) { mlog_errno(-EINVAL); return -EINVAL; } mutex_lock(&alloc_inode->i_mutex); status = ocfs2_meta_lock(alloc_inode, &bh, 1); if (status < 0) { mutex_unlock(&alloc_inode->i_mutex); iput(alloc_inode); mlog_errno(status); return status; } ac->ac_inode = alloc_inode; fe = (struct ocfs2_dinode *) bh->b_data; if (!OCFS2_IS_VALID_DINODE(fe)) { OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe); status = -EIO; goto bail; } if (!(fe->i_flags & cpu_to_le32(OCFS2_CHAIN_FL))) { ocfs2_error(alloc_inode->i_sb, "Invalid chain allocator %llu", (unsigned long long)le64_to_cpu(fe->i_blkno)); status = -EIO; goto bail; } free_bits = le32_to_cpu(fe->id1.bitmap1.i_total) - le32_to_cpu(fe->id1.bitmap1.i_used); if (bits_wanted > free_bits) { /* cluster bitmap never grows */ if (ocfs2_is_cluster_bitmap(alloc_inode)) { mlog(0, "Disk Full: wanted=%u, free_bits=%u\n", bits_wanted, free_bits); status = -ENOSPC; goto bail; } status = ocfs2_block_group_alloc(osb, alloc_inode, bh); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } atomic_inc(&osb->alloc_stats.bg_extends); /* You should never ask for this much metadata */ BUG_ON(bits_wanted > (le32_to_cpu(fe->id1.bitmap1.i_total) - le32_to_cpu(fe->id1.bitmap1.i_used))); } get_bh(bh); ac->ac_bh = bh; bail: if (bh) brelse(bh); mlog_exit(status); return status; }
static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac, int type, u32 slot, u64 *last_alloc_group, int flags) { int status; u32 bits_wanted = ac->ac_bits_wanted; struct inode *alloc_inode; struct buffer_head *bh = NULL; struct ocfs2_dinode *fe; u32 free_bits; alloc_inode = ocfs2_get_system_file_inode(osb, type, slot); if (!alloc_inode) { mlog_errno(-EINVAL); return -EINVAL; } mutex_lock(&alloc_inode->i_mutex); status = ocfs2_inode_lock(alloc_inode, &bh, 1); if (status < 0) { mutex_unlock(&alloc_inode->i_mutex); iput(alloc_inode); mlog_errno(status); return status; } ac->ac_inode = alloc_inode; ac->ac_alloc_slot = slot; fe = (struct ocfs2_dinode *) bh->b_data; /* The bh was validated by the inode read inside * ocfs2_inode_lock(). Any corruption is a code bug. */ BUG_ON(!OCFS2_IS_VALID_DINODE(fe)); if (!(fe->i_flags & cpu_to_le32(OCFS2_CHAIN_FL))) { status = ocfs2_error(alloc_inode->i_sb, "Invalid chain allocator %llu\n", (unsigned long long)le64_to_cpu(fe->i_blkno)); goto bail; } free_bits = le32_to_cpu(fe->id1.bitmap1.i_total) - le32_to_cpu(fe->id1.bitmap1.i_used); if (bits_wanted > free_bits) { /* cluster bitmap never grows */ if (ocfs2_is_cluster_bitmap(alloc_inode)) { trace_ocfs2_reserve_suballoc_bits_nospc(bits_wanted, free_bits); status = -ENOSPC; goto bail; } if (!(flags & ALLOC_NEW_GROUP)) { trace_ocfs2_reserve_suballoc_bits_no_new_group( slot, bits_wanted, free_bits); status = -ENOSPC; goto bail; } status = ocfs2_block_group_alloc(osb, alloc_inode, bh, ac->ac_max_block, last_alloc_group, flags); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } atomic_inc(&osb->alloc_stats.bg_extends); /* You should never ask for this much metadata */ BUG_ON(bits_wanted > (le32_to_cpu(fe->id1.bitmap1.i_total) - le32_to_cpu(fe->id1.bitmap1.i_used))); } get_bh(bh); ac->ac_bh = bh; bail: brelse(bh); if (status) mlog_errno(status); return status; }