implement generic xfs_btree_update
PATCH 15/15 implement generic xfs_btree_update
From: Dave Chinner <[email protected]>
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 <[email protected]>
fs/xfs/xfs_btree.c +87 -0
@@ -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; +} +
fs/xfs/xfs_alloc_btree.c +92 -104
254 lines not on this page · raw message
fs/xfs/xfs_btree.h +18 -1
@@ -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_btreeint 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 *);/*
fs/xfs/xfs_btree_trace.c +21 -0
@@ -158,6 +158,27 @@ xfs_btree_trace_argik( }/* +* Add a trace buffer entry for arguments, for record. +*/ +void +xfs_btree_trace_argr ( +const char *func, +struct xfs_btree_cur *cur, +union xfs_btree_rec *rec, +int line) +{ +__uint64_t l0, l1, l2; + + cur->bc_ops->trace_record (cur, rec, &l0, &l1, &l2); + cur->bc_ops->trace_enter (cur, func,XBT_ARGS ,XFS_BTREE_KTRACE_ARGR , + line, + l0 >>32 , (int )l0, + l1 >>32 , (int )l1, + l2 >>32 , (int )l2, +0 ,0 ,0 ,0 ,0 ); +} + +/* * Add a trace buffer entry for the cursor/operation. */ void
fs/xfs/xfs_btree_trace.h +7 -1
@@ -44,7 +44,8 @@ struct xfs_buf;#define XFS_BTREE_KTRACE_ARGIFK 5#define XFS_BTREE_KTRACE_ARGIFR 6#define XFS_BTREE_KTRACE_ARGIK 7 -#define XFS_BTREE_KTRACE_CUR 8 +#define XFS_BTREE_KTRACE_ARGR 8 +#define XFS_BTREE_KTRACE_CUR 9/* * Sub-types for cursor traces.
@@ -67,6 +68,8 @@ void xfs_btree_trace_argifr(const char * xfs_fsblock_t, union xfs_btree_rec *, int);void xfs_btree_trace_argik (const char *,struct xfs_btree_cur *,int ,union xfs_btree_key *,int ); +void xfs_btree_trace_argr (const char *,struct xfs_btree_cur *, +union xfs_btree_rec *,int );void xfs_btree_trace_cursor (const char *,struct xfs_btree_cur *,int ,int );
@@ -95,6 +98,8 @@ extern ktrace_t *xfs_bmbt_trace_buf; xfs_btree_trace_argifr(__func__, c, i, f, r, __LINE__)#define XFS_BTREE_TRACE_ARGIK (c,i,k) \ xfs_btree_trace_argik(__func__, c, i, k, __LINE__) +#define XFS_BTREE_TRACE_ARGR (c,r) \ + xfs_btree_trace_argr(__func__, c, r, __LINE__)#define XFS_BTREE_TRACE_CURSOR (c,t) \ xfs_btree_trace_cursor(__func__, c, t, __LINE__)#else
@@ -105,6 +110,7 @@ extern ktrace_t *xfs_bmbt_trace_buf;#define XFS_BTREE_TRACE_ARGIFK (c,i,f,s)#define XFS_BTREE_TRACE_ARGIFR (c,i,f,r)#define XFS_BTREE_TRACE_ARGIK (c,i,k) +#define XFS_BTREE_TRACE_ARGR (c,r)#define XFS_BTREE_TRACE_CURSOR (c,t)#endif /* XFS_BTREE_TRACE */
fs/xfs/xfsidbg.c +9 -0
@@ -2952,6 +2952,15 @@ xfs_btree_trace_entry( (unsigned long )ktep->val[8 ], (unsigned long)ktep->val[9]);break ; +case XFS_BTREE_KTRACE_ARGR : +xfsidb_btree_trace_record (btnum, + (unsigned long )ktep->val[5 ], + (unsigned long )ktep->val[6 ], + (unsigned long )ktep->val[7 ], + (unsigned long )ktep->val[8 ], + (unsigned long )ktep->val[9 ], + (unsigned long )ktep->val[10 ]); +break ;case XFS_BTREE_KTRACE_CUR : xfsidb_btree_trace_cursor(btnum,
fs/xfs/xfs_alloc.c +17 -0
@@ -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.
fs/xfs/xfs_alloc_btree.h +0 -7
@@ -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 *,
fs/xfs/xfs_ialloc.c +20 -0
@@ -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. */
fs/xfs/xfs_ialloc_btree.c +41 -74
146 lines not on this page · raw message
fs/xfs/xfs_ialloc_btree.h +0 -8
@@ -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 );
fs/xfs/xfs_bmap.c +18 -0
@@ -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.
fs/xfs/xfs_bmap_btree.c +40 -73
144 lines not on this page · raw message
fs/xfs/xfs_bmap_btree.h +0 -2
@@ -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 );