/* * Actually mark the segment clean. * Must be called with the segment lock held. */ int lfs_do_segclean(struct lfs *fs, unsigned long segnum) { extern int lfs_dostats; struct buf *bp; CLEANERINFO *cip; SEGUSE *sup; if (lfs_dtosn(fs, fs->lfs_curseg) == segnum) { return (EBUSY); } LFS_SEGENTRY(sup, fs, segnum, bp); if (sup->su_nbytes) { DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:" " %d live bytes\n", segnum, sup->su_nbytes)); brelse(bp, 0); return (EBUSY); } if (sup->su_flags & SEGUSE_ACTIVE) { DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:" " segment is active\n", segnum)); brelse(bp, 0); return (EBUSY); } if (!(sup->su_flags & SEGUSE_DIRTY)) { DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:" " segment is already clean\n", segnum)); brelse(bp, 0); return (EALREADY); } fs->lfs_avail += lfs_segtod(fs, 1); if (sup->su_flags & SEGUSE_SUPERBLOCK) fs->lfs_avail -= lfs_btofsb(fs, LFS_SBPAD); if (fs->lfs_version > 1 && segnum == 0 && fs->lfs_start < lfs_btofsb(fs, LFS_LABELPAD)) fs->lfs_avail -= lfs_btofsb(fs, LFS_LABELPAD) - fs->lfs_start; mutex_enter(&lfs_lock); fs->lfs_bfree += sup->su_nsums * lfs_btofsb(fs, fs->lfs_sumsize) + lfs_btofsb(fs, sup->su_ninos * fs->lfs_ibsize); fs->lfs_dmeta -= sup->su_nsums * lfs_btofsb(fs, fs->lfs_sumsize) + lfs_btofsb(fs, sup->su_ninos * fs->lfs_ibsize); if (fs->lfs_dmeta < 0) fs->lfs_dmeta = 0; mutex_exit(&lfs_lock); sup->su_flags &= ~SEGUSE_DIRTY; LFS_WRITESEGENTRY(sup, fs, segnum, bp); LFS_CLEANERINFO(cip, fs, bp); ++cip->clean; --cip->dirty; fs->lfs_nclean = cip->clean; cip->bfree = fs->lfs_bfree; mutex_enter(&lfs_lock); cip->avail = fs->lfs_avail - fs->lfs_ravail - fs->lfs_favail; wakeup(&fs->lfs_avail); mutex_exit(&lfs_lock); (void) LFS_BWRITE_LOG(bp); if (lfs_dostats) ++lfs_stats.segs_reclaimed; return (0); }
/* * Actually mark the segment clean. * Must be called with the segment lock held. */ int lfs_do_segclean(struct lfs *fs, unsigned long segnum) { extern int lfs_dostats; struct buf *bp; CLEANERINFO *cip; SEGUSE *sup; if (lfs_dtosn(fs, lfs_sb_getcurseg(fs)) == segnum) { return (EBUSY); } LFS_SEGENTRY(sup, fs, segnum, bp); if (sup->su_nbytes) { DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:" " %d live bytes\n", segnum, sup->su_nbytes)); brelse(bp, 0); return (EBUSY); } if (sup->su_flags & SEGUSE_ACTIVE) { DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:" " segment is active\n", segnum)); brelse(bp, 0); return (EBUSY); } if (!(sup->su_flags & SEGUSE_DIRTY)) { DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:" " segment is already clean\n", segnum)); brelse(bp, 0); return (EALREADY); } lfs_sb_addavail(fs, lfs_segtod(fs, 1)); if (sup->su_flags & SEGUSE_SUPERBLOCK) lfs_sb_subavail(fs, lfs_btofsb(fs, LFS_SBPAD)); if (lfs_sb_getversion(fs) > 1 && segnum == 0 && lfs_sb_gets0addr(fs) < lfs_btofsb(fs, LFS_LABELPAD)) lfs_sb_subavail(fs, lfs_btofsb(fs, LFS_LABELPAD) - lfs_sb_gets0addr(fs)); mutex_enter(&lfs_lock); lfs_sb_addbfree(fs, sup->su_nsums * lfs_btofsb(fs, lfs_sb_getsumsize(fs)) + lfs_btofsb(fs, sup->su_ninos * lfs_sb_getibsize(fs))); lfs_sb_subdmeta(fs, sup->su_nsums * lfs_btofsb(fs, lfs_sb_getsumsize(fs)) + lfs_btofsb(fs, sup->su_ninos * lfs_sb_getibsize(fs))); if (lfs_sb_getdmeta(fs) < 0) lfs_sb_setdmeta(fs, 0); mutex_exit(&lfs_lock); sup->su_flags &= ~SEGUSE_DIRTY; LFS_WRITESEGENTRY(sup, fs, segnum, bp); LFS_CLEANERINFO(cip, fs, bp); lfs_ci_shiftdirtytoclean(fs, cip, 1); lfs_sb_setnclean(fs, lfs_ci_getclean(fs, cip)); mutex_enter(&lfs_lock); lfs_ci_setbfree(fs, cip, lfs_sb_getbfree(fs)); lfs_ci_setavail(fs, cip, lfs_sb_getavail(fs) - fs->lfs_ravail - fs->lfs_favail); wakeup(&fs->lfs_availsleep); mutex_exit(&lfs_lock); (void) LFS_BWRITE_LOG(bp); if (lfs_dostats) ++lfs_stats.segs_reclaimed; return (0); }