aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/vfs_vnops.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2014-07-14 08:34:54 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2014-07-14 08:34:54 +0000
commita69452162a1036e0b2b086e43afb2a68634078bf (patch)
treebe7a3e638a2f72e4bb601f1af70678e77135e970 /sys/kern/vfs_vnops.c
parentfca015d30184282217d50d29f5c3d906ea726b0d (diff)
downloadsrc-a69452162a1036e0b2b086e43afb2a68634078bf.tar.gz
src-a69452162a1036e0b2b086e43afb2a68634078bf.zip
Generalize vn_get_ino() to allow filesystems to use custom vnode
producer, instead of hard-coding VFS_VGET(). New function, which takes callback, is called vn_get_ino_gen(), standard callback for vn_get_ino() is provided. Convert inline copies of vn_get_ino() in msdosfs and cd9660 into the uses of vn_get_ino_gen(). Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=268606
Diffstat (limited to 'sys/kern/vfs_vnops.c')
-rw-r--r--sys/kern/vfs_vnops.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index d97e56f8a47e..e7e0f9ecde29 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1953,12 +1953,30 @@ vn_extattr_rm(struct vnode *vp, int ioflg, int attrnamespace,
return (error);
}
+static int
+vn_get_ino_alloc_vget(struct mount *mp, void *arg, int lkflags,
+ struct vnode **rvp)
+{
+
+ return (VFS_VGET(mp, *(ino_t *)arg, lkflags, rvp));
+}
+
int
vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags, struct vnode **rvp)
{
+
+ return (vn_vget_ino_gen(vp, vn_get_ino_alloc_vget, &ino,
+ lkflags, rvp));
+}
+
+int
+vn_vget_ino_gen(struct vnode *vp, vn_get_ino_t alloc, void *alloc_arg,
+ int lkflags, struct vnode **rvp)
+{
struct mount *mp;
int ltype, error;
+ ASSERT_VOP_LOCKED(vp, "vn_vget_ino_get");
mp = vp->v_mount;
ltype = VOP_ISLOCKED(vp);
KASSERT(ltype == LK_EXCLUSIVE || ltype == LK_SHARED,
@@ -1978,12 +1996,17 @@ vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags, struct vnode **rvp)
}
}
VOP_UNLOCK(vp, 0);
- error = VFS_VGET(mp, ino, lkflags, rvp);
+ error = alloc(mp, alloc_arg, lkflags, rvp);
vfs_unbusy(mp);
- vn_lock(vp, ltype | LK_RETRY);
+ if (*rvp != vp)
+ vn_lock(vp, ltype | LK_RETRY);
if (vp->v_iflag & VI_DOOMED) {
- if (error == 0)
- vput(*rvp);
+ if (error == 0) {
+ if (*rvp == vp)
+ vunref(vp);
+ else
+ vput(*rvp);
+ }
error = ENOENT;
}
return (error);