⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alloc.c

📁 ocfs1.2.7 源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* -*- mode: c; c-basic-offset: 8; -*- * vim: noexpandtab sw=8 ts=8 sts=0: * * alloc.c * * Extent allocs and frees * * 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>#define MLOG_MASK_PREFIX ML_DISK_ALLOC#include <cluster/masklog.h>#include "ocfs2.h"#include "alloc.h"#include "dlmglue.h"#include "extent_map.h"#include "inode.h"#include "journal.h"#include "localalloc.h"#include "suballoc.h"#include "sysfile.h"#include "file.h"#include "super.h"#include "uptodate.h"#include "buffer_head_io.h"static int ocfs2_extent_contig(struct inode *inode,			       struct ocfs2_extent_rec *ext,			       u64 blkno);static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,				     struct ocfs2_journal_handle *handle,				     struct inode *inode,				     int wanted,				     struct ocfs2_alloc_context *meta_ac,				     struct buffer_head *bhs[]);static int ocfs2_add_branch(struct ocfs2_super *osb,			    struct ocfs2_journal_handle *handle,			    struct inode *inode,			    struct buffer_head *fe_bh,			    struct buffer_head *eb_bh,			    struct buffer_head *last_eb_bh,			    struct ocfs2_alloc_context *meta_ac);static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,				  struct ocfs2_journal_handle *handle,				  struct inode *inode,				  struct buffer_head *fe_bh,				  struct ocfs2_alloc_context *meta_ac,				  struct buffer_head **ret_new_eb_bh);static int ocfs2_do_insert_extent(struct ocfs2_super *osb,				  struct ocfs2_journal_handle *handle,				  struct inode *inode,				  struct buffer_head *fe_bh,				  u64 blkno,				  u32 new_clusters);static int ocfs2_find_branch_target(struct ocfs2_super *osb,				    struct inode *inode,				    struct buffer_head *fe_bh,				    struct buffer_head **target_bh);static int ocfs2_find_new_last_ext_blk(struct ocfs2_super *osb,				       struct inode *inode,				       struct ocfs2_dinode *fe,				       unsigned int new_i_clusters,				       struct buffer_head *old_last_eb,				       struct buffer_head **new_last_eb);static int ocfs2_extent_contig(struct inode *inode,			       struct ocfs2_extent_rec *ext,			       u64 blkno){	return blkno == (le64_to_cpu(ext->e_blkno) +			 ocfs2_clusters_to_blocks(inode->i_sb,						  le32_to_cpu(ext->e_clusters)));}/* * How many free extents have we got before we need more meta data? */int ocfs2_num_free_extents(struct ocfs2_super *osb,			   struct inode *inode,			   struct ocfs2_dinode *fe){	int retval;	struct ocfs2_extent_list *el;	struct ocfs2_extent_block *eb;	struct buffer_head *eb_bh = NULL;	mlog_entry_void();	if (!OCFS2_IS_VALID_DINODE(fe)) {		OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);		retval = -EIO;		goto bail;	}	if (fe->i_last_eb_blk) {		retval = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),					  &eb_bh, OCFS2_BH_CACHED, inode);		if (retval < 0) {			mlog_errno(retval);			goto bail;		}		eb = (struct ocfs2_extent_block *) eb_bh->b_data;		el = &eb->h_list;	} else		el = &fe->id2.i_list;	BUG_ON(el->l_tree_depth != 0);	retval = le16_to_cpu(el->l_count) - le16_to_cpu(el->l_next_free_rec);bail:	if (eb_bh)		brelse(eb_bh);	mlog_exit(retval);	return retval;}/* expects array to already be allocated * * sets h_signature, h_blkno, h_suballoc_bit, h_suballoc_slot, and * l_count for you */static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,				     struct ocfs2_journal_handle *handle,				     struct inode *inode,				     int wanted,				     struct ocfs2_alloc_context *meta_ac,				     struct buffer_head *bhs[]){	int count, status, i;	u16 suballoc_bit_start;	u32 num_got;	u64 first_blkno;	struct ocfs2_extent_block *eb;	mlog_entry_void();	count = 0;	while (count < wanted) {		status = ocfs2_claim_metadata(osb,					      handle,					      meta_ac,					      wanted - count,					      &suballoc_bit_start,					      &num_got,					      &first_blkno);		if (status < 0) {			mlog_errno(status);			goto bail;		}		for(i = count;  i < (num_got + count); i++) {			bhs[i] = sb_getblk(osb->sb, first_blkno);			if (bhs[i] == NULL) {				status = -EIO;				mlog_errno(status);				goto bail;			}			ocfs2_set_new_buffer_uptodate(inode, bhs[i]);			status = ocfs2_journal_access(handle, inode, bhs[i],						      OCFS2_JOURNAL_ACCESS_CREATE);			if (status < 0) {				mlog_errno(status);				goto bail;			}			memset(bhs[i]->b_data, 0, osb->sb->s_blocksize);			eb = (struct ocfs2_extent_block *) bhs[i]->b_data;			/* Ok, setup the minimal stuff here. */			strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);			eb->h_blkno = cpu_to_le64(first_blkno);			eb->h_fs_generation = cpu_to_le32(osb->fs_generation);#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS			/* we always use slot zero's suballocator */			eb->h_suballoc_slot = 0;#else			eb->h_suballoc_slot = cpu_to_le16(osb->slot_num);#endif			eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);			eb->h_list.l_count =				cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));			suballoc_bit_start++;			first_blkno++;			/* We'll also be dirtied by the caller, so			 * this isn't absolutely necessary. */			status = ocfs2_journal_dirty(handle, bhs[i]);			if (status < 0) {				mlog_errno(status);				goto bail;			}		}		count += num_got;	}	status = 0;bail:	if (status < 0) {		for(i = 0; i < wanted; i++) {			if (bhs[i])				brelse(bhs[i]);			bhs[i] = NULL;		}	}	mlog_exit(status);	return status;}/* * Add an entire tree branch to our inode. eb_bh is the extent block * to start at, if we don't want to start the branch at the dinode * structure. * * last_eb_bh is required as we have to update it's next_leaf pointer * for the new last extent block. * * the new branch will be 'empty' in the sense that every block will * contain a single record with e_clusters == 0. */static int ocfs2_add_branch(struct ocfs2_super *osb,			    struct ocfs2_journal_handle *handle,			    struct inode *inode,			    struct buffer_head *fe_bh,			    struct buffer_head *eb_bh,			    struct buffer_head *last_eb_bh,			    struct ocfs2_alloc_context *meta_ac){	int status, new_blocks, i;	u64 next_blkno, new_last_eb_blk;	struct buffer_head *bh;	struct buffer_head **new_eb_bhs = NULL;	struct ocfs2_dinode *fe;	struct ocfs2_extent_block *eb;	struct ocfs2_extent_list  *eb_el;	struct ocfs2_extent_list  *el;	mlog_entry_void();	BUG_ON(!last_eb_bh);	fe = (struct ocfs2_dinode *) fe_bh->b_data;	if (eb_bh) {		eb = (struct ocfs2_extent_block *) eb_bh->b_data;		el = &eb->h_list;	} else		el = &fe->id2.i_list;	/* we never add a branch to a leaf. */	BUG_ON(!el->l_tree_depth);	new_blocks = le16_to_cpu(el->l_tree_depth);	/* allocate the number of new eb blocks we need */	new_eb_bhs = kcalloc(new_blocks, sizeof(struct buffer_head *),			     GFP_KERNEL);	if (!new_eb_bhs) {		status = -ENOMEM;		mlog_errno(status);		goto bail;	}	status = ocfs2_create_new_meta_bhs(osb, handle, inode, new_blocks,					   meta_ac, new_eb_bhs);	if (status < 0) {		mlog_errno(status);		goto bail;	}	/* Note: new_eb_bhs[new_blocks - 1] is the guy which will be	 * linked with the rest of the tree.	 * conversly, new_eb_bhs[0] is the new bottommost leaf.	 *	 * when we leave the loop, new_last_eb_blk will point to the	 * newest leaf, and next_blkno will point to the topmost extent	 * block. */	next_blkno = new_last_eb_blk = 0;	for(i = 0; i < new_blocks; i++) {		bh = new_eb_bhs[i];		eb = (struct ocfs2_extent_block *) bh->b_data;		if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {			OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);			status = -EIO;			goto bail;		}		eb_el = &eb->h_list;		status = ocfs2_journal_access(handle, inode, bh,					      OCFS2_JOURNAL_ACCESS_CREATE);		if (status < 0) {			mlog_errno(status);			goto bail;		}		eb->h_next_leaf_blk = 0;		eb_el->l_tree_depth = cpu_to_le16(i);		eb_el->l_next_free_rec = cpu_to_le16(1);		eb_el->l_recs[0].e_cpos = fe->i_clusters;		eb_el->l_recs[0].e_blkno = cpu_to_le64(next_blkno);		eb_el->l_recs[0].e_clusters = cpu_to_le32(0);		if (!eb_el->l_tree_depth)			new_last_eb_blk = le64_to_cpu(eb->h_blkno);		status = ocfs2_journal_dirty(handle, bh);		if (status < 0) {			mlog_errno(status);			goto bail;		}		next_blkno = le64_to_cpu(eb->h_blkno);	}	/* This is a bit hairy. We want to update up to three blocks	 * here without leaving any of them in an inconsistent state	 * in case of error. We don't have to worry about	 * journal_dirty erroring as it won't unless we've aborted the	 * handle (in which case we would never be here) so reserving	 * the write with journal_access is all we need to do. */	status = ocfs2_journal_access(handle, inode, last_eb_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto bail;	}	status = ocfs2_journal_access(handle, inode, fe_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto bail;	}	if (eb_bh) {		status = ocfs2_journal_access(handle, inode, eb_bh,					      OCFS2_JOURNAL_ACCESS_WRITE);		if (status < 0) {			mlog_errno(status);			goto bail;		}	}	/* Link the new branch into the rest of the tree (el will	 * either be on the fe, or the extent block passed in. */	i = le16_to_cpu(el->l_next_free_rec);	el->l_recs[i].e_blkno = cpu_to_le64(next_blkno);	el->l_recs[i].e_cpos = fe->i_clusters;	el->l_recs[i].e_clusters = 0;	le16_add_cpu(&el->l_next_free_rec, 1);	/* fe needs a new last extent block pointer, as does the	 * next_leaf on the previously last-extent-block. */	fe->i_last_eb_blk = cpu_to_le64(new_last_eb_blk);	eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;	eb->h_next_leaf_blk = cpu_to_le64(new_last_eb_blk);	status = ocfs2_journal_dirty(handle, last_eb_bh);	if (status < 0)		mlog_errno(status);	status = ocfs2_journal_dirty(handle, fe_bh);	if (status < 0)		mlog_errno(status);	if (eb_bh) {		status = ocfs2_journal_dirty(handle, eb_bh);		if (status < 0)			mlog_errno(status);	}	status = 0;bail:	if (new_eb_bhs) {		for (i = 0; i < new_blocks; i++)			if (new_eb_bhs[i])				brelse(new_eb_bhs[i]);		kfree(new_eb_bhs);	}	mlog_exit(status);	return status;}/* * adds another level to the allocation tree. * returns back the new extent block so you can add a branch to it * after this call. */static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,				  struct ocfs2_journal_handle *handle,				  struct inode *inode,				  struct buffer_head *fe_bh,				  struct ocfs2_alloc_context *meta_ac,				  struct buffer_head **ret_new_eb_bh){	int status, i;	struct buffer_head *new_eb_bh = NULL;	struct ocfs2_dinode *fe;	struct ocfs2_extent_block *eb;	struct ocfs2_extent_list  *fe_el;	struct ocfs2_extent_list  *eb_el;	mlog_entry_void();	status = ocfs2_create_new_meta_bhs(osb, handle, inode, 1, meta_ac,					   &new_eb_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	eb = (struct ocfs2_extent_block *) new_eb_bh->b_data;	if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {		OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);		status = -EIO;		goto bail;	}	eb_el = &eb->h_list;	fe = (struct ocfs2_dinode *) fe_bh->b_data;	fe_el = &fe->id2.i_list;	status = ocfs2_journal_access(handle, inode, new_eb_bh,				      OCFS2_JOURNAL_ACCESS_CREATE);	if (status < 0) {		mlog_errno(status);		goto bail;	}	/* copy the fe data into the new extent block */	eb_el->l_tree_depth = fe_el->l_tree_depth;	eb_el->l_next_free_rec = fe_el->l_next_free_rec;	for(i = 0; i < le16_to_cpu(fe_el->l_next_free_rec); i++) {		eb_el->l_recs[i].e_cpos = fe_el->l_recs[i].e_cpos;		eb_el->l_recs[i].e_clusters = fe_el->l_recs[i].e_clusters;		eb_el->l_recs[i].e_blkno = fe_el->l_recs[i].e_blkno;	}	status = ocfs2_journal_dirty(handle, new_eb_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	status = ocfs2_journal_access(handle, inode, fe_bh,				      OCFS2_JOURNAL_ACCESS_WRITE);	if (status < 0) {		mlog_errno(status);		goto bail;	}	/* update fe now */	le16_add_cpu(&fe_el->l_tree_depth, 1);	fe_el->l_recs[0].e_cpos = 0;	fe_el->l_recs[0].e_blkno = eb->h_blkno;	fe_el->l_recs[0].e_clusters = fe->i_clusters;	for(i = 1; i < le16_to_cpu(fe_el->l_next_free_rec); i++) {		fe_el->l_recs[i].e_cpos = 0;		fe_el->l_recs[i].e_clusters = 0;		fe_el->l_recs[i].e_blkno = 0;	}	fe_el->l_next_free_rec = cpu_to_le16(1);	/* If this is our 1st tree depth shift, then last_eb_blk	 * becomes the allocated extent block */	if (fe_el->l_tree_depth == cpu_to_le16(1))		fe->i_last_eb_blk = eb->h_blkno;	status = ocfs2_journal_dirty(handle, fe_bh);	if (status < 0) {		mlog_errno(status);		goto bail;	}	*ret_new_eb_bh = new_eb_bh;	new_eb_bh = NULL;	status = 0;bail:	if (new_eb_bh)		brelse(new_eb_bh);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -