/* * Copy and transform the summary file, given the old and new * parameters in the mount structures. */ STATIC int /* error */ xfs_rtcopy_summary( xfs_mount_t *omp, /* old file system mount point */ xfs_mount_t *nmp, /* new file system mount point */ xfs_trans_t *tp) /* transaction pointer */ { xfs_rtblock_t bbno; /* bitmap block number */ xfs_buf_t *bp; /* summary buffer */ int error; /* error return value */ int log; /* summary level number (log length) */ xfs_suminfo_t sum; /* summary data */ xfs_fsblock_t sumbno; /* summary block number */ bp = NULL; for (log = omp->m_rsumlevels - 1; log >= 0; log--) { for (bbno = omp->m_sb.sb_rbmblocks - 1; (xfs_srtblock_t)bbno >= 0; bbno--) { error = xfs_rtget_summary(omp, tp, log, bbno, &bp, &sumbno, &sum); if (error) return error; if (sum == 0) continue; error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum, &bp, &sumbno); if (error) return error; error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum, &bp, &sumbno); if (error) return error; ASSERT(sum > 0); } } return 0; }
/* * Mark an extent specified by start and len freed. * Updates all the summary information as well as the bitmap. */ int xfs_rtfree_range( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_rtblock_t start, /* starting block to free */ xfs_extlen_t len, /* length to free */ xfs_buf_t **rbpp, /* in/out: summary block buffer */ xfs_fsblock_t *rsb) /* in/out: summary block number */ { xfs_rtblock_t end; /* end of the freed extent */ int error; /* error value */ xfs_rtblock_t postblock; /* first block freed > end */ xfs_rtblock_t preblock; /* first block freed < start */ end = start + len - 1; /* * Modify the bitmap to mark this extent freed. */ error = xfs_rtmodify_range(mp, tp, start, len, 1); if (error) { return error; } /* * Assume we're freeing out of the middle of an allocated extent. * We need to find the beginning and end of the extent so we can * properly update the summary. */ error = xfs_rtfind_back(mp, tp, start, 0, &preblock); if (error) { return error; } /* * Find the next allocated block (end of allocated extent). */ error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, &postblock); if (error) return error; /* * If there are blocks not being freed at the front of the * old extent, add summary data for them to be allocated. */ if (preblock < start) { error = xfs_rtmodify_summary(mp, tp, XFS_RTBLOCKLOG(start - preblock), XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); if (error) { return error; } } /* * If there are blocks not being freed at the end of the * old extent, add summary data for them to be allocated. */ if (postblock > end) { error = xfs_rtmodify_summary(mp, tp, XFS_RTBLOCKLOG(postblock - end), XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb); if (error) { return error; } } /* * Increment the summary information corresponding to the entire * (new) free extent. */ error = xfs_rtmodify_summary(mp, tp, XFS_RTBLOCKLOG(postblock + 1 - preblock), XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); return error; }