Skip to contentSkip to conversation

implement generic xfs_btree_update

PATCH In review Christoph Hellwig 1 participant 1 message Aug 4, 2008 XFS filesystem

lore
Share & tools
lore
#0 lore raw

PATCH 14/26 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]

fs/xfs/xfs_btree.c +87 -0
Index: linux-2.6-xfs/fs/xfs/xfs_btree.c
===================================================================
@@ -868,6 +868,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 xfs_daddr_t
 xfs_btree_ptr_to_daddr(
 	struct xfs_btree_cur	*cur,
@@ -1419,3 +1443,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 +102 -104

264 lines not on this page · raw message

fs/xfs/xfs_btree.h +19 -1
Index: linux-2.6-xfs/fs/xfs/xfs_btree.h
===================================================================
@@ -191,6 +191,12 @@ 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 *cur,
+				  struct xfs_btree_block *block,
+				  union xfs_btree_rec *rec,
+				  int ptr, int reason);
+
 	/* 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 +220,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 +251,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 +300,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 +556,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 *);
 
 
 /*
fs/xfs/xfs_alloc.c +17 -0
Index: linux-2.6-xfs/fs/xfs/xfs_alloc.c
===================================================================
@@ -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
Index: linux-2.6-xfs/fs/xfs/xfs_alloc_btree.h
===================================================================
@@ -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
Index: linux-2.6-xfs/fs/xfs/xfs_ialloc.c
===================================================================
@@ -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 +40 -74

145 lines not on this page · raw message

fs/xfs/xfs_ialloc_btree.h +0 -8
Index: linux-2.6-xfs/fs/xfs/xfs_ialloc_btree.h
===================================================================
@@ -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
Index: linux-2.6-xfs/fs/xfs/xfs_bmap.c
===================================================================
@@ -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 +39 -73

143 lines not on this page · raw message

fs/xfs/xfs_bmap_btree.h +0 -2
Index: linux-2.6-xfs/fs/xfs/xfs_bmap_btree.h
===================================================================
@@ -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);