Module Name:    src
Committed By:   hannken
Date:           Sun May 31 15:45:18 UTC 2015

Modified Files:
        src/sys/ufs/lfs: lfs_extern.h lfs_syscalls.c

Log Message:
Make lfs_fastvget() private to lfs_syscalls.c, change it to take the
BLOCK_INFO and vnode lock type instead of the inode disk address and
return the vnode locked.

Change lfs_markv() and lfs_bmapv() to work on locked vnodes.


To generate a diff of this commit:
cvs rdiff -u -r1.103 -r1.104 src/sys/ufs/lfs/lfs_extern.h
cvs rdiff -u -r1.158 -r1.159 src/sys/ufs/lfs/lfs_syscalls.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/ufs/lfs/lfs_extern.h
diff -u src/sys/ufs/lfs/lfs_extern.h:1.103 src/sys/ufs/lfs/lfs_extern.h:1.104
--- src/sys/ufs/lfs/lfs_extern.h:1.103	Sun May 31 15:44:31 2015
+++ src/sys/ufs/lfs/lfs_extern.h	Sun May 31 15:45:18 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_extern.h,v 1.103 2015/05/31 15:44:31 hannken Exp $	*/
+/*	$NetBSD: lfs_extern.h,v 1.104 2015/05/31 15:45:18 hannken Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -215,7 +215,6 @@ void lfs_writer_leave(struct lfs *);
 void lfs_wakeup_cleaner(struct lfs *);
 
 /* lfs_syscalls.c */
-int lfs_fastvget(struct mount *, ino_t, daddr_t, struct vnode **, struct ulfs1_dinode *);
 struct buf *lfs_fakebuf(struct lfs *, struct vnode *, int, size_t, void *);
 int lfs_do_segclean(struct lfs *, unsigned long);
 int lfs_segwait(fsid_t *, struct timeval *);

Index: src/sys/ufs/lfs/lfs_syscalls.c
diff -u src/sys/ufs/lfs/lfs_syscalls.c:1.158 src/sys/ufs/lfs/lfs_syscalls.c:1.159
--- src/sys/ufs/lfs/lfs_syscalls.c:1.158	Sun May 31 15:44:31 2015
+++ src/sys/ufs/lfs/lfs_syscalls.c	Sun May 31 15:45:18 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_syscalls.c,v 1.158 2015/05/31 15:44:31 hannken Exp $	*/
+/*	$NetBSD: lfs_syscalls.c,v 1.159 2015/05/31 15:45:18 hannken Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007, 2008
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.158 2015/05/31 15:44:31 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.159 2015/05/31 15:45:18 hannken Exp $");
 
 #ifndef LFS
 # define LFS		/* for prototypes in syscallargs.h */
@@ -87,6 +87,7 @@ __KERNEL_RCSID(0, "$NetBSD: lfs_syscalls
 
 struct buf *lfs_fakebuf(struct lfs *, struct vnode *, int, size_t, void *);
 int lfs_fasthashget(dev_t, ino_t, struct vnode **);
+int lfs_fastvget(struct mount *, ino_t, BLOCK_INFO *, int, struct vnode **);
 
 pid_t lfs_cleaner_pid = 0;
 
@@ -230,9 +231,10 @@ lfs_markv(struct proc *p, fsid_t *fsidp,
 	struct inode *ip = NULL;
 	struct lfs *fs;
 	struct mount *mntp;
-	struct vnode *vp = NULL;
+	struct ulfsmount *ump;
+	struct vnode *vp;
 	ino_t lastino;
-	daddr_t b_daddr, v_daddr;
+	daddr_t b_daddr;
 	int cnt, error;
 	int do_again = 0;
 	int numrefed = 0;
@@ -245,7 +247,8 @@ lfs_markv(struct proc *p, fsid_t *fsidp,
 	if ((mntp = vfs_getvfs(fsidp)) == NULL)
 		return (ENOENT);
 
-	fs = VFSTOULFS(mntp)->um_lfs;
+	ump = VFSTOULFS(mntp);
+	fs = ump->um_lfs;
 
 	if (fs->lfs_ronly)
 		return EROFS;
@@ -273,7 +276,7 @@ lfs_markv(struct proc *p, fsid_t *fsidp,
 	error = 0;
 
 	/* these were inside the initialization for the for loop */
-	v_daddr = LFS_UNUSED_DADDR;
+	vp = NULL;
 	lastino = LFS_UNUSED_INUM;
 	nblkwritten = ninowritten = 0;
 	for (blkp = blkiov; cnt--; ++blkp)
@@ -289,11 +292,12 @@ lfs_markv(struct proc *p, fsid_t *fsidp,
 		 */
 		if (lastino != blkp->bi_inode) {
 			/*
-			 * Finish the old file, if there was one.  The presence
-			 * of a usable vnode in vp is signaled by a valid v_daddr.
+			 * Finish the old file, if there was one.
 			 */
-			if (v_daddr != LFS_UNUSED_DADDR) {
+			if (vp != NULL) {
+				VOP_UNLOCK(vp);
 				lfs_vunref(vp);
+				vp = NULL;
 				numrefed--;
 			}
 
@@ -301,27 +305,10 @@ lfs_markv(struct proc *p, fsid_t *fsidp,
 			 * Start a new file
 			 */
 			lastino = blkp->bi_inode;
-			if (blkp->bi_inode == LFS_IFILE_INUM)
-				v_daddr = fs->lfs_idaddr;
-			else {
-				LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
-				/* XXX fix for force write */
-				v_daddr = ifp->if_daddr;
-				brelse(bp, 0);
-			}
-			if (v_daddr == LFS_UNUSED_DADDR)
-				continue;
 
 			/* Get the vnode/inode. */
-			error = lfs_fastvget(mntp, blkp->bi_inode, v_daddr,
-					   &vp,
-					   (blkp->bi_lbn == LFS_UNUSED_LBN
-					    ? blkp->bi_bp
-					    : NULL));
-
-			if (!error) {
-				numrefed++;
-			}
+			error = lfs_fastvget(mntp, blkp->bi_inode, blkp,
+			    LK_EXCLUSIVE | LK_NOWAIT, &vp);
 			if (error) {
 				DLOG((DLOG_CLEAN, "lfs_markv: lfs_fastvget"
 				      " failed with %d (ino %d, segment %d)\n",
@@ -335,28 +322,22 @@ lfs_markv(struct proc *p, fsid_t *fsidp,
 				 * again with another.	(When the
 				 * cleaner runs again, this segment will
 				 * sort high on the list, since it is
-				 * now almost entirely empty.) But, we
-				 * still set v_daddr = LFS_UNUSED_ADDR
-				 * so as not to test this over and over
-				 * again.
+				 * now almost entirely empty.)
 				 */
 				if (error == EAGAIN) {
 					error = 0;
 					do_again++;
-				}
-#ifdef DIAGNOSTIC
-				else if (error != ENOENT)
-					panic("lfs_markv VFS_VGET FAILED");
-#endif
-				/* lastino = LFS_UNUSED_INUM; */
-				v_daddr = LFS_UNUSED_DADDR;
-				vp = NULL;
+				} else
+					KASSERT(error == ENOENT);
+				KASSERT(vp == NULL);
 				ip = NULL;
 				continue;
 			}
+
 			ip = VTOI(vp);
+			numrefed++;
 			ninowritten++;
-		} else if (v_daddr == LFS_UNUSED_DADDR) {
+		} else if (vp == NULL) {
 			/*
 			 * This can only happen if the vnode is dead (or
 			 * in any case we can't get it...e.g., it is
@@ -484,8 +465,10 @@ lfs_markv(struct proc *p, fsid_t *fsidp,
 	/*
 	 * Finish the old file, if there was one
 	 */
-	if (v_daddr != LFS_UNUSED_DADDR) {
+	if (vp != NULL) {
+		VOP_UNLOCK(vp);
 		lfs_vunref(vp);
+		vp = NULL;
 		numrefed--;
 	}
 
@@ -528,8 +511,10 @@ err3:
 	 * XXX should do segwrite here anyway?
 	 */
 
-	if (v_daddr != LFS_UNUSED_DADDR) {
+	if (vp != NULL) {
+		VOP_UNLOCK(vp);
 		lfs_vunref(vp);
+		vp = NULL;
 		--numrefed;
 	}
 
@@ -673,19 +658,15 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp,
 	struct inode *ip = NULL;
 	struct lfs *fs;
 	struct mount *mntp;
-	struct ulfsmount *ump;
 	struct vnode *vp;
 	ino_t lastino;
 	daddr_t v_daddr;
 	int cnt, error;
 	int numrefed = 0;
 
-	lfs_cleaner_pid = p->p_pid;
-
 	if ((mntp = vfs_getvfs(fsidp)) == NULL)
 		return (ENOENT);
 
-	ump = VFSTOULFS(mntp);
 	if ((error = vfs_busy(mntp, NULL)) != 0)
 		return (error);
 
@@ -696,6 +677,7 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp,
 	error = 0;
 
 	/* these were inside the initialization for the for loop */
+	vp = NULL;
 	v_daddr = LFS_UNUSED_DADDR;
 	lastino = LFS_UNUSED_INUM;
 	for (blkp = blkiov; cnt--; ++blkp)
@@ -706,20 +688,12 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp,
 		 */
 		if (lastino != blkp->bi_inode) {
 			/*
-			 * Finish the old file, if there was one.  The presence
-			 * of a usable vnode in vp is signaled by a valid
-			 * v_daddr.
+			 * Finish the old file, if there was one.
 			 */
-			if (v_daddr != LFS_UNUSED_DADDR) {
+			if (vp != NULL) {
+				VOP_UNLOCK(vp);
 				lfs_vunref(vp);
-				if (VTOI(vp)->i_lfs_iflags & LFSI_BMAP) {
-					mutex_enter(vp->v_interlock);
-					if (vget(vp, LK_NOWAIT,
-						false /* !wait */) == 0) {
-						if (! vrecycle(vp))
-							vrele(vp);
-					}
-				}
+				vp = NULL;
 				numrefed--;
 			}
 
@@ -738,50 +712,20 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp,
 				blkp->bi_daddr = LFS_UNUSED_DADDR;
 				continue;
 			}
-			/*
-			 * A regular call to VFS_VGET could deadlock
-			 * here.  Instead, we try an unlocked access.
-			 */
-			mutex_enter(&ulfs_ihash_lock);
-			vp = ulfs_ihashlookup(ump->um_dev, blkp->bi_inode);
-			if (vp != NULL)
-				mutex_enter(vp->v_interlock);
-			if (vp != NULL && vdead_check(vp, VDEAD_NOWAIT) == 0) {
-				ip = VTOI(vp);
-				mutex_exit(&ulfs_ihash_lock);
-				if (lfs_vref(vp)) {
-					v_daddr = LFS_UNUSED_DADDR;
-					continue;
-				}
-				numrefed++;
+			error = lfs_fastvget(mntp, blkp->bi_inode, NULL,
+			    LK_SHARED, &vp);
+			if (error) {
+				DLOG((DLOG_CLEAN, "lfs_bmapv: lfs_fastvget ino"
+				      "%d failed with %d",
+				      blkp->bi_inode,error));
+				KASSERT(vp == NULL);
+				continue;
 			} else {
-				if (vp != NULL)
-					mutex_exit(vp->v_interlock);
-				mutex_exit(&ulfs_ihash_lock);
-				/*
-				 * Don't VFS_VGET if we're being unmounted,
-				 * since we hold vfs_busy().
-				 */
-				if (mntp->mnt_iflag & IMNT_UNMOUNT) {
-					v_daddr = LFS_UNUSED_DADDR;
-					continue;
-				}
-				error = VFS_VGET(mntp, blkp->bi_inode, &vp);
-				if (error) {
-					DLOG((DLOG_CLEAN, "lfs_bmapv: vget ino"
-					      "%d failed with %d",
-					      blkp->bi_inode,error));
-					v_daddr = LFS_UNUSED_DADDR;
-					continue;
-				} else {
-					KASSERT(VOP_ISLOCKED(vp));
-					VTOI(vp)->i_lfs_iflags |= LFSI_BMAP;
-					VOP_UNLOCK(vp);
-					numrefed++;
-				}
+				KASSERT(VOP_ISLOCKED(vp));
+				numrefed++;
 			}
 			ip = VTOI(vp);
-		} else if (v_daddr == LFS_UNUSED_DADDR) {
+		} else if (vp == NULL) {
 			/*
 			 * This can only happen if the vnode is dead.
 			 * Keep going.	Note that we DO NOT set the
@@ -792,7 +736,6 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp,
 			 * lfs_markv will throw them out if we are
 			 * wrong.
 			 */
-			/* blkp->bi_daddr = LFS_UNUSED_DADDR; */
 			continue;
 		}
 
@@ -825,19 +768,12 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp,
 	}
 
 	/*
-	 * Finish the old file, if there was one.  The presence
-	 * of a usable vnode in vp is signaled by a valid v_daddr.
+	 * Finish the old file, if there was one.
 	 */
-	if (v_daddr != LFS_UNUSED_DADDR) {
+	if (vp != NULL) {
+		VOP_UNLOCK(vp);
 		lfs_vunref(vp);
-		/* Recycle as above. */
-		if (ip->i_lfs_iflags & LFSI_BMAP) {
-			mutex_enter(vp->v_interlock);
-			if (vget(vp, LK_NOWAIT, false /* !wait */) == 0) {
-				if (! vrecycle(vp))
-					vrele(vp);
-			}
-		}
+		vp = NULL;
 		numrefed--;
 	}
 
@@ -1076,13 +1012,15 @@ lfs_fasthashget(dev_t dev, ino_t ino, st
 }
 
 int
-lfs_fastvget(struct mount *mp, ino_t ino, daddr_t daddr, struct vnode **vpp,
-	     struct ulfs1_dinode *dinp)
+lfs_fastvget(struct mount *mp, ino_t ino, BLOCK_INFO *blkp, int lk_flags,
+    struct vnode **vpp)
 {
+	IFILE *ifp;
 	struct inode *ip;
-	struct ulfs1_dinode *dip;
+	struct ulfs1_dinode *dip, *dinp;
 	struct vnode *vp;
 	struct ulfsmount *ump;
+	daddr_t daddr;
 	dev_t dev;
 	int error, retries;
 	struct buf *bp;
@@ -1110,8 +1048,33 @@ lfs_fastvget(struct mount *mp, ino_t ino
 	 */
 
 	error = lfs_fasthashget(dev, ino, vpp);
-	if (error != 0 || *vpp != NULL)
-		return (error);
+	if (error != 0)
+		return error;
+	else if (*vpp != NULL) {
+		error = vn_lock(*vpp, lk_flags);
+		if (error == EBUSY)
+			error = EAGAIN;
+		if (error) {
+			lfs_vunref(*vpp);
+			*vpp = NULL;
+			return error;
+		}
+	}
+
+	if (blkp != NULL && blkp->bi_lbn == LFS_UNUSED_LBN)
+		dinp = blkp->bi_bp;
+	else
+		dinp = NULL;
+
+	if (ino == LFS_IFILE_INUM)
+		daddr = fs->lfs_idaddr;
+	else {
+		LFS_IENTRY(ifp, fs, ino, bp);
+		daddr = ifp->if_daddr;
+		brelse(bp, 0);
+	}
+	if (daddr == LFS_UNUSED_DADDR)
+		return ENOENT;
 
 	/*
 	 * getnewvnode(9) will call vfs_busy, which will block if the
@@ -1219,7 +1182,6 @@ lfs_fastvget(struct mount *mp, ino_t ino
 	*vpp = vp;
 
 	KASSERT(VOP_ISLOCKED(vp));
-	VOP_UNLOCK(vp);
 
 	return (0);
 }

Reply via email to