-/* subr_xxx.c 4.10 82/04/19 */
-
-/* merged into kernel: @(#)subr.c 2.2 4/8/82 */
+/* subr_xxx.c 4.19 82/10/17 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/buf.h"
#include "../h/proc.h"
#include "../h/fs.h"
+#include "../h/vm.h"
+#include "../h/pte.h"
+#include "../h/cmap.h"
+#include "../h/uio.h"
/*
- * Bmap defines the structure of file system storage
- * by returning the physical block number on a device given the
- * inode and the logical block number in a file.
- * When convenient, it also leaves the physical
- * block number of the next block of the file in rablock
- * for use in read-ahead.
+ * Routine placed in illegal entries in the bdevsw and cdevsw tables.
*/
-/*VARARGS3*/
-daddr_t
-bmap(ip, bn, rwflg, size)
- register struct inode *ip;
- daddr_t bn;
- int rwflg;
- int size; /* supplied only when rwflg == B_WRITE */
+nodev()
{
- register int i;
- int osize, nsize;
- struct buf *bp, *nbp;
- struct fs *fs;
- int j, sh;
- daddr_t nb, *bap, pref, blkpref();
-
- if (bn < 0) {
- u.u_error = EFBIG;
- return ((daddr_t)0);
- }
- fs = ip->i_fs;
- rablock = 0;
- /*
- * 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.
- */
- 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_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
- * so they never appear with garbage in
- * them on the disk.
- */
- bwrite(bp);
- else
- bdwrite(bp);
- ip->i_db[i] = nb;
- ip->i_flag |= IUPD|ICHG;
- }
-gotit:
- if (i < NDADDR - 1)
- rablock = ip->i_db[i+1];
- return (nb);
- }
+ return (ENODEV);
+}
- /*
- * Determine how many levels of indirection.
- */
- sh = 1;
- bn -= NDADDR;
- for (j = NIADDR; j>0; j--) {
- sh *= NINDIR(fs);
- if (bn < sh)
- break;
- bn -= sh;
- }
- if (j == 0) {
- u.u_error = EFBIG;
- return ((daddr_t)0);
- }
+/*
+ * Null routine; placed in insignificant entries
+ * in the bdevsw and cdevsw tables.
+ */
+nulldev()
+{
- /*
- * fetch the first indirect block
- */
- 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_ib[NIADDR - j] = nb;
- ip->i_flag |= IUPD|ICHG;
- }
+ return (0);
+}
- /*
- * fetch through the indirect blocks
- */
- 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);
- }
- bap = bp->b_un.b_daddr;
- sh /= NINDIR(fs);
- i = (bn / sh) % NINDIR(fs);
- nb = bap[i];
- 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);
- }
- 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
- * in directories never contain garbage.
- */
- bwrite(nbp);
- else
- bdwrite(nbp);
- bap[i] = nb;
- bdwrite(bp);
- } else
- brelse(bp);
- }
+imin(a, b)
+{
- /*
- * calculate read-ahead.
- */
- if (i < NINDIR(fs) - 1)
- rablock = bap[i+1];
- return (nb);
+ return (a < b ? a : b);
}
-/*
- * Pass back c to the user at his location u_base;
- * update u_base, u_count, and u_offset. Return -1
- * on the last character of the user's read.
- * u_base is in the user address space unless u_segflg is set.
- */
-passc(c)
-register c;
+imax(a, b)
{
- register id;
- if ((id = u.u_segflg) == 1)
- *u.u_base = c;
- else
- if (id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) {
- u.u_error = EFAULT;
- return (-1);
- }
- u.u_count--;
- u.u_offset++;
- u.u_base++;
- return (u.u_count == 0? -1: 0);
+ return (a > b ? a : b);
}
-#include "ct.h"
-#if NCT > 0
-/*
- * Pick up and return the next character from the user's
- * write call at location u_base;
- * update u_base, u_count, and u_offset. Return -1
- * when u_count is exhausted. u_base is in the user's
- * address space unless u_segflg is set.
- */
-cpass()
+unsigned
+min(a, b)
+ u_int a, b;
{
- register c, id;
- 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) {
- u.u_error = EFAULT;
- return (-1);
- }
- u.u_count--;
- u.u_offset++;
- u.u_base++;
- return (c&0377);
+ return (a < b ? a : b);
}
-#endif
-/*
- * Routine which sets a user error; placed in
- * illegal entries in the bdevsw and cdevsw tables.
- */
-nodev()
+unsigned
+max(a, b)
+ u_int a, b;
{
- u.u_error = ENODEV;
+ return (a > b ? a : b);
}
+extern cabase, calimit;
+extern struct pte camap[];
+
+caddr_t cacur = (caddr_t)&cabase;
+caddr_t camax = (caddr_t)&cabase;
+int cax = 0;
/*
- * Null routine; placed in insignificant entries
- * in the bdevsw and cdevsw tables.
+ * This is a kernel-mode storage allocator.
+ * It is very primitive, currently, in that
+ * there is no way to give space back.
+ * It serves, for the time being, the needs of
+ * auto-configuration code and the like which
+ * need to allocate some stuff at boot time.
*/
-nulldev()
+caddr_t
+calloc(size)
+ int size;
{
+ register caddr_t res;
+ register int i;
+ if (cacur+size >= (caddr_t)&calimit)
+ panic("calloc");
+ while (cacur+size > camax) {
+ (void) vmemall(&camap[cax], CLSIZE, &proc[0], CSYS);
+ vmaccess(&camap[cax], camax, CLSIZE);
+ for (i = 0; i < CLSIZE; i++)
+ clearseg(camap[cax++].pg_pfnum);
+ camax += NBPG * CLSIZE;
+ }
+ res = cacur;
+ cacur += size;
+ return (res);
}
-imin(a, b)
+#ifndef vax
+ffs(mask)
+ register long mask;
{
+ register int i;
- return (a < b ? a : b);
+ for(i=1; i<NSIG; i++) {
+ if (mask & 1)
+ return (i);
+ mask >>= 1;
+ }
+ return (0);
}
-imax(a, b)
+ffs(mask)
+ register long mask;
{
+ register int i;
- return (a > b ? a : b);
+ for(i=1; i<NSIG; i++) {
+ if (mask & 1)
+ return (i);
+ mask >>= 1;
+ }
+ return (0);
}
-unsigned
-min(a, b)
- unsigned int a, b;
+bcmp(s1, s2, len)
+ register char *s1, *s2;
+ register int len;
{
- return (a < b ? a : b);
+ while (--len)
+ if (*s1++ != *s2++)
+ return (1);
+ return (0);
}
-unsigned
-max(a, b)
- unsigned int a, b;
+strlen(s1)
+ register char *s1;
{
+ register int len;
- return (a > b ? a : b);
+ for (len = 0; *s1++ != '\0'; len++)
+ /* void */;
+ return (len);
}
+#endif
-struct proc *
-pfind(pid)
- int pid;
+/*
+ * Pass back c to the user.
+ */
+passuc(c, uio)
+ register c;
+ struct uio *uio;
{
- register struct proc *p;
+ register struct iovec *iov = uio->uio_iov;
+
+ switch (uio->uio_segflg) {
- for (p = &proc[pidhash[PIDHASH(pid)]]; p != &proc[0]; p = &proc[p->p_idhash])
- if (p->p_pid == pid)
- return (p);
- return ((struct proc *)0);
+ case 0:
+ if (subyte(iov->iov_base, c) < 0)
+ goto fault;
+ break;
+
+ case 1:
+ *iov->iov_base = c;
+ break;
+
+ case 2:
+ if (suibyte(iov->iov_base, c) < 0)
+ goto fault;
+ break;
+ }
+ iov->iov_base++;
+ iov->iov_len--;
+ uio->uio_resid--;
+ uio->uio_offset++;
+ if (iov->iov_len <= 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ }
+ return (0);
+fault:
+ return (EFAULT);
}