Skip to content

Commit

Permalink
[XFS] implement generic xfs_btree_update
Browse files Browse the repository at this point in the history
From: Dave Chinner <dgc@sgi.com>

The most complicated part here is the lastrec tracking for the alloc
btree. Most logic is in the update_lastrec method which has to do some
hopefully good enough dirty magic to maintain it.

[hch: split out from bigger patch and a rework of the lastrec

logic]

SGI-PV: 985583

SGI-Modid: xfs-linux-melb:xfs-kern:32194a

Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: Bill O'Donnell <billodo@sgi.com>
Signed-off-by: David Chinner <david@fromorbit.com>
  • Loading branch information
Christoph Hellwig authored and Lachlan McIlroy committed Oct 30, 2008
1 parent 38bb742 commit 278d0ca
Show file tree
Hide file tree
Showing 11 changed files with 228 additions and 182 deletions.
17 changes: 17 additions & 0 deletions fs/xfs/xfs_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,23 @@ xfs_alloc_lookup_le(
return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
}

/*
* Update the record referred to by cur to the value given
* by [bno, len].
* This either works (return 0) or gets an EFSCORRUPTED error.
*/
STATIC int /* error */
xfs_alloc_update(
struct xfs_btree_cur *cur, /* btree cursor */
xfs_agblock_t bno, /* starting block of extent */
xfs_extlen_t len) /* length of extent */
{
union xfs_btree_rec rec;

rec.alloc.ar_startblock = cpu_to_be32(bno);
rec.alloc.ar_blockcount = cpu_to_be32(len);
return xfs_btree_update(cur, &rec);
}

/*
* Compute aligned version of the found extent.
Expand Down
106 changes: 38 additions & 68 deletions fs/xfs/xfs_alloc_btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1661,83 +1661,50 @@ xfs_alloc_insert(
return 0;
}

STATIC struct xfs_btree_cur *
xfs_allocbt_dup_cursor(
struct xfs_btree_cur *cur)
{
return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
cur->bc_private.a.agbp, cur->bc_private.a.agno,
cur->bc_btnum);
}

/*
* Update the record referred to by cur, to the value given by [bno, len].
* This either works (return 0) or gets an EFSCORRUPTED error.
* Update the longest extent in the AGF
*/
int /* error */
xfs_alloc_update(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_agblock_t bno, /* starting block of extent */
xfs_extlen_t len) /* length of extent */
STATIC void
xfs_allocbt_update_lastrec(
struct xfs_btree_cur *cur,
struct xfs_btree_block *block,
union xfs_btree_rec *rec,
int ptr,
int reason)
{
xfs_alloc_block_t *block; /* btree block to update */
int error; /* error return value */
int ptr; /* current record number (updating) */
struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno);
__be32 len;

ASSERT(len > 0);
/*
* Pick up the a.g. freelist struct and the current block.
*/
block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]);
#ifdef DEBUG
if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0])))
return error;
#endif
/*
* Get the address of the rec to be updated.
*/
ptr = cur->bc_ptrs[0];
{
xfs_alloc_rec_t *rp; /* pointer to updated record */
ASSERT(cur->bc_btnum == XFS_BTNUM_CNT);

rp = XFS_ALLOC_REC_ADDR(block, ptr, cur);
switch (reason) {
case LASTREC_UPDATE:
/*
* Fill in the new contents and log them.
* If this is the last leaf block and it's the last record,
* then update the size of the longest extent in the AG.
*/
rp->ar_startblock = cpu_to_be32(bno);
rp->ar_blockcount = cpu_to_be32(len);
xfs_alloc_log_recs(cur, cur->bc_bufs[0], ptr, ptr);
}
/*
* If it's the by-size btree and it's the last leaf block and
* it's the last record... then update the size of the longest
* extent in the a.g., which we cache in the a.g. freelist header.
*/
if (cur->bc_btnum == XFS_BTNUM_CNT &&
be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK &&
ptr == be16_to_cpu(block->bb_numrecs)) {
xfs_agf_t *agf; /* a.g. freespace header */
xfs_agnumber_t seqno;

agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
seqno = be32_to_cpu(agf->agf_seqno);
cur->bc_mp->m_perag[seqno].pagf_longest = len;
agf->agf_longest = cpu_to_be32(len);
xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
XFS_AGF_LONGEST);
}
/*
* Updating first record in leaf. Pass new key value up to our parent.
*/
if (ptr == 1) {
xfs_alloc_key_t key; /* key containing [bno, len] */

key.ar_startblock = cpu_to_be32(bno);
key.ar_blockcount = cpu_to_be32(len);
if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, 1)))
return error;
if (ptr != xfs_btree_get_numrecs(block))
return;
len = rec->alloc.ar_blockcount;
break;
default:
ASSERT(0);
return;
}
return 0;
}

STATIC struct xfs_btree_cur *
xfs_allocbt_dup_cursor(
struct xfs_btree_cur *cur)
{
return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
cur->bc_private.a.agbp, cur->bc_private.a.agno,
cur->bc_btnum);
agf->agf_longest = len;
cur->bc_mp->m_perag[seqno].pagf_longest = be32_to_cpu(len);
xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST);
}

STATIC int
Expand Down Expand Up @@ -1864,6 +1831,7 @@ static const struct xfs_btree_ops xfs_allocbt_ops = {
.key_len = sizeof(xfs_alloc_key_t),

.dup_cursor = xfs_allocbt_dup_cursor,
.update_lastrec = xfs_allocbt_update_lastrec,
.get_maxrecs = xfs_allocbt_get_maxrecs,
.init_key_from_rec = xfs_allocbt_init_key_from_rec,
.init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur,
Expand Down Expand Up @@ -1902,6 +1870,8 @@ xfs_allocbt_init_cursor(
cur->bc_blocklog = mp->m_sb.sb_blocklog;

cur->bc_ops = &xfs_allocbt_ops;
if (btnum == XFS_BTNUM_CNT)
cur->bc_flags = XFS_BTREE_LASTREC_UPDATE;

cur->bc_private.a.agbp = agbp;
cur->bc_private.a.agno = agno;
Expand Down
7 changes: 0 additions & 7 deletions fs/xfs/xfs_alloc_btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,6 @@ extern int xfs_alloc_get_rec(struct xfs_btree_cur *cur, xfs_agblock_t *bno,
*/
extern int xfs_alloc_insert(struct xfs_btree_cur *cur, int *stat);

/*
* Update the record referred to by cur, to the value given by [bno, len].
* This either works (return 0) or gets an EFSCORRUPTED error.
*/
extern int xfs_alloc_update(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len);


extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *,
struct xfs_trans *, struct xfs_buf *,
Expand Down
18 changes: 18 additions & 0 deletions fs/xfs/xfs_bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,24 @@ xfs_bmbt_lookup_ge(
return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat);
}

/*
* Update the record referred to by cur to the value given
* by [off, bno, len, state].
* This either works (return 0) or gets an EFSCORRUPTED error.
*/
STATIC int
xfs_bmbt_update(
struct xfs_btree_cur *cur,
xfs_fileoff_t off,
xfs_fsblock_t bno,
xfs_filblks_t len,
xfs_exntst_t state)
{
union xfs_btree_rec rec;

xfs_bmbt_disk_set_allf(&rec.bmbt, off, bno, len, state);
return xfs_btree_update(cur, &rec);
}

/*
* Called from xfs_bmap_add_attrfork to handle btree format files.
Expand Down
45 changes: 0 additions & 45 deletions fs/xfs/xfs_bmap_btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1963,51 +1963,6 @@ xfs_bmbt_to_bmdr(
memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
}

/*
* Update the record to the passed values.
*/
int
xfs_bmbt_update(
xfs_btree_cur_t *cur,
xfs_fileoff_t off,
xfs_fsblock_t bno,
xfs_filblks_t len,
xfs_exntst_t state)
{
xfs_bmbt_block_t *block;
xfs_buf_t *bp;
int error;
xfs_bmbt_key_t key;
int ptr;
xfs_bmbt_rec_t *rp;

XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno,
(xfs_dfilblks_t)len, (int)state);
block = xfs_bmbt_get_block(cur, 0, &bp);
#ifdef DEBUG
if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) {
XFS_BMBT_TRACE_CURSOR(cur, ERROR);
return error;
}
#endif
ptr = cur->bc_ptrs[0];
rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
xfs_bmbt_disk_set_allf(rp, off, bno, len, state);
xfs_bmbt_log_recs(cur, bp, ptr, ptr);
if (ptr > 1) {
XFS_BMBT_TRACE_CURSOR(cur, EXIT);
return 0;
}
key.br_startoff = cpu_to_be64(off);
if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, 1))) {
XFS_BMBT_TRACE_CURSOR(cur, ERROR);
return error;
}
XFS_BMBT_TRACE_CURSOR(cur, EXIT);
return 0;
}

/*
* Check extent records, which have just been read, for
* any bit in the extent flag field. ASSERT on debug
Expand Down
2 changes: 0 additions & 2 deletions fs/xfs/xfs_bmap_btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,6 @@ extern void xfs_bmbt_disk_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o,
xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);

extern void xfs_bmbt_to_bmdr(xfs_bmbt_block_t *, int, xfs_bmdr_block_t *, int);
extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t,
xfs_fsblock_t, xfs_filblks_t, xfs_exntst_t);

extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
struct xfs_trans *, struct xfs_inode *, int);
Expand Down
Loading

0 comments on commit 278d0ca

Please sign in to comment.