blob: d901e751830391ce4451ca4becad8a6c1a14be3b [file] [log] [blame]
// 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