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
This commit is contained in:
Konstantin Belousov 2014-07-14 08:34:54 +00:00
parent fca015d301
commit a69452162a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=268606
4 changed files with 83 additions and 89 deletions

View File

@ -50,6 +50,23 @@ __FBSDID("$FreeBSD$");
#include <fs/cd9660/cd9660_node.h>
#include <fs/cd9660/iso_rrip.h>
struct cd9660_ino_alloc_arg {
ino_t ino;
ino_t i_ino;
struct iso_directory_record *ep;
};
static int
cd9660_ino_alloc(struct mount *mp, void *arg, int lkflags,
struct vnode **vpp)
{
struct cd9660_ino_alloc_arg *dd_arg;
dd_arg = arg;
return (cd9660_vget_internal(mp, dd_arg->i_ino, lkflags, vpp,
dd_arg->i_ino != dd_arg->ino, dd_arg->ep));
}
/*
* Convert a component of a pathname into a pointer to a locked inode.
* This is a very central and rather complicated routine.
@ -104,6 +121,7 @@ cd9660_lookup(ap)
doff_t endsearch; /* offset to end directory search */
struct vnode *pdp; /* saved dp during symlink work */
struct vnode *tdp; /* returned by cd9660_vget_internal */
struct cd9660_ino_alloc_arg dd_arg;
u_long bmask; /* block offset mask */
int error;
ino_t ino, i_ino;
@ -114,7 +132,6 @@ cd9660_lookup(ap)
int res;
int assoc, len;
char *name;
struct mount *mp;
struct vnode **vpp = ap->a_vpp;
struct componentname *cnp = ap->a_cnp;
int flags = cnp->cn_flags;
@ -368,39 +385,13 @@ cd9660_lookup(ap)
* it's a relocated directory.
*/
if (flags & ISDOTDOT) {
/*
* Expanded copy of vn_vget_ino() so that we can use
* cd9660_vget_internal().
*/
mp = pdp->v_mount;
ltype = VOP_ISLOCKED(pdp);
error = vfs_busy(mp, MBF_NOWAIT);
if (error != 0) {
vfs_ref(mp);
VOP_UNLOCK(pdp, 0);
error = vfs_busy(mp, 0);
vn_lock(pdp, ltype | LK_RETRY);
vfs_rel(mp);
if (error)
return (ENOENT);
if (pdp->v_iflag & VI_DOOMED) {
vfs_unbusy(mp);
return (ENOENT);
}
}
VOP_UNLOCK(pdp, 0);
error = cd9660_vget_internal(vdp->v_mount, i_ino,
cnp->cn_lkflags, &tdp,
i_ino != ino, ep);
dd_arg.ino = ino;
dd_arg.i_ino = i_ino;
dd_arg.ep = ep;
error = vn_vget_ino_gen(pdp, cd9660_ino_alloc, &dd_arg,
cnp->cn_lkflags, &tdp);
free(ep2, M_TEMP);
vfs_unbusy(mp);
vn_lock(pdp, ltype | LK_RETRY);
if (pdp->v_iflag & VI_DOOMED) {
if (error == 0)
vput(tdp);
error = ENOENT;
}
if (error)
if (error != 0)
return (error);
*vpp = tdp;
} else if (dp->i_number == i_ino) {

View File

@ -63,8 +63,6 @@
static int msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp,
struct componentname *cnp, u_int64_t *inum);
static int msdosfs_deget_dotdot(struct vnode *vp, u_long cluster, int blkoff,
struct vnode **rvp);
int
msdosfs_lookup(struct vop_cachedlookup_args *ap)
@ -73,6 +71,28 @@ msdosfs_lookup(struct vop_cachedlookup_args *ap)
return (msdosfs_lookup_(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL));
}
struct deget_dotdot {
u_long cluster;
int blkoff;
};
static int
msdosfs_deget_dotdot(struct mount *mp, void *arg, int lkflags,
struct vnode **rvp)
{
struct deget_dotdot *dd_arg;
struct denode *rdp;
struct msdosfsmount *pmp;
int error;
pmp = VFSTOMSDOSFS(mp);
dd_arg = arg;
error = deget(pmp, dd_arg->cluster, dd_arg->blkoff, &rdp);
if (error == 0)
*rvp = DETOV(rdp);
return (error);
}
/*
* When we search a directory the blocks containing directory entries are
* read and examined. The directory entries contain information that would
@ -110,6 +130,7 @@ msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp,
struct msdosfsmount *pmp;
struct buf *bp = NULL;
struct direntry *dep = NULL;
struct deget_dotdot dd_arg;
u_char dosfilename[12];
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
@ -524,8 +545,11 @@ msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp,
*/
pdp = vdp;
if (flags & ISDOTDOT) {
error = msdosfs_deget_dotdot(pdp, cluster, blkoff, vpp);
if (error) {
dd_arg.cluster = cluster;
dd_arg.blkoff = blkoff;
error = vn_vget_ino_gen(vdp, msdosfs_deget_dotdot,
&dd_arg, cnp->cn_lkflags, vpp);
if (error != 0) {
*vpp = NULL;
return (error);
}
@ -560,54 +584,6 @@ msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp,
return (0);
}
static int
msdosfs_deget_dotdot(struct vnode *vp, u_long cluster, int blkoff,
struct vnode **rvp)
{
struct mount *mp;
struct msdosfsmount *pmp;
struct denode *rdp;
int ltype, error;
mp = vp->v_mount;
pmp = VFSTOMSDOSFS(mp);
ltype = VOP_ISLOCKED(vp);
KASSERT(ltype == LK_EXCLUSIVE || ltype == LK_SHARED,
("msdosfs_deget_dotdot: vp not locked"));
error = vfs_busy(mp, MBF_NOWAIT);
if (error != 0) {
vfs_ref(mp);
VOP_UNLOCK(vp, 0);
error = vfs_busy(mp, 0);
vn_lock(vp, ltype | LK_RETRY);
vfs_rel(mp);
if (error != 0)
return (ENOENT);
if (vp->v_iflag & VI_DOOMED) {
vfs_unbusy(mp);
return (ENOENT);
}
}
VOP_UNLOCK(vp, 0);
error = deget(pmp, cluster, blkoff, &rdp);
vfs_unbusy(mp);
if (error == 0)
*rvp = DETOV(rdp);
if (*rvp != vp)
vn_lock(vp, ltype | LK_RETRY);
if (vp->v_iflag & VI_DOOMED) {
if (error == 0) {
if (*rvp == vp)
vunref(*rvp);
else
vput(*rvp);
}
error = ENOENT;
}
return (error);
}
/*
* dep - directory entry to copy into the directory
* ddep - directory to add to

View File

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

View File

@ -593,6 +593,8 @@ struct uio;
struct vattr;
struct vnode;
typedef int (*vn_get_ino_t)(struct mount *, void *, int, struct vnode **);
/* cache_* may belong in namei.h. */
#define cache_enter(dvp, vp, cnp) \
cache_enter_time(dvp, vp, cnp, NULL, NULL)
@ -696,6 +698,8 @@ int vn_extattr_rm(struct vnode *vp, int ioflg, int attrnamespace,
const char *attrname, struct thread *td);
int vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags,
struct vnode **rvp);
int vn_vget_ino_gen(struct vnode *vp, vn_get_ino_t alloc,
void *alloc_arg, int lkflags, struct vnode **rvp);
int vn_utimes_perm(struct vnode *vp, struct vattr *vap,
struct ucred *cred, struct thread *td);