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

📄 xfs_trans.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2000-2003,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_error.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_ialloc.h"#include "xfs_alloc.h"#include "xfs_bmap.h"#include "xfs_quota.h"#include "xfs_trans_priv.h"#include "xfs_trans_space.h"STATIC void	xfs_trans_apply_sb_deltas(xfs_trans_t *);STATIC uint	xfs_trans_count_vecs(xfs_trans_t *);STATIC void	xfs_trans_fill_vecs(xfs_trans_t *, xfs_log_iovec_t *);STATIC void	xfs_trans_uncommit(xfs_trans_t *, uint);STATIC void	xfs_trans_committed(xfs_trans_t *, int);STATIC void	xfs_trans_chunk_committed(xfs_log_item_chunk_t *, xfs_lsn_t, int);STATIC void	xfs_trans_free(xfs_trans_t *);kmem_zone_t	*xfs_trans_zone;/* * Reservation functions here avoid a huge stack in xfs_trans_init * due to register overflow from temporaries in the calculations. */STATIC uintxfs_calc_write_reservation(xfs_mount_t *mp){	return XFS_CALC_WRITE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_itruncate_reservation(xfs_mount_t *mp){	return XFS_CALC_ITRUNCATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_rename_reservation(xfs_mount_t *mp){	return XFS_CALC_RENAME_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_link_reservation(xfs_mount_t *mp){	return XFS_CALC_LINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_remove_reservation(xfs_mount_t *mp){	return XFS_CALC_REMOVE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_symlink_reservation(xfs_mount_t *mp){	return XFS_CALC_SYMLINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_create_reservation(xfs_mount_t *mp){	return XFS_CALC_CREATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_mkdir_reservation(xfs_mount_t *mp){	return XFS_CALC_MKDIR_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_ifree_reservation(xfs_mount_t *mp){	return XFS_CALC_IFREE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_ichange_reservation(xfs_mount_t *mp){	return XFS_CALC_ICHANGE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_growdata_reservation(xfs_mount_t *mp){	return XFS_CALC_GROWDATA_LOG_RES(mp);}STATIC uintxfs_calc_growrtalloc_reservation(xfs_mount_t *mp){	return XFS_CALC_GROWRTALLOC_LOG_RES(mp);}STATIC uintxfs_calc_growrtzero_reservation(xfs_mount_t *mp){	return XFS_CALC_GROWRTZERO_LOG_RES(mp);}STATIC uintxfs_calc_growrtfree_reservation(xfs_mount_t *mp){	return XFS_CALC_GROWRTFREE_LOG_RES(mp);}STATIC uintxfs_calc_swrite_reservation(xfs_mount_t *mp){	return XFS_CALC_SWRITE_LOG_RES(mp);}STATIC uintxfs_calc_writeid_reservation(xfs_mount_t *mp){	return XFS_CALC_WRITEID_LOG_RES(mp);}STATIC uintxfs_calc_addafork_reservation(xfs_mount_t *mp){	return XFS_CALC_ADDAFORK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_attrinval_reservation(xfs_mount_t *mp){	return XFS_CALC_ATTRINVAL_LOG_RES(mp);}STATIC uintxfs_calc_attrset_reservation(xfs_mount_t *mp){	return XFS_CALC_ATTRSET_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_attrrm_reservation(xfs_mount_t *mp){	return XFS_CALC_ATTRRM_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);}STATIC uintxfs_calc_clear_agi_bucket_reservation(xfs_mount_t *mp){	return XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp);}/* * Initialize the precomputed transaction reservation values * in the mount structure. */voidxfs_trans_init(	xfs_mount_t	*mp){	xfs_trans_reservations_t	*resp;	resp = &(mp->m_reservations);	resp->tr_write = xfs_calc_write_reservation(mp);	resp->tr_itruncate = xfs_calc_itruncate_reservation(mp);	resp->tr_rename = xfs_calc_rename_reservation(mp);	resp->tr_link = xfs_calc_link_reservation(mp);	resp->tr_remove = xfs_calc_remove_reservation(mp);	resp->tr_symlink = xfs_calc_symlink_reservation(mp);	resp->tr_create = xfs_calc_create_reservation(mp);	resp->tr_mkdir = xfs_calc_mkdir_reservation(mp);	resp->tr_ifree = xfs_calc_ifree_reservation(mp);	resp->tr_ichange = xfs_calc_ichange_reservation(mp);	resp->tr_growdata = xfs_calc_growdata_reservation(mp);	resp->tr_swrite = xfs_calc_swrite_reservation(mp);	resp->tr_writeid = xfs_calc_writeid_reservation(mp);	resp->tr_addafork = xfs_calc_addafork_reservation(mp);	resp->tr_attrinval = xfs_calc_attrinval_reservation(mp);	resp->tr_attrset = xfs_calc_attrset_reservation(mp);	resp->tr_attrrm = xfs_calc_attrrm_reservation(mp);	resp->tr_clearagi = xfs_calc_clear_agi_bucket_reservation(mp);	resp->tr_growrtalloc = xfs_calc_growrtalloc_reservation(mp);	resp->tr_growrtzero = xfs_calc_growrtzero_reservation(mp);	resp->tr_growrtfree = xfs_calc_growrtfree_reservation(mp);}/* * This routine is called to allocate a transaction structure. * The type parameter indicates the type of the transaction.  These * are enumerated in xfs_trans.h. * * Dynamically allocate the transaction structure from the transaction * zone, initialize it, and return it to the caller. */xfs_trans_t *xfs_trans_alloc(	xfs_mount_t	*mp,	uint		type){	xfs_wait_for_freeze(mp, SB_FREEZE_TRANS);	return _xfs_trans_alloc(mp, type);}xfs_trans_t *_xfs_trans_alloc(	xfs_mount_t	*mp,	uint		type){	xfs_trans_t	*tp;	atomic_inc(&mp->m_active_trans);	tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);	tp->t_magic = XFS_TRANS_MAGIC;	tp->t_type = type;	tp->t_mountp = mp;	tp->t_items_free = XFS_LIC_NUM_SLOTS;	tp->t_busy_free = XFS_LBC_NUM_SLOTS;	XFS_LIC_INIT(&(tp->t_items));	XFS_LBC_INIT(&(tp->t_busy));	return tp;}/* * This is called to create a new transaction which will share the * permanent log reservation of the given transaction.  The remaining * unused block and rt extent reservations are also inherited.  This * implies that the original transaction is no longer allowed to allocate * blocks.  Locks and log items, however, are no inherited.  They must * be added to the new transaction explicitly. */xfs_trans_t *xfs_trans_dup(	xfs_trans_t	*tp){	xfs_trans_t	*ntp;	ntp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);	/*	 * Initialize the new transaction structure.	 */	ntp->t_magic = XFS_TRANS_MAGIC;	ntp->t_type = tp->t_type;	ntp->t_mountp = tp->t_mountp;	ntp->t_items_free = XFS_LIC_NUM_SLOTS;	ntp->t_busy_free = XFS_LBC_NUM_SLOTS;	XFS_LIC_INIT(&(ntp->t_items));	XFS_LBC_INIT(&(ntp->t_busy));	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);	ASSERT(tp->t_ticket != NULL);	ntp->t_flags = XFS_TRANS_PERM_LOG_RES | (tp->t_flags & XFS_TRANS_RESERVE);	ntp->t_ticket = tp->t_ticket;	ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used;	tp->t_blk_res = tp->t_blk_res_used;	ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used;	tp->t_rtx_res = tp->t_rtx_res_used;	ntp->t_pflags = tp->t_pflags;	XFS_TRANS_DUP_DQINFO(tp->t_mountp, tp, ntp);	atomic_inc(&tp->t_mountp->m_active_trans);	return ntp;}/* * This is called to reserve free disk blocks and log space for the * given transaction.  This must be done before allocating any resources * within the transaction. * * This will return ENOSPC if there are not enough blocks available. * It will sleep waiting for available log space. * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which * is used by long running transactions.  If any one of the reservations * fails then they will all be backed out. * * This does not do quota reservations. That typically is done by the * caller afterwards. */intxfs_trans_reserve(	xfs_trans_t	*tp,	uint		blocks,	uint		logspace,	uint		rtextents,	uint		flags,	uint		logcount){	int		log_flags;	int		error = 0;	int		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;	/* Mark this thread as being in a transaction */	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);	/*	 * Attempt to reserve the needed disk blocks by decrementing	 * the number needed from the number available.  This will	 * fail if the count would go below zero.	 */	if (blocks > 0) {		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,					  -((int64_t)blocks), rsvd);		if (error != 0) {			current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);			return (XFS_ERROR(ENOSPC));		}		tp->t_blk_res += blocks;	}	/*	 * Reserve the log space needed for this transaction.	 */	if (logspace > 0) {		ASSERT((tp->t_log_res == 0) || (tp->t_log_res == logspace));		ASSERT((tp->t_log_count == 0) ||			(tp->t_log_count == logcount));		if (flags & XFS_TRANS_PERM_LOG_RES) {			log_flags = XFS_LOG_PERM_RESERV;			tp->t_flags |= XFS_TRANS_PERM_LOG_RES;		} else {			ASSERT(tp->t_ticket == NULL);			ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));			log_flags = 0;		}		error = xfs_log_reserve(tp->t_mountp, logspace, logcount,					&tp->t_ticket,					XFS_TRANSACTION, log_flags, tp->t_type);		if (error) {			goto undo_blocks;		}		tp->t_log_res = logspace;		tp->t_log_count = logcount;	}	/*	 * Attempt to reserve the needed realtime extents by decrementing	 * the number needed from the number available.  This will	 * fail if the count would go below zero.	 */	if (rtextents > 0) {		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS,					  -((int64_t)rtextents), rsvd);		if (error) {			error = XFS_ERROR(ENOSPC);			goto undo_log;		}		tp->t_rtx_res += rtextents;	}	return 0;	/*	 * Error cases jump to one of these labels to undo any	 * reservations which have already been performed.	 */undo_log:	if (logspace > 0) {		if (flags & XFS_TRANS_PERM_LOG_RES) {			log_flags = XFS_LOG_REL_PERM_RESERV;		} else {			log_flags = 0;		}		xfs_log_done(tp->t_mountp, tp->t_ticket, NULL, log_flags);		tp->t_ticket = NULL;		tp->t_log_res = 0;		tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;	}undo_blocks:	if (blocks > 0) {		(void) xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,					 (int64_t)blocks, rsvd);		tp->t_blk_res = 0;	}	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);	return error;}/* * Record the indicated change to the given field for application * to the file system's superblock when the transaction commits. * For now, just store the change in the transaction structure. * * Mark the transaction structure to indicate that the superblock * needs to be updated before committing. * * Because we may not be keeping track of allocated/free inodes and * used filesystem blocks in the superblock, we do not mark the * superblock dirty in this transaction if we modify these fields. * We still need to update the transaction deltas so that they get * applied to the incore superblock, but we don't want them to * cause the superblock to get locked and logged if these are the * only fields in the superblock that the transaction modifies. */voidxfs_trans_mod_sb(	xfs_trans_t	*tp,	uint		field,	int64_t		delta){	uint32_t	flags = (XFS_TRANS_DIRTY|XFS_TRANS_SB_DIRTY);	xfs_mount_t	*mp = tp->t_mountp;	switch (field) {	case XFS_TRANS_SB_ICOUNT:		tp->t_icount_delta += delta;		if (xfs_sb_version_haslazysbcount(&mp->m_sb))			flags &= ~XFS_TRANS_SB_DIRTY;		break;	case XFS_TRANS_SB_IFREE:		tp->t_ifree_delta += delta;		if (xfs_sb_version_haslazysbcount(&mp->m_sb))			flags &= ~XFS_TRANS_SB_DIRTY;		break;	case XFS_TRANS_SB_FDBLOCKS:		/*		 * Track the number of blocks allocated in the		 * transaction.  Make sure it does not exceed the		 * number reserved.		 */

⌨️ 快捷键说明

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