Ver código fonte

xfs: unlock the inode before log force in xfs_fsync

Only read the LSN we need to push to with the ilock held, and then release
it before we do the log force to improve concurrency.

This also removes the only direct caller of _xfs_trans_commit, thus
allowing it to be merged into the plain xfs_trans_commit again.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>
Christoph Hellwig 13 anos atrás
pai
commit
b103705853
3 arquivos alterados com 13 adições e 18 exclusões
  1. 8 7
      fs/xfs/xfs_file.c
  2. 4 7
      fs/xfs/xfs_trans.c
  3. 1 4
      fs/xfs/xfs_trans.h

+ 8 - 7
fs/xfs/xfs_file.c

@@ -137,6 +137,7 @@ xfs_file_fsync(
 	struct xfs_trans	*tp;
 	struct xfs_trans	*tp;
 	int			error = 0;
 	int			error = 0;
 	int			log_flushed = 0;
 	int			log_flushed = 0;
+	xfs_lsn_t		lsn = 0;
 
 
 	trace_xfs_file_fsync(ip);
 	trace_xfs_file_fsync(ip);
 
 
@@ -214,9 +215,9 @@ xfs_file_fsync(
 		 */
 		 */
 		xfs_trans_ijoin(tp, ip);
 		xfs_trans_ijoin(tp, ip);
 		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-		xfs_trans_set_sync(tp);
-		error = _xfs_trans_commit(tp, 0, &log_flushed);
+		error = xfs_trans_commit(tp, 0);
 
 
+		lsn = ip->i_itemp->ili_last_lsn;
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	} else {
 	} else {
 		/*
 		/*
@@ -227,14 +228,14 @@ xfs_file_fsync(
 		 * disk yet, the inode will be still be pinned.  If it is,
 		 * disk yet, the inode will be still be pinned.  If it is,
 		 * force the log.
 		 * force the log.
 		 */
 		 */
-		if (xfs_ipincount(ip)) {
-			error = _xfs_log_force_lsn(mp,
-					ip->i_itemp->ili_last_lsn,
-					XFS_LOG_SYNC, &log_flushed);
-		}
+		if (xfs_ipincount(ip))
+			lsn = ip->i_itemp->ili_last_lsn;
 		xfs_iunlock(ip, XFS_ILOCK_SHARED);
 		xfs_iunlock(ip, XFS_ILOCK_SHARED);
 	}
 	}
 
 
+	if (!error && lsn)
+		error = _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, &log_flushed);
+
 	/*
 	/*
 	 * If we only have a single device, and the log force about was
 	 * If we only have a single device, and the log force about was
 	 * a no-op we might have to flush the data device cache here.
 	 * a no-op we might have to flush the data device cache here.

+ 4 - 7
fs/xfs/xfs_trans.c

@@ -1790,9 +1790,7 @@ xfs_trans_commit_cil(
 }
 }
 
 
 /*
 /*
- * xfs_trans_commit
- *
- * Commit the given transaction to the log a/synchronously.
+ * Commit the given transaction to the log.
  *
  *
  * XFS disk error handling mechanism is not based on a typical
  * XFS disk error handling mechanism is not based on a typical
  * transaction abort mechanism. Logically after the filesystem
  * transaction abort mechanism. Logically after the filesystem
@@ -1804,10 +1802,9 @@ xfs_trans_commit_cil(
  * Do not reference the transaction structure after this call.
  * Do not reference the transaction structure after this call.
  */
  */
 int
 int
-_xfs_trans_commit(
+xfs_trans_commit(
 	struct xfs_trans	*tp,
 	struct xfs_trans	*tp,
-	uint			flags,
-	int			*log_flushed)
+	uint			flags)
 {
 {
 	struct xfs_mount	*mp = tp->t_mountp;
 	struct xfs_mount	*mp = tp->t_mountp;
 	xfs_lsn_t		commit_lsn = -1;
 	xfs_lsn_t		commit_lsn = -1;
@@ -1866,7 +1863,7 @@ _xfs_trans_commit(
 	if (sync) {
 	if (sync) {
 		if (!error) {
 		if (!error) {
 			error = _xfs_log_force_lsn(mp, commit_lsn,
 			error = _xfs_log_force_lsn(mp, commit_lsn,
-				      XFS_LOG_SYNC, log_flushed);
+				      XFS_LOG_SYNC, NULL);
 		}
 		}
 		XFS_STATS_INC(xs_trans_sync);
 		XFS_STATS_INC(xs_trans_sync);
 	} else {
 	} else {

+ 1 - 4
fs/xfs/xfs_trans.h

@@ -487,10 +487,7 @@ void		xfs_trans_log_efd_extent(xfs_trans_t *,
 					 struct xfs_efd_log_item *,
 					 struct xfs_efd_log_item *,
 					 xfs_fsblock_t,
 					 xfs_fsblock_t,
 					 xfs_extlen_t);
 					 xfs_extlen_t);
-int		_xfs_trans_commit(xfs_trans_t *,
-				  uint flags,
-				  int *);
-#define xfs_trans_commit(tp, flags)	_xfs_trans_commit(tp, flags, NULL)
+int		xfs_trans_commit(xfs_trans_t *, uint flags);
 void		xfs_trans_cancel(xfs_trans_t *, int);
 void		xfs_trans_cancel(xfs_trans_t *, int);
 int		xfs_trans_ail_init(struct xfs_mount *);
 int		xfs_trans_ail_init(struct xfs_mount *);
 void		xfs_trans_ail_destroy(struct xfs_mount *);
 void		xfs_trans_ail_destroy(struct xfs_mount *);