📄 xfs_bmap.c
字号:
/* * Copyright (c) 2000-2006 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_da_btree.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_dmapi.h"#include "xfs_mount.h"#include "xfs_ialloc.h"#include "xfs_itable.h"#include "xfs_dir2_data.h"#include "xfs_dir2_leaf.h"#include "xfs_dir2_block.h"#include "xfs_inode_item.h"#include "xfs_extfree_item.h"#include "xfs_alloc.h"#include "xfs_bmap.h"#include "xfs_rtalloc.h"#include "xfs_error.h"#include "xfs_attr_leaf.h"#include "xfs_rw.h"#include "xfs_quota.h"#include "xfs_trans_space.h"#include "xfs_buf_item.h"#include "xfs_filestream.h"#include "xfs_vnodeops.h"#ifdef DEBUGSTATIC voidxfs_bmap_check_leaf_extents(xfs_btree_cur_t *cur, xfs_inode_t *ip, int whichfork);#endifkmem_zone_t *xfs_bmap_free_item_zone;/* * Prototypes for internal bmap routines. *//* * Called from xfs_bmap_add_attrfork to handle extents format files. */STATIC int /* error */xfs_bmap_add_attrfork_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ xfs_bmap_free_t *flist, /* blocks to free at commit */ int *flags); /* inode logging flags *//* * Called from xfs_bmap_add_attrfork to handle local format files. */STATIC int /* error */xfs_bmap_add_attrfork_local( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ xfs_bmap_free_t *flist, /* blocks to free at commit */ int *flags); /* inode logging flags *//* * Called by xfs_bmapi to update file extent records and the btree * after allocating space (or doing a delayed allocation). */STATIC int /* error */xfs_bmap_add_extent( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ int *logflagsp, /* inode logging flags */ xfs_extdelta_t *delta, /* Change made to incore extents */ int whichfork, /* data or attr fork */ int rsvd); /* OK to allocate reserved blocks *//* * Called by xfs_bmap_add_extent to handle cases converting a delayed * allocation to a real allocation. */STATIC int /* error */xfs_bmap_add_extent_delay_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_filblks_t *dnew, /* new delayed-alloc indirect blocks */ xfs_fsblock_t *first, /* pointer to firstblock variable */ xfs_bmap_free_t *flist, /* list of extents to be freed */ int *logflagsp, /* inode logging flags */ xfs_extdelta_t *delta, /* Change made to incore extents */ int rsvd); /* OK to allocate reserved blocks *//* * Called by xfs_bmap_add_extent to handle cases converting a hole * to a delayed allocation. */STATIC int /* error */xfs_bmap_add_extent_hole_delay( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp,/* inode logging flags */ xfs_extdelta_t *delta, /* Change made to incore extents */ int rsvd); /* OK to allocate reserved blocks *//* * Called by xfs_bmap_add_extent to handle cases converting a hole * to a real allocation. */STATIC int /* error */xfs_bmap_add_extent_hole_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ xfs_extdelta_t *delta, /* Change made to incore extents */ int whichfork); /* data or attr fork *//* * Called by xfs_bmap_add_extent to handle cases converting an unwritten * allocation to a real allocation or vice versa. */STATIC int /* error */xfs_bmap_add_extent_unwritten_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp, /* inode logging flags */ xfs_extdelta_t *delta); /* Change made to incore extents *//* * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. * It figures out where to ask the underlying allocator to put the new extent. */STATIC int /* error */xfs_bmap_alloc( xfs_bmalloca_t *ap); /* bmap alloc argument struct *//* * Transform a btree format file with only one leaf node, where the * extents list will fit in the inode, into an extents format file. * Since the file extents are already in-core, all we have to do is * give up the space for the btree root and pitch the leaf block. */STATIC int /* error */xfs_bmap_btree_to_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_btree_cur_t *cur, /* btree cursor */ int *logflagsp, /* inode logging flags */ int whichfork); /* data or attr fork *//* * Called by xfs_bmapi to update file extent records and the btree * after removing space (or undoing a delayed allocation). */STATIC int /* error */xfs_bmap_del_extent( xfs_inode_t *ip, /* incore inode pointer */ xfs_trans_t *tp, /* current trans pointer */ xfs_extnum_t idx, /* extent number to update/insert */ xfs_bmap_free_t *flist, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ int *logflagsp,/* inode logging flags */ xfs_extdelta_t *delta, /* Change made to incore extents */ int whichfork, /* data or attr fork */ int rsvd); /* OK to allocate reserved blocks *//* * Remove the entry "free" from the free item list. Prev points to the * previous entry, unless "free" is the head of the list. */STATIC voidxfs_bmap_del_free( xfs_bmap_free_t *flist, /* free item list header */ xfs_bmap_free_item_t *prev, /* previous item on list, if any */ xfs_bmap_free_item_t *free); /* list item to be freed *//* * Convert an extents-format file into a btree-format file. * The new file will have a root block (in the inode) and a single child block. */STATIC int /* error */xfs_bmap_extents_to_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first-block-allocated */ xfs_bmap_free_t *flist, /* blocks freed in xaction */ xfs_btree_cur_t **curp, /* cursor returned to caller */ int wasdel, /* converting a delayed alloc */ int *logflagsp, /* inode logging flags */ int whichfork); /* data or attr fork *//* * Convert a local file to an extents file. * This code is sort of bogus, since the file data needs to get * logged so it won't be lost. The bmap-level manipulations are ok, though. */STATIC int /* error */xfs_bmap_local_to_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated in xaction */ xfs_extlen_t total, /* total blocks needed by transaction */ int *logflagsp, /* inode logging flags */ int whichfork); /* data or attr fork *//* * Search the extents list for the inode, for the extent containing bno. * If bno lies in a hole, point to the next entry. If bno lies past eof, * *eofp will be set, and *prevp will contain the last entry (null if none). * Else, *lastxp will be set to the index of the found * entry; *gotp will contain the entry. */STATIC xfs_bmbt_rec_host_t * /* pointer to found extent entry */xfs_bmap_search_extents( xfs_inode_t *ip, /* incore inode pointer */ xfs_fileoff_t bno, /* block number searched for */ int whichfork, /* data or attr fork */ int *eofp, /* out: end of file found */ xfs_extnum_t *lastxp, /* out: last extent index */ xfs_bmbt_irec_t *gotp, /* out: extent entry found */ xfs_bmbt_irec_t *prevp); /* out: previous extent entry found *//* * Check the last inode extent to determine whether this allocation will result * in blocks being allocated at the end of the file. When we allocate new data * blocks at the end of the file which do not start at the previous data block, * we will try to align the new blocks at stripe unit boundaries. */STATIC int /* error */xfs_bmap_isaeof( xfs_inode_t *ip, /* incore inode pointer */ xfs_fileoff_t off, /* file offset in fsblocks */ int whichfork, /* data or attribute fork */ char *aeof); /* return value */#ifdef XFS_BMAP_TRACE/* * Add bmap trace entry prior to a call to xfs_iext_remove. */STATIC voidxfs_bmap_trace_delete( const char *fname, /* function name */ char *desc, /* operation description */ xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* index of entry(entries) deleted */ xfs_extnum_t cnt, /* count of entries deleted, 1 or 2 */ int whichfork); /* data or attr fork *//* * Add bmap trace entry prior to a call to xfs_iext_insert, or * reading in the extents list from the disk (in the btree). */STATIC voidxfs_bmap_trace_insert( const char *fname, /* function name */ char *desc, /* operation description */ xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* index of entry(entries) inserted */ xfs_extnum_t cnt, /* count of entries inserted, 1 or 2 */ xfs_bmbt_irec_t *r1, /* inserted record 1 */ xfs_bmbt_irec_t *r2, /* inserted record 2 or null */ int whichfork); /* data or attr fork *//* * Add bmap trace entry after updating an extent record in place. */STATIC voidxfs_bmap_trace_post_update( const char *fname, /* function name */ char *desc, /* operation description */ xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* index of entry updated */ int whichfork); /* data or attr fork *//* * Add bmap trace entry prior to updating an extent record in place. */STATIC voidxfs_bmap_trace_pre_update( const char *fname, /* function name */ char *desc, /* operation description */ xfs_inode_t *ip, /* incore inode pointer */ xfs_extnum_t idx, /* index of entry to be updated */ int whichfork); /* data or attr fork */#define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w) \ xfs_bmap_trace_delete(__FUNCTION__,d,ip,i,c,w)#define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w) \ xfs_bmap_trace_insert(__FUNCTION__,d,ip,i,c,r1,r2,w)#define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w) \ xfs_bmap_trace_post_update(__FUNCTION__,d,ip,i,w)#define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w) \ xfs_bmap_trace_pre_update(__FUNCTION__,d,ip,i,w)#else#define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)#define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)#define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)#define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)#endif /* XFS_BMAP_TRACE *//* * Compute the worst-case number of indirect blocks that will be used * for ip's delayed extent of length "len". */STATIC xfs_filblks_txfs_bmap_worst_indlen( xfs_inode_t *ip, /* incore inode pointer */ xfs_filblks_t len); /* delayed extent length */#ifdef DEBUG/* * Perform various validation checks on the values being returned * from xfs_bmapi(). */STATIC voidxfs_bmap_validate_ret( xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_bmbt_irec_t *mval, int nmap, int ret_nmap);#else#define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)#endif /* DEBUG */#if defined(XFS_RW_TRACE)STATIC voidxfs_bunmap_trace( xfs_inode_t *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, inst_t *ra);#else#define xfs_bunmap_trace(ip, bno, len, flags, ra)#endif /* XFS_RW_TRACE */STATIC intxfs_bmap_count_tree( xfs_mount_t *mp, xfs_trans_t *tp, xfs_ifork_t *ifp, xfs_fsblock_t blockno, int levelin, int *count);STATIC intxfs_bmap_count_leaves( xfs_ifork_t *ifp, xfs_extnum_t idx, int numrecs, int *count);STATIC intxfs_bmap_disk_count_leaves( xfs_extnum_t idx, xfs_bmbt_block_t *block, int numrecs, int *count);/* * Bmap internal routines. *//* * Called from xfs_bmap_add_attrfork to handle btree format files.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -