|
@@ -4605,6 +4605,147 @@ xfs_bmapi_delay(
|
|
|
}
|
|
|
|
|
|
|
|
|
+STATIC int
|
|
|
+xfs_bmapi_allocate(
|
|
|
+ struct xfs_bmalloca *bma,
|
|
|
+ xfs_extnum_t *lastx,
|
|
|
+ struct xfs_btree_cur **cur,
|
|
|
+ xfs_fsblock_t *firstblock,
|
|
|
+ struct xfs_bmap_free *flist,
|
|
|
+ int flags,
|
|
|
+ int *nallocs,
|
|
|
+ int *logflags)
|
|
|
+{
|
|
|
+ struct xfs_mount *mp = bma->ip->i_mount;
|
|
|
+ int whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
|
|
|
+ XFS_ATTR_FORK : XFS_DATA_FORK;
|
|
|
+ struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork);
|
|
|
+ xfs_fsblock_t abno;
|
|
|
+ xfs_extlen_t alen;
|
|
|
+ xfs_fileoff_t aoff;
|
|
|
+ int error;
|
|
|
+ int rt;
|
|
|
+
|
|
|
+ rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(bma->ip);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * For the wasdelay case, we could also just allocate the stuff asked
|
|
|
+ * for in this bmap call but that wouldn't be as good.
|
|
|
+ */
|
|
|
+ if (bma->wasdel) {
|
|
|
+ alen = (xfs_extlen_t)bma->gotp->br_blockcount;
|
|
|
+ aoff = bma->gotp->br_startoff;
|
|
|
+ if (*lastx != NULLEXTNUM && *lastx) {
|
|
|
+ xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx - 1),
|
|
|
+ bma->prevp);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ alen = (xfs_extlen_t)XFS_FILBLKS_MIN(bma->alen, MAXEXTLEN);
|
|
|
+ if (!bma->eof)
|
|
|
+ alen = (xfs_extlen_t)XFS_FILBLKS_MIN(alen,
|
|
|
+ bma->gotp->br_startoff - bma->off);
|
|
|
+ aoff = bma->off;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Indicate if this is the first user data in the file, or just any
|
|
|
+ * user data.
|
|
|
+ */
|
|
|
+ if (!(flags & XFS_BMAPI_METADATA)) {
|
|
|
+ bma->userdata = (aoff == 0) ?
|
|
|
+ XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Fill in changeable bma fields.
|
|
|
+ */
|
|
|
+ bma->alen = alen;
|
|
|
+ bma->off = aoff;
|
|
|
+ bma->firstblock = *firstblock;
|
|
|
+ bma->minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1;
|
|
|
+ bma->low = flist->xbf_low;
|
|
|
+ bma->aeof = 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Only want to do the alignment at the eof if it is userdata and
|
|
|
+ * allocation length is larger than a stripe unit.
|
|
|
+ */
|
|
|
+ if (mp->m_dalign && alen >= mp->m_dalign &&
|
|
|
+ !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
|
|
|
+ error = xfs_bmap_isaeof(bma->ip, aoff, whichfork, &bma->aeof);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+
|
|
|
+ error = xfs_bmap_alloc(bma);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Copy out result fields.
|
|
|
+ */
|
|
|
+ abno = bma->rval;
|
|
|
+ flist->xbf_low = bma->low;
|
|
|
+ alen = bma->alen;
|
|
|
+ aoff = bma->off;
|
|
|
+ ASSERT(*firstblock == NULLFSBLOCK ||
|
|
|
+ XFS_FSB_TO_AGNO(mp, *firstblock) ==
|
|
|
+ XFS_FSB_TO_AGNO(mp, bma->firstblock) ||
|
|
|
+ (flist->xbf_low &&
|
|
|
+ XFS_FSB_TO_AGNO(mp, *firstblock) <
|
|
|
+ XFS_FSB_TO_AGNO(mp, bma->firstblock)));
|
|
|
+ *firstblock = bma->firstblock;
|
|
|
+ if (*cur)
|
|
|
+ (*cur)->bc_private.b.firstblock = *firstblock;
|
|
|
+ if (abno == NULLFSBLOCK)
|
|
|
+ return 0;
|
|
|
+ if ((ifp->if_flags & XFS_IFBROOT) && !*cur) {
|
|
|
+ (*cur) = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork);
|
|
|
+ (*cur)->bc_private.b.firstblock = *firstblock;
|
|
|
+ (*cur)->bc_private.b.flist = flist;
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * Bump the number of extents we've allocated
|
|
|
+ * in this call.
|
|
|
+ */
|
|
|
+ (*nallocs)++;
|
|
|
+
|
|
|
+ if (*cur)
|
|
|
+ (*cur)->bc_private.b.flags =
|
|
|
+ bma->wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
|
|
|
+
|
|
|
+ bma->gotp->br_startoff = aoff;
|
|
|
+ bma->gotp->br_startblock = abno;
|
|
|
+ bma->gotp->br_blockcount = alen;
|
|
|
+ bma->gotp->br_state = XFS_EXT_NORM;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * A wasdelay extent has been initialized, so shouldn't be flagged
|
|
|
+ * as unwritten.
|
|
|
+ */
|
|
|
+ if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) &&
|
|
|
+ xfs_sb_version_hasextflgbit(&mp->m_sb))
|
|
|
+ bma->gotp->br_state = XFS_EXT_UNWRITTEN;
|
|
|
+
|
|
|
+ error = xfs_bmap_add_extent(bma->tp, bma->ip, lastx, cur, bma->gotp,
|
|
|
+ firstblock, flist, logflags, whichfork);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Update our extent pointer, given that xfs_bmap_add_extent might
|
|
|
+ * have merged it into one of the neighbouring ones.
|
|
|
+ */
|
|
|
+ xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), bma->gotp);
|
|
|
+
|
|
|
+ ASSERT(bma->gotp->br_startoff <= aoff);
|
|
|
+ ASSERT(bma->gotp->br_startoff + bma->gotp->br_blockcount >=
|
|
|
+ aoff + alen);
|
|
|
+ ASSERT(bma->gotp->br_state == XFS_EXT_NORM ||
|
|
|
+ bma->gotp->br_state == XFS_EXT_UNWRITTEN);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Map file blocks to filesystem blocks.
|
|
|
* File range is given by the bno/len pair.
|
|
@@ -4632,9 +4773,6 @@ xfs_bmapi(
|
|
|
int *nmap, /* i/o: mval size/count */
|
|
|
xfs_bmap_free_t *flist) /* i/o: list extents to free */
|
|
|
{
|
|
|
- xfs_fsblock_t abno; /* allocated block number */
|
|
|
- xfs_extlen_t alen; /* allocated extent length */
|
|
|
- xfs_fileoff_t aoff; /* allocated file offset */
|
|
|
xfs_bmalloca_t bma = { 0 }; /* args for xfs_bmap_alloc */
|
|
|
xfs_btree_cur_t *cur; /* bmap btree cursor */
|
|
|
xfs_fileoff_t end; /* end of mapped file region */
|
|
@@ -4646,7 +4784,6 @@ xfs_bmapi(
|
|
|
xfs_extnum_t lastx; /* last useful extent number */
|
|
|
int logflags; /* flags for transaction logging */
|
|
|
xfs_extlen_t minleft; /* min blocks left after allocation */
|
|
|
- xfs_extlen_t minlen; /* min allocation size */
|
|
|
xfs_mount_t *mp; /* xfs mount structure */
|
|
|
int n; /* current extent index */
|
|
|
int nallocs; /* number of extents alloc'd */
|
|
@@ -4737,7 +4874,13 @@ xfs_bmapi(
|
|
|
n = 0;
|
|
|
end = bno + len;
|
|
|
obno = bno;
|
|
|
- bma.ip = NULL;
|
|
|
+
|
|
|
+ bma.tp = tp;
|
|
|
+ bma.ip = ip;
|
|
|
+ bma.prevp = &prev;
|
|
|
+ bma.gotp = &got;
|
|
|
+ bma.total = total;
|
|
|
+ bma.userdata = 0;
|
|
|
|
|
|
while (bno < end && n < *nmap) {
|
|
|
/*
|
|
@@ -4753,144 +4896,23 @@ xfs_bmapi(
|
|
|
* that we found, if any.
|
|
|
*/
|
|
|
if (wr && (inhole || wasdelay)) {
|
|
|
- /*
|
|
|
- * For the wasdelay case, we could also just
|
|
|
- * allocate the stuff asked for in this bmap call
|
|
|
- * but that wouldn't be as good.
|
|
|
- */
|
|
|
- if (wasdelay) {
|
|
|
- alen = (xfs_extlen_t)got.br_blockcount;
|
|
|
- aoff = got.br_startoff;
|
|
|
- if (lastx != NULLEXTNUM && lastx) {
|
|
|
- ep = xfs_iext_get_ext(ifp, lastx - 1);
|
|
|
- xfs_bmbt_get_all(ep, &prev);
|
|
|
- }
|
|
|
- } else {
|
|
|
- alen = (xfs_extlen_t)
|
|
|
- XFS_FILBLKS_MIN(len, MAXEXTLEN);
|
|
|
- if (!eof)
|
|
|
- alen = (xfs_extlen_t)
|
|
|
- XFS_FILBLKS_MIN(alen,
|
|
|
- got.br_startoff - bno);
|
|
|
- aoff = bno;
|
|
|
- }
|
|
|
- minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1;
|
|
|
- {
|
|
|
- /*
|
|
|
- * If first time, allocate and fill in
|
|
|
- * once-only bma fields.
|
|
|
- */
|
|
|
- if (bma.ip == NULL) {
|
|
|
- bma.tp = tp;
|
|
|
- bma.ip = ip;
|
|
|
- bma.prevp = &prev;
|
|
|
- bma.gotp = &got;
|
|
|
- bma.total = total;
|
|
|
- bma.userdata = 0;
|
|
|
- }
|
|
|
- /* Indicate if this is the first user data
|
|
|
- * in the file, or just any user data.
|
|
|
- */
|
|
|
- if (!(flags & XFS_BMAPI_METADATA)) {
|
|
|
- bma.userdata = (aoff == 0) ?
|
|
|
- XFS_ALLOC_INITIAL_USER_DATA :
|
|
|
- XFS_ALLOC_USERDATA;
|
|
|
- }
|
|
|
- /*
|
|
|
- * Fill in changeable bma fields.
|
|
|
- */
|
|
|
- bma.eof = eof;
|
|
|
- bma.firstblock = *firstblock;
|
|
|
- bma.alen = alen;
|
|
|
- bma.off = aoff;
|
|
|
- bma.conv = !!(flags & XFS_BMAPI_CONVERT);
|
|
|
- bma.wasdel = wasdelay;
|
|
|
- bma.minlen = minlen;
|
|
|
- bma.low = flist->xbf_low;
|
|
|
- bma.minleft = minleft;
|
|
|
- /*
|
|
|
- * Only want to do the alignment at the
|
|
|
- * eof if it is userdata and allocation length
|
|
|
- * is larger than a stripe unit.
|
|
|
- */
|
|
|
- if (mp->m_dalign && alen >= mp->m_dalign &&
|
|
|
- (!(flags & XFS_BMAPI_METADATA)) &&
|
|
|
- (whichfork == XFS_DATA_FORK)) {
|
|
|
- if ((error = xfs_bmap_isaeof(ip, aoff,
|
|
|
- whichfork, &bma.aeof)))
|
|
|
- goto error0;
|
|
|
- } else
|
|
|
- bma.aeof = 0;
|
|
|
- /*
|
|
|
- * Call allocator.
|
|
|
- */
|
|
|
- if ((error = xfs_bmap_alloc(&bma)))
|
|
|
- goto error0;
|
|
|
- /*
|
|
|
- * Copy out result fields.
|
|
|
- */
|
|
|
- abno = bma.rval;
|
|
|
- if ((flist->xbf_low = bma.low))
|
|
|
- minleft = 0;
|
|
|
- alen = bma.alen;
|
|
|
- aoff = bma.off;
|
|
|
- ASSERT(*firstblock == NULLFSBLOCK ||
|
|
|
- XFS_FSB_TO_AGNO(mp, *firstblock) ==
|
|
|
- XFS_FSB_TO_AGNO(mp, bma.firstblock) ||
|
|
|
- (flist->xbf_low &&
|
|
|
- XFS_FSB_TO_AGNO(mp, *firstblock) <
|
|
|
- XFS_FSB_TO_AGNO(mp, bma.firstblock)));
|
|
|
- *firstblock = bma.firstblock;
|
|
|
- if (cur)
|
|
|
- cur->bc_private.b.firstblock =
|
|
|
- *firstblock;
|
|
|
- if (abno == NULLFSBLOCK)
|
|
|
- break;
|
|
|
- if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
|
|
|
- cur = xfs_bmbt_init_cursor(mp, tp,
|
|
|
- ip, whichfork);
|
|
|
- cur->bc_private.b.firstblock =
|
|
|
- *firstblock;
|
|
|
- cur->bc_private.b.flist = flist;
|
|
|
- }
|
|
|
- /*
|
|
|
- * Bump the number of extents we've allocated
|
|
|
- * in this call.
|
|
|
- */
|
|
|
- nallocs++;
|
|
|
- }
|
|
|
- if (cur)
|
|
|
- cur->bc_private.b.flags =
|
|
|
- wasdelay ? XFS_BTCUR_BPRV_WASDEL : 0;
|
|
|
- got.br_startoff = aoff;
|
|
|
- got.br_startblock = abno;
|
|
|
- got.br_blockcount = alen;
|
|
|
- got.br_state = XFS_EXT_NORM; /* assume normal */
|
|
|
- /*
|
|
|
- * Determine state of extent, and the filesystem.
|
|
|
- * A wasdelay extent has been initialized, so
|
|
|
- * shouldn't be flagged as unwritten.
|
|
|
- */
|
|
|
- if (wr && xfs_sb_version_hasextflgbit(&mp->m_sb)) {
|
|
|
- if (!wasdelay && (flags & XFS_BMAPI_PREALLOC))
|
|
|
- got.br_state = XFS_EXT_UNWRITTEN;
|
|
|
- }
|
|
|
- error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, &got,
|
|
|
- firstblock, flist, &tmp_logflags,
|
|
|
- whichfork);
|
|
|
+ bma.eof = eof;
|
|
|
+ bma.conv = !!(flags & XFS_BMAPI_CONVERT);
|
|
|
+ bma.wasdel = wasdelay;
|
|
|
+ bma.alen = len;
|
|
|
+ bma.off = bno;
|
|
|
+ bma.minleft = minleft;
|
|
|
+
|
|
|
+ error = xfs_bmapi_allocate(&bma, &lastx, &cur,
|
|
|
+ firstblock, flist, flags, &nallocs,
|
|
|
+ &tmp_logflags);
|
|
|
logflags |= tmp_logflags;
|
|
|
if (error)
|
|
|
goto error0;
|
|
|
- ep = xfs_iext_get_ext(ifp, lastx);
|
|
|
- xfs_bmbt_get_all(ep, &got);
|
|
|
- ASSERT(got.br_startoff <= aoff);
|
|
|
- ASSERT(got.br_startoff + got.br_blockcount >=
|
|
|
- aoff + alen);
|
|
|
- ASSERT(got.br_state == XFS_EXT_NORM ||
|
|
|
- got.br_state == XFS_EXT_UNWRITTEN);
|
|
|
- /*
|
|
|
- * Fall down into the found allocated space case.
|
|
|
- */
|
|
|
+ if (flist && flist->xbf_low)
|
|
|
+ minleft = 0;
|
|
|
+ if (bma.rval == NULLFSBLOCK)
|
|
|
+ break;
|
|
|
} else if (inhole) {
|
|
|
/*
|
|
|
* Reading in a hole.
|