- Speed up pendingblock processing again. Having too much delay between
ffs_blkfree() and the pending adjustment causes all kinds of space related problems.
This commit is contained in:
parent
f2803e61fa
commit
e9b4d8327f
@ -880,6 +880,7 @@ static inline void setup_freeext(struct freeblks *, struct inode *, int, int);
|
|||||||
static inline void setup_freeindir(struct freeblks *, struct inode *, int,
|
static inline void setup_freeindir(struct freeblks *, struct inode *, int,
|
||||||
ufs_lbn_t, int);
|
ufs_lbn_t, int);
|
||||||
static inline struct freeblks *newfreeblks(struct mount *, struct inode *);
|
static inline struct freeblks *newfreeblks(struct mount *, struct inode *);
|
||||||
|
static void freeblks_free(struct ufsmount *, struct freeblks *, int);
|
||||||
static void indir_trunc(struct freework *, ufs2_daddr_t, ufs_lbn_t);
|
static void indir_trunc(struct freework *, ufs2_daddr_t, ufs_lbn_t);
|
||||||
ufs2_daddr_t blkcount(struct fs *, ufs2_daddr_t, off_t);
|
ufs2_daddr_t blkcount(struct fs *, ufs2_daddr_t, off_t);
|
||||||
static int trunc_check_buf(struct buf *, int *, ufs_lbn_t, int, int);
|
static int trunc_check_buf(struct buf *, int *, ufs_lbn_t, int, int);
|
||||||
@ -5751,7 +5752,6 @@ newfreeblks(mp, ip)
|
|||||||
freeblks->fb_modrev = DIP(ip, i_modrev);
|
freeblks->fb_modrev = DIP(ip, i_modrev);
|
||||||
freeblks->fb_devvp = ip->i_devvp;
|
freeblks->fb_devvp = ip->i_devvp;
|
||||||
freeblks->fb_chkcnt = 0;
|
freeblks->fb_chkcnt = 0;
|
||||||
freeblks->fb_freecnt = 0;
|
|
||||||
freeblks->fb_len = 0;
|
freeblks->fb_len = 0;
|
||||||
|
|
||||||
return (freeblks);
|
return (freeblks);
|
||||||
@ -6199,7 +6199,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
|
|||||||
quotaref(vp, freeblks->fb_quota);
|
quotaref(vp, freeblks->fb_quota);
|
||||||
(void) chkdq(ip, -datablocks, NOCRED, 0);
|
(void) chkdq(ip, -datablocks, NOCRED, 0);
|
||||||
#endif
|
#endif
|
||||||
freeblks->fb_chkcnt = datablocks;
|
freeblks->fb_chkcnt = -datablocks;
|
||||||
UFS_LOCK(ip->i_ump);
|
UFS_LOCK(ip->i_ump);
|
||||||
fs->fs_pendingblocks += datablocks;
|
fs->fs_pendingblocks += datablocks;
|
||||||
UFS_UNLOCK(ip->i_ump);
|
UFS_UNLOCK(ip->i_ump);
|
||||||
@ -6429,7 +6429,7 @@ softdep_setup_freeblocks(ip, length, flags)
|
|||||||
quotaref(vp, freeblks->fb_quota);
|
quotaref(vp, freeblks->fb_quota);
|
||||||
(void) chkdq(ip, -datablocks, NOCRED, 0);
|
(void) chkdq(ip, -datablocks, NOCRED, 0);
|
||||||
#endif
|
#endif
|
||||||
freeblks->fb_chkcnt = datablocks;
|
freeblks->fb_chkcnt = -datablocks;
|
||||||
UFS_LOCK(ip->i_ump);
|
UFS_LOCK(ip->i_ump);
|
||||||
fs->fs_pendingblocks += datablocks;
|
fs->fs_pendingblocks += datablocks;
|
||||||
UFS_UNLOCK(ip->i_ump);
|
UFS_UNLOCK(ip->i_ump);
|
||||||
@ -7284,8 +7284,8 @@ freework_freeblock(freework)
|
|||||||
freeblks->fb_cgwait++;
|
freeblks->fb_cgwait++;
|
||||||
WORKLIST_INSERT(&wkhd, &freework->fw_list);
|
WORKLIST_INSERT(&wkhd, &freework->fw_list);
|
||||||
}
|
}
|
||||||
freeblks->fb_freecnt += btodb(bsize);
|
|
||||||
FREE_LOCK(&lk);
|
FREE_LOCK(&lk);
|
||||||
|
freeblks_free(ump, freeblks, btodb(bsize));
|
||||||
ffs_blkfree(ump, fs, freeblks->fb_devvp, freework->fw_blkno, bsize,
|
ffs_blkfree(ump, fs, freeblks->fb_devvp, freework->fw_blkno, bsize,
|
||||||
freeblks->fb_inum, freeblks->fb_vtype, &wkhd);
|
freeblks->fb_inum, freeblks->fb_vtype, &wkhd);
|
||||||
ACQUIRE_LOCK(&lk);
|
ACQUIRE_LOCK(&lk);
|
||||||
@ -7458,6 +7458,33 @@ handle_workitem_freeblocks(freeblks, flags)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle completion of block free via truncate. This allows fs_pending
|
||||||
|
* to track the actual free block count more closely than if we only updated
|
||||||
|
* it at the end. We must be careful to handle cases where the block count
|
||||||
|
* on free was incorrect.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
freeblks_free(ump, freeblks, blocks)
|
||||||
|
struct ufsmount *ump;
|
||||||
|
struct freeblks *freeblks;
|
||||||
|
int blocks;
|
||||||
|
{
|
||||||
|
struct fs *fs;
|
||||||
|
ufs2_daddr_t remain;
|
||||||
|
|
||||||
|
UFS_LOCK(ump);
|
||||||
|
remain = -freeblks->fb_chkcnt;
|
||||||
|
freeblks->fb_chkcnt += blocks;
|
||||||
|
if (remain > 0) {
|
||||||
|
if (remain < blocks)
|
||||||
|
blocks = remain;
|
||||||
|
fs = ump->um_fs;
|
||||||
|
fs->fs_pendingblocks -= blocks;
|
||||||
|
}
|
||||||
|
UFS_UNLOCK(ump);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Once all of the freework workitems are complete we can retire the
|
* Once all of the freework workitems are complete we can retire the
|
||||||
* freeblocks dependency and any journal work awaiting completion. This
|
* freeblocks dependency and any journal work awaiting completion. This
|
||||||
@ -7478,7 +7505,7 @@ handle_complete_freeblocks(freeblks, flags)
|
|||||||
ump = VFSTOUFS(freeblks->fb_list.wk_mp);
|
ump = VFSTOUFS(freeblks->fb_list.wk_mp);
|
||||||
fs = ump->um_fs;
|
fs = ump->um_fs;
|
||||||
flags = LK_EXCLUSIVE | flags;
|
flags = LK_EXCLUSIVE | flags;
|
||||||
spare = freeblks->fb_freecnt - freeblks->fb_chkcnt;
|
spare = freeblks->fb_chkcnt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we did not release the expected number of blocks we may have
|
* If we did not release the expected number of blocks we may have
|
||||||
@ -7501,9 +7528,9 @@ handle_complete_freeblocks(freeblks, flags)
|
|||||||
}
|
}
|
||||||
vput(vp);
|
vput(vp);
|
||||||
}
|
}
|
||||||
if (freeblks->fb_chkcnt) {
|
if (spare < 0) {
|
||||||
UFS_LOCK(ump);
|
UFS_LOCK(ump);
|
||||||
fs->fs_pendingblocks -= freeblks->fb_chkcnt;
|
fs->fs_pendingblocks += spare;
|
||||||
UFS_UNLOCK(ump);
|
UFS_UNLOCK(ump);
|
||||||
}
|
}
|
||||||
#ifdef QUOTA
|
#ifdef QUOTA
|
||||||
@ -7559,7 +7586,7 @@ indir_trunc(freework, dbn, lbn)
|
|||||||
ufs2_daddr_t nb, nnb, *bap2 = 0;
|
ufs2_daddr_t nb, nnb, *bap2 = 0;
|
||||||
ufs_lbn_t lbnadd, nlbn;
|
ufs_lbn_t lbnadd, nlbn;
|
||||||
int i, nblocks, ufs1fmt;
|
int i, nblocks, ufs1fmt;
|
||||||
int fs_pendingblocks;
|
int freedblocks;
|
||||||
int goingaway;
|
int goingaway;
|
||||||
int freedeps;
|
int freedeps;
|
||||||
int needj;
|
int needj;
|
||||||
@ -7701,16 +7728,18 @@ indir_trunc(freework, dbn, lbn)
|
|||||||
bp->b_flags |= B_INVAL | B_NOCACHE;
|
bp->b_flags |= B_INVAL | B_NOCACHE;
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
}
|
}
|
||||||
fs_pendingblocks = 0;
|
freedblocks = 0;
|
||||||
if (level == 0)
|
if (level == 0)
|
||||||
fs_pendingblocks = (nblocks * cnt);
|
freedblocks = (nblocks * cnt);
|
||||||
|
if (needj == 0)
|
||||||
|
freedblocks += nblocks;
|
||||||
|
freeblks_free(ump, freeblks, freedblocks);
|
||||||
/*
|
/*
|
||||||
* If we are journaling set up the ref counts and offset so this
|
* If we are journaling set up the ref counts and offset so this
|
||||||
* indirect can be completed when its children are free.
|
* indirect can be completed when its children are free.
|
||||||
*/
|
*/
|
||||||
if (needj) {
|
if (needj) {
|
||||||
ACQUIRE_LOCK(&lk);
|
ACQUIRE_LOCK(&lk);
|
||||||
freeblks->fb_freecnt += fs_pendingblocks;
|
|
||||||
freework->fw_off = i;
|
freework->fw_off = i;
|
||||||
freework->fw_ref += freedeps;
|
freework->fw_ref += freedeps;
|
||||||
freework->fw_ref -= NINDIR(fs) + 1;
|
freework->fw_ref -= NINDIR(fs) + 1;
|
||||||
@ -7724,12 +7753,10 @@ indir_trunc(freework, dbn, lbn)
|
|||||||
/*
|
/*
|
||||||
* If we're not journaling we can free the indirect now.
|
* If we're not journaling we can free the indirect now.
|
||||||
*/
|
*/
|
||||||
fs_pendingblocks += nblocks;
|
|
||||||
dbn = dbtofsb(fs, dbn);
|
dbn = dbtofsb(fs, dbn);
|
||||||
ffs_blkfree(ump, fs, freeblks->fb_devvp, dbn, fs->fs_bsize,
|
ffs_blkfree(ump, fs, freeblks->fb_devvp, dbn, fs->fs_bsize,
|
||||||
freeblks->fb_inum, freeblks->fb_vtype, NULL);
|
freeblks->fb_inum, freeblks->fb_vtype, NULL);
|
||||||
/* Non SUJ softdep does single-threaded truncations. */
|
/* Non SUJ softdep does single-threaded truncations. */
|
||||||
freeblks->fb_freecnt += fs_pendingblocks;
|
|
||||||
if (freework->fw_blkno == dbn) {
|
if (freework->fw_blkno == dbn) {
|
||||||
freework->fw_state |= ALLCOMPLETE;
|
freework->fw_state |= ALLCOMPLETE;
|
||||||
ACQUIRE_LOCK(&lk);
|
ACQUIRE_LOCK(&lk);
|
||||||
|
@ -536,8 +536,7 @@ struct freeblks {
|
|||||||
#endif
|
#endif
|
||||||
uint64_t fb_modrev; /* Inode revision at start of trunc. */
|
uint64_t fb_modrev; /* Inode revision at start of trunc. */
|
||||||
off_t fb_len; /* Length we're truncating to. */
|
off_t fb_len; /* Length we're truncating to. */
|
||||||
ufs2_daddr_t fb_chkcnt; /* Expected blks released. */
|
ufs2_daddr_t fb_chkcnt; /* Blocks released. */
|
||||||
ufs2_daddr_t fb_freecnt; /* Actual blocks released. */
|
|
||||||
ino_t fb_inum; /* inode owner of blocks */
|
ino_t fb_inum; /* inode owner of blocks */
|
||||||
enum vtype fb_vtype; /* inode owner's file type */
|
enum vtype fb_vtype; /* inode owner's file type */
|
||||||
uid_t fb_uid; /* uid of previous owner of blocks */
|
uid_t fb_uid; /* uid of previous owner of blocks */
|
||||||
|
Loading…
Reference in New Issue
Block a user