diff options
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 416 |
1 files changed, 165 insertions, 251 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 70e3ba32e6be..35cca98bd94c 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 37 | #include "xfs_inode.h" |
38 | #include "xfs_inode_item.h" | 38 | #include "xfs_inode_item.h" |
39 | #include "xfs_imap.h" | ||
40 | #include "xfs_alloc.h" | 39 | #include "xfs_alloc.h" |
41 | #include "xfs_ialloc.h" | 40 | #include "xfs_ialloc.h" |
42 | #include "xfs_log_priv.h" | 41 | #include "xfs_log_priv.h" |
@@ -54,10 +53,8 @@ STATIC void xlog_recover_insert_item_backq(xlog_recover_item_t **q, | |||
54 | xlog_recover_item_t *item); | 53 | xlog_recover_item_t *item); |
55 | #if defined(DEBUG) | 54 | #if defined(DEBUG) |
56 | STATIC void xlog_recover_check_summary(xlog_t *); | 55 | STATIC void xlog_recover_check_summary(xlog_t *); |
57 | STATIC void xlog_recover_check_ail(xfs_mount_t *, xfs_log_item_t *, int); | ||
58 | #else | 56 | #else |
59 | #define xlog_recover_check_summary(log) | 57 | #define xlog_recover_check_summary(log) |
60 | #define xlog_recover_check_ail(mp, lip, gen) | ||
61 | #endif | 58 | #endif |
62 | 59 | ||
63 | 60 | ||
@@ -270,21 +267,16 @@ STATIC void | |||
270 | xlog_recover_iodone( | 267 | xlog_recover_iodone( |
271 | struct xfs_buf *bp) | 268 | struct xfs_buf *bp) |
272 | { | 269 | { |
273 | xfs_mount_t *mp; | ||
274 | |||
275 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *)); | ||
276 | |||
277 | if (XFS_BUF_GETERROR(bp)) { | 270 | if (XFS_BUF_GETERROR(bp)) { |
278 | /* | 271 | /* |
279 | * We're not going to bother about retrying | 272 | * We're not going to bother about retrying |
280 | * this during recovery. One strike! | 273 | * this during recovery. One strike! |
281 | */ | 274 | */ |
282 | mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *); | ||
283 | xfs_ioerror_alert("xlog_recover_iodone", | 275 | xfs_ioerror_alert("xlog_recover_iodone", |
284 | mp, bp, XFS_BUF_ADDR(bp)); | 276 | bp->b_mount, bp, XFS_BUF_ADDR(bp)); |
285 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); | 277 | xfs_force_shutdown(bp->b_mount, SHUTDOWN_META_IO_ERROR); |
286 | } | 278 | } |
287 | XFS_BUF_SET_FSPRIVATE(bp, NULL); | 279 | bp->b_mount = NULL; |
288 | XFS_BUF_CLR_IODONE_FUNC(bp); | 280 | XFS_BUF_CLR_IODONE_FUNC(bp); |
289 | xfs_biodone(bp); | 281 | xfs_biodone(bp); |
290 | } | 282 | } |
@@ -2228,9 +2220,8 @@ xlog_recover_do_buffer_trans( | |||
2228 | XFS_BUF_STALE(bp); | 2220 | XFS_BUF_STALE(bp); |
2229 | error = xfs_bwrite(mp, bp); | 2221 | error = xfs_bwrite(mp, bp); |
2230 | } else { | 2222 | } else { |
2231 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL || | 2223 | ASSERT(bp->b_mount == NULL || bp->b_mount == mp); |
2232 | XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp); | 2224 | bp->b_mount = mp; |
2233 | XFS_BUF_SET_FSPRIVATE(bp, mp); | ||
2234 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone); | 2225 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone); |
2235 | xfs_bdwrite(mp, bp); | 2226 | xfs_bdwrite(mp, bp); |
2236 | } | 2227 | } |
@@ -2247,7 +2238,6 @@ xlog_recover_do_inode_trans( | |||
2247 | xfs_inode_log_format_t *in_f; | 2238 | xfs_inode_log_format_t *in_f; |
2248 | xfs_mount_t *mp; | 2239 | xfs_mount_t *mp; |
2249 | xfs_buf_t *bp; | 2240 | xfs_buf_t *bp; |
2250 | xfs_imap_t imap; | ||
2251 | xfs_dinode_t *dip; | 2241 | xfs_dinode_t *dip; |
2252 | xfs_ino_t ino; | 2242 | xfs_ino_t ino; |
2253 | int len; | 2243 | int len; |
@@ -2275,54 +2265,35 @@ xlog_recover_do_inode_trans( | |||
2275 | } | 2265 | } |
2276 | ino = in_f->ilf_ino; | 2266 | ino = in_f->ilf_ino; |
2277 | mp = log->l_mp; | 2267 | mp = log->l_mp; |
2278 | if (ITEM_TYPE(item) == XFS_LI_INODE) { | ||
2279 | imap.im_blkno = (xfs_daddr_t)in_f->ilf_blkno; | ||
2280 | imap.im_len = in_f->ilf_len; | ||
2281 | imap.im_boffset = in_f->ilf_boffset; | ||
2282 | } else { | ||
2283 | /* | ||
2284 | * It's an old inode format record. We don't know where | ||
2285 | * its cluster is located on disk, and we can't allow | ||
2286 | * xfs_imap() to figure it out because the inode btrees | ||
2287 | * are not ready to be used. Therefore do not pass the | ||
2288 | * XFS_IMAP_LOOKUP flag to xfs_imap(). This will give | ||
2289 | * us only the single block in which the inode lives | ||
2290 | * rather than its cluster, so we must make sure to | ||
2291 | * invalidate the buffer when we write it out below. | ||
2292 | */ | ||
2293 | imap.im_blkno = 0; | ||
2294 | error = xfs_imap(log->l_mp, NULL, ino, &imap, 0); | ||
2295 | if (error) | ||
2296 | goto error; | ||
2297 | } | ||
2298 | 2268 | ||
2299 | /* | 2269 | /* |
2300 | * Inode buffers can be freed, look out for it, | 2270 | * Inode buffers can be freed, look out for it, |
2301 | * and do not replay the inode. | 2271 | * and do not replay the inode. |
2302 | */ | 2272 | */ |
2303 | if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) { | 2273 | if (xlog_check_buffer_cancelled(log, in_f->ilf_blkno, |
2274 | in_f->ilf_len, 0)) { | ||
2304 | error = 0; | 2275 | error = 0; |
2305 | goto error; | 2276 | goto error; |
2306 | } | 2277 | } |
2307 | 2278 | ||
2308 | bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len, | 2279 | bp = xfs_buf_read_flags(mp->m_ddev_targp, in_f->ilf_blkno, |
2309 | XFS_BUF_LOCK); | 2280 | in_f->ilf_len, XFS_BUF_LOCK); |
2310 | if (XFS_BUF_ISERROR(bp)) { | 2281 | if (XFS_BUF_ISERROR(bp)) { |
2311 | xfs_ioerror_alert("xlog_recover_do..(read#2)", mp, | 2282 | xfs_ioerror_alert("xlog_recover_do..(read#2)", mp, |
2312 | bp, imap.im_blkno); | 2283 | bp, in_f->ilf_blkno); |
2313 | error = XFS_BUF_GETERROR(bp); | 2284 | error = XFS_BUF_GETERROR(bp); |
2314 | xfs_buf_relse(bp); | 2285 | xfs_buf_relse(bp); |
2315 | goto error; | 2286 | goto error; |
2316 | } | 2287 | } |
2317 | error = 0; | 2288 | error = 0; |
2318 | ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); | 2289 | ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); |
2319 | dip = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset); | 2290 | dip = (xfs_dinode_t *)xfs_buf_offset(bp, in_f->ilf_boffset); |
2320 | 2291 | ||
2321 | /* | 2292 | /* |
2322 | * Make sure the place we're flushing out to really looks | 2293 | * Make sure the place we're flushing out to really looks |
2323 | * like an inode! | 2294 | * like an inode! |
2324 | */ | 2295 | */ |
2325 | if (unlikely(be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC)) { | 2296 | if (unlikely(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)) { |
2326 | xfs_buf_relse(bp); | 2297 | xfs_buf_relse(bp); |
2327 | xfs_fs_cmn_err(CE_ALERT, mp, | 2298 | xfs_fs_cmn_err(CE_ALERT, mp, |
2328 | "xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld", | 2299 | "xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld", |
@@ -2345,12 +2316,12 @@ xlog_recover_do_inode_trans( | |||
2345 | } | 2316 | } |
2346 | 2317 | ||
2347 | /* Skip replay when the on disk inode is newer than the log one */ | 2318 | /* Skip replay when the on disk inode is newer than the log one */ |
2348 | if (dicp->di_flushiter < be16_to_cpu(dip->di_core.di_flushiter)) { | 2319 | if (dicp->di_flushiter < be16_to_cpu(dip->di_flushiter)) { |
2349 | /* | 2320 | /* |
2350 | * Deal with the wrap case, DI_MAX_FLUSH is less | 2321 | * Deal with the wrap case, DI_MAX_FLUSH is less |
2351 | * than smaller numbers | 2322 | * than smaller numbers |
2352 | */ | 2323 | */ |
2353 | if (be16_to_cpu(dip->di_core.di_flushiter) == DI_MAX_FLUSH && | 2324 | if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH && |
2354 | dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) { | 2325 | dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) { |
2355 | /* do nothing */ | 2326 | /* do nothing */ |
2356 | } else { | 2327 | } else { |
@@ -2410,7 +2381,7 @@ xlog_recover_do_inode_trans( | |||
2410 | error = EFSCORRUPTED; | 2381 | error = EFSCORRUPTED; |
2411 | goto error; | 2382 | goto error; |
2412 | } | 2383 | } |
2413 | if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) { | 2384 | if (unlikely(item->ri_buf[1].i_len > sizeof(struct xfs_icdinode))) { |
2414 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", | 2385 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", |
2415 | XFS_ERRLEVEL_LOW, mp, dicp); | 2386 | XFS_ERRLEVEL_LOW, mp, dicp); |
2416 | xfs_buf_relse(bp); | 2387 | xfs_buf_relse(bp); |
@@ -2422,23 +2393,24 @@ xlog_recover_do_inode_trans( | |||
2422 | } | 2393 | } |
2423 | 2394 | ||
2424 | /* The core is in in-core format */ | 2395 | /* The core is in in-core format */ |
2425 | xfs_dinode_to_disk(&dip->di_core, | 2396 | xfs_dinode_to_disk(dip, (xfs_icdinode_t *)item->ri_buf[1].i_addr); |
2426 | (xfs_icdinode_t *)item->ri_buf[1].i_addr); | ||
2427 | 2397 | ||
2428 | /* the rest is in on-disk format */ | 2398 | /* the rest is in on-disk format */ |
2429 | if (item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t)) { | 2399 | if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) { |
2430 | memcpy((xfs_caddr_t) dip + sizeof(xfs_dinode_core_t), | 2400 | memcpy((xfs_caddr_t) dip + sizeof(struct xfs_icdinode), |
2431 | item->ri_buf[1].i_addr + sizeof(xfs_dinode_core_t), | 2401 | item->ri_buf[1].i_addr + sizeof(struct xfs_icdinode), |
2432 | item->ri_buf[1].i_len - sizeof(xfs_dinode_core_t)); | 2402 | item->ri_buf[1].i_len - sizeof(struct xfs_icdinode)); |
2433 | } | 2403 | } |
2434 | 2404 | ||
2435 | fields = in_f->ilf_fields; | 2405 | fields = in_f->ilf_fields; |
2436 | switch (fields & (XFS_ILOG_DEV | XFS_ILOG_UUID)) { | 2406 | switch (fields & (XFS_ILOG_DEV | XFS_ILOG_UUID)) { |
2437 | case XFS_ILOG_DEV: | 2407 | case XFS_ILOG_DEV: |
2438 | dip->di_u.di_dev = cpu_to_be32(in_f->ilf_u.ilfu_rdev); | 2408 | xfs_dinode_put_rdev(dip, in_f->ilf_u.ilfu_rdev); |
2439 | break; | 2409 | break; |
2440 | case XFS_ILOG_UUID: | 2410 | case XFS_ILOG_UUID: |
2441 | dip->di_u.di_muuid = in_f->ilf_u.ilfu_uuid; | 2411 | memcpy(XFS_DFORK_DPTR(dip), |
2412 | &in_f->ilf_u.ilfu_uuid, | ||
2413 | sizeof(uuid_t)); | ||
2442 | break; | 2414 | break; |
2443 | } | 2415 | } |
2444 | 2416 | ||
@@ -2454,12 +2426,12 @@ xlog_recover_do_inode_trans( | |||
2454 | switch (fields & XFS_ILOG_DFORK) { | 2426 | switch (fields & XFS_ILOG_DFORK) { |
2455 | case XFS_ILOG_DDATA: | 2427 | case XFS_ILOG_DDATA: |
2456 | case XFS_ILOG_DEXT: | 2428 | case XFS_ILOG_DEXT: |
2457 | memcpy(&dip->di_u, src, len); | 2429 | memcpy(XFS_DFORK_DPTR(dip), src, len); |
2458 | break; | 2430 | break; |
2459 | 2431 | ||
2460 | case XFS_ILOG_DBROOT: | 2432 | case XFS_ILOG_DBROOT: |
2461 | xfs_bmbt_to_bmdr((xfs_bmbt_block_t *)src, len, | 2433 | xfs_bmbt_to_bmdr(mp, (struct xfs_btree_block *)src, len, |
2462 | &(dip->di_u.di_bmbt), | 2434 | (xfs_bmdr_block_t *)XFS_DFORK_DPTR(dip), |
2463 | XFS_DFORK_DSIZE(dip, mp)); | 2435 | XFS_DFORK_DSIZE(dip, mp)); |
2464 | break; | 2436 | break; |
2465 | 2437 | ||
@@ -2496,8 +2468,8 @@ xlog_recover_do_inode_trans( | |||
2496 | 2468 | ||
2497 | case XFS_ILOG_ABROOT: | 2469 | case XFS_ILOG_ABROOT: |
2498 | dest = XFS_DFORK_APTR(dip); | 2470 | dest = XFS_DFORK_APTR(dip); |
2499 | xfs_bmbt_to_bmdr((xfs_bmbt_block_t *)src, len, | 2471 | xfs_bmbt_to_bmdr(mp, (struct xfs_btree_block *)src, |
2500 | (xfs_bmdr_block_t*)dest, | 2472 | len, (xfs_bmdr_block_t*)dest, |
2501 | XFS_DFORK_ASIZE(dip, mp)); | 2473 | XFS_DFORK_ASIZE(dip, mp)); |
2502 | break; | 2474 | break; |
2503 | 2475 | ||
@@ -2512,9 +2484,8 @@ xlog_recover_do_inode_trans( | |||
2512 | 2484 | ||
2513 | write_inode_buffer: | 2485 | write_inode_buffer: |
2514 | if (ITEM_TYPE(item) == XFS_LI_INODE) { | 2486 | if (ITEM_TYPE(item) == XFS_LI_INODE) { |
2515 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL || | 2487 | ASSERT(bp->b_mount == NULL || bp->b_mount == mp); |
2516 | XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp); | 2488 | bp->b_mount = mp; |
2517 | XFS_BUF_SET_FSPRIVATE(bp, mp); | ||
2518 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone); | 2489 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone); |
2519 | xfs_bdwrite(mp, bp); | 2490 | xfs_bdwrite(mp, bp); |
2520 | } else { | 2491 | } else { |
@@ -2645,9 +2616,8 @@ xlog_recover_do_dquot_trans( | |||
2645 | memcpy(ddq, recddq, item->ri_buf[1].i_len); | 2616 | memcpy(ddq, recddq, item->ri_buf[1].i_len); |
2646 | 2617 | ||
2647 | ASSERT(dq_f->qlf_size == 2); | 2618 | ASSERT(dq_f->qlf_size == 2); |
2648 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL || | 2619 | ASSERT(bp->b_mount == NULL || bp->b_mount == mp); |
2649 | XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp); | 2620 | bp->b_mount = mp; |
2650 | XFS_BUF_SET_FSPRIVATE(bp, mp); | ||
2651 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone); | 2621 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone); |
2652 | xfs_bdwrite(mp, bp); | 2622 | xfs_bdwrite(mp, bp); |
2653 | 2623 | ||
@@ -2689,11 +2659,11 @@ xlog_recover_do_efi_trans( | |||
2689 | efip->efi_next_extent = efi_formatp->efi_nextents; | 2659 | efip->efi_next_extent = efi_formatp->efi_nextents; |
2690 | efip->efi_flags |= XFS_EFI_COMMITTED; | 2660 | efip->efi_flags |= XFS_EFI_COMMITTED; |
2691 | 2661 | ||
2692 | spin_lock(&mp->m_ail_lock); | 2662 | spin_lock(&log->l_ailp->xa_lock); |
2693 | /* | 2663 | /* |
2694 | * xfs_trans_update_ail() drops the AIL lock. | 2664 | * xfs_trans_ail_update() drops the AIL lock. |
2695 | */ | 2665 | */ |
2696 | xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn); | 2666 | xfs_trans_ail_update(log->l_ailp, (xfs_log_item_t *)efip, lsn); |
2697 | return 0; | 2667 | return 0; |
2698 | } | 2668 | } |
2699 | 2669 | ||
@@ -2712,12 +2682,12 @@ xlog_recover_do_efd_trans( | |||
2712 | xlog_recover_item_t *item, | 2682 | xlog_recover_item_t *item, |
2713 | int pass) | 2683 | int pass) |
2714 | { | 2684 | { |
2715 | xfs_mount_t *mp; | ||
2716 | xfs_efd_log_format_t *efd_formatp; | 2685 | xfs_efd_log_format_t *efd_formatp; |
2717 | xfs_efi_log_item_t *efip = NULL; | 2686 | xfs_efi_log_item_t *efip = NULL; |
2718 | xfs_log_item_t *lip; | 2687 | xfs_log_item_t *lip; |
2719 | int gen; | ||
2720 | __uint64_t efi_id; | 2688 | __uint64_t efi_id; |
2689 | struct xfs_ail_cursor cur; | ||
2690 | struct xfs_ail *ailp = log->l_ailp; | ||
2721 | 2691 | ||
2722 | if (pass == XLOG_RECOVER_PASS1) { | 2692 | if (pass == XLOG_RECOVER_PASS1) { |
2723 | return; | 2693 | return; |
@@ -2734,25 +2704,26 @@ xlog_recover_do_efd_trans( | |||
2734 | * Search for the efi with the id in the efd format structure | 2704 | * Search for the efi with the id in the efd format structure |
2735 | * in the AIL. | 2705 | * in the AIL. |
2736 | */ | 2706 | */ |
2737 | mp = log->l_mp; | 2707 | spin_lock(&ailp->xa_lock); |
2738 | spin_lock(&mp->m_ail_lock); | 2708 | lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); |
2739 | lip = xfs_trans_first_ail(mp, &gen); | ||
2740 | while (lip != NULL) { | 2709 | while (lip != NULL) { |
2741 | if (lip->li_type == XFS_LI_EFI) { | 2710 | if (lip->li_type == XFS_LI_EFI) { |
2742 | efip = (xfs_efi_log_item_t *)lip; | 2711 | efip = (xfs_efi_log_item_t *)lip; |
2743 | if (efip->efi_format.efi_id == efi_id) { | 2712 | if (efip->efi_format.efi_id == efi_id) { |
2744 | /* | 2713 | /* |
2745 | * xfs_trans_delete_ail() drops the | 2714 | * xfs_trans_ail_delete() drops the |
2746 | * AIL lock. | 2715 | * AIL lock. |
2747 | */ | 2716 | */ |
2748 | xfs_trans_delete_ail(mp, lip); | 2717 | xfs_trans_ail_delete(ailp, lip); |
2749 | xfs_efi_item_free(efip); | 2718 | xfs_efi_item_free(efip); |
2750 | return; | 2719 | spin_lock(&ailp->xa_lock); |
2720 | break; | ||
2751 | } | 2721 | } |
2752 | } | 2722 | } |
2753 | lip = xfs_trans_next_ail(mp, lip, &gen, NULL); | 2723 | lip = xfs_trans_ail_cursor_next(ailp, &cur); |
2754 | } | 2724 | } |
2755 | spin_unlock(&mp->m_ail_lock); | 2725 | xfs_trans_ail_cursor_done(ailp, &cur); |
2726 | spin_unlock(&ailp->xa_lock); | ||
2756 | } | 2727 | } |
2757 | 2728 | ||
2758 | /* | 2729 | /* |
@@ -3036,33 +3007,6 @@ abort_error: | |||
3036 | } | 3007 | } |
3037 | 3008 | ||
3038 | /* | 3009 | /* |
3039 | * Verify that once we've encountered something other than an EFI | ||
3040 | * in the AIL that there are no more EFIs in the AIL. | ||
3041 | */ | ||
3042 | #if defined(DEBUG) | ||
3043 | STATIC void | ||
3044 | xlog_recover_check_ail( | ||
3045 | xfs_mount_t *mp, | ||
3046 | xfs_log_item_t *lip, | ||
3047 | int gen) | ||
3048 | { | ||
3049 | int orig_gen = gen; | ||
3050 | |||
3051 | do { | ||
3052 | ASSERT(lip->li_type != XFS_LI_EFI); | ||
3053 | lip = xfs_trans_next_ail(mp, lip, &gen, NULL); | ||
3054 | /* | ||
3055 | * The check will be bogus if we restart from the | ||
3056 | * beginning of the AIL, so ASSERT that we don't. | ||
3057 | * We never should since we're holding the AIL lock | ||
3058 | * the entire time. | ||
3059 | */ | ||
3060 | ASSERT(gen == orig_gen); | ||
3061 | } while (lip != NULL); | ||
3062 | } | ||
3063 | #endif /* DEBUG */ | ||
3064 | |||
3065 | /* | ||
3066 | * When this is called, all of the EFIs which did not have | 3010 | * When this is called, all of the EFIs which did not have |
3067 | * corresponding EFDs should be in the AIL. What we do now | 3011 | * corresponding EFDs should be in the AIL. What we do now |
3068 | * is free the extents associated with each one. | 3012 | * is free the extents associated with each one. |
@@ -3086,20 +3030,23 @@ xlog_recover_process_efis( | |||
3086 | { | 3030 | { |
3087 | xfs_log_item_t *lip; | 3031 | xfs_log_item_t *lip; |
3088 | xfs_efi_log_item_t *efip; | 3032 | xfs_efi_log_item_t *efip; |
3089 | int gen; | ||
3090 | xfs_mount_t *mp; | ||
3091 | int error = 0; | 3033 | int error = 0; |
3034 | struct xfs_ail_cursor cur; | ||
3035 | struct xfs_ail *ailp; | ||
3092 | 3036 | ||
3093 | mp = log->l_mp; | 3037 | ailp = log->l_ailp; |
3094 | spin_lock(&mp->m_ail_lock); | 3038 | spin_lock(&ailp->xa_lock); |
3095 | 3039 | lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); | |
3096 | lip = xfs_trans_first_ail(mp, &gen); | ||
3097 | while (lip != NULL) { | 3040 | while (lip != NULL) { |
3098 | /* | 3041 | /* |
3099 | * We're done when we see something other than an EFI. | 3042 | * We're done when we see something other than an EFI. |
3043 | * There should be no EFIs left in the AIL now. | ||
3100 | */ | 3044 | */ |
3101 | if (lip->li_type != XFS_LI_EFI) { | 3045 | if (lip->li_type != XFS_LI_EFI) { |
3102 | xlog_recover_check_ail(mp, lip, gen); | 3046 | #ifdef DEBUG |
3047 | for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur)) | ||
3048 | ASSERT(lip->li_type != XFS_LI_EFI); | ||
3049 | #endif | ||
3103 | break; | 3050 | break; |
3104 | } | 3051 | } |
3105 | 3052 | ||
@@ -3108,18 +3055,20 @@ xlog_recover_process_efis( | |||
3108 | */ | 3055 | */ |
3109 | efip = (xfs_efi_log_item_t *)lip; | 3056 | efip = (xfs_efi_log_item_t *)lip; |
3110 | if (efip->efi_flags & XFS_EFI_RECOVERED) { | 3057 | if (efip->efi_flags & XFS_EFI_RECOVERED) { |
3111 | lip = xfs_trans_next_ail(mp, lip, &gen, NULL); | 3058 | lip = xfs_trans_ail_cursor_next(ailp, &cur); |
3112 | continue; | 3059 | continue; |
3113 | } | 3060 | } |
3114 | 3061 | ||
3115 | spin_unlock(&mp->m_ail_lock); | 3062 | spin_unlock(&ailp->xa_lock); |
3116 | error = xlog_recover_process_efi(mp, efip); | 3063 | error = xlog_recover_process_efi(log->l_mp, efip); |
3064 | spin_lock(&ailp->xa_lock); | ||
3117 | if (error) | 3065 | if (error) |
3118 | return error; | 3066 | goto out; |
3119 | spin_lock(&mp->m_ail_lock); | 3067 | lip = xfs_trans_ail_cursor_next(ailp, &cur); |
3120 | lip = xfs_trans_next_ail(mp, lip, &gen, NULL); | ||
3121 | } | 3068 | } |
3122 | spin_unlock(&mp->m_ail_lock); | 3069 | out: |
3070 | xfs_trans_ail_cursor_done(ailp, &cur); | ||
3071 | spin_unlock(&ailp->xa_lock); | ||
3123 | return error; | 3072 | return error; |
3124 | } | 3073 | } |
3125 | 3074 | ||
@@ -3140,19 +3089,16 @@ xlog_recover_clear_agi_bucket( | |||
3140 | int error; | 3089 | int error; |
3141 | 3090 | ||
3142 | tp = xfs_trans_alloc(mp, XFS_TRANS_CLEAR_AGI_BUCKET); | 3091 | tp = xfs_trans_alloc(mp, XFS_TRANS_CLEAR_AGI_BUCKET); |
3143 | error = xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), 0, 0, 0); | 3092 | error = xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), |
3144 | if (!error) | 3093 | 0, 0, 0); |
3145 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, | ||
3146 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), | ||
3147 | XFS_FSS_TO_BB(mp, 1), 0, &agibp); | ||
3148 | if (error) | 3094 | if (error) |
3149 | goto out_abort; | 3095 | goto out_abort; |
3150 | 3096 | ||
3151 | error = EINVAL; | 3097 | error = xfs_read_agi(mp, tp, agno, &agibp); |
3152 | agi = XFS_BUF_TO_AGI(agibp); | 3098 | if (error) |
3153 | if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) | ||
3154 | goto out_abort; | 3099 | goto out_abort; |
3155 | 3100 | ||
3101 | agi = XFS_BUF_TO_AGI(agibp); | ||
3156 | agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); | 3102 | agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); |
3157 | offset = offsetof(xfs_agi_t, agi_unlinked) + | 3103 | offset = offsetof(xfs_agi_t, agi_unlinked) + |
3158 | (sizeof(xfs_agino_t) * bucket); | 3104 | (sizeof(xfs_agino_t) * bucket); |
@@ -3172,6 +3118,62 @@ out_error: | |||
3172 | return; | 3118 | return; |
3173 | } | 3119 | } |
3174 | 3120 | ||
3121 | STATIC xfs_agino_t | ||
3122 | xlog_recover_process_one_iunlink( | ||
3123 | struct xfs_mount *mp, | ||
3124 | xfs_agnumber_t agno, | ||
3125 | xfs_agino_t agino, | ||
3126 | int bucket) | ||
3127 | { | ||
3128 | struct xfs_buf *ibp; | ||
3129 | struct xfs_dinode *dip; | ||
3130 | struct xfs_inode *ip; | ||
3131 | xfs_ino_t ino; | ||
3132 | int error; | ||
3133 | |||
3134 | ino = XFS_AGINO_TO_INO(mp, agno, agino); | ||
3135 | error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0); | ||
3136 | if (error) | ||
3137 | goto fail; | ||
3138 | |||
3139 | /* | ||
3140 | * Get the on disk inode to find the next inode in the bucket. | ||
3141 | */ | ||
3142 | error = xfs_itobp(mp, NULL, ip, &dip, &ibp, XFS_BUF_LOCK); | ||
3143 | if (error) | ||
3144 | goto fail_iput; | ||
3145 | |||
3146 | ASSERT(ip->i_d.di_nlink == 0); | ||
3147 | ASSERT(ip->i_d.di_mode != 0); | ||
3148 | |||
3149 | /* setup for the next pass */ | ||
3150 | agino = be32_to_cpu(dip->di_next_unlinked); | ||
3151 | xfs_buf_relse(ibp); | ||
3152 | |||
3153 | /* | ||
3154 | * Prevent any DMAPI event from being sent when the reference on | ||
3155 | * the inode is dropped. | ||
3156 | */ | ||
3157 | ip->i_d.di_dmevmask = 0; | ||
3158 | |||
3159 | IRELE(ip); | ||
3160 | return agino; | ||
3161 | |||
3162 | fail_iput: | ||
3163 | IRELE(ip); | ||
3164 | fail: | ||
3165 | /* | ||
3166 | * We can't read in the inode this bucket points to, or this inode | ||
3167 | * is messed up. Just ditch this bucket of inodes. We will lose | ||
3168 | * some inodes and space, but at least we won't hang. | ||
3169 | * | ||
3170 | * Call xlog_recover_clear_agi_bucket() to perform a transaction to | ||
3171 | * clear the inode pointer in the bucket. | ||
3172 | */ | ||
3173 | xlog_recover_clear_agi_bucket(mp, agno, bucket); | ||
3174 | return NULLAGINO; | ||
3175 | } | ||
3176 | |||
3175 | /* | 3177 | /* |
3176 | * xlog_iunlink_recover | 3178 | * xlog_iunlink_recover |
3177 | * | 3179 | * |
@@ -3192,11 +3194,7 @@ xlog_recover_process_iunlinks( | |||
3192 | xfs_agnumber_t agno; | 3194 | xfs_agnumber_t agno; |
3193 | xfs_agi_t *agi; | 3195 | xfs_agi_t *agi; |
3194 | xfs_buf_t *agibp; | 3196 | xfs_buf_t *agibp; |
3195 | xfs_buf_t *ibp; | ||
3196 | xfs_dinode_t *dip; | ||
3197 | xfs_inode_t *ip; | ||
3198 | xfs_agino_t agino; | 3197 | xfs_agino_t agino; |
3199 | xfs_ino_t ino; | ||
3200 | int bucket; | 3198 | int bucket; |
3201 | int error; | 3199 | int error; |
3202 | uint mp_dmevmask; | 3200 | uint mp_dmevmask; |
@@ -3213,22 +3211,21 @@ xlog_recover_process_iunlinks( | |||
3213 | /* | 3211 | /* |
3214 | * Find the agi for this ag. | 3212 | * Find the agi for this ag. |
3215 | */ | 3213 | */ |
3216 | agibp = xfs_buf_read(mp->m_ddev_targp, | 3214 | error = xfs_read_agi(mp, NULL, agno, &agibp); |
3217 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), | 3215 | if (error) { |
3218 | XFS_FSS_TO_BB(mp, 1), 0); | 3216 | /* |
3219 | if (XFS_BUF_ISERROR(agibp)) { | 3217 | * AGI is b0rked. Don't process it. |
3220 | xfs_ioerror_alert("xlog_recover_process_iunlinks(#1)", | 3218 | * |
3221 | log->l_mp, agibp, | 3219 | * We should probably mark the filesystem as corrupt |
3222 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp))); | 3220 | * after we've recovered all the ag's we can.... |
3221 | */ | ||
3222 | continue; | ||
3223 | } | 3223 | } |
3224 | agi = XFS_BUF_TO_AGI(agibp); | 3224 | agi = XFS_BUF_TO_AGI(agibp); |
3225 | ASSERT(XFS_AGI_MAGIC == be32_to_cpu(agi->agi_magicnum)); | ||
3226 | 3225 | ||
3227 | for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) { | 3226 | for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) { |
3228 | |||
3229 | agino = be32_to_cpu(agi->agi_unlinked[bucket]); | 3227 | agino = be32_to_cpu(agi->agi_unlinked[bucket]); |
3230 | while (agino != NULLAGINO) { | 3228 | while (agino != NULLAGINO) { |
3231 | |||
3232 | /* | 3229 | /* |
3233 | * Release the agi buffer so that it can | 3230 | * Release the agi buffer so that it can |
3234 | * be acquired in the normal course of the | 3231 | * be acquired in the normal course of the |
@@ -3236,87 +3233,17 @@ xlog_recover_process_iunlinks( | |||
3236 | */ | 3233 | */ |
3237 | xfs_buf_relse(agibp); | 3234 | xfs_buf_relse(agibp); |
3238 | 3235 | ||
3239 | ino = XFS_AGINO_TO_INO(mp, agno, agino); | 3236 | agino = xlog_recover_process_one_iunlink(mp, |
3240 | error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0); | 3237 | agno, agino, bucket); |
3241 | ASSERT(error || (ip != NULL)); | ||
3242 | |||
3243 | if (!error) { | ||
3244 | /* | ||
3245 | * Get the on disk inode to find the | ||
3246 | * next inode in the bucket. | ||
3247 | */ | ||
3248 | error = xfs_itobp(mp, NULL, ip, &dip, | ||
3249 | &ibp, 0, 0, | ||
3250 | XFS_BUF_LOCK); | ||
3251 | ASSERT(error || (dip != NULL)); | ||
3252 | } | ||
3253 | |||
3254 | if (!error) { | ||
3255 | ASSERT(ip->i_d.di_nlink == 0); | ||
3256 | |||
3257 | /* setup for the next pass */ | ||
3258 | agino = be32_to_cpu( | ||
3259 | dip->di_next_unlinked); | ||
3260 | xfs_buf_relse(ibp); | ||
3261 | /* | ||
3262 | * Prevent any DMAPI event from | ||
3263 | * being sent when the | ||
3264 | * reference on the inode is | ||
3265 | * dropped. | ||
3266 | */ | ||
3267 | ip->i_d.di_dmevmask = 0; | ||
3268 | |||
3269 | /* | ||
3270 | * If this is a new inode, handle | ||
3271 | * it specially. Otherwise, | ||
3272 | * just drop our reference to the | ||
3273 | * inode. If there are no | ||
3274 | * other references, this will | ||
3275 | * send the inode to | ||
3276 | * xfs_inactive() which will | ||
3277 | * truncate the file and free | ||
3278 | * the inode. | ||
3279 | */ | ||
3280 | if (ip->i_d.di_mode == 0) | ||
3281 | xfs_iput_new(ip, 0); | ||
3282 | else | ||
3283 | IRELE(ip); | ||
3284 | } else { | ||
3285 | /* | ||
3286 | * We can't read in the inode | ||
3287 | * this bucket points to, or | ||
3288 | * this inode is messed up. Just | ||
3289 | * ditch this bucket of inodes. We | ||
3290 | * will lose some inodes and space, | ||
3291 | * but at least we won't hang. Call | ||
3292 | * xlog_recover_clear_agi_bucket() | ||
3293 | * to perform a transaction to clear | ||
3294 | * the inode pointer in the bucket. | ||
3295 | */ | ||
3296 | xlog_recover_clear_agi_bucket(mp, agno, | ||
3297 | bucket); | ||
3298 | |||
3299 | agino = NULLAGINO; | ||
3300 | } | ||
3301 | 3238 | ||
3302 | /* | 3239 | /* |
3303 | * Reacquire the agibuffer and continue around | 3240 | * Reacquire the agibuffer and continue around |
3304 | * the loop. | 3241 | * the loop. This should never fail as we know |
3242 | * the buffer was good earlier on. | ||
3305 | */ | 3243 | */ |
3306 | agibp = xfs_buf_read(mp->m_ddev_targp, | 3244 | error = xfs_read_agi(mp, NULL, agno, &agibp); |
3307 | XFS_AG_DADDR(mp, agno, | 3245 | ASSERT(error == 0); |
3308 | XFS_AGI_DADDR(mp)), | ||
3309 | XFS_FSS_TO_BB(mp, 1), 0); | ||
3310 | if (XFS_BUF_ISERROR(agibp)) { | ||
3311 | xfs_ioerror_alert( | ||
3312 | "xlog_recover_process_iunlinks(#2)", | ||
3313 | log->l_mp, agibp, | ||
3314 | XFS_AG_DADDR(mp, agno, | ||
3315 | XFS_AGI_DADDR(mp))); | ||
3316 | } | ||
3317 | agi = XFS_BUF_TO_AGI(agibp); | 3246 | agi = XFS_BUF_TO_AGI(agibp); |
3318 | ASSERT(XFS_AGI_MAGIC == be32_to_cpu( | ||
3319 | agi->agi_magicnum)); | ||
3320 | } | 3247 | } |
3321 | } | 3248 | } |
3322 | 3249 | ||
@@ -3367,7 +3294,6 @@ xlog_pack_data( | |||
3367 | int size = iclog->ic_offset + roundoff; | 3294 | int size = iclog->ic_offset + roundoff; |
3368 | __be32 cycle_lsn; | 3295 | __be32 cycle_lsn; |
3369 | xfs_caddr_t dp; | 3296 | xfs_caddr_t dp; |
3370 | xlog_in_core_2_t *xhdr; | ||
3371 | 3297 | ||
3372 | xlog_pack_data_checksum(log, iclog, size); | 3298 | xlog_pack_data_checksum(log, iclog, size); |
3373 | 3299 | ||
@@ -3382,7 +3308,8 @@ xlog_pack_data( | |||
3382 | } | 3308 | } |
3383 | 3309 | ||
3384 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { | 3310 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { |
3385 | xhdr = (xlog_in_core_2_t *)&iclog->ic_header; | 3311 | xlog_in_core_2_t *xhdr = iclog->ic_data; |
3312 | |||
3386 | for ( ; i < BTOBB(size); i++) { | 3313 | for ( ; i < BTOBB(size); i++) { |
3387 | j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE); | 3314 | j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE); |
3388 | k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE); | 3315 | k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE); |
@@ -3440,7 +3367,6 @@ xlog_unpack_data( | |||
3440 | xlog_t *log) | 3367 | xlog_t *log) |
3441 | { | 3368 | { |
3442 | int i, j, k; | 3369 | int i, j, k; |
3443 | xlog_in_core_2_t *xhdr; | ||
3444 | 3370 | ||
3445 | for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) && | 3371 | for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) && |
3446 | i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) { | 3372 | i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) { |
@@ -3449,7 +3375,7 @@ xlog_unpack_data( | |||
3449 | } | 3375 | } |
3450 | 3376 | ||
3451 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { | 3377 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { |
3452 | xhdr = (xlog_in_core_2_t *)rhead; | 3378 | xlog_in_core_2_t *xhdr = (xlog_in_core_2_t *)rhead; |
3453 | for ( ; i < BTOBB(be32_to_cpu(rhead->h_len)); i++) { | 3379 | for ( ; i < BTOBB(be32_to_cpu(rhead->h_len)); i++) { |
3454 | j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE); | 3380 | j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE); |
3455 | k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE); | 3381 | k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE); |
@@ -4003,11 +3929,8 @@ xlog_recover_check_summary( | |||
4003 | { | 3929 | { |
4004 | xfs_mount_t *mp; | 3930 | xfs_mount_t *mp; |
4005 | xfs_agf_t *agfp; | 3931 | xfs_agf_t *agfp; |
4006 | xfs_agi_t *agip; | ||
4007 | xfs_buf_t *agfbp; | 3932 | xfs_buf_t *agfbp; |
4008 | xfs_buf_t *agibp; | 3933 | xfs_buf_t *agibp; |
4009 | xfs_daddr_t agfdaddr; | ||
4010 | xfs_daddr_t agidaddr; | ||
4011 | xfs_buf_t *sbbp; | 3934 | xfs_buf_t *sbbp; |
4012 | #ifdef XFS_LOUD_RECOVERY | 3935 | #ifdef XFS_LOUD_RECOVERY |
4013 | xfs_sb_t *sbp; | 3936 | xfs_sb_t *sbp; |
@@ -4016,6 +3939,7 @@ xlog_recover_check_summary( | |||
4016 | __uint64_t freeblks; | 3939 | __uint64_t freeblks; |
4017 | __uint64_t itotal; | 3940 | __uint64_t itotal; |
4018 | __uint64_t ifree; | 3941 | __uint64_t ifree; |
3942 | int error; | ||
4019 | 3943 | ||
4020 | mp = log->l_mp; | 3944 | mp = log->l_mp; |
4021 | 3945 | ||
@@ -4023,37 +3947,27 @@ xlog_recover_check_summary( | |||
4023 | itotal = 0LL; | 3947 | itotal = 0LL; |
4024 | ifree = 0LL; | 3948 | ifree = 0LL; |
4025 | for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { | 3949 | for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { |
4026 | agfdaddr = XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)); | 3950 | error = xfs_read_agf(mp, NULL, agno, 0, &agfbp); |
4027 | agfbp = xfs_buf_read(mp->m_ddev_targp, agfdaddr, | 3951 | if (error) { |
4028 | XFS_FSS_TO_BB(mp, 1), 0); | 3952 | xfs_fs_cmn_err(CE_ALERT, mp, |
4029 | if (XFS_BUF_ISERROR(agfbp)) { | 3953 | "xlog_recover_check_summary(agf)" |
4030 | xfs_ioerror_alert("xlog_recover_check_summary(agf)", | 3954 | "agf read failed agno %d error %d", |
4031 | mp, agfbp, agfdaddr); | 3955 | agno, error); |
4032 | } | 3956 | } else { |
4033 | agfp = XFS_BUF_TO_AGF(agfbp); | 3957 | agfp = XFS_BUF_TO_AGF(agfbp); |
4034 | ASSERT(XFS_AGF_MAGIC == be32_to_cpu(agfp->agf_magicnum)); | 3958 | freeblks += be32_to_cpu(agfp->agf_freeblks) + |
4035 | ASSERT(XFS_AGF_GOOD_VERSION(be32_to_cpu(agfp->agf_versionnum))); | 3959 | be32_to_cpu(agfp->agf_flcount); |
4036 | ASSERT(be32_to_cpu(agfp->agf_seqno) == agno); | 3960 | xfs_buf_relse(agfbp); |
4037 | |||
4038 | freeblks += be32_to_cpu(agfp->agf_freeblks) + | ||
4039 | be32_to_cpu(agfp->agf_flcount); | ||
4040 | xfs_buf_relse(agfbp); | ||
4041 | |||
4042 | agidaddr = XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)); | ||
4043 | agibp = xfs_buf_read(mp->m_ddev_targp, agidaddr, | ||
4044 | XFS_FSS_TO_BB(mp, 1), 0); | ||
4045 | if (XFS_BUF_ISERROR(agibp)) { | ||
4046 | xfs_ioerror_alert("xlog_recover_check_summary(agi)", | ||
4047 | mp, agibp, agidaddr); | ||
4048 | } | 3961 | } |
4049 | agip = XFS_BUF_TO_AGI(agibp); | ||
4050 | ASSERT(XFS_AGI_MAGIC == be32_to_cpu(agip->agi_magicnum)); | ||
4051 | ASSERT(XFS_AGI_GOOD_VERSION(be32_to_cpu(agip->agi_versionnum))); | ||
4052 | ASSERT(be32_to_cpu(agip->agi_seqno) == agno); | ||
4053 | 3962 | ||
4054 | itotal += be32_to_cpu(agip->agi_count); | 3963 | error = xfs_read_agi(mp, NULL, agno, &agibp); |
4055 | ifree += be32_to_cpu(agip->agi_freecount); | 3964 | if (!error) { |
4056 | xfs_buf_relse(agibp); | 3965 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agibp); |
3966 | |||
3967 | itotal += be32_to_cpu(agi->agi_count); | ||
3968 | ifree += be32_to_cpu(agi->agi_freecount); | ||
3969 | xfs_buf_relse(agibp); | ||
3970 | } | ||
4057 | } | 3971 | } |
4058 | 3972 | ||
4059 | sbbp = xfs_getsb(mp, 0); | 3973 | sbbp = xfs_getsb(mp, 0); |