From 6d52186e53b4cb45089156a1e4d61f5805032da7 Mon Sep 17 00:00:00 2001 From: mckusick Date: Thu, 26 May 2011 23:56:58 +0000 Subject: The check for whether a block is going to be claimed by a snapshot needs to happen before we notify the underlying layer that it is being freed. --- sys/ufs/ffs/ffs_alloc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'sys/ufs/ffs/ffs_alloc.c') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index e60514d..9b5425b 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -1873,10 +1873,7 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd) /* devvp is a normal disk device */ dev = devvp->v_rdev; cgblkno = fsbtodb(fs, cgtod(fs, cg)); - ASSERT_VOP_LOCKED(devvp, "ffs_blkfree"); - if ((devvp->v_vflag & VV_COPYONWRITE) && - ffs_snapblkfree(fs, devvp, bno, size, inum)) - return; + ASSERT_VOP_LOCKED(devvp, "ffs_blkfree_cg"); } #ifdef INVARIANTS if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 || @@ -2030,6 +2027,17 @@ ffs_blkfree(ump, fs, devvp, bno, size, inum, dephd) struct bio *bip; struct ffs_blkfree_trim_params *tp; + /* + * Check to see if a snapshot wants to claim the block. + * Check that devvp is a normal disk device, not a snapshot, + * it has a snapshot(s) associated with it, and one of the + * snapshots wants to claim the block. + */ + if (devvp->v_type != VREG && + (devvp->v_vflag & VV_COPYONWRITE) && + ffs_snapblkfree(fs, devvp, bno, size, inum)) { + return; + } if (!ump->um_candelete) { ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd); return; -- cgit v1.1 From 75b483b1f1722f50c988b8968eff3b6c1c77554c Mon Sep 17 00:00:00 2001 From: mckusick Date: Sat, 28 May 2011 15:07:29 +0000 Subject: Due to a lag in updating the fs_pendinginodes count, we cannot depend on it to decide whether we should try to reclaim inodes when we run short. Discovered by: Peter Holm --- sys/ufs/ffs/ffs_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys/ufs/ffs/ffs_alloc.c') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 9b5425b..5b8f3c8 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -1022,7 +1022,7 @@ dup_alloc: (*vpp)->v_op = &ffs_vnodeops1; return (0); noinodes: - if (fs->fs_pendinginodes > 0 && reclaimed == 0) { + if (reclaimed == 0) { reclaimed = 1; softdep_request_cleanup(fs, pvp, cred, FLUSH_INODES_WAIT); goto retry; -- cgit v1.1 From 6e1743e29a10cf5d4dd61f59fa24c367a2e8087b Mon Sep 17 00:00:00 2001 From: mckusick Date: Sun, 5 Jun 2011 22:36:30 +0000 Subject: Grammer fix in comment. Eliminate one (of several) possible conflicting buffer locks when trying to reclaim blocks. Rest of fix to be incorporated as part of SUJ update by jeff. Pointed out by: Kostik Belousov --- sys/ufs/ffs/ffs_alloc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sys/ufs/ffs/ffs_alloc.c') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 5b8f3c8..7f5d1b4 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -420,13 +420,13 @@ nospace: */ if (reclaimed == 0) { reclaimed = 1; - softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); UFS_UNLOCK(ump); if (bp) { brelse(bp); bp = NULL; } UFS_LOCK(ump); + softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); goto retry; } UFS_UNLOCK(ump); @@ -2356,8 +2356,8 @@ ffs_fserr(fs, inum, cp) * specified inode by the specified amount. Under normal * operation the count should always go down. Decrementing * the count to zero will cause the inode to be freed. - * adjblkcnt(inode, amt) - adjust the number of blocks used to - * by the specifed amount. + * adjblkcnt(inode, amt) - adjust the number of blocks used by the + * inode by the specified amount. * adjndir, adjbfree, adjifree, adjffree, adjnumclusters(amt) - * adjust the superblock summary. * freedirs(inode, count) - directory inodes [inode..inode + count - 1] -- cgit v1.1 From 6ba8b7f04c93a101c89962061bbd3307c0c54379 Mon Sep 17 00:00:00 2001 From: jeff Date: Fri, 10 Jun 2011 22:48:35 +0000 Subject: Implement fully asynchronous partial truncation with softupdates journaling to resolve errors which can cause corruption on recovery with the old synchronous mechanism. - Append partial truncation freework structures to indirdeps while truncation is proceeding. These prevent new block pointers from becoming valid until truncation completes and serialize truncations. - On completion of a partial truncate journal work waits for zeroed pointers to hit indirects. - softdep_journal_freeblocks() handles last frag allocation and last block zeroing. - vtruncbuf/ffs_page_remove moved into softdep_*_freeblocks() so it is only implemented in one place. - Block allocation failure handling moved up one level so it does not proceed with buf locks held. This permits us to do more extensive reclaims when filesystem space is exhausted. - softdep_sync_metadata() is broken into two parts, the first executes once at the start of ffs_syncvnode() and flushes truncations and inode dependencies. The second is called on each locked buf. This eliminates excessive looping and rollbacks. - Improve the mechanism in process_worklist_item() that handles acquiring vnode locks for handle_workitem_remove() so that it works more generally and does not loop excessively over the same worklist items on each call. - Don't corrupt directories by zeroing the tail in fsck. This is only done for regular files. - Push a fsync complete record for files that need it so the checker knows a truncation in the journal is no longer valid. Discussed with: mckusick, kib (ffs_pages_remove and ffs_truncate parts) Tested by: pho --- sys/ufs/ffs/ffs_alloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sys/ufs/ffs/ffs_alloc.c') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 7f5d1b4..685b9e1 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -217,7 +217,7 @@ nospace: (void) chkdq(ip, -btodb(size), cred, FORCE); UFS_LOCK(ump); #endif - if (reclaimed == 0) { + if (reclaimed == 0 && (flags & IO_BUFLOCKED) == 0) { reclaimed = 1; softdep_request_cleanup(fs, ITOV(ip), cred, FLUSH_BLOCKS_WAIT); goto retry; @@ -418,7 +418,7 @@ nospace: /* * no space available */ - if (reclaimed == 0) { + if (reclaimed == 0 && (flags & IO_BUFLOCKED) == 0) { reclaimed = 1; UFS_UNLOCK(ump); if (bp) { -- cgit v1.1 From 5f2600c6a978923a3904716ce73814baca63fd0f Mon Sep 17 00:00:00 2001 From: mckusick Date: Sun, 12 Jun 2011 19:27:05 +0000 Subject: Update to soft updates journaling to properly track freed blocks that get claimed by snapshots. Submitted by: Jeff Roberson Tested by: Peter Holm --- sys/ufs/ffs/ffs_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys/ufs/ffs/ffs_alloc.c') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 685b9e1..de34bb8 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -2035,7 +2035,7 @@ ffs_blkfree(ump, fs, devvp, bno, size, inum, dephd) */ if (devvp->v_type != VREG && (devvp->v_vflag & VV_COPYONWRITE) && - ffs_snapblkfree(fs, devvp, bno, size, inum)) { + ffs_snapblkfree(fs, devvp, bno, size, inum, dephd)) { return; } if (!ump->um_candelete) { -- cgit v1.1 From f433c75fa7942f76c35a192c39eb88870863892f Mon Sep 17 00:00:00 2001 From: mckusick Date: Wed, 15 Jun 2011 18:05:08 +0000 Subject: With the restructuring of the block reclaimation code, the notification messages for a filesystem being out of space need to be moved so that they do not print out until after a failed cleanup attempt. Suggested by: Jeff Roberson --- sys/ufs/ffs/ffs_alloc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sys/ufs/ffs/ffs_alloc.c') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index de34bb8..f1db84d 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -116,7 +116,6 @@ static ufs2_daddr_t ffs_clusteralloc(struct inode *, u_int, ufs2_daddr_t, int, static ino_t ffs_dirpref(struct inode *); static ufs2_daddr_t ffs_fragextend(struct inode *, u_int, ufs2_daddr_t, int, int); -static void ffs_fserr(struct fs *, ino_t, char *); static ufs2_daddr_t ffs_hashalloc (struct inode *, u_int, ufs2_daddr_t, int, int, allocfcn_t *); static ufs2_daddr_t ffs_nodealloccg(struct inode *, u_int, ufs2_daddr_t, int, @@ -223,7 +222,7 @@ nospace: goto retry; } UFS_UNLOCK(ump); - if (ppsratecheck(&lastfail, &curfail, 1)) { + if (reclaimed > 0 && ppsratecheck(&lastfail, &curfail, 1)) { ffs_fserr(fs, ip->i_number, "filesystem full"); uprintf("\n%s: write failed, filesystem is full\n", fs->fs_fsmnt); @@ -432,7 +431,7 @@ nospace: UFS_UNLOCK(ump); if (bp) brelse(bp); - if (ppsratecheck(&lastfail, &curfail, 1)) { + if (reclaimed > 0 && ppsratecheck(&lastfail, &curfail, 1)) { ffs_fserr(fs, ip->i_number, "filesystem full"); uprintf("\n%s: write failed, filesystem is full\n", fs->fs_fsmnt); @@ -2335,7 +2334,7 @@ ffs_mapsearch(fs, cgp, bpref, allocsiz) * The form of the error message is: * fs: error message */ -static void +void ffs_fserr(fs, inum, cp) struct fs *fs; ino_t inum; -- cgit v1.1 From ef6ee3faed283f9910e11c5d56af10d587a6803a Mon Sep 17 00:00:00 2001 From: mckusick Date: Wed, 15 Jun 2011 23:19:09 +0000 Subject: Ensure that filesystem metadata contained within persistent snapshots is always kept consistent. Suggested by: Jeff Roberson --- sys/ufs/ffs/ffs_alloc.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'sys/ufs/ffs/ffs_alloc.c') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index f1db84d..7d7866c 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -390,7 +390,7 @@ retry: bp->b_blkno = fsbtodb(fs, bno); if (!DOINGSOFTDEP(vp)) ffs_blkfree(ump, fs, ip->i_devvp, bprev, (long)osize, - ip->i_number, NULL); + ip->i_number, vp->v_type, NULL); delta = btodb(nsize - osize); DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta); if (flags & IO_EXT) @@ -670,7 +670,7 @@ ffs_reallocblks_ufs1(ap) if (!DOINGSOFTDEP(vp)) ffs_blkfree(ump, fs, ip->i_devvp, dbtofsb(fs, buflist->bs_children[i]->b_blkno), - fs->fs_bsize, ip->i_number, NULL); + fs->fs_bsize, ip->i_number, vp->v_type, NULL); buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); #ifdef INVARIANTS if (!ffs_checkblk(ip, @@ -878,7 +878,7 @@ ffs_reallocblks_ufs2(ap) if (!DOINGSOFTDEP(vp)) ffs_blkfree(ump, fs, ip->i_devvp, dbtofsb(fs, buflist->bs_children[i]->b_blkno), - fs->fs_bsize, ip->i_number, NULL); + fs->fs_bsize, ip->i_number, vp->v_type, NULL); buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); #ifdef INVARIANTS if (!ffs_checkblk(ip, @@ -1880,7 +1880,7 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd) printf("dev=%s, bno = %jd, bsize = %ld, size = %ld, fs = %s\n", devtoname(dev), (intmax_t)bno, (long)fs->fs_bsize, size, fs->fs_fsmnt); - panic("ffs_blkfree: bad size"); + panic("ffs_blkfree_cg: bad size"); } #endif if ((u_int)bno >= fs->fs_size) { @@ -1914,7 +1914,7 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd) } printf("dev = %s, block = %jd, fs = %s\n", devtoname(dev), (intmax_t)bno, fs->fs_fsmnt); - panic("ffs_blkfree: freeing free block"); + panic("ffs_blkfree_cg: freeing free block"); } ffs_setblock(fs, blksfree, fragno); ffs_clusteracct(fs, cgp, fragno, 1); @@ -1937,7 +1937,7 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd) printf("dev = %s, block = %jd, fs = %s\n", devtoname(dev), (intmax_t)(bno + i), fs->fs_fsmnt); - panic("ffs_blkfree: freeing free frag"); + panic("ffs_blkfree_cg: freeing free frag"); } setbit(blksfree, cgbno + i); } @@ -2013,13 +2013,14 @@ ffs_blkfree_trim_completed(bip) } void -ffs_blkfree(ump, fs, devvp, bno, size, inum, dephd) +ffs_blkfree(ump, fs, devvp, bno, size, inum, vtype, dephd) struct ufsmount *ump; struct fs *fs; struct vnode *devvp; ufs2_daddr_t bno; long size; ino_t inum; + enum vtype vtype; struct workhead *dephd; { struct mount *mp; @@ -2034,7 +2035,7 @@ ffs_blkfree(ump, fs, devvp, bno, size, inum, dephd) */ if (devvp->v_type != VREG && (devvp->v_vflag & VV_COPYONWRITE) && - ffs_snapblkfree(fs, devvp, bno, size, inum, dephd)) { + ffs_snapblkfree(fs, devvp, bno, size, inum, vtype, dephd)) { return; } if (!ump->um_candelete) { @@ -2571,7 +2572,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS) if (blksize > blkcnt) blksize = blkcnt; ffs_blkfree(ump, fs, ump->um_devvp, blkno, - blksize * fs->fs_fsize, ROOTINO, NULL); + blksize * fs->fs_fsize, ROOTINO, VDIR, NULL); blkno += blksize; blkcnt -= blksize; blksize = fs->fs_frag; -- cgit v1.1 From 045528c230abc49a8b1b1393bc45366a302fa5bf Mon Sep 17 00:00:00 2001 From: jeff Date: Mon, 20 Jun 2011 03:25:09 +0000 Subject: - Fix directory count rollbacks by passing the mode to the journal dep earlier. - Add rollback/forward code for frag and cluster accounting. - Handle the FREEDEP case in softdep_sync_buf(). (submitted by pho) --- sys/ufs/ffs/ffs_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys/ufs/ffs/ffs_alloc.c') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 7d7866c..6d27ace 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -1829,7 +1829,7 @@ gotit: } UFS_UNLOCK(ump); if (DOINGSOFTDEP(ITOV(ip))) - softdep_setup_inomapdep(bp, ip, cg * fs->fs_ipg + ipref); + softdep_setup_inomapdep(bp, ip, cg * fs->fs_ipg + ipref, mode); bdwrite(bp); if (ibp != NULL) bawrite(ibp); -- cgit v1.1