From: Jeff Liu <jeff.liu@oracle.com>
To: Mark Tinguely <tinguely@sgi.com>
Cc: Christoph Hellwig <hch@infradead.org>, Ben Myers <bpm@sgi.com>,
Chris Mason <chris.mason@oracle.com>,
xfs@oss.sgi.com
Subject: Re: Introduce SEEK_DATA/SEEK_HOLE to XFS V5
Date: Thu, 12 Jan 2012 21:52:54 +0800 [thread overview]
Message-ID: <4F0EE5B6.2040408@oracle.com> (raw)
In-Reply-To: <4F0DFB20.7030704@sgi.com>
Hi Mark,
On 01/12/2012 05:12 AM, Mark Tinguely wrote:
> xfs_has_unwritten_buffer() always returns the offset of the first
> dirty unwritten page. This can cause xfs_seek_data() and xfs_seek_hole()
> to give the wrong results in certain circumstances.
Sorry, am was well understood your opinions in this point for now.
IMHO, we can only find and return the data buffer offset at a dirty or
unwritten page once the first page was probed.
>
>
> In xfs_seek_data(), every page past first dirty/unwritten page in the
> unwritten extent will be reported as data.
Hmm, consider the user level utility that make use of SEEK_XXX stuff to
copy data from an offset in source file:
Generally, it will call xfs_seek_data() firstly,
if we read an unwritten extent and there is data buffer was probed in
xfs_seek_data(), it only means we can read file data starting from the
returned offset of xfs_has_unwritten_buffer().
Then it will call xfs_seek_hole() to calculate this extent length.
next, a couple of read()/write() will be called in a loop depending on
the extent length.
[ page 1 ] | [ page 2 ] | [ page 3 ] | .... [ page N ]
|data offset at page 2|
If we got the data offset from page2, and there is no data at page 3,
the user utility call read(2) will returns ZERO, and it will break
immediately.
>
>
> in xfs_seek_data():
> + /*
> + * Landed in an unwritten extent, try to find out the data
> + * buffer offset from page cache firstly. If nothing was
> + * found, treat it as a hole, and skip to check the next
> + * extent, something just like above.
> + */
> + if (map[0].br_state == XFS_EXT_UNWRITTEN) {
> + if (xfs_has_unwritten_buffer(inode, &map[0],
> + PAGECACHE_TAG_DIRTY,
> + &offset) ||
> + xfs_has_unwritten_buffer(inode, &map[0],
> + PAGECACHE_TAG_WRITEBACK,
> + &offset)) {
> + offset = max_t(loff_t, seekoff, offset);
> + break;
> + }
>
> Since the xfs_has_unwritten_buffer() returns the offset of the first
> dirty/unwritten page (the first page in this example), the max_t()
> comparison will say that every page after the first dirty page has
> data.
>
> -----
>
> xfs_seek_hole() can only find a hole if it precedes the first dirty
> page.
Yes, for my current implementation, it is the case.
Anyway, I need a careful consideration for probing unwritten extent. :-)
Thanks,
-Jeff
>
> in xfs_seek_hole():
> + /*
> + * Landed in an unwritten extent, try to lookup the page
> + * cache to find out if there is dirty data or not. If
> + * nothing was found, treate it as a hole. If there has
> + * dirty data and its offset starts past both the start
> + * block of the map and the current seek offset, it should
> + * be treated as hole too. Otherwise, go through the next
> + * extent to fetch holes.
> + */
> + if (map[0].br_state == XFS_EXT_UNWRITTEN) {
> + if (xfs_has_unwritten_buffer(inode, &map[0],
> + PAGECACHE_TAG_DIRTY,
> + &offset) ||
> + xfs_has_unwritten_buffer(inode, &map[0],
> + PAGECACHE_TAG_WRITEBACK,
> + &offset)) {
> + if (offset > max_t(loff_t, seekoff,
> + XFS_FSB_TO_B(mp,
> + map[0].br_startoff))) {
> + offset = max_t(loff_t, seekoff,
> + XFS_FSB_TO_B(mp,
> + map[0].br_startoff));
> + break;
> + }
> + } else {
> + offset = max_t(loff_t, seekoff,
> + XFS_FSB_TO_B(mp, map[0].br_startoff));
> + break;
> + }
>
> --Mark Tinguely.
>
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2012-01-12 13:53 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-06 13:28 Introduce SEEK_DATA/SEEK_HOLE to XFS V5 Jeff Liu
2012-01-10 17:18 ` Ben Myers
2012-01-11 5:45 ` Jeff Liu
2012-01-11 21:06 ` Mark Tinguely
2012-01-12 16:22 ` Christoph Hellwig
2012-01-12 17:50 ` Ben Myers
2012-01-11 21:07 ` Mark Tinguely
2012-01-12 13:29 ` Jeff Liu
2012-01-12 16:39 ` Christoph Hellwig
2012-01-13 2:14 ` Jeff Liu
2012-01-11 21:12 ` Mark Tinguely
2012-01-12 13:52 ` Jeff Liu [this message]
2012-01-12 15:01 ` Mark Tinguely
2012-01-12 16:41 ` Christoph Hellwig
2012-01-12 17:39 ` Ben Myers
2012-01-13 2:41 ` Jeff Liu
2012-01-11 15:43 ` Ben Myers
2012-01-11 22:28 ` Ben Myers
2012-01-12 13:21 ` Jeff Liu
2012-01-12 12:53 ` Jeff Liu
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=4F0EE5B6.2040408@oracle.com \
--to=jeff.liu@oracle.com \
--cc=bpm@sgi.com \
--cc=chris.mason@oracle.com \
--cc=hch@infradead.org \
--cc=tinguely@sgi.com \
--cc=xfs@oss.sgi.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox