The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Chi Zhiling <chizhiling@163.com>
To: cem@kernel.org
Cc: linux-xfs@vger.kernel.org, linux-kernel@vger.kernel.org,
	Chi Zhiling <chizhiling@kylinos.cn>
Subject: [RFC PATCH 1/2] xfs: Add i_direct_mode to indicate the IO mode of inode
Date: Fri, 25 Apr 2025 18:38:40 +0800	[thread overview]
Message-ID: <20250425103841.3164087-2-chizhiling@163.com> (raw)
In-Reply-To: <20250425103841.3164087-1-chizhiling@163.com>

From: Chi Zhiling <chizhiling@kylinos.cn>

Direct IO already uses shared lock. If buffered write also uses
shared lock, we need to ensure mutual exclusion between DIO and
buffered IO. Therefore, Now introduce a flag `i_direct_mode` to
indicate the IO mode currently used by the file. In practical
scenarios, DIO and buffered IO are typically not used together,
so this flag is usually not modified.

Additionally, this flag is protected by the i_rwsem lock,
which avoids the need to introduce new lock. When reading this
flag, we need to hold a read lock, and when writing, a write lock
is required.

When a file that uses buffered IO starts using DIO, it needs to
acquire a write lock to modify i_direct_mode, which will force DIO
to wait for the previous IO to complete before starting. After
acquiring the write lock to modify `i_direct_mode`, subsequent
buffered IO will need to acquire the write lock again to modify
i_direct_mode, which will force those IOs to wait for the current
IO to complete.

Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
---
 fs/xfs/xfs_file.c  | 37 +++++++++++++++++++++++++++++++++----
 fs/xfs/xfs_inode.h |  6 ++++++
 2 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 84f08c976ac4..a6f214f57238 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -206,7 +206,8 @@ xfs_ilock_iocb(
 static int
 xfs_ilock_iocb_for_write(
 	struct kiocb		*iocb,
-	unsigned int		*lock_mode)
+	unsigned int		*lock_mode,
+	bool			is_dio)
 {
 	ssize_t			ret;
 	struct xfs_inode	*ip = XFS_I(file_inode(iocb->ki_filp));
@@ -226,6 +227,21 @@ xfs_ilock_iocb_for_write(
 		return xfs_ilock_iocb(iocb, *lock_mode);
 	}
 
+	/*
+	 * If the i_direct_mode need update, take the iolock exclusively to write
+	 * it.
+	 */
+	if (ip->i_direct_mode != is_dio) {
+		if (*lock_mode == XFS_IOLOCK_SHARED) {
+			xfs_iunlock(ip, *lock_mode);
+			*lock_mode = XFS_IOLOCK_EXCL;
+			ret = xfs_ilock_iocb(iocb, *lock_mode);
+			if (ret)
+				return ret;
+		}
+		ip->i_direct_mode = is_dio;
+	}
+
 	return 0;
 }
 
@@ -247,6 +263,19 @@ xfs_file_dio_read(
 	ret = xfs_ilock_iocb(iocb, XFS_IOLOCK_SHARED);
 	if (ret)
 		return ret;
+
+	if (!ip->i_direct_mode) {
+		xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+		ret = xfs_ilock_iocb(iocb, XFS_IOLOCK_EXCL);
+		if (ret)
+			return ret;
+
+		ip->i_direct_mode = 1;
+
+		/* Update finished, now downgrade to shared lock */
+		xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
+	}
+
 	ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, 0, NULL, 0);
 	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
@@ -680,7 +709,7 @@ xfs_file_dio_write_aligned(
 	unsigned int		iolock = XFS_IOLOCK_SHARED;
 	ssize_t			ret;
 
-	ret = xfs_ilock_iocb_for_write(iocb, &iolock);
+	ret = xfs_ilock_iocb_for_write(iocb, &iolock, true);
 	if (ret)
 		return ret;
 	ret = xfs_file_write_checks(iocb, from, &iolock, ac);
@@ -767,7 +796,7 @@ xfs_file_dio_write_unaligned(
 		flags = IOMAP_DIO_FORCE_WAIT;
 	}
 
-	ret = xfs_ilock_iocb_for_write(iocb, &iolock);
+	ret = xfs_ilock_iocb_for_write(iocb, &iolock, true);
 	if (ret)
 		return ret;
 
@@ -898,7 +927,7 @@ xfs_file_buffered_write(
 
 write_retry:
 	iolock = XFS_IOLOCK_EXCL;
-	ret = xfs_ilock_iocb(iocb, iolock);
+	ret = xfs_ilock_iocb_for_write(iocb, &iolock, false);
 	if (ret)
 		return ret;
 
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index eae0159983ca..04f6c4174fab 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -51,6 +51,12 @@ typedef struct xfs_inode {
 	uint16_t		i_checked;
 	uint16_t		i_sick;
 
+	/*
+	 * Indicates the current IO mode of this inode, (DIO/buffered IO)
+	 * protected by i_rwsem lock.
+	 */
+	uint32_t		i_direct_mode;
+
 	spinlock_t		i_flags_lock;	/* inode i_flags lock */
 	/* Miscellaneous state. */
 	unsigned long		i_flags;	/* see defined flags below */
-- 
2.43.0


  reply	other threads:[~2025-04-25 10:57 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-25 10:38 [RFC PATCH 0/2] Implement concurrent buffered write with folio lock Chi Zhiling
2025-04-25 10:38 ` Chi Zhiling [this message]
2025-04-25 15:12   ` [RFC PATCH 1/2] xfs: Add i_direct_mode to indicate the IO mode of inode Darrick J. Wong
2025-04-26  1:28     ` Chi Zhiling
2025-04-25 10:38 ` [RFC PATCH 2/2] xfs: Enable concurrency when writing within single block Chi Zhiling
2025-04-25 15:15   ` Darrick J. Wong
2025-04-26  1:34     ` Chi Zhiling
2025-04-30  2:05 ` [RFC PATCH 0/2] Implement concurrent buffered write with folio lock Dave Chinner
2025-04-30  9:03   ` Chi Zhiling
2025-04-30 23:45     ` Dave Chinner
2025-05-01 23:57       ` Chi Zhiling

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250425103841.3164087-2-chizhiling@163.com \
    --to=chizhiling@163.com \
    --cc=cem@kernel.org \
    --cc=chizhiling@kylinos.cn \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox