📄 suballoc.c
字号:
int status; u64 bg_blkno; BUG_ON(!ac); BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted)); BUG_ON(ac->ac_which != OCFS2_AC_USE_META); status = ocfs2_claim_suballoc_bits(osb, ac, handle, bits_wanted, 1, suballoc_bit_start, num_bits, &bg_blkno); if (status < 0) { mlog_errno(status); goto bail; } atomic_inc(&osb->alloc_stats.bg_allocs); *blkno_start = bg_blkno + (u64) *suballoc_bit_start; ac->ac_bits_given += (*num_bits); status = 0;bail: mlog_exit(status); return status;}int ocfs2_claim_new_inode(struct ocfs2_super *osb, handle_t *handle, struct ocfs2_alloc_context *ac, u16 *suballoc_bit, u64 *fe_blkno){ int status; unsigned int num_bits; u64 bg_blkno; mlog_entry_void(); BUG_ON(!ac); BUG_ON(ac->ac_bits_given != 0); BUG_ON(ac->ac_bits_wanted != 1); BUG_ON(ac->ac_which != OCFS2_AC_USE_INODE); status = ocfs2_claim_suballoc_bits(osb, ac, handle, 1, 1, suballoc_bit, &num_bits, &bg_blkno); if (status < 0) { mlog_errno(status); goto bail; } atomic_inc(&osb->alloc_stats.bg_allocs); BUG_ON(num_bits != 1); *fe_blkno = bg_blkno + (u64) (*suballoc_bit); ac->ac_bits_given++; status = 0;bail: mlog_exit(status); return status;}/* translate a group desc. blkno and it's bitmap offset into * disk cluster offset. */static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode, u64 bg_blkno, u16 bg_bit_off){ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); u32 cluster = 0; BUG_ON(!ocfs2_is_cluster_bitmap(inode)); if (bg_blkno != osb->first_cluster_group_blkno) cluster = ocfs2_blocks_to_clusters(inode->i_sb, bg_blkno); cluster += (u32) bg_bit_off; return cluster;}/* given a cluster offset, calculate which block group it belongs to * and return that block offset. */static inline u64 ocfs2_which_cluster_group(struct inode *inode, u32 cluster){ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); u32 group_no; BUG_ON(!ocfs2_is_cluster_bitmap(inode)); group_no = cluster / osb->bitmap_cpg; if (!group_no) return osb->first_cluster_group_blkno; return ocfs2_clusters_to_blocks(inode->i_sb, group_no * osb->bitmap_cpg);}/* given the block number of a cluster start, calculate which cluster * group and descriptor bitmap offset that corresponds to. */static inline void ocfs2_block_to_cluster_group(struct inode *inode, u64 data_blkno, u64 *bg_blkno, u16 *bg_bit_off){ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); u32 data_cluster = ocfs2_blocks_to_clusters(osb->sb, data_blkno); BUG_ON(!ocfs2_is_cluster_bitmap(inode)); *bg_blkno = ocfs2_which_cluster_group(inode, data_cluster); if (*bg_blkno == osb->first_cluster_group_blkno) *bg_bit_off = (u16) data_cluster; else *bg_bit_off = (u16) ocfs2_blocks_to_clusters(osb->sb, data_blkno - *bg_blkno);}/* * min_bits - minimum contiguous chunk from this total allocation we * can handle. set to what we asked for originally for a full * contig. allocation, set to '1' to indicate we can deal with extents * of any size. */int __ocfs2_claim_clusters(struct ocfs2_super *osb, handle_t *handle, struct ocfs2_alloc_context *ac, u32 min_clusters, u32 max_clusters, u32 *cluster_start, u32 *num_clusters){ int status; unsigned int bits_wanted = max_clusters; u64 bg_blkno = 0; u16 bg_bit_off; mlog_entry_void(); BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted); BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL && ac->ac_which != OCFS2_AC_USE_MAIN); if (ac->ac_which == OCFS2_AC_USE_LOCAL) { status = ocfs2_claim_local_alloc_bits(osb, handle, ac, bits_wanted, cluster_start, num_clusters); if (!status) atomic_inc(&osb->alloc_stats.local_data); } else { if (min_clusters > (osb->bitmap_cpg - 1)) { /* The only paths asking for contiguousness * should know about this already. */ mlog(ML_ERROR, "minimum allocation requested exceeds " "group bitmap size!"); status = -ENOSPC; goto bail; } /* clamp the current request down to a realistic size. */ if (bits_wanted > (osb->bitmap_cpg - 1)) bits_wanted = osb->bitmap_cpg - 1; status = ocfs2_claim_suballoc_bits(osb, ac, handle, bits_wanted, min_clusters, &bg_bit_off, num_clusters, &bg_blkno); if (!status) { *cluster_start = ocfs2_desc_bitmap_to_cluster_off(ac->ac_inode, bg_blkno, bg_bit_off); atomic_inc(&osb->alloc_stats.bitmap_data); } } if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } ac->ac_bits_given += *num_clusters;bail: mlog_exit(status); return status;}int ocfs2_claim_clusters(struct ocfs2_super *osb, handle_t *handle, struct ocfs2_alloc_context *ac, u32 min_clusters, u32 *cluster_start, u32 *num_clusters){ unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; return __ocfs2_claim_clusters(osb, handle, ac, min_clusters, bits_wanted, cluster_start, num_clusters);}static inline int ocfs2_block_group_clear_bits(handle_t *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, struct buffer_head *group_bh, unsigned int bit_off, unsigned int num_bits){ int status; unsigned int tmp; int journal_type = OCFS2_JOURNAL_ACCESS_WRITE; struct ocfs2_group_desc *undo_bg = NULL; mlog_entry_void(); if (!OCFS2_IS_VALID_GROUP_DESC(bg)) { OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg); status = -EIO; goto bail; } mlog(0, "off = %u, num = %u\n", bit_off, num_bits); if (ocfs2_is_cluster_bitmap(alloc_inode)) journal_type = OCFS2_JOURNAL_ACCESS_UNDO; status = ocfs2_journal_access(handle, alloc_inode, group_bh, journal_type); if (status < 0) { mlog_errno(status); goto bail; } if (ocfs2_is_cluster_bitmap(alloc_inode)) undo_bg = (struct ocfs2_group_desc *) bh2jh(group_bh)->b_committed_data; tmp = num_bits; while(tmp--) { ocfs2_clear_bit((bit_off + tmp), (unsigned long *) bg->bg_bitmap); if (ocfs2_is_cluster_bitmap(alloc_inode)) ocfs2_set_bit(bit_off + tmp, (unsigned long *) undo_bg->bg_bitmap); } le16_add_cpu(&bg->bg_free_bits_count, num_bits); status = ocfs2_journal_dirty(handle, group_bh); if (status < 0) mlog_errno(status);bail: return status;}/* * expects the suballoc inode to already be locked. */int ocfs2_free_suballoc_bits(handle_t *handle, struct inode *alloc_inode, struct buffer_head *alloc_bh, unsigned int start_bit, u64 bg_blkno, unsigned int count){ int status = 0; u32 tmp_used; struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb); struct ocfs2_dinode *fe = (struct ocfs2_dinode *) alloc_bh->b_data; struct ocfs2_chain_list *cl = &fe->id2.i_chain; struct buffer_head *group_bh = NULL; struct ocfs2_group_desc *group; mlog_entry_void(); if (!OCFS2_IS_VALID_DINODE(fe)) { OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe); status = -EIO; goto bail; } BUG_ON((count + start_bit) > ocfs2_bits_per_group(cl)); mlog(0, "%llu: freeing %u bits from group %llu, starting at %u\n", (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, count, (unsigned long long)bg_blkno, start_bit); status = ocfs2_read_block(osb, bg_blkno, &group_bh, OCFS2_BH_CACHED, alloc_inode); if (status < 0) { mlog_errno(status); goto bail; } group = (struct ocfs2_group_desc *) group_bh->b_data; status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, group); if (status) { mlog_errno(status); goto bail; } BUG_ON((count + start_bit) > le16_to_cpu(group->bg_bits)); status = ocfs2_block_group_clear_bits(handle, alloc_inode, group, group_bh, start_bit, count); if (status < 0) { mlog_errno(status); goto bail; } status = ocfs2_journal_access(handle, alloc_inode, alloc_bh, OCFS2_JOURNAL_ACCESS_WRITE); if (status < 0) { mlog_errno(status); goto bail; } le32_add_cpu(&cl->cl_recs[le16_to_cpu(group->bg_chain)].c_free, count); tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used); fe->id1.bitmap1.i_used = cpu_to_le32(tmp_used - count); status = ocfs2_journal_dirty(handle, alloc_bh); if (status < 0) { mlog_errno(status); goto bail; }bail: if (group_bh) brelse(group_bh); mlog_exit(status); return status;}int ocfs2_free_dinode(handle_t *handle, struct inode *inode_alloc_inode, struct buffer_head *inode_alloc_bh, struct ocfs2_dinode *di){ u64 blk = le64_to_cpu(di->i_blkno); u16 bit = le16_to_cpu(di->i_suballoc_bit); u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit); return ocfs2_free_suballoc_bits(handle, inode_alloc_inode, inode_alloc_bh, bit, bg_blkno, 1);}int ocfs2_free_clusters(handle_t *handle, struct inode *bitmap_inode, struct buffer_head *bitmap_bh, u64 start_blk, unsigned int num_clusters){ int status; u16 bg_start_bit; u64 bg_blkno; struct ocfs2_dinode *fe; /* You can't ever have a contiguous set of clusters * bigger than a block group bitmap so we never have to worry * about looping on them. */ mlog_entry_void(); /* This is expensive. We can safely remove once this stuff has * gotten tested really well. */ BUG_ON(start_blk != ocfs2_clusters_to_blocks(bitmap_inode->i_sb, ocfs2_blocks_to_clusters(bitmap_inode->i_sb, start_blk))); fe = (struct ocfs2_dinode *) bitmap_bh->b_data; ocfs2_block_to_cluster_group(bitmap_inode, start_blk, &bg_blkno, &bg_start_bit); mlog(0, "want to free %u clusters starting at block %llu\n", num_clusters, (unsigned long long)start_blk); mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n", (unsigned long long)bg_blkno, bg_start_bit); status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh, bg_start_bit, bg_blkno, num_clusters); if (status < 0) mlog_errno(status); mlog_exit(status); return status;}static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg){ printk("Block Group:\n"); printk("bg_signature: %s\n", bg->bg_signature); printk("bg_size: %u\n", bg->bg_size); printk("bg_bits: %u\n", bg->bg_bits); printk("bg_free_bits_count: %u\n", bg->bg_free_bits_count); printk("bg_chain: %u\n", bg->bg_chain); printk("bg_generation: %u\n", le32_to_cpu(bg->bg_generation)); printk("bg_next_group: %llu\n", (unsigned long long)bg->bg_next_group); printk("bg_parent_dinode: %llu\n", (unsigned long long)bg->bg_parent_dinode); printk("bg_blkno: %llu\n", (unsigned long long)bg->bg_blkno);}static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe){ int i; printk("Suballoc Inode %llu:\n", (unsigned long long)fe->i_blkno); printk("i_signature: %s\n", fe->i_signature); printk("i_size: %llu\n", (unsigned long long)fe->i_size); printk("i_clusters: %u\n", fe->i_clusters); printk("i_generation: %u\n", le32_to_cpu(fe->i_generation)); printk("id1.bitmap1.i_used: %u\n", le32_to_cpu(fe->id1.bitmap1.i_used)); printk("id1.bitmap1.i_total: %u\n", le32_to_cpu(fe->id1.bitmap1.i_total)); printk("id2.i_chain.cl_cpg: %u\n", fe->id2.i_chain.cl_cpg); printk("id2.i_chain.cl_bpc: %u\n", fe->id2.i_chain.cl_bpc); printk("id2.i_chain.cl_count: %u\n", fe->id2.i_chain.cl_count); printk("id2.i_chain.cl_next_free_rec: %u\n", fe->id2.i_chain.cl_next_free_rec); for(i = 0; i < fe->id2.i_chain.cl_next_free_rec; i++) { printk("fe->id2.i_chain.cl_recs[%d].c_free: %u\n", i, fe->id2.i_chain.cl_recs[i].c_free); printk("fe->id2.i_chain.cl_recs[%d].c_total: %u\n", i, fe->id2.i_chain.cl_recs[i].c_total); printk("fe->id2.i_chain.cl_recs[%d].c_blkno: %llu\n", i, (unsigned long long)fe->id2.i_chain.cl_recs[i].c_blkno); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -