This is the kernel Lite/2 commit. There are some requisite userland
changes, so don't expect to be able to run the kernel as-is (very well) without the appropriate Lite/2 userland changes. The system boots and can mount UFS filesystems. Untested: ext2fs, msdosfs, NFS Known problems: Incorrect Berkeley ID strings in some files. Mount_std mounts will not work until the getfsent library routine is changed. Reviewed by: various people Submitted by: Jeffery Hsu <hsu@freebsd.org>
This commit is contained in:
parent
d243e2f7f4
commit
996c772f58
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=22521
@ -53,6 +53,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <machine/bootinfo.h>
|
||||
@ -88,31 +89,15 @@
|
||||
static void configure __P((void *));
|
||||
SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
|
||||
|
||||
#ifdef MFS_ROOT
|
||||
extern struct vfsops mfs_vfsops;
|
||||
#endif
|
||||
#ifdef FFS
|
||||
extern struct vfsops ufs_vfsops;
|
||||
#endif
|
||||
#ifdef LFS
|
||||
extern struct vfsops lfs_vfsops;
|
||||
#endif
|
||||
#ifdef NFS
|
||||
extern int nfs_mountroot __P((void *));
|
||||
#endif
|
||||
#ifdef CD9660
|
||||
extern int cd9660_mountroot __P((void *));
|
||||
#endif
|
||||
#ifdef MSDOSFS
|
||||
extern int msdosfs_mountroot __P((void *));
|
||||
#endif
|
||||
|
||||
static void configure_finish __P((void));
|
||||
static void configure_start __P((void));
|
||||
static int setdumpdev __P((dev_t dev));
|
||||
static void setroot __P((void));
|
||||
|
||||
#ifdef CD9660
|
||||
|
||||
#include <isofs/cd9660/iso.h>
|
||||
|
||||
/* We need to try out all our potential CDROM drives, so we need a table. */
|
||||
static struct {
|
||||
char *name;
|
||||
@ -138,7 +123,7 @@ find_cdrom_root(dummy)
|
||||
rootdev = makedev(try_cdrom[k].major,j*8);
|
||||
printf("trying rootdev=0x%lx (%s%d)\n",
|
||||
rootdev, try_cdrom[k].name,j);
|
||||
i = (*cd9660_mountroot)((void *)NULL);
|
||||
i = (*cd9660_mountroot)();
|
||||
if (!i) return i;
|
||||
}
|
||||
return EINVAL;
|
||||
@ -176,6 +161,11 @@ configure(dummy)
|
||||
enable_intr();
|
||||
INTREN(IRQ_SLAVE);
|
||||
|
||||
#if NCRD > 0
|
||||
/* Before isa_configure to avoid ISA drivers finding our cards */
|
||||
pccard_configure();
|
||||
#endif
|
||||
|
||||
#if NEISA > 0
|
||||
eisa_configure();
|
||||
#endif
|
||||
@ -188,11 +178,6 @@ configure(dummy)
|
||||
isa_configure();
|
||||
#endif
|
||||
|
||||
#if NCRD > 0
|
||||
/* After everyone else has a chance at grabbing resources */
|
||||
pccard_configure();
|
||||
#endif
|
||||
|
||||
if (setdumpdev(dumpdev) != 0)
|
||||
dumpdev = NODEV;
|
||||
|
||||
@ -235,19 +220,26 @@ configure(dummy)
|
||||
}
|
||||
|
||||
#ifdef CD9660
|
||||
if ((boothowto & RB_CDROM) && !mountroot) {
|
||||
if ((boothowto & RB_CDROM)) {
|
||||
if (bootverbose)
|
||||
printf("Considering CD-ROM root f/s.\n");
|
||||
mountroot = find_cdrom_root;
|
||||
mountrootfsname = "cd9660";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NFS
|
||||
if (!mountrootfsname && nfs_diskless_valid) {
|
||||
if (bootverbose)
|
||||
printf("Considering NFS root f/s.\n");
|
||||
mountrootfsname = "nfs";
|
||||
}
|
||||
#endif /* NFS */
|
||||
|
||||
#ifdef MFS_ROOT
|
||||
if (!mountroot) {
|
||||
if (!mountrootfsname) {
|
||||
if (bootverbose)
|
||||
printf("Considering MFS root f/s.\n");
|
||||
mountroot = vfs_mountroot; /* XXX goes away*/
|
||||
mountrootvfsops = &mfs_vfsops;
|
||||
mountrootfsname = "mfs";
|
||||
/*
|
||||
* Ignore the -a flag if this kernel isn't compiled
|
||||
* with a generic root/swap configuration: if we skip
|
||||
@ -260,21 +252,11 @@ configure(dummy)
|
||||
setroot();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NFS
|
||||
if (!mountroot && nfs_diskless_valid) {
|
||||
if (bootverbose)
|
||||
printf("Considering NFS root f/s.\n");
|
||||
mountroot = nfs_mountroot;
|
||||
}
|
||||
#endif /* NFS */
|
||||
|
||||
#ifdef FFS
|
||||
if (!mountroot) {
|
||||
if (!mountrootfsname) {
|
||||
mountrootfsname = "ufs";
|
||||
if (bootverbose)
|
||||
printf("Considering FFS root f/s.\n");
|
||||
mountroot = vfs_mountroot; /* XXX goes away*/
|
||||
mountrootvfsops = &ufs_vfsops;
|
||||
/*
|
||||
* Ignore the -a flag if this kernel isn't compiled
|
||||
* with a generic root/swap configuration: if we skip
|
||||
@ -288,11 +270,10 @@ configure(dummy)
|
||||
}
|
||||
#endif
|
||||
#ifdef LFS
|
||||
if (!mountroot) {
|
||||
if (!mountrootfsname) {
|
||||
if (bootverbose)
|
||||
printf("Considering LFS root f/s.\n");
|
||||
mountroot = vfs_mountroot; /* XXX goes away*/
|
||||
mountrootvfsops = &lfs_vfsops;
|
||||
mountrootfsname = "lfs";
|
||||
/*
|
||||
* Ignore the -a flag if this kernel isn't compiled
|
||||
* with a generic root/swap configuration: if we skip
|
||||
@ -305,8 +286,7 @@ configure(dummy)
|
||||
setroot();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!mountroot) {
|
||||
if (!mountrootfsname) {
|
||||
panic("Nobody wants to mount my root for me");
|
||||
}
|
||||
|
||||
@ -417,4 +397,4 @@ sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
|
||||
0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
|
||||
0, sizeof dumpdev, sysctl_kern_dumpdev, "I", "");
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <ddb/ddb.h>
|
||||
|
@ -61,13 +61,15 @@
|
||||
#include <sys/vmmeter.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <sys/user.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsdiskless.h>
|
||||
|
||||
extern int main __P((void));
|
||||
|
@ -82,7 +82,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
|
@ -68,7 +68,7 @@
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
@ -85,7 +85,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
@ -61,7 +61,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_map.h>
|
||||
|
@ -58,7 +58,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
|
@ -450,7 +450,7 @@ linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval)
|
||||
buflen = max(DIRBLKSIZ, nbytes + blockoff);
|
||||
buflen = min(buflen, MAXBSIZE);
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
again:
|
||||
aiov.iov_base = buf;
|
||||
aiov.iov_len = buflen;
|
||||
@ -530,7 +530,7 @@ linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval)
|
||||
eof:
|
||||
*retval = nbytes - resid;
|
||||
out:
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, p);
|
||||
free(buf, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
|
||||
/*
|
||||
* Lock no longer needed
|
||||
*/
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, p);
|
||||
locked = 0;
|
||||
|
||||
/*
|
||||
@ -392,7 +392,7 @@ printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]);
|
||||
* Unlock vnode if needed
|
||||
*/
|
||||
if (locked)
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, p);
|
||||
|
||||
/*
|
||||
* Release the kernel mapping.
|
||||
|
@ -52,6 +52,7 @@ kern/kern_exit.c standard
|
||||
kern/kern_fork.c standard
|
||||
kern/kern_ktrace.c standard
|
||||
kern/kern_lkm.c standard
|
||||
kern/kern_lock.c standard
|
||||
kern/kern_lockf.c standard
|
||||
kern/kern_malloc.c standard
|
||||
kern/kern_mib.c standard
|
||||
@ -373,7 +374,6 @@ ufs/ufs/ufs_vfsops.c standard
|
||||
ufs/ufs/ufs_vnops.c standard
|
||||
vm/default_pager.c standard
|
||||
vm/device_pager.c standard
|
||||
vm/kern_lock.c standard
|
||||
vm/swap_pager.c standard
|
||||
vm/vm_fault.c standard
|
||||
vm/vm_glue.c standard
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_prot.h>
|
||||
|
@ -277,7 +277,7 @@ static d_strategy_t fdstrategy;
|
||||
static struct cdevsw fd_cdevsw;
|
||||
static struct bdevsw fd_bdevsw =
|
||||
{ Fdopen, fdclose, fdstrategy, fdioctl, /*2*/
|
||||
nodump, nopsize, 0, "fd", &fd_cdevsw, -1 };
|
||||
nodump, nopsize, D_DISK, "fd", &fd_cdevsw, -1 };
|
||||
|
||||
|
||||
static struct isa_device *fdcdevs[NFDC];
|
||||
|
@ -457,11 +457,11 @@ vnioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
|
||||
return(error);
|
||||
error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
|
||||
if (error) {
|
||||
VOP_UNLOCK(nd.ni_vp);
|
||||
VOP_UNLOCK(nd.ni_vp, 0, p);
|
||||
(void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
|
||||
return(error);
|
||||
}
|
||||
VOP_UNLOCK(nd.ni_vp);
|
||||
VOP_UNLOCK(nd.ni_vp, 0, p);
|
||||
vn->sc_vp = nd.ni_vp;
|
||||
vn->sc_size = btodb(vattr.va_size); /* note truncation */
|
||||
error = vnsetcred(vn, p->p_ucred);
|
||||
|
@ -25,16 +25,6 @@
|
||||
There is some preliminary stuff in there that (ab-)uses the mknod
|
||||
system call, but this needs a writable filesystem
|
||||
|
||||
3) should be called cdfs, as there are other ISO file system soon possible
|
||||
|
||||
Not yet. Probably we should make another file system when the ECMA draft
|
||||
is valid and do it. For doing Rock Ridge Support, I can use almost same
|
||||
code. So I just use the same file system interface...
|
||||
|
||||
4) should have file handles implemented for use with NFS, etc
|
||||
|
||||
Yes. we have already this one, and I based it for this release.
|
||||
|
||||
5) should have name translation enabled by mount flag
|
||||
|
||||
Yes. we can disable the Rock Ridge Extension by follows option;
|
||||
@ -57,23 +47,3 @@
|
||||
clean. As far as I know, if you export the cdrom by NFS, the client
|
||||
can access the 8 bit clean (ie. Solaris Japanese with EUC code )
|
||||
|
||||
9) Access checks in isofs_access
|
||||
|
||||
Not yet.
|
||||
|
||||
10) Support for generation numbers
|
||||
|
||||
Yes. Default is to list only the last file (the one with the highest
|
||||
generation number). If you mount with -gen, all files are shown with
|
||||
their generation numbers. In both cases you can specify the generation
|
||||
number on opening files (if you happen to know it) or leave it off,
|
||||
when it will again find the last file.
|
||||
|
||||
11) Support for extended attributes
|
||||
|
||||
Yes. Since this requires an extra block buffer for the attributes
|
||||
this must be enabled on mounting with the option -extattr.
|
||||
|
||||
----------
|
||||
Last update July 19, '93 by Atsushi Murai. (amurai@spec.co.jp)
|
||||
Last update August 19, '93 by Wolfgang Solfrank. (ws@tools.de)
|
||||
|
@ -67,7 +67,7 @@ cd9660_bmap(ap)
|
||||
{
|
||||
struct iso_node *ip = VTOI(ap->a_vp);
|
||||
daddr_t lblkno = ap->a_bn;
|
||||
long bsize;
|
||||
int bshift;
|
||||
|
||||
/*
|
||||
* Check for underlying vnode requests and ensure that logical
|
||||
@ -81,8 +81,8 @@ cd9660_bmap(ap)
|
||||
/*
|
||||
* Compute the requested block number
|
||||
*/
|
||||
bsize = ip->i_mnt->logical_block_size;
|
||||
*ap->a_bnp = (ip->iso_start + lblkno) * btodb(bsize);
|
||||
bshift = ip->i_mnt->im_bshift;
|
||||
*ap->a_bnp = (ip->iso_start + lblkno) << (bshift - DEV_BSHIFT);
|
||||
|
||||
/*
|
||||
* Determine maximum number of readahead blocks following the
|
||||
@ -91,11 +91,11 @@ cd9660_bmap(ap)
|
||||
if (ap->a_runp) {
|
||||
int nblk;
|
||||
|
||||
nblk = (ip->i_size - (lblkno + 1) * bsize) / bsize;
|
||||
nblk = (ip->i_size >> bshift) - (lblkno + 1);
|
||||
if (nblk <= 0)
|
||||
*ap->a_runp = 0;
|
||||
else if (nblk >= MAXBSIZE/bsize)
|
||||
*ap->a_runp = MAXBSIZE/bsize - 1;
|
||||
else if (nblk >= (MAXBSIZE >> bshift))
|
||||
*ap->a_runp = (MAXBSIZE >> bshift) - 1;
|
||||
else
|
||||
*ap->a_runp = nblk;
|
||||
}
|
||||
|
@ -108,8 +108,9 @@ cd9660_lookup(ap)
|
||||
int saveoffset = 0; /* offset of last directory entry in dir */
|
||||
int numdirpasses; /* strategy for directory search */
|
||||
doff_t endsearch; /* offset to end directory search */
|
||||
struct iso_node *pdp; /* saved dp during symlink work */
|
||||
struct iso_node *tdp; /* returned by iget */
|
||||
struct vnode *pdp; /* saved dp during symlink work */
|
||||
struct vnode *tdp; /* returned by cd9660_vget_internal */
|
||||
u_long bmask; /* block offset mask */
|
||||
int lockparent; /* 1 => lockparent flag is set */
|
||||
int wantparent; /* 1 => wantparent or lockparent flag */
|
||||
int error;
|
||||
@ -126,6 +127,7 @@ cd9660_lookup(ap)
|
||||
struct ucred *cred = cnp->cn_cred;
|
||||
int flags = cnp->cn_flags;
|
||||
int nameiop = cnp->cn_nameiop;
|
||||
struct proc *p = cnp->cn_proc;
|
||||
|
||||
bp = NULL;
|
||||
*vpp = NULL;
|
||||
@ -139,13 +141,13 @@ cd9660_lookup(ap)
|
||||
* Check accessiblity of directory.
|
||||
*/
|
||||
if (vdp->v_type != VDIR)
|
||||
return (ENOTDIR);
|
||||
if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)))
|
||||
return (ENOTDIR);
|
||||
if (error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc))
|
||||
return (error);
|
||||
if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
|
||||
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
|
||||
return (EROFS);
|
||||
|
||||
|
||||
/*
|
||||
* We now have a segment name to search for, and a directory to search.
|
||||
*
|
||||
@ -160,29 +162,29 @@ cd9660_lookup(ap)
|
||||
return (error);
|
||||
#ifdef PARANOID
|
||||
if ((vdp->v_flag & VROOT) && (flags & ISDOTDOT))
|
||||
panic("ufs_lookup: .. through root");
|
||||
panic("cd9660_lookup: .. through root");
|
||||
#endif
|
||||
/*
|
||||
* Get the next vnode in the path.
|
||||
* See comment below starting `Step through' for
|
||||
* an explaination of the locking protocol.
|
||||
*/
|
||||
pdp = dp;
|
||||
pdp = vdp;
|
||||
dp = VTOI(*vpp);
|
||||
vdp = *vpp;
|
||||
vpid = vdp->v_id;
|
||||
if (pdp == dp) {
|
||||
if (pdp == vdp) {
|
||||
VREF(vdp);
|
||||
error = 0;
|
||||
} else if (flags & ISDOTDOT) {
|
||||
ISO_IUNLOCK(pdp);
|
||||
error = vget(vdp, 1);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
error = vget(vdp, LK_EXCLUSIVE, p);
|
||||
if (!error && lockparent && (flags & ISLASTCN))
|
||||
ISO_ILOCK(pdp);
|
||||
error = vn_lock(pdp, LK_EXCLUSIVE, p);
|
||||
} else {
|
||||
error = vget(vdp, 1);
|
||||
error = vget(vdp, LK_EXCLUSIVE, p);
|
||||
if (!lockparent || error || !(flags & ISLASTCN))
|
||||
ISO_IUNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
}
|
||||
/*
|
||||
* Check that the capability number did not change
|
||||
@ -191,13 +193,14 @@ cd9660_lookup(ap)
|
||||
if (!error) {
|
||||
if (vpid == vdp->v_id)
|
||||
return (0);
|
||||
iso_iput(dp);
|
||||
if (lockparent && pdp != dp && (flags & ISLASTCN))
|
||||
ISO_IUNLOCK(pdp);
|
||||
vput(vdp);
|
||||
if (lockparent && pdp != vdp && (flags & ISLASTCN))
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
}
|
||||
ISO_ILOCK(pdp);
|
||||
dp = pdp;
|
||||
vdp = ITOV(dp);
|
||||
if (error = vn_lock(pdp, LK_EXCLUSIVE, p))
|
||||
return (error);
|
||||
vdp = pdp;
|
||||
dp = VTOI(pdp);
|
||||
*vpp = NULL;
|
||||
}
|
||||
|
||||
@ -223,6 +226,7 @@ cd9660_lookup(ap)
|
||||
* profiling time and hence has been removed in the interest
|
||||
* of simplicity.
|
||||
*/
|
||||
bmask = imp->im_bmask;
|
||||
if (nameiop != LOOKUP || dp->i_diroff == 0 ||
|
||||
dp->i_diroff > dp->i_size) {
|
||||
entryoffsetinblock = 0;
|
||||
@ -230,16 +234,14 @@ cd9660_lookup(ap)
|
||||
numdirpasses = 1;
|
||||
} else {
|
||||
dp->i_offset = dp->i_diroff;
|
||||
entryoffsetinblock = iso_blkoff(imp, dp->i_offset);
|
||||
if (entryoffsetinblock != 0) {
|
||||
if ((error = iso_blkatoff(dp, dp->i_offset, &bp)))
|
||||
if ((entryoffsetinblock = dp->i_offset & bmask) &&
|
||||
(error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)))
|
||||
return (error);
|
||||
}
|
||||
numdirpasses = 2;
|
||||
iso_nchstats.ncs_2passes++;
|
||||
}
|
||||
endsearch = roundup(dp->i_size, imp->logical_block_size);
|
||||
|
||||
endsearch = dp->i_size;
|
||||
|
||||
searchloop:
|
||||
while (dp->i_offset < endsearch) {
|
||||
/*
|
||||
@ -247,10 +249,11 @@ cd9660_lookup(ap)
|
||||
* read the next directory block.
|
||||
* Release previous if it exists.
|
||||
*/
|
||||
if (iso_blkoff(imp, dp->i_offset) == 0) {
|
||||
if ((dp->i_offset & bmask) == 0) {
|
||||
if (bp != NULL)
|
||||
brelse(bp);
|
||||
if ((error = iso_blkatoff(dp, dp->i_offset, &bp)))
|
||||
if (error =
|
||||
VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp))
|
||||
return (error);
|
||||
entryoffsetinblock = 0;
|
||||
}
|
||||
@ -258,13 +261,13 @@ cd9660_lookup(ap)
|
||||
* Get pointer to next entry.
|
||||
*/
|
||||
ep = (struct iso_directory_record *)
|
||||
(bp->b_un.b_addr + entryoffsetinblock);
|
||||
|
||||
reclen = isonum_711 (ep->length);
|
||||
((char *)bp->b_data + entryoffsetinblock);
|
||||
|
||||
reclen = isonum_711(ep->length);
|
||||
if (reclen == 0) {
|
||||
/* skip to next block, if any */
|
||||
dp->i_offset =
|
||||
roundup(dp->i_offset, imp->logical_block_size);
|
||||
(dp->i_offset & ~bmask) + imp->logical_block_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -275,10 +278,7 @@ cd9660_lookup(ap)
|
||||
if (entryoffsetinblock + reclen > imp->logical_block_size)
|
||||
/* entries are not allowed to cross boundaries */
|
||||
break;
|
||||
|
||||
/*
|
||||
* Check for a name match.
|
||||
*/
|
||||
|
||||
namelen = isonum_711(ep->name_len);
|
||||
isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
|
||||
&ep->date[6]: ep->flags);
|
||||
@ -286,7 +286,10 @@ cd9660_lookup(ap)
|
||||
if (reclen < ISO_DIRECTORY_RECORD_SIZE + namelen)
|
||||
/* illegal entry, stop */
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
* Check for a name match.
|
||||
*/
|
||||
switch (imp->iso_ftype) {
|
||||
default:
|
||||
if (!(isoflags & 4) == !assoc) {
|
||||
@ -297,10 +300,9 @@ cd9660_lookup(ap)
|
||||
&& ep->name[0] == ((flags & ISDOTDOT) ? 1 : 0)) {
|
||||
/*
|
||||
* Save directory entry's inode number and
|
||||
* reclen in ndp->ni_ufs area, and release
|
||||
* directory buffer.
|
||||
* release directory buffer.
|
||||
*/
|
||||
isodirino(&dp->i_ino,ep,imp);
|
||||
dp->i_ino = isodirino(ep, imp);
|
||||
goto found;
|
||||
}
|
||||
if (namelen != 1
|
||||
@ -308,8 +310,8 @@ cd9660_lookup(ap)
|
||||
goto notfound;
|
||||
} else if (!(res = isofncmp(name,len,
|
||||
ep->name,namelen))) {
|
||||
if (isoflags & 2)
|
||||
isodirino(&ino,ep,imp);
|
||||
if (isonum_711(ep->flags)&2)
|
||||
ino = isodirino(ep, imp);
|
||||
else
|
||||
ino = dbtob(bp->b_blkno)
|
||||
+ entryoffsetinblock;
|
||||
@ -326,7 +328,7 @@ cd9660_lookup(ap)
|
||||
break;
|
||||
case ISO_FTYPE_RRIP:
|
||||
if (isonum_711(ep->flags)&2)
|
||||
isodirino(&ino,ep,imp);
|
||||
ino = isodirino(ep, imp);
|
||||
else
|
||||
ino = dbtob(bp->b_blkno) + entryoffsetinblock;
|
||||
dp->i_ino = ino;
|
||||
@ -344,15 +346,17 @@ cd9660_lookup(ap)
|
||||
foundino:
|
||||
dp->i_ino = ino;
|
||||
if (saveoffset != dp->i_offset) {
|
||||
if (iso_lblkno(imp,dp->i_offset)
|
||||
!= iso_lblkno(imp,saveoffset)) {
|
||||
if (lblkno(imp, dp->i_offset) !=
|
||||
lblkno(imp, saveoffset)) {
|
||||
if (bp != NULL)
|
||||
brelse(bp);
|
||||
if ((error = iso_blkatoff(dp, saveoffset, &bp)))
|
||||
if (error = VOP_BLKATOFF(vdp,
|
||||
(off_t)saveoffset, NULL, &bp))
|
||||
return (error);
|
||||
}
|
||||
ep = (struct iso_directory_record *)(bp->b_un.b_addr
|
||||
+ iso_blkoff(imp,saveoffset));
|
||||
entryoffsetinblock = saveoffset & bmask;
|
||||
ep = (struct iso_directory_record *)
|
||||
((char *)bp->b_data + entryoffsetinblock);
|
||||
dp->i_offset = saveoffset;
|
||||
}
|
||||
goto found;
|
||||
@ -370,6 +374,7 @@ cd9660_lookup(ap)
|
||||
}
|
||||
if (bp != NULL)
|
||||
brelse(bp);
|
||||
|
||||
/*
|
||||
* Insert name into cache (as non-existent) if appropriate.
|
||||
*/
|
||||
@ -382,9 +387,7 @@ cd9660_lookup(ap)
|
||||
found:
|
||||
if (numdirpasses == 2)
|
||||
iso_nchstats.ncs_pass2++;
|
||||
if (bp != NULL)
|
||||
brelse(bp);
|
||||
|
||||
|
||||
/*
|
||||
* Found component in pathname.
|
||||
* If the final component of path name, save information
|
||||
@ -412,31 +415,39 @@ cd9660_lookup(ap)
|
||||
* work if the file system has any hard links other than ".."
|
||||
* that point backwards in the directory structure.
|
||||
*/
|
||||
pdp = dp;
|
||||
pdp = vdp;
|
||||
/*
|
||||
* If ino is different from dp->i_ino,
|
||||
* it's a relocated directory.
|
||||
*/
|
||||
if (flags & ISDOTDOT) {
|
||||
ISO_IUNLOCK(pdp); /* race to get the inode */
|
||||
if ((error = iso_iget(dp,dp->i_ino,
|
||||
dp->i_ino != ino,
|
||||
&tdp,ep))) {
|
||||
ISO_ILOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, p); /* race to get the inode */
|
||||
error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
|
||||
dp->i_ino != ino, ep);
|
||||
brelse(bp);
|
||||
if (error) {
|
||||
vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
return (error);
|
||||
}
|
||||
if (lockparent && (flags & ISLASTCN))
|
||||
ISO_ILOCK(pdp);
|
||||
*vpp = ITOV(tdp);
|
||||
if (lockparent && (flags & ISLASTCN) &&
|
||||
(error = vn_lock(pdp, LK_EXCLUSIVE, p))) {
|
||||
vput(tdp);
|
||||
return (error);
|
||||
}
|
||||
*vpp = tdp;
|
||||
} else if (dp->i_number == dp->i_ino) {
|
||||
brelse(bp);
|
||||
VREF(vdp); /* we want ourself, ie "." */
|
||||
*vpp = vdp;
|
||||
} else {
|
||||
if ((error = iso_iget(dp,dp->i_ino,dp->i_ino!=ino,&tdp,ep)))
|
||||
error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
|
||||
dp->i_ino != ino, ep);
|
||||
brelse(bp);
|
||||
if (error)
|
||||
return (error);
|
||||
if (!lockparent || !(flags & ISLASTCN))
|
||||
ISO_IUNLOCK(pdp);
|
||||
*vpp = ITOV(tdp);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
*vpp = tdp;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -448,29 +459,37 @@ cd9660_lookup(ap)
|
||||
}
|
||||
|
||||
/*
|
||||
* Return buffer with contents of block "offset"
|
||||
* from the beginning of directory "ip". If "res"
|
||||
* is non-zero, fill it in with a pointer to the
|
||||
* Return buffer with the contents of block "offset" from the beginning of
|
||||
* directory "ip". If "res" is non-zero, fill it in with a pointer to the
|
||||
* remaining space in the directory.
|
||||
*/
|
||||
int
|
||||
iso_blkatoff(ip, offset, bpp)
|
||||
struct iso_node *ip;
|
||||
doff_t offset;
|
||||
struct buf **bpp;
|
||||
cd9660_blkatoff(ap)
|
||||
struct vop_blkatoff_args /* {
|
||||
struct vnode *a_vp;
|
||||
off_t a_offset;
|
||||
char **a_res;
|
||||
struct buf **a_bpp;
|
||||
} */ *ap;
|
||||
{
|
||||
register struct iso_mnt *imp = ip->i_mnt;
|
||||
daddr_t lbn = iso_lblkno(imp,offset);
|
||||
int bsize = iso_blksize(imp,ip,lbn);
|
||||
struct iso_node *ip;
|
||||
register struct iso_mnt *imp;
|
||||
struct buf *bp;
|
||||
int error;
|
||||
daddr_t lbn;
|
||||
int bsize, error;
|
||||
|
||||
if ((error = bread(ITOV(ip),lbn,bsize,NOCRED,&bp))) {
|
||||
ip = VTOI(ap->a_vp);
|
||||
imp = ip->i_mnt;
|
||||
lbn = lblkno(imp, ap->a_offset);
|
||||
bsize = blksize(imp, ip, lbn);
|
||||
|
||||
if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) {
|
||||
brelse(bp);
|
||||
*bpp = 0;
|
||||
*ap->a_bpp = NULL;
|
||||
return (error);
|
||||
}
|
||||
*bpp = bp;
|
||||
|
||||
if (ap->a_res)
|
||||
*ap->a_res = (char *)bp->b_data + blkoff(imp, ap->a_offset);
|
||||
*ap->a_bpp = bp;
|
||||
return (0);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1989, 1994
|
||||
* Copyright (c) 1982, 1986, 1989, 1994, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley
|
||||
@ -52,32 +52,21 @@
|
||||
|
||||
#include <isofs/cd9660/iso.h>
|
||||
#include <isofs/cd9660/cd9660_node.h>
|
||||
#include <isofs/cd9660/cd9660_mount.h>
|
||||
#include <isofs/cd9660/iso_rrip.h>
|
||||
|
||||
#define INOHSZ 512
|
||||
#if ((INOHSZ&(INOHSZ-1)) == 0)
|
||||
#define INOHASH(dev,ino) (((dev)+((ino)>>12))&(INOHSZ-1))
|
||||
#else
|
||||
#define INOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%INOHSZ)
|
||||
#endif
|
||||
/*
|
||||
* Structures associated with iso_node caching.
|
||||
*/
|
||||
struct iso_node **isohashtbl;
|
||||
u_long isohash;
|
||||
#define INOHASH(device, inum) (((device) + ((inum)>>12)) & isohash)
|
||||
struct simplelock cd9660_ihash_slock;
|
||||
|
||||
union iso_ihead {
|
||||
union iso_ihead *ih_head[2];
|
||||
struct iso_node *ih_chain[2];
|
||||
} iso_ihead[INOHSZ];
|
||||
|
||||
#ifdef ISODEVMAP
|
||||
#define DNOHSZ 64
|
||||
#if ((DNOHSZ&(DNOHSZ-1)) == 0)
|
||||
#define DNOHASH(dev,ino) (((dev)+((ino)>>12))&(DNOHSZ-1))
|
||||
#else
|
||||
#define DNOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%DNOHSZ)
|
||||
#endif
|
||||
|
||||
union iso_dhead {
|
||||
union iso_dhead *dh_head[2];
|
||||
struct iso_dnode *dh_chain[2];
|
||||
} iso_dhead[DNOHSZ];
|
||||
#ifdef ISODEVMAP
|
||||
struct iso_node **idvhashtbl;
|
||||
u_long idvhash;
|
||||
#define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash)
|
||||
#endif
|
||||
|
||||
static unsigned cd9660_chars2ui __P((unsigned char *begin, int len));
|
||||
@ -86,73 +75,68 @@ static unsigned cd9660_chars2ui __P((unsigned char *begin, int len));
|
||||
* Initialize hash links for inodes and dnodes.
|
||||
*/
|
||||
int
|
||||
cd9660_init()
|
||||
cd9660_init(vfsp)
|
||||
struct vfsconf *vfsp;
|
||||
{
|
||||
register int i;
|
||||
register union iso_ihead *ih = iso_ihead;
|
||||
#ifdef ISODEVMAP
|
||||
register union iso_dhead *dh = iso_dhead;
|
||||
#endif
|
||||
|
||||
for (i = INOHSZ; --i >= 0; ih++) {
|
||||
ih->ih_head[0] = ih;
|
||||
ih->ih_head[1] = ih;
|
||||
}
|
||||
#ifdef ISODEVMAP
|
||||
for (i = DNOHSZ; --i >= 0; dh++) {
|
||||
dh->dh_head[0] = dh;
|
||||
dh->dh_head[1] = dh;
|
||||
}
|
||||
isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash);
|
||||
simple_lock_init(&cd9660_ihash_slock);
|
||||
#ifdef ISODEVMAP
|
||||
idvhashtbl = hashinit(desiredvnodes / 8, M_ISOFSMNT, &idvhash);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef ISODEVMAP
|
||||
#ifdef ISODEVMAP
|
||||
/*
|
||||
* Enter a new node into the device hash list
|
||||
*/
|
||||
struct iso_dnode *
|
||||
iso_dmap(dev,ino,create)
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
iso_dmap(device, inum, create)
|
||||
dev_t device;
|
||||
ino_t inum;
|
||||
int create;
|
||||
{
|
||||
struct iso_dnode *dp;
|
||||
union iso_dhead *dh;
|
||||
register struct iso_dnode **dpp, *dp, *dq;
|
||||
|
||||
dh = &iso_dhead[DNOHASH(dev, ino)];
|
||||
for (dp = dh->dh_chain[0];
|
||||
dp != (struct iso_dnode *)dh;
|
||||
dp = dp->d_forw)
|
||||
if (ino == dp->i_number && dev == dp->i_dev)
|
||||
return dp;
|
||||
dpp = &idvhashtbl[DNOHASH(device, inum)];
|
||||
for (dp = *dpp;; dp = dp->d_next) {
|
||||
if (dp == NULL)
|
||||
return (NULL);
|
||||
if (inum == dp->i_number && device == dp->i_dev)
|
||||
return (dp);
|
||||
|
||||
if (!create)
|
||||
return (struct iso_dnode *)0;
|
||||
return (NULL);
|
||||
|
||||
MALLOC(dp,struct iso_dnode *,sizeof(struct iso_dnode),M_CACHE,M_WAITOK);
|
||||
MALLOC(dp, struct iso_dnode *, sizeof(struct iso_dnode), M_CACHE,
|
||||
M_WAITOK);
|
||||
dp->i_dev = dev;
|
||||
dp->i_number = ino;
|
||||
insque(dp,dh);
|
||||
|
||||
return dp;
|
||||
if (dq = *dpp)
|
||||
dq->d_prev = dp->d_next;
|
||||
dp->d_next = dq;
|
||||
dp->d_prev = dpp;
|
||||
*dpp = dp;
|
||||
|
||||
return (dp);
|
||||
}
|
||||
|
||||
void
|
||||
iso_dunmap(dev)
|
||||
dev_t dev;
|
||||
iso_dunmap(device)
|
||||
dev_t device;
|
||||
{
|
||||
struct iso_dnode *dp, *dq;
|
||||
union iso_dhead *dh;
|
||||
|
||||
for (dh = iso_dhead; dh < iso_dhead + DNOHSZ; dh++) {
|
||||
for (dp = dh->dh_chain[0];
|
||||
dp != (struct iso_dnode *)dh;
|
||||
dp = dq) {
|
||||
dq = dp->d_forw;
|
||||
if (dev == dp->i_dev) {
|
||||
remque(dp);
|
||||
FREE(dp,M_CACHE);
|
||||
struct iso_dnode **dpp, *dp, *dq;
|
||||
|
||||
for (dpp = idvhashtbl; dpp <= idvhashtbl + idvhash; dpp++) {
|
||||
for (dp = *dpp; dp != NULL; dp = dq)
|
||||
dq = dp->d_next;
|
||||
if (device == dp->i_dev) {
|
||||
if (dq)
|
||||
dq->d_prev = dp->d_prev;
|
||||
*dp->d_prev = dq;
|
||||
FREE(dp, M_CACHE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,197 +144,74 @@ iso_dunmap(dev)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Look up a ISOFS dinode number to find its incore vnode.
|
||||
* If it is not in core, read it in from the specified device.
|
||||
* If it is in core, wait for the lock bit to clear, then
|
||||
* return the inode locked. Detection and handling of mount
|
||||
* points must be done by the calling routine.
|
||||
* Use the device/inum pair to find the incore inode, and return a pointer
|
||||
* to it. If it is in core, but locked, wait for it.
|
||||
*/
|
||||
int
|
||||
iso_iget(xp, ino, relocated, ipp, isodir)
|
||||
struct iso_node *xp;
|
||||
ino_t ino;
|
||||
int relocated;
|
||||
struct iso_node **ipp;
|
||||
struct iso_directory_record *isodir;
|
||||
struct vnode *
|
||||
cd9660_ihashget(dev, inum)
|
||||
dev_t dev;
|
||||
ino_t inum;
|
||||
{
|
||||
dev_t dev = xp->i_dev;
|
||||
struct mount *mntp = ITOV(xp)->v_mount;
|
||||
register struct iso_node *ip, *iq;
|
||||
register struct vnode *vp;
|
||||
#ifdef ISODEVMAP
|
||||
register struct iso_dnode *dp;
|
||||
#endif
|
||||
struct vnode *nvp;
|
||||
struct buf *bp = NULL, *bp2 = NULL;
|
||||
union iso_ihead *ih;
|
||||
int error, result;
|
||||
struct iso_mnt *imp;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct iso_node *ip;
|
||||
struct vnode *vp;
|
||||
|
||||
ih = &iso_ihead[INOHASH(dev, ino)];
|
||||
loop:
|
||||
for (ip = ih->ih_chain[0];
|
||||
ip != (struct iso_node *)ih;
|
||||
ip = ip->i_forw) {
|
||||
if (ino != ip->i_number || dev != ip->i_dev)
|
||||
continue;
|
||||
if ((ip->i_flag&ILOCKED) != 0) {
|
||||
ip->i_flag |= IWANT;
|
||||
(void) tsleep((caddr_t)ip, PINOD, "isoigt", 0);
|
||||
goto loop;
|
||||
}
|
||||
if (vget(ITOV(ip), 1))
|
||||
goto loop;
|
||||
*ipp = ip;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the MALLOC before the getnewvnode since doing so afterward
|
||||
* might cause a bogus v_data pointer to get dereferenced
|
||||
* elsewhere if MALLOC should block.
|
||||
*/
|
||||
MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE, M_WAITOK);
|
||||
|
||||
/*
|
||||
* Allocate a new vnode/iso_node.
|
||||
*/
|
||||
if ((error = getnewvnode(VT_ISOFS, mntp, cd9660_vnodeop_p, &nvp))) {
|
||||
*ipp = NULL;
|
||||
FREE(ip, M_ISOFSNODE);
|
||||
return error;
|
||||
}
|
||||
bzero((caddr_t)ip, sizeof(struct iso_node));
|
||||
nvp->v_data = ip;
|
||||
ip->i_vnode = nvp;
|
||||
ip->i_flag = 0;
|
||||
ip->i_devvp = 0;
|
||||
ip->i_diroff = 0;
|
||||
ip->i_lockf = 0;
|
||||
|
||||
/*
|
||||
* Put it onto its hash chain and lock it so that other requests for
|
||||
* this inode will block if they arrive while we are sleeping waiting
|
||||
* for old data structures to be purged or for the contents of the
|
||||
* disk portion of this inode to be read.
|
||||
*/
|
||||
ip->i_dev = dev;
|
||||
ip->i_number = ino;
|
||||
insque(ip, ih);
|
||||
ISO_ILOCK(ip);
|
||||
|
||||
imp = VFSTOISOFS (mntp);
|
||||
ip->i_mnt = imp;
|
||||
ip->i_devvp = imp->im_devvp;
|
||||
VREF(ip->i_devvp);
|
||||
|
||||
if (relocated) {
|
||||
/*
|
||||
* On relocated directories we must
|
||||
* read the `.' entry out of a dir.
|
||||
*/
|
||||
ip->iso_start = ino >> imp->im_bshift;
|
||||
if ((error = iso_blkatoff(ip,0,&bp))) {
|
||||
vrele(ip->i_devvp);
|
||||
remque(ip);
|
||||
ip->i_forw = ip;
|
||||
ip->i_back = ip;
|
||||
iso_iput(ip);
|
||||
*ipp = 0;
|
||||
return error;
|
||||
}
|
||||
isodir = (struct iso_directory_record *)bp->b_un.b_addr;
|
||||
}
|
||||
|
||||
ip->iso_extent = isonum_733(isodir->extent);
|
||||
ip->i_size = isonum_733(isodir->size);
|
||||
ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
|
||||
|
||||
vp = ITOV(ip);
|
||||
|
||||
/*
|
||||
* Setup time stamp, attribute
|
||||
*/
|
||||
vp->v_type = VNON;
|
||||
switch (imp->iso_ftype) {
|
||||
default: /* ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA */
|
||||
if ((imp->im_flags&ISOFSMNT_EXTATT)
|
||||
&& isonum_711(isodir->ext_attr_length))
|
||||
iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length),
|
||||
&bp2);
|
||||
cd9660_defattr(isodir,ip,bp2,imp->iso_ftype );
|
||||
cd9660_deftstamp(isodir,ip,bp2,imp->iso_ftype );
|
||||
break;
|
||||
case ISO_FTYPE_RRIP:
|
||||
result = cd9660_rrip_analyze(isodir,ip,imp);
|
||||
break;
|
||||
}
|
||||
if (bp2)
|
||||
brelse(bp2);
|
||||
if (bp)
|
||||
brelse(bp);
|
||||
|
||||
/*
|
||||
* Initialize the associated vnode
|
||||
*/
|
||||
vp->v_type = IFTOVT(ip->inode.iso_mode);
|
||||
|
||||
if ( vp->v_type == VFIFO ) {
|
||||
vp->v_op = cd9660_fifoop_p;
|
||||
} else if ( vp->v_type == VCHR || vp->v_type == VBLK ) {
|
||||
/*
|
||||
* if device, look at device number table for translation
|
||||
*/
|
||||
#ifdef ISODEVMAP
|
||||
if (dp = iso_dmap(dev,ino,0))
|
||||
ip->inode.iso_rdev = dp->d_dev;
|
||||
#endif
|
||||
vp->v_op = cd9660_specop_p;
|
||||
if ((nvp = checkalias(vp, ip->inode.iso_rdev, mntp))) {
|
||||
/*
|
||||
* Reinitialize aliased inode.
|
||||
*/
|
||||
vp = nvp;
|
||||
iq = VTOI(vp);
|
||||
iq->i_vnode = vp;
|
||||
iq->i_flag = 0;
|
||||
ISO_ILOCK(iq);
|
||||
iq->i_dev = dev;
|
||||
iq->i_number = ino;
|
||||
iq->i_mnt = ip->i_mnt;
|
||||
bcopy(&ip->iso_extent,&iq->iso_extent,
|
||||
(char *)(ip + 1) - (char *)&ip->iso_extent);
|
||||
insque(iq, ih);
|
||||
/*
|
||||
* Discard unneeded vnode
|
||||
* (This introduces the need of INACTIVE modification)
|
||||
*/
|
||||
ip->inode.iso_mode = 0;
|
||||
iso_iput(ip);
|
||||
ip = iq;
|
||||
simple_lock(&cd9660_ihash_slock);
|
||||
for (ip = isohashtbl[INOHASH(dev, inum)]; ip; ip = ip->i_next) {
|
||||
if (inum == ip->i_number && dev == ip->i_dev) {
|
||||
vp = ITOV(ip);
|
||||
simple_lock(&vp->v_interlock);
|
||||
simple_unlock(&cd9660_ihash_slock);
|
||||
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p))
|
||||
goto loop;
|
||||
return (vp);
|
||||
}
|
||||
}
|
||||
|
||||
if (ip->iso_extent == imp->root_extent)
|
||||
vp->v_flag |= VROOT;
|
||||
|
||||
*ipp = ip;
|
||||
return 0;
|
||||
simple_unlock(&cd9660_ihash_slock);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlock and decrement the reference count of an inode structure.
|
||||
* Insert the inode into the hash table, and return it locked.
|
||||
*/
|
||||
int
|
||||
iso_iput(ip)
|
||||
void
|
||||
cd9660_ihashins(ip)
|
||||
struct iso_node *ip;
|
||||
{
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct iso_node **ipp, *iq;
|
||||
|
||||
simple_lock(&cd9660_ihash_slock);
|
||||
ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)];
|
||||
if (iq = *ipp)
|
||||
iq->i_prev = &ip->i_next;
|
||||
ip->i_next = iq;
|
||||
ip->i_prev = ipp;
|
||||
*ipp = ip;
|
||||
simple_unlock(&cd9660_ihash_slock);
|
||||
|
||||
lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the inode from the hash table.
|
||||
*/
|
||||
void
|
||||
cd9660_ihashrem(ip)
|
||||
register struct iso_node *ip;
|
||||
{
|
||||
register struct iso_node *iq;
|
||||
|
||||
if ((ip->i_flag & ILOCKED) == 0)
|
||||
panic("iso_iput");
|
||||
ISO_IUNLOCK(ip);
|
||||
vrele(ITOV(ip));
|
||||
return (0);
|
||||
simple_lock(&cd9660_ihash_slock);
|
||||
if (iq = ip->i_next)
|
||||
iq->i_prev = ip->i_prev;
|
||||
*ip->i_prev = iq;
|
||||
#ifdef DIAGNOSTIC
|
||||
ip->i_next = NULL;
|
||||
ip->i_prev = NULL;
|
||||
#endif
|
||||
simple_unlock(&cd9660_ihash_slock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -361,9 +222,11 @@ int
|
||||
cd9660_inactive(ap)
|
||||
struct vop_inactive_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct proc *p = ap->a_p;
|
||||
register struct iso_node *ip = VTOI(vp);
|
||||
int error = 0;
|
||||
|
||||
@ -371,12 +234,13 @@ cd9660_inactive(ap)
|
||||
vprint("cd9660_inactive: pushing active", vp);
|
||||
|
||||
ip->i_flag = 0;
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
/*
|
||||
* If we are done with the inode, reclaim it
|
||||
* so that it can be reused immediately.
|
||||
*/
|
||||
if (vp->v_usecount == 0 && ip->inode.iso_mode == 0)
|
||||
vgone(vp);
|
||||
if (ip->inode.iso_mode == 0)
|
||||
vrecycle(vp, (struct simplelock *)0, p);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -387,6 +251,7 @@ int
|
||||
cd9660_reclaim(ap)
|
||||
struct vop_reclaim_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
@ -397,9 +262,7 @@ cd9660_reclaim(ap)
|
||||
/*
|
||||
* Remove the inode from its hash chain.
|
||||
*/
|
||||
remque(ip);
|
||||
ip->i_forw = ip;
|
||||
ip->i_back = ip;
|
||||
cd9660_ihashrem(ip);
|
||||
/*
|
||||
* Purge old data structures associated with the inode.
|
||||
*/
|
||||
@ -410,46 +273,6 @@ cd9660_reclaim(ap)
|
||||
}
|
||||
FREE(vp->v_data, M_ISOFSNODE);
|
||||
vp->v_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock an inode. If its already locked, set the WANT bit and sleep.
|
||||
*/
|
||||
int
|
||||
iso_ilock(ip)
|
||||
register struct iso_node *ip;
|
||||
{
|
||||
|
||||
while (ip->i_flag & ILOCKED) {
|
||||
ip->i_flag |= IWANT;
|
||||
if (ip->i_spare0 == curproc->p_pid)
|
||||
panic("locking against myself");
|
||||
ip->i_spare1 = curproc->p_pid;
|
||||
(void) tsleep((caddr_t)ip, PINOD, "isoilk", 0);
|
||||
}
|
||||
ip->i_spare1 = 0;
|
||||
ip->i_spare0 = curproc->p_pid;
|
||||
ip->i_flag |= ILOCKED;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlock an inode. If WANT bit is on, wakeup.
|
||||
*/
|
||||
int
|
||||
iso_iunlock(ip)
|
||||
register struct iso_node *ip;
|
||||
{
|
||||
|
||||
if ((ip->i_flag & ILOCKED) == 0)
|
||||
vprint("iso_iunlock: unlocked inode", ITOV(ip));
|
||||
ip->i_spare0 = 0;
|
||||
ip->i_flag &= ~ILOCKED;
|
||||
if (ip->i_flag&IWANT) {
|
||||
ip->i_flag &= ~IWANT;
|
||||
wakeup((caddr_t)ip);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -457,7 +280,7 @@ iso_iunlock(ip)
|
||||
* File attributes
|
||||
*/
|
||||
void
|
||||
cd9660_defattr(isodir,inop,bp,ftype)
|
||||
cd9660_defattr(isodir, inop, bp, ftype)
|
||||
struct iso_directory_record *isodir;
|
||||
struct iso_node *inop;
|
||||
struct buf *bp;
|
||||
@ -482,14 +305,15 @@ cd9660_defattr(isodir,inop,bp,ftype)
|
||||
inop->inode.iso_links = 1;
|
||||
}
|
||||
if (!bp
|
||||
&& ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT)
|
||||
&& ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
|
||||
&& (off = isonum_711(isodir->ext_attr_length))) {
|
||||
iso_blkatoff(inop,-off * imp->logical_block_size,&bp2);
|
||||
VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
|
||||
&bp2);
|
||||
bp = bp2;
|
||||
}
|
||||
if (bp) {
|
||||
ap = (struct iso_extended_attributes *)bp->b_un.b_addr;
|
||||
|
||||
ap = (struct iso_extended_attributes *)bp->b_data;
|
||||
|
||||
if (isonum_711(ap->version) == 1) {
|
||||
if (!(ap->perm[0]&0x40))
|
||||
inop->inode.iso_mode |= VEXEC >> 6;
|
||||
@ -533,16 +357,16 @@ cd9660_deftstamp(isodir,inop,bp,ftype)
|
||||
int off;
|
||||
|
||||
if (!bp
|
||||
&& ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT)
|
||||
&& ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
|
||||
&& (off = isonum_711(isodir->ext_attr_length))) {
|
||||
iso_blkatoff(inop,-off * imp->logical_block_size,&bp2);
|
||||
VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
|
||||
&bp2);
|
||||
bp = bp2;
|
||||
}
|
||||
if (bp) {
|
||||
ap = (struct iso_extended_attributes *)bp->b_un.b_addr;
|
||||
|
||||
if (ftype != ISO_FTYPE_HIGH_SIERRA
|
||||
&& isonum_711(ap->version) == 1) {
|
||||
ap = (struct iso_extended_attributes *)bp->b_data;
|
||||
|
||||
if (isonum_711(ap->version) == 1) {
|
||||
if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime))
|
||||
cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime);
|
||||
if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime))
|
||||
@ -563,9 +387,9 @@ cd9660_deftstamp(isodir,inop,bp,ftype)
|
||||
|
||||
int
|
||||
cd9660_tstamp_conv7(pi,pu,ftype)
|
||||
char *pi;
|
||||
struct timespec *pu;
|
||||
enum ISO_FTYPE ftype;
|
||||
u_char *pi;
|
||||
struct timespec *pu;
|
||||
enum ISO_FTYPE ftype;
|
||||
{
|
||||
int crtime, days;
|
||||
int y, m, d, hour, minute, second, tz;
|
||||
@ -609,13 +433,13 @@ enum ISO_FTYPE ftype;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
static u_int
|
||||
cd9660_chars2ui(begin,len)
|
||||
unsigned char *begin;
|
||||
u_char *begin;
|
||||
int len;
|
||||
{
|
||||
unsigned rc;
|
||||
|
||||
u_int rc;
|
||||
|
||||
for (rc = 0; --len >= 0;) {
|
||||
rc *= 10;
|
||||
rc += *begin++ - '0';
|
||||
@ -625,12 +449,12 @@ cd9660_chars2ui(begin,len)
|
||||
|
||||
int
|
||||
cd9660_tstamp_conv17(pi,pu)
|
||||
unsigned char *pi;
|
||||
u_char *pi;
|
||||
struct timespec *pu;
|
||||
{
|
||||
unsigned char buf[7];
|
||||
|
||||
/* year:"0001"-"9999" -> -1900 */
|
||||
u_char buf[7];
|
||||
|
||||
/* year:"0001"-"9999" -> -1900 */
|
||||
buf[0] = cd9660_chars2ui(pi,4) - 1900;
|
||||
|
||||
/* month: " 1"-"12" -> 1 - 12 */
|
||||
@ -654,12 +478,14 @@ cd9660_tstamp_conv17(pi,pu)
|
||||
return cd9660_tstamp_conv7(buf, pu, ISO_FTYPE_DEFAULT);
|
||||
}
|
||||
|
||||
void
|
||||
isodirino(inump,isodir,imp)
|
||||
ino_t *inump;
|
||||
ino_t
|
||||
isodirino(isodir, imp)
|
||||
struct iso_directory_record *isodir;
|
||||
struct iso_mnt *imp;
|
||||
{
|
||||
*inump = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
|
||||
* imp->logical_block_size;
|
||||
ino_t ino;
|
||||
|
||||
ino = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
|
||||
<< imp->im_bshift;
|
||||
return (ino);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)cd9660_node.h 8.2 (Berkeley) 1/23/94
|
||||
* @(#)cd9660_node.h 8.6 (Berkeley) 5/14/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -59,22 +59,20 @@ typedef struct {
|
||||
dev_t iso_rdev; /* Major/Minor number for special */
|
||||
} ISO_RRIP_INODE;
|
||||
|
||||
#ifdef ISODEVMAP
|
||||
#ifdef ISODEVMAP
|
||||
/*
|
||||
* FOr device# (major,minor) translation table
|
||||
*/
|
||||
struct iso_dnode {
|
||||
struct iso_dnode *d_chain[2]; /* hash chain, MUST be first */
|
||||
struct iso_dnode *d_next, **d_prev; /* hash chain */
|
||||
dev_t i_dev; /* device where dnode resides */
|
||||
ino_t i_number; /* the identity of the inode */
|
||||
dev_t d_dev; /* device # for translation */
|
||||
};
|
||||
#define d_forw d_chain[0]
|
||||
#define d_back d_chain[1]
|
||||
#endif
|
||||
|
||||
struct iso_node {
|
||||
struct iso_node *i_chain[2]; /* hash chain, MUST be first */
|
||||
struct iso_node *i_next, **i_prev; /* hash chain */
|
||||
struct vnode *i_vnode; /* vnode associated with this inode */
|
||||
struct vnode *i_devvp; /* vnode for block I/O */
|
||||
u_long i_flag; /* see below */
|
||||
@ -87,8 +85,7 @@ struct iso_node {
|
||||
doff_t i_diroff; /* offset in dir, where we found last entry */
|
||||
doff_t i_offset; /* offset of free space in directory */
|
||||
ino_t i_ino; /* inode number of found directory */
|
||||
long i_spare0;
|
||||
long i_spare1;
|
||||
struct lock i_lock; /* node lock */
|
||||
|
||||
long iso_extent; /* extent of file */
|
||||
long i_size;
|
||||
@ -101,19 +98,11 @@ struct iso_node {
|
||||
#define i_back i_chain[1]
|
||||
|
||||
/* flags */
|
||||
#define ILOCKED 0x0001 /* inode is locked */
|
||||
#define IWANT 0x0002 /* some process waiting on lock */
|
||||
#define IACC 0x0020 /* inode access time to be updated */
|
||||
#define IN_ACCESS 0x0020 /* inode access time to be updated */
|
||||
|
||||
#define VTOI(vp) ((struct iso_node *)(vp)->v_data)
|
||||
#define ITOV(ip) ((ip)->i_vnode)
|
||||
|
||||
#define ISO_ILOCK(ip) iso_ilock(ip)
|
||||
#define ISO_IUNLOCK(ip) iso_iunlock(ip)
|
||||
|
||||
extern vop_t **cd9660_fifoop_p;
|
||||
extern vop_t **cd9660_specop_p;
|
||||
|
||||
/*
|
||||
* Prototypes for ISOFS vnode operations
|
||||
*/
|
||||
@ -121,14 +110,19 @@ int cd9660_lookup __P((struct vop_lookup_args *));
|
||||
int cd9660_inactive __P((struct vop_inactive_args *));
|
||||
int cd9660_reclaim __P((struct vop_reclaim_args *));
|
||||
int cd9660_bmap __P((struct vop_bmap_args *));
|
||||
int cd9660_pathconf __P((struct vop_pathconf_args *));
|
||||
int cd9660_blkatoff __P((struct vop_blkatoff_args *));
|
||||
#define cd9660_revoke vop_revoke
|
||||
|
||||
void cd9660_defattr __P((struct iso_directory_record *,
|
||||
struct iso_node *, struct buf *, enum ISO_FTYPE));
|
||||
void cd9660_deftstamp __P((struct iso_directory_record *,
|
||||
struct iso_node *, struct buf *, enum ISO_FTYPE));
|
||||
int cd9660_tstamp_conv7 __P((char *pi, struct timespec *pu, enum ISO_FTYPE));
|
||||
int cd9660_tstamp_conv17 __P((unsigned char *pi, struct timespec *pu));
|
||||
void isodirino __P((ino_t *inump, struct iso_directory_record *isodir,
|
||||
struct iso_mnt *imp));
|
||||
struct vnode *cd9660_ihashget __P((dev_t, ino_t));
|
||||
void cd9660_ihashins __P((struct iso_node *));
|
||||
void cd9660_ihashrem __P((struct iso_node *));
|
||||
int cd9660_tstamp_conv7 __P((u_char *, struct timespec *, enum ISO_FTYPE));
|
||||
int cd9660_tstamp_conv17 __P((u_char *, struct timespec *));
|
||||
#ifdef ISODEVMAP
|
||||
struct iso_dnode *iso_dmap __P((dev_t, ino_t, int));
|
||||
void iso_dunmap __P((dev_t));
|
||||
|
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)cd9660_rrip.c 8.2 (Berkeley) 1/23/94
|
||||
* @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -104,10 +104,10 @@ cd9660_rrip_attr(p,ana)
|
||||
ISO_RRIP_ATTR *p;
|
||||
ISO_RRIP_ANALYZE *ana;
|
||||
{
|
||||
ana->inop->inode.iso_mode = isonum_731(p->mode_l);
|
||||
ana->inop->inode.iso_uid = (uid_t)isonum_731(p->uid_l);
|
||||
ana->inop->inode.iso_gid = (gid_t)isonum_731(p->gid_l);
|
||||
ana->inop->inode.iso_links = isonum_731(p->links_l);
|
||||
ana->inop->inode.iso_mode = isonum_733(p->mode);
|
||||
ana->inop->inode.iso_uid = isonum_733(p->uid);
|
||||
ana->inop->inode.iso_gid = isonum_733(p->gid);
|
||||
ana->inop->inode.iso_links = isonum_733(p->links);
|
||||
ana->fields &= ~ISO_SUSP_ATTR;
|
||||
return ISO_SUSP_ATTR;
|
||||
}
|
||||
@ -352,8 +352,8 @@ cd9660_rrip_tstamp(p,ana)
|
||||
ISO_RRIP_TSTAMP *p;
|
||||
ISO_RRIP_ANALYZE *ana;
|
||||
{
|
||||
unsigned char *ptime;
|
||||
|
||||
u_char *ptime;
|
||||
|
||||
ptime = p->time;
|
||||
|
||||
/* Check a format of time stamp (7bytes/17bytes) */
|
||||
@ -367,7 +367,7 @@ cd9660_rrip_tstamp(p,ana)
|
||||
ptime += 7;
|
||||
} else
|
||||
bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
|
||||
|
||||
|
||||
if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
|
||||
cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime,
|
||||
ISO_FTYPE_RRIP);
|
||||
@ -390,7 +390,7 @@ cd9660_rrip_tstamp(p,ana)
|
||||
ptime += 17;
|
||||
} else
|
||||
bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
|
||||
|
||||
|
||||
if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
|
||||
cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
|
||||
ptime += 17;
|
||||
@ -423,16 +423,15 @@ cd9660_rrip_device(p,ana)
|
||||
ISO_RRIP_DEVICE *p;
|
||||
ISO_RRIP_ANALYZE *ana;
|
||||
{
|
||||
unsigned high, low;
|
||||
|
||||
high = isonum_733(p->dev_t_high_l);
|
||||
low = isonum_733(p->dev_t_low_l);
|
||||
|
||||
if ( high == 0 ) {
|
||||
ana->inop->inode.iso_rdev = makedev( major(low), minor(low) );
|
||||
} else {
|
||||
ana->inop->inode.iso_rdev = makedev( high, minor(low) );
|
||||
}
|
||||
u_int high, low;
|
||||
|
||||
high = isonum_733(p->dev_t_high);
|
||||
low = isonum_733(p->dev_t_low);
|
||||
|
||||
if (high == 0)
|
||||
ana->inop->inode.iso_rdev = makedev(major(low), minor(low));
|
||||
else
|
||||
ana->inop->inode.iso_rdev = makedev(high, minor(low));
|
||||
ana->fields &= ~ISO_SUSP_DEVICE;
|
||||
return ISO_SUSP_DEVICE;
|
||||
}
|
||||
@ -475,8 +474,6 @@ cd9660_rrip_stop(p,ana)
|
||||
ISO_SUSP_HEADER *p;
|
||||
ISO_RRIP_ANALYZE *ana;
|
||||
{
|
||||
/* stop analyzing */
|
||||
ana->fields = 0;
|
||||
return ISO_SUSP_STOP;
|
||||
}
|
||||
|
||||
@ -545,22 +542,30 @@ cd9660_rrip_loop(isodir,ana,table)
|
||||
if (!ana->fields)
|
||||
break;
|
||||
}
|
||||
if (result&ISO_SUSP_STOP) {
|
||||
result &= ~ISO_SUSP_STOP;
|
||||
break;
|
||||
}
|
||||
/* plausibility check */
|
||||
if (isonum_711(phead->length) < sizeof(*phead))
|
||||
break;
|
||||
/*
|
||||
* move to next SUSP
|
||||
* Hopefully this works with newer versions, too
|
||||
*/
|
||||
phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
|
||||
}
|
||||
|
||||
if ( ana->fields && ana->iso_ce_len ) {
|
||||
|
||||
if (ana->fields && ana->iso_ce_len) {
|
||||
if (ana->iso_ce_blk >= ana->imp->volume_space_size
|
||||
|| ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
|
||||
|| bread(ana->imp->im_devvp,
|
||||
iso_lblktodaddr(ana->imp, ana->iso_ce_blk),
|
||||
ana->imp->logical_block_size,NOCRED,&bp))
|
||||
ana->iso_ce_blk <<
|
||||
(ana->imp->im_bshift - DEV_BSHIFT),
|
||||
ana->imp->logical_block_size, NOCRED, &bp))
|
||||
/* what to do now? */
|
||||
break;
|
||||
phead = (ISO_SUSP_HEADER *)(bp->b_un.b_addr + ana->iso_ce_off);
|
||||
phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off);
|
||||
pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
|
||||
} else
|
||||
break;
|
||||
@ -569,7 +574,7 @@ cd9660_rrip_loop(isodir,ana,table)
|
||||
brelse(bp);
|
||||
/*
|
||||
* If we don't find the Basic SUSP stuffs, just set default value
|
||||
* ( attribute/time stamp )
|
||||
* (attribute/time stamp)
|
||||
*/
|
||||
for (ptable = table; ptable->func2; ptable++)
|
||||
if (!(ptable->result&result))
|
||||
@ -578,6 +583,9 @@ cd9660_rrip_loop(isodir,ana,table)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get Attributes.
|
||||
*/
|
||||
/*
|
||||
* XXX the casts are bogus but will do for now.
|
||||
*/
|
||||
@ -607,10 +615,8 @@ cd9660_rrip_analyze(isodir,inop,imp)
|
||||
return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get Alternate Name from 'AL' record
|
||||
* If either no AL record or 0 length,
|
||||
* it will be return the translated ISO9660 name,
|
||||
/*
|
||||
* Get Alternate Name.
|
||||
*/
|
||||
static RRIP_TABLE rrip_table_getname[] = {
|
||||
{ "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME },
|
||||
@ -654,10 +660,8 @@ cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
|
||||
return cd9660_rrip_loop(isodir,&analyze,tab);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get Symbolic Name from 'SL' record
|
||||
*
|
||||
* Note: isodir should contains SL record!
|
||||
/*
|
||||
* Get Symbolic Link.
|
||||
*/
|
||||
static RRIP_TABLE rrip_table_getsymname[] = {
|
||||
{ "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK },
|
||||
@ -696,7 +700,7 @@ static RRIP_TABLE rrip_table_extref[] = {
|
||||
|
||||
/*
|
||||
* Check for Rock Ridge Extension and return offset of its fields.
|
||||
* Note: We require the ER field.
|
||||
* Note: We insist on the ER field.
|
||||
*/
|
||||
int
|
||||
cd9660_rrip_offset(isodir,imp)
|
||||
|
@ -35,36 +35,30 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)cd9660_rrip.h 8.1 (Berkeley) 1/21/94
|
||||
* $FreeBSD$
|
||||
* @(#)cd9660_rrip.h 8.2 (Berkeley) 12/5/94
|
||||
* $Id: cd9660_rrip.h,v 1.3.2000.1 1996/09/30 12:46:48 dfr Exp $
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
char type [ISODCL ( 0, 1)];
|
||||
unsigned char length [ISODCL ( 2, 2)]; /* 711 */
|
||||
unsigned char version [ISODCL ( 3, 3)];
|
||||
char type [ISODCL ( 0, 1)];
|
||||
u_char length [ISODCL ( 2, 2)]; /* 711 */
|
||||
u_char version [ISODCL ( 3, 3)];
|
||||
} ISO_SUSP_HEADER;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
char mode_l [ISODCL ( 4, 7)]; /* 731 */
|
||||
char mode_m [ISODCL ( 8, 11)]; /* 732 */
|
||||
char links_l [ISODCL ( 12, 15)]; /* 731 */
|
||||
char links_m [ISODCL ( 16, 19)]; /* 732 */
|
||||
char uid_l [ISODCL ( 20, 23)]; /* 731 */
|
||||
char uid_m [ISODCL ( 24, 27)]; /* 732 */
|
||||
char gid_l [ISODCL ( 28, 31)]; /* 731 */
|
||||
char gid_m [ISODCL ( 32, 35)]; /* 732 */
|
||||
char mode [ISODCL ( 4, 11)]; /* 733 */
|
||||
char links [ISODCL ( 12, 19)]; /* 733 */
|
||||
char uid [ISODCL ( 20, 27)]; /* 733 */
|
||||
char gid [ISODCL ( 28, 35)]; /* 733 */
|
||||
} ISO_RRIP_ATTR;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
char dev_t_high_l [ISODCL ( 4, 7)]; /* 731 */
|
||||
char dev_t_high_m [ISODCL ( 8, 11)]; /* 732 */
|
||||
char dev_t_low_l [ISODCL ( 12, 15)]; /* 731 */
|
||||
char dev_t_low_m [ISODCL ( 16, 19)]; /* 732 */
|
||||
char dev_t_high [ISODCL ( 4, 11)]; /* 733 */
|
||||
char dev_t_low [ISODCL ( 12, 19)]; /* 733 */
|
||||
} ISO_RRIP_DEVICE;
|
||||
|
||||
|
||||
#define ISO_SUSP_CFLAG_CONTINUE 0x01
|
||||
#define ISO_SUSP_CFLAG_CURRENT 0x02
|
||||
#define ISO_SUSP_CFLAG_PARENT 0x04
|
||||
@ -73,9 +67,9 @@ typedef struct {
|
||||
#define ISO_SUSP_CFLAG_HOST 0x20
|
||||
|
||||
typedef struct {
|
||||
u_char cflag [ISODCL ( 1, 1)];
|
||||
u_char clen [ISODCL ( 2, 2)];
|
||||
u_char name [0];
|
||||
u_char cflag [ISODCL ( 1, 1)];
|
||||
u_char clen [ISODCL ( 2, 2)];
|
||||
u_char name [1]; /* XXX */
|
||||
} ISO_RRIP_SLINK_COMPONENT;
|
||||
#define ISO_RRIP_SLSIZ 2
|
||||
|
||||
@ -116,13 +110,13 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
unsigned char flags [ISODCL ( 4, 4)];
|
||||
unsigned char time [ISODCL ( 5, 5)];
|
||||
u_char flags [ISODCL ( 4, 4)];
|
||||
u_char time [ISODCL ( 5, 5)];
|
||||
} ISO_RRIP_TSTAMP;
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
unsigned char flags [ISODCL ( 4, 4)];
|
||||
u_char flags [ISODCL ( 4, 4)];
|
||||
} ISO_RRIP_IDFLAG;
|
||||
|
||||
typedef struct {
|
||||
|
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)cd9660_util.c 8.1 (Berkeley) 1/21/94
|
||||
* @(#)cd9660_util.c 8.3 (Berkeley) 12/5/94
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -58,104 +58,14 @@
|
||||
|
||||
#include <isofs/cd9660/iso.h>
|
||||
|
||||
#ifdef __notanymore__
|
||||
int
|
||||
isonum_711 (p)
|
||||
unsigned char *p;
|
||||
{
|
||||
return (*p);
|
||||
}
|
||||
|
||||
int
|
||||
isonum_712 (p)
|
||||
signed char *p;
|
||||
{
|
||||
return (*p);
|
||||
}
|
||||
|
||||
int
|
||||
isonum_721 (p)
|
||||
unsigned char *p;
|
||||
{
|
||||
/* little endian short */
|
||||
#if BYTE_ORDER != LITTLE_ENDIAN
|
||||
printf ("isonum_721 called on non little-endian machine!\n");
|
||||
#endif
|
||||
|
||||
return *(short *)p;
|
||||
}
|
||||
|
||||
int
|
||||
isonum_722 (p)
|
||||
unsigned char *p;
|
||||
{
|
||||
/* big endian short */
|
||||
#if BYTE_ORDER != BIG_ENDIAN
|
||||
printf ("isonum_722 called on non big-endian machine!\n");
|
||||
#endif
|
||||
|
||||
return *(short *)p;
|
||||
}
|
||||
|
||||
int
|
||||
isonum_723 (p)
|
||||
unsigned char *p;
|
||||
{
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
return isonum_722 (p + 2);
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
return isonum_721 (p);
|
||||
#else
|
||||
printf ("isonum_723 unsupported byte order!\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
isonum_731 (p)
|
||||
unsigned char *p;
|
||||
{
|
||||
/* little endian long */
|
||||
#if BYTE_ORDER != LITTLE_ENDIAN
|
||||
printf ("isonum_731 called on non little-endian machine!\n");
|
||||
#endif
|
||||
|
||||
return *(long *)p;
|
||||
}
|
||||
|
||||
int
|
||||
isonum_732 (p)
|
||||
unsigned char *p;
|
||||
{
|
||||
/* big endian long */
|
||||
#if BYTE_ORDER != BIG_ENDIAN
|
||||
printf ("isonum_732 called on non big-endian machine!\n");
|
||||
#endif
|
||||
|
||||
return *(long *)p;
|
||||
}
|
||||
|
||||
int
|
||||
isonum_733 (p)
|
||||
unsigned char *p;
|
||||
{
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
return isonum_732 (p + 4);
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
return isonum_731 (p);
|
||||
#else
|
||||
printf ("isonum_733 unsupported byte order!\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif /* __notanymore__ */
|
||||
|
||||
/*
|
||||
* translate and compare a filename
|
||||
* Note: Version number plus ';' may be omitted.
|
||||
*/
|
||||
int
|
||||
isofncmp(unsigned char *fn,int fnlen,unsigned char *isofn,int isolen)
|
||||
isofncmp(fn, fnlen, isofn, isolen)
|
||||
u_char *fn, *isofn;
|
||||
int fnlen, isolen;
|
||||
{
|
||||
int i, j;
|
||||
unsigned char c;
|
||||
@ -211,9 +121,12 @@ isofncmp(unsigned char *fn,int fnlen,unsigned char *isofn,int isolen)
|
||||
* translate a filename
|
||||
*/
|
||||
void
|
||||
isofntrans(unsigned char *infn,int infnlen,
|
||||
unsigned char *outfn,unsigned short *outfnlen,
|
||||
int original,int assoc)
|
||||
isofntrans(infn, infnlen, outfn, outfnlen, original, assoc)
|
||||
u_char *infn, *outfn;
|
||||
int infnlen;
|
||||
u_short *outfnlen;
|
||||
int original;
|
||||
int assoc;
|
||||
{
|
||||
int fnidx = 0;
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)cd9660_vfsops.c 8.3 (Berkeley) 1/31/94
|
||||
* @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -52,10 +52,12 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <isofs/cd9660/iso.h>
|
||||
#include <isofs/cd9660/cd9660_node.h>
|
||||
#include <isofs/cd9660/iso_rrip.h>
|
||||
#include <isofs/cd9660/cd9660_node.h>
|
||||
#include <isofs/cd9660/cd9660_mount.h>
|
||||
|
||||
|
||||
static int cd9660_mount __P((struct mount *,
|
||||
@ -84,17 +86,14 @@ static struct vfsops cd9660_vfsops = {
|
||||
cd9660_vget,
|
||||
cd9660_fhtovp,
|
||||
cd9660_vptofh,
|
||||
cd9660_init,
|
||||
cd9660_init
|
||||
};
|
||||
VFS_SET(cd9660_vfsops, cd9660, MOUNT_CD9660, VFCF_READONLY);
|
||||
|
||||
|
||||
/*
|
||||
* Called by vfs_mountroot when iso is going to be mounted as root.
|
||||
*
|
||||
* Name is updated by mount(8) after booting.
|
||||
*/
|
||||
#define ROOTNAME "root_device"
|
||||
|
||||
static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
|
||||
struct proc *p, struct iso_args *argp));
|
||||
@ -102,54 +101,37 @@ static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
|
||||
int
|
||||
cd9660_mountroot()
|
||||
{
|
||||
register struct mount *mp;
|
||||
struct mount *mp;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct iso_mnt *imp;
|
||||
u_int size;
|
||||
int error;
|
||||
struct iso_args args;
|
||||
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Get vnode for rootdev.
|
||||
*/
|
||||
if (bdevvp(rootdev, &rootvp))
|
||||
panic("cd9660_mountroot: can't setup bdevvp for rootdev");
|
||||
if ((error = bdevvp(swapdev, &swapdev_vp)) ||
|
||||
(error = bdevvp(rootdev, &rootvp))) {
|
||||
printf("cd9660_mountroot: can't setup bdevvp's");
|
||||
return (error);
|
||||
}
|
||||
|
||||
mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
|
||||
bzero((char *)mp, (u_long)sizeof(struct mount));
|
||||
mp->mnt_op = &cd9660_vfsops;
|
||||
mp->mnt_flag = MNT_RDONLY;
|
||||
if (error = vfs_rootmountalloc("cd9660", "root_device", &mp))
|
||||
return (error);
|
||||
args.flags = ISOFSMNT_ROOT;
|
||||
if ((error = iso_mountfs(rootvp, mp, p, &args))) {
|
||||
free(mp, M_MOUNT);
|
||||
return (error);
|
||||
}
|
||||
if ((error = vfs_lock(mp))) {
|
||||
(void)cd9660_unmount(mp, 0, p);
|
||||
if (error = iso_mountfs(rootvp, mp, p, &args)) {
|
||||
mp->mnt_vfc->vfc_refcount--;
|
||||
vfs_unbusy(mp, p);
|
||||
free(mp, M_MOUNT);
|
||||
return (error);
|
||||
}
|
||||
simple_lock(&mountlist_slock);
|
||||
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
|
||||
mp->mnt_flag |= MNT_ROOTFS;
|
||||
mp->mnt_vnodecovered = NULLVP;
|
||||
imp = VFSTOISOFS(mp);
|
||||
bzero(imp->im_fsmnt, sizeof(imp->im_fsmnt));
|
||||
imp->im_fsmnt[0] = '/';
|
||||
bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
|
||||
MNAMELEN);
|
||||
(void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
|
||||
&size);
|
||||
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
|
||||
(void) cd9660_statfs(mp, &mp->mnt_stat, p);
|
||||
vfs_unlock(mp);
|
||||
simple_unlock(&mountlist_slock);
|
||||
(void)cd9660_statfs(mp, &mp->mnt_stat, p);
|
||||
vfs_unbusy(mp, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flag to allow forcible unmounting.
|
||||
*/
|
||||
static int iso_doforce = 1;
|
||||
|
||||
/*
|
||||
* VFS Operations.
|
||||
*
|
||||
@ -214,10 +196,8 @@ cd9660_mount(mp, path, data, ndp, p)
|
||||
return error;
|
||||
}
|
||||
imp = VFSTOISOFS(mp);
|
||||
(void) copyinstr(path, imp->im_fsmnt, sizeof(imp->im_fsmnt)-1, &size);
|
||||
bzero(imp->im_fsmnt + size, sizeof(imp->im_fsmnt) - size);
|
||||
bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
|
||||
MNAMELEN);
|
||||
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
|
||||
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
|
||||
(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
|
||||
&size);
|
||||
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
|
||||
@ -277,11 +257,11 @@ iso_mountfs(devvp, mp, p, argp)
|
||||
iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
|
||||
|
||||
for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
|
||||
if ((error = bread (devvp, btodb(iso_blknum * iso_bsize),
|
||||
iso_bsize, NOCRED, &bp)))
|
||||
if (error = bread(devvp, iso_blknum * btodb(iso_bsize),
|
||||
iso_bsize, NOCRED, &bp))
|
||||
goto out;
|
||||
|
||||
vdp = (struct iso_volume_descriptor *)bp->b_un.b_addr;
|
||||
|
||||
vdp = (struct iso_volume_descriptor *)bp->b_data;
|
||||
if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
|
||||
if (bcmp (vdp->id_sierra, ISO_SIERRA_ID,
|
||||
sizeof vdp->id) != 0) {
|
||||
@ -347,7 +327,7 @@ iso_mountfs(devvp, mp, p, argp)
|
||||
|
||||
mp->mnt_data = (qaddr_t)isomp;
|
||||
mp->mnt_stat.f_fsid.val[0] = (long)dev;
|
||||
mp->mnt_stat.f_fsid.val[1] = MOUNT_CD9660;
|
||||
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
|
||||
mp->mnt_maxsymlinklen = 0;
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
isomp->im_mountp = mp;
|
||||
@ -358,14 +338,14 @@ iso_mountfs(devvp, mp, p, argp)
|
||||
|
||||
/* Check the Rock Ridge Extention support */
|
||||
if (!(argp->flags & ISOFSMNT_NORRIP)) {
|
||||
if ((error = bread (isomp->im_devvp,
|
||||
(isomp->root_extent + isonum_711(rootp->ext_attr_length))
|
||||
* isomp->logical_block_size / DEV_BSIZE,
|
||||
isomp->logical_block_size,NOCRED,&bp)))
|
||||
if (error = bread(isomp->im_devvp,
|
||||
(isomp->root_extent + isonum_711(rootp->ext_attr_length)) <<
|
||||
(isomp->im_bshift - DEV_BSHIFT),
|
||||
isomp->logical_block_size, NOCRED, &bp))
|
||||
goto out;
|
||||
|
||||
rootp = (struct iso_directory_record *)bp->b_un.b_addr;
|
||||
|
||||
|
||||
rootp = (struct iso_directory_record *)bp->b_data;
|
||||
|
||||
if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
|
||||
argp->flags |= ISOFSMNT_NORRIP;
|
||||
} else {
|
||||
@ -436,12 +416,9 @@ cd9660_unmount(mp, mntflags, p)
|
||||
{
|
||||
register struct iso_mnt *isomp;
|
||||
int error, flags = 0;
|
||||
|
||||
if (mntflags & MNT_FORCE) {
|
||||
if (!iso_doforce)
|
||||
return (EINVAL);
|
||||
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
}
|
||||
#if 0
|
||||
mntflushbuf(mp, 0);
|
||||
if (mntinvalbuf(mp))
|
||||
@ -474,33 +451,17 @@ cd9660_root(mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
register struct iso_node *ip;
|
||||
struct iso_node tip, *nip;
|
||||
struct vnode tvp;
|
||||
int error;
|
||||
struct iso_mnt *imp = VFSTOISOFS (mp);
|
||||
struct iso_directory_record *dp;
|
||||
|
||||
tvp.v_mount = mp;
|
||||
tvp.v_data = &tip;
|
||||
ip = VTOI(&tvp);
|
||||
ip->i_vnode = &tvp;
|
||||
ip->i_dev = imp->im_dev;
|
||||
ip->i_diroff = 0;
|
||||
dp = (struct iso_directory_record *)imp->root;
|
||||
isodirino(&ip->i_number,dp,imp);
|
||||
|
||||
struct iso_mnt *imp = VFSTOISOFS(mp);
|
||||
struct iso_directory_record *dp =
|
||||
(struct iso_directory_record *)imp->root;
|
||||
ino_t ino = isodirino(dp, imp);
|
||||
|
||||
/*
|
||||
* With RRIP we must use the `.' entry of the root directory.
|
||||
* Simply tell iget, that it's a relocated directory.
|
||||
* Simply tell vget, that it's a relocated directory.
|
||||
*/
|
||||
error = iso_iget(ip,ip->i_number,
|
||||
imp->iso_ftype == ISO_FTYPE_RRIP,
|
||||
&nip,dp);
|
||||
if (error)
|
||||
return error;
|
||||
*vpp = ITOV(nip);
|
||||
return 0;
|
||||
return (cd9660_vget_internal(mp, ino, vpp,
|
||||
imp->iso_ftype == ISO_FTYPE_RRIP, dp));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -541,10 +502,8 @@ cd9660_statfs(mp, sbp, p)
|
||||
sbp->f_files = 0; /* total files */
|
||||
sbp->f_ffree = 0; /* free file nodes */
|
||||
if (sbp != &mp->mnt_stat) {
|
||||
bcopy((caddr_t)mp->mnt_stat.f_mntonname,
|
||||
(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
|
||||
bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
|
||||
(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
|
||||
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
|
||||
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
|
||||
}
|
||||
/* Use the first spare for flags: */
|
||||
sbp->f_spare[0] = isomp->im_flags;
|
||||
@ -562,21 +521,6 @@ cd9660_sync(mp, waitfor, cred, p)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flat namespace lookup.
|
||||
* Currently unsupported.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
cd9660_vget(mp, ino, vpp)
|
||||
struct mount *mp;
|
||||
ino_t ino;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
* File handle to vnode
|
||||
*
|
||||
@ -604,92 +548,262 @@ cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
|
||||
int *exflagsp;
|
||||
struct ucred **credanonp;
|
||||
{
|
||||
struct vnode tvp;
|
||||
int error;
|
||||
int lbn, off;
|
||||
struct ifid *ifhp;
|
||||
struct iso_mnt *imp;
|
||||
struct buf *bp;
|
||||
struct iso_directory_record *dirp;
|
||||
struct iso_node tip, *ip, *nip;
|
||||
struct netcred *np;
|
||||
|
||||
imp = VFSTOISOFS (mp);
|
||||
ifhp = (struct ifid *)fhp;
|
||||
|
||||
struct ifid *ifhp = (struct ifid *)fhp;
|
||||
register struct iso_node *ip;
|
||||
register struct netcred *np;
|
||||
register struct iso_mnt *imp = VFSTOISOFS(mp);
|
||||
struct vnode *nvp;
|
||||
int error;
|
||||
|
||||
#ifdef ISOFS_DBG
|
||||
printf("fhtovp: ino %d, start %ld\n",
|
||||
ifhp->ifid_ino, ifhp->ifid_start);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Get the export permission structure for this <mp, client> tuple.
|
||||
*/
|
||||
np = vfs_export_lookup(mp, &imp->im_export, nam);
|
||||
if (np == NULL)
|
||||
return (EACCES);
|
||||
|
||||
lbn = iso_lblkno(imp, ifhp->ifid_ino);
|
||||
if (lbn >= imp->volume_space_size) {
|
||||
printf("fhtovp: lbn exceed volume space %d\n", lbn);
|
||||
return (ESTALE);
|
||||
}
|
||||
|
||||
off = iso_blkoff(imp, ifhp->ifid_ino);
|
||||
if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
|
||||
printf("fhtovp: crosses block boundary %d\n",
|
||||
off + ISO_DIRECTORY_RECORD_SIZE);
|
||||
return (ESTALE);
|
||||
}
|
||||
|
||||
error = bread(imp->im_devvp, btodb(lbn * imp->logical_block_size),
|
||||
imp->logical_block_size, NOCRED, &bp);
|
||||
if (error) {
|
||||
printf("fhtovp: bread error %d\n",error);
|
||||
brelse(bp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
dirp = (struct iso_directory_record *)(bp->b_un.b_addr + off);
|
||||
if (off + isonum_711(dirp->length) > imp->logical_block_size) {
|
||||
brelse(bp);
|
||||
printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
|
||||
off+isonum_711(dirp->length), off,
|
||||
isonum_711(dirp->length));
|
||||
return (ESTALE);
|
||||
}
|
||||
|
||||
if (isonum_733(dirp->extent) + isonum_711(dirp->ext_attr_length) !=
|
||||
ifhp->ifid_start) {
|
||||
brelse(bp);
|
||||
printf("fhtovp: file start miss %d vs %ld\n",
|
||||
isonum_733(dirp->extent)+isonum_711(dirp->ext_attr_length),
|
||||
ifhp->ifid_start);
|
||||
return (ESTALE);
|
||||
}
|
||||
brelse(bp);
|
||||
|
||||
ip = &tip;
|
||||
tvp.v_mount = mp;
|
||||
tvp.v_data = ip;
|
||||
ip->i_vnode = &tvp;
|
||||
ip->i_dev = imp->im_dev;
|
||||
if ((error = iso_iget(ip, ifhp->ifid_ino, 0, &nip, dirp))) {
|
||||
if (error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) {
|
||||
*vpp = NULLVP;
|
||||
printf("fhtovp: failed to get inode\n");
|
||||
return (error);
|
||||
}
|
||||
ip = nip;
|
||||
ip = VTOI(nvp);
|
||||
if (ip->inode.iso_mode == 0) {
|
||||
vput(nvp);
|
||||
*vpp = NULLVP;
|
||||
return (ESTALE);
|
||||
}
|
||||
*vpp = nvp;
|
||||
*exflagsp = np->netc_exflags;
|
||||
*credanonp = &np->netc_anon;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_vget(mp, ino, vpp)
|
||||
struct mount *mp;
|
||||
ino_t ino;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
|
||||
/*
|
||||
* XXXX
|
||||
* It would be nice if we didn't always set the `relocated' flag
|
||||
* and force the extra read, but I don't want to think about fixing
|
||||
* that right now.
|
||||
*/
|
||||
return (cd9660_vget_internal(mp, ino, vpp,
|
||||
#if 0
|
||||
VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
(struct iso_directory_record *)0));
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
|
||||
struct mount *mp;
|
||||
ino_t ino;
|
||||
struct vnode **vpp;
|
||||
int relocated;
|
||||
struct iso_directory_record *isodir;
|
||||
{
|
||||
struct iso_mnt *imp;
|
||||
struct iso_node *ip;
|
||||
struct buf *bp;
|
||||
struct vnode *vp, *nvp;
|
||||
dev_t dev;
|
||||
int error;
|
||||
|
||||
imp = VFSTOISOFS(mp);
|
||||
dev = imp->im_dev;
|
||||
if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
|
||||
return (0);
|
||||
|
||||
/* Allocate a new vnode/iso_node. */
|
||||
if (error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) {
|
||||
*vpp = NULLVP;
|
||||
return (error);
|
||||
}
|
||||
MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE,
|
||||
M_WAITOK);
|
||||
bzero((caddr_t)ip, sizeof(struct iso_node));
|
||||
lockinit(&ip->i_lock, PINOD, "isonode", 0, 0);
|
||||
vp->v_data = ip;
|
||||
ip->i_vnode = vp;
|
||||
ip->i_dev = dev;
|
||||
ip->i_number = ino;
|
||||
|
||||
/*
|
||||
* Put it onto its hash chain and lock it so that other requests for
|
||||
* this inode will block if they arrive while we are sleeping waiting
|
||||
* for old data structures to be purged or for the contents of the
|
||||
* disk portion of this inode to be read.
|
||||
*/
|
||||
cd9660_ihashins(ip);
|
||||
|
||||
if (isodir == 0) {
|
||||
int lbn, off;
|
||||
|
||||
lbn = lblkno(imp, ino);
|
||||
if (lbn >= imp->volume_space_size) {
|
||||
vput(vp);
|
||||
printf("fhtovp: lbn exceed volume space %d\n", lbn);
|
||||
return (ESTALE);
|
||||
}
|
||||
|
||||
off = blkoff(imp, ino);
|
||||
if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
|
||||
vput(vp);
|
||||
printf("fhtovp: crosses block boundary %d\n",
|
||||
off + ISO_DIRECTORY_RECORD_SIZE);
|
||||
return (ESTALE);
|
||||
}
|
||||
|
||||
error = bread(imp->im_devvp,
|
||||
lbn << (imp->im_bshift - DEV_BSHIFT),
|
||||
imp->logical_block_size, NOCRED, &bp);
|
||||
if (error) {
|
||||
vput(vp);
|
||||
brelse(bp);
|
||||
printf("fhtovp: bread error %d\n",error);
|
||||
return (error);
|
||||
}
|
||||
isodir = (struct iso_directory_record *)(bp->b_data + off);
|
||||
|
||||
if (off + isonum_711(isodir->length) >
|
||||
imp->logical_block_size) {
|
||||
vput(vp);
|
||||
if (bp != 0)
|
||||
brelse(bp);
|
||||
printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
|
||||
off +isonum_711(isodir->length), off,
|
||||
isonum_711(isodir->length));
|
||||
return (ESTALE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (isonum_733(isodir->extent) +
|
||||
isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
|
||||
if (bp != 0)
|
||||
brelse(bp);
|
||||
printf("fhtovp: file start miss %d vs %d\n",
|
||||
isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
|
||||
ifhp->ifid_start);
|
||||
return (ESTALE);
|
||||
}
|
||||
#endif
|
||||
} else
|
||||
bp = 0;
|
||||
|
||||
ip->i_mnt = imp;
|
||||
ip->i_devvp = imp->im_devvp;
|
||||
VREF(ip->i_devvp);
|
||||
|
||||
if (relocated) {
|
||||
/*
|
||||
* On relocated directories we must
|
||||
* read the `.' entry out of a dir.
|
||||
*/
|
||||
ip->iso_start = ino >> imp->im_bshift;
|
||||
if (bp != 0)
|
||||
brelse(bp);
|
||||
if (error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) {
|
||||
vput(vp);
|
||||
return (error);
|
||||
}
|
||||
isodir = (struct iso_directory_record *)bp->b_data;
|
||||
}
|
||||
|
||||
ip->iso_extent = isonum_733(isodir->extent);
|
||||
ip->i_size = isonum_733(isodir->size);
|
||||
ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
|
||||
|
||||
/*
|
||||
* Setup time stamp, attribute
|
||||
*/
|
||||
vp->v_type = VNON;
|
||||
switch (imp->iso_ftype) {
|
||||
default: /* ISO_FTYPE_9660 */
|
||||
{
|
||||
struct buf *bp2;
|
||||
int off;
|
||||
if ((imp->im_flags & ISOFSMNT_EXTATT)
|
||||
&& (off = isonum_711(isodir->ext_attr_length)))
|
||||
VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL,
|
||||
&bp2);
|
||||
else
|
||||
bp2 = NULL;
|
||||
cd9660_defattr(isodir, ip, bp2, ISO_FTYPE_9660);
|
||||
cd9660_deftstamp(isodir, ip, bp2, ISO_FTYPE_9660);
|
||||
if (bp2)
|
||||
brelse(bp2);
|
||||
break;
|
||||
}
|
||||
case ISO_FTYPE_RRIP:
|
||||
cd9660_rrip_analyze(isodir, ip, imp);
|
||||
break;
|
||||
}
|
||||
|
||||
if (bp != 0)
|
||||
brelse(bp);
|
||||
|
||||
/*
|
||||
* Initialize the associated vnode
|
||||
*/
|
||||
switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
|
||||
case VFIFO:
|
||||
#ifdef FIFO
|
||||
vp->v_op = cd9660_fifoop_p;
|
||||
break;
|
||||
#else
|
||||
vput(vp);
|
||||
return (EOPNOTSUPP);
|
||||
#endif /* FIFO */
|
||||
case VCHR:
|
||||
case VBLK:
|
||||
/*
|
||||
* if device, look at device number table for translation
|
||||
*/
|
||||
#ifdef ISODEVMAP
|
||||
if (dp = iso_dmap(dev, ino, 0))
|
||||
ip->inode.iso_rdev = dp->d_dev;
|
||||
#endif
|
||||
vp->v_op = cd9660_specop_p;
|
||||
if (nvp = checkalias(vp, ip->inode.iso_rdev, mp)) {
|
||||
/*
|
||||
* Discard unneeded vnode, but save its iso_node.
|
||||
* Note that the lock is carried over in the iso_node
|
||||
* to the replacement vnode.
|
||||
*/
|
||||
nvp->v_data = vp->v_data;
|
||||
vp->v_data = NULL;
|
||||
vp->v_op = spec_vnodeop_p;
|
||||
vrele(vp);
|
||||
vgone(vp);
|
||||
/*
|
||||
* Reinitialize aliased inode.
|
||||
*/
|
||||
vp = nvp;
|
||||
ip->i_vnode = vp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ip->iso_extent == imp->root_extent)
|
||||
vp->v_flag |= VROOT;
|
||||
|
||||
/*
|
||||
* XXX need generation number?
|
||||
*/
|
||||
if (ip->inode.iso_mode == 0) {
|
||||
iso_iput(ip);
|
||||
*vpp = NULLVP;
|
||||
printf("fhtovp: inode mode == 0\n");
|
||||
return (ESTALE);
|
||||
}
|
||||
*vpp = ITOV(ip);
|
||||
*exflagsp = np->netc_exflags;
|
||||
*credanonp = &np->netc_anon;
|
||||
return 0;
|
||||
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)iso.h 8.2 (Berkeley) 1/23/94
|
||||
* @(#)iso.h 8.6 (Berkeley) 5/10/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -138,37 +138,37 @@ struct iso_sierra_primary_descriptor {
|
||||
struct iso_directory_record {
|
||||
char length [ISODCL (1, 1)]; /* 711 */
|
||||
char ext_attr_length [ISODCL (2, 2)]; /* 711 */
|
||||
unsigned char extent [ISODCL (3, 10)]; /* 733 */
|
||||
unsigned char size [ISODCL (11, 18)]; /* 733 */
|
||||
u_char extent [ISODCL (3, 10)]; /* 733 */
|
||||
u_char size [ISODCL (11, 18)]; /* 733 */
|
||||
char date [ISODCL (19, 25)]; /* 7 by 711 */
|
||||
char flags [ISODCL (26, 26)];
|
||||
char file_unit_size [ISODCL (27, 27)]; /* 711 */
|
||||
char interleave [ISODCL (28, 28)]; /* 711 */
|
||||
char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
|
||||
char name_len [ISODCL (33, 33)]; /* 711 */
|
||||
char name [0];
|
||||
char name [1]; /* XXX */
|
||||
};
|
||||
/* can't take sizeof(iso_directory_record), because of possible alignment
|
||||
of the last entry (34 instead of 33) */
|
||||
#define ISO_DIRECTORY_RECORD_SIZE 33
|
||||
|
||||
struct iso_extended_attributes {
|
||||
unsigned char owner [ISODCL (1, 4)]; /* 723 */
|
||||
unsigned char group [ISODCL (5, 8)]; /* 723 */
|
||||
unsigned char perm [ISODCL (9, 10)]; /* 9.5.3 */
|
||||
u_char owner [ISODCL (1, 4)]; /* 723 */
|
||||
u_char group [ISODCL (5, 8)]; /* 723 */
|
||||
u_char perm [ISODCL (9, 10)]; /* 9.5.3 */
|
||||
char ctime [ISODCL (11, 27)]; /* 8.4.26.1 */
|
||||
char mtime [ISODCL (28, 44)]; /* 8.4.26.1 */
|
||||
char xtime [ISODCL (45, 61)]; /* 8.4.26.1 */
|
||||
char ftime [ISODCL (62, 78)]; /* 8.4.26.1 */
|
||||
char recfmt [ISODCL (79, 79)]; /* 711 */
|
||||
char recattr [ISODCL (80, 80)]; /* 711 */
|
||||
unsigned char reclen [ISODCL (81, 84)]; /* 723 */
|
||||
u_char reclen [ISODCL (81, 84)]; /* 723 */
|
||||
char system_id [ISODCL (85, 116)]; /* achars */
|
||||
char system_use [ISODCL (117, 180)];
|
||||
char version [ISODCL (181, 181)]; /* 711 */
|
||||
char len_esc [ISODCL (182, 182)]; /* 711 */
|
||||
char reserved [ISODCL (183, 246)];
|
||||
unsigned char len_au [ISODCL (247, 250)]; /* 723 */
|
||||
u_char len_au [ISODCL (247, 250)]; /* 723 */
|
||||
};
|
||||
|
||||
/* CD-ROM Format type */
|
||||
@ -191,7 +191,6 @@ struct iso_mnt {
|
||||
int im_bmask;
|
||||
|
||||
int volume_space_size;
|
||||
char im_fsmnt[50];
|
||||
struct netexport im_export;
|
||||
|
||||
char root[ISODCL (157, 190)];
|
||||
@ -205,94 +204,102 @@ struct iso_mnt {
|
||||
|
||||
#define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data))
|
||||
|
||||
#define iso_blkoff(imp, loc) ((loc) & (imp)->im_bmask)
|
||||
#define iso_lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
|
||||
#define iso_blksize(imp, ip, lbn) ((imp)->logical_block_size)
|
||||
#define iso_lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
|
||||
#define iso_lblktodaddr(imp, lbn) btodb(iso_lblktosize(imp, lbn))
|
||||
#define iso_dblkinc(imp, lbn) ((lbn) + iso_lblktodaddr(imp, 1))
|
||||
#define iso_dblkno(imp, loc) iso_lblktodaddr(imp, iso_lblkno(imp, loc))
|
||||
int cd9660_init __P((void));
|
||||
#define blkoff(imp, loc) ((loc) & (imp)->im_bmask)
|
||||
#define lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
|
||||
#define lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
|
||||
#define blksize(imp, ip, lbn) ((imp)->logical_block_size)
|
||||
|
||||
struct iso_node;
|
||||
int iso_blkatoff __P((struct iso_node *ip, long offset, struct buf **bpp));
|
||||
int iso_iget __P((struct iso_node *xp, ino_t ino, int relocated,
|
||||
struct iso_node **ipp, struct iso_directory_record *isodir));
|
||||
int iso_iput __P((struct iso_node *ip));
|
||||
int iso_ilock __P((struct iso_node *ip));
|
||||
int iso_iunlock __P((struct iso_node *ip));
|
||||
int cd9660_mountroot __P((void));
|
||||
int cd9660_vget_internal __P((struct mount *, ino_t, struct vnode **, int,
|
||||
struct iso_directory_record *));
|
||||
int cd9660_init __P((struct vfsconf *));
|
||||
#define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
|
||||
size_t, struct proc *)))eopnotsupp)
|
||||
|
||||
int cd9660_mountroot __P((void));
|
||||
|
||||
extern vop_t **cd9660_vnodeop_p;
|
||||
extern vop_t **cd9660_specop_p;
|
||||
#ifdef FIFO
|
||||
extern vop_t **cd9660_fifoop_p;
|
||||
#endif
|
||||
|
||||
static int isonum_711 __P((unsigned char *p));
|
||||
static int isonum_712 __P((char *p));
|
||||
static int isonum_721 __P((unsigned char *p));
|
||||
static int isonum_722 __P((unsigned char *p));
|
||||
static int isonum_723 __P((unsigned char *p));
|
||||
static int isonum_731 __P((unsigned char *p));
|
||||
static int isonum_732 __P((unsigned char *p));
|
||||
static int isonum_733 __P((unsigned char *p));
|
||||
|
||||
static inline int
|
||||
static __inline int isonum_711 __P((u_char *));
|
||||
static __inline int
|
||||
isonum_711(p)
|
||||
unsigned char *p;
|
||||
u_char *p;
|
||||
{
|
||||
return *p;
|
||||
}
|
||||
|
||||
static inline int
|
||||
static __inline int isonum_712 __P((char *));
|
||||
static __inline int
|
||||
isonum_712(p)
|
||||
char *p;
|
||||
{
|
||||
return *p;
|
||||
}
|
||||
|
||||
static inline int
|
||||
isonum_721(p)
|
||||
unsigned char *p;
|
||||
{
|
||||
return *p|((char)p[1] << 8);
|
||||
}
|
||||
#ifndef UNALIGNED_ACCESS
|
||||
|
||||
static inline int
|
||||
isonum_722(p)
|
||||
unsigned char *p;
|
||||
{
|
||||
return ((char)*p << 8)|p[1];
|
||||
}
|
||||
|
||||
static inline int
|
||||
static __inline int isonum_723 __P((u_char *));
|
||||
static __inline int
|
||||
isonum_723(p)
|
||||
unsigned char *p;
|
||||
u_char *p;
|
||||
{
|
||||
return isonum_721(p);
|
||||
return *p|(p[1] << 8);
|
||||
}
|
||||
|
||||
static inline int
|
||||
isonum_731(p)
|
||||
unsigned char *p;
|
||||
static __inline int isonum_733 __P((u_char *));
|
||||
static __inline int
|
||||
isonum_733(p)
|
||||
u_char *p;
|
||||
{
|
||||
return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
|
||||
}
|
||||
|
||||
static inline int
|
||||
isonum_732(p)
|
||||
unsigned char *p;
|
||||
#else /* UNALIGNED_ACCESS */
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
|
||||
static __inline int
|
||||
isonum_723(p)
|
||||
u_char *p
|
||||
{
|
||||
return (*p << 24)|(p[1] << 16)|(p[2] << 8)|p[3];
|
||||
return *(u_int16t *)p;
|
||||
}
|
||||
|
||||
static inline int
|
||||
static __inline int
|
||||
isonum_733(p)
|
||||
unsigned char *p;
|
||||
u_char *p;
|
||||
{
|
||||
return isonum_731(p);
|
||||
return *(u_int32t *)p;
|
||||
}
|
||||
|
||||
int isofncmp __P((unsigned char *, int, unsigned char *, int));
|
||||
void isofntrans __P((unsigned char *, int, unsigned char *, unsigned short *,
|
||||
int, int));
|
||||
#endif
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
|
||||
static __inline int
|
||||
isonum_723(p)
|
||||
u_char *p
|
||||
{
|
||||
return *(u_int16t *)(p + 2);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
isonum_733(p)
|
||||
u_char *p;
|
||||
{
|
||||
return *(u_int32t *)(p + 4);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* UNALIGNED_ACCESS */
|
||||
|
||||
int isofncmp __P((u_char *, int, u_char *, int));
|
||||
void isofntrans __P((u_char *, int, u_char *, u_short *, int, int));
|
||||
ino_t isodirino __P((struct iso_directory_record *, struct iso_mnt *));
|
||||
|
||||
/*
|
||||
* Associated files have a leading '='.
|
||||
|
@ -77,11 +77,11 @@ static int dead_select __P((struct vop_select_args *));
|
||||
#define dead_inactive ((int (*) __P((struct vop_inactive_args *)))nullop)
|
||||
#define dead_reclaim ((int (*) __P((struct vop_reclaim_args *)))nullop)
|
||||
static int dead_lock __P((struct vop_lock_args *));
|
||||
#define dead_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
|
||||
#define dead_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
|
||||
static int dead_bmap __P((struct vop_bmap_args *));
|
||||
static int dead_strategy __P((struct vop_strategy_args *));
|
||||
static int dead_print __P((struct vop_print_args *));
|
||||
#define dead_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
|
||||
#define dead_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
|
||||
#define dead_pathconf ((int (*) __P((struct vop_pathconf_args *)))dead_ebadf)
|
||||
#define dead_advlock ((int (*) __P((struct vop_advlock_args *)))dead_ebadf)
|
||||
#define dead_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))dead_badop)
|
||||
@ -191,11 +191,20 @@ dead_read(ap)
|
||||
|
||||
if (chkvnlock(ap->a_vp))
|
||||
panic("dead_read: lock");
|
||||
#if 0
|
||||
/* Lite2 behaviour */
|
||||
/*
|
||||
* Return EOF for tty devices, EIO for others
|
||||
*/
|
||||
if ((ap->a_vp->v_flag & VISTTY) == 0)
|
||||
return (EIO);
|
||||
#else
|
||||
/*
|
||||
* Return EOF for character devices, EIO for others
|
||||
*/
|
||||
if (ap->a_vp->v_type != VCHR)
|
||||
return (EIO);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -282,12 +291,23 @@ static int
|
||||
dead_lock(ap)
|
||||
struct vop_lock_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_flags;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
|
||||
if (!chkvnlock(ap->a_vp))
|
||||
/*
|
||||
* Since we are not using the lock manager, we must clear
|
||||
* the interlock here.
|
||||
*/
|
||||
if (ap->a_flags & LK_INTERLOCK) {
|
||||
simple_unlock(&vp->v_interlock);
|
||||
ap->a_flags &= ~LK_INTERLOCK;
|
||||
}
|
||||
if (!chkvnlock(vp))
|
||||
return (0);
|
||||
return (VCALL(ap->a_vp, VOFFSET(vop_lock), ap));
|
||||
return (VCALL(vp, VOFFSET(vop_lock), ap));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -61,8 +61,7 @@ typedef enum {
|
||||
} fdntype;
|
||||
|
||||
struct fdescnode {
|
||||
struct fdescnode *fd_forw; /* Hash chain */
|
||||
struct fdescnode *fd_back;
|
||||
LIST_ENTRY(fdescnode) fd_hash; /* Hash list */
|
||||
struct vnode *fd_vnode; /* Back ptr to vnode */
|
||||
fdntype fd_type; /* Type of this node */
|
||||
unsigned fd_fd; /* Fd to be dup'ed */
|
||||
@ -74,7 +73,7 @@ struct fdescnode {
|
||||
#define VTOFDESC(vp) ((struct fdescnode *)(vp)->v_data)
|
||||
|
||||
extern dev_t devctty;
|
||||
extern int fdesc_init __P((void));
|
||||
extern int fdesc_init __P((struct vfsconf *));
|
||||
extern int fdesc_root __P((struct mount *, struct vnode **));
|
||||
extern int fdesc_allocvp __P((fdntype, int, struct mount *, struct vnode **));
|
||||
extern vop_t **fdesc_vnodeop_p;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* Copyright (c) 1992, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software donated to Berkeley by
|
||||
@ -108,7 +108,7 @@ fdesc_mount(mp, path, data, ndp, p)
|
||||
/* XXX -- don't mark as local to work around fts() problems */
|
||||
/*mp->mnt_flag |= MNT_LOCAL;*/
|
||||
mp->mnt_data = (qaddr_t) fmp;
|
||||
getnewfsid(mp, MOUNT_FDESC);
|
||||
vfs_getnewfsid(mp);
|
||||
|
||||
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
|
||||
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
|
||||
@ -137,12 +137,8 @@ fdesc_unmount(mp, mntflags, p)
|
||||
int flags = 0;
|
||||
struct vnode *rootvp = VFSTOFDESC(mp)->f_root;
|
||||
|
||||
if (mntflags & MNT_FORCE) {
|
||||
/* fdesc can never be rootfs so don't check for it */
|
||||
if (!doforce)
|
||||
return (EINVAL);
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear out buffer cache. I don't think we
|
||||
@ -176,6 +172,7 @@ fdesc_root(mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct vnode *vp;
|
||||
|
||||
/*
|
||||
@ -183,23 +180,11 @@ fdesc_root(mp, vpp)
|
||||
*/
|
||||
vp = VFSTOFDESC(mp)->f_root;
|
||||
VREF(vp);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fdesc_quotactl(mp, cmd, uid, arg, p)
|
||||
struct mount *mp;
|
||||
int cmd;
|
||||
uid_t uid;
|
||||
caddr_t arg;
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
fdesc_statfs(mp, sbp, p)
|
||||
struct mount *mp;
|
||||
@ -233,7 +218,6 @@ fdesc_statfs(mp, sbp, p)
|
||||
if (fdp->fd_nfiles < lim)
|
||||
freefd += (lim - fdp->fd_nfiles);
|
||||
|
||||
sbp->f_type = MOUNT_FDESC;
|
||||
sbp->f_flags = 0;
|
||||
sbp->f_bsize = DEV_BSIZE;
|
||||
sbp->f_iosize = DEV_BSIZE;
|
||||
@ -243,6 +227,7 @@ fdesc_statfs(mp, sbp, p)
|
||||
sbp->f_files = lim + 1; /* Allow for "." */
|
||||
sbp->f_ffree = freefd; /* See comments above */
|
||||
if (sbp != &mp->mnt_stat) {
|
||||
sbp->f_type = mp->mnt_vfc->vfc_typenum;
|
||||
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
|
||||
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
|
||||
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
|
||||
@ -261,41 +246,15 @@ fdesc_sync(mp, waitfor, cred, p)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fdesc flat namespace lookup.
|
||||
* Currently unsupported.
|
||||
*/
|
||||
static int
|
||||
fdesc_vget(mp, ino, vpp)
|
||||
struct mount *mp;
|
||||
ino_t ino;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
fdesc_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
|
||||
struct mount *mp;
|
||||
struct fid *fhp;
|
||||
struct mbuf *nam;
|
||||
struct vnode **vpp;
|
||||
int *exflagsp;
|
||||
struct ucred **credanonp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
fdesc_vptofh(vp, fhp)
|
||||
struct vnode *vp;
|
||||
struct fid *fhp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
#define fdesc_fhtovp ((int (*) __P((struct mount *, struct fid *, \
|
||||
struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
|
||||
#define fdesc_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
|
||||
struct proc *)))eopnotsupp)
|
||||
#define fdesc_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
|
||||
size_t, struct proc *)))eopnotsupp)
|
||||
#define fdesc_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
|
||||
eopnotsupp)
|
||||
#define fdesc_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
|
||||
|
||||
static struct vfsops fdesc_vfsops = {
|
||||
fdesc_mount,
|
||||
|
@ -77,22 +77,14 @@ FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
|
||||
#endif
|
||||
|
||||
#define NFDCACHE 4
|
||||
#define FD_NHASH(ix) ((ix) & NFDCACHE-1)
|
||||
|
||||
/*
|
||||
* Cache head
|
||||
*/
|
||||
struct fdcache {
|
||||
struct fdescnode *fc_forw;
|
||||
struct fdescnode *fc_back;
|
||||
};
|
||||
|
||||
static struct fdcache fdcache[NFDCACHE];
|
||||
#define FD_NHASH(ix) \
|
||||
(&fdhashtbl[(ix) & fdhash])
|
||||
LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
|
||||
u_long fdhash;
|
||||
|
||||
static int fdesc_attr __P((int fd, struct vattr *vap, struct ucred *cred,
|
||||
struct proc *p));
|
||||
static int fdesc_badop __P((void));
|
||||
static int fdesc_enotsupp __P((void));
|
||||
static int fdesc_getattr __P((struct vop_getattr_args *ap));
|
||||
static struct fdcache *
|
||||
fdesc_hash __P((int ix));
|
||||
@ -115,28 +107,15 @@ static int fdesc_write __P((struct vop_write_args *ap));
|
||||
* Initialise cache headers
|
||||
*/
|
||||
int
|
||||
fdesc_init()
|
||||
fdesc_init(vfsp)
|
||||
struct vfsconf *vfsp;
|
||||
{
|
||||
struct fdcache *fc;
|
||||
|
||||
devctty = makedev(nchrdev, 0);
|
||||
|
||||
for (fc = fdcache; fc < fdcache + NFDCACHE; fc++)
|
||||
fc->fc_forw = fc->fc_back = (struct fdescnode *) fc;
|
||||
fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute hash list for given target vnode
|
||||
*/
|
||||
static struct fdcache *
|
||||
fdesc_hash(ix)
|
||||
int ix;
|
||||
{
|
||||
|
||||
return (&fdcache[FD_NHASH(ix)]);
|
||||
}
|
||||
|
||||
int
|
||||
fdesc_allocvp(ftype, ix, mp, vpp)
|
||||
fdntype ftype;
|
||||
@ -144,15 +123,16 @@ fdesc_allocvp(ftype, ix, mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct fdcache *fc;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct fdhashhead *fc;
|
||||
struct fdescnode *fd;
|
||||
int error = 0;
|
||||
|
||||
fc = FD_NHASH(ix);
|
||||
loop:
|
||||
fc = fdesc_hash(ix);
|
||||
for (fd = fc->fc_forw; fd != (struct fdescnode *) fc; fd = fd->fd_forw) {
|
||||
for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) {
|
||||
if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
|
||||
if (vget(fd->fd_vnode, 0))
|
||||
if (vget(fd->fd_vnode, 0, p))
|
||||
goto loop;
|
||||
*vpp = fd->fd_vnode;
|
||||
return (error);
|
||||
@ -188,8 +168,7 @@ fdesc_allocvp(ftype, ix, mp, vpp)
|
||||
fd->fd_fd = -1;
|
||||
fd->fd_link = 0;
|
||||
fd->fd_ix = ix;
|
||||
fc = fdesc_hash(ix);
|
||||
insque(fd, fc);
|
||||
LIST_INSERT_HEAD(fc, fd, fd_hash);
|
||||
|
||||
out:;
|
||||
fdcache_lock &= ~FDL_LOCKED;
|
||||
@ -216,31 +195,28 @@ fdesc_lookup(ap)
|
||||
{
|
||||
struct vnode **vpp = ap->a_vpp;
|
||||
struct vnode *dvp = ap->a_dvp;
|
||||
char *pname;
|
||||
struct proc *p;
|
||||
int nfiles;
|
||||
unsigned fd = 0;
|
||||
struct componentname *cnp = ap->a_cnp;
|
||||
char *pname = cnp->cn_nameptr;
|
||||
struct proc *p = cnp->cn_proc;
|
||||
int nfiles = p->p_fd->fd_nfiles;
|
||||
unsigned fd;
|
||||
int error;
|
||||
struct vnode *fvp;
|
||||
char *ln;
|
||||
|
||||
if (ap->a_cnp->cn_nameiop == DELETE ||
|
||||
ap->a_cnp->cn_nameiop == RENAME) {
|
||||
if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) {
|
||||
error = EROFS;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
pname = ap->a_cnp->cn_nameptr;
|
||||
if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
if (cnp->cn_namelen == 1 && *pname == '.') {
|
||||
*vpp = dvp;
|
||||
VREF(dvp);
|
||||
VOP_LOCK(dvp);
|
||||
VREF(dvp);
|
||||
vn_lock(dvp, LK_SHARED | LK_RETRY, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
p = ap->a_cnp->cn_proc;
|
||||
nfiles = p->p_fd->fd_nfiles;
|
||||
|
||||
switch (VTOFDESC(dvp)->fd_type) {
|
||||
default:
|
||||
case Flink:
|
||||
@ -250,17 +226,17 @@ fdesc_lookup(ap)
|
||||
goto bad;
|
||||
|
||||
case Froot:
|
||||
if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
|
||||
if (cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
|
||||
error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp);
|
||||
if (error)
|
||||
goto bad;
|
||||
*vpp = fvp;
|
||||
fvp->v_type = VDIR;
|
||||
VOP_LOCK(fvp);
|
||||
vn_lock(fvp, LK_SHARED | LK_RETRY, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (ap->a_cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
|
||||
if (cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
|
||||
struct vnode *ttyvp = cttyvp(p);
|
||||
if (ttyvp == NULL) {
|
||||
error = ENXIO;
|
||||
@ -271,12 +247,12 @@ fdesc_lookup(ap)
|
||||
goto bad;
|
||||
*vpp = fvp;
|
||||
fvp->v_type = VFIFO;
|
||||
VOP_LOCK(fvp);
|
||||
vn_lock(fvp, LK_SHARED | LK_RETRY, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
ln = 0;
|
||||
switch (ap->a_cnp->cn_namelen) {
|
||||
switch (cnp->cn_namelen) {
|
||||
case 5:
|
||||
if (bcmp(pname, "stdin", 5) == 0) {
|
||||
ln = "fd/0";
|
||||
@ -302,7 +278,7 @@ fdesc_lookup(ap)
|
||||
VTOFDESC(fvp)->fd_link = ln;
|
||||
*vpp = fvp;
|
||||
fvp->v_type = VLNK;
|
||||
VOP_LOCK(fvp);
|
||||
vn_lock(fvp, LK_SHARED | LK_RETRY, p);
|
||||
return (0);
|
||||
} else {
|
||||
error = ENOENT;
|
||||
@ -312,9 +288,10 @@ fdesc_lookup(ap)
|
||||
/* FALL THROUGH */
|
||||
|
||||
case Fdevfd:
|
||||
if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
|
||||
error = fdesc_root(dvp->v_mount, vpp);
|
||||
return (error);
|
||||
if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
|
||||
if (error = fdesc_root(dvp->v_mount, vpp))
|
||||
goto bad;
|
||||
return (0);
|
||||
}
|
||||
|
||||
fd = 0;
|
||||
@ -338,11 +315,13 @@ fdesc_lookup(ap)
|
||||
if (error)
|
||||
goto bad;
|
||||
VTOFDESC(fvp)->fd_fd = fd;
|
||||
vn_lock(fvp, LK_SHARED | LK_RETRY, p);
|
||||
*vpp = fvp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
bad:;
|
||||
vn_lock(dvp, LK_SHARED | LK_RETRY, p);
|
||||
*vpp = NULL;
|
||||
return (error);
|
||||
}
|
||||
@ -402,10 +381,10 @@ fdesc_attr(fd, vap, cred, p)
|
||||
error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
|
||||
if (error == 0 && vap->va_type == VDIR) {
|
||||
/*
|
||||
* don't allow directories to show up because
|
||||
* that causes loops in the namespace.
|
||||
* directories can cause loops in the namespace,
|
||||
* so turn off the 'x' bits to avoid trouble.
|
||||
*/
|
||||
vap->va_type = VFIFO;
|
||||
vap->va_mode &= ~((VEXEC)|(VEXEC>>3)|(VEXEC>>6));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -591,6 +570,9 @@ fdesc_readdir(ap)
|
||||
struct vnode *a_vp;
|
||||
struct uio *a_uio;
|
||||
struct ucred *a_cred;
|
||||
int *a_eofflag;
|
||||
u_long *a_cookies;
|
||||
int a_ncookies;
|
||||
} */ *ap;
|
||||
{
|
||||
struct uio *uio = ap->a_uio;
|
||||
@ -598,6 +580,13 @@ fdesc_readdir(ap)
|
||||
int i;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* We don't allow exporting fdesc mounts, and currently local
|
||||
* requests do not need cookies.
|
||||
*/
|
||||
if (ap->a_ncookies)
|
||||
panic("fdesc_readdir: not hungry");
|
||||
|
||||
switch (VTOFDESC(ap->a_vp)->fd_type) {
|
||||
case Fctty:
|
||||
return (0);
|
||||
@ -814,6 +803,7 @@ static int
|
||||
fdesc_inactive(ap)
|
||||
struct vop_inactive_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
@ -822,6 +812,7 @@ fdesc_inactive(ap)
|
||||
* Clear out the v_type field to avoid
|
||||
* nasty things happening in vgone().
|
||||
*/
|
||||
VOP_UNLOCK(vp, 0, ap->a_p);
|
||||
vp->v_type = VNON;
|
||||
return (0);
|
||||
}
|
||||
@ -833,8 +824,9 @@ fdesc_reclaim(ap)
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct fdescnode *fd = VTOFDESC(vp);
|
||||
|
||||
remque(VTOFDESC(vp));
|
||||
LIST_REMOVE(fd, fd_hash);
|
||||
FREE(vp->v_data, M_TEMP);
|
||||
vp->v_data = 0;
|
||||
|
||||
@ -906,16 +898,6 @@ fdesc_vfree(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* /dev/fd vnode unsupported operation
|
||||
*/
|
||||
static int
|
||||
fdesc_enotsupp()
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
* /dev/fd "should never get here" operation
|
||||
*/
|
||||
@ -927,38 +909,39 @@ fdesc_badop()
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#define fdesc_create ((int (*) __P((struct vop_create_args *)))fdesc_enotsupp)
|
||||
#define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))fdesc_enotsupp)
|
||||
#define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
|
||||
#define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
|
||||
#define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop)
|
||||
#define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop)
|
||||
#define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))fdesc_enotsupp)
|
||||
#define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
|
||||
#define fdesc_revoke vop_revoke
|
||||
#define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
|
||||
#define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
|
||||
#define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp)
|
||||
#define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp)
|
||||
#define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp)
|
||||
#define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp)
|
||||
#define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp)
|
||||
#define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp)
|
||||
#define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
|
||||
#define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
|
||||
#define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
|
||||
#define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
|
||||
#define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
|
||||
#define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
|
||||
#define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
|
||||
#define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop)
|
||||
#define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
|
||||
#define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
|
||||
#define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
|
||||
#define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
|
||||
#define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop)
|
||||
#define fdesc_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
|
||||
#define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))fdesc_enotsupp)
|
||||
#define fdesc_islocked \
|
||||
((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
|
||||
#define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
|
||||
#define fdesc_blkatoff \
|
||||
((int (*) __P((struct vop_blkatoff_args *)))fdesc_enotsupp)
|
||||
#define fdesc_vget ((int (*) __P((struct vop_vget_args *)))fdesc_enotsupp)
|
||||
((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
|
||||
#define fdesc_valloc ((int(*) __P(( \
|
||||
struct vnode *pvp, \
|
||||
int mode, \
|
||||
struct ucred *cred, \
|
||||
struct vnode **vpp))) fdesc_enotsupp)
|
||||
struct vnode **vpp))) eopnotsupp)
|
||||
#define fdesc_truncate \
|
||||
((int (*) __P((struct vop_truncate_args *)))fdesc_enotsupp)
|
||||
#define fdesc_update ((int (*) __P((struct vop_update_args *)))fdesc_enotsupp)
|
||||
#define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))fdesc_enotsupp)
|
||||
((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
|
||||
#define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
|
||||
#define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
|
||||
|
||||
static vop_t **fdesc_vnodeop_p;
|
||||
static struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
|
||||
@ -975,6 +958,7 @@ static struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
|
||||
{ &vop_write_desc, (vop_t *)fdesc_write }, /* write */
|
||||
{ &vop_ioctl_desc, (vop_t *)fdesc_ioctl }, /* ioctl */
|
||||
{ &vop_select_desc, (vop_t *)fdesc_select }, /* select */
|
||||
{ &vop_revoke_desc, (vop_t *)fdesc_revoke }, /* revoke */
|
||||
{ &vop_mmap_desc, (vop_t *)fdesc_mmap }, /* mmap */
|
||||
{ &vop_fsync_desc, (vop_t *)fdesc_fsync }, /* fsync */
|
||||
{ &vop_seek_desc, (vop_t *)fdesc_seek }, /* seek */
|
||||
|
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fifo.h 8.2 (Berkeley) 2/2/94
|
||||
* @(#)fifo.h 8.6 (Berkeley) 5/21/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -51,8 +51,10 @@ int fifo_close __P((struct vop_close_args *));
|
||||
#define fifo_setattr ((int (*) __P((struct vop_setattr_args *)))fifo_ebadf)
|
||||
int fifo_read __P((struct vop_read_args *));
|
||||
int fifo_write __P((struct vop_write_args *));
|
||||
#define fifo_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
|
||||
int fifo_ioctl __P((struct vop_ioctl_args *));
|
||||
int fifo_select __P((struct vop_select_args *));
|
||||
#define fifo_revoke vop_revoke
|
||||
#define fifo_mmap ((int (*) __P((struct vop_mmap_args *)))fifo_badop)
|
||||
#define fifo_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
|
||||
#define fifo_seek ((int (*) __P((struct vop_seek_args *)))fifo_badop)
|
||||
@ -65,11 +67,13 @@ int fifo_select __P((struct vop_select_args *));
|
||||
#define fifo_readdir ((int (*) __P((struct vop_readdir_args *)))fifo_badop)
|
||||
#define fifo_readlink ((int (*) __P((struct vop_readlink_args *)))fifo_badop)
|
||||
#define fifo_abortop ((int (*) __P((struct vop_abortop_args *)))fifo_badop)
|
||||
#define fifo_inactive ((int (*) __P((struct vop_inactive_args *)))nullop)
|
||||
int fifo_inactive __P((struct vop_inactive_args *));
|
||||
#define fifo_reclaim ((int (*) __P((struct vop_reclaim_args *)))nullop)
|
||||
#define fifo_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
|
||||
#define fifo_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
|
||||
int fifo_bmap __P((struct vop_bmap_args *));
|
||||
#define fifo_strategy ((int (*) __P((struct vop_strategy_args *)))fifo_badop)
|
||||
#define fifo_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
|
||||
#define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
|
||||
int fifo_pathconf __P((struct vop_pathconf_args *));
|
||||
int fifo_advlock __P((struct vop_advlock_args *));
|
||||
#define fifo_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))fifo_badop)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* Copyright (c) 1990, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -30,12 +30,12 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fifo_vnops.c 8.2 (Berkeley) 1/4/94
|
||||
* @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/namei.h>
|
||||
@ -44,7 +44,6 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/errno.h>
|
||||
@ -64,8 +63,6 @@ struct fifoinfo {
|
||||
};
|
||||
|
||||
static int fifo_ebadf __P((void));
|
||||
static int fifo_unlock __P((struct vop_unlock_args *));
|
||||
static int fifo_lock __P((struct vop_lock_args *));
|
||||
static int fifo_print __P((struct vop_print_args *));
|
||||
|
||||
vop_t **fifo_vnodeop_p;
|
||||
@ -81,8 +78,10 @@ static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
|
||||
{ &vop_setattr_desc, (vop_t *)fifo_setattr }, /* setattr */
|
||||
{ &vop_read_desc, (vop_t *)fifo_read }, /* read */
|
||||
{ &vop_write_desc, (vop_t *)fifo_write }, /* write */
|
||||
{ &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
|
||||
{ &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
|
||||
{ &vop_select_desc, (vop_t *)fifo_select }, /* select */
|
||||
{ &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
|
||||
{ &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
|
||||
{ &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
|
||||
{ &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
|
||||
@ -149,8 +148,9 @@ fifo_open(ap)
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
register struct fifoinfo *fip;
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct fifoinfo *fip;
|
||||
struct proc *p = ap->a_p;
|
||||
struct socket *rso, *wso;
|
||||
int error;
|
||||
static char openstr[] = "fifo";
|
||||
@ -158,14 +158,14 @@ fifo_open(ap)
|
||||
if ((fip = vp->v_fifoinfo) == NULL) {
|
||||
MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
|
||||
vp->v_fifoinfo = fip;
|
||||
error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, ap->a_p);
|
||||
error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, ap->a_p);
|
||||
if (error) {
|
||||
free(fip, M_VNODE);
|
||||
vp->v_fifoinfo = NULL;
|
||||
return (error);
|
||||
}
|
||||
fip->fi_readsock = rso;
|
||||
error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, ap->a_p);
|
||||
error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, ap->a_p);
|
||||
if (error) {
|
||||
(void)soclose(rso);
|
||||
free(fip, M_VNODE);
|
||||
@ -185,60 +185,52 @@ fifo_open(ap)
|
||||
wso->so_state |= SS_CANTRCVMORE;
|
||||
rso->so_state |= SS_CANTSENDMORE;
|
||||
}
|
||||
error = 0;
|
||||
if ((ap->a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) {
|
||||
if (fip->fi_readers == 0) {
|
||||
fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
|
||||
if (fip->fi_writers > 0)
|
||||
wakeup((caddr_t)&fip->fi_writers);
|
||||
}
|
||||
if (fip->fi_writers == 0) {
|
||||
fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
|
||||
if (fip->fi_readers > 0)
|
||||
wakeup((caddr_t)&fip->fi_readers);
|
||||
}
|
||||
fip->fi_readers++;
|
||||
fip->fi_writers++;
|
||||
}
|
||||
else if (ap->a_mode & FREAD) {
|
||||
if (ap->a_mode & FREAD) {
|
||||
fip->fi_readers++;
|
||||
if (fip->fi_readers == 1) {
|
||||
fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
|
||||
if (fip->fi_writers > 0)
|
||||
wakeup((caddr_t)&fip->fi_writers);
|
||||
}
|
||||
if (!(ap->a_mode & O_NONBLOCK))
|
||||
while (fip->fi_writers == 0) {
|
||||
VOP_UNLOCK(vp);
|
||||
error = tsleep((caddr_t)&fip->fi_readers,
|
||||
PCATCH | PSOCK, openstr, 0);
|
||||
VOP_LOCK(vp);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ap->a_mode & FWRITE) {
|
||||
fip->fi_writers++;
|
||||
if (fip->fi_readers == 0 && (ap->a_mode & O_NONBLOCK)) {
|
||||
error = ENXIO;
|
||||
} else {
|
||||
if (fip->fi_writers == 1) {
|
||||
fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
|
||||
if (fip->fi_readers > 0)
|
||||
wakeup((caddr_t)&fip->fi_readers);
|
||||
if (fip->fi_writers == 1) {
|
||||
fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
|
||||
if (fip->fi_readers > 0)
|
||||
wakeup((caddr_t)&fip->fi_readers);
|
||||
}
|
||||
}
|
||||
if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
|
||||
while (fip->fi_writers == 0) {
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
error = tsleep((caddr_t)&fip->fi_readers,
|
||||
PCATCH | PSOCK, openstr, 0);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
if (error)
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
if (ap->a_mode & FWRITE) {
|
||||
if (ap->a_mode & O_NONBLOCK) {
|
||||
if (fip->fi_readers == 0) {
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
while (fip->fi_readers == 0) {
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
error = tsleep((caddr_t)&fip->fi_writers,
|
||||
PCATCH | PSOCK, openstr, 0);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
if (error)
|
||||
break;
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
|
||||
return (0);
|
||||
bad:
|
||||
VOP_CLOSE(vp, ap->a_mode, ap->a_cred, p);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -255,8 +247,9 @@ fifo_read(ap)
|
||||
struct ucred *a_cred;
|
||||
} */ *ap;
|
||||
{
|
||||
register struct uio *uio = ap->a_uio;
|
||||
register struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
|
||||
struct uio *uio = ap->a_uio;
|
||||
struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
|
||||
struct proc *p = uio->uio_procp;
|
||||
int error, startresid;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
@ -268,10 +261,10 @@ fifo_read(ap)
|
||||
if (ap->a_ioflag & IO_NDELAY)
|
||||
rso->so_state |= SS_NBIO;
|
||||
startresid = uio->uio_resid;
|
||||
VOP_UNLOCK(ap->a_vp);
|
||||
error = soreceive(rso, (struct mbuf **)0, uio,
|
||||
(struct mbuf **)0, (struct mbuf **)0, (int*)0);
|
||||
VOP_LOCK(ap->a_vp);
|
||||
VOP_UNLOCK(ap->a_vp, 0, p);
|
||||
error = soreceive(rso, (struct mbuf **)0, uio, (struct mbuf **)0,
|
||||
(struct mbuf **)0, (int *)0);
|
||||
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
/*
|
||||
* Clear EOF indication after first such return.
|
||||
*/
|
||||
@ -296,6 +289,7 @@ fifo_write(ap)
|
||||
} */ *ap;
|
||||
{
|
||||
struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
|
||||
struct proc *p = ap->a_uio->uio_procp;
|
||||
int error;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
@ -304,9 +298,9 @@ fifo_write(ap)
|
||||
#endif
|
||||
if (ap->a_ioflag & IO_NDELAY)
|
||||
wso->so_state |= SS_NBIO;
|
||||
VOP_UNLOCK(ap->a_vp);
|
||||
VOP_UNLOCK(ap->a_vp, 0, p);
|
||||
error = sosend(wso, (struct mbuf *)0, ap->a_uio, 0, (struct mbuf *)0, 0);
|
||||
VOP_LOCK(ap->a_vp);
|
||||
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
if (ap->a_ioflag & IO_NDELAY)
|
||||
wso->so_state &= ~SS_NBIO;
|
||||
return (error);
|
||||
@ -328,14 +322,23 @@ fifo_ioctl(ap)
|
||||
} */ *ap;
|
||||
{
|
||||
struct file filetmp;
|
||||
int error;
|
||||
|
||||
if (ap->a_command == FIONBIO)
|
||||
return (0);
|
||||
if (ap->a_fflag & FREAD)
|
||||
if (ap->a_fflag & FREAD) {
|
||||
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
|
||||
else
|
||||
error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
if (ap->a_fflag & FWRITE) {
|
||||
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
|
||||
return (soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p));
|
||||
error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
@ -350,12 +353,33 @@ fifo_select(ap)
|
||||
} */ *ap;
|
||||
{
|
||||
struct file filetmp;
|
||||
int ready;
|
||||
|
||||
if (ap->a_fflags & FREAD)
|
||||
if (ap->a_fflags & FREAD) {
|
||||
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
|
||||
else
|
||||
ready = soo_select(&filetmp, ap->a_which, ap->a_p);
|
||||
if (ready)
|
||||
return (ready);
|
||||
}
|
||||
if (ap->a_fflags & FWRITE) {
|
||||
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
|
||||
return (soo_select(&filetmp, ap->a_which, ap->a_p));
|
||||
ready = soo_select(&filetmp, ap->a_which, ap->a_p);
|
||||
if (ready)
|
||||
return (ready);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
fifo_inactive(ap)
|
||||
struct vop_inactive_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -384,31 +408,6 @@ fifo_bmap(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* At the moment we do not do any locking.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
fifo_lock(ap)
|
||||
struct vop_lock_args /* {
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
fifo_unlock(ap)
|
||||
struct vop_unlock_args /* {
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Device close routine
|
||||
*/
|
||||
@ -426,16 +425,16 @@ fifo_close(ap)
|
||||
register struct fifoinfo *fip = vp->v_fifoinfo;
|
||||
int error1, error2;
|
||||
|
||||
if (ap->a_fflag & FWRITE) {
|
||||
fip->fi_writers--;
|
||||
if (fip->fi_writers == 0)
|
||||
socantrcvmore(fip->fi_readsock);
|
||||
}
|
||||
if (ap->a_fflag & FREAD) {
|
||||
fip->fi_readers--;
|
||||
if (fip->fi_readers == 0)
|
||||
socantsendmore(fip->fi_writesock);
|
||||
}
|
||||
if (ap->a_fflag & FWRITE) {
|
||||
fip->fi_writers--;
|
||||
if (fip->fi_writers == 0)
|
||||
socantrcvmore(fip->fi_readsock);
|
||||
}
|
||||
if (vp->v_usecount > 1)
|
||||
return (0);
|
||||
error1 = soclose(fip->fi_readsock);
|
||||
|
@ -124,7 +124,7 @@ msdosfs_hashget(dev, dirclust, diroff)
|
||||
(void) tsleep((caddr_t)dep, PINOD, "msdhgt", 0);
|
||||
break;
|
||||
}
|
||||
if (!vget(DETOV(dep), 1))
|
||||
if (!vget(DETOV(dep), LK_EXCLUSIVE | LK_INTERLOCK, curproc))
|
||||
return dep;
|
||||
break;
|
||||
}
|
||||
@ -259,7 +259,7 @@ deget(pmp, dirclust, diroffset, direntptr, depp)
|
||||
* can't be accessed until we've read it in and have done what we
|
||||
* need to it.
|
||||
*/
|
||||
VOP_LOCK(nvp);
|
||||
vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY, curproc);
|
||||
msdosfs_hashins(ldep);
|
||||
|
||||
/*
|
||||
@ -716,7 +716,7 @@ msdosfs_inactive(ap)
|
||||
printf("msdosfs_inactive(): dep %p, refcnt %ld, mntflag %x, MNT_RDONLY %x\n",
|
||||
dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY);
|
||||
#endif
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
|
||||
if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
|
||||
error = detrunc(dep, (u_long) 0, 0, NOCRED, NULL);
|
||||
dep->de_flag |= DE_UPDATE;
|
||||
@ -726,7 +726,7 @@ msdosfs_inactive(ap)
|
||||
TIMEVAL_TO_TIMESPEC(&time, &ts);
|
||||
deupdat(dep, &ts, 0);
|
||||
}
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, 0, curproc);
|
||||
dep->de_flag = 0;
|
||||
|
||||
/*
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <msdosfs/bpb.h>
|
||||
#include <msdosfs/direntry.h>
|
||||
@ -156,14 +157,14 @@ msdosfs_lookup(ap)
|
||||
VREF(vdp);
|
||||
error = 0;
|
||||
} else if (flags & ISDOTDOT) {
|
||||
VOP_UNLOCK(pdp);
|
||||
error = vget(vdp, 1);
|
||||
VOP_UNLOCK(pdp, 0, curproc);
|
||||
error = vget(vdp, LK_EXCLUSIVE | LK_INTERLOCK, curproc);
|
||||
if (!error && lockparent && (flags & ISLASTCN))
|
||||
error = VOP_LOCK(pdp);
|
||||
error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
|
||||
} else {
|
||||
error = vget(vdp, 1);
|
||||
error = vget(vdp, LK_EXCLUSIVE | LK_INTERLOCK, curproc);
|
||||
if (!lockparent || error || !(flags & ISLASTCN))
|
||||
VOP_UNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, curproc);
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
@ -183,9 +184,9 @@ msdosfs_lookup(ap)
|
||||
}
|
||||
vput(vdp);
|
||||
if (lockparent && pdp != vdp && (flags & ISLASTCN))
|
||||
VOP_UNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, curproc);
|
||||
}
|
||||
error = VOP_LOCK(pdp);
|
||||
error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
|
||||
if (error)
|
||||
return error;
|
||||
vdp = pdp;
|
||||
@ -345,7 +346,7 @@ notfound:;
|
||||
/* dp->de_flag |= DE_UPDATE; never update dos directories */
|
||||
cnp->cn_flags |= SAVENAME;
|
||||
if (!lockparent)/* leave searched dir locked? */
|
||||
VOP_UNLOCK(vdp);
|
||||
VOP_UNLOCK(vdp, 0, curproc);
|
||||
return EJUSTRETURN;
|
||||
}
|
||||
/*
|
||||
@ -398,7 +399,7 @@ foundroot:;
|
||||
}
|
||||
*vpp = DETOV(tdp);
|
||||
if (!lockparent)
|
||||
VOP_UNLOCK(vdp);
|
||||
VOP_UNLOCK(vdp, 0, curproc);
|
||||
if (bp)
|
||||
brelse(bp);
|
||||
return 0;
|
||||
@ -428,7 +429,7 @@ foundroot:;
|
||||
*vpp = DETOV(tdp);
|
||||
cnp->cn_flags |= SAVENAME;
|
||||
if (!lockparent)
|
||||
VOP_UNLOCK(vdp);
|
||||
VOP_UNLOCK(vdp, 0, curproc);
|
||||
if (bp)
|
||||
brelse(bp);
|
||||
return 0;
|
||||
@ -439,16 +440,16 @@ foundroot:;
|
||||
*/
|
||||
pdp = vdp;
|
||||
if (flags & ISDOTDOT) {
|
||||
VOP_UNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, curproc);
|
||||
error = deget(pmp, cluster, diroff, dep, &tdp);
|
||||
if (error) {
|
||||
VOP_LOCK(pdp);
|
||||
vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
|
||||
if (bp)
|
||||
brelse(bp);
|
||||
return error;
|
||||
}
|
||||
if (lockparent && (flags & ISLASTCN)
|
||||
&& (error = VOP_LOCK(pdp))) {
|
||||
&& (error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc))) {
|
||||
vput(DETOV(tdp));
|
||||
return error;
|
||||
}
|
||||
@ -464,7 +465,7 @@ foundroot:;
|
||||
return error;
|
||||
}
|
||||
if (!lockparent || !(flags & ISLASTCN))
|
||||
VOP_UNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, curproc);
|
||||
*vpp = DETOV(tdp);
|
||||
}
|
||||
if (bp)
|
||||
|
@ -130,10 +130,10 @@ msdosfs_mount(mp, path, data, ndp, p)
|
||||
flags = WRITECLOSE;
|
||||
if (mp->mnt_flag & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
if (vfs_busy(mp))
|
||||
if (vfs_busy(mp, LK_NOWAIT, 0, p))
|
||||
return EBUSY;
|
||||
error = vflush(mp, NULLVP, flags);
|
||||
vfs_unbusy(mp);
|
||||
vfs_unbusy(mp, p);
|
||||
}
|
||||
if (!error && (mp->mnt_flag & MNT_RELOAD))
|
||||
/* not yet implemented */
|
||||
@ -707,7 +707,7 @@ msdosfs_sync(mp, waitfor, cred, p)
|
||||
if ((dep->de_flag & (DE_MODIFIED | DE_UPDATE)) == 0 &&
|
||||
vp->v_dirtyblkhd.lh_first == NULL)
|
||||
continue;
|
||||
if (vget(vp, 1)) /* not there anymore? */
|
||||
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) /* not there anymore? */
|
||||
goto loop;
|
||||
error = VOP_FSYNC(vp, cred, waitfor, p);
|
||||
if (error)
|
||||
|
@ -1172,17 +1172,17 @@ msdosfs_rename(ap)
|
||||
*/
|
||||
if (newparent == 0) {
|
||||
/* tddep and fddep point to the same denode here */
|
||||
VOP_LOCK(ap->a_fvp); /* ap->a_fdvp is already locked */
|
||||
vn_lock(ap->a_fvp, LK_EXCLUSIVE | LK_RETRY, curproc); /* ap->a_fdvp is already locked */
|
||||
error = readep(fddep->de_pmp, fdep->de_dirclust,
|
||||
fdep->de_diroffset, &bp, &ep);
|
||||
if (error) {
|
||||
VOP_UNLOCK(ap->a_fvp);
|
||||
VOP_UNLOCK(ap->a_fvp, 0, curproc);
|
||||
goto bad;
|
||||
}
|
||||
bcopy(toname, ep->deName, 11);
|
||||
error = bwrite(bp);
|
||||
if (error) {
|
||||
VOP_UNLOCK(ap->a_fvp);
|
||||
VOP_UNLOCK(ap->a_fvp, 0, curproc);
|
||||
goto bad;
|
||||
}
|
||||
bcopy(toname, fdep->de_Name, 11); /* update denode */
|
||||
@ -1204,7 +1204,7 @@ msdosfs_rename(ap)
|
||||
* will also insure that the directory entry on disk has a
|
||||
* filesize of zero.
|
||||
*/
|
||||
VOP_LOCK(ap->a_fvp);
|
||||
vn_lock(ap->a_fvp, LK_EXCLUSIVE | LK_RETRY, curproc);
|
||||
bcopy(toname, fdep->de_Name, 11); /* update denode */
|
||||
if (fdep->de_Attributes & ATTR_DIRECTORY) {
|
||||
dirsize = fdep->de_FileSize;
|
||||
@ -1216,22 +1216,22 @@ msdosfs_rename(ap)
|
||||
}
|
||||
if (error) {
|
||||
/* should put back filename */
|
||||
VOP_UNLOCK(ap->a_fvp);
|
||||
VOP_UNLOCK(ap->a_fvp, 0, curproc);
|
||||
goto bad;
|
||||
}
|
||||
VOP_LOCK(ap->a_fdvp);
|
||||
vn_lock(ap->a_fdvp, LK_EXCLUSIVE | LK_RETRY, curproc);
|
||||
error = readep(fddep->de_pmp, fddep->de_fndclust,
|
||||
fddep->de_fndoffset, &bp, &ep);
|
||||
if (error) {
|
||||
VOP_UNLOCK(ap->a_fvp);
|
||||
VOP_UNLOCK(ap->a_fdvp);
|
||||
VOP_UNLOCK(ap->a_fvp, 0, curproc);
|
||||
VOP_UNLOCK(ap->a_fdvp, 0, curproc);
|
||||
goto bad;
|
||||
}
|
||||
ep->deName[0] = SLOT_DELETED;
|
||||
error = bwrite(bp);
|
||||
if (error) {
|
||||
VOP_UNLOCK(ap->a_fvp);
|
||||
VOP_UNLOCK(ap->a_fdvp);
|
||||
VOP_UNLOCK(ap->a_fvp, 0, curproc);
|
||||
VOP_UNLOCK(ap->a_fdvp, 0, curproc);
|
||||
goto bad;
|
||||
}
|
||||
if (!sourceisadirectory) {
|
||||
@ -1239,7 +1239,7 @@ msdosfs_rename(ap)
|
||||
fdep->de_diroffset = tddep->de_fndoffset;
|
||||
reinsert(fdep);
|
||||
}
|
||||
VOP_UNLOCK(ap->a_fdvp);
|
||||
VOP_UNLOCK(ap->a_fdvp, 0, curproc);
|
||||
}
|
||||
/* fdep is still locked here */
|
||||
|
||||
@ -1259,19 +1259,19 @@ msdosfs_rename(ap)
|
||||
NOCRED, &bp);
|
||||
if (error) {
|
||||
/* should really panic here, fs is corrupt */
|
||||
VOP_UNLOCK(ap->a_fvp);
|
||||
VOP_UNLOCK(ap->a_fvp, 0, curproc);
|
||||
goto bad;
|
||||
}
|
||||
dotdotp = (struct direntry *) bp->b_data + 1;
|
||||
putushort(dotdotp->deStartCluster, tddep->de_StartCluster);
|
||||
error = bwrite(bp);
|
||||
VOP_UNLOCK(ap->a_fvp);
|
||||
VOP_UNLOCK(ap->a_fvp, 0, curproc);
|
||||
if (error) {
|
||||
/* should really panic here, fs is corrupt */
|
||||
goto bad;
|
||||
}
|
||||
} else
|
||||
VOP_UNLOCK(ap->a_fvp);
|
||||
VOP_UNLOCK(ap->a_fvp, 0, curproc);
|
||||
bad: ;
|
||||
vrele(DETOV(fdep));
|
||||
vrele(DETOV(fddep));
|
||||
|
@ -169,3 +169,15 @@ struct msdosfsmount {
|
||||
(((size) + (pmp)->pm_bpcluster - 1) >> (pmp)->pm_cnshift)
|
||||
|
||||
int msdosfs_init __P((void));
|
||||
|
||||
/*
|
||||
* Arguments to mount MSDOS filesystems.
|
||||
*/
|
||||
struct msdosfs_args {
|
||||
char *fspec; /* blocks special holding the fs to mount */
|
||||
struct export_args export; /* network export information */
|
||||
uid_t uid; /* uid that owns msdosfs files */
|
||||
gid_t gid; /* gid that owns msdosfs files */
|
||||
mode_t mask; /* mask to be applied for msdosfs perms */
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)null.h 8.2 (Berkeley) 1/21/94
|
||||
* @(#)null.h 8.3 (Berkeley) 8/20/94
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -52,8 +52,7 @@ struct null_mount {
|
||||
* A cache of vnode references
|
||||
*/
|
||||
struct null_node {
|
||||
struct null_node *null_forw; /* Hash chain */
|
||||
struct null_node *null_back;
|
||||
LIST_ENTRY(null_node) null_hash; /* Hash list */
|
||||
struct vnode *null_lowervp; /* VREFed once */
|
||||
struct vnode *null_vnode; /* Back pointer */
|
||||
};
|
||||
|
@ -33,13 +33,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)null_subr.c 8.4 (Berkeley) 1/21/94
|
||||
* @(#)null_subr.c 8.7 (Berkeley) 5/14/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/vnode.h>
|
||||
@ -48,11 +49,8 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <miscfs/nullfs/null.h>
|
||||
|
||||
extern int nullfs_init __P((void));
|
||||
|
||||
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
|
||||
#define NNULLNODECACHE 16
|
||||
#define NULL_NHASH(vp) ((((u_long)vp)>>LOG2_SIZEVNODE) & (NNULLNODECACHE-1))
|
||||
|
||||
/*
|
||||
* Null layer cache:
|
||||
@ -62,50 +60,31 @@ extern int nullfs_init __P((void));
|
||||
* alias is removed the lower vnode is vrele'd.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Cache head
|
||||
*/
|
||||
struct null_node_cache {
|
||||
struct null_node *ac_forw;
|
||||
struct null_node *ac_back;
|
||||
};
|
||||
|
||||
static struct null_node_cache null_node_cache[NNULLNODECACHE];
|
||||
#define NULL_NHASH(vp) \
|
||||
(&null_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & null_node_hash])
|
||||
LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
|
||||
u_long null_node_hash;
|
||||
|
||||
static int null_node_alloc __P((struct mount *mp, struct vnode *lowervp,
|
||||
struct vnode **vpp));
|
||||
static struct vnode *
|
||||
null_node_find __P((struct mount *mp, struct vnode *lowervp));
|
||||
static struct null_node_cache *
|
||||
null_node_hash __P((struct vnode *lowervp));
|
||||
|
||||
/*
|
||||
* Initialise cache headers
|
||||
*/
|
||||
int
|
||||
nullfs_init()
|
||||
nullfs_init(vfsp)
|
||||
struct vfsconf *vfsp;
|
||||
{
|
||||
struct null_node_cache *ac;
|
||||
|
||||
#ifdef NULLFS_DIAGNOSTIC
|
||||
printf("nullfs_init\n"); /* printed during system boot */
|
||||
#endif
|
||||
|
||||
for (ac = null_node_cache; ac < null_node_cache + NNULLNODECACHE; ac++)
|
||||
ac->ac_forw = ac->ac_back = (struct null_node *) ac;
|
||||
null_node_hashtbl = hashinit(NNULLNODECACHE, M_CACHE, &null_node_hash);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute hash list for given lower vnode
|
||||
*/
|
||||
static struct null_node_cache *
|
||||
null_node_hash(lowervp)
|
||||
struct vnode *lowervp;
|
||||
{
|
||||
|
||||
return (&null_node_cache[NULL_NHASH(lowervp)]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a VREF'ed alias for lower vnode if already exists, else 0.
|
||||
*/
|
||||
@ -114,7 +93,8 @@ null_node_find(mp, lowervp)
|
||||
struct mount *mp;
|
||||
struct vnode *lowervp;
|
||||
{
|
||||
struct null_node_cache *hd;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct null_node_hashhead *hd;
|
||||
struct null_node *a;
|
||||
struct vnode *vp;
|
||||
|
||||
@ -124,9 +104,9 @@ null_node_find(mp, lowervp)
|
||||
* the lower vnode. If found, the increment the null_node
|
||||
* reference count (but NOT the lower vnode's VREF counter).
|
||||
*/
|
||||
hd = null_node_hash(lowervp);
|
||||
hd = NULL_NHASH(lowervp);
|
||||
loop:
|
||||
for (a = hd->ac_forw; a != (struct null_node *) hd; a = a->null_forw) {
|
||||
for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
|
||||
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
|
||||
vp = NULLTOV(a);
|
||||
/*
|
||||
@ -134,7 +114,7 @@ null_node_find(mp, lowervp)
|
||||
* stuff, but we don't want to lock
|
||||
* the lower node.
|
||||
*/
|
||||
if (vget(vp, 0)) {
|
||||
if (vget(vp, 0, p)) {
|
||||
printf ("null_node_find: vget failed.\n");
|
||||
goto loop;
|
||||
};
|
||||
@ -157,7 +137,7 @@ null_node_alloc(mp, lowervp, vpp)
|
||||
struct vnode *lowervp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct null_node_cache *hd;
|
||||
struct null_node_hashhead *hd;
|
||||
struct null_node *xp;
|
||||
struct vnode *othervp, *vp;
|
||||
int error;
|
||||
@ -194,8 +174,8 @@ null_node_alloc(mp, lowervp, vpp)
|
||||
return 0;
|
||||
};
|
||||
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
|
||||
hd = null_node_hash(lowervp);
|
||||
insque(xp, hd);
|
||||
hd = NULL_NHASH(lowervp);
|
||||
LIST_INSERT_HEAD(hd, xp, null_hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -250,9 +230,8 @@ null_node_create(mp, lowervp, newvpp)
|
||||
#ifdef DIAGNOSTIC
|
||||
if (lowervp->v_usecount < 1) {
|
||||
/* Should never happen... */
|
||||
vprint ("null_node_create: alias ",aliasvp);
|
||||
vprint ("null_node_create: lower ",lowervp);
|
||||
printf ("null_node_create: lower has 0 usecount.\n");
|
||||
vprint ("null_node_create: alias ", aliasvp);
|
||||
vprint ("null_node_create: lower ", lowervp);
|
||||
panic ("null_node_create: lower has 0 usecount.");
|
||||
};
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* Copyright (c) 1992, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software donated to Berkeley by
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/vnode.h>
|
||||
@ -55,7 +55,7 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <miscfs/nullfs/null.h>
|
||||
|
||||
extern int nullfs_init __P((void));
|
||||
extern int nullfs_init __P((struct vfsconf *));
|
||||
|
||||
static int nullfs_fhtovp __P((struct mount *mp, struct fid *fidp,
|
||||
struct mbuf *nam, struct vnode **vpp,
|
||||
@ -146,7 +146,7 @@ nullfs_mount(mp, path, data, ndp, p)
|
||||
/*
|
||||
* Unlock the node (either the lower or the alias)
|
||||
*/
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
/*
|
||||
* Make sure the node alias worked
|
||||
*/
|
||||
@ -166,7 +166,7 @@ nullfs_mount(mp, path, data, ndp, p)
|
||||
if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
mp->mnt_data = (qaddr_t) xmp;
|
||||
getnewfsid(mp, MOUNT_LOFS);
|
||||
vfs_getnewfsid(mp);
|
||||
|
||||
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
|
||||
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
|
||||
@ -212,12 +212,8 @@ nullfs_unmount(mp, mntflags, p)
|
||||
printf("nullfs_unmount(mp = %x)\n", mp);
|
||||
#endif
|
||||
|
||||
if (mntflags & MNT_FORCE) {
|
||||
/* lofs can never be rootfs so don't check for it */
|
||||
if (!doforce)
|
||||
return (EINVAL);
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear out buffer cache. I don't think we
|
||||
@ -259,6 +255,7 @@ nullfs_root(mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct vnode *vp;
|
||||
|
||||
#ifdef NULLFS_DIAGNOSTIC
|
||||
@ -273,7 +270,7 @@ nullfs_root(mp, vpp)
|
||||
*/
|
||||
vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
|
||||
VREF(vp);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
*vpp = vp;
|
||||
return 0;
|
||||
}
|
||||
|
@ -33,7 +33,13 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)null_vnops.c 8.1 (Berkeley) 6/10/93
|
||||
* @(#)null_vnops.c 8.6 (Berkeley) 5/27/95
|
||||
*
|
||||
* Ancestors:
|
||||
* @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
|
||||
* $Id: null_vnops.c,v 1.11.2000.1 1996/09/17 14:32:31 peter Exp $
|
||||
* ...and...
|
||||
* @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -88,13 +94,21 @@
|
||||
* in the arguments and, if a vnode is return by the operation,
|
||||
* stacks a null-node on top of the returned vnode.
|
||||
*
|
||||
* Although bypass handles most operations,
|
||||
* vop_getattr, _inactive, _reclaim, and _print are not bypassed.
|
||||
* Vop_getattr must change the fsid being returned.
|
||||
* Although bypass handles most operations, vop_getattr, vop_lock,
|
||||
* vop_unlock, vop_inactive, vop_reclaim, and vop_print are not
|
||||
* bypassed. Vop_getattr must change the fsid being returned.
|
||||
* Vop_lock and vop_unlock must handle any locking for the
|
||||
* current vnode as well as pass the lock request down.
|
||||
* Vop_inactive and vop_reclaim are not bypassed so that
|
||||
* they can handle freeing null-layer specific data.
|
||||
* Vop_print is not bypassed to avoid excessive debugging
|
||||
* information.
|
||||
* they can handle freeing null-layer specific data. Vop_print
|
||||
* is not bypassed to avoid excessive debugging information.
|
||||
* Also, certain vnode operations change the locking state within
|
||||
* the operation (create, mknod, remove, link, rename, mkdir, rmdir,
|
||||
* and symlink). Ideally these operations should not change the
|
||||
* lock state, but should be changed to let the caller of the
|
||||
* function unlock them. Otherwise all intermediate vnode layers
|
||||
* (such as union, umapfs, etc) must catch these functions to do
|
||||
* the necessary locking at their layer.
|
||||
*
|
||||
*
|
||||
* INSTANTIATING VNODE STACKS
|
||||
@ -178,7 +192,7 @@ static int null_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
|
||||
SYSCTL_INT(_debug, OID_AUTO, nullfs_bug_bypass, CTLFLAG_RW,
|
||||
&null_bug_bypass, 0, "");
|
||||
|
||||
static int null_bypass __P((struct vop_generic_args *ap));
|
||||
int null_bypass __P((struct vop_generic_args *ap));
|
||||
static int null_bwrite __P((struct vop_bwrite_args *ap));
|
||||
static int null_getattr __P((struct vop_getattr_args *ap));
|
||||
static int null_inactive __P((struct vop_inactive_args *ap));
|
||||
@ -211,7 +225,7 @@ static int null_strategy __P((struct vop_strategy_args *ap));
|
||||
* - all mapped vnodes are of our vnode-type (NEEDSWORK:
|
||||
* problems on rmdir'ing mount points and renaming?)
|
||||
*/
|
||||
static int
|
||||
int
|
||||
null_bypass(ap)
|
||||
struct vop_generic_args /* {
|
||||
struct vnodeop_desc *a_desc;
|
||||
@ -254,7 +268,8 @@ null_bypass(ap)
|
||||
* are of our type. Check for and don't map any
|
||||
* that aren't. (We must always map first vp or vclean fails.)
|
||||
*/
|
||||
if (i && (*this_vp_p)->v_op != null_vnodeop_p) {
|
||||
if (i && (*this_vp_p == NULL ||
|
||||
(*this_vp_p)->v_op != null_vnodeop_p)) {
|
||||
old_vps[i] = NULL;
|
||||
} else {
|
||||
old_vps[i] = *this_vp_p;
|
||||
@ -317,6 +332,105 @@ null_bypass(ap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have to carry on the locking protocol on the null layer vnodes
|
||||
* as we progress through the tree. We also have to enforce read-only
|
||||
* if this layer is mounted read-only.
|
||||
*/
|
||||
static int
|
||||
null_lookup(ap)
|
||||
struct vop_lookup_args /* {
|
||||
struct vnode * a_dvp;
|
||||
struct vnode ** a_vpp;
|
||||
struct componentname * a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
struct componentname *cnp = ap->a_cnp;
|
||||
struct proc *p = cnp->cn_proc;
|
||||
int flags = cnp->cn_flags;
|
||||
struct vop_lock_args lockargs;
|
||||
struct vop_unlock_args unlockargs;
|
||||
struct vnode *dvp, *vp;
|
||||
int error;
|
||||
|
||||
if ((flags & ISLASTCN) && (ap->a_dvp->v_mount->mnt_flag & MNT_RDONLY) &&
|
||||
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
|
||||
return (EROFS);
|
||||
error = null_bypass(ap);
|
||||
if (error == EJUSTRETURN && (flags & ISLASTCN) &&
|
||||
(ap->a_dvp->v_mount->mnt_flag & MNT_RDONLY) &&
|
||||
(cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME))
|
||||
error = EROFS;
|
||||
/*
|
||||
* We must do the same locking and unlocking at this layer as
|
||||
* is done in the layers below us. We could figure this out
|
||||
* based on the error return and the LASTCN, LOCKPARENT, and
|
||||
* LOCKLEAF flags. However, it is more expidient to just find
|
||||
* out the state of the lower level vnodes and set ours to the
|
||||
* same state.
|
||||
*/
|
||||
dvp = ap->a_dvp;
|
||||
vp = *ap->a_vpp;
|
||||
if (dvp == vp)
|
||||
return (error);
|
||||
if (!VOP_ISLOCKED(dvp)) {
|
||||
unlockargs.a_vp = dvp;
|
||||
unlockargs.a_flags = 0;
|
||||
unlockargs.a_p = p;
|
||||
vop_nounlock(&unlockargs);
|
||||
}
|
||||
if (vp != NULL && VOP_ISLOCKED(vp)) {
|
||||
lockargs.a_vp = vp;
|
||||
lockargs.a_flags = LK_SHARED;
|
||||
lockargs.a_p = p;
|
||||
vop_nolock(&lockargs);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setattr call. Disallow write attempts if the layer is mounted read-only.
|
||||
*/
|
||||
int
|
||||
null_setattr(ap)
|
||||
struct vop_setattr_args /* {
|
||||
struct vnodeop_desc *a_desc;
|
||||
struct vnode *a_vp;
|
||||
struct vattr *a_vap;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct vattr *vap = ap->a_vap;
|
||||
|
||||
if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
|
||||
vap->va_gid != (gid_t)VNOVAL || vap->va_atime.ts_sec != VNOVAL ||
|
||||
vap->va_mtime.ts_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
|
||||
(vp->v_mount->mnt_flag & MNT_RDONLY))
|
||||
return (EROFS);
|
||||
if (vap->va_size != VNOVAL) {
|
||||
switch (vp->v_type) {
|
||||
case VDIR:
|
||||
return (EISDIR);
|
||||
case VCHR:
|
||||
case VBLK:
|
||||
case VSOCK:
|
||||
case VFIFO:
|
||||
return (0);
|
||||
case VREG:
|
||||
case VLNK:
|
||||
default:
|
||||
/*
|
||||
* Disallow write attempts if the filesystem is
|
||||
* mounted read-only.
|
||||
*/
|
||||
if (vp->v_mount->mnt_flag & MNT_RDONLY)
|
||||
return (EROFS);
|
||||
}
|
||||
}
|
||||
return (null_bypass(ap));
|
||||
}
|
||||
|
||||
/*
|
||||
* We handle getattr only to change the fsid.
|
||||
@ -331,19 +445,90 @@ null_getattr(ap)
|
||||
} */ *ap;
|
||||
{
|
||||
int error;
|
||||
error = null_bypass(ap);
|
||||
if (error)
|
||||
|
||||
if (error = null_bypass(ap))
|
||||
return (error);
|
||||
/* Requires that arguments be restored. */
|
||||
ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
null_access(ap)
|
||||
struct vop_access_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_mode;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
mode_t mode = ap->a_mode;
|
||||
|
||||
/*
|
||||
* Disallow write attempts on read-only layers;
|
||||
* unless the file is a socket, fifo, or a block or
|
||||
* character device resident on the file system.
|
||||
*/
|
||||
if (mode & VWRITE) {
|
||||
switch (vp->v_type) {
|
||||
case VDIR:
|
||||
case VLNK:
|
||||
case VREG:
|
||||
if (vp->v_mount->mnt_flag & MNT_RDONLY)
|
||||
return (EROFS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (null_bypass(ap));
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to process our own vnode lock and then clear the
|
||||
* interlock flag as it applies only to our vnode, not the
|
||||
* vnodes below us on the stack.
|
||||
*/
|
||||
int
|
||||
null_lock(ap)
|
||||
struct vop_lock_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_flags;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
vop_nolock(ap);
|
||||
if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN)
|
||||
return (0);
|
||||
ap->a_flags &= ~LK_INTERLOCK;
|
||||
return (null_bypass(ap));
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to process our own vnode unlock and then clear the
|
||||
* interlock flag as it applies only to our vnode, not the
|
||||
* vnodes below us on the stack.
|
||||
*/
|
||||
int
|
||||
null_unlock(ap)
|
||||
struct vop_unlock_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_flags;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
|
||||
vop_nounlock(ap);
|
||||
ap->a_flags &= ~LK_INTERLOCK;
|
||||
return (null_bypass(ap));
|
||||
}
|
||||
|
||||
int
|
||||
null_inactive(ap)
|
||||
struct vop_inactive_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
/*
|
||||
@ -358,6 +543,7 @@ null_inactive(ap)
|
||||
* like they do in the name lookup cache code.
|
||||
* That's too much work for now.
|
||||
*/
|
||||
VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -365,6 +551,7 @@ static int
|
||||
null_reclaim(ap)
|
||||
struct vop_reclaim_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
@ -377,14 +564,13 @@ null_reclaim(ap)
|
||||
*/
|
||||
/* After this assignment, this node will not be re-used. */
|
||||
xp->null_lowervp = NULL;
|
||||
remque(xp);
|
||||
LIST_REMOVE(xp, null_hash);
|
||||
FREE(vp->v_data, M_TEMP);
|
||||
vp->v_data = NULL;
|
||||
vrele (lowervp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
null_print(ap)
|
||||
struct vop_print_args /* {
|
||||
@ -396,7 +582,6 @@ null_print(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XXX - vop_strategy must be hand coded because it has no
|
||||
* vnode in its arguments.
|
||||
@ -422,7 +607,6 @@ null_strategy(ap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XXX - like vop_strategy, vop_bwrite must be hand coded because it has no
|
||||
* vnode in its arguments.
|
||||
@ -455,7 +639,12 @@ vop_t **null_vnodeop_p;
|
||||
static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
|
||||
{ &vop_default_desc, (vop_t *)null_bypass },
|
||||
|
||||
{ &vop_lookup_desc, (vop_t *)null_lookup },
|
||||
{ &vop_setattr_desc, (vop_t *)null_setattr },
|
||||
{ &vop_getattr_desc, (vop_t *)null_getattr },
|
||||
{ &vop_access_desc, (vop_t *)null_access },
|
||||
{ &vop_lock_desc, (vop_t *)null_lock },
|
||||
{ &vop_unlock_desc, (vop_t *)null_unlock },
|
||||
{ &vop_inactive_desc, (vop_t *)null_inactive },
|
||||
{ &vop_reclaim_desc, (vop_t *)null_reclaim },
|
||||
{ &vop_print_desc, (vop_t *)null_print },
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* Copyright (c) 1992, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software donated to Berkeley by
|
||||
@ -33,7 +33,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)portal_vfsops.c 8.6 (Berkeley) 1/21/94
|
||||
* @(#)portal_vfsops.c 8.11 (Berkeley) 5/14/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -62,28 +62,18 @@
|
||||
#include <sys/un.h>
|
||||
#include <miscfs/portal/portal.h>
|
||||
|
||||
static int portal_init __P((void));
|
||||
static int portal_mount __P((struct mount *mp, char *path, caddr_t data,
|
||||
struct nameidata *ndp, struct proc *p));
|
||||
static int portal_start __P((struct mount *mp, int flags, struct proc *p));
|
||||
static int portal_unmount __P((struct mount *mp, int mntflags,
|
||||
struct proc *p));
|
||||
static int portal_root __P((struct mount *mp, struct vnode **vpp));
|
||||
static int portal_quotactl __P((struct mount *mp, int cmd, uid_t uid,
|
||||
caddr_t arg, struct proc *p));
|
||||
static int portal_statfs __P((struct mount *mp, struct statfs *sbp,
|
||||
struct proc *p));
|
||||
static int portal_sync __P((struct mount *mp, int waitfor,
|
||||
struct ucred *cred, struct proc *p));
|
||||
static int portal_vget __P((struct mount *mp, ino_t ino,
|
||||
struct vnode **vpp));
|
||||
static int portal_fhtovp __P((struct mount *mp, struct fid *fhp,
|
||||
struct mbuf *nam, struct vnode **vpp,
|
||||
int *exflagsp, struct ucred **credanonp));
|
||||
static int portal_vptofh __P((struct vnode *vp, struct fid *fhp));
|
||||
|
||||
static int
|
||||
portal_init()
|
||||
portal_init(vfsp)
|
||||
struct vfsconf *vfsp;
|
||||
{
|
||||
|
||||
return (0);
|
||||
@ -150,7 +140,7 @@ portal_mount(mp, path, data, ndp, p)
|
||||
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
mp->mnt_data = (qaddr_t) fmp;
|
||||
getnewfsid(mp, MOUNT_PORTAL);
|
||||
vfs_getnewfsid(mp);
|
||||
|
||||
(void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
|
||||
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
|
||||
@ -186,12 +176,8 @@ portal_unmount(mp, mntflags, p)
|
||||
int error, flags = 0;
|
||||
|
||||
|
||||
if (mntflags & MNT_FORCE) {
|
||||
/* portal can never be rootfs so don't check for it */
|
||||
if (!doforce)
|
||||
return (EINVAL);
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear out buffer cache. I don't think we
|
||||
@ -241,31 +227,19 @@ portal_root(mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct vnode *vp;
|
||||
|
||||
|
||||
/*
|
||||
* Return locked reference to root.
|
||||
*/
|
||||
vp = VFSTOPORTAL(mp)->pm_root;
|
||||
VREF(vp);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
portal_quotactl(mp, cmd, uid, arg, p)
|
||||
struct mount *mp;
|
||||
int cmd;
|
||||
uid_t uid;
|
||||
caddr_t arg;
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
portal_statfs(mp, sbp, p)
|
||||
struct mount *mp;
|
||||
@ -273,7 +247,6 @@ portal_statfs(mp, sbp, p)
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
sbp->f_type = MOUNT_PORTAL;
|
||||
sbp->f_flags = 0;
|
||||
sbp->f_bsize = DEV_BSIZE;
|
||||
sbp->f_iosize = DEV_BSIZE;
|
||||
@ -283,6 +256,7 @@ portal_statfs(mp, sbp, p)
|
||||
sbp->f_files = 1; /* Allow for "." */
|
||||
sbp->f_ffree = 0; /* See comments above */
|
||||
if (sbp != &mp->mnt_stat) {
|
||||
sbp->f_type = mp->mnt_vfc->vfc_typenum;
|
||||
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
|
||||
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
|
||||
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
|
||||
@ -290,48 +264,17 @@ portal_statfs(mp, sbp, p)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
portal_sync(mp, waitfor, cred, p)
|
||||
struct mount *mp;
|
||||
int waitfor;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
portal_vget(mp, ino, vpp)
|
||||
struct mount *mp;
|
||||
ino_t ino;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
portal_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
|
||||
struct mount *mp;
|
||||
struct fid *fhp;
|
||||
struct mbuf *nam;
|
||||
struct vnode **vpp;
|
||||
int *exflagsp;
|
||||
struct ucred **credanonp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
portal_vptofh(vp, fhp)
|
||||
struct vnode *vp;
|
||||
struct fid *fhp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
#define portal_fhtovp ((int (*) __P((struct mount *, struct fid *, \
|
||||
struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
|
||||
#define portal_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
|
||||
struct proc *)))eopnotsupp)
|
||||
#define portal_sync ((int (*) __P((struct mount *, int, struct ucred *, \
|
||||
struct proc *)))nullop)
|
||||
#define portal_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
|
||||
size_t, struct proc *)))eopnotsupp)
|
||||
#define portal_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
|
||||
eopnotsupp)
|
||||
#define portal_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
|
||||
|
||||
static struct vfsops portal_vfsops = {
|
||||
portal_mount,
|
||||
|
@ -33,7 +33,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)portal_vnops.c 8.8 (Berkeley) 1/21/94
|
||||
* @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -112,17 +112,25 @@ portal_lookup(ap)
|
||||
struct componentname * a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
char *pname = ap->a_cnp->cn_nameptr;
|
||||
struct componentname *cnp = ap->a_cnp;
|
||||
struct vnode **vpp = ap->a_vpp;
|
||||
struct vnode *dvp = ap->a_dvp;
|
||||
char *pname = cnp->cn_nameptr;
|
||||
struct portalnode *pt;
|
||||
int error;
|
||||
struct vnode *fvp = 0;
|
||||
char *path;
|
||||
int size;
|
||||
|
||||
if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
|
||||
*ap->a_vpp = ap->a_dvp;
|
||||
VREF(ap->a_dvp);
|
||||
/*VOP_LOCK(ap->a_dvp);*/
|
||||
*vpp = NULLVP;
|
||||
|
||||
if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
|
||||
return (EROFS);
|
||||
|
||||
if (cnp->cn_namelen == 1 && *pname == '.') {
|
||||
*vpp = dvp;
|
||||
VREF(dvp);
|
||||
/*VOP_LOCK(dvp);*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -134,7 +142,7 @@ portal_lookup(ap)
|
||||
MALLOC(pt, struct portalnode *, sizeof(struct portalnode),
|
||||
M_TEMP, M_WAITOK);
|
||||
|
||||
error = getnewvnode(VT_PORTAL, ap->a_dvp->v_mount, portal_vnodeop_p, &fvp);
|
||||
error = getnewvnode(VT_PORTAL, dvp->v_mount, portal_vnodeop_p, &fvp);
|
||||
if (error) {
|
||||
FREE(pt, M_TEMP);
|
||||
goto bad;
|
||||
@ -148,22 +156,20 @@ portal_lookup(ap)
|
||||
*/
|
||||
for (size = 0, path = pname; *path; path++)
|
||||
size++;
|
||||
ap->a_cnp->cn_consume = size - ap->a_cnp->cn_namelen;
|
||||
cnp->cn_consume = size - cnp->cn_namelen;
|
||||
|
||||
pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK);
|
||||
pt->pt_size = size+1;
|
||||
bcopy(pname, pt->pt_arg, pt->pt_size);
|
||||
pt->pt_fileid = portal_fileid++;
|
||||
|
||||
*ap->a_vpp = fvp;
|
||||
*vpp = fvp;
|
||||
/*VOP_LOCK(fvp);*/
|
||||
return (0);
|
||||
|
||||
bad:;
|
||||
if (fvp) {
|
||||
if (fvp)
|
||||
vrele(fvp);
|
||||
}
|
||||
*ap->a_vpp = NULL;
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -444,6 +450,7 @@ portal_getattr(ap)
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct vattr *vap = ap->a_vap;
|
||||
struct timeval tv;
|
||||
|
||||
bzero(vap, sizeof(*vap));
|
||||
vattr_null(vap);
|
||||
@ -452,8 +459,8 @@ portal_getattr(ap)
|
||||
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
|
||||
vap->va_size = DEV_BSIZE;
|
||||
vap->va_blocksize = DEV_BSIZE;
|
||||
microtime((struct timeval *)&vap->va_atime);
|
||||
TIMEVAL_TO_TIMESPEC((struct timeval *)&vap->va_atime, (struct timespec *)&vap->va_atime);
|
||||
microtime(&tv);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime);
|
||||
vap->va_mtime = vap->va_atime;
|
||||
vap->va_ctime = vap->va_ctime;
|
||||
vap->va_gen = 0;
|
||||
@ -509,9 +516,19 @@ portal_readdir(ap)
|
||||
struct vnode *a_vp;
|
||||
struct uio *a_uio;
|
||||
struct ucred *a_cred;
|
||||
int *a_eofflag;
|
||||
u_long *a_cookies;
|
||||
int a_ncookies;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
/*
|
||||
* We don't allow exporting portal mounts, and currently local
|
||||
* requests do not need cookies.
|
||||
*/
|
||||
if (ap->a_ncookies)
|
||||
panic("portal_readdir: not hungry");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -519,9 +536,11 @@ static int
|
||||
portal_inactive(ap)
|
||||
struct vop_inactive_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -639,6 +658,7 @@ portal_badop()
|
||||
#define portal_ioctl ((int (*) __P((struct vop_ioctl_args *)))portal_enotsupp)
|
||||
#define portal_select ((int (*) __P((struct vop_select_args *)))portal_enotsupp)
|
||||
#define portal_mmap ((int (*) __P((struct vop_mmap_args *)))portal_enotsupp)
|
||||
#define portal_revoke vop_revoke
|
||||
#define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
|
||||
#define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop)
|
||||
#define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp)
|
||||
@ -651,12 +671,14 @@ portal_badop()
|
||||
#define portal_readlink \
|
||||
((int (*) __P((struct vop_readlink_args *)))portal_enotsupp)
|
||||
#define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
|
||||
#define portal_lock ((int (*) __P((struct vop_lock_args *)))nullop)
|
||||
#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
|
||||
#define portal_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
|
||||
#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
|
||||
#define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop)
|
||||
#define portal_strategy \
|
||||
((int (*) __P((struct vop_strategy_args *)))portal_badop)
|
||||
#define portal_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
|
||||
#define portal_islocked \
|
||||
((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
|
||||
#define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
|
||||
#define portal_advlock \
|
||||
((int (*) __P((struct vop_advlock_args *)))portal_enotsupp)
|
||||
#define portal_blkatoff \
|
||||
@ -687,6 +709,7 @@ static struct vnodeopv_entry_desc portal_vnodeop_entries[] = {
|
||||
{ &vop_ioctl_desc, (vop_t *)portal_ioctl }, /* ioctl */
|
||||
{ &vop_select_desc, (vop_t *)portal_select }, /* select */
|
||||
{ &vop_mmap_desc, (vop_t *)portal_mmap }, /* mmap */
|
||||
{ &vop_revoke_desc, (vop_t *)portal_revoke }, /* revoke */
|
||||
{ &vop_fsync_desc, (vop_t *)portal_fsync }, /* fsync */
|
||||
{ &vop_seek_desc, (vop_t *)portal_seek }, /* seek */
|
||||
{ &vop_remove_desc, (vop_t *)portal_remove }, /* remove */
|
||||
|
@ -34,8 +34,9 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)procfs.h 8.6 (Berkeley) 2/3/94
|
||||
* @(#)procfs.h 8.9 (Berkeley) 5/14/95
|
||||
*
|
||||
* From:
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -44,6 +45,7 @@
|
||||
*/
|
||||
typedef enum {
|
||||
Proot, /* the filesystem root */
|
||||
Pcurproc, /* symbolic link for curproc */
|
||||
Pproc, /* a process-specific sub-directory */
|
||||
Pfile, /* the executable file */
|
||||
Pmem, /* the process's memory image */
|
||||
@ -97,9 +99,9 @@ struct pfsdent {
|
||||
};
|
||||
#define UIO_MX sizeof(struct pfsdent)
|
||||
#define PROCFS_FILENO(pid, type) \
|
||||
(((type) == Proot) ? \
|
||||
2 : \
|
||||
((((pid)+1) << 3) + ((int) (type))))
|
||||
(((type) < Pproc) ? \
|
||||
((type) + 2) : \
|
||||
((((pid)+1) << 4) + ((int) (type))))
|
||||
|
||||
/*
|
||||
* Convert between pfsnode vnode
|
||||
@ -113,33 +115,33 @@ struct vfs_namemap {
|
||||
int nm_val;
|
||||
};
|
||||
|
||||
extern int vfs_getuserstr __P((struct uio *, char *, int *));
|
||||
extern vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
|
||||
int vfs_getuserstr __P((struct uio *, char *, int *));
|
||||
vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
|
||||
|
||||
/* <machine/reg.h> */
|
||||
struct reg;
|
||||
struct fpreg;
|
||||
|
||||
#define PFIND(pid) ((pid) ? pfind(pid) : &proc0)
|
||||
extern int procfs_freevp __P((struct vnode *));
|
||||
extern int procfs_allocvp __P((struct mount *, struct vnode **, long, pfstype));
|
||||
extern struct vnode *procfs_findtextvp __P((struct proc *));
|
||||
extern int procfs_sstep __P((struct proc *));
|
||||
extern void procfs_fix_sstep __P((struct proc *));
|
||||
extern int procfs_read_regs __P((struct proc *, struct reg *));
|
||||
extern int procfs_write_regs __P((struct proc *, struct reg *));
|
||||
extern int procfs_read_fpregs __P((struct proc *, struct fpreg *));
|
||||
extern int procfs_write_fpregs __P((struct proc *, struct fpreg *));
|
||||
extern int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
extern int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
extern int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
extern int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
extern int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
extern int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
extern int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
extern int procfs_dotype __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_freevp __P((struct vnode *));
|
||||
int procfs_allocvp __P((struct mount *, struct vnode **, long, pfstype));
|
||||
struct vnode *procfs_findtextvp __P((struct proc *));
|
||||
int procfs_sstep __P((struct proc *));
|
||||
void procfs_fix_sstep __P((struct proc *));
|
||||
int procfs_read_regs __P((struct proc *, struct reg *));
|
||||
int procfs_write_regs __P((struct proc *, struct reg *));
|
||||
int procfs_read_fpregs __P((struct proc *, struct fpreg *));
|
||||
int procfs_write_fpregs __P((struct proc *, struct fpreg *));
|
||||
int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_dotype __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
|
||||
/* check to see if the process has the "items" (regs/file) */
|
||||
/* functions to check whether or not files should be displayed */
|
||||
int procfs_validfile __P((struct proc *));
|
||||
int procfs_validfpregs __P((struct proc *));
|
||||
int procfs_validregs __P((struct proc *));
|
||||
|
@ -34,8 +34,9 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)procfs_ctl.c 8.3 (Berkeley) 1/21/94
|
||||
* @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94
|
||||
*
|
||||
* From:
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -51,13 +52,13 @@
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/signalvar.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <miscfs/procfs/procfs.h>
|
||||
|
||||
#ifndef FIX_SSTEP
|
||||
#define FIX_SSTEP(p)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* True iff process (p) is in trace wait state
|
||||
* relative to process (curp)
|
||||
@ -67,13 +68,6 @@
|
||||
(p)->p_pptr == (curp) && \
|
||||
((p)->p_flag & P_TRACED))
|
||||
|
||||
#ifdef notdef
|
||||
#define FIX_SSTEP(p) { \
|
||||
procfs_fix_sstep(p); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define PROCFS_CTL_ATTACH 1
|
||||
#define PROCFS_CTL_DETACH 2
|
||||
#define PROCFS_CTL_STEP 3
|
||||
@ -220,8 +214,10 @@ procfs_control(curp, p, op)
|
||||
*/
|
||||
case PROCFS_CTL_STEP:
|
||||
PHOLD(p);
|
||||
procfs_sstep(p);
|
||||
error = procfs_sstep(p);
|
||||
PRELE(p);
|
||||
if (error)
|
||||
return (error);
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -34,8 +34,9 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)procfs_fpregs.c 8.1 (Berkeley) 1/27/94
|
||||
* @(#)procfs_fpregs.c 8.2 (Berkeley) 6/15/94
|
||||
*
|
||||
* From:
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
@ -59,7 +59,7 @@
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/vm_inherit.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_page.h>
|
||||
|
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)procfs_mem.c 8.4 (Berkeley) 1/21/94
|
||||
* @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -55,7 +55,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_kern.h>
|
||||
@ -295,14 +295,11 @@ procfs_domem(curp, p, pfs, uio)
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
{
|
||||
int error;
|
||||
|
||||
if (uio->uio_resid == 0)
|
||||
return (0);
|
||||
|
||||
error = procfs_rwmem(p, uio);
|
||||
|
||||
return (error);
|
||||
return (procfs_rwmem(p, uio));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -320,5 +317,6 @@ struct vnode *
|
||||
procfs_findtextvp(p)
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
return (p->p_textvp);
|
||||
}
|
||||
|
@ -34,8 +34,9 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)procfs_regs.c 8.3 (Berkeley) 1/27/94
|
||||
* @(#)procfs_regs.c 8.4 (Berkeley) 6/15/94
|
||||
*
|
||||
* From:
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
@ -34,8 +34,9 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)procfs_status.c 8.3 (Berkeley) 2/17/94
|
||||
* @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
|
||||
*
|
||||
* From:
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -142,7 +143,7 @@ procfs_dostatus(curp, p, pfs, uio)
|
||||
xlen = ps - psbuf;
|
||||
xlen -= uio->uio_offset;
|
||||
ps = psbuf + uio->uio_offset;
|
||||
xlen = min(xlen, uio->uio_resid);
|
||||
xlen = imin(xlen, uio->uio_resid);
|
||||
if (xlen <= 0)
|
||||
error = 0;
|
||||
else
|
||||
|
@ -34,7 +34,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)procfs_subr.c 8.4 (Berkeley) 1/27/94
|
||||
* @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -84,18 +84,21 @@ procfs_allocvp(mp, vpp, pid, pfs_type)
|
||||
long pid;
|
||||
pfstype pfs_type;
|
||||
{
|
||||
int error;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct pfsnode *pfs;
|
||||
struct vnode *vp;
|
||||
struct pfsnode **pp;
|
||||
int error;
|
||||
|
||||
loop:
|
||||
for (pfs = pfshead; pfs != 0; pfs = pfs->pfs_next) {
|
||||
vp = PFSTOV(pfs);
|
||||
if (pfs->pfs_pid == pid &&
|
||||
pfs->pfs_type == pfs_type &&
|
||||
PFSTOV(pfs)->v_mount == mp) {
|
||||
if (vget(pfs->pfs_vnode, 0))
|
||||
vp->v_mount == mp) {
|
||||
if (vget(vp, 0, p))
|
||||
goto loop;
|
||||
*vpp = pfs->pfs_vnode;
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
@ -118,17 +121,18 @@ procfs_allocvp(mp, vpp, pid, pfs_type)
|
||||
*/
|
||||
MALLOC(pfs, struct pfsnode *, sizeof(struct pfsnode), M_TEMP, M_WAITOK);
|
||||
|
||||
error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp);
|
||||
if (error) {
|
||||
if (error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) {
|
||||
FREE(pfs, M_TEMP);
|
||||
goto out;
|
||||
}
|
||||
vp = *vpp;
|
||||
|
||||
vp->v_data = pfs;
|
||||
|
||||
(*vpp)->v_data = pfs;
|
||||
pfs->pfs_next = 0;
|
||||
pfs->pfs_pid = (pid_t) pid;
|
||||
pfs->pfs_type = pfs_type;
|
||||
pfs->pfs_vnode = *vpp;
|
||||
pfs->pfs_vnode = vp;
|
||||
pfs->pfs_flags = 0;
|
||||
pfs->pfs_lockowner = 0;
|
||||
pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type);
|
||||
@ -138,33 +142,41 @@ procfs_allocvp(mp, vpp, pid, pfs_type)
|
||||
pfs->pfs_mode = (VREAD|VEXEC) |
|
||||
(VREAD|VEXEC) >> 3 |
|
||||
(VREAD|VEXEC) >> 6;
|
||||
vp->v_type = VDIR;
|
||||
vp->v_flag = VROOT;
|
||||
break;
|
||||
|
||||
case Pcurproc: /* /proc/curproc = lr--r--r-- */
|
||||
pfs->pfs_mode = (VREAD) |
|
||||
(VREAD >> 3) |
|
||||
(VREAD >> 6);
|
||||
vp->v_type = VLNK;
|
||||
break;
|
||||
|
||||
case Pproc:
|
||||
pfs->pfs_mode = (VREAD|VEXEC) |
|
||||
(VREAD|VEXEC) >> 3 |
|
||||
(VREAD|VEXEC) >> 6;
|
||||
vp->v_type = VDIR;
|
||||
break;
|
||||
|
||||
case Pfile:
|
||||
pfs->pfs_mode = (VREAD|VWRITE);
|
||||
break;
|
||||
|
||||
case Pmem:
|
||||
pfs->pfs_mode = (VREAD|VWRITE) |
|
||||
(VREAD) >> 3;;
|
||||
break;
|
||||
|
||||
case Pregs:
|
||||
pfs->pfs_mode = (VREAD|VWRITE);
|
||||
break;
|
||||
|
||||
case Pfpregs:
|
||||
pfs->pfs_mode = (VREAD|VWRITE);
|
||||
vp->v_type = VREG;
|
||||
break;
|
||||
|
||||
case Pctl:
|
||||
case Pnote:
|
||||
case Pnotepg:
|
||||
pfs->pfs_mode = (VWRITE);
|
||||
vp->v_type = VREG;
|
||||
break;
|
||||
|
||||
case Ptype:
|
||||
@ -173,14 +185,7 @@ procfs_allocvp(mp, vpp, pid, pfs_type)
|
||||
pfs->pfs_mode = (VREAD) |
|
||||
(VREAD >> 3) |
|
||||
(VREAD >> 6);
|
||||
break;
|
||||
|
||||
case Pnote:
|
||||
pfs->pfs_mode = (VWRITE);
|
||||
break;
|
||||
|
||||
case Pnotepg:
|
||||
pfs->pfs_mode = (VWRITE);
|
||||
vp->v_type = VREG;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -316,8 +321,7 @@ vfs_getuserstr(uio, buf, buflenp)
|
||||
return (EMSGSIZE);
|
||||
xlen = uio->uio_resid;
|
||||
|
||||
error = uiomove(buf, xlen, uio);
|
||||
if (error)
|
||||
if (error = uiomove(buf, xlen, uio))
|
||||
return (error);
|
||||
|
||||
/* allow multiple writes without seeks */
|
||||
@ -339,6 +343,7 @@ vfs_findname(nm, buf, buflen)
|
||||
char *buf;
|
||||
int buflen;
|
||||
{
|
||||
|
||||
for (; nm->nm_name; nm++)
|
||||
if (bcmp(buf, nm->nm_name, buflen+1) == 0)
|
||||
return (nm);
|
||||
|
@ -34,7 +34,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)procfs_vfsops.c 8.4 (Berkeley) 1/21/94
|
||||
* @(#)procfs_vfsops.c 8.7 (Berkeley) 5/10/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -56,24 +56,14 @@
|
||||
#include <miscfs/procfs/procfs.h>
|
||||
#include <vm/vm.h> /* for PAGE_SIZE */
|
||||
|
||||
static int procfs_fhtovp __P((struct mount *mp, struct fid *fhp,
|
||||
struct mbuf *nam, struct vnode **vpp,
|
||||
int *exflagsp, struct ucred **credanonp));
|
||||
static int procfs_init __P((void));
|
||||
static int procfs_init __P((struct vfsconf *vfsp));
|
||||
static int procfs_mount __P((struct mount *mp, char *path, caddr_t data,
|
||||
struct nameidata *ndp, struct proc *p));
|
||||
static int procfs_quotactl __P((struct mount *mp, int cmds, uid_t uid,
|
||||
caddr_t arg, struct proc *p));
|
||||
static int procfs_start __P((struct mount *mp, int flags, struct proc *p));
|
||||
static int procfs_statfs __P((struct mount *mp, struct statfs *sbp,
|
||||
struct proc *p));
|
||||
static int procfs_sync __P((struct mount *mp, int waitfor,
|
||||
struct ucred *cred, struct proc *p));
|
||||
static int procfs_unmount __P((struct mount *mp, int mntflags,
|
||||
struct proc *p));
|
||||
static int procfs_vget __P((struct mount *mp, ino_t ino,
|
||||
struct vnode **vpp));
|
||||
static int procfs_vptofh __P((struct vnode *vp, struct fid *fhp));
|
||||
|
||||
/*
|
||||
* VFS Operations.
|
||||
@ -101,7 +91,7 @@ procfs_mount(mp, path, data, ndp, p)
|
||||
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
mp->mnt_data = 0;
|
||||
getnewfsid(mp, MOUNT_PROCFS);
|
||||
vfs_getnewfsid(mp);
|
||||
|
||||
(void) copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname, MNAMELEN, &size);
|
||||
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
|
||||
@ -125,12 +115,8 @@ procfs_unmount(mp, mntflags, p)
|
||||
int error;
|
||||
int flags = 0;
|
||||
|
||||
if (mntflags & MNT_FORCE) {
|
||||
/* procfs can never be rootfs so don't check for it */
|
||||
if (!doforce)
|
||||
return (EINVAL);
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
}
|
||||
|
||||
error = vflush(mp, 0, flags);
|
||||
if (error)
|
||||
@ -144,24 +130,10 @@ procfs_root(mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct pfsnode *pfs;
|
||||
struct vnode *vp;
|
||||
int error;
|
||||
|
||||
error = procfs_allocvp(mp, &vp, (pid_t) 0, Proot);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
vp->v_type = VDIR;
|
||||
vp->v_flag = VROOT;
|
||||
pfs = VTOPFS(vp);
|
||||
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
return (procfs_allocvp(mp, vpp, 0, Proot));
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
procfs_start(mp, flags, p)
|
||||
@ -182,7 +154,6 @@ procfs_statfs(mp, sbp, p)
|
||||
struct statfs *sbp;
|
||||
struct proc *p;
|
||||
{
|
||||
sbp->f_type = MOUNT_PROCFS;
|
||||
sbp->f_bsize = PAGE_SIZE;
|
||||
sbp->f_iosize = PAGE_SIZE;
|
||||
sbp->f_blocks = 1; /* avoid divide by zero in some df's */
|
||||
@ -192,6 +163,7 @@ procfs_statfs(mp, sbp, p)
|
||||
sbp->f_ffree = maxproc - nprocs; /* approx */
|
||||
|
||||
if (sbp != &mp->mnt_stat) {
|
||||
sbp->f_type = mp->mnt_vfc->vfc_typenum;
|
||||
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
|
||||
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
|
||||
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
|
||||
@ -200,68 +172,25 @@ procfs_statfs(mp, sbp, p)
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
procfs_quotactl(mp, cmds, uid, arg, p)
|
||||
struct mount *mp;
|
||||
int cmds;
|
||||
uid_t uid;
|
||||
caddr_t arg;
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
procfs_sync(mp, waitfor, cred, p)
|
||||
struct mount *mp;
|
||||
int waitfor;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
procfs_init(vfsp)
|
||||
struct vfsconf *vfsp;
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
procfs_vget(mp, ino, vpp)
|
||||
struct mount *mp;
|
||||
ino_t ino;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
procfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
|
||||
struct mount *mp;
|
||||
struct fid *fhp;
|
||||
struct mbuf *nam;
|
||||
struct vnode **vpp;
|
||||
int *exflagsp;
|
||||
struct ucred **credanonp;
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static int
|
||||
procfs_vptofh(vp, fhp)
|
||||
struct vnode *vp;
|
||||
struct fid *fhp;
|
||||
{
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
procfs_init()
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
#define procfs_fhtovp ((int (*) __P((struct mount *, struct fid *, \
|
||||
struct mbuf *, struct vnode **, int *, struct ucred **)))einval)
|
||||
#define procfs_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
|
||||
struct proc *)))eopnotsupp)
|
||||
#define procfs_sync ((int (*) __P((struct mount *, int, struct ucred *, \
|
||||
struct proc *)))nullop)
|
||||
#define procfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
|
||||
size_t, struct proc *)))eopnotsupp)
|
||||
#define procfs_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
|
||||
eopnotsupp)
|
||||
#define procfs_vptofh ((int (*) __P((struct vnode *, struct fid *)))einval)
|
||||
|
||||
static struct vfsops procfs_vfsops = {
|
||||
procfs_mount,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1993 Jan-Simon Pendry
|
||||
* Copyright (c) 1993
|
||||
* Copyright (c) 1993, 1995 Jan-Simon Pendry
|
||||
* Copyright (c) 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
@ -34,7 +34,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)procfs_vnops.c 8.6 (Berkeley) 2/7/94
|
||||
* @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -55,8 +55,9 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <miscfs/procfs/procfs.h>
|
||||
#include <vm/vm.h> /* for PAGE_SIZE */
|
||||
#include <machine/reg.h>
|
||||
#include <miscfs/procfs/procfs.h>
|
||||
|
||||
static int procfs_abortop __P((struct vop_abortop_args *));
|
||||
static int procfs_access __P((struct vop_access_args *));
|
||||
@ -78,29 +79,30 @@ static int procfs_setattr __P((struct vop_setattr_args *));
|
||||
* process-specific sub-directories. It is
|
||||
* used in procfs_lookup and procfs_readdir
|
||||
*/
|
||||
static struct pfsnames {
|
||||
u_short d_namlen;
|
||||
char d_name[PROCFS_NAMELEN];
|
||||
pfstype d_pfstype;
|
||||
int (*d_valid) __P((struct proc *));
|
||||
} procent[] = {
|
||||
struct proc_target {
|
||||
u_char pt_type;
|
||||
u_char pt_namlen;
|
||||
char *pt_name;
|
||||
pfstype pt_pfstype;
|
||||
int (*pt_valid) __P((struct proc *p));
|
||||
} proc_targets[] = {
|
||||
#define N(s) sizeof(s)-1, s
|
||||
/* namlen, nam, type validp */
|
||||
{ N("."), Pproc, NULL },
|
||||
{ N(".."), Proot, NULL },
|
||||
{ N("file"), Pfile, procfs_validfile },
|
||||
{ N("mem"), Pmem, NULL },
|
||||
{ N("regs"), Pregs, procfs_validregs },
|
||||
{ N("fpregs"), Pfpregs, procfs_validfpregs },
|
||||
{ N("ctl"), Pctl, NULL },
|
||||
{ N("status"), Pstatus, NULL },
|
||||
{ N("note"), Pnote, NULL },
|
||||
{ N("notepg"), Pnotepg, NULL },
|
||||
{ N("map"), Pmap, procfs_validmap },
|
||||
{ N("etype"), Ptype, procfs_validtype },
|
||||
/* name type validp */
|
||||
{ DT_DIR, N("."), Pproc, NULL },
|
||||
{ DT_DIR, N(".."), Proot, NULL },
|
||||
{ DT_REG, N("file"), Pfile, procfs_validfile },
|
||||
{ DT_REG, N("mem"), Pmem, NULL },
|
||||
{ DT_REG, N("regs"), Pregs, procfs_validregs },
|
||||
{ DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs },
|
||||
{ DT_REG, N("ctl"), Pctl, NULL },
|
||||
{ DT_REG, N("status"), Pstatus, NULL },
|
||||
{ DT_REG, N("note"), Pnote, NULL },
|
||||
{ DT_REG, N("notepg"), Pnotepg, NULL },
|
||||
{ DT_REG, N("map"), Pmap, procfs_validmap },
|
||||
{ DT_REG, N("etype"), Ptype, procfs_validtype },
|
||||
#undef N
|
||||
};
|
||||
#define Nprocent (sizeof(procent)/sizeof(procent[0]))
|
||||
static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
|
||||
|
||||
static pid_t atopid __P((const char *, u_int));
|
||||
|
||||
@ -117,7 +119,12 @@ static pid_t atopid __P((const char *, u_int));
|
||||
*/
|
||||
static int
|
||||
procfs_open(ap)
|
||||
struct vop_open_args *ap;
|
||||
struct vop_open_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_mode;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct pfsnode *pfs = VTOPFS(ap->a_vp);
|
||||
|
||||
@ -126,11 +133,10 @@ procfs_open(ap)
|
||||
if (PFIND(pfs->pfs_pid) == 0)
|
||||
return (ENOENT); /* was ESRCH, jsp */
|
||||
|
||||
if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
|
||||
((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE)))
|
||||
if ((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL) ||
|
||||
(pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))
|
||||
return (EBUSY);
|
||||
|
||||
|
||||
if (ap->a_mode & FWRITE)
|
||||
pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
|
||||
|
||||
@ -152,7 +158,12 @@ procfs_open(ap)
|
||||
*/
|
||||
static int
|
||||
procfs_close(ap)
|
||||
struct vop_close_args *ap;
|
||||
struct vop_close_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_fflag;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct pfsnode *pfs = VTOPFS(ap->a_vp);
|
||||
|
||||
@ -174,14 +185,51 @@ procfs_close(ap)
|
||||
*/
|
||||
static int
|
||||
procfs_ioctl(ap)
|
||||
struct vop_ioctl_args *ap;
|
||||
struct vop_ioctl_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_command;
|
||||
caddr_t a_data;
|
||||
int a_fflag;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
/*
|
||||
* _inactive is called when the pfsnode
|
||||
* do block mapping for pfsnode (vp).
|
||||
* since we don't use the buffer cache
|
||||
* for procfs this function should never
|
||||
* be called. in any case, it's not clear
|
||||
* what part of the kernel ever makes use
|
||||
* of this function. for sanity, this is the
|
||||
* usual no-op bmap, although returning
|
||||
* (EIO) would be a reasonable alternative.
|
||||
*/
|
||||
int
|
||||
procfs_bmap(ap)
|
||||
struct vop_bmap_args /* {
|
||||
struct vnode *a_vp;
|
||||
daddr_t a_bn;
|
||||
struct vnode **a_vpp;
|
||||
daddr_t *a_bnp;
|
||||
int *a_runp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
if (ap->a_vpp != NULL)
|
||||
*ap->a_vpp = ap->a_vp;
|
||||
if (ap->a_bnp != NULL)
|
||||
*ap->a_bnp = ap->a_bn;
|
||||
if (ap->a_runp != NULL)
|
||||
*ap->a_runp = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* procfs_inactive is called when the pfsnode
|
||||
* is vrele'd and the reference count goes
|
||||
* to zero. (vp) will be on the vnode free
|
||||
* list, so to get it back vget() must be
|
||||
@ -194,16 +242,20 @@ procfs_ioctl(ap)
|
||||
* chances are that the process will still be
|
||||
* there and PFIND is not free.
|
||||
*
|
||||
* (vp) is not locked on entry or exit.
|
||||
* (vp) is locked on entry, but must be unlocked on exit.
|
||||
*/
|
||||
static int
|
||||
procfs_inactive(ap)
|
||||
struct vop_inactive_args *ap;
|
||||
struct vop_inactive_args /* {
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
struct pfsnode *pfs = VTOPFS(ap->a_vp);
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct pfsnode *pfs = VTOPFS(vp);
|
||||
|
||||
VOP_UNLOCK(vp, 0, ap->a_p);
|
||||
if (PFIND(pfs->pfs_pid) == 0)
|
||||
vgone(ap->a_vp);
|
||||
vgone(vp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -217,12 +269,12 @@ procfs_inactive(ap)
|
||||
*/
|
||||
static int
|
||||
procfs_reclaim(ap)
|
||||
struct vop_reclaim_args *ap;
|
||||
struct vop_reclaim_args /* {
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
int error;
|
||||
|
||||
error = procfs_freevp(ap->a_vp);
|
||||
return (error);
|
||||
return (procfs_freevp(ap->a_vp));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -269,13 +321,14 @@ procfs_pathconf(ap)
|
||||
*/
|
||||
static int
|
||||
procfs_print(ap)
|
||||
struct vop_print_args *ap;
|
||||
struct vop_print_args /* {
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
struct pfsnode *pfs = VTOPFS(ap->a_vp);
|
||||
|
||||
printf("tag VT_PROCFS, pid %lu, mode %x, flags %lx\n",
|
||||
pfs->pfs_pid,
|
||||
pfs->pfs_mode, pfs->pfs_flags);
|
||||
printf("tag VT_PROCFS, type %s, pid %d, mode %x, flags %x\n",
|
||||
pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -287,7 +340,10 @@ procfs_print(ap)
|
||||
*/
|
||||
static int
|
||||
procfs_abortop(ap)
|
||||
struct vop_abortop_args *ap;
|
||||
struct vop_abortop_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
|
||||
@ -316,7 +372,12 @@ procfs_badop()
|
||||
*/
|
||||
static int
|
||||
procfs_getattr(ap)
|
||||
struct vop_getattr_args *ap;
|
||||
struct vop_getattr_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct vattr *a_vap;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct pfsnode *pfs = VTOPFS(ap->a_vp);
|
||||
struct vattr *vap = ap->a_vap;
|
||||
@ -329,6 +390,7 @@ procfs_getattr(ap)
|
||||
*/
|
||||
switch (pfs->pfs_type) {
|
||||
case Proot:
|
||||
case Pcurproc:
|
||||
procp = 0;
|
||||
break;
|
||||
|
||||
@ -352,6 +414,21 @@ procfs_getattr(ap)
|
||||
vap->va_blocksize = PAGE_SIZE;
|
||||
vap->va_bytes = vap->va_size = 0;
|
||||
|
||||
/*
|
||||
* Make all times be current TOD.
|
||||
* It would be possible to get the process start
|
||||
* time from the p_stat structure, but there's
|
||||
* no "file creation" time stamp anyway, and the
|
||||
* p_stat structure is not addressible if u. gets
|
||||
* swapped out for that process.
|
||||
*/
|
||||
{
|
||||
struct timeval tv;
|
||||
microtime(&tv);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime);
|
||||
}
|
||||
vap->va_atime = vap->va_mtime = vap->va_ctime;
|
||||
|
||||
/*
|
||||
* If the process has exercised some setuid or setgid
|
||||
* privilege, then rip away read/write permission so
|
||||
@ -375,21 +452,6 @@ procfs_getattr(ap)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make all times be current TOD.
|
||||
* It would be possible to get the process start
|
||||
* time from the p_stat structure, but there's
|
||||
* no "file creation" time stamp anyway, and the
|
||||
* p_stat structure is not addressible if u. gets
|
||||
* swapped out for that process.
|
||||
*/
|
||||
{
|
||||
struct timeval tv;
|
||||
microtime(&tv);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime);
|
||||
}
|
||||
vap->va_atime = vap->va_mtime = vap->va_ctime;
|
||||
|
||||
/*
|
||||
* now do the object specific fields
|
||||
*
|
||||
@ -402,17 +464,30 @@ procfs_getattr(ap)
|
||||
|
||||
switch (pfs->pfs_type) {
|
||||
case Proot:
|
||||
vap->va_nlink = nprocs + 3;
|
||||
/*
|
||||
* Set nlink to 1 to tell fts(3) we don't actually know.
|
||||
*/
|
||||
vap->va_nlink = 1;
|
||||
vap->va_uid = 0;
|
||||
vap->va_gid = 0;
|
||||
vap->va_bytes = vap->va_size = DEV_BSIZE;
|
||||
vap->va_size = vap->va_bytes = DEV_BSIZE;
|
||||
break;
|
||||
|
||||
case Pcurproc: {
|
||||
char buf[16]; /* should be enough */
|
||||
vap->va_nlink = 1;
|
||||
vap->va_uid = 0;
|
||||
vap->va_gid = 0;
|
||||
vap->va_size = vap->va_bytes =
|
||||
sprintf(buf, "%ld", (long)curproc->p_pid);
|
||||
break;
|
||||
}
|
||||
|
||||
case Pproc:
|
||||
vap->va_nlink = Nprocent;
|
||||
vap->va_nlink = nproc_targets;
|
||||
vap->va_uid = procp->p_ucred->cr_uid;
|
||||
vap->va_gid = procp->p_ucred->cr_gid;
|
||||
vap->va_bytes = vap->va_size = DEV_BSIZE;
|
||||
vap->va_size = vap->va_bytes = DEV_BSIZE;
|
||||
break;
|
||||
|
||||
case Pfile:
|
||||
@ -436,7 +511,15 @@ procfs_getattr(ap)
|
||||
case Ptype:
|
||||
case Pmap:
|
||||
case Pregs:
|
||||
vap->va_bytes = vap->va_size = sizeof(struct reg);
|
||||
vap->va_nlink = 1;
|
||||
vap->va_uid = procp->p_ucred->cr_uid;
|
||||
vap->va_gid = procp->p_ucred->cr_gid;
|
||||
break;
|
||||
|
||||
case Pfpregs:
|
||||
vap->va_bytes = vap->va_size = sizeof(struct fpreg);
|
||||
|
||||
case Pctl:
|
||||
case Pstatus:
|
||||
case Pnote:
|
||||
@ -455,7 +538,12 @@ procfs_getattr(ap)
|
||||
|
||||
static int
|
||||
procfs_setattr(ap)
|
||||
struct vop_setattr_args *ap;
|
||||
struct vop_setattr_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct vattr *a_vap;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
/*
|
||||
* just fake out attribute setting
|
||||
@ -484,7 +572,12 @@ procfs_setattr(ap)
|
||||
*/
|
||||
static int
|
||||
procfs_access(ap)
|
||||
struct vop_access_args *ap;
|
||||
struct vop_access_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_mode;
|
||||
struct ucred *a_cred;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vattr *vap;
|
||||
struct vattr vattr;
|
||||
@ -494,8 +587,9 @@ procfs_access(ap)
|
||||
* If you're the super-user,
|
||||
* you always get access.
|
||||
*/
|
||||
if (ap->a_cred->cr_uid == (uid_t) 0)
|
||||
if (ap->a_cred->cr_uid == 0)
|
||||
return (0);
|
||||
|
||||
vap = &vattr;
|
||||
error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p);
|
||||
if (error)
|
||||
@ -510,7 +604,7 @@ procfs_access(ap)
|
||||
gid_t *gp;
|
||||
int i;
|
||||
|
||||
(ap->a_mode) >>= 3;
|
||||
ap->a_mode >>= 3;
|
||||
gp = ap->a_cred->cr_groups;
|
||||
for (i = 0; i < ap->a_cred->cr_ngroups; i++, gp++)
|
||||
if (vap->va_gid == *gp)
|
||||
@ -537,18 +631,23 @@ procfs_access(ap)
|
||||
*/
|
||||
static int
|
||||
procfs_lookup(ap)
|
||||
struct vop_lookup_args *ap;
|
||||
struct vop_lookup_args /* {
|
||||
struct vnode * a_dvp;
|
||||
struct vnode ** a_vpp;
|
||||
struct componentname * a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
struct componentname *cnp = ap->a_cnp;
|
||||
struct vnode **vpp = ap->a_vpp;
|
||||
struct vnode *dvp = ap->a_dvp;
|
||||
char *pname = cnp->cn_nameptr;
|
||||
struct proc *curp = cnp->cn_proc;
|
||||
int error = 0;
|
||||
struct proc_target *pt;
|
||||
struct vnode *fvp;
|
||||
pid_t pid;
|
||||
struct vnode *nvp;
|
||||
struct pfsnode *pfs;
|
||||
struct proc *procp;
|
||||
pfstype pfs_type;
|
||||
struct proc *p;
|
||||
int i;
|
||||
|
||||
*vpp = NULL;
|
||||
@ -559,7 +658,7 @@ procfs_lookup(ap)
|
||||
if (cnp->cn_namelen == 1 && *pname == '.') {
|
||||
*vpp = dvp;
|
||||
VREF(dvp);
|
||||
/*VOP_LOCK(dvp);*/
|
||||
/* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -570,72 +669,52 @@ procfs_lookup(ap)
|
||||
return (EIO);
|
||||
|
||||
if (CNEQ(cnp, "curproc", 7))
|
||||
pid = cnp->cn_proc->p_pid;
|
||||
else
|
||||
pid = atopid(pname, cnp->cn_namelen);
|
||||
return (procfs_allocvp(dvp->v_mount, vpp, 0, Pcurproc));
|
||||
|
||||
pid = atopid(pname, cnp->cn_namelen);
|
||||
if (pid == NO_PID)
|
||||
return (ENOENT);
|
||||
break;
|
||||
|
||||
procp = PFIND(pid);
|
||||
if (procp == 0)
|
||||
return (ENOENT);
|
||||
p = PFIND(pid);
|
||||
if (p == 0)
|
||||
break;
|
||||
|
||||
error = procfs_allocvp(dvp->v_mount, &nvp, pid, Pproc);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
nvp->v_type = VDIR;
|
||||
pfs = VTOPFS(nvp);
|
||||
|
||||
*vpp = nvp;
|
||||
return (0);
|
||||
return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
|
||||
|
||||
case Pproc:
|
||||
if (cnp->cn_flags & ISDOTDOT) {
|
||||
error = procfs_root(dvp->v_mount, vpp);
|
||||
return (error);
|
||||
}
|
||||
if (cnp->cn_flags & ISDOTDOT)
|
||||
return (procfs_root(dvp->v_mount, vpp));
|
||||
|
||||
procp = PFIND(pfs->pfs_pid);
|
||||
if (procp == 0)
|
||||
return (ENOENT);
|
||||
p = PFIND(pfs->pfs_pid);
|
||||
if (p == 0)
|
||||
break;
|
||||
|
||||
for (i = 0; i < Nprocent; i++) {
|
||||
struct pfsnames *dp = &procent[i];
|
||||
|
||||
if (cnp->cn_namelen == dp->d_namlen &&
|
||||
bcmp(pname, dp->d_name, dp->d_namlen) == 0 &&
|
||||
(dp->d_valid == NULL || (*dp->d_valid)(procp))) {
|
||||
pfs_type = dp->d_pfstype;
|
||||
for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) {
|
||||
if (cnp->cn_namelen == pt->pt_namlen &&
|
||||
bcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
|
||||
(pt->pt_valid == NULL || (*pt->pt_valid)(p)))
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return (ENOENT);
|
||||
break;
|
||||
|
||||
found:
|
||||
if (pfs_type == Pfile) {
|
||||
nvp = procfs_findtextvp(procp);
|
||||
if (nvp) {
|
||||
VREF(nvp);
|
||||
VOP_LOCK(nvp);
|
||||
} else {
|
||||
error = ENXIO;
|
||||
}
|
||||
} else {
|
||||
error = procfs_allocvp(dvp->v_mount, &nvp,
|
||||
pfs->pfs_pid, pfs_type);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
nvp->v_type = VREG;
|
||||
pfs = VTOPFS(nvp);
|
||||
if (pt->pt_pfstype == Pfile) {
|
||||
fvp = procfs_findtextvp(p);
|
||||
/* We already checked that it exists. */
|
||||
VREF(fvp);
|
||||
vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curp);
|
||||
*vpp = fvp;
|
||||
return (0);
|
||||
}
|
||||
*vpp = nvp;
|
||||
return (error);
|
||||
|
||||
return (procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
|
||||
pt->pt_pfstype));
|
||||
|
||||
default:
|
||||
return (ENOTDIR);
|
||||
}
|
||||
|
||||
return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -645,6 +724,7 @@ int
|
||||
procfs_validfile(p)
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
return (procfs_findtextvp(p) != NULLVP);
|
||||
}
|
||||
|
||||
@ -662,7 +742,14 @@ procfs_validfile(p)
|
||||
*/
|
||||
static int
|
||||
procfs_readdir(ap)
|
||||
struct vop_readdir_args *ap;
|
||||
struct vop_readdir_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct uio *a_uio;
|
||||
struct ucred *a_cred;
|
||||
int *a_eofflag;
|
||||
u_long *a_cookies;
|
||||
int a_ncookies;
|
||||
} */ *ap;
|
||||
{
|
||||
struct uio *uio = ap->a_uio;
|
||||
struct pfsdent d;
|
||||
@ -672,6 +759,13 @@ procfs_readdir(ap)
|
||||
int count;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We don't allow exporting procfs mounts, and currently local
|
||||
* requests do not need cookies.
|
||||
*/
|
||||
if (ap->a_ncookies)
|
||||
panic("procfs_readdir: not hungry");
|
||||
|
||||
pfs = VTOPFS(ap->a_vp);
|
||||
|
||||
if (uio->uio_resid < UIO_MX)
|
||||
@ -693,39 +787,28 @@ procfs_readdir(ap)
|
||||
*/
|
||||
case Pproc: {
|
||||
struct proc *p;
|
||||
struct proc_target *pt;
|
||||
|
||||
p = PFIND(pfs->pfs_pid);
|
||||
if (p == NULL)
|
||||
break;
|
||||
|
||||
while (uio->uio_resid >= UIO_MX) {
|
||||
struct pfsnames *dt;
|
||||
|
||||
if (i >= Nprocent)
|
||||
break;
|
||||
|
||||
dt = &procent[i];
|
||||
|
||||
/* see if we should show this one. */
|
||||
if (dt->d_valid && (*dt->d_valid)(p) == 0) {
|
||||
i++;
|
||||
for (pt = &proc_targets[i];
|
||||
uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) {
|
||||
if (pt->pt_valid && (*pt->pt_valid)(p) == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
dp->d_reclen = UIO_MX;
|
||||
dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, dt->d_pfstype);
|
||||
dp->d_type = DT_REG;
|
||||
dp->d_namlen = dt->d_namlen;
|
||||
bcopy(dt->d_name, dp->d_name, sizeof(dt->d_name)-1);
|
||||
error = uiomove((caddr_t) dp, UIO_MX, uio);
|
||||
if (error)
|
||||
dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype);
|
||||
dp->d_namlen = pt->pt_namlen;
|
||||
bcopy(pt->pt_name, dp->d_name, pt->pt_namlen + 1);
|
||||
dp->d_type = pt->pt_type;
|
||||
|
||||
if (error = uiomove((caddr_t)dp, UIO_MX, uio))
|
||||
break;
|
||||
count += UIO_MX;
|
||||
i++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -738,63 +821,61 @@ procfs_readdir(ap)
|
||||
*/
|
||||
|
||||
case Proot: {
|
||||
int pcnt;
|
||||
#ifdef PROCFS_ZOMBIE
|
||||
int doingzomb = 0;
|
||||
#endif
|
||||
int pcnt = 0;
|
||||
volatile struct proc *p = allproc.lh_first;
|
||||
|
||||
#define PROCFS_XFILES 3 /* number of other entries, like "curproc" */
|
||||
pcnt = PROCFS_XFILES;
|
||||
|
||||
while (p && uio->uio_resid >= UIO_MX) {
|
||||
again:
|
||||
for (; p && uio->uio_resid >= UIO_MX; i++, pcnt++) {
|
||||
bzero((char *) dp, UIO_MX);
|
||||
dp->d_type = DT_DIR;
|
||||
dp->d_reclen = UIO_MX;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
case 0: /* `.' */
|
||||
case 1: /* `..' */
|
||||
dp->d_fileno = PROCFS_FILENO(0, Proot);
|
||||
dp->d_namlen = sprintf(dp->d_name, ".");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
dp->d_fileno = PROCFS_FILENO(0, Proot);
|
||||
dp->d_namlen = sprintf(dp->d_name, "..");
|
||||
dp->d_namlen = i + 1;
|
||||
bcopy("..", dp->d_name, dp->d_namlen);
|
||||
dp->d_name[i + 1] = '\0';
|
||||
dp->d_type = DT_DIR;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* ship out entry for "curproc" */
|
||||
dp->d_fileno = PROCFS_FILENO(PID_MAX+1, Pproc);
|
||||
dp->d_namlen = sprintf(dp->d_name, "curproc");
|
||||
dp->d_fileno = PROCFS_FILENO(0, Pcurproc);
|
||||
dp->d_namlen = 7;
|
||||
bcopy("curproc", dp->d_name, 8);
|
||||
dp->d_type = DT_LNK;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (pcnt >= i) {
|
||||
dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
|
||||
dp->d_namlen = sprintf(dp->d_name, "%ld", (long) p->p_pid);
|
||||
while (pcnt < i) {
|
||||
pcnt++;
|
||||
p = p->p_list.le_next;
|
||||
if (!p)
|
||||
goto done;
|
||||
}
|
||||
|
||||
dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
|
||||
dp->d_namlen = sprintf(dp->d_name, "%ld",
|
||||
(long)p->p_pid);
|
||||
dp->d_type = DT_REG;
|
||||
p = p->p_list.le_next;
|
||||
|
||||
#ifdef PROCFS_ZOMBIE
|
||||
if (p == 0 && doingzomb == 0) {
|
||||
doingzomb = 1;
|
||||
p = zombproc.lh_first;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pcnt++ < i)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
error = uiomove((caddr_t) dp, UIO_MX, uio);
|
||||
if (error)
|
||||
|
||||
if (error = uiomove((caddr_t)dp, UIO_MX, uio))
|
||||
break;
|
||||
count += UIO_MX;
|
||||
i++;
|
||||
}
|
||||
done:
|
||||
|
||||
#ifdef PROCFS_ZOMBIE
|
||||
if (p == 0 && doingzomb == 0) {
|
||||
doingzomb = 1;
|
||||
p = zombproc.lh_first;
|
||||
goto again;
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
@ -810,6 +891,25 @@ procfs_readdir(ap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* readlink reads the link of `curproc'
|
||||
*/
|
||||
int
|
||||
procfs_readlink(ap)
|
||||
struct vop_readlink_args *ap;
|
||||
{
|
||||
struct uio *uio = ap->a_uio;
|
||||
char buf[16]; /* should be enough */
|
||||
int len;
|
||||
|
||||
if (VTOPFS(ap->a_vp)->pfs_fileno != PROCFS_FILENO(0, Pcurproc))
|
||||
return (EINVAL);
|
||||
|
||||
len = sprintf(buf, "%ld", (long)curproc->p_pid);
|
||||
|
||||
return (uiomove((caddr_t)buf, len, ap->a_uio));
|
||||
}
|
||||
|
||||
/*
|
||||
* convert decimal ascii to pid_t
|
||||
*/
|
||||
@ -838,6 +938,7 @@ atopid(b, len)
|
||||
#define procfs_write procfs_rw
|
||||
#define procfs_select ((int (*) __P((struct vop_select_args *))) procfs_badop)
|
||||
#define procfs_mmap ((int (*) __P((struct vop_mmap_args *))) procfs_badop)
|
||||
#define procfs_revoke vop_revoke
|
||||
#define procfs_fsync ((int (*) __P((struct vop_fsync_args *))) procfs_badop)
|
||||
#define procfs_seek ((int (*) __P((struct vop_seek_args *))) procfs_badop)
|
||||
#define procfs_remove ((int (*) __P((struct vop_remove_args *))) procfs_badop)
|
||||
@ -849,7 +950,6 @@ atopid(b, len)
|
||||
#define procfs_readlink ((int (*) __P((struct vop_readlink_args *))) procfs_badop)
|
||||
#define procfs_lock ((int (*) __P((struct vop_lock_args *))) nullop)
|
||||
#define procfs_unlock ((int (*) __P((struct vop_unlock_args *))) nullop)
|
||||
#define procfs_bmap ((int (*) __P((struct vop_bmap_args *))) procfs_badop)
|
||||
#define procfs_strategy ((int (*) __P((struct vop_strategy_args *))) procfs_badop)
|
||||
#define procfs_islocked ((int (*) __P((struct vop_islocked_args *))) nullop)
|
||||
#define procfs_advlock ((int (*) __P((struct vop_advlock_args *))) procfs_badop)
|
||||
@ -859,6 +959,9 @@ atopid(b, len)
|
||||
#define procfs_truncate ((int (*) __P((struct vop_truncate_args *))) procfs_badop)
|
||||
#define procfs_update ((int (*) __P((struct vop_update_args *))) nullop)
|
||||
|
||||
/*
|
||||
* procfs vnode operations.
|
||||
*/
|
||||
vop_t **procfs_vnodeop_p;
|
||||
static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
|
||||
{ &vop_default_desc, (vop_t *)vn_default_error },
|
||||
@ -875,6 +978,7 @@ static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
|
||||
{ &vop_ioctl_desc, (vop_t *)procfs_ioctl }, /* ioctl */
|
||||
{ &vop_select_desc, (vop_t *)procfs_select }, /* select */
|
||||
{ &vop_mmap_desc, (vop_t *)procfs_mmap }, /* mmap */
|
||||
{ &vop_revoke_desc, (vop_t *)procfs_revoke }, /* revoke */
|
||||
{ &vop_fsync_desc, (vop_t *)procfs_fsync }, /* fsync */
|
||||
{ &vop_seek_desc, (vop_t *)procfs_seek }, /* seek */
|
||||
{ &vop_remove_desc, (vop_t *)procfs_remove }, /* remove */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* Copyright (c) 1989, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)spec_vnops.c 8.6 (Berkeley) 4/9/94
|
||||
* @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -79,8 +79,10 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
|
||||
{ &vop_setattr_desc, (vop_t *)spec_setattr }, /* setattr */
|
||||
{ &vop_read_desc, (vop_t *)spec_read }, /* read */
|
||||
{ &vop_write_desc, (vop_t *)spec_write }, /* write */
|
||||
{ &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
|
||||
{ &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
|
||||
{ &vop_select_desc, (vop_t *)spec_select }, /* select */
|
||||
{ &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
|
||||
{ &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
|
||||
{ &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
|
||||
{ &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
|
||||
@ -148,9 +150,10 @@ spec_open(ap)
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct proc *p = ap->a_p;
|
||||
struct vnode *bvp, *vp = ap->a_vp;
|
||||
dev_t bdev, dev = (dev_t)vp->v_rdev;
|
||||
register int maj = major(dev);
|
||||
int maj = major(dev);
|
||||
int error;
|
||||
|
||||
/*
|
||||
@ -171,7 +174,9 @@ spec_open(ap)
|
||||
* When running in very secure mode, do not allow
|
||||
* opens for writing of any disk character devices.
|
||||
*/
|
||||
if (securelevel >= 2 && isdisk(dev, VCHR))
|
||||
if (securelevel >= 2
|
||||
&& cdevsw[maj]->d_bdev
|
||||
&& cdevsw[maj]->d_bdev->d_flags == D_DISK)
|
||||
return (EPERM);
|
||||
/*
|
||||
* When running in secure mode, do not allow opens
|
||||
@ -189,9 +194,20 @@ spec_open(ap)
|
||||
return (EPERM);
|
||||
}
|
||||
}
|
||||
VOP_UNLOCK(vp);
|
||||
error = (*cdevsw[maj]->d_open)(dev, ap->a_mode, S_IFCHR, ap->a_p);
|
||||
VOP_LOCK(vp);
|
||||
#if 0
|
||||
/*
|
||||
* Lite2 stuff. We will almost certainly do this
|
||||
* differently with devfs. The only use of this flag
|
||||
* is in dead_read to make ttys return EOF instead of
|
||||
* EIO when they are dead. Pre-lite2 FreeBSD returns
|
||||
* EOF for all character devices.
|
||||
*/
|
||||
if (cdevsw[maj]->d_type == D_TTY)
|
||||
vp->v_flag |= VISTTY;
|
||||
#endif
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
error = (*cdevsw[maj]->d_open)(dev, ap->a_mode, S_IFCHR, p);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
return (error);
|
||||
|
||||
case VBLK:
|
||||
@ -204,7 +220,7 @@ spec_open(ap)
|
||||
* opens for writing of any disk block devices.
|
||||
*/
|
||||
if (securelevel >= 2 && ap->a_cred != FSCRED &&
|
||||
(ap->a_mode & FWRITE) && isdisk(dev, VBLK))
|
||||
(ap->a_mode & FWRITE) && bdevsw[maj]->d_flags == D_DISK)
|
||||
return (EPERM);
|
||||
/*
|
||||
* Do not allow opens of block devices that are
|
||||
@ -213,9 +229,7 @@ spec_open(ap)
|
||||
error = vfs_mountedon(vp);
|
||||
if (error)
|
||||
return (error);
|
||||
return ((*bdevsw[maj]->d_open)(dev, ap->a_mode, S_IFBLK, ap->a_p));
|
||||
default:
|
||||
break;
|
||||
return ((*bdevsw[maj]->d_open)(dev, ap->a_mode, S_IFBLK, p));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@ -257,10 +271,10 @@ spec_read(ap)
|
||||
switch (vp->v_type) {
|
||||
|
||||
case VCHR:
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
error = (*cdevsw[major(vp->v_rdev)]->d_read)
|
||||
(vp->v_rdev, uio, ap->a_ioflag);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
return (error);
|
||||
|
||||
case VBLK:
|
||||
@ -335,10 +349,10 @@ spec_write(ap)
|
||||
switch (vp->v_type) {
|
||||
|
||||
case VCHR:
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
error = (*cdevsw[major(vp->v_rdev)]->d_write)
|
||||
(vp->v_rdev, uio, ap->a_ioflag);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
return (error);
|
||||
|
||||
case VBLK:
|
||||
@ -408,7 +422,7 @@ spec_ioctl(ap)
|
||||
|
||||
case VBLK:
|
||||
if (ap->a_command == 0 && (int)ap->a_data == B_TAPE)
|
||||
if (bdevsw[major(dev)]->d_flags & B_TAPE)
|
||||
if (bdevsw[major(dev)]->d_flags == D_TAPE)
|
||||
return (0);
|
||||
else
|
||||
return (1);
|
||||
@ -498,6 +512,18 @@ spec_fsync(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spec_inactive(ap)
|
||||
struct vop_inactive_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Just call the device strategy routine
|
||||
*/
|
||||
@ -538,31 +564,6 @@ spec_bmap(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* At the moment we do not do any locking.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
spec_lock(ap)
|
||||
struct vop_lock_args /* {
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
spec_unlock(ap)
|
||||
struct vop_unlock_args /* {
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Device close routine
|
||||
*/
|
||||
@ -577,6 +578,7 @@ spec_close(ap)
|
||||
} */ *ap;
|
||||
{
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
struct proc *p = ap->a_p;
|
||||
dev_t dev = vp->v_rdev;
|
||||
d_close_t *devclose;
|
||||
int mode, error;
|
||||
@ -631,8 +633,11 @@ spec_close(ap)
|
||||
(vp->v_flag & VXLOCK) == 0)
|
||||
return (0);
|
||||
|
||||
if (vp->v_object)
|
||||
vnode_pager_uncache(vp);
|
||||
if (vp->v_object) {
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
vnode_pager_uncache(vp, p);
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
}
|
||||
|
||||
devclose = bdevsw[major(dev)]->d_close;
|
||||
mode = S_IFBLK;
|
||||
|
@ -33,7 +33,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)umap.h 8.3 (Berkeley) 1/21/94
|
||||
* @(#)umap.h 8.4 (Berkeley) 8/20/94
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -67,8 +67,7 @@ struct umap_mount {
|
||||
* A cache of vnode references
|
||||
*/
|
||||
struct umap_node {
|
||||
struct umap_node *umap_forw; /* Hash chain */
|
||||
struct umap_node *umap_back;
|
||||
LIST_ENTRY(umap_node) umap_hash; /* Hash list */
|
||||
struct vnode *umap_lowervp; /* Aliased vnode - VREFed once */
|
||||
struct vnode *umap_vnode; /* Back pointer to vnode/umap_node */
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* Copyright (c) 1992, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software donated to Berkeley by
|
||||
@ -33,13 +33,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)umap_subr.c 8.6 (Berkeley) 1/26/94
|
||||
* @(#)umap_subr.c 8.9 (Berkeley) 5/14/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/vnode.h>
|
||||
@ -48,11 +49,8 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <miscfs/umapfs/umap.h>
|
||||
|
||||
extern int umapfs_init __P((void));
|
||||
|
||||
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
|
||||
#define NUMAPNODECACHE 16
|
||||
#define UMAP_NHASH(vp) ((((u_long) vp)>>LOG2_SIZEVNODE) & (NUMAPNODECACHE-1))
|
||||
|
||||
/*
|
||||
* Null layer cache:
|
||||
@ -62,51 +60,32 @@ extern int umapfs_init __P((void));
|
||||
* alias is removed the target vnode is vrele'd.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Cache head
|
||||
*/
|
||||
struct umap_node_cache {
|
||||
struct umap_node *ac_forw;
|
||||
struct umap_node *ac_back;
|
||||
};
|
||||
|
||||
static struct umap_node_cache umap_node_cache[NUMAPNODECACHE];
|
||||
#define UMAP_NHASH(vp) \
|
||||
(&umap_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & umap_node_hash])
|
||||
LIST_HEAD(umap_node_hashhead, umap_node) *umap_node_hashtbl;
|
||||
u_long umap_node_hash;
|
||||
|
||||
static u_long umap_findid __P((u_long id, u_long map[][2], int nentries));
|
||||
static int umap_node_alloc __P((struct mount *mp, struct vnode *lowervp,
|
||||
struct vnode **vpp));
|
||||
static struct vnode *
|
||||
umap_node_find __P((struct mount *mp, struct vnode *targetvp));
|
||||
static struct umap_node_cache *
|
||||
umap_node_hash __P((struct vnode *targetvp));
|
||||
|
||||
/*
|
||||
* Initialise cache headers
|
||||
*/
|
||||
int
|
||||
umapfs_init()
|
||||
umapfs_init(vfsp)
|
||||
struct vfsconf *vfsp;
|
||||
{
|
||||
struct umap_node_cache *ac;
|
||||
|
||||
#ifdef UMAPFS_DIAGNOSTIC
|
||||
printf("umapfs_init\n"); /* printed during system boot */
|
||||
#endif
|
||||
|
||||
for (ac = umap_node_cache; ac < umap_node_cache + NUMAPNODECACHE; ac++)
|
||||
ac->ac_forw = ac->ac_back = (struct umap_node *) ac;
|
||||
umap_node_hashtbl = hashinit(NUMAPNODECACHE, M_CACHE, &umap_node_hash);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute hash list for given target vnode
|
||||
*/
|
||||
static struct umap_node_cache *
|
||||
umap_node_hash(targetvp)
|
||||
struct vnode *targetvp;
|
||||
{
|
||||
|
||||
return (&umap_node_cache[UMAP_NHASH(targetvp)]);
|
||||
}
|
||||
|
||||
/*
|
||||
* umap_findid is called by various routines in umap_vnodeops.c to
|
||||
* find a user or group id in a map.
|
||||
@ -163,7 +142,8 @@ umap_node_find(mp, targetvp)
|
||||
struct mount *mp;
|
||||
struct vnode *targetvp;
|
||||
{
|
||||
struct umap_node_cache *hd;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct umap_node_hashhead *hd;
|
||||
struct umap_node *a;
|
||||
struct vnode *vp;
|
||||
|
||||
@ -177,10 +157,9 @@ umap_node_find(mp, targetvp)
|
||||
* the target vnode. If found, the increment the umap_node
|
||||
* reference count (but NOT the target vnode's VREF counter).
|
||||
*/
|
||||
hd = umap_node_hash(targetvp);
|
||||
|
||||
loop:
|
||||
for (a = hd->ac_forw; a != (struct umap_node *) hd; a = a->umap_forw) {
|
||||
hd = UMAP_NHASH(targetvp);
|
||||
loop:
|
||||
for (a = hd->lh_first; a != 0; a = a->umap_hash.le_next) {
|
||||
if (a->umap_lowervp == targetvp &&
|
||||
a->umap_vnode->v_mount == mp) {
|
||||
vp = UMAPTOV(a);
|
||||
@ -189,7 +168,7 @@ umap_node_find(mp, targetvp)
|
||||
* stuff, but we don't want to lock
|
||||
* the lower node.
|
||||
*/
|
||||
if (vget(vp, 0)) {
|
||||
if (vget(vp, 0, p)) {
|
||||
#ifdef UMAPFS_DIAGNOSTIC
|
||||
printf ("umap_node_find: vget failed.\n");
|
||||
#endif
|
||||
@ -217,7 +196,7 @@ umap_node_alloc(mp, lowervp, vpp)
|
||||
struct vnode *lowervp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct umap_node_cache *hd;
|
||||
struct umap_node_hashhead *hd;
|
||||
struct umap_node *xp;
|
||||
struct vnode *othervp, *vp;
|
||||
int error;
|
||||
@ -257,8 +236,8 @@ umap_node_alloc(mp, lowervp, vpp)
|
||||
return (0);
|
||||
}
|
||||
VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */
|
||||
hd = umap_node_hash(lowervp);
|
||||
insque(xp, hd);
|
||||
hd = UMAP_NHASH(lowervp);
|
||||
LIST_INSERT_HEAD(hd, xp, umap_hash);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* Copyright (c) 1992, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software donated to Berkeley by
|
||||
@ -33,7 +33,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)umap_vfsops.c 8.3 (Berkeley) 1/21/94
|
||||
* @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -46,6 +46,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/vnode.h>
|
||||
@ -54,7 +55,7 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <miscfs/umapfs/umap.h>
|
||||
|
||||
extern int umapfs_init __P((void));
|
||||
extern int umapfs_init __P((struct vfsconf *));
|
||||
|
||||
static int umapfs_fhtovp __P((struct mount *mp, struct fid *fidp,
|
||||
struct mbuf *nam, struct vnode **vpp,
|
||||
@ -187,7 +188,7 @@ umapfs_mount(mp, path, data, ndp, p)
|
||||
/*
|
||||
* Unlock the node (either the lower or the alias)
|
||||
*/
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
/*
|
||||
* Make sure the node alias worked
|
||||
*/
|
||||
@ -207,7 +208,7 @@ umapfs_mount(mp, path, data, ndp, p)
|
||||
if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
mp->mnt_data = (qaddr_t) amp;
|
||||
getnewfsid(mp, MOUNT_LOFS);
|
||||
vfs_getnewfsid(mp);
|
||||
|
||||
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
|
||||
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
|
||||
@ -253,12 +254,8 @@ umapfs_unmount(mp, mntflags, p)
|
||||
printf("umapfs_unmount(mp = %x)\n", mp);
|
||||
#endif
|
||||
|
||||
if (mntflags & MNT_FORCE) {
|
||||
/* lofs can never be rootfs so don't check for it */
|
||||
if (!doforce)
|
||||
return (EINVAL);
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear out buffer cache. I don't think we
|
||||
@ -300,6 +297,7 @@ umapfs_root(mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct vnode *vp;
|
||||
|
||||
#ifdef UMAPFS_DIAGNOSTIC
|
||||
@ -314,7 +312,7 @@ umapfs_root(mp, vpp)
|
||||
*/
|
||||
vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
|
||||
VREF(vp);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
}
|
||||
@ -429,4 +427,3 @@ static struct vfsops umap_vfsops = {
|
||||
};
|
||||
|
||||
VFS_SET(umap_vfsops, umap, MOUNT_UMAP, VFCF_LOOPBACK);
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)umap_vnops.c 8.3 (Berkeley) 1/5/94
|
||||
* @(#)umap_vnops.c 8.6 (Berkeley) 5/22/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -336,10 +336,52 @@ umap_getattr(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to process our own vnode lock and then clear the
|
||||
* interlock flag as it applies only to our vnode, not the
|
||||
* vnodes below us on the stack.
|
||||
*/
|
||||
int
|
||||
umap_lock(ap)
|
||||
struct vop_lock_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_flags;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
vop_nolock(ap);
|
||||
if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN)
|
||||
return (0);
|
||||
ap->a_flags &= ~LK_INTERLOCK;
|
||||
return (null_bypass(ap));
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to process our own vnode unlock and then clear the
|
||||
* interlock flag as it applies only to our vnode, not the
|
||||
* vnodes below us on the stack.
|
||||
*/
|
||||
int
|
||||
umap_unlock(ap)
|
||||
struct vop_unlock_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_flags;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
|
||||
vop_nounlock(ap);
|
||||
ap->a_flags &= ~LK_INTERLOCK;
|
||||
return (null_bypass(ap));
|
||||
}
|
||||
|
||||
static int
|
||||
umap_inactive(ap)
|
||||
struct vop_inactive_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
/*
|
||||
@ -349,6 +391,7 @@ umap_inactive(ap)
|
||||
* cache and reusable.
|
||||
*
|
||||
*/
|
||||
VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -364,7 +407,7 @@ umap_reclaim(ap)
|
||||
|
||||
/* After this assignment, this node will not be re-used. */
|
||||
xp->umap_lowervp = NULL;
|
||||
remque(xp);
|
||||
LIST_REMOVE(xp, umap_hash);
|
||||
FREE(vp->v_data, M_TEMP);
|
||||
vp->v_data = NULL;
|
||||
vrele(lowervp);
|
||||
@ -487,6 +530,8 @@ static struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
|
||||
{ &vop_default_desc, (vop_t *)umap_bypass },
|
||||
|
||||
{ &vop_getattr_desc, (vop_t *)umap_getattr },
|
||||
{ &vop_lock_desc, (vop_t *)umap_lock },
|
||||
{ &vop_unlock_desc, (vop_t *)umap_unlock },
|
||||
{ &vop_inactive_desc, (vop_t *)umap_inactive },
|
||||
{ &vop_reclaim_desc, (vop_t *)umap_reclaim },
|
||||
{ &vop_print_desc, (vop_t *)umap_print },
|
||||
|
@ -34,7 +34,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)union.h 8.2 (Berkeley) 2/17/94
|
||||
* @(#)union.h 8.9 (Berkeley) 12/10/94
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -75,10 +75,14 @@ struct union_node {
|
||||
struct vnode *un_uppervp; /* overlaying object */
|
||||
struct vnode *un_lowervp; /* underlying object */
|
||||
struct vnode *un_dirvp; /* Parent dir of uppervp */
|
||||
struct vnode *un_pvp; /* Parent vnode */
|
||||
char *un_path; /* saved component name */
|
||||
int un_hash; /* saved un_path hash value */
|
||||
int un_openl; /* # of opens on lowervp */
|
||||
int un_flags;
|
||||
unsigned int un_flags;
|
||||
struct vnode **un_dircache; /* cached union stack */
|
||||
off_t un_uppersz; /* size of upper object */
|
||||
off_t un_lowersz; /* size of lower object */
|
||||
#ifdef DIAGNOSTIC
|
||||
pid_t un_pid;
|
||||
#endif
|
||||
@ -88,16 +92,23 @@ struct union_node {
|
||||
#define UN_LOCKED 0x02
|
||||
#define UN_ULOCK 0x04 /* Upper node is locked */
|
||||
#define UN_KLOCK 0x08 /* Keep upper node locked on vput */
|
||||
#define UN_CACHED 0x10 /* In union cache */
|
||||
|
||||
extern int union_allocvp __P((struct vnode **, struct mount *,
|
||||
struct vnode *, struct vnode *,
|
||||
struct componentname *, struct vnode *,
|
||||
struct vnode *));
|
||||
struct vnode *, int));
|
||||
extern int union_freevp __P((struct vnode *));
|
||||
extern int union_copyfile __P((struct proc *, struct ucred *,
|
||||
struct vnode *, struct vnode *));
|
||||
extern int union_copyfile __P((struct vnode *, struct vnode *,
|
||||
struct ucred *, struct proc *));
|
||||
extern int union_copyup __P((struct union_node *, int, struct ucred *,
|
||||
struct proc *));
|
||||
extern int union_dowhiteout __P((struct union_node *, struct ucred *,
|
||||
struct proc *));
|
||||
extern int union_mkshadow __P((struct union_mount *, struct vnode *,
|
||||
struct componentname *, struct vnode **));
|
||||
extern int union_mkwhiteout __P((struct union_mount *, struct vnode *,
|
||||
struct componentname *, char *));
|
||||
extern int union_vn_create __P((struct vnode **, struct union_node *,
|
||||
struct proc *));
|
||||
extern int union_vn_close __P((struct vnode *, int, struct ucred *,
|
||||
@ -108,6 +119,7 @@ extern void union_removed_upper __P((struct union_node *un));
|
||||
extern struct vnode *union_lowervp __P((struct vnode *));
|
||||
extern void union_newlower __P((struct union_node *, struct vnode *));
|
||||
extern void union_newupper __P((struct union_node *, struct vnode *));
|
||||
extern void union_newsize __P((struct vnode *, off_t, off_t));
|
||||
|
||||
#define MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
|
||||
#define VTOUNION(vp) ((struct union_node *)(vp)->v_data)
|
||||
|
@ -34,7 +34,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)union_subr.c 8.4 (Berkeley) 2/17/94
|
||||
* @(#)union_subr.c 8.20 (Berkeley) 5/20/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -48,6 +48,9 @@
|
||||
#include <sys/file.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <vm/vm.h> /* for vnode_pager_setsize */
|
||||
#include <miscfs/union/union.h>
|
||||
|
||||
#include <sys/proc.h>
|
||||
@ -118,31 +121,38 @@ union_updatevp(un, uppervp, lowervp)
|
||||
{
|
||||
int ohash = UNION_HASH(un->un_uppervp, un->un_lowervp);
|
||||
int nhash = UNION_HASH(uppervp, lowervp);
|
||||
int docache = (lowervp != NULLVP || uppervp != NULLVP);
|
||||
int lhash, hhash, uhash;
|
||||
|
||||
if (ohash != nhash) {
|
||||
/*
|
||||
* Ensure locking is ordered from lower to higher
|
||||
* to avoid deadlocks.
|
||||
*/
|
||||
if (nhash < ohash) {
|
||||
int t = ohash;
|
||||
ohash = nhash;
|
||||
nhash = t;
|
||||
}
|
||||
|
||||
while (union_list_lock(ohash))
|
||||
continue;
|
||||
|
||||
while (union_list_lock(nhash))
|
||||
continue;
|
||||
|
||||
LIST_REMOVE(un, un_cache);
|
||||
union_list_unlock(ohash);
|
||||
/*
|
||||
* Ensure locking is ordered from lower to higher
|
||||
* to avoid deadlocks.
|
||||
*/
|
||||
if (nhash < ohash) {
|
||||
lhash = nhash;
|
||||
uhash = ohash;
|
||||
} else {
|
||||
while (union_list_lock(nhash))
|
||||
continue;
|
||||
lhash = ohash;
|
||||
uhash = nhash;
|
||||
}
|
||||
|
||||
if (lhash != uhash)
|
||||
while (union_list_lock(lhash))
|
||||
continue;
|
||||
|
||||
while (union_list_lock(uhash))
|
||||
continue;
|
||||
|
||||
if (ohash != nhash || !docache) {
|
||||
if (un->un_flags & UN_CACHED) {
|
||||
un->un_flags &= ~UN_CACHED;
|
||||
LIST_REMOVE(un, un_cache);
|
||||
}
|
||||
}
|
||||
|
||||
if (ohash != nhash)
|
||||
union_list_unlock(ohash);
|
||||
|
||||
if (un->un_lowervp != lowervp) {
|
||||
if (un->un_lowervp) {
|
||||
vrele(un->un_lowervp);
|
||||
@ -156,6 +166,7 @@ union_updatevp(un, uppervp, lowervp)
|
||||
}
|
||||
}
|
||||
un->un_lowervp = lowervp;
|
||||
un->un_lowersz = VNOVAL;
|
||||
}
|
||||
|
||||
if (un->un_uppervp != uppervp) {
|
||||
@ -163,10 +174,13 @@ union_updatevp(un, uppervp, lowervp)
|
||||
vrele(un->un_uppervp);
|
||||
|
||||
un->un_uppervp = uppervp;
|
||||
un->un_uppersz = VNOVAL;
|
||||
}
|
||||
|
||||
if (ohash != nhash)
|
||||
if (docache && (ohash != nhash)) {
|
||||
LIST_INSERT_HEAD(&unhead[nhash], un, un_cache);
|
||||
un->un_flags |= UN_CACHED;
|
||||
}
|
||||
|
||||
union_list_unlock(nhash);
|
||||
}
|
||||
@ -189,6 +203,47 @@ union_newupper(un, uppervp)
|
||||
union_updatevp(un, uppervp, un->un_lowervp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep track of size changes in the underlying vnodes.
|
||||
* If the size changes, then callback to the vm layer
|
||||
* giving priority to the upper layer size.
|
||||
*/
|
||||
void
|
||||
union_newsize(vp, uppersz, lowersz)
|
||||
struct vnode *vp;
|
||||
off_t uppersz, lowersz;
|
||||
{
|
||||
struct union_node *un;
|
||||
off_t sz;
|
||||
|
||||
/* only interested in regular files */
|
||||
if (vp->v_type != VREG)
|
||||
return;
|
||||
|
||||
un = VTOUNION(vp);
|
||||
sz = VNOVAL;
|
||||
|
||||
if ((uppersz != VNOVAL) && (un->un_uppersz != uppersz)) {
|
||||
un->un_uppersz = uppersz;
|
||||
if (sz == VNOVAL)
|
||||
sz = un->un_uppersz;
|
||||
}
|
||||
|
||||
if ((lowersz != VNOVAL) && (un->un_lowersz != lowersz)) {
|
||||
un->un_lowersz = lowersz;
|
||||
if (sz == VNOVAL)
|
||||
sz = un->un_lowersz;
|
||||
}
|
||||
|
||||
if (sz != VNOVAL) {
|
||||
#ifdef UNION_DIAGNOSTIC
|
||||
printf("union: %s size now %ld\n",
|
||||
uppersz != VNOVAL ? "upper" : "lower", (long) sz);
|
||||
#endif
|
||||
vnode_pager_setsize(vp, sz);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate a union_node/vnode pair. the vnode is
|
||||
* referenced and locked. the new vnode is returned
|
||||
@ -221,19 +276,22 @@ union_newupper(un, uppervp)
|
||||
* the vnode free list.
|
||||
*/
|
||||
int
|
||||
union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
|
||||
union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp, docache)
|
||||
struct vnode **vpp;
|
||||
struct mount *mp;
|
||||
struct vnode *undvp;
|
||||
struct vnode *undvp; /* parent union vnode */
|
||||
struct vnode *dvp; /* may be null */
|
||||
struct componentname *cnp; /* may be null */
|
||||
struct vnode *uppervp; /* may be null */
|
||||
struct vnode *lowervp; /* may be null */
|
||||
int docache;
|
||||
{
|
||||
int error;
|
||||
struct union_node *un = 0;
|
||||
struct vnode *xlowervp = NULLVP;
|
||||
int hash = 0;
|
||||
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
|
||||
int hash;
|
||||
int vflag;
|
||||
int try;
|
||||
|
||||
if (uppervp == NULLVP && lowervp == NULLVP)
|
||||
@ -244,8 +302,22 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
|
||||
lowervp = NULLVP;
|
||||
}
|
||||
|
||||
/* detect the root vnode (and aliases) */
|
||||
vflag = 0;
|
||||
if ((uppervp == um->um_uppervp) &&
|
||||
((lowervp == NULLVP) || lowervp == um->um_lowervp)) {
|
||||
if (lowervp == NULLVP) {
|
||||
lowervp = um->um_lowervp;
|
||||
if (lowervp != NULLVP)
|
||||
VREF(lowervp);
|
||||
}
|
||||
vflag = VROOT;
|
||||
}
|
||||
|
||||
loop:
|
||||
for (try = 0; try < 3; try++) {
|
||||
if (!docache) {
|
||||
un = 0;
|
||||
} else for (try = 0; try < 3; try++) {
|
||||
switch (try) {
|
||||
case 0:
|
||||
if (lowervp == NULLVP)
|
||||
@ -276,7 +348,8 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
|
||||
(un->un_uppervp == uppervp ||
|
||||
un->un_uppervp == NULLVP) &&
|
||||
(UNIONTOV(un)->v_mount == mp)) {
|
||||
if (vget(UNIONTOV(un), 0)) {
|
||||
if (vget(UNIONTOV(un), 0,
|
||||
cnp ? cnp->cn_proc : NULL)) {
|
||||
union_list_unlock(hash);
|
||||
goto loop;
|
||||
}
|
||||
@ -359,8 +432,7 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
|
||||
*/
|
||||
if (lowervp != un->un_lowervp) {
|
||||
union_newlower(un, lowervp);
|
||||
if (cnp && (lowervp != NULLVP) &&
|
||||
(lowervp->v_type == VREG)) {
|
||||
if (cnp && (lowervp != NULLVP)) {
|
||||
un->un_hash = cnp->cn_hash;
|
||||
un->un_path = malloc(cnp->cn_namelen+1,
|
||||
M_TEMP, M_WAITOK);
|
||||
@ -377,14 +449,16 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* otherwise lock the vp list while we call getnewvnode
|
||||
* since that can block.
|
||||
*/
|
||||
hash = UNION_HASH(uppervp, lowervp);
|
||||
if (docache) {
|
||||
/*
|
||||
* otherwise lock the vp list while we call getnewvnode
|
||||
* since that can block.
|
||||
*/
|
||||
hash = UNION_HASH(uppervp, lowervp);
|
||||
|
||||
if (union_list_lock(hash))
|
||||
goto loop;
|
||||
if (union_list_lock(hash))
|
||||
goto loop;
|
||||
}
|
||||
|
||||
error = getnewvnode(VT_UNION, mp, union_vnodeop_p, vpp);
|
||||
if (error) {
|
||||
@ -403,6 +477,7 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
|
||||
MALLOC((*vpp)->v_data, void *, sizeof(struct union_node),
|
||||
M_TEMP, M_WAITOK);
|
||||
|
||||
(*vpp)->v_flag |= vflag;
|
||||
if (uppervp)
|
||||
(*vpp)->v_type = uppervp->v_type;
|
||||
else
|
||||
@ -410,7 +485,13 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
|
||||
un = VTOUNION(*vpp);
|
||||
un->un_vnode = *vpp;
|
||||
un->un_uppervp = uppervp;
|
||||
un->un_uppersz = VNOVAL;
|
||||
un->un_lowervp = lowervp;
|
||||
un->un_lowersz = VNOVAL;
|
||||
un->un_pvp = undvp;
|
||||
if (undvp != NULLVP)
|
||||
VREF(undvp);
|
||||
un->un_dircache = 0;
|
||||
un->un_openl = 0;
|
||||
un->un_flags = UN_LOCKED;
|
||||
if (un->un_uppervp)
|
||||
@ -421,7 +502,7 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
|
||||
else
|
||||
un->un_pid = -1;
|
||||
#endif
|
||||
if (cnp && (lowervp != NULLVP) && (lowervp->v_type == VREG)) {
|
||||
if (cnp && (lowervp != NULLVP)) {
|
||||
un->un_hash = cnp->cn_hash;
|
||||
un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
|
||||
bcopy(cnp->cn_nameptr, un->un_path, cnp->cn_namelen);
|
||||
@ -434,13 +515,17 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
|
||||
un->un_dirvp = 0;
|
||||
}
|
||||
|
||||
LIST_INSERT_HEAD(&unhead[hash], un, un_cache);
|
||||
if (docache) {
|
||||
LIST_INSERT_HEAD(&unhead[hash], un, un_cache);
|
||||
un->un_flags |= UN_CACHED;
|
||||
}
|
||||
|
||||
if (xlowervp)
|
||||
vrele(xlowervp);
|
||||
|
||||
out:
|
||||
union_list_unlock(hash);
|
||||
if (docache)
|
||||
union_list_unlock(hash);
|
||||
|
||||
return (error);
|
||||
}
|
||||
@ -451,13 +536,18 @@ union_freevp(vp)
|
||||
{
|
||||
struct union_node *un = VTOUNION(vp);
|
||||
|
||||
LIST_REMOVE(un, un_cache);
|
||||
if (un->un_flags & UN_CACHED) {
|
||||
un->un_flags &= ~UN_CACHED;
|
||||
LIST_REMOVE(un, un_cache);
|
||||
}
|
||||
|
||||
if (un->un_uppervp)
|
||||
if (un->un_pvp != NULLVP)
|
||||
vrele(un->un_pvp);
|
||||
if (un->un_uppervp != NULLVP)
|
||||
vrele(un->un_uppervp);
|
||||
if (un->un_lowervp)
|
||||
if (un->un_lowervp != NULLVP)
|
||||
vrele(un->un_lowervp);
|
||||
if (un->un_dirvp)
|
||||
if (un->un_dirvp != NULLVP)
|
||||
vrele(un->un_dirvp);
|
||||
if (un->un_path)
|
||||
free(un->un_path, M_TEMP);
|
||||
@ -474,11 +564,11 @@ union_freevp(vp)
|
||||
* and (tvp) are locked on entry and exit.
|
||||
*/
|
||||
int
|
||||
union_copyfile(p, cred, fvp, tvp)
|
||||
struct proc *p;
|
||||
struct ucred *cred;
|
||||
union_copyfile(fvp, tvp, cred, p)
|
||||
struct vnode *fvp;
|
||||
struct vnode *tvp;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
{
|
||||
char *buf;
|
||||
struct uio uio;
|
||||
@ -497,12 +587,12 @@ union_copyfile(p, cred, fvp, tvp)
|
||||
uio.uio_segflg = UIO_SYSSPACE;
|
||||
uio.uio_offset = 0;
|
||||
|
||||
VOP_UNLOCK(fvp); /* XXX */
|
||||
LEASE_CHECK(fvp, p, cred, LEASE_READ);
|
||||
VOP_LOCK(fvp); /* XXX */
|
||||
VOP_UNLOCK(tvp); /* XXX */
|
||||
LEASE_CHECK(tvp, p, cred, LEASE_WRITE);
|
||||
VOP_LOCK(tvp); /* XXX */
|
||||
VOP_UNLOCK(fvp, 0, p); /* XXX */
|
||||
VOP_LEASE(fvp, p, cred, LEASE_READ);
|
||||
vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
|
||||
VOP_UNLOCK(tvp, 0, p); /* XXX */
|
||||
VOP_LEASE(tvp, p, cred, LEASE_WRITE);
|
||||
vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
|
||||
|
||||
buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
|
||||
|
||||
@ -541,6 +631,123 @@ union_copyfile(p, cred, fvp, tvp)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* (un) is assumed to be locked on entry and remains
|
||||
* locked on exit.
|
||||
*/
|
||||
int
|
||||
union_copyup(un, docopy, cred, p)
|
||||
struct union_node *un;
|
||||
int docopy;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
{
|
||||
int error;
|
||||
struct vnode *lvp, *uvp;
|
||||
|
||||
error = union_vn_create(&uvp, un, p);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* at this point, uppervp is locked */
|
||||
union_newupper(un, uvp);
|
||||
un->un_flags |= UN_ULOCK;
|
||||
|
||||
lvp = un->un_lowervp;
|
||||
|
||||
if (docopy) {
|
||||
/*
|
||||
* XX - should not ignore errors
|
||||
* from VOP_CLOSE
|
||||
*/
|
||||
vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
error = VOP_OPEN(lvp, FREAD, cred, p);
|
||||
if (error == 0) {
|
||||
error = union_copyfile(lvp, uvp, cred, p);
|
||||
VOP_UNLOCK(lvp, 0, p);
|
||||
(void) VOP_CLOSE(lvp, FREAD, cred, p);
|
||||
}
|
||||
#ifdef UNION_DIAGNOSTIC
|
||||
if (error == 0)
|
||||
uprintf("union: copied up %s\n", un->un_path);
|
||||
#endif
|
||||
|
||||
}
|
||||
un->un_flags &= ~UN_ULOCK;
|
||||
VOP_UNLOCK(uvp, 0, p);
|
||||
union_vn_close(uvp, FWRITE, cred, p);
|
||||
vn_lock(uvp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
un->un_flags |= UN_ULOCK;
|
||||
|
||||
/*
|
||||
* Subsequent IOs will go to the top layer, so
|
||||
* call close on the lower vnode and open on the
|
||||
* upper vnode to ensure that the filesystem keeps
|
||||
* its references counts right. This doesn't do
|
||||
* the right thing with (cred) and (FREAD) though.
|
||||
* Ignoring error returns is not right, either.
|
||||
*/
|
||||
if (error == 0) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < un->un_openl; i++) {
|
||||
(void) VOP_CLOSE(lvp, FREAD, cred, p);
|
||||
(void) VOP_OPEN(uvp, FREAD, cred, p);
|
||||
}
|
||||
un->un_openl = 0;
|
||||
}
|
||||
|
||||
return (error);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
union_relookup(um, dvp, vpp, cnp, cn, path, pathlen)
|
||||
struct union_mount *um;
|
||||
struct vnode *dvp;
|
||||
struct vnode **vpp;
|
||||
struct componentname *cnp;
|
||||
struct componentname *cn;
|
||||
char *path;
|
||||
int pathlen;
|
||||
{
|
||||
int error;
|
||||
|
||||
/*
|
||||
* A new componentname structure must be faked up because
|
||||
* there is no way to know where the upper level cnp came
|
||||
* from or what it is being used for. This must duplicate
|
||||
* some of the work done by NDINIT, some of the work done
|
||||
* by namei, some of the work done by lookup and some of
|
||||
* the work done by VOP_LOOKUP when given a CREATE flag.
|
||||
* Conclusion: Horrible.
|
||||
*
|
||||
* The pathname buffer will be FREEed by VOP_MKDIR.
|
||||
*/
|
||||
cn->cn_namelen = pathlen;
|
||||
cn->cn_pnbuf = malloc(cn->cn_namelen+1, M_NAMEI, M_WAITOK);
|
||||
bcopy(path, cn->cn_pnbuf, cn->cn_namelen);
|
||||
cn->cn_pnbuf[cn->cn_namelen] = '\0';
|
||||
|
||||
cn->cn_nameiop = CREATE;
|
||||
cn->cn_flags = (LOCKPARENT|HASBUF|SAVENAME|SAVESTART|ISLASTCN);
|
||||
cn->cn_proc = cnp->cn_proc;
|
||||
if (um->um_op == UNMNT_ABOVE)
|
||||
cn->cn_cred = cnp->cn_cred;
|
||||
else
|
||||
cn->cn_cred = um->um_cred;
|
||||
cn->cn_nameptr = cn->cn_pnbuf;
|
||||
cn->cn_hash = cnp->cn_hash;
|
||||
cn->cn_consume = cnp->cn_consume;
|
||||
|
||||
VREF(dvp);
|
||||
error = relookup(dvp, vpp, cn);
|
||||
if (!error)
|
||||
vrele(dvp);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a shadow directory in the upper layer.
|
||||
* The new vnode is returned locked.
|
||||
@ -565,6 +772,19 @@ union_mkshadow(um, dvp, cnp, vpp)
|
||||
struct proc *p = cnp->cn_proc;
|
||||
struct componentname cn;
|
||||
|
||||
error = union_relookup(um, dvp, vpp, cnp, &cn,
|
||||
cnp->cn_nameptr, cnp->cn_namelen);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (*vpp) {
|
||||
VOP_ABORTOP(dvp, &cn);
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
vrele(*vpp);
|
||||
*vpp = NULLVP;
|
||||
return (EEXIST);
|
||||
}
|
||||
|
||||
/*
|
||||
* policy: when creating the shadow directory in the
|
||||
* upper layer, create it owned by the user who did
|
||||
@ -573,58 +793,65 @@ union_mkshadow(um, dvp, cnp, vpp)
|
||||
* mkdir syscall). (jsp, kb)
|
||||
*/
|
||||
|
||||
/*
|
||||
* A new componentname structure must be faked up because
|
||||
* there is no way to know where the upper level cnp came
|
||||
* from or what it is being used for. This must duplicate
|
||||
* some of the work done by NDINIT, some of the work done
|
||||
* by namei, some of the work done by lookup and some of
|
||||
* the work done by VOP_LOOKUP when given a CREATE flag.
|
||||
* Conclusion: Horrible.
|
||||
*
|
||||
* The pathname buffer will be FREEed by VOP_MKDIR.
|
||||
*/
|
||||
cn.cn_pnbuf = malloc(cnp->cn_namelen+1, M_NAMEI, M_WAITOK);
|
||||
bcopy(cnp->cn_nameptr, cn.cn_pnbuf, cnp->cn_namelen);
|
||||
cn.cn_pnbuf[cnp->cn_namelen] = '\0';
|
||||
|
||||
cn.cn_nameiop = CREATE;
|
||||
cn.cn_flags = (LOCKPARENT|HASBUF|SAVENAME|SAVESTART|ISLASTCN);
|
||||
cn.cn_proc = cnp->cn_proc;
|
||||
if (um->um_op == UNMNT_ABOVE)
|
||||
cn.cn_cred = cnp->cn_cred;
|
||||
else
|
||||
cn.cn_cred = um->um_cred;
|
||||
cn.cn_nameptr = cn.cn_pnbuf;
|
||||
cn.cn_namelen = cnp->cn_namelen;
|
||||
cn.cn_hash = cnp->cn_hash;
|
||||
cn.cn_consume = cnp->cn_consume;
|
||||
|
||||
VREF(dvp);
|
||||
error = relookup(dvp, vpp, &cn);
|
||||
if (error)
|
||||
return (error);
|
||||
vrele(dvp);
|
||||
|
||||
if (*vpp) {
|
||||
VOP_ABORTOP(dvp, &cn);
|
||||
VOP_UNLOCK(dvp);
|
||||
vrele(*vpp);
|
||||
*vpp = NULLVP;
|
||||
return (EEXIST);
|
||||
}
|
||||
|
||||
VATTR_NULL(&va);
|
||||
va.va_type = VDIR;
|
||||
va.va_mode = um->um_cmode;
|
||||
|
||||
/* LEASE_CHECK: dvp is locked */
|
||||
LEASE_CHECK(dvp, p, p->p_ucred, LEASE_WRITE);
|
||||
/* VOP_LEASE: dvp is locked */
|
||||
VOP_LEASE(dvp, p, cn.cn_cred, LEASE_WRITE);
|
||||
|
||||
error = VOP_MKDIR(dvp, vpp, &cn, &va);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a whiteout entry in the upper layer.
|
||||
*
|
||||
* (um) points to the union mount structure for access to the
|
||||
* the mounting process's credentials.
|
||||
* (dvp) is the directory in which to create the whiteout.
|
||||
* it is locked on entry and exit.
|
||||
* (cnp) is the componentname to be created.
|
||||
*/
|
||||
int
|
||||
union_mkwhiteout(um, dvp, cnp, path)
|
||||
struct union_mount *um;
|
||||
struct vnode *dvp;
|
||||
struct componentname *cnp;
|
||||
char *path;
|
||||
{
|
||||
int error;
|
||||
struct vattr va;
|
||||
struct proc *p = cnp->cn_proc;
|
||||
struct vnode *wvp;
|
||||
struct componentname cn;
|
||||
|
||||
VOP_UNLOCK(dvp, 0, p);
|
||||
error = union_relookup(um, dvp, &wvp, cnp, &cn, path, strlen(path));
|
||||
if (error) {
|
||||
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (wvp) {
|
||||
VOP_ABORTOP(dvp, &cn);
|
||||
vrele(dvp);
|
||||
vrele(wvp);
|
||||
return (EEXIST);
|
||||
}
|
||||
|
||||
/* VOP_LEASE: dvp is locked */
|
||||
VOP_LEASE(dvp, p, p->p_ucred, LEASE_WRITE);
|
||||
|
||||
error = VOP_WHITEOUT(dvp, &cn, CREATE);
|
||||
if (error)
|
||||
VOP_ABORTOP(dvp, &cn);
|
||||
|
||||
vrele(dvp);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* union_vn_create: creates and opens a new shadow file
|
||||
* on the upper union layer. this function is similar
|
||||
@ -699,9 +926,8 @@ union_vn_create(vpp, un, p)
|
||||
VATTR_NULL(vap);
|
||||
vap->va_type = VREG;
|
||||
vap->va_mode = cmode;
|
||||
LEASE_CHECK(un->un_dirvp, p, cred, LEASE_WRITE);
|
||||
error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap);
|
||||
if (error)
|
||||
VOP_LEASE(un->un_dirvp, p, cred, LEASE_WRITE);
|
||||
if (error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap))
|
||||
return (error);
|
||||
|
||||
error = VOP_OPEN(vp, fmode, cred, p);
|
||||
@ -722,6 +948,7 @@ union_vn_close(vp, fmode, cred, p)
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
if (fmode & FWRITE)
|
||||
--vp->v_writecount;
|
||||
return (VOP_CLOSE(vp, fmode, cred, p));
|
||||
@ -731,24 +958,137 @@ void
|
||||
union_removed_upper(un)
|
||||
struct union_node *un;
|
||||
{
|
||||
if (un->un_flags & UN_ULOCK) {
|
||||
un->un_flags &= ~UN_ULOCK;
|
||||
VOP_UNLOCK(un->un_uppervp);
|
||||
}
|
||||
struct proc *p = curproc; /* XXX */
|
||||
|
||||
union_newupper(un, NULLVP);
|
||||
if (un->un_flags & UN_CACHED) {
|
||||
un->un_flags &= ~UN_CACHED;
|
||||
LIST_REMOVE(un, un_cache);
|
||||
}
|
||||
|
||||
if (un->un_flags & UN_ULOCK) {
|
||||
un->un_flags &= ~UN_ULOCK;
|
||||
VOP_UNLOCK(un->un_uppervp, 0, p);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct vnode *
|
||||
union_lowervp(vp)
|
||||
struct vnode *vp;
|
||||
{
|
||||
struct union_node *un = VTOUNION(vp);
|
||||
|
||||
if (un->un_lowervp && (vp->v_type == un->un_lowervp->v_type)) {
|
||||
if (vget(un->un_lowervp, 0))
|
||||
return (NULLVP);
|
||||
if ((un->un_lowervp != NULLVP) &&
|
||||
(vp->v_type == un->un_lowervp->v_type)) {
|
||||
if (vget(un->un_lowervp, 0) == 0)
|
||||
return (un->un_lowervp);
|
||||
}
|
||||
|
||||
return (un->un_lowervp);
|
||||
return (NULLVP);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* determine whether a whiteout is needed
|
||||
* during a remove/rmdir operation.
|
||||
*/
|
||||
int
|
||||
union_dowhiteout(un, cred, p)
|
||||
struct union_node *un;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
{
|
||||
struct vattr va;
|
||||
|
||||
if (un->un_lowervp != NULLVP)
|
||||
return (1);
|
||||
|
||||
if (VOP_GETATTR(un->un_uppervp, &va, cred, p) == 0 &&
|
||||
(va.va_flags & OPAQUE))
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
union_dircache_r(vp, vppp, cntp)
|
||||
struct vnode *vp;
|
||||
struct vnode ***vppp;
|
||||
int *cntp;
|
||||
{
|
||||
struct union_node *un;
|
||||
|
||||
if (vp->v_op != union_vnodeop_p) {
|
||||
if (vppp) {
|
||||
VREF(vp);
|
||||
*(*vppp)++ = vp;
|
||||
if (--(*cntp) == 0)
|
||||
panic("union: dircache table too small");
|
||||
} else {
|
||||
(*cntp)++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
un = VTOUNION(vp);
|
||||
if (un->un_uppervp != NULLVP)
|
||||
union_dircache_r(un->un_uppervp, vppp, cntp);
|
||||
if (un->un_lowervp != NULLVP)
|
||||
union_dircache_r(un->un_lowervp, vppp, cntp);
|
||||
}
|
||||
|
||||
struct vnode *
|
||||
union_dircache(vp, p)
|
||||
struct vnode *vp;
|
||||
struct proc *p;
|
||||
{
|
||||
int cnt;
|
||||
struct vnode *nvp;
|
||||
struct vnode **vpp;
|
||||
struct vnode **dircache;
|
||||
struct union_node *un;
|
||||
int error;
|
||||
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
dircache = VTOUNION(vp)->un_dircache;
|
||||
|
||||
nvp = NULLVP;
|
||||
|
||||
if (dircache == 0) {
|
||||
cnt = 0;
|
||||
union_dircache_r(vp, 0, &cnt);
|
||||
cnt++;
|
||||
dircache = (struct vnode **)
|
||||
malloc(cnt * sizeof(struct vnode *),
|
||||
M_TEMP, M_WAITOK);
|
||||
vpp = dircache;
|
||||
union_dircache_r(vp, &vpp, &cnt);
|
||||
*vpp = NULLVP;
|
||||
vpp = dircache + 1;
|
||||
} else {
|
||||
vpp = dircache;
|
||||
do {
|
||||
if (*vpp++ == VTOUNION(vp)->un_uppervp)
|
||||
break;
|
||||
} while (*vpp != NULLVP);
|
||||
}
|
||||
|
||||
if (*vpp == NULLVP)
|
||||
goto out;
|
||||
|
||||
vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
VREF(*vpp);
|
||||
error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, 0, *vpp, NULLVP, 0);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
VTOUNION(vp)->un_dircache = 0;
|
||||
un = VTOUNION(nvp);
|
||||
un->un_dircache = dircache;
|
||||
|
||||
out:
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
return (nvp);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1994 The Regents of the University of California.
|
||||
* Copyright (c) 1994 Jan-Simon Pendry.
|
||||
* Copyright (c) 1994, 1995 The Regents of the University of California.
|
||||
* Copyright (c) 1994, 1995 Jan-Simon Pendry.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software donated to Berkeley by
|
||||
@ -34,7 +34,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)union_vfsops.c 8.7 (Berkeley) 3/5/94
|
||||
* @(#)union_vfsops.c 8.20 (Berkeley) 5/20/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
#include <sys/queue.h>
|
||||
#include <miscfs/union/union.h>
|
||||
|
||||
extern int union_init __P((void));
|
||||
extern int union_init __P((struct vfsconf *));
|
||||
|
||||
extern int union_fhtovp __P((struct mount *mp, struct fid *fidp,
|
||||
struct mbuf *nam, struct vnode **vpp,
|
||||
@ -92,7 +92,7 @@ union_mount(mp, path, data, ndp, p)
|
||||
struct union_args args;
|
||||
struct vnode *lowerrootvp = NULLVP;
|
||||
struct vnode *upperrootvp = NULLVP;
|
||||
struct union_mount *um;
|
||||
struct union_mount *um = 0;
|
||||
struct ucred *cred = 0;
|
||||
struct ucred *scred;
|
||||
struct vattr va;
|
||||
@ -117,34 +117,6 @@ union_mount(mp, path, data, ndp, p)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a copy of the process's credentials. This isn't
|
||||
* quite right since the euid will always be zero and we
|
||||
* want to get the "real" users credentials. So fix up
|
||||
* the uid field after taking the copy.
|
||||
*/
|
||||
cred = crdup(p->p_ucred);
|
||||
cred->cr_uid = p->p_cred->p_ruid;
|
||||
|
||||
/*
|
||||
* Ensure the *real* user has write permission on the
|
||||
* mounted-on directory. This allows the mount_union
|
||||
* command to be made setuid root so allowing anyone
|
||||
* to do union mounts onto any directory on which they
|
||||
* have write permission and which they also own.
|
||||
*/
|
||||
error = VOP_GETATTR(mp->mnt_vnodecovered, &va, cred, p);
|
||||
if (error)
|
||||
goto bad;
|
||||
if ((va.va_uid != cred->cr_uid) &&
|
||||
(cred->cr_uid != 0)) {
|
||||
error = EACCES;
|
||||
goto bad;
|
||||
}
|
||||
error = VOP_ACCESS(mp->mnt_vnodecovered, VWRITE, cred, p);
|
||||
if (error)
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* Get argument
|
||||
*/
|
||||
@ -156,18 +128,10 @@ union_mount(mp, path, data, ndp, p)
|
||||
VREF(lowerrootvp);
|
||||
|
||||
/*
|
||||
* Find upper node. Use the real process credentials,
|
||||
* not the effective ones since this will have come
|
||||
* through a setuid process (mount_union). All this
|
||||
* messing around with permissions is entirely bogus
|
||||
* and should be removed by allowing any user straight
|
||||
* past the mount system call.
|
||||
* Find upper node.
|
||||
*/
|
||||
scred = p->p_ucred;
|
||||
p->p_ucred = cred;
|
||||
NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT,
|
||||
UIO_USERSPACE, args.target, p);
|
||||
p->p_ucred = scred;
|
||||
|
||||
error = namei(ndp);
|
||||
if (error)
|
||||
@ -218,7 +182,18 @@ union_mount(mp, path, data, ndp, p)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
um->um_cred = cred;
|
||||
/*
|
||||
* Unless the mount is readonly, ensure that the top layer
|
||||
* supports whiteout operations
|
||||
*/
|
||||
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
|
||||
error = VOP_WHITEOUT(um->um_uppervp, (struct componentname *) 0, LOOKUP);
|
||||
if (error)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
um->um_cred = p->p_ucred;
|
||||
crhold(um->um_cred);
|
||||
um->um_cmode = UN_DIRMODE &~ p->p_fd->fd_cmask;
|
||||
|
||||
/*
|
||||
@ -246,24 +221,18 @@ union_mount(mp, path, data, ndp, p)
|
||||
*/
|
||||
mp->mnt_flag |= (um->um_uppervp->v_mount->mnt_flag & MNT_RDONLY);
|
||||
|
||||
/*
|
||||
* This is a user mount. Privilege check for unmount
|
||||
* will be done in union_unmount.
|
||||
*/
|
||||
mp->mnt_flag |= MNT_USER;
|
||||
|
||||
mp->mnt_data = (qaddr_t) um;
|
||||
getnewfsid(mp, MOUNT_UNION);
|
||||
vfs_getnewfsid(mp);
|
||||
|
||||
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
|
||||
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
|
||||
|
||||
switch (um->um_op) {
|
||||
case UNMNT_ABOVE:
|
||||
cp = "<above>";
|
||||
cp = "<above>:";
|
||||
break;
|
||||
case UNMNT_BELOW:
|
||||
cp = "<below>";
|
||||
cp = "<below>:";
|
||||
break;
|
||||
case UNMNT_REPLACE:
|
||||
cp = "";
|
||||
@ -287,6 +256,8 @@ union_mount(mp, path, data, ndp, p)
|
||||
return (0);
|
||||
|
||||
bad:
|
||||
if (um)
|
||||
free(um, M_UFSMNT);
|
||||
if (cred)
|
||||
crfree(cred);
|
||||
if (upperrootvp)
|
||||
@ -323,40 +294,55 @@ union_unmount(mp, mntflags, p)
|
||||
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
|
||||
struct vnode *um_rootvp;
|
||||
int error;
|
||||
int freeing;
|
||||
int flags = 0;
|
||||
|
||||
#ifdef UNION_DIAGNOSTIC
|
||||
printf("union_unmount(mp = %x)\n", mp);
|
||||
#endif
|
||||
|
||||
/* only the mounter, or superuser can unmount */
|
||||
if ((p->p_cred->p_ruid != um->um_cred->cr_uid) &&
|
||||
(error = suser(p->p_ucred, &p->p_acflag)))
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
|
||||
if (error = union_root(mp, &um_rootvp))
|
||||
return (error);
|
||||
|
||||
if (mntflags & MNT_FORCE) {
|
||||
/* union can never be rootfs so don't check for it */
|
||||
if (!doforce)
|
||||
return (EINVAL);
|
||||
flags |= FORCECLOSE;
|
||||
/*
|
||||
* Keep flushing vnodes from the mount list.
|
||||
* This is needed because of the un_pvp held
|
||||
* reference to the parent vnode.
|
||||
* If more vnodes have been freed on a given pass,
|
||||
* the try again. The loop will iterate at most
|
||||
* (d) times, where (d) is the maximum tree depth
|
||||
* in the filesystem.
|
||||
*/
|
||||
for (freeing = 0; vflush(mp, um_rootvp, flags) != 0;) {
|
||||
struct vnode *vp;
|
||||
int n;
|
||||
|
||||
/* count #vnodes held on mount list */
|
||||
for (n = 0, vp = mp->mnt_vnodelist.lh_first;
|
||||
vp != NULLVP;
|
||||
vp = vp->v_mntvnodes.le_next)
|
||||
n++;
|
||||
|
||||
/* if this is unchanged then stop */
|
||||
if (n == freeing)
|
||||
break;
|
||||
|
||||
/* otherwise try once more time */
|
||||
freeing = n;
|
||||
}
|
||||
|
||||
error = union_root(mp, &um_rootvp);
|
||||
if (error)
|
||||
return (error);
|
||||
/* At this point the root vnode should have a single reference */
|
||||
if (um_rootvp->v_usecount > 1) {
|
||||
vput(um_rootvp);
|
||||
return (EBUSY);
|
||||
}
|
||||
error = vflush(mp, um_rootvp, flags);
|
||||
if (error) {
|
||||
vput(um_rootvp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef UNION_DIAGNOSTIC
|
||||
vprint("alias root of lower", um_rootvp);
|
||||
#endif
|
||||
vprint("union root", um_rootvp);
|
||||
#endif
|
||||
/*
|
||||
* Discard references to upper and lower target vnodes.
|
||||
*/
|
||||
@ -385,16 +371,11 @@ union_root(mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
|
||||
int error;
|
||||
int loselock;
|
||||
|
||||
#ifdef UNION_DIAGNOSTIC
|
||||
printf("union_root(mp = %x, lvp = %x, uvp = %x)\n", mp,
|
||||
um->um_lowervp,
|
||||
um->um_uppervp);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return locked reference to root.
|
||||
*/
|
||||
@ -403,7 +384,7 @@ union_root(mp, vpp)
|
||||
VOP_ISLOCKED(um->um_uppervp)) {
|
||||
loselock = 1;
|
||||
} else {
|
||||
VOP_LOCK(um->um_uppervp);
|
||||
vn_lock(um->um_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
loselock = 0;
|
||||
}
|
||||
if (um->um_lowervp)
|
||||
@ -413,16 +394,17 @@ union_root(mp, vpp)
|
||||
(struct vnode *) 0,
|
||||
(struct componentname *) 0,
|
||||
um->um_uppervp,
|
||||
um->um_lowervp);
|
||||
um->um_lowervp,
|
||||
1);
|
||||
|
||||
if (error) {
|
||||
if (!loselock)
|
||||
VOP_UNLOCK(um->um_uppervp);
|
||||
vrele(um->um_uppervp);
|
||||
if (loselock)
|
||||
vrele(um->um_uppervp);
|
||||
else
|
||||
vput(um->um_uppervp);
|
||||
if (um->um_lowervp)
|
||||
vrele(um->um_lowervp);
|
||||
} else {
|
||||
(*vpp)->v_flag |= VROOT;
|
||||
if (loselock)
|
||||
VTOUNION(*vpp)->un_flags &= ~UN_ULOCK;
|
||||
}
|
||||
@ -430,18 +412,6 @@ union_root(mp, vpp)
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
union_quotactl(mp, cmd, uid, arg, p)
|
||||
struct mount *mp;
|
||||
int cmd;
|
||||
uid_t uid;
|
||||
caddr_t arg;
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
int
|
||||
union_statfs(mp, sbp, p)
|
||||
struct mount *mp;
|
||||
@ -485,7 +455,6 @@ union_statfs(mp, sbp, p)
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
sbp->f_type = MOUNT_UNION;
|
||||
sbp->f_flags = mstat.f_flags;
|
||||
sbp->f_bsize = mstat.f_bsize;
|
||||
sbp->f_iosize = mstat.f_iosize;
|
||||
@ -496,18 +465,23 @@ union_statfs(mp, sbp, p)
|
||||
* kind of sense. none of this makes sense though.
|
||||
*/
|
||||
|
||||
if (mstat.f_bsize != lbsize) {
|
||||
if (mstat.f_bsize != lbsize)
|
||||
sbp->f_blocks = sbp->f_blocks * lbsize / mstat.f_bsize;
|
||||
sbp->f_bfree = sbp->f_bfree * lbsize / mstat.f_bsize;
|
||||
sbp->f_bavail = sbp->f_bavail * lbsize / mstat.f_bsize;
|
||||
}
|
||||
|
||||
/*
|
||||
* The "total" fields count total resources in all layers,
|
||||
* the "free" fields count only those resources which are
|
||||
* free in the upper layer (since only the upper layer
|
||||
* is writeable).
|
||||
*/
|
||||
sbp->f_blocks += mstat.f_blocks;
|
||||
sbp->f_bfree += mstat.f_bfree;
|
||||
sbp->f_bavail += mstat.f_bavail;
|
||||
sbp->f_bfree = mstat.f_bfree;
|
||||
sbp->f_bavail = mstat.f_bavail;
|
||||
sbp->f_files += mstat.f_files;
|
||||
sbp->f_ffree += mstat.f_ffree;
|
||||
sbp->f_ffree = mstat.f_ffree;
|
||||
|
||||
if (sbp != &mp->mnt_stat) {
|
||||
sbp->f_type = mp->mnt_vfc->vfc_typenum;
|
||||
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
|
||||
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
|
||||
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
|
||||
@ -515,51 +489,21 @@ union_statfs(mp, sbp, p)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
union_sync(mp, waitfor, cred, p)
|
||||
struct mount *mp;
|
||||
int waitfor;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
{
|
||||
/*
|
||||
* XXX - Assumes no data cached at union layer.
|
||||
*/
|
||||
#define union_sync ((int (*) __P((struct mount *, int, struct ucred *, \
|
||||
struct proc *)))nullop)
|
||||
|
||||
/*
|
||||
* XXX - Assumes no data cached at union layer.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
union_vget(mp, ino, vpp)
|
||||
struct mount *mp;
|
||||
ino_t ino;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
int
|
||||
union_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
|
||||
struct mount *mp;
|
||||
struct fid *fidp;
|
||||
struct mbuf *nam;
|
||||
struct vnode **vpp;
|
||||
int *exflagsp;
|
||||
struct ucred **credanonp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
int
|
||||
union_vptofh(vp, fhp)
|
||||
struct vnode *vp;
|
||||
struct fid *fhp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
#define union_fhtovp ((int (*) __P((struct mount *, struct fid *, \
|
||||
struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
|
||||
#define union_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
|
||||
struct proc *)))eopnotsupp)
|
||||
#define union_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
|
||||
size_t, struct proc *)))eopnotsupp)
|
||||
#define union_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
|
||||
eopnotsupp)
|
||||
#define union_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
|
||||
|
||||
struct vfsops union_vfsops = {
|
||||
union_mount,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufs_bmap.c 8.6 (Berkeley) 1/21/94
|
||||
* @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -63,9 +63,9 @@ int
|
||||
ufs_bmap(ap)
|
||||
struct vop_bmap_args /* {
|
||||
struct vnode *a_vp;
|
||||
daddr_t a_bn;
|
||||
ufs_daddr_t a_bn;
|
||||
struct vnode **a_vpp;
|
||||
daddr_t *a_bnp;
|
||||
ufs_daddr_t *a_bnp;
|
||||
int *a_runp;
|
||||
int *a_runb;
|
||||
} */ *ap;
|
||||
@ -100,8 +100,8 @@ ufs_bmap(ap)
|
||||
int
|
||||
ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
|
||||
struct vnode *vp;
|
||||
register daddr_t bn;
|
||||
daddr_t *bnp;
|
||||
ufs_daddr_t bn;
|
||||
ufs_daddr_t *bnp;
|
||||
struct indir *ap;
|
||||
int *nump;
|
||||
int *runp;
|
||||
@ -113,7 +113,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
|
||||
struct mount *mp;
|
||||
struct vnode *devvp;
|
||||
struct indir a[NIADDR+1], *xap;
|
||||
daddr_t daddr;
|
||||
ufs_daddr_t daddr;
|
||||
long metalbn;
|
||||
int error, maxrun = 0, num;
|
||||
|
||||
@ -209,12 +209,13 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
|
||||
}
|
||||
}
|
||||
|
||||
daddr = ((daddr_t *)bp->b_data)[xap->in_off];
|
||||
daddr = ((ufs_daddr_t *)bp->b_data)[xap->in_off];
|
||||
if (num == 1 && daddr && runp) {
|
||||
for (bn = xap->in_off + 1;
|
||||
bn < MNINDIR(ump) && *runp < maxrun &&
|
||||
is_sequential(ump, ((daddr_t *)bp->b_data)[bn - 1],
|
||||
((daddr_t *)bp->b_data)[bn]);
|
||||
is_sequential(ump,
|
||||
((ufs_daddr_t *)bp->b_data)[bn - 1],
|
||||
((ufs_daddr_t *)bp->b_data)[bn]);
|
||||
++bn, ++*runp);
|
||||
bn = xap->in_off;
|
||||
if (runb && bn) {
|
||||
@ -245,7 +246,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
|
||||
int
|
||||
ufs_getlbns(vp, bn, ap, nump)
|
||||
struct vnode *vp;
|
||||
register daddr_t bn;
|
||||
ufs_daddr_t bn;
|
||||
struct indir *ap;
|
||||
int *nump;
|
||||
{
|
||||
|
@ -56,7 +56,7 @@ int ext2_blkatoff __P((struct vop_blkatoff_args *));
|
||||
void ext2_blkfree __P((struct inode *, daddr_t, long));
|
||||
daddr_t ext2_blkpref __P((struct inode *, daddr_t, int, daddr_t *, daddr_t));
|
||||
int ext2_bmap __P((struct vop_bmap_args *));
|
||||
int ext2_init __P((void));
|
||||
int ext2_init __P((struct vfsconf *));
|
||||
int ext2_reallocblks __P((struct vop_reallocblks_args *));
|
||||
int ext2_reclaim __P((struct vop_reclaim_args *));
|
||||
void ext2_setblock __P((struct ext2_sb_info *, u_char *, daddr_t));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1991, 1993
|
||||
* Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufs_ihash.c 8.4 (Berkeley) 12/30/93
|
||||
* @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -47,9 +47,10 @@
|
||||
/*
|
||||
* Structures associated with inode cacheing.
|
||||
*/
|
||||
struct inode **ihashtbl;
|
||||
LIST_HEAD(ihashhead, inode) *ihashtbl;
|
||||
u_long ihash; /* size of hash table - 1 */
|
||||
#define INOHASH(device, inum) (((device) + (inum)) & ihash)
|
||||
#define INOHASH(device, inum) (&ihashtbl[((device) + (inum)) & ihash])
|
||||
struct simplelock ufs_ihash_slock;
|
||||
|
||||
/*
|
||||
* Initialize inode hash table.
|
||||
@ -59,6 +60,7 @@ ufs_ihashinit()
|
||||
{
|
||||
|
||||
ihashtbl = hashinit(desiredvnodes, M_UFSMNT, &ihash);
|
||||
simple_lock_init(&ufs_ihash_slock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -66,19 +68,21 @@ ufs_ihashinit()
|
||||
* to it. If it is in core, return it, even if it is locked.
|
||||
*/
|
||||
struct vnode *
|
||||
ufs_ihashlookup(device, inum)
|
||||
dev_t device;
|
||||
ufs_ihashlookup(dev, inum)
|
||||
dev_t dev;
|
||||
ino_t inum;
|
||||
{
|
||||
register struct inode *ip;
|
||||
struct inode *ip;
|
||||
|
||||
for (ip = ihashtbl[INOHASH(device, inum)];; ip = ip->i_next) {
|
||||
if (ip == NULL)
|
||||
return (NULL);
|
||||
if (inum == ip->i_number && device == ip->i_dev)
|
||||
return (ITOV(ip));
|
||||
}
|
||||
/* NOTREACHED */
|
||||
simple_lock(&ufs_ihash_slock);
|
||||
for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next)
|
||||
if (inum == ip->i_number && dev == ip->i_dev)
|
||||
break;
|
||||
simple_unlock(&ufs_ihash_slock);
|
||||
|
||||
if (ip)
|
||||
return (ITOV(ip));
|
||||
return (NULLVP);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -86,36 +90,28 @@ ufs_ihashlookup(device, inum)
|
||||
* to it. If it is in core, but locked, wait for it.
|
||||
*/
|
||||
struct vnode *
|
||||
ufs_ihashget(device, inum)
|
||||
dev_t device;
|
||||
ufs_ihashget(dev, inum)
|
||||
dev_t dev;
|
||||
ino_t inum;
|
||||
{
|
||||
register struct inode *ip;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct inode *ip;
|
||||
struct vnode *vp;
|
||||
|
||||
for (;;)
|
||||
for (ip = ihashtbl[INOHASH(device, inum)];; ip = ip->i_next) {
|
||||
if (ip == NULL)
|
||||
return (NULL);
|
||||
if (inum == ip->i_number && device == ip->i_dev) {
|
||||
if (ip->i_flag & IN_LOCKED) {
|
||||
if( curproc->p_pid != ip->i_lockholder) {
|
||||
ip->i_flag |= IN_WANTED;
|
||||
(void) tsleep(ip, PINOD, "uihget", 0);
|
||||
break;
|
||||
} else if (ip->i_flag & IN_RECURSE) {
|
||||
ip->i_lockcount++;
|
||||
} else {
|
||||
panic("ufs_ihashget: recursive lock not expected -- pid %d\n", ip->i_lockholder);
|
||||
}
|
||||
}
|
||||
vp = ITOV(ip);
|
||||
if (!vget(vp, 1))
|
||||
return (vp);
|
||||
break;
|
||||
}
|
||||
loop:
|
||||
simple_lock(&ufs_ihash_slock);
|
||||
for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) {
|
||||
if (inum == ip->i_number && dev == ip->i_dev) {
|
||||
vp = ITOV(ip);
|
||||
simple_lock(&vp->v_interlock);
|
||||
simple_unlock(&ufs_ihash_slock);
|
||||
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p))
|
||||
goto loop;
|
||||
return (vp);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
simple_unlock(&ufs_ihash_slock);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -125,26 +121,16 @@ void
|
||||
ufs_ihashins(ip)
|
||||
struct inode *ip;
|
||||
{
|
||||
struct inode **ipp, *iq;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct ihashhead *ipp;
|
||||
|
||||
ipp = &ihashtbl[INOHASH(ip->i_dev, ip->i_number)];
|
||||
iq = *ipp;
|
||||
if (iq)
|
||||
iq->i_prev = &ip->i_next;
|
||||
ip->i_next = iq;
|
||||
ip->i_prev = ipp;
|
||||
*ipp = ip;
|
||||
if ((ip->i_flag & IN_LOCKED) &&
|
||||
((ip->i_flag & IN_RECURSE) == 0 ||
|
||||
(!curproc || (curproc && (ip->i_lockholder != curproc->p_pid)))))
|
||||
panic("ufs_ihashins: already locked");
|
||||
if (curproc) {
|
||||
ip->i_lockcount += 1;
|
||||
ip->i_lockholder = curproc->p_pid;
|
||||
} else {
|
||||
ip->i_lockholder = -1;
|
||||
}
|
||||
ip->i_flag |= IN_LOCKED;
|
||||
/* lock the inode, then put it on the appropriate hash list */
|
||||
lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p);
|
||||
|
||||
simple_lock(&ufs_ihash_slock);
|
||||
ipp = INOHASH(ip->i_dev, ip->i_number);
|
||||
LIST_INSERT_HEAD(ipp, ip, i_hash);
|
||||
simple_unlock(&ufs_ihash_slock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -152,16 +138,13 @@ ufs_ihashins(ip)
|
||||
*/
|
||||
void
|
||||
ufs_ihashrem(ip)
|
||||
register struct inode *ip;
|
||||
struct inode *ip;
|
||||
{
|
||||
register struct inode *iq;
|
||||
|
||||
iq = ip->i_next;
|
||||
if (iq)
|
||||
iq->i_prev = ip->i_prev;
|
||||
*ip->i_prev = iq;
|
||||
simple_lock(&ufs_ihash_slock);
|
||||
LIST_REMOVE(ip, i_hash);
|
||||
#ifdef DIAGNOSTIC
|
||||
ip->i_next = NULL;
|
||||
ip->i_prev = NULL;
|
||||
ip->i_hash.le_next = NULL;
|
||||
ip->i_hash.le_prev = NULL;
|
||||
#endif
|
||||
simple_unlock(&ufs_ihash_slock);
|
||||
}
|
||||
|
@ -77,9 +77,9 @@ static int ext2_indirtrunc __P((struct inode *, daddr_t, daddr_t, daddr_t, int,
|
||||
long *));
|
||||
|
||||
int
|
||||
ext2_init()
|
||||
ext2_init(struct vfsconf *vfsp)
|
||||
{
|
||||
return (ufs_init());
|
||||
return (ufs_init(vfsp));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -118,16 +118,16 @@ ext2_update(ap)
|
||||
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)
|
||||
return (0);
|
||||
if (ip->i_flag & IN_ACCESS)
|
||||
ip->i_atime.tv_sec = ap->a_access->tv_sec;
|
||||
ip->i_atime = ap->a_access->tv_sec;
|
||||
if (ip->i_flag & IN_UPDATE) {
|
||||
ip->i_mtime.tv_sec = ap->a_modify->tv_sec;
|
||||
ip->i_mtime = ap->a_modify->tv_sec;
|
||||
ip->i_modrev++;
|
||||
}
|
||||
if (ip->i_flag & IN_CHANGE) {
|
||||
#if !defined(__FreeBSD__)
|
||||
get_time(&time);
|
||||
#endif
|
||||
ip->i_ctime.tv_sec = time.tv_sec;
|
||||
ip->i_ctime = time.tv_sec;
|
||||
}
|
||||
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
|
||||
fs = ip->i_e2fs;
|
||||
|
@ -66,17 +66,17 @@ ext2_print_dinode( di )
|
||||
di->di_uid, di->di_gid, di->di_size);
|
||||
printf( "Links: %3d Blockcount: %d\n",
|
||||
di->di_nlink, di->di_blocks);
|
||||
printf( "ctime: 0x%x", di->di_ctime.tv_sec);
|
||||
printf( "ctime: 0x%x", di->di_ctime);
|
||||
#if !defined(__FreeBSD__)
|
||||
print_time(" -- %s\n", di->di_ctime.tv_sec);
|
||||
print_time(" -- %s\n", di->di_ctime);
|
||||
#endif
|
||||
printf( "atime: 0x%x", di->di_atime.tv_sec);
|
||||
printf( "atime: 0x%x", di->di_atime);
|
||||
#if !defined(__FreeBSD__)
|
||||
print_time(" -- %s\n", di->di_atime.tv_sec);
|
||||
print_time(" -- %s\n", di->di_atime);
|
||||
#endif
|
||||
printf( "mtime: 0x%x", di->di_mtime.tv_sec);
|
||||
printf( "mtime: 0x%x", di->di_mtime);
|
||||
#if !defined(__FreeBSD__)
|
||||
print_time(" -- %s\n", di->di_mtime.tv_sec);
|
||||
print_time(" -- %s\n", di->di_mtime);
|
||||
#endif
|
||||
printf( "BLOCKS: ");
|
||||
for(i=0; i < (di->di_blocks <= 24 ? ((di->di_blocks+1)/2): 12); i++)
|
||||
@ -110,9 +110,9 @@ ext2_ei2di(ei, di)
|
||||
*/
|
||||
di->di_mode = ei->i_links_count ? ei->i_mode : 0;
|
||||
di->di_size = ei->i_size;
|
||||
di->di_atime.tv_sec = ei->i_atime;
|
||||
di->di_mtime.tv_sec = ei->i_mtime;
|
||||
di->di_ctime.tv_sec = ei->i_ctime;
|
||||
di->di_atime = ei->i_atime;
|
||||
di->di_mtime = ei->i_mtime;
|
||||
di->di_ctime = ei->i_ctime;
|
||||
di->di_flags = 0;
|
||||
di->di_flags |= (ei->i_flags & EXT2_APPEND_FL) ? APPEND : 0;
|
||||
di->di_flags |= (ei->i_flags & EXT2_IMMUTABLE_FL) ? IMMUTABLE : 0;
|
||||
@ -143,11 +143,11 @@ ext2_di2ei(di, ei)
|
||||
Godmar thinks: if dtime is nonzero, ext2 says this inode
|
||||
has been deleted, this would correspond to a zero link count
|
||||
*/
|
||||
ei->i_dtime = ei->i_links_count ? 0 : di->di_mtime.tv_sec;
|
||||
ei->i_dtime = ei->i_links_count ? 0 : di->di_mtime;
|
||||
ei->i_size = di->di_size;
|
||||
ei->i_atime = di->di_atime.tv_sec;
|
||||
ei->i_mtime = di->di_mtime.tv_sec;
|
||||
ei->i_ctime = di->di_ctime.tv_sec;
|
||||
ei->i_atime = di->di_atime;
|
||||
ei->i_mtime = di->di_mtime;
|
||||
ei->i_ctime = di->di_ctime;
|
||||
ei->i_flags = di->di_flags;
|
||||
ei->i_flags = 0;
|
||||
ei->i_flags |= (di->di_flags & APPEND) ? EXT2_APPEND_FL: 0;
|
||||
|
@ -274,6 +274,7 @@ ext2_lookup(ap)
|
||||
struct ucred *cred = cnp->cn_cred;
|
||||
int flags = cnp->cn_flags;
|
||||
int nameiop = cnp->cn_nameiop;
|
||||
struct proc *p = cnp->cn_proc;
|
||||
|
||||
int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->s_blocksize;
|
||||
|
||||
@ -318,14 +319,14 @@ ext2_lookup(ap)
|
||||
VREF(vdp);
|
||||
error = 0;
|
||||
} else if (flags & ISDOTDOT) {
|
||||
VOP_UNLOCK(pdp);
|
||||
error = vget(vdp, 1);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
error = vget(vdp, LK_EXCLUSIVE, p);
|
||||
if (!error && lockparent && (flags & ISLASTCN))
|
||||
error = VOP_LOCK(pdp);
|
||||
error = vn_lock(pdp, LK_EXCLUSIVE, p);
|
||||
} else {
|
||||
error = vget(vdp, 1);
|
||||
error = vget(vdp, LK_EXCLUSIVE, p);
|
||||
if (!lockparent || error || !(flags & ISLASTCN))
|
||||
VOP_UNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
}
|
||||
/*
|
||||
* Check that the capability number did not change
|
||||
@ -336,9 +337,9 @@ ext2_lookup(ap)
|
||||
return (0);
|
||||
vput(vdp);
|
||||
if (lockparent && pdp != vdp && (flags & ISLASTCN))
|
||||
VOP_UNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
}
|
||||
if (error = VOP_LOCK(pdp))
|
||||
if (error = vn_lock(pdp, LK_EXCLUSIVE, p))
|
||||
return (error);
|
||||
vdp = pdp;
|
||||
dp = VTOI(pdp);
|
||||
@ -548,7 +549,7 @@ ext2_lookup(ap)
|
||||
*/
|
||||
cnp->cn_flags |= SAVENAME;
|
||||
if (!lockparent)
|
||||
VOP_UNLOCK(vdp);
|
||||
VOP_UNLOCK(vdp, 0, p);
|
||||
return (EJUSTRETURN);
|
||||
}
|
||||
/*
|
||||
@ -625,7 +626,7 @@ ext2_lookup(ap)
|
||||
}
|
||||
*vpp = tdp;
|
||||
if (!lockparent)
|
||||
VOP_UNLOCK(vdp);
|
||||
VOP_UNLOCK(vdp, 0, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -650,7 +651,7 @@ ext2_lookup(ap)
|
||||
*vpp = tdp;
|
||||
cnp->cn_flags |= SAVENAME;
|
||||
if (!lockparent)
|
||||
VOP_UNLOCK(vdp);
|
||||
VOP_UNLOCK(vdp, 0, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -675,13 +676,13 @@ ext2_lookup(ap)
|
||||
*/
|
||||
pdp = vdp;
|
||||
if (flags & ISDOTDOT) {
|
||||
VOP_UNLOCK(pdp); /* race to get the inode */
|
||||
VOP_UNLOCK(pdp, 0, p); /* race to get the inode */
|
||||
if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) {
|
||||
VOP_LOCK(pdp);
|
||||
vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
return (error);
|
||||
}
|
||||
if (lockparent && (flags & ISLASTCN) &&
|
||||
(error = VOP_LOCK(pdp))) {
|
||||
(error = vn_lock(pdp, LK_EXCLUSIVE, p))) {
|
||||
vput(tdp);
|
||||
return (error);
|
||||
}
|
||||
@ -693,7 +694,7 @@ ext2_lookup(ap)
|
||||
if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp))
|
||||
return (error);
|
||||
if (!lockparent || !(flags & ISLASTCN))
|
||||
VOP_UNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
*vpp = tdp;
|
||||
}
|
||||
|
||||
|
@ -30,13 +30,34 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufsmount.h 8.2 (Berkeley) 1/12/94
|
||||
* @(#)ufsmount.h 8.6 (Berkeley) 3/30/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_UFSMOUNT_H_
|
||||
#define _UFS_UFS_UFSMOUNT_H_
|
||||
|
||||
/*
|
||||
* Arguments to mount UFS-based filesystems
|
||||
*/
|
||||
struct ufs_args {
|
||||
char *fspec; /* block special device to mount */
|
||||
struct export_args export; /* network export information */
|
||||
};
|
||||
|
||||
#ifdef MFS
|
||||
/*
|
||||
* Arguments to mount MFS
|
||||
*/
|
||||
struct mfs_args {
|
||||
char *fspec; /* name to export for statfs */
|
||||
struct export_args export; /* if exported MFSes are supported */
|
||||
caddr_t base; /* base of file system in memory */
|
||||
u_long size; /* size of file system */
|
||||
};
|
||||
#endif /* MFS */
|
||||
|
||||
#ifdef KERNEL
|
||||
struct buf;
|
||||
struct inode;
|
||||
struct nameidata;
|
||||
@ -51,6 +72,7 @@ struct ufsmount {
|
||||
struct mount *um_mountp; /* filesystem vfs structure */
|
||||
dev_t um_dev; /* device mounted */
|
||||
struct vnode *um_devvp; /* block device mounted vnode */
|
||||
|
||||
union { /* pointer to superblock */
|
||||
struct lfs *lfs; /* LFS */
|
||||
struct fs *fs; /* FFS */
|
||||
@ -60,6 +82,7 @@ struct ufsmount {
|
||||
#define um_lfs ufsmount_u.lfs
|
||||
#define um_e2fs ufsmount_u.e2fs
|
||||
#define um_e2fsb ufsmount_u.e2fs->s_es
|
||||
|
||||
struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */
|
||||
struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */
|
||||
u_long um_nindir; /* indirect ptrs per block */
|
||||
@ -69,7 +92,9 @@ struct ufsmount {
|
||||
time_t um_itime[MAXQUOTAS]; /* inode quota time limit */
|
||||
char um_qflags[MAXQUOTAS]; /* quota specific flags */
|
||||
struct netexport um_export; /* export information */
|
||||
int64_t um_savedmaxfilesize; /* XXX - limit maxfilesize */
|
||||
};
|
||||
|
||||
/*
|
||||
* Flags describing the state of quotas.
|
||||
*/
|
||||
@ -83,8 +108,9 @@ struct ufsmount {
|
||||
* Macros to access file system parameters in the ufsmount structure.
|
||||
* Used by ufs_bmap.
|
||||
*/
|
||||
#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
|
||||
#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
|
||||
#define MNINDIR(ump) ((ump)->um_nindir)
|
||||
#define MNINDIR(ump) ((ump)->um_nindir)
|
||||
#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
|
||||
#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif
|
||||
|
@ -221,10 +221,10 @@ ext2_mount(mp, path, data, ndp, p)
|
||||
flags = WRITECLOSE;
|
||||
if (mp->mnt_flag & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
if (vfs_busy(mp))
|
||||
if (vfs_busy(mp, LK_NOWAIT, 0, p))
|
||||
return (EBUSY);
|
||||
error = ext2_flushfiles(mp, flags, p);
|
||||
vfs_unbusy(mp);
|
||||
vfs_unbusy(mp, p);
|
||||
}
|
||||
if (!error && (mp->mnt_flag & MNT_RELOAD))
|
||||
error = ext2_reload(mp, ndp->ni_cnd.cn_cred, p);
|
||||
@ -515,7 +515,7 @@ ext2_reload(mountp, cred, p)
|
||||
/*
|
||||
* Step 5: invalidate all cached file data.
|
||||
*/
|
||||
if (vget(vp, 1))
|
||||
if (vget(vp, LK_EXCLUSIVE, p))
|
||||
goto loop;
|
||||
if (vinvalbuf(vp, 0, cred, p, 0, 0))
|
||||
panic("ext2_reload: dirty2");
|
||||
@ -727,17 +727,12 @@ ext2_flushfiles(mp, flags, p)
|
||||
int flags;
|
||||
struct proc *p;
|
||||
{
|
||||
#if !defined(__FreeBSD__)
|
||||
extern int doforce;
|
||||
#endif
|
||||
register struct ufsmount *ump;
|
||||
int error;
|
||||
#if QUOTA
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if (!doforce)
|
||||
flags &= ~FORCECLOSE;
|
||||
ump = VFSTOUFS(mp);
|
||||
#if QUOTA
|
||||
if (mp->mnt_flag & MNT_QUOTA) {
|
||||
@ -872,7 +867,7 @@ ext2_sync(mp, waitfor, cred, p)
|
||||
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
|
||||
vp->v_dirtyblkhd.lh_first == NULL)
|
||||
continue;
|
||||
if (vget(vp, 1))
|
||||
if (vget(vp, LK_EXCLUSIVE, p))
|
||||
goto loop;
|
||||
if (error = VOP_FSYNC(vp, cred, waitfor, p))
|
||||
allerror = error;
|
||||
|
@ -152,6 +152,6 @@ extern u_char *fragtbl[];
|
||||
* I think I'll try a VOP_LOCK/VOP_UNLOCK on the device vnode
|
||||
*/
|
||||
#define DEVVP(inode) (VFSTOUFS(ITOV(inode)->v_mount)->um_devvp)
|
||||
#define lock_super(devvp) VOP_LOCK(devvp)
|
||||
#define unlock_super(devvp) VOP_UNLOCK(devvp)
|
||||
#define lock_super(devvp) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, curproc)
|
||||
#define unlock_super(devvp) VOP_UNLOCK(devvp, 0, curproc)
|
||||
|
||||
|
@ -35,42 +35,33 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)inode.h 8.4 (Berkeley) 1/21/94
|
||||
* @(#)inode.h 8.9 (Berkeley) 5/14/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_INODE_H_
|
||||
#define _UFS_UFS_INODE_H_
|
||||
|
||||
#include <ufs/ufs/dir.h>
|
||||
#include <ufs/ufs/dinode.h>
|
||||
|
||||
/*
|
||||
* Theoretically, directories can be more than 2Gb in length, however, in
|
||||
* practice this seems unlikely. So, we define the type doff_t as a long
|
||||
* to keep down the cost of doing lookup on a 32-bit machine. If you are
|
||||
* porting to a 64-bit architecture, you should make doff_t the same as off_t.
|
||||
*/
|
||||
#define doff_t long
|
||||
|
||||
/*
|
||||
* The inode is used to describe each active (or recently active)
|
||||
* file in the UFS filesystem. It is composed of two types of
|
||||
* information. The first part is the information that is needed
|
||||
* only while the file is active (such as the identity of the file
|
||||
* and linkage to speed its lookup). The second part is the
|
||||
* permanent meta-data associated with the file which is read
|
||||
* in from the permanent dinode from long term storage when the
|
||||
* file becomes active, and is put back when the file is no longer
|
||||
* being used.
|
||||
* The inode is used to describe each active (or recently active) file in the
|
||||
* UFS filesystem. It is composed of two types of information. The first part
|
||||
* is the information that is needed only while the file is active (such as
|
||||
* the identity of the file and linkage to speed its lookup). The second part
|
||||
* is the permanent meta-data associated with the file which is read in
|
||||
* from the permanent dinode from long term storage when the file becomes
|
||||
* active, and is put back when the file is no longer being used.
|
||||
*/
|
||||
struct inode {
|
||||
struct inode *i_next; /* Hash chain forward. */
|
||||
struct inode **i_prev; /* Hash chain back. */
|
||||
struct vnode *i_vnode; /* Vnode associated with this inode. */
|
||||
struct vnode *i_devvp; /* Vnode for block I/O. */
|
||||
u_long i_flag; /* I* flags. */
|
||||
dev_t i_dev; /* Device associated with the inode. */
|
||||
ino_t i_number; /* The identity of the inode. */
|
||||
LIST_ENTRY(inode) i_hash;/* Hash chain. */
|
||||
struct vnode *i_vnode;/* Vnode associated with this inode. */
|
||||
struct vnode *i_devvp;/* Vnode for block I/O. */
|
||||
u_int32_t i_flag; /* flags, see below */
|
||||
dev_t i_dev; /* Device associated with the inode. */
|
||||
ino_t i_number; /* The identity of the inode. */
|
||||
|
||||
union { /* Associated filesystem. */
|
||||
struct fs *fs; /* FFS */
|
||||
struct lfs *lfs; /* LFS */
|
||||
@ -79,22 +70,21 @@ struct inode {
|
||||
#define i_fs inode_u.fs
|
||||
#define i_lfs inode_u.lfs
|
||||
#define i_e2fs inode_u.e2fs
|
||||
struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
|
||||
u_quad_t i_modrev; /* Revision level for lease. */
|
||||
struct lockf *i_lockf; /* Head of byte-level lock list. */
|
||||
pid_t i_lockholder; /* DEBUG: holder of inode lock. */
|
||||
pid_t i_lockwaiter; /* DEBUG: latest blocked for inode lock. */
|
||||
struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
|
||||
u_quad_t i_modrev; /* Revision level for NFS lease. */
|
||||
struct lockf *i_lockf;/* Head of byte-level lock list. */
|
||||
struct lock i_lock; /* Inode lock. */
|
||||
/*
|
||||
* Side effects; used during directory lookup.
|
||||
*/
|
||||
long i_count; /* Size of free slot in directory. */
|
||||
doff_t i_endoff; /* End of useful stuff in directory. */
|
||||
doff_t i_diroff; /* Offset in dir, where we found last entry. */
|
||||
doff_t i_offset; /* Offset of free space in directory. */
|
||||
ino_t i_ino; /* Inode number of found directory. */
|
||||
u_long i_reclen; /* Size of found directory entry. */
|
||||
int i_lockcount; /* Process lock count (recursion) */
|
||||
long i_spare[10]; /* Spares to round up to 128 bytes. */
|
||||
int32_t i_count; /* Size of free slot in directory. */
|
||||
doff_t i_endoff; /* End of useful stuff in directory. */
|
||||
doff_t i_diroff; /* Offset in dir, where we found last entry. */
|
||||
doff_t i_offset; /* Offset of free space in directory. */
|
||||
ino_t i_ino; /* Inode number of found directory. */
|
||||
u_int32_t i_reclen; /* Size of found directory entry. */
|
||||
int i_lockcount; /* Process lock count (recursion) */
|
||||
int i_spare[10]; /* XXX spare storage (for ext2fs) */
|
||||
/*
|
||||
* The on-disk dinode itself.
|
||||
*/
|
||||
@ -102,8 +92,10 @@ struct inode {
|
||||
};
|
||||
|
||||
#define i_atime i_din.di_atime
|
||||
#define i_atimensec i_din.di_atimensec
|
||||
#define i_blocks i_din.di_blocks
|
||||
#define i_ctime i_din.di_ctime
|
||||
#define i_ctimensec i_din.di_ctimensec
|
||||
#define i_db i_din.di_db
|
||||
#define i_flags i_din.di_flags
|
||||
#define i_gen i_din.di_gen
|
||||
@ -111,6 +103,7 @@ struct inode {
|
||||
#define i_ib i_din.di_ib
|
||||
#define i_mode i_din.di_mode
|
||||
#define i_mtime i_din.di_mtime
|
||||
#define i_mtimensec i_din.di_mtimensec
|
||||
#define i_nlink i_din.di_nlink
|
||||
#define i_rdev i_din.di_rdev
|
||||
#define i_shortlink i_din.di_shortlink
|
||||
@ -120,15 +113,12 @@ struct inode {
|
||||
/* These flags are kept in i_flag. */
|
||||
#define IN_ACCESS 0x0001 /* Access time update request. */
|
||||
#define IN_CHANGE 0x0002 /* Inode change time update request. */
|
||||
#define IN_EXLOCK 0x0004 /* File has exclusive lock. */
|
||||
#define IN_LOCKED 0x0008 /* Inode lock. */
|
||||
#define IN_LWAIT 0x0010 /* Process waiting on file lock. */
|
||||
#define IN_MODIFIED 0x0020 /* Inode has been modified. */
|
||||
#define IN_RENAME 0x0040 /* Inode is being renamed. */
|
||||
#define IN_SHLOCK 0x0080 /* File has shared lock. */
|
||||
#define IN_UPDATE 0x0100 /* Modification time update request. */
|
||||
#define IN_WANTED 0x0200 /* Inode is wanted by a process. */
|
||||
#define IN_RECURSE 0x0400 /* Recursion expected */
|
||||
#define IN_UPDATE 0x0004 /* Modification time update request. */
|
||||
#define IN_MODIFIED 0x0008 /* Inode has been modified. */
|
||||
#define IN_RENAME 0x0010 /* Inode is being renamed. */
|
||||
#define IN_SHLOCK 0x0020 /* File has shared lock. */
|
||||
#define IN_EXLOCK 0x0040 /* File has exclusive lock. */
|
||||
#define IN_RECURSE 0x0080 /* Recursion expected */
|
||||
|
||||
#ifdef KERNEL
|
||||
/*
|
||||
@ -136,7 +126,7 @@ struct inode {
|
||||
* ufs_getlbns and used by truncate and bmap code.
|
||||
*/
|
||||
struct indir {
|
||||
daddr_t in_lbn; /* Logical block number. */
|
||||
ufs_daddr_t in_lbn; /* Logical block number. */
|
||||
int in_off; /* Offset in buffer. */
|
||||
int in_exists; /* Flag if the block exists. */
|
||||
};
|
||||
@ -155,25 +145,25 @@ struct indir {
|
||||
if ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) { \
|
||||
(ip)->i_flag |= IN_MODIFIED; \
|
||||
if ((ip)->i_flag & IN_ACCESS) \
|
||||
(ip)->i_atime.tv_sec \
|
||||
(ip)->i_atime \
|
||||
= ((t1) == &time ? tv_sec : (t1)->tv_sec); \
|
||||
if ((ip)->i_flag & IN_UPDATE) { \
|
||||
(ip)->i_mtime.tv_sec \
|
||||
(ip)->i_mtime \
|
||||
= ((t2) == &time ? tv_sec : (t2)->tv_sec); \
|
||||
(ip)->i_modrev++; \
|
||||
} \
|
||||
if ((ip)->i_flag & IN_CHANGE) \
|
||||
(ip)->i_ctime.tv_sec = tv_sec; \
|
||||
(ip)->i_ctime = tv_sec; \
|
||||
(ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* This overlays the fid structure (see mount.h). */
|
||||
struct ufid {
|
||||
u_short ufid_len; /* Length of structure. */
|
||||
u_short ufid_pad; /* Force long alignment. */
|
||||
ino_t ufid_ino; /* File number (ino). */
|
||||
long ufid_gen; /* Generation number. */
|
||||
u_int16_t ufid_len; /* Length of structure. */
|
||||
u_int16_t ufid_pad; /* Force 32-bit alignment. */
|
||||
ino_t ufid_ino; /* File number (ino). */
|
||||
int32_t ufid_gen; /* Generation number. */
|
||||
};
|
||||
#endif /* KERNEL */
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufs_bmap.c 8.6 (Berkeley) 1/21/94
|
||||
* @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -63,9 +63,9 @@ int
|
||||
ufs_bmap(ap)
|
||||
struct vop_bmap_args /* {
|
||||
struct vnode *a_vp;
|
||||
daddr_t a_bn;
|
||||
ufs_daddr_t a_bn;
|
||||
struct vnode **a_vpp;
|
||||
daddr_t *a_bnp;
|
||||
ufs_daddr_t *a_bnp;
|
||||
int *a_runp;
|
||||
int *a_runb;
|
||||
} */ *ap;
|
||||
@ -100,8 +100,8 @@ ufs_bmap(ap)
|
||||
int
|
||||
ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
|
||||
struct vnode *vp;
|
||||
register daddr_t bn;
|
||||
daddr_t *bnp;
|
||||
ufs_daddr_t bn;
|
||||
ufs_daddr_t *bnp;
|
||||
struct indir *ap;
|
||||
int *nump;
|
||||
int *runp;
|
||||
@ -113,7 +113,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
|
||||
struct mount *mp;
|
||||
struct vnode *devvp;
|
||||
struct indir a[NIADDR+1], *xap;
|
||||
daddr_t daddr;
|
||||
ufs_daddr_t daddr;
|
||||
long metalbn;
|
||||
int error, maxrun = 0, num;
|
||||
|
||||
@ -209,12 +209,13 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
|
||||
}
|
||||
}
|
||||
|
||||
daddr = ((daddr_t *)bp->b_data)[xap->in_off];
|
||||
daddr = ((ufs_daddr_t *)bp->b_data)[xap->in_off];
|
||||
if (num == 1 && daddr && runp) {
|
||||
for (bn = xap->in_off + 1;
|
||||
bn < MNINDIR(ump) && *runp < maxrun &&
|
||||
is_sequential(ump, ((daddr_t *)bp->b_data)[bn - 1],
|
||||
((daddr_t *)bp->b_data)[bn]);
|
||||
is_sequential(ump,
|
||||
((ufs_daddr_t *)bp->b_data)[bn - 1],
|
||||
((ufs_daddr_t *)bp->b_data)[bn]);
|
||||
++bn, ++*runp);
|
||||
bn = xap->in_off;
|
||||
if (runb && bn) {
|
||||
@ -245,7 +246,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
|
||||
int
|
||||
ufs_getlbns(vp, bn, ap, nump)
|
||||
struct vnode *vp;
|
||||
register daddr_t bn;
|
||||
ufs_daddr_t bn;
|
||||
struct indir *ap;
|
||||
int *nump;
|
||||
{
|
||||
|
@ -56,7 +56,7 @@ int ext2_blkatoff __P((struct vop_blkatoff_args *));
|
||||
void ext2_blkfree __P((struct inode *, daddr_t, long));
|
||||
daddr_t ext2_blkpref __P((struct inode *, daddr_t, int, daddr_t *, daddr_t));
|
||||
int ext2_bmap __P((struct vop_bmap_args *));
|
||||
int ext2_init __P((void));
|
||||
int ext2_init __P((struct vfsconf *));
|
||||
int ext2_reallocblks __P((struct vop_reallocblks_args *));
|
||||
int ext2_reclaim __P((struct vop_reclaim_args *));
|
||||
void ext2_setblock __P((struct ext2_sb_info *, u_char *, daddr_t));
|
||||
|
@ -77,9 +77,9 @@ static int ext2_indirtrunc __P((struct inode *, daddr_t, daddr_t, daddr_t, int,
|
||||
long *));
|
||||
|
||||
int
|
||||
ext2_init()
|
||||
ext2_init(struct vfsconf *vfsp)
|
||||
{
|
||||
return (ufs_init());
|
||||
return (ufs_init(vfsp));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -118,16 +118,16 @@ ext2_update(ap)
|
||||
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)
|
||||
return (0);
|
||||
if (ip->i_flag & IN_ACCESS)
|
||||
ip->i_atime.tv_sec = ap->a_access->tv_sec;
|
||||
ip->i_atime = ap->a_access->tv_sec;
|
||||
if (ip->i_flag & IN_UPDATE) {
|
||||
ip->i_mtime.tv_sec = ap->a_modify->tv_sec;
|
||||
ip->i_mtime = ap->a_modify->tv_sec;
|
||||
ip->i_modrev++;
|
||||
}
|
||||
if (ip->i_flag & IN_CHANGE) {
|
||||
#if !defined(__FreeBSD__)
|
||||
get_time(&time);
|
||||
#endif
|
||||
ip->i_ctime.tv_sec = time.tv_sec;
|
||||
ip->i_ctime = time.tv_sec;
|
||||
}
|
||||
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
|
||||
fs = ip->i_e2fs;
|
||||
|
@ -66,17 +66,17 @@ ext2_print_dinode( di )
|
||||
di->di_uid, di->di_gid, di->di_size);
|
||||
printf( "Links: %3d Blockcount: %d\n",
|
||||
di->di_nlink, di->di_blocks);
|
||||
printf( "ctime: 0x%x", di->di_ctime.tv_sec);
|
||||
printf( "ctime: 0x%x", di->di_ctime);
|
||||
#if !defined(__FreeBSD__)
|
||||
print_time(" -- %s\n", di->di_ctime.tv_sec);
|
||||
print_time(" -- %s\n", di->di_ctime);
|
||||
#endif
|
||||
printf( "atime: 0x%x", di->di_atime.tv_sec);
|
||||
printf( "atime: 0x%x", di->di_atime);
|
||||
#if !defined(__FreeBSD__)
|
||||
print_time(" -- %s\n", di->di_atime.tv_sec);
|
||||
print_time(" -- %s\n", di->di_atime);
|
||||
#endif
|
||||
printf( "mtime: 0x%x", di->di_mtime.tv_sec);
|
||||
printf( "mtime: 0x%x", di->di_mtime);
|
||||
#if !defined(__FreeBSD__)
|
||||
print_time(" -- %s\n", di->di_mtime.tv_sec);
|
||||
print_time(" -- %s\n", di->di_mtime);
|
||||
#endif
|
||||
printf( "BLOCKS: ");
|
||||
for(i=0; i < (di->di_blocks <= 24 ? ((di->di_blocks+1)/2): 12); i++)
|
||||
@ -110,9 +110,9 @@ ext2_ei2di(ei, di)
|
||||
*/
|
||||
di->di_mode = ei->i_links_count ? ei->i_mode : 0;
|
||||
di->di_size = ei->i_size;
|
||||
di->di_atime.tv_sec = ei->i_atime;
|
||||
di->di_mtime.tv_sec = ei->i_mtime;
|
||||
di->di_ctime.tv_sec = ei->i_ctime;
|
||||
di->di_atime = ei->i_atime;
|
||||
di->di_mtime = ei->i_mtime;
|
||||
di->di_ctime = ei->i_ctime;
|
||||
di->di_flags = 0;
|
||||
di->di_flags |= (ei->i_flags & EXT2_APPEND_FL) ? APPEND : 0;
|
||||
di->di_flags |= (ei->i_flags & EXT2_IMMUTABLE_FL) ? IMMUTABLE : 0;
|
||||
@ -143,11 +143,11 @@ ext2_di2ei(di, ei)
|
||||
Godmar thinks: if dtime is nonzero, ext2 says this inode
|
||||
has been deleted, this would correspond to a zero link count
|
||||
*/
|
||||
ei->i_dtime = ei->i_links_count ? 0 : di->di_mtime.tv_sec;
|
||||
ei->i_dtime = ei->i_links_count ? 0 : di->di_mtime;
|
||||
ei->i_size = di->di_size;
|
||||
ei->i_atime = di->di_atime.tv_sec;
|
||||
ei->i_mtime = di->di_mtime.tv_sec;
|
||||
ei->i_ctime = di->di_ctime.tv_sec;
|
||||
ei->i_atime = di->di_atime;
|
||||
ei->i_mtime = di->di_mtime;
|
||||
ei->i_ctime = di->di_ctime;
|
||||
ei->i_flags = di->di_flags;
|
||||
ei->i_flags = 0;
|
||||
ei->i_flags |= (di->di_flags & APPEND) ? EXT2_APPEND_FL: 0;
|
||||
|
@ -274,6 +274,7 @@ ext2_lookup(ap)
|
||||
struct ucred *cred = cnp->cn_cred;
|
||||
int flags = cnp->cn_flags;
|
||||
int nameiop = cnp->cn_nameiop;
|
||||
struct proc *p = cnp->cn_proc;
|
||||
|
||||
int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->s_blocksize;
|
||||
|
||||
@ -318,14 +319,14 @@ ext2_lookup(ap)
|
||||
VREF(vdp);
|
||||
error = 0;
|
||||
} else if (flags & ISDOTDOT) {
|
||||
VOP_UNLOCK(pdp);
|
||||
error = vget(vdp, 1);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
error = vget(vdp, LK_EXCLUSIVE, p);
|
||||
if (!error && lockparent && (flags & ISLASTCN))
|
||||
error = VOP_LOCK(pdp);
|
||||
error = vn_lock(pdp, LK_EXCLUSIVE, p);
|
||||
} else {
|
||||
error = vget(vdp, 1);
|
||||
error = vget(vdp, LK_EXCLUSIVE, p);
|
||||
if (!lockparent || error || !(flags & ISLASTCN))
|
||||
VOP_UNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
}
|
||||
/*
|
||||
* Check that the capability number did not change
|
||||
@ -336,9 +337,9 @@ ext2_lookup(ap)
|
||||
return (0);
|
||||
vput(vdp);
|
||||
if (lockparent && pdp != vdp && (flags & ISLASTCN))
|
||||
VOP_UNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
}
|
||||
if (error = VOP_LOCK(pdp))
|
||||
if (error = vn_lock(pdp, LK_EXCLUSIVE, p))
|
||||
return (error);
|
||||
vdp = pdp;
|
||||
dp = VTOI(pdp);
|
||||
@ -548,7 +549,7 @@ ext2_lookup(ap)
|
||||
*/
|
||||
cnp->cn_flags |= SAVENAME;
|
||||
if (!lockparent)
|
||||
VOP_UNLOCK(vdp);
|
||||
VOP_UNLOCK(vdp, 0, p);
|
||||
return (EJUSTRETURN);
|
||||
}
|
||||
/*
|
||||
@ -625,7 +626,7 @@ ext2_lookup(ap)
|
||||
}
|
||||
*vpp = tdp;
|
||||
if (!lockparent)
|
||||
VOP_UNLOCK(vdp);
|
||||
VOP_UNLOCK(vdp, 0, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -650,7 +651,7 @@ ext2_lookup(ap)
|
||||
*vpp = tdp;
|
||||
cnp->cn_flags |= SAVENAME;
|
||||
if (!lockparent)
|
||||
VOP_UNLOCK(vdp);
|
||||
VOP_UNLOCK(vdp, 0, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -675,13 +676,13 @@ ext2_lookup(ap)
|
||||
*/
|
||||
pdp = vdp;
|
||||
if (flags & ISDOTDOT) {
|
||||
VOP_UNLOCK(pdp); /* race to get the inode */
|
||||
VOP_UNLOCK(pdp, 0, p); /* race to get the inode */
|
||||
if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) {
|
||||
VOP_LOCK(pdp);
|
||||
vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
return (error);
|
||||
}
|
||||
if (lockparent && (flags & ISLASTCN) &&
|
||||
(error = VOP_LOCK(pdp))) {
|
||||
(error = vn_lock(pdp, LK_EXCLUSIVE, p))) {
|
||||
vput(tdp);
|
||||
return (error);
|
||||
}
|
||||
@ -693,7 +694,7 @@ ext2_lookup(ap)
|
||||
if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp))
|
||||
return (error);
|
||||
if (!lockparent || !(flags & ISLASTCN))
|
||||
VOP_UNLOCK(pdp);
|
||||
VOP_UNLOCK(pdp, 0, p);
|
||||
*vpp = tdp;
|
||||
}
|
||||
|
||||
|
@ -30,13 +30,34 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufsmount.h 8.2 (Berkeley) 1/12/94
|
||||
* @(#)ufsmount.h 8.6 (Berkeley) 3/30/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_UFSMOUNT_H_
|
||||
#define _UFS_UFS_UFSMOUNT_H_
|
||||
|
||||
/*
|
||||
* Arguments to mount UFS-based filesystems
|
||||
*/
|
||||
struct ufs_args {
|
||||
char *fspec; /* block special device to mount */
|
||||
struct export_args export; /* network export information */
|
||||
};
|
||||
|
||||
#ifdef MFS
|
||||
/*
|
||||
* Arguments to mount MFS
|
||||
*/
|
||||
struct mfs_args {
|
||||
char *fspec; /* name to export for statfs */
|
||||
struct export_args export; /* if exported MFSes are supported */
|
||||
caddr_t base; /* base of file system in memory */
|
||||
u_long size; /* size of file system */
|
||||
};
|
||||
#endif /* MFS */
|
||||
|
||||
#ifdef KERNEL
|
||||
struct buf;
|
||||
struct inode;
|
||||
struct nameidata;
|
||||
@ -51,6 +72,7 @@ struct ufsmount {
|
||||
struct mount *um_mountp; /* filesystem vfs structure */
|
||||
dev_t um_dev; /* device mounted */
|
||||
struct vnode *um_devvp; /* block device mounted vnode */
|
||||
|
||||
union { /* pointer to superblock */
|
||||
struct lfs *lfs; /* LFS */
|
||||
struct fs *fs; /* FFS */
|
||||
@ -60,6 +82,7 @@ struct ufsmount {
|
||||
#define um_lfs ufsmount_u.lfs
|
||||
#define um_e2fs ufsmount_u.e2fs
|
||||
#define um_e2fsb ufsmount_u.e2fs->s_es
|
||||
|
||||
struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */
|
||||
struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */
|
||||
u_long um_nindir; /* indirect ptrs per block */
|
||||
@ -69,7 +92,9 @@ struct ufsmount {
|
||||
time_t um_itime[MAXQUOTAS]; /* inode quota time limit */
|
||||
char um_qflags[MAXQUOTAS]; /* quota specific flags */
|
||||
struct netexport um_export; /* export information */
|
||||
int64_t um_savedmaxfilesize; /* XXX - limit maxfilesize */
|
||||
};
|
||||
|
||||
/*
|
||||
* Flags describing the state of quotas.
|
||||
*/
|
||||
@ -83,8 +108,9 @@ struct ufsmount {
|
||||
* Macros to access file system parameters in the ufsmount structure.
|
||||
* Used by ufs_bmap.
|
||||
*/
|
||||
#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
|
||||
#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
|
||||
#define MNINDIR(ump) ((ump)->um_nindir)
|
||||
#define MNINDIR(ump) ((ump)->um_nindir)
|
||||
#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
|
||||
#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif
|
||||
|
@ -221,10 +221,10 @@ ext2_mount(mp, path, data, ndp, p)
|
||||
flags = WRITECLOSE;
|
||||
if (mp->mnt_flag & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
if (vfs_busy(mp))
|
||||
if (vfs_busy(mp, LK_NOWAIT, 0, p))
|
||||
return (EBUSY);
|
||||
error = ext2_flushfiles(mp, flags, p);
|
||||
vfs_unbusy(mp);
|
||||
vfs_unbusy(mp, p);
|
||||
}
|
||||
if (!error && (mp->mnt_flag & MNT_RELOAD))
|
||||
error = ext2_reload(mp, ndp->ni_cnd.cn_cred, p);
|
||||
@ -515,7 +515,7 @@ ext2_reload(mountp, cred, p)
|
||||
/*
|
||||
* Step 5: invalidate all cached file data.
|
||||
*/
|
||||
if (vget(vp, 1))
|
||||
if (vget(vp, LK_EXCLUSIVE, p))
|
||||
goto loop;
|
||||
if (vinvalbuf(vp, 0, cred, p, 0, 0))
|
||||
panic("ext2_reload: dirty2");
|
||||
@ -727,17 +727,12 @@ ext2_flushfiles(mp, flags, p)
|
||||
int flags;
|
||||
struct proc *p;
|
||||
{
|
||||
#if !defined(__FreeBSD__)
|
||||
extern int doforce;
|
||||
#endif
|
||||
register struct ufsmount *ump;
|
||||
int error;
|
||||
#if QUOTA
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if (!doforce)
|
||||
flags &= ~FORCECLOSE;
|
||||
ump = VFSTOUFS(mp);
|
||||
#if QUOTA
|
||||
if (mp->mnt_flag & MNT_QUOTA) {
|
||||
@ -872,7 +867,7 @@ ext2_sync(mp, waitfor, cred, p)
|
||||
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
|
||||
vp->v_dirtyblkhd.lh_first == NULL)
|
||||
continue;
|
||||
if (vget(vp, 1))
|
||||
if (vget(vp, LK_EXCLUSIVE, p))
|
||||
goto loop;
|
||||
if (error = VOP_FSYNC(vp, cred, waitfor, p))
|
||||
allerror = error;
|
||||
|
@ -152,6 +152,6 @@ extern u_char *fragtbl[];
|
||||
* I think I'll try a VOP_LOCK/VOP_UNLOCK on the device vnode
|
||||
*/
|
||||
#define DEVVP(inode) (VFSTOUFS(ITOV(inode)->v_mount)->um_devvp)
|
||||
#define lock_super(devvp) VOP_LOCK(devvp)
|
||||
#define unlock_super(devvp) VOP_UNLOCK(devvp)
|
||||
#define lock_super(devvp) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, curproc)
|
||||
#define unlock_super(devvp) VOP_UNLOCK(devvp, 0, curproc)
|
||||
|
||||
|
@ -35,42 +35,33 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)inode.h 8.4 (Berkeley) 1/21/94
|
||||
* @(#)inode.h 8.9 (Berkeley) 5/14/95
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_INODE_H_
|
||||
#define _UFS_UFS_INODE_H_
|
||||
|
||||
#include <ufs/ufs/dir.h>
|
||||
#include <ufs/ufs/dinode.h>
|
||||
|
||||
/*
|
||||
* Theoretically, directories can be more than 2Gb in length, however, in
|
||||
* practice this seems unlikely. So, we define the type doff_t as a long
|
||||
* to keep down the cost of doing lookup on a 32-bit machine. If you are
|
||||
* porting to a 64-bit architecture, you should make doff_t the same as off_t.
|
||||
*/
|
||||
#define doff_t long
|
||||
|
||||
/*
|
||||
* The inode is used to describe each active (or recently active)
|
||||
* file in the UFS filesystem. It is composed of two types of
|
||||
* information. The first part is the information that is needed
|
||||
* only while the file is active (such as the identity of the file
|
||||
* and linkage to speed its lookup). The second part is the
|
||||
* permanent meta-data associated with the file which is read
|
||||
* in from the permanent dinode from long term storage when the
|
||||
* file becomes active, and is put back when the file is no longer
|
||||
* being used.
|
||||
* The inode is used to describe each active (or recently active) file in the
|
||||
* UFS filesystem. It is composed of two types of information. The first part
|
||||
* is the information that is needed only while the file is active (such as
|
||||
* the identity of the file and linkage to speed its lookup). The second part
|
||||
* is the permanent meta-data associated with the file which is read in
|
||||
* from the permanent dinode from long term storage when the file becomes
|
||||
* active, and is put back when the file is no longer being used.
|
||||
*/
|
||||
struct inode {
|
||||
struct inode *i_next; /* Hash chain forward. */
|
||||
struct inode **i_prev; /* Hash chain back. */
|
||||
struct vnode *i_vnode; /* Vnode associated with this inode. */
|
||||
struct vnode *i_devvp; /* Vnode for block I/O. */
|
||||
u_long i_flag; /* I* flags. */
|
||||
dev_t i_dev; /* Device associated with the inode. */
|
||||
ino_t i_number; /* The identity of the inode. */
|
||||
LIST_ENTRY(inode) i_hash;/* Hash chain. */
|
||||
struct vnode *i_vnode;/* Vnode associated with this inode. */
|
||||
struct vnode *i_devvp;/* Vnode for block I/O. */
|
||||
u_int32_t i_flag; /* flags, see below */
|
||||
dev_t i_dev; /* Device associated with the inode. */
|
||||
ino_t i_number; /* The identity of the inode. */
|
||||
|
||||
union { /* Associated filesystem. */
|
||||
struct fs *fs; /* FFS */
|
||||
struct lfs *lfs; /* LFS */
|
||||
@ -79,22 +70,21 @@ struct inode {
|
||||
#define i_fs inode_u.fs
|
||||
#define i_lfs inode_u.lfs
|
||||
#define i_e2fs inode_u.e2fs
|
||||
struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
|
||||
u_quad_t i_modrev; /* Revision level for lease. */
|
||||
struct lockf *i_lockf; /* Head of byte-level lock list. */
|
||||
pid_t i_lockholder; /* DEBUG: holder of inode lock. */
|
||||
pid_t i_lockwaiter; /* DEBUG: latest blocked for inode lock. */
|
||||
struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
|
||||
u_quad_t i_modrev; /* Revision level for NFS lease. */
|
||||
struct lockf *i_lockf;/* Head of byte-level lock list. */
|
||||
struct lock i_lock; /* Inode lock. */
|
||||
/*
|
||||
* Side effects; used during directory lookup.
|
||||
*/
|
||||
long i_count; /* Size of free slot in directory. */
|
||||
doff_t i_endoff; /* End of useful stuff in directory. */
|
||||
doff_t i_diroff; /* Offset in dir, where we found last entry. */
|
||||
doff_t i_offset; /* Offset of free space in directory. */
|
||||
ino_t i_ino; /* Inode number of found directory. */
|
||||
u_long i_reclen; /* Size of found directory entry. */
|
||||
int i_lockcount; /* Process lock count (recursion) */
|
||||
long i_spare[10]; /* Spares to round up to 128 bytes. */
|
||||
int32_t i_count; /* Size of free slot in directory. */
|
||||
doff_t i_endoff; /* End of useful stuff in directory. */
|
||||
doff_t i_diroff; /* Offset in dir, where we found last entry. */
|
||||
doff_t i_offset; /* Offset of free space in directory. */
|
||||
ino_t i_ino; /* Inode number of found directory. */
|
||||
u_int32_t i_reclen; /* Size of found directory entry. */
|
||||
int i_lockcount; /* Process lock count (recursion) */
|
||||
int i_spare[10]; /* XXX spare storage (for ext2fs) */
|
||||
/*
|
||||
* The on-disk dinode itself.
|
||||
*/
|
||||
@ -102,8 +92,10 @@ struct inode {
|
||||
};
|
||||
|
||||
#define i_atime i_din.di_atime
|
||||
#define i_atimensec i_din.di_atimensec
|
||||
#define i_blocks i_din.di_blocks
|
||||
#define i_ctime i_din.di_ctime
|
||||
#define i_ctimensec i_din.di_ctimensec
|
||||
#define i_db i_din.di_db
|
||||
#define i_flags i_din.di_flags
|
||||
#define i_gen i_din.di_gen
|
||||
@ -111,6 +103,7 @@ struct inode {
|
||||
#define i_ib i_din.di_ib
|
||||
#define i_mode i_din.di_mode
|
||||
#define i_mtime i_din.di_mtime
|
||||
#define i_mtimensec i_din.di_mtimensec
|
||||
#define i_nlink i_din.di_nlink
|
||||
#define i_rdev i_din.di_rdev
|
||||
#define i_shortlink i_din.di_shortlink
|
||||
@ -120,15 +113,12 @@ struct inode {
|
||||
/* These flags are kept in i_flag. */
|
||||
#define IN_ACCESS 0x0001 /* Access time update request. */
|
||||
#define IN_CHANGE 0x0002 /* Inode change time update request. */
|
||||
#define IN_EXLOCK 0x0004 /* File has exclusive lock. */
|
||||
#define IN_LOCKED 0x0008 /* Inode lock. */
|
||||
#define IN_LWAIT 0x0010 /* Process waiting on file lock. */
|
||||
#define IN_MODIFIED 0x0020 /* Inode has been modified. */
|
||||
#define IN_RENAME 0x0040 /* Inode is being renamed. */
|
||||
#define IN_SHLOCK 0x0080 /* File has shared lock. */
|
||||
#define IN_UPDATE 0x0100 /* Modification time update request. */
|
||||
#define IN_WANTED 0x0200 /* Inode is wanted by a process. */
|
||||
#define IN_RECURSE 0x0400 /* Recursion expected */
|
||||
#define IN_UPDATE 0x0004 /* Modification time update request. */
|
||||
#define IN_MODIFIED 0x0008 /* Inode has been modified. */
|
||||
#define IN_RENAME 0x0010 /* Inode is being renamed. */
|
||||
#define IN_SHLOCK 0x0020 /* File has shared lock. */
|
||||
#define IN_EXLOCK 0x0040 /* File has exclusive lock. */
|
||||
#define IN_RECURSE 0x0080 /* Recursion expected */
|
||||
|
||||
#ifdef KERNEL
|
||||
/*
|
||||
@ -136,7 +126,7 @@ struct inode {
|
||||
* ufs_getlbns and used by truncate and bmap code.
|
||||
*/
|
||||
struct indir {
|
||||
daddr_t in_lbn; /* Logical block number. */
|
||||
ufs_daddr_t in_lbn; /* Logical block number. */
|
||||
int in_off; /* Offset in buffer. */
|
||||
int in_exists; /* Flag if the block exists. */
|
||||
};
|
||||
@ -155,25 +145,25 @@ struct indir {
|
||||
if ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) { \
|
||||
(ip)->i_flag |= IN_MODIFIED; \
|
||||
if ((ip)->i_flag & IN_ACCESS) \
|
||||
(ip)->i_atime.tv_sec \
|
||||
(ip)->i_atime \
|
||||
= ((t1) == &time ? tv_sec : (t1)->tv_sec); \
|
||||
if ((ip)->i_flag & IN_UPDATE) { \
|
||||
(ip)->i_mtime.tv_sec \
|
||||
(ip)->i_mtime \
|
||||
= ((t2) == &time ? tv_sec : (t2)->tv_sec); \
|
||||
(ip)->i_modrev++; \
|
||||
} \
|
||||
if ((ip)->i_flag & IN_CHANGE) \
|
||||
(ip)->i_ctime.tv_sec = tv_sec; \
|
||||
(ip)->i_ctime = tv_sec; \
|
||||
(ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* This overlays the fid structure (see mount.h). */
|
||||
struct ufid {
|
||||
u_short ufid_len; /* Length of structure. */
|
||||
u_short ufid_pad; /* Force long alignment. */
|
||||
ino_t ufid_ino; /* File number (ino). */
|
||||
long ufid_gen; /* Generation number. */
|
||||
u_int16_t ufid_len; /* Length of structure. */
|
||||
u_int16_t ufid_pad; /* Force 32-bit alignment. */
|
||||
ino_t ufid_ino; /* File number (ino). */
|
||||
int32_t ufid_gen; /* Generation number. */
|
||||
};
|
||||
#endif /* KERNEL */
|
||||
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <machine/bootinfo.h>
|
||||
@ -88,31 +89,15 @@
|
||||
static void configure __P((void *));
|
||||
SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
|
||||
|
||||
#ifdef MFS_ROOT
|
||||
extern struct vfsops mfs_vfsops;
|
||||
#endif
|
||||
#ifdef FFS
|
||||
extern struct vfsops ufs_vfsops;
|
||||
#endif
|
||||
#ifdef LFS
|
||||
extern struct vfsops lfs_vfsops;
|
||||
#endif
|
||||
#ifdef NFS
|
||||
extern int nfs_mountroot __P((void *));
|
||||
#endif
|
||||
#ifdef CD9660
|
||||
extern int cd9660_mountroot __P((void *));
|
||||
#endif
|
||||
#ifdef MSDOSFS
|
||||
extern int msdosfs_mountroot __P((void *));
|
||||
#endif
|
||||
|
||||
static void configure_finish __P((void));
|
||||
static void configure_start __P((void));
|
||||
static int setdumpdev __P((dev_t dev));
|
||||
static void setroot __P((void));
|
||||
|
||||
#ifdef CD9660
|
||||
|
||||
#include <isofs/cd9660/iso.h>
|
||||
|
||||
/* We need to try out all our potential CDROM drives, so we need a table. */
|
||||
static struct {
|
||||
char *name;
|
||||
@ -138,7 +123,7 @@ find_cdrom_root(dummy)
|
||||
rootdev = makedev(try_cdrom[k].major,j*8);
|
||||
printf("trying rootdev=0x%lx (%s%d)\n",
|
||||
rootdev, try_cdrom[k].name,j);
|
||||
i = (*cd9660_mountroot)((void *)NULL);
|
||||
i = (*cd9660_mountroot)();
|
||||
if (!i) return i;
|
||||
}
|
||||
return EINVAL;
|
||||
@ -176,6 +161,11 @@ configure(dummy)
|
||||
enable_intr();
|
||||
INTREN(IRQ_SLAVE);
|
||||
|
||||
#if NCRD > 0
|
||||
/* Before isa_configure to avoid ISA drivers finding our cards */
|
||||
pccard_configure();
|
||||
#endif
|
||||
|
||||
#if NEISA > 0
|
||||
eisa_configure();
|
||||
#endif
|
||||
@ -188,11 +178,6 @@ configure(dummy)
|
||||
isa_configure();
|
||||
#endif
|
||||
|
||||
#if NCRD > 0
|
||||
/* After everyone else has a chance at grabbing resources */
|
||||
pccard_configure();
|
||||
#endif
|
||||
|
||||
if (setdumpdev(dumpdev) != 0)
|
||||
dumpdev = NODEV;
|
||||
|
||||
@ -235,19 +220,26 @@ configure(dummy)
|
||||
}
|
||||
|
||||
#ifdef CD9660
|
||||
if ((boothowto & RB_CDROM) && !mountroot) {
|
||||
if ((boothowto & RB_CDROM)) {
|
||||
if (bootverbose)
|
||||
printf("Considering CD-ROM root f/s.\n");
|
||||
mountroot = find_cdrom_root;
|
||||
mountrootfsname = "cd9660";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NFS
|
||||
if (!mountrootfsname && nfs_diskless_valid) {
|
||||
if (bootverbose)
|
||||
printf("Considering NFS root f/s.\n");
|
||||
mountrootfsname = "nfs";
|
||||
}
|
||||
#endif /* NFS */
|
||||
|
||||
#ifdef MFS_ROOT
|
||||
if (!mountroot) {
|
||||
if (!mountrootfsname) {
|
||||
if (bootverbose)
|
||||
printf("Considering MFS root f/s.\n");
|
||||
mountroot = vfs_mountroot; /* XXX goes away*/
|
||||
mountrootvfsops = &mfs_vfsops;
|
||||
mountrootfsname = "mfs";
|
||||
/*
|
||||
* Ignore the -a flag if this kernel isn't compiled
|
||||
* with a generic root/swap configuration: if we skip
|
||||
@ -260,21 +252,11 @@ configure(dummy)
|
||||
setroot();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NFS
|
||||
if (!mountroot && nfs_diskless_valid) {
|
||||
if (bootverbose)
|
||||
printf("Considering NFS root f/s.\n");
|
||||
mountroot = nfs_mountroot;
|
||||
}
|
||||
#endif /* NFS */
|
||||
|
||||
#ifdef FFS
|
||||
if (!mountroot) {
|
||||
if (!mountrootfsname) {
|
||||
mountrootfsname = "ufs";
|
||||
if (bootverbose)
|
||||
printf("Considering FFS root f/s.\n");
|
||||
mountroot = vfs_mountroot; /* XXX goes away*/
|
||||
mountrootvfsops = &ufs_vfsops;
|
||||
/*
|
||||
* Ignore the -a flag if this kernel isn't compiled
|
||||
* with a generic root/swap configuration: if we skip
|
||||
@ -288,11 +270,10 @@ configure(dummy)
|
||||
}
|
||||
#endif
|
||||
#ifdef LFS
|
||||
if (!mountroot) {
|
||||
if (!mountrootfsname) {
|
||||
if (bootverbose)
|
||||
printf("Considering LFS root f/s.\n");
|
||||
mountroot = vfs_mountroot; /* XXX goes away*/
|
||||
mountrootvfsops = &lfs_vfsops;
|
||||
mountrootfsname = "lfs";
|
||||
/*
|
||||
* Ignore the -a flag if this kernel isn't compiled
|
||||
* with a generic root/swap configuration: if we skip
|
||||
@ -305,8 +286,7 @@ configure(dummy)
|
||||
setroot();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!mountroot) {
|
||||
if (!mountrootfsname) {
|
||||
panic("Nobody wants to mount my root for me");
|
||||
}
|
||||
|
||||
@ -417,4 +397,4 @@ sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
|
||||
0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
|
||||
0, sizeof dumpdev, sysctl_kern_dumpdev, "I", "");
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <ddb/ddb.h>
|
||||
|
@ -61,13 +61,15 @@
|
||||
#include <sys/vmmeter.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <sys/user.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <nfs/nfsv2.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsdiskless.h>
|
||||
|
||||
extern int main __P((void));
|
||||
|
@ -82,7 +82,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
|
@ -56,7 +56,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <sys/user.h>
|
||||
|
@ -68,7 +68,7 @@
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
@ -85,7 +85,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
|
@ -80,7 +80,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
@ -61,7 +61,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_map.h>
|
||||
|
@ -58,7 +58,7 @@
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/lock.h>
|
||||
#include <sys/lock.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
|
@ -354,7 +354,7 @@ ibcs2_getdents(p, uap, retval)
|
||||
buflen = max(DIRBLKSIZ, SCARG(uap, nbytes) + blockoff);
|
||||
buflen = min(buflen, MAXBSIZE);
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
again:
|
||||
aiov.iov_base = buf;
|
||||
aiov.iov_len = buflen;
|
||||
@ -420,7 +420,7 @@ ibcs2_getdents(p, uap, retval)
|
||||
eof:
|
||||
*retval = SCARG(uap, nbytes) - resid;
|
||||
out:
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, p);
|
||||
free(buf, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
@ -465,7 +465,7 @@ ibcs2_read(p, uap, retval)
|
||||
buflen = max(DIRBLKSIZ, SCARG(uap, nbytes) + blockoff);
|
||||
buflen = min(buflen, MAXBSIZE);
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
again:
|
||||
aiov.iov_base = buf;
|
||||
aiov.iov_len = buflen;
|
||||
@ -535,7 +535,7 @@ ibcs2_read(p, uap, retval)
|
||||
eof:
|
||||
*retval = SCARG(uap, nbytes) - resid;
|
||||
out:
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, p);
|
||||
free(buf, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ coff_load_file(struct proc *p, char *name)
|
||||
* Lose the lock on the vnode. It's no longer needed, and must not
|
||||
* exist for the pagefault paging to work below.
|
||||
*/
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, p);
|
||||
|
||||
if (error = vm_mmap(kernel_map,
|
||||
(vm_offset_t *) &ptr,
|
||||
|
@ -45,6 +45,7 @@
|
||||
*/
|
||||
|
||||
#define MACHINE "i386"
|
||||
#define NCPUS 1
|
||||
#define MID_MACHINE MID_I386
|
||||
|
||||
/*
|
||||
@ -125,4 +126,63 @@
|
||||
#define i386_btop(x) ((unsigned)(x) >> PAGE_SHIFT)
|
||||
#define i386_ptob(x) ((unsigned)(x) << PAGE_SHIFT)
|
||||
|
||||
#ifndef _SIMPLELOCK_H_
|
||||
#define _SIMPLELOCK_H_
|
||||
/*
|
||||
* A simple spin lock.
|
||||
*
|
||||
* This structure only sets one bit of data, but is sized based on the
|
||||
* minimum word size that can be operated on by the hardware test-and-set
|
||||
* instruction. It is only needed for multiprocessors, as uniprocessors
|
||||
* will always run to completion or a sleep. It is an error to hold one
|
||||
* of these locks while a process is sleeping.
|
||||
*/
|
||||
struct simplelock {
|
||||
int lock_data;
|
||||
};
|
||||
|
||||
#if !defined(SIMPLELOCK_DEBUG) && NCPUS > 1
|
||||
/*
|
||||
* The simple-lock routines are the primitives out of which the lock
|
||||
* package is built. The machine-dependent code must implement an
|
||||
* atomic test_and_set operation that indivisibly sets the simple lock
|
||||
* to non-zero and returns its old value. It also assumes that the
|
||||
* setting of the lock to zero below is indivisible. Simple locks may
|
||||
* only be used for exclusive locks.
|
||||
*/
|
||||
static __inline void
|
||||
simple_lock_init(lkp)
|
||||
struct simplelock *lkp;
|
||||
{
|
||||
|
||||
lkp->lock_data = 0;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
simple_lock(lkp)
|
||||
__volatile struct simplelock *lkp;
|
||||
{
|
||||
|
||||
while (test_and_set(&lkp->lock_data))
|
||||
continue;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
simple_lock_try(lkp)
|
||||
__volatile struct simplelock *lkp;
|
||||
{
|
||||
|
||||
return (!test_and_set(&lkp->lock_data))
|
||||
}
|
||||
|
||||
static __inline void
|
||||
simple_unlock(lkp)
|
||||
__volatile struct simplelock *lkp;
|
||||
{
|
||||
|
||||
lkp->lock_data = 0;
|
||||
}
|
||||
#endif /* NCPUS > 1 */
|
||||
#endif /* !_SIMPLELOCK_H_ */
|
||||
|
||||
#endif /* !_MACHINE_PARAM_H_ */
|
||||
|
@ -67,4 +67,6 @@ typedef unsigned long long u_int64_t;
|
||||
|
||||
typedef int32_t register_t;
|
||||
|
||||
typedef int32_t ufs_daddr_t;
|
||||
|
||||
#endif /* !_MACHINE_TYPES_H_ */
|
||||
|
@ -277,7 +277,7 @@ static d_strategy_t fdstrategy;
|
||||
static struct cdevsw fd_cdevsw;
|
||||
static struct bdevsw fd_bdevsw =
|
||||
{ Fdopen, fdclose, fdstrategy, fdioctl, /*2*/
|
||||
nodump, nopsize, 0, "fd", &fd_cdevsw, -1 };
|
||||
nodump, nopsize, D_DISK, "fd", &fd_cdevsw, -1 };
|
||||
|
||||
|
||||
static struct isa_device *fdcdevs[NFDC];
|
||||
|
@ -236,7 +236,7 @@ static d_psize_t wdsize;
|
||||
static struct cdevsw wd_cdevsw;
|
||||
static struct bdevsw wd_bdevsw =
|
||||
{ wdopen, wdclose, wdstrategy, wdioctl, /*0*/
|
||||
wddump, wdsize, 0, "wd", &wd_cdevsw, -1 };
|
||||
wddump, wdsize, D_DISK, "wd", &wd_cdevsw, -1 };
|
||||
|
||||
/*
|
||||
* Probe for controller.
|
||||
|
@ -450,7 +450,7 @@ linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval)
|
||||
buflen = max(DIRBLKSIZ, nbytes + blockoff);
|
||||
buflen = min(buflen, MAXBSIZE);
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||
again:
|
||||
aiov.iov_base = buf;
|
||||
aiov.iov_len = buflen;
|
||||
@ -530,7 +530,7 @@ linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval)
|
||||
eof:
|
||||
*retval = nbytes - resid;
|
||||
out:
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, p);
|
||||
free(buf, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
|
||||
/*
|
||||
* Lock no longer needed
|
||||
*/
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, p);
|
||||
locked = 0;
|
||||
|
||||
/*
|
||||
@ -392,7 +392,7 @@ printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]);
|
||||
* Unlock vnode if needed
|
||||
*/
|
||||
if (locked)
|
||||
VOP_UNLOCK(vp);
|
||||
VOP_UNLOCK(vp, p);
|
||||
|
||||
/*
|
||||
* Release the kernel mapping.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user