From: Kirk McKusick Date: Tue, 20 Apr 1982 10:37:01 +0000 (-0800) Subject: merge into new file system X-Git-Tag: BSD-4_1c_2-Snapshot-Development~3614 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/6459ebe02c8462c90494d12e080fe0c4952ff0c0 merge into new file system SCCS-vsn: sys/ufs/ffs/ffs_alloc.c 2.4 SCCS-vsn: sys/ufs/lfs/lfs_alloc.c 2.4 SCCS-vsn: sys/kern/kern_proc.c 4.26 SCCS-vsn: sys/kern/vfs_vnops.c 4.23 SCCS-vsn: sys/ufs/ffs/ffs_inode.c 4.10 SCCS-vsn: sys/ufs/ffs/ufs_inode.c 4.10 SCCS-vsn: sys/ufs/lfs/lfs_inode.c 4.10 SCCS-vsn: sys/ufs/ufs/ufs_inode.c 4.10 SCCS-vsn: sys/kern/init_main.c 4.29 SCCS-vsn: sys/kern/vfs_lookup.c 4.15 SCCS-vsn: sys/ufs/ffs/ufs_lookup.c 4.15 SCCS-vsn: sys/ufs/ufs/ufs_lookup.c 4.15 SCCS-vsn: sys/ufs/ffs/ffs_tables.c 2.2 SCCS-vsn: sys/kern/subr_xxx.c 4.10 SCCS-vsn: sys/kern/vfs_syscalls.c 4.23 SCCS-vsn: sys/ufs/ffs/ffs_vnops.c 4.23 SCCS-vsn: sys/ufs/ffs/ufs_vnops.c 4.23 SCCS-vsn: sys/ufs/lfs/lfs_vnops.c 4.23 SCCS-vsn: sys/ufs/ufs/ufs_vnops.c 4.23 --- diff --git a/usr/src/sys/kern/init_main.c b/usr/src/sys/kern/init_main.c index 5c6fee08de..ec291d886e 100644 --- a/usr/src/sys/kern/init_main.c +++ b/usr/src/sys/kern/init_main.c @@ -1,10 +1,10 @@ -/* 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" @@ -45,6 +45,7 @@ main(firstaddr) { register int i; register struct proc *p; + struct fs *fsp; rqinit(); #include "loop.h" @@ -96,9 +97,10 @@ main(firstaddr) 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; @@ -159,28 +161,39 @@ main(firstaddr) 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); + } } /* @@ -200,10 +213,11 @@ binit() dp->b_flags = B_HEAD; } dp--; /* dp = &bfreelist[BQUEUES-1]; */ - for (i=0; ib_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; diff --git a/usr/src/sys/kern/kern_proc.c b/usr/src/sys/kern/kern_proc.c index 53cab4f7c7..f3a38bc524 100644 --- a/usr/src/sys/kern/kern_proc.c +++ b/usr/src/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* kern_proc.c 4.25 82/04/02 */ +/* kern_proc.c 4.26 82/04/19 */ #include "../h/param.h" #include "../h/systm.h" @@ -46,7 +46,7 @@ exece() 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) @@ -151,7 +151,8 @@ exece() 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); @@ -188,7 +189,7 @@ exece() uap->envp++; ne++; } - if (ap==NULL) + if (ap == NULL) break; na++; if (ap == -1) @@ -206,28 +207,31 @@ exece() 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); @@ -254,11 +258,11 @@ badarg: 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; @@ -435,7 +439,8 @@ setregs() * 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); } /* diff --git a/usr/src/sys/kern/subr_xxx.c b/usr/src/sys/kern/subr_xxx.c index 2579f9f1bb..09c8fec942 100644 --- a/usr/src/sys/kern/subr_xxx.c +++ b/usr/src/sys/kern/subr_xxx.c @@ -1,4 +1,6 @@ -/* 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" @@ -8,6 +10,7 @@ #include "../h/user.h" #include "../h/buf.h" #include "../h/proc.h" +#include "../h/fs.h" /* * Bmap defines the structure of file system storage @@ -17,34 +20,79 @@ * 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 @@ -54,72 +102,79 @@ daddr_t bn; 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 @@ -137,9 +192,9 @@ daddr_t bn; /* * calculate read-ahead. */ - if(i < NINDIR-1) + if (i < NINDIR(fs) - 1) rablock = bap[i+1]; - return(nb); + return (nb); } /* @@ -153,17 +208,17 @@ register c; { 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" @@ -179,19 +234,19 @@ cpass() { 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 @@ -226,6 +281,22 @@ imax(a, b) 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; diff --git a/usr/src/sys/kern/vfs_lookup.c b/usr/src/sys/kern/vfs_lookup.c index 8c5a98ba5a..c861d1a563 100644 --- a/usr/src/sys/kern/vfs_lookup.c +++ b/usr/src/sys/kern/vfs_lookup.c @@ -1,8 +1,11 @@ -/* 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" @@ -29,34 +32,41 @@ namei(func, flag, follow) 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; /* @@ -72,108 +82,199 @@ namei(func, flag, follow) } 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; ii_dev) { iput(dp); dp = mount[i].m_inodp; ilock(dp); dp->i_count++; + fs = dp->i_fs; cp -= 2; /* back over .. */ goto dirloop2; } @@ -182,32 +283,44 @@ 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); @@ -226,6 +339,7 @@ dirloop2: dp = pdp; ilock(dp); } + fs = dp->i_fs; goto dirloop; } iput(pdp); @@ -234,29 +348,39 @@ dirloop2: 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); } /* @@ -286,17 +410,24 @@ uchar() } #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 diff --git a/usr/src/sys/kern/vfs_syscalls.c b/usr/src/sys/kern/vfs_syscalls.c index 70204a00f2..78a31c0aff 100644 --- a/usr/src/sys/kern/vfs_syscalls.c +++ b/usr/src/sys/kern/vfs_syscalls.c @@ -1,23 +1,21 @@ -/* 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() { @@ -174,7 +172,7 @@ mknod() * 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; } @@ -282,6 +280,9 @@ unlink() struct a { char *fname; }; + struct fs *fs; + struct buf *bp; + int lbn, bn, base; pp = namei(uchar, 2, 0); if(pp == NULL) @@ -294,7 +295,7 @@ unlink() 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()) @@ -314,11 +315,32 @@ unlink() 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; @@ -409,7 +431,7 @@ fstat() } /* - * Stat system call; this follows links. + * Stat system call. This version follows links. */ stat() { @@ -428,7 +450,7 @@ stat() } /* - * Lstat system call; like stat but doesn't follow links. + * Lstat system call. This version does not follow links. */ lstat() { @@ -454,8 +476,6 @@ stat1(ip, ub) register struct inode *ip; struct stat *ub; { - register struct dinode *dp; - register struct buf *bp; struct stat ds; IUPDAT(ip, &time, &time, 0); @@ -468,18 +488,11 @@ stat1(ip, ub) 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; } diff --git a/usr/src/sys/kern/vfs_vnops.c b/usr/src/sys/kern/vfs_vnops.c index 67693a47c9..26b82b4bf9 100644 --- a/usr/src/sys/kern/vfs_vnops.c +++ b/usr/src/sys/kern/vfs_vnops.c @@ -1,10 +1,12 @@ -/* 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" @@ -72,7 +74,7 @@ closef(fp, nouser) 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); @@ -101,7 +103,7 @@ closef(fp, nouser) 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) { @@ -126,7 +128,7 @@ openi(ip, rw) 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) { @@ -168,7 +170,7 @@ access(ip, mode) 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); } diff --git a/usr/src/sys/ufs/ffs/ffs_alloc.c b/usr/src/sys/ufs/ffs/ffs_alloc.c index 043f89bebf..4a4f00480c 100644 --- a/usr/src/sys/ufs/ffs/ffs_alloc.c +++ b/usr/src/sys/ufs/ffs/ffs_alloc.c @@ -1,8 +1,4 @@ -/* 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" @@ -11,7 +7,7 @@ #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(); @@ -70,7 +66,7 @@ alloc(ip, bpref, size) 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); @@ -99,7 +95,6 @@ realloccg(ip, bprev, bpref, osize, nsize) daddr_t bno; register struct fs *fs; register struct buf *bp, *obp; - caddr_t cp; int cg; fs = ip->i_fs; @@ -120,30 +115,24 @@ realloccg(ip, bprev, bpref, osize, nsize) 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: @@ -441,7 +430,7 @@ alloccg(ip, cg, bpref, size) 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); @@ -561,7 +550,7 @@ norot: * 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: @@ -660,8 +649,10 @@ fre(ip, bno, size) 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) { @@ -670,8 +661,10 @@ fre(ip, bno, size) } 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++; @@ -866,6 +859,7 @@ badblock(fs, bn) { if ((unsigned)bn >= fs->fs_size) { + printf("bad block %d, ", bn); fserr(fs, "bad block"); return (1); } diff --git a/usr/src/sys/ufs/ffs/ffs_inode.c b/usr/src/sys/ufs/ffs/ffs_inode.c index 0592361f9e..cb02dc3a9d 100644 --- a/usr/src/sys/ufs/ffs/ffs_inode.c +++ b/usr/src/sys/ufs/ffs/ffs_inode.c @@ -1,4 +1,6 @@ -/* 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" @@ -6,8 +8,7 @@ #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" @@ -34,25 +35,6 @@ ihinit() 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), @@ -69,8 +51,9 @@ ifind(dev, ino) * "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; @@ -80,6 +63,8 @@ iget(dev, ino) register int slot; loop: + if (getfs(dev) != fs) + panic("iget: bad fs"); slot = INOHASH(dev, ino); ip = &inode[inohash[slot]]; while (ip != &inode[-1]) { @@ -90,9 +75,10 @@ loop: 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; } @@ -114,11 +100,12 @@ 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 */ @@ -128,32 +115,10 @@ loop: 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; ii_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); @@ -217,40 +184,27 @@ iupdat(ip, ta, tm, waitfor) { 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 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 @@ -274,19 +228,21 @@ itrunc(ip) 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); @@ -296,28 +252,34 @@ itrunc(ip) * 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; /* @@ -326,19 +288,22 @@ itrunc(ip) */ } -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; @@ -348,16 +313,14 @@ daddr_t bn; 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); } /* @@ -365,16 +328,22 @@ daddr_t bn; */ 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; @@ -385,8 +354,17 @@ maknode(mode) * 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); } @@ -398,13 +376,82 @@ maknode(mode) 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); } diff --git a/usr/src/sys/ufs/ffs/ffs_tables.c b/usr/src/sys/ufs/ffs/ffs_tables.c index 73ca4c0b60..369dbe7585 100644 --- a/usr/src/sys/ufs/ffs/ffs_tables.c +++ b/usr/src/sys/ufs/ffs/ffs_tables.c @@ -1,6 +1,4 @@ -/* 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" diff --git a/usr/src/sys/ufs/ffs/ffs_vnops.c b/usr/src/sys/ufs/ffs/ffs_vnops.c index d8c6b823de..e0a24c5e6e 100644 --- a/usr/src/sys/ufs/ffs/ffs_vnops.c +++ b/usr/src/sys/ufs/ffs/ffs_vnops.c @@ -1,23 +1,21 @@ -/* 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() { @@ -174,7 +172,7 @@ mknod() * 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; } @@ -282,6 +280,9 @@ unlink() struct a { char *fname; }; + struct fs *fs; + struct buf *bp; + int lbn, bn, base; pp = namei(uchar, 2, 0); if(pp == NULL) @@ -294,7 +295,7 @@ unlink() 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()) @@ -314,11 +315,32 @@ unlink() 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; @@ -409,7 +431,7 @@ fstat() } /* - * Stat system call; this follows links. + * Stat system call. This version follows links. */ stat() { @@ -428,7 +450,7 @@ stat() } /* - * Lstat system call; like stat but doesn't follow links. + * Lstat system call. This version does not follow links. */ lstat() { @@ -454,8 +476,6 @@ stat1(ip, ub) register struct inode *ip; struct stat *ub; { - register struct dinode *dp; - register struct buf *bp; struct stat ds; IUPDAT(ip, &time, &time, 0); @@ -468,18 +488,11 @@ stat1(ip, ub) 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; } diff --git a/usr/src/sys/ufs/ffs/ufs_inode.c b/usr/src/sys/ufs/ffs/ufs_inode.c index bac9d12a04..c0d39c2026 100644 --- a/usr/src/sys/ufs/ffs/ufs_inode.c +++ b/usr/src/sys/ufs/ffs/ufs_inode.c @@ -1,4 +1,6 @@ -/* 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" @@ -6,8 +8,7 @@ #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" @@ -34,25 +35,6 @@ ihinit() 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), @@ -69,8 +51,9 @@ ifind(dev, ino) * "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; @@ -80,6 +63,8 @@ iget(dev, ino) register int slot; loop: + if (getfs(dev) != fs) + panic("iget: bad fs"); slot = INOHASH(dev, ino); ip = &inode[inohash[slot]]; while (ip != &inode[-1]) { @@ -90,9 +75,10 @@ loop: 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; } @@ -114,11 +100,12 @@ 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 */ @@ -128,32 +115,10 @@ loop: 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; ii_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); @@ -217,40 +184,27 @@ iupdat(ip, ta, tm, waitfor) { 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 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 @@ -274,19 +228,21 @@ itrunc(ip) 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); @@ -296,28 +252,34 @@ itrunc(ip) * 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; /* @@ -326,19 +288,22 @@ itrunc(ip) */ } -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; @@ -348,16 +313,14 @@ daddr_t bn; 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); } /* @@ -365,16 +328,22 @@ daddr_t bn; */ 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; @@ -385,8 +354,17 @@ maknode(mode) * 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); } @@ -398,13 +376,82 @@ maknode(mode) 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); } diff --git a/usr/src/sys/ufs/ffs/ufs_lookup.c b/usr/src/sys/ufs/ffs/ufs_lookup.c index cc4c3d3093..8f405429e5 100644 --- a/usr/src/sys/ufs/ffs/ufs_lookup.c +++ b/usr/src/sys/ufs/ffs/ufs_lookup.c @@ -1,8 +1,11 @@ -/* 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" @@ -29,34 +32,41 @@ namei(func, flag, follow) 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; /* @@ -72,108 +82,199 @@ namei(func, flag, follow) } 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; ii_dev) { iput(dp); dp = mount[i].m_inodp; ilock(dp); dp->i_count++; + fs = dp->i_fs; cp -= 2; /* back over .. */ goto dirloop2; } @@ -182,32 +283,44 @@ 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); @@ -226,6 +339,7 @@ dirloop2: dp = pdp; ilock(dp); } + fs = dp->i_fs; goto dirloop; } iput(pdp); @@ -234,29 +348,39 @@ dirloop2: 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); } /* @@ -286,17 +410,24 @@ uchar() } #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 diff --git a/usr/src/sys/ufs/ffs/ufs_vnops.c b/usr/src/sys/ufs/ffs/ufs_vnops.c index abc15ffa8c..8850d687a4 100644 --- a/usr/src/sys/ufs/ffs/ufs_vnops.c +++ b/usr/src/sys/ufs/ffs/ufs_vnops.c @@ -1,23 +1,21 @@ -/* 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() { @@ -174,7 +172,7 @@ mknod() * 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; } @@ -282,6 +280,9 @@ unlink() struct a { char *fname; }; + struct fs *fs; + struct buf *bp; + int lbn, bn, base; pp = namei(uchar, 2, 0); if(pp == NULL) @@ -294,7 +295,7 @@ unlink() 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()) @@ -314,11 +315,32 @@ unlink() 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; @@ -409,7 +431,7 @@ fstat() } /* - * Stat system call; this follows links. + * Stat system call. This version follows links. */ stat() { @@ -428,7 +450,7 @@ stat() } /* - * Lstat system call; like stat but doesn't follow links. + * Lstat system call. This version does not follow links. */ lstat() { @@ -454,8 +476,6 @@ stat1(ip, ub) register struct inode *ip; struct stat *ub; { - register struct dinode *dp; - register struct buf *bp; struct stat ds; IUPDAT(ip, &time, &time, 0); @@ -468,18 +488,11 @@ stat1(ip, ub) 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; } diff --git a/usr/src/sys/ufs/lfs/lfs_alloc.c b/usr/src/sys/ufs/lfs/lfs_alloc.c index a194ac1d58..8a54d05686 100644 --- a/usr/src/sys/ufs/lfs/lfs_alloc.c +++ b/usr/src/sys/ufs/lfs/lfs_alloc.c @@ -1,8 +1,4 @@ -/* 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" @@ -11,7 +7,7 @@ #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(); @@ -70,7 +66,7 @@ alloc(ip, bpref, size) 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); @@ -99,7 +95,6 @@ realloccg(ip, bprev, bpref, osize, nsize) daddr_t bno; register struct fs *fs; register struct buf *bp, *obp; - caddr_t cp; int cg; fs = ip->i_fs; @@ -120,30 +115,24 @@ realloccg(ip, bprev, bpref, osize, nsize) 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: @@ -441,7 +430,7 @@ alloccg(ip, cg, bpref, size) 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); @@ -561,7 +550,7 @@ norot: * 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: @@ -660,8 +649,10 @@ fre(ip, bno, size) 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) { @@ -670,8 +661,10 @@ fre(ip, bno, size) } 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++; @@ -866,6 +859,7 @@ badblock(fs, bn) { if ((unsigned)bn >= fs->fs_size) { + printf("bad block %d, ", bn); fserr(fs, "bad block"); return (1); } diff --git a/usr/src/sys/ufs/lfs/lfs_inode.c b/usr/src/sys/ufs/lfs/lfs_inode.c index 67ed51b810..8fc27d37ee 100644 --- a/usr/src/sys/ufs/lfs/lfs_inode.c +++ b/usr/src/sys/ufs/lfs/lfs_inode.c @@ -1,4 +1,6 @@ -/* 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" @@ -6,8 +8,7 @@ #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" @@ -34,25 +35,6 @@ ihinit() 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), @@ -69,8 +51,9 @@ ifind(dev, ino) * "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; @@ -80,6 +63,8 @@ iget(dev, ino) register int slot; loop: + if (getfs(dev) != fs) + panic("iget: bad fs"); slot = INOHASH(dev, ino); ip = &inode[inohash[slot]]; while (ip != &inode[-1]) { @@ -90,9 +75,10 @@ loop: 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; } @@ -114,11 +100,12 @@ 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 */ @@ -128,32 +115,10 @@ loop: 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; ii_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); @@ -217,40 +184,27 @@ iupdat(ip, ta, tm, waitfor) { 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 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 @@ -274,19 +228,21 @@ itrunc(ip) 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); @@ -296,28 +252,34 @@ itrunc(ip) * 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; /* @@ -326,19 +288,22 @@ itrunc(ip) */ } -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; @@ -348,16 +313,14 @@ daddr_t bn; 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); } /* @@ -365,16 +328,22 @@ daddr_t bn; */ 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; @@ -385,8 +354,17 @@ maknode(mode) * 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); } @@ -398,13 +376,82 @@ maknode(mode) 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); } diff --git a/usr/src/sys/ufs/lfs/lfs_vnops.c b/usr/src/sys/ufs/lfs/lfs_vnops.c index 5b0008a4d9..69dfa8d6c5 100644 --- a/usr/src/sys/ufs/lfs/lfs_vnops.c +++ b/usr/src/sys/ufs/lfs/lfs_vnops.c @@ -1,23 +1,21 @@ -/* 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() { @@ -174,7 +172,7 @@ mknod() * 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; } @@ -282,6 +280,9 @@ unlink() struct a { char *fname; }; + struct fs *fs; + struct buf *bp; + int lbn, bn, base; pp = namei(uchar, 2, 0); if(pp == NULL) @@ -294,7 +295,7 @@ unlink() 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()) @@ -314,11 +315,32 @@ unlink() 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; @@ -409,7 +431,7 @@ fstat() } /* - * Stat system call; this follows links. + * Stat system call. This version follows links. */ stat() { @@ -428,7 +450,7 @@ stat() } /* - * Lstat system call; like stat but doesn't follow links. + * Lstat system call. This version does not follow links. */ lstat() { @@ -454,8 +476,6 @@ stat1(ip, ub) register struct inode *ip; struct stat *ub; { - register struct dinode *dp; - register struct buf *bp; struct stat ds; IUPDAT(ip, &time, &time, 0); @@ -468,18 +488,11 @@ stat1(ip, ub) 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; } diff --git a/usr/src/sys/ufs/ufs/ufs_inode.c b/usr/src/sys/ufs/ufs/ufs_inode.c index bac9d12a04..c0d39c2026 100644 --- a/usr/src/sys/ufs/ufs/ufs_inode.c +++ b/usr/src/sys/ufs/ufs/ufs_inode.c @@ -1,4 +1,6 @@ -/* 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" @@ -6,8 +8,7 @@ #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" @@ -34,25 +35,6 @@ ihinit() 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), @@ -69,8 +51,9 @@ ifind(dev, ino) * "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; @@ -80,6 +63,8 @@ iget(dev, ino) register int slot; loop: + if (getfs(dev) != fs) + panic("iget: bad fs"); slot = INOHASH(dev, ino); ip = &inode[inohash[slot]]; while (ip != &inode[-1]) { @@ -90,9 +75,10 @@ loop: 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; } @@ -114,11 +100,12 @@ 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 */ @@ -128,32 +115,10 @@ loop: 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; ii_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); @@ -217,40 +184,27 @@ iupdat(ip, ta, tm, waitfor) { 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 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 @@ -274,19 +228,21 @@ itrunc(ip) 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); @@ -296,28 +252,34 @@ itrunc(ip) * 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; /* @@ -326,19 +288,22 @@ itrunc(ip) */ } -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; @@ -348,16 +313,14 @@ daddr_t bn; 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); } /* @@ -365,16 +328,22 @@ daddr_t bn; */ 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; @@ -385,8 +354,17 @@ maknode(mode) * 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); } @@ -398,13 +376,82 @@ maknode(mode) 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); } diff --git a/usr/src/sys/ufs/ufs/ufs_lookup.c b/usr/src/sys/ufs/ufs/ufs_lookup.c index cc4c3d3093..8f405429e5 100644 --- a/usr/src/sys/ufs/ufs/ufs_lookup.c +++ b/usr/src/sys/ufs/ufs/ufs_lookup.c @@ -1,8 +1,11 @@ -/* 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" @@ -29,34 +32,41 @@ namei(func, flag, follow) 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; /* @@ -72,108 +82,199 @@ namei(func, flag, follow) } 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; ii_dev) { iput(dp); dp = mount[i].m_inodp; ilock(dp); dp->i_count++; + fs = dp->i_fs; cp -= 2; /* back over .. */ goto dirloop2; } @@ -182,32 +283,44 @@ 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); @@ -226,6 +339,7 @@ dirloop2: dp = pdp; ilock(dp); } + fs = dp->i_fs; goto dirloop; } iput(pdp); @@ -234,29 +348,39 @@ dirloop2: 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); } /* @@ -286,17 +410,24 @@ uchar() } #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 diff --git a/usr/src/sys/ufs/ufs/ufs_vnops.c b/usr/src/sys/ufs/ufs/ufs_vnops.c index abc15ffa8c..8850d687a4 100644 --- a/usr/src/sys/ufs/ufs/ufs_vnops.c +++ b/usr/src/sys/ufs/ufs/ufs_vnops.c @@ -1,23 +1,21 @@ -/* 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() { @@ -174,7 +172,7 @@ mknod() * 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; } @@ -282,6 +280,9 @@ unlink() struct a { char *fname; }; + struct fs *fs; + struct buf *bp; + int lbn, bn, base; pp = namei(uchar, 2, 0); if(pp == NULL) @@ -294,7 +295,7 @@ unlink() 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()) @@ -314,11 +315,32 @@ unlink() 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; @@ -409,7 +431,7 @@ fstat() } /* - * Stat system call; this follows links. + * Stat system call. This version follows links. */ stat() { @@ -428,7 +450,7 @@ stat() } /* - * Lstat system call; like stat but doesn't follow links. + * Lstat system call. This version does not follow links. */ lstat() { @@ -454,8 +476,6 @@ stat1(ip, ub) register struct inode *ip; struct stat *ub; { - register struct dinode *dp; - register struct buf *bp; struct stat ds; IUPDAT(ip, &time, &time, 0); @@ -468,18 +488,11 @@ stat1(ip, ub) 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; }