All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eryu Guan <eguan@redhat.com>
To: Christoph Hellwig <hch@infradead.org>
Cc: Brian Foster <bfoster@redhat.com>,
	Eric Sandeen <sandeen@redhat.com>,
	fstests <fstests@vger.kernel.org>,
	Zheng Liu <wenqing.lz@taobao.com>,
	linux-xfs@vger.kernel.org
Subject: Re: [PATCH] test race when checking i_size on direct i/o read
Date: Wed, 20 Sep 2017 19:05:04 +0800	[thread overview]
Message-ID: <20170920110504.GU8034@eguan.usersys.redhat.com> (raw)
In-Reply-To: <20170919143406.GA7437@infradead.org>

On Tue, Sep 19, 2017 at 07:34:06AM -0700, Christoph Hellwig wrote:
> On Tue, Sep 19, 2017 at 10:13:52AM -0400, Brian Foster wrote:
> > Can we pass a boolean or flag to xfs_iomap_write_unwritten() to have it
> > update the incore i_size after unwritten extent conversion? Then move
> > (or remove) the associated update from xfs_dio_write_end_io().
> 
> I don't think we even need a flag - all three callers of
> xfs_iomap_write_unwritten want to update the file size.

I tried this approach, but seems there's some problem in the buffered
aio path, generic/112 (aio fsx) failed quickly. But I haven't digged
into the reason (maybe I screwed it up, not the method is wrong..).

Then I tried Brian's suggestion, pass a boolean to
xfs_iomap_write_unwritten() to tell if we want it to update in-core
isize after unwritten extent conversion, and skip the in-core isize
update in xfs_dio_write_end_io() accordingly. This approach seems to
work, it passed the test Eric posted here, and fstests 'aio' group
tests, a run of 'quick' group didn't find any new failure as well.

I attached the WIP patch (without proper comments) I was testing, if
this looks fine I can format a formal patch and do more testings.

Thanks,
Eryu

diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 29172609f2a3..288da47e9ac5 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -343,7 +343,7 @@ xfs_end_io(
 		error = xfs_reflink_end_cow(ip, offset, size);
 		break;
 	case XFS_IO_UNWRITTEN:
-		error = xfs_iomap_write_unwritten(ip, offset, size);
+		error = xfs_iomap_write_unwritten(ip, offset, size, false);
 		break;
 	default:
 		ASSERT(!xfs_ioend_is_append(ioend) || ioend->io_append_trans);
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 350b6d43ba23..f3ad024573e7 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -435,6 +435,7 @@ xfs_dio_write_end_io(
 	struct xfs_inode	*ip = XFS_I(inode);
 	loff_t			offset = iocb->ki_pos;
 	bool			update_size = false;
+	bool			write_unwritten = (flags & IOMAP_DIO_UNWRITTEN);
 	int			error = 0;
 
 	trace_xfs_end_io_direct_write(ip, offset, size);
@@ -458,7 +459,8 @@ xfs_dio_write_end_io(
 	 */
 	spin_lock(&ip->i_flags_lock);
 	if (offset + size > i_size_read(inode)) {
-		i_size_write(inode, offset + size);
+		if (!write_unwritten)
+			i_size_write(inode, offset + size);
 		update_size = true;
 	}
 	spin_unlock(&ip->i_flags_lock);
@@ -469,8 +471,8 @@ xfs_dio_write_end_io(
 			return error;
 	}
 
-	if (flags & IOMAP_DIO_UNWRITTEN)
-		error = xfs_iomap_write_unwritten(ip, offset, size);
+	if (write_unwritten)
+		error = xfs_iomap_write_unwritten(ip, offset, size, update_size);
 	else if (update_size)
 		error = xfs_setfilesize(ip, offset, size);
 
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index a1909bc064e9..0a088586371e 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -829,7 +829,8 @@ int
 xfs_iomap_write_unwritten(
 	xfs_inode_t	*ip,
 	xfs_off_t	offset,
-	xfs_off_t	count)
+	xfs_off_t	count,
+	bool		update_size)
 {
 	xfs_mount_t	*mp = ip->i_mount;
 	xfs_fileoff_t	offset_fsb;
@@ -840,6 +841,7 @@ xfs_iomap_write_unwritten(
 	xfs_trans_t	*tp;
 	xfs_bmbt_irec_t imap;
 	struct xfs_defer_ops dfops;
+	struct inode	*inode = VFS_I(ip);
 	xfs_fsize_t	i_size;
 	uint		resblks;
 	int		error;
@@ -900,6 +902,13 @@ xfs_iomap_write_unwritten(
 		if (i_size > offset + count)
 			i_size = offset + count;
 
+		if (update_size) {
+			spin_lock(&ip->i_flags_lock);
+			if (i_size > i_size_read(inode))
+				i_size_write(inode, i_size);
+			spin_unlock(&ip->i_flags_lock);
+		}
+
 		i_size = xfs_new_eof(ip, i_size);
 		if (i_size) {
 			ip->i_d.di_size = i_size;
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index 00db3ecea084..ee535065c5d0 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -27,7 +27,7 @@ int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t,
 			struct xfs_bmbt_irec *, int);
 int xfs_iomap_write_allocate(struct xfs_inode *, int, xfs_off_t,
 			struct xfs_bmbt_irec *);
-int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t);
+int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t, bool);
 
 void xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *,
 		struct xfs_bmbt_irec *);
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index 2f2dc3c09ad0..4246876df7b7 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -274,7 +274,7 @@ xfs_fs_commit_blocks(
 					(end - 1) >> PAGE_SHIFT);
 		WARN_ON_ONCE(error);
 
-		error = xfs_iomap_write_unwritten(ip, start, length);
+		error = xfs_iomap_write_unwritten(ip, start, length, false);
 		if (error)
 			goto out_drop_iolock;
 	}

  parent reply	other threads:[~2017-09-20 11:05 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-18 20:35 [PATCH] test race when checking i_size on direct i/o read Eric Sandeen
2017-08-28 10:35 ` Eryu Guan
2017-08-29 13:46   ` Nikolay Borisov
2017-09-19  7:36 ` Eryu Guan
2017-09-19 14:13   ` Brian Foster
2017-09-19 14:34     ` Christoph Hellwig
2017-09-19 14:58       ` Brian Foster
2017-09-20 11:05       ` Eryu Guan [this message]
2017-09-20 12:55         ` Brian Foster
2017-09-21 10:09           ` Eryu Guan

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=20170920110504.GU8034@eguan.usersys.redhat.com \
    --to=eguan@redhat.com \
    --cc=bfoster@redhat.com \
    --cc=fstests@vger.kernel.org \
    --cc=hch@infradead.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=sandeen@redhat.com \
    --cc=wenqing.lz@taobao.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.