aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_bmap.c2
-rw-r--r--fs/xfs/xfs_bmap_btree.c113
-rw-r--r--fs/xfs/xfs_bmap_btree.h6
-rw-r--r--fs/xfs/xfs_btree.c101
-rw-r--r--fs/xfs/xfs_btree.h1
5 files changed, 104 insertions, 119 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 7d6c4ace8052..315bc2912682 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -476,7 +476,7 @@ xfs_bmap_add_attrfork_btree(
476 goto error0; 476 goto error0;
477 /* must be at least one entry */ 477 /* must be at least one entry */
478 XFS_WANT_CORRUPTED_GOTO(stat == 1, error0); 478 XFS_WANT_CORRUPTED_GOTO(stat == 1, error0);
479 if ((error = xfs_bmbt_newroot(cur, flags, &stat))) 479 if ((error = xfs_btree_new_iroot(cur, flags, &stat)))
480 goto error0; 480 goto error0;
481 if (stat == 0) { 481 if (stat == 0) {
482 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); 482 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index e7539263457f..204f276aeaad 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -525,7 +525,7 @@ xfs_bmbt_insrec(
525 cur->bc_private.b.whichfork); 525 cur->bc_private.b.whichfork);
526 block = xfs_bmbt_get_block(cur, level, &bp); 526 block = xfs_bmbt_get_block(cur, level, &bp);
527 } else if (level == cur->bc_nlevels - 1) { 527 } else if (level == cur->bc_nlevels - 1) {
528 if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) || 528 if ((error = xfs_btree_new_iroot(cur, &logflags, stat)) ||
529 *stat == 0) { 529 *stat == 0) {
530 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 530 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
531 return error; 531 return error;
@@ -1183,117 +1183,6 @@ xfs_bmbt_log_recs(
1183} 1183}
1184 1184
1185/* 1185/*
1186 * Give the bmap btree a new root block. Copy the old broot contents
1187 * down into a real block and make the broot point to it.
1188 */
1189int /* error */
1190xfs_bmbt_newroot(
1191 xfs_btree_cur_t *cur, /* btree cursor */
1192 int *logflags, /* logging flags for inode */
1193 int *stat) /* return status - 0 fail */
1194{
1195 xfs_alloc_arg_t args; /* allocation arguments */
1196 xfs_bmbt_block_t *block; /* bmap btree block */
1197 xfs_buf_t *bp; /* buffer for block */
1198 xfs_bmbt_block_t *cblock; /* child btree block */
1199 xfs_bmbt_key_t *ckp; /* child key pointer */
1200 xfs_bmbt_ptr_t *cpp; /* child ptr pointer */
1201 int error; /* error return code */
1202#ifdef DEBUG
1203 int i; /* loop counter */
1204#endif
1205 xfs_bmbt_key_t *kp; /* pointer to bmap btree key */
1206 int level; /* btree level */
1207 xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */
1208
1209 XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1210 level = cur->bc_nlevels - 1;
1211 block = xfs_bmbt_get_block(cur, level, &bp);
1212 /*
1213 * Copy the root into a real block.
1214 */
1215 args.mp = cur->bc_mp;
1216 pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
1217 args.tp = cur->bc_tp;
1218 args.fsbno = cur->bc_private.b.firstblock;
1219 args.mod = args.minleft = args.alignment = args.total = args.isfl =
1220 args.userdata = args.minalignslop = 0;
1221 args.minlen = args.maxlen = args.prod = 1;
1222 args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
1223 args.firstblock = args.fsbno;
1224 if (args.fsbno == NULLFSBLOCK) {
1225#ifdef DEBUG
1226 if ((error = xfs_btree_check_lptr_disk(cur, *pp, level))) {
1227 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1228 return error;
1229 }
1230#endif
1231 args.fsbno = be64_to_cpu(*pp);
1232 args.type = XFS_ALLOCTYPE_START_BNO;
1233 } else if (cur->bc_private.b.flist->xbf_low)
1234 args.type = XFS_ALLOCTYPE_START_BNO;
1235 else
1236 args.type = XFS_ALLOCTYPE_NEAR_BNO;
1237 if ((error = xfs_alloc_vextent(&args))) {
1238 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1239 return error;
1240 }
1241 if (args.fsbno == NULLFSBLOCK) {
1242 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1243 *stat = 0;
1244 return 0;
1245 }
1246 ASSERT(args.len == 1);
1247 cur->bc_private.b.firstblock = args.fsbno;
1248 cur->bc_private.b.allocated++;
1249 cur->bc_private.b.ip->i_d.di_nblocks++;
1250 XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
1251 XFS_TRANS_DQ_BCOUNT, 1L);
1252 bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0);
1253 cblock = XFS_BUF_TO_BMBT_BLOCK(bp);
1254 *cblock = *block;
1255 be16_add_cpu(&block->bb_level, 1);
1256 block->bb_numrecs = cpu_to_be16(1);
1257 cur->bc_nlevels++;
1258 cur->bc_ptrs[level + 1] = 1;
1259 kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
1260 ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
1261 memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp));
1262 cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
1263#ifdef DEBUG
1264 for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
1265 if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) {
1266 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1267 return error;
1268 }
1269 }
1270#endif
1271 memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp));
1272#ifdef DEBUG
1273 if ((error = xfs_btree_check_lptr(cur, args.fsbno, level))) {
1274 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1275 return error;
1276 }
1277#endif
1278 *pp = cpu_to_be64(args.fsbno);
1279 xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs),
1280 cur->bc_private.b.whichfork);
1281 xfs_btree_setbuf(cur, level, bp);
1282 /*
1283 * Do all this logging at the end so that
1284 * the root is at the right level.
1285 */
1286 xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS);
1287 xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs));
1288 xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs));
1289 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
1290 *logflags |=
1291 XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork);
1292 *stat = 1;
1293 return 0;
1294}
1295
1296/*
1297 * Set all the fields in a bmap extent record from the arguments. 1186 * Set all the fields in a bmap extent record from the arguments.
1298 */ 1187 */
1299void 1188void
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 6bfd62ec54fb..26fd8ace3e77 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -255,12 +255,6 @@ extern void xfs_bmbt_log_block(struct xfs_btree_cur *, struct xfs_buf *, int);
255extern void xfs_bmbt_log_recs(struct xfs_btree_cur *, struct xfs_buf *, int, 255extern void xfs_bmbt_log_recs(struct xfs_btree_cur *, struct xfs_buf *, int,
256 int); 256 int);
257 257
258/*
259 * Give the bmap btree a new root block. Copy the old broot contents
260 * down into a real block and make the broot point to it.
261 */
262extern int xfs_bmbt_newroot(struct xfs_btree_cur *cur, int *lflags, int *stat);
263
264extern void xfs_bmbt_set_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s); 258extern void xfs_bmbt_set_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s);
265extern void xfs_bmbt_set_allf(xfs_bmbt_rec_host_t *r, xfs_fileoff_t o, 259extern void xfs_bmbt_set_allf(xfs_bmbt_rec_host_t *r, xfs_fileoff_t o,
266 xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v); 260 xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 8de884c4dab7..3b6e01dea669 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -2469,6 +2469,107 @@ error0:
2469} 2469}
2470 2470
2471/* 2471/*
2472 * Copy the old inode root contents into a real block and make the
2473 * broot point to it.
2474 */
2475int /* error */
2476xfs_btree_new_iroot(
2477 struct xfs_btree_cur *cur, /* btree cursor */
2478 int *logflags, /* logging flags for inode */
2479 int *stat) /* return status - 0 fail */
2480{
2481 struct xfs_buf *cbp; /* buffer for cblock */
2482 struct xfs_btree_block *block; /* btree block */
2483 struct xfs_btree_block *cblock; /* child btree block */
2484 union xfs_btree_key *ckp; /* child key pointer */
2485 union xfs_btree_ptr *cpp; /* child ptr pointer */
2486 union xfs_btree_key *kp; /* pointer to btree key */
2487 union xfs_btree_ptr *pp; /* pointer to block addr */
2488 union xfs_btree_ptr nptr; /* new block addr */
2489 int level; /* btree level */
2490 int error; /* error return code */
2491#ifdef DEBUG
2492 int i; /* loop counter */
2493#endif
2494
2495 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
2496 XFS_BTREE_STATS_INC(cur, newroot);
2497
2498 ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
2499
2500 level = cur->bc_nlevels - 1;
2501
2502 block = xfs_btree_get_iroot(cur);
2503 pp = xfs_btree_ptr_addr(cur, 1, block);
2504
2505 /* Allocate the new block. If we can't do it, we're toast. Give up. */
2506 error = cur->bc_ops->alloc_block(cur, pp, &nptr, 1, stat);
2507 if (error)
2508 goto error0;
2509 if (*stat == 0) {
2510 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2511 return 0;
2512 }
2513 XFS_BTREE_STATS_INC(cur, alloc);
2514
2515 /* Copy the root into a real block. */
2516 error = xfs_btree_get_buf_block(cur, &nptr, 0, &cblock, &cbp);
2517 if (error)
2518 goto error0;
2519
2520 memcpy(cblock, block, xfs_btree_block_len(cur));
2521
2522 be16_add_cpu(&block->bb_level, 1);
2523 xfs_btree_set_numrecs(block, 1);
2524 cur->bc_nlevels++;
2525 cur->bc_ptrs[level + 1] = 1;
2526
2527 kp = xfs_btree_key_addr(cur, 1, block);
2528 ckp = xfs_btree_key_addr(cur, 1, cblock);
2529 xfs_btree_copy_keys(cur, ckp, kp, xfs_btree_get_numrecs(cblock));
2530
2531 cpp = xfs_btree_ptr_addr(cur, 1, cblock);
2532#ifdef DEBUG
2533 for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
2534 error = xfs_btree_check_ptr(cur, pp, i, level);
2535 if (error)
2536 goto error0;
2537 }
2538#endif
2539 xfs_btree_copy_ptrs(cur, cpp, pp, xfs_btree_get_numrecs(cblock));
2540
2541#ifdef DEBUG
2542 error = xfs_btree_check_ptr(cur, &nptr, 0, level);
2543 if (error)
2544 goto error0;
2545#endif
2546 xfs_btree_copy_ptrs(cur, pp, &nptr, 1);
2547
2548 xfs_iroot_realloc(cur->bc_private.b.ip,
2549 1 - xfs_btree_get_numrecs(cblock),
2550 cur->bc_private.b.whichfork);
2551
2552 xfs_btree_setbuf(cur, level, cbp);
2553
2554 /*
2555 * Do all this logging at the end so that
2556 * the root is at the right level.
2557 */
2558 xfs_btree_log_block(cur, cbp, XFS_BB_ALL_BITS);
2559 xfs_btree_log_keys(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs));
2560 xfs_btree_log_ptrs(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs));
2561
2562 *logflags |=
2563 XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork);
2564 *stat = 1;
2565 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2566 return 0;
2567error0:
2568 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
2569 return error;
2570}
2571
2572/*
2472 * Allocate a new root block, fill it in. 2573 * Allocate a new root block, fill it in.
2473 */ 2574 */
2474int /* error */ 2575int /* error */
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 18015392feb0..21eec863f00f 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -548,6 +548,7 @@ int xfs_btree_rshift(struct xfs_btree_cur *, int, int *);
548int xfs_btree_split(struct xfs_btree_cur *, int, union xfs_btree_ptr *, 548int xfs_btree_split(struct xfs_btree_cur *, int, union xfs_btree_ptr *,
549 union xfs_btree_key *, struct xfs_btree_cur **, int *); 549 union xfs_btree_key *, struct xfs_btree_cur **, int *);
550int xfs_btree_new_root(struct xfs_btree_cur *, int *); 550int xfs_btree_new_root(struct xfs_btree_cur *, int *);
551int xfs_btree_new_iroot(struct xfs_btree_cur *, int *, int *);
551 552
552/* 553/*
553 * Helpers. 554 * Helpers.