Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 Jul 2010 07:11:05 +0000 (UTC)
From:      Jeff Roberson <jeff@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r209717 - in head/sys/ufs: ffs ufs
Message-ID:  <201007060711.o667B5t3097539@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jeff
Date: Tue Jul  6 07:11:04 2010
New Revision: 209717
URL: http://svn.freebsd.org/changeset/base/209717

Log:
   - Handle the truncation of an inode with an effective link count of 0 in
     the context of the process that reduced the effective count.  Previously
     all truncation as a result of unlink happened in the softdep flush
     thread.  This had the effect of being impossible to rate limit properly
     with the journal code.  Now the process issuing unlinks is suspended
     when the journal files.  This has a side-effect of improving rm
     performance by allowing more concurrent work.
   - Handle two cases in inactive, one for effnlink == 0 and another when
     nlink finally reaches 0.
   - Eliminate the SPACECOUNTED related code since the truncation is no
     longer delayed.
  
  Discussed with:	mckusick

Modified:
  head/sys/ufs/ffs/ffs_alloc.c
  head/sys/ufs/ffs/ffs_inode.c
  head/sys/ufs/ffs/ffs_softdep.c
  head/sys/ufs/ffs/ffs_vnops.c
  head/sys/ufs/ffs/softdep.h
  head/sys/ufs/ufs/inode.h
  head/sys/ufs/ufs/ufs_inode.c
  head/sys/ufs/ufs/ufs_lookup.c
  head/sys/ufs/ufs/ufs_vnops.c

Modified: head/sys/ufs/ffs/ffs_alloc.c
==============================================================================
--- head/sys/ufs/ffs/ffs_alloc.c	Tue Jul  6 07:07:29 2010	(r209716)
+++ head/sys/ufs/ffs/ffs_alloc.c	Tue Jul  6 07:11:04 2010	(r209717)
@@ -191,11 +191,6 @@ retry:
 	bno = ffs_hashalloc(ip, cg, bpref, size, size, ffs_alloccg);
 	if (bno > 0) {
 		delta = btodb(size);
-		if (ip->i_flag & IN_SPACECOUNTED) {
-			UFS_LOCK(ump);
-			fs->fs_pendingblocks += delta;
-			UFS_UNLOCK(ump);
-		}
 		DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta);
 		if (flags & IO_EXT)
 			ip->i_flag |= IN_CHANGE;
@@ -321,11 +316,6 @@ retry:
 		if (bp->b_blkno != fsbtodb(fs, bno))
 			panic("ffs_realloccg: bad blockno");
 		delta = btodb(nsize - osize);
-		if (ip->i_flag & IN_SPACECOUNTED) {
-			UFS_LOCK(ump);
-			fs->fs_pendingblocks += delta;
-			UFS_UNLOCK(ump);
-		}
 		DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta);
 		if (flags & IO_EXT)
 			ip->i_flag |= IN_CHANGE;
@@ -394,11 +384,6 @@ retry:
 			ffs_blkfree(ump, fs, ip->i_devvp, bprev, (long)osize,
 			    ip->i_number, NULL);
 		delta = btodb(nsize - osize);
-		if (ip->i_flag & IN_SPACECOUNTED) {
-			UFS_LOCK(ump);
-			fs->fs_pendingblocks += delta;
-			UFS_UNLOCK(ump);
-		}
 		DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta);
 		if (flags & IO_EXT)
 			ip->i_flag |= IN_CHANGE;
@@ -2422,11 +2407,6 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
 		if ((error = ffs_vget(mp, (ino_t)cmd.value, LK_EXCLUSIVE, &vp)))
 			break;
 		ip = VTOI(vp);
-		if (ip->i_flag & IN_SPACECOUNTED) {
-			UFS_LOCK(ump);
-			fs->fs_pendingblocks += cmd.size;
-			UFS_UNLOCK(ump);
-		}
 		DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + cmd.size);
 		ip->i_flag |= IN_CHANGE;
 		vput(vp);

Modified: head/sys/ufs/ffs/ffs_inode.c
==============================================================================
--- head/sys/ufs/ffs/ffs_inode.c	Tue Jul  6 07:07:29 2010	(r209716)
+++ head/sys/ufs/ffs/ffs_inode.c	Tue Jul  6 07:11:04 2010	(r209717)
@@ -180,6 +180,8 @@ ffs_truncate(vp, length, flags, cred, td
 	 */
 	if ((flags & (IO_EXT | IO_NORMAL)) == 0)
 		flags |= IO_NORMAL;
+	if (!DOINGSOFTDEP(vp) && !DOINGASYNC(vp))
+		flags |= IO_SYNC;
 	/*
 	 * If we are truncating the extended-attributes, and cannot
 	 * do it with soft updates, then do it slowly here. If we are
@@ -310,10 +312,6 @@ ffs_truncate(vp, length, flags, cred, td
 			 */
 			if ((error = ffs_syncvnode(vp, MNT_WAIT)) != 0)
 				goto out;
-			UFS_LOCK(ump);
-			if (ip->i_flag & IN_SPACECOUNTED)
-				fs->fs_pendingblocks -= datablocks;
-			UFS_UNLOCK(ump);
 			/*
 			 * We have to journal the truncation before we change
 			 * any blocks so we don't leave the file partially

Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c	Tue Jul  6 07:07:29 2010	(r209716)
+++ head/sys/ufs/ffs/ffs_softdep.c	Tue Jul  6 07:11:04 2010	(r209717)
@@ -5183,16 +5183,9 @@ softdep_setup_freeblocks(ip, length, fla
 				    fs->fs_frag, needj);
 			lbn += tmpval;
 		}
-		/*
-		 * If the file was removed, then the space being freed was
-		 * accounted for then (see softdep_releasefile()). If the
-		 * file is merely being truncated, then we account for it now.
-		 */
-		if ((ip->i_flag & IN_SPACECOUNTED) == 0) {
-			UFS_LOCK(ip->i_ump);
-			fs->fs_pendingblocks += datablocks;
-			UFS_UNLOCK(ip->i_ump);
-		}
+		UFS_LOCK(ip->i_ump);
+		fs->fs_pendingblocks += datablocks;
+		UFS_UNLOCK(ip->i_ump);
 	}
 	if ((flags & IO_EXT) != 0) {
 		oldextsize = ip->i_din2->di_extsize;
@@ -5674,11 +5667,9 @@ softdep_freefile(pvp, ino, mode)
 	freefile->fx_oldinum = ino;
 	freefile->fx_devvp = ip->i_devvp;
 	LIST_INIT(&freefile->fx_jwork);
-	if ((ip->i_flag & IN_SPACECOUNTED) == 0) {
-		UFS_LOCK(ip->i_ump);
-		ip->i_fs->fs_pendinginodes += 1;
-		UFS_UNLOCK(ip->i_ump);
-	}
+	UFS_LOCK(ip->i_ump);
+	ip->i_fs->fs_pendinginodes += 1;
+	UFS_UNLOCK(ip->i_ump);
 
 	/*
 	 * If the inodedep does not exist, then the zero'ed inode has
@@ -7379,55 +7370,6 @@ softdep_change_linkcnt(ip)
 }
 
 /*
- * Called when the effective link count and the reference count
- * on an inode drops to zero. At this point there are no names
- * referencing the file in the filesystem and no active file
- * references. The space associated with the file will be freed
- * as soon as the necessary soft dependencies are cleared.
- */
-void
-softdep_releasefile(ip)
-	struct inode *ip;	/* inode with the zero effective link count */
-{
-	struct inodedep *inodedep;
-	struct fs *fs;
-	int extblocks;
-
-	if (ip->i_effnlink > 0)
-		panic("softdep_releasefile: file still referenced");
-	/*
-	 * We may be called several times as the on-disk link count
-	 * drops to zero. We only want to account for the space once.
-	 */
-	if (ip->i_flag & IN_SPACECOUNTED)
-		return;
-	/*
-	 * We have to deactivate a snapshot otherwise copyonwrites may
-	 * add blocks and the cleanup may remove blocks after we have
-	 * tried to account for them.
-	 */
-	if ((ip->i_flags & SF_SNAPSHOT) != 0)
-		ffs_snapremove(ITOV(ip));
-	/*
-	 * If we are tracking an nlinkdelta, we have to also remember
-	 * whether we accounted for the freed space yet.
-	 */
-	ACQUIRE_LOCK(&lk);
-	if ((inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, 0, &inodedep)))
-		inodedep->id_state |= SPACECOUNTED;
-	FREE_LOCK(&lk);
-	fs = ip->i_fs;
-	extblocks = 0;
-	if (fs->fs_magic == FS_UFS2_MAGIC)
-		extblocks = btodb(fragroundup(fs, ip->i_din2->di_extsize));
-	UFS_LOCK(ip->i_ump);
-	ip->i_fs->fs_pendingblocks += DIP(ip, i_blocks) - extblocks;
-	ip->i_fs->fs_pendinginodes += 1;
-	UFS_UNLOCK(ip->i_ump);
-	ip->i_flag |= IN_SPACECOUNTED;
-}
-
-/*
  * Attach a sbdep dependency to the superblock buf so that we can keep
  * track of the head of the linked list of referenced but unlinked inodes.
  */
@@ -7735,7 +7677,6 @@ handle_workitem_remove(dirrem, xp)
 	struct dirrem *dirrem;
 	struct vnode *xp;
 {
-	struct thread *td = curthread;
 	struct inodedep *inodedep;
 	struct workhead dotdotwk;
 	struct worklist *wk;
@@ -7808,9 +7749,8 @@ handle_workitem_remove(dirrem, xp)
 	/*
 	 * Directory deletion. Decrement reference count for both the
 	 * just deleted parent directory entry and the reference for ".".
-	 * Next truncate the directory to length zero. When the
-	 * truncation completes, arrange to have the reference count on
-	 * the parent decremented to account for the loss of "..".
+	 * Arrange to have the reference count on the parent decremented
+	 * to account for the loss of "..".
 	 */
 	ip->i_nlink -= 2;
 	DIP_SET(ip, i_nlink, ip->i_nlink);
@@ -7820,10 +7760,6 @@ handle_workitem_remove(dirrem, xp)
 	if (ip->i_nlink == 0)
 		unlinked_inodedep(mp, inodedep);
 	inodedep->id_nlinkdelta = ip->i_nlink - ip->i_effnlink;
-	FREE_LOCK(&lk);
-	if ((error = ffs_truncate(vp, (off_t)0, 0, td->td_ucred, td)) != 0)
-		softdep_error("handle_workitem_remove: truncate", error);
-	ACQUIRE_LOCK(&lk);
 	/*
 	 * Rename a directory to a new parent. Since, we are both deleting
 	 * and creating a new directory entry, the link count on the new
@@ -9899,8 +9835,6 @@ softdep_load_inodeblock(ip)
 		return;
 	}
 	ip->i_effnlink -= inodedep->id_nlinkdelta;
-	if (inodedep->id_state & SPACECOUNTED)
-		ip->i_flag |= IN_SPACECOUNTED;
 	FREE_LOCK(&lk);
 }
 

Modified: head/sys/ufs/ffs/ffs_vnops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vnops.c	Tue Jul  6 07:07:29 2010	(r209716)
+++ head/sys/ufs/ffs/ffs_vnops.c	Tue Jul  6 07:11:04 2010	(r209717)
@@ -1036,9 +1036,6 @@ ffs_extwrite(struct vnode *vp, struct ui
 	fs = ip->i_fs;
 	dp = ip->i_din2;
 
-	KASSERT(!(ip->i_flag & IN_SPACECOUNTED), ("inode %u: inode is dead",
-	    ip->i_number));
-
 #ifdef INVARIANTS
 	if (uio->uio_rw != UIO_WRITE || fs->fs_magic != FS_UFS2_MAGIC)
 		panic("ffs_extwrite: mode");

Modified: head/sys/ufs/ffs/softdep.h
==============================================================================
--- head/sys/ufs/ffs/softdep.h	Tue Jul  6 07:07:29 2010	(r209716)
+++ head/sys/ufs/ffs/softdep.h	Tue Jul  6 07:11:04 2010	(r209717)
@@ -118,7 +118,7 @@
 #define	DIRCHG		0x000080 /* diradd, dirrem only */
 #define	GOINGAWAY	0x000100 /* indirdep, jremref only */
 #define	IOSTARTED	0x000200 /* inodedep, pagedep, bmsafemap only */
-#define	SPACECOUNTED	0x000400 /* inodedep only */
+#define	UNUSED400	0x000400 /* currently available. */
 #define	NEWBLOCK	0x000800 /* pagedep, jaddref only */
 #define	INPROGRESS	0x001000 /* dirrem, freeblks, freefrag, freefile only */
 #define	UFS1FMT		0x002000 /* indirdep only */

Modified: head/sys/ufs/ufs/inode.h
==============================================================================
--- head/sys/ufs/ufs/inode.h	Tue Jul  6 07:07:29 2010	(r209716)
+++ head/sys/ufs/ufs/inode.h	Tue Jul  6 07:11:04 2010	(r209717)
@@ -122,7 +122,6 @@ struct inode {
 #define	IN_MODIFIED	0x0008		/* Inode has been modified. */
 #define	IN_NEEDSYNC	0x0010		/* Inode requires fsync. */
 #define	IN_LAZYMOD	0x0040		/* Modified, but don't write yet. */
-#define	IN_SPACECOUNTED	0x0080		/* Blocks to be freed in free count. */
 #define	IN_LAZYACCESS	0x0100		/* Process IN_ACCESS after the
 					   suspension finished */
 #define	IN_EA_LOCKED	0x0200

Modified: head/sys/ufs/ufs/ufs_inode.c
==============================================================================
--- head/sys/ufs/ufs/ufs_inode.c	Tue Jul  6 07:07:29 2010	(r209716)
+++ head/sys/ufs/ufs/ufs_inode.c	Tue Jul  6 07:11:04 2010	(r209717)
@@ -76,6 +76,7 @@ ufs_inactive(ap)
 	struct thread *td = ap->a_td;
 	mode_t mode;
 	int error = 0;
+	int isize;
 	struct mount *mp;
 
 	mp = NULL;
@@ -118,18 +119,21 @@ ufs_inactive(ap)
 			}
 		}
 	}
-	if (ip->i_effnlink == 0 && DOINGSOFTDEP(vp))
-		softdep_releasefile(ip);
-	if (ip->i_nlink <= 0 && !UFS_RDONLY(ip)) {
+	isize = ip->i_size;
+	if (ip->i_ump->um_fstype == UFS2)
+		isize += ip->i_din2->di_extsize;
+	if (ip->i_effnlink <= 0 && isize && !UFS_RDONLY(ip)) {
 #ifdef QUOTA
 		if (!getinoquota(ip))
 			(void)chkiq(ip, -1, NOCRED, FORCE);
 #endif
+		error = UFS_TRUNCATE(vp, (off_t)0, IO_EXT | IO_NORMAL,
+		    NOCRED, td);
+	}
+	if (ip->i_nlink <= 0 && ip->i_mode && !UFS_RDONLY(ip)) {
 #ifdef UFS_EXTATTR
 		ufs_extattr_vnode_inactive(vp, td);
 #endif
-		error = UFS_TRUNCATE(vp, (off_t)0, IO_EXT | IO_NORMAL,
-		    NOCRED, td);
 		/*
 		 * Setting the mode to zero needs to wait for the inode
 		 * to be written just as does a change to the link count.

Modified: head/sys/ufs/ufs/ufs_lookup.c
==============================================================================
--- head/sys/ufs/ufs/ufs_lookup.c	Tue Jul  6 07:07:29 2010	(r209716)
+++ head/sys/ufs/ufs/ufs_lookup.c	Tue Jul  6 07:11:04 2010	(r209717)
@@ -248,6 +248,8 @@ ufs_lookup_ino(struct vnode *vdp, struct
 		*vpp = NULL;
 
 	dp = VTOI(vdp);
+	if (dp->i_effnlink == 0)
+		return (ENOENT);
 
 	/*
 	 * Create a vm object if vmiodirenable is enabled.

Modified: head/sys/ufs/ufs/ufs_vnops.c
==============================================================================
--- head/sys/ufs/ufs/ufs_vnops.c	Tue Jul  6 07:07:29 2010	(r209716)
+++ head/sys/ufs/ufs/ufs_vnops.c	Tue Jul  6 07:11:04 2010	(r209717)
@@ -1119,7 +1119,7 @@ ufs_rename(ap)
 	struct direct newdir;
 	off_t endoff;
 	int doingdirectory, newparent;
-	int error = 0, ioflag;
+	int error = 0;
 	struct mount *mp;
 	ino_t ino;
 
@@ -1443,8 +1443,8 @@ relock:
 		}
 		if (doingdirectory && !DOINGSOFTDEP(tvp)) {
 			/*
-			 * Truncate inode. The only stuff left in the directory
-			 * is "." and "..". The "." reference is inconsequential
+			 * The only stuff left in the directory is "."
+			 * and "..". The "." reference is inconsequential
 			 * since we are quashing it. We have removed the "."
 			 * reference and the reference in the parent directory,
 			 * but there may be other hard links. The soft
@@ -1461,13 +1461,6 @@ relock:
 			tip->i_nlink--;
 			DIP_SET(tip, i_nlink, tip->i_nlink);
 			tip->i_flag |= IN_CHANGE;
-			ioflag = IO_NORMAL;
-			if (!DOINGASYNC(tvp))
-				ioflag |= IO_SYNC;
-			/* Don't go to bad here as the new link exists. */
-			if ((error = UFS_TRUNCATE(tvp, (off_t)0, ioflag,
-			    tcnp->cn_cred, tcnp->cn_thread)) != 0)
-				goto unlockout;
 		}
 	}
 
@@ -1993,7 +1986,7 @@ ufs_rmdir(ap)
 	struct vnode *dvp = ap->a_dvp;
 	struct componentname *cnp = ap->a_cnp;
 	struct inode *ip, *dp;
-	int error, ioflag;
+	int error;
 
 	ip = VTOI(vp);
 	dp = VTOI(dvp);
@@ -2049,10 +2042,10 @@ ufs_rmdir(ap)
 	}
 	cache_purge(dvp);
 	/*
-	 * Truncate inode. The only stuff left in the directory is "." and
-	 * "..". The "." reference is inconsequential since we are quashing
-	 * it. The soft dependency code will arrange to do these operations
-	 * after the parent directory entry has been deleted on disk, so
+	 * The only stuff left in the directory is "." and "..". The "."
+	 * reference is inconsequential since we are quashing it. The soft
+	 * dependency code will arrange to do these operations after
+	 * the parent directory entry has been deleted on disk, so
 	 * when running with that code we avoid doing them now.
 	 */
 	if (!DOINGSOFTDEP(vp)) {
@@ -2062,11 +2055,6 @@ ufs_rmdir(ap)
 		ip->i_nlink--;
 		DIP_SET(ip, i_nlink, ip->i_nlink);
 		ip->i_flag |= IN_CHANGE;
-		ioflag = IO_NORMAL;
-		if (!DOINGASYNC(vp))
-			ioflag |= IO_SYNC;
-		error = UFS_TRUNCATE(vp, (off_t)0, ioflag, cnp->cn_cred,
-		    cnp->cn_thread);
 	}
 	cache_purge(vp);
 #ifdef UFS_DIRHASH
@@ -2137,6 +2125,7 @@ ufs_readdir(ap)
 	} */ *ap;
 {
 	struct uio *uio = ap->a_uio;
+	struct inode *ip;
 	int error;
 	size_t count, lost;
 	off_t off;
@@ -2147,6 +2136,9 @@ ufs_readdir(ap)
 		 * the cookies to determine where in the block to start.
 		 */
 		uio->uio_offset &= ~(DIRBLKSIZ - 1);
+	ip = VTOI(ap->a_vp);
+	if (ip->i_effnlink == 0)
+		return (0);
 	off = uio->uio_offset;
 	count = uio->uio_resid;
 	/* Make sure we don't return partial entries. */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007060711.o667B5t3097539>