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

📄 xfs_vfsops.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	if (!error && rtdev)		error = xfs_setsize_buftarg(mp->m_rtdev_targp,					    mp->m_sb.sb_blocksize,					    mp->m_sb.sb_sectsize);	if (error)		goto error2;	if (mp->m_flags & XFS_MOUNT_BARRIER)		xfs_mountfs_check_barriers(mp);	if ((error = xfs_filestream_mount(mp)))		goto error2;	error = XFS_IOINIT(mp, args, flags);	if (error)		goto error2;	XFS_SEND_MOUNT(mp, DM_RIGHT_NULL, args->mtpt, args->fsname);	return 0;error2:	if (mp->m_sb_bp)		xfs_freesb(mp);error1:	xfs_binval(mp->m_ddev_targp);	if (logdev && logdev != ddev)		xfs_binval(mp->m_logdev_targp);	if (rtdev)		xfs_binval(mp->m_rtdev_targp);error0:	xfs_unmountfs_close(mp, credp);	xfs_qmops_put(mp);	xfs_dmops_put(mp);	return error;}intxfs_unmount(	xfs_mount_t	*mp,	int		flags,	cred_t		*credp){	xfs_inode_t	*rip;	bhv_vnode_t	*rvp;	int		unmount_event_wanted = 0;	int		unmount_event_flags = 0;	int		xfs_unmountfs_needed = 0;	int		error;	rip = mp->m_rootip;	rvp = XFS_ITOV(rip);#ifdef HAVE_DMAPI	if (mp->m_flags & XFS_MOUNT_DMAPI) {		error = XFS_SEND_PREUNMOUNT(mp,				rvp, DM_RIGHT_NULL, rvp, DM_RIGHT_NULL,				NULL, NULL, 0, 0,				(mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))?					0:DM_FLAGS_UNWANTED);			if (error)				return XFS_ERROR(error);		unmount_event_wanted = 1;		unmount_event_flags = (mp->m_dmevmask & (1<<DM_EVENT_UNMOUNT))?					0 : DM_FLAGS_UNWANTED;	}#endif	/*	 * First blow any referenced inode from this file system	 * out of the reference cache, and delete the timer.	 */	xfs_refcache_purge_mp(mp);	/*	 * Blow away any referenced inode in the filestreams cache.	 * This can and will cause log traffic as inodes go inactive	 * here.	 */	xfs_filestream_unmount(mp);	XFS_bflush(mp->m_ddev_targp);	error = xfs_unmount_flush(mp, 0);	if (error)		goto out;	ASSERT(vn_count(rvp) == 1);	/*	 * Drop the reference count	 */	VN_RELE(rvp);	/*	 * If we're forcing a shutdown, typically because of a media error,	 * we want to make sure we invalidate dirty pages that belong to	 * referenced vnodes as well.	 */	if (XFS_FORCED_SHUTDOWN(mp)) {		error = xfs_sync(mp, SYNC_WAIT | SYNC_CLOSE);		ASSERT(error != EFSCORRUPTED);	}	xfs_unmountfs_needed = 1;out:	/*	Send DMAPI event, if required.	 *	Then do xfs_unmountfs() if needed.	 *	Then return error (or zero).	 */	if (unmount_event_wanted) {		/* Note: mp structure must still exist for		 * XFS_SEND_UNMOUNT() call.		 */		XFS_SEND_UNMOUNT(mp, error == 0 ? rvp : NULL,			DM_RIGHT_NULL, 0, error, unmount_event_flags);	}	if (xfs_unmountfs_needed) {		/*		 * Call common unmount function to flush to disk		 * and free the super block buffer & mount structures.		 */		xfs_unmountfs(mp, credp);		xfs_qmops_put(mp);		xfs_dmops_put(mp);		kmem_free(mp, sizeof(xfs_mount_t));	}	return XFS_ERROR(error);}STATIC intxfs_quiesce_fs(	xfs_mount_t		*mp){	int			count = 0, pincount;	xfs_refcache_purge_mp(mp);	xfs_flush_buftarg(mp->m_ddev_targp, 0);	xfs_finish_reclaim_all(mp, 0);	/* This loop must run at least twice.	 * The first instance of the loop will flush	 * most meta data but that will generate more	 * meta data (typically directory updates).	 * Which then must be flushed and logged before	 * we can write the unmount record.	 */	do {		xfs_syncsub(mp, SYNC_INODE_QUIESCE, NULL);		pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);		if (!pincount) {			delay(50);			count++;		}	} while (count < 2);	return 0;}/* * Second stage of a quiesce. The data is already synced, now we have to take * care of the metadata. New transactions are already blocked, so we need to * wait for any remaining transactions to drain out before proceding. */STATIC voidxfs_attr_quiesce(	xfs_mount_t	*mp){	/* wait for all modifications to complete */	while (atomic_read(&mp->m_active_trans) > 0)		delay(100);	/* flush inodes and push all remaining buffers out to disk */	xfs_quiesce_fs(mp);	ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);	/* Push the superblock and write an unmount record */	xfs_log_sbcount(mp, 1);	xfs_log_unmount_write(mp);	xfs_unmountfs_writesb(mp);}intxfs_mntupdate(	struct xfs_mount		*mp,	int				*flags,	struct xfs_mount_args		*args){	if (!(*flags & MS_RDONLY)) {			/* rw/ro -> rw */		if (mp->m_flags & XFS_MOUNT_RDONLY)			mp->m_flags &= ~XFS_MOUNT_RDONLY;		if (args->flags & XFSMNT_BARRIER) {			mp->m_flags |= XFS_MOUNT_BARRIER;			xfs_mountfs_check_barriers(mp);		} else {			mp->m_flags &= ~XFS_MOUNT_BARRIER;		}	} else if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {	/* rw -> ro */		xfs_filestream_flush(mp);		xfs_sync(mp, SYNC_DATA_QUIESCE);		xfs_attr_quiesce(mp);		mp->m_flags |= XFS_MOUNT_RDONLY;	}	return 0;}/* * xfs_unmount_flush implements a set of flush operation on special * inodes, which are needed as a separate set of operations so that * they can be called as part of relocation process. */intxfs_unmount_flush(	xfs_mount_t	*mp,		/* Mount structure we are getting					   rid of. */	int             relocation)	/* Called from vfs relocation. */{	xfs_inode_t	*rip = mp->m_rootip;	xfs_inode_t	*rbmip;	xfs_inode_t	*rsumip = NULL;	bhv_vnode_t	*rvp = XFS_ITOV(rip);	int		error;	xfs_ilock(rip, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);	xfs_iflock(rip);	/*	 * Flush out the real time inodes.	 */	if ((rbmip = mp->m_rbmip) != NULL) {		xfs_ilock(rbmip, XFS_ILOCK_EXCL);		xfs_iflock(rbmip);		error = xfs_iflush(rbmip, XFS_IFLUSH_SYNC);		xfs_iunlock(rbmip, XFS_ILOCK_EXCL);		if (error == EFSCORRUPTED)			goto fscorrupt_out;		ASSERT(vn_count(XFS_ITOV(rbmip)) == 1);		rsumip = mp->m_rsumip;		xfs_ilock(rsumip, XFS_ILOCK_EXCL);		xfs_iflock(rsumip);		error = xfs_iflush(rsumip, XFS_IFLUSH_SYNC);		xfs_iunlock(rsumip, XFS_ILOCK_EXCL);		if (error == EFSCORRUPTED)			goto fscorrupt_out;		ASSERT(vn_count(XFS_ITOV(rsumip)) == 1);	}	/*	 * Synchronously flush root inode to disk	 */	error = xfs_iflush(rip, XFS_IFLUSH_SYNC);	if (error == EFSCORRUPTED)		goto fscorrupt_out2;	if (vn_count(rvp) != 1 && !relocation) {		xfs_iunlock(rip, XFS_ILOCK_EXCL);		return XFS_ERROR(EBUSY);	}	/*	 * Release dquot that rootinode, rbmino and rsumino might be holding,	 * flush and purge the quota inodes.	 */	error = XFS_QM_UNMOUNT(mp);	if (error == EFSCORRUPTED)		goto fscorrupt_out2;	if (rbmip) {		VN_RELE(XFS_ITOV(rbmip));		VN_RELE(XFS_ITOV(rsumip));	}	xfs_iunlock(rip, XFS_ILOCK_EXCL);	return 0;fscorrupt_out:	xfs_ifunlock(rip);fscorrupt_out2:	xfs_iunlock(rip, XFS_ILOCK_EXCL);	return XFS_ERROR(EFSCORRUPTED);}/* * xfs_root extracts the root vnode from a vfs. * * vfsp -- the vfs struct for the desired file system * vpp  -- address of the caller's vnode pointer which should be *         set to the desired fs root vnode */intxfs_root(	xfs_mount_t	*mp,	bhv_vnode_t	**vpp){	bhv_vnode_t	*vp;	vp = XFS_ITOV(mp->m_rootip);	VN_HOLD(vp);	*vpp = vp;	return 0;}/* * xfs_statvfs * * Fill in the statvfs structure for the given file system.  We use * the superblock lock in the mount structure to ensure a consistent * snapshot of the counters returned. */intxfs_statvfs(	xfs_mount_t	*mp,	bhv_statvfs_t	*statp,	bhv_vnode_t	*vp){	__uint64_t	fakeinos;	xfs_extlen_t	lsize;	xfs_sb_t	*sbp;	unsigned long	s;	sbp = &(mp->m_sb);	statp->f_type = XFS_SB_MAGIC;	xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);	s = XFS_SB_LOCK(mp);	statp->f_bsize = sbp->sb_blocksize;	lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;	statp->f_blocks = sbp->sb_dblocks - lsize;	statp->f_bfree = statp->f_bavail =				sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);	fakeinos = statp->f_bfree << sbp->sb_inopblog;#if XFS_BIG_INUMS	fakeinos += mp->m_inoadd;#endif	statp->f_files =	    MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);	if (mp->m_maxicount)#if XFS_BIG_INUMS		if (!mp->m_inoadd)#endif			statp->f_files = min_t(typeof(statp->f_files),						statp->f_files,						mp->m_maxicount);	statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);	XFS_SB_UNLOCK(mp, s);	xfs_statvfs_fsid(statp, mp);	statp->f_namelen = MAXNAMELEN - 1;	if (vp)		XFS_QM_DQSTATVFS(xfs_vtoi(vp), statp);	return 0;}/* * xfs_sync flushes any pending I/O to file system vfsp. * * This routine is called by vfs_sync() to make sure that things make it * out to disk eventually, on sync() system calls to flush out everything, * and when the file system is unmounted.  For the vfs_sync() case, all * we really need to do is sync out the log to make all of our meta-data * updates permanent (except for timestamps).  For calls from pflushd(), * dirty pages are kept moving by calling pdflush() on the inodes * containing them.  We also flush the inodes that we can lock without * sleeping and the superblock if we can lock it without sleeping from * vfs_sync() so that items at the tail of the log are always moving out. * * Flags: *      SYNC_BDFLUSH - We're being called from vfs_sync() so we don't want *		       to sleep if we can help it.  All we really need *		       to do is ensure that the log is synced at least *		       periodically.  We also push the inodes and *		       superblock if we can lock them without sleeping *			and they are not pinned. *      SYNC_ATTR    - We need to flush the inodes.  If SYNC_BDFLUSH is not *		       set, then we really want to lock each inode and flush *		       it. *      SYNC_WAIT    - All the flushes that take place in this call should *		       be synchronous. *      SYNC_DELWRI  - This tells us to push dirty pages associated with *		       inodes.  SYNC_WAIT and SYNC_BDFLUSH are used to *		       determine if they should be flushed sync, async, or *		       delwri. *      SYNC_CLOSE   - This flag is passed when the system is being *		       unmounted.  We should sync and invalidate everything. *      SYNC_FSDATA  - This indicates that the caller would like to make *		       sure the superblock is safe on disk.  We can ensure *		       this by simply making sure the log gets flushed *		       if SYNC_BDFLUSH is set, and by actually writing it *		       out otherwise. *	SYNC_IOWAIT  - The caller wants us to wait for all data I/O to complete *		       before we return (including direct I/O). Forms the drain *		       side of the write barrier needed to safely quiesce the *		       filesystem. * */intxfs_sync(	xfs_mount_t	*mp,	int		flags){	int		error;	/*	 * Get the Quota Manager to flush the dquots.	 *	 * If XFS quota support is not enabled or this filesystem	 * instance does not use quotas XFS_QM_DQSYNC will always	 * return zero.	 */	error = XFS_QM_DQSYNC(mp, flags);	if (error) {		/*		 * If we got an IO error, we will be shutting down.		 * So, there's nothing more for us to do here.		 */		ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp));		if (XFS_FORCED_SHUTDOWN(mp))			return XFS_ERROR(error);	}	if (flags & SYNC_IOWAIT)		xfs_filestream_flush(mp);	return xfs_syncsub(mp, flags, NULL);}/* * xfs sync routine for internal use * * This routine supports all of the flags defined for the generic vfs_sync * interface as explained above under xfs_sync. * */intxfs_sync_inodes(	xfs_mount_t	*mp,	int		flags,	int             *bypassed){	xfs_inode_t	*ip = NULL;	xfs_inode_t	*ip_next;	xfs_buf_t	*bp;	bhv_vnode_t	*vp = NULL;	int		error;	int		last_error;	uint64_t	fflag;	uint		lock_flags;	uint		base_lock_flags;	boolean_t	mount_locked;	boolean_t	vnode_refed;	int		preempt;	xfs_dinode_t	*dip;	xfs_iptr_t	*ipointer;#ifdef DEBUG	boolean_t	ipointer_in = B_FALSE;#define IPOINTER_SET	ipointer_in = B_TRUE#define IPOINTER_CLR	ipointer_in = B_FALSE#else#define IPOINTER_SET#define IPOINTER_CLR#endif/* Insert a marker record into the inode list after inode ip. The list * must be locked when this is called. After the call the list will no * longer be locked. */#define IPOINTER_INSERT(ip, mp)	{ \		ASSERT(ipointer_in == B_FALSE); \		ipointer->ip_mnext = ip->i_mnext; \		ipointer->ip_mprev = ip; \		ip->i_mnext = (xfs_inode_t *)ipointer; \		ipointer->ip_mnext->i_mprev = (xfs_inode_t *)ipointer; \		preempt = 0; \		XFS_MOUNT_IUNLOCK(mp); \		mount_locked = B_FALSE; \		IPOINTER_SET; \	}/* Remove the marker from the inode list. If the marker was the only item * in the list then there are no remaining inodes and we should zero out * the whole list. If we are the current head of the list then move the head * past us. */#define IPOINTER_REMOVE(ip, mp)	{ \		ASSERT(ipointer_in == B_TRUE); \		if (ipointer->ip_mnext != (xfs_inode_t *)ipointer) { \			ip = ipointer->ip_mnext; \			ip->i_mprev = ipointer->ip_mprev; \			ipointer->ip_mprev->i_mnext = ip; \			if (mp->m_inodes == (xfs_inode_t *)ipointer) { \				mp->m_inodes = ip; \			} \		} else { \			ASSERT(mp->m_inodes == (xfs_inode_t *)ipointer); \			mp->m_inodes = NULL; \			ip = NULL; \		} \		IPOINTER_CLR; \	}#define XFS_PREEMPT_MASK	0x7f	if (bypassed)		*bypassed = 0;	if (mp->m_flags & XFS_MOUNT_RDONLY)		return 0;	error = 0;	last_error = 0;	preempt = 0;	/* Allocate a reference marker */	ipointer = (xfs_iptr_t *)kmem_zalloc(sizeof(xfs_iptr_t), KM_SLEEP);	fflag = XFS_B_ASYNC;		/* default is don't wait */	if (flags & (SYNC_BDFLUSH | SYNC_DELWRI))		fflag = XFS_B_DELWRI;	if (flags & SYNC_WAIT)		fflag = 0;		/* synchronous overrides all */

⌨️ 快捷键说明

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