Initial commit of Andrew McMurry's Acorn Filecore filesystem.

This is a read only implementation of the filecore filesystem found
on Acorn RiscPC machines (arm32).
This commit is contained in:
mark 1998-08-14 03:26:12 +00:00
parent 4283228f33
commit faf4eed3e3
11 changed files with 2770 additions and 0 deletions

8
sys/filecorefs/Makefile Normal file
View File

@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.1 1998/08/14 03:26:12 mark Exp $
KDIR= /sys/filecorefs
INCSDIR=/usr/include/filecorefs
INCS= filecore_mount.h
.include <bsd.kinc.mk>

119
sys/filecorefs/filecore.h Normal file
View File

@ -0,0 +1,119 @@
/* $NetBSD: filecore.h,v 1.1 1998/08/14 03:26:12 mark Exp $ */
/*-
* Copyright (c) 1998 Andrew McMurry
* Copyright (c) 1994 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* filecore.h 1.0 1998/6/1
*/
/*
* Definitions describing Acorn Filecore file system structure, as well as
* the functions necessary to access fields of filecore file system
* structures.
*/
#define FILECORE_BOOTBLOCK_BLKN 6
#define FILECORE_BOOTBLOCK_SIZE 0x200
#define FILECORE_BB_DISCREC 0x1C0
#define FILECORE_DISCREC_SIZE 60
#define FILECORE_DIR_SIZE 2048
#define FILECORE_DIRENT_SIZE 26
#define FILECORE_MAXDIRENTS 77
#define FILECORE_ROOTINO 0xFFFFFFFF
#define FILECORE_INO_MASK 0x00FFFFFF
#define FILECORE_INO_INDEX 24
#define FILECORE_ATTR_READ 1
#define FILECORE_ATTR_WRITE 2
#define FILECORE_ATTR_DIR 8
#define FILECORE_ATTR_OREAD 32
#define FILECORE_ATTR_OWRITE 64
#if 0
#define FILECORE_DEBUG
#define FILECORE_DEBUG_BR
#endif
struct filecore_disc_record {
unsigned log2secsize:8; /* base 2 log of the sector size */
unsigned secspertrack:8; /* number of sectors per track */
unsigned heads:8; /* number of heads */
unsigned density:8; /* 0: harddisc, else floppy density */
unsigned idlen:8; /* length of fragment id in bits */
unsigned log2bpmb:8; /* base 2 log of the bytes per FAU */
unsigned skew:8; /* track to sector skew */
unsigned bootoption:8; /* *OPT option */
unsigned lowsector:8; /* lowest sector id on a track */
unsigned nzones:8; /* number of zones in the map */
unsigned zone_spare:16; /* number of non-map bits per zone */
unsigned root; /* address of root directory */
unsigned disc_size; /* disc size in bytes (low word) */
unsigned disc_id:16; /* disc cycle id */
char disc_name[10]; /* disc name */
unsigned disc_type; /* disc type */
unsigned disc_size_2; /* disc size in bytes (high word) */
unsigned share_size:8; /* base 2 log sharing granularity */
unsigned big_flag:8; /* 1 if disc > 512Mb */
char reserved[18];
};
struct filecore_direntry {
char name[10];
unsigned load:32;
unsigned exec:32;
unsigned len:32;
unsigned addr:24;
unsigned attr:8;
};
struct filecore_dirhead {
unsigned mas_seq:8;
unsigned chkname:32;
};
struct filecore_dirtail {
unsigned lastmark:8;
unsigned reserved:16;
unsigned parent1:16;
unsigned parent2:8;
char title[19];
char name[10];
unsigned mas_seq:8;
unsigned chkname:32;
unsigned checkbyte:8;
};
#define fcdirhead(dp) ((struct filecore_dirhead *)(dp))
#define fcdirentry(dp,n) (((struct filecore_direntry *)(((char *)(dp))+5))+(n))
#define fcdirtail(dp) ((struct filecore_dirtail *)(((char *)(dp))+2007))

View File

@ -0,0 +1,233 @@
/* $NetBSD: filecore_bmap.c,v 1.1 1998/08/14 03:26:12 mark Exp $ */
/*-
* Copyright (c) 1998 Andrew McMurry
* Copyright (c) 1994 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* filecore_bmap.c 1.1 1998/6/26
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <filecorefs/filecore.h>
#include <filecorefs/filecore_extern.h>
#include <filecorefs/filecore_node.h>
/*
* Bmap converts a the logical block number of a file to its physical block
* number on the disk. The conversion is done by using the logical block
* number to index into the data block (extent) for the file.
*/
int
filecore_bmap(v)
void *v;
{
struct vop_bmap_args /* {
struct vnode *a_vp;
daddr_t a_bn;
struct vnode **a_vpp;
daddr_t *a_bnp;
int *a_runp;
} */ *ap = v;
struct filecore_node *ip = VTOI(ap->a_vp);
struct filecore_mnt *fcmp = ip->i_mnt;
daddr_t lbn = ap->a_bn;
/*
* Check for underlying vnode requests and ensure that logical
* to physical mapping is requested.
*/
if (ap->a_vpp != NULL)
*ap->a_vpp = ip->i_devvp;
if (ap->a_bnp == NULL)
return (0);
/*
* Determine maximum number of readahead blocks following the
* requested block.
*/
if (ap->a_runp) {
int nblk;
int bshift=fcmp->log2bsize;
nblk = (ip->i_size >> bshift) - (lbn + 1);
if (nblk <= 0)
*ap->a_runp = 0;
else if (nblk >= (MAXBSIZE >> bshift))
*ap->a_runp = (MAXBSIZE >> bshift) - 1;
else
*ap->a_runp = nblk;
}
/*
* Compute the requested block number
*/
return filecore_map(fcmp, ip->i_dirent.addr, lbn, ap->a_bnp);
}
int
filecore_map(fcmp, addr, lbn, bnp)
struct filecore_mnt *fcmp;
u_int32_t addr;
daddr_t lbn;
daddr_t *bnp;
{
struct buf *bp;
u_long frag,sect,zone,izone,a,b,m,n;
u_int64_t zaddr;
unsigned *ptr;
long c;
int error=0;
#ifdef FILECORE_DEBUG
printf("filecore_map(addr=%x, lbn=%x)\n",addr,lbn);
#endif
frag=addr>>8;
sect=(addr & 0xff) +
((lbn<<fcmp->log2bsize)>>fcmp->drec.log2secsize);
if (frag!=2)
zone=frag/fcmp->idspz; else zone=fcmp->drec.nzones/2;
izone=zone;
if (zone!=0)
zaddr=((8<<fcmp->drec.log2secsize)-fcmp->drec.zone_spare)*zone
- 8*FILECORE_DISCREC_SIZE;
else
zaddr=0;
if (sect>0) sect--;
do {
error=bread(fcmp->fc_devvp, fcmp->map + zone,
1<<fcmp->drec.log2secsize, NOCRED, &bp);
#ifdef FILECORE_DEBUG_BR
printf("bread(%p, %lx, %d, CRED, %p)=%d\n",fcmp->fc_devvp,
fcmp->map+zone, 1<<fcmp->drec.log2secsize, bp, error);
printf("block is at %p\n",bp->b_data);
#endif
if (error!=0) {
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) bm1\n",bp);
#endif
brelse(bp);
return error;
}
ptr=(unsigned *)(bp->b_data)+1; /* skip map zone header */
if (zone==0) ptr+=FILECORE_DISCREC_SIZE>>2;
b=0;
while (b < (8<<(fcmp->drec.log2secsize))-fcmp->drec.zone_spare) {
a=ptr[b>>5]>>(b&31);
c=32-(b&31)-fcmp->drec.idlen;
if (c<=0) {
m = ptr[(b>>5)+1];
a |= m << (fcmp->drec.idlen+c);
m >>= -c;
c+=32;
} else m = a >> fcmp->drec.idlen;
n=fcmp->drec.idlen+1;
while ((m&1)==0) {
m>>=1; n++;
if (--c==0) { c=32; m=ptr[(b+n-1)>>5]; }
}
a &= fcmp->mask;
if (a==frag) {
if (sect<<fcmp->drec.log2secsize<n<<fcmp->drec.log2bpmb) {
*bnp=(((zaddr+b)<<fcmp->drec.log2bpmb)>>fcmp->drec.log2secsize)+sect;
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) bm2\n",bp);
#endif
brelse(bp);
return 0;
} else sect -= (n<<fcmp->drec.log2bpmb) >> fcmp->drec.log2secsize;
}
b+=n;
}
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) bm3\n",bp);
#endif
brelse(bp);
if (++zone==fcmp->drec.nzones) {
zone=0; zaddr=0;
} else zaddr+=((8<<fcmp->drec.log2secsize)-fcmp->drec.zone_spare);
} while (zone!=izone);
return (E2BIG);
}
int
filecore_bread(fcmp, addr, size, cred, bp)
struct filecore_mnt *fcmp;
u_int32_t addr;
int size;
struct ucred *cred;
struct buf **bp;
{
int error=0;
daddr_t bn;
error = filecore_map(fcmp, addr, 0, &bn);
if (error) {
#ifdef FILECORE_DEBUG
printf("filecore_bread(error=%d)\n",error);
#endif
return error;
}
error = bread(fcmp->fc_devvp, bn, size, cred, bp);
#ifdef FILECORE_DEBUG_BR
printf("bread(%p, %x, %d, CRED, %p)=%d\n",fcmp->fc_devvp, bn, size,
*bp, error);
#endif
return error;
}
int
filecore_dbread(ip, bp)
struct filecore_node *ip;
struct buf **bp;
{
int error=0;
if (ip->i_block==-1) error = filecore_map(ip->i_mnt, ip->i_dirent.addr,
0, &(ip->i_block));
if (error) return error;
error = bread(ip->i_mnt->fc_devvp, ip->i_block, FILECORE_DIR_SIZE,
NOCRED, bp);
#ifdef FILECORE_DEBUG_BR
printf("bread(%p, %x, %d, CRED, %p)=%d\n",ip->i_mnt->fc_devvp,
ip->i_block, FILECORE_DIR_SIZE, *bp, error);
#endif
return error;
}

View File

@ -0,0 +1,94 @@
/* $NetBSD: filecore_extern.h,v 1.1 1998/08/14 03:26:12 mark Exp $ */
/*-
* Copyright (c) 1998 Andrew McMurry
* Copyright (c) 1994 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* filecore_extern.h 1.1 1998/6/26
*/
/*
* Definitions used in the kernel for Acorn Filecore file system support.
*/
#ifndef FILECOREMNT_ROOT
#define FILECOREMNT_ROOT 0
#endif
struct filecore_mnt {
struct mount *fc_mountp;
dev_t fc_dev;
struct vnode *fc_devvp;
u_int32_t blksize;
u_int32_t log2bsize;
u_int32_t map;
u_int32_t idspz;
u_int32_t mask;
u_int64_t nblks;
uid_t fc_uid; /* uid to set as owner of the files */
gid_t fc_gid; /* gid to set as owner of the files */
int fc_mntflags;
struct netexport fc_export;
struct filecore_disc_record drec;
};
#define VFSTOFILECORE(mp) ((struct filecore_mnt *)((mp)->mnt_data))
#define blkoff(fcp, loc) ((loc) & ((fcp)->blksize-1))
#define lblktosize(fcp, blk) ((blk) << (fcp)->log2bsize)
#define lblkno(fcp, loc) ((loc) >> (fcp)->log2bsize)
#define blksize(fcp, ip, lbn) ((fcp)->blksize)
int filecore_mount __P((struct mount *,
const char *, void *, struct nameidata *, struct proc *));
int filecore_start __P((struct mount *, int, struct proc *));
int filecore_unmount __P((struct mount *, int, struct proc *));
int filecore_root __P((struct mount *, struct vnode **));
int filecore_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *));
int filecore_statfs __P((struct mount *, struct statfs *, struct proc *));
int filecore_sync __P((struct mount *, int, struct ucred *, struct proc *));
int filecore_vget __P((struct mount *, ino_t, struct vnode **));
int filecore_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
struct vnode **, int *, struct ucred **));
int filecore_vptofh __P((struct vnode *, struct fid *));
void filecore_init __P((void));
int filecore_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
struct proc *));
extern int (**filecore_vnodeop_p) __P((void *));
int filecore_bbchecksum __P((void *));
int filecore_bread __P((struct filecore_mnt *, u_int32_t, int, struct ucred *,
struct buf **));
int filecore_map __P((struct filecore_mnt *, u_int32_t, daddr_t, daddr_t *));

View File

@ -0,0 +1,340 @@
/* $NetBSD: filecore_lookup.c,v 1.1 1998/08/14 03:26:12 mark Exp $ */
/*-
* Copyright (c) 1998 Andrew McMurry
* Copyright (c) 1989, 1993, 1994 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* filecore_lookup.c 1.1 1998/6/26
*/
#include <sys/param.h>
#include <sys/namei.h>
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/systm.h>
#include <filecorefs/filecore.h>
#include <filecorefs/filecore_extern.h>
#include <filecorefs/filecore_node.h>
struct nchstats filecore_nchstats;
/*
* Convert a component of a pathname into a pointer to a locked inode.
* This is a very central and rather complicated routine.
* If the file system is not maintained in a strict tree hierarchy,
* this can result in a deadlock situation (see comments in code below).
*
* The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
* whether the name is to be looked up, created, renamed, or deleted.
* When CREATE, RENAME, or DELETE is specified, information usable in
* creating, renaming, or deleting a directory entry may be calculated.
* If flag has LOCKPARENT or'ed into it and the target of the pathname
* exists, lookup returns both the target and its parent directory locked.
* When creating or renaming and LOCKPARENT is specified, the target may
* not be ".". When deleting and LOCKPARENT is specified, the target may
* be "."., but the caller must check to ensure it does an vrele and iput
* instead of two iputs.
*
* Overall outline of ufs_lookup:
*
* check accessibility of directory
* look for name in cache, if found, then if at end of path
* and deleting or creating, drop it, else return name
* search for name in directory, to found or notfound
* notfound:
* if creating, return locked directory, leaving info on available slots
* else return error
* found:
* if at end of path and deleting, return information to allow delete
* if at end of path and rewriting (RENAME and LOCKPARENT), lock target
* inode and return info to allow rewrite
* if not at end, add name to cache; if at end and neither creating
* nor deleting, add name to cache
*
* NOTE: (LOOKUP | LOCKPARENT) currently returns the parent inode unlocked.
*/
int
filecore_lookup(v)
void *v;
{
struct vop_lookup_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
} */ *ap = v;
register struct vnode *vdp; /* vnode for directory being searched */
register struct filecore_node *dp; /* inode for directory being searched */
register struct filecore_mnt *fcmp; /* file system that directory is in */
struct buf *bp; /* a buffer of directory entries */
register struct filecore_direntry *de;
int numdirpasses; /* strategy for directory search */
struct vnode *pdp; /* saved dp during symlink work */
struct vnode *tdp; /* returned by filecore_vget_internal */
int lockparent; /* 1 => lockparent flag is set */
int wantparent; /* 1 => wantparent or lockparent flag */
int error;
u_short namelen;
int res;
const char *name;
struct vnode **vpp = ap->a_vpp;
struct componentname *cnp = ap->a_cnp;
struct ucred *cred = cnp->cn_cred;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
int i, endsearch;
bp = NULL;
*vpp = NULL;
vdp = ap->a_dvp;
dp = VTOI(vdp);
fcmp = dp->i_mnt;
lockparent = flags & LOCKPARENT;
wantparent = flags & (LOCKPARENT|WANTPARENT);
/*
* Check accessiblity of directory.
*/
if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) != 0)
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.
*
* Before tediously performing a linear scan of the directory,
* check the name cache to see if the directory/name pair
* we are looking for is known already.
*/
if ((error = cache_lookup(vdp, vpp, cnp)) != 0) {
int vpid; /* capability number of vnode */
if (error == ENOENT)
return (error);
#ifdef PARANOID
if ((vdp->v_flag & VROOT) && (flags & ISDOTDOT))
panic("filecore_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 = vdp;
dp = VTOI(*vpp);
vdp = *vpp;
vpid = vdp->v_id;
if (pdp == vdp) {
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
VOP_UNLOCK(pdp, 0);
error = vget(vdp, LK_EXCLUSIVE);
if (!error && lockparent && (flags & ISLASTCN))
error = vn_lock(pdp, LK_EXCLUSIVE);
} else {
error = vget(vdp, LK_EXCLUSIVE);
if (!lockparent || error || !(flags & ISLASTCN))
VOP_UNLOCK(pdp, 0);
}
/*
* Check that the capability number did not change
* while we were waiting for the lock.
*/
if (!error) {
if (vpid == vdp->v_id)
return (0);
vput(vdp);
if (lockparent && pdp != vdp && (flags & ISLASTCN))
VOP_UNLOCK(pdp, 0);
}
if ((error = vn_lock(pdp, LK_EXCLUSIVE)) != 0)
return (error);
vdp = pdp;
dp = VTOI(pdp);
*vpp = NULL;
}
name = cnp->cn_nameptr;
namelen = cnp->cn_namelen;
/*
* If there is cached information on a previous search of
* this directory, pick up where we last left off.
* We cache only lookups as these are the most common
* and have the greatest payoff. Caching CREATE has little
* benefit as it usually must search the entire directory
* to determine that the entry does not exist. Caching the
* location of the last DELETE or RENAME has not reduced
* profiling time and hence has been removed in the interest
* of simplicity.
*/
if (nameiop != LOOKUP || dp->i_diroff == 0 ||
dp->i_diroff >= FILECORE_MAXDIRENTS) {
i = 0;
numdirpasses = 1;
} else {
i = dp->i_diroff;
numdirpasses = 2;
filecore_nchstats.ncs_2passes++;
}
endsearch = FILECORE_MAXDIRENTS;
if ((flags & ISDOTDOT) || (name[0]=='.' && namelen==1))
goto found;
error = filecore_dbread(dp, &bp);
if (error) return error;
de = fcdirentry(bp->b_data,i);
searchloop:
while (de->name[0]!=0 && i<endsearch) {
/*
* Check for a name match.
*/
res = filecore_fncmp(de->name,name,namelen);
if (res==0) goto found;
if (res<0) goto notfound;
i++;
de++;
}
notfound:
/*
* If we started in the middle of the directory and failed
* to find our target, we must check the beginning as well.
*/
if (numdirpasses == 2) {
numdirpasses--;
i = 0;
de = fcdirentry(bp->b_data,i);
endsearch = dp->i_diroff;
goto searchloop;
}
if (bp != NULL) {
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) lo1\n",bp);
#endif
brelse(bp);
}
/*
* Insert name into cache (as non-existent) if appropriate.
*/
if (cnp->cn_flags & MAKEENTRY)
cache_enter(vdp, *vpp, cnp);
if (nameiop == CREATE || nameiop == RENAME)
return (EJUSTRETURN);
return (ENOENT);
found:
if (numdirpasses == 2)
filecore_nchstats.ncs_pass2++;
/*
* Found component in pathname.
* If the final component of path name, save information
* in the cache as to where the entry was found.
*/
if ((flags & ISLASTCN) && nameiop == LOOKUP)
dp->i_diroff = i;
/*
* Step through the translation in the name. We do not `iput' the
* directory because we may need it again if a symbolic link
* is relative to the current directory. Instead we save it
* unlocked as "pdp". We must get the target inode before unlocking
* the directory to insure that the inode will not be removed
* before we get it. We prevent deadlock by always fetching
* inodes from the root, moving down the directory tree. Thus
* when following backward pointers ".." we must unlock the
* parent directory before getting the requested directory.
* There is a potential race condition here if both the current
* and parent directories are removed before the `iget' for the
* inode associated with ".." returns. We hope that this occurs
* infrequently since we cannot avoid this race condition without
* implementing a sophisticated deadlock detection algorithm.
* Note also that this simple deadlock detection scheme will not
* work if the file system has any hard links other than ".."
* that point backwards in the directory structure.
*/
pdp = vdp;
/*
* If ino is different from dp->i_ino,
* it's a relocated directory.
*/
if (flags & ISDOTDOT) {
ino_t pin = filecore_getparent(dp);
VOP_UNLOCK(pdp, 0); /* race to get the inode */
error = VFS_VGET(vdp->v_mount, pin, &tdp);
if (error) {
vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY);
return (error);
}
if (lockparent && (flags & ISLASTCN) &&
(error = vn_lock(pdp, LK_EXCLUSIVE))) {
vput(tdp);
return (error);
}
*vpp = tdp;
} else if (name[0]=='.' && namelen==1) {
VREF(vdp); /* we want ourself, ie "." */
*vpp = vdp;
} else {
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) lo4\n",bp);
#endif
brelse(bp);
error = VFS_VGET(vdp->v_mount, dp->i_dirent.addr |
(i<<FILECORE_INO_INDEX), &tdp);
if (error)
return (error);
if (!lockparent || !(flags & ISLASTCN))
VOP_UNLOCK(pdp, 0);
*vpp = tdp;
}
/*
* Insert name into cache if appropriate.
*/
if (cnp->cn_flags & MAKEENTRY)
cache_enter(vdp, *vpp, cnp);
return (0);
}

View File

@ -0,0 +1,55 @@
/* $NetBSD: filecore_mount.h,v 1.1 1998/08/14 03:26:13 mark Exp $ */
/*
* Copyright (c) 1998 Andrew McMurry
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* filecore_mount.h 1.1 1998/6/26
*/
/*
* Arguments to mount Acorn Filecore filesystems.
*/
struct filecore_args {
char *fspec; /* block special device to mount */
struct export_args export; /* network export info */
uid_t uid; /* uid that owns filecore files */
gid_t gid; /* gid that owns filecore files */
int flags; /* mounting flags, see below */
};
#define FILECOREMNT_ROOT 0
#define FILECOREMNT_OWNACCESS 1 /* Only user has Owner access */
#define FILECOREMNT_ALLACCESS 2 /* World has Owner access */
#define FILECOREMNT_OWNREAD 4 /* All files have Owner read access */
#define FILECOREMNT_USEUID 8 /* Use uid of mount process */
#define FILECOREMNT_FILETYPE 16 /* Include filetype in filename */

View File

@ -0,0 +1,209 @@
/* $NetBSD: filecore_node.c,v 1.1 1998/08/14 03:26:13 mark Exp $ */
/*-
* Copyright (c) 1998 Andrew McMurry
* Copyright (c) 1982, 1986, 1989, 1994
* The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* filecore_node.c 1.0 1998/6/4
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/buf.h>
#include <sys/vnode.h>
#include <sys/namei.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/stat.h>
#include <filecorefs/filecore.h>
#include <filecorefs/filecore_extern.h>
#include <filecorefs/filecore_node.h>
#include <filecorefs/filecore_mount.h>
/*
* Structures associated with filecore_node caching.
*/
struct filecore_node **filecorehashtbl;
u_long filecorehash;
#define INOHASH(device, inum) (((device) + ((inum)>>12)) & filecorehash)
struct simplelock filecore_ihash_slock;
int prtactive; /* 1 => print out reclaim of active vnodes */
/*
* Initialize hash links for inodes and dnodes.
*/
void
filecore_init()
{
filecorehashtbl = hashinit(desiredvnodes, M_FILECOREMNT, M_WAITOK, &filecorehash);
simple_lock_init(&filecore_ihash_slock);
}
/*
* 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.
*/
struct vnode *
filecore_ihashget(dev, inum)
dev_t dev;
ino_t inum;
{
struct filecore_node *ip;
struct vnode *vp;
loop:
simple_lock(&filecore_ihash_slock);
for (ip = filecorehashtbl[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(&filecore_ihash_slock);
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
goto loop;
return (vp);
}
}
simple_unlock(&filecore_ihash_slock);
return (NULL);
}
/*
* Insert the inode into the hash table, and return it locked.
*/
void
filecore_ihashins(ip)
struct filecore_node *ip;
{
struct filecore_node **ipp, *iq;
simple_lock(&filecore_ihash_slock);
ipp = &filecorehashtbl[INOHASH(ip->i_dev, ip->i_number)];
if ((iq = *ipp) != NULL)
iq->i_prev = &ip->i_next;
ip->i_next = iq;
ip->i_prev = ipp;
*ipp = ip;
simple_unlock(&filecore_ihash_slock);
lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0);
}
/*
* Remove the inode from the hash table.
*/
void
filecore_ihashrem(ip)
register struct filecore_node *ip;
{
register struct filecore_node *iq;
simple_lock(&filecore_ihash_slock);
if ((iq = ip->i_next) != NULL)
iq->i_prev = ip->i_prev;
*ip->i_prev = iq;
#ifdef DIAGNOSTIC
ip->i_next = NULL;
ip->i_prev = NULL;
#endif
simple_unlock(&filecore_ihash_slock);
}
/*
* Last reference to an inode, write the inode out and if necessary,
* truncate and deallocate the file.
*/
int
filecore_inactive(v)
void *v;
{
struct vop_inactive_args /* {
struct vnode *a_vp;
struct proc *a_p;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct proc *p = ap->a_p;
register struct filecore_node *ip = VTOI(vp);
int error = 0;
if (prtactive && vp->v_usecount != 0)
vprint("filecore_inactive: pushing active", vp);
ip->i_flag = 0;
VOP_UNLOCK(vp, 0);
/*
* If we are done with the inode, reclaim it
* so that it can be reused immediately.
*/
if (filecore_staleinode(ip))
vrecycle(vp, (struct simplelock *)0, p);
return error;
}
/*
* Reclaim an inode so that it can be used for other purposes.
*/
int
filecore_reclaim(v)
void *v;
{
struct vop_reclaim_args /* {
struct vnode *a_vp;
struct proc *a_p;
} */ *ap = v;
register struct vnode *vp = ap->a_vp;
register struct filecore_node *ip = VTOI(vp);
if (prtactive && vp->v_usecount != 0)
vprint("filecore_reclaim: pushing active", vp);
/*
* Remove the inode from its hash chain.
*/
filecore_ihashrem(ip);
/*
* Purge old data structures associated with the inode.
*/
cache_purge(vp);
if (ip->i_devvp) {
vrele(ip->i_devvp);
ip->i_devvp = 0;
}
FREE(vp->v_data, M_FILECORENODE);
vp->v_data = NULL;
return (0);
}

View File

@ -0,0 +1,115 @@
/* $NetBSD: filecore_node.h,v 1.1 1998/08/14 03:26:13 mark Exp $ */
/*-
* Copyright (c) 1998 Andrew McMurry
* Copyright (c) 1994 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* filecore_node.h 1.1 1998/6/26
*/
/*
* In a future format, directories may 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
struct filecore_node {
struct filecore_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 */
dev_t i_dev; /* device where inode resides */
ino_t i_number; /* the identity of the inode */
daddr_t i_block; /* the disc address of the file */
ino_t i_parent; /* the ino of the file's parent */
struct filecore_mnt *i_mnt; /* filesystem associated with this inode */
struct lockf *i_lockf; /* head of byte-level lock list */
struct lock i_lock; /* node lock */
int i_diroff; /* offset in dir, where we found last entry */
struct filecore_direntry i_dirent; /* directory entry */
};
#define i_forw i_chain[0]
#define i_back i_chain[1]
#define i_size i_dirent.len
/* flags */
#define IN_ACCESS 0x0020 /* inode access time to be updated */
#define VTOI(vp) ((struct filecore_node *)(vp)->v_data)
#define ITOV(ip) ((ip)->i_vnode)
#define filecore_staleinode(ip) ((ip)->i_dirent.name[0]==0)
/*
* Prototypes for Filecore vnode operations
*/
int filecore_lookup __P((void *));
#define filecore_open genfs_nullop
#define filecore_close genfs_nullop
int filecore_access __P((void *));
int filecore_getattr __P((void *));
int filecore_read __P((void *));
#define filecore_poll genfs_poll
int filecore_mmap __P((void *));
#define filecore_seek genfs_seek
int filecore_readdir __P((void *));
int filecore_readlink __P((void *));
#define filecore_abortop genfs_abortop
int filecore_inactive __P((void *));
int filecore_reclaim __P((void *));
int filecore_link __P((void *));
int filecore_symlink __P((void *));
int filecore_bmap __P((void *));
int filecore_lock __P((void *));
int filecore_unlock __P((void *));
int filecore_strategy __P((void *));
int filecore_print __P((void *));
int filecore_islocked __P((void *));
int filecore_pathconf __P((void *));
int filecore_blkatoff __P((void *));
struct vnode *filecore_ihashget __P((dev_t, ino_t));
void filecore_ihashins __P((struct filecore_node *));
void filecore_ihashrem __P((struct filecore_node *));
mode_t filecore_mode __P((struct filecore_node *));
struct timespec filecore_time __P((struct filecore_node *));
ino_t filecore_getparent __P((struct filecore_node *));
int filecore_fn2unix __P((char *, char *, u_int8_t *));
int filecore_fncmp __P((const char *, const char *, u_short));
int filecore_dbread __P((struct filecore_node *, struct buf **));

View File

@ -0,0 +1,316 @@
/* $NetBSD: filecore_utils.c,v 1.1 1998/08/14 03:26:13 mark Exp $ */
/*-
* Copyright (c) 1998 Andrew McMurry
* Copyright (c) 1994 The Regents of the University of California.
* All rights reserved.
*
* This code includes code derived from software contributed to the
* NetBSD project by Mark Brinicombe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* filecore_utils.c 1.1 1998/6/26
*/
/*
* Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christopher G. Demetriou
* for the NetBSD Project.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/stat.h>
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/dirent.h>
#include <filecorefs/filecore.h>
#include <filecorefs/filecore_extern.h>
#include <filecorefs/filecore_node.h>
#include <filecorefs/filecore_mount.h>
/*
* int filecore_bbchecksum(u_char *bootblock)
*
* Calculates the filecore boot block checksum. This is used to validate
* a filecore boot block on the disk. If a boot block is validated then
* it is used to locate the partition table. If the boot block is not
* validated, it is assumed that the whole disk is NetBSD.
*
* The basic algorithm is:
*
* for (each byte in block, excluding checksum) {
* sum += byte;
* if (sum > 255)
* sum -= 255;
* }
*
* That's equivalent to summing all of the bytes in the block
* (excluding the checksum byte, of course), then calculating the
* checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That
* expression may or may not yield a faster checksum function,
* but it's easier to reason about.
*
* Note that if you have a block filled with bytes of a single
* value "X" (regardless of that value!) and calculate the cksum
* of the block (excluding the checksum byte), you will _always_
* end up with a checksum of X. (Do the math; that can be derived
* from the checksum calculation function!) That means that
* blocks which contain bytes which all have the same value will
* always checksum properly. That's a _very_ unlikely occurence
* (probably impossible, actually) for a valid filecore boot block,
* so we treat such blocks as invalid.
*/
int
filecore_bbchecksum(bb)
void *bb;
{
u_char *bootblock = bb;
u_char byte0, accum_diff;
u_int sum;
int i;
sum = 0;
accum_diff = 0;
byte0 = bootblock[0];
/*
* Sum the contents of the block, keeping track of whether
* or not all bytes are the same. If 'accum_diff' ends up
* being zero, all of the bytes are, in fact, the same.
*/
for (i = 0; i < 511; ++i) {
sum += bootblock[i];
accum_diff |= bootblock[i] ^ byte0;
}
/*
* Check to see if the checksum byte is the same as the
* rest of the bytes, too. (Note that if all of the bytes
* are the same except the checksum, a checksum compare
* won't succeed, but that's not our problem.)
*/
accum_diff |= bootblock[i] ^ byte0;
sum = (sum - ((sum - 1) / 255) * 255);
/*
* If all bytes in block are the same
* or the checksum does not match ; call it invalid.
*/
if (accum_diff == 0 || sum != bootblock[511])
return -1;
return 0;
}
mode_t
filecore_mode(ip)
struct filecore_node *ip;
{
mode_t m=0;
int rf=0;
if ((ip->i_dirent.attr & FILECORE_ATTR_READ) ||
(ip->i_mnt->fc_mntflags & FILECOREMNT_OWNREAD) ||
(ip->i_dirent.attr & FILECORE_ATTR_DIR)) rf=1;
if (ip->i_mnt->fc_mntflags & FILECOREMNT_ALLACCESS) {
m|=S_IRUSR|S_IXUSR;
if (rf || (ip->i_dirent.attr & FILECORE_ATTR_OREAD))
m|=S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
} else if (ip->i_mnt->fc_mntflags & FILECOREMNT_OWNACCESS) {
if (rf) m|=S_IRUSR|S_IXUSR;
if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
m|=S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
} else {
m|=S_IRUSR|S_IXUSR;
if (rf) m|=S_IRGRP|S_IXGRP;
if (ip->i_dirent.attr & FILECORE_ATTR_OREAD)
m|=S_IROTH|S_IXOTH;
}
if (ip->i_dirent.attr & FILECORE_ATTR_DIR) {
m|=S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH;
} else m|=S_IFREG;
return m;
}
struct timespec
filecore_time(ip)
struct filecore_node *ip;
{
struct timespec ts;
u_int64_t cs;
cs=(((u_int64_t)(ip->i_dirent.load&0xFF))<<32) + ip->i_dirent.exec -
((u_int64_t)1725772500 << 7);
ts.tv_sec = cs/100;
ts.tv_nsec = (cs%100)*10000000;
return ts;
}
ino_t
filecore_getparent(ip)
struct filecore_node *ip;
{
struct buf *pbp;
u_int32_t addr;
u_int32_t paddr;
int error=0;
int i=0;
#ifdef FILECORE_DEBUG
printf("filecore_getparent(ino=%x)\n",ip->i_number);
#endif
if (ip->i_parent != -2) {
return ip->i_parent;
}
if (ip->i_number == FILECORE_ROOTINO) {
ip->i_parent = ip->i_number;
return ip->i_number;
}
addr=ip->i_number & FILECORE_INO_MASK;
/* Read directory data for parent dir to find its parent */
#ifdef FILECORE_DEBUG
printf("filecore_getparent() read parent dir contents\n");
#endif
error=filecore_bread(ip->i_mnt, addr,
FILECORE_DIR_SIZE, NOCRED, &pbp);
if (error)
return error;
paddr=fcdirtail(pbp->b_data)->parent1 | fcdirtail(pbp->b_data)->parent2<<16;
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) ut1\n",pbp);
#endif
brelse(pbp);
/* If parent's parent is the parent then parent is root dir */
if (paddr == addr) {
ip->i_parent = FILECORE_ROOTINO;
return FILECORE_ROOTINO;
}
#ifdef FILECORE_DEBUG
printf("filecore_getparent() read grand-parent dir contents\n");
#endif
error=filecore_bread(ip->i_mnt, paddr,
FILECORE_DIR_SIZE, NOCRED, &pbp);
if (error)
return error;
while (fcdirentry(pbp->b_data,i)->addr != addr) {
if (fcdirentry(pbp->b_data,i++)->name[0]==0) {
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) ut2\n",pbp);
#endif
brelse(pbp);
return FILECORE_ROOTINO;
}
}
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) ut3\n",pbp);
#endif
brelse(pbp);
ip->i_parent = paddr + (i<<FILECORE_INO_INDEX);
return (paddr + (i<<FILECORE_INO_INDEX));
}
/*static char filecore_hexchar[16]="0123456789abcdef";*/
int
filecore_fn2unix(fcfn, ufn, len)
char *fcfn;
char *ufn;
u_int8_t *len;
{
int i=0;
if (*fcfn==0) return (-1);
while (i++<10 && *fcfn>=' ') {
if (*fcfn=='/') *ufn++ = '.';
else *ufn++ = *fcfn;
fcfn++;
}
/* if (ip->i_mnt->fc_mntflags & FILECOREMNT_FILETYPE) {
*ufn++ = ',';
*ufn++ = filecore_hexchar[(ip->i_dirent.load>>10) & 15];
*ufn++ = filecore_hexchar[(ip->i_dirent.load>>9) & 15];
*ufn++ = filecore_hexchar[(ip->i_dirent.load>>8) & 15];
} */
*ufn=0;
*len=i-1;
return 0;
}
int
filecore_fncmp(fcfn, ufn, len)
const char *fcfn;
const char *ufn;
u_short len;
{
char f, u;
int i=0;
if (*fcfn==0 || len>10) return -1;
while (i++<len) {
if (*fcfn<' ') return 1;
f = *fcfn++;
u = *ufn++;
if (u=='.') u = '/';
if (u>='a' && u<='z') u -= 'a'-'A';
if (f>='a' && f<='z') f -= 'a'-'A';
if (f<u) return 1;
else if (f>u) return -1;
}
if (len==10 || *fcfn<' ') return 0;
return -1;
}

View File

@ -0,0 +1,665 @@
/* $NetBSD: filecore_vfsops.c,v 1.1 1998/08/14 03:26:13 mark Exp $ */
/*-
* Copyright (c) 1998 Andrew McMurry
* Copyright (c) 1994 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* filecore_vfsops.c 1.1 1998/6/26
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <miscfs/specfs/specdev.h>
#include <sys/mount.h>
#include <sys/buf.h>
#include <sys/file.h>
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <filecorefs/filecore.h>
#include <filecorefs/filecore_extern.h>
#include <filecorefs/filecore_node.h>
#include <filecorefs/filecore_mount.h>
extern struct vnodeopv_desc filecore_vnodeop_opv_desc;
struct vnodeopv_desc *filecore_vnodeopv_descs[] = {
&filecore_vnodeop_opv_desc,
NULL,
};
struct vfsops filecore_vfsops = {
MOUNT_FILECORE,
filecore_mount,
filecore_start,
filecore_unmount,
filecore_root,
filecore_quotactl,
filecore_statfs,
filecore_sync,
filecore_vget,
filecore_fhtovp,
filecore_vptofh,
filecore_init,
filecore_sysctl,
NULL, /* filecore_mountroot */
filecore_vnodeopv_descs,
};
/*
* Called by vfs_mountroot when iso is going to be mounted as root.
*
* Name is updated by mount(8) after booting.
*/
static int filecore_mountfs __P((struct vnode *devvp, struct mount *mp,
struct proc *p, struct filecore_args *argp));
#if 0
int
filecore_mountroot()
{
struct mount *mp;
extern struct vnode *rootvp;
struct proc *p = curproc; /* XXX */
int error;
struct filecore_args args;
if (root_device->dv_class != DV_DISK)
return (ENODEV);
/*
* Get vnodes for swapdev and rootdev.
*/
if (bdevvp(rootdev, &rootvp))
panic("filecore_mountroot: can't setup rootvp");
if ((error = vfs_rootmountalloc(MOUNT_FILECORE, "root_device", &mp)) != 0)
return (error);
args.flags = FILECOREMNT_ROOT;
if ((error = filecore_mountfs(rootvp, mp, p, &args)) != 0) {
mp->mnt_op->vfs_refcount--;
vfs_unbusy(mp);
free(mp, M_MOUNT);
return (error);
}
simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
simple_unlock(&mountlist_slock);
(void)filecore_statfs(mp, &mp->mnt_stat, p);
vfs_unbusy(mp);
return (0);
}
#endif
/*
* VFS Operations.
*
* mount system call
*/
int
filecore_mount(mp, path, data, ndp, p)
struct mount *mp;
const char *path;
void *data;
struct nameidata *ndp;
struct proc *p;
{
struct vnode *devvp;
struct filecore_args args;
size_t size;
int error;
struct filecore_mnt *fcmp = NULL;
error = copyin(data, (caddr_t)&args, sizeof (struct filecore_args));
if (error)
return (error);
if ((mp->mnt_flag & MNT_RDONLY) == 0)
return (EROFS);
/*
* If updating, check whether changing from read-only to
* read/write; if there is no device name, that's all we do.
*/
if (mp->mnt_flag & MNT_UPDATE) {
fcmp = VFSTOFILECORE(mp);
if (args.fspec == 0)
return (vfs_export(mp, &fcmp->fc_export, &args.export));
}
/*
* Not an update, or updating the name: look up the name
* and verify that it refers to a sensible block device.
*/
NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
if ((error = namei(ndp)) != 0)
return (error);
devvp = ndp->ni_vp;
if (devvp->v_type != VBLK) {
vrele(devvp);
return ENOTBLK;
}
if (major(devvp->v_rdev) >= nblkdev) {
vrele(devvp);
return ENXIO;
}
if ((mp->mnt_flag & MNT_UPDATE) == 0)
error = filecore_mountfs(devvp, mp, p, &args);
else {
if (devvp != fcmp->fc_devvp)
error = EINVAL; /* needs translation */
else
vrele(devvp);
}
if (error) {
vrele(devvp);
return error;
}
fcmp = VFSTOFILECORE(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
&size);
memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
return 0;
}
/*
* Common code for mount and mountroot
*/
static int
filecore_mountfs(devvp, mp, p, argp)
register struct vnode *devvp;
struct mount *mp;
struct proc *p;
struct filecore_args *argp;
{
register struct filecore_mnt *fcmp = (struct filecore_mnt *)0;
struct buf *bp = NULL;
dev_t dev = devvp->v_rdev;
int error = EINVAL;
int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
extern struct vnode *rootvp;
struct filecore_disc_record *fcdr;
unsigned map;
unsigned log2secsize;
if (!ronly)
return EROFS;
/*
* Disallow multiple mounts of the same device.
* Disallow mounting of a device that is currently in use
* (except for root, which might share swap device for miniroot).
* Flush out any old buffers remaining from a previous use.
*/
if ((error = vfs_mountedon(devvp)) != 0)
return error;
if (vcount(devvp) > 1 && devvp != rootvp)
return EBUSY;
if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
return (error);
error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
if (error)
return error;
/* Read the filecore boot block to check FS validity and to find the map */
error = bread(devvp, FILECORE_BOOTBLOCK_BLKN,
FILECORE_BOOTBLOCK_SIZE, NOCRED, &bp);
#ifdef FILECORE_DEBUG_BR
printf("bread(%p, %x, %d, CRED, %p)=%d\n",devvp,
FILECORE_BOOTBLOCK_BLKN, FILECORE_BOOTBLOCK_SIZE,
bp, error);
#endif
if (error != 0)
goto out;
if (filecore_bbchecksum(bp->b_data) != 0) {
error = EINVAL;
goto out;
}
fcdr = (struct filecore_disc_record *)(bp->b_data+FILECORE_BB_DISCREC);
map = ((((8<<fcdr->log2secsize)-fcdr->zone_spare)*(fcdr->nzones/2) -
8*FILECORE_DISCREC_SIZE) << fcdr->log2bpmb) >> fcdr->log2secsize;
log2secsize = fcdr->log2secsize;
bp->b_flags |= B_AGE;
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) vf1\n",bp);
#endif
brelse(bp);
bp = NULL;
/* Read the bootblock in the map */
error = bread(devvp, map, 1<<log2secsize, NOCRED, &bp);
#ifdef FILECORE_DEBUG_BR
printf("bread(%p, %x, %d, CRED, %p)=%d\n",devvp,
map, 1<<log2secsize, bp, error);
#endif
if (error != 0)
goto out;
fcdr = (struct filecore_disc_record *)(bp->b_data+4);
fcmp = malloc(sizeof *fcmp, M_FILECOREMNT, M_WAITOK);
memset((caddr_t)fcmp, 0, sizeof *fcmp);
if (fcdr->log2bpmb > fcdr->log2secsize)
fcmp->log2bsize = fcdr->log2bpmb;
else fcmp->log2bsize = fcdr->log2secsize;
fcmp->blksize = 1<<fcmp->log2bsize;
memcpy((caddr_t)&fcmp->drec, (caddr_t)fcdr, sizeof(*fcdr));
fcmp->map=map;
fcmp->idspz=((8<<fcdr->log2secsize)-fcdr->zone_spare)/(fcdr->idlen+1);
fcmp->mask=(1<<fcdr->idlen)-1;
if (fcdr->big_flag & 1) {
fcmp->nblks=((((u_int64_t)fcdr->disc_size_2)<<32)+fcdr->disc_size) /
fcmp->blksize;
} else {
fcmp->nblks=fcdr->disc_size / fcmp->blksize;
}
bp->b_flags |= B_AGE;
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) vf2\n",bp);
#endif
brelse(bp);
bp = NULL;
mp->mnt_data = (qaddr_t)fcmp;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_FILECORE);
mp->mnt_maxsymlinklen = 0;
mp->mnt_flag |= MNT_LOCAL;
fcmp->fc_mountp = mp;
fcmp->fc_dev = dev;
fcmp->fc_devvp = devvp;
fcmp->fc_mntflags = argp->flags;
if (argp->flags & FILECOREMNT_USEUID) {
fcmp->fc_uid = p->p_cred->p_ruid;
fcmp->fc_gid = p->p_cred->p_rgid;
} else {
fcmp->fc_uid = argp->uid;
fcmp->fc_gid = argp->gid;
}
devvp->v_specflags |= SI_MOUNTEDON;
return 0;
out:
if (bp) {
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) vf3\n",bp);
#endif
brelse(bp);
}
(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
if (fcmp) {
free((caddr_t)fcmp, M_FILECOREMNT);
mp->mnt_data = (qaddr_t)0;
}
return error;
}
/*
* Make a filesystem operational.
* Nothing to do at the moment.
*/
/* ARGSUSED */
int
filecore_start(mp, flags, p)
struct mount *mp;
int flags;
struct proc *p;
{
return 0;
}
/*
* unmount system call
*/
int
filecore_unmount(mp, mntflags, p)
struct mount *mp;
int mntflags;
struct proc *p;
{
register struct filecore_mnt *fcmp;
int error, flags = 0;
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
#if 0
mntflushbuf(mp, 0);
if (mntinvalbuf(mp))
return EBUSY;
#endif
if ((error = vflush(mp, NULLVP, flags)) != 0)
return (error);
fcmp = VFSTOFILECORE(mp);
fcmp->fc_devvp->v_specflags &= ~SI_MOUNTEDON;
error = VOP_CLOSE(fcmp->fc_devvp, FREAD, NOCRED, p);
vrele(fcmp->fc_devvp);
free((caddr_t)fcmp, M_FILECOREMNT);
mp->mnt_data = (qaddr_t)0;
mp->mnt_flag &= ~MNT_LOCAL;
return (error);
}
/*
* Return root of a filesystem
*/
int
filecore_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
struct vnode *nvp;
int error;
if ((error = VFS_VGET(mp, FILECORE_ROOTINO, &nvp)) != 0)
return (error);
*vpp = nvp;
return (0);
}
/*
* Do operations associated with quotas, not supported
*/
/* ARGSUSED */
int
filecore_quotactl(mp, cmd, uid, arg, p)
struct mount *mp;
int cmd;
uid_t uid;
caddr_t arg;
struct proc *p;
{
return (EOPNOTSUPP);
}
/*
* Get file system statistics.
*/
int
filecore_statfs(mp, sbp, p)
struct mount *mp;
register struct statfs *sbp;
struct proc *p;
{
register struct filecore_mnt *fcmp = VFSTOFILECORE(mp);
#ifdef COMPAT_09
sbp->f_type = 255;
#else
sbp->f_type = 0;
#endif
sbp->f_bsize = fcmp->blksize;
sbp->f_iosize = sbp->f_bsize; /* XXX */
sbp->f_blocks = fcmp->nblks;
sbp->f_bfree = 0; /* total free blocks */
sbp->f_bavail = 0; /* blocks free for non superuser */
sbp->f_files = 0; /* total files */
sbp->f_ffree = 0; /* free file nodes */
if (sbp != &mp->mnt_stat) {
memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN);
memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN);
}
strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
return 0;
}
/* ARGSUSED */
int
filecore_sync(mp, waitfor, cred, p)
struct mount *mp;
int waitfor;
struct ucred *cred;
struct proc *p;
{
return (0);
}
/*
* File handle to vnode
*
* Have to be really careful about stale file handles:
* - check that the inode number is in range
* - call iget() to get the locked inode
* - check for an unallocated inode (i_mode == 0)
* - check that the generation number matches
*/
struct ifid {
ushort ifid_len;
ushort ifid_pad;
u_int32_t ifid_ino;
};
/* ARGSUSED */
int
filecore_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
register struct mount *mp;
struct fid *fhp;
struct mbuf *nam;
struct vnode **vpp;
int *exflagsp;
struct ucred **credanonp;
{
struct ifid *ifhp = (struct ifid *)fhp;
register struct netcred *np;
register struct filecore_mnt *fcmp = VFSTOFILECORE(mp);
struct vnode *nvp;
struct filecore_node *ip;
int error;
/*
* Get the export permission structure for this <mp, client> tuple.
*/
np = vfs_export_lookup(mp, &fcmp->fc_export, nam);
if (np == NULL)
return (EACCES);
if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
*vpp = NULLVP;
return (error);
}
ip = VTOI(nvp);
if (filecore_staleinode(ip)) {
vput(nvp);
*vpp = NULLVP;
return (ESTALE);
} *vpp = nvp;
*exflagsp = np->netc_exflags;
*credanonp = &np->netc_anon;
return (0);
}
/* This looks complicated. Look at other vgets as well as the iso9660 one.
The filecore inode number is made up of 1 byte directory entry index and
3 bytes of the internal disc address of the directory. On a read-only
filesystem this is unique. For a read-write version we may not be able to
do vget, see msdosfs.
*/
int
filecore_vget(mp, ino, vpp)
struct mount *mp;
ino_t ino;
struct vnode **vpp;
{
register struct filecore_mnt *fcmp;
struct filecore_node *ip;
struct buf *bp;
struct vnode *vp;
dev_t dev;
int error;
fcmp = VFSTOFILECORE(mp);
dev = fcmp->fc_dev;
if ((*vpp = filecore_ihashget(dev, ino)) != NULLVP)
return (0);
/* Allocate a new vnode/filecore_node. */
if ((error=getnewvnode(VT_FILECORE,mp,filecore_vnodeop_p,&vp)) != 0) {
*vpp = NULLVP;
return (error);
}
MALLOC(ip, struct filecore_node *, sizeof(struct filecore_node),
M_FILECORENODE, M_WAITOK);
memset((caddr_t)ip, 0, sizeof(struct filecore_node));
lockinit(&ip->i_lock, PINOD, "filecorenode", 0, 0);
vp->v_data = ip;
ip->i_vnode = vp;
ip->i_dev = dev;
ip->i_number = ino;
ip->i_block = -1;
ip->i_parent = -2;
/*
* 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.
*/
filecore_ihashins(ip);
if (ino==FILECORE_ROOTINO) {
/* Here we need to construct a root directory inode */
memcpy((caddr_t)ip->i_dirent.name,(caddr_t)"root",4);
ip->i_dirent.load=0;
ip->i_dirent.exec=0;
ip->i_dirent.len=FILECORE_DIR_SIZE;
ip->i_dirent.addr=fcmp->drec.root;
ip->i_dirent.attr=FILECORE_ATTR_DIR | FILECORE_ATTR_READ;
} else {
/* Read in Data from Directory Entry */
if ((error=filecore_bread(fcmp, ino & FILECORE_INO_MASK,
FILECORE_DIR_SIZE, NOCRED, &bp)) != 0) {
vput(vp);
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) vf4\n",bp);
#endif
brelse(bp);
*vpp = NULL;
return (error);
}
memcpy((caddr_t)&ip->i_dirent,
(caddr_t)fcdirentry(bp->b_data, ino>>FILECORE_INO_INDEX),
sizeof(struct filecore_direntry));
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) vf5\n",bp);
#endif
brelse(bp);
}
ip->i_mnt = fcmp;
ip->i_devvp = fcmp->fc_devvp;
ip->i_diroff = 0;
VREF(ip->i_devvp);
/*
* Setup type
*/
vp->v_type = VREG;
if (ip->i_dirent.attr & FILECORE_ATTR_DIR) vp->v_type = VDIR;
/*
* Initialize the associated vnode
*/
switch (vp->v_type) {
case VFIFO:
case VCHR:
case VBLK:
/*
* Devices not supported.
*/
vput(vp);
return (EOPNOTSUPP);
case VLNK:
case VNON:
case VSOCK:
case VDIR:
case VBAD:
case VREG:
break;
}
if (ino == FILECORE_ROOTINO)
vp->v_flag |= VROOT;
/*
* XXX need generation number?
*/
*vpp = vp;
return (0);
}
/*
* Vnode pointer to File handle
*/
/* ARGSUSED */
int
filecore_vptofh(vp, fhp)
struct vnode *vp;
struct fid *fhp;
{
register struct filecore_node *ip = VTOI(vp);
register struct ifid *ifhp;
ifhp = (struct ifid *)fhp;
ifhp->ifid_len = sizeof(struct ifid);
ifhp->ifid_ino = ip->i_number;
return 0;
}
int
filecore_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
int *name;
u_int namelen;
void *oldp;
size_t *oldlenp;
void *newp;
size_t newlen;
struct proc *p;
{
return (EOPNOTSUPP);
}

View File

@ -0,0 +1,616 @@
/* $NetBSD: filecore_vnops.c,v 1.1 1998/08/14 03:26:13 mark Exp $ */
/*-
* Copyright (c) 1998 Andrew McMurry
* Copyright (c) 1994 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* filecore_vnops.c 1.1 1998/6/26
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/resourcevar.h>
#include <sys/kernel.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/buf.h>
#include <sys/proc.h>
#include <sys/conf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <miscfs/genfs/genfs.h>
#include <miscfs/specfs/specdev.h>
#include <filecorefs/filecore.h>
#include <filecorefs/filecore_extern.h>
#include <filecorefs/filecore_node.h>
/*
* Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
* The mode is shifted to select the owner/group/other fields. The
* super user is granted all permissions.
*/
int
filecore_access(v)
void *v;
{
struct vop_access_args /* {
struct vnode *a_vp;
int a_mode;
struct ucred *a_cred;
struct proc *a_p;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct filecore_node *ip = VTOI(vp);
struct filecore_mnt *fcmp = ip->i_mnt;
/*
* Disallow write attempts unless the file is a socket,
* fifo, or a block or character device resident on the
* file system.
*/
if (ap->a_mode & VWRITE) {
switch (vp->v_type) {
case VDIR:
case VLNK:
case VREG:
return (EROFS);
default:
break;
}
}
return (vaccess(vp->v_type, filecore_mode(ip),
fcmp->fc_uid, fcmp->fc_gid, ap->a_mode, ap->a_cred));
}
int
filecore_getattr(v)
void *v;
{
struct vop_getattr_args /* {
struct vnode *a_vp;
struct vattr *a_vap;
struct ucred *a_cred;
struct proc *a_p;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct filecore_node *ip = VTOI(vp);
register struct vattr *vap = ap->a_vap;
struct filecore_mnt *fcmp = ip->i_mnt;
vap->va_fsid = ip->i_dev;
vap->va_fileid = ip->i_number;
vap->va_mode = filecore_mode(ip);
vap->va_nlink = 1;
vap->va_uid = fcmp->fc_uid;
vap->va_gid = fcmp->fc_gid;
vap->va_atime = filecore_time(ip);
vap->va_mtime = filecore_time(ip);
vap->va_ctime = filecore_time(ip);
vap->va_rdev = 0; /* We don't support specials */
vap->va_size = (u_quad_t) ip->i_size;
vap->va_flags = 0;
vap->va_gen = 1;
vap->va_blocksize = fcmp->blksize;
vap->va_bytes = vap->va_size;
vap->va_type = vp->v_type;
return (0);
}
/*
* Vnode op for reading.
*/
int
filecore_read(v)
void *v;
{
struct vop_read_args /* {
struct vnode *a_vp;
struct uio *a_uio;
int a_ioflag;
struct ucred *a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
register struct uio *uio = ap->a_uio;
register struct filecore_node *ip = VTOI(vp);
register struct filecore_mnt *fcmp;
struct buf *bp;
daddr_t lbn, rablock;
off_t diff;
int rasize, error = 0;
long size, n, on;
if (uio->uio_resid == 0)
return (0);
if (uio->uio_offset < 0)
return (EINVAL);
ip->i_flag |= IN_ACCESS;
fcmp = ip->i_mnt;
do {
lbn = lblkno(fcmp, uio->uio_offset);
on = blkoff(fcmp, uio->uio_offset);
n = min((u_int)(blksize(fcmp, ip, lbn) - on),
uio->uio_resid);
diff = (off_t)ip->i_size - uio->uio_offset;
if (diff <= 0)
return (0);
if (diff < n)
n = diff;
size = blksize(fcmp, ip, lbn);
rablock = lbn + 1;
if (ip->i_dirent.attr & FILECORE_ATTR_DIR) {
error = filecore_dbread(ip, &bp);
on = uio->uio_offset;
n = min(FILECORE_DIR_SIZE-on, uio->uio_resid);
size = FILECORE_DIR_SIZE;
} else {
if (vp->v_lastr + 1 == lbn &&
lblktosize(fcmp, rablock) < ip->i_size) {
rasize = blksize(fcmp, ip, rablock);
error = breadn(vp, lbn, size, &rablock,
&rasize, 1, NOCRED, &bp);
#ifdef FILECORE_DEBUG_BR
printf("breadn(%p, %x, %ld, CRED, %p)=%d\n",vp,
lbn, size, bp, error);
#endif
} else {
error = bread(vp, lbn, size, NOCRED, &bp);
#ifdef FILECORE_DEBUG_BR
printf("bread(%p, %x, %ld, CRED, %p)=%d\n",vp, lbn, size,
bp, error);
#endif
}
}
vp->v_lastr = lbn;
n = min(n, size - bp->b_resid);
if (error) {
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) vn1\n",bp);
#endif
brelse(bp);
return (error);
}
error = uiomove(bp->b_data + on, (int)n, uio);
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) vn2\n",bp);
#endif
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n != 0);
return (error);
}
/*
* Mmap a file
*
* NB Currently unsupported.
*/
/* ARGSUSED */
int
filecore_mmap(v)
void *v;
{
return (EINVAL);
}
/*
* Vnode op for readdir
*/
int
filecore_readdir(v)
void *v;
{
struct vop_readdir_args /* {
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
int *a_eofflag;
off_t **a_cookies;
int *a_ncookies;
} */ *ap = v;
register struct uio *uio = ap->a_uio;
struct vnode *vdp = ap->a_vp;
struct filecore_node *dp;
struct filecore_mnt *fcmp;
struct buf *bp = NULL;
struct dirent de;
struct filecore_direntry *dep = NULL;
int error = 0;
off_t *cookies = NULL;
int ncookies = 0;
int nent, i;
dp = VTOI(vdp);
if ((dp->i_dirent.attr & FILECORE_ATTR_DIR) == 0)
return (ENOTDIR);
if (uio->uio_offset % FILECORE_DIRENT_SIZE !=0 ||
uio->uio_resid < FILECORE_DIRENT_SIZE)
return (EINVAL);
nent=uio->uio_resid / FILECORE_DIRENT_SIZE;
i=uio->uio_offset / FILECORE_DIRENT_SIZE;
uio->uio_resid=nent * FILECORE_DIRENT_SIZE;
fcmp = dp->i_mnt;
error = filecore_dbread(dp, &bp);
if (error) {
return error;
}
if (ap->a_ncookies == NULL)
cookies = NULL;
else {
ncookies = nent;
MALLOC(cookies, off_t *, ncookies * sizeof(off_t), M_TEMP,
M_WAITOK);
}
nent+=i;
for (; i<nent; i++) {
switch (i) {
case 0:
/* Fake the '.' entry */
de.d_fileno = dp->i_number;
de.d_type = DT_DIR;
de.d_namlen = 1;
strcpy(de.d_name, ".");
break;
case 1:
/* Fake the '..' entry */
de.d_fileno = filecore_getparent(dp);
de.d_type = DT_DIR;
de.d_namlen = 2;
strcpy(de.d_name, "..");
break;
default:
de.d_fileno = dp->i_dirent.addr +
((i-2)<<FILECORE_INO_INDEX);
dep = fcdirentry(bp->b_data, i-2);
if (dep->attr & FILECORE_ATTR_DIR)
de.d_type = DT_DIR;
else
de.d_type = DT_REG;
if (filecore_fn2unix(dep->name, de.d_name,
&de.d_namlen))
goto out;
break;
}
de.d_reclen = DIRENT_SIZE(&de);
if (uio->uio_resid < de.d_reclen)
goto out;
error = uiomove((caddr_t) &de, de.d_reclen, uio);
if (error)
goto out;
if (cookies) {
*cookies++ = i*FILECORE_DIRENT_SIZE;
(*ap->a_ncookies)++;
}
}
out:
if (ap->a_ncookies) {
if (error) {
FREE(cookies, M_TEMP);
*ap->a_ncookies = 0;
*ap->a_cookies = NULL;
}
}
if (dep != NULL && dep->name[0]==0)
*ap->a_eofflag = 1;
else
*ap->a_eofflag = 0;
#ifdef FILECORE_DEBUG_BR
printf("brelse(%p) vn3\n",bp);
#endif
brelse (bp);
return (error);
}
/*
* Return target name of a symbolic link
* Shouldn't we get the parent vnode and read the data from there?
* This could eventually result in deadlocks in filecore_lookup.
* But otherwise the block read here is in the block buffer two times.
*/
int
filecore_readlink(v)
void *v;
{
#if 0
struct vop_readlink_args /* {
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
} */ *ap = v;
#endif
return (EINVAL);
}
int
filecore_link(v)
void *v;
{
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap = v;
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
filecore_symlink(v)
void *v;
{
struct vop_symlink_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
char *a_target;
} */ *ap = v;
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
/*
* Lock an inode.
*/
int
filecore_lock(v)
void *v;
{
struct vop_lock_args /* {
struct vnode *a_vp;
int a_flags;
struct proc *a_p;
} */ *ap = v;
register struct vnode *vp = ap->a_vp;
return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock));
}
/*
* Unlock an inode.
*/
int
filecore_unlock(v)
void *v;
{
struct vop_unlock_args /* {
struct vnode *a_vp;
int a_flags;
struct proc *a_p;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE,
&vp->v_interlock));
}
/*
* Calculate the logical to physical mapping if not done already,
* then call the device strategy routine.
*/
int
filecore_strategy(v)
void *v;
{
struct vop_strategy_args /* {
struct buf *a_bp;
} */ *ap = v;
register struct buf *bp = ap->a_bp;
register struct vnode *vp = bp->b_vp;
register struct filecore_node *ip;
int error;
ip = VTOI(vp);
if (bp->b_blkno == bp->b_lblkno) {
error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
if (error) {
bp->b_error = error;
bp->b_flags |= B_ERROR;
biodone(bp);
return (error);
}
if ((long)bp->b_blkno == -1)
clrbuf(bp);
}
if ((long)bp->b_blkno == -1) {
biodone(bp);
return (0);
}
vp = ip->i_devvp;
bp->b_dev = vp->v_rdev;
VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
return (0);
}
/*
* Print out the contents of an inode.
*/
/*ARGSUSED*/
int
filecore_print(v)
void *v;
{
printf("tag VT_FILECORE, filecore vnode\n");
return (0);
}
/*
* Check for a locked inode.
*/
int
filecore_islocked(v)
void *v;
{
struct vop_islocked_args /* {
struct vnode *a_vp;
} */ *ap = v;
return (lockstatus(&VTOI(ap->a_vp)->i_lock));
}
/*
* Return POSIX pathconf information applicable to filecore filesystems.
*/
int
filecore_pathconf(v)
void *v;
{
struct vop_pathconf_args /* {
struct vnode *a_vp;
int a_name;
register_t *a_retval;
} */ *ap = v;
switch (ap->a_name) {
case _PC_LINK_MAX:
*ap->a_retval = 1;
return (0);
case _PC_NAME_MAX:
*ap->a_retval = 10;
return (0);
case _PC_PATH_MAX:
*ap->a_retval = 256;
return (0);
case _PC_CHOWN_RESTRICTED:
*ap->a_retval = 1;
return (0);
case _PC_NO_TRUNC:
*ap->a_retval = 1;
return (0);
default:
return (EINVAL);
}
/* NOTREACHED */
}
/*
* Global vfs data structures for isofs
*/
#define filecore_create genfs_eopnotsupp
#define filecore_mknod genfs_eopnotsupp
#define filecore_write genfs_eopnotsupp
#define filecore_setattr genfs_eopnotsupp
#ifdef NFSSERVER
int lease_check __P((void *));
#define filecore_lease_check lease_check
#else
#define filecore_lease_check genfs_nullop
#endif
#define filecore_ioctl genfs_enoioctl
#define filecore_fsync genfs_nullop
#define filecore_remove genfs_eopnotsupp
#define filecore_rename genfs_eopnotsupp
#define filecore_mkdir genfs_eopnotsupp
#define filecore_rmdir genfs_eopnotsupp
#define filecore_advlock genfs_eopnotsupp
#define filecore_valloc genfs_eopnotsupp
#define filecore_vfree genfs_nullop
#define filecore_truncate genfs_eopnotsupp
#define filecore_update genfs_nullop
#define filecore_bwrite genfs_eopnotsupp
#define filecore_revoke genfs_revoke
#define filecore_blkatoff genfs_eopnotsupp
/*
* Global vfs data structures for filecore
*/
int (**filecore_vnodeop_p) __P((void *));
struct vnodeopv_entry_desc filecore_vnodeop_entries[] = {
{ &vop_default_desc, vn_default_error },
{ &vop_lookup_desc, filecore_lookup }, /* lookup */
{ &vop_create_desc, filecore_create }, /* create */
{ &vop_mknod_desc, filecore_mknod }, /* mknod */
{ &vop_open_desc, filecore_open }, /* open */
{ &vop_close_desc, filecore_close }, /* close */
{ &vop_access_desc, filecore_access }, /* access */
{ &vop_getattr_desc, filecore_getattr }, /* getattr */
{ &vop_setattr_desc, filecore_setattr }, /* setattr */
{ &vop_read_desc, filecore_read }, /* read */
{ &vop_write_desc, filecore_write }, /* write */
{ &vop_lease_desc, filecore_lease_check }, /* lease */
{ &vop_ioctl_desc, filecore_ioctl }, /* ioctl */
{ &vop_poll_desc, filecore_poll }, /* poll */
{ &vop_revoke_desc, filecore_revoke }, /* revoke */
{ &vop_mmap_desc, filecore_mmap }, /* mmap */
{ &vop_fsync_desc, filecore_fsync }, /* fsync */
{ &vop_seek_desc, filecore_seek }, /* seek */
{ &vop_remove_desc, filecore_remove }, /* remove */
{ &vop_link_desc, filecore_link }, /* link */
{ &vop_rename_desc, filecore_rename }, /* rename */
{ &vop_mkdir_desc, filecore_mkdir }, /* mkdir */
{ &vop_rmdir_desc, filecore_rmdir }, /* rmdir */
{ &vop_symlink_desc, filecore_symlink }, /* symlink */
{ &vop_readdir_desc, filecore_readdir }, /* readdir */
{ &vop_readlink_desc, filecore_readlink }, /* readlink */
{ &vop_abortop_desc, filecore_abortop }, /* abortop */
{ &vop_inactive_desc, filecore_inactive }, /* inactive */
{ &vop_reclaim_desc, filecore_reclaim }, /* reclaim */
{ &vop_lock_desc, filecore_lock }, /* lock */
{ &vop_unlock_desc, filecore_unlock }, /* unlock */
{ &vop_bmap_desc, filecore_bmap }, /* bmap */
{ &vop_strategy_desc, filecore_strategy }, /* strategy */
{ &vop_print_desc, filecore_print }, /* print */
{ &vop_islocked_desc, filecore_islocked }, /* islocked */
{ &vop_pathconf_desc, filecore_pathconf }, /* pathconf */
{ &vop_advlock_desc, filecore_advlock }, /* advlock */
{ &vop_blkatoff_desc, filecore_blkatoff }, /* blkatoff */
{ &vop_valloc_desc, filecore_valloc }, /* valloc */
{ &vop_vfree_desc, filecore_vfree }, /* vfree */
{ &vop_truncate_desc, filecore_truncate }, /* truncate */
{ &vop_update_desc, filecore_update }, /* update */
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
{ (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL }
};
struct vnodeopv_desc filecore_vnodeop_opv_desc =
{ &filecore_vnodeop_p, filecore_vnodeop_entries };