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);
}