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

📄 xfs_inode_item.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2000-2002,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_buf_item.h"#include "xfs_sb.h"#include "xfs_ag.h"#include "xfs_dir2.h"#include "xfs_dmapi.h"#include "xfs_mount.h"#include "xfs_trans_priv.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_inode_item.h"#include "xfs_btree.h"#include "xfs_ialloc.h"#include "xfs_rw.h"kmem_zone_t	*xfs_ili_zone;		/* inode log item zone *//* * This returns the number of iovecs needed to log the given inode item. * * We need one iovec for the inode log format structure, one for the * inode core, and possibly one for the inode data/extents/b-tree root * and one for the inode attribute data/extents/b-tree root. */STATIC uintxfs_inode_item_size(	xfs_inode_log_item_t	*iip){	uint		nvecs;	xfs_inode_t	*ip;	ip = iip->ili_inode;	nvecs = 2;	/*	 * Only log the data/extents/b-tree root if there is something	 * left to log.	 */	iip->ili_format.ilf_fields |= XFS_ILOG_CORE;	switch (ip->i_d.di_format) {	case XFS_DINODE_FMT_EXTENTS:		iip->ili_format.ilf_fields &=			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |			  XFS_ILOG_DEV | XFS_ILOG_UUID);		if ((iip->ili_format.ilf_fields & XFS_ILOG_DEXT) &&		    (ip->i_d.di_nextents > 0) &&		    (ip->i_df.if_bytes > 0)) {			ASSERT(ip->i_df.if_u1.if_extents != NULL);			nvecs++;		} else {			iip->ili_format.ilf_fields &= ~XFS_ILOG_DEXT;		}		break;	case XFS_DINODE_FMT_BTREE:		ASSERT(ip->i_df.if_ext_max ==		       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));		iip->ili_format.ilf_fields &=			~(XFS_ILOG_DDATA | XFS_ILOG_DEXT |			  XFS_ILOG_DEV | XFS_ILOG_UUID);		if ((iip->ili_format.ilf_fields & XFS_ILOG_DBROOT) &&		    (ip->i_df.if_broot_bytes > 0)) {			ASSERT(ip->i_df.if_broot != NULL);			nvecs++;		} else {			ASSERT(!(iip->ili_format.ilf_fields &				 XFS_ILOG_DBROOT));#ifdef XFS_TRANS_DEBUG			if (iip->ili_root_size > 0) {				ASSERT(iip->ili_root_size ==				       ip->i_df.if_broot_bytes);				ASSERT(memcmp(iip->ili_orig_root,					    ip->i_df.if_broot,					    iip->ili_root_size) == 0);			} else {				ASSERT(ip->i_df.if_broot_bytes == 0);			}#endif			iip->ili_format.ilf_fields &= ~XFS_ILOG_DBROOT;		}		break;	case XFS_DINODE_FMT_LOCAL:		iip->ili_format.ilf_fields &=			~(XFS_ILOG_DEXT | XFS_ILOG_DBROOT |			  XFS_ILOG_DEV | XFS_ILOG_UUID);		if ((iip->ili_format.ilf_fields & XFS_ILOG_DDATA) &&		    (ip->i_df.if_bytes > 0)) {			ASSERT(ip->i_df.if_u1.if_data != NULL);			ASSERT(ip->i_d.di_size > 0);			nvecs++;		} else {			iip->ili_format.ilf_fields &= ~XFS_ILOG_DDATA;		}		break;	case XFS_DINODE_FMT_DEV:		iip->ili_format.ilf_fields &=			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |			  XFS_ILOG_DEXT | XFS_ILOG_UUID);		break;	case XFS_DINODE_FMT_UUID:		iip->ili_format.ilf_fields &=			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |			  XFS_ILOG_DEXT | XFS_ILOG_DEV);		break;	default:		ASSERT(0);		break;	}	/*	 * If there are no attributes associated with this file,	 * then there cannot be anything more to log.	 * Clear all attribute-related log flags.	 */	if (!XFS_IFORK_Q(ip)) {		iip->ili_format.ilf_fields &=			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT);		return nvecs;	}	/*	 * Log any necessary attribute data.	 */	switch (ip->i_d.di_aformat) {	case XFS_DINODE_FMT_EXTENTS:		iip->ili_format.ilf_fields &=			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);		if ((iip->ili_format.ilf_fields & XFS_ILOG_AEXT) &&		    (ip->i_d.di_anextents > 0) &&		    (ip->i_afp->if_bytes > 0)) {			ASSERT(ip->i_afp->if_u1.if_extents != NULL);			nvecs++;		} else {			iip->ili_format.ilf_fields &= ~XFS_ILOG_AEXT;		}		break;	case XFS_DINODE_FMT_BTREE:		iip->ili_format.ilf_fields &=			~(XFS_ILOG_ADATA | XFS_ILOG_AEXT);		if ((iip->ili_format.ilf_fields & XFS_ILOG_ABROOT) &&		    (ip->i_afp->if_broot_bytes > 0)) {			ASSERT(ip->i_afp->if_broot != NULL);			nvecs++;		} else {			iip->ili_format.ilf_fields &= ~XFS_ILOG_ABROOT;		}		break;	case XFS_DINODE_FMT_LOCAL:		iip->ili_format.ilf_fields &=			~(XFS_ILOG_AEXT | XFS_ILOG_ABROOT);		if ((iip->ili_format.ilf_fields & XFS_ILOG_ADATA) &&		    (ip->i_afp->if_bytes > 0)) {			ASSERT(ip->i_afp->if_u1.if_data != NULL);			nvecs++;		} else {			iip->ili_format.ilf_fields &= ~XFS_ILOG_ADATA;		}		break;	default:		ASSERT(0);		break;	}	return nvecs;}/* * This is called to fill in the vector of log iovecs for the * given inode log item.  It fills the first item with an inode * log format structure, the second with the on-disk inode structure, * and a possible third and/or fourth with the inode data/extents/b-tree * root and inode attributes data/extents/b-tree root. */STATIC voidxfs_inode_item_format(	xfs_inode_log_item_t	*iip,	xfs_log_iovec_t		*log_vector){	uint			nvecs;	xfs_log_iovec_t		*vecp;	xfs_inode_t		*ip;	size_t			data_bytes;	xfs_bmbt_rec_t		*ext_buffer;	int			nrecs;	xfs_mount_t		*mp;	ip = iip->ili_inode;	vecp = log_vector;	vecp->i_addr = (xfs_caddr_t)&iip->ili_format;	vecp->i_len  = sizeof(xfs_inode_log_format_t);	XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IFORMAT);	vecp++;	nvecs	     = 1;	/*	 * Clear i_update_core if the timestamps (or any other	 * non-transactional modification) need flushing/logging	 * and we're about to log them with the rest of the core.	 *	 * This is the same logic as xfs_iflush() but this code can't	 * run at the same time as xfs_iflush because we're in commit	 * processing here and so we have the inode lock held in	 * exclusive mode.  Although it doesn't really matter	 * for the timestamps if both routines were to grab the	 * timestamps or not.  That would be ok.	 *	 * We clear i_update_core before copying out the data.	 * This is for coordination with our timestamp updates	 * that don't hold the inode lock. They will always	 * update the timestamps BEFORE setting i_update_core,	 * so if we clear i_update_core after they set it we	 * are guaranteed to see their updates to the timestamps	 * either here.  Likewise, if they set it after we clear it	 * here, we'll see it either on the next commit of this	 * inode or the next time the inode gets flushed via	 * xfs_iflush().  This depends on strongly ordered memory	 * semantics, but we have that.  We use the SYNCHRONIZE	 * macro to make sure that the compiler does not reorder	 * the i_update_core access below the data copy below.	 */	if (ip->i_update_core)  {		ip->i_update_core = 0;		SYNCHRONIZE();	}	/*	 * We don't have to worry about re-ordering here because	 * the update_size field is protected by the inode lock	 * and we have that held in exclusive mode.	 */	if (ip->i_update_size)		ip->i_update_size = 0;	/*	 * Make sure to get the latest atime from the Linux inode.	 */	xfs_synchronize_atime(ip);	vecp->i_addr = (xfs_caddr_t)&ip->i_d;	vecp->i_len  = sizeof(xfs_dinode_core_t);	XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ICORE);	vecp++;	nvecs++;	iip->ili_format.ilf_fields |= XFS_ILOG_CORE;	/*	 * If this is really an old format inode, then we need to	 * log it as such.  This means that we have to copy the link	 * count from the new field to the old.  We don't have to worry	 * about the new fields, because nothing trusts them as long as	 * the old inode version number is there.  If the superblock already	 * has a new version number, then we don't bother converting back.	 */	mp = ip->i_mount;	ASSERT(ip->i_d.di_version == XFS_DINODE_VERSION_1 ||	       XFS_SB_VERSION_HASNLINK(&mp->m_sb));	if (ip->i_d.di_version == XFS_DINODE_VERSION_1) {		if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) {			/*			 * Convert it back.			 */			ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);			ip->i_d.di_onlink = ip->i_d.di_nlink;		} else {			/*			 * The superblock version has already been bumped,			 * so just make the conversion to the new inode			 * format permanent.			 */			ip->i_d.di_version = XFS_DINODE_VERSION_2;			ip->i_d.di_onlink = 0;			memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));		}	}	switch (ip->i_d.di_format) {	case XFS_DINODE_FMT_EXTENTS:		ASSERT(!(iip->ili_format.ilf_fields &			 (XFS_ILOG_DDATA | XFS_ILOG_DBROOT |			  XFS_ILOG_DEV | XFS_ILOG_UUID)));		if (iip->ili_format.ilf_fields & XFS_ILOG_DEXT) {			ASSERT(ip->i_df.if_bytes > 0);			ASSERT(ip->i_df.if_u1.if_extents != NULL);			ASSERT(ip->i_d.di_nextents > 0);			ASSERT(iip->ili_extents_buf == NULL);			nrecs = ip->i_df.if_bytes /				(uint)sizeof(xfs_bmbt_rec_t);			ASSERT(nrecs > 0);#ifdef XFS_NATIVE_HOST			if (nrecs == ip->i_d.di_nextents) {				/*				 * There are no delayed allocation				 * extents, so just point to the				 * real extents array.				 */				vecp->i_addr =					(char *)(ip->i_df.if_u1.if_extents);				vecp->i_len = ip->i_df.if_bytes;				XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IEXT);			} else#endif			{				/*				 * There are delayed allocation extents				 * in the inode, or we need to convert				 * the extents to on disk format.				 * Use xfs_iextents_copy()				 * to copy only the real extents into				 * a separate buffer.  We'll free the				 * buffer in the unlock routine.				 */				ext_buffer = kmem_alloc(ip->i_df.if_bytes,					KM_SLEEP);				iip->ili_extents_buf = ext_buffer;				vecp->i_addr = (xfs_caddr_t)ext_buffer;				vecp->i_len = xfs_iextents_copy(ip, ext_buffer,						XFS_DATA_FORK);				XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IEXT);			}			ASSERT(vecp->i_len <= ip->i_df.if_bytes);			iip->ili_format.ilf_dsize = vecp->i_len;			vecp++;			nvecs++;		}		break;	case XFS_DINODE_FMT_BTREE:		ASSERT(!(iip->ili_format.ilf_fields &			 (XFS_ILOG_DDATA | XFS_ILOG_DEXT |			  XFS_ILOG_DEV | XFS_ILOG_UUID)));		if (iip->ili_format.ilf_fields & XFS_ILOG_DBROOT) {			ASSERT(ip->i_df.if_broot_bytes > 0);			ASSERT(ip->i_df.if_broot != NULL);			vecp->i_addr = (xfs_caddr_t)ip->i_df.if_broot;			vecp->i_len = ip->i_df.if_broot_bytes;

⌨️ 快捷键说明

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