aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2017-01-09 10:38:43 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-12 05:39:41 -0500
commitcf168f2ff8bae8a4eb966c3c0f055086c1fae87d (patch)
treed356dceff9e25ab5aaec46aace50cc623888f84f /fs
parentcf4fb510473b4529a0969b1d0af898b7a844bc36 (diff)
xfs: track preallocation separately in xfs_bmapi_reserve_delalloc()
commit 974ae922efd93b07b6cdf989ae959883f6f05fd8 upstream. Speculative preallocation is currently processed entirely by the callers of xfs_bmapi_reserve_delalloc(). The caller determines how much preallocation to include, adjusts the extent length and passes down the resulting request. While this works fine for post-eof speculative preallocation, it is not as reliable for COW fork preallocation. COW fork preallocation is implemented via the cowextszhint, which aligns the start offset as well as the length of the extent. Further, it is difficult for the caller to accurately identify when preallocation occurs because the returned extent could have been merged with neighboring extents in the fork. To simplify this situation and facilitate further COW fork preallocation enhancements, update xfs_bmapi_reserve_delalloc() to take a separate preallocation parameter to incorporate into the allocation request. The preallocation blocks value is tacked onto the end of the request and adjusted to accommodate neighboring extents and extent size limits. Since xfs_bmapi_reserve_delalloc() now knows precisely how much preallocation was included in the allocation, it can also tag the inodes appropriately to support preallocation reclaim. Note that xfs_bmapi_reserve_delalloc() callers are not yet updated to use the preallocation mechanism. This patch should not change behavior outside of correctly tagging reflink inodes when start offset preallocation occurs (which the caller does not handle correctly). Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c23
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h2
-rw-r--r--fs/xfs/xfs_iomap.c2
-rw-r--r--fs/xfs/xfs_reflink.c2
4 files changed, 24 insertions, 5 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 09b5d4f07636..aab523a7dcaf 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -50,6 +50,7 @@
50#include "xfs_ag_resv.h" 50#include "xfs_ag_resv.h"
51#include "xfs_refcount.h" 51#include "xfs_refcount.h"
52#include "xfs_rmap_btree.h" 52#include "xfs_rmap_btree.h"
53#include "xfs_icache.h"
53 54
54 55
55kmem_zone_t *xfs_bmap_free_item_zone; 56kmem_zone_t *xfs_bmap_free_item_zone;
@@ -4247,8 +4248,9 @@ int
4247xfs_bmapi_reserve_delalloc( 4248xfs_bmapi_reserve_delalloc(
4248 struct xfs_inode *ip, 4249 struct xfs_inode *ip,
4249 int whichfork, 4250 int whichfork,
4250 xfs_fileoff_t aoff, 4251 xfs_fileoff_t off,
4251 xfs_filblks_t len, 4252 xfs_filblks_t len,
4253 xfs_filblks_t prealloc,
4252 struct xfs_bmbt_irec *got, 4254 struct xfs_bmbt_irec *got,
4253 xfs_extnum_t *lastx, 4255 xfs_extnum_t *lastx,
4254 int eof) 4256 int eof)
@@ -4260,10 +4262,17 @@ xfs_bmapi_reserve_delalloc(
4260 char rt = XFS_IS_REALTIME_INODE(ip); 4262 char rt = XFS_IS_REALTIME_INODE(ip);
4261 xfs_extlen_t extsz; 4263 xfs_extlen_t extsz;
4262 int error; 4264 int error;
4265 xfs_fileoff_t aoff = off;
4263 4266
4264 alen = XFS_FILBLKS_MIN(len, MAXEXTLEN); 4267 /*
4268 * Cap the alloc length. Keep track of prealloc so we know whether to
4269 * tag the inode before we return.
4270 */
4271 alen = XFS_FILBLKS_MIN(len + prealloc, MAXEXTLEN);
4265 if (!eof) 4272 if (!eof)
4266 alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff); 4273 alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
4274 if (prealloc && alen >= len)
4275 prealloc = alen - len;
4267 4276
4268 /* Figure out the extent size, adjust alen */ 4277 /* Figure out the extent size, adjust alen */
4269 if (whichfork == XFS_COW_FORK) 4278 if (whichfork == XFS_COW_FORK)
@@ -4329,6 +4338,16 @@ xfs_bmapi_reserve_delalloc(
4329 */ 4338 */
4330 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got); 4339 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got);
4331 4340
4341 /*
4342 * Tag the inode if blocks were preallocated. Note that COW fork
4343 * preallocation can occur at the start or end of the extent, even when
4344 * prealloc == 0, so we must also check the aligned offset and length.
4345 */
4346 if (whichfork == XFS_DATA_FORK && prealloc)
4347 xfs_inode_set_eofblocks_tag(ip);
4348 if (whichfork == XFS_COW_FORK && (prealloc || aoff < off || alen > len))
4349 xfs_inode_set_cowblocks_tag(ip);
4350
4332 ASSERT(got->br_startoff <= aoff); 4351 ASSERT(got->br_startoff <= aoff);
4333 ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen); 4352 ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen);
4334 ASSERT(isnullstartblock(got->br_startblock)); 4353 ASSERT(isnullstartblock(got->br_startblock));
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index e3c2b5adf505..d6d175a4fdec 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -242,7 +242,7 @@ struct xfs_bmbt_rec_host *
242 int fork, int *eofp, xfs_extnum_t *lastxp, 242 int fork, int *eofp, xfs_extnum_t *lastxp,
243 struct xfs_bmbt_irec *gotp, struct xfs_bmbt_irec *prevp); 243 struct xfs_bmbt_irec *gotp, struct xfs_bmbt_irec *prevp);
244int xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork, 244int xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
245 xfs_fileoff_t aoff, xfs_filblks_t len, 245 xfs_fileoff_t off, xfs_filblks_t len, xfs_filblks_t prealloc,
246 struct xfs_bmbt_irec *got, xfs_extnum_t *lastx, int eof); 246 struct xfs_bmbt_irec *got, xfs_extnum_t *lastx, int eof);
247 247
248enum xfs_bmap_intent_type { 248enum xfs_bmap_intent_type {
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 59ffcac8a47d..cc25892cfc63 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -622,7 +622,7 @@ xfs_file_iomap_begin_delay(
622 622
623retry: 623retry:
624 error = xfs_bmapi_reserve_delalloc(ip, XFS_DATA_FORK, offset_fsb, 624 error = xfs_bmapi_reserve_delalloc(ip, XFS_DATA_FORK, offset_fsb,
625 end_fsb - offset_fsb, &got, &idx, eof); 625 end_fsb - offset_fsb, 0, &got, &idx, eof);
626 switch (error) { 626 switch (error) {
627 case 0: 627 case 0:
628 break; 628 break;
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index ae17b81e7053..e65cd0a3c055 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -293,7 +293,7 @@ xfs_reflink_reserve_cow(
293 293
294retry: 294retry:
295 error = xfs_bmapi_reserve_delalloc(ip, XFS_COW_FORK, imap->br_startoff, 295 error = xfs_bmapi_reserve_delalloc(ip, XFS_COW_FORK, imap->br_startoff,
296 end_fsb - imap->br_startoff, &got, &idx, eof); 296 end_fsb - imap->br_startoff, 0, &got, &idx, eof);
297 switch (error) { 297 switch (error) {
298 case 0: 298 case 0:
299 break; 299 break;