-/* init_main.c 4.28 82/03/28 */
+/* init_main.c 4.29 82/04/19 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
-#include "../h/filsys.h"
+#include "../h/fs.h"
#include "../h/mount.h"
#include "../h/map.h"
#include "../h/proc.h"
{
register int i;
register struct proc *p;
+ struct fs *fsp;
rqinit();
#include "loop.h"
binit();
bswinit();
iinit();
- rootdir = iget(rootdev, (ino_t)ROOTINO);
+ fsp = getfs(rootdev);
+ rootdir = iget(rootdev, fsp, (ino_t)ROOTINO);
rootdir->i_flag &= ~ILOCK;
- u.u_cdir = iget(rootdev, (ino_t)ROOTINO);
+ u.u_cdir = iget(rootdev, fsp, (ino_t)ROOTINO);
u.u_cdir->i_flag &= ~ILOCK;
u.u_rdir = NULL;
u.u_dmap = zdmap;
iinit()
{
register struct buf *bp;
- register struct filsys *fp;
+ register struct fs *fp;
register int i;
+ int blks;
(*bdevsw[major(rootdev)].d_open)(rootdev, 1);
- bp = bread(rootdev, SUPERB);
+ bp = bread(rootdev, SBLOCK, SBSIZE);
if(u.u_error)
panic("iinit");
bp->b_flags |= B_LOCKED; /* block can never be re-used */
brelse(bp);
mount[0].m_dev = rootdev;
mount[0].m_bufp = bp;
- fp = bp->b_un.b_filsys;
- fp->s_flock = 0;
- fp->s_ilock = 0;
- fp->s_ronly = 0;
- fp->s_lasti = 1;
- fp->s_nbehind = 0;
- fp->s_fsmnt[0] = '/';
- for (i = 1; i < sizeof(fp->s_fsmnt); i++)
- fp->s_fsmnt[i] = 0;
- clkinit(fp->s_time);
- bootime = time;
+ fp = bp->b_un.b_fs;
+ if (fp->fs_magic != FS_MAGIC)
+ panic("root bad magic number");
+ if (fp->fs_bsize > MAXBSIZE)
+ panic("root fs_bsize too big");
+ fp->fs_ronly = 0;
+ fp->fs_fsmnt[0] = '/';
+ for (i = 1; i < sizeof(fp->fs_fsmnt); i++)
+ fp->fs_fsmnt[i] = 0;
+ blks = howmany(fp->fs_cssize, fp->fs_fsize);
+ for (i = 0; i < blks; i += fp->fs_frag) {
+ bp = bread(rootdev, fsbtodb(fp, fp->fs_csaddr + i),
+ blks - i < fp->fs_frag ?
+ (blks - i) * fp->fs_fsize :
+ fp->fs_bsize);
+ if (u.u_error)
+ panic("root can't read csum");
+ fp->fs_csp[i / fp->fs_frag] = bp->b_un.b_cs;
+ bp->b_flags |= B_LOCKED;
+ brelse(bp);
+ }
}
/*
dp->b_flags = B_HEAD;
}
dp--; /* dp = &bfreelist[BQUEUES-1]; */
- for (i=0; i<nbuf; i++) {
+ for (i = 0; i < nbuf; i++) {
bp = &buf[i];
bp->b_dev = NODEV;
- bp->b_un.b_addr = buffers + i * BSIZE;
+ bp->b_un.b_addr = buffers + i * MAXBSIZE;
+ bp->b_bcount = MAXBSIZE;
bp->b_back = dp;
bp->b_forw = dp->b_forw;
dp->b_forw->b_back = bp;
-/* kern_proc.c 4.25 82/04/02 */
+/* kern_proc.c 4.26 82/04/19 */
#include "../h/param.h"
#include "../h/systm.h"
char *sharg;
struct inode *ip;
swblk_t bno;
- char cfname[DIRSIZ];
+ char cfname[MAXNAMLEN + 1];
char cfarg[SHSIZE];
if ((ip = namei(uchar, 0, 1)) == NULL)
sharg = cfarg;
}
}
- bcopy((caddr_t)u.u_dbuf, (caddr_t)cfname, DIRSIZ);
+ bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname,
+ u.u_dent.d_namlen + 1);
indir = 1;
iput(ip);
ip = namei(schar, 0, 1);
uap->envp++;
ne++;
}
- if (ap==NULL)
+ if (ap == NULL)
break;
na++;
if (ap == -1)
bp = 0;
goto badarg;
}
- if ((nc&BMASK) == 0) {
+ if (nc % (CLSIZE*NBPG) == 0) {
if (bp)
bdwrite(bp);
- bp = getblk(argdev,
- (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT)));
+ bp = getblk(argdev, bno + nc / NBPG,
+ CLSIZE*NBPG);
cp = bp->b_un.b_addr;
}
nc++;
*cp++ = c;
- } while (c>0);
+ } while (c > 0);
}
if (bp)
bdwrite(bp);
bp = 0;
nc = (nc + NBPW-1) & ~(NBPW-1);
- if (indir)
- bcopy((caddr_t)cfname, (caddr_t)u.u_dbuf, DIRSIZ);
+ if (indir) {
+ u.u_dent.d_namlen = strlen(cfname);
+ bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name,
+ u.u_dent.d_namlen + 1);
+ }
getxfile(ip, nc + (na+4)*NBPW, uid, gid);
if (u.u_error) {
badarg:
- for (c = 0; c < nc; c += BSIZE)
- if (bp = baddr(argdev, dbtofsb(bno)+(c>>BSHIFT))) {
+ for (c = 0; c < nc; c += CLSIZE*NBPG)
+ if (bp = baddr(argdev, bno + c / NBPG, CLSIZE*NBPG)) {
bp->b_flags |= B_AGE; /* throw away */
bp->b_flags &= ~B_DELWRI; /* cancel io */
brelse(bp);
break;
(void) suword((caddr_t)ap, ucp);
do {
- if ((nc&BMASK) == 0) {
+ if (nc % (CLSIZE*NBPG) == 0) {
if (bp)
brelse(bp);
- bp = bread(argdev,
- (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT)));
+ bp = bread(argdev, bno + nc / NBPG,
+ CLSIZE*NBPG);
bp->b_flags |= B_AGE; /* throw away */
bp->b_flags &= ~B_DELWRI; /* cancel io */
cp = bp->b_un.b_addr;
* Remember file name for accounting.
*/
u.u_acflag &= ~AFORK;
- bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ);
+ bcopy((caddr_t)u.u_dent.d_name, (caddr_t)u.u_comm,
+ u.u_dent.d_namlen + 1);
}
/*
-/* subr_xxx.c 4.9 81/11/20 */
+/* subr_xxx.c 4.10 82/04/19 */
+
+/* merged into kernel: @(#)subr.c 2.2 4/8/82 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/user.h"
#include "../h/buf.h"
#include "../h/proc.h"
+#include "../h/fs.h"
/*
* Bmap defines the structure of file system storage
* block number of the next block of the file in rablock
* for use in read-ahead.
*/
+/*VARARGS3*/
daddr_t
-bmap(ip, bn, rwflg)
-register struct inode *ip;
-daddr_t bn;
+bmap(ip, bn, rwflg, size)
+ register struct inode *ip;
+ daddr_t bn;
+ int rwflg;
+ int size; /* supplied only when rwflg == B_WRITE */
{
- register i;
+ register int i;
+ int osize, nsize;
struct buf *bp, *nbp;
+ struct fs *fs;
int j, sh;
- daddr_t nb, *bap;
- dev_t dev;
+ daddr_t nb, *bap, pref, blkpref();
- if(bn < 0) {
+ if (bn < 0) {
u.u_error = EFBIG;
- return((daddr_t)0);
+ return ((daddr_t)0);
}
- dev = ip->i_dev;
+ fs = ip->i_fs;
rablock = 0;
/*
- * blocks 0..NADDR-4 are direct blocks
+ * If the next write will extend the file into a new block,
+ * and the file is currently composed of a fragment
+ * this fragment has to be extended to be a full block.
*/
- if(bn < NADDR-3) {
+ nb = lblkno(fs, ip->i_size);
+ if (rwflg == B_WRITE && nb < NDADDR && nb < bn) {
+ osize = blksize(fs, ip, nb);
+ if (osize < fs->fs_bsize && osize > 0) {
+ bp = realloccg(ip, ip->i_db[nb],
+ nb == 0 ? 0 : ip->i_db[nb - 1] + fs->fs_frag,
+ osize, fs->fs_bsize);
+ ip->i_size = (nb + 1) * fs->fs_bsize;
+ ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
+ ip->i_flag |= IUPD|ICHG;
+ bdwrite(bp);
+ }
+ }
+ /*
+ * The first NDADDR blocks are direct blocks
+ */
+ if (bn < NDADDR) {
i = bn;
- nb = ip->i_un.i_addr[i];
- if(nb == 0) {
- if(rwflg==B_READ || (bp = alloc(dev))==NULL)
- return((daddr_t)-1);
- nb = dbtofsb(bp->b_blkno);
+ nb = ip->i_db[i];
+ if (rwflg == B_READ) {
+ if (nb == 0)
+ return ((daddr_t)-1);
+ goto gotit;
+ }
+ if (nb == 0 || ip->i_size < (i + 1) * fs->fs_bsize) {
+ if (nb != 0) {
+ /* consider need to reallocate a frag */
+ osize = fragroundup(fs, blkoff(fs, ip->i_size));
+ nsize = fragroundup(fs, size);
+ if (nsize <= osize)
+ goto gotit;
+ bp = realloccg(ip, nb, i == 0 ?
+ 0 : ip->i_db[i - 1] + fs->fs_frag,
+ osize, nsize);
+ } else {
+ if (ip->i_size < (i + 1) * fs->fs_bsize)
+ nsize = fragroundup(fs, size);
+ else
+ nsize = fs->fs_bsize;
+ bp = alloc(ip, i > 0 ?
+ ip->i_db[i - 1] + fs->fs_frag : 0,
+ nsize);
+ }
+ if (bp == NULL)
+ return ((daddr_t)-1);
+ nb = dbtofsb(fs, bp->b_blkno);
if ((ip->i_mode&IFMT) == IFDIR)
/*
* Write directory blocks synchronously
bwrite(bp);
else
bdwrite(bp);
- ip->i_un.i_addr[i] = nb;
+ ip->i_db[i] = nb;
ip->i_flag |= IUPD|ICHG;
}
- if(i < NADDR-4)
- rablock = ip->i_un.i_addr[i+1];
- return(nb);
+gotit:
+ if (i < NDADDR - 1)
+ rablock = ip->i_db[i+1];
+ return (nb);
}
/*
- * addresses NADDR-3, NADDR-2, and NADDR-1
- * have single, double, triple indirect blocks.
- * the first step is to determine
- * how many levels of indirection.
+ * Determine how many levels of indirection.
*/
- sh = 0;
- nb = 1;
- bn -= NADDR-3;
- for(j=3; j>0; j--) {
- sh += NSHIFT;
- nb <<= NSHIFT;
- if(bn < nb)
+ sh = 1;
+ bn -= NDADDR;
+ for (j = NIADDR; j>0; j--) {
+ sh *= NINDIR(fs);
+ if (bn < sh)
break;
- bn -= nb;
+ bn -= sh;
}
- if(j == 0) {
+ if (j == 0) {
u.u_error = EFBIG;
- return((daddr_t)0);
+ return ((daddr_t)0);
}
/*
* fetch the first indirect block
*/
- nb = ip->i_un.i_addr[NADDR-j];
- if(nb == 0) {
- if(rwflg==B_READ || (bp = alloc(dev))==NULL)
- return((daddr_t)-1);
- nb = dbtofsb(bp->b_blkno);
+ nb = ip->i_ib[NIADDR - j];
+ if (nb == 0) {
+ if (rwflg==B_READ ||
+ (bp = alloc(ip, (daddr_t)0, fs->fs_bsize)) == NULL)
+ return ((daddr_t)-1);
+ nb = dbtofsb(fs, bp->b_blkno);
/*
* Write synchronously so that indirect blocks
* never point at garbage.
*/
bwrite(bp);
- ip->i_un.i_addr[NADDR-j] = nb;
+ ip->i_ib[NIADDR - j] = nb;
ip->i_flag |= IUPD|ICHG;
}
/*
* fetch through the indirect blocks
*/
- for(; j<=3; j++) {
- bp = bread(dev, nb);
- if(bp->b_flags & B_ERROR) {
+ for (; j <= NIADDR; j++) {
+ bp = bread(ip->i_dev, fsbtodb(fs, nb), fs->fs_bsize);
+ if (bp->b_flags & B_ERROR) {
brelse(bp);
- return((daddr_t)0);
+ return ((daddr_t)0);
}
bap = bp->b_un.b_daddr;
- sh -= NSHIFT;
- i = (bn>>sh) & NMASK;
+ sh /= NINDIR(fs);
+ i = (bn / sh) % NINDIR(fs);
nb = bap[i];
- if(nb == 0) {
- if(rwflg==B_READ || (nbp = alloc(dev))==NULL) {
+ if (nb == 0) {
+ if (rwflg==B_READ) {
+ brelse(bp);
+ return ((daddr_t)-1);
+ }
+ if (i % (fs->fs_fsize / sizeof(daddr_t)) == 0 ||
+ bap[i - 1] == 0)
+ pref = blkpref(ip->i_fs);
+ else
+ pref = bap[i - 1] + fs->fs_frag;
+ nbp = alloc(ip, pref, fs->fs_bsize);
+ if (nbp == NULL) {
brelse(bp);
- return((daddr_t)-1);
+ return ((daddr_t)-1);
}
- nb = dbtofsb(nbp->b_blkno);
- if (j < 3 || (ip->i_mode&IFMT) == IFDIR)
+ nb = dbtofsb(fs, nbp->b_blkno);
+ if (j < NIADDR || (ip->i_mode&IFMT) == IFDIR)
/*
* Write synchronously so indirect blocks
* never point at garbage and blocks
/*
* calculate read-ahead.
*/
- if(i < NINDIR-1)
+ if (i < NINDIR(fs) - 1)
rablock = bap[i+1];
- return(nb);
+ return (nb);
}
/*
{
register id;
- if((id = u.u_segflg) == 1)
+ if ((id = u.u_segflg) == 1)
*u.u_base = c;
else
- if(id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) {
+ if (id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) {
u.u_error = EFAULT;
- return(-1);
+ return (-1);
}
u.u_count--;
u.u_offset++;
u.u_base++;
- return(u.u_count == 0? -1: 0);
+ return (u.u_count == 0? -1: 0);
}
#include "ct.h"
{
register c, id;
- if(u.u_count == 0)
- return(-1);
- if((id = u.u_segflg) == 1)
+ if (u.u_count == 0)
+ return (-1);
+ if ((id = u.u_segflg) == 1)
c = *u.u_base;
else
- if((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) {
+ if ((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) {
u.u_error = EFAULT;
- return(-1);
+ return (-1);
}
u.u_count--;
u.u_offset++;
u.u_base++;
- return(c&0377);
+ return (c&0377);
}
#endif
return (a > b ? a : b);
}
+unsigned
+min(a, b)
+ unsigned int a, b;
+{
+
+ return (a < b ? a : b);
+}
+
+unsigned
+max(a, b)
+ unsigned int a, b;
+{
+
+ return (a > b ? a : b);
+}
+
struct proc *
pfind(pid)
int pid;
-/* vfs_lookup.c 4.14 82/03/31 */
+/* vfs_lookup.c 4.15 82/04/19 */
+
+/* merged into kernel: @(#)nami.c 2.3 4/8/82 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/inode.h"
+#include "../h/fs.h"
#include "../h/mount.h"
#include "../h/dir.h"
#include "../h/user.h"
register char *cp;
register struct buf *bp, *nbp;
register struct direct *ep;
+ register struct fs *fs;
struct inode *pdp;
- int i, nlink;
+ enum {NONE, COMPACT, FOUND} slot;
+ int entryfree, entrysize;
+ int spccnt, size, newsize;
+ int loc, prevoff, curoff;
+ int i, nlink, bsize;
+ unsigned pathlen;
+ daddr_t lbn, bn;
dev_t d;
- off_t eo;
/*
* allocate name buffer; copy name
*/
- nbp = geteblk();
+ nbp = geteblk(MAXPATHLEN);
nlink = 0;
- for (i=0, cp = nbp->b_un.b_addr; *cp = (*func)(); i++) {
- if ((*cp&0377) == ('/'|0200)) {
+ for (i = 0, cp = nbp->b_un.b_addr; *cp = (*func)(); i++) {
+ if ((*cp & 0377) == ('/'|0200)) {
u.u_error = EPERM;
break;
}
#ifdef notdef
- if (*cp++&0200 && flag==1 || cp >= nbp->b_un.b_addr+BSIZE) {
+ if (*cp++ & 0200 && flag == 1 ||
+ cp >= nbp->b_un.b_addr + MAXPATHLEN) {
#else
cp++;
- if (cp >= nbp->b_un.b_addr+BSIZE) {
+ if (cp >= nbp->b_un.b_addr + MAXPATHLEN) {
#endif
u.u_error = ENOENT;
break;
}
}
if (u.u_error) {
- dp = NULL;
- goto out1;
+ brelse(nbp);
+ return (NULL);
}
cp = nbp->b_un.b_addr;
/*
}
ilock(dp);
dp->i_count++;
-
+ fs = dp->i_fs;
+ newsize = 0;
+dirloop:
/*
* dp must be a directory and
* must have X permission.
* cp is a path name relative to that directory.
*/
-
-dirloop:
if ((dp->i_mode&IFMT) != IFDIR)
u.u_error = ENOTDIR;
(void) access(dp, IEXEC);
dirloop2:
- for (i=0; *cp!='\0' && *cp!='/'; i++) {
+ for (i = 0; *cp != '\0' && *cp != '/'; cp++) {
#ifdef notdef
- if (i >= DIRSIZ) {
+ if (i >= MAXNAMLEN) {
u.u_error = ENOENT;
break;
}
- u.u_dbuf[i] = *cp++;
+ u.u_dent.d_name[i] = *cp;
#else
- if (i < DIRSIZ)
- u.u_dbuf[i] = *cp;
- cp++;
+ if (i < MAXNAMLEN) {
+ u.u_dent.d_name[i] = *cp;
+ i++;
+ }
#endif
}
- if (u.u_error)
- goto out;
+ if (u.u_error) {
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
+ }
+ u.u_dent.d_namlen = i;
+ u.u_dent.d_name[i] = '\0';
+ newsize = DIRSIZ(&u.u_dent);
u.u_pdir = dp;
- while (i < DIRSIZ)
- u.u_dbuf[i++] = '\0';
- if (u.u_dbuf[0] == '\0') { /* null name, e.g. "/" or "" */
- if (flag) {
+ if (u.u_dent.d_name[0] == '\0') { /* null name, e.g. "/" or "" */
+ if (flag != 0) {
u.u_error = ENOENT;
- goto out;
+ iput(dp);
+ dp = NULL;
}
- goto out1;
+ u.u_offset = 0;
+ u.u_count = newsize;
+ brelse(nbp);
+ return (dp);
}
+ /*
+ * set up to search a directory
+ */
+ if (flag == 1)
+ slot = NONE;
+ else
+ slot = FOUND;
+ u.u_offset = 0;
u.u_segflg = 1;
- eo = -1;
bp = NULL;
-
- for (u.u_offset=0; u.u_offset < dp->i_size;
- u.u_offset += sizeof(struct direct), ep++) {
+ spccnt = 0;
+ loc = 0;
+ while (u.u_offset < dp->i_size) {
+ /*
+ * check to see if enough space has been accumulated to make
+ * an entry by compaction. Reset the free space counter each
+ * time a directory block is crossed.
+ */
+ if (slot == NONE) {
+ if (spccnt >= newsize) {
+ slot = COMPACT;
+ entrysize = u.u_offset - entryfree;
+ } else if (loc % DIRBLKSIZ == 0) {
+ entryfree = NULL;
+ spccnt = 0;
+ }
+ }
/*
* If offset is on a block boundary,
* read the next directory block.
* Release previous if it exists.
*/
- if ((u.u_offset&BMASK) == 0) {
+ if (blkoff(fs, u.u_offset) == 0) {
if (bp != NULL)
brelse(bp);
- bp = bread(dp->i_dev,
- bmap(dp,(daddr_t)(u.u_offset>>BSHIFT), B_READ));
+ lbn = (daddr_t)lblkno(fs, u.u_offset);
+ bsize = blksize(fs, dp, lbn);
+ if ((bn = bmap(dp, lbn, B_READ)) < 0) {
+ printf("hole in dir: %s i = %d\n",
+ fs->fs_fsmnt, dp->i_number);
+ if (fs->fs_ronly != 0 ||
+ (bn = bmap(dp, lbn, B_WRITE, bsize)) < 0) {
+ u.u_offset += bsize;
+ bp = NULL;
+ continue;
+ }
+ }
+ bp = bread(dp->i_dev, fsbtodb(fs, bn), bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
- goto out;
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
+ }
+ loc = 0;
+ } else {
+ loc += ep->d_reclen;
+ }
+ /*
+ * calculate the next directory entry and run
+ * some rudimentary bounds checks to make sure
+ * that it is reasonable. If the check fails
+ * resync at the beginning of the next directory
+ * block.
+ */
+ ep = (struct direct *)(bp->b_un.b_addr + loc);
+ i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
+ if (ep->d_reclen <= 0 || ep->d_reclen > i) {
+ loc += i;
+ u.u_offset += i;
+ continue;
+ }
+ /*
+ * If an appropriate sized hole has not yet been found,
+ * check to see if one is available. Also accumulate space
+ * in the current block so that we can determine if
+ * compaction is viable.
+ */
+ if (slot != FOUND) {
+ size = ep->d_reclen;
+ if (ep->d_ino != 0)
+ size -= DIRSIZ(ep);
+ if (size > 0) {
+ if (size >= newsize) {
+ slot = FOUND;
+ entryfree = u.u_offset;
+ entrysize = DIRSIZ(ep) + newsize;
+ }
+ if (entryfree == NULL)
+ entryfree = u.u_offset;
+ spccnt += size;
}
- ep = (struct direct *)bp->b_un.b_addr;
}
/*
- * Note first empty directory slot
- * in eo for possible creat.
* String compare the directory entry
* and the current component.
+ * If they do not match, continue to the next entry.
*/
- if (ep->d_ino == 0) {
- if (eo < 0)
- eo = u.u_offset;
+ prevoff = curoff;
+ curoff = u.u_offset;
+ u.u_offset += ep->d_reclen;
+ if (ep->d_ino == 0)
continue;
- }
- if (strncmp(u.u_dbuf, ep->d_name, DIRSIZ) != 0)
+ if (ep->d_namlen != u.u_dent.d_namlen)
+ continue;
+ if (bcmp(u.u_dent.d_name, ep->d_name, ep->d_namlen))
continue;
/*
* Here a component matched in a directory.
* If there is more pathname, go back to
* dirloop, otherwise return.
*/
- bcopy((caddr_t)ep, (caddr_t)&u.u_dent, sizeof(struct direct));
+ bcopy((caddr_t)ep, (caddr_t)&u.u_dent, DIRSIZ(ep));
brelse(bp);
- if (flag==2 && *cp=='\0') {
- if (access(dp, IWRITE))
- goto out;
- /* should fix unlink */
- u.u_offset += sizeof(struct direct);
- goto out1;
+ if (flag == 2 && *cp == '\0') {
+ brelse(nbp);
+ if (access(dp, IWRITE)) {
+ iput(dp);
+ return (NULL);
+ }
+ if (curoff % DIRBLKSIZ == 0) {
+ u.u_offset = curoff;
+ u.u_count = 0;
+ return (dp);
+ }
+ u.u_offset = prevoff;
+ u.u_count = DIRSIZ((struct direct *)
+ (bp->b_un.b_addr + blkoff(fs, prevoff)));
+ return (dp);
}
/*
* Special handling for ".."
*/
- if (u.u_dent.d_name[0]=='.' && u.u_dent.d_name[1]=='.' &&
- u.u_dent.d_name[2]=='\0') {
+ if (u.u_dent.d_name[0] == '.' && u.u_dent.d_name[1] == '.' &&
+ u.u_dent.d_name[2] == '\0') {
if (dp == u.u_rdir)
u.u_dent.d_ino = dp->i_number;
- else if (u.u_dent.d_ino==ROOTINO &&
+ else if (u.u_dent.d_ino == ROOTINO &&
dp->i_number == ROOTINO) {
- for(i=1; i<NMOUNT; i++)
+ for (i = 1; i < NMOUNT; i++)
if (mount[i].m_bufp != NULL &&
mount[i].m_dev == dp->i_dev) {
iput(dp);
dp = mount[i].m_inodp;
ilock(dp);
dp->i_count++;
+ fs = dp->i_fs;
cp -= 2; /* back over .. */
goto dirloop2;
}
d = dp->i_dev;
irele(dp);
pdp = dp;
- dp = iget(d, u.u_dent.d_ino);
+ dp = iget(d, fs, u.u_dent.d_ino);
if (dp == NULL) {
iput(pdp);
- goto out1;
+ brelse(nbp);
+ return (NULL);
}
+ fs = dp->i_fs;
/*
* Check for symbolic link
*/
- if ((dp->i_mode&IFMT)==IFLNK && (follow || *cp=='/')) {
- char *ocp;
-
- ocp = cp;
- while (*cp++)
- ;
- if (dp->i_size + (cp-ocp) >= BSIZE-1 || ++nlink>8) {
+ if ((dp->i_mode & IFMT) == IFLNK && (follow || *cp == '/')) {
+ pathlen = strlen(cp) + 1;
+ if (dp->i_size + pathlen >= MAXPATHLEN - 1 ||
+ ++nlink > MAXSYMLINKS) {
u.u_error = ELOOP;
iput(pdp);
- goto out;
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
}
- bcopy(ocp, nbp->b_un.b_addr+dp->i_size,
- (unsigned)(cp-ocp));
- bp = bread(dp->i_dev, bmap(dp, (daddr_t)0, B_READ));
+ bcopy(cp, nbp->b_un.b_addr + dp->i_size, pathlen);
+ bn = bmap(dp, (daddr_t)0, B_READ);
+ if (bn < 0) {
+ printf("hole in symlink: %s i = %d\n",
+ fs->fs_fsmnt, dp->i_number);
+ iput(pdp);
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
+ }
+ bp = bread(dp->i_dev, fsbtodb(fs, bn),
+ (int)blksize(fs, dp, (daddr_t)0));
if (bp->b_flags & B_ERROR) {
brelse(bp);
iput(pdp);
- goto out;
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
}
bcopy(bp->b_un.b_addr, nbp->b_un.b_addr,
(unsigned)dp->i_size);
dp = pdp;
ilock(dp);
}
+ fs = dp->i_fs;
goto dirloop;
}
iput(pdp);
cp++;
goto dirloop;
}
- goto out1;
+ /*
+ * End of path, so return name matched.
+ */
+ u.u_offset -= ep->d_reclen;
+ u.u_count = newsize;
+ brelse(nbp);
+ return (dp);
}
/*
* Search failed.
+ * Report what is appropriate as per flag.
*/
if (bp != NULL)
brelse(bp);
- if (flag==1 && *cp=='\0' && dp->i_nlink) {
- if (access(dp, IWRITE))
- goto out;
- if (eo>=0)
- u.u_offset = eo;
+ if (flag == 1 && *cp == '\0' && dp->i_nlink != 0) {
+ brelse(nbp);
+ if (access(dp, IWRITE)) {
+ iput(dp);
+ return (NULL);
+ }
+ if (slot == NONE) {
+ u.u_count = 0;
+ } else {
+ u.u_offset = entryfree;
+ u.u_count = entrysize;
+ }
dp->i_flag |= IUPD|ICHG;
- dp = NULL;
- goto out1;
+ return (NULL);
}
u.u_error = ENOENT;
-out:
iput(dp);
- dp = NULL;
-out1:
brelse(nbp);
- return (dp);
+ return (NULL);
}
/*
}
#ifndef vax
-strncmp(s1, s2, len)
+bcmp(s1, s2, len)
register char *s1, *s2;
- register len;
+ register int len;
{
- do {
- if (*s1 != *s2++)
+ while (--len)
+ if (*s1++ != *s2++)
return (1);
- if (*s1++ == '\0')
- return (0);
- } while (--len);
return (0);
}
+
+strlen(s1)
+ register char *s1;
+{
+ register int len;
+
+ for (len = 0; *s1++ != '\0'; len++)
+ /* void */;
+ return (len);
+}
#endif
-/* vfs_syscalls.c 4.22 82/04/01 */
+/* vfs_syscalls.c 4.23 82/04/19 */
+/* merged into kernel: @(#)sys3.c 2.2 4/8/82 */
+
+#ifdef SIMFS
+#include "../h/sysrenam.h"
+#endif
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
-#include "../h/reg.h"
#include "../h/file.h"
+#include "../h/stat.h"
#include "../h/inode.h"
-#include "../h/ino.h"
-#include "../h/pte.h"
-#include "../h/vm.h"
+#include "../h/fs.h"
#include "../h/buf.h"
-#include "../h/mtpr.h"
#include "../h/proc.h"
#include "../h/inline.h"
-#include "../h/conf.h"
-#include "../h/socket.h"
-#include "../h/socketvar.h"
-#include "../h/stat.h"
chdir()
{
* Want to be able to use this to make badblock
* inodes, so don't truncate the dev number.
*/
- ip->i_un.i_rdev = uap->dev;
+ ip->i_rdev = uap->dev;
ip->i_flag |= IACC|IUPD|ICHG;
}
struct a {
char *fname;
};
+ struct fs *fs;
+ struct buf *bp;
+ int lbn, bn, base;
pp = namei(uchar, 2, 0);
if(pp == NULL)
ip = pp;
ip->i_count++;
} else
- ip = iget(pp->i_dev, u.u_dent.d_ino);
+ ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
if(ip == NULL)
goto out1;
if((ip->i_mode&IFMT)==IFDIR && !suser())
goto out;
}
*/
- u.u_offset -= sizeof(struct direct);
- u.u_base = (caddr_t)&u.u_dent;
- u.u_count = sizeof(struct direct);
- u.u_dent.d_ino = 0;
- writei(pp);
+ if (u.u_count == 0) {
+ /*
+ * first entry in block, so set d_ino to zero.
+ */
+ u.u_base = (caddr_t)&u.u_dent;
+ u.u_count = DIRSIZ(&u.u_dent);
+ u.u_dent.d_ino = 0;
+ writei(pp);
+ } else {
+ /*
+ * updating preceeding entry to skip over current entry.
+ */
+ fs = pp->i_fs;
+ lbn = lblkno(fs, u.u_offset);
+ base = blkoff(fs, u.u_offset);
+ bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count));
+ bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn));
+ if (bp->b_flags & B_ERROR) {
+ brelse(bp);
+ goto out;
+ }
+ ((struct direct *)(bp->b_un.b_addr + base))->d_reclen +=
+ u.u_dent.d_reclen;
+ bwrite(bp);
+ pp->i_flag |= IUPD|ICHG;
+ }
ip->i_nlink--;
ip->i_flag |= ICHG;
}
/*
- * Stat system call; this follows links.
+ * Stat system call. This version follows links.
*/
stat()
{
}
/*
- * Lstat system call; like stat but doesn't follow links.
+ * Lstat system call. This version does not follow links.
*/
lstat()
{
register struct inode *ip;
struct stat *ub;
{
- register struct dinode *dp;
- register struct buf *bp;
struct stat ds;
IUPDAT(ip, &time, &time, 0);
ds.st_nlink = ip->i_nlink;
ds.st_uid = ip->i_uid;
ds.st_gid = ip->i_gid;
- ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+ ds.st_rdev = (dev_t)ip->i_rdev;
ds.st_size = ip->i_size;
- /*
- * next the dates in the disk
- */
- bp = bread(ip->i_dev, itod(ip->i_number));
- dp = bp->b_un.b_dino;
- dp += itoo(ip->i_number);
- ds.st_atime = dp->di_atime;
- ds.st_mtime = dp->di_mtime;
- ds.st_ctime = dp->di_ctime;
- brelse(bp);
+ ds.st_atime = ip->i_atime;
+ ds.st_mtime = ip->i_mtime;
+ ds.st_ctime = ip->i_ctime;
if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
u.u_error = EFAULT;
}
-/* vfs_vnops.c 4.22 82/02/27 */
+/* vfs_vnops.c 4.23 82/04/19 */
+
+/* merged into kernel: @(#)fio.c 2.2 4/8/82 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
-#include "../h/filsys.h"
+#include "../h/fs.h"
#include "../h/file.h"
#include "../h/conf.h"
#include "../h/inode.h"
return;
}
ip = fp->f_inode;
- dev = (dev_t)ip->i_un.i_rdev;
+ dev = (dev_t)ip->i_rdev;
mode = ip->i_mode & IFMT;
ilock(ip);
iput(ip);
if (fp->f_flag & FSOCKET)
continue;
if (fp->f_count && (ip = fp->f_inode) &&
- ip->i_un.i_rdev == dev && (ip->i_mode&IFMT) == mode)
+ ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
return;
}
if (mode == IFBLK) {
dev_t dev;
register unsigned int maj;
- dev = (dev_t)ip->i_un.i_rdev;
+ dev = (dev_t)ip->i_rdev;
maj = major(dev);
switch (ip->i_mode&IFMT) {
m = mode;
if (m == IWRITE) {
- if (getfs(ip->i_dev)->s_ronly != 0) {
+ if (ip->i_fs->fs_ronly != 0) {
u.u_error = EROFS;
return (1);
}
-/* alloc.c 4.1 82/03/25 */
-
-/* merged into kernel: @(#)ffs_alloc.c 2.3 %G% */
-
-/* last monet version: alloc.c 4.8 81/03/08 */
+/* ffs_alloc.c 2.4 82/04/19 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/inode.h"
-#include "../h/ndir.h"
+#include "../h/dir.h"
#include "../h/user.h"
extern u_long hashalloc();
else
cg = dtog(fs, bpref);
bno = (daddr_t)hashalloc(ip, cg, (long)bpref, size, alloccg);
- if (bno == 0)
+ if (bno <= 0)
goto nospace;
bp = getblk(ip->i_dev, fsbtodb(fs, bno), size);
clrbuf(bp);
daddr_t bno;
register struct fs *fs;
register struct buf *bp, *obp;
- caddr_t cp;
int cg;
fs = ip->i_fs;
brelse(bp);
return (NULL);
}
- bp->b_bcount = nsize;
+ brealloc(bp, nsize);
blkclr(bp->b_un.b_addr + osize, nsize - osize);
return (bp);
}
if (bpref >= fs->fs_size)
bpref = 0;
bno = (daddr_t)hashalloc(ip, cg, (long)bpref, nsize, alloccg);
- if (bno != 0) {
- /*
- * make a new copy
- */
+ if (bno > 0) {
obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize);
if (obp->b_flags & B_ERROR) {
brelse(obp);
return (NULL);
}
bp = getblk(ip->i_dev, fsbtodb(fs, bno), nsize);
- cp = bp->b_un.b_addr;
- bp->b_un.b_addr = obp->b_un.b_addr;
- obp->b_un.b_addr = cp;
- obp->b_flags |= B_INVAL;
+ bcopy(obp->b_un.b_addr, bp->b_un.b_addr, osize);
+ blkclr(bp->b_un.b_addr + osize, nsize - osize);
brelse(obp);
fre(ip, bprev, (off_t)osize);
- blkclr(bp->b_un.b_addr + osize, nsize - osize);
return (bp);
}
nospace:
return (bno);
}
bno = mapsearch(fs, cgp, bpref, allocsiz);
- if (bno == -1)
+ if (bno < 0)
return (NULL);
for (i = 0; i < frags; i++)
clrbit(cgp->cg_free, bno + i);
* available one in this cylinder group.
*/
bno = mapsearch(fs, cgp, bpref, fs->fs_frag);
- if (bno == -1)
+ if (bno < 0)
return (NULL);
cgp->cg_rotor = bno;
gotit:
if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0)
panic("free: bad size");
cg = dtog(fs, bno);
- if (badblock(fs, bno))
+ if (badblock(fs, bno)) {
+ printf("bad block %d, ino %d\n", bno, ip->i_number);
return;
+ }
bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize);
cgp = bp->b_un.b_cg;
if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) {
}
bno = dtogd(fs, bno);
if (size == fs->fs_bsize) {
- if (isblock(fs, cgp->cg_free, bno/fs->fs_frag))
+ if (isblock(fs, cgp->cg_free, bno/fs->fs_frag)) {
+ printf("free block %d, fs %s\n", bno, fs->fs_fsmnt);
panic("free: freeing free block");
+ }
setblock(fs, cgp->cg_free, bno/fs->fs_frag);
cgp->cg_cs.cs_nbfree++;
fs->fs_cstotal.cs_nbfree++;
{
if ((unsigned)bn >= fs->fs_size) {
+ printf("bad block %d, ", bn);
fserr(fs, "bad block");
return (1);
}
-/* ffs_inode.c 4.9 82/02/27 */
+/* ffs_inode.c 4.10 82/04/19 */
+
+/* merged into kernel: @(#)iget.c 2.2 4/8/82 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/inode.h"
-#include "../h/ino.h"
-#include "../h/filsys.h"
+#include "../h/fs.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/inline.h"
inohash[i] = -1;
}
-/*
- * Find an inode if it is incore.
- * This is the equivalent, for inodes,
- * of ``incore'' in bio.c or ``pfind'' in subr.c.
- */
-struct inode *
-ifind(dev, ino)
- dev_t dev;
- ino_t ino;
-{
- register struct inode *ip;
-
- for (ip = &inode[inohash[INOHASH(dev,ino)]]; ip != &inode[-1];
- ip = &inode[ip->i_hlink])
- if (ino==ip->i_number && dev==ip->i_dev)
- return (ip);
- return ((struct inode *)0);
-}
-
/*
* Look up an inode by device,inumber.
* If it is in core (in the inode structure),
* "cannot happen"
*/
struct inode *
-iget(dev, ino)
+iget(dev, fs, ino)
dev_t dev;
+ register struct fs *fs;
ino_t ino;
{
register struct inode *ip;
register int slot;
loop:
+ if (getfs(dev) != fs)
+ panic("iget: bad fs");
slot = INOHASH(dev, ino);
ip = &inode[inohash[slot]];
while (ip != &inode[-1]) {
goto loop;
}
if ((ip->i_flag&IMOUNT) != 0) {
- for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+ for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
if (mp->m_inodp == ip) {
dev = mp->m_dev;
+ fs = mp->m_bufp->b_un.b_fs;
ino = ROOTINO;
goto loop;
}
ip->i_hlink = inohash[slot];
inohash[slot] = ip - inode;
ip->i_dev = dev;
+ ip->i_fs = fs;
ip->i_number = ino;
ip->i_flag = ILOCK;
ip->i_count++;
- ip->i_un.i_lastr = 0;
- bp = bread(dev, itod(ino));
+ ip->i_lastr = 0;
+ bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize);
/*
* Check I/O errors
*/
return(NULL);
}
dp = bp->b_un.b_dino;
- dp += itoo(ino);
- iexpand(ip, dp);
+ dp += itoo(fs, ino);
+ ip->i_ic = dp->di_ic;
brelse(bp);
- return(ip);
-}
-
-iexpand(ip, dp)
- register struct inode *ip;
- register struct dinode *dp;
-{
- register char *p1, *p2;
- register int i;
-
- ip->i_mode = dp->di_mode;
- ip->i_nlink = dp->di_nlink;
- ip->i_uid = dp->di_uid;
- ip->i_gid = dp->di_gid;
- ip->i_size = dp->di_size;
- p1 = (char *)ip->i_un.i_addr;
- p2 = (char *)dp->di_addr;
- for(i=0; i<NADDR; i++) {
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = 0;
- }
+ return (ip);
}
/*
{
register int i, x;
register struct inode *jp;
+ int mode;
if (ip->i_count == 1) {
ip->i_flag |= ILOCK;
if (ip->i_nlink <= 0) {
itrunc(ip);
+ mode = ip->i_mode;
ip->i_mode = 0;
ip->i_flag |= IUPD|ICHG;
- ifree(ip->i_dev, ip->i_number);
+ ifree(ip, ip->i_number, mode);
}
IUPDAT(ip, &time, &time, 0);
irele(ip);
{
register struct buf *bp;
struct dinode *dp;
- register char *p1, *p2;
- register int i;
+ register struct fs *fp;
- if ((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
- if (getfs(ip->i_dev)->s_ronly)
+ fp = ip->i_fs;
+ if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
+ if (fp->fs_ronly)
return;
- bp = bread(ip->i_dev, itod(ip->i_number));
+ bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
+ fp->fs_bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
return;
}
- dp = bp->b_un.b_dino;
- dp += itoo(ip->i_number);
- dp->di_mode = ip->i_mode;
- dp->di_nlink = ip->i_nlink;
- dp->di_uid = ip->i_uid;
- dp->di_gid = ip->i_gid;
- dp->di_size = ip->i_size;
- p1 = (char *)dp->di_addr;
- p2 = (char *)ip->i_un.i_addr;
- for(i=0; i<NADDR; i++) {
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = *p2++;
- if (*p2++ != 0)
- printf("iaddress > 2^24\n");
- }
if (ip->i_flag&IACC)
- dp->di_atime = *ta;
+ ip->i_atime = *ta;
if (ip->i_flag&IUPD)
- dp->di_mtime = *tm;
+ ip->i_mtime = *tm;
if (ip->i_flag&ICHG)
- dp->di_ctime = time;
+ ip->i_ctime = time;
ip->i_flag &= ~(IUPD|IACC|ICHG);
+ dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
+ dp->di_ic = ip->i_ic;
if (waitfor)
bwrite(bp);
else
dev_t dev;
daddr_t bn;
struct inode itmp;
+ register struct fs *fs;
i = ip->i_mode & IFMT;
- if (i!=IFREG && i!=IFDIR && i!=IFLNK)
+ if (i != IFREG && i != IFDIR && i != IFLNK)
return;
-
/*
* Clean inode on disk before freeing blocks
* to insure no duplicates if system crashes.
*/
itmp = *ip;
itmp.i_size = 0;
- for (i = 0; i < NADDR; i++)
- itmp.i_un.i_addr[i] = 0;
+ for (i = 0; i < NDADDR; i++)
+ itmp.i_db[i] = 0;
+ for (i = 0; i < NIADDR; i++)
+ itmp.i_ib[i] = 0;
itmp.i_flag |= ICHG|IUPD;
iupdat(&itmp, &time, &time, 1);
ip->i_flag &= ~(IUPD|IACC|ICHG);
* crashes, they will be harmless MISSING blocks.
*/
dev = ip->i_dev;
- for(i=NADDR-1; i>=0; i--) {
- bn = ip->i_un.i_addr[i];
+ fs = ip->i_fs;
+ /*
+ * release double indirect block first
+ */
+ bn = ip->i_ib[NIADDR-1];
+ if (bn != (daddr_t)0) {
+ ip->i_ib[NIADDR - 1] = (daddr_t)0;
+ tloop(ip, bn, 1);
+ }
+ /*
+ * release single indirect blocks second
+ */
+ for (i = NIADDR - 2; i >= 0; i--) {
+ bn = ip->i_ib[i];
+ if (bn != (daddr_t)0) {
+ ip->i_ib[i] = (daddr_t)0;
+ tloop(ip, bn, 0);
+ }
+ }
+ /*
+ * finally release direct blocks
+ */
+ for (i = NDADDR - 1; i>=0; i--) {
+ bn = ip->i_db[i];
if (bn == (daddr_t)0)
continue;
- ip->i_un.i_addr[i] = (daddr_t)0;
- switch(i) {
-
- default:
- free(dev, bn);
- break;
-
- case NADDR-3:
- tloop(dev, bn, 0, 0);
- break;
-
- case NADDR-2:
- tloop(dev, bn, 1, 0);
- break;
-
- case NADDR-1:
- tloop(dev, bn, 1, 1);
- }
+ ip->i_db[i] = (daddr_t)0;
+ fre(ip, bn, (off_t)blksize(fs, ip, i));
}
ip->i_size = 0;
/*
*/
}
-tloop(dev, bn, f1, f2)
-dev_t dev;
-daddr_t bn;
+tloop(ip, bn, indflg)
+ register struct inode *ip;
+ daddr_t bn;
+ int indflg;
{
register i;
register struct buf *bp;
register daddr_t *bap;
+ register struct fs *fs;
daddr_t nb;
bp = NULL;
- for(i=NINDIR-1; i>=0; i--) {
+ fs = ip->i_fs;
+ for (i = NINDIR(fs) - 1; i >= 0; i--) {
if (bp == NULL) {
- bp = bread(dev, bn);
+ bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
return;
nb = bap[i];
if (nb == (daddr_t)0)
continue;
- if (f1) {
- brelse(bp);
- bp = NULL;
- tloop(dev, nb, f2, 0);
- } else
- free(dev, nb);
+ if (indflg)
+ tloop(ip, nb, 0);
+ else
+ fre(ip, nb, fs->fs_bsize);
}
if (bp != NULL)
brelse(bp);
- free(dev, bn);
+ fre(ip, bn, fs->fs_bsize);
}
/*
*/
struct inode *
maknode(mode)
+ int mode;
{
register struct inode *ip;
+ ino_t ipref;
- ip = ialloc(u.u_pdir->i_dev);
+ if ((mode & IFMT) == IFDIR)
+ ipref = dirpref(u.u_pdir->i_fs);
+ else
+ ipref = u.u_pdir->i_number;
+ ip = ialloc(u.u_pdir, ipref, mode);
if (ip == NULL) {
iput(u.u_pdir);
return(NULL);
}
ip->i_flag |= IACC|IUPD|ICHG;
- if ((mode&IFMT) == 0)
+ if ((mode & IFMT) == 0)
mode |= IFREG;
ip->i_mode = mode & ~u.u_cmask;
ip->i_nlink = 1;
* Make sure inode goes to disk before directory entry.
*/
iupdat(ip, &time, &time, 1);
-
wdir(ip);
+ if (u.u_error) {
+ /*
+ * write error occurred trying to update directory
+ * so must deallocate the inode
+ */
+ ip->i_nlink = 0;
+ ip->i_flag |= ICHG;
+ iput(ip);
+ return(NULL);
+ }
return(ip);
}
wdir(ip)
struct inode *ip;
{
+ register struct direct *dp, *ndp;
+ struct fs *fs;
+ struct buf *bp;
+ int lbn, bn, base;
+ int loc, dsize, spccnt, newsize;
+ char *dirbuf;
u.u_dent.d_ino = ip->i_number;
- bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
- u.u_count = sizeof(struct direct);
u.u_segflg = 1;
- u.u_base = (caddr_t)&u.u_dent;
- writei(u.u_pdir);
+ newsize = DIRSIZ(&u.u_dent);
+ /*
+ * if u.u_count == 0, a new directory block must be allocated.
+ */
+ if (u.u_count == 0) {
+ u.u_dent.d_reclen = DIRBLKSIZ;
+ u.u_count = newsize;
+ u.u_base = (caddr_t)&u.u_dent;
+ writei(u.u_pdir);
+ iput(u.u_pdir);
+ return;
+ }
+ /*
+ * must read in an existing directory block
+ * to prepare to place the new entry into it.
+ */
+ fs = u.u_pdir->i_fs;
+ lbn = lblkno(fs, u.u_offset);
+ base = blkoff(fs, u.u_offset);
+ bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
+ if (u.u_offset + u.u_count > u.u_pdir->i_size)
+ u.u_pdir->i_size = u.u_offset + u.u_count;
+ bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
+ if (bp->b_flags & B_ERROR) {
+ brelse(bp);
+ return;
+ }
+ dirbuf = bp->b_un.b_addr + base;
+ dp = (struct direct *)dirbuf;
+ dsize = DIRSIZ(dp);
+ spccnt = dp->d_reclen - dsize;
+ /*
+ * if there is insufficient room to make an entry at this point
+ * namei insures that compacting from u.u_offset for u.u_count
+ * bytes will provide the necessary space.
+ */
+ for (loc = dp->d_reclen; loc < u.u_count; ) {
+ ndp = (struct direct *)(dirbuf + loc);
+ if (dp->d_ino == 0) {
+ spccnt += dsize;
+ } else {
+ dp->d_reclen = dsize;
+ dp = (struct direct *)((char *)dp + dsize);
+ }
+ dsize = DIRSIZ(ndp);
+ spccnt += ndp->d_reclen - dsize;
+ loc += ndp->d_reclen;
+ bcopy(ndp, dp, dsize);
+ }
+ /*
+ * Update the pointer fields in the previous entry (if any),
+ * copy in the new entry, and write out the block.
+ */
+ if (dp->d_ino == 0) {
+ if (spccnt + dsize < newsize)
+ panic("wdir: compact failed");
+ u.u_dent.d_reclen = spccnt + dsize;
+ } else {
+ if (spccnt < newsize)
+ panic("wdir: compact failed");
+ u.u_dent.d_reclen = spccnt;
+ dp->d_reclen = dsize;
+ dp = (struct direct *)((char *)dp + dsize);
+ }
+ bcopy(&u.u_dent, dp, newsize);
+ bwrite(bp);
+ u.u_pdir->i_flag |= IUPD|ICHG;
iput(u.u_pdir);
}
-/* Copyright (c) 1981 Regents of the University of California */
-
-/* @(#)ffs_tables.c 2.1 %G% */
+/* ffs_tables.c 2.2 82/04/19 */
#include "../h/param.h"
-/* ffs_vnops.c 4.22 82/04/01 */
+/* ffs_vnops.c 4.23 82/04/19 */
+/* merged into kernel: @(#)sys3.c 2.2 4/8/82 */
+
+#ifdef SIMFS
+#include "../h/sysrenam.h"
+#endif
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
-#include "../h/reg.h"
#include "../h/file.h"
+#include "../h/stat.h"
#include "../h/inode.h"
-#include "../h/ino.h"
-#include "../h/pte.h"
-#include "../h/vm.h"
+#include "../h/fs.h"
#include "../h/buf.h"
-#include "../h/mtpr.h"
#include "../h/proc.h"
#include "../h/inline.h"
-#include "../h/conf.h"
-#include "../h/socket.h"
-#include "../h/socketvar.h"
-#include "../h/stat.h"
chdir()
{
* Want to be able to use this to make badblock
* inodes, so don't truncate the dev number.
*/
- ip->i_un.i_rdev = uap->dev;
+ ip->i_rdev = uap->dev;
ip->i_flag |= IACC|IUPD|ICHG;
}
struct a {
char *fname;
};
+ struct fs *fs;
+ struct buf *bp;
+ int lbn, bn, base;
pp = namei(uchar, 2, 0);
if(pp == NULL)
ip = pp;
ip->i_count++;
} else
- ip = iget(pp->i_dev, u.u_dent.d_ino);
+ ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
if(ip == NULL)
goto out1;
if((ip->i_mode&IFMT)==IFDIR && !suser())
goto out;
}
*/
- u.u_offset -= sizeof(struct direct);
- u.u_base = (caddr_t)&u.u_dent;
- u.u_count = sizeof(struct direct);
- u.u_dent.d_ino = 0;
- writei(pp);
+ if (u.u_count == 0) {
+ /*
+ * first entry in block, so set d_ino to zero.
+ */
+ u.u_base = (caddr_t)&u.u_dent;
+ u.u_count = DIRSIZ(&u.u_dent);
+ u.u_dent.d_ino = 0;
+ writei(pp);
+ } else {
+ /*
+ * updating preceeding entry to skip over current entry.
+ */
+ fs = pp->i_fs;
+ lbn = lblkno(fs, u.u_offset);
+ base = blkoff(fs, u.u_offset);
+ bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count));
+ bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn));
+ if (bp->b_flags & B_ERROR) {
+ brelse(bp);
+ goto out;
+ }
+ ((struct direct *)(bp->b_un.b_addr + base))->d_reclen +=
+ u.u_dent.d_reclen;
+ bwrite(bp);
+ pp->i_flag |= IUPD|ICHG;
+ }
ip->i_nlink--;
ip->i_flag |= ICHG;
}
/*
- * Stat system call; this follows links.
+ * Stat system call. This version follows links.
*/
stat()
{
}
/*
- * Lstat system call; like stat but doesn't follow links.
+ * Lstat system call. This version does not follow links.
*/
lstat()
{
register struct inode *ip;
struct stat *ub;
{
- register struct dinode *dp;
- register struct buf *bp;
struct stat ds;
IUPDAT(ip, &time, &time, 0);
ds.st_nlink = ip->i_nlink;
ds.st_uid = ip->i_uid;
ds.st_gid = ip->i_gid;
- ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+ ds.st_rdev = (dev_t)ip->i_rdev;
ds.st_size = ip->i_size;
- /*
- * next the dates in the disk
- */
- bp = bread(ip->i_dev, itod(ip->i_number));
- dp = bp->b_un.b_dino;
- dp += itoo(ip->i_number);
- ds.st_atime = dp->di_atime;
- ds.st_mtime = dp->di_mtime;
- ds.st_ctime = dp->di_ctime;
- brelse(bp);
+ ds.st_atime = ip->i_atime;
+ ds.st_mtime = ip->i_mtime;
+ ds.st_ctime = ip->i_ctime;
if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
u.u_error = EFAULT;
}
-/* ufs_inode.c 4.9 82/02/27 */
+/* ufs_inode.c 4.10 82/04/19 */
+
+/* merged into kernel: @(#)iget.c 2.2 4/8/82 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/inode.h"
-#include "../h/ino.h"
-#include "../h/filsys.h"
+#include "../h/fs.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/inline.h"
inohash[i] = -1;
}
-/*
- * Find an inode if it is incore.
- * This is the equivalent, for inodes,
- * of ``incore'' in bio.c or ``pfind'' in subr.c.
- */
-struct inode *
-ifind(dev, ino)
- dev_t dev;
- ino_t ino;
-{
- register struct inode *ip;
-
- for (ip = &inode[inohash[INOHASH(dev,ino)]]; ip != &inode[-1];
- ip = &inode[ip->i_hlink])
- if (ino==ip->i_number && dev==ip->i_dev)
- return (ip);
- return ((struct inode *)0);
-}
-
/*
* Look up an inode by device,inumber.
* If it is in core (in the inode structure),
* "cannot happen"
*/
struct inode *
-iget(dev, ino)
+iget(dev, fs, ino)
dev_t dev;
+ register struct fs *fs;
ino_t ino;
{
register struct inode *ip;
register int slot;
loop:
+ if (getfs(dev) != fs)
+ panic("iget: bad fs");
slot = INOHASH(dev, ino);
ip = &inode[inohash[slot]];
while (ip != &inode[-1]) {
goto loop;
}
if ((ip->i_flag&IMOUNT) != 0) {
- for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+ for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
if (mp->m_inodp == ip) {
dev = mp->m_dev;
+ fs = mp->m_bufp->b_un.b_fs;
ino = ROOTINO;
goto loop;
}
ip->i_hlink = inohash[slot];
inohash[slot] = ip - inode;
ip->i_dev = dev;
+ ip->i_fs = fs;
ip->i_number = ino;
ip->i_flag = ILOCK;
ip->i_count++;
- ip->i_un.i_lastr = 0;
- bp = bread(dev, itod(ino));
+ ip->i_lastr = 0;
+ bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize);
/*
* Check I/O errors
*/
return(NULL);
}
dp = bp->b_un.b_dino;
- dp += itoo(ino);
- iexpand(ip, dp);
+ dp += itoo(fs, ino);
+ ip->i_ic = dp->di_ic;
brelse(bp);
- return(ip);
-}
-
-iexpand(ip, dp)
- register struct inode *ip;
- register struct dinode *dp;
-{
- register char *p1, *p2;
- register int i;
-
- ip->i_mode = dp->di_mode;
- ip->i_nlink = dp->di_nlink;
- ip->i_uid = dp->di_uid;
- ip->i_gid = dp->di_gid;
- ip->i_size = dp->di_size;
- p1 = (char *)ip->i_un.i_addr;
- p2 = (char *)dp->di_addr;
- for(i=0; i<NADDR; i++) {
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = 0;
- }
+ return (ip);
}
/*
{
register int i, x;
register struct inode *jp;
+ int mode;
if (ip->i_count == 1) {
ip->i_flag |= ILOCK;
if (ip->i_nlink <= 0) {
itrunc(ip);
+ mode = ip->i_mode;
ip->i_mode = 0;
ip->i_flag |= IUPD|ICHG;
- ifree(ip->i_dev, ip->i_number);
+ ifree(ip, ip->i_number, mode);
}
IUPDAT(ip, &time, &time, 0);
irele(ip);
{
register struct buf *bp;
struct dinode *dp;
- register char *p1, *p2;
- register int i;
+ register struct fs *fp;
- if ((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
- if (getfs(ip->i_dev)->s_ronly)
+ fp = ip->i_fs;
+ if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
+ if (fp->fs_ronly)
return;
- bp = bread(ip->i_dev, itod(ip->i_number));
+ bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
+ fp->fs_bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
return;
}
- dp = bp->b_un.b_dino;
- dp += itoo(ip->i_number);
- dp->di_mode = ip->i_mode;
- dp->di_nlink = ip->i_nlink;
- dp->di_uid = ip->i_uid;
- dp->di_gid = ip->i_gid;
- dp->di_size = ip->i_size;
- p1 = (char *)dp->di_addr;
- p2 = (char *)ip->i_un.i_addr;
- for(i=0; i<NADDR; i++) {
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = *p2++;
- if (*p2++ != 0)
- printf("iaddress > 2^24\n");
- }
if (ip->i_flag&IACC)
- dp->di_atime = *ta;
+ ip->i_atime = *ta;
if (ip->i_flag&IUPD)
- dp->di_mtime = *tm;
+ ip->i_mtime = *tm;
if (ip->i_flag&ICHG)
- dp->di_ctime = time;
+ ip->i_ctime = time;
ip->i_flag &= ~(IUPD|IACC|ICHG);
+ dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
+ dp->di_ic = ip->i_ic;
if (waitfor)
bwrite(bp);
else
dev_t dev;
daddr_t bn;
struct inode itmp;
+ register struct fs *fs;
i = ip->i_mode & IFMT;
- if (i!=IFREG && i!=IFDIR && i!=IFLNK)
+ if (i != IFREG && i != IFDIR && i != IFLNK)
return;
-
/*
* Clean inode on disk before freeing blocks
* to insure no duplicates if system crashes.
*/
itmp = *ip;
itmp.i_size = 0;
- for (i = 0; i < NADDR; i++)
- itmp.i_un.i_addr[i] = 0;
+ for (i = 0; i < NDADDR; i++)
+ itmp.i_db[i] = 0;
+ for (i = 0; i < NIADDR; i++)
+ itmp.i_ib[i] = 0;
itmp.i_flag |= ICHG|IUPD;
iupdat(&itmp, &time, &time, 1);
ip->i_flag &= ~(IUPD|IACC|ICHG);
* crashes, they will be harmless MISSING blocks.
*/
dev = ip->i_dev;
- for(i=NADDR-1; i>=0; i--) {
- bn = ip->i_un.i_addr[i];
+ fs = ip->i_fs;
+ /*
+ * release double indirect block first
+ */
+ bn = ip->i_ib[NIADDR-1];
+ if (bn != (daddr_t)0) {
+ ip->i_ib[NIADDR - 1] = (daddr_t)0;
+ tloop(ip, bn, 1);
+ }
+ /*
+ * release single indirect blocks second
+ */
+ for (i = NIADDR - 2; i >= 0; i--) {
+ bn = ip->i_ib[i];
+ if (bn != (daddr_t)0) {
+ ip->i_ib[i] = (daddr_t)0;
+ tloop(ip, bn, 0);
+ }
+ }
+ /*
+ * finally release direct blocks
+ */
+ for (i = NDADDR - 1; i>=0; i--) {
+ bn = ip->i_db[i];
if (bn == (daddr_t)0)
continue;
- ip->i_un.i_addr[i] = (daddr_t)0;
- switch(i) {
-
- default:
- free(dev, bn);
- break;
-
- case NADDR-3:
- tloop(dev, bn, 0, 0);
- break;
-
- case NADDR-2:
- tloop(dev, bn, 1, 0);
- break;
-
- case NADDR-1:
- tloop(dev, bn, 1, 1);
- }
+ ip->i_db[i] = (daddr_t)0;
+ fre(ip, bn, (off_t)blksize(fs, ip, i));
}
ip->i_size = 0;
/*
*/
}
-tloop(dev, bn, f1, f2)
-dev_t dev;
-daddr_t bn;
+tloop(ip, bn, indflg)
+ register struct inode *ip;
+ daddr_t bn;
+ int indflg;
{
register i;
register struct buf *bp;
register daddr_t *bap;
+ register struct fs *fs;
daddr_t nb;
bp = NULL;
- for(i=NINDIR-1; i>=0; i--) {
+ fs = ip->i_fs;
+ for (i = NINDIR(fs) - 1; i >= 0; i--) {
if (bp == NULL) {
- bp = bread(dev, bn);
+ bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
return;
nb = bap[i];
if (nb == (daddr_t)0)
continue;
- if (f1) {
- brelse(bp);
- bp = NULL;
- tloop(dev, nb, f2, 0);
- } else
- free(dev, nb);
+ if (indflg)
+ tloop(ip, nb, 0);
+ else
+ fre(ip, nb, fs->fs_bsize);
}
if (bp != NULL)
brelse(bp);
- free(dev, bn);
+ fre(ip, bn, fs->fs_bsize);
}
/*
*/
struct inode *
maknode(mode)
+ int mode;
{
register struct inode *ip;
+ ino_t ipref;
- ip = ialloc(u.u_pdir->i_dev);
+ if ((mode & IFMT) == IFDIR)
+ ipref = dirpref(u.u_pdir->i_fs);
+ else
+ ipref = u.u_pdir->i_number;
+ ip = ialloc(u.u_pdir, ipref, mode);
if (ip == NULL) {
iput(u.u_pdir);
return(NULL);
}
ip->i_flag |= IACC|IUPD|ICHG;
- if ((mode&IFMT) == 0)
+ if ((mode & IFMT) == 0)
mode |= IFREG;
ip->i_mode = mode & ~u.u_cmask;
ip->i_nlink = 1;
* Make sure inode goes to disk before directory entry.
*/
iupdat(ip, &time, &time, 1);
-
wdir(ip);
+ if (u.u_error) {
+ /*
+ * write error occurred trying to update directory
+ * so must deallocate the inode
+ */
+ ip->i_nlink = 0;
+ ip->i_flag |= ICHG;
+ iput(ip);
+ return(NULL);
+ }
return(ip);
}
wdir(ip)
struct inode *ip;
{
+ register struct direct *dp, *ndp;
+ struct fs *fs;
+ struct buf *bp;
+ int lbn, bn, base;
+ int loc, dsize, spccnt, newsize;
+ char *dirbuf;
u.u_dent.d_ino = ip->i_number;
- bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
- u.u_count = sizeof(struct direct);
u.u_segflg = 1;
- u.u_base = (caddr_t)&u.u_dent;
- writei(u.u_pdir);
+ newsize = DIRSIZ(&u.u_dent);
+ /*
+ * if u.u_count == 0, a new directory block must be allocated.
+ */
+ if (u.u_count == 0) {
+ u.u_dent.d_reclen = DIRBLKSIZ;
+ u.u_count = newsize;
+ u.u_base = (caddr_t)&u.u_dent;
+ writei(u.u_pdir);
+ iput(u.u_pdir);
+ return;
+ }
+ /*
+ * must read in an existing directory block
+ * to prepare to place the new entry into it.
+ */
+ fs = u.u_pdir->i_fs;
+ lbn = lblkno(fs, u.u_offset);
+ base = blkoff(fs, u.u_offset);
+ bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
+ if (u.u_offset + u.u_count > u.u_pdir->i_size)
+ u.u_pdir->i_size = u.u_offset + u.u_count;
+ bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
+ if (bp->b_flags & B_ERROR) {
+ brelse(bp);
+ return;
+ }
+ dirbuf = bp->b_un.b_addr + base;
+ dp = (struct direct *)dirbuf;
+ dsize = DIRSIZ(dp);
+ spccnt = dp->d_reclen - dsize;
+ /*
+ * if there is insufficient room to make an entry at this point
+ * namei insures that compacting from u.u_offset for u.u_count
+ * bytes will provide the necessary space.
+ */
+ for (loc = dp->d_reclen; loc < u.u_count; ) {
+ ndp = (struct direct *)(dirbuf + loc);
+ if (dp->d_ino == 0) {
+ spccnt += dsize;
+ } else {
+ dp->d_reclen = dsize;
+ dp = (struct direct *)((char *)dp + dsize);
+ }
+ dsize = DIRSIZ(ndp);
+ spccnt += ndp->d_reclen - dsize;
+ loc += ndp->d_reclen;
+ bcopy(ndp, dp, dsize);
+ }
+ /*
+ * Update the pointer fields in the previous entry (if any),
+ * copy in the new entry, and write out the block.
+ */
+ if (dp->d_ino == 0) {
+ if (spccnt + dsize < newsize)
+ panic("wdir: compact failed");
+ u.u_dent.d_reclen = spccnt + dsize;
+ } else {
+ if (spccnt < newsize)
+ panic("wdir: compact failed");
+ u.u_dent.d_reclen = spccnt;
+ dp->d_reclen = dsize;
+ dp = (struct direct *)((char *)dp + dsize);
+ }
+ bcopy(&u.u_dent, dp, newsize);
+ bwrite(bp);
+ u.u_pdir->i_flag |= IUPD|ICHG;
iput(u.u_pdir);
}
-/* ufs_lookup.c 4.14 82/03/31 */
+/* ufs_lookup.c 4.15 82/04/19 */
+
+/* merged into kernel: @(#)nami.c 2.3 4/8/82 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/inode.h"
+#include "../h/fs.h"
#include "../h/mount.h"
#include "../h/dir.h"
#include "../h/user.h"
register char *cp;
register struct buf *bp, *nbp;
register struct direct *ep;
+ register struct fs *fs;
struct inode *pdp;
- int i, nlink;
+ enum {NONE, COMPACT, FOUND} slot;
+ int entryfree, entrysize;
+ int spccnt, size, newsize;
+ int loc, prevoff, curoff;
+ int i, nlink, bsize;
+ unsigned pathlen;
+ daddr_t lbn, bn;
dev_t d;
- off_t eo;
/*
* allocate name buffer; copy name
*/
- nbp = geteblk();
+ nbp = geteblk(MAXPATHLEN);
nlink = 0;
- for (i=0, cp = nbp->b_un.b_addr; *cp = (*func)(); i++) {
- if ((*cp&0377) == ('/'|0200)) {
+ for (i = 0, cp = nbp->b_un.b_addr; *cp = (*func)(); i++) {
+ if ((*cp & 0377) == ('/'|0200)) {
u.u_error = EPERM;
break;
}
#ifdef notdef
- if (*cp++&0200 && flag==1 || cp >= nbp->b_un.b_addr+BSIZE) {
+ if (*cp++ & 0200 && flag == 1 ||
+ cp >= nbp->b_un.b_addr + MAXPATHLEN) {
#else
cp++;
- if (cp >= nbp->b_un.b_addr+BSIZE) {
+ if (cp >= nbp->b_un.b_addr + MAXPATHLEN) {
#endif
u.u_error = ENOENT;
break;
}
}
if (u.u_error) {
- dp = NULL;
- goto out1;
+ brelse(nbp);
+ return (NULL);
}
cp = nbp->b_un.b_addr;
/*
}
ilock(dp);
dp->i_count++;
-
+ fs = dp->i_fs;
+ newsize = 0;
+dirloop:
/*
* dp must be a directory and
* must have X permission.
* cp is a path name relative to that directory.
*/
-
-dirloop:
if ((dp->i_mode&IFMT) != IFDIR)
u.u_error = ENOTDIR;
(void) access(dp, IEXEC);
dirloop2:
- for (i=0; *cp!='\0' && *cp!='/'; i++) {
+ for (i = 0; *cp != '\0' && *cp != '/'; cp++) {
#ifdef notdef
- if (i >= DIRSIZ) {
+ if (i >= MAXNAMLEN) {
u.u_error = ENOENT;
break;
}
- u.u_dbuf[i] = *cp++;
+ u.u_dent.d_name[i] = *cp;
#else
- if (i < DIRSIZ)
- u.u_dbuf[i] = *cp;
- cp++;
+ if (i < MAXNAMLEN) {
+ u.u_dent.d_name[i] = *cp;
+ i++;
+ }
#endif
}
- if (u.u_error)
- goto out;
+ if (u.u_error) {
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
+ }
+ u.u_dent.d_namlen = i;
+ u.u_dent.d_name[i] = '\0';
+ newsize = DIRSIZ(&u.u_dent);
u.u_pdir = dp;
- while (i < DIRSIZ)
- u.u_dbuf[i++] = '\0';
- if (u.u_dbuf[0] == '\0') { /* null name, e.g. "/" or "" */
- if (flag) {
+ if (u.u_dent.d_name[0] == '\0') { /* null name, e.g. "/" or "" */
+ if (flag != 0) {
u.u_error = ENOENT;
- goto out;
+ iput(dp);
+ dp = NULL;
}
- goto out1;
+ u.u_offset = 0;
+ u.u_count = newsize;
+ brelse(nbp);
+ return (dp);
}
+ /*
+ * set up to search a directory
+ */
+ if (flag == 1)
+ slot = NONE;
+ else
+ slot = FOUND;
+ u.u_offset = 0;
u.u_segflg = 1;
- eo = -1;
bp = NULL;
-
- for (u.u_offset=0; u.u_offset < dp->i_size;
- u.u_offset += sizeof(struct direct), ep++) {
+ spccnt = 0;
+ loc = 0;
+ while (u.u_offset < dp->i_size) {
+ /*
+ * check to see if enough space has been accumulated to make
+ * an entry by compaction. Reset the free space counter each
+ * time a directory block is crossed.
+ */
+ if (slot == NONE) {
+ if (spccnt >= newsize) {
+ slot = COMPACT;
+ entrysize = u.u_offset - entryfree;
+ } else if (loc % DIRBLKSIZ == 0) {
+ entryfree = NULL;
+ spccnt = 0;
+ }
+ }
/*
* If offset is on a block boundary,
* read the next directory block.
* Release previous if it exists.
*/
- if ((u.u_offset&BMASK) == 0) {
+ if (blkoff(fs, u.u_offset) == 0) {
if (bp != NULL)
brelse(bp);
- bp = bread(dp->i_dev,
- bmap(dp,(daddr_t)(u.u_offset>>BSHIFT), B_READ));
+ lbn = (daddr_t)lblkno(fs, u.u_offset);
+ bsize = blksize(fs, dp, lbn);
+ if ((bn = bmap(dp, lbn, B_READ)) < 0) {
+ printf("hole in dir: %s i = %d\n",
+ fs->fs_fsmnt, dp->i_number);
+ if (fs->fs_ronly != 0 ||
+ (bn = bmap(dp, lbn, B_WRITE, bsize)) < 0) {
+ u.u_offset += bsize;
+ bp = NULL;
+ continue;
+ }
+ }
+ bp = bread(dp->i_dev, fsbtodb(fs, bn), bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
- goto out;
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
+ }
+ loc = 0;
+ } else {
+ loc += ep->d_reclen;
+ }
+ /*
+ * calculate the next directory entry and run
+ * some rudimentary bounds checks to make sure
+ * that it is reasonable. If the check fails
+ * resync at the beginning of the next directory
+ * block.
+ */
+ ep = (struct direct *)(bp->b_un.b_addr + loc);
+ i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
+ if (ep->d_reclen <= 0 || ep->d_reclen > i) {
+ loc += i;
+ u.u_offset += i;
+ continue;
+ }
+ /*
+ * If an appropriate sized hole has not yet been found,
+ * check to see if one is available. Also accumulate space
+ * in the current block so that we can determine if
+ * compaction is viable.
+ */
+ if (slot != FOUND) {
+ size = ep->d_reclen;
+ if (ep->d_ino != 0)
+ size -= DIRSIZ(ep);
+ if (size > 0) {
+ if (size >= newsize) {
+ slot = FOUND;
+ entryfree = u.u_offset;
+ entrysize = DIRSIZ(ep) + newsize;
+ }
+ if (entryfree == NULL)
+ entryfree = u.u_offset;
+ spccnt += size;
}
- ep = (struct direct *)bp->b_un.b_addr;
}
/*
- * Note first empty directory slot
- * in eo for possible creat.
* String compare the directory entry
* and the current component.
+ * If they do not match, continue to the next entry.
*/
- if (ep->d_ino == 0) {
- if (eo < 0)
- eo = u.u_offset;
+ prevoff = curoff;
+ curoff = u.u_offset;
+ u.u_offset += ep->d_reclen;
+ if (ep->d_ino == 0)
continue;
- }
- if (strncmp(u.u_dbuf, ep->d_name, DIRSIZ) != 0)
+ if (ep->d_namlen != u.u_dent.d_namlen)
+ continue;
+ if (bcmp(u.u_dent.d_name, ep->d_name, ep->d_namlen))
continue;
/*
* Here a component matched in a directory.
* If there is more pathname, go back to
* dirloop, otherwise return.
*/
- bcopy((caddr_t)ep, (caddr_t)&u.u_dent, sizeof(struct direct));
+ bcopy((caddr_t)ep, (caddr_t)&u.u_dent, DIRSIZ(ep));
brelse(bp);
- if (flag==2 && *cp=='\0') {
- if (access(dp, IWRITE))
- goto out;
- /* should fix unlink */
- u.u_offset += sizeof(struct direct);
- goto out1;
+ if (flag == 2 && *cp == '\0') {
+ brelse(nbp);
+ if (access(dp, IWRITE)) {
+ iput(dp);
+ return (NULL);
+ }
+ if (curoff % DIRBLKSIZ == 0) {
+ u.u_offset = curoff;
+ u.u_count = 0;
+ return (dp);
+ }
+ u.u_offset = prevoff;
+ u.u_count = DIRSIZ((struct direct *)
+ (bp->b_un.b_addr + blkoff(fs, prevoff)));
+ return (dp);
}
/*
* Special handling for ".."
*/
- if (u.u_dent.d_name[0]=='.' && u.u_dent.d_name[1]=='.' &&
- u.u_dent.d_name[2]=='\0') {
+ if (u.u_dent.d_name[0] == '.' && u.u_dent.d_name[1] == '.' &&
+ u.u_dent.d_name[2] == '\0') {
if (dp == u.u_rdir)
u.u_dent.d_ino = dp->i_number;
- else if (u.u_dent.d_ino==ROOTINO &&
+ else if (u.u_dent.d_ino == ROOTINO &&
dp->i_number == ROOTINO) {
- for(i=1; i<NMOUNT; i++)
+ for (i = 1; i < NMOUNT; i++)
if (mount[i].m_bufp != NULL &&
mount[i].m_dev == dp->i_dev) {
iput(dp);
dp = mount[i].m_inodp;
ilock(dp);
dp->i_count++;
+ fs = dp->i_fs;
cp -= 2; /* back over .. */
goto dirloop2;
}
d = dp->i_dev;
irele(dp);
pdp = dp;
- dp = iget(d, u.u_dent.d_ino);
+ dp = iget(d, fs, u.u_dent.d_ino);
if (dp == NULL) {
iput(pdp);
- goto out1;
+ brelse(nbp);
+ return (NULL);
}
+ fs = dp->i_fs;
/*
* Check for symbolic link
*/
- if ((dp->i_mode&IFMT)==IFLNK && (follow || *cp=='/')) {
- char *ocp;
-
- ocp = cp;
- while (*cp++)
- ;
- if (dp->i_size + (cp-ocp) >= BSIZE-1 || ++nlink>8) {
+ if ((dp->i_mode & IFMT) == IFLNK && (follow || *cp == '/')) {
+ pathlen = strlen(cp) + 1;
+ if (dp->i_size + pathlen >= MAXPATHLEN - 1 ||
+ ++nlink > MAXSYMLINKS) {
u.u_error = ELOOP;
iput(pdp);
- goto out;
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
}
- bcopy(ocp, nbp->b_un.b_addr+dp->i_size,
- (unsigned)(cp-ocp));
- bp = bread(dp->i_dev, bmap(dp, (daddr_t)0, B_READ));
+ bcopy(cp, nbp->b_un.b_addr + dp->i_size, pathlen);
+ bn = bmap(dp, (daddr_t)0, B_READ);
+ if (bn < 0) {
+ printf("hole in symlink: %s i = %d\n",
+ fs->fs_fsmnt, dp->i_number);
+ iput(pdp);
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
+ }
+ bp = bread(dp->i_dev, fsbtodb(fs, bn),
+ (int)blksize(fs, dp, (daddr_t)0));
if (bp->b_flags & B_ERROR) {
brelse(bp);
iput(pdp);
- goto out;
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
}
bcopy(bp->b_un.b_addr, nbp->b_un.b_addr,
(unsigned)dp->i_size);
dp = pdp;
ilock(dp);
}
+ fs = dp->i_fs;
goto dirloop;
}
iput(pdp);
cp++;
goto dirloop;
}
- goto out1;
+ /*
+ * End of path, so return name matched.
+ */
+ u.u_offset -= ep->d_reclen;
+ u.u_count = newsize;
+ brelse(nbp);
+ return (dp);
}
/*
* Search failed.
+ * Report what is appropriate as per flag.
*/
if (bp != NULL)
brelse(bp);
- if (flag==1 && *cp=='\0' && dp->i_nlink) {
- if (access(dp, IWRITE))
- goto out;
- if (eo>=0)
- u.u_offset = eo;
+ if (flag == 1 && *cp == '\0' && dp->i_nlink != 0) {
+ brelse(nbp);
+ if (access(dp, IWRITE)) {
+ iput(dp);
+ return (NULL);
+ }
+ if (slot == NONE) {
+ u.u_count = 0;
+ } else {
+ u.u_offset = entryfree;
+ u.u_count = entrysize;
+ }
dp->i_flag |= IUPD|ICHG;
- dp = NULL;
- goto out1;
+ return (NULL);
}
u.u_error = ENOENT;
-out:
iput(dp);
- dp = NULL;
-out1:
brelse(nbp);
- return (dp);
+ return (NULL);
}
/*
}
#ifndef vax
-strncmp(s1, s2, len)
+bcmp(s1, s2, len)
register char *s1, *s2;
- register len;
+ register int len;
{
- do {
- if (*s1 != *s2++)
+ while (--len)
+ if (*s1++ != *s2++)
return (1);
- if (*s1++ == '\0')
- return (0);
- } while (--len);
return (0);
}
+
+strlen(s1)
+ register char *s1;
+{
+ register int len;
+
+ for (len = 0; *s1++ != '\0'; len++)
+ /* void */;
+ return (len);
+}
#endif
-/* ufs_vnops.c 4.22 82/04/01 */
+/* ufs_vnops.c 4.23 82/04/19 */
+/* merged into kernel: @(#)sys3.c 2.2 4/8/82 */
+
+#ifdef SIMFS
+#include "../h/sysrenam.h"
+#endif
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
-#include "../h/reg.h"
#include "../h/file.h"
+#include "../h/stat.h"
#include "../h/inode.h"
-#include "../h/ino.h"
-#include "../h/pte.h"
-#include "../h/vm.h"
+#include "../h/fs.h"
#include "../h/buf.h"
-#include "../h/mtpr.h"
#include "../h/proc.h"
#include "../h/inline.h"
-#include "../h/conf.h"
-#include "../h/socket.h"
-#include "../h/socketvar.h"
-#include "../h/stat.h"
chdir()
{
* Want to be able to use this to make badblock
* inodes, so don't truncate the dev number.
*/
- ip->i_un.i_rdev = uap->dev;
+ ip->i_rdev = uap->dev;
ip->i_flag |= IACC|IUPD|ICHG;
}
struct a {
char *fname;
};
+ struct fs *fs;
+ struct buf *bp;
+ int lbn, bn, base;
pp = namei(uchar, 2, 0);
if(pp == NULL)
ip = pp;
ip->i_count++;
} else
- ip = iget(pp->i_dev, u.u_dent.d_ino);
+ ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
if(ip == NULL)
goto out1;
if((ip->i_mode&IFMT)==IFDIR && !suser())
goto out;
}
*/
- u.u_offset -= sizeof(struct direct);
- u.u_base = (caddr_t)&u.u_dent;
- u.u_count = sizeof(struct direct);
- u.u_dent.d_ino = 0;
- writei(pp);
+ if (u.u_count == 0) {
+ /*
+ * first entry in block, so set d_ino to zero.
+ */
+ u.u_base = (caddr_t)&u.u_dent;
+ u.u_count = DIRSIZ(&u.u_dent);
+ u.u_dent.d_ino = 0;
+ writei(pp);
+ } else {
+ /*
+ * updating preceeding entry to skip over current entry.
+ */
+ fs = pp->i_fs;
+ lbn = lblkno(fs, u.u_offset);
+ base = blkoff(fs, u.u_offset);
+ bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count));
+ bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn));
+ if (bp->b_flags & B_ERROR) {
+ brelse(bp);
+ goto out;
+ }
+ ((struct direct *)(bp->b_un.b_addr + base))->d_reclen +=
+ u.u_dent.d_reclen;
+ bwrite(bp);
+ pp->i_flag |= IUPD|ICHG;
+ }
ip->i_nlink--;
ip->i_flag |= ICHG;
}
/*
- * Stat system call; this follows links.
+ * Stat system call. This version follows links.
*/
stat()
{
}
/*
- * Lstat system call; like stat but doesn't follow links.
+ * Lstat system call. This version does not follow links.
*/
lstat()
{
register struct inode *ip;
struct stat *ub;
{
- register struct dinode *dp;
- register struct buf *bp;
struct stat ds;
IUPDAT(ip, &time, &time, 0);
ds.st_nlink = ip->i_nlink;
ds.st_uid = ip->i_uid;
ds.st_gid = ip->i_gid;
- ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+ ds.st_rdev = (dev_t)ip->i_rdev;
ds.st_size = ip->i_size;
- /*
- * next the dates in the disk
- */
- bp = bread(ip->i_dev, itod(ip->i_number));
- dp = bp->b_un.b_dino;
- dp += itoo(ip->i_number);
- ds.st_atime = dp->di_atime;
- ds.st_mtime = dp->di_mtime;
- ds.st_ctime = dp->di_ctime;
- brelse(bp);
+ ds.st_atime = ip->i_atime;
+ ds.st_mtime = ip->i_mtime;
+ ds.st_ctime = ip->i_ctime;
if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
u.u_error = EFAULT;
}
-/* alloc.c 4.1 82/03/25 */
-
-/* merged into kernel: @(#)lfs_alloc.c 2.3 %G% */
-
-/* last monet version: alloc.c 4.8 81/03/08 */
+/* lfs_alloc.c 2.4 82/04/19 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/inode.h"
-#include "../h/ndir.h"
+#include "../h/dir.h"
#include "../h/user.h"
extern u_long hashalloc();
else
cg = dtog(fs, bpref);
bno = (daddr_t)hashalloc(ip, cg, (long)bpref, size, alloccg);
- if (bno == 0)
+ if (bno <= 0)
goto nospace;
bp = getblk(ip->i_dev, fsbtodb(fs, bno), size);
clrbuf(bp);
daddr_t bno;
register struct fs *fs;
register struct buf *bp, *obp;
- caddr_t cp;
int cg;
fs = ip->i_fs;
brelse(bp);
return (NULL);
}
- bp->b_bcount = nsize;
+ brealloc(bp, nsize);
blkclr(bp->b_un.b_addr + osize, nsize - osize);
return (bp);
}
if (bpref >= fs->fs_size)
bpref = 0;
bno = (daddr_t)hashalloc(ip, cg, (long)bpref, nsize, alloccg);
- if (bno != 0) {
- /*
- * make a new copy
- */
+ if (bno > 0) {
obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize);
if (obp->b_flags & B_ERROR) {
brelse(obp);
return (NULL);
}
bp = getblk(ip->i_dev, fsbtodb(fs, bno), nsize);
- cp = bp->b_un.b_addr;
- bp->b_un.b_addr = obp->b_un.b_addr;
- obp->b_un.b_addr = cp;
- obp->b_flags |= B_INVAL;
+ bcopy(obp->b_un.b_addr, bp->b_un.b_addr, osize);
+ blkclr(bp->b_un.b_addr + osize, nsize - osize);
brelse(obp);
fre(ip, bprev, (off_t)osize);
- blkclr(bp->b_un.b_addr + osize, nsize - osize);
return (bp);
}
nospace:
return (bno);
}
bno = mapsearch(fs, cgp, bpref, allocsiz);
- if (bno == -1)
+ if (bno < 0)
return (NULL);
for (i = 0; i < frags; i++)
clrbit(cgp->cg_free, bno + i);
* available one in this cylinder group.
*/
bno = mapsearch(fs, cgp, bpref, fs->fs_frag);
- if (bno == -1)
+ if (bno < 0)
return (NULL);
cgp->cg_rotor = bno;
gotit:
if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0)
panic("free: bad size");
cg = dtog(fs, bno);
- if (badblock(fs, bno))
+ if (badblock(fs, bno)) {
+ printf("bad block %d, ino %d\n", bno, ip->i_number);
return;
+ }
bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize);
cgp = bp->b_un.b_cg;
if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) {
}
bno = dtogd(fs, bno);
if (size == fs->fs_bsize) {
- if (isblock(fs, cgp->cg_free, bno/fs->fs_frag))
+ if (isblock(fs, cgp->cg_free, bno/fs->fs_frag)) {
+ printf("free block %d, fs %s\n", bno, fs->fs_fsmnt);
panic("free: freeing free block");
+ }
setblock(fs, cgp->cg_free, bno/fs->fs_frag);
cgp->cg_cs.cs_nbfree++;
fs->fs_cstotal.cs_nbfree++;
{
if ((unsigned)bn >= fs->fs_size) {
+ printf("bad block %d, ", bn);
fserr(fs, "bad block");
return (1);
}
-/* lfs_inode.c 4.9 82/02/27 */
+/* lfs_inode.c 4.10 82/04/19 */
+
+/* merged into kernel: @(#)iget.c 2.2 4/8/82 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/inode.h"
-#include "../h/ino.h"
-#include "../h/filsys.h"
+#include "../h/fs.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/inline.h"
inohash[i] = -1;
}
-/*
- * Find an inode if it is incore.
- * This is the equivalent, for inodes,
- * of ``incore'' in bio.c or ``pfind'' in subr.c.
- */
-struct inode *
-ifind(dev, ino)
- dev_t dev;
- ino_t ino;
-{
- register struct inode *ip;
-
- for (ip = &inode[inohash[INOHASH(dev,ino)]]; ip != &inode[-1];
- ip = &inode[ip->i_hlink])
- if (ino==ip->i_number && dev==ip->i_dev)
- return (ip);
- return ((struct inode *)0);
-}
-
/*
* Look up an inode by device,inumber.
* If it is in core (in the inode structure),
* "cannot happen"
*/
struct inode *
-iget(dev, ino)
+iget(dev, fs, ino)
dev_t dev;
+ register struct fs *fs;
ino_t ino;
{
register struct inode *ip;
register int slot;
loop:
+ if (getfs(dev) != fs)
+ panic("iget: bad fs");
slot = INOHASH(dev, ino);
ip = &inode[inohash[slot]];
while (ip != &inode[-1]) {
goto loop;
}
if ((ip->i_flag&IMOUNT) != 0) {
- for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+ for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
if (mp->m_inodp == ip) {
dev = mp->m_dev;
+ fs = mp->m_bufp->b_un.b_fs;
ino = ROOTINO;
goto loop;
}
ip->i_hlink = inohash[slot];
inohash[slot] = ip - inode;
ip->i_dev = dev;
+ ip->i_fs = fs;
ip->i_number = ino;
ip->i_flag = ILOCK;
ip->i_count++;
- ip->i_un.i_lastr = 0;
- bp = bread(dev, itod(ino));
+ ip->i_lastr = 0;
+ bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize);
/*
* Check I/O errors
*/
return(NULL);
}
dp = bp->b_un.b_dino;
- dp += itoo(ino);
- iexpand(ip, dp);
+ dp += itoo(fs, ino);
+ ip->i_ic = dp->di_ic;
brelse(bp);
- return(ip);
-}
-
-iexpand(ip, dp)
- register struct inode *ip;
- register struct dinode *dp;
-{
- register char *p1, *p2;
- register int i;
-
- ip->i_mode = dp->di_mode;
- ip->i_nlink = dp->di_nlink;
- ip->i_uid = dp->di_uid;
- ip->i_gid = dp->di_gid;
- ip->i_size = dp->di_size;
- p1 = (char *)ip->i_un.i_addr;
- p2 = (char *)dp->di_addr;
- for(i=0; i<NADDR; i++) {
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = 0;
- }
+ return (ip);
}
/*
{
register int i, x;
register struct inode *jp;
+ int mode;
if (ip->i_count == 1) {
ip->i_flag |= ILOCK;
if (ip->i_nlink <= 0) {
itrunc(ip);
+ mode = ip->i_mode;
ip->i_mode = 0;
ip->i_flag |= IUPD|ICHG;
- ifree(ip->i_dev, ip->i_number);
+ ifree(ip, ip->i_number, mode);
}
IUPDAT(ip, &time, &time, 0);
irele(ip);
{
register struct buf *bp;
struct dinode *dp;
- register char *p1, *p2;
- register int i;
+ register struct fs *fp;
- if ((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
- if (getfs(ip->i_dev)->s_ronly)
+ fp = ip->i_fs;
+ if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
+ if (fp->fs_ronly)
return;
- bp = bread(ip->i_dev, itod(ip->i_number));
+ bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
+ fp->fs_bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
return;
}
- dp = bp->b_un.b_dino;
- dp += itoo(ip->i_number);
- dp->di_mode = ip->i_mode;
- dp->di_nlink = ip->i_nlink;
- dp->di_uid = ip->i_uid;
- dp->di_gid = ip->i_gid;
- dp->di_size = ip->i_size;
- p1 = (char *)dp->di_addr;
- p2 = (char *)ip->i_un.i_addr;
- for(i=0; i<NADDR; i++) {
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = *p2++;
- if (*p2++ != 0)
- printf("iaddress > 2^24\n");
- }
if (ip->i_flag&IACC)
- dp->di_atime = *ta;
+ ip->i_atime = *ta;
if (ip->i_flag&IUPD)
- dp->di_mtime = *tm;
+ ip->i_mtime = *tm;
if (ip->i_flag&ICHG)
- dp->di_ctime = time;
+ ip->i_ctime = time;
ip->i_flag &= ~(IUPD|IACC|ICHG);
+ dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
+ dp->di_ic = ip->i_ic;
if (waitfor)
bwrite(bp);
else
dev_t dev;
daddr_t bn;
struct inode itmp;
+ register struct fs *fs;
i = ip->i_mode & IFMT;
- if (i!=IFREG && i!=IFDIR && i!=IFLNK)
+ if (i != IFREG && i != IFDIR && i != IFLNK)
return;
-
/*
* Clean inode on disk before freeing blocks
* to insure no duplicates if system crashes.
*/
itmp = *ip;
itmp.i_size = 0;
- for (i = 0; i < NADDR; i++)
- itmp.i_un.i_addr[i] = 0;
+ for (i = 0; i < NDADDR; i++)
+ itmp.i_db[i] = 0;
+ for (i = 0; i < NIADDR; i++)
+ itmp.i_ib[i] = 0;
itmp.i_flag |= ICHG|IUPD;
iupdat(&itmp, &time, &time, 1);
ip->i_flag &= ~(IUPD|IACC|ICHG);
* crashes, they will be harmless MISSING blocks.
*/
dev = ip->i_dev;
- for(i=NADDR-1; i>=0; i--) {
- bn = ip->i_un.i_addr[i];
+ fs = ip->i_fs;
+ /*
+ * release double indirect block first
+ */
+ bn = ip->i_ib[NIADDR-1];
+ if (bn != (daddr_t)0) {
+ ip->i_ib[NIADDR - 1] = (daddr_t)0;
+ tloop(ip, bn, 1);
+ }
+ /*
+ * release single indirect blocks second
+ */
+ for (i = NIADDR - 2; i >= 0; i--) {
+ bn = ip->i_ib[i];
+ if (bn != (daddr_t)0) {
+ ip->i_ib[i] = (daddr_t)0;
+ tloop(ip, bn, 0);
+ }
+ }
+ /*
+ * finally release direct blocks
+ */
+ for (i = NDADDR - 1; i>=0; i--) {
+ bn = ip->i_db[i];
if (bn == (daddr_t)0)
continue;
- ip->i_un.i_addr[i] = (daddr_t)0;
- switch(i) {
-
- default:
- free(dev, bn);
- break;
-
- case NADDR-3:
- tloop(dev, bn, 0, 0);
- break;
-
- case NADDR-2:
- tloop(dev, bn, 1, 0);
- break;
-
- case NADDR-1:
- tloop(dev, bn, 1, 1);
- }
+ ip->i_db[i] = (daddr_t)0;
+ fre(ip, bn, (off_t)blksize(fs, ip, i));
}
ip->i_size = 0;
/*
*/
}
-tloop(dev, bn, f1, f2)
-dev_t dev;
-daddr_t bn;
+tloop(ip, bn, indflg)
+ register struct inode *ip;
+ daddr_t bn;
+ int indflg;
{
register i;
register struct buf *bp;
register daddr_t *bap;
+ register struct fs *fs;
daddr_t nb;
bp = NULL;
- for(i=NINDIR-1; i>=0; i--) {
+ fs = ip->i_fs;
+ for (i = NINDIR(fs) - 1; i >= 0; i--) {
if (bp == NULL) {
- bp = bread(dev, bn);
+ bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
return;
nb = bap[i];
if (nb == (daddr_t)0)
continue;
- if (f1) {
- brelse(bp);
- bp = NULL;
- tloop(dev, nb, f2, 0);
- } else
- free(dev, nb);
+ if (indflg)
+ tloop(ip, nb, 0);
+ else
+ fre(ip, nb, fs->fs_bsize);
}
if (bp != NULL)
brelse(bp);
- free(dev, bn);
+ fre(ip, bn, fs->fs_bsize);
}
/*
*/
struct inode *
maknode(mode)
+ int mode;
{
register struct inode *ip;
+ ino_t ipref;
- ip = ialloc(u.u_pdir->i_dev);
+ if ((mode & IFMT) == IFDIR)
+ ipref = dirpref(u.u_pdir->i_fs);
+ else
+ ipref = u.u_pdir->i_number;
+ ip = ialloc(u.u_pdir, ipref, mode);
if (ip == NULL) {
iput(u.u_pdir);
return(NULL);
}
ip->i_flag |= IACC|IUPD|ICHG;
- if ((mode&IFMT) == 0)
+ if ((mode & IFMT) == 0)
mode |= IFREG;
ip->i_mode = mode & ~u.u_cmask;
ip->i_nlink = 1;
* Make sure inode goes to disk before directory entry.
*/
iupdat(ip, &time, &time, 1);
-
wdir(ip);
+ if (u.u_error) {
+ /*
+ * write error occurred trying to update directory
+ * so must deallocate the inode
+ */
+ ip->i_nlink = 0;
+ ip->i_flag |= ICHG;
+ iput(ip);
+ return(NULL);
+ }
return(ip);
}
wdir(ip)
struct inode *ip;
{
+ register struct direct *dp, *ndp;
+ struct fs *fs;
+ struct buf *bp;
+ int lbn, bn, base;
+ int loc, dsize, spccnt, newsize;
+ char *dirbuf;
u.u_dent.d_ino = ip->i_number;
- bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
- u.u_count = sizeof(struct direct);
u.u_segflg = 1;
- u.u_base = (caddr_t)&u.u_dent;
- writei(u.u_pdir);
+ newsize = DIRSIZ(&u.u_dent);
+ /*
+ * if u.u_count == 0, a new directory block must be allocated.
+ */
+ if (u.u_count == 0) {
+ u.u_dent.d_reclen = DIRBLKSIZ;
+ u.u_count = newsize;
+ u.u_base = (caddr_t)&u.u_dent;
+ writei(u.u_pdir);
+ iput(u.u_pdir);
+ return;
+ }
+ /*
+ * must read in an existing directory block
+ * to prepare to place the new entry into it.
+ */
+ fs = u.u_pdir->i_fs;
+ lbn = lblkno(fs, u.u_offset);
+ base = blkoff(fs, u.u_offset);
+ bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
+ if (u.u_offset + u.u_count > u.u_pdir->i_size)
+ u.u_pdir->i_size = u.u_offset + u.u_count;
+ bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
+ if (bp->b_flags & B_ERROR) {
+ brelse(bp);
+ return;
+ }
+ dirbuf = bp->b_un.b_addr + base;
+ dp = (struct direct *)dirbuf;
+ dsize = DIRSIZ(dp);
+ spccnt = dp->d_reclen - dsize;
+ /*
+ * if there is insufficient room to make an entry at this point
+ * namei insures that compacting from u.u_offset for u.u_count
+ * bytes will provide the necessary space.
+ */
+ for (loc = dp->d_reclen; loc < u.u_count; ) {
+ ndp = (struct direct *)(dirbuf + loc);
+ if (dp->d_ino == 0) {
+ spccnt += dsize;
+ } else {
+ dp->d_reclen = dsize;
+ dp = (struct direct *)((char *)dp + dsize);
+ }
+ dsize = DIRSIZ(ndp);
+ spccnt += ndp->d_reclen - dsize;
+ loc += ndp->d_reclen;
+ bcopy(ndp, dp, dsize);
+ }
+ /*
+ * Update the pointer fields in the previous entry (if any),
+ * copy in the new entry, and write out the block.
+ */
+ if (dp->d_ino == 0) {
+ if (spccnt + dsize < newsize)
+ panic("wdir: compact failed");
+ u.u_dent.d_reclen = spccnt + dsize;
+ } else {
+ if (spccnt < newsize)
+ panic("wdir: compact failed");
+ u.u_dent.d_reclen = spccnt;
+ dp->d_reclen = dsize;
+ dp = (struct direct *)((char *)dp + dsize);
+ }
+ bcopy(&u.u_dent, dp, newsize);
+ bwrite(bp);
+ u.u_pdir->i_flag |= IUPD|ICHG;
iput(u.u_pdir);
}
-/* lfs_vnops.c 4.22 82/04/01 */
+/* lfs_vnops.c 4.23 82/04/19 */
+/* merged into kernel: @(#)sys3.c 2.2 4/8/82 */
+
+#ifdef SIMFS
+#include "../h/sysrenam.h"
+#endif
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
-#include "../h/reg.h"
#include "../h/file.h"
+#include "../h/stat.h"
#include "../h/inode.h"
-#include "../h/ino.h"
-#include "../h/pte.h"
-#include "../h/vm.h"
+#include "../h/fs.h"
#include "../h/buf.h"
-#include "../h/mtpr.h"
#include "../h/proc.h"
#include "../h/inline.h"
-#include "../h/conf.h"
-#include "../h/socket.h"
-#include "../h/socketvar.h"
-#include "../h/stat.h"
chdir()
{
* Want to be able to use this to make badblock
* inodes, so don't truncate the dev number.
*/
- ip->i_un.i_rdev = uap->dev;
+ ip->i_rdev = uap->dev;
ip->i_flag |= IACC|IUPD|ICHG;
}
struct a {
char *fname;
};
+ struct fs *fs;
+ struct buf *bp;
+ int lbn, bn, base;
pp = namei(uchar, 2, 0);
if(pp == NULL)
ip = pp;
ip->i_count++;
} else
- ip = iget(pp->i_dev, u.u_dent.d_ino);
+ ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
if(ip == NULL)
goto out1;
if((ip->i_mode&IFMT)==IFDIR && !suser())
goto out;
}
*/
- u.u_offset -= sizeof(struct direct);
- u.u_base = (caddr_t)&u.u_dent;
- u.u_count = sizeof(struct direct);
- u.u_dent.d_ino = 0;
- writei(pp);
+ if (u.u_count == 0) {
+ /*
+ * first entry in block, so set d_ino to zero.
+ */
+ u.u_base = (caddr_t)&u.u_dent;
+ u.u_count = DIRSIZ(&u.u_dent);
+ u.u_dent.d_ino = 0;
+ writei(pp);
+ } else {
+ /*
+ * updating preceeding entry to skip over current entry.
+ */
+ fs = pp->i_fs;
+ lbn = lblkno(fs, u.u_offset);
+ base = blkoff(fs, u.u_offset);
+ bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count));
+ bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn));
+ if (bp->b_flags & B_ERROR) {
+ brelse(bp);
+ goto out;
+ }
+ ((struct direct *)(bp->b_un.b_addr + base))->d_reclen +=
+ u.u_dent.d_reclen;
+ bwrite(bp);
+ pp->i_flag |= IUPD|ICHG;
+ }
ip->i_nlink--;
ip->i_flag |= ICHG;
}
/*
- * Stat system call; this follows links.
+ * Stat system call. This version follows links.
*/
stat()
{
}
/*
- * Lstat system call; like stat but doesn't follow links.
+ * Lstat system call. This version does not follow links.
*/
lstat()
{
register struct inode *ip;
struct stat *ub;
{
- register struct dinode *dp;
- register struct buf *bp;
struct stat ds;
IUPDAT(ip, &time, &time, 0);
ds.st_nlink = ip->i_nlink;
ds.st_uid = ip->i_uid;
ds.st_gid = ip->i_gid;
- ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+ ds.st_rdev = (dev_t)ip->i_rdev;
ds.st_size = ip->i_size;
- /*
- * next the dates in the disk
- */
- bp = bread(ip->i_dev, itod(ip->i_number));
- dp = bp->b_un.b_dino;
- dp += itoo(ip->i_number);
- ds.st_atime = dp->di_atime;
- ds.st_mtime = dp->di_mtime;
- ds.st_ctime = dp->di_ctime;
- brelse(bp);
+ ds.st_atime = ip->i_atime;
+ ds.st_mtime = ip->i_mtime;
+ ds.st_ctime = ip->i_ctime;
if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
u.u_error = EFAULT;
}
-/* ufs_inode.c 4.9 82/02/27 */
+/* ufs_inode.c 4.10 82/04/19 */
+
+/* merged into kernel: @(#)iget.c 2.2 4/8/82 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/inode.h"
-#include "../h/ino.h"
-#include "../h/filsys.h"
+#include "../h/fs.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/inline.h"
inohash[i] = -1;
}
-/*
- * Find an inode if it is incore.
- * This is the equivalent, for inodes,
- * of ``incore'' in bio.c or ``pfind'' in subr.c.
- */
-struct inode *
-ifind(dev, ino)
- dev_t dev;
- ino_t ino;
-{
- register struct inode *ip;
-
- for (ip = &inode[inohash[INOHASH(dev,ino)]]; ip != &inode[-1];
- ip = &inode[ip->i_hlink])
- if (ino==ip->i_number && dev==ip->i_dev)
- return (ip);
- return ((struct inode *)0);
-}
-
/*
* Look up an inode by device,inumber.
* If it is in core (in the inode structure),
* "cannot happen"
*/
struct inode *
-iget(dev, ino)
+iget(dev, fs, ino)
dev_t dev;
+ register struct fs *fs;
ino_t ino;
{
register struct inode *ip;
register int slot;
loop:
+ if (getfs(dev) != fs)
+ panic("iget: bad fs");
slot = INOHASH(dev, ino);
ip = &inode[inohash[slot]];
while (ip != &inode[-1]) {
goto loop;
}
if ((ip->i_flag&IMOUNT) != 0) {
- for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+ for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
if (mp->m_inodp == ip) {
dev = mp->m_dev;
+ fs = mp->m_bufp->b_un.b_fs;
ino = ROOTINO;
goto loop;
}
ip->i_hlink = inohash[slot];
inohash[slot] = ip - inode;
ip->i_dev = dev;
+ ip->i_fs = fs;
ip->i_number = ino;
ip->i_flag = ILOCK;
ip->i_count++;
- ip->i_un.i_lastr = 0;
- bp = bread(dev, itod(ino));
+ ip->i_lastr = 0;
+ bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize);
/*
* Check I/O errors
*/
return(NULL);
}
dp = bp->b_un.b_dino;
- dp += itoo(ino);
- iexpand(ip, dp);
+ dp += itoo(fs, ino);
+ ip->i_ic = dp->di_ic;
brelse(bp);
- return(ip);
-}
-
-iexpand(ip, dp)
- register struct inode *ip;
- register struct dinode *dp;
-{
- register char *p1, *p2;
- register int i;
-
- ip->i_mode = dp->di_mode;
- ip->i_nlink = dp->di_nlink;
- ip->i_uid = dp->di_uid;
- ip->i_gid = dp->di_gid;
- ip->i_size = dp->di_size;
- p1 = (char *)ip->i_un.i_addr;
- p2 = (char *)dp->di_addr;
- for(i=0; i<NADDR; i++) {
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = 0;
- }
+ return (ip);
}
/*
{
register int i, x;
register struct inode *jp;
+ int mode;
if (ip->i_count == 1) {
ip->i_flag |= ILOCK;
if (ip->i_nlink <= 0) {
itrunc(ip);
+ mode = ip->i_mode;
ip->i_mode = 0;
ip->i_flag |= IUPD|ICHG;
- ifree(ip->i_dev, ip->i_number);
+ ifree(ip, ip->i_number, mode);
}
IUPDAT(ip, &time, &time, 0);
irele(ip);
{
register struct buf *bp;
struct dinode *dp;
- register char *p1, *p2;
- register int i;
+ register struct fs *fp;
- if ((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
- if (getfs(ip->i_dev)->s_ronly)
+ fp = ip->i_fs;
+ if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
+ if (fp->fs_ronly)
return;
- bp = bread(ip->i_dev, itod(ip->i_number));
+ bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
+ fp->fs_bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
return;
}
- dp = bp->b_un.b_dino;
- dp += itoo(ip->i_number);
- dp->di_mode = ip->i_mode;
- dp->di_nlink = ip->i_nlink;
- dp->di_uid = ip->i_uid;
- dp->di_gid = ip->i_gid;
- dp->di_size = ip->i_size;
- p1 = (char *)dp->di_addr;
- p2 = (char *)ip->i_un.i_addr;
- for(i=0; i<NADDR; i++) {
- *p1++ = *p2++;
- *p1++ = *p2++;
- *p1++ = *p2++;
- if (*p2++ != 0)
- printf("iaddress > 2^24\n");
- }
if (ip->i_flag&IACC)
- dp->di_atime = *ta;
+ ip->i_atime = *ta;
if (ip->i_flag&IUPD)
- dp->di_mtime = *tm;
+ ip->i_mtime = *tm;
if (ip->i_flag&ICHG)
- dp->di_ctime = time;
+ ip->i_ctime = time;
ip->i_flag &= ~(IUPD|IACC|ICHG);
+ dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
+ dp->di_ic = ip->i_ic;
if (waitfor)
bwrite(bp);
else
dev_t dev;
daddr_t bn;
struct inode itmp;
+ register struct fs *fs;
i = ip->i_mode & IFMT;
- if (i!=IFREG && i!=IFDIR && i!=IFLNK)
+ if (i != IFREG && i != IFDIR && i != IFLNK)
return;
-
/*
* Clean inode on disk before freeing blocks
* to insure no duplicates if system crashes.
*/
itmp = *ip;
itmp.i_size = 0;
- for (i = 0; i < NADDR; i++)
- itmp.i_un.i_addr[i] = 0;
+ for (i = 0; i < NDADDR; i++)
+ itmp.i_db[i] = 0;
+ for (i = 0; i < NIADDR; i++)
+ itmp.i_ib[i] = 0;
itmp.i_flag |= ICHG|IUPD;
iupdat(&itmp, &time, &time, 1);
ip->i_flag &= ~(IUPD|IACC|ICHG);
* crashes, they will be harmless MISSING blocks.
*/
dev = ip->i_dev;
- for(i=NADDR-1; i>=0; i--) {
- bn = ip->i_un.i_addr[i];
+ fs = ip->i_fs;
+ /*
+ * release double indirect block first
+ */
+ bn = ip->i_ib[NIADDR-1];
+ if (bn != (daddr_t)0) {
+ ip->i_ib[NIADDR - 1] = (daddr_t)0;
+ tloop(ip, bn, 1);
+ }
+ /*
+ * release single indirect blocks second
+ */
+ for (i = NIADDR - 2; i >= 0; i--) {
+ bn = ip->i_ib[i];
+ if (bn != (daddr_t)0) {
+ ip->i_ib[i] = (daddr_t)0;
+ tloop(ip, bn, 0);
+ }
+ }
+ /*
+ * finally release direct blocks
+ */
+ for (i = NDADDR - 1; i>=0; i--) {
+ bn = ip->i_db[i];
if (bn == (daddr_t)0)
continue;
- ip->i_un.i_addr[i] = (daddr_t)0;
- switch(i) {
-
- default:
- free(dev, bn);
- break;
-
- case NADDR-3:
- tloop(dev, bn, 0, 0);
- break;
-
- case NADDR-2:
- tloop(dev, bn, 1, 0);
- break;
-
- case NADDR-1:
- tloop(dev, bn, 1, 1);
- }
+ ip->i_db[i] = (daddr_t)0;
+ fre(ip, bn, (off_t)blksize(fs, ip, i));
}
ip->i_size = 0;
/*
*/
}
-tloop(dev, bn, f1, f2)
-dev_t dev;
-daddr_t bn;
+tloop(ip, bn, indflg)
+ register struct inode *ip;
+ daddr_t bn;
+ int indflg;
{
register i;
register struct buf *bp;
register daddr_t *bap;
+ register struct fs *fs;
daddr_t nb;
bp = NULL;
- for(i=NINDIR-1; i>=0; i--) {
+ fs = ip->i_fs;
+ for (i = NINDIR(fs) - 1; i >= 0; i--) {
if (bp == NULL) {
- bp = bread(dev, bn);
+ bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
return;
nb = bap[i];
if (nb == (daddr_t)0)
continue;
- if (f1) {
- brelse(bp);
- bp = NULL;
- tloop(dev, nb, f2, 0);
- } else
- free(dev, nb);
+ if (indflg)
+ tloop(ip, nb, 0);
+ else
+ fre(ip, nb, fs->fs_bsize);
}
if (bp != NULL)
brelse(bp);
- free(dev, bn);
+ fre(ip, bn, fs->fs_bsize);
}
/*
*/
struct inode *
maknode(mode)
+ int mode;
{
register struct inode *ip;
+ ino_t ipref;
- ip = ialloc(u.u_pdir->i_dev);
+ if ((mode & IFMT) == IFDIR)
+ ipref = dirpref(u.u_pdir->i_fs);
+ else
+ ipref = u.u_pdir->i_number;
+ ip = ialloc(u.u_pdir, ipref, mode);
if (ip == NULL) {
iput(u.u_pdir);
return(NULL);
}
ip->i_flag |= IACC|IUPD|ICHG;
- if ((mode&IFMT) == 0)
+ if ((mode & IFMT) == 0)
mode |= IFREG;
ip->i_mode = mode & ~u.u_cmask;
ip->i_nlink = 1;
* Make sure inode goes to disk before directory entry.
*/
iupdat(ip, &time, &time, 1);
-
wdir(ip);
+ if (u.u_error) {
+ /*
+ * write error occurred trying to update directory
+ * so must deallocate the inode
+ */
+ ip->i_nlink = 0;
+ ip->i_flag |= ICHG;
+ iput(ip);
+ return(NULL);
+ }
return(ip);
}
wdir(ip)
struct inode *ip;
{
+ register struct direct *dp, *ndp;
+ struct fs *fs;
+ struct buf *bp;
+ int lbn, bn, base;
+ int loc, dsize, spccnt, newsize;
+ char *dirbuf;
u.u_dent.d_ino = ip->i_number;
- bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
- u.u_count = sizeof(struct direct);
u.u_segflg = 1;
- u.u_base = (caddr_t)&u.u_dent;
- writei(u.u_pdir);
+ newsize = DIRSIZ(&u.u_dent);
+ /*
+ * if u.u_count == 0, a new directory block must be allocated.
+ */
+ if (u.u_count == 0) {
+ u.u_dent.d_reclen = DIRBLKSIZ;
+ u.u_count = newsize;
+ u.u_base = (caddr_t)&u.u_dent;
+ writei(u.u_pdir);
+ iput(u.u_pdir);
+ return;
+ }
+ /*
+ * must read in an existing directory block
+ * to prepare to place the new entry into it.
+ */
+ fs = u.u_pdir->i_fs;
+ lbn = lblkno(fs, u.u_offset);
+ base = blkoff(fs, u.u_offset);
+ bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
+ if (u.u_offset + u.u_count > u.u_pdir->i_size)
+ u.u_pdir->i_size = u.u_offset + u.u_count;
+ bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
+ if (bp->b_flags & B_ERROR) {
+ brelse(bp);
+ return;
+ }
+ dirbuf = bp->b_un.b_addr + base;
+ dp = (struct direct *)dirbuf;
+ dsize = DIRSIZ(dp);
+ spccnt = dp->d_reclen - dsize;
+ /*
+ * if there is insufficient room to make an entry at this point
+ * namei insures that compacting from u.u_offset for u.u_count
+ * bytes will provide the necessary space.
+ */
+ for (loc = dp->d_reclen; loc < u.u_count; ) {
+ ndp = (struct direct *)(dirbuf + loc);
+ if (dp->d_ino == 0) {
+ spccnt += dsize;
+ } else {
+ dp->d_reclen = dsize;
+ dp = (struct direct *)((char *)dp + dsize);
+ }
+ dsize = DIRSIZ(ndp);
+ spccnt += ndp->d_reclen - dsize;
+ loc += ndp->d_reclen;
+ bcopy(ndp, dp, dsize);
+ }
+ /*
+ * Update the pointer fields in the previous entry (if any),
+ * copy in the new entry, and write out the block.
+ */
+ if (dp->d_ino == 0) {
+ if (spccnt + dsize < newsize)
+ panic("wdir: compact failed");
+ u.u_dent.d_reclen = spccnt + dsize;
+ } else {
+ if (spccnt < newsize)
+ panic("wdir: compact failed");
+ u.u_dent.d_reclen = spccnt;
+ dp->d_reclen = dsize;
+ dp = (struct direct *)((char *)dp + dsize);
+ }
+ bcopy(&u.u_dent, dp, newsize);
+ bwrite(bp);
+ u.u_pdir->i_flag |= IUPD|ICHG;
iput(u.u_pdir);
}
-/* ufs_lookup.c 4.14 82/03/31 */
+/* ufs_lookup.c 4.15 82/04/19 */
+
+/* merged into kernel: @(#)nami.c 2.3 4/8/82 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/inode.h"
+#include "../h/fs.h"
#include "../h/mount.h"
#include "../h/dir.h"
#include "../h/user.h"
register char *cp;
register struct buf *bp, *nbp;
register struct direct *ep;
+ register struct fs *fs;
struct inode *pdp;
- int i, nlink;
+ enum {NONE, COMPACT, FOUND} slot;
+ int entryfree, entrysize;
+ int spccnt, size, newsize;
+ int loc, prevoff, curoff;
+ int i, nlink, bsize;
+ unsigned pathlen;
+ daddr_t lbn, bn;
dev_t d;
- off_t eo;
/*
* allocate name buffer; copy name
*/
- nbp = geteblk();
+ nbp = geteblk(MAXPATHLEN);
nlink = 0;
- for (i=0, cp = nbp->b_un.b_addr; *cp = (*func)(); i++) {
- if ((*cp&0377) == ('/'|0200)) {
+ for (i = 0, cp = nbp->b_un.b_addr; *cp = (*func)(); i++) {
+ if ((*cp & 0377) == ('/'|0200)) {
u.u_error = EPERM;
break;
}
#ifdef notdef
- if (*cp++&0200 && flag==1 || cp >= nbp->b_un.b_addr+BSIZE) {
+ if (*cp++ & 0200 && flag == 1 ||
+ cp >= nbp->b_un.b_addr + MAXPATHLEN) {
#else
cp++;
- if (cp >= nbp->b_un.b_addr+BSIZE) {
+ if (cp >= nbp->b_un.b_addr + MAXPATHLEN) {
#endif
u.u_error = ENOENT;
break;
}
}
if (u.u_error) {
- dp = NULL;
- goto out1;
+ brelse(nbp);
+ return (NULL);
}
cp = nbp->b_un.b_addr;
/*
}
ilock(dp);
dp->i_count++;
-
+ fs = dp->i_fs;
+ newsize = 0;
+dirloop:
/*
* dp must be a directory and
* must have X permission.
* cp is a path name relative to that directory.
*/
-
-dirloop:
if ((dp->i_mode&IFMT) != IFDIR)
u.u_error = ENOTDIR;
(void) access(dp, IEXEC);
dirloop2:
- for (i=0; *cp!='\0' && *cp!='/'; i++) {
+ for (i = 0; *cp != '\0' && *cp != '/'; cp++) {
#ifdef notdef
- if (i >= DIRSIZ) {
+ if (i >= MAXNAMLEN) {
u.u_error = ENOENT;
break;
}
- u.u_dbuf[i] = *cp++;
+ u.u_dent.d_name[i] = *cp;
#else
- if (i < DIRSIZ)
- u.u_dbuf[i] = *cp;
- cp++;
+ if (i < MAXNAMLEN) {
+ u.u_dent.d_name[i] = *cp;
+ i++;
+ }
#endif
}
- if (u.u_error)
- goto out;
+ if (u.u_error) {
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
+ }
+ u.u_dent.d_namlen = i;
+ u.u_dent.d_name[i] = '\0';
+ newsize = DIRSIZ(&u.u_dent);
u.u_pdir = dp;
- while (i < DIRSIZ)
- u.u_dbuf[i++] = '\0';
- if (u.u_dbuf[0] == '\0') { /* null name, e.g. "/" or "" */
- if (flag) {
+ if (u.u_dent.d_name[0] == '\0') { /* null name, e.g. "/" or "" */
+ if (flag != 0) {
u.u_error = ENOENT;
- goto out;
+ iput(dp);
+ dp = NULL;
}
- goto out1;
+ u.u_offset = 0;
+ u.u_count = newsize;
+ brelse(nbp);
+ return (dp);
}
+ /*
+ * set up to search a directory
+ */
+ if (flag == 1)
+ slot = NONE;
+ else
+ slot = FOUND;
+ u.u_offset = 0;
u.u_segflg = 1;
- eo = -1;
bp = NULL;
-
- for (u.u_offset=0; u.u_offset < dp->i_size;
- u.u_offset += sizeof(struct direct), ep++) {
+ spccnt = 0;
+ loc = 0;
+ while (u.u_offset < dp->i_size) {
+ /*
+ * check to see if enough space has been accumulated to make
+ * an entry by compaction. Reset the free space counter each
+ * time a directory block is crossed.
+ */
+ if (slot == NONE) {
+ if (spccnt >= newsize) {
+ slot = COMPACT;
+ entrysize = u.u_offset - entryfree;
+ } else if (loc % DIRBLKSIZ == 0) {
+ entryfree = NULL;
+ spccnt = 0;
+ }
+ }
/*
* If offset is on a block boundary,
* read the next directory block.
* Release previous if it exists.
*/
- if ((u.u_offset&BMASK) == 0) {
+ if (blkoff(fs, u.u_offset) == 0) {
if (bp != NULL)
brelse(bp);
- bp = bread(dp->i_dev,
- bmap(dp,(daddr_t)(u.u_offset>>BSHIFT), B_READ));
+ lbn = (daddr_t)lblkno(fs, u.u_offset);
+ bsize = blksize(fs, dp, lbn);
+ if ((bn = bmap(dp, lbn, B_READ)) < 0) {
+ printf("hole in dir: %s i = %d\n",
+ fs->fs_fsmnt, dp->i_number);
+ if (fs->fs_ronly != 0 ||
+ (bn = bmap(dp, lbn, B_WRITE, bsize)) < 0) {
+ u.u_offset += bsize;
+ bp = NULL;
+ continue;
+ }
+ }
+ bp = bread(dp->i_dev, fsbtodb(fs, bn), bsize);
if (bp->b_flags & B_ERROR) {
brelse(bp);
- goto out;
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
+ }
+ loc = 0;
+ } else {
+ loc += ep->d_reclen;
+ }
+ /*
+ * calculate the next directory entry and run
+ * some rudimentary bounds checks to make sure
+ * that it is reasonable. If the check fails
+ * resync at the beginning of the next directory
+ * block.
+ */
+ ep = (struct direct *)(bp->b_un.b_addr + loc);
+ i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
+ if (ep->d_reclen <= 0 || ep->d_reclen > i) {
+ loc += i;
+ u.u_offset += i;
+ continue;
+ }
+ /*
+ * If an appropriate sized hole has not yet been found,
+ * check to see if one is available. Also accumulate space
+ * in the current block so that we can determine if
+ * compaction is viable.
+ */
+ if (slot != FOUND) {
+ size = ep->d_reclen;
+ if (ep->d_ino != 0)
+ size -= DIRSIZ(ep);
+ if (size > 0) {
+ if (size >= newsize) {
+ slot = FOUND;
+ entryfree = u.u_offset;
+ entrysize = DIRSIZ(ep) + newsize;
+ }
+ if (entryfree == NULL)
+ entryfree = u.u_offset;
+ spccnt += size;
}
- ep = (struct direct *)bp->b_un.b_addr;
}
/*
- * Note first empty directory slot
- * in eo for possible creat.
* String compare the directory entry
* and the current component.
+ * If they do not match, continue to the next entry.
*/
- if (ep->d_ino == 0) {
- if (eo < 0)
- eo = u.u_offset;
+ prevoff = curoff;
+ curoff = u.u_offset;
+ u.u_offset += ep->d_reclen;
+ if (ep->d_ino == 0)
continue;
- }
- if (strncmp(u.u_dbuf, ep->d_name, DIRSIZ) != 0)
+ if (ep->d_namlen != u.u_dent.d_namlen)
+ continue;
+ if (bcmp(u.u_dent.d_name, ep->d_name, ep->d_namlen))
continue;
/*
* Here a component matched in a directory.
* If there is more pathname, go back to
* dirloop, otherwise return.
*/
- bcopy((caddr_t)ep, (caddr_t)&u.u_dent, sizeof(struct direct));
+ bcopy((caddr_t)ep, (caddr_t)&u.u_dent, DIRSIZ(ep));
brelse(bp);
- if (flag==2 && *cp=='\0') {
- if (access(dp, IWRITE))
- goto out;
- /* should fix unlink */
- u.u_offset += sizeof(struct direct);
- goto out1;
+ if (flag == 2 && *cp == '\0') {
+ brelse(nbp);
+ if (access(dp, IWRITE)) {
+ iput(dp);
+ return (NULL);
+ }
+ if (curoff % DIRBLKSIZ == 0) {
+ u.u_offset = curoff;
+ u.u_count = 0;
+ return (dp);
+ }
+ u.u_offset = prevoff;
+ u.u_count = DIRSIZ((struct direct *)
+ (bp->b_un.b_addr + blkoff(fs, prevoff)));
+ return (dp);
}
/*
* Special handling for ".."
*/
- if (u.u_dent.d_name[0]=='.' && u.u_dent.d_name[1]=='.' &&
- u.u_dent.d_name[2]=='\0') {
+ if (u.u_dent.d_name[0] == '.' && u.u_dent.d_name[1] == '.' &&
+ u.u_dent.d_name[2] == '\0') {
if (dp == u.u_rdir)
u.u_dent.d_ino = dp->i_number;
- else if (u.u_dent.d_ino==ROOTINO &&
+ else if (u.u_dent.d_ino == ROOTINO &&
dp->i_number == ROOTINO) {
- for(i=1; i<NMOUNT; i++)
+ for (i = 1; i < NMOUNT; i++)
if (mount[i].m_bufp != NULL &&
mount[i].m_dev == dp->i_dev) {
iput(dp);
dp = mount[i].m_inodp;
ilock(dp);
dp->i_count++;
+ fs = dp->i_fs;
cp -= 2; /* back over .. */
goto dirloop2;
}
d = dp->i_dev;
irele(dp);
pdp = dp;
- dp = iget(d, u.u_dent.d_ino);
+ dp = iget(d, fs, u.u_dent.d_ino);
if (dp == NULL) {
iput(pdp);
- goto out1;
+ brelse(nbp);
+ return (NULL);
}
+ fs = dp->i_fs;
/*
* Check for symbolic link
*/
- if ((dp->i_mode&IFMT)==IFLNK && (follow || *cp=='/')) {
- char *ocp;
-
- ocp = cp;
- while (*cp++)
- ;
- if (dp->i_size + (cp-ocp) >= BSIZE-1 || ++nlink>8) {
+ if ((dp->i_mode & IFMT) == IFLNK && (follow || *cp == '/')) {
+ pathlen = strlen(cp) + 1;
+ if (dp->i_size + pathlen >= MAXPATHLEN - 1 ||
+ ++nlink > MAXSYMLINKS) {
u.u_error = ELOOP;
iput(pdp);
- goto out;
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
}
- bcopy(ocp, nbp->b_un.b_addr+dp->i_size,
- (unsigned)(cp-ocp));
- bp = bread(dp->i_dev, bmap(dp, (daddr_t)0, B_READ));
+ bcopy(cp, nbp->b_un.b_addr + dp->i_size, pathlen);
+ bn = bmap(dp, (daddr_t)0, B_READ);
+ if (bn < 0) {
+ printf("hole in symlink: %s i = %d\n",
+ fs->fs_fsmnt, dp->i_number);
+ iput(pdp);
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
+ }
+ bp = bread(dp->i_dev, fsbtodb(fs, bn),
+ (int)blksize(fs, dp, (daddr_t)0));
if (bp->b_flags & B_ERROR) {
brelse(bp);
iput(pdp);
- goto out;
+ iput(dp);
+ brelse(nbp);
+ return (NULL);
}
bcopy(bp->b_un.b_addr, nbp->b_un.b_addr,
(unsigned)dp->i_size);
dp = pdp;
ilock(dp);
}
+ fs = dp->i_fs;
goto dirloop;
}
iput(pdp);
cp++;
goto dirloop;
}
- goto out1;
+ /*
+ * End of path, so return name matched.
+ */
+ u.u_offset -= ep->d_reclen;
+ u.u_count = newsize;
+ brelse(nbp);
+ return (dp);
}
/*
* Search failed.
+ * Report what is appropriate as per flag.
*/
if (bp != NULL)
brelse(bp);
- if (flag==1 && *cp=='\0' && dp->i_nlink) {
- if (access(dp, IWRITE))
- goto out;
- if (eo>=0)
- u.u_offset = eo;
+ if (flag == 1 && *cp == '\0' && dp->i_nlink != 0) {
+ brelse(nbp);
+ if (access(dp, IWRITE)) {
+ iput(dp);
+ return (NULL);
+ }
+ if (slot == NONE) {
+ u.u_count = 0;
+ } else {
+ u.u_offset = entryfree;
+ u.u_count = entrysize;
+ }
dp->i_flag |= IUPD|ICHG;
- dp = NULL;
- goto out1;
+ return (NULL);
}
u.u_error = ENOENT;
-out:
iput(dp);
- dp = NULL;
-out1:
brelse(nbp);
- return (dp);
+ return (NULL);
}
/*
}
#ifndef vax
-strncmp(s1, s2, len)
+bcmp(s1, s2, len)
register char *s1, *s2;
- register len;
+ register int len;
{
- do {
- if (*s1 != *s2++)
+ while (--len)
+ if (*s1++ != *s2++)
return (1);
- if (*s1++ == '\0')
- return (0);
- } while (--len);
return (0);
}
+
+strlen(s1)
+ register char *s1;
+{
+ register int len;
+
+ for (len = 0; *s1++ != '\0'; len++)
+ /* void */;
+ return (len);
+}
#endif
-/* ufs_vnops.c 4.22 82/04/01 */
+/* ufs_vnops.c 4.23 82/04/19 */
+/* merged into kernel: @(#)sys3.c 2.2 4/8/82 */
+
+#ifdef SIMFS
+#include "../h/sysrenam.h"
+#endif
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
-#include "../h/reg.h"
#include "../h/file.h"
+#include "../h/stat.h"
#include "../h/inode.h"
-#include "../h/ino.h"
-#include "../h/pte.h"
-#include "../h/vm.h"
+#include "../h/fs.h"
#include "../h/buf.h"
-#include "../h/mtpr.h"
#include "../h/proc.h"
#include "../h/inline.h"
-#include "../h/conf.h"
-#include "../h/socket.h"
-#include "../h/socketvar.h"
-#include "../h/stat.h"
chdir()
{
* Want to be able to use this to make badblock
* inodes, so don't truncate the dev number.
*/
- ip->i_un.i_rdev = uap->dev;
+ ip->i_rdev = uap->dev;
ip->i_flag |= IACC|IUPD|ICHG;
}
struct a {
char *fname;
};
+ struct fs *fs;
+ struct buf *bp;
+ int lbn, bn, base;
pp = namei(uchar, 2, 0);
if(pp == NULL)
ip = pp;
ip->i_count++;
} else
- ip = iget(pp->i_dev, u.u_dent.d_ino);
+ ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
if(ip == NULL)
goto out1;
if((ip->i_mode&IFMT)==IFDIR && !suser())
goto out;
}
*/
- u.u_offset -= sizeof(struct direct);
- u.u_base = (caddr_t)&u.u_dent;
- u.u_count = sizeof(struct direct);
- u.u_dent.d_ino = 0;
- writei(pp);
+ if (u.u_count == 0) {
+ /*
+ * first entry in block, so set d_ino to zero.
+ */
+ u.u_base = (caddr_t)&u.u_dent;
+ u.u_count = DIRSIZ(&u.u_dent);
+ u.u_dent.d_ino = 0;
+ writei(pp);
+ } else {
+ /*
+ * updating preceeding entry to skip over current entry.
+ */
+ fs = pp->i_fs;
+ lbn = lblkno(fs, u.u_offset);
+ base = blkoff(fs, u.u_offset);
+ bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count));
+ bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn));
+ if (bp->b_flags & B_ERROR) {
+ brelse(bp);
+ goto out;
+ }
+ ((struct direct *)(bp->b_un.b_addr + base))->d_reclen +=
+ u.u_dent.d_reclen;
+ bwrite(bp);
+ pp->i_flag |= IUPD|ICHG;
+ }
ip->i_nlink--;
ip->i_flag |= ICHG;
}
/*
- * Stat system call; this follows links.
+ * Stat system call. This version follows links.
*/
stat()
{
}
/*
- * Lstat system call; like stat but doesn't follow links.
+ * Lstat system call. This version does not follow links.
*/
lstat()
{
register struct inode *ip;
struct stat *ub;
{
- register struct dinode *dp;
- register struct buf *bp;
struct stat ds;
IUPDAT(ip, &time, &time, 0);
ds.st_nlink = ip->i_nlink;
ds.st_uid = ip->i_uid;
ds.st_gid = ip->i_gid;
- ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+ ds.st_rdev = (dev_t)ip->i_rdev;
ds.st_size = ip->i_size;
- /*
- * next the dates in the disk
- */
- bp = bread(ip->i_dev, itod(ip->i_number));
- dp = bp->b_un.b_dino;
- dp += itoo(ip->i_number);
- ds.st_atime = dp->di_atime;
- ds.st_mtime = dp->di_mtime;
- ds.st_ctime = dp->di_ctime;
- brelse(bp);
+ ds.st_atime = ip->i_atime;
+ ds.st_mtime = ip->i_mtime;
+ ds.st_ctime = ip->i_ctime;
if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
u.u_error = EFAULT;
}