Skip to content

Commit

Permalink
Merge branch 'xfs-4.10-extent-lookup' into for-next
Browse files Browse the repository at this point in the history
  • Loading branch information
dchinner committed Nov 24, 2016
2 parents 0fc204e + 0e8d630 commit ed24bee
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 267 deletions.
234 changes: 65 additions & 169 deletions fs/xfs/libxfs/xfs_bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1370,97 +1370,6 @@ xfs_bmap_read_extents(
return -EFSCORRUPTED;
}


/*
* Search the extent records for the entry containing block bno.
* If bno lies in a hole, point to the next entry. If bno lies
* past eof, *eofp will be set, and *prevp will contain the last
* entry (null if none). Else, *lastxp will be set to the index
* of the found entry; *gotp will contain the entry.
*/
STATIC xfs_bmbt_rec_host_t * /* pointer to found extent entry */
xfs_bmap_search_multi_extents(
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_fileoff_t bno, /* block number searched for */
int *eofp, /* out: end of file found */
xfs_extnum_t *lastxp, /* out: last extent index */
xfs_bmbt_irec_t *gotp, /* out: extent entry found */
xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
{
xfs_bmbt_rec_host_t *ep; /* extent record pointer */
xfs_extnum_t lastx; /* last extent index */

/*
* Initialize the extent entry structure to catch access to
* uninitialized br_startblock field.
*/
gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL;
gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL;
gotp->br_state = XFS_EXT_INVALID;
gotp->br_startblock = 0xffffa5a5a5a5a5a5LL;
prevp->br_startoff = NULLFILEOFF;

ep = xfs_iext_bno_to_ext(ifp, bno, &lastx);
if (lastx > 0) {
xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp);
}
if (lastx < xfs_iext_count(ifp)) {
xfs_bmbt_get_all(ep, gotp);
*eofp = 0;
} else {
if (lastx > 0) {
*gotp = *prevp;
}
*eofp = 1;
ep = NULL;
}
*lastxp = lastx;
return ep;
}

/*
* Search the extents list for the inode, for the extent containing bno.
* If bno lies in a hole, point to the next entry. If bno lies past eof,
* *eofp will be set, and *prevp will contain the last entry (null if none).
* Else, *lastxp will be set to the index of the found
* entry; *gotp will contain the entry.
*/
xfs_bmbt_rec_host_t * /* pointer to found extent entry */
xfs_bmap_search_extents(
xfs_inode_t *ip, /* incore inode pointer */
xfs_fileoff_t bno, /* block number searched for */
int fork, /* data or attr fork */
int *eofp, /* out: end of file found */
xfs_extnum_t *lastxp, /* out: last extent index */
xfs_bmbt_irec_t *gotp, /* out: extent entry found */
xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
{
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_bmbt_rec_host_t *ep; /* extent record pointer */

XFS_STATS_INC(ip->i_mount, xs_look_exlist);
ifp = XFS_IFORK_PTR(ip, fork);

ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp);

if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&
!(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) {
xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO,
"Access to block zero in inode %llu "
"start_block: %llx start_off: %llx "
"blkcnt: %llx extent-state: %x lastx: %x",
(unsigned long long)ip->i_ino,
(unsigned long long)gotp->br_startblock,
(unsigned long long)gotp->br_startoff,
(unsigned long long)gotp->br_blockcount,
gotp->br_state, *lastxp);
*lastxp = NULLEXTNUM;
*eofp = 1;
return NULL;
}
return ep;
}

/*
* Returns the file-relative block number of the first unused block(s)
* in the file with at least "len" logically contiguous blocks free.
Expand Down Expand Up @@ -1523,44 +1432,44 @@ xfs_bmap_first_unused(
*/
int /* error */
xfs_bmap_last_before(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *ip, /* incore inode */
xfs_fileoff_t *last_block, /* last block */
int whichfork) /* data or attr fork */
struct xfs_trans *tp, /* transaction pointer */
struct xfs_inode *ip, /* incore inode */
xfs_fileoff_t *last_block, /* last block */
int whichfork) /* data or attr fork */
{
xfs_fileoff_t bno; /* input file offset */
int eof; /* hit end of file */
xfs_bmbt_rec_host_t *ep; /* pointer to last extent */
int error; /* error return value */
xfs_bmbt_irec_t got; /* current extent value */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_extnum_t lastx; /* last extent used */
xfs_bmbt_irec_t prev; /* previous extent value */
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
struct xfs_bmbt_irec got;
xfs_extnum_t idx;
int error;

if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
return -EIO;
if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
switch (XFS_IFORK_FORMAT(ip, whichfork)) {
case XFS_DINODE_FMT_LOCAL:
*last_block = 0;
return 0;
case XFS_DINODE_FMT_BTREE:
case XFS_DINODE_FMT_EXTENTS:
break;
default:
return -EIO;
}
ifp = XFS_IFORK_PTR(ip, whichfork);
if (!(ifp->if_flags & XFS_IFEXTENTS) &&
(error = xfs_iread_extents(tp, ip, whichfork)))
return error;
bno = *last_block - 1;
ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
&prev);
if (eof || xfs_bmbt_get_startoff(ep) > bno) {
if (prev.br_startoff == NULLFILEOFF)
*last_block = 0;
else
*last_block = prev.br_startoff + prev.br_blockcount;

if (!(ifp->if_flags & XFS_IFEXTENTS)) {
error = xfs_iread_extents(tp, ip, whichfork);
if (error)
return error;
}
/*
* Otherwise *last_block is already the right answer.
*/

if (xfs_iext_lookup_extent(ip, ifp, *last_block - 1, &idx, &got)) {
if (got.br_startoff <= *last_block - 1)
return 0;
}

if (xfs_iext_get_extent(ifp, idx - 1, &got)) {
*last_block = got.br_startoff + got.br_blockcount;
return 0;
}

*last_block = 0;
return 0;
}

Expand Down Expand Up @@ -4145,12 +4054,11 @@ xfs_bmapi_read(
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp;
struct xfs_bmbt_irec got;
struct xfs_bmbt_irec prev;
xfs_fileoff_t obno;
xfs_fileoff_t end;
xfs_extnum_t lastx;
xfs_extnum_t idx;
int error;
int eof;
bool eof = false;
int n = 0;
int whichfork = xfs_bmapi_whichfork(flags);

Expand Down Expand Up @@ -4190,7 +4098,8 @@ xfs_bmapi_read(
return error;
}

xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev);
if (!xfs_iext_lookup_extent(ip, ifp, bno, &idx, &got))
eof = true;
end = bno + len;
obno = bno;

Expand Down Expand Up @@ -4221,10 +4130,8 @@ xfs_bmapi_read(
break;

/* Else go on to the next record. */
if (++lastx < xfs_iext_count(ifp))
xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got);
else
eof = 1;
if (!xfs_iext_get_extent(ifp, ++idx, &got))
eof = true;
}
*nmap = n;
return 0;
Expand All @@ -4237,7 +4144,6 @@ xfs_bmapi_reserve_delalloc(
xfs_fileoff_t aoff,
xfs_filblks_t len,
struct xfs_bmbt_irec *got,
struct xfs_bmbt_irec *prev,
xfs_extnum_t *lastx,
int eof)
{
Expand All @@ -4259,7 +4165,12 @@ xfs_bmapi_reserve_delalloc(
else
extsz = xfs_get_extsz_hint(ip);
if (extsz) {
error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof,
struct xfs_bmbt_irec prev;

if (!xfs_iext_get_extent(ifp, *lastx - 1, &prev))
prev.br_startoff = NULLFILEOFF;

error = xfs_bmap_extsize_align(mp, got, &prev, extsz, rt, eof,
1, 0, &aoff, &alen);
ASSERT(!error);
}
Expand Down Expand Up @@ -4349,7 +4260,7 @@ xfs_bmapi_allocate(
if (bma->wasdel) {
bma->length = (xfs_extlen_t)bma->got.br_blockcount;
bma->offset = bma->got.br_startoff;
if (bma->idx != NULLEXTNUM && bma->idx) {
if (bma->idx) {
xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1),
&bma->prev);
}
Expand Down Expand Up @@ -4563,7 +4474,7 @@ xfs_bmapi_write(
struct xfs_ifork *ifp;
struct xfs_bmalloca bma = { NULL }; /* args for xfs_bmap_alloc */
xfs_fileoff_t end; /* end of mapped file region */
int eof; /* after the end of extents */
bool eof = false; /* after the end of extents */
int error; /* error return */
int n; /* current extent index */
xfs_fileoff_t obno; /* old block number (offset) */
Expand Down Expand Up @@ -4641,12 +4552,14 @@ xfs_bmapi_write(
goto error0;
}

xfs_bmap_search_extents(ip, bno, whichfork, &eof, &bma.idx, &bma.got,
&bma.prev);
n = 0;
end = bno + len;
obno = bno;

if (!xfs_iext_lookup_extent(ip, ifp, bno, &bma.idx, &bma.got))
eof = true;
if (!xfs_iext_get_extent(ifp, bma.idx - 1, &bma.prev))
bma.prev.br_startoff = NULLFILEOFF;
bma.tp = tp;
bma.ip = ip;
bma.total = total;
Expand Down Expand Up @@ -4733,11 +4646,8 @@ xfs_bmapi_write(

/* Else go on to the next record. */
bma.prev = bma.got;
if (++bma.idx < xfs_iext_count(ifp)) {
xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma.idx),
&bma.got);
} else
eof = 1;
if (!xfs_iext_get_extent(ifp, ++bma.idx, &bma.got))
eof = true;
}
*nmap = n;

Expand Down Expand Up @@ -5436,8 +5346,6 @@ __xfs_bunmapi(
{
xfs_btree_cur_t *cur; /* bmap btree cursor */
xfs_bmbt_irec_t del; /* extent being deleted */
int eof; /* is deleting at eof */
xfs_bmbt_rec_host_t *ep; /* extent record pointer */
int error; /* error return value */
xfs_extnum_t extno; /* extent number in list */
xfs_bmbt_irec_t got; /* current extent record */
Expand All @@ -5447,7 +5355,6 @@ __xfs_bunmapi(
int logflags; /* transaction logging flags */
xfs_extlen_t mod; /* rt extent offset */
xfs_mount_t *mp; /* mount structure */
xfs_bmbt_irec_t prev; /* previous extent record */
xfs_fileoff_t start; /* first file offset deleted */
int tmp_logflags; /* partial logging flags */
int wasdel; /* was a delayed alloc extent */
Expand Down Expand Up @@ -5486,18 +5393,17 @@ __xfs_bunmapi(
isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
start = bno;
bno = start + len - 1;
ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
&prev);

/*
* Check to see if the given block number is past the end of the
* file, back up to the last block if so...
*/
if (eof) {
ep = xfs_iext_get_ext(ifp, --lastx);
xfs_bmbt_get_all(ep, &got);
if (!xfs_iext_lookup_extent(ip, ifp, bno, &lastx, &got)) {
ASSERT(lastx > 0);
xfs_iext_get_extent(ifp, --lastx, &got);
bno = got.br_startoff + got.br_blockcount - 1;
}

logflags = 0;
if (ifp->if_flags & XFS_IFBROOT) {
ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
Expand Down Expand Up @@ -5528,8 +5434,7 @@ __xfs_bunmapi(
if (got.br_startoff > bno) {
if (--lastx < 0)
break;
ep = xfs_iext_get_ext(ifp, lastx);
xfs_bmbt_get_all(ep, &got);
xfs_iext_get_extent(ifp, lastx, &got);
}
/*
* Is the last block of this extent before the range
Expand All @@ -5543,7 +5448,6 @@ __xfs_bunmapi(
* Then deal with the (possibly delayed) allocated space
* we found.
*/
ASSERT(ep != NULL);
del = got;
wasdel = isnullstartblock(del.br_startblock);
if (got.br_startoff < start) {
Expand Down Expand Up @@ -5624,24 +5528,20 @@ __xfs_bunmapi(
*/
ASSERT(bno >= del.br_blockcount);
bno -= del.br_blockcount;
if (got.br_startoff > bno) {
if (--lastx >= 0) {
ep = xfs_iext_get_ext(ifp,
lastx);
xfs_bmbt_get_all(ep, &got);
}
}
if (got.br_startoff > bno && --lastx >= 0)
xfs_iext_get_extent(ifp, lastx, &got);
continue;
} else if (del.br_state == XFS_EXT_UNWRITTEN) {
struct xfs_bmbt_irec prev;

/*
* This one is already unwritten.
* It must have a written left neighbor.
* Unwrite the killed part of that one and
* try again.
*/
ASSERT(lastx > 0);
xfs_bmbt_get_all(xfs_iext_get_ext(ifp,
lastx - 1), &prev);
xfs_iext_get_extent(ifp, lastx - 1, &prev);
ASSERT(prev.br_state == XFS_EXT_NORM);
ASSERT(!isnullstartblock(prev.br_startblock));
ASSERT(del.br_startblock ==
Expand Down Expand Up @@ -5739,13 +5639,9 @@ __xfs_bunmapi(
*/
if (bno != (xfs_fileoff_t)-1 && bno >= start) {
if (lastx >= 0) {
ep = xfs_iext_get_ext(ifp, lastx);
if (xfs_bmbt_get_startoff(ep) > bno) {
if (--lastx >= 0)
ep = xfs_iext_get_ext(ifp,
lastx);
}
xfs_bmbt_get_all(ep, &got);
xfs_iext_get_extent(ifp, lastx, &got);
if (got.br_startoff > bno && --lastx >= 0)
xfs_iext_get_extent(ifp, lastx, &got);
}
extno++;
}
Expand Down
Loading

0 comments on commit ed24bee

Please sign in to comment.