* [PATCH 13/21] implement generic xfs_btree_update
@ 2008-07-29 19:31 Christoph Hellwig
2008-07-30 5:29 ` Dave Chinner
0 siblings, 1 reply; 4+ messages in thread
From: Christoph Hellwig @ 2008-07-29 19:31 UTC (permalink / raw)
To: xfs
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: xfs-common-btree-update --]
[-- Type: text/plain; charset=unknown-8bit, Size: 27279 bytes --]
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]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: linux-2.6-xfs/fs/xfs/xfs_btree.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_btree.c 2008-07-21 05:10:43.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_btree.c 2008-07-21 05:24:20.000000000 +0200
@@ -867,6 +867,30 @@ xfs_btree_get_sibling(
}
}
+/*
+ * Return true if ptr is the last record in the btree and
+ * we need to track updateѕ to this record. The decision
+ * will be further refined in the update_lastrec method.
+ */
+STATIC int
+xfs_btree_is_lastrec(
+ struct xfs_btree_cur *cur,
+ struct xfs_btree_block *block,
+ int level)
+{
+ union xfs_btree_ptr ptr;
+
+ if (level > 0)
+ return 0;
+ if (!(cur->bc_flags & XFS_BTREE_LASTREC_UPDATE))
+ return 0;
+
+ xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB);
+ if (!xfs_btree_ptr_is_null(cur, &ptr))
+ return 0;
+ return 1;
+}
+
STATIC struct xfs_btree_block *
xfs_btree_buf_to_block(
struct xfs_btree_cur *cur,
@@ -1417,3 +1441,66 @@ xfs_btree_updkey(
XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
return 0;
}
+
+/*
+ * Update the record referred to by cur to the value in the
+ * given record. This either works (return 0) or gets an
+ * EFSCORRUPTED error.
+ */
+int
+xfs_btree_update(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_rec *rec)
+{
+ struct xfs_btree_block *block;
+ struct xfs_buf *bp;
+ int error;
+ int ptr;
+ union xfs_btree_rec *rp;
+
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
+ XFS_BTREE_TRACE_ARGR(cur, rec);
+
+ /* Pick up the current block. */
+ block = xfs_btree_get_block(cur, 0, &bp);
+
+#ifdef DEBUG
+ error = xfs_btree_check_block(cur, block, 0, bp);
+ if (error)
+ goto error0;
+#endif
+ /* Get the address of the rec to be updated. */
+ ptr = cur->bc_ptrs[0];
+ rp = cur->bc_ops->rec_addr(cur, ptr, block);
+
+ /* Fill in the new contents and log them. */
+ cur->bc_ops->copy_recs(cur, rec, rp, 1);
+ cur->bc_ops->log_recs(cur, bp, ptr, ptr);
+
+ /*
+ * If we are tracking the last record in the tree and
+ * we are at the far right edge of the tree, update it.
+ */
+ if (xfs_btree_is_lastrec(cur, block, 0)) {
+ cur->bc_ops->update_lastrec(cur, block, rec,
+ ptr, LASTREC_UPDATE);
+ }
+
+ /* Updating first rec in leaf. Pass new key value up to our parent. */
+ if (ptr == 1) {
+ union xfs_btree_key key;
+
+ cur->bc_ops->init_key_from_rec(cur, &key, rec);
+ error = xfs_btree_updkey(cur, &key, 1);
+ if (error)
+ goto error0;
+ }
+
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
+ return 0;
+
+error0:
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
+ return error;
+}
+
Index: linux-2.6-xfs/fs/xfs/xfs_alloc_btree.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_alloc_btree.c 2008-07-21 05:10:35.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_alloc_btree.c 2008-07-21 05:45:02.000000000 +0200
@@ -49,7 +49,9 @@ STATIC void xfs_allocbt_log_keys(xfs_btr
#define xfs_alloc_log_keys(c, b, i, j) \
xfs_allocbt_log_keys(c, b, i, j)
STATIC void xfs_alloc_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
-STATIC void xfs_alloc_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
+STATIC void xfs_allocbt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
+#define xfs_alloc_log_recs(c, b, i, j) \
+ xfs_allocbt_log_recs(c, b, i, j)
STATIC int xfs_alloc_lshift(xfs_btree_cur_t *, int, int *);
STATIC int xfs_alloc_newroot(xfs_btree_cur_t *, int *);
STATIC int xfs_alloc_rshift(xfs_btree_cur_t *, int, int *);
@@ -883,41 +885,6 @@ xfs_alloc_log_ptrs(
}
/*
- * Log records from a btree block (leaf).
- */
-STATIC void
-xfs_alloc_log_recs(
- xfs_btree_cur_t *cur, /* btree cursor */
- xfs_buf_t *bp, /* buffer containing btree block */
- int rfirst, /* index of first record to log */
- int rlast) /* index of last record to log */
-{
- xfs_alloc_block_t *block; /* btree block to log from */
- int first; /* first byte offset logged */
- int last; /* last byte offset logged */
- xfs_alloc_rec_t *rp; /* record pointer for btree block */
-
-
- block = XFS_BUF_TO_ALLOC_BLOCK(bp);
- rp = XFS_ALLOC_REC_ADDR(block, 1, cur);
-#ifdef DEBUG
- {
- xfs_agf_t *agf;
- xfs_alloc_rec_t *p;
-
- agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
- for (p = &rp[rfirst - 1]; p <= &rp[rlast - 1]; p++)
- ASSERT(be32_to_cpu(p->ar_startblock) +
- be32_to_cpu(p->ar_blockcount) <=
- be32_to_cpu(agf->agf_length));
- }
-#endif
- first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
- last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
- xfs_trans_log_buf(cur->bc_tp, bp, first, last);
-}
-
-/*
* Move 1 record left from cur/level if possible.
* Update cur to reflect the new path.
*/
@@ -1642,83 +1609,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 (ptr != xfs_btree_get_numrecs(block))
+ return;
+ len = rec->alloc.ar_blockcount;
+ break;
+ default:
+ ASSERT(0);
+ return;
}
- /*
- * 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;
- }
- 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 void
@@ -1808,6 +1742,17 @@ xfs_allocbt_copy_keys(
memcpy(dst_key, src_key, numkeys * sizeof(xfs_alloc_key_t));
}
+STATIC void
+xfs_allocbt_copy_recs(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_rec *src_rec,
+ union xfs_btree_rec *dst_rec,
+ int numrecs)
+{
+ ASSERT(numrecs >= 0);
+ memcpy(dst_rec, src_rec, numrecs * sizeof(xfs_alloc_rec_t));
+}
+
/*
* Log keys from a btree block (nonleaf).
*/
@@ -1835,6 +1780,44 @@ xfs_allocbt_log_keys(
XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
}
+/*
+ * Log records from a btree block (leaf).
+ */
+STATIC void
+xfs_alloc_log_recs(
+ struct xfs_btree_cur *cur, /* btree cursor */
+ struct xfs_buf *bp, /* buffer containing btree block */
+ int rfirst, /* index of first record to log */
+ int rlast) /* index of last record to log */
+{
+ struct xfs_btree_sblock *block; /* btree block to log from */
+ int first; /* first byte offset logged */
+ int last; /* last byte offset logged */
+ xfs_alloc_rec_t *rp; /* record pointer for btree block */
+
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
+ XFS_BTREE_TRACE_ARGBII(cur, bp, rfirst, rlast);
+
+ block = XFS_BUF_TO_SBLOCK(bp);
+ rp = XFS_ALLOC_REC_ADDR(block, 1, cur);
+#ifdef DEBUG
+ {
+ struct xfs_agf *agf;
+ xfs_alloc_rec_t *p;
+
+ agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
+ for (p = &rp[rfirst - 1]; p <= &rp[rlast - 1]; p++)
+ ASSERT(be32_to_cpu(p->ar_startblock) +
+ be32_to_cpu(p->ar_blockcount) <=
+ be32_to_cpu(agf->agf_length));
+ }
+#endif
+ first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
+ last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
+ xfs_trans_log_buf(cur->bc_tp, bp, first, last);
+
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
+}
#ifdef XFS_BTREE_TRACE
@@ -1905,6 +1888,7 @@ xfs_allocbt_trace_record(
static const struct xfs_btree_ops xfs_allocbt_ops = {
.dup_cursor = xfs_allocbt_dup_cursor,
+ .update_lastrec = xfs_allocbt_update_lastrec,
.init_key_from_rec = xfs_allocbt_init_key_from_rec,
.init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur,
.ptr_addr = xfs_allocbt_ptr_addr,
@@ -1912,7 +1896,9 @@ static const struct xfs_btree_ops xfs_al
.rec_addr = xfs_allocbt_rec_addr,
.key_diff = xfs_allocbt_key_diff,
.copy_keys = xfs_allocbt_copy_keys,
+ .copy_recs = xfs_allocbt_copy_recs,
.log_keys = xfs_allocbt_log_keys,
+ .log_recs = xfs_allocbt_log_recs,
#ifdef XFS_BTREE_TRACE
.trace_enter = xfs_allocbt_trace_enter,
@@ -1947,6 +1933,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;
Index: linux-2.6-xfs/fs/xfs/xfs_btree.h
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_btree.h 2008-07-21 05:11:01.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_btree.h 2008-07-21 05:23:07.000000000 +0200
@@ -191,6 +191,11 @@ struct xfs_btree_ops {
/* get inode rooted btree root */
struct xfs_btree_block *(*get_root_from_inode)(struct xfs_btree_cur *);
+ /* updated last record information */
+ void (*update_lastrec)(struct xfs_btree_cur *,
+ struct xfs_btree_block *,
+ union xfs_btree_rec *, int, int);
+
/* return address of btree structures */
union xfs_btree_ptr *(*ptr_addr)(struct xfs_btree_cur *cur, int index,
struct xfs_btree_block *block);
@@ -214,11 +219,15 @@ struct xfs_btree_ops {
void (*copy_keys)(struct xfs_btree_cur *cur,
union xfs_btree_key *src_key,
union xfs_btree_key *dst_key, int numkeys);
+ void (*copy_recs)(struct xfs_btree_cur *cur,
+ union xfs_btree_rec *src_rec,
+ union xfs_btree_rec *dst_rec, int numkeys);
/* log changes to btree structures */
void (*log_keys)(struct xfs_btree_cur *cur, struct xfs_buf *bp,
int first, int last);
-
+ void (*log_recs)(struct xfs_btree_cur *cur, struct xfs_buf *bp,
+ int first, int last);
/* btree tracing */
#ifdef XFS_BTREE_TRACE
@@ -241,6 +250,12 @@ struct xfs_btree_ops {
};
/*
+ * Reasons for the update_lastrec method to be called.
+ */
+#define LASTREC_UPDATE 0
+
+
+/*
* Btree cursor structure.
* This collects all information needed by the btree code in one place.
*/
@@ -284,6 +299,7 @@ typedef struct xfs_btree_cur
/* cursor flags */
#define XFS_BTREE_LONG_PTRS (1<<0) /* pointers are 64bits long */
#define XFS_BTREE_ROOT_IN_INODE (1<<1) /* root may be variable size */
+#define XFS_BTREE_LASTREC_UPDATE (1<<2) /* track last rec externally */
#define XFS_BTREE_NOERROR 0
@@ -539,6 +555,7 @@ int xfs_btree_increment(struct xfs_btree
int xfs_btree_decrement(struct xfs_btree_cur *, int, int *);
int xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *);
int xfs_btree_updkey(struct xfs_btree_cur *, union xfs_btree_key *, int);
+int xfs_btree_update(struct xfs_btree_cur *, union xfs_btree_rec *);
/*
Index: linux-2.6-xfs/fs/xfs/xfs_alloc.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_alloc.c 2008-07-21 05:08:28.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_alloc.c 2008-07-21 05:22:00.000000000 +0200
@@ -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.
Index: linux-2.6-xfs/fs/xfs/xfs_alloc_btree.h
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_alloc_btree.h 2008-07-21 05:08:28.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_alloc_btree.h 2008-07-21 05:17:12.000000000 +0200
@@ -113,13 +113,6 @@ extern int xfs_alloc_get_rec(struct xfs_
*/
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 *,
Index: linux-2.6-xfs/fs/xfs/xfs_ialloc.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_ialloc.c 2008-07-21 05:25:57.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_ialloc.c 2008-07-21 05:30:09.000000000 +0200
@@ -172,6 +172,26 @@ xfs_inobt_lookup_le(
}
/*
+ * Update the record referred to by cur to the value given
+ * by [ino, fcnt, free].
+ * This either works (return 0) or gets an EFSCORRUPTED error.
+ */
+STATIC int /* error */
+xfs_inobt_update(
+ struct xfs_btree_cur *cur, /* btree cursor */
+ xfs_agino_t ino, /* starting inode of chunk */
+ __int32_t fcnt, /* free inode count */
+ xfs_inofree_t free) /* free inode mask */
+{
+ union xfs_btree_rec rec;
+
+ rec.inobt.ir_startino = cpu_to_be32(ino);
+ rec.inobt.ir_freecount = cpu_to_be32(fcnt);
+ rec.inobt.ir_free = cpu_to_be64(free);
+ return xfs_btree_update(cur, &rec);
+}
+
+/*
* Allocate new inodes in the allocation group specified by agbp.
* Return 0 for success, else error code.
*/
Index: linux-2.6-xfs/fs/xfs/xfs_ialloc_btree.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_ialloc_btree.c 2008-07-21 05:25:48.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_ialloc_btree.c 2008-07-21 05:44:35.000000000 +0200
@@ -785,28 +785,6 @@ xfs_inobt_log_ptrs(
}
/*
- * Log records from a btree block (leaf).
- */
-STATIC void
-xfs_inobt_log_recs(
- xfs_btree_cur_t *cur, /* btree cursor */
- xfs_buf_t *bp, /* buffer containing btree block */
- int rfirst, /* index of first record to log */
- int rlast) /* index of last record to log */
-{
- xfs_inobt_block_t *block; /* btree block to log from */
- int first; /* first byte offset logged */
- int last; /* last byte offset logged */
- xfs_inobt_rec_t *rp; /* record pointer for btree block */
-
- block = XFS_BUF_TO_INOBT_BLOCK(bp);
- rp = XFS_INOBT_REC_ADDR(block, 1, cur);
- first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
- last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
- xfs_trans_log_buf(cur->bc_tp, bp, first, last);
-}
-
-/*
* Move 1 record left from cur/level if possible.
* Update cur to reflect the new path.
*/
@@ -1530,58 +1508,6 @@ xfs_inobt_insert(
return 0;
}
-/*
- * Update the record referred to by cur, to the value given
- * by [ino, fcnt, free].
- * This either works (return 0) or gets an EFSCORRUPTED error.
- */
-int /* error */
-xfs_inobt_update(
- xfs_btree_cur_t *cur, /* btree cursor */
- xfs_agino_t ino, /* starting inode of chunk */
- __int32_t fcnt, /* free inode count */
- xfs_inofree_t free) /* free inode mask */
-{
- xfs_inobt_block_t *block; /* btree block to update */
- xfs_buf_t *bp; /* buffer containing btree block */
- int error; /* error return value */
- int ptr; /* current record number (updating) */
- xfs_inobt_rec_t *rp; /* pointer to updated record */
-
- /*
- * Pick up the current block.
- */
- bp = cur->bc_bufs[0];
- block = XFS_BUF_TO_INOBT_BLOCK(bp);
-#ifdef DEBUG
- if ((error = xfs_btree_check_sblock(cur, block, 0, bp)))
- return error;
-#endif
- /*
- * Get the address of the rec to be updated.
- */
- ptr = cur->bc_ptrs[0];
- rp = XFS_INOBT_REC_ADDR(block, ptr, cur);
- /*
- * Fill in the new contents and log them.
- */
- rp->ir_startino = cpu_to_be32(ino);
- rp->ir_freecount = cpu_to_be32(fcnt);
- rp->ir_free = cpu_to_be64(free);
- xfs_inobt_log_recs(cur, bp, ptr, ptr);
- /*
- * Updating first record in leaf. Pass new key value up to our parent.
- */
- if (ptr == 1) {
- xfs_inobt_key_t key; /* key containing [ino] */
-
- key.ir_startino = cpu_to_be32(ino);
- if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, 1)))
- return error;
- }
- return 0;
-}
-
STATIC struct xfs_btree_cur *
xfs_inobt_dup_cursor(
struct xfs_btree_cur *cur)
@@ -1664,6 +1590,17 @@ xfs_inobt_copy_keys(
memcpy(dst_key, src_key, numkeys * sizeof(xfs_inobt_key_t));
}
+STATIC void
+xfs_inobt_copy_recs(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_rec *src_rec,
+ union xfs_btree_rec *dst_rec,
+ int numrecs)
+{
+ ASSERT(numrecs >= 0);
+ memcpy(dst_rec, src_rec, numrecs * sizeof(xfs_inobt_rec_t));
+}
+
/*
* Log keys from a btree block (nonleaf).
*/
@@ -1691,6 +1628,34 @@ xfs_inobt_log_keys(
XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
}
+/*
+ * Log records from a btree block (leaf).
+ */
+STATIC void
+xfs_inobt_log_recs(
+ xfs_btree_cur_t *cur, /* btree cursor */
+ xfs_buf_t *bp, /* buffer containing btree block */
+ int rfirst, /* index of first record to log */
+ int rlast) /* index of last record to log */
+{
+ struct xfs_btree_sblock *block; /* btree block to log from */
+ int first; /* first byte offset logged */
+ int last; /* last byte offset logged */
+ xfs_inobt_rec_t *rp; /* record pointer for btree block */
+
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
+ XFS_BTREE_TRACE_ARGBII(cur, bp, rfirst, rlast);
+
+ block = XFS_BUF_TO_SBLOCK(bp);
+ rp = XFS_INOBT_REC_ADDR(block, 1, cur);
+ first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
+ last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
+ xfs_trans_log_buf(cur->bc_tp, bp, first, last);
+
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
+}
+
+
#ifdef XFS_BTREE_TRACE
ktrace_t *xfs_inobt_trace_buf;
@@ -1767,7 +1732,9 @@ static const struct xfs_btree_ops xfs_in
.rec_addr = xfs_inobt_rec_addr,
.key_diff = xfs_inobt_key_diff,
.copy_keys = xfs_inobt_copy_keys,
+ .copy_recs = xfs_inobt_copy_recs,
.log_keys = xfs_inobt_log_keys,
+ .log_recs = xfs_inobt_log_recs,
#ifdef XFS_BTREE_TRACE
.trace_enter = xfs_inobt_trace_enter,
Index: linux-2.6-xfs/fs/xfs/xfs_ialloc_btree.h
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_ialloc_btree.h 2008-07-21 05:25:23.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_ialloc_btree.h 2008-07-21 05:25:47.000000000 +0200
@@ -135,14 +135,6 @@ extern int xfs_inobt_get_rec(struct xfs_
*/
extern int xfs_inobt_insert(struct xfs_btree_cur *cur, int *stat);
-/*
- * Update the record referred to by cur, to the value given
- * by [ino, fcnt, free].
- * This either works (return 0) or gets an EFSCORRUPTED error.
- */
-extern int xfs_inobt_update(struct xfs_btree_cur *cur, xfs_agino_t ino,
- __int32_t fcnt, xfs_inofree_t free);
-
extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *,
struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t);
Index: linux-2.6-xfs/fs/xfs/xfs_bmap.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_bmap.c 2008-07-21 05:27:45.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_bmap.c 2008-07-21 05:29:42.000000000 +0200
@@ -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.
Index: linux-2.6-xfs/fs/xfs/xfs_bmap_btree.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_bmap_btree.c 2008-07-21 05:27:36.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_bmap_btree.c 2008-07-21 05:49:46.000000000 +0200
@@ -1565,34 +1565,6 @@ xfs_bmbt_log_block(
}
/*
- * Log record values from the btree block.
- */
-void
-xfs_bmbt_log_recs(
- xfs_btree_cur_t *cur,
- xfs_buf_t *bp,
- int rfirst,
- int rlast)
-{
- xfs_bmbt_block_t *block;
- int first;
- int last;
- xfs_bmbt_rec_t *rp;
- xfs_trans_t *tp;
-
- XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
- XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast);
- ASSERT(bp);
- tp = cur->bc_tp;
- block = XFS_BUF_TO_BMBT_BLOCK(bp);
- rp = XFS_BMAP_REC_DADDR(block, 1, cur);
- first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
- last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
- xfs_trans_log_buf(tp, bp, first, last);
- XFS_BMBT_TRACE_CURSOR(cur, EXIT);
-}
-
-/*
* Give the bmap btree a new root block. Copy the old broot contents
* down into a real block and make the broot point to it.
*/
@@ -1926,51 +1898,6 @@ xfs_bmbt_to_bmdr(
}
/*
- * 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
* kernels, as this condition should not occur.
@@ -2094,6 +2021,17 @@ xfs_bmbt_copy_keys(
memcpy(dst_key, src_key, numkeys * sizeof(xfs_bmbt_key_t));
}
+STATIC void
+xfs_bmbt_copy_recs(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_rec *src_rec,
+ union xfs_btree_rec *dst_rec,
+ int numrecs)
+{
+ ASSERT(numrecs >= 0);
+ memcpy(dst_rec, src_rec, numrecs * sizeof(xfs_bmbt_rec_t));
+}
+
/*
* Log key values from the btree block.
*/
@@ -2126,6 +2064,33 @@ xfs_bmbt_log_keys(
XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
}
+/*
+ * Log record values from the btree block.
+ */
+void
+xfs_bmbt_log_recs(
+ struct xfs_btree_cur *cur,
+ struct xfs_buf *bp,
+ int rfirst,
+ int rlast)
+{
+ struct xfs_btree_lblock *block;
+ int first;
+ int last;
+ xfs_bmbt_rec_t *rp;
+
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
+ XFS_BTREE_TRACE_ARGBII(cur, bp, rfirst, rlast);
+
+ block = XFS_BUF_TO_LBLOCK(bp);
+ rp = XFS_BMAP_REC_DADDR(block, 1, cur);
+ first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
+ last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
+ xfs_trans_log_buf(cur->bc_tp, bp, first, last);
+
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
+}
+
#ifdef XFS_BTREE_TRACE
ktrace_t *xfs_bmbt_trace_buf;
@@ -2222,7 +2187,9 @@ static const struct xfs_btree_ops xfs_bm
.rec_addr = xfs_bmbt_rec_addr,
.key_diff = xfs_bmbt_key_diff,
.copy_keys = xfs_bmbt_copy_keys,
+ .copy_recs = xfs_bmbt_copy_recs,
.log_keys = xfs_bmbt_log_keys,
+ .log_recs = xfs_bmbt_log_recs,
#ifdef XFS_BTREE_TRACE
.trace_enter = xfs_bmbt_trace_enter,
Index: linux-2.6-xfs/fs/xfs/xfs_bmap_btree.h
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_bmap_btree.h 2008-07-21 05:27:31.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_bmap_btree.h 2008-07-21 05:27:35.000000000 +0200
@@ -274,8 +274,6 @@ extern void xfs_bmbt_disk_set_allf(xfs_b
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);
--
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 13/21] implement generic xfs_btree_update
2008-07-29 19:31 [PATCH 13/21] implement generic xfs_btree_update Christoph Hellwig
@ 2008-07-30 5:29 ` Dave Chinner
2008-08-01 19:46 ` Christoph Hellwig
0 siblings, 1 reply; 4+ messages in thread
From: Dave Chinner @ 2008-07-30 5:29 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
On Tue, Jul 29, 2008 at 09:31:16PM +0200, Christoph Hellwig wrote:
> 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]
>
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
>
> Index: linux-2.6-xfs/fs/xfs/xfs_btree.c
> ===================================================================
> --- linux-2.6-xfs.orig/fs/xfs/xfs_btree.c 2008-07-21 05:10:43.000000000 +0200
> +++ linux-2.6-xfs/fs/xfs/xfs_btree.c 2008-07-21 05:24:20.000000000 +0200
> @@ -867,6 +867,30 @@ xfs_btree_get_sibling(
> }
> }
>
> +/*
> + * Return true if ptr is the last record in the btree and
> + * we need to track updateѕ to this record. The decision
> + * will be further refined in the update_lastrec method.
> + */
> +STATIC int
> +xfs_btree_is_lastrec(
> + struct xfs_btree_cur *cur,
> + struct xfs_btree_block *block,
> + int level)
> +{
> + union xfs_btree_ptr ptr;
> +
> + if (level > 0)
> + return 0;
> + if (!(cur->bc_flags & XFS_BTREE_LASTREC_UPDATE))
> + return 0;
> +
> + xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB);
> + if (!xfs_btree_ptr_is_null(cur, &ptr))
> + return 0;
> + return 1;
> +}
That is not checking if it's the last record - it's checking if it
is the rightmost block in the btree. i.e. if the block contains
the last record. If the code is to remain this way, that needs
renaming.
> +
> STATIC struct xfs_btree_block *
> xfs_btree_buf_to_block(
> struct xfs_btree_cur *cur,
> @@ -1417,3 +1441,66 @@ xfs_btree_updkey(
> XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
> return 0;
> }
> +
> +/*
> + * Update the record referred to by cur to the value in the
> + * given record. This either works (return 0) or gets an
> + * EFSCORRUPTED error.
> + */
> +int
> +xfs_btree_update(
> + struct xfs_btree_cur *cur,
> + union xfs_btree_rec *rec)
> +{
> + struct xfs_btree_block *block;
> + struct xfs_buf *bp;
> + int error;
> + int ptr;
> + union xfs_btree_rec *rp;
> +
> + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
> + XFS_BTREE_TRACE_ARGR(cur, rec);
> +
> + /* Pick up the current block. */
> + block = xfs_btree_get_block(cur, 0, &bp);
> +
> +#ifdef DEBUG
> + error = xfs_btree_check_block(cur, block, 0, bp);
> + if (error)
> + goto error0;
> +#endif
> + /* Get the address of the rec to be updated. */
> + ptr = cur->bc_ptrs[0];
> + rp = cur->bc_ops->rec_addr(cur, ptr, block);
> +
> + /* Fill in the new contents and log them. */
> + cur->bc_ops->copy_recs(cur, rec, rp, 1);
> + cur->bc_ops->log_recs(cur, bp, ptr, ptr);
> +
> + /*
> + * If we are tracking the last record in the tree and
> + * we are at the far right edge of the tree, update it.
> + */
> + if (xfs_btree_is_lastrec(cur, block, 0)) {
> + cur->bc_ops->update_lastrec(cur, block, rec,
> + ptr, LASTREC_UPDATE);
> + }
So this will update the last record on any update to a record in
the last block. Seeing as we will typically be allocating out of
the last block (where the biggest extents are) this is somewhat
additional overhead, right? This is the code that used to trigger
the update:
/*
* 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)) {
So it's clear we aren't doing the same check here. My original code
had the ptr check in it. Why did you drop it?
> +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)
> {
.....
> + 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(cur->bc_btnum == XFS_BTNUM_CNT);
>
.....
> + switch (reason) {
> + case LASTREC_UPDATE:
> /*
.....
> + * If this is the last leaf block and it's the last record,
> + * then update the size of the longest extent in the AG.
> */
.....
> + if (ptr != xfs_btree_get_numrecs(block))
> + return;
> + len = rec->alloc.ar_blockcount;
> + break;
> + default:
> + ASSERT(0);
> + return;
> }
Oh, it's be moved inside the update code itself. So, why always call
the update function and then check the ptr? Why not the way it was
originally done?
> ===================================================================
> --- linux-2.6-xfs.orig/fs/xfs/xfs_btree.h 2008-07-21 05:11:01.000000000 +0200
> +++ linux-2.6-xfs/fs/xfs/xfs_btree.h 2008-07-21 05:23:07.000000000 +0200
> @@ -191,6 +191,11 @@ struct xfs_btree_ops {
> /* get inode rooted btree root */
> struct xfs_btree_block *(*get_root_from_inode)(struct xfs_btree_cur *);
>
> + /* updated last record information */
> + void (*update_lastrec)(struct xfs_btree_cur *,
> + struct xfs_btree_block *,
> + union xfs_btree_rec *, int, int);
Can you add the variable names to the prototype parameters?
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 13/21] implement generic xfs_btree_update
2008-07-30 5:29 ` Dave Chinner
@ 2008-08-01 19:46 ` Christoph Hellwig
2008-08-02 1:15 ` Dave Chinner
0 siblings, 1 reply; 4+ messages in thread
From: Christoph Hellwig @ 2008-08-01 19:46 UTC (permalink / raw)
To: Christoph Hellwig, xfs
On Wed, Jul 30, 2008 at 03:29:59PM +1000, Dave Chinner wrote:
> Oh, it's be moved inside the update code itself. So, why always call
> the update function and then check the ptr? Why not the way it was
> originally done?
Because all three callers do different checks, and I could not proof
that they are either identical or hamrless for the other cases.
We can clean this mess up later in small standalone patches.
> > + /* updated last record information */
> > + void (*update_lastrec)(struct xfs_btree_cur *,
> > + struct xfs_btree_block *,
> > + union xfs_btree_rec *, int, int);
>
> Can you add the variable names to the prototype parameters?
Done.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 13/21] implement generic xfs_btree_update
2008-08-01 19:46 ` Christoph Hellwig
@ 2008-08-02 1:15 ` Dave Chinner
0 siblings, 0 replies; 4+ messages in thread
From: Dave Chinner @ 2008-08-02 1:15 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
On Fri, Aug 01, 2008 at 09:46:24PM +0200, Christoph Hellwig wrote:
> On Wed, Jul 30, 2008 at 03:29:59PM +1000, Dave Chinner wrote:
> > Oh, it's be moved inside the update code itself. So, why always call
> > the update function and then check the ptr? Why not the way it was
> > originally done?
>
> Because all three callers do different checks, and I could not proof
> that they are either identical or hamrless for the other cases.
> We can clean this mess up later in small standalone patches.
Ok. Sounds like a good plan.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-08-02 1:14 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-29 19:31 [PATCH 13/21] implement generic xfs_btree_update Christoph Hellwig
2008-07-30 5:29 ` Dave Chinner
2008-08-01 19:46 ` Christoph Hellwig
2008-08-02 1:15 ` Dave Chinner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox