Skip to contentSkip to conversation

XFS: clean up sync code

PATCH New Dave Chinner 1 participant 11 messages Oct 7, 2008 XFS filesystem

lore
Share & tools
lore
#0 lore raw

cover XFS: clean up sync code

xfs_sync and xfs_syncsub are multiplexed interfaces that shares relatively little code between callers. Because it is a multiplexed interface, it's hard to tell what is executed in each context it is called.

Factor out the sync code and explicitly call the sync functions needed rather than the multiplexed interfaces. Once this is done, we can remove xfs_syncsub and xfs_sync altogether.

#1 lore raw

PATCH 1/10 XFS: split out two helpers from xfs_syncsub

From: Christoph Hellwig <[email protected]>

Split out two helpers from xfs_syncsub for the dummy log commit and the superblock writeout.

---
 fs/xfs/linux-2.6/xfs_sync.c |  162 +++++++++++++++++++++++++------------------
 1 files changed, 93 insertions(+), 69 deletions(-)
fs/xfs/linux-2.6/xfs_sync.c +93 -69
index 53d85ec..59da332 100644
@@ -315,6 +315,93 @@ xfs_sync_inodes(
 	return XFS_ERROR(last_error);
 }
 
+STATIC int
+xfs_commit_dummy_trans(
+	struct xfs_mount	*mp,
+	uint			log_flags)
+{
+	struct xfs_inode	*ip = mp->m_rootip;
+	struct xfs_trans	*tp;
+	int			error;
+
+	/*
+	 * Put a dummy transaction in the log to tell recovery
+	 * that all others are OK.
+	 */
+	tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
+	error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
+	if (error) {
+		xfs_trans_cancel(tp, 0);
+		return error;
+	}
+
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+	xfs_trans_ihold(tp, ip);
+	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+	/* XXX(hch): ignoring the error here.. */
+	error = xfs_trans_commit(tp, 0);
+
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+	xfs_log_force(mp, 0, log_flags);
+	return 0;
+}
+
+STATIC int
+xfs_sync_fsdata(
+	struct xfs_mount	*mp,
+	int			flags)
+{
+	struct xfs_buf		*bp;
+	struct xfs_buf_log_item	*bip;
+	int			error = 0;
+
+	/*
+	 * If this is xfssyncd() then only sync the superblock if we can
+	 * lock it without sleeping and it is not pinned.
+	 */
+	if (flags & SYNC_BDFLUSH) {
+		ASSERT(!(flags & SYNC_WAIT));
+
+		bp = xfs_getsb(mp, XFS_BUF_TRYLOCK);
+		if (!bp)
+			goto out;
+
+		bip = XFS_BUF_FSPRIVATE(bp, struct xfs_buf_log_item *);
+		if (!bip || !xfs_buf_item_dirty(bip) || XFS_BUF_ISPINNED(bp))
+			goto out_brelse;
+	} else {
+		bp = xfs_getsb(mp, 0);
+
+		/*
+		 * If the buffer is pinned then push on the log so we won't
+		 * get stuck waiting in the write for someone, maybe
+		 * ourselves, to flush the log.
+		 *
+		 * Even though we just pushed the log above, we did not have
+		 * the superblock buffer locked at that point so it can
+		 * become pinned in between there and here.
+		 */
+		if (XFS_BUF_ISPINNED(bp))
+			xfs_log_force(mp, 0, XFS_LOG_FORCE);
+	}
+
+
+	if (flags & SYNC_WAIT)
+		XFS_BUF_UNASYNC(bp);
+	else
+		XFS_BUF_ASYNC(bp);
+
+	return xfs_bwrite(mp, bp);
+
+ out_brelse:
+	xfs_buf_relse(bp);
+ out:
+	return error;
+}
+
 /*
  * xfs sync routine for internal use
  *
@@ -331,8 +418,6 @@ xfs_syncsub(
 	int		error = 0;
 	int		last_error = 0;
 	uint		log_flags = XFS_LOG_FORCE;
-	xfs_buf_t	*bp;
-	xfs_buf_log_item_t	*bip;
 
 	/*
 	 * Sync out the log.  This ensures that the log is periodically
@@ -355,83 +440,22 @@ xfs_syncsub(
 	 * log activity, so if this isn't vfs_sync() then flush
 	 * the log again.
 	 */
-	if (flags & SYNC_DELWRI) {
-		xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
-	}
+	if (flags & SYNC_DELWRI)
+		xfs_log_force(mp, 0, log_flags);
 
 	if (flags & SYNC_FSDATA) {
-		/*
-		 * If this is vfs_sync() then only sync the superblock
-		 * if we can lock it without sleeping and it is not pinned.
-		 */
-		if (flags & SYNC_BDFLUSH) {
-			bp = xfs_getsb(mp, XFS_BUF_TRYLOCK);
-			if (bp != NULL) {
-				bip = XFS_BUF_FSPRIVATE(bp,xfs_buf_log_item_t*);
-				if ((bip != NULL) &&
-				    xfs_buf_item_dirty(bip)) {
-					if (!(XFS_BUF_ISPINNED(bp))) {
-						XFS_BUF_ASYNC(bp);
-						error = xfs_bwrite(mp, bp);
-					} else {
-						xfs_buf_relse(bp);
-					}
-				} else {
-					xfs_buf_relse(bp);
-				}
-			}
-		} else {
-			bp = xfs_getsb(mp, 0);
-			/*
-			 * If the buffer is pinned then push on the log so
-			 * we won't get stuck waiting in the write for
-			 * someone, maybe ourselves, to flush the log.
-			 * Even though we just pushed the log above, we
-			 * did not have the superblock buffer locked at
-			 * that point so it can become pinned in between
-			 * there and here.
-			 */
-			if (XFS_BUF_ISPINNED(bp))
-				xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
-			if (flags & SYNC_WAIT)
-				XFS_BUF_UNASYNC(bp);
-			else
-				XFS_BUF_ASYNC(bp);
-			error = xfs_bwrite(mp, bp);
-		}
-		if (error) {
+		error = xfs_sync_fsdata(mp, flags);
+		if (error)
 			last_error = error;
-		}
 	}
 
 	/*
 	 * Now check to see if the log needs a "dummy" transaction.
 	 */
 	if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) {
-		xfs_trans_t *tp;
-		xfs_inode_t *ip;
-
-		/*
-		 * Put a dummy transaction in the log to tell
-		 * recovery that all others are OK.
-		 */
-		tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
-		if ((error = xfs_trans_reserve(tp, 0,
-				XFS_ICHANGE_LOG_RES(mp),
-				0, 0, 0)))  {
-			xfs_trans_cancel(tp, 0);
+		error = xfs_commit_dummy_trans(mp, log_flags);
+		if (error)
 			return error;
-		}
-
-		ip = mp->m_rootip;
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-
-		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-		xfs_trans_ihold(tp, ip);
-		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-		error = xfs_trans_commit(tp, 0);
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
 	}
 
 	/*
Signature · 1 line
1.5.6.5
#2 lore raw

PATCH 2/10 XFS: Use struct inodes instead of vnodes to kill vn_grab

In reply to Dave Chinner

With the sync code relocated to the linux-2.6 directory we can use struct inodes directly. If we do the same thing for the quota release code, we can remove vn_grab altogether. While here, convert the VN_BAD() checks to is_bad_inode() so we can remove vnodes entirely from this code.

---
 fs/xfs/linux-2.6/xfs_sync.c    |   53 +++++++++++++++++++--------------------
 fs/xfs/linux-2.6/xfs_vnode.c   |    6 ++--
 fs/xfs/linux-2.6/xfs_vnode.h   |    5 ----
 fs/xfs/quota/xfs_qm_syscalls.c |   16 ++++++------
 4 files changed, 37 insertions(+), 43 deletions(-)
fs/xfs/linux-2.6/xfs_sync.c +26 -27
index 59da332..461c1dc 100644
@@ -131,10 +131,7 @@ xfs_sync_inodes_ag(
 	int		flags,
 	int		*bypassed)
 {
-	xfs_inode_t	*ip = NULL;
-	struct inode	*vp = NULL;
 	xfs_perag_t	*pag = &mp->m_perag[ag];
-	boolean_t	vnode_refed = B_FALSE;
 	int		nr_found;
 	int		first_index = 0;
 	int		error = 0;
@@ -156,6 +153,10 @@ xfs_sync_inodes_ag(
 	}
 
 	do {
+		struct inode	*inode;
+		boolean_t	inode_refed;
+		xfs_inode_t	*ip = NULL;
+
 		/*
 		 * use a gang lookup to find the next inode in the tree
 		 * as the tree is sparse and a gang lookup walks to find
@@ -177,14 +178,14 @@ xfs_sync_inodes_ag(
 		 * skip inodes in reclaim. Let xfs_syncsub do that for
 		 * us so we don't need to worry.
 		 */
-		vp = VFS_I(ip);
-		if (!vp) {
+		if (xfs_iflags_test(ip, (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
 			read_unlock(&pag->pag_ici_lock);
 			continue;
 		}
 
 		/* bad inodes are dealt with elsewhere */
-		if (VN_BAD(vp)) {
+		inode = VFS_I(ip);
+		if (is_bad_inode(inode)) {
 			read_unlock(&pag->pag_ici_lock);
 			continue;
 		}
@@ -196,30 +197,29 @@ xfs_sync_inodes_ag(
 		}
 
 		/*
-		 * The inode lock here actually coordinates with the almost
-		 * spurious inode lock in xfs_ireclaim() to prevent the vnode
-		 * we handle here without a reference from being freed while we
-		 * reference it.  If we lock the inode while it's on the mount
-		 * list here, then the spurious inode lock in xfs_ireclaim()
-		 * after the inode is pulled from the mount list will sleep
-		 * until we release it here.  This keeps the vnode from being
-		 * freed while we reference it.
+		 * If we can't get a reference on the VFS_I, the inode must be
+		 * in reclaim. If we can get the inode lock without blocking,
+		 * it is safe to flush the inode because we hold the tree lock
+		 * and xfs_iextract will block right now. Hence if we lock the
+		 * inode while holding the tree lock, xfs_ireclaim() is
+		 * guaranteed to block on the inode lock we now hold and hence
+		 * it is safe to reference the inode until we drop the inode
+		 * locks completely.
 		 */
-		if (xfs_ilock_nowait(ip, lock_flags) == 0) {
-			vp = vn_grab(vp);
+		inode_refed = B_FALSE;
+		if (igrab(inode)) {
 			read_unlock(&pag->pag_ici_lock);
-			if (!vp)
-				continue;
 			xfs_ilock(ip, lock_flags);
-
-			ASSERT(vp == VFS_I(ip));
-			ASSERT(ip->i_mount == mp);
-
-			vnode_refed = B_TRUE;
+			inode_refed = B_TRUE;
 		} else {
-			/* safe to unlock here as we have a reference */
+			if (!xfs_ilock_nowait(ip, lock_flags)) {
+				/* leave it to reclaim */
+				read_unlock(&pag->pag_ici_lock);
+				continue;
+			}
 			read_unlock(&pag->pag_ici_lock);
 		}
+
 		/*
 		 * If we have to flush data or wait for I/O completion
 		 * we need to drop the ilock that we currently hold.
@@ -240,7 +240,7 @@ xfs_sync_inodes_ag(
 			xfs_ilock(ip, XFS_ILOCK_SHARED);
 		}
 
-		if ((flags & SYNC_DELWRI) && VN_DIRTY(vp)) {
+		if ((flags & SYNC_DELWRI) && VN_DIRTY(inode)) {
 			xfs_iunlock(ip, XFS_ILOCK_SHARED);
 			error = xfs_flush_pages(ip, 0, -1, fflag, FI_NONE);
 			if (flags & SYNC_IOWAIT)
@@ -268,9 +268,8 @@ xfs_sync_inodes_ag(
 		if (lock_flags)
 			xfs_iunlock(ip, lock_flags);
 
-		if (vnode_refed) {
+		if (inode_refed) {
 			IRELE(ip);
-			vnode_refed = B_FALSE;
 		}
 
 		if (error)
fs/xfs/linux-2.6/xfs_vnode.c +3 -3
index b52528b..dceb6db 100644
@@ -90,10 +90,10 @@ vn_ioerror(
  */
 static inline int xfs_icount(struct xfs_inode *ip)
 {
-	struct inode *vp = VFS_I(ip);
+	struct inode *inode = VFS_I(ip);
 
-	if (vp)
-		return vn_count(vp);
+	if (!inode)
+		return atomic_read(&inode->i_count);
 	return -1;
 }
 
fs/xfs/linux-2.6/xfs_vnode.h +0 -5
index 683ce16..bf89e41 100644
@@ -80,11 +80,6 @@ do { \
 	iput(VFS_I(ip)); \
 } while (0)
 
-static inline struct inode *vn_grab(struct inode *vp)
-{
-	return igrab(vp);
-}
-
 /*
  * Dealing with bad inodes
  */
fs/xfs/quota/xfs_qm_syscalls.c +8 -8
index 26152b9..4254b07 100644
@@ -1031,13 +1031,13 @@ xfs_qm_dqrele_inodes_ag(
 	uint		flags)
 {
 	xfs_inode_t	*ip = NULL;
-	struct inode	*vp = NULL;
 	xfs_perag_t	*pag = &mp->m_perag[ag];
 	int		first_index = 0;
 	int		nr_found;
 
 	do {
-		boolean_t	vnode_refd = B_FALSE;
+		boolean_t	inode_refed;
+		struct inode	*inode;
 
 		/*
 		 * use a gang lookup to find the next inode in the tree
@@ -1057,19 +1057,19 @@ xfs_qm_dqrele_inodes_ag(
 		first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
 
 		/* skip quota inodes and those in reclaim */
-		vp = VFS_I(ip);
-		if (!vp || ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) {
+		inode = VFS_I(ip);
+		if (!inode || ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) {
 			ASSERT(ip->i_udquot == NULL);
 			ASSERT(ip->i_gdquot == NULL);
 			read_unlock(&pag->pag_ici_lock);
 			continue;
 		}
 		if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) {
-			vp = vn_grab(vp);
+			inode = igrab(inode);
 			read_unlock(&pag->pag_ici_lock);
-			if (!vp)
+			if (!inode)
 				continue;
-			vnode_refd = B_TRUE;
+			inode_refed = B_TRUE;
 			xfs_ilock(ip, XFS_ILOCK_EXCL);
 		} else {
 			read_unlock(&pag->pag_ici_lock);
@@ -1084,7 +1084,7 @@ xfs_qm_dqrele_inodes_ag(
 			ip->i_gdquot = NULL;
 		}
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		if (vnode_refd)
+		if (inode_refed)
 			IRELE(ip);
 	} while (nr_found);
 }
Signature · 1 line
1.5.6.5
#3 lore raw

PATCH 3/10 XFS: use xfs_sync_inodes rather than xfs_syncsub

In reply to Dave Chinner

Kill the unused arg in xfs_syncsub() and xfs_sync_inodes(). For callers of xfs_syncsub() that only want to flush inodes, replace xfs_syncsub() with direct calls to xfs_sync_inodes() as that is all that is being done with the specific flags being passed in.

---
 fs/xfs/linux-2.6/xfs_sync.c    |   21 +++++++--------------
 fs/xfs/linux-2.6/xfs_sync.h    |    2 +-
 fs/xfs/quota/xfs_qm_syscalls.c |    2 +-
 fs/xfs/xfs_mount.h             |    2 --
 fs/xfs/xfs_vfsops.c            |   14 +++++++-------
 5 files changed, 16 insertions(+), 25 deletions(-)
fs/xfs/linux-2.6/xfs_sync.c +7 -14
index 461c1dc..7e9fb52 100644
@@ -117,7 +117,7 @@ xfs_sync(
 	if (flags & SYNC_IOWAIT)
 		xfs_filestream_flush(mp);
 
-	return xfs_syncsub(mp, flags, NULL);
+	return xfs_syncsub(mp, flags);
 }
 
 /*
@@ -128,8 +128,7 @@ STATIC int
 xfs_sync_inodes_ag(
 	xfs_mount_t	*mp,
 	int		ag,
-	int		flags,
-	int		*bypassed)
+	int		flags)
 {
 	xfs_perag_t	*pag = &mp->m_perag[ag];
 	int		nr_found;
@@ -260,8 +259,6 @@ xfs_sync_inodes_ag(
 					error = xfs_iflush(ip, XFS_IFLUSH_DELWRI);
 				else
 					xfs_ifunlock(ip);
-			} else if (bypassed) {
-				(*bypassed)++;
 			}
 		}
 
@@ -288,15 +285,12 @@ xfs_sync_inodes_ag(
 int
 xfs_sync_inodes(
 	xfs_mount_t	*mp,
-	int		flags,
-	int             *bypassed)
+	int		flags)
 {
 	int		error;
 	int		last_error;
 	int		i;
 
-	if (bypassed)
-		*bypassed = 0;
 	if (mp->m_flags & XFS_MOUNT_RDONLY)
 		return 0;
 	error = 0;
@@ -305,7 +299,7 @@ xfs_sync_inodes(
 	for (i = 0; i < mp->m_sb.sb_agcount; i++) {
 		if (!mp->m_perag[i].pag_ici_init)
 			continue;
-		error = xfs_sync_inodes_ag(mp, i, flags, bypassed);
+		error = xfs_sync_inodes_ag(mp, i, flags);
 		if (error)
 			last_error = error;
 		if (error == EFSCORRUPTED)
@@ -408,11 +402,10 @@ xfs_sync_fsdata(
  * interface as explained above under xfs_sync.
  *
  */
-int
+STATIC int
 xfs_syncsub(
 	xfs_mount_t	*mp,
-	int		flags,
-	int             *bypassed)
+	int		flags)
 {
 	int		error = 0;
 	int		last_error = 0;
@@ -431,7 +424,7 @@ xfs_syncsub(
 		if (flags & SYNC_BDFLUSH)
 			xfs_finish_reclaim_all(mp, 1, XFS_IFLUSH_DELWRI_ELSE_ASYNC);
 		else
-			error = xfs_sync_inodes(mp, flags, bypassed);
+			error = xfs_sync_inodes(mp, flags);
 	}
 
 	/*
fs/xfs/linux-2.6/xfs_sync.h +1 -1
index 3746d15..2954861 100644
@@ -55,7 +55,7 @@ int xfs_syncd_init(struct xfs_mount *mp);
 void xfs_syncd_stop(struct xfs_mount *mp);
 
 int xfs_sync(struct xfs_mount *mp, int flags);
-int xfs_syncsub(struct xfs_mount *mp, int flags, int *bypassed);
+int xfs_sync_inodes(struct xfs_mount *mp, int flags);
 
 void xfs_flush_inode(struct xfs_inode *ip);
 void xfs_flush_device(struct xfs_inode *ip);
fs/xfs/quota/xfs_qm_syscalls.c +1 -1
index 4254b07..9ff28e6 100644
@@ -127,7 +127,7 @@ xfs_qm_quotactl(
 		break;
 
 	case Q_XQUOTASYNC:
-		return (xfs_sync_inodes(mp, SYNC_DELWRI, NULL));
+		return xfs_sync_inodes(mp, SYNC_DELWRI);
 
 	default:
 		break;
fs/xfs/xfs_mount.h +0 -2
index dfa307d..7e02a86 100644
@@ -524,8 +524,6 @@ extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
 extern int	xfs_readsb(xfs_mount_t *, int);
 extern void	xfs_freesb(xfs_mount_t *);
 extern int	xfs_fs_writable(xfs_mount_t *);
-extern int	xfs_syncsub(xfs_mount_t *, int, int *);
-extern int	xfs_sync_inodes(xfs_mount_t *, int, int *);
 extern int	xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
 
 extern int	xfs_dmops_get(struct xfs_mount *, struct xfs_mount_args *);
fs/xfs/xfs_vfsops.c +7 -7
index 0c5ee5e..d5396d6 100644
@@ -68,15 +68,15 @@ xfs_quiesce_fs(
 	xfs_flush_buftarg(mp->m_ddev_targp, 0);
 	xfs_finish_reclaim_all(mp, 0, XFS_IFLUSH_DELWRI_ELSE_ASYNC);
 
-	/* 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.
+	/*
+	 * 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);
+		xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);
+		xfs_sync_inodes(mp, SYNC_INODE_QUIESCE);
 		pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
 		if (!pincount) {
 			delay(50);
Signature · 1 line
1.5.6.5
#4 lore raw

PATCH 4/10 XFS: kill xfs_syncsub

In reply to Dave Chinner

Now that the only caller is xfs_sync(), merge the two together as it makes no sense to keep them separate.

---
 fs/xfs/linux-2.6/xfs_sync.c |  141 +++++++++++++++++++------------------------
 1 files changed, 62 insertions(+), 79 deletions(-)
fs/xfs/linux-2.6/xfs_sync.c +62 -79
index 7e9fb52..d4b7b21 100644
@@ -48,79 +48,6 @@
 #include <linux/freezer.h>
 
 /*
- * 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.
- *
- */
-int
-xfs_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);
-}
-
-/*
  * Sync all the inodes in the given AG according to the
  * direction given by the flags.
  */
@@ -396,22 +323,78 @@ xfs_sync_fsdata(
 }
 
 /*
- * xfs sync routine for internal use
+ * xfs_sync flushes any pending I/O to file system vfsp.
  *
- * This routine supports all of the flags defined for the generic vfs_sync
- * interface as explained above under xfs_sync.
+ * 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.
  *
  */
-STATIC int
-xfs_syncsub(
+int
+xfs_sync(
 	xfs_mount_t	*mp,
 	int		flags)
 {
-	int		error = 0;
+	int		error;
 	int		last_error = 0;
 	uint		log_flags = XFS_LOG_FORCE;
 
 	/*
+	 * 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);
+
+	/*
 	 * Sync out the log.  This ensures that the log is periodically
 	 * flushed even if there is not enough activity to fill it up.
 	 */
Signature · 1 line
1.5.6.5
#5 lore raw

PATCH 5/10 XFS: xfssyncd: don't call xfs_sync

In reply to Dave Chinner

Start de-multiplexing xfs_sync() by making xfs_sync_worker() call the specific sync functions it needs. This is only a small, unique subset of the entire xfs_sync() code so is easier to follow.

---
 fs/xfs/linux-2.6/xfs_sync.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)
fs/xfs/linux-2.6/xfs_sync.c +14 -2
index d4b7b21..3c31137 100644
@@ -526,6 +526,11 @@ xfs_flush_device(
 	xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
 }
 
+/*
+ * Every sync period we need to unpin all items, reclaim inodes, sync
+ * quota and write out the superblock. We might need to cover the log
+ * to indicate it is idle.
+ */
 STATIC void
 xfs_sync_worker(
 	struct xfs_mount *mp,
@@ -533,8 +538,15 @@ xfs_sync_worker(
 {
 	int		error;
 
-	if (!(mp->m_flags & XFS_MOUNT_RDONLY))
-		error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR);
+	if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
+		xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
+		xfs_finish_reclaim_all(mp, 1, XFS_IFLUSH_DELWRI_ELSE_ASYNC);
+		/* dgc: errors ignored here */
+		error = XFS_QM_DQSYNC(mp, SYNC_BDFLUSH);
+		error = xfs_sync_fsdata(mp, SYNC_BDFLUSH);
+		if (xfs_log_need_covered(mp))
+			error = xfs_commit_dummy_trans(mp, XFS_LOG_FORCE);
+	}
 	mp->m_sync_seq++;
 	wake_up(&mp->m_wait_single_sync_task);
 }
Signature · 1 line
1.5.6.5
#6 lore raw

PATCH 6/10 XFS: make SYNC_ATTR no longer use xfs_sync

In reply to Dave Chinner

Continue to de-multiplex xfs_sync be replacing all SYNC_ATTR callers with direct calls xfs_sync_inodes(). Add an assert into xfs_sync() to ensure we caught all the SYNC_ATTR callers.

---
 fs/xfs/linux-2.6/xfs_super.c |    3 ++-
 fs/xfs/linux-2.6/xfs_sync.c  |   23 +++++++++++------------
 fs/xfs/linux-2.6/xfs_sync.h  |    1 -
 fs/xfs/xfs_vfsops.c          |    2 +-
 4 files changed, 14 insertions(+), 15 deletions(-)
fs/xfs/linux-2.6/xfs_super.c +2 -1
index ab09f6a..17958b7 100644
@@ -998,7 +998,8 @@ xfs_fs_put_super(
 	int			error;
 
 	xfs_syncd_stop(mp);
-	xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI);
+	xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);
+	xfs_sync_inodes(mp, SYNC_ATTR|SYNC_DELWRI);
 
 #ifdef HAVE_DMAPI
 	if (mp->m_flags & XFS_MOUNT_DMAPI) {
fs/xfs/linux-2.6/xfs_sync.c +11 -12
index 3c31137..002ccb6 100644
@@ -342,9 +342,8 @@ xfs_sync_fsdata(
  *		       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_ATTR    - We need to flush the inodes. Now handled by direct calls
+ *		       to xfs_sync_inodes().
  *      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
@@ -373,6 +372,8 @@ xfs_sync(
 	int		last_error = 0;
 	uint		log_flags = XFS_LOG_FORCE;
 
+	ASSERT(!(flags & SYNC_ATTR));
+
 	/*
 	 * Get the Quota Manager to flush the dquots.
 	 *
@@ -403,20 +404,18 @@ xfs_sync(
 
 	xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
 
-	if (flags & (SYNC_ATTR|SYNC_DELWRI)) {
+	if (flags & SYNC_DELWRI) {
 		if (flags & SYNC_BDFLUSH)
 			xfs_finish_reclaim_all(mp, 1, XFS_IFLUSH_DELWRI_ELSE_ASYNC);
 		else
 			error = xfs_sync_inodes(mp, flags);
-	}
-
-	/*
-	 * Flushing out dirty data above probably generated more
-	 * log activity, so if this isn't vfs_sync() then flush
-	 * the log again.
-	 */
-	if (flags & SYNC_DELWRI)
+		/*
+		 * Flushing out dirty data above probably generated more
+		 * log activity, so if this isn't vfs_sync() then flush
+		 * the log again.
+		 */
 		xfs_log_force(mp, 0, log_flags);
+	}
 
 	if (flags & SYNC_FSDATA) {
 		error = xfs_sync_fsdata(mp, flags);
fs/xfs/linux-2.6/xfs_sync.h +0 -1
index 2954861..5316915 100644
@@ -49,7 +49,6 @@ typedef struct bhv_vfs_sync_work {
  * to disk (this is the main difference between a sync and a quiesce).
  */
 #define SYNC_DATA_QUIESCE	(SYNC_DELWRI|SYNC_FSDATA|SYNC_WAIT|SYNC_IOWAIT)
-#define SYNC_INODE_QUIESCE	(SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)
 
 int xfs_syncd_init(struct xfs_mount *mp);
 void xfs_syncd_stop(struct xfs_mount *mp);
fs/xfs/xfs_vfsops.c +1 -1
index d5396d6..c82b955 100644
@@ -76,7 +76,7 @@ xfs_quiesce_fs(
 	 */
 	do {
 		xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);
-		xfs_sync_inodes(mp, SYNC_INODE_QUIESCE);
+		xfs_sync_inodes(mp, SYNC_ATTR|SYNC_WAIT);
 		pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
 		if (!pincount) {
 			delay(50);
Signature · 1 line
1.5.6.5
#7 lore raw

PATCH 7/10 XFS: make SYNC_DELWRI no longer use xfs_sync V2

In reply to Dave Chinner

Continue to de-multiplex xfs_sync be replacing all SYNC_DELWRI callers with direct calls functions that do the work. Isolate the data quiesce case to a function in xfs_sync.c. Isolate the FSDATA case with explicit calls to xfs_sync_fsdata().

Version 2:
o Push delwri related log forces into xfs_sync_inodes().

---
 fs/xfs/linux-2.6/xfs_super.c |   25 ++++++-------------------
 fs/xfs/linux-2.6/xfs_sync.c  |   42 +++++++++++++++++++++++++++++++++++++++++-
 fs/xfs/linux-2.6/xfs_sync.h  |    3 +++
 fs/xfs/xfs_vfsops.c          |    1 -
 4 files changed, 50 insertions(+), 21 deletions(-)
fs/xfs/linux-2.6/xfs_super.c +6 -19
index 17958b7..4d9762c 100644
@@ -998,7 +998,6 @@ xfs_fs_put_super(
 	int			error;
 
 	xfs_syncd_stop(mp);
-	xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);
 	xfs_sync_inodes(mp, SYNC_ATTR|SYNC_DELWRI);
 
 #ifdef HAVE_DMAPI
@@ -1057,7 +1056,7 @@ xfs_fs_write_super(
 	struct super_block	*sb)
 {
 	if (!(sb->s_flags & MS_RDONLY))
-		xfs_sync(XFS_M(sb), SYNC_FSDATA);
+		xfs_sync_fsdata(XFS_M(sb), 0);
 	sb->s_dirt = 0;
 }
 
@@ -1068,7 +1067,6 @@ xfs_fs_sync_super(
 {
 	struct xfs_mount	*mp = XFS_M(sb);
 	int			error;
-	int			flags;
 
 	/*
 	 * Treat a sync operation like a freeze.  This is to work
@@ -1082,20 +1080,10 @@ xfs_fs_sync_super(
 	 * dirty the Linux inode until after the transaction I/O
 	 * completes.
 	 */
-	if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
-		/*
-		 * First stage of freeze - no more writers will make progress
-		 * now we are here, so we flush delwri and delalloc buffers
-		 * here, then wait for all I/O to complete.  Data is frozen at
-		 * that point. Metadata is not frozen, transactions can still
-		 * occur here so don't bother flushing the buftarg (i.e
-		 * SYNC_QUIESCE) because it'll just get dirty again.
-		 */
-		flags = SYNC_DATA_QUIESCE;
-	} else
-		flags = SYNC_FSDATA;
-
-	error = xfs_sync(mp, flags);
+	if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE))
+		error = xfs_quiesce_data(mp);
+	else
+		error = xfs_sync_fsdata(mp, 0);
 	sb->s_dirt = 0;
 
 	if (unlikely(laptop_mode)) {
@@ -1233,8 +1221,7 @@ xfs_fs_remount(
 
 	/* rw -> ro */
 	if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) {
-		xfs_filestream_flush(mp);
-		xfs_sync(mp, SYNC_DATA_QUIESCE);
+		xfs_quiesce_data(mp);
 		xfs_attr_quiesce(mp);
 		mp->m_flags |= XFS_MOUNT_RDONLY;
 	}
fs/xfs/linux-2.6/xfs_sync.c +41 -1

72 lines not on this page · raw message

fs/xfs/linux-2.6/xfs_sync.h +3 -0
index 5316915..fcd4040 100644
@@ -55,6 +55,9 @@ void xfs_syncd_stop(struct xfs_mount *mp);
 
 int xfs_sync(struct xfs_mount *mp, int flags);
 int xfs_sync_inodes(struct xfs_mount *mp, int flags);
+int xfs_sync_fsdata(struct xfs_mount *mp, int flags);
+
+int xfs_quiesce_data(struct xfs_mount *mp);
 
 void xfs_flush_inode(struct xfs_inode *ip);
 void xfs_flush_device(struct xfs_inode *ip);
fs/xfs/xfs_vfsops.c +0 -1
index c82b955..b55a9bb 100644
@@ -75,7 +75,6 @@ xfs_quiesce_fs(
 	 * logged before we can write the unmount record.
 	 */
 	do {
-		xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);
 		xfs_sync_inodes(mp, SYNC_ATTR|SYNC_WAIT);
 		pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
 		if (!pincount) {
Signature · 1 line
1.5.6.5
#8 lore raw

PATCH 8/10 XFS: Kill SYNC_CLOSE

In reply to Dave Chinner

SYNC_CLOSE is only ever used and checked in conjunction with SYNC_WAIT, and this only done in one spot. The only thing this does is make XFS_bflush() calls to the data buftargs.

This will happen very shortly afterwards the xfs_sync() call anyway in the unmount path via the xfs_close_devices(), so this code is redundant and can be removed. That only user of SYNC_CLOSE is now gone, so kill the flag completely.

---
 fs/xfs/linux-2.6/xfs_super.c |   10 ----------
 fs/xfs/linux-2.6/xfs_sync.c  |   31 ++-----------------------------
 fs/xfs/linux-2.6/xfs_sync.h  |    1 -
 3 files changed, 2 insertions(+), 40 deletions(-)
fs/xfs/linux-2.6/xfs_super.c +0 -10
index 4d9762c..9cd49dc 100644
@@ -1026,16 +1026,6 @@ xfs_fs_put_super(
 	error = xfs_unmount_flush(mp, 0);
 	WARN_ON(error);
 
-	/*
-	 * 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);
-	}
-
 	if (mp->m_flags & XFS_MOUNT_DMAPI) {
 		XFS_SEND_UNMOUNT(mp, rip, DM_RIGHT_NULL, 0, 0,
 				unmount_event_flags);
fs/xfs/linux-2.6/xfs_sync.c +2 -29
index 838070c..91a54a7 100644
@@ -70,7 +70,7 @@ xfs_sync_inodes_ag(
 	if (flags & SYNC_WAIT)
 		fflag = 0;		/* synchronous overrides all */
 
-	if (flags & (SYNC_DELWRI | SYNC_CLOSE)) {
+	if (flags & SYNC_DELWRI) {
 		/*
 		 * We need the I/O lock if we're going to call any of
 		 * the flush/inval routines.
@@ -117,7 +117,7 @@ xfs_sync_inodes_ag(
 		}
 
 		/* nothing to sync during shutdown */
-		if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
+		if (XFS_FORCED_SHUTDOWN(mp)) {
 			read_unlock(&pag->pag_ici_lock);
 			return 0;
 		}
@@ -152,20 +152,6 @@ xfs_sync_inodes_ag(
 		 * If we need to drop the lock, insert a marker if we
 		 * have not already done so.
 		 */
-		if (flags & SYNC_CLOSE) {
-			xfs_iunlock(ip, XFS_ILOCK_SHARED);
-			if (XFS_FORCED_SHUTDOWN(mp))
-				xfs_tosspages(ip, 0, -1, FI_REMAPF);
-			else
-				error = xfs_flushinval_pages(ip, 0, -1,
-							FI_REMAPF);
-			/* wait for I/O on freeze */
-			if (flags & SYNC_IOWAIT)
-				vn_iowait(ip);
-
-			xfs_ilock(ip, XFS_ILOCK_SHARED);
-		}
-
 		if ((flags & SYNC_DELWRI) && VN_DIRTY(inode)) {
 			xfs_iunlock(ip, XFS_ILOCK_SHARED);
 			error = xfs_flush_pages(ip, 0, -1, fflag, FI_NONE);
@@ -390,8 +376,6 @@ xfs_quiesce_data(
  *		       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
@@ -472,17 +456,6 @@ xfs_sync(
 			return error;
 	}
 
-	/*
-	 * When shutting down, we need to insure that the AIL is pushed
-	 * to disk or the filesystem can appear corrupt from the PROM.
-	 */
-	if ((flags & (SYNC_CLOSE|SYNC_WAIT)) == (SYNC_CLOSE|SYNC_WAIT)) {
-		XFS_bflush(mp->m_ddev_targp);
-		if (mp->m_rtdev_targp) {
-			XFS_bflush(mp->m_rtdev_targp);
-		}
-	}
-
 	return XFS_ERROR(last_error);
 }
 
fs/xfs/linux-2.6/xfs_sync.h +0 -1
index fcd4040..2509db0 100644
@@ -28,7 +28,6 @@ typedef struct bhv_vfs_sync_work {
 } bhv_vfs_sync_work_t;
 
 #define SYNC_ATTR		0x0001	/* sync attributes */
-#define SYNC_CLOSE		0x0002	/* close file system down */
 #define SYNC_DELWRI		0x0004	/* look at delayed writes */
 #define SYNC_WAIT		0x0008	/* wait for i/o to complete */
 #define SYNC_BDFLUSH		0x0010	/* BDFLUSH is calling -- don't block */
Signature · 1 line
1.5.6.5
#9 lore raw

PATCH 9/10 XFS: Kill xfs_sync()

In reply to Dave Chinner

There are no more callers to xfs_sync() now, so remove the function altogther.

---
 fs/xfs/linux-2.6/xfs_sync.c |  132 +++++--------------------------------------
 fs/xfs/linux-2.6/xfs_sync.h |   25 +-------
 fs/xfs/quota/xfs_qm.c       |   10 +--
 fs/xfs/xfs_iget.c           |   15 ++---
 4 files changed, 29 insertions(+), 153 deletions(-)
fs/xfs/linux-2.6/xfs_sync.c +15 -117
index 91a54a7..ed24435 100644
@@ -316,11 +316,21 @@ xfs_sync_fsdata(
 }
 
 /*
- * First stage of freeze - no more writers will make progress now we are here,
+ * When remounting a filesystem read-only or freezing the filesystem, we have
+ * two phases to execute. This first phase is syncing the data before we
+ * quiesce the filesystem, and the second is flushing all the inodes out after
+ * we've waited for all the transactions created by the first phase to
+ * complete. The second phase ensures that the inodes are written to their
+ * location on disk rather than just existing in transactions in the log. This
+ * means after a quiesce there is no log replay required to write the inodes to
+ * disk (this is the main difference between a sync and a quiesce).
+ */
+/*
+ * First stage of freeze - no writers will make progress now we are here,
  * so we flush delwri and delalloc buffers here, then wait for all I/O to
  * complete.  Data is frozen at that point. Metadata is not frozen,
- * transactions can still occur here so don't bother flushing the buftarg (i.e
- * SYNC_QUIESCE) because it'll just get dirty again.
+ * transactions can still occur here so don't bother flushing the buftarg
+ * because it'll just get dirty again.
  */
 int
 xfs_quiesce_data(
@@ -337,11 +347,10 @@ xfs_quiesce_data(
 	xfs_sync_inodes(mp, SYNC_DELWRI|SYNC_WAIT|SYNC_IOWAIT);
 	XFS_QM_DQSYNC(mp, SYNC_WAIT);
 
-	/* write superblock and hoover shutdown errors */
+	/* write superblock and hoover up shutdown errors */
 	error = xfs_sync_fsdata(mp, 0);
 
-	/* flush devices */
-	XFS_bflush(mp->m_ddev_targp);
+	/* flush data-only devices */
 	if (mp->m_rtdev_targp)
 		XFS_bflush(mp->m_rtdev_targp);
 
@@ -349,117 +358,6 @@ xfs_quiesce_data(
 }
 
 /*
- * 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. Now handled by direct calls
- *		       to xfs_sync_inodes().
- *      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_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.
- *
- */
-int
-xfs_sync(
-	xfs_mount_t	*mp,
-	int		flags)
-{
-	int		error;
-	int		last_error = 0;
-	uint		log_flags = XFS_LOG_FORCE;
-
-	ASSERT(!(flags & SYNC_ATTR));
-
-	/*
-	 * 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);
-
-	/*
-	 * Sync out the log.  This ensures that the log is periodically
-	 * flushed even if there is not enough activity to fill it up.
-	 */
-	if (flags & SYNC_WAIT)
-		log_flags |= XFS_LOG_SYNC;
-
-	xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
-
-	if (flags & SYNC_DELWRI) {
-		if (flags & SYNC_BDFLUSH)
-			xfs_finish_reclaim_all(mp, 1, XFS_IFLUSH_DELWRI_ELSE_ASYNC);
-		else
-			error = xfs_sync_inodes(mp, flags);
-		/*
-		 * Flushing out dirty data above probably generated more
-		 * log activity, so if this isn't vfs_sync() then flush
-		 * the log again.
-		 */
-		xfs_log_force(mp, 0, log_flags);
-	}
-
-	if (flags & SYNC_FSDATA) {
-		error = xfs_sync_fsdata(mp, flags);
-		if (error)
-			last_error = error;
-	}
-
-	/*
-	 * Now check to see if the log needs a "dummy" transaction.
-	 */
-	if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) {
-		error = xfs_commit_dummy_trans(mp, log_flags);
-		if (error)
-			return error;
-	}
-
-	return XFS_ERROR(last_error);
-}
-
-/*
  * Enqueue a work item to be picked up by the vfs xfssyncd thread.
  * Doing this has two advantages:
  * - It saves on stack space, which is tight in certain situations
fs/xfs/linux-2.6/xfs_sync.h +4 -21
index 2509db0..4591dc0 100644
@@ -28,31 +28,14 @@ typedef struct bhv_vfs_sync_work {
 } bhv_vfs_sync_work_t;
 
 #define SYNC_ATTR		0x0001	/* sync attributes */
-#define SYNC_DELWRI		0x0004	/* look at delayed writes */
-#define SYNC_WAIT		0x0008	/* wait for i/o to complete */
-#define SYNC_BDFLUSH		0x0010	/* BDFLUSH is calling -- don't block */
-#define SYNC_FSDATA		0x0020	/* flush fs data (e.g. superblocks) */
-#define SYNC_REFCACHE		0x0040  /* prune some of the nfs ref cache */
-#define SYNC_REMOUNT		0x0080  /* remount readonly, no dummy LRs */
-#define SYNC_IOWAIT		0x0100  /* wait for all I/O to complete */
-
-/*
- * When remounting a filesystem read-only or freezing the filesystem,
- * we have two phases to execute. This first phase is syncing the data
- * before we quiesce the fielsystem, and the second is flushing all the
- * inodes out after we've waited for all the transactions created by
- * the first phase to complete. The second phase uses SYNC_INODE_QUIESCE
- * to ensure that the inodes are written to their location on disk
- * rather than just existing in transactions in the log. This means
- * after a quiesce there is no log replay required to write the inodes
- * to disk (this is the main difference between a sync and a quiesce).
- */
-#define SYNC_DATA_QUIESCE	(SYNC_DELWRI|SYNC_FSDATA|SYNC_WAIT|SYNC_IOWAIT)
+#define SYNC_DELWRI		0x0002	/* look at delayed writes */
+#define SYNC_WAIT		0x0004	/* wait for i/o to complete */
+#define SYNC_BDFLUSH		0x0008	/* BDFLUSH is calling -- don't block */
+#define SYNC_IOWAIT		0x0010  /* wait for all I/O to complete */
 
 int xfs_syncd_init(struct xfs_mount *mp);
 void xfs_syncd_stop(struct xfs_mount *mp);
 
-int xfs_sync(struct xfs_mount *mp, int flags);
 int xfs_sync_inodes(struct xfs_mount *mp, int flags);
 int xfs_sync_fsdata(struct xfs_mount *mp, int flags);
 
fs/xfs/quota/xfs_qm.c +3 -7
index 270f775..db1986a 100644
@@ -987,14 +987,10 @@ xfs_qm_dqdetach(
 }
 
 /*
- * This is called by VFS_SYNC and flags arg determines the caller,
- * and its motives, as done in xfs_sync.
- *
- * vfs_sync: SYNC_FSDATA|SYNC_ATTR|SYNC_BDFLUSH 0x31
- * syscall sync: SYNC_FSDATA|SYNC_ATTR|SYNC_DELWRI 0x25
- * umountroot : SYNC_WAIT | SYNC_CLOSE | SYNC_ATTR | SYNC_FSDATA
+ * This is called to sync quotas. We can be told to use non-blocking
+ * semantics by either the SYNC_BDFLUSH flag or the absence of the
+ * SYNC_WAIT flag.
  */
-
 int
 xfs_qm_sync(
 	xfs_mount_t	*mp,
fs/xfs/xfs_iget.c +7 -8
index 1256746..58865fe 100644
@@ -431,14 +431,13 @@ xfs_ireclaim(xfs_inode_t *ip)
 	xfs_iextract(ip);
 
 	/*
-	 * Here we do a spurious inode lock in order to coordinate with
-	 * xfs_sync().  This is because xfs_sync() references the inodes
-	 * in the mount list without taking references on the corresponding
-	 * vnodes.  We make that OK here by ensuring that we wait until
-	 * the inode is unlocked in xfs_sync() before we go ahead and
-	 * free it.  We get both the regular lock and the io lock because
-	 * the xfs_sync() code may need to drop the regular one but will
-	 * still hold the io lock.
+	 * Here we do a spurious inode lock in order to coordinate with inode
+	 * cache radix tree lookups.  This is because the lookup can reference
+	 * the inodes in the cache without taking references.  We make that OK
+	 * here by ensuring that we wait until the inode is unlocked after the
+	 * lookup before we go ahead and free it.  We get both the ilock and
+	 * the iolock because the code may need to drop the ilock one but will
+	 * still hold the iolock.
 	 */
 	xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
 
Signature · 1 line
1.5.6.5
#10 lore raw

PATCH 10/10 XFS: Move remaining quiesce code.

In reply to Dave Chinner

With all the other filesystem sync code it in xfs_sync.c including the data quiesce code, it makes sense to move the remaining quiesce code to the same place.

---
 fs/xfs/linux-2.6/xfs_super.c |    6 ++--
 fs/xfs/linux-2.6/xfs_sync.c  |   55 ++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/linux-2.6/xfs_sync.h  |    1 +
 fs/xfs/xfs_vfsops.c          |   55 ------------------------------------------
 fs/xfs/xfs_vfsops.h          |    1 -
 5 files changed, 59 insertions(+), 59 deletions(-)
fs/xfs/linux-2.6/xfs_super.c +3 -3
index 9cd49dc..1f9c5a9 100644
@@ -1212,7 +1212,7 @@ xfs_fs_remount(
 	/* rw -> ro */
 	if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) {
 		xfs_quiesce_data(mp);
-		xfs_attr_quiesce(mp);
+		xfs_quiesce_attr(mp);
 		mp->m_flags |= XFS_MOUNT_RDONLY;
 	}
 
@@ -1221,7 +1221,7 @@ xfs_fs_remount(
 
 /*
  * Second stage of a freeze. The data is already frozen so we only
- * need to take care of themetadata. Once that's done write a dummy
+ * need to take care of the metadata. Once that's done write a dummy
  * record to dirty the log in case of a crash while frozen.
  */
 STATIC void
@@ -1230,7 +1230,7 @@ xfs_fs_lockfs(
 {
 	struct xfs_mount	*mp = XFS_M(sb);
 
-	xfs_attr_quiesce(mp);
+	xfs_quiesce_attr(mp);
 	xfs_fs_log_dummy(mp);
 }
 
fs/xfs/linux-2.6/xfs_sync.c +55 -0

61 lines not on this page · raw message

fs/xfs/linux-2.6/xfs_sync.h +1 -0
index 4591dc0..3b49aa3 100644
@@ -40,6 +40,7 @@ int xfs_sync_inodes(struct xfs_mount *mp, int flags);
 int xfs_sync_fsdata(struct xfs_mount *mp, int flags);
 
 int xfs_quiesce_data(struct xfs_mount *mp);
+void xfs_quiesce_attr(struct xfs_mount *mp);
 
 void xfs_flush_inode(struct xfs_inode *ip);
 void xfs_flush_device(struct xfs_inode *ip);
fs/xfs/xfs_vfsops.c +0 -55

61 lines not on this page · raw message

fs/xfs/xfs_vfsops.h +0 -1
index 6701d0e..6b8e0b5 100644
@@ -10,6 +10,5 @@ struct xfs_mount_args;
 
 void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
 		int lnnum);
-void xfs_attr_quiesce(struct xfs_mount *mp);
 
 #endif /* _XFS_VFSOPS_H */
Signature · 1 line
1.5.6.5