📄 suballoc.c
字号:
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 " "# %"MLFu64, 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;}int ocfs2_reserve_new_metadata(struct ocfs2_super *osb, struct ocfs2_journal_handle *handle, struct ocfs2_dinode *fe, struct ocfs2_alloc_context **ac){ int status; struct inode *alloc_inode = NULL; *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { status = -ENOMEM; mlog_errno(status); goto bail; } (*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe); (*ac)->ac_handle = handle; (*ac)->ac_which = OCFS2_AC_USE_META;#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, 0);#else alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, osb->slot_num);#endif if (!alloc_inode) { status = -ENOMEM; mlog_errno(status); goto bail; } (*ac)->ac_inode = igrab(alloc_inode); (*ac)->ac_group_search = ocfs2_block_group_search; status = ocfs2_reserve_suballoc_bits(osb, (*ac)); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } status = 0;bail: if ((status < 0) && *ac) { ocfs2_free_alloc_context(*ac); *ac = NULL; } if (alloc_inode) iput(alloc_inode); mlog_exit(status); return status;}int ocfs2_reserve_new_inode(struct ocfs2_super *osb, struct ocfs2_journal_handle *handle, struct ocfs2_alloc_context **ac){ int status; struct inode *alloc_inode = NULL; *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { status = -ENOMEM; mlog_errno(status); goto bail; } (*ac)->ac_bits_wanted = 1; (*ac)->ac_handle = handle; (*ac)->ac_which = OCFS2_AC_USE_INODE; alloc_inode = ocfs2_get_system_file_inode(osb, INODE_ALLOC_SYSTEM_INODE, osb->slot_num); if (!alloc_inode) { status = -ENOMEM; mlog_errno(status); goto bail; } (*ac)->ac_inode = igrab(alloc_inode); (*ac)->ac_group_search = ocfs2_block_group_search; status = ocfs2_reserve_suballoc_bits(osb, *ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } status = 0;bail: if ((status < 0) && *ac) { ocfs2_free_alloc_context(*ac); *ac = NULL; } if (alloc_inode) iput(alloc_inode); mlog_exit(status); return status;}/* local alloc code has to do the same thing, so rather than do this * twice.. */int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac){ int status; ac->ac_inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, OCFS2_INVALID_SLOT); if (!ac->ac_inode) { status = -EINVAL; mlog(ML_ERROR, "Could not get bitmap inode!\n"); goto bail; } ac->ac_which = OCFS2_AC_USE_MAIN; ac->ac_group_search = ocfs2_cluster_group_search; status = ocfs2_reserve_suballoc_bits(osb, ac); if (status < 0 && status != -ENOSPC) mlog_errno(status);bail: return status;}/* 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, struct ocfs2_journal_handle *handle, u32 bits_wanted, struct ocfs2_alloc_context **ac){ int status; mlog_entry_void(); BUG_ON(!handle); *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { status = -ENOMEM; mlog_errno(status); goto bail; } (*ac)->ac_bits_wanted = bits_wanted; (*ac)->ac_handle = handle; status = -ENOSPC; if (ocfs2_alloc_should_use_local(osb, bits_wanted)) { status = ocfs2_reserve_local_alloc_bits(osb, handle, bits_wanted, *ac); if ((status < 0) && (status != -ENOSPC)) { mlog_errno(status); goto bail; } else if (status == -ENOSPC) { /* reserve_local_bits will return enospc with * the local alloc inode still locked, so we * can change this safely here. */ mlog(0, "Disabling local alloc\n"); /* We set to OCFS2_LA_DISABLED so that umount * can clean up what's left of the local * allocation */ osb->local_alloc_state = OCFS2_LA_DISABLED; } } if (status == -ENOSPC) { status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } } status = 0;bail: if ((status < 0) && *ac) { ocfs2_free_alloc_context(*ac); *ac = NULL; } mlog_exit(status); return status;}/* * More or less lifted from ext3. I'll leave their description below: * * "For ext3 allocations, we must not reuse any blocks which are * allocated in the bitmap buffer's "last committed data" copy. This * prevents deletes from freeing up the page for reuse until we have * committed the delete transaction. * * If we didn't do this, then deleting something and reallocating it as * data would allow the old block to be overwritten before the * transaction committed (because we force data to disk before commit). * This would lead to corruption if we crashed between overwriting the * data and committing the delete. * * @@@ We may want to make this allocation behaviour conditional on * data-writes at some point, and disable it for metadata allocations or * sync-data inodes." * * Note: OCFS2 already does this differently for metadata vs data * allocations, as those bitmaps are seperate and undo access is never * called on a metadata group descriptor. */static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, int nr){ struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap)) return 0; if (!buffer_jbd(bg_bh) || !bh2jh(bg_bh)->b_committed_data) return 1; bg = (struct ocfs2_group_desc *) bh2jh(bg_bh)->b_committed_data; return !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap);}static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, struct buffer_head *bg_bh, unsigned int bits_wanted, unsigned int total_bits, u16 *bit_off, u16 *bits_found){ void *bitmap; u16 best_offset, best_size; int offset, start, found, status = 0; struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; if (!OCFS2_IS_VALID_GROUP_DESC(bg)) { OCFS2_RO_ON_INVALID_GROUP_DESC(osb->sb, bg); return -EIO; } found = start = best_offset = best_size = 0; bitmap = bg->bg_bitmap; while((offset = ocfs2_find_next_zero_bit(bitmap, total_bits, start)) != -1) { if (offset == total_bits) break; if (!ocfs2_test_bg_bit_allocatable(bg_bh, offset)) { /* We found a zero, but we can't use it as it * hasn't been put to disk yet! */ found = 0; start = offset + 1; } else if (offset == start) { /* we found a zero */ found++; /* move start to the next bit to test */ start++; } else { /* got a zero after some ones */ found = 1; start = offset + 1; } if (found > best_size) { best_size = found; best_offset = start - found; } /* we got everything we needed */ if (found == bits_wanted) { /* mlog(0, "Found it all!\n"); */ break; } } /* XXX: I think the first clause is equivalent to the second * - jlbec */ if (found == bits_wanted) { *bit_off = start - found; *bits_found = found; } else if (best_size) { *bit_off = best_offset; *bits_found = best_size; } else { status = -ENOSPC; /* No error log here -- see the comment above * ocfs2_test_bg_bit_allocatable */ } return status;}static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *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; void *bitmap = bg->bg_bitmap; int journal_type = OCFS2_JOURNAL_ACCESS_WRITE; 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; } BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits); mlog(0, "block_group_set_bits: 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; } le16_add_cpu(&bg->bg_free_bits_count, -num_bits); while(num_bits--) ocfs2_set_bit(bit_off++, bitmap); status = ocfs2_journal_dirty(handle, group_bh); if (status < 0) { mlog_errno(status); goto bail; }bail: mlog_exit(status); return status;}/* find the one with the most empty bits */static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl){ u16 curr, best; BUG_ON(!cl->cl_next_free_rec); best = curr = 0; while (curr < le16_to_cpu(cl->cl_next_free_rec)) { if (le32_to_cpu(cl->cl_recs[curr].c_free) > le32_to_cpu(cl->cl_recs[best].c_free)) best = curr; curr++; } BUG_ON(best >= le16_to_cpu(cl->cl_next_free_rec)); return best;}static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle, struct inode *alloc_inode, struct buffer_head *fe_bh, struct buffer_head *bg_bh, struct buffer_head *prev_bg_bh, u16 chain){ int status; /* there is a really tiny chance the journal calls could fail, * but we wouldn't want inconsistent blocks in *any* case. */ u64 fe_ptr, bg_ptr, prev_bg_ptr; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -