| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| */ |
| |
| #include "libxfs.h" |
| #include "avl.h" |
| #include "globals.h" |
| #include "agheader.h" |
| #include "incore.h" |
| #include "dinode.h" |
| #include "protos.h" |
| #include "err_protos.h" |
| #include "rt.h" |
| |
| #define xfs_highbit64 libxfs_highbit64 /* for XFS_RTBLOCKLOG macro */ |
| |
| void |
| rtinit(xfs_mount_t *mp) |
| { |
| if (mp->m_sb.sb_rblocks == 0) |
| return; |
| |
| /* |
| * realtime init -- blockmap initialization is |
| * handled by incore_init() |
| */ |
| /* |
| sumfile = calloc(mp->m_rsumsize, 1); |
| */ |
| if ((btmcompute = calloc(mp->m_sb.sb_rbmblocks * |
| mp->m_sb.sb_blocksize, 1)) == NULL) |
| do_error( |
| _("couldn't allocate memory for incore realtime bitmap.\n")); |
| |
| if ((sumcompute = calloc(mp->m_rsumsize, 1)) == NULL) |
| do_error( |
| _("couldn't allocate memory for incore realtime summary info.\n")); |
| } |
| |
| /* |
| * generate the real-time bitmap and summary info based on the |
| * incore realtime extent map. |
| */ |
| int |
| generate_rtinfo(xfs_mount_t *mp, |
| xfs_rtword_t *words, |
| xfs_suminfo_t *sumcompute) |
| { |
| xfs_rtblock_t extno; |
| xfs_rtblock_t start_ext; |
| int bitsperblock; |
| int bmbno; |
| xfs_rtword_t freebit; |
| xfs_rtword_t bits; |
| int start_bmbno; |
| int i; |
| int offs; |
| int log; |
| int len; |
| int in_extent; |
| |
| ASSERT(mp->m_rbmip == NULL); |
| |
| bitsperblock = mp->m_sb.sb_blocksize * NBBY; |
| extno = start_ext = 0; |
| bmbno = in_extent = start_bmbno = 0; |
| |
| /* |
| * slower but simple, don't play around with trying to set |
| * things one word at a time, just set bit as required. |
| * Have to * track start and end (size) of each range of |
| * free extents to set the summary info properly. |
| */ |
| while (extno < mp->m_sb.sb_rextents) { |
| freebit = 1; |
| *words = 0; |
| bits = 0; |
| for (i = 0; i < sizeof(xfs_rtword_t) * NBBY && |
| extno < mp->m_sb.sb_rextents; i++, extno++) { |
| if (get_rtbmap(extno) == XR_E_FREE) { |
| sb_frextents++; |
| bits |= freebit; |
| |
| if (in_extent == 0) { |
| start_ext = extno; |
| start_bmbno = bmbno; |
| in_extent = 1; |
| } |
| } else if (in_extent == 1) { |
| len = (int) (extno - start_ext); |
| log = XFS_RTBLOCKLOG(len); |
| offs = XFS_SUMOFFS(mp, log, start_bmbno); |
| sumcompute[offs]++; |
| in_extent = 0; |
| } |
| |
| freebit <<= 1; |
| } |
| *words = bits; |
| words++; |
| |
| if (extno % bitsperblock == 0) |
| bmbno++; |
| } |
| if (in_extent == 1) { |
| len = (int) (extno - start_ext); |
| log = XFS_RTBLOCKLOG(len); |
| offs = XFS_SUMOFFS(mp, log, start_bmbno); |
| sumcompute[offs]++; |
| } |
| |
| return(0); |
| } |
| |
| #if 0 |
| /* |
| * returns 1 if bad, 0 if good |
| */ |
| int |
| check_summary(xfs_mount_t *mp) |
| { |
| xfs_rfsblock_t bno; |
| xfs_suminfo_t *csp; |
| xfs_suminfo_t *fsp; |
| int log; |
| int error = 0; |
| |
| error = 0; |
| csp = sumcompute; |
| fsp = sumfile; |
| for (log = 0; log < mp->m_rsumlevels; log++) { |
| for (bno = 0; |
| bno < mp->m_sb.sb_rbmblocks; |
| bno++, csp++, fsp++) { |
| if (*csp != *fsp) { |
| do_warn( |
| _("rt summary mismatch, size %d block %llu, file: %d, computed: %d\n"), |
| log, bno, *fsp, *csp); |
| error = 1; |
| } |
| } |
| } |
| |
| return(error); |
| } |
| |
| /* |
| * examine the real-time bitmap file and compute summary |
| * info off it. Should probably be changed to compute |
| * the summary information off the incore computed bitmap |
| * instead of the realtime bitmap file |
| */ |
| void |
| process_rtbitmap(xfs_mount_t *mp, |
| xfs_dinode_t *dino, |
| blkmap_t *blkmap) |
| { |
| int error; |
| int bit; |
| int bitsperblock; |
| int bmbno; |
| int end_bmbno; |
| xfs_fsblock_t bno; |
| xfs_buf_t *bp; |
| xfs_rtblock_t extno; |
| int i; |
| int len; |
| int log; |
| int offs; |
| int prevbit; |
| int start_bmbno; |
| int start_bit; |
| xfs_rtword_t *words; |
| |
| ASSERT(mp->m_rbmip == NULL); |
| |
| bitsperblock = mp->m_sb.sb_blocksize * NBBY; |
| prevbit = 0; |
| extno = 0; |
| error = 0; |
| |
| end_bmbno = howmany(be64_to_cpu(dino->di_size), |
| mp->m_sb.sb_blocksize); |
| |
| for (bmbno = 0; bmbno < end_bmbno; bmbno++) { |
| bno = blkmap_get(blkmap, bmbno); |
| |
| if (bno == NULLFSBLOCK) { |
| do_warn(_("can't find block %d for rtbitmap inode\n"), |
| bmbno); |
| error = 1; |
| continue; |
| } |
| error = -libxfs_buf_read(mp->m_dev, XFS_FSB_TO_DADDR(mp, bno), |
| XFS_FSB_TO_BB(mp, 1), 0, NULL, &bp); |
| if (error) { |
| do_warn(_("can't read block %d for rtbitmap inode\n"), |
| bmbno); |
| error = 1; |
| continue; |
| } |
| words = (xfs_rtword_t *)bp->b_un.b_addr; |
| for (bit = 0; |
| bit < bitsperblock && extno < mp->m_sb.sb_rextents; |
| bit++, extno++) { |
| if (xfs_isset(words, bit)) { |
| set_rtbmap(extno, XR_E_FREE); |
| sb_frextents++; |
| if (prevbit == 0) { |
| start_bmbno = bmbno; |
| start_bit = bit; |
| prevbit = 1; |
| } |
| } else if (prevbit == 1) { |
| len = (bmbno - start_bmbno) * bitsperblock + |
| (bit - start_bit); |
| log = XFS_RTBLOCKLOG(len); |
| offs = XFS_SUMOFFS(mp, log, start_bmbno); |
| sumcompute[offs]++; |
| prevbit = 0; |
| } |
| } |
| libxfs_buf_relse(bp); |
| if (extno == mp->m_sb.sb_rextents) |
| break; |
| } |
| if (prevbit == 1) { |
| len = (bmbno - start_bmbno) * bitsperblock + (bit - start_bit); |
| log = XFS_RTBLOCKLOG(len); |
| offs = XFS_SUMOFFS(mp, log, start_bmbno); |
| sumcompute[offs]++; |
| } |
| } |
| |
| /* |
| * copy the real-time summary file data into memory |
| */ |
| void |
| process_rtsummary(xfs_mount_t *mp, |
| xfs_dinode_t *dino, |
| blkmap_t *blkmap) |
| { |
| xfs_fsblock_t bno; |
| xfs_buf_t *bp; |
| char *bytes; |
| int sumbno; |
| |
| for (sumbno = 0; sumbno < blkmap->count; sumbno++) { |
| bno = blkmap_get(blkmap, sumbno); |
| if (bno == NULLFSBLOCK) { |
| do_warn(_("block %d for rtsummary inode is missing\n"), |
| sumbno); |
| error++; |
| continue; |
| } |
| error = -libxfs_buf_read(mp->m_dev, XFS_FSB_TO_DADDR(mp, bno), |
| XFS_FSB_TO_BB(mp, 1), 0, NULL, &bp); |
| if (error) { |
| do_warn(_("can't read block %d for rtsummary inode\n"), |
| sumbno); |
| error++; |
| continue; |
| } |
| bytes = bp->b_un.b_addr; |
| memmove((char *)sumfile + sumbno * mp->m_sb.sb_blocksize, bytes, |
| mp->m_sb.sb_blocksize); |
| libxfs_buf_relse(bp); |
| } |
| } |
| #endif |