Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 352941
b: refs/heads/master
c: a1e16c2
h: refs/heads/master
i:
  352939: 8d3cd03
v: v3
  • Loading branch information
Dave Chinner authored and Ben Myers committed Feb 14, 2013
1 parent 6f9e4a9 commit 5a11ca9
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 311f08acde635e4e5ccea9b9d8c856cc2e0ced95
refs/heads/master: a1e16c26660b301cc8423185924cf1b0b16ea92b
77 changes: 67 additions & 10 deletions trunk/fs/xfs/xfs_iomap.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,62 @@ xfs_iomap_eof_want_preallocate(
return 0;
}

/*
* Determine the initial size of the preallocation. We are beyond the current
* EOF here, but we need to take into account whether this is a sparse write or
* an extending write when determining the preallocation size. Hence we need to
* look up the extent that ends at the current write offset and use the result
* to determine the preallocation size.
*
* If the extent is a hole, then preallocation is essentially disabled.
* Otherwise we take the size of the preceeding data extent as the basis for the
* preallocation size. If the size of the extent is greater than half the
* maximum extent length, then use the current offset as the basis. This ensures
* that for large files the preallocation size always extends to MAXEXTLEN
* rather than falling short due to things like stripe unit/width alignment of
* real extents.
*/
STATIC int
xfs_iomap_eof_prealloc_initial_size(
struct xfs_mount *mp,
struct xfs_inode *ip,
xfs_off_t offset,
xfs_bmbt_irec_t *imap,
int nimaps)
{
xfs_fileoff_t start_fsb;
int imaps = 1;
int error;

ASSERT(nimaps >= imaps);

/* if we are using a specific prealloc size, return now */
if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
return 0;

/*
* As we write multiple pages, the offset will always align to the
* start of a page and hence point to a hole at EOF. i.e. if the size is
* 4096 bytes, we only have one block at FSB 0, but XFS_B_TO_FSB(4096)
* will return FSB 1. Hence if there are blocks in the file, we want to
* point to the block prior to the EOF block and not the hole that maps
* directly at @offset.
*/
start_fsb = XFS_B_TO_FSB(mp, offset);
if (start_fsb)
start_fsb--;
error = xfs_bmapi_read(ip, start_fsb, 1, imap, &imaps, XFS_BMAPI_ENTIRE);
if (error)
return 0;

ASSERT(imaps == 1);
if (imap[0].br_startblock == HOLESTARTBLOCK)
return 0;
if (imap[0].br_blockcount <= (MAXEXTLEN >> 1))
return imap[0].br_blockcount;
return XFS_B_TO_FSB(mp, offset);
}

/*
* If we don't have a user specified preallocation size, dynamically increase
* the preallocation size as the size of the file grows. Cap the maximum size
Expand All @@ -319,20 +375,19 @@ xfs_iomap_eof_want_preallocate(
STATIC xfs_fsblock_t
xfs_iomap_prealloc_size(
struct xfs_mount *mp,
struct xfs_inode *ip)
struct xfs_inode *ip,
xfs_off_t offset,
struct xfs_bmbt_irec *imap,
int nimaps)
{
xfs_fsblock_t alloc_blocks = 0;

if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) {
alloc_blocks = xfs_iomap_eof_prealloc_initial_size(mp, ip, offset,
imap, nimaps);
if (alloc_blocks > 0) {
int shift = 0;
int64_t freesp;

/*
* rounddown_pow_of_two() returns an undefined result
* if we pass in alloc_blocks = 0. Hence the "+ 1" to
* ensure we always pass in a non-zero value.
*/
alloc_blocks = XFS_B_TO_FSB(mp, XFS_ISIZE(ip)) + 1;
alloc_blocks = XFS_FILEOFF_MIN(MAXEXTLEN,
rounddown_pow_of_two(alloc_blocks));

Expand Down Expand Up @@ -399,15 +454,17 @@ xfs_iomap_write_delay(
extsz = xfs_get_extsz_hint(ip);
offset_fsb = XFS_B_TO_FSBT(mp, offset);


error = xfs_iomap_eof_want_preallocate(mp, ip, offset, count,
imap, XFS_WRITE_IMAPS, &prealloc);
if (error)
return error;

retry:
if (prealloc) {
xfs_fsblock_t alloc_blocks = xfs_iomap_prealloc_size(mp, ip);
xfs_fsblock_t alloc_blocks;

alloc_blocks = xfs_iomap_prealloc_size(mp, ip, offset, imap,
XFS_WRITE_IMAPS);

aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1));
ioalign = XFS_B_TO_FSBT(mp, aligned_offset);
Expand Down

0 comments on commit 5a11ca9

Please sign in to comment.