xfs_extfree_item.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 669 行 · 第 1/2 页

C
669
字号
/* * Copyright (c) 2000-2001 Silicon Graphics, Inc.  All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 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. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like.  Any license provided herein, whether implied or * otherwise, applies only to this software file.  Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA  94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ *//* * This file contains the implementation of the xfs_efi_log_item * and xfs_efd_log_item items. */#include "xfs.h"#include "xfs_macros.h"#include "xfs_types.h"#include "xfs_inum.h"#include "xfs_log.h"#include "xfs_trans.h"#include "xfs_buf_item.h"#include "xfs_sb.h"#include "xfs_dir.h"#include "xfs_dmapi.h"#include "xfs_mount.h"#include "xfs_trans_priv.h"#include "xfs_extfree_item.h"kmem_zone_t	*xfs_efi_zone;kmem_zone_t	*xfs_efd_zone;STATIC void	xfs_efi_item_unlock(xfs_efi_log_item_t *);STATIC void	xfs_efi_item_abort(xfs_efi_log_item_t *);STATIC void	xfs_efd_item_abort(xfs_efd_log_item_t *);/* * This returns the number of iovecs needed to log the given efi item. * We only need 1 iovec for an efi item.  It just logs the efi_log_format * structure. *//*ARGSUSED*/STATIC uintxfs_efi_item_size(xfs_efi_log_item_t *efip){	return 1;}/* * This is called to fill in the vector of log iovecs for the * given efi log item. We use only 1 iovec, and we point that * at the efi_log_format structure embedded in the efi item. * It is at this point that we assert that all of the extent * slots in the efi item have been filled. */STATIC voidxfs_efi_item_format(xfs_efi_log_item_t	*efip,		    xfs_log_iovec_t	*log_vector){	uint	size;	ASSERT(efip->efi_next_extent == efip->efi_format.efi_nextents);	efip->efi_format.efi_type = XFS_LI_EFI;	size = sizeof(xfs_efi_log_format_t);	size += (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t);	efip->efi_format.efi_size = 1;	log_vector->i_addr = (xfs_caddr_t)&(efip->efi_format);	log_vector->i_len = size;	ASSERT(size >= sizeof(xfs_efi_log_format_t));}/* * Pinning has no meaning for an efi item, so just return. *//*ARGSUSED*/STATIC voidxfs_efi_item_pin(xfs_efi_log_item_t *efip){	return;}/* * While EFIs cannot really be pinned, the unpin operation is the * last place at which the EFI is manipulated during a transaction. * Here we coordinate with xfs_efi_cancel() to determine who gets to * free the EFI. *//*ARGSUSED*/STATIC voidxfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale){	int		nexts;	int		size;	xfs_mount_t	*mp;	SPLDECL(s);	mp = efip->efi_item.li_mountp;	AIL_LOCK(mp, s);	if (efip->efi_flags & XFS_EFI_CANCELED) {		/*		 * xfs_trans_delete_ail() drops the AIL lock.		 */		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);		nexts = efip->efi_format.efi_nextents;		if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {			size = sizeof(xfs_efi_log_item_t);			size += (nexts - 1) * sizeof(xfs_extent_t);			kmem_free(efip, size);		} else {			kmem_zone_free(xfs_efi_zone, efip);		}	} else {		efip->efi_flags |= XFS_EFI_COMMITTED;		AIL_UNLOCK(mp, s);	}	return;}/* * like unpin only we have to also clear the xaction descriptor * pointing the log item if we free the item.  This routine duplicates * unpin because efi_flags is protected by the AIL lock.  Freeing * the descriptor and then calling unpin would force us to drop the AIL * lock which would open up a race condition. */STATIC voidxfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp){	int		nexts;	int		size;	xfs_mount_t	*mp;	xfs_log_item_desc_t	*lidp;	SPLDECL(s);	mp = efip->efi_item.li_mountp;	AIL_LOCK(mp, s);	if (efip->efi_flags & XFS_EFI_CANCELED) {		/*		 * free the xaction descriptor pointing to this item		 */		lidp = xfs_trans_find_item(tp, (xfs_log_item_t *) efip);		xfs_trans_free_item(tp, lidp);		/*		 * pull the item off the AIL.		 * xfs_trans_delete_ail() drops the AIL lock.		 */		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);		/*		 * now free the item itself		 */		nexts = efip->efi_format.efi_nextents;		if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {			size = sizeof(xfs_efi_log_item_t);			size += (nexts - 1) * sizeof(xfs_extent_t);			kmem_free(efip, size);		} else {			kmem_zone_free(xfs_efi_zone, efip);		}	} else {		efip->efi_flags |= XFS_EFI_COMMITTED;		AIL_UNLOCK(mp, s);	}	return;}/* * Efi items have no locking or pushing.  However, since EFIs are * pulled from the AIL when their corresponding EFDs are committed * to disk, their situation is very similar to being pinned.  Return * XFS_ITEM_PINNED so that the caller will eventually flush the log. * This should help in getting the EFI out of the AIL. *//*ARGSUSED*/STATIC uintxfs_efi_item_trylock(xfs_efi_log_item_t *efip){	return XFS_ITEM_PINNED;}/* * Efi items have no locking, so just return. *//*ARGSUSED*/STATIC voidxfs_efi_item_unlock(xfs_efi_log_item_t *efip){	if (efip->efi_item.li_flags & XFS_LI_ABORTED)		xfs_efi_item_abort(efip);	return;}/* * The EFI is logged only once and cannot be moved in the log, so * simply return the lsn at which it's been logged.  The canceled * flag is not paid any attention here.  Checking for that is delayed * until the EFI is unpinned. *//*ARGSUSED*/STATIC xfs_lsn_txfs_efi_item_committed(xfs_efi_log_item_t *efip, xfs_lsn_t lsn){	return lsn;}/* * This is called when the transaction logging the EFI is aborted. * Free up the EFI and return.  No need to clean up the slot for * the item in the transaction.  That was done by the unpin code * which is called prior to this routine in the abort/fs-shutdown path. */STATIC voidxfs_efi_item_abort(xfs_efi_log_item_t *efip){	int	nexts;	int	size;	nexts = efip->efi_format.efi_nextents;	if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {		size = sizeof(xfs_efi_log_item_t);		size += (nexts - 1) * sizeof(xfs_extent_t);		kmem_free(efip, size);	} else {		kmem_zone_free(xfs_efi_zone, efip);	}	return;}/* * There isn't much you can do to push on an efi item.  It is simply * stuck waiting for all of its corresponding efd items to be * committed to disk. *//*ARGSUSED*/STATIC voidxfs_efi_item_push(xfs_efi_log_item_t *efip){	return;}/* * The EFI dependency tracking op doesn't do squat.  It can't because * it doesn't know where the free extent is coming from.  The dependency * tracking has to be handled by the "enclosing" metadata object.  For * example, for inodes, the inode is locked throughout the extent freeing * so the dependency should be recorded there. *//*ARGSUSED*/STATIC voidxfs_efi_item_committing(xfs_efi_log_item_t *efip, xfs_lsn_t lsn){	return;}/* * This is the ops vector shared by all efi log items. */struct xfs_item_ops xfs_efi_item_ops = {	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_efi_item_size,	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))					xfs_efi_item_format,	.iop_pin	= (void(*)(xfs_log_item_t*))xfs_efi_item_pin,	.iop_unpin	= (void(*)(xfs_log_item_t*, int))xfs_efi_item_unpin,	.iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t *))					xfs_efi_item_unpin_remove,	.iop_trylock	= (uint(*)(xfs_log_item_t*))xfs_efi_item_trylock,	.iop_unlock	= (void(*)(xfs_log_item_t*))xfs_efi_item_unlock,	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))					xfs_efi_item_committed,	.iop_push	= (void(*)(xfs_log_item_t*))xfs_efi_item_push,	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_efi_item_abort,	.iop_pushbuf	= NULL,	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))					xfs_efi_item_committing};/* * Allocate and initialize an efi item with the given number of extents. */xfs_efi_log_item_t *xfs_efi_init(xfs_mount_t	*mp,	     uint		nextents){	xfs_efi_log_item_t	*efip;	uint			size;	ASSERT(nextents > 0);	if (nextents > XFS_EFI_MAX_FAST_EXTENTS) {		size = (uint)(sizeof(xfs_efi_log_item_t) +			((nextents - 1) * sizeof(xfs_extent_t)));		efip = (xfs_efi_log_item_t*)kmem_zalloc(size, KM_SLEEP);	} else {		efip = (xfs_efi_log_item_t*)kmem_zone_zalloc(xfs_efi_zone,							     KM_SLEEP);	}	efip->efi_item.li_type = XFS_LI_EFI;	efip->efi_item.li_ops = &xfs_efi_item_ops;	efip->efi_item.li_mountp = mp;	efip->efi_format.efi_nextents = nextents;

⌨️ 快捷键说明

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