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

📄 xfs_rtalloc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */#include "xfs.h"#include "xfs_fs.h"#include "xfs_types.h"#include "xfs_bit.h"#include "xfs_log.h"#include "xfs_inum.h"#include "xfs_trans.h"#include "xfs_sb.h"#include "xfs_ag.h"#include "xfs_dir2.h"#include "xfs_dmapi.h"#include "xfs_mount.h"#include "xfs_bmap_btree.h"#include "xfs_alloc_btree.h"#include "xfs_ialloc_btree.h"#include "xfs_dir2_sf.h"#include "xfs_attr_sf.h"#include "xfs_dinode.h"#include "xfs_inode.h"#include "xfs_btree.h"#include "xfs_ialloc.h"#include "xfs_alloc.h"#include "xfs_bmap.h"#include "xfs_rtalloc.h"#include "xfs_fsops.h"#include "xfs_error.h"#include "xfs_rw.h"#include "xfs_inode_item.h"#include "xfs_trans_space.h"/* * Prototypes for internal functions. */STATIC int xfs_rtallocate_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,		xfs_extlen_t, xfs_buf_t **, xfs_fsblock_t *);STATIC int xfs_rtany_summary(xfs_mount_t *, xfs_trans_t *, int, int,		xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, int *);STATIC int xfs_rtcheck_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,		xfs_extlen_t, int, xfs_rtblock_t *, int *);STATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,		xfs_rtblock_t, xfs_rtblock_t *);STATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,		xfs_rtblock_t, xfs_rtblock_t *);STATIC int xfs_rtget_summary( xfs_mount_t *, xfs_trans_t *, int,		xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, xfs_suminfo_t *);STATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,		xfs_extlen_t, int);STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int,		xfs_rtblock_t, int, xfs_buf_t **, xfs_fsblock_t *);/* * Internal functions. *//* * xfs_lowbit32: get low bit set out of 32-bit argument, -1 if none set. */STATIC intxfs_lowbit32(	__uint32_t	v){	if (v)		return ffs(v) - 1;	return -1;}/* * Allocate space to the bitmap or summary file, and zero it, for growfs. */STATIC int				/* error */xfs_growfs_rt_alloc(	xfs_mount_t	*mp,		/* file system mount point */	xfs_extlen_t	oblocks,	/* old count of blocks */	xfs_extlen_t	nblocks,	/* new count of blocks */	xfs_ino_t	ino)		/* inode number (bitmap/summary) */{	xfs_fileoff_t	bno;		/* block number in file */	xfs_buf_t	*bp;		/* temporary buffer for zeroing */	int		cancelflags;	/* flags for xfs_trans_cancel */	int		committed;	/* transaction committed flag */	xfs_daddr_t	d;		/* disk block address */	int		error;		/* error return value */	xfs_fsblock_t	firstblock;	/* first block allocated in xaction */	xfs_bmap_free_t	flist;		/* list of freed blocks */	xfs_fsblock_t	fsbno;		/* filesystem block for bno */	xfs_inode_t	*ip;		/* pointer to incore inode */	xfs_bmbt_irec_t	map;		/* block map output */	int		nmap;		/* number of block maps */	int		resblks;	/* space reservation */	xfs_trans_t	*tp;		/* transaction pointer */	/*	 * Allocate space to the file, as necessary.	 */	while (oblocks < nblocks) {		tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC);		resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);		cancelflags = 0;		/*		 * Reserve space & log for one extent added to the file.		 */		if ((error = xfs_trans_reserve(tp, resblks,				XFS_GROWRTALLOC_LOG_RES(mp), 0,				XFS_TRANS_PERM_LOG_RES,				XFS_DEFAULT_PERM_LOG_COUNT)))			goto error_exit;		cancelflags = XFS_TRANS_RELEASE_LOG_RES;		/*		 * Lock the inode.		 */		if ((error = xfs_trans_iget(mp, tp, ino, 0,						XFS_ILOCK_EXCL, &ip)))			goto error_exit;		XFS_BMAP_INIT(&flist, &firstblock);		/*		 * Allocate blocks to the bitmap file.		 */		nmap = 1;		cancelflags |= XFS_TRANS_ABORT;		error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks,			XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock,			resblks, &map, &nmap, &flist, NULL);		if (!error && nmap < 1)			error = XFS_ERROR(ENOSPC);		if (error)			goto error_exit;		/*		 * Free any blocks freed up in the transaction, then commit.		 */		error = xfs_bmap_finish(&tp, &flist, &committed);		if (error)			goto error_exit;		xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);		/*		 * Now we need to clear the allocated blocks.		 * Do this one block per transaction, to keep it simple.		 */		cancelflags = 0;		for (bno = map.br_startoff, fsbno = map.br_startblock;		     bno < map.br_startoff + map.br_blockcount;		     bno++, fsbno++) {			tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);			/*			 * Reserve log for one block zeroing.			 */			if ((error = xfs_trans_reserve(tp, 0,					XFS_GROWRTZERO_LOG_RES(mp), 0, 0, 0)))				goto error_exit;			/*			 * Lock the bitmap inode.			 */			if ((error = xfs_trans_iget(mp, tp, ino, 0,							XFS_ILOCK_EXCL, &ip)))				goto error_exit;			/*			 * Get a buffer for the block.			 */			d = XFS_FSB_TO_DADDR(mp, fsbno);			bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,				mp->m_bsize, 0);			if (bp == NULL) {				error = XFS_ERROR(EIO);				goto error_exit;			}			memset(XFS_BUF_PTR(bp), 0, mp->m_sb.sb_blocksize);			xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);			/*			 * Commit the transaction.			 */			xfs_trans_commit(tp, 0);		}		/*		 * Go on to the next extent, if any.		 */		oblocks = map.br_startoff + map.br_blockcount;	}	return 0;error_exit:	xfs_trans_cancel(tp, cancelflags);	return error;}/* * Attempt to allocate an extent minlen<=len<=maxlen starting from * bitmap block bbno.  If we don't get maxlen then use prod to trim * the length, if given.  Returns error; returns starting block in *rtblock. * The lengths are all in rtextents. */STATIC int				/* error */xfs_rtallocate_extent_block(	xfs_mount_t	*mp,		/* file system mount point */	xfs_trans_t	*tp,		/* transaction pointer */	xfs_rtblock_t	bbno,		/* bitmap block number */	xfs_extlen_t	minlen,		/* minimum length to allocate */	xfs_extlen_t	maxlen,		/* maximum length to allocate */	xfs_extlen_t	*len,		/* out: actual length allocated */	xfs_rtblock_t	*nextp,		/* out: next block to try */	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */	xfs_fsblock_t	*rsb,		/* in/out: summary block number */	xfs_extlen_t	prod,		/* extent product factor */	xfs_rtblock_t	*rtblock)	/* out: start block allocated */{	xfs_rtblock_t	besti;		/* best rtblock found so far */	xfs_rtblock_t	bestlen;	/* best length found so far */	xfs_rtblock_t	end;		/* last rtblock in chunk */	int		error;		/* error value */	xfs_rtblock_t	i;		/* current rtblock trying */	xfs_rtblock_t	next;		/* next rtblock to try */	int		stat;		/* status from internal calls */	/*	 * Loop over all the extents starting in this bitmap block,	 * looking for one that's long enough.	 */	for (i = XFS_BLOCKTOBIT(mp, bbno), besti = -1, bestlen = 0,		end = XFS_BLOCKTOBIT(mp, bbno + 1) - 1;	     i <= end;	     i++) {		/*		 * See if there's a free extent of maxlen starting at i.		 * If it's not so then next will contain the first non-free.		 */		error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, &next, &stat);		if (error) {			return error;		}		if (stat) {			/*			 * i for maxlen is all free, allocate and return that.			 */			error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp,				rsb);			if (error) {				return error;			}			*len = maxlen;			*rtblock = i;			return 0;		}		/*		 * In the case where we have a variable-sized allocation		 * request, figure out how big this free piece is,		 * and if it's big enough for the minimum, and the best		 * so far, remember it.		 */		if (minlen < maxlen) {			xfs_rtblock_t	thislen;	/* this extent size */			thislen = next - i;			if (thislen >= minlen && thislen > bestlen) {				besti = i;				bestlen = thislen;			}		}		/*		 * If not done yet, find the start of the next free space.		 */		if (next < end) {			error = xfs_rtfind_forw(mp, tp, next, end, &i);			if (error) {				return error;			}		} else			break;	}	/*	 * Searched the whole thing & didn't find a maxlen free extent.	 */	if (minlen < maxlen && besti != -1) {		xfs_extlen_t	p;	/* amount to trim length by */		/*		 * If size should be a multiple of prod, make that so.		 */		if (prod > 1 && (p = do_mod(bestlen, prod)))			bestlen -= p;		/*		 * Allocate besti for bestlen & return that.		 */		error = xfs_rtallocate_range(mp, tp, besti, bestlen, rbpp, rsb);		if (error) {			return error;		}		*len = bestlen;		*rtblock = besti;		return 0;	}	/*	 * Allocation failed.  Set *nextp to the next block to try.	 */	*nextp = next;	*rtblock = NULLRTBLOCK;	return 0;}/* * Allocate an extent of length minlen<=len<=maxlen, starting at block * bno.  If we don't get maxlen then use prod to trim the length, if given. * Returns error; returns starting block in *rtblock. * The lengths are all in rtextents. */STATIC int				/* error */xfs_rtallocate_extent_exact(	xfs_mount_t	*mp,		/* file system mount point */	xfs_trans_t	*tp,		/* transaction pointer */	xfs_rtblock_t	bno,		/* starting block number to allocate */	xfs_extlen_t	minlen,		/* minimum length to allocate */	xfs_extlen_t	maxlen,		/* maximum length to allocate */	xfs_extlen_t	*len,		/* out: actual length allocated */	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */	xfs_fsblock_t	*rsb,		/* in/out: summary block number */	xfs_extlen_t	prod,		/* extent product factor */	xfs_rtblock_t	*rtblock)	/* out: start block allocated */{	int		error;		/* error value */	xfs_extlen_t	i;		/* extent length trimmed due to prod */	int		isfree;		/* extent is free */	xfs_rtblock_t	next;		/* next block to try (dummy) */	ASSERT(minlen % prod == 0 && maxlen % prod == 0);	/*	 * Check if the range in question (for maxlen) is free.	 */	error = xfs_rtcheck_range(mp, tp, bno, maxlen, 1, &next, &isfree);	if (error) {		return error;	}	if (isfree) {		/*		 * If it is, allocate it and return success.		 */		error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);		if (error) {			return error;		}		*len = maxlen;		*rtblock = bno;		return 0;	}	/*	 * If not, allocate what there is, if it's at least minlen.	 */	maxlen = next - bno;	if (maxlen < minlen) {		/*		 * Failed, return failure status.		 */		*rtblock = NULLRTBLOCK;		return 0;	}	/*	 * Trim off tail of extent, if prod is specified.	 */	if (prod > 1 && (i = maxlen % prod)) {		maxlen -= i;		if (maxlen < minlen) {			/*			 * Now we can't do it, return failure status.			 */			*rtblock = NULLRTBLOCK;			return 0;		}	}	/*	 * Allocate what we can and return it.	 */	error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);	if (error) {		return error;	}	*len = maxlen;	*rtblock = bno;	return 0;}/* * Allocate an extent of length minlen<=len<=maxlen, starting as near * to bno as possible.  If we don't get maxlen then use prod to trim * the length, if given.  The lengths are all in rtextents. */STATIC int				/* error */xfs_rtallocate_extent_near(	xfs_mount_t	*mp,		/* file system mount point */	xfs_trans_t	*tp,		/* transaction pointer */	xfs_rtblock_t	bno,		/* starting block number to allocate */	xfs_extlen_t	minlen,		/* minimum length to allocate */	xfs_extlen_t	maxlen,		/* maximum length to allocate */	xfs_extlen_t	*len,		/* out: actual length allocated */	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */	xfs_fsblock_t	*rsb,		/* in/out: summary block number */	xfs_extlen_t	prod,		/* extent product factor */	xfs_rtblock_t	*rtblock)	/* out: start block allocated */{	int		any;		/* any useful extents from summary */	xfs_rtblock_t	bbno;		/* bitmap block number */	int		error;		/* error value */	int		i;		/* bitmap block offset (loop control) */	int		j;		/* secondary loop control */	int		log2len;	/* log2 of minlen */	xfs_rtblock_t	n;		/* next block to try */	xfs_rtblock_t	r;		/* result block */	ASSERT(minlen % prod == 0 && maxlen % prod == 0);	/*	 * If the block number given is off the end, silently set it to	 * the last block.	 */	if (bno >= mp->m_sb.sb_rextents)		bno = mp->m_sb.sb_rextents - 1;	/*	 * Try the exact allocation first.	 */	error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen, len,		rbpp, rsb, prod, &r);	if (error) {		return error;	}	/*	 * If the exact allocation worked, return that.	 */	if (r != NULLRTBLOCK) {		*rtblock = r;		return 0;	}	bbno = XFS_BITTOBLOCK(mp, bno);	i = 0;	log2len = xfs_highbit32(minlen);	/*	 * Loop over all bitmap blocks (bbno + i is current block).	 */	for (;;) {		/*		 * Get summary information of extents of all useful levels		 * starting in this bitmap block.		 */		error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1,			bbno + i, rbpp, rsb, &any);		if (error) {			return error;		}		/*		 * If there are any useful extents starting here, try		 * allocating one.		 */		if (any) {			/*			 * On the positive side of the starting location.			 */

⌨️ 快捷键说明

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