|
@@ -50,6 +50,7 @@
|
|
#include "xfs_ag_resv.h"
|
|
#include "xfs_ag_resv.h"
|
|
#include "xfs_refcount.h"
|
|
#include "xfs_refcount.h"
|
|
#include "xfs_rmap_btree.h"
|
|
#include "xfs_rmap_btree.h"
|
|
|
|
+#include "xfs_icache.h"
|
|
|
|
|
|
|
|
|
|
kmem_zone_t *xfs_bmap_free_item_zone;
|
|
kmem_zone_t *xfs_bmap_free_item_zone;
|
|
@@ -4154,8 +4155,9 @@ int
|
|
xfs_bmapi_reserve_delalloc(
|
|
xfs_bmapi_reserve_delalloc(
|
|
struct xfs_inode *ip,
|
|
struct xfs_inode *ip,
|
|
int whichfork,
|
|
int whichfork,
|
|
- xfs_fileoff_t aoff,
|
|
|
|
|
|
+ xfs_fileoff_t off,
|
|
xfs_filblks_t len,
|
|
xfs_filblks_t len,
|
|
|
|
+ xfs_filblks_t prealloc,
|
|
struct xfs_bmbt_irec *got,
|
|
struct xfs_bmbt_irec *got,
|
|
xfs_extnum_t *lastx,
|
|
xfs_extnum_t *lastx,
|
|
int eof)
|
|
int eof)
|
|
@@ -4167,10 +4169,17 @@ xfs_bmapi_reserve_delalloc(
|
|
char rt = XFS_IS_REALTIME_INODE(ip);
|
|
char rt = XFS_IS_REALTIME_INODE(ip);
|
|
xfs_extlen_t extsz;
|
|
xfs_extlen_t extsz;
|
|
int error;
|
|
int error;
|
|
|
|
+ xfs_fileoff_t aoff = off;
|
|
|
|
|
|
- alen = XFS_FILBLKS_MIN(len, MAXEXTLEN);
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Cap the alloc length. Keep track of prealloc so we know whether to
|
|
|
|
+ * tag the inode before we return.
|
|
|
|
+ */
|
|
|
|
+ alen = XFS_FILBLKS_MIN(len + prealloc, MAXEXTLEN);
|
|
if (!eof)
|
|
if (!eof)
|
|
alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
|
|
alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
|
|
|
|
+ if (prealloc && alen >= len)
|
|
|
|
+ prealloc = alen - len;
|
|
|
|
|
|
/* Figure out the extent size, adjust alen */
|
|
/* Figure out the extent size, adjust alen */
|
|
if (whichfork == XFS_COW_FORK)
|
|
if (whichfork == XFS_COW_FORK)
|
|
@@ -4236,6 +4245,16 @@ xfs_bmapi_reserve_delalloc(
|
|
*/
|
|
*/
|
|
xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got);
|
|
xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Tag the inode if blocks were preallocated. Note that COW fork
|
|
|
|
+ * preallocation can occur at the start or end of the extent, even when
|
|
|
|
+ * prealloc == 0, so we must also check the aligned offset and length.
|
|
|
|
+ */
|
|
|
|
+ if (whichfork == XFS_DATA_FORK && prealloc)
|
|
|
|
+ xfs_inode_set_eofblocks_tag(ip);
|
|
|
|
+ if (whichfork == XFS_COW_FORK && (prealloc || aoff < off || alen > len))
|
|
|
|
+ xfs_inode_set_cowblocks_tag(ip);
|
|
|
|
+
|
|
ASSERT(got->br_startoff <= aoff);
|
|
ASSERT(got->br_startoff <= aoff);
|
|
ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen);
|
|
ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen);
|
|
ASSERT(isnullstartblock(got->br_startblock));
|
|
ASSERT(isnullstartblock(got->br_startblock));
|