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

📄 xfs_inode_item.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * failed to get the inode flush lock but did get the inode locked SHARED. * Here we're trying to see if the inode buffer is incore, and if so whether it's * marked delayed write. If that's the case, we'll initiate a bawrite on that * buffer to expedite the process. * * We aren't holding the AIL_LOCK (or the flush lock) when this gets called, * so it is inherently race-y. */STATIC voidxfs_inode_item_pushbuf(	xfs_inode_log_item_t	*iip){	xfs_inode_t	*ip;	xfs_mount_t	*mp;	xfs_buf_t	*bp;	uint		dopush;	ip = iip->ili_inode;	ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));	/*	 * The ili_pushbuf_flag keeps others from	 * trying to duplicate our effort.	 */	ASSERT(iip->ili_pushbuf_flag != 0);	ASSERT(iip->ili_push_owner == current_pid());	/*	 * If flushlock isn't locked anymore, chances are that the	 * inode flush completed and the inode was taken off the AIL.	 * So, just get out.	 */	if (!issemalocked(&(ip->i_flock)) ||	    ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) {		iip->ili_pushbuf_flag = 0;		xfs_iunlock(ip, XFS_ILOCK_SHARED);		return;	}	mp = ip->i_mount;	bp = xfs_incore(mp->m_ddev_targp, iip->ili_format.ilf_blkno,		    iip->ili_format.ilf_len, XFS_INCORE_TRYLOCK);	if (bp != NULL) {		if (XFS_BUF_ISDELAYWRITE(bp)) {			/*			 * We were racing with iflush because we don't hold			 * the AIL_LOCK or the flush lock. However, at this point,			 * we have the buffer, and we know that it's dirty.			 * So, it's possible that iflush raced with us, and			 * this item is already taken off the AIL.			 * If not, we can flush it async.			 */			dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) &&				  issemalocked(&(ip->i_flock)));			iip->ili_pushbuf_flag = 0;			xfs_iunlock(ip, XFS_ILOCK_SHARED);			xfs_buftrace("INODE ITEM PUSH", bp);			if (XFS_BUF_ISPINNED(bp)) {				xfs_log_force(mp, (xfs_lsn_t)0,					      XFS_LOG_FORCE);			}			if (dopush) {				xfs_bawrite(mp, bp);			} else {				xfs_buf_relse(bp);			}		} else {			iip->ili_pushbuf_flag = 0;			xfs_iunlock(ip, XFS_ILOCK_SHARED);			xfs_buf_relse(bp);		}		return;	}	/*	 * We have to be careful about resetting pushbuf flag too early (above).	 * Even though in theory we can do it as soon as we have the buflock,	 * we don't want others to be doing work needlessly. They'll come to	 * this function thinking that pushing the buffer is their	 * responsibility only to find that the buffer is still locked by	 * another doing the same thing	 */	iip->ili_pushbuf_flag = 0;	xfs_iunlock(ip, XFS_ILOCK_SHARED);	return;}/* * This is called to asynchronously write the inode associated with this * inode log item out to disk. The inode will already have been locked by * a successful call to xfs_inode_item_trylock(). */STATIC voidxfs_inode_item_push(	xfs_inode_log_item_t	*iip){	xfs_inode_t	*ip;	ip = iip->ili_inode;	ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));	ASSERT(issemalocked(&(ip->i_flock)));	/*	 * Since we were able to lock the inode's flush lock and	 * we found it on the AIL, the inode must be dirty.  This	 * is because the inode is removed from the AIL while still	 * holding the flush lock in xfs_iflush_done().  Thus, if	 * we found it in the AIL and were able to obtain the flush	 * lock without sleeping, then there must not have been	 * anyone in the process of flushing the inode.	 */	ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) ||	       iip->ili_format.ilf_fields != 0);	/*	 * Write out the inode.  The completion routine ('iflush_done') will	 * pull it from the AIL, mark it clean, unlock the flush lock.	 */	(void) xfs_iflush(ip, XFS_IFLUSH_ASYNC);	xfs_iunlock(ip, XFS_ILOCK_SHARED);	return;}/* * XXX rcc - this one really has to do something.  Probably needs * to stamp in a new field in the incore inode. *//* ARGSUSED */STATIC voidxfs_inode_item_committing(	xfs_inode_log_item_t	*iip,	xfs_lsn_t		lsn){	iip->ili_last_lsn = lsn;	return;}/* * This is the ops vector shared by all buf log items. */static struct xfs_item_ops xfs_inode_item_ops = {	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_inode_item_size,	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))					xfs_inode_item_format,	.iop_pin	= (void(*)(xfs_log_item_t*))xfs_inode_item_pin,	.iop_unpin	= (void(*)(xfs_log_item_t*, int))xfs_inode_item_unpin,	.iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t*))					xfs_inode_item_unpin_remove,	.iop_trylock	= (uint(*)(xfs_log_item_t*))xfs_inode_item_trylock,	.iop_unlock	= (void(*)(xfs_log_item_t*))xfs_inode_item_unlock,	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))					xfs_inode_item_committed,	.iop_push	= (void(*)(xfs_log_item_t*))xfs_inode_item_push,	.iop_pushbuf	= (void(*)(xfs_log_item_t*))xfs_inode_item_pushbuf,	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))					xfs_inode_item_committing};/* * Initialize the inode log item for a newly allocated (in-core) inode. */voidxfs_inode_item_init(	xfs_inode_t	*ip,	xfs_mount_t	*mp){	xfs_inode_log_item_t	*iip;	ASSERT(ip->i_itemp == NULL);	iip = ip->i_itemp = kmem_zone_zalloc(xfs_ili_zone, KM_SLEEP);	iip->ili_item.li_type = XFS_LI_INODE;	iip->ili_item.li_ops = &xfs_inode_item_ops;	iip->ili_item.li_mountp = mp;	iip->ili_inode = ip;	/*	   We have zeroed memory. No need ...	   iip->ili_extents_buf = NULL;	   iip->ili_pushbuf_flag = 0;	 */	iip->ili_format.ilf_type = XFS_LI_INODE;	iip->ili_format.ilf_ino = ip->i_ino;	iip->ili_format.ilf_blkno = ip->i_blkno;	iip->ili_format.ilf_len = ip->i_len;	iip->ili_format.ilf_boffset = ip->i_boffset;}/* * Free the inode log item and any memory hanging off of it. */voidxfs_inode_item_destroy(	xfs_inode_t	*ip){#ifdef XFS_TRANS_DEBUG	if (ip->i_itemp->ili_root_size != 0) {		kmem_free(ip->i_itemp->ili_orig_root,			  ip->i_itemp->ili_root_size);	}#endif	kmem_zone_free(xfs_ili_zone, ip->i_itemp);}/* * This is the inode flushing I/O completion routine.  It is called * from interrupt level when the buffer containing the inode is * flushed to disk.  It is responsible for removing the inode item * from the AIL if it has not been re-logged, and unlocking the inode's * flush lock. *//*ARGSUSED*/voidxfs_iflush_done(	xfs_buf_t		*bp,	xfs_inode_log_item_t	*iip){	xfs_inode_t	*ip;	SPLDECL(s);	ip = iip->ili_inode;	/*	 * We only want to pull the item from the AIL if it is	 * actually there and its location in the log has not	 * changed since we started the flush.  Thus, we only bother	 * if the ili_logged flag is set and the inode's lsn has not	 * changed.  First we check the lsn outside	 * the lock since it's cheaper, and then we recheck while	 * holding the lock before removing the inode from the AIL.	 */	if (iip->ili_logged &&	    (iip->ili_item.li_lsn == iip->ili_flush_lsn)) {		AIL_LOCK(ip->i_mount, s);		if (iip->ili_item.li_lsn == iip->ili_flush_lsn) {			/*			 * xfs_trans_delete_ail() drops the AIL lock.			 */			xfs_trans_delete_ail(ip->i_mount,					     (xfs_log_item_t*)iip, s);		} else {			AIL_UNLOCK(ip->i_mount, s);		}	}	iip->ili_logged = 0;	/*	 * Clear the ili_last_fields bits now that we know that the	 * data corresponding to them is safely on disk.	 */	iip->ili_last_fields = 0;	/*	 * Release the inode's flush lock since we're done with it.	 */	xfs_ifunlock(ip);	return;}/* * This is the inode flushing abort routine.  It is called * from xfs_iflush when the filesystem is shutting down to clean * up the inode state. * It is responsible for removing the inode item * from the AIL if it has not been re-logged, and unlocking the inode's * flush lock. */voidxfs_iflush_abort(	xfs_inode_t		*ip){	xfs_inode_log_item_t	*iip;	xfs_mount_t		*mp;	SPLDECL(s);	iip = ip->i_itemp;	mp = ip->i_mount;	if (iip) {		if (iip->ili_item.li_flags & XFS_LI_IN_AIL) {			AIL_LOCK(mp, s);			if (iip->ili_item.li_flags & XFS_LI_IN_AIL) {				/*				 * xfs_trans_delete_ail() drops the AIL lock.				 */				xfs_trans_delete_ail(mp, (xfs_log_item_t *)iip,					s);			} else				AIL_UNLOCK(mp, s);		}		iip->ili_logged = 0;		/*		 * Clear the ili_last_fields bits now that we know that the		 * data corresponding to them is safely on disk.		 */		iip->ili_last_fields = 0;		/*		 * Clear the inode logging fields so no more flushes are		 * attempted.		 */		iip->ili_format.ilf_fields = 0;	}	/*	 * Release the inode's flush lock since we're done with it.	 */	xfs_ifunlock(ip);}voidxfs_istale_done(	xfs_buf_t		*bp,	xfs_inode_log_item_t	*iip){	xfs_iflush_abort(iip->ili_inode);}/* * convert an xfs_inode_log_format struct from either 32 or 64 bit versions * (which can have different field alignments) to the native version */intxfs_inode_item_format_convert(	xfs_log_iovec_t		*buf,	xfs_inode_log_format_t	*in_f){	if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) {		xfs_inode_log_format_32_t *in_f32;		in_f32 = (xfs_inode_log_format_32_t *)buf->i_addr;		in_f->ilf_type = in_f32->ilf_type;		in_f->ilf_size = in_f32->ilf_size;		in_f->ilf_fields = in_f32->ilf_fields;		in_f->ilf_asize = in_f32->ilf_asize;		in_f->ilf_dsize = in_f32->ilf_dsize;		in_f->ilf_ino = in_f32->ilf_ino;		/* copy biggest field of ilf_u */		memcpy(in_f->ilf_u.ilfu_uuid.__u_bits,		       in_f32->ilf_u.ilfu_uuid.__u_bits,		       sizeof(uuid_t));		in_f->ilf_blkno = in_f32->ilf_blkno;		in_f->ilf_len = in_f32->ilf_len;		in_f->ilf_boffset = in_f32->ilf_boffset;		return 0;	} else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){		xfs_inode_log_format_64_t *in_f64;		in_f64 = (xfs_inode_log_format_64_t *)buf->i_addr;		in_f->ilf_type = in_f64->ilf_type;		in_f->ilf_size = in_f64->ilf_size;		in_f->ilf_fields = in_f64->ilf_fields;		in_f->ilf_asize = in_f64->ilf_asize;		in_f->ilf_dsize = in_f64->ilf_dsize;		in_f->ilf_ino = in_f64->ilf_ino;		/* copy biggest field of ilf_u */		memcpy(in_f->ilf_u.ilfu_uuid.__u_bits,		       in_f64->ilf_u.ilfu_uuid.__u_bits,		       sizeof(uuid_t));		in_f->ilf_blkno = in_f64->ilf_blkno;		in_f->ilf_len = in_f64->ilf_len;		in_f->ilf_boffset = in_f64->ilf_boffset;		return 0;	}	return EFSCORRUPTED;}

⌨️ 快捷键说明

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