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:
parent
fca015d301
commit
a69452162a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=268606
@ -50,6 +50,23 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <fs/cd9660/cd9660_node.h>
|
#include <fs/cd9660/cd9660_node.h>
|
||||||
#include <fs/cd9660/iso_rrip.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.
|
* Convert a component of a pathname into a pointer to a locked inode.
|
||||||
* This is a very central and rather complicated routine.
|
* This is a very central and rather complicated routine.
|
||||||
@ -104,6 +121,7 @@ cd9660_lookup(ap)
|
|||||||
doff_t endsearch; /* offset to end directory search */
|
doff_t endsearch; /* offset to end directory search */
|
||||||
struct vnode *pdp; /* saved dp during symlink work */
|
struct vnode *pdp; /* saved dp during symlink work */
|
||||||
struct vnode *tdp; /* returned by cd9660_vget_internal */
|
struct vnode *tdp; /* returned by cd9660_vget_internal */
|
||||||
|
struct cd9660_ino_alloc_arg dd_arg;
|
||||||
u_long bmask; /* block offset mask */
|
u_long bmask; /* block offset mask */
|
||||||
int error;
|
int error;
|
||||||
ino_t ino, i_ino;
|
ino_t ino, i_ino;
|
||||||
@ -114,7 +132,6 @@ cd9660_lookup(ap)
|
|||||||
int res;
|
int res;
|
||||||
int assoc, len;
|
int assoc, len;
|
||||||
char *name;
|
char *name;
|
||||||
struct mount *mp;
|
|
||||||
struct vnode **vpp = ap->a_vpp;
|
struct vnode **vpp = ap->a_vpp;
|
||||||
struct componentname *cnp = ap->a_cnp;
|
struct componentname *cnp = ap->a_cnp;
|
||||||
int flags = cnp->cn_flags;
|
int flags = cnp->cn_flags;
|
||||||
@ -368,39 +385,13 @@ cd9660_lookup(ap)
|
|||||||
* it's a relocated directory.
|
* it's a relocated directory.
|
||||||
*/
|
*/
|
||||||
if (flags & ISDOTDOT) {
|
if (flags & ISDOTDOT) {
|
||||||
/*
|
dd_arg.ino = ino;
|
||||||
* Expanded copy of vn_vget_ino() so that we can use
|
dd_arg.i_ino = i_ino;
|
||||||
* cd9660_vget_internal().
|
dd_arg.ep = ep;
|
||||||
*/
|
error = vn_vget_ino_gen(pdp, cd9660_ino_alloc, &dd_arg,
|
||||||
mp = pdp->v_mount;
|
cnp->cn_lkflags, &tdp);
|
||||||
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);
|
|
||||||
free(ep2, M_TEMP);
|
free(ep2, M_TEMP);
|
||||||
vfs_unbusy(mp);
|
if (error != 0)
|
||||||
vn_lock(pdp, ltype | LK_RETRY);
|
|
||||||
if (pdp->v_iflag & VI_DOOMED) {
|
|
||||||
if (error == 0)
|
|
||||||
vput(tdp);
|
|
||||||
error = ENOENT;
|
|
||||||
}
|
|
||||||
if (error)
|
|
||||||
return (error);
|
return (error);
|
||||||
*vpp = tdp;
|
*vpp = tdp;
|
||||||
} else if (dp->i_number == i_ino) {
|
} else if (dp->i_number == i_ino) {
|
||||||
|
@ -63,8 +63,6 @@
|
|||||||
|
|
||||||
static int msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp,
|
static int msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp,
|
||||||
struct componentname *cnp, u_int64_t *inum);
|
struct componentname *cnp, u_int64_t *inum);
|
||||||
static int msdosfs_deget_dotdot(struct vnode *vp, u_long cluster, int blkoff,
|
|
||||||
struct vnode **rvp);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
msdosfs_lookup(struct vop_cachedlookup_args *ap)
|
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));
|
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
|
* When we search a directory the blocks containing directory entries are
|
||||||
* read and examined. The directory entries contain information that would
|
* 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 msdosfsmount *pmp;
|
||||||
struct buf *bp = NULL;
|
struct buf *bp = NULL;
|
||||||
struct direntry *dep = NULL;
|
struct direntry *dep = NULL;
|
||||||
|
struct deget_dotdot dd_arg;
|
||||||
u_char dosfilename[12];
|
u_char dosfilename[12];
|
||||||
int flags = cnp->cn_flags;
|
int flags = cnp->cn_flags;
|
||||||
int nameiop = cnp->cn_nameiop;
|
int nameiop = cnp->cn_nameiop;
|
||||||
@ -524,8 +545,11 @@ msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp,
|
|||||||
*/
|
*/
|
||||||
pdp = vdp;
|
pdp = vdp;
|
||||||
if (flags & ISDOTDOT) {
|
if (flags & ISDOTDOT) {
|
||||||
error = msdosfs_deget_dotdot(pdp, cluster, blkoff, vpp);
|
dd_arg.cluster = cluster;
|
||||||
if (error) {
|
dd_arg.blkoff = blkoff;
|
||||||
|
error = vn_vget_ino_gen(vdp, msdosfs_deget_dotdot,
|
||||||
|
&dd_arg, cnp->cn_lkflags, vpp);
|
||||||
|
if (error != 0) {
|
||||||
*vpp = NULL;
|
*vpp = NULL;
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -560,54 +584,6 @@ msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp,
|
|||||||
return (0);
|
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
|
* dep - directory entry to copy into the directory
|
||||||
* ddep - directory to add to
|
* ddep - directory to add to
|
||||||
|
@ -1953,12 +1953,30 @@ vn_extattr_rm(struct vnode *vp, int ioflg, int attrnamespace,
|
|||||||
return (error);
|
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
|
int
|
||||||
vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags, struct vnode **rvp)
|
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;
|
struct mount *mp;
|
||||||
int ltype, error;
|
int ltype, error;
|
||||||
|
|
||||||
|
ASSERT_VOP_LOCKED(vp, "vn_vget_ino_get");
|
||||||
mp = vp->v_mount;
|
mp = vp->v_mount;
|
||||||
ltype = VOP_ISLOCKED(vp);
|
ltype = VOP_ISLOCKED(vp);
|
||||||
KASSERT(ltype == LK_EXCLUSIVE || ltype == LK_SHARED,
|
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);
|
VOP_UNLOCK(vp, 0);
|
||||||
error = VFS_VGET(mp, ino, lkflags, rvp);
|
error = alloc(mp, alloc_arg, lkflags, rvp);
|
||||||
vfs_unbusy(mp);
|
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 (vp->v_iflag & VI_DOOMED) {
|
||||||
if (error == 0)
|
if (error == 0) {
|
||||||
vput(*rvp);
|
if (*rvp == vp)
|
||||||
|
vunref(vp);
|
||||||
|
else
|
||||||
|
vput(*rvp);
|
||||||
|
}
|
||||||
error = ENOENT;
|
error = ENOENT;
|
||||||
}
|
}
|
||||||
return (error);
|
return (error);
|
||||||
|
@ -593,6 +593,8 @@ struct uio;
|
|||||||
struct vattr;
|
struct vattr;
|
||||||
struct vnode;
|
struct vnode;
|
||||||
|
|
||||||
|
typedef int (*vn_get_ino_t)(struct mount *, void *, int, struct vnode **);
|
||||||
|
|
||||||
/* cache_* may belong in namei.h. */
|
/* cache_* may belong in namei.h. */
|
||||||
#define cache_enter(dvp, vp, cnp) \
|
#define cache_enter(dvp, vp, cnp) \
|
||||||
cache_enter_time(dvp, vp, cnp, NULL, NULL)
|
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);
|
const char *attrname, struct thread *td);
|
||||||
int vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags,
|
int vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags,
|
||||||
struct vnode **rvp);
|
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,
|
int vn_utimes_perm(struct vnode *vp, struct vattr *vap,
|
||||||
struct ucred *cred, struct thread *td);
|
struct ucred *cred, struct thread *td);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user