Files
Arquivotheca.SunOS-4.1.4/sys/lofs/lo_vnodeops.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

472 lines
9.1 KiB
C

/* @(#)lo_vnodeops.c 1.1 94/10/31 SMI */
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/user.h>
#include <sys/vnode.h>
#include <sys/vfs.h>
#include <sys/file.h>
#include <sys/uio.h>
#include <sys/buf.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/pathname.h>
#include <lofs/lnode.h>
#include <lofs/loinfo.h>
struct vnode *makelonode();
#ifdef LODEBUG
int lodebug;
#endif LODEBUG
/*
* These are the vnode ops routines which implement the vnode interface to
* the looped-back file system. These routines just take their parameters,
* and then calling the appropriate real vnode routine(s) to do the work.
*/
static int lo_open();
static int lo_close();
static int lo_getattr();
static int lo_setattr();
static int lo_access();
static int lo_lookup();
static int lo_create();
static int lo_remove();
static int lo_link();
static int lo_rename();
static int lo_mkdir();
static int lo_rmdir();
static int lo_readdir();
static int lo_symlink();
static int lo_fsync();
static int lo_inactive();
static int lo_lockctl();
static int lo_cmp();
static int lo_realvp();
static int lo_cntl();
int lo_badop(); /* used by lo_vfsops.c */
/*
* Loopback operations: Only directories are covered by loopback vnodes
* so we only have to support operations on directories
*/
struct vnodeops lo_vnodeops = {
lo_open,
lo_close,
lo_badop, /* rdwr */
lo_badop, /* ioctl */
lo_badop, /* select */
lo_getattr,
lo_setattr,
lo_access,
lo_lookup,
lo_create,
lo_remove,
lo_link,
lo_rename,
lo_mkdir,
lo_rmdir,
lo_readdir,
lo_symlink,
lo_badop, /* readlink */
lo_fsync,
lo_inactive,
lo_lockctl, /* lockctl */
lo_badop, /* fid - can't export lofs's */
lo_badop, /* getpage */
lo_badop, /* putpage */
lo_badop, /* map */
lo_badop, /* dump */
lo_cmp,
lo_realvp,
lo_cntl,
};
static int
lo_open(vpp, flag, cred)
register struct vnode **vpp;
int flag;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_open vp %x realvp %x\n", *vpp, realvp(*vpp));
#endif
return (VOP_OPEN(&realvp(*vpp), flag, cred));
}
static int
lo_close(vp, flag, count, cred)
struct vnode *vp;
int flag;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_close vp %x realvp %x\n", vp, realvp(vp));
#endif
return (VOP_CLOSE(realvp(vp), flag, count, cred));
}
static int
lo_getattr(vp, vap, cred)
struct vnode *vp;
struct vattr *vap;
struct ucred *cred;
{
int error;
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_getattr vp %x realvp %x\n", vp, realvp(vp));
#endif
error = VOP_GETATTR(realvp(vp), vap, cred);
return (error);
}
static int
lo_setattr(vp, vap, cred)
register struct vnode *vp;
register struct vattr *vap;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_setattr vp %x realvp %x\n", vp, realvp(vp));
#endif
return (VOP_SETATTR(realvp(vp), vap, cred));
}
static int
lo_access(vp, mode, cred)
struct vnode *vp;
int mode;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_access vp %x realvp %x\n", vp, realvp(vp));
#endif
return (VOP_ACCESS(realvp(vp), mode, cred));
}
static int
lo_fsync(vp, cred)
struct vnode *vp;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_fsync vp %x realvp %x\n", vp, realvp(vp));
#endif
return (VOP_FSYNC(realvp(vp), cred));
}
/*ARGSUSED*/
static int
lo_inactive(vp, cred)
struct vnode *vp;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_inactive %x, realvp %x\n", vp, realvp(vp));
#endif
VN_RELE(realvp(vp));
freelonode(vtol(vp));
return (0);
}
static int
lo_lookup(dvp, nm, vpp, cred, pnp, flags)
struct vnode *dvp;
char *nm;
struct vnode **vpp;
struct ucred *cred;
struct pathname *pnp;
int flags;
{
struct vnode *vp = NULL, *tvp;
int error;
struct vnode *realdvp = realvp(dvp);
struct vfs *vfsp;
*vpp = NULL; /* default(error) case */
/*
* Handle ".." out of mounted filesystem
*/
while ((realdvp->v_flag & VROOT) && strcmp(nm, "..") == 0)
realdvp = realdvp->v_vfsp->vfs_vnodecovered;
/*
* Do the normal lookup
*/
error = VOP_LOOKUP(realdvp, nm, &vp, cred, pnp, flags);
if (error)
goto out;
/*
* If this vnode is mounted on, then we
* transparently indirect to the vnode which
* is the root of the mounted file system.
* Before we do this we must check that an unmount is not
* in progress on this vnode. This maintains the fs status
* quo while a possibly lengthy unmount is going on.
* (stolen from vfs_lookup.c)
*/
mloop:
while ((vfsp = vp->v_vfsmountedhere) != 0) {
/*
* Don't traverse a loopback mountpoint unless its
* going to the next higher depth
* This prevents loops to ourselves either directly or not
*/
if (vfsp->vfs_op == &lo_vfsops &&
vtoli(vfsp)->li_depth != vtoli(dvp->v_vfsp)->li_depth+1)
break;
while (vfsp->vfs_flag & VFS_MLOCK) {
vfsp->vfs_flag |= VFS_MWAIT;
(void) sleep((caddr_t)vfsp, PVFS);
goto mloop;
}
error = VFS_ROOT(vfsp, &tvp);
VN_RELE(vp);
if (error)
goto out;
vp = tvp;
}
/*
* Now make our loop vnode for the real vnode
* But we only have to do it if the real vnode is a directory
* We can't do it for shared text without hacking on distpte
*/
if (vp->v_type == VDIR)
*vpp = makelonode(vp, vtoli(dvp->v_vfsp));
else
*vpp = vp;
out:
#ifdef LODEBUG
lo_dprint(lodebug, 4,
"lo_lookup dvp %x realdvp %x nm '%s' newvp %x real vp %x error %d\n",
dvp, realvp(dvp), nm, *vpp, vp, error);
#endif
return (error);
}
/*ARGSUSED*/
static int
lo_create(dvp, nm, va, exclusive, mode, vpp, cred)
struct vnode *dvp;
char *nm;
struct vattr *va;
enum vcexcl exclusive;
int mode;
struct vnode **vpp;
struct ucred *cred;
{
struct vnode *vp;
int error;
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_create vp %x realvp %x\n", dvp, realvp(dvp));
#endif
error = VOP_CREATE(realvp(dvp), nm, va, exclusive, mode, &vp, cred);
if (!error) {
*vpp = vp;
} else {
*vpp = NULL;
}
return (error);
}
static int
lo_remove(dvp, nm, cred)
struct vnode *dvp;
char *nm;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_remove vp %x realvp %x\n", dvp, realvp(dvp));
#endif
return (VOP_REMOVE(realvp(dvp), nm, cred));
}
static int
lo_link(vp, tdvp, tnm, cred)
struct vnode *vp;
struct vnode *tdvp;
char *tnm;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_link vp %x realvp %x\n", vp, realvp(vp));
#endif
while (vp->v_op == &lo_vnodeops)
vp = realvp(vp);
while (tdvp->v_op == &lo_vnodeops)
tdvp = realvp(tdvp);
if (vp->v_vfsp != tdvp->v_vfsp)
return (EXDEV);
return (VOP_LINK(vp, tdvp, tnm, cred));
}
static int
lo_rename(odvp, onm, ndvp, nnm, cred)
struct vnode *odvp;
char *onm;
struct vnode *ndvp;
char *nnm;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_rename vp %x realvp %x\n", odvp, realvp(odvp));
#endif
while (odvp->v_op == &lo_vnodeops)
odvp = realvp(odvp);
while (ndvp->v_op == &lo_vnodeops)
ndvp = realvp(ndvp);
if (odvp->v_vfsp != ndvp->v_vfsp)
return (EXDEV);
return (VOP_RENAME(odvp, onm, ndvp, nnm, cred));
}
static int
lo_mkdir(dvp, nm, va, vpp, cred)
struct vnode *dvp;
char *nm;
register struct vattr *va;
struct vnode **vpp;
struct ucred *cred;
{
struct vnode *vp;
int error;
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_mkdir vp %x realvp %x\n", dvp, realvp(dvp));
#endif
error = VOP_MKDIR(realvp(dvp), nm, va, &vp, cred);
if (!error) {
*vpp = makelonode(vp, vtoli(dvp->v_vfsp));
} else {
*vpp = NULL;
}
return (error);
}
static int
lo_rmdir(dvp, nm, cred)
struct vnode *dvp;
char *nm;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_rmdir vp %x realvp %x\n", dvp, realvp(dvp));
#endif
return (VOP_RMDIR(realvp(dvp), nm, cred));
}
static int
lo_symlink(dvp, lnm, tva, tnm, cred)
struct vnode *dvp;
char *lnm;
struct vattr *tva;
char *tnm;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_symlink vp %x realvp %x\n", dvp, realvp(dvp));
#endif
return (VOP_SYMLINK(realvp(dvp), lnm, tva, tnm, cred));
}
static int
lo_readdir(vp, uiop, cred)
struct vnode *vp;
register struct uio *uiop;
struct ucred *cred;
{
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_readdir vp %x realvp %x\n", vp, realvp(vp));
#endif
return (VOP_READDIR(realvp(vp), uiop, cred));
}
static int
lo_lockctl(vp, ld, cmd, cred, clid)
struct vnode *vp;
struct flock *ld;
int cmd;
struct ucred *cred;
int clid;
{
#ifdef LODEBUG
lo_dprint(lodebug, 2, "lo_lockctl vp %x realvp %x\n", vp, realvp(vp));
#endif
return (VOP_LOCKCTL(realvp(vp), ld, cmd, cred, clid));
}
static int
lo_cmp(vp1, vp2)
struct vnode *vp1, *vp2;
{
if (vp1->v_op == &lo_vnodeops)
vp1 = realvp(vp1);
if (vp2->v_op == &lo_vnodeops)
vp2 = realvp(vp2);
return (VOP_CMP(vp1, vp2));
}
static int
lo_realvp(vp, vpp)
struct vnode *vp;
struct vnode **vpp;
{
struct vnode *rvp;
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_realvp %x\n", vp);
#endif
if (vp->v_op == &lo_vnodeops) {
vp = realvp(vp);
}
if (VOP_REALVP(vp, &rvp) == 0) {
vp = rvp;
}
*vpp = vp;
#ifdef LODEBUG
lo_dprint(lodebug, 4, "lo_realvp returning %x\n", vp);
#endif
return (0);
}
int
lo_badop()
{
return (EISDIR);
}
/*ARGSUSED*/
static int
lo_cntl(vp, cmd, idata, odata, iflg, oflg)
struct vnode *vp;
caddr_t idata, odata;
{
return ENOSYS;
}