From 072464b1987f27964703650957bbf91f8350ace1 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 11 Mar 1996 20:02:06 +0000 Subject: Import 4.4BSD-Lite2 onto the vendor branch, note that in the kernel, all files are off the vendor branch, so this should not change anything. A "U" marker generally means that the file was not changed in between the 4.4Lite and Lite-2 releases, and does not need a merge. "C" generally means that there was a change. [note new unused (in this form) syscalls.conf, to be 'cvs rm'ed] --- sys/kern/Make.tags.inc | 3 +- sys/kern/Makefile | 6 +- sys/kern/init_main.c | 82 ++- sys/kern/init_sysent.c | 819 ++++++++++++++++-------- sys/kern/kern_acct.c | 23 +- sys/kern/kern_descrip.c | 240 ++++---- sys/kern/kern_exit.c | 73 +-- sys/kern/kern_fork.c | 66 +- sys/kern/kern_ktrace.c | 85 +-- sys/kern/kern_malloc.c | 17 +- sys/kern/kern_proc.c | 159 ++--- sys/kern/kern_prot.c | 277 +++++---- sys/kern/kern_resource.c | 183 +++--- sys/kern/kern_sig.c | 290 +++++---- sys/kern/kern_subr.c | 15 +- sys/kern/kern_synch.c | 11 +- sys/kern/kern_sysctl.c | 140 +++-- sys/kern/kern_time.c | 129 ++-- sys/kern/kern_xxx.c | 85 +-- sys/kern/makesyscalls.sh | 476 +++++++++----- sys/kern/subr_autoconf.c | 13 +- sys/kern/subr_log.c | 10 +- sys/kern/subr_prf.c | 7 +- sys/kern/subr_prof.c | 36 +- sys/kern/subr_xxx.c | 19 +- sys/kern/sys_generic.c | 253 ++++---- sys/kern/sys_socket.c | 10 +- sys/kern/syscalls.c | 202 +++--- sys/kern/syscalls.conf | 12 + sys/kern/syscalls.master | 557 ++++++++++------- sys/kern/tty.c | 20 +- sys/kern/tty_compat.c | 4 +- sys/kern/tty_conf.c | 10 +- sys/kern/tty_pty.c | 6 +- sys/kern/tty_tb.c | 4 +- sys/kern/tty_tty.c | 24 +- sys/kern/uipc_domain.c | 13 +- sys/kern/uipc_mbuf.c | 23 +- sys/kern/uipc_proto.c | 4 +- sys/kern/uipc_socket.c | 40 +- sys/kern/uipc_socket2.c | 28 +- sys/kern/uipc_syscalls.c | 642 ++++++++++--------- sys/kern/uipc_usrreq.c | 40 +- sys/kern/vfs_cache.c | 314 +++++----- sys/kern/vfs_cluster.c | 66 +- sys/kern/vfs_conf.c | 174 +++--- sys/kern/vfs_init.c | 19 +- sys/kern/vfs_lookup.c | 217 +++++-- sys/kern/vfs_subr.c | 826 +++++++++++++++++++------ sys/kern/vfs_syscalls.c | 1538 ++++++++++++++++++++++++++++------------------ sys/kern/vfs_vnops.c | 89 ++- sys/kern/vnode_if.sh | 611 ++++++++---------- sys/kern/vnode_if.src | 206 ++++++- 53 files changed, 5554 insertions(+), 3662 deletions(-) create mode 100644 sys/kern/syscalls.conf (limited to 'sys') diff --git a/sys/kern/Make.tags.inc b/sys/kern/Make.tags.inc index 1563c41..79cb83a 100644 --- a/sys/kern/Make.tags.inc +++ b/sys/kern/Make.tags.inc @@ -1,4 +1,4 @@ -# @(#)Make.tags.inc 8.1 (Berkeley) 6/11/93 +# @(#)Make.tags.inc 8.2 (Berkeley) 11/23/94 # Common files for "make tags". # Included by the Makefile for each architecture. @@ -9,6 +9,7 @@ COMM= /sys/conf/*.[ch] \ /sys/dev/*.[ch] /sys/dev/scsi/*.[ch] \ + /sys/isofs/*/*.[ch] \ /sys/kern/*.[ch] /sys/libkern/*.[ch] \ /sys/miscfs/*/*.[ch] \ /sys/net/*.[ch] /sys/netccitt/*.[ch] /sys/netinet/*.[ch] \ diff --git a/sys/kern/Makefile b/sys/kern/Makefile index cfe962a..3159d20 100644 --- a/sys/kern/Makefile +++ b/sys/kern/Makefile @@ -1,4 +1,4 @@ -# @(#)Makefile 8.2 (Berkeley) 3/21/94 +# @(#)Makefile 8.3 (Berkeley) 2/14/95 # Makefile for kernel tags files, init_sysent, etc. @@ -7,11 +7,11 @@ ARCH= hp300 i386 luna68k news3400 pmax sparc tahoe vax all: @echo "make tags, make links or init_sysent.c only" -init_sysent.c syscalls.c ../sys/syscall.h: makesyscalls.sh syscalls.master +init_sysent.c syscalls.c ../sys/syscall.h ../sys/syscallargs.h: makesyscalls.sh syscalls.master -mv -f init_sysent.c init_sysent.c.bak -mv -f syscalls.c syscalls.c.bak -mv -f ../sys/syscall.h ../sys/syscall.h.bak - sh makesyscalls.sh syscalls.master + sh makesyscalls.sh syscalls.conf syscalls.master # Kernel tags: # Tags files are built in the top-level directory for each architecture, diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index c649715..61a0a14 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)init_main.c 8.9 (Berkeley) 1/21/94 + * @(#)init_main.c 8.16 (Berkeley) 5/14/95 */ #include @@ -57,6 +57,7 @@ #include #include #include +#include #include @@ -106,8 +107,8 @@ main(framep) register struct filedesc0 *fdp; register struct pdevinit *pdev; register int i; - int s, rval[2]; - extern int (*mountroot) __P((void)); + int s; + register_t rval[2]; extern struct pdevinit pdevinit[]; extern void roundrobin __P((void *)); extern void schedcpu __P((void *)); @@ -130,13 +131,19 @@ main(framep) cpu_startup(); /* + * Initialize process and pgrp structures. + */ + procinit(); + + /* * Create process 0 (the swapper). */ - allproc = (volatile struct proc *)p; - p->p_prev = (struct proc **)&allproc; + LIST_INSERT_HEAD(&allproc, p, p_list); p->p_pgrp = &pgrp0; - pgrphash[0] = &pgrp0; - pgrp0.pg_mem = p; + LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); + LIST_INIT(&pgrp0.pg_members); + LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); + pgrp0.pg_session = &session0; session0.s_count = 1; session0.s_leader = p; @@ -191,10 +198,8 @@ main(framep) p->p_sigacts = &p->p_addr->u_sigacts; /* - * Initialize per uid information structure and charge - * root for one process. + * Charge root for one process. */ - usrinfoinit(); (void)chgproccnt(0, 1); rqinit(); @@ -242,15 +247,16 @@ main(framep) schedcpu(NULL); /* Mount the root file system. */ - if ((*mountroot)()) + if (vfs_mountroot()) panic("cannot mount root"); + mountlist.cqh_first->mnt_flag |= MNT_ROOTFS; /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ - if (VFS_ROOT(mountlist.tqh_first, &rootvnode)) + if (VFS_ROOT(mountlist.cqh_first, &rootvnode)) panic("cannot find root vnode"); fdp->fd_fd.fd_cdir = rootvnode; VREF(fdp->fd_fd.fd_cdir); - VOP_UNLOCK(rootvnode); + VOP_UNLOCK(rootvnode, 0, p); fdp->fd_fd.fd_rdir = NULL; swapinit(); @@ -313,8 +319,14 @@ start_init(p, framep) void *framep; { vm_offset_t addr; - struct execve_args args; - int options, i, retval[2], error; + struct execve_args /* { + syscallarg(char *) path; + syscallarg(char **) argp; + syscallarg(char **) envp; + } */ args; + int options, i, error; + register_t retval[2]; + char flags[4] = "-", *flagsp; char **pathp, *path, *ucp, **uap, *arg0, *arg1; initproc = p; @@ -338,53 +350,59 @@ start_init(p, framep) for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { /* - * Move out the boot flag argument. + * Construct the boot flag argument. */ options = 0; + flagsp = flags + 1; ucp = (char *)USRSTACK; - (void)subyte(--ucp, 0); /* trailing zero */ if (boothowto & RB_SINGLE) { - (void)subyte(--ucp, 's'); + *flagsp++ = 's'; options = 1; } #ifdef notyet if (boothowto & RB_FASTBOOT) { - (void)subyte(--ucp, 'f'); + *flagsp++ = 'f'; options = 1; } #endif - if (options == 0) - (void)subyte(--ucp, '-'); - (void)subyte(--ucp, '-'); /* leading hyphen */ - arg1 = ucp; + /* + * Move out the flags (arg 1), if necessary. + */ + if (options != 0) { + *flagsp++ = '\0'; + i = flagsp - flags; + (void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i); + arg1 = ucp; + } /* * Move out the file name (also arg 0). */ - for (i = strlen(path) + 1; i >= 0; i--) - (void)subyte(--ucp, path[i]); + i = strlen(path) + 1; + (void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i); arg0 = ucp; /* * Move out the arg pointers. */ - uap = (char **)((int)ucp & ~(NBPW-1)); + uap = (char **)((long)ucp & ~ALIGNBYTES); (void)suword((caddr_t)--uap, 0); /* terminator */ - (void)suword((caddr_t)--uap, (int)arg1); - (void)suword((caddr_t)--uap, (int)arg0); + if (options != 0) + (void)suword((caddr_t)--uap, (long)arg1); + (void)suword((caddr_t)--uap, (long)arg0); /* * Point at the arguments. */ - args.fname = arg0; - args.argp = uap; - args.envp = NULL; + SCARG(&args, path) = arg0; + SCARG(&args, argp) = uap; + SCARG(&args, envp) = NULL; /* * Now try to exec the program. If can't for any reason * other than it doesn't exist, complain. */ - if ((error = execve(p, &args, &retval)) == 0) + if ((error = execve(p, &args, retval)) == 0) return; if (error != ENOENT) printf("exec %s: error %d\n", path, error); diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 4b25c06..0bbdd20 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -2,14 +2,14 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * created from @(#)syscalls.master 8.2 (Berkeley) 1/13/94 + * created from @(#)syscalls.master 8.6 (Berkeley) 3/30/95 */ #include #include - -int nosys(); - +#include +#include +#include int nosys(); int exit(); int fork(); @@ -138,8 +138,7 @@ int fstatfs(); int getfh(); #else #endif -#ifdef SYSVSHM -int shmsys(); +#if defined(SYSVSHM) && !defined(alpha) #else #endif int setgid(); @@ -168,313 +167,601 @@ int ftruncate(); int __sysctl(); int mlock(); int munlock(); +int undelete(); +#if defined(SYSVSHM) && 0 +int shmat(); +int shmctl(); +int shmdt(); +int shmget(); +#else +#endif #ifdef COMPAT_43 -#define compat(n, name) n, __CONCAT(o,name) +#define compat_43(func) __CONCAT(compat_43_,func) -int ocreat(); -int olseek(); -int ostat(); -int olstat(); +int compat_43(creat)(); +int compat_43(lseek)(); +int compat_43(stat)(); +int compat_43(lstat)(); #ifdef KTRACE #else #endif -int ofstat(); -int ogetkerninfo(); -int ogetpagesize(); -int ommap(); -int owait(); -int ogethostname(); -int osethostname(); -int oaccept(); -int osend(); -int orecv(); -int osigvec(); -int osigblock(); -int osigsetmask(); -int osigstack(); -int orecvmsg(); -int osendmsg(); +int compat_43(fstat)(); +int compat_43(getkerninfo)(); +int compat_43(getpagesize)(); +int compat_43(mmap)(); +int compat_43(wait)(); +int compat_43(gethostname)(); +int compat_43(sethostname)(); +int compat_43(accept)(); +int compat_43(send)(); +int compat_43(recv)(); +int compat_43(sigvec)(); +int compat_43(sigblock)(); +int compat_43(sigsetmask)(); +int compat_43(sigstack)(); +int compat_43(recvmsg)(); +int compat_43(sendmsg)(); #ifdef TRACE #else #endif #ifdef vax #else #endif -int orecvfrom(); -int osetreuid(); -int osetregid(); -int otruncate(); -int oftruncate(); -int ogetpeername(); -int ogethostid(); -int osethostid(); -int ogetrlimit(); -int osetrlimit(); -int okillpg(); -int oquota(); -int ogetsockname(); +int compat_43(recvfrom)(); +int compat_43(setreuid)(); +int compat_43(setregid)(); +int compat_43(truncate)(); +int compat_43(ftruncate)(); +int compat_43(getpeername)(); +int compat_43(gethostid)(); +int compat_43(sethostid)(); +int compat_43(getrlimit)(); +int compat_43(setrlimit)(); +int compat_43(killpg)(); +int compat_43(quota)(); +int compat_43(getsockname)(); #ifdef NFS #else #endif -int ogetdirentries(); +int compat_43(getdirentries)(); #ifdef NFS #else #endif -#ifdef SYSVSHM +#if defined(SYSVSHM) && !defined(alpha) +int compat_43(shmsys)(); #else #endif #ifdef LFS #else #endif +#if defined(SYSVSHM) && 0 +#else +#endif #else /* COMPAT_43 */ -#define compat(n, name) 0, nosys +#define compat_43(func) nosys #endif /* COMPAT_43 */ +#define s(type) sizeof(type) + struct sysent sysent[] = { - { 0, nosys }, /* 0 = syscall */ - { 1, exit }, /* 1 = exit */ - { 0, fork }, /* 2 = fork */ - { 3, read }, /* 3 = read */ - { 3, write }, /* 4 = write */ - { 3, open }, /* 5 = open */ - { 1, close }, /* 6 = close */ - { 4, wait4 }, /* 7 = wait4 */ - { compat(2,creat) }, /* 8 = old creat */ - { 2, link }, /* 9 = link */ - { 1, unlink }, /* 10 = unlink */ - { 0, nosys }, /* 11 = obsolete execv */ - { 1, chdir }, /* 12 = chdir */ - { 1, fchdir }, /* 13 = fchdir */ - { 3, mknod }, /* 14 = mknod */ - { 2, chmod }, /* 15 = chmod */ - { 3, chown }, /* 16 = chown */ - { 1, obreak }, /* 17 = break */ - { 3, getfsstat }, /* 18 = getfsstat */ - { compat(3,lseek) }, /* 19 = old lseek */ - { 0, getpid }, /* 20 = getpid */ - { 4, mount }, /* 21 = mount */ - { 2, unmount }, /* 22 = unmount */ - { 1, setuid }, /* 23 = setuid */ - { 0, getuid }, /* 24 = getuid */ - { 0, geteuid }, /* 25 = geteuid */ - { 4, ptrace }, /* 26 = ptrace */ - { 3, recvmsg }, /* 27 = recvmsg */ - { 3, sendmsg }, /* 28 = sendmsg */ - { 6, recvfrom }, /* 29 = recvfrom */ - { 3, accept }, /* 30 = accept */ - { 3, getpeername }, /* 31 = getpeername */ - { 3, getsockname }, /* 32 = getsockname */ - { 2, access }, /* 33 = access */ - { 2, chflags }, /* 34 = chflags */ - { 2, fchflags }, /* 35 = fchflags */ - { 0, sync }, /* 36 = sync */ - { 2, kill }, /* 37 = kill */ - { compat(2,stat) }, /* 38 = old stat */ - { 0, getppid }, /* 39 = getppid */ - { compat(2,lstat) }, /* 40 = old lstat */ - { 2, dup }, /* 41 = dup */ - { 0, pipe }, /* 42 = pipe */ - { 0, getegid }, /* 43 = getegid */ - { 4, profil }, /* 44 = profil */ + { 0, 0, + nosys }, /* 0 = syscall */ + { 1, s(struct exit_args), + exit }, /* 1 = exit */ + { 0, 0, + fork }, /* 2 = fork */ + { 3, s(struct read_args), + read }, /* 3 = read */ + { 3, s(struct write_args), + write }, /* 4 = write */ + { 3, s(struct open_args), + open }, /* 5 = open */ + { 1, s(struct close_args), + close }, /* 6 = close */ + { 4, s(struct wait4_args), + wait4 }, /* 7 = wait4 */ + { 2, s(struct compat_43_creat_args), + compat_43(creat) }, /* 8 = compat_43 creat */ + { 2, s(struct link_args), + link }, /* 9 = link */ + { 1, s(struct unlink_args), + unlink }, /* 10 = unlink */ + { 0, 0, + nosys }, /* 11 = obsolete execv */ + { 1, s(struct chdir_args), + chdir }, /* 12 = chdir */ + { 1, s(struct fchdir_args), + fchdir }, /* 13 = fchdir */ + { 3, s(struct mknod_args), + mknod }, /* 14 = mknod */ + { 2, s(struct chmod_args), + chmod }, /* 15 = chmod */ + { 3, s(struct chown_args), + chown }, /* 16 = chown */ + { 1, s(struct obreak_args), + obreak }, /* 17 = break */ + { 3, s(struct getfsstat_args), + getfsstat }, /* 18 = getfsstat */ + { 3, s(struct compat_43_lseek_args), + compat_43(lseek) }, /* 19 = compat_43 lseek */ + { 0, 0, + getpid }, /* 20 = getpid */ + { 4, s(struct mount_args), + mount }, /* 21 = mount */ + { 2, s(struct unmount_args), + unmount }, /* 22 = unmount */ + { 1, s(struct setuid_args), + setuid }, /* 23 = setuid */ + { 0, 0, + getuid }, /* 24 = getuid */ + { 0, 0, + geteuid }, /* 25 = geteuid */ + { 4, s(struct ptrace_args), + ptrace }, /* 26 = ptrace */ + { 3, s(struct recvmsg_args), + recvmsg }, /* 27 = recvmsg */ + { 3, s(struct sendmsg_args), + sendmsg }, /* 28 = sendmsg */ + { 6, s(struct recvfrom_args), + recvfrom }, /* 29 = recvfrom */ + { 3, s(struct accept_args), + accept }, /* 30 = accept */ + { 3, s(struct getpeername_args), + getpeername }, /* 31 = getpeername */ + { 3, s(struct getsockname_args), + getsockname }, /* 32 = getsockname */ + { 2, s(struct access_args), + access }, /* 33 = access */ + { 2, s(struct chflags_args), + chflags }, /* 34 = chflags */ + { 2, s(struct fchflags_args), + fchflags }, /* 35 = fchflags */ + { 0, 0, + sync }, /* 36 = sync */ + { 2, s(struct kill_args), + kill }, /* 37 = kill */ + { 2, s(struct compat_43_stat_args), + compat_43(stat) }, /* 38 = compat_43 stat */ + { 0, 0, + getppid }, /* 39 = getppid */ + { 2, s(struct compat_43_lstat_args), + compat_43(lstat) }, /* 40 = compat_43 lstat */ + { 1, s(struct dup_args), + dup }, /* 41 = dup */ + { 0, 0, + pipe }, /* 42 = pipe */ + { 0, 0, + getegid }, /* 43 = getegid */ + { 4, s(struct profil_args), + profil }, /* 44 = profil */ #ifdef KTRACE - { 4, ktrace }, /* 45 = ktrace */ + { 4, s(struct ktrace_args), + ktrace }, /* 45 = ktrace */ #else - { 0, nosys }, /* 45 = ktrace */ + { 0, 0, + nosys }, /* 45 = unimplemented ktrace */ #endif - { 3, sigaction }, /* 46 = sigaction */ - { 0, getgid }, /* 47 = getgid */ - { 2, sigprocmask }, /* 48 = sigprocmask */ - { 2, getlogin }, /* 49 = getlogin */ - { 1, setlogin }, /* 50 = setlogin */ - { 1, acct }, /* 51 = acct */ - { 0, sigpending }, /* 52 = sigpending */ - { 2, sigaltstack }, /* 53 = sigaltstack */ - { 3, ioctl }, /* 54 = ioctl */ - { 1, reboot }, /* 55 = reboot */ - { 1, revoke }, /* 56 = revoke */ - { 2, symlink }, /* 57 = symlink */ - { 3, readlink }, /* 58 = readlink */ - { 3, execve }, /* 59 = execve */ - { 1, umask }, /* 60 = umask */ - { 1, chroot }, /* 61 = chroot */ - { compat(2,fstat) }, /* 62 = old fstat */ - { compat(4,getkerninfo) }, /* 63 = old getkerninfo */ - { compat(0,getpagesize) }, /* 64 = old getpagesize */ - { 2, msync }, /* 65 = msync */ - { 0, vfork }, /* 66 = vfork */ - { 0, nosys }, /* 67 = obsolete vread */ - { 0, nosys }, /* 68 = obsolete vwrite */ - { 1, sbrk }, /* 69 = sbrk */ - { 1, sstk }, /* 70 = sstk */ - { compat(7,mmap) }, /* 71 = old mmap */ - { 1, ovadvise }, /* 72 = vadvise */ - { 2, munmap }, /* 73 = munmap */ - { 3, mprotect }, /* 74 = mprotect */ - { 3, madvise }, /* 75 = madvise */ - { 0, nosys }, /* 76 = obsolete vhangup */ - { 0, nosys }, /* 77 = obsolete vlimit */ - { 3, mincore }, /* 78 = mincore */ - { 2, getgroups }, /* 79 = getgroups */ - { 2, setgroups }, /* 80 = setgroups */ - { 0, getpgrp }, /* 81 = getpgrp */ - { 2, setpgid }, /* 82 = setpgid */ - { 3, setitimer }, /* 83 = setitimer */ - { compat(0,wait) }, /* 84 = old wait */ - { 1, swapon }, /* 85 = swapon */ - { 2, getitimer }, /* 86 = getitimer */ - { compat(2,gethostname) }, /* 87 = old gethostname */ - { compat(2,sethostname) }, /* 88 = old sethostname */ - { 0, getdtablesize }, /* 89 = getdtablesize */ - { 2, dup2 }, /* 90 = dup2 */ - { 0, nosys }, /* 91 = getdopt */ - { 3, fcntl }, /* 92 = fcntl */ - { 5, select }, /* 93 = select */ - { 0, nosys }, /* 94 = setdopt */ - { 1, fsync }, /* 95 = fsync */ - { 3, setpriority }, /* 96 = setpriority */ - { 3, socket }, /* 97 = socket */ - { 3, connect }, /* 98 = connect */ - { compat(3,accept) }, /* 99 = old accept */ - { 2, getpriority }, /* 100 = getpriority */ - { compat(4,send) }, /* 101 = old send */ - { compat(4,recv) }, /* 102 = old recv */ - { 1, sigreturn }, /* 103 = sigreturn */ - { 3, bind }, /* 104 = bind */ - { 5, setsockopt }, /* 105 = setsockopt */ - { 2, listen }, /* 106 = listen */ - { 0, nosys }, /* 107 = obsolete vtimes */ - { compat(3,sigvec) }, /* 108 = old sigvec */ - { compat(1,sigblock) }, /* 109 = old sigblock */ - { compat(1,sigsetmask) }, /* 110 = old sigsetmask */ - { 1, sigsuspend }, /* 111 = sigsuspend */ - { compat(2,sigstack) }, /* 112 = old sigstack */ - { compat(3,recvmsg) }, /* 113 = old recvmsg */ - { compat(3,sendmsg) }, /* 114 = old sendmsg */ + { 3, s(struct sigaction_args), + sigaction }, /* 46 = sigaction */ + { 0, 0, + getgid }, /* 47 = getgid */ + { 2, s(struct sigprocmask_args), + sigprocmask }, /* 48 = sigprocmask */ + { 2, s(struct getlogin_args), + getlogin }, /* 49 = getlogin */ + { 1, s(struct setlogin_args), + setlogin }, /* 50 = setlogin */ + { 1, s(struct acct_args), + acct }, /* 51 = acct */ + { 0, 0, + sigpending }, /* 52 = sigpending */ + { 2, s(struct sigaltstack_args), + sigaltstack }, /* 53 = sigaltstack */ + { 3, s(struct ioctl_args), + ioctl }, /* 54 = ioctl */ + { 1, s(struct reboot_args), + reboot }, /* 55 = reboot */ + { 1, s(struct revoke_args), + revoke }, /* 56 = revoke */ + { 2, s(struct symlink_args), + symlink }, /* 57 = symlink */ + { 3, s(struct readlink_args), + readlink }, /* 58 = readlink */ + { 3, s(struct execve_args), + execve }, /* 59 = execve */ + { 1, s(struct umask_args), + umask }, /* 60 = umask */ + { 1, s(struct chroot_args), + chroot }, /* 61 = chroot */ + { 2, s(struct compat_43_fstat_args), + compat_43(fstat) }, /* 62 = compat_43 fstat */ + { 4, s(struct compat_43_getkerninfo_args), + compat_43(getkerninfo) }, /* 63 = compat_43 getkerninfo */ + { 0, 0, + compat_43(getpagesize) }, /* 64 = compat_43 getpagesize */ + { 2, s(struct msync_args), + msync }, /* 65 = msync */ + { 0, 0, + vfork }, /* 66 = vfork */ + { 0, 0, + nosys }, /* 67 = obsolete vread */ + { 0, 0, + nosys }, /* 68 = obsolete vwrite */ + { 1, s(struct sbrk_args), + sbrk }, /* 69 = sbrk */ + { 1, s(struct sstk_args), + sstk }, /* 70 = sstk */ + { 6, s(struct compat_43_mmap_args), + compat_43(mmap) }, /* 71 = compat_43 mmap */ + { 1, s(struct ovadvise_args), + ovadvise }, /* 72 = vadvise */ + { 2, s(struct munmap_args), + munmap }, /* 73 = munmap */ + { 3, s(struct mprotect_args), + mprotect }, /* 74 = mprotect */ + { 3, s(struct madvise_args), + madvise }, /* 75 = madvise */ + { 0, 0, + nosys }, /* 76 = obsolete vhangup */ + { 0, 0, + nosys }, /* 77 = obsolete vlimit */ + { 3, s(struct mincore_args), + mincore }, /* 78 = mincore */ + { 2, s(struct getgroups_args), + getgroups }, /* 79 = getgroups */ + { 2, s(struct setgroups_args), + setgroups }, /* 80 = setgroups */ + { 0, 0, + getpgrp }, /* 81 = getpgrp */ + { 2, s(struct setpgid_args), + setpgid }, /* 82 = setpgid */ + { 3, s(struct setitimer_args), + setitimer }, /* 83 = setitimer */ + { 0, 0, + compat_43(wait) }, /* 84 = compat_43 wait */ + { 1, s(struct swapon_args), + swapon }, /* 85 = swapon */ + { 2, s(struct getitimer_args), + getitimer }, /* 86 = getitimer */ + { 2, s(struct compat_43_gethostname_args), + compat_43(gethostname) }, /* 87 = compat_43 gethostname */ + { 2, s(struct compat_43_sethostname_args), + compat_43(sethostname) }, /* 88 = compat_43 sethostname */ + { 0, 0, + getdtablesize }, /* 89 = getdtablesize */ + { 2, s(struct dup2_args), + dup2 }, /* 90 = dup2 */ + { 0, 0, + nosys }, /* 91 = unimplemented getdopt */ + { 3, s(struct fcntl_args), + fcntl }, /* 92 = fcntl */ + { 5, s(struct select_args), + select }, /* 93 = select */ + { 0, 0, + nosys }, /* 94 = unimplemented setdopt */ + { 1, s(struct fsync_args), + fsync }, /* 95 = fsync */ + { 3, s(struct setpriority_args), + setpriority }, /* 96 = setpriority */ + { 3, s(struct socket_args), + socket }, /* 97 = socket */ + { 3, s(struct connect_args), + connect }, /* 98 = connect */ + { 3, s(struct compat_43_accept_args), + compat_43(accept) }, /* 99 = compat_43 accept */ + { 2, s(struct getpriority_args), + getpriority }, /* 100 = getpriority */ + { 4, s(struct compat_43_send_args), + compat_43(send) }, /* 101 = compat_43 send */ + { 4, s(struct compat_43_recv_args), + compat_43(recv) }, /* 102 = compat_43 recv */ + { 1, s(struct sigreturn_args), + sigreturn }, /* 103 = sigreturn */ + { 3, s(struct bind_args), + bind }, /* 104 = bind */ + { 5, s(struct setsockopt_args), + setsockopt }, /* 105 = setsockopt */ + { 2, s(struct listen_args), + listen }, /* 106 = listen */ + { 0, 0, + nosys }, /* 107 = obsolete vtimes */ + { 3, s(struct compat_43_sigvec_args), + compat_43(sigvec) }, /* 108 = compat_43 sigvec */ + { 1, s(struct compat_43_sigblock_args), + compat_43(sigblock) }, /* 109 = compat_43 sigblock */ + { 1, s(struct compat_43_sigsetmask_args), + compat_43(sigsetmask) }, /* 110 = compat_43 sigsetmask */ + { 1, s(struct sigsuspend_args), + sigsuspend }, /* 111 = sigsuspend */ + { 2, s(struct compat_43_sigstack_args), + compat_43(sigstack) }, /* 112 = compat_43 sigstack */ + { 3, s(struct compat_43_recvmsg_args), + compat_43(recvmsg) }, /* 113 = compat_43 recvmsg */ + { 3, s(struct compat_43_sendmsg_args), + compat_43(sendmsg) }, /* 114 = compat_43 sendmsg */ #ifdef TRACE - { 2, vtrace }, /* 115 = vtrace */ + { 2, s(struct vtrace_args), + vtrace }, /* 115 = vtrace */ #else - { 0, nosys }, /* 115 = obsolete vtrace */ + { 0, 0, + nosys }, /* 115 = obsolete vtrace */ #endif - { 2, gettimeofday }, /* 116 = gettimeofday */ - { 2, getrusage }, /* 117 = getrusage */ - { 5, getsockopt }, /* 118 = getsockopt */ + { 2, s(struct gettimeofday_args), + gettimeofday }, /* 116 = gettimeofday */ + { 2, s(struct getrusage_args), + getrusage }, /* 117 = getrusage */ + { 5, s(struct getsockopt_args), + getsockopt }, /* 118 = getsockopt */ #ifdef vax - { 1, resuba }, /* 119 = resuba */ + { 1, s(struct resuba_args), + resuba }, /* 119 = resuba */ #else - { 0, nosys }, /* 119 = nosys */ + { 0, 0, + nosys }, /* 119 = unimplemented resuba */ #endif - { 3, readv }, /* 120 = readv */ - { 3, writev }, /* 121 = writev */ - { 2, settimeofday }, /* 122 = settimeofday */ - { 3, fchown }, /* 123 = fchown */ - { 2, fchmod }, /* 124 = fchmod */ - { compat(6,recvfrom) }, /* 125 = old recvfrom */ - { compat(2,setreuid) }, /* 126 = old setreuid */ - { compat(2,setregid) }, /* 127 = old setregid */ - { 2, rename }, /* 128 = rename */ - { compat(2,truncate) }, /* 129 = old truncate */ - { compat(2,ftruncate) }, /* 130 = old ftruncate */ - { 2, flock }, /* 131 = flock */ - { 2, mkfifo }, /* 132 = mkfifo */ - { 6, sendto }, /* 133 = sendto */ - { 2, shutdown }, /* 134 = shutdown */ - { 5, socketpair }, /* 135 = socketpair */ - { 2, mkdir }, /* 136 = mkdir */ - { 1, rmdir }, /* 137 = rmdir */ - { 2, utimes }, /* 138 = utimes */ - { 0, nosys }, /* 139 = obsolete 4.2 sigreturn */ - { 2, adjtime }, /* 140 = adjtime */ - { compat(3,getpeername) }, /* 141 = old getpeername */ - { compat(0,gethostid) }, /* 142 = old gethostid */ - { compat(1,sethostid) }, /* 143 = old sethostid */ - { compat(2,getrlimit) }, /* 144 = old getrlimit */ - { compat(2,setrlimit) }, /* 145 = old setrlimit */ - { compat(2,killpg) }, /* 146 = old killpg */ - { 0, setsid }, /* 147 = setsid */ - { 4, quotactl }, /* 148 = quotactl */ - { compat(4,quota) }, /* 149 = old quota */ - { compat(3,getsockname) }, /* 150 = old getsockname */ - { 0, nosys }, /* 151 = nosys */ - { 0, nosys }, /* 152 = nosys */ - { 0, nosys }, /* 153 = nosys */ - { 0, nosys }, /* 154 = nosys */ + { 3, s(struct readv_args), + readv }, /* 120 = readv */ + { 3, s(struct writev_args), + writev }, /* 121 = writev */ + { 2, s(struct settimeofday_args), + settimeofday }, /* 122 = settimeofday */ + { 3, s(struct fchown_args), + fchown }, /* 123 = fchown */ + { 2, s(struct fchmod_args), + fchmod }, /* 124 = fchmod */ + { 6, s(struct compat_43_recvfrom_args), + compat_43(recvfrom) }, /* 125 = compat_43 recvfrom */ + { 2, s(struct compat_43_setreuid_args), + compat_43(setreuid) }, /* 126 = compat_43 setreuid */ + { 2, s(struct compat_43_setregid_args), + compat_43(setregid) }, /* 127 = compat_43 setregid */ + { 2, s(struct rename_args), + rename }, /* 128 = rename */ + { 2, s(struct compat_43_truncate_args), + compat_43(truncate) }, /* 129 = compat_43 truncate */ + { 2, s(struct compat_43_ftruncate_args), + compat_43(ftruncate) }, /* 130 = compat_43 ftruncate */ + { 2, s(struct flock_args), + flock }, /* 131 = flock */ + { 2, s(struct mkfifo_args), + mkfifo }, /* 132 = mkfifo */ + { 6, s(struct sendto_args), + sendto }, /* 133 = sendto */ + { 2, s(struct shutdown_args), + shutdown }, /* 134 = shutdown */ + { 4, s(struct socketpair_args), + socketpair }, /* 135 = socketpair */ + { 2, s(struct mkdir_args), + mkdir }, /* 136 = mkdir */ + { 1, s(struct rmdir_args), + rmdir }, /* 137 = rmdir */ + { 2, s(struct utimes_args), + utimes }, /* 138 = utimes */ + { 0, 0, + nosys }, /* 139 = obsolete 4.2 sigreturn */ + { 2, s(struct adjtime_args), + adjtime }, /* 140 = adjtime */ + { 3, s(struct compat_43_getpeername_args), + compat_43(getpeername) }, /* 141 = compat_43 getpeername */ + { 0, 0, + compat_43(gethostid) }, /* 142 = compat_43 gethostid */ + { 1, s(struct compat_43_sethostid_args), + compat_43(sethostid) }, /* 143 = compat_43 sethostid */ + { 2, s(struct compat_43_getrlimit_args), + compat_43(getrlimit) }, /* 144 = compat_43 getrlimit */ + { 2, s(struct compat_43_setrlimit_args), + compat_43(setrlimit) }, /* 145 = compat_43 setrlimit */ + { 2, s(struct compat_43_killpg_args), + compat_43(killpg) }, /* 146 = compat_43 killpg */ + { 0, 0, + setsid }, /* 147 = setsid */ + { 4, s(struct quotactl_args), + quotactl }, /* 148 = quotactl */ + { 0, 0, + compat_43(quota) }, /* 149 = compat_43 quota */ + { 3, s(struct compat_43_getsockname_args), + compat_43(getsockname) }, /* 150 = compat_43 getsockname */ + { 0, 0, + nosys }, /* 151 = unimplemented */ + { 0, 0, + nosys }, /* 152 = unimplemented */ + { 0, 0, + nosys }, /* 153 = unimplemented */ + { 0, 0, + nosys }, /* 154 = unimplemented */ #ifdef NFS - { 2, nfssvc }, /* 155 = nfssvc */ + { 2, s(struct nfssvc_args), + nfssvc }, /* 155 = nfssvc */ #else - { 0, nosys }, /* 155 = nosys */ + { 0, 0, + nosys }, /* 155 = unimplemented nfssvc */ #endif - { compat(4,getdirentries) }, /* 156 = old getdirentries */ - { 2, statfs }, /* 157 = statfs */ - { 2, fstatfs }, /* 158 = fstatfs */ - { 0, nosys }, /* 159 = nosys */ - { 0, nosys }, /* 160 = nosys */ + { 4, s(struct compat_43_getdirentries_args), + compat_43(getdirentries) }, /* 156 = compat_43 getdirentries */ + { 2, s(struct statfs_args), + statfs }, /* 157 = statfs */ + { 2, s(struct fstatfs_args), + fstatfs }, /* 158 = fstatfs */ + { 0, 0, + nosys }, /* 159 = unimplemented */ + { 0, 0, + nosys }, /* 160 = unimplemented */ #ifdef NFS - { 2, getfh }, /* 161 = getfh */ + { 2, s(struct getfh_args), + getfh }, /* 161 = getfh */ #else - { 0, nosys }, /* 161 = nosys */ + { 0, 0, + nosys }, /* 161 = unimplemented getfh */ #endif - { 0, nosys }, /* 162 = nosys */ - { 0, nosys }, /* 163 = nosys */ - { 0, nosys }, /* 164 = nosys */ - { 0, nosys }, /* 165 = nosys */ - { 0, nosys }, /* 166 = nosys */ - { 0, nosys }, /* 167 = nosys */ - { 0, nosys }, /* 168 = nosys */ - { 0, nosys }, /* 169 = nosys */ - { 0, nosys }, /* 170 = nosys */ -#ifdef SYSVSHM - { 4, shmsys }, /* 171 = shmsys */ + { 0, 0, + nosys }, /* 162 = unimplemented getdomainname */ + { 0, 0, + nosys }, /* 163 = unimplemented setdomainname */ + { 0, 0, + nosys }, /* 164 = unimplemented */ + { 0, 0, + nosys }, /* 165 = unimplemented */ + { 0, 0, + nosys }, /* 166 = unimplemented */ + { 0, 0, + nosys }, /* 167 = unimplemented */ + { 0, 0, + nosys }, /* 168 = unimplemented */ + { 0, 0, + nosys }, /* 169 = unimplemented semsys */ + { 0, 0, + nosys }, /* 170 = unimplemented msgsys */ +#if defined(SYSVSHM) && !defined(alpha) + { 4, s(struct compat_43_shmsys_args), + compat_43(shmsys) }, /* 171 = compat_43 shmsys */ #else - { 0, nosys }, /* 171 = nosys */ + { 0, 0, + nosys }, /* 171 = unimplemented shmsys */ #endif - { 0, nosys }, /* 172 = nosys */ - { 0, nosys }, /* 173 = nosys */ - { 0, nosys }, /* 174 = nosys */ - { 0, nosys }, /* 175 = nosys */ - { 0, nosys }, /* 176 = nosys */ - { 0, nosys }, /* 177 = nosys */ - { 0, nosys }, /* 178 = nosys */ - { 0, nosys }, /* 179 = nosys */ - { 0, nosys }, /* 180 = nosys */ - { 1, setgid }, /* 181 = setgid */ - { 1, setegid }, /* 182 = setegid */ - { 1, seteuid }, /* 183 = seteuid */ + { 0, 0, + nosys }, /* 172 = unimplemented */ + { 0, 0, + nosys }, /* 173 = unimplemented */ + { 0, 0, + nosys }, /* 174 = unimplemented */ + { 0, 0, + nosys }, /* 175 = unimplemented */ + { 0, 0, + nosys }, /* 176 = unimplemented */ + { 0, 0, + nosys }, /* 177 = unimplemented */ + { 0, 0, + nosys }, /* 178 = unimplemented */ + { 0, 0, + nosys }, /* 179 = unimplemented */ + { 0, 0, + nosys }, /* 180 = unimplemented */ + { 1, s(struct setgid_args), + setgid }, /* 181 = setgid */ + { 1, s(struct setegid_args), + setegid }, /* 182 = setegid */ + { 1, s(struct seteuid_args), + seteuid }, /* 183 = seteuid */ #ifdef LFS - { 3, lfs_bmapv }, /* 184 = lfs_bmapv */ - { 3, lfs_markv }, /* 185 = lfs_markv */ - { 2, lfs_segclean }, /* 186 = lfs_segclean */ - { 2, lfs_segwait }, /* 187 = lfs_segwait */ + { 3, s(struct lfs_bmapv_args), + lfs_bmapv }, /* 184 = lfs_bmapv */ + { 3, s(struct lfs_markv_args), + lfs_markv }, /* 185 = lfs_markv */ + { 2, s(struct lfs_segclean_args), + lfs_segclean }, /* 186 = lfs_segclean */ + { 2, s(struct lfs_segwait_args), + lfs_segwait }, /* 187 = lfs_segwait */ +#else + { 0, 0, + nosys }, /* 184 = unimplemented lfs_bmapv */ + { 0, 0, + nosys }, /* 185 = unimplemented lfs_markv */ + { 0, 0, + nosys }, /* 186 = unimplemented lfs_segclean */ + { 0, 0, + nosys }, /* 187 = unimplemented lfs_segwait */ +#endif + { 2, s(struct stat_args), + stat }, /* 188 = stat */ + { 2, s(struct fstat_args), + fstat }, /* 189 = fstat */ + { 2, s(struct lstat_args), + lstat }, /* 190 = lstat */ + { 2, s(struct pathconf_args), + pathconf }, /* 191 = pathconf */ + { 2, s(struct fpathconf_args), + fpathconf }, /* 192 = fpathconf */ + { 0, 0, + nosys }, /* 193 = unimplemented */ + { 2, s(struct getrlimit_args), + getrlimit }, /* 194 = getrlimit */ + { 2, s(struct setrlimit_args), + setrlimit }, /* 195 = setrlimit */ + { 4, s(struct getdirentries_args), + getdirentries }, /* 196 = getdirentries */ + { 7, s(struct mmap_args), + mmap }, /* 197 = mmap */ + { 0, 0, + nosys }, /* 198 = __syscall */ + { 4, s(struct lseek_args), + lseek }, /* 199 = lseek */ + { 3, s(struct truncate_args), + truncate }, /* 200 = truncate */ + { 3, s(struct ftruncate_args), + ftruncate }, /* 201 = ftruncate */ + { 6, s(struct __sysctl_args), + __sysctl }, /* 202 = __sysctl */ + { 2, s(struct mlock_args), + mlock }, /* 203 = mlock */ + { 2, s(struct munlock_args), + munlock }, /* 204 = munlock */ + { 1, s(struct undelete_args), + undelete }, /* 205 = undelete */ + { 0, 0, + nosys }, /* 206 = unimplemented */ + { 0, 0, + nosys }, /* 207 = unimplemented */ + { 0, 0, + nosys }, /* 208 = unimplemented */ + { 0, 0, + nosys }, /* 209 = unimplemented */ + { 0, 0, + nosys }, /* 210 = unimplemented */ + { 0, 0, + nosys }, /* 211 = unimplemented */ + { 0, 0, + nosys }, /* 212 = unimplemented */ + { 0, 0, + nosys }, /* 213 = unimplemented */ + { 0, 0, + nosys }, /* 214 = unimplemented */ + { 0, 0, + nosys }, /* 215 = unimplemented */ + { 0, 0, + nosys }, /* 216 = unimplemented */ + { 0, 0, + nosys }, /* 217 = unimplemented */ + { 0, 0, + nosys }, /* 218 = unimplemented */ + { 0, 0, + nosys }, /* 219 = unimplemented */ + { 0, 0, + nosys }, /* 220 = unimplemented semctl */ + { 0, 0, + nosys }, /* 221 = unimplemented semget */ + { 0, 0, + nosys }, /* 222 = unimplemented semop */ + { 0, 0, + nosys }, /* 223 = unimplemented semconfig */ + { 0, 0, + nosys }, /* 224 = unimplemented msgctl */ + { 0, 0, + nosys }, /* 225 = unimplemented msgget */ + { 0, 0, + nosys }, /* 226 = unimplemented msgsnd */ + { 0, 0, + nosys }, /* 227 = unimplemented msgrcv */ +#if defined(SYSVSHM) && 0 + { 3, s(struct shmat_args), + shmat }, /* 228 = shmat */ + { 3, s(struct shmctl_args), + shmctl }, /* 229 = shmctl */ + { 1, s(struct shmdt_args), + shmdt }, /* 230 = shmdt */ + { 3, s(struct shmget_args), + shmget }, /* 231 = shmget */ #else - { 0, nosys }, /* 184 = nosys */ - { 0, nosys }, /* 185 = nosys */ - { 0, nosys }, /* 186 = nosys */ - { 0, nosys }, /* 187 = nosys */ + { 0, 0, + nosys }, /* 228 = unimplemented shmat */ + { 0, 0, + nosys }, /* 229 = unimplemented shmctl */ + { 0, 0, + nosys }, /* 230 = unimplemented shmdt */ + { 0, 0, + nosys }, /* 231 = unimplemented shmget */ #endif - { 2, stat }, /* 188 = stat */ - { 2, fstat }, /* 189 = fstat */ - { 2, lstat }, /* 190 = lstat */ - { 2, pathconf }, /* 191 = pathconf */ - { 2, fpathconf }, /* 192 = fpathconf */ - { 0, nosys }, /* 193 = nosys */ - { 2, getrlimit }, /* 194 = getrlimit */ - { 2, setrlimit }, /* 195 = setrlimit */ - { 4, getdirentries }, /* 196 = getdirentries */ - { 8, mmap }, /* 197 = mmap */ - { 0, nosys }, /* 198 = __syscall */ - { 5, lseek }, /* 199 = lseek */ - { 4, truncate }, /* 200 = truncate */ - { 4, ftruncate }, /* 201 = ftruncate */ - { 6, __sysctl }, /* 202 = __sysctl */ - { 2, mlock }, /* 203 = mlock */ - { 2, munlock }, /* 204 = munlock */ - { 0, nosys }, /* 205 = nosys */ - { 0, nosys }, /* 206 = nosys */ - { 0, nosys }, /* 207 = nosys */ - { 0, nosys }, /* 208 = nosys */ - { 0, nosys }, /* 209 = nosys */ - { 0, nosys }, /* 210 = nosys */ }; -int nsysent = sizeof(sysent) / sizeof(sysent[0]); +int nsysent= sizeof(sysent) / sizeof(sysent[0]); diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c index b752279..a23543c 100644 --- a/sys/kern/kern_acct.c +++ b/sys/kern/kern_acct.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)kern_acct.c 8.1 (Berkeley) 6/14/93 + * from: @(#)kern_acct.c 8.8 (Berkeley) 5/14/95 */ #include @@ -46,12 +46,11 @@ #include #include -struct acct_args { - char *fname; -}; acct(a1, a2, a3) struct proc *a1; - struct acct_args *a2; + struct acct_args /* { + syscallarg(char *) path; + } */ *a2; int *a3; { /* @@ -72,7 +71,9 @@ acct_process(a1) /* * Periodically check the file system to see if accounting - * should be turned on or off. + * should be turned on or off. Beware the case where the vnode + * has been vgone()'d out from underneath us, e.g. when the file + * system containing the accounting file has been forcibly unmounted. */ /* @@ -96,6 +97,11 @@ acctwatch(a) struct statfs sb; if (savacctp) { + if (savacctp->v_type == VBAD) { + (void) vn_close(savacctp, FWRITE, NOCRED, NULL); + savacctp = NULL; + return; + } (void)VFS_STATFS(savacctp->v_mount, &sb, (struct proc *)0); if (sb.f_bavail > acctresume * sb.f_blocks / 100) { acctp = savacctp; @@ -105,6 +111,11 @@ acctwatch(a) } else { if (acctp == NULL) return; + if (acctp->v_type == VBAD) { + (void) vn_close(acctp, FWRITE, NOCRED, NULL); + acctp = NULL; + return; + } (void)VFS_STATFS(acctp->v_mount, &sb, (struct proc *)0); if (sb.f_bavail <= acctsuspend * sb.f_blocks / 100) { savacctp = acctp; diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 543946d..3f2e424 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 + * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95 */ #include @@ -55,23 +55,24 @@ #include #include +#include +#include + /* * Descriptor management. */ -struct file *filehead; /* head of list of open files */ -int nfiles; /* actual number of open files */ +struct filelist filehead; /* head of list of open files */ +int nfiles; /* actual number of open files */ /* * System calls on descriptors. */ -struct getdtablesize_args { - int dummy; -}; /* ARGSUSED */ +int getdtablesize(p, uap, retval) struct proc *p; - struct getdtablesize_args *uap; - int *retval; + void *uap; + register_t *retval; { *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles); @@ -81,24 +82,27 @@ getdtablesize(p, uap, retval) /* * Duplicate a file descriptor. */ -struct dup_args { - u_int fd; -}; /* ARGSUSED */ +int dup(p, uap, retval) struct proc *p; - struct dup_args *uap; - int *retval; + struct dup_args /* { + syscallarg(u_int) fd; + } */ *uap; + register_t *retval; { register struct filedesc *fdp; u_int old; int new, error; - old = uap->fd; + old = SCARG(uap, fd); /* * XXX Compatibility */ - if (old &~ 077) { uap->fd &= 077; return (dup2(p, uap, retval)); } + if (old &~ 077) { + SCARG(uap, fd) &= 077; + return (dup2(p, uap, retval)); + } fdp = p->p_fd; if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL) @@ -111,18 +115,18 @@ dup(p, uap, retval) /* * Duplicate a file descriptor to a particular value. */ -struct dup2_args { - u_int from; - u_int to; -}; /* ARGSUSED */ +int dup2(p, uap, retval) struct proc *p; - struct dup2_args *uap; - int *retval; + struct dup2_args /* { + syscallarg(u_int) from; + syscallarg(u_int) to; + } */ *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; - register u_int old = uap->from, new = uap->to; + register int old = SCARG(uap, from), new = SCARG(uap, to); int i, error; if (old >= fdp->fd_nfiles || @@ -153,17 +157,18 @@ dup2(p, uap, retval) /* * The file control system call. */ -struct fcntl_args { - int fd; - int cmd; - int arg; -}; /* ARGSUSED */ +int fcntl(p, uap, retval) struct proc *p; - register struct fcntl_args *uap; - int *retval; + register struct fcntl_args /* { + syscallarg(int) fd; + syscallarg(int) cmd; + syscallarg(void *) arg; + } */ *uap; + register_t *retval; { + int fd = SCARG(uap, fd); register struct filedesc *fdp = p->p_fd; register struct file *fp; register char *pop; @@ -172,27 +177,27 @@ fcntl(p, uap, retval) struct flock fl; u_int newmin; - if ((unsigned)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) + if ((u_int)fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fd]) == NULL) return (EBADF); - pop = &fdp->fd_ofileflags[uap->fd]; - switch (uap->cmd) { + pop = &fdp->fd_ofileflags[fd]; + switch (SCARG(uap, cmd)) { case F_DUPFD: - newmin = uap->arg; + newmin = (long)SCARG(uap, arg); if (newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur || newmin >= maxfiles) return (EINVAL); if (error = fdalloc(p, newmin, &i)) return (error); - return (finishdup(fdp, uap->fd, i, retval)); + return (finishdup(fdp, fd, i, retval)); case F_GETFD: *retval = *pop & 1; return (0); case F_SETFD: - *pop = (*pop &~ 1) | (uap->arg & 1); + *pop = (*pop &~ 1) | ((long)SCARG(uap, arg) & 1); return (0); case F_GETFL: @@ -201,7 +206,7 @@ fcntl(p, uap, retval) case F_SETFL: fp->f_flag &= ~FCNTLFLAGS; - fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS; + fp->f_flag |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS; tmp = fp->f_flag & FNONBLOCK; error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); if (error) @@ -221,25 +226,26 @@ fcntl(p, uap, retval) return (0); } error = (*fp->f_ops->fo_ioctl) - (fp, (int)TIOCGPGRP, (caddr_t)retval, p); + (fp, TIOCGPGRP, (caddr_t)retval, p); *retval = -*retval; return (error); case F_SETOWN: if (fp->f_type == DTYPE_SOCKET) { - ((struct socket *)fp->f_data)->so_pgid = uap->arg; + ((struct socket *)fp->f_data)->so_pgid = + (long)SCARG(uap, arg); return (0); } - if (uap->arg <= 0) { - uap->arg = -uap->arg; + if ((long)SCARG(uap, arg) <= 0) { + SCARG(uap, arg) = (void *)(-(long)SCARG(uap, arg)); } else { - struct proc *p1 = pfind(uap->arg); + struct proc *p1 = pfind((long)SCARG(uap, arg)); if (p1 == 0) return (ESRCH); - uap->arg = p1->p_pgrp->pg_id; + SCARG(uap, arg) = (void *)(long)p1->p_pgrp->pg_id; } return ((*fp->f_ops->fo_ioctl) - (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p)); + (fp, TIOCSPGRP, (caddr_t)&SCARG(uap, arg), p)); case F_SETLKW: flg |= F_WAIT; @@ -250,7 +256,8 @@ fcntl(p, uap, retval) return (EBADF); vp = (struct vnode *)fp->f_data; /* Copy in the lock structure */ - error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); + error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl, + sizeof (fl)); if (error) return (error); if (fl.l_whence == SEEK_CUR) @@ -282,14 +289,16 @@ fcntl(p, uap, retval) return (EBADF); vp = (struct vnode *)fp->f_data; /* Copy in the lock structure */ - error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); + error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl, + sizeof (fl)); if (error) return (error); if (fl.l_whence == SEEK_CUR) fl.l_start += fp->f_offset; if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX)) return (error); - return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl))); + return (copyout((caddr_t)&fl, (caddr_t)SCARG(uap, arg), + sizeof (fl))); default: return (EINVAL); @@ -303,7 +312,8 @@ fcntl(p, uap, retval) int finishdup(fdp, old, new, retval) register struct filedesc *fdp; - register int old, new, *retval; + register int old, new; + register_t *retval; { register struct file *fp; @@ -320,21 +330,21 @@ finishdup(fdp, old, new, retval) /* * Close a file descriptor. */ -struct close_args { - int fd; -}; /* ARGSUSED */ +int close(p, uap, retval) struct proc *p; - struct close_args *uap; - int *retval; + struct close_args /* { + syscallarg(int) fd; + } */ *uap; + register_t *retval; { + int fd = SCARG(uap, fd); register struct filedesc *fdp = p->p_fd; register struct file *fp; - register int fd = uap->fd; register u_char *pf; - if ((unsigned)fd >= fdp->fd_nfiles || + if ((u_int)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) return (EBADF); pf = (u_char *)&fdp->fd_ofileflags[fd]; @@ -353,24 +363,25 @@ close(p, uap, retval) /* * Return status information about a file descriptor. */ -struct ofstat_args { - int fd; - struct ostat *sb; -}; /* ARGSUSED */ -ofstat(p, uap, retval) +int +compat_43_fstat(p, uap, retval) struct proc *p; - register struct ofstat_args *uap; - int *retval; + register struct compat_43_fstat_args /* { + syscallarg(int) fd; + syscallarg(struct ostat *) sb; + } */ *uap; + register_t *retval; { + int fd = SCARG(uap, fd); register struct filedesc *fdp = p->p_fd; register struct file *fp; struct stat ub; struct ostat oub; int error; - if ((unsigned)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) + if ((u_int)fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fd]) == NULL) return (EBADF); switch (fp->f_type) { @@ -388,7 +399,8 @@ ofstat(p, uap, retval) } cvtstat(&ub, &oub); if (error == 0) - error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub)); + error = copyout((caddr_t)&oub, (caddr_t)SCARG(uap, sb), + sizeof (oub)); return (error); } #endif /* COMPAT_43 || COMPAT_SUNOS */ @@ -396,23 +408,24 @@ ofstat(p, uap, retval) /* * Return status information about a file descriptor. */ -struct fstat_args { - int fd; - struct stat *sb; -}; /* ARGSUSED */ +int fstat(p, uap, retval) struct proc *p; - register struct fstat_args *uap; - int *retval; + register struct fstat_args /* { + syscallarg(int) fd; + syscallarg(struct stat *) sb; + } */ *uap; + register_t *retval; { + int fd = SCARG(uap, fd); register struct filedesc *fdp = p->p_fd; register struct file *fp; struct stat ub; int error; - if ((unsigned)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) + if ((u_int)fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fd]) == NULL) return (EBADF); switch (fp->f_type) { @@ -429,41 +442,43 @@ fstat(p, uap, retval) /*NOTREACHED*/ } if (error == 0) - error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); + error = copyout((caddr_t)&ub, (caddr_t)SCARG(uap, sb), + sizeof (ub)); return (error); } /* * Return pathconf information about a file descriptor. */ -struct fpathconf_args { - int fd; - int name; -}; /* ARGSUSED */ +int fpathconf(p, uap, retval) struct proc *p; - register struct fpathconf_args *uap; - int *retval; + register struct fpathconf_args /* { + syscallarg(int) fd; + syscallarg(int) name; + } */ *uap; + register_t *retval; { + int fd = SCARG(uap, fd); struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; - if ((unsigned)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) + if ((u_int)fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fd]) == NULL) return (EBADF); switch (fp->f_type) { case DTYPE_SOCKET: - if (uap->name != _PC_PIPE_BUF) + if (SCARG(uap, name) != _PC_PIPE_BUF) return (EINVAL); *retval = PIPE_BUF; return (0); case DTYPE_VNODE: vp = (struct vnode *)fp->f_data; - return (VOP_PATHCONF(vp, uap->name, retval)); + return (VOP_PATHCONF(vp, SCARG(uap, name), retval)); default: panic("fpathconf"); @@ -476,6 +491,7 @@ fpathconf(p, uap, retval) */ int fdexpand; +int fdalloc(p, want, result) struct proc *p; int want; @@ -544,6 +560,7 @@ fdalloc(p, want, result) * Check to see whether n user file descriptors * are available to the process p. */ +int fdavail(p, n) struct proc *p; register int n; @@ -566,12 +583,13 @@ fdavail(p, n) * Create a new open file structure and allocate * a file decriptor for the process that refers to it. */ +int falloc(p, resultfp, resultfd) register struct proc *p; struct file **resultfp; int *resultfd; { - register struct file *fp, *fq, **fpp; + register struct file *fp, *fq; int error, i; if (error = fdalloc(p, 0, &i)) @@ -589,16 +607,12 @@ falloc(p, resultfp, resultfd) nfiles++; MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK); bzero(fp, sizeof(struct file)); - if (fq = p->p_fd->fd_ofiles[0]) - fpp = &fq->f_filef; - else - fpp = &filehead; + if (fq = p->p_fd->fd_ofiles[0]) { + LIST_INSERT_AFTER(fq, fp, f_list); + } else { + LIST_INSERT_HEAD(&filehead, fp, f_list); + } p->p_fd->fd_ofiles[i] = fp; - if (fq = *fpp) - fq->f_fileb = &fp->f_filef; - fp->f_filef = fq; - fp->f_fileb = fpp; - *fpp = fp; fp->f_count = 1; fp->f_cred = p->p_ucred; crhold(fp->f_cred); @@ -612,18 +626,15 @@ falloc(p, resultfp, resultfd) /* * Free a file descriptor. */ +void ffree(fp) register struct file *fp; { register struct file *fq; - if (fq = fp->f_filef) - fq->f_fileb = fp->f_fileb; - *fp->f_fileb = fq; + LIST_REMOVE(fp, f_list); crfree(fp->f_cred); #ifdef DIAGNOSTIC - fp->f_filef = NULL; - fp->f_fileb = NULL; fp->f_count = 0; #endif nfiles--; @@ -714,6 +725,7 @@ fdfree(p) * Note: p may be NULL when closing a file * that was being passed in a message. */ +int closef(fp, p) register struct file *fp; register struct proc *p; @@ -766,23 +778,25 @@ closef(fp, p) * Just attempt to get a record lock of the requested type on * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). */ -struct flock_args { - int fd; - int how; -}; /* ARGSUSED */ +int flock(p, uap, retval) struct proc *p; - register struct flock_args *uap; - int *retval; + register struct flock_args /* { + syscallarg(int) fd; + syscallarg(int) how; + } */ *uap; + register_t *retval; { + int fd = SCARG(uap, fd); + int how = SCARG(uap, how); register struct filedesc *fdp = p->p_fd; register struct file *fp; struct vnode *vp; struct flock lf; - if ((unsigned)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) + if ((u_int)fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fd]) == NULL) return (EBADF); if (fp->f_type != DTYPE_VNODE) return (EOPNOTSUPP); @@ -790,19 +804,19 @@ flock(p, uap, retval) lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; - if (uap->how & LOCK_UN) { + if (how & LOCK_UN) { lf.l_type = F_UNLCK; fp->f_flag &= ~FHASLOCK; return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK)); } - if (uap->how & LOCK_EX) + if (how & LOCK_EX) lf.l_type = F_WRLCK; - else if (uap->how & LOCK_SH) + else if (how & LOCK_SH) lf.l_type = F_RDLCK; else return (EBADF); fp->f_flag |= FHASLOCK; - if (uap->how & LOCK_NB) + if (how & LOCK_NB) return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK)); return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT)); } @@ -816,6 +830,7 @@ flock(p, uap, retval) * references to this file will be direct to the other driver. */ /* ARGSUSED */ +int fdopen(dev, mode, type, p) dev_t dev; int mode, type; @@ -837,6 +852,7 @@ fdopen(dev, mode, type, p) /* * Duplicate the specified descriptor to a free descriptor. */ +int dupfdopen(fdp, indx, dfd, mode, error) register struct filedesc *fdp; register int indx, dfd; @@ -845,7 +861,7 @@ dupfdopen(fdp, indx, dfd, mode, error) { register struct file *wfp; struct file *fp; - + /* * If the to-be-dup'd fd number is greater than the allowed number * of file descriptors, or the fd to be dup'd has already been diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 03353c7..4ed48ac 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 + * @(#)kern_exit.c 8.10 (Berkeley) 2/23/95 */ #include @@ -163,7 +163,7 @@ exit1(p, rv) * if we blocked. */ if (sp->s_ttyvp) - vgoneall(sp->s_ttyvp); + VOP_REVOKE(sp->s_ttyvp, REVOKEALL); } if (sp->s_ttyvp) vrele(sp->s_ttyvp); @@ -191,34 +191,19 @@ exit1(p, rv) * Remove proc from allproc queue and pidhash chain. * Place onto zombproc. Unlink from parent's child list. */ - if (*p->p_prev = p->p_next) - p->p_next->p_prev = p->p_prev; - if (p->p_next = zombproc) - p->p_next->p_prev = &p->p_next; - p->p_prev = &zombproc; - zombproc = p; + LIST_REMOVE(p, p_list); + LIST_INSERT_HEAD(&zombproc, p, p_list); p->p_stat = SZOMB; - for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) - if (*pp == p) { - *pp = p->p_hash; - goto done; - } - panic("exit"); -done: + LIST_REMOVE(p, p_hash); - if (p->p_cptr) /* only need this if any child is S_ZOMB */ + q = p->p_children.lh_first; + if (q) /* only need this if any child is S_ZOMB */ wakeup((caddr_t) initproc); - for (q = p->p_cptr; q != NULL; q = nq) { - nq = q->p_osptr; - if (nq != NULL) - nq->p_ysptr = NULL; - if (initproc->p_cptr) - initproc->p_cptr->p_ysptr = q; - q->p_osptr = initproc->p_cptr; - q->p_ysptr = NULL; - initproc->p_cptr = q; - + for (; q != 0; q = nq) { + nq = q->p_sibling.le_next; + LIST_REMOVE(q, p_sibling); + LIST_INSERT_HEAD(&initproc->p_children, q, p_sibling); q->p_pptr = initproc; /* * Traced processes are killed @@ -229,7 +214,6 @@ done: psignal(q, SIGKILL); } } - p->p_cptr = NULL; /* * Save exit status and final rusage info, adding in child rusage @@ -293,7 +277,7 @@ struct wait_args { #define GETPS(rp) (rp)[PS] #endif -owait(p, uap, retval) +compat_43_wait(p, uap, retval) struct proc *p; register struct wait_args *uap; int *retval; @@ -348,7 +332,7 @@ wait1(q, uap, retval) #endif loop: nfound = 0; - for (p = q->p_cptr; p; p = p->p_osptr) { + for (p = q->p_children.lh_first; p != 0; p = p->p_sibling.le_next) { if (uap->pid != WAIT_ANY && p->p_pid != uap->pid && p->p_pgid != -uap->pid) continue; @@ -408,14 +392,8 @@ loop: * Unlink it from its process group and free it. */ leavepgrp(p); - if (*p->p_prev = p->p_next) /* off zombproc */ - p->p_next->p_prev = p->p_prev; - if (q = p->p_ysptr) - q->p_osptr = p->p_osptr; - if (q = p->p_osptr) - q->p_ysptr = p->p_ysptr; - if ((q = p->p_pptr)->p_cptr == p) - q->p_cptr = p->p_osptr; + LIST_REMOVE(p, p_list); /* off zombproc */ + LIST_REMOVE(p, p_sibling); /* * Give machine-dependent layer a chance @@ -465,28 +443,11 @@ proc_reparent(child, parent) register struct proc *child; register struct proc *parent; { - register struct proc *o; - register struct proc *y; if (child->p_pptr == parent) return; - /* fix up the child linkage for the old parent */ - o = child->p_osptr; - y = child->p_ysptr; - if (y) - y->p_osptr = o; - if (o) - o->p_ysptr = y; - if (child->p_pptr->p_cptr == child) - child->p_pptr->p_cptr = o; - - /* fix up child linkage for new parent */ - o = parent->p_cptr; - if (o) - o->p_ysptr = child; - child->p_osptr = o; - child->p_ysptr = NULL; - parent->p_cptr = child; + LIST_REMOVE(child, p_sibling); + LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); child->p_pptr = parent; } diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 8bec2fa..6c5f22f 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_fork.c 8.6 (Berkeley) 4/8/94 + * @(#)kern_fork.c 8.8 (Berkeley) 2/14/95 */ #include @@ -51,14 +51,11 @@ #include #include -struct fork_args { - int dummy; -}; /* ARGSUSED */ fork(p, uap, retval) struct proc *p; - struct fork_args *uap; - int retval[]; + void *uap; + register_t *retval; { return (fork1(p, 0, retval)); @@ -67,8 +64,8 @@ fork(p, uap, retval) /* ARGSUSED */ vfork(p, uap, retval) struct proc *p; - struct fork_args *uap; - int retval[]; + void *uap; + register_t *retval; { return (fork1(p, 1, retval)); @@ -78,7 +75,8 @@ int nprocs = 1; /* process 0 */ fork1(p1, isvfork, retval) register struct proc *p1; - int isvfork, retval[]; + int isvfork; + register_t *retval; { register struct proc *p2; register uid_t uid; @@ -99,6 +97,7 @@ fork1(p1, isvfork, retval) tablefull("proc"); return (EAGAIN); } + /* * Increment the count of procs running with this uid. Don't allow * a nonprivileged user to exceed their current limit. @@ -136,9 +135,9 @@ retry: * is in use. Remember the lowest pid that's greater * than nextpid, so we can avoid checking for a while. */ - p2 = (struct proc *)allproc; + p2 = allproc.lh_first; again: - for (; p2 != NULL; p2 = p2->p_next) { + for (; p2 != 0; p2 = p2->p_list.le_next) { while (p2->p_pid == nextpid || p2->p_pgrp->pg_id == nextpid) { nextpid++; @@ -153,43 +152,18 @@ again: } if (!doingzomb) { doingzomb = 1; - p2 = zombproc; + p2 = zombproc.lh_first; goto again; } } - - /* - * Link onto allproc (this should probably be delayed). - * Heavy use of volatile here to prevent the compiler from - * rearranging code. Yes, it *is* terribly ugly, but at least - * it works. - */ nprocs++; p2 = newproc; -#define Vp2 ((volatile struct proc *)p2) - Vp2->p_stat = SIDL; /* protect against others */ - Vp2->p_pid = nextpid; - /* - * This is really: - * p2->p_next = allproc; - * allproc->p_prev = &p2->p_next; - * p2->p_prev = &allproc; - * allproc = p2; - * The assignment via allproc is legal since it is never NULL. - */ - *(volatile struct proc **)&Vp2->p_next = allproc; - *(volatile struct proc ***)&allproc->p_prev = - (volatile struct proc **)&Vp2->p_next; - *(volatile struct proc ***)&Vp2->p_prev = &allproc; - allproc = Vp2; -#undef Vp2 + p2->p_stat = SIDL; /* protect against others */ + p2->p_pid = nextpid; + LIST_INSERT_HEAD(&allproc, p2, p_list); p2->p_forw = p2->p_back = NULL; /* shouldn't be necessary */ - - /* Insert on the hash chain. */ - hash = &pidhash[PIDHASH(p2->p_pid)]; - p2->p_hash = *hash; - *hash = p2; + LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash); /* * Make a proc table entry for the new process. @@ -238,13 +212,11 @@ again: p2->p_flag |= P_CONTROLT; if (isvfork) p2->p_flag |= P_PPWAIT; - p2->p_pgrpnxt = p1->p_pgrpnxt; - p1->p_pgrpnxt = p2; + LIST_INSERT_AFTER(p1, p2, p_pglist); p2->p_pptr = p1; - p2->p_osptr = p1->p_cptr; - if (p1->p_cptr) - p1->p_cptr->p_ysptr = p2; - p1->p_cptr = p2; + LIST_INSERT_HEAD(&p1->p_children, p2, p_sibling); + LIST_INIT(&p2->p_children); + #ifdef KTRACE /* * Copy traceflag and tracefile if enabled. diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 763cfb2..b841754 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -30,12 +30,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_ktrace.c 8.2 (Berkeley) 9/23/93 + * @(#)kern_ktrace.c 8.5 (Berkeley) 5/14/95 */ #ifdef KTRACE #include +#include #include #include #include @@ -44,6 +45,9 @@ #include #include +#include +#include + struct ktr_header * ktrgetheader(type) int type; @@ -60,23 +64,26 @@ ktrgetheader(type) return (kth); } -ktrsyscall(vp, code, narg, args) +void +ktrsyscall(vp, code, argsize, args) struct vnode *vp; - int code, narg, args[]; + int code, argsize; + register_t args[]; { struct ktr_header *kth; struct ktr_syscall *ktp; - register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); + register len = sizeof(struct ktr_syscall) + argsize; struct proc *p = curproc; /* XXX */ - int *argp, i; + register_t *argp; + int i; p->p_traceflag |= KTRFAC_ACTIVE; kth = ktrgetheader(KTR_SYSCALL); MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); ktp->ktr_code = code; - ktp->ktr_narg = narg; - argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); - for (i = 0; i < narg; i++) + ktp->ktr_argsize = argsize; + argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall)); + for (i = 0; i < (argsize / sizeof *argp); i++) *argp++ = args[i]; kth->ktr_buf = (caddr_t)ktp; kth->ktr_len = len; @@ -86,6 +93,7 @@ ktrsyscall(vp, code, narg, args) p->p_traceflag &= ~KTRFAC_ACTIVE; } +void ktrsysret(vp, code, error, retval) struct vnode *vp; int code, error, retval; @@ -108,6 +116,7 @@ ktrsysret(vp, code, error, retval) p->p_traceflag &= ~KTRFAC_ACTIVE; } +void ktrnamei(vp, path) struct vnode *vp; char *path; @@ -125,6 +134,7 @@ ktrnamei(vp, path) p->p_traceflag &= ~KTRFAC_ACTIVE; } +void ktrgenio(vp, fd, rw, iov, len, error) struct vnode *vp; int fd; @@ -166,6 +176,7 @@ done: p->p_traceflag &= ~KTRFAC_ACTIVE; } +void ktrpsig(vp, sig, action, mask, code) struct vnode *vp; int sig; @@ -190,6 +201,7 @@ ktrpsig(vp, sig, action, mask, code) p->p_traceflag &= ~KTRFAC_ACTIVE; } +void ktrcsw(vp, out, user) struct vnode *vp; int out, user; @@ -215,24 +227,24 @@ ktrcsw(vp, out, user) /* * ktrace system call */ -struct ktrace_args { - char *fname; - int ops; - int facs; - int pid; -}; /* ARGSUSED */ +int ktrace(curp, uap, retval) struct proc *curp; - register struct ktrace_args *uap; - int *retval; + register struct ktrace_args /* { + syscallarg(char *) fname; + syscallarg(int) ops; + syscallarg(int) facs; + syscallarg(int) pid; + } */ *uap; + register_t *retval; { register struct vnode *vp = NULL; register struct proc *p; struct pgrp *pg; - int facs = uap->facs & ~KTRFAC_ROOT; - int ops = KTROP(uap->ops); - int descend = uap->ops & KTRFLAG_DESCEND; + int facs = SCARG(uap, facs) & ~KTRFAC_ROOT; + int ops = KTROP(SCARG(uap, ops)); + int descend = SCARG(uap, ops) & KTRFLAG_DESCEND; int ret = 0; int error = 0; struct nameidata nd; @@ -242,13 +254,14 @@ ktrace(curp, uap, retval) /* * an operation which requires a file argument. */ - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, curp); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname), + curp); if (error = vn_open(&nd, FREAD|FWRITE, 0)) { curp->p_traceflag &= ~KTRFAC_ACTIVE; return (error); } vp = nd.ni_vp; - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); if (vp->v_type != VREG) { (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); curp->p_traceflag &= ~KTRFAC_ACTIVE; @@ -259,7 +272,7 @@ ktrace(curp, uap, retval) * Clear all uses of the tracefile */ if (ops == KTROP_CLEARFILE) { - for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { + for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { if (p->p_tracep == vp) { if (ktrcanset(curp, p)) { p->p_tracep = NULL; @@ -282,16 +295,16 @@ ktrace(curp, uap, retval) /* * do it */ - if (uap->pid < 0) { + if (SCARG(uap, pid) < 0) { /* * by process group */ - pg = pgfind(-uap->pid); + pg = pgfind(-SCARG(uap, pid)); if (pg == NULL) { error = ESRCH; goto done; } - for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) + for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) if (descend) ret |= ktrsetchildren(curp, p, ops, facs, vp); else @@ -301,7 +314,7 @@ ktrace(curp, uap, retval) /* * by pid */ - p = pfind(uap->pid); + p = pfind(SCARG(uap, pid)); if (p == NULL) { error = ESRCH; goto done; @@ -373,20 +386,16 @@ ktrsetchildren(curp, top, ops, facs, vp) * otherwise do any siblings, and if done with this level, * follow back up the tree (but not past top). */ - if (p->p_cptr) - p = p->p_cptr; - else if (p == top) - return (ret); - else if (p->p_osptr) - p = p->p_osptr; + if (p->p_children.lh_first) + p = p->p_children.lh_first; else for (;;) { - p = p->p_pptr; if (p == top) return (ret); - if (p->p_osptr) { - p = p->p_osptr; + if (p->p_sibling.le_next) { + p = p->p_sibling.le_next; break; } + p = p->p_pptr; } } /*NOTREACHED*/ @@ -418,9 +427,9 @@ ktrwrite(vp, kth) aiov[1].iov_len = kth->ktr_len; auio.uio_resid += kth->ktr_len; } - VOP_LOCK(vp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred); - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); if (!error) return; /* @@ -428,7 +437,7 @@ ktrwrite(vp, kth) */ log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", error); - for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { + for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { if (p->p_tracep == vp) { p->p_tracep = NULL; p->p_traceflag = 0; diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index c6276bc..363cde5 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_malloc.c 8.3 (Berkeley) 1/4/94 + * @(#)kern_malloc.c 8.4 (Berkeley) 5/20/95 */ #include @@ -103,6 +103,9 @@ malloc(size, type, flags) int copysize; char *savedtype; #endif +#ifdef DEBUG + extern int simplelockrecurse; +#endif #ifdef KMEMSTATS register struct kmemstats *ksp = &kmemstats[type]; @@ -127,6 +130,10 @@ malloc(size, type, flags) #ifdef DIAGNOSTIC copysize = 1 << indx < MAX_COPY ? 1 << indx : MAX_COPY; #endif +#ifdef DEBUG + if (flags & M_NOWAIT) + simplelockrecurse++; +#endif if (kbp->kb_next == NULL) { kbp->kb_last = NULL; if (size > MAXALLOCSAVE) @@ -138,6 +145,10 @@ malloc(size, type, flags) !(flags & M_NOWAIT)); if (va == NULL) { splx(s); +#ifdef DEBUG + if (flags & M_NOWAIT) + simplelockrecurse--; +#endif return ((void *) NULL); } #ifdef KMEMSTATS @@ -239,6 +250,10 @@ out: out: #endif splx(s); +#ifdef DEBUG + if (flags & M_NOWAIT) + simplelockrecurse--; +#endif return ((void *) va); } diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 91d9e21..6701793 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94 + * @(#)kern_proc.c 8.7 (Berkeley) 2/14/95 */ #include @@ -53,20 +53,35 @@ * Structure associated with user cacheing. */ struct uidinfo { - struct uidinfo *ui_next; - struct uidinfo **ui_prev; + LIST_ENTRY(uidinfo) ui_hash; uid_t ui_uid; long ui_proccnt; -} **uihashtbl; -u_long uihash; /* size of hash table - 1 */ -#define UIHASH(uid) ((uid) & uihash) +}; +#define UIHASH(uid) (&uihashtbl[(uid) & uihash]) +LIST_HEAD(uihashhead, uidinfo) *uihashtbl; +u_long uihash; /* size of hash table - 1 */ /* - * Allocate a hash table. + * Other process lists */ -usrinfoinit() +struct pidhashhead *pidhashtbl; +u_long pidhash; +struct pgrphashhead *pgrphashtbl; +u_long pgrphash; +struct proclist allproc; +struct proclist zombproc; + +/* + * Initialize global process hashing structures. + */ +void +procinit() { + LIST_INIT(&allproc); + LIST_INIT(&zombproc); + pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); + pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); } @@ -79,10 +94,11 @@ chgproccnt(uid, diff) uid_t uid; int diff; { - register struct uidinfo **uipp, *uip, *uiq; + register struct uidinfo *uip; + register struct uihashhead *uipp; - uipp = &uihashtbl[UIHASH(uid)]; - for (uip = *uipp; uip; uip = uip->ui_next) + uipp = UIHASH(uid); + for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) if (uip->ui_uid == uid) break; if (uip) { @@ -91,9 +107,7 @@ chgproccnt(uid, diff) return (uip->ui_proccnt); if (uip->ui_proccnt < 0) panic("chgproccnt: procs < 0"); - if (uiq = uip->ui_next) - uiq->ui_prev = uip->ui_prev; - *uip->ui_prev = uiq; + LIST_REMOVE(uip, ui_hash); FREE(uip, M_PROC); return (0); } @@ -103,11 +117,7 @@ chgproccnt(uid, diff) panic("chgproccnt: lost user"); } MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); - if (uiq = *uipp) - uiq->ui_prev = &uip->ui_next; - uip->ui_next = uiq; - uip->ui_prev = uipp; - *uipp = uip; + LIST_INSERT_HEAD(uipp, uip, ui_hash); uip->ui_uid = uid; uip->ui_proccnt = diff; return (diff); @@ -135,7 +145,7 @@ pfind(pid) { register struct proc *p; - for (p = pidhash[PIDHASH(pid)]; p != NULL; p = p->p_hash) + for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next) if (p->p_pid == pid) return (p); return (NULL); @@ -150,8 +160,8 @@ pgfind(pgid) { register struct pgrp *pgrp; - for (pgrp = pgrphash[PIDHASH(pgid)]; - pgrp != NULL; pgrp = pgrp->pg_hforw) + for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0; + pgrp = pgrp->pg_hash.le_next) if (pgrp->pg_id == pgid) return (pgrp); return (NULL); @@ -160,14 +170,13 @@ pgfind(pgid) /* * Move p to a new or existing process group (and session) */ +int enterpgrp(p, pgid, mksess) register struct proc *p; pid_t pgid; int mksess; { register struct pgrp *pgrp = pgfind(pgid); - register struct proc **pp; - int n; #ifdef DIAGNOSTIC if (pgrp != NULL && mksess) /* firewalls */ @@ -186,7 +195,7 @@ enterpgrp(p, pgid, mksess) panic("enterpgrp: new pgrp and pid != pgid"); #endif MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, - M_WAITOK); + M_WAITOK); if ((np = pfind(savepid)) == NULL || np != p) return (ESRCH); if (mksess) { @@ -196,7 +205,7 @@ enterpgrp(p, pgid, mksess) * new session */ MALLOC(sess, struct session *, sizeof(struct session), - M_SESSION, M_WAITOK); + M_SESSION, M_WAITOK); sess->s_leader = p; sess->s_count = 1; sess->s_ttyvp = NULL; @@ -214,10 +223,9 @@ enterpgrp(p, pgid, mksess) pgrp->pg_session->s_count++; } pgrp->pg_id = pgid; - pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; - pgrphash[n] = pgrp; + LIST_INIT(&pgrp->pg_members); + LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); pgrp->pg_jobc = 0; - pgrp->pg_mem = NULL; } else if (pgrp == p->p_pgrp) return (0); @@ -229,52 +237,24 @@ enterpgrp(p, pgid, mksess) fixjobc(p, pgrp, 1); fixjobc(p, p->p_pgrp, 0); - /* - * unlink p from old process group - */ - for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) { - if (*pp == p) { - *pp = p->p_pgrpnxt; - break; - } - } -#ifdef DIAGNOSTIC - if (pp == NULL) - panic("enterpgrp: can't find p on old pgrp"); -#endif - /* - * delete old if empty - */ - if (p->p_pgrp->pg_mem == 0) + LIST_REMOVE(p, p_pglist); + if (p->p_pgrp->pg_members.lh_first == 0) pgdelete(p->p_pgrp); - /* - * link into new one - */ p->p_pgrp = pgrp; - p->p_pgrpnxt = pgrp->pg_mem; - pgrp->pg_mem = p; + LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); return (0); } /* * remove process from process group */ +int leavepgrp(p) register struct proc *p; { - register struct proc **pp = &p->p_pgrp->pg_mem; - for (; *pp; pp = &(*pp)->p_pgrpnxt) { - if (*pp == p) { - *pp = p->p_pgrpnxt; - break; - } - } -#ifdef DIAGNOSTIC - if (pp == NULL) - panic("leavepgrp: can't find p in pgrp"); -#endif - if (!p->p_pgrp->pg_mem) + LIST_REMOVE(p, p_pglist); + if (p->p_pgrp->pg_members.lh_first == 0) pgdelete(p->p_pgrp); p->p_pgrp = 0; return (0); @@ -283,24 +263,15 @@ leavepgrp(p) /* * delete a process group */ +void pgdelete(pgrp) register struct pgrp *pgrp; { - register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; if (pgrp->pg_session->s_ttyp != NULL && pgrp->pg_session->s_ttyp->t_pgrp == pgrp) pgrp->pg_session->s_ttyp->t_pgrp = NULL; - for (; *pgp; pgp = &(*pgp)->pg_hforw) { - if (*pgp == pgrp) { - *pgp = pgrp->pg_hforw; - break; - } - } -#ifdef DIAGNOSTIC - if (pgp == NULL) - panic("pgdelete: can't find pgrp on hash chain"); -#endif + LIST_REMOVE(pgrp, pg_hash); if (--pgrp->pg_session->s_count == 0) FREE(pgrp->pg_session, M_SESSION); FREE(pgrp, M_PGRP); @@ -318,6 +289,7 @@ static void orphanpg(); * entering == 0 => p is leaving specified group. * entering == 1 => p is entering specified group. */ +void fixjobc(p, pgrp, entering) register struct proc *p; register struct pgrp *pgrp; @@ -342,7 +314,7 @@ fixjobc(p, pgrp, entering) * their process groups; if so, adjust counts for children's * process groups. */ - for (p = p->p_cptr; p; p = p->p_osptr) + for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next) if ((hispgrp = p->p_pgrp) != pgrp && hispgrp->pg_session == mysession && p->p_stat != SZOMB) @@ -363,9 +335,10 @@ orphanpg(pg) { register struct proc *p; - for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { + for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { if (p->p_stat == SSTOP) { - for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { + for (p = pg->pg_members.lh_first; p != 0; + p = p->p_pglist.le_next) { psignal(p, SIGHUP); psignal(p, SIGCONT); } @@ -374,28 +347,28 @@ orphanpg(pg) } } -#ifdef debug -/* DEBUG */ +#ifdef DEBUG pgrpdump() { register struct pgrp *pgrp; register struct proc *p; register i; - for (i=0; ipg_hforw) { - printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", - pgrp, pgrp->pg_id, pgrp->pg_session, - pgrp->pg_session->s_count, pgrp->pg_mem); - for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { - printf("\t\tpid %d addr %x pgrp %x\n", - p->p_pid, p, p->p_pgrp); - } - } - + for (i = 0; i <= pgrphash; i++) { + if (pgrp = pgrphashtbl[i].lh_first) { + printf("\tindx %d\n", i); + for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) { + printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", + pgrp, pgrp->pg_id, pgrp->pg_session, + pgrp->pg_session->s_count, + pgrp->pg_members.lh_first); + for (p = pgrp->pg_members.lh_first; p != 0; + p = p->p_pglist.le_next) { + printf("\t\tpid %d addr %x pgrp %x\n", + p->p_pid, p, p->p_pgrp); + } + } } } } -#endif /* debug */ +#endif /* DEBUG */ diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index ef40077..29e4c67 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 + * @(#)kern_prot.c 8.9 (Berkeley) 2/14/95 */ /* @@ -51,15 +51,15 @@ #include #include -struct args { - int dummy; -}; +#include +#include /* ARGSUSED */ +int getpid(p, uap, retval) struct proc *p; - struct args *uap; - int *retval; + void *uap; + register_t *retval; { *retval = p->p_pid; @@ -70,10 +70,11 @@ getpid(p, uap, retval) } /* ARGSUSED */ +int getppid(p, uap, retval) struct proc *p; - struct args *uap; - int *retval; + void *uap; + register_t *retval; { *retval = p->p_pptr->p_pid; @@ -81,10 +82,11 @@ getppid(p, uap, retval) } /* Get process group ID; note that POSIX getpgrp takes no parameter */ +int getpgrp(p, uap, retval) struct proc *p; - struct args *uap; - int *retval; + void *uap; + register_t *retval; { *retval = p->p_pgrp->pg_id; @@ -92,10 +94,11 @@ getpgrp(p, uap, retval) } /* ARGSUSED */ +int getuid(p, uap, retval) struct proc *p; - struct args *uap; - int *retval; + void *uap; + register_t *retval; { *retval = p->p_cred->p_ruid; @@ -106,10 +109,11 @@ getuid(p, uap, retval) } /* ARGSUSED */ +int geteuid(p, uap, retval) struct proc *p; - struct args *uap; - int *retval; + void *uap; + register_t *retval; { *retval = p->p_ucred->cr_uid; @@ -117,10 +121,11 @@ geteuid(p, uap, retval) } /* ARGSUSED */ +int getgid(p, uap, retval) struct proc *p; - struct args *uap; - int *retval; + void *uap; + register_t *retval; { *retval = p->p_cred->p_rgid; @@ -136,30 +141,31 @@ getgid(p, uap, retval) * correctly in a library function. */ /* ARGSUSED */ +int getegid(p, uap, retval) struct proc *p; - struct args *uap; - int *retval; + void *uap; + register_t *retval; { *retval = p->p_ucred->cr_groups[0]; return (0); } -struct getgroups_args { - u_int gidsetsize; - gid_t *gidset; -}; +int getgroups(p, uap, retval) struct proc *p; - register struct getgroups_args *uap; - int *retval; + register struct getgroups_args /* { + syscallarg(u_int) gidsetsize; + syscallarg(gid_t *) gidset; + } */ *uap; + register_t *retval; { register struct pcred *pc = p->p_cred; register u_int ngrp; int error; - if ((ngrp = uap->gidsetsize) == 0) { + if ((ngrp = SCARG(uap, gidsetsize)) == 0) { *retval = pc->pc_ucred->cr_ngroups; return (0); } @@ -167,17 +173,18 @@ getgroups(p, uap, retval) return (EINVAL); ngrp = pc->pc_ucred->cr_ngroups; if (error = copyout((caddr_t)pc->pc_ucred->cr_groups, - (caddr_t)uap->gidset, ngrp * sizeof(gid_t))) + (caddr_t)SCARG(uap, gidset), ngrp * sizeof(gid_t))) return (error); *retval = ngrp; return (0); } /* ARGSUSED */ +int setsid(p, uap, retval) register struct proc *p; - struct args *uap; - int *retval; + void *uap; + register_t *retval; { if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { @@ -202,21 +209,21 @@ setsid(p, uap, retval) * there must exist some pid in same session having pgid (EPERM) * pid must not be session leader (EPERM) */ -struct setpgid_args { - int pid; /* target process id */ - int pgid; /* target pgrp id */ -}; /* ARGSUSED */ +int setpgid(curp, uap, retval) struct proc *curp; - register struct setpgid_args *uap; - int *retval; + register struct setpgid_args /* { + syscallarg(int) pid; + syscallarg(int) pgid; + } */ *uap; + register_t *retval; { register struct proc *targp; /* target process */ register struct pgrp *pgrp; /* target pgrp */ - if (uap->pid != 0 && uap->pid != curp->p_pid) { - if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) + if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != curp->p_pid) { + if ((targp = pfind(SCARG(uap, pid))) == 0 || !inferior(targp)) return (ESRCH); if (targp->p_session != curp->p_session) return (EPERM); @@ -226,29 +233,29 @@ setpgid(curp, uap, retval) targp = curp; if (SESS_LEADER(targp)) return (EPERM); - if (uap->pgid == 0) - uap->pgid = targp->p_pid; - else if (uap->pgid != targp->p_pid) - if ((pgrp = pgfind(uap->pgid)) == 0 || + if (SCARG(uap, pgid) == 0) + SCARG(uap, pgid) = targp->p_pid; + else if (SCARG(uap, pgid) != targp->p_pid) + if ((pgrp = pgfind(SCARG(uap, pgid))) == 0 || pgrp->pg_session != curp->p_session) return (EPERM); - return (enterpgrp(targp, uap->pgid, 0)); + return (enterpgrp(targp, SCARG(uap, pgid), 0)); } -struct setuid_args { - uid_t uid; -}; /* ARGSUSED */ +int setuid(p, uap, retval) struct proc *p; - struct setuid_args *uap; - int *retval; + struct setuid_args /* { + syscallarg(uid_t) uid; + } */ *uap; + register_t *retval; { register struct pcred *pc = p->p_cred; register uid_t uid; int error; - uid = uap->uid; + uid = SCARG(uap, uid); if (uid != pc->p_ruid && (error = suser(pc->pc_ucred, &p->p_acflag))) return (error); @@ -267,20 +274,20 @@ setuid(p, uap, retval) return (0); } -struct seteuid_args { - uid_t euid; -}; /* ARGSUSED */ +int seteuid(p, uap, retval) struct proc *p; - struct seteuid_args *uap; - int *retval; + struct seteuid_args /* { + syscallarg(uid_t) euid; + } */ *uap; + register_t *retval; { register struct pcred *pc = p->p_cred; register uid_t euid; int error; - euid = uap->euid; + euid = SCARG(uap, euid); if (euid != pc->p_ruid && euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag))) return (error); @@ -294,20 +301,20 @@ seteuid(p, uap, retval) return (0); } -struct setgid_args { - gid_t gid; -}; /* ARGSUSED */ +int setgid(p, uap, retval) struct proc *p; - struct setgid_args *uap; - int *retval; + struct setgid_args /* { + syscallarg(gid_t) gid; + } */ *uap; + register_t *retval; { register struct pcred *pc = p->p_cred; register gid_t gid; int error; - gid = uap->gid; + gid = SCARG(uap, gid); if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag))) return (error); pc->pc_ucred = crcopy(pc->pc_ucred); @@ -318,20 +325,20 @@ setgid(p, uap, retval) return (0); } -struct setegid_args { - gid_t egid; -}; /* ARGSUSED */ +int setegid(p, uap, retval) struct proc *p; - struct setegid_args *uap; - int *retval; + struct setegid_args /* { + syscallarg(gid_t) egid; + } */ *uap; + register_t *retval; { register struct pcred *pc = p->p_cred; register gid_t egid; int error; - egid = uap->egid; + egid = SCARG(uap, egid); if (egid != pc->p_rgid && egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag))) return (error); @@ -341,15 +348,15 @@ setegid(p, uap, retval) return (0); } -struct setgroups_args { - u_int gidsetsize; - gid_t *gidset; -}; /* ARGSUSED */ +int setgroups(p, uap, retval) struct proc *p; - struct setgroups_args *uap; - int *retval; + struct setgroups_args /* { + syscallarg(u_int) gidsetsize; + syscallarg(gid_t *) gidset; + } */ *uap; + register_t *retval; { register struct pcred *pc = p->p_cred; register u_int ngrp; @@ -357,10 +364,11 @@ setgroups(p, uap, retval) if (error = suser(pc->pc_ucred, &p->p_acflag)) return (error); - if ((ngrp = uap->gidsetsize) > NGROUPS) + ngrp = SCARG(uap, gidsetsize); + if (ngrp < 1 || ngrp > NGROUPS) return (EINVAL); pc->pc_ucred = crcopy(pc->pc_ucred); - if (error = copyin((caddr_t)uap->gidset, + if (error = copyin((caddr_t)SCARG(uap, gidset), (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))) return (error); pc->pc_ucred->cr_ngroups = ngrp; @@ -369,64 +377,89 @@ setgroups(p, uap, retval) } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) -struct setreuid_args { - int ruid; - int euid; -}; /* ARGSUSED */ -osetreuid(p, uap, retval) +int +compat_43_setreuid(p, uap, retval) register struct proc *p; - struct setreuid_args *uap; - int *retval; + struct compat_43_setreuid_args /* { + syscallarg(int) ruid; + syscallarg(int) euid; + } */ *uap; + register_t *retval; { register struct pcred *pc = p->p_cred; - struct seteuid_args args; + union { + struct setuid_args sa; + struct seteuid_args ea; + } args; /* - * we assume that the intent of setting ruid is to be able to get - * back ruid priviledge. So we make sure that we will be able to - * do so, but do not actually set the ruid. + * If ruid == euid then setreuid is being used to emulate setuid, + * just do it. */ - if (uap->ruid != (uid_t)-1 && uap->ruid != pc->p_ruid && - uap->ruid != pc->p_svuid) + if (SCARG(uap, ruid) != -1 && SCARG(uap, ruid) == SCARG(uap, euid)) { + SCARG(&args.sa, uid) = SCARG(uap, ruid); + return (setuid(p, &args.sa, retval)); + } + /* + * Otherwise we assume that the intent of setting ruid is to be + * able to get back ruid priviledge (i.e. swapping ruid and euid). + * So we make sure that we will be able to do so, but do not + * actually set the ruid. + */ + if (SCARG(uap, ruid) != (uid_t)-1 && SCARG(uap, ruid) != pc->p_ruid && + SCARG(uap, ruid) != pc->p_svuid) return (EPERM); - if (uap->euid == (uid_t)-1) + if (SCARG(uap, euid) == (uid_t)-1) return (0); - args.euid = uap->euid; - return (seteuid(p, &args, retval)); + SCARG(&args.ea, euid) = SCARG(uap, euid); + return (seteuid(p, &args.ea, retval)); } -struct setregid_args { - int rgid; - int egid; -}; /* ARGSUSED */ -osetregid(p, uap, retval) +int +compat_43_setregid(p, uap, retval) register struct proc *p; - struct setregid_args *uap; - int *retval; + struct compat_43_setregid_args /* { + syscallarg(int) rgid; + syscallarg(int) egid; + } */ *uap; + register_t *retval; { register struct pcred *pc = p->p_cred; - struct setegid_args args; + union { + struct setgid_args sa; + struct setegid_args ea; + } args; /* - * we assume that the intent of setting rgid is to be able to get - * back rgid priviledge. So we make sure that we will be able to - * do so, but do not actually set the rgid. + * If rgid == egid then setreuid is being used to emulate setgid, + * just do it. + */ + if (SCARG(uap, rgid) != -1 && SCARG(uap, rgid) == SCARG(uap, egid)) { + SCARG(&args.sa, gid) = SCARG(uap, rgid); + return (setgid(p, &args.sa, retval)); + } + /* + * Otherwise we assume that the intent of setting rgid is to be + * able to get back rgid priviledge (i.e. swapping rgid and egid). + * So we make sure that we will be able to do so, but do not + * actually set the rgid. */ - if (uap->rgid != (gid_t)-1 && uap->rgid != pc->p_rgid && - uap->rgid != pc->p_svgid) + if (SCARG(uap, rgid) != (gid_t)-1 && SCARG(uap, rgid) != pc->p_rgid && + SCARG(uap, rgid) != pc->p_svgid) return (EPERM); - if (uap->egid == (gid_t)-1) + if (SCARG(uap, egid) == (gid_t)-1) return (0); - args.egid = uap->egid; - return (setegid(p, &args, retval)); + SCARG(&args.ea, egid) = SCARG(uap, egid); + return (setegid(p, &args.ea, retval)); } #endif /* defined(COMPAT_43) || defined(COMPAT_SUNOS) */ /* * Check if gid is a member of the group set. */ +int groupmember(gid, cred) gid_t gid; register struct ucred *cred; @@ -447,9 +480,10 @@ groupmember(gid, cred) * indicating use of super-powers. * Returns 0 or error. */ +int suser(cred, acflag) struct ucred *cred; - short *acflag; + u_short *acflag; { if (cred->cr_uid == 0) { if (acflag) @@ -477,6 +511,7 @@ crget() * Free a cred structure. * Throws away space when ref count gets to 0. */ +void crfree(cr) struct ucred *cr; { @@ -524,40 +559,40 @@ crdup(cr) /* * Get login name, if available. */ -struct getlogin_args { - char *namebuf; - u_int namelen; -}; /* ARGSUSED */ +int getlogin(p, uap, retval) struct proc *p; - struct getlogin_args *uap; - int *retval; + struct getlogin_args /* { + syscallarg(char *) namebuf; + syscallarg(u_int) namelen; + } */ *uap; + register_t *retval; { - if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login)) - uap->namelen = sizeof (p->p_pgrp->pg_session->s_login); + if (SCARG(uap, namelen) > sizeof (p->p_pgrp->pg_session->s_login)) + SCARG(uap, namelen) = sizeof (p->p_pgrp->pg_session->s_login); return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, - (caddr_t) uap->namebuf, uap->namelen)); + (caddr_t) SCARG(uap, namebuf), SCARG(uap, namelen))); } /* * Set login name. */ -struct setlogin_args { - char *namebuf; -}; /* ARGSUSED */ +int setlogin(p, uap, retval) struct proc *p; - struct setlogin_args *uap; - int *retval; + struct setlogin_args /* { + syscallarg(char *) namebuf; + } */ *uap; + register_t *retval; { int error; if (error = suser(p->p_ucred, &p->p_acflag)) return (error); - error = copyinstr((caddr_t) uap->namebuf, + error = copyinstr((caddr_t) SCARG(uap, namebuf), (caddr_t) p->p_pgrp->pg_session->s_login, sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0); if (error == ENAMETOOLONG) diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 68e9dfb..569b9d9 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -35,41 +35,48 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94 + * @(#)kern_resource.c 8.8 (Berkeley) 2/14/95 */ #include +#include #include #include #include #include #include +#include +#include + #include +int donice __P((struct proc *curp, struct proc *chgp, int n)); +int dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp)); + /* * Resource controls and accounting. */ -struct getpriority_args { - int which; - int who; -}; +int getpriority(curp, uap, retval) struct proc *curp; - register struct getpriority_args *uap; - int *retval; + register struct getpriority_args /* { + syscallarg(int) which; + syscallarg(int) who; + } */ *uap; + register_t *retval; { register struct proc *p; register int low = PRIO_MAX + 1; - switch (uap->which) { + switch (SCARG(uap, which)) { case PRIO_PROCESS: - if (uap->who == 0) + if (SCARG(uap, who) == 0) p = curp; else - p = pfind(uap->who); + p = pfind(SCARG(uap, who)); if (p == 0) break; low = p->p_nice; @@ -78,11 +85,12 @@ getpriority(curp, uap, retval) case PRIO_PGRP: { register struct pgrp *pg; - if (uap->who == 0) + if (SCARG(uap, who) == 0) pg = curp->p_pgrp; - else if ((pg = pgfind(uap->who)) == NULL) + else if ((pg = pgfind(SCARG(uap, who))) == NULL) break; - for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { + for (p = pg->pg_members.lh_first; p != 0; + p = p->p_pglist.le_next) { if (p->p_nice < low) low = p->p_nice; } @@ -90,13 +98,12 @@ getpriority(curp, uap, retval) } case PRIO_USER: - if (uap->who == 0) - uap->who = curp->p_ucred->cr_uid; - for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { - if (p->p_ucred->cr_uid == uap->who && + if (SCARG(uap, who) == 0) + SCARG(uap, who) = curp->p_ucred->cr_uid; + for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) + if (p->p_ucred->cr_uid == SCARG(uap, who) && p->p_nice < low) low = p->p_nice; - } break; default: @@ -108,53 +115,54 @@ getpriority(curp, uap, retval) return (0); } -struct setpriority_args { - int which; - int who; - int prio; -}; /* ARGSUSED */ +int setpriority(curp, uap, retval) struct proc *curp; - register struct setpriority_args *uap; - int *retval; + register struct setpriority_args /* { + syscallarg(int) which; + syscallarg(int) who; + syscallarg(int) prio; + } */ *uap; + register_t *retval; { register struct proc *p; int found = 0, error = 0; - switch (uap->which) { + switch (SCARG(uap, which)) { case PRIO_PROCESS: - if (uap->who == 0) + if (SCARG(uap, who) == 0) p = curp; else - p = pfind(uap->who); + p = pfind(SCARG(uap, who)); if (p == 0) break; - error = donice(curp, p, uap->prio); + error = donice(curp, p, SCARG(uap, prio)); found++; break; case PRIO_PGRP: { register struct pgrp *pg; - if (uap->who == 0) + if (SCARG(uap, who) == 0) pg = curp->p_pgrp; - else if ((pg = pgfind(uap->who)) == NULL) + else if ((pg = pgfind(SCARG(uap, who))) == NULL) break; - for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { - error = donice(curp, p, uap->prio); + for (p = pg->pg_members.lh_first; p != 0; + p = p->p_pglist.le_next) { + error = donice(curp, p, SCARG(uap, prio)); found++; } break; } case PRIO_USER: - if (uap->who == 0) - uap->who = curp->p_ucred->cr_uid; - for (p = (struct proc *)allproc; p != NULL; p = p->p_next) - if (p->p_ucred->cr_uid == uap->who) { - error = donice(curp, p, uap->prio); + if (SCARG(uap, who) == 0) + SCARG(uap, who) = curp->p_ucred->cr_uid; + for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) + if (p->p_ucred->cr_uid == SCARG(uap, who)) { + error = donice(curp, p, SCARG(uap, prio)); found++; } break; @@ -167,6 +175,7 @@ setpriority(curp, uap, retval) return (error); } +int donice(curp, chgp, n) register struct proc *curp, *chgp; register int n; @@ -189,71 +198,73 @@ donice(curp, chgp, n) } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) -struct setrlimit_args { - u_int which; - struct orlimit *lim; -}; /* ARGSUSED */ -osetrlimit(p, uap, retval) +int +compat_43_setrlimit(p, uap, retval) struct proc *p; - register struct setrlimit_args *uap; - int *retval; + struct compat_43_setrlimit_args /* { + syscallarg(u_int) which; + syscallarg(struct ogetrlimit *) rlp; + } */ *uap; + register_t *retval; { struct orlimit olim; struct rlimit lim; int error; - if (error = - copyin((caddr_t)uap->lim, (caddr_t)&olim, sizeof (struct orlimit))) + if (error = copyin((caddr_t)SCARG(uap, rlp), (caddr_t)&olim, + sizeof (struct orlimit))) return (error); lim.rlim_cur = olim.rlim_cur; lim.rlim_max = olim.rlim_max; - return (dosetrlimit(p, uap->which, &lim)); + return (dosetrlimit(p, SCARG(uap, which), &lim)); } -struct getrlimit_args { - u_int which; - struct orlimit *rlp; -}; /* ARGSUSED */ -ogetrlimit(p, uap, retval) +int +compat_43_getrlimit(p, uap, retval) struct proc *p; - register struct getrlimit_args *uap; - int *retval; + register struct compat_43_getrlimit_args /* { + syscallarg(u_int) which; + syscallarg(struct ogetrlimit *) rlp; + } */ *uap; + register_t *retval; { struct orlimit olim; - if (uap->which >= RLIM_NLIMITS) + if (SCARG(uap, which) >= RLIM_NLIMITS) return (EINVAL); - olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; + olim.rlim_cur = p->p_rlimit[SCARG(uap, which)].rlim_cur; if (olim.rlim_cur == -1) olim.rlim_cur = 0x7fffffff; - olim.rlim_max = p->p_rlimit[uap->which].rlim_max; + olim.rlim_max = p->p_rlimit[SCARG(uap, which)].rlim_max; if (olim.rlim_max == -1) olim.rlim_max = 0x7fffffff; - return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim))); + return (copyout((caddr_t)&olim, (caddr_t)SCARG(uap, rlp), + sizeof(olim))); } #endif /* COMPAT_43 || COMPAT_SUNOS */ -struct __setrlimit_args { - u_int which; - struct rlimit *lim; -}; /* ARGSUSED */ +int setrlimit(p, uap, retval) struct proc *p; - register struct __setrlimit_args *uap; - int *retval; + register struct setrlimit_args /* { + syscallarg(u_int) which; + syscallarg(struct rlimit *) rlp; + } */ *uap; + register_t *retval; { struct rlimit alim; int error; - if (error = - copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) + if (error = copyin((caddr_t)SCARG(uap, rlp), (caddr_t)&alim, + sizeof (struct rlimit))) return (error); - return (dosetrlimit(p, uap->which, &alim)); + return (dosetrlimit(p, SCARG(uap, which), &alim)); } +int dosetrlimit(p, which, limp) struct proc *p; u_int which; @@ -337,27 +348,28 @@ dosetrlimit(p, which, limp) return (0); } -struct __getrlimit_args { - u_int which; - struct rlimit *rlp; -}; /* ARGSUSED */ +int getrlimit(p, uap, retval) struct proc *p; - register struct __getrlimit_args *uap; - int *retval; + register struct getrlimit_args /* { + syscallarg(u_int) which; + syscallarg(struct rlimit *) rlp; + } */ *uap; + register_t *retval; { - if (uap->which >= RLIM_NLIMITS) + if (SCARG(uap, which) >= RLIM_NLIMITS) return (EINVAL); - return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, - sizeof (struct rlimit))); + return (copyout((caddr_t)&p->p_rlimit[SCARG(uap, which)], + (caddr_t)SCARG(uap, rlp), sizeof (struct rlimit))); } /* * Transform the running time and tick information in proc p into user, * system, and interrupt time usage. */ +void calcru(p, up, sp, ip) register struct proc *p; register struct timeval *up; @@ -410,19 +422,19 @@ calcru(p, up, sp, ip) } } -struct getrusage_args { - int who; - struct rusage *rusage; -}; /* ARGSUSED */ +int getrusage(p, uap, retval) register struct proc *p; - register struct getrusage_args *uap; - int *retval; + register struct getrusage_args /* { + syscallarg(int) who; + syscallarg(struct rusage *) rusage; + } */ *uap; + register_t *retval; { register struct rusage *rup; - switch (uap->who) { + switch (SCARG(uap, who)) { case RUSAGE_SELF: rup = &p->p_stats->p_ru; @@ -436,10 +448,11 @@ getrusage(p, uap, retval) default: return (EINVAL); } - return (copyout((caddr_t)rup, (caddr_t)uap->rusage, + return (copyout((caddr_t)rup, (caddr_t)SCARG(uap, rusage), sizeof (struct rusage))); } +void ruadd(ru, ru2) register struct rusage *ru, *ru2; { diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 3dcff92..5683b9c 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_sig.c 8.7 (Berkeley) 4/18/94 + * @(#)kern_sig.c 8.14 (Berkeley) 5/14/95 */ #define SIGPROP /* include signal properties table */ @@ -57,11 +57,16 @@ #include #include +#include +#include + #include #include #include /* for coredump */ +void stop __P((struct proc *p)); + /* * Can process p, with pcred pc, send the signal signum to process q? */ @@ -73,16 +78,16 @@ (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \ ((signum) == SIGCONT && (q)->p_session == (p)->p_session)) -struct sigaction_args { - int signum; - struct sigaction *nsa; - struct sigaction *osa; -}; /* ARGSUSED */ +int sigaction(p, uap, retval) struct proc *p; - register struct sigaction_args *uap; - int *retval; + register struct sigaction_args /* { + syscallarg(int) signum; + syscallarg(struct sigaction *) nsa; + syscallarg(struct sigaction *) osa; + } */ *uap; + register_t *retval; { struct sigaction vec; register struct sigaction *sa; @@ -90,12 +95,12 @@ sigaction(p, uap, retval) register int signum; int bit, error; - signum = uap->signum; + signum = SCARG(uap, signum); if (signum <= 0 || signum >= NSIG || signum == SIGKILL || signum == SIGSTOP) return (EINVAL); sa = &vec; - if (uap->osa) { + if (SCARG(uap, osa)) { sa->sa_handler = ps->ps_sigact[signum]; sa->sa_mask = ps->ps_catchmask[signum]; bit = sigmask(signum); @@ -106,12 +111,12 @@ sigaction(p, uap, retval) sa->sa_flags |= SA_RESTART; if (p->p_flag & P_NOCLDSTOP) sa->sa_flags |= SA_NOCLDSTOP; - if (error = copyout((caddr_t)sa, (caddr_t)uap->osa, + if (error = copyout((caddr_t)sa, (caddr_t)SCARG(uap, osa), sizeof (vec))) return (error); } - if (uap->nsa) { - if (error = copyin((caddr_t)uap->nsa, (caddr_t)sa, + if (SCARG(uap, nsa)) { + if (error = copyin((caddr_t)SCARG(uap, nsa), (caddr_t)sa, sizeof (vec))) return (error); setsigvec(p, signum, sa); @@ -119,6 +124,7 @@ sigaction(p, uap, retval) return (0); } +void setsigvec(p, signum, sa) register struct proc *p; int signum; @@ -233,31 +239,31 @@ execsigs(p) * and return old mask as return value; * the library stub does the rest. */ -struct sigprocmask_args { - int how; - sigset_t mask; -}; +int sigprocmask(p, uap, retval) register struct proc *p; - struct sigprocmask_args *uap; - int *retval; + struct sigprocmask_args /* { + syscallarg(int) how; + syscallarg(sigset_t) mask; + } */ *uap; + register_t *retval; { int error = 0; *retval = p->p_sigmask; (void) splhigh(); - switch (uap->how) { + switch (SCARG(uap, how)) { case SIG_BLOCK: - p->p_sigmask |= uap->mask &~ sigcantmask; + p->p_sigmask |= SCARG(uap, mask) &~ sigcantmask; break; case SIG_UNBLOCK: - p->p_sigmask &= ~uap->mask; + p->p_sigmask &= ~SCARG(uap, mask); break; case SIG_SETMASK: - p->p_sigmask = uap->mask &~ sigcantmask; + p->p_sigmask = SCARG(uap, mask) &~ sigcantmask; break; default: @@ -268,14 +274,12 @@ sigprocmask(p, uap, retval) return (error); } -struct sigpending_args { - int dummy; -}; /* ARGSUSED */ +int sigpending(p, uap, retval) struct proc *p; - struct sigpending_args *uap; - int *retval; + void *uap; + register_t *retval; { *retval = p->p_siglist; @@ -286,16 +290,16 @@ sigpending(p, uap, retval) /* * Generalized interface signal handler, 4.3-compatible. */ -struct osigvec_args { - int signum; - struct sigvec *nsv; - struct sigvec *osv; -}; /* ARGSUSED */ -osigvec(p, uap, retval) +int +compat_43_sigvec(p, uap, retval) struct proc *p; - register struct osigvec_args *uap; - int *retval; + register struct compat_43_sigvec_args /* { + syscallarg(int) signum; + syscallarg(struct sigvec *) nsv; + syscallarg(struct sigvec *) osv; + } */ *uap; + register_t *retval; { struct sigvec vec; register struct sigacts *ps = p->p_sigacts; @@ -303,12 +307,12 @@ osigvec(p, uap, retval) register int signum; int bit, error; - signum = uap->signum; + signum = SCARG(uap, signum); if (signum <= 0 || signum >= NSIG || signum == SIGKILL || signum == SIGSTOP) return (EINVAL); sv = &vec; - if (uap->osv) { + if (SCARG(uap, osv)) { *(sig_t *)&sv->sv_handler = ps->ps_sigact[signum]; sv->sv_mask = ps->ps_catchmask[signum]; bit = sigmask(signum); @@ -321,12 +325,12 @@ osigvec(p, uap, retval) if (p->p_flag & P_NOCLDSTOP) sv->sv_flags |= SA_NOCLDSTOP; #endif - if (error = copyout((caddr_t)sv, (caddr_t)uap->osv, + if (error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, osv), sizeof (vec))) return (error); } - if (uap->nsv) { - if (error = copyin((caddr_t)uap->nsv, (caddr_t)sv, + if (SCARG(uap, nsv)) { + if (error = copyin((caddr_t)SCARG(uap, nsv), (caddr_t)sv, sizeof (vec))) return (error); #ifdef COMPAT_SUNOS @@ -345,34 +349,34 @@ osigvec(p, uap, retval) return (0); } -struct osigblock_args { - int mask; -}; -osigblock(p, uap, retval) +int +compat_43_sigblock(p, uap, retval) register struct proc *p; - struct osigblock_args *uap; - int *retval; + struct compat_43_sigblock_args /* { + syscallarg(int) mask; + } */ *uap; + register_t *retval; { (void) splhigh(); *retval = p->p_sigmask; - p->p_sigmask |= uap->mask &~ sigcantmask; + p->p_sigmask |= SCARG(uap, mask) &~ sigcantmask; (void) spl0(); return (0); } -struct osigsetmask_args { - int mask; -}; -osigsetmask(p, uap, retval) +int +compat_43_sigsetmask(p, uap, retval) struct proc *p; - struct osigsetmask_args *uap; - int *retval; + struct compat_43_sigsetmask_args /* { + syscallarg(int) mask; + } */ *uap; + register_t *retval; { (void) splhigh(); *retval = p->p_sigmask; - p->p_sigmask = uap->mask &~ sigcantmask; + p->p_sigmask = SCARG(uap, mask) &~ sigcantmask; (void) spl0(); return (0); } @@ -383,14 +387,14 @@ osigsetmask(p, uap, retval) * in the meantime. Note nonstandard calling convention: * libc stub passes mask, not pointer, to save a copyin. */ -struct sigsuspend_args { - sigset_t mask; -}; /* ARGSUSED */ +int sigsuspend(p, uap, retval) register struct proc *p; - struct sigsuspend_args *uap; - int *retval; + struct sigsuspend_args /* { + syscallarg(int) mask; + } */ *uap; + register_t *retval; { register struct sigacts *ps = p->p_sigacts; @@ -403,7 +407,7 @@ sigsuspend(p, uap, retval) */ ps->ps_oldmask = p->p_sigmask; ps->ps_flags |= SAS_OLDMASK; - p->p_sigmask = uap->mask &~ sigcantmask; + p->p_sigmask = SCARG(uap, mask) &~ sigcantmask; while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0) == 0) /* void */; /* always return EINTR rather than ERESTART... */ @@ -411,15 +415,15 @@ sigsuspend(p, uap, retval) } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) -struct osigstack_args { - struct sigstack *nss; - struct sigstack *oss; -}; /* ARGSUSED */ -osigstack(p, uap, retval) +int +compat_43_sigstack(p, uap, retval) struct proc *p; - register struct osigstack_args *uap; - int *retval; + register struct compat_43_sigstack_args /* { + syscallarg(struct sigstack *) nss; + syscallarg(struct sigstack *) oss; + } */ *uap; + register_t *retval; { struct sigstack ss; struct sigacts *psp; @@ -428,11 +432,11 @@ osigstack(p, uap, retval) psp = p->p_sigacts; ss.ss_sp = psp->ps_sigstk.ss_base; ss.ss_onstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; - if (uap->oss && (error = copyout((caddr_t)&ss, (caddr_t)uap->oss, - sizeof (struct sigstack)))) + if (SCARG(uap, oss) && (error = copyout((caddr_t)&ss, + (caddr_t)SCARG(uap, oss), sizeof (struct sigstack)))) return (error); - if (uap->nss && (error = copyin((caddr_t)uap->nss, (caddr_t)&ss, - sizeof (ss))) == 0) { + if (SCARG(uap, nss) && (error = copyin((caddr_t)SCARG(uap, nss), + (caddr_t)&ss, sizeof (ss))) == 0) { psp->ps_sigstk.ss_base = ss.ss_sp; psp->ps_sigstk.ss_size = 0; psp->ps_sigstk.ss_flags |= ss.ss_onstack & SA_ONSTACK; @@ -442,15 +446,15 @@ osigstack(p, uap, retval) } #endif /* COMPAT_43 || COMPAT_SUNOS */ -struct sigaltstack_args { - struct sigaltstack *nss; - struct sigaltstack *oss; -}; /* ARGSUSED */ +int sigaltstack(p, uap, retval) struct proc *p; - register struct sigaltstack_args *uap; - int *retval; + register struct sigaltstack_args /* { + syscallarg(struct sigaltstack *) nss; + syscallarg(struct sigaltstack *) oss; + } */ *uap; + register_t *retval; { struct sigacts *psp; struct sigaltstack ss; @@ -459,12 +463,13 @@ sigaltstack(p, uap, retval) psp = p->p_sigacts; if ((psp->ps_flags & SAS_ALTSTACK) == 0) psp->ps_sigstk.ss_flags |= SA_DISABLE; - if (uap->oss && (error = copyout((caddr_t)&psp->ps_sigstk, - (caddr_t)uap->oss, sizeof (struct sigaltstack)))) + if (SCARG(uap, oss) && (error = copyout((caddr_t)&psp->ps_sigstk, + (caddr_t)SCARG(uap, oss), sizeof (struct sigaltstack)))) return (error); - if (uap->nss == 0) + if (SCARG(uap, nss) == 0) return (0); - if (error = copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss))) + if (error = copyin((caddr_t)SCARG(uap, nss), (caddr_t)&ss, + sizeof (ss))) return (error); if (ss.ss_flags & SA_DISABLE) { if (psp->ps_sigstk.ss_flags & SA_ONSTACK) @@ -480,57 +485,57 @@ sigaltstack(p, uap, retval) return (0); } -struct kill_args { - int pid; - int signum; -}; /* ARGSUSED */ +int kill(cp, uap, retval) register struct proc *cp; - register struct kill_args *uap; - int *retval; + register struct kill_args /* { + syscallarg(int) pid; + syscallarg(int) signum; + } */ *uap; + register_t *retval; { register struct proc *p; register struct pcred *pc = cp->p_cred; - if ((u_int)uap->signum >= NSIG) + if ((u_int)SCARG(uap, signum) >= NSIG) return (EINVAL); - if (uap->pid > 0) { + if (SCARG(uap, pid) > 0) { /* kill single process */ - if ((p = pfind(uap->pid)) == NULL) + if ((p = pfind(SCARG(uap, pid))) == NULL) return (ESRCH); - if (!CANSIGNAL(cp, pc, p, uap->signum)) + if (!CANSIGNAL(cp, pc, p, SCARG(uap, signum))) return (EPERM); - if (uap->signum) - psignal(p, uap->signum); + if (SCARG(uap, signum)) + psignal(p, SCARG(uap, signum)); return (0); } - switch (uap->pid) { + switch (SCARG(uap, pid)) { case -1: /* broadcast signal */ - return (killpg1(cp, uap->signum, 0, 1)); + return (killpg1(cp, SCARG(uap, signum), 0, 1)); case 0: /* signal own process group */ - return (killpg1(cp, uap->signum, 0, 0)); + return (killpg1(cp, SCARG(uap, signum), 0, 0)); default: /* negative explicit process group */ - return (killpg1(cp, uap->signum, -uap->pid, 0)); + return (killpg1(cp, SCARG(uap, signum), -SCARG(uap, pid), 0)); } /* NOTREACHED */ } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) -struct okillpg_args { - int pgid; - int signum; -}; /* ARGSUSED */ -okillpg(p, uap, retval) +int +compat_43_killpg(p, uap, retval) struct proc *p; - register struct okillpg_args *uap; - int *retval; + register struct compat_43_killpg_args /* { + syscallarg(int) pgid; + syscallarg(int) signum; + } */ *uap; + register_t *retval; { - if ((u_int)uap->signum >= NSIG) + if ((u_int)SCARG(uap, signum) >= NSIG) return (EINVAL); - return (killpg1(p, uap->signum, uap->pgid, 0)); + return (killpg1(p, SCARG(uap, signum), SCARG(uap, pgid), 0)); } #endif /* COMPAT_43 || COMPAT_SUNOS */ @@ -538,6 +543,7 @@ okillpg(p, uap, retval) * Common code for kill process group/broadcast kill. * cp is calling process. */ +int killpg1(cp, signum, pgid, all) register struct proc *cp; int signum, pgid, all; @@ -551,7 +557,7 @@ killpg1(cp, signum, pgid, all) /* * broadcast */ - for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { + for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p == cp || !CANSIGNAL(cp, pc, p, signum)) continue; @@ -570,7 +576,8 @@ killpg1(cp, signum, pgid, all) if (pgrp == NULL) return (ESRCH); } - for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) { + for (p = pgrp->pg_members.lh_first; p != 0; + p = p->p_pglist.le_next) { if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p->p_stat == SZOMB || !CANSIGNAL(cp, pc, p, signum)) @@ -597,7 +604,7 @@ gsignal(pgid, signum) } /* - * Send a signal to a process group. If checktty is 1, + * Send a signal to a process group. If checktty is 1, * limit to members which have a controlling terminal. */ void @@ -608,7 +615,8 @@ pgsignal(pgrp, signum, checkctty) register struct proc *p; if (pgrp) - for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) + for (p = pgrp->pg_members.lh_first; p != 0; + p = p->p_pglist.le_next) if (checkctty == 0 || p->p_flag & P_CONTROLT) psignal(p, signum); } @@ -622,7 +630,7 @@ void trapsignal(p, signum, code) struct proc *p; register int signum; - u_int code; + u_long code; { register struct sigacts *ps = p->p_sigacts; int mask; @@ -640,6 +648,7 @@ trapsignal(p, signum, code) p->p_sigmask |= ps->ps_catchmask[signum] | mask; } else { ps->ps_code = code; /* XXX for core dump/debugger */ + ps->ps_sig = signum; /* XXX to verify code */ psignal(p, signum); } } @@ -710,7 +719,7 @@ psignal(p, signum) */ if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 && action == SIG_DFL) - return; + return; p->p_siglist &= ~contsigmask; } p->p_siglist |= mask; @@ -864,6 +873,7 @@ out: * while (signum = CURSIG(curproc)) * postsig(signum); */ +int issignal(p) register struct proc *p; { @@ -890,8 +900,17 @@ issignal(p) /* * If traced, always stop, and stay * stopped until released by the parent. + * + * Note that we must clear the pending signal + * before we call trace_req since that routine + * might cause a fault, calling tsleep and + * leading us back here again with the same signal. + * Then we would be deadlocked because the tracer + * would still be blocked on the ipc struct from + * the initial request. */ p->p_xstat = signum; + p->p_siglist &= ~mask; psignal(p->p_pptr, SIGCHLD); do { stop(p); @@ -899,19 +918,10 @@ issignal(p) } while (!trace_req(p) && p->p_flag & P_TRACED); /* - * If the traced bit got turned off, go back up - * to the top to rescan signals. This ensures - * that p_sig* and ps_sigact are consistent. - */ - if ((p->p_flag & P_TRACED) == 0) - continue; - - /* * If parent wants us to take the signal, * then it will leave it in p->p_xstat; * otherwise we just look for signals again. */ - p->p_siglist &= ~mask; /* clear the old signal */ signum = p->p_xstat; if (signum == 0) continue; @@ -924,6 +934,14 @@ issignal(p) p->p_siglist |= mask; if (p->p_sigmask & mask) continue; + + /* + * If the traced bit got turned off, go back up + * to the top to rescan signals. This ensures + * that p_sig* and ps_sigact are consistent. + */ + if ((p->p_flag & P_TRACED) == 0) + continue; } /* @@ -931,9 +949,9 @@ issignal(p) * Return the signal's number, or fall through * to clear it from the pending mask. */ - switch ((int)p->p_sigacts->ps_sigact[signum]) { + switch ((long)p->p_sigacts->ps_sigact[signum]) { - case SIG_DFL: + case (long)SIG_DFL: /* * Don't take default actions on system processes. */ @@ -976,7 +994,7 @@ issignal(p) return (signum); /*NOTREACHED*/ - case SIG_IGN: + case (long)SIG_IGN: /* * Masking above should prevent us ever trying * to take action on an ignored signal other @@ -1004,6 +1022,7 @@ issignal(p) * via wakeup. Signals are handled elsewhere. The process must not be * on the run queue. */ +void stop(p) register struct proc *p; { @@ -1024,7 +1043,8 @@ postsig(signum) register struct proc *p = curproc; register struct sigacts *ps = p->p_sigacts; register sig_t action; - int code, mask, returnmask; + u_long code; + int mask, returnmask; #ifdef DIAGNOSTIC if (signum == 0) @@ -1077,6 +1097,7 @@ postsig(signum) } else { code = ps->ps_code; ps->ps_code = 0; + ps->ps_sig = 0; } sendsig(action, signum, returnmask, code); } @@ -1085,6 +1106,7 @@ postsig(signum) /* * Kill the current process for stated reason. */ +void killproc(p, why) struct proc *p; char *why; @@ -1103,6 +1125,7 @@ killproc(p, why) * If dumping core, save the signal number for the debugger. Calls exit and * does not return. */ +void sigexit(p, signum) register struct proc *p; int signum; @@ -1122,6 +1145,7 @@ sigexit(p, signum) * Dump core, into a file named "progname.core", unless the process was * setuid/setgid. */ +int coredump(p) register struct proc *p; { @@ -1154,7 +1178,7 @@ coredump(p) } VATTR_NULL(&vattr); vattr.va_size = 0; - LEASE_CHECK(vp, p, cred, LEASE_WRITE); + VOP_LEASE(vp, p, cred, LEASE_WRITE); VOP_SETATTR(vp, &vattr, cred, p); p->p_acflag |= ACORE; bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc)); @@ -1171,7 +1195,7 @@ coredump(p) (off_t)ctob(UPAGES) + ctob(vm->vm_dsize), UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); out: - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); error1 = vn_close(vp, FWRITE, cred, p); if (error == 0) error = error1; @@ -1182,16 +1206,14 @@ out: * Nonexistent system call-- signal process (may want to handle it). * Flag error in case process won't see signal immediately (blocked or ignored). */ -struct nosys_args { - int dummy; -}; /* ARGSUSED */ +int nosys(p, args, retval) struct proc *p; - struct nosys_args *args; - int *retval; + void *args; + register_t *retval; { psignal(p, SIGSYS); - return (EINVAL); + return (ENOSYS); } diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index 5c12afc..df83710 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 + * @(#)kern_subr.c 8.4 (Berkeley) 2/14/95 */ #include @@ -44,6 +44,7 @@ #include #include +int uiomove(cp, n, uio) register caddr_t cp; register int n; @@ -101,17 +102,20 @@ uiomove(cp, n, uio) /* * Give next character to user as result of read. */ +int ureadc(c, uio) register int c; register struct uio *uio; { register struct iovec *iov; + if (uio->uio_resid <= 0) + panic("ureadc: non-positive resid"); again: - if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) - panic("ureadc"); + if (uio->uio_iovcnt <= 0) + panic("ureadc: non-positive iovcnt"); iov = uio->uio_iov; - if (iov->iov_len == 0) { + if (iov->iov_len <= 0) { uio->uio_iovcnt--; uio->uio_iov++; goto again; @@ -143,6 +147,7 @@ again: /* * Get next character written in by user from uio. */ +int uwritec(uio) struct uio *uio; { @@ -153,7 +158,7 @@ uwritec(uio) return (-1); again: if (uio->uio_iovcnt <= 0) - panic("uwritec"); + panic("uwritec: non-positive iovcnt"); iov = uio->uio_iov; if (iov->iov_len == 0) { uio->uio_iov++; diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 1c2a578..6c82027 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_synch.c 8.6 (Berkeley) 1/21/94 + * @(#)kern_synch.c 8.9 (Berkeley) 5/19/95 */ #include @@ -167,7 +167,7 @@ schedcpu(arg) register unsigned int newcpu; wakeup((caddr_t)&lbolt); - for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { + for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { /* * Increment time in/out of memory and sleep time * (if sleeping). We ignore overflow; with 16-bit int's @@ -249,7 +249,7 @@ updatepri(p) * of 2. Shift right by 8, i.e. drop the bottom 256 worth. */ #define TABLESIZE 128 -#define LOOKUP(x) (((int)(x) >> 8) & (TABLESIZE - 1)) +#define LOOKUP(x) (((long)(x) >> 8) & (TABLESIZE - 1)) struct slpque { struct proc *sq_head; struct proc **sq_tailp; @@ -551,6 +551,10 @@ mi_switch() register long s, u; struct timeval tv; +#ifdef DEBUG + if (p->p_simple_locks) + panic("sleep: holding simple lock"); +#endif /* * Compute the amount of time during which the current * process was running, and add that to its total so far. @@ -600,6 +604,7 @@ mi_switch() * Initialize the (doubly-linked) run queues * to be empty. */ +void rqinit() { register int i; diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index ae16dec..b178da3 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 + * @(#)kern_sysctl.c 8.9 (Berkeley) 5/20/95 */ /* @@ -54,13 +54,16 @@ #include #include +#include +#include + sysctlfn kern_sysctl; sysctlfn hw_sysctl; #ifdef DEBUG sysctlfn debug_sysctl; #endif extern sysctlfn vm_sysctl; -extern sysctlfn fs_sysctl; +extern sysctlfn vfs_sysctl; extern sysctlfn net_sysctl; extern sysctlfn cpu_sysctl; @@ -73,40 +76,40 @@ static struct sysctl_lock { int sl_locked; } memlock; -struct sysctl_args { - int *name; - u_int namelen; - void *old; - size_t *oldlenp; - void *new; - size_t newlen; -}; - int __sysctl(p, uap, retval) struct proc *p; - register struct sysctl_args *uap; - int *retval; + register struct __sysctl_args /* { + syscallarg(int *) name; + syscallarg(u_int) namelen; + syscallarg(void *) old; + syscallarg(size_t *) oldlenp; + syscallarg(void *) new; + syscallarg(size_t) newlen; + } */ *uap; + register_t *retval; { int error, dolock = 1; - u_int savelen, oldlen = 0; + size_t savelen, oldlen = 0; sysctlfn *fn; int name[CTL_MAXNAME]; - if (uap->new != NULL && (error = suser(p->p_ucred, &p->p_acflag))) + if (SCARG(uap, new) != NULL && + (error = suser(p->p_ucred, &p->p_acflag))) return (error); /* * all top-level sysctl names are non-terminal */ - if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) + if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) return (EINVAL); - if (error = copyin(uap->name, &name, uap->namelen * sizeof(int))) + if (error = + copyin(SCARG(uap, name), &name, SCARG(uap, namelen) * sizeof(int))) return (error); switch (name[0]) { case CTL_KERN: fn = kern_sysctl; - if (name[2] != KERN_VNODE) /* XXX */ + if (name[2] == KERN_VNODE) /* XXX */ dolock = 0; break; case CTL_HW: @@ -118,11 +121,9 @@ __sysctl(p, uap, retval) case CTL_NET: fn = net_sysctl; break; -#ifdef notyet - case CTL_FS: - fn = fs_sysctl; + case CTL_VFS: + fn = vfs_sysctl; break; -#endif case CTL_MACHDEP: fn = cpu_sysctl; break; @@ -135,11 +136,11 @@ __sysctl(p, uap, retval) return (EOPNOTSUPP); } - if (uap->oldlenp && - (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen)))) + if (SCARG(uap, oldlenp) && + (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen)))) return (error); - if (uap->old != NULL) { - if (!useracc(uap->old, oldlen, B_WRITE)) + if (SCARG(uap, old) != NULL) { + if (!useracc(SCARG(uap, old), oldlen, B_WRITE)) return (EFAULT); while (memlock.sl_lock) { memlock.sl_want = 1; @@ -148,14 +149,14 @@ __sysctl(p, uap, retval) } memlock.sl_lock = 1; if (dolock) - vslock(uap->old, oldlen); + vslock(SCARG(uap, old), oldlen); savelen = oldlen; } - error = (*fn)(name + 1, uap->namelen - 1, uap->old, &oldlen, - uap->new, uap->newlen, p); - if (uap->old != NULL) { + error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old), + &oldlen, SCARG(uap, new), SCARG(uap, newlen), p); + if (SCARG(uap, old) != NULL) { if (dolock) - vsunlock(uap->old, savelen, B_WRITE); + vsunlock(SCARG(uap, old), savelen, B_WRITE); memlock.sl_lock = 0; if (memlock.sl_want) { memlock.sl_want = 0; @@ -164,8 +165,8 @@ __sysctl(p, uap, retval) } if (error) return (error); - if (uap->oldlenp) - error = copyout(&oldlen, uap->oldlenp, sizeof(oldlen)); + if (SCARG(uap, oldlenp)) + error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen)); *retval = oldlen; return (0); } @@ -240,7 +241,7 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, sizeof(struct timeval))); case KERN_VNODE: - return (sysctl_vnode(oldp, oldlenp)); + return (sysctl_vnode(oldp, oldlenp, p)); case KERN_PROC: return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); case KERN_FILE: @@ -338,7 +339,7 @@ debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) if (namelen != 2) return (ENOTDIR); /* overloaded */ cdp = debugvars[name[0]]; - if (cdp->debugname == 0) + if (name[0] >= CTL_DEBUG_MAXID || cdp->debugname == 0) return (EOPNOTSUPP); switch (name[1]) { case CTL_DEBUG_NAME: @@ -534,7 +535,7 @@ sysctl_file(where, sizep) /* * followed by an array of file structures */ - for (fp = filehead; fp != NULL; fp = fp->f_filef) { + for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) { if (buflen < sizeof(struct file)) { *sizep = where - start; return (ENOMEM); @@ -569,10 +570,10 @@ sysctl_doproc(name, namelen, where, sizep) if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) return (EINVAL); - p = (struct proc *)allproc; + p = allproc.lh_first; doingzomb = 0; again: - for (; p != NULL; p = p->p_next) { + for (; p != 0; p = p->p_list.le_next) { /* * Skip embryonic processes. */ @@ -627,7 +628,7 @@ again: needed += sizeof(struct kinfo_proc); } if (doingzomb == 0) { - p = zombproc; + p = zombproc.lh_first; doingzomb++; goto again; } @@ -711,66 +712,71 @@ fill_eproc(p, ep) #define KINFO_LOADAVG (5<<8) #define KINFO_CLOCKRATE (6<<8) -struct getkerninfo_args { - int op; - char *where; - int *size; - int arg; -}; - -ogetkerninfo(p, uap, retval) +compat_43_getkerninfo(p, uap, retval) struct proc *p; - register struct getkerninfo_args *uap; - int *retval; + register struct compat_43_getkerninfo_args /* { + syscallarg(int) op; + syscallarg(char *) where; + syscallarg(int *) size; + syscallarg(int) arg; + } */ *uap; + register_t *retval; { int error, name[5]; - u_int size; + size_t size; - if (uap->size && - (error = copyin((caddr_t)uap->size, (caddr_t)&size, sizeof(size)))) + if (SCARG(uap, size) && (error = copyin((caddr_t)SCARG(uap, size), + (caddr_t)&size, sizeof(size)))) return (error); - switch (uap->op & 0xff00) { + switch (SCARG(uap, op) & 0xff00) { case KINFO_RT: name[0] = PF_ROUTE; name[1] = 0; - name[2] = (uap->op & 0xff0000) >> 16; - name[3] = uap->op & 0xff; - name[4] = uap->arg; - error = net_sysctl(name, 5, uap->where, &size, NULL, 0, p); + name[2] = (SCARG(uap, op) & 0xff0000) >> 16; + name[3] = SCARG(uap, op) & 0xff; + name[4] = SCARG(uap, arg); + error = + net_sysctl(name, 5, SCARG(uap, where), &size, NULL, 0, p); break; case KINFO_VNODE: name[0] = KERN_VNODE; - error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); + error = + kern_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p); break; case KINFO_PROC: name[0] = KERN_PROC; - name[1] = uap->op & 0xff; - name[2] = uap->arg; - error = kern_sysctl(name, 3, uap->where, &size, NULL, 0, p); + name[1] = SCARG(uap, op) & 0xff; + name[2] = SCARG(uap, arg); + error = + kern_sysctl(name, 3, SCARG(uap, where), &size, NULL, 0, p); break; case KINFO_FILE: name[0] = KERN_FILE; - error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); + error = + kern_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p); break; case KINFO_METER: name[0] = VM_METER; - error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); + error = + vm_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p); break; case KINFO_LOADAVG: name[0] = VM_LOADAVG; - error = vm_sysctl(name, 1, uap->where, &size, NULL, 0, p); + error = + vm_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p); break; case KINFO_CLOCKRATE: name[0] = KERN_CLOCKRATE; - error = kern_sysctl(name, 1, uap->where, &size, NULL, 0, p); + error = + kern_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p); break; default: @@ -779,8 +785,8 @@ ogetkerninfo(p, uap, retval) if (error) return (error); *retval = size; - if (uap->size) - error = copyout((caddr_t)&size, (caddr_t)uap->size, + if (SCARG(uap, size)) + error = copyout((caddr_t)&size, (caddr_t)SCARG(uap, size), sizeof(size)); return (error); } diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 4dadcb8..f4facf6 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_time.c 8.1 (Berkeley) 6/10/93 + * @(#)kern_time.c 8.4 (Berkeley) 5/26/95 */ #include @@ -40,6 +40,9 @@ #include #include +#include +#include + #include /* @@ -52,40 +55,40 @@ * timers when they expire. */ -struct gettimeofday_args { - struct timeval *tp; - struct timezone *tzp; -}; /* ARGSUSED */ +int gettimeofday(p, uap, retval) struct proc *p; - register struct gettimeofday_args *uap; - int *retval; + register struct gettimeofday_args /* { + syscallarg(struct timeval *) tp; + syscallarg(struct timezone *) tzp; + } */ *uap; + register_t *retval; { struct timeval atv; int error = 0; - if (uap->tp) { + if (SCARG(uap, tp)) { microtime(&atv); - if (error = copyout((caddr_t)&atv, (caddr_t)uap->tp, + if (error = copyout((caddr_t)&atv, (caddr_t)SCARG(uap, tp), sizeof (atv))) return (error); } - if (uap->tzp) - error = copyout((caddr_t)&tz, (caddr_t)uap->tzp, + if (SCARG(uap, tzp)) + error = copyout((caddr_t)&tz, (caddr_t)SCARG(uap, tzp), sizeof (tz)); return (error); } -struct settimeofday_args { - struct timeval *tv; - struct timezone *tzp; -}; /* ARGSUSED */ +int settimeofday(p, uap, retval) struct proc *p; - struct settimeofday_args *uap; - int *retval; + struct settimeofday_args /* { + syscallarg(struct timeval *) tv; + syscallarg(struct timezone *) tzp; + } */ *uap; + register_t *retval; { struct timeval atv, delta; struct timezone atz; @@ -94,13 +97,21 @@ settimeofday(p, uap, retval) if (error = suser(p->p_ucred, &p->p_acflag)) return (error); /* Verify all parameters before changing time. */ - if (uap->tv && - (error = copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof(atv)))) + if (SCARG(uap, tv) && (error = copyin((caddr_t)SCARG(uap, tv), + (caddr_t)&atv, sizeof(atv)))) return (error); - if (uap->tzp && - (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz)))) + if (SCARG(uap, tzp) && (error = copyin((caddr_t)SCARG(uap, tzp), + (caddr_t)&atz, sizeof(atz)))) return (error); - if (uap->tv) { + if (SCARG(uap, tv)) { + /* + * If the system is secure, we do not allow the time to be + * set to an earlier value (it may be slowed using adjtime, + * but not set back). This feature prevent interlopers from + * setting arbitrary time stamps on files. + */ + if (securelevel > 0 && timercmp(&atv, &time, <)) + return (EPERM); /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ s = splclock(); /* nb. delta.tv_usec may be < 0, but this is OK here */ @@ -112,11 +123,13 @@ settimeofday(p, uap, retval) timevalfix(&boottime); timevaladd(&runtime, &delta); timevalfix(&runtime); - LEASE_UPDATETIME(delta.tv_sec); +# ifdef NFS + lease_updatetime(delta.tv_sec); +# endif splx(s); resettodr(); } - if (uap->tzp) + if (SCARG(uap, tzp)) tz = atz; return (0); } @@ -126,15 +139,15 @@ int tickdelta; /* current clock skew, us. per tick */ long timedelta; /* unapplied time correction, us. */ long bigadj = 1000000; /* use 10x skew above bigadj us. */ -struct adjtime_args { - struct timeval *delta; - struct timeval *olddelta; -}; /* ARGSUSED */ +int adjtime(p, uap, retval) struct proc *p; - register struct adjtime_args *uap; - int *retval; + register struct adjtime_args /* { + syscallarg(struct timeval *) delta; + syscallarg(struct timeval *) olddelta; + } */ *uap; + register_t *retval; { struct timeval atv; register long ndelta, ntickdelta, odelta; @@ -142,8 +155,8 @@ adjtime(p, uap, retval) if (error = suser(p->p_ucred, &p->p_acflag)) return (error); - if (error = - copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval))) + if (error = copyin((caddr_t)SCARG(uap, delta), (caddr_t)&atv, + sizeof(struct timeval))) return (error); /* @@ -174,10 +187,10 @@ adjtime(p, uap, retval) tickdelta = ntickdelta; splx(s); - if (uap->olddelta) { + if (SCARG(uap, olddelta)) { atv.tv_sec = odelta / 1000000; atv.tv_usec = odelta % 1000000; - (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta, + (void) copyout((caddr_t)&atv, (caddr_t)SCARG(uap, olddelta), sizeof(struct timeval)); } return (0); @@ -204,25 +217,25 @@ adjtime(p, uap, retval) * real time timers .it_interval. Rather, we compute the next time in * absolute time the timer should go off. */ -struct getitimer_args { - u_int which; - struct itimerval *itv; -}; /* ARGSUSED */ +int getitimer(p, uap, retval) struct proc *p; - register struct getitimer_args *uap; - int *retval; + register struct getitimer_args /* { + syscallarg(u_int) which; + syscallarg(struct itimerval *) itv; + } */ *uap; + register_t *retval; { struct itimerval aitv; int s; - if (uap->which > ITIMER_PROF) + if (SCARG(uap, which) > ITIMER_PROF) return (EINVAL); s = splclock(); - if (uap->which == ITIMER_REAL) { + if (SCARG(uap, which) == ITIMER_REAL) { /* - * Convert from absoulte to relative time in .it_value + * Convert from absolute to relative time in .it_value * part of real time timer. If time for real time timer * has passed return 0, else return difference between * current time and time for the timer to go off. @@ -235,40 +248,42 @@ getitimer(p, uap, retval) timevalsub(&aitv.it_value, (struct timeval *)&time); } else - aitv = p->p_stats->p_timer[uap->which]; + aitv = p->p_stats->p_timer[SCARG(uap, which)]; splx(s); - return (copyout((caddr_t)&aitv, (caddr_t)uap->itv, + return (copyout((caddr_t)&aitv, (caddr_t)SCARG(uap, itv), sizeof (struct itimerval))); } -struct setitimer_args { - u_int which; - struct itimerval *itv, *oitv; -}; /* ARGSUSED */ +int setitimer(p, uap, retval) struct proc *p; - register struct setitimer_args *uap; - int *retval; + register struct setitimer_args /* { + syscallarg(u_int) which; + syscallarg(struct itimerval *) itv; + syscallarg(struct itimerval *) oitv; + } */ *uap; + register_t *retval; { struct itimerval aitv; register struct itimerval *itvp; int s, error; - if (uap->which > ITIMER_PROF) + if (SCARG(uap, which) > ITIMER_PROF) return (EINVAL); - itvp = uap->itv; + itvp = SCARG(uap, itv); if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv, sizeof(struct itimerval)))) return (error); - if ((uap->itv = uap->oitv) && (error = getitimer(p, uap, retval))) + if ((SCARG(uap, itv) = SCARG(uap, oitv)) && + (error = getitimer(p, uap, retval))) return (error); if (itvp == 0) return (0); if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) return (EINVAL); s = splclock(); - if (uap->which == ITIMER_REAL) { + if (SCARG(uap, which) == ITIMER_REAL) { untimeout(realitexpire, (caddr_t)p); if (timerisset(&aitv.it_value)) { timevaladd(&aitv.it_value, (struct timeval *)&time); @@ -276,7 +291,7 @@ setitimer(p, uap, retval) } p->p_realtimer = aitv; } else - p->p_stats->p_timer[uap->which] = aitv; + p->p_stats->p_timer[SCARG(uap, which)] = aitv; splx(s); return (0); } @@ -322,6 +337,7 @@ realitexpire(arg) * fix it to have at least minimal value (i.e. if it is less * than the resolution of the clock, round it up.) */ +int itimerfix(tv) struct timeval *tv; { @@ -344,6 +360,7 @@ itimerfix(tv) * that it is called in a context where the timers * on which it is operating cannot change in value. */ +int itimerdecr(itp, usec) register struct itimerval *itp; int usec; diff --git a/sys/kern/kern_xxx.c b/sys/kern/kern_xxx.c index 64fac91..caa1cdd 100644 --- a/sys/kern/kern_xxx.c +++ b/sys/kern/kern_xxx.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)kern_xxx.c 8.2 (Berkeley) 11/14/93 + * @(#)kern_xxx.c 8.3 (Berkeley) 2/14/95 */ #include @@ -41,50 +41,54 @@ #include #include -struct reboot_args { - int opt; -}; +#include +#include + /* ARGSUSED */ +int reboot(p, uap, retval) struct proc *p; - struct reboot_args *uap; - int *retval; + struct reboot_args /* { + syscallarg(int) opt; + } */ *uap; + register_t *retval; { int error; if (error = suser(p->p_ucred, &p->p_acflag)) return (error); - boot(uap->opt); + boot(SCARG(uap, opt)); return (0); } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) -struct gethostname_args { - char *hostname; - u_int len; -}; /* ARGSUSED */ -ogethostname(p, uap, retval) +int +compat_43_gethostname(p, uap, retval) struct proc *p; - struct gethostname_args *uap; - int *retval; + struct compat_43_gethostname_args /* { + syscallarg(char *) hostname; + syscallarg(u_int) len; + } */ *uap; + register_t *retval; { int name; name = KERN_HOSTNAME; - return (kern_sysctl(&name, 1, uap->hostname, &uap->len, 0, 0)); + return (kern_sysctl(&name, 1, SCARG(uap, hostname), &SCARG(uap, len), + 0, 0)); } -struct sethostname_args { - char *hostname; - u_int len; -}; /* ARGSUSED */ -osethostname(p, uap, retval) +int +compat_43_sethostname(p, uap, retval) struct proc *p; - register struct sethostname_args *uap; - int *retval; + register struct compat_43_sethostname_args /* { + syscallarg(char *) hostname; + syscallarg(u_int) len; + } */ *uap; + register_t *retval; { int name; int error; @@ -92,45 +96,46 @@ osethostname(p, uap, retval) if (error = suser(p->p_ucred, &p->p_acflag)) return (error); name = KERN_HOSTNAME; - return (kern_sysctl(&name, 1, 0, 0, uap->hostname, uap->len)); + return (kern_sysctl(&name, 1, 0, 0, SCARG(uap, hostname), + SCARG(uap, len))); } -extern long hostid; - -struct gethostid_args { - int dummy; -}; /* ARGSUSED */ -ogethostid(p, uap, retval) +int +compat_43_gethostid(p, uap, retval) struct proc *p; - struct gethostid_args *uap; - int *retval; + void *uap; + register_t *retval; { - *(long *)retval = hostid; + *(int32_t *)retval = hostid; return (0); } #endif /* COMPAT_43 || COMPAT_SUNOS */ #ifdef COMPAT_43 -struct sethostid_args { - long hostid; -}; /* ARGSUSED */ -osethostid(p, uap, retval) +int +compat_43_sethostid(p, uap, retval) struct proc *p; - struct sethostid_args *uap; - int *retval; + struct compat_43_sethostid_args /* { + syscallarg(int32_t) hostid; + } */ *uap; + register_t *retval; { int error; if (error = suser(p->p_ucred, &p->p_acflag)) return (error); - hostid = uap->hostid; + hostid = SCARG(uap, hostid); return (0); } -oquota() +int +compat_43_quota(p, uap, retval) + struct proc *p; + void *uap; + register_t *retval; { return (ENOSYS); diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh index 0ddea0c..4e2c28c 100644 --- a/sys/kern/makesyscalls.sh +++ b/sys/kern/makesyscalls.sh @@ -1,171 +1,365 @@ #! /bin/sh - -# @(#)makesyscalls.sh 8.1 (Berkeley) 6/10/93 +# +# @(#)makesyscalls.sh 8.2 (Berkeley) 2/14/95 set -e -# name of compat option: -compat=COMPAT_43 +case $# in + 2) ;; + *) echo "Usage: $0 config-file input-file" 1>&2 + exit 1 + ;; +esac + +# source the config file. +. $1 -# output files: -sysnames="syscalls.c" -syshdr="../sys/syscall.h" -syssw="init_sysent.c" +# the config file sets the following variables: +# sysnames the syscall names file +# sysnumhdr the syscall numbers file +# syssw the syscall switch file +# sysarghdr the syscall argument struct definitions +# compatopts those syscall types that are for 'compat' syscalls +# switchname the name for the 'struct sysent' we define +# namesname the name for the 'char *[]' we define +# constprefix the prefix for the system call constants +# +# NOTE THAT THIS makesyscalls.sh DOES NOT SUPPORT 'LIBCOMPAT'. # tmp files: sysdcl="sysent.dcl" -syscompat="sysent.compat" +syscompat_pref="sysent." sysent="sysent.switch" -trap "rm $sysdcl $syscompat $sysent" 0 +syscompat_files="" +for file in $compatopts; do + syscompat_files="$syscompat_files $syscompat_pref$file" +done -case $# in - 0) echo "Usage: $0 input-file" 1>&2 - exit 1 - ;; -esac +trap "rm $sysdcl $syscompat_files $sysent" 0 + +# Awk program (must support nawk extensions) +# Use "awk" at Berkeley, "nawk" or "gawk" elsewhere. +awk=${AWK:-awk} -awk < $1 " - BEGIN { - sysdcl = \"$sysdcl\" - syscompat = \"$syscompat\" - sysent = \"$sysent\" - sysnames = \"$sysnames\" - syshdr = \"$syshdr\" - compat = \"$compat\" - infile = \"$1\" - "' +# Does this awk have a "toupper" function? (i.e. is it GNU awk) +isgawk=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null` - printf "/*\n * System call switch table.\n *\n" > sysdcl - printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl +# If this awk does not define "toupper" then define our own. +if [ "$isgawk" = TRUE ] ; then + # GNU awk provides it. + toupper= +else + # Provide our own toupper() + toupper=' +function toupper(str) { + _toupper_cmd = "echo "str" |tr a-z A-Z" + _toupper_cmd | getline _toupper_str; + close(_toupper_cmd); + return _toupper_str; +}' +fi - printf "\n#ifdef %s\n", compat > syscompat - printf "#define compat(n, name) n, __CONCAT(o,name)\n\n" > syscompat +# before handing it off to awk, make a few adjustments: +# (1) insert spaces around {, }, (, ), *, and commas. +# (2) get rid of any and all dollar signs (so that rcs id use safe) +# +# The awk script will deal with blank lines and lines that +# start with the comment character (';'). - printf "/*\n * System call names.\n *\n" > sysnames - printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames +sed -e ' +s/\$//g +:join + /\\$/{a\ - printf "/*\n * System call numbers.\n *\n" > syshdr - printf " * DO NOT EDIT-- this file is automatically generated.\n" > syshdr + N + s/\\\n// + b join } - NR == 1 { - printf " * created from%s\n */\n\n", $0 > sysdcl - printf "#include \n" > sysdcl - printf "#include \n\n" > sysdcl - printf "int\tnosys();\n\n" > sysdcl +2,${ + /^#/!s/\([{}()*,]\)/ \1 /g +} +' < $2 | $awk " +$toupper +BEGIN { + sysnames = \"$sysnames\" + sysnumhdr = \"$sysnumhdr\" + sysarghdr = \"$sysarghdr\" + switchname = \"$switchname\" + namesname = \"$namesname\" + constprefix = \"$constprefix\" - printf "struct sysent sysent[] = {\n" > sysent + sysdcl = \"$sysdcl\" + syscompat_pref = \"$syscompat_pref\" + sysent = \"$sysent\" + infile = \"$2\" - printf " * created from%s\n */\n\n", $0 > sysnames - printf "char *syscallnames[] = {\n" > sysnames + compatopts = \"$compatopts\" + "' - printf " * created from%s\n */\n\n", $0 > syshdr - next - } - NF == 0 || $1 ~ /^;/ { - next - } - $1 ~ /^#[ ]*if/ { - print > sysent - print > sysdcl - print > syscompat - print > sysnames - savesyscall = syscall - next - } - $1 ~ /^#[ ]*else/ { - print > sysent - print > sysdcl - print > syscompat - print > sysnames - syscall = savesyscall - next - } - $1 ~ /^#/ { - print > sysent - print > sysdcl - print > syscompat - print > sysnames - next - } - syscall != $1 { - printf "%s: line %d: syscall number out of sync at %d\n", \ - infile, NR, syscall - printf "line is:\n" - print - exit 1 - } - { comment = $4 - for (i = 5; i <= NF; i++) - comment = comment " " $i - if (NF < 5) - $5 = $4 - } - $2 == "STD" { - printf("int\t%s();\n", $4) > sysdcl - printf("\t{ %d, %s },\t\t\t/* %d = %s */\n", \ - $3, $4, syscall, $5) > sysent - printf("\t\"%s\",\t\t\t/* %d = %s */\n", \ - $5, syscall, $5) > sysnames - printf("#define\tSYS_%s\t%d\n", \ - $5, syscall) > syshdr - syscall++ - next + printf "/*\n * System call switch table.\n *\n" > sysdcl + printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl + + ncompat = split(compatopts,compat) + for (i = 1; i <= ncompat; i++) { + compat_upper[i] = toupper(compat[i]) + compat_file[i] = sprintf("%s%s", syscompat_pref, compat[i]) + + printf "\n#ifdef %s\n", compat_upper[i] > compat_file[i] + printf "#define %s(func) __CONCAT(%s_,func)\n\n", \ + compat[i], compat[i] > compat_file[i] } - $2 == "COMPAT" { - printf("int\to%s();\n", $4) > syscompat - printf("\t{ compat(%d,%s) },\t\t/* %d = old %s */\n", \ - $3, $4, syscall, $5) > sysent - printf("\t\"old.%s\",\t\t/* %d = old %s */\n", \ - $5, syscall, $5) > sysnames - printf("\t\t\t\t/* %d is old %s */\n", \ - syscall, comment) > syshdr - syscall++ - next + + printf "/*\n * System call names.\n *\n" > sysnames + printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames + + printf "/*\n * System call numbers.\n *\n" > sysnumhdr + printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnumhdr + + printf "/*\n * System call argument lists.\n *\n" > sysarghdr + printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarghdr +} +NR == 1 { + printf " * created from%s\n */\n\n", $0 > sysdcl + + printf "#define\ts(type)\tsizeof(type)\n\n" > sysent + printf "struct sysent %s[] = {\n",switchname > sysent + + printf " * created from%s\n */\n\n", $0 > sysnames + printf "char *%s[] = {\n",namesname > sysnames + + printf " * created from%s\n */\n\n", $0 > sysnumhdr + + printf " * created from%s\n */\n\n", $0 > sysarghdr + printf "#define\tsyscallarg(x)\tunion { x datum; register_t pad; }\n" \ + > sysarghdr + next +} +NF == 0 || $1 ~ /^;/ { + next +} +$1 ~ /^#[ ]*include/ { + print > sysdcl + next +} +$1 ~ /^#[ ]*if/ { + print > sysent + print > sysdcl + for (i = 1; i <= ncompat; i++) + print > compat_file[i] + print > sysnames + savesyscall = syscall + next +} +$1 ~ /^#[ ]*else/ { + print > sysent + print > sysdcl + for (i = 1; i <= ncompat; i++) + print > compat_file[i] + print > sysnames + syscall = savesyscall + next +} +$1 ~ /^#/ { + print > sysent + print > sysdcl + for (i = 1; i <= ncompat; i++) + print > compat_file[i] + print > sysnames + next +} +syscall != $1 { + printf "%s: line %d: syscall number out of sync at %d\n", \ + infile, NR, syscall + printf "line is:\n" + print + exit 1 +} +function parserr(was, wanted) { + printf "%s: line %d: unexpected %s (expected %s)\n", \ + infile, NR, was, wanted + exit 1 +} +function parseline() { + f=3 # toss number and type + if ($NF != "}") { + funcalias=$NF + end=NF-1 + } else { + funcalias="" + end=NF } - $2 == "LIBCOMPAT" { - printf("int\to%s();\n", $4) > syscompat - printf("\t{ compat(%d,%s) },\t\t/* %d = old %s */\n", \ - $3, $4, syscall, $5) > sysent - printf("\t\"old.%s\",\t\t/* %d = old %s */\n", \ - $5, syscall, $5) > sysnames - printf("#define\tSYS_%s\t%d\t/* compatibility; still used by libc */\n", \ - $5, syscall) > syshdr - syscall++ - next + if ($f != "{") + parserr($f, "{") + f++ + if ($end != "}") + parserr($end, "}") + end-- + if ($end != ";") + parserr($end, ";") + end-- + if ($end != ")") + parserr($end, ")") + end-- + + f++ # toss return type + + funcname=$f + if (funcalias == "") + funcalias=funcname + f++ + + if ($f != "(") + parserr($f, ")") + f++ + + argc= 0; + if (f == end) { + if ($f != "void") + parserr($f, "argument definition") + return } - $2 == "OBSOL" { - printf("\t{ 0, nosys },\t\t\t/* %d = obsolete %s */\n", \ - syscall, comment) > sysent - printf("\t\"obs_%s\",\t\t\t/* %d = obsolete %s */\n", \ - $4, syscall, comment) > sysnames - printf("\t\t\t\t/* %d is obsolete %s */\n", \ - syscall, comment) > syshdr - syscall++ - next + + while (f <= end) { + argc++ + argtype[argc]="" + oldf="" + while (f < end && $(f+1) != ",") { + if (argtype[argc] != "" && oldf != "*") + argtype[argc] = argtype[argc]" "; + argtype[argc] = argtype[argc]$f; + oldf = $f; + f++ + } + if (argtype[argc] == "") + parserr($f, "argument definition") + argname[argc]=$f; + f += 2; # skip name, and any comma } - $2 == "UNIMPL" { - printf("\t{ 0, nosys },\t\t\t/* %d = %s */\n", \ - syscall, comment) > sysent - printf("\t\"#%d\",\t\t\t/* %d = %s */\n", \ - syscall, syscall, comment) > sysnames - syscall++ - next +} +function putent(nodefs, declfile, compatwrap) { + # output syscall declaration for switch table + if (compatwrap == "") + printf("int\t%s();\n", funcname) > declfile + else + printf("int\t%s(%s)();\n", compatwrap, funcname) > declfile + + # output syscall switch entry +# printf("\t{ { %d", argc) > sysent +# for (i = 1; i <= argc; i++) { +# if (i == 5) # wrap the line +# printf(",\n\t ") > sysent +# else +# printf(", ") > sysent +# printf("s(%s)", argtypenospc[i]) > sysent +# } + printf("\t{ %d, ", argc) > sysent + if (argc == 0) + printf("0") > sysent + else if (compatwrap == "") + printf("s(struct %s_args)", funcname) > sysent + else + printf("s(struct %s_%s_args)", compatwrap, funcname) > sysent + if (compatwrap == "") + wfn = sprintf("%s", funcname); + else + wfn = sprintf("%s(%s)", compatwrap, funcname); + printf(",\n\t %s },", wfn) > sysent + for (i = 0; i < (33 - length(wfn)) / 8; i++) + printf("\t") > sysent + if (compatwrap == "") + printf("/* %d = %s */\n", syscall, funcalias) > sysent + else + printf("/* %d = %s %s */\n", syscall, compatwrap, + funcalias) > sysent + + # output syscall name for names table + if (compatwrap == "") + printf("\t\"%s\",\t\t\t/* %d = %s */\n", funcalias, syscall, + funcalias) > sysnames + else + printf("\t\"%s_%s\",\t/* %d = %s %s */\n", compatwrap, + funcalias, syscall, compatwrap, funcalias) > sysnames + + # output syscall number of header, if appropriate + if (nodefs == "" || nodefs == "NOARGS") + printf("#define\t%s%s\t%d\n", constprefix, funcalias, + syscall) > sysnumhdr + else if (nodefs != "NODEF") + printf("\t\t\t\t/* %d is %s %s */\n", syscall, + compatwrap, funcalias) > sysnumhdr + + # output syscall argument structure, if it has arguments + if (argc != 0 && nodefs != "NOARGS") { + if (compatwrap == "") + printf("\nstruct %s_args {\n", funcname) > sysarghdr + else + printf("\nstruct %s_%s_args {\n", compatwrap, + funcname) > sysarghdr + for (i = 1; i <= argc; i++) + printf("\tsyscallarg(%s) %s;\n", argtype[i], + argname[i]) > sysarghdr + printf("};\n") > sysarghdr } - { - printf "%s: line %d: unrecognized keyword %s\n", infile, NR, $2 - exit 1 +} +$2 == "STD" { + parseline() + putent("", sysdcl, "") + syscall++ + next +} +$2 == "NODEF" || $2 == "NOARGS" { + parseline() + putent($2, sysdcl, "") + syscall++ + next +} +$2 == "OBSOL" || $2 == "UNIMPL" { + if ($2 == "OBSOL") + comment="obsolete" + else + comment="unimplemented" + for (i = 3; i <= NF; i++) + comment=comment " " $i + + printf("\t{ 0, 0,\n\t nosys },\t\t\t\t/* %d = %s */\n", \ + syscall, comment) > sysent + printf("\t\"#%d (%s)\",\t\t/* %d = %s */\n", \ + syscall, comment, syscall, comment) > sysnames + if ($2 != "UNIMPL") + printf("\t\t\t\t/* %d is %s */\n", syscall, comment) > sysnumhdr + syscall++ + next +} +{ + for (i = 1; i <= ncompat; i++) { + if ($2 == compat_upper[i]) { + parseline(); + putent("COMMENT", compat_file[i], compat[i]) + syscall++ + next + } } - END { - printf("\n#else /* %s */\n", compat) > syscompat - printf("#define compat(n, name) 0, nosys\n") > syscompat - printf("#endif /* %s */\n\n", compat) > syscompat + printf "%s: line %d: unrecognized keyword %s\n", infile, NR, $2 + exit 1 +} +END { + printf "\n#undef\tsyscallarg\n" > sysarghdr + + for (i = 1; i <= ncompat; i++) { + printf("\n#else /* %s */\n", compat_upper[i]) > compat_file[i] + printf("#define %s(func) nosys\n", compat[i]) > \ + compat_file[i] + printf("#endif /* %s */\n\n", compat_upper[i]) > compat_file[i] + } - printf("};\n\n") > sysent - printf("int\tnsysent = sizeof(sysent) / sizeof(sysent[0]);\n") > sysent + printf("};\n\n") > sysent + printf("int\tn%s= sizeof(%s) / sizeof(%s[0]);\n", switchname, + switchname, switchname) > sysent - printf("};\n") > sysnames - } ' + printf("};\n") > sysnames +} ' -cat $sysdcl $syscompat $sysent >$syssw +cat $sysdcl $syscompat_files $sysent > $syssw -chmod 444 $sysnames $syshdr $syssw +#chmod 444 $sysnames $syshdr $syssw diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c index af17988..7281339 100644 --- a/sys/kern/subr_autoconf.c +++ b/sys/kern/subr_autoconf.c @@ -39,7 +39,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)subr_autoconf.c 8.1 (Berkeley) 6/10/93 + * @(#)subr_autoconf.c 8.3 (Berkeley) 5/17/94 * * from: $Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp $ (LBL) */ @@ -47,6 +47,7 @@ #include #include #include +#include /* * Autoconfiguration subroutines. @@ -283,15 +284,16 @@ config_attach(parent, cf, aux, print) void **nsp; if (old == 0) { - nsp = malloc(MINALLOCSIZE, M_DEVBUF, M_WAITOK); /*XXX*/ - bzero(nsp, MINALLOCSIZE); - cd->cd_ndevs = MINALLOCSIZE / sizeof(void *); + new = max(MINALLOCSIZE / sizeof(void *), + dev->dv_unit + 1); + newbytes = new * sizeof(void *); + nsp = malloc(newbytes, M_DEVBUF, M_WAITOK); /*XXX*/ + bzero(nsp, newbytes); } else { new = cd->cd_ndevs; do { new *= 2; } while (new <= dev->dv_unit); - cd->cd_ndevs = new; oldbytes = old * sizeof(void *); newbytes = new * sizeof(void *); nsp = malloc(newbytes, M_DEVBUF, M_WAITOK); /*XXX*/ @@ -299,6 +301,7 @@ config_attach(parent, cf, aux, print) bzero(&nsp[old], newbytes - oldbytes); free(cd->cd_devs, M_DEVBUF); } + cd->cd_ndevs = new; cd->cd_devs = nsp; } if (cd->cd_devs[dev->dv_unit]) diff --git a/sys/kern/subr_log.c b/sys/kern/subr_log.c index f065761..792a1ce 100644 --- a/sys/kern/subr_log.c +++ b/sys/kern/subr_log.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)subr_log.c 8.1 (Berkeley) 6/10/93 + * @(#)subr_log.c 8.3 (Berkeley) 2/14/95 */ /* @@ -59,6 +59,7 @@ struct logsoftc { int log_open; /* also used in log() */ /*ARGSUSED*/ +int logopen(dev, flags, mode, p) dev_t dev; int flags, mode; @@ -87,6 +88,7 @@ logopen(dev, flags, mode, p) } /*ARGSUSED*/ +int logclose(dev, flag, mode, p) dev_t dev; int flag, mode; @@ -99,6 +101,7 @@ logclose(dev, flag, mode, p) } /*ARGSUSED*/ +int logread(dev, uio, flag) dev_t dev; struct uio *uio; @@ -144,6 +147,7 @@ logread(dev, uio, flag) } /*ARGSUSED*/ +int logselect(dev, rw, p) dev_t dev; int rw; @@ -165,6 +169,7 @@ logselect(dev, rw, p) return (0); } +void logwakeup() { struct proc *p; @@ -185,9 +190,10 @@ logwakeup() } /*ARGSUSED*/ +int logioctl(dev, com, data, flag, p) dev_t dev; - int com; + u_long com; caddr_t data; int flag; struct proc *p; diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c index 2adb779..8a9a44e 100644 --- a/sys/kern/subr_prf.c +++ b/sys/kern/subr_prf.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 + * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95 */ #include @@ -499,6 +499,11 @@ putchar(c, flags, tp) mbp->msg_bufc[mbp->msg_bufx++] = c; if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) mbp->msg_bufx = 0; + /* If the buffer is full, keep the most recent data. */ + if (mbp->msg_bufr == mbp->msg_bufx) { + if (++mbp->msg_bufr >= MSG_BSIZE) + mbp->msg_bufr = 0; + } } if ((flags & TOCONS) && constty == NULL && c != '\0') (*v_putc)(c); diff --git a/sys/kern/subr_prof.c b/sys/kern/subr_prof.c index 4fb81d8..237553d 100644 --- a/sys/kern/subr_prof.c +++ b/sys/kern/subr_prof.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)subr_prof.c 8.3 (Berkeley) 9/23/93 + * @(#)subr_prof.c 8.4 (Berkeley) 2/14/95 */ #include @@ -38,6 +38,10 @@ #include #include #include + +#include +#include + #include #ifdef GPROF @@ -51,6 +55,7 @@ struct gmonparam _gmonparam = { GMON_PROF_OFF }; extern char etext[]; +void kmstartup() { char *cp; @@ -90,6 +95,7 @@ kmstartup() /* * Return kernel profiling information. */ +int sysctl_doprof(name, namelen, oldp, oldlenp, newp, newlen, p) int *name; u_int namelen; @@ -139,24 +145,24 @@ sysctl_doprof(name, namelen, oldp, oldlenp, newp, newlen, p) * The scale factor is a fixed point number with 16 bits of fraction, so that * 1.0 is represented as 0x10000. A scale factor of 0 turns off profiling. */ -struct profil_args { - caddr_t samples; - u_int size; - u_int offset; - u_int scale; -}; /* ARGSUSED */ +int profil(p, uap, retval) struct proc *p; - register struct profil_args *uap; - int *retval; + register struct profil_args /* { + syscallarg(caddr_t) samples; + syscallarg(u_int) size; + syscallarg(u_int) offset; + syscallarg(u_int) scale; + } */ *uap; + register_t *retval; { register struct uprof *upp; int s; - if (uap->scale > (1 << 16)) + if (SCARG(uap, scale) > (1 << 16)) return (EINVAL); - if (uap->scale == 0) { + if (SCARG(uap, scale) == 0) { stopprofclock(p); return (0); } @@ -164,10 +170,10 @@ profil(p, uap, retval) /* Block profile interrupts while changing state. */ s = splstatclock(); - upp->pr_off = uap->offset; - upp->pr_scale = uap->scale; - upp->pr_base = uap->samples; - upp->pr_size = uap->size; + upp->pr_off = SCARG(uap, offset); + upp->pr_scale = SCARG(uap, scale); + upp->pr_base = SCARG(uap, samples); + upp->pr_size = SCARG(uap, size); startprofclock(p); splx(s); diff --git a/sys/kern/subr_xxx.c b/sys/kern/subr_xxx.c index c692ec1..45b2d64 100644 --- a/sys/kern/subr_xxx.c +++ b/sys/kern/subr_xxx.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)subr_xxx.c 8.1 (Berkeley) 6/10/93 + * @(#)subr_xxx.c 8.3 (Berkeley) 3/29/95 */ /* @@ -45,6 +45,7 @@ /* * Unsupported device function (e.g. writing to read-only device). */ +int enodev() { @@ -54,6 +55,7 @@ enodev() /* * Unconfigured device function; driver not configured. */ +int enxio() { @@ -63,6 +65,7 @@ enxio() /* * Unsupported ioctl function. */ +int enoioctl() { @@ -74,6 +77,7 @@ enoioctl() * This is used for an otherwise-reasonable operation * that is not supported by the current system binary. */ +int enosys() { @@ -84,6 +88,7 @@ enosys() * Return error for operation not supported * on a specific object or file type. */ +int eopnotsupp() { @@ -91,8 +96,20 @@ eopnotsupp() } /* + * Return error for an inval operation + * on a specific object or file type. + */ +int +einval() +{ + + return (EINVAL); +} + +/* * Generic null operation, always returns success. */ +int nullop() { diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index a121209..08385b3 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94 + * @(#)sys_generic.c 8.9 (Berkeley) 2/14/95 */ #include @@ -53,19 +53,22 @@ #include #endif +#include +#include + /* * Read system call. */ -struct read_args { - int fd; - char *buf; - u_int nbyte; -}; /* ARGSUSED */ +int read(p, uap, retval) struct proc *p; - register struct read_args *uap; - int *retval; + register struct read_args /* { + syscallarg(int) fd; + syscallarg(char *) buf; + syscallarg(u_int) nbyte; + } */ *uap; + register_t *retval; { register struct file *fp; register struct filedesc *fdp = p->p_fd; @@ -76,15 +79,15 @@ read(p, uap, retval) struct iovec ktriov; #endif - if (((u_int)uap->fd) >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL || + if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || (fp->f_flag & FREAD) == 0) return (EBADF); - aiov.iov_base = (caddr_t)uap->buf; - aiov.iov_len = uap->nbyte; + aiov.iov_base = (caddr_t)SCARG(uap, buf); + aiov.iov_len = SCARG(uap, nbyte); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; - auio.uio_resid = uap->nbyte; + auio.uio_resid = SCARG(uap, nbyte); auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; @@ -95,7 +98,7 @@ read(p, uap, retval) if (KTRPOINT(p, KTR_GENIO)) ktriov = aiov; #endif - cnt = uap->nbyte; + cnt = SCARG(uap, nbyte); if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) if (auio.uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) @@ -103,7 +106,8 @@ read(p, uap, retval) cnt -= auio.uio_resid; #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO) && error == 0) - ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktriov, cnt, error); + ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, &ktriov, + cnt, error); #endif *retval = cnt; return (error); @@ -112,15 +116,15 @@ read(p, uap, retval) /* * Scatter read system call. */ -struct readv_args { - int fdes; - struct iovec *iovp; - u_int iovcnt; -}; +int readv(p, uap, retval) struct proc *p; - register struct readv_args *uap; - int *retval; + register struct readv_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(u_int) iovcnt; + } */ *uap; + register_t *retval; { register struct file *fp; register struct filedesc *fdp = p->p_fd; @@ -134,14 +138,14 @@ readv(p, uap, retval) struct iovec *ktriov = NULL; #endif - if (((u_int)uap->fdes) >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fdes]) == NULL || + if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || (fp->f_flag & FREAD) == 0) return (EBADF); /* note: can't use iovlen until iovcnt is validated */ - iovlen = uap->iovcnt * sizeof (struct iovec); - if (uap->iovcnt > UIO_SMALLIOV) { - if (uap->iovcnt > UIO_MAXIOV) + iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec); + if (SCARG(uap, iovcnt) > UIO_SMALLIOV) { + if (SCARG(uap, iovcnt) > UIO_MAXIOV) return (EINVAL); MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); needfree = iov; @@ -150,23 +154,19 @@ readv(p, uap, retval) needfree = NULL; } auio.uio_iov = iov; - auio.uio_iovcnt = uap->iovcnt; + auio.uio_iovcnt = SCARG(uap, iovcnt); auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; - if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) + if (error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen)) goto done; auio.uio_resid = 0; - for (i = 0; i < uap->iovcnt; i++) { - if (iov->iov_len < 0) { + for (i = 0; i < SCARG(uap, iovcnt); i++) { + if (auio.uio_resid + iov->iov_len < auio.uio_resid) { error = EINVAL; goto done; } auio.uio_resid += iov->iov_len; - if (auio.uio_resid < 0) { - error = EINVAL; - goto done; - } iov++; } #ifdef KTRACE @@ -187,7 +187,7 @@ readv(p, uap, retval) #ifdef KTRACE if (ktriov != NULL) { if (error == 0) - ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, + ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, ktriov, cnt, error); FREE(ktriov, M_TEMP); } @@ -202,15 +202,15 @@ done: /* * Write system call */ -struct write_args { - int fd; - char *buf; - u_int nbyte; -}; +int write(p, uap, retval) struct proc *p; - register struct write_args *uap; - int *retval; + register struct write_args /* { + syscallarg(int) fd; + syscallarg(char *) buf; + syscallarg(u_int) nbyte; + } */ *uap; + register_t *retval; { register struct file *fp; register struct filedesc *fdp = p->p_fd; @@ -221,15 +221,15 @@ write(p, uap, retval) struct iovec ktriov; #endif - if (((u_int)uap->fd) >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL || + if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || (fp->f_flag & FWRITE) == 0) return (EBADF); - aiov.iov_base = (caddr_t)uap->buf; - aiov.iov_len = uap->nbyte; + aiov.iov_base = (caddr_t)SCARG(uap, buf); + aiov.iov_len = SCARG(uap, nbyte); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; - auio.uio_resid = uap->nbyte; + auio.uio_resid = SCARG(uap, nbyte); auio.uio_rw = UIO_WRITE; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; @@ -240,7 +240,7 @@ write(p, uap, retval) if (KTRPOINT(p, KTR_GENIO)) ktriov = aiov; #endif - cnt = uap->nbyte; + cnt = SCARG(uap, nbyte); if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { if (auio.uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) @@ -251,7 +251,7 @@ write(p, uap, retval) cnt -= auio.uio_resid; #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO) && error == 0) - ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, + ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE, &ktriov, cnt, error); #endif *retval = cnt; @@ -261,15 +261,15 @@ write(p, uap, retval) /* * Gather write system call */ -struct writev_args { - int fd; - struct iovec *iovp; - u_int iovcnt; -}; +int writev(p, uap, retval) struct proc *p; - register struct writev_args *uap; - int *retval; + register struct writev_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(u_int) iovcnt; + } */ *uap; + register_t *retval; { register struct file *fp; register struct filedesc *fdp = p->p_fd; @@ -283,14 +283,14 @@ writev(p, uap, retval) struct iovec *ktriov = NULL; #endif - if (((u_int)uap->fd) >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL || + if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || (fp->f_flag & FWRITE) == 0) return (EBADF); /* note: can't use iovlen until iovcnt is validated */ - iovlen = uap->iovcnt * sizeof (struct iovec); - if (uap->iovcnt > UIO_SMALLIOV) { - if (uap->iovcnt > UIO_MAXIOV) + iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec); + if (SCARG(uap, iovcnt) > UIO_SMALLIOV) { + if (SCARG(uap, iovcnt) > UIO_MAXIOV) return (EINVAL); MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); needfree = iov; @@ -299,23 +299,19 @@ writev(p, uap, retval) needfree = NULL; } auio.uio_iov = iov; - auio.uio_iovcnt = uap->iovcnt; + auio.uio_iovcnt = SCARG(uap, iovcnt); auio.uio_rw = UIO_WRITE; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; - if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) + if (error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen)) goto done; auio.uio_resid = 0; - for (i = 0; i < uap->iovcnt; i++) { - if (iov->iov_len < 0) { + for (i = 0; i < SCARG(uap, iovcnt); i++) { + if (auio.uio_resid + iov->iov_len < auio.uio_resid) { error = EINVAL; goto done; } auio.uio_resid += iov->iov_len; - if (auio.uio_resid < 0) { - error = EINVAL; - goto done; - } iov++; } #ifdef KTRACE @@ -339,7 +335,7 @@ writev(p, uap, retval) #ifdef KTRACE if (ktriov != NULL) { if (error == 0) - ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, + ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE, ktriov, cnt, error); FREE(ktriov, M_TEMP); } @@ -354,20 +350,21 @@ done: /* * Ioctl system call */ -struct ioctl_args { - int fd; - int com; - caddr_t data; -}; /* ARGSUSED */ +int ioctl(p, uap, retval) struct proc *p; - register struct ioctl_args *uap; - int *retval; + register struct ioctl_args /* { + syscallarg(int) fd; + syscallarg(u_long) com; + syscallarg(caddr_t) data; + } */ *uap; + register_t *retval; { register struct file *fp; register struct filedesc *fdp; - register int com, error; + register u_long com; + register int error; register u_int size; caddr_t data, memp; int tmp; @@ -375,19 +372,19 @@ ioctl(p, uap, retval) char stkbuf[STK_PARAMS]; fdp = p->p_fd; - if ((u_int)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) + if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) return (EBADF); if ((fp->f_flag & (FREAD | FWRITE)) == 0) return (EBADF); - switch (com = uap->com) { + switch (com = SCARG(uap, com)) { case FIONCLEX: - fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE; + fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE; return (0); case FIOCLEX: - fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE; + fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE; return (0); } @@ -406,14 +403,14 @@ ioctl(p, uap, retval) data = stkbuf; if (com&IOC_IN) { if (size) { - error = copyin(uap->data, data, (u_int)size); + error = copyin(SCARG(uap, data), data, (u_int)size); if (error) { if (memp) free(memp, M_IOCTLOPS); return (error); } } else - *(caddr_t *)data = uap->data; + *(caddr_t *)data = SCARG(uap, data); } else if ((com&IOC_OUT) && size) /* * Zero the buffer so the user always @@ -421,7 +418,7 @@ ioctl(p, uap, retval) */ bzero(data, size); else if (com&IOC_VOID) - *(caddr_t *)data = uap->data; + *(caddr_t *)data = SCARG(uap, data); switch (com) { @@ -459,7 +456,7 @@ ioctl(p, uap, retval) tmp = p1->p_pgrp->pg_id; } error = (*fp->f_ops->fo_ioctl) - (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); + (fp, TIOCSPGRP, (caddr_t)&tmp, p); break; case FIOGETOWN: @@ -468,7 +465,7 @@ ioctl(p, uap, retval) *(int *)data = ((struct socket *)fp->f_data)->so_pgid; break; } - error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); + error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p); *(int *)data = -*(int *)data; break; @@ -479,7 +476,7 @@ ioctl(p, uap, retval) * already set and checked above. */ if (error == 0 && (com&IOC_OUT) && size) - error = copyout(data, uap->data, (u_int)size); + error = copyout(data, SCARG(uap, data), (u_int)size); break; } if (memp) @@ -492,40 +489,44 @@ int selwait, nselcoll; /* * Select system call. */ -struct select_args { - u_int nd; - fd_set *in, *ou, *ex; - struct timeval *tv; -}; +int select(p, uap, retval) register struct proc *p; - register struct select_args *uap; - int *retval; + register struct select_args /* { + syscallarg(u_int) nd; + syscallarg(fd_set *) in; + syscallarg(fd_set *) ou; + syscallarg(fd_set *) ex; + syscallarg(struct timeval *) tv; + } */ *uap; + register_t *retval; { fd_set ibits[3], obits[3]; struct timeval atv; - int s, ncoll, error = 0, timo; + int s, ncoll, error, timo = 0; u_int ni; bzero((caddr_t)ibits, sizeof(ibits)); bzero((caddr_t)obits, sizeof(obits)); - if (uap->nd > FD_SETSIZE) + if (SCARG(uap, nd) > FD_SETSIZE) return (EINVAL); - if (uap->nd > p->p_fd->fd_nfiles) - uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ - ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask); + if (SCARG(uap, nd) > p->p_fd->fd_nfiles) { + /* forgiving; slightly wrong */ + SCARG(uap, nd) = p->p_fd->fd_nfiles; + } + ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask); #define getbits(name, x) \ - if (uap->name && \ - (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \ + if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, name), \ + (caddr_t)&ibits[x], ni))) \ goto done; getbits(in, 0); getbits(ou, 1); getbits(ex, 2); #undef getbits - if (uap->tv) { - error = copyin((caddr_t)uap->tv, (caddr_t)&atv, + if (SCARG(uap, tv)) { + error = copyin((caddr_t)SCARG(uap, tv), (caddr_t)&atv, sizeof (atv)); if (error) goto done; @@ -535,27 +536,30 @@ select(p, uap, retval) } s = splclock(); timevaladd(&atv, (struct timeval *)&time); - timo = hzto(&atv); - /* - * Avoid inadvertently sleeping forever. - */ - if (timo == 0) - timo = 1; splx(s); - } else - timo = 0; + } retry: ncoll = nselcoll; p->p_flag |= P_SELECT; - error = selscan(p, ibits, obits, uap->nd, retval); + error = selscan(p, ibits, obits, SCARG(uap, nd), retval); if (error || *retval) goto done; s = splhigh(); - /* this should be timercmp(&time, &atv, >=) */ - if (uap->tv && (time.tv_sec > atv.tv_sec || - time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { - splx(s); - goto done; + if (SCARG(uap, tv)) { + if (timercmp(&time, &atv, >=)) { + splx(s); + goto done; + } + /* + * If poll wait was tiny, this could be zero; we will + * have to round it up to avoid sleeping forever. If + * we retry below, the timercmp above will get us out. + * Note that if wait was 0, the timercmp will prevent + * us from getting here the first time. + */ + timo = hzto(&atv); + if (timo == 0) + timo = 1; } if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { splx(s); @@ -574,8 +578,8 @@ done: if (error == EWOULDBLOCK) error = 0; #define putbits(name, x) \ - if (uap->name && \ - (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \ + if (SCARG(uap, name) && (error2 = copyout((caddr_t)&obits[x], \ + (caddr_t)SCARG(uap, name), ni))) \ error = error2; if (error == 0) { int error2; @@ -588,10 +592,12 @@ done: return (error); } +int selscan(p, ibits, obits, nfd, retval) struct proc *p; fd_set *ibits, *obits; - int nfd, *retval; + int nfd; + register_t *retval; { register struct filedesc *fdp = p->p_fd; register int msk, i, j, fd; @@ -620,6 +626,7 @@ selscan(p, ibits, obits, nfd, retval) } /*ARGSUSED*/ +int seltrue(dev, flag, p) dev_t dev; int flag; diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index a93ae86..abc2dc7 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93 + * @(#)sys_socket.c 8.3 (Berkeley) 2/14/95 */ #include @@ -51,6 +51,7 @@ struct fileops socketops = { soo_read, soo_write, soo_ioctl, soo_select, soo_close }; /* ARGSUSED */ +int soo_read(fp, uio, cred) struct file *fp; struct uio *uio; @@ -62,6 +63,7 @@ soo_read(fp, uio, cred) } /* ARGSUSED */ +int soo_write(fp, uio, cred) struct file *fp; struct uio *uio; @@ -72,9 +74,10 @@ soo_write(fp, uio, cred) uio, (struct mbuf *)0, (struct mbuf *)0, 0)); } +int soo_ioctl(fp, cmd, data, p) struct file *fp; - int cmd; + u_long cmd; register caddr_t data; struct proc *p; { @@ -130,6 +133,7 @@ soo_ioctl(fp, cmd, data, p) (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0)); } +int soo_select(fp, which, p) struct file *fp; int which; @@ -171,6 +175,7 @@ soo_select(fp, which, p) return (0); } +int soo_stat(so, ub) register struct socket *so; register struct stat *ub; @@ -184,6 +189,7 @@ soo_stat(so, ub) } /* ARGSUSED */ +int soo_close(fp, p) struct file *fp; struct proc *p; diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 1809905..91cbdc9 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -2,7 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * created from @(#)syscalls.master 8.2 (Berkeley) 1/13/94 + * created from @(#)syscalls.master 8.6 (Berkeley) 3/30/95 */ char *syscallnames[] = { @@ -14,10 +14,10 @@ char *syscallnames[] = { "open", /* 5 = open */ "close", /* 6 = close */ "wait4", /* 7 = wait4 */ - "old.creat", /* 8 = old creat */ + "compat_43_creat", /* 8 = compat_43 creat */ "link", /* 9 = link */ "unlink", /* 10 = unlink */ - "obs_execv", /* 11 = obsolete execv */ + "#11 (obsolete execv)", /* 11 = obsolete execv */ "chdir", /* 12 = chdir */ "fchdir", /* 13 = fchdir */ "mknod", /* 14 = mknod */ @@ -25,7 +25,7 @@ char *syscallnames[] = { "chown", /* 16 = chown */ "break", /* 17 = break */ "getfsstat", /* 18 = getfsstat */ - "old.lseek", /* 19 = old lseek */ + "compat_43_lseek", /* 19 = compat_43 lseek */ "getpid", /* 20 = getpid */ "mount", /* 21 = mount */ "unmount", /* 22 = unmount */ @@ -44,9 +44,9 @@ char *syscallnames[] = { "fchflags", /* 35 = fchflags */ "sync", /* 36 = sync */ "kill", /* 37 = kill */ - "old.stat", /* 38 = old stat */ + "compat_43_stat", /* 38 = compat_43 stat */ "getppid", /* 39 = getppid */ - "old.lstat", /* 40 = old lstat */ + "compat_43_lstat", /* 40 = compat_43 lstat */ "dup", /* 41 = dup */ "pipe", /* 42 = pipe */ "getegid", /* 43 = getegid */ @@ -54,7 +54,7 @@ char *syscallnames[] = { #ifdef KTRACE "ktrace", /* 45 = ktrace */ #else - "#45", /* 45 = ktrace */ + "#45 (unimplemented ktrace)", /* 45 = unimplemented ktrace */ #endif "sigaction", /* 46 = sigaction */ "getgid", /* 47 = getgid */ @@ -72,63 +72,63 @@ char *syscallnames[] = { "execve", /* 59 = execve */ "umask", /* 60 = umask */ "chroot", /* 61 = chroot */ - "old.fstat", /* 62 = old fstat */ - "old.getkerninfo", /* 63 = old getkerninfo */ - "old.getpagesize", /* 64 = old getpagesize */ + "compat_43_fstat", /* 62 = compat_43 fstat */ + "compat_43_getkerninfo", /* 63 = compat_43 getkerninfo */ + "compat_43_getpagesize", /* 64 = compat_43 getpagesize */ "msync", /* 65 = msync */ "vfork", /* 66 = vfork */ - "obs_vread", /* 67 = obsolete vread */ - "obs_vwrite", /* 68 = obsolete vwrite */ + "#67 (obsolete vread)", /* 67 = obsolete vread */ + "#68 (obsolete vwrite)", /* 68 = obsolete vwrite */ "sbrk", /* 69 = sbrk */ "sstk", /* 70 = sstk */ - "old.mmap", /* 71 = old mmap */ + "compat_43_mmap", /* 71 = compat_43 mmap */ "vadvise", /* 72 = vadvise */ "munmap", /* 73 = munmap */ "mprotect", /* 74 = mprotect */ "madvise", /* 75 = madvise */ - "obs_vhangup", /* 76 = obsolete vhangup */ - "obs_vlimit", /* 77 = obsolete vlimit */ + "#76 (obsolete vhangup)", /* 76 = obsolete vhangup */ + "#77 (obsolete vlimit)", /* 77 = obsolete vlimit */ "mincore", /* 78 = mincore */ "getgroups", /* 79 = getgroups */ "setgroups", /* 80 = setgroups */ "getpgrp", /* 81 = getpgrp */ "setpgid", /* 82 = setpgid */ "setitimer", /* 83 = setitimer */ - "old.wait", /* 84 = old wait */ + "compat_43_wait", /* 84 = compat_43 wait */ "swapon", /* 85 = swapon */ "getitimer", /* 86 = getitimer */ - "old.gethostname", /* 87 = old gethostname */ - "old.sethostname", /* 88 = old sethostname */ + "compat_43_gethostname", /* 87 = compat_43 gethostname */ + "compat_43_sethostname", /* 88 = compat_43 sethostname */ "getdtablesize", /* 89 = getdtablesize */ "dup2", /* 90 = dup2 */ - "#91", /* 91 = getdopt */ + "#91 (unimplemented getdopt)", /* 91 = unimplemented getdopt */ "fcntl", /* 92 = fcntl */ "select", /* 93 = select */ - "#94", /* 94 = setdopt */ + "#94 (unimplemented setdopt)", /* 94 = unimplemented setdopt */ "fsync", /* 95 = fsync */ "setpriority", /* 96 = setpriority */ "socket", /* 97 = socket */ "connect", /* 98 = connect */ - "old.accept", /* 99 = old accept */ + "compat_43_accept", /* 99 = compat_43 accept */ "getpriority", /* 100 = getpriority */ - "old.send", /* 101 = old send */ - "old.recv", /* 102 = old recv */ + "compat_43_send", /* 101 = compat_43 send */ + "compat_43_recv", /* 102 = compat_43 recv */ "sigreturn", /* 103 = sigreturn */ "bind", /* 104 = bind */ "setsockopt", /* 105 = setsockopt */ "listen", /* 106 = listen */ - "obs_vtimes", /* 107 = obsolete vtimes */ - "old.sigvec", /* 108 = old sigvec */ - "old.sigblock", /* 109 = old sigblock */ - "old.sigsetmask", /* 110 = old sigsetmask */ + "#107 (obsolete vtimes)", /* 107 = obsolete vtimes */ + "compat_43_sigvec", /* 108 = compat_43 sigvec */ + "compat_43_sigblock", /* 109 = compat_43 sigblock */ + "compat_43_sigsetmask", /* 110 = compat_43 sigsetmask */ "sigsuspend", /* 111 = sigsuspend */ - "old.sigstack", /* 112 = old sigstack */ - "old.recvmsg", /* 113 = old recvmsg */ - "old.sendmsg", /* 114 = old sendmsg */ + "compat_43_sigstack", /* 112 = compat_43 sigstack */ + "compat_43_recvmsg", /* 113 = compat_43 recvmsg */ + "compat_43_sendmsg", /* 114 = compat_43 sendmsg */ #ifdef TRACE "vtrace", /* 115 = vtrace */ #else - "obs_vtrace", /* 115 = obsolete vtrace */ + "#115 (obsolete vtrace)", /* 115 = obsolete vtrace */ #endif "gettimeofday", /* 116 = gettimeofday */ "getrusage", /* 117 = getrusage */ @@ -136,19 +136,19 @@ char *syscallnames[] = { #ifdef vax "resuba", /* 119 = resuba */ #else - "#119", /* 119 = nosys */ + "#119 (unimplemented resuba)", /* 119 = unimplemented resuba */ #endif "readv", /* 120 = readv */ "writev", /* 121 = writev */ "settimeofday", /* 122 = settimeofday */ "fchown", /* 123 = fchown */ "fchmod", /* 124 = fchmod */ - "old.recvfrom", /* 125 = old recvfrom */ - "old.setreuid", /* 126 = old setreuid */ - "old.setregid", /* 127 = old setregid */ + "compat_43_recvfrom", /* 125 = compat_43 recvfrom */ + "compat_43_setreuid", /* 126 = compat_43 setreuid */ + "compat_43_setregid", /* 127 = compat_43 setregid */ "rename", /* 128 = rename */ - "old.truncate", /* 129 = old truncate */ - "old.ftruncate", /* 130 = old ftruncate */ + "compat_43_truncate", /* 129 = compat_43 truncate */ + "compat_43_ftruncate", /* 130 = compat_43 ftruncate */ "flock", /* 131 = flock */ "mkfifo", /* 132 = mkfifo */ "sendto", /* 133 = sendto */ @@ -157,60 +157,60 @@ char *syscallnames[] = { "mkdir", /* 136 = mkdir */ "rmdir", /* 137 = rmdir */ "utimes", /* 138 = utimes */ - "obs_4.2", /* 139 = obsolete 4.2 sigreturn */ + "#139 (obsolete 4.2 sigreturn)", /* 139 = obsolete 4.2 sigreturn */ "adjtime", /* 140 = adjtime */ - "old.getpeername", /* 141 = old getpeername */ - "old.gethostid", /* 142 = old gethostid */ - "old.sethostid", /* 143 = old sethostid */ - "old.getrlimit", /* 144 = old getrlimit */ - "old.setrlimit", /* 145 = old setrlimit */ - "old.killpg", /* 146 = old killpg */ + "compat_43_getpeername", /* 141 = compat_43 getpeername */ + "compat_43_gethostid", /* 142 = compat_43 gethostid */ + "compat_43_sethostid", /* 143 = compat_43 sethostid */ + "compat_43_getrlimit", /* 144 = compat_43 getrlimit */ + "compat_43_setrlimit", /* 145 = compat_43 setrlimit */ + "compat_43_killpg", /* 146 = compat_43 killpg */ "setsid", /* 147 = setsid */ "quotactl", /* 148 = quotactl */ - "old.quota", /* 149 = old quota */ - "old.getsockname", /* 150 = old getsockname */ - "#151", /* 151 = nosys */ - "#152", /* 152 = nosys */ - "#153", /* 153 = nosys */ - "#154", /* 154 = nosys */ + "compat_43_quota", /* 149 = compat_43 quota */ + "compat_43_getsockname", /* 150 = compat_43 getsockname */ + "#151 (unimplemented)", /* 151 = unimplemented */ + "#152 (unimplemented)", /* 152 = unimplemented */ + "#153 (unimplemented)", /* 153 = unimplemented */ + "#154 (unimplemented)", /* 154 = unimplemented */ #ifdef NFS "nfssvc", /* 155 = nfssvc */ #else - "#155", /* 155 = nosys */ + "#155 (unimplemented nfssvc)", /* 155 = unimplemented nfssvc */ #endif - "old.getdirentries", /* 156 = old getdirentries */ + "compat_43_getdirentries", /* 156 = compat_43 getdirentries */ "statfs", /* 157 = statfs */ "fstatfs", /* 158 = fstatfs */ - "#159", /* 159 = nosys */ - "#160", /* 160 = nosys */ + "#159 (unimplemented)", /* 159 = unimplemented */ + "#160 (unimplemented)", /* 160 = unimplemented */ #ifdef NFS "getfh", /* 161 = getfh */ #else - "#161", /* 161 = nosys */ + "#161 (unimplemented getfh)", /* 161 = unimplemented getfh */ #endif - "#162", /* 162 = nosys */ - "#163", /* 163 = nosys */ - "#164", /* 164 = nosys */ - "#165", /* 165 = nosys */ - "#166", /* 166 = nosys */ - "#167", /* 167 = nosys */ - "#168", /* 168 = nosys */ - "#169", /* 169 = nosys */ - "#170", /* 170 = nosys */ -#ifdef SYSVSHM - "shmsys", /* 171 = shmsys */ + "#162 (unimplemented getdomainname)", /* 162 = unimplemented getdomainname */ + "#163 (unimplemented setdomainname)", /* 163 = unimplemented setdomainname */ + "#164 (unimplemented)", /* 164 = unimplemented */ + "#165 (unimplemented)", /* 165 = unimplemented */ + "#166 (unimplemented)", /* 166 = unimplemented */ + "#167 (unimplemented)", /* 167 = unimplemented */ + "#168 (unimplemented)", /* 168 = unimplemented */ + "#169 (unimplemented semsys)", /* 169 = unimplemented semsys */ + "#170 (unimplemented msgsys)", /* 170 = unimplemented msgsys */ +#if defined(SYSVSHM) && !defined(alpha) + "compat_43_shmsys", /* 171 = compat_43 shmsys */ #else - "#171", /* 171 = nosys */ + "#171 (unimplemented shmsys)", /* 171 = unimplemented shmsys */ #endif - "#172", /* 172 = nosys */ - "#173", /* 173 = nosys */ - "#174", /* 174 = nosys */ - "#175", /* 175 = nosys */ - "#176", /* 176 = nosys */ - "#177", /* 177 = nosys */ - "#178", /* 178 = nosys */ - "#179", /* 179 = nosys */ - "#180", /* 180 = nosys */ + "#172 (unimplemented)", /* 172 = unimplemented */ + "#173 (unimplemented)", /* 173 = unimplemented */ + "#174 (unimplemented)", /* 174 = unimplemented */ + "#175 (unimplemented)", /* 175 = unimplemented */ + "#176 (unimplemented)", /* 176 = unimplemented */ + "#177 (unimplemented)", /* 177 = unimplemented */ + "#178 (unimplemented)", /* 178 = unimplemented */ + "#179 (unimplemented)", /* 179 = unimplemented */ + "#180 (unimplemented)", /* 180 = unimplemented */ "setgid", /* 181 = setgid */ "setegid", /* 182 = setegid */ "seteuid", /* 183 = seteuid */ @@ -220,17 +220,17 @@ char *syscallnames[] = { "lfs_segclean", /* 186 = lfs_segclean */ "lfs_segwait", /* 187 = lfs_segwait */ #else - "#184", /* 184 = nosys */ - "#185", /* 185 = nosys */ - "#186", /* 186 = nosys */ - "#187", /* 187 = nosys */ + "#184 (unimplemented lfs_bmapv)", /* 184 = unimplemented lfs_bmapv */ + "#185 (unimplemented lfs_markv)", /* 185 = unimplemented lfs_markv */ + "#186 (unimplemented lfs_segclean)", /* 186 = unimplemented lfs_segclean */ + "#187 (unimplemented lfs_segwait)", /* 187 = unimplemented lfs_segwait */ #endif "stat", /* 188 = stat */ "fstat", /* 189 = fstat */ "lstat", /* 190 = lstat */ "pathconf", /* 191 = pathconf */ "fpathconf", /* 192 = fpathconf */ - "#193", /* 193 = nosys */ + "#193 (unimplemented)", /* 193 = unimplemented */ "getrlimit", /* 194 = getrlimit */ "setrlimit", /* 195 = setrlimit */ "getdirentries", /* 196 = getdirentries */ @@ -242,10 +242,38 @@ char *syscallnames[] = { "__sysctl", /* 202 = __sysctl */ "mlock", /* 203 = mlock */ "munlock", /* 204 = munlock */ - "#205", /* 205 = nosys */ - "#206", /* 206 = nosys */ - "#207", /* 207 = nosys */ - "#208", /* 208 = nosys */ - "#209", /* 209 = nosys */ - "#210", /* 210 = nosys */ + "undelete", /* 205 = undelete */ + "#206 (unimplemented)", /* 206 = unimplemented */ + "#207 (unimplemented)", /* 207 = unimplemented */ + "#208 (unimplemented)", /* 208 = unimplemented */ + "#209 (unimplemented)", /* 209 = unimplemented */ + "#210 (unimplemented)", /* 210 = unimplemented */ + "#211 (unimplemented)", /* 211 = unimplemented */ + "#212 (unimplemented)", /* 212 = unimplemented */ + "#213 (unimplemented)", /* 213 = unimplemented */ + "#214 (unimplemented)", /* 214 = unimplemented */ + "#215 (unimplemented)", /* 215 = unimplemented */ + "#216 (unimplemented)", /* 216 = unimplemented */ + "#217 (unimplemented)", /* 217 = unimplemented */ + "#218 (unimplemented)", /* 218 = unimplemented */ + "#219 (unimplemented)", /* 219 = unimplemented */ + "#220 (unimplemented semctl)", /* 220 = unimplemented semctl */ + "#221 (unimplemented semget)", /* 221 = unimplemented semget */ + "#222 (unimplemented semop)", /* 222 = unimplemented semop */ + "#223 (unimplemented semconfig)", /* 223 = unimplemented semconfig */ + "#224 (unimplemented msgctl)", /* 224 = unimplemented msgctl */ + "#225 (unimplemented msgget)", /* 225 = unimplemented msgget */ + "#226 (unimplemented msgsnd)", /* 226 = unimplemented msgsnd */ + "#227 (unimplemented msgrcv)", /* 227 = unimplemented msgrcv */ +#if defined(SYSVSHM) && 0 + "shmat", /* 228 = shmat */ + "shmctl", /* 229 = shmctl */ + "shmdt", /* 230 = shmdt */ + "shmget", /* 231 = shmget */ +#else + "#228 (unimplemented shmat)", /* 228 = unimplemented shmat */ + "#229 (unimplemented shmctl)", /* 229 = unimplemented shmctl */ + "#230 (unimplemented shmdt)", /* 230 = unimplemented shmdt */ + "#231 (unimplemented shmget)", /* 231 = unimplemented shmget */ +#endif }; diff --git a/sys/kern/syscalls.conf b/sys/kern/syscalls.conf new file mode 100644 index 0000000..71b82ce --- /dev/null +++ b/sys/kern/syscalls.conf @@ -0,0 +1,12 @@ +# @(#)syscalls.conf 8.1 (Berkeley) 2/14/95 + +sysnames="syscalls.c" +sysnumhdr="../sys/syscall.h" +syssw="init_sysent.c" +sysarghdr="../sys/syscallargs.h" +compatopts="compat_43" +libcompatopts="" + +switchname="sysent" +namesname="syscallnames" +constprefix="SYS_" diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 1b8de14..b57cd73 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -1,23 +1,38 @@ - @(#)syscalls.master 8.2 (Berkeley) 1/13/94 -; System call name/number master file. -; Processed to created init_sysent.c, syscalls.c and syscall.h. - -; Columns: number type nargs name altname/comments + @(#)syscalls.master 8.6 (Berkeley) 3/30/95 +; System call name/number "master" file. +; (See syscalls.conf to see what it is processed into.) +; +; Fields: number type [type-dependent ...] ; number system call number, must be in order -; type one of STD, OBSOL, UNIMPL, COMPAT -; nargs number of arguments -; name name of syscall routine -; altname name of system call if different -; for UNIMPL/OBSOL, name continues with comments - +; type one of STD, OBSOL, UNIMPL, NODEF, NOARGS, or one of +; the compatibility options defined in syscalls.conf. +; ; types: ; STD always included -; COMPAT included on COMPAT #ifdef -; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h -; OBSOL obsolete, not included in system, only specifies name -; UNIMPL not implemented, placeholder only - +; OBSOL obsolete, not included in system +; UNIMPL unimplemented, not included in system +; NODEF included, but don't define the syscall number +; NOARGS included, but don't define the syscall args structure +; +; The compat options are defined in the syscalls.conf file, and the +; compat option name is prefixed to the syscall name. Other than +; that, they're like NODEF (for 'compat' options), or STD (for +; 'libcompat' options). +; +; The type-dependent arguments are as follows: +; For STD, NODEF, NOARGS, and compat syscalls: +; { pseudo-proto } [alias] +; For other syscalls: +; [comment] +; ; #ifdef's, etc. may be included, and are copied to the output files. +; #include's are copied to the syscall switch definition file only. + +#include +#include +#include +#include +#include ; Reserved/unimplemented system calls in the range 0-150 inclusive ; are reserved for use in future Berkeley releases. @@ -25,252 +40,316 @@ ; redistributions should be placed in the reserved range at the end ; of the current calls. -0 STD 0 nosys syscall -1 STD 1 exit -2 STD 0 fork -3 STD 3 read -4 STD 3 write -5 STD 3 open -6 STD 1 close -7 STD 4 wait4 -8 COMPAT 2 creat -9 STD 2 link -10 STD 1 unlink -11 OBSOL 2 execv -12 STD 1 chdir -13 STD 1 fchdir -14 STD 3 mknod -15 STD 2 chmod -16 STD 3 chown -17 STD 1 obreak break -18 STD 3 getfsstat -19 COMPAT 3 lseek -20 STD 0 getpid -21 STD 4 mount -22 STD 2 unmount -23 STD 1 setuid -24 STD 0 getuid -25 STD 0 geteuid -26 STD 4 ptrace -27 STD 3 recvmsg -28 STD 3 sendmsg -29 STD 6 recvfrom -30 STD 3 accept -31 STD 3 getpeername -32 STD 3 getsockname -33 STD 2 access -34 STD 2 chflags -35 STD 2 fchflags -36 STD 0 sync -37 STD 2 kill -38 COMPAT 2 stat -39 STD 0 getppid -40 COMPAT 2 lstat -41 STD 2 dup -42 STD 0 pipe -43 STD 0 getegid -44 STD 4 profil +0 STD { int nosys(void); } syscall +1 STD { int exit(int rval); } +2 STD { int fork(void); } +3 STD { int read(int fd, char *buf, u_int nbyte); } +4 STD { int write(int fd, char *buf, u_int nbyte); } +5 STD { int open(char *path, int flags, int mode); } +6 STD { int close(int fd); } +7 STD { int wait4(int pid, int *status, int options, \ + struct rusage *rusage); } +8 COMPAT_43 { int creat(char *path, int mode); } +9 STD { int link(char *path, char *link); } +10 STD { int unlink(char *path); } +11 OBSOL execv +12 STD { int chdir(char *path); } +13 STD { int fchdir(int fd); } +14 STD { int mknod(char *path, int mode, int dev); } +15 STD { int chmod(char *path, int mode); } +16 STD { int chown(char *path, int uid, int gid); } +17 STD { int obreak(char *nsize); } break +18 STD { int getfsstat(struct statfs *buf, long bufsize, \ + int flags); } +19 COMPAT_43 { long lseek(int fd, long offset, int whence); } +20 STD { pid_t getpid(void); } +21 STD { int mount(char *type, char *path, int flags, \ + caddr_t data); } +22 STD { int unmount(char *path, int flags); } +23 STD { int setuid(uid_t uid); } +24 STD { uid_t getuid(void); } +25 STD { uid_t geteuid(void); } +26 STD { int ptrace(int req, pid_t pid, caddr_t addr, \ + int data); } +27 STD { int recvmsg(int s, struct msghdr *msg, int flags); } +28 STD { int sendmsg(int s, caddr_t msg, int flags); } +29 STD { int recvfrom(int s, caddr_t buf, size_t len, \ + int flags, caddr_t from, int *fromlenaddr); } +30 STD { int accept(int s, caddr_t name, int *anamelen); } +31 STD { int getpeername(int fdes, caddr_t asa, int *alen); } +32 STD { int getsockname(int fdes, caddr_t asa, int *alen); } +33 STD { int access(char *path, int flags); } +34 STD { int chflags(char *path, int flags); } +35 STD { int fchflags(int fd, int flags); } +36 STD { int sync(void); } +37 STD { int kill(int pid, int signum); } +38 COMPAT_43 { int stat(char *path, struct ostat *ub); } +39 STD { pid_t getppid(void); } +40 COMPAT_43 { int lstat(char *path, struct ostat *ub); } +41 STD { int dup(u_int fd); } +42 STD { int pipe(void); } +43 STD { gid_t getegid(void); } +44 STD { int profil(caddr_t samples, u_int size, \ + u_int offset, u_int scale); } #ifdef KTRACE -45 STD 4 ktrace +45 STD { int ktrace(char *fname, int ops, int facs, \ + int pid); } #else -45 UNIMPL 0 ktrace +45 UNIMPL ktrace #endif -46 STD 3 sigaction -47 STD 0 getgid -48 STD 2 sigprocmask -49 STD 2 getlogin -50 STD 1 setlogin -51 STD 1 acct -52 STD 0 sigpending -53 STD 2 sigaltstack -54 STD 3 ioctl -55 STD 1 reboot -56 STD 1 revoke -57 STD 2 symlink -58 STD 3 readlink -59 STD 3 execve -60 STD 1 umask -61 STD 1 chroot -62 COMPAT 2 fstat -63 COMPAT 4 getkerninfo -64 COMPAT 0 getpagesize -65 STD 2 msync -66 STD 0 vfork -67 OBSOL 0 vread -68 OBSOL 0 vwrite -69 STD 1 sbrk -70 STD 1 sstk -71 COMPAT 7 mmap -72 STD 1 ovadvise vadvise -73 STD 2 munmap -74 STD 3 mprotect -75 STD 3 madvise -76 OBSOL 0 vhangup -77 OBSOL 0 vlimit -78 STD 3 mincore -79 STD 2 getgroups -80 STD 2 setgroups -81 STD 0 getpgrp -82 STD 2 setpgid -83 STD 3 setitimer -84 COMPAT 0 wait -85 STD 1 swapon -86 STD 2 getitimer -87 COMPAT 2 gethostname -88 COMPAT 2 sethostname -89 STD 0 getdtablesize -90 STD 2 dup2 -91 UNIMPL 2 getdopt -92 STD 3 fcntl -93 STD 5 select -94 UNIMPL 2 setdopt -95 STD 1 fsync -96 STD 3 setpriority -97 STD 3 socket -98 STD 3 connect -99 COMPAT 3 accept -100 STD 2 getpriority -101 COMPAT 4 send -102 COMPAT 4 recv -103 STD 1 sigreturn -104 STD 3 bind -105 STD 5 setsockopt -106 STD 2 listen -107 OBSOL 0 vtimes -108 COMPAT 3 sigvec -109 COMPAT 1 sigblock -110 COMPAT 1 sigsetmask -111 STD 1 sigsuspend -112 COMPAT 2 sigstack -113 COMPAT 3 recvmsg -114 COMPAT 3 sendmsg +46 STD { int sigaction(int signum, struct sigaction *nsa, \ + struct sigaction *osa); } +47 STD { gid_t getgid(void); } +48 STD { int sigprocmask(int how, sigset_t mask); } +49 STD { int getlogin(char *namebuf, u_int namelen); } +50 STD { int setlogin(char *namebuf); } +51 STD { int acct(char *path); } +52 STD { int sigpending(void); } +53 STD { int sigaltstack(struct sigaltstack *nss, \ + struct sigaltstack *oss); } +54 STD { int ioctl(int fd, u_long com, caddr_t data); } +55 STD { int reboot(int opt); } +56 STD { int revoke(char *path); } +57 STD { int symlink(char *path, char *link); } +58 STD { int readlink(char *path, char *buf, int count); } +59 STD { int execve(char *path, char **argp, char **envp); } +60 STD { int umask(int newmask); } +61 STD { int chroot(char *path); } +62 COMPAT_43 { int fstat(int fd, struct ostat *sb); } +63 COMPAT_43 { int getkerninfo(int op, char *where, int *size, \ + int arg); } +64 COMPAT_43 { int getpagesize(void); } +65 STD { int msync(caddr_t addr, int len); } +66 STD { int vfork(void); } +67 OBSOL vread +68 OBSOL vwrite +69 STD { int sbrk(int incr); } +70 STD { int sstk(int incr); } +71 COMPAT_43 { int mmap(caddr_t addr, int len, int prot, \ + int flags, int fd, long pos); } +72 STD { int ovadvise(int anom); } vadvise +73 STD { int munmap(caddr_t addr, int len); } +74 STD { int mprotect(caddr_t addr, int len, int prot); } +75 STD { int madvise(caddr_t addr, int len, int behav); } +76 OBSOL vhangup +77 OBSOL vlimit +78 STD { int mincore(caddr_t addr, int len, char *vec); } +79 STD { int getgroups(u_int gidsetsize, gid_t *gidset); } +80 STD { int setgroups(u_int gidsetsize, gid_t *gidset); } +81 STD { int getpgrp(void); } +82 STD { int setpgid(int pid, int pgid); } +83 STD { int setitimer(u_int which, struct itimerval *itv, \ + struct itimerval *oitv); } +84 COMPAT_43 { int wait(void); } +85 STD { int swapon(char *name); } +86 STD { int getitimer(u_int which, struct itimerval *itv); } +87 COMPAT_43 { int gethostname(char *hostname, u_int len); } +88 COMPAT_43 { int sethostname(char *hostname, u_int len); } +89 STD { int getdtablesize(void); } +90 STD { int dup2(u_int from, u_int to); } +91 UNIMPL getdopt +92 STD { int fcntl(int fd, int cmd, void *arg); } +93 STD { int select(u_int nd, fd_set *in, fd_set *ou, \ + fd_set *ex, struct timeval *tv); } +94 UNIMPL setdopt +95 STD { int fsync(int fd); } +96 STD { int setpriority(int which, int who, int prio); } +97 STD { int socket(int domain, int type, int protocol); } +98 STD { int connect(int s, caddr_t name, int namelen); } +99 COMPAT_43 { int accept(int s, caddr_t name, int *anamelen); } +100 STD { int getpriority(int which, int who); } +101 COMPAT_43 { int send(int s, caddr_t buf, int len, int flags); } +102 COMPAT_43 { int recv(int s, caddr_t buf, int len, int flags); } +103 STD { int sigreturn(struct sigcontext *sigcntxp); } +104 STD { int bind(int s, caddr_t name, int namelen); } +105 STD { int setsockopt(int s, int level, int name, \ + caddr_t val, int valsize); } +106 STD { int listen(int s, int backlog); } +107 OBSOL vtimes +108 COMPAT_43 { int sigvec(int signum, struct sigvec *nsv, \ + struct sigvec *osv); } +109 COMPAT_43 { int sigblock(int mask); } +110 COMPAT_43 { int sigsetmask(int mask); } +111 STD { int sigsuspend(int mask); } +112 COMPAT_43 { int sigstack(struct sigstack *nss, \ + struct sigstack *oss); } +113 COMPAT_43 { int recvmsg(int s, struct omsghdr *msg, int flags); } +114 COMPAT_43 { int sendmsg(int s, caddr_t msg, int flags); } #ifdef TRACE -115 STD 2 vtrace +115 STD { int vtrace(int request, int value); } #else -115 OBSOL 2 vtrace +115 OBSOL vtrace #endif -116 STD 2 gettimeofday -117 STD 2 getrusage -118 STD 5 getsockopt +116 STD { int gettimeofday(struct timeval *tp, \ + struct timezone *tzp); } +117 STD { int getrusage(int who, struct rusage *rusage); } +118 STD { int getsockopt(int s, int level, int name, \ + caddr_t val, int *avalsize); } #ifdef vax -119 STD 1 resuba +119 STD { int resuba(int value); } #else -119 UNIMPL 0 nosys +119 UNIMPL resuba #endif -120 STD 3 readv -121 STD 3 writev -122 STD 2 settimeofday -123 STD 3 fchown -124 STD 2 fchmod -125 COMPAT 6 recvfrom -126 COMPAT 2 setreuid -127 COMPAT 2 setregid -128 STD 2 rename -129 COMPAT 2 truncate -130 COMPAT 2 ftruncate -131 STD 2 flock -132 STD 2 mkfifo -133 STD 6 sendto -134 STD 2 shutdown -135 STD 5 socketpair -136 STD 2 mkdir -137 STD 1 rmdir -138 STD 2 utimes -139 OBSOL 0 4.2 sigreturn -140 STD 2 adjtime -141 COMPAT 3 getpeername -142 COMPAT 0 gethostid -143 COMPAT 1 sethostid -144 COMPAT 2 getrlimit -145 COMPAT 2 setrlimit -146 COMPAT 2 killpg -147 STD 0 setsid -148 STD 4 quotactl -149 COMPAT 4 quota -150 COMPAT 3 getsockname +120 STD { int readv(int fd, struct iovec *iovp, u_int iovcnt); } +121 STD { int writev(int fd, struct iovec *iovp, \ + u_int iovcnt); } +122 STD { int settimeofday(struct timeval *tv, \ + struct timezone *tzp); } +123 STD { int fchown(int fd, int uid, int gid); } +124 STD { int fchmod(int fd, int mode); } +125 COMPAT_43 { int recvfrom(int s, caddr_t buf, size_t len, \ + int flags, caddr_t from, int *fromlenaddr); } +126 COMPAT_43 { int setreuid(int ruid, int euid); } +127 COMPAT_43 { int setregid(int rgid, int egid); } +128 STD { int rename(char *from, char *to); } +129 COMPAT_43 { int truncate(char *path, long length); } +130 COMPAT_43 { int ftruncate(int fd, long length); } +131 STD { int flock(int fd, int how); } +132 STD { int mkfifo(char *path, int mode); } +133 STD { int sendto(int s, caddr_t buf, size_t len, \ + int flags, caddr_t to, int tolen); } +134 STD { int shutdown(int s, int how); } +135 STD { int socketpair(int domain, int type, int protocol, \ + int *rsv); } +136 STD { int mkdir(char *path, int mode); } +137 STD { int rmdir(char *path); } +138 STD { int utimes(char *path, struct timeval *tptr); } +139 OBSOL 4.2 sigreturn +140 STD { int adjtime(struct timeval *delta, \ + struct timeval *olddelta); } +141 COMPAT_43 { int getpeername(int fdes, caddr_t asa, int *alen); } +142 COMPAT_43 { int32_t gethostid(void); } +143 COMPAT_43 { int sethostid(int32_t hostid); } +144 COMPAT_43 { int getrlimit(u_int which, struct ogetrlimit *rlp); } +145 COMPAT_43 { int setrlimit(u_int which, struct ogetrlimit *rlp); } +146 COMPAT_43 { int killpg(int pgid, int signum); } +147 STD { int setsid(void); } +148 STD { int quotactl(char *path, int cmd, int uid, \ + caddr_t arg); } +149 COMPAT_43 { int quota(void); } +150 COMPAT_43 { int getsockname(int fdec, caddr_t asa, int *alen); } ; Syscalls 151-180 inclusive are reserved for vendor-specific ; system calls. (This includes various calls added for compatibity ; with other Unix variants.) ; Some of these calls are now supported by BSD... -151 UNIMPL 0 nosys -152 UNIMPL 0 nosys -153 UNIMPL 0 nosys -154 UNIMPL 0 nosys +151 UNIMPL +152 UNIMPL +153 UNIMPL +154 UNIMPL #ifdef NFS -155 STD 2 nfssvc +155 STD { int nfssvc(int flag, caddr_t argp); } #else -155 UNIMPL 0 nosys +155 UNIMPL nfssvc #endif -156 COMPAT 4 getdirentries -157 STD 2 statfs -158 STD 2 fstatfs -159 UNIMPL 0 nosys -160 UNIMPL 0 nosys +156 COMPAT_43 { int getdirentries(int fd, char *buf, u_int count, \ + long *basep); } +157 STD { int statfs(char *path, struct statfs *buf); } +158 STD { int fstatfs(int fd, struct statfs *buf); } +159 UNIMPL +160 UNIMPL #ifdef NFS -161 STD 2 getfh +161 STD { int getfh(char *fname, fhandle_t *fhp); } #else -161 UNIMPL 0 nosys +161 UNIMPL getfh #endif -162 UNIMPL 0 nosys -163 UNIMPL 0 nosys -164 UNIMPL 0 nosys -165 UNIMPL 0 nosys -166 UNIMPL 0 nosys -167 UNIMPL 0 nosys -168 UNIMPL 0 nosys -169 UNIMPL 0 nosys -170 UNIMPL 0 nosys -#ifdef SYSVSHM -171 STD 4 shmsys +162 UNIMPL getdomainname +163 UNIMPL setdomainname +164 UNIMPL +165 UNIMPL +166 UNIMPL +167 UNIMPL +168 UNIMPL +169 UNIMPL semsys +170 UNIMPL msgsys +; XXX more generally, never on machines where sizeof(void *) != sizeof(int) +#if defined(SYSVSHM) && !defined(alpha) +171 COMPAT_43 { int shmsys(int which, int a2, int a3, int a4); } #else -171 UNIMPL 0 nosys +171 UNIMPL shmsys #endif -172 UNIMPL 0 nosys -173 UNIMPL 0 nosys -174 UNIMPL 0 nosys -175 UNIMPL 0 nosys -176 UNIMPL 0 nosys -177 UNIMPL 0 nosys -178 UNIMPL 0 nosys -179 UNIMPL 0 nosys -180 UNIMPL 0 nosys +172 UNIMPL +173 UNIMPL +174 UNIMPL +175 UNIMPL +176 UNIMPL +177 UNIMPL +178 UNIMPL +179 UNIMPL +180 UNIMPL -; Syscalls 180-199 are used by/reserved for BSD -181 STD 1 setgid -182 STD 1 setegid -183 STD 1 seteuid +; Syscalls 180-209 are used by/reserved for BSD +181 STD { int setgid(gid_t gid); } +182 STD { int setegid(gid_t egid); } +183 STD { int seteuid(uid_t euid); } #ifdef LFS -184 STD 3 lfs_bmapv -185 STD 3 lfs_markv -186 STD 2 lfs_segclean -187 STD 2 lfs_segwait +184 STD { int lfs_bmapv(fsid_t *fsidp, \ + struct block_info *blkiov, int blkcnt); } +185 STD { int lfs_markv(fsid_t *fsidp, \ + struct block_info *blkiov, int blkcnt); } +186 STD { int lfs_segclean(fsid_t *fsidp, u_long segment); } +187 STD { int lfs_segwait(fsid_t *fsidp, struct timeval *tv); } +#else +184 UNIMPL lfs_bmapv +185 UNIMPL lfs_markv +186 UNIMPL lfs_segclean +187 UNIMPL lfs_segwait +#endif +188 STD { int stat(char *path, struct stat *ub); } +189 STD { int fstat(int fd, struct stat *sb); } +190 STD { int lstat(char *path, struct stat *ub); } +191 STD { int pathconf(char *path, int name); } +192 STD { int fpathconf(int fd, int name); } +193 UNIMPL +194 STD { int getrlimit(u_int which, struct rlimit *rlp); } +195 STD { int setrlimit(u_int which, struct rlimit *rlp); } +196 STD { int getdirentries(int fd, char *buf, u_int count, \ + long *basep); } +197 STD { caddr_t mmap(caddr_t addr, size_t len, int prot, \ + int flags, int fd, long pad, off_t pos); } +198 STD { int nosys(void); } __syscall +199 STD { off_t lseek(int fd, int pad, off_t offset, \ + int whence); } +200 STD { int truncate(char *path, int pad, off_t length); } +201 STD { int ftruncate(int fd, int pad, off_t length); } +202 STD { int __sysctl(int *name, u_int namelen, void *old, \ + size_t *oldlenp, void *new, size_t newlen); } +203 STD { int mlock(caddr_t addr, size_t len); } +204 STD { int munlock(caddr_t addr, size_t len); } +205 STD { int undelete(char *path); } +206 UNIMPL +207 UNIMPL +208 UNIMPL +209 UNIMPL +; Syscalls 210-219 are used by/reserved for vendor-specific system calls +210 UNIMPL +211 UNIMPL +212 UNIMPL +213 UNIMPL +214 UNIMPL +215 UNIMPL +216 UNIMPL +217 UNIMPL +218 UNIMPL +219 UNIMPL +; System calls 220-240 are reserved for use by BSD +220 UNIMPL semctl +221 UNIMPL semget +222 UNIMPL semop +223 UNIMPL semconfig +224 UNIMPL msgctl +225 UNIMPL msgget +226 UNIMPL msgsnd +227 UNIMPL msgrcv +#if defined(SYSVSHM) && 0 +228 STD { int shmat(int shmid, void *shmaddr, int shmflg); } +229 STD { int shmctl(int shmid, int cmd, \ + struct shmid_ds *buf); } +230 STD { int shmdt(void *shmaddr); } +231 STD { int shmget(key_t key, int size, int shmflg); } #else -184 UNIMPL 0 nosys -185 UNIMPL 0 nosys -186 UNIMPL 0 nosys -187 UNIMPL 0 nosys +228 UNIMPL shmat +229 UNIMPL shmctl +230 UNIMPL shmdt +231 UNIMPL shmget #endif -188 STD 2 stat -189 STD 2 fstat -190 STD 2 lstat -191 STD 2 pathconf -192 STD 2 fpathconf -193 UNIMPL 0 nosys -194 STD 2 getrlimit -195 STD 2 setrlimit -196 STD 4 getdirentries -197 STD 8 mmap -198 STD 0 nosys __syscall -199 STD 5 lseek -200 STD 4 truncate -201 STD 4 ftruncate -202 STD 6 __sysctl -203 STD 2 mlock -204 STD 2 munlock -205 UNIMPL 0 nosys -206 UNIMPL 0 nosys -207 UNIMPL 0 nosys -208 UNIMPL 0 nosys -209 UNIMPL 0 nosys -210 UNIMPL 0 nosys diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 6cc7be2..5d698b1 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)tty.c 8.8 (Berkeley) 1/21/94 + * @(#)tty.c 8.13 (Berkeley) 1/9/95 */ #include @@ -531,7 +531,7 @@ ttyoutput(c, tp) register struct tty *tp; { register long oflag; - register int col, s; + register int notout, col, s; oflag = tp->t_oflag; if (!ISSET(oflag, OPOST)) { @@ -553,15 +553,18 @@ ttyoutput(c, tp) if (c == '\t' && ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) { c = 8 - (tp->t_column & 7); - if (!ISSET(tp->t_lflag, FLUSHO)) { + if (ISSET(tp->t_lflag, FLUSHO)) { + notout = 0; + } else { s = spltty(); /* Don't interrupt tabs. */ - c -= b_to_q(" ", c, &tp->t_outq); + notout = b_to_q(" ", c, &tp->t_outq); + c -= notout; tk_nout += c; tp->t_outcc += c; splx(s); } tp->t_column += c; - return (c ? -1 : '\t'); + return (notout ? '\t' : -1); } if (c == CEOT && ISSET(oflag, ONOEOT)) return (-1); @@ -613,8 +616,9 @@ ttyoutput(c, tp) int ttioctl(tp, cmd, data, flag) register struct tty *tp; - int cmd, flag; + u_long cmd; void *data; + int flag; { extern struct tty *constty; /* Temporary virtual console. */ extern int nlinesw; @@ -1766,11 +1770,11 @@ ttyinfo(tp) ttyprintf(tp, "not a controlling terminal\n"); else if (tp->t_pgrp == NULL) ttyprintf(tp, "no foreground process group\n"); - else if ((p = tp->t_pgrp->pg_mem) == NULL) + else if ((p = tp->t_pgrp->pg_members.lh_first) == 0) ttyprintf(tp, "empty foreground process group\n"); else { /* Pick interesting process. */ - for (pick = NULL; p != NULL; p = p->p_pgrpnxt) + for (pick = NULL; p != 0; p = p->p_pglist.le_next) if (proc_compare(pick, p)) pick = p; diff --git a/sys/kern/tty_compat.c b/sys/kern/tty_compat.c index a6a39d9..ce95853 100644 --- a/sys/kern/tty_compat.c +++ b/sys/kern/tty_compat.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)tty_compat.c 8.1 (Berkeley) 6/10/93 + * @(#)tty_compat.c 8.2 (Berkeley) 1/9/95 */ /* @@ -78,7 +78,7 @@ static int compatspcodes[16] = { /*ARGSUSED*/ ttcompat(tp, com, data, flag) register struct tty *tp; - int com; + u_long com; caddr_t data; int flag; { diff --git a/sys/kern/tty_conf.c b/sys/kern/tty_conf.c index b53edb42..1453675 100644 --- a/sys/kern/tty_conf.c +++ b/sys/kern/tty_conf.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)tty_conf.c 8.4 (Berkeley) 1/21/94 + * @(#)tty_conf.c 8.5 (Berkeley) 1/9/95 */ #include @@ -52,7 +52,7 @@ #define ttyerrinput ((int (*) __P((int c, struct tty *)))enodev) #define ttyerrstart ((int (*) __P((struct tty *)))enodev) -int nullioctl __P((struct tty *tp, int cmd, caddr_t data, +int nullioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)); #include "tb.h" @@ -60,7 +60,7 @@ int nullioctl __P((struct tty *tp, int cmd, caddr_t data, int tbopen __P((dev_t dev, struct tty *tp)); int tbclose __P((struct tty *tp, int flags)); int tbread __P((struct tty *, struct uio *, int flags)); -int tbioctl __P((struct tty *tp, int cmd, caddr_t data, +int tbioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)); int tbinput __P((int c, struct tty *tp)); #endif @@ -69,7 +69,7 @@ int tbinput __P((int c, struct tty *tp)); #if NSL > 0 int slopen __P((dev_t dev, struct tty *tp)); int slclose __P((struct tty *tp, int flags)); -int sltioctl __P((struct tty *tp, int cmd, caddr_t data, +int sltioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)); int slinput __P((int c, struct tty *tp)); int slstart __P((struct tty *tp)); @@ -113,7 +113,7 @@ int nlinesw = sizeof (linesw) / sizeof (linesw[0]); /*ARGSUSED*/ nullioctl(tp, cmd, data, flags, p) struct tty *tp; - int cmd; + u_long cmd; char *data; int flags; struct proc *p; diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index 0e6911b..2c37984 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)tty_pty.c 8.2 (Berkeley) 9/23/93 + * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95 */ /* @@ -536,7 +536,7 @@ block: /*ARGSUSED*/ ptyioctl(dev, cmd, data, flag, p) dev_t dev; - int cmd; + u_long cmd; caddr_t data; int flag; struct proc *p; @@ -563,7 +563,7 @@ ptyioctl(dev, cmd, data, flag, p) } tp->t_lflag |= EXTPROC; } else { - if ((tp->t_state & EXTPROC) && + if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); diff --git a/sys/kern/tty_tb.c b/sys/kern/tty_tb.c index 242301a..05a46ba 100644 --- a/sys/kern/tty_tb.c +++ b/sys/kern/tty_tb.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)tty_tb.c 8.1 (Berkeley) 6/10/93 + * @(#)tty_tb.c 8.2 (Berkeley) 1/9/95 */ #include "tb.h" @@ -310,7 +310,9 @@ poldecode(tc, cp, polpos) /*ARGSUSED*/ tbioctl(tp, cmd, data, flag) struct tty *tp; + u_long cmd; caddr_t data; + int flag; { register struct tb *tbp = (struct tb *)tp->T_LINEP; diff --git a/sys/kern/tty_tty.c b/sys/kern/tty_tty.c index 964fc6f..d9dd1b4 100644 --- a/sys/kern/tty_tty.c +++ b/sys/kern/tty_tty.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1982, 1986, 1991, 1993 + * Copyright (c) 1982, 1986, 1991, 1993, 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)tty_tty.c 8.2 (Berkeley) 9/23/93 + * @(#)tty_tty.c 8.4 (Berkeley) 5/14/95 */ /* @@ -58,7 +58,7 @@ cttyopen(dev, flag, mode, p) if (ttyvp == NULL) return (ENXIO); - VOP_LOCK(ttyvp); + vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p); #ifdef PARANOID /* * Since group is tty and mode is 620 on most terminal lines @@ -73,7 +73,7 @@ cttyopen(dev, flag, mode, p) if (!error) #endif /* PARANOID */ error = VOP_OPEN(ttyvp, flag, NOCRED, p); - VOP_UNLOCK(ttyvp); + VOP_UNLOCK(ttyvp, 0, p); return (error); } @@ -83,14 +83,15 @@ cttyread(dev, uio, flag) struct uio *uio; int flag; { - register struct vnode *ttyvp = cttyvp(uio->uio_procp); + struct proc *p = uio->uio_procp; + register struct vnode *ttyvp = cttyvp(p); int error; if (ttyvp == NULL) return (EIO); - VOP_LOCK(ttyvp); + vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_READ(ttyvp, uio, flag, NOCRED); - VOP_UNLOCK(ttyvp); + VOP_UNLOCK(ttyvp, 0, p); return (error); } @@ -100,21 +101,22 @@ cttywrite(dev, uio, flag) struct uio *uio; int flag; { - register struct vnode *ttyvp = cttyvp(uio->uio_procp); + struct proc *p = uio->uio_procp; + struct vnode *ttyvp = cttyvp(uio->uio_procp); int error; if (ttyvp == NULL) return (EIO); - VOP_LOCK(ttyvp); + vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_WRITE(ttyvp, uio, flag, NOCRED); - VOP_UNLOCK(ttyvp); + VOP_UNLOCK(ttyvp, 0, p); return (error); } /*ARGSUSED*/ cttyioctl(dev, cmd, addr, flag, p) dev_t dev; - int cmd; + u_long cmd; caddr_t addr; int flag; struct proc *p; diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c index 8834dbf..1c91f2a 100644 --- a/sys/kern/uipc_domain.c +++ b/sys/kern/uipc_domain.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)uipc_domain.c 8.2 (Berkeley) 10/18/93 + * @(#)uipc_domain.c 8.3 (Berkeley) 2/14/95 */ #include @@ -54,6 +54,7 @@ void pfslowtimo __P((void *)); domains = &__CONCAT(x,domain); \ } +void domaininit() { register struct domain *dp; @@ -93,8 +94,8 @@ if (max_linkhdr < 16) /* XXX */ max_linkhdr = 16; max_hdr = max_linkhdr + max_protohdr; max_datalen = MHLEN - max_hdr; - timeout(pffasttimo, (void *)0, 1); - timeout(pfslowtimo, (void *)0, 1); + timeout(pffasttimo, NULL, 1); + timeout(pfslowtimo, NULL, 1); } struct protosw * @@ -141,6 +142,7 @@ found: return (maybe); } +int net_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) int *name; u_int namelen; @@ -178,6 +180,7 @@ found: return (ENOPROTOOPT); } +void pfctlinput(cmd, sa) int cmd; struct sockaddr *sa; @@ -202,7 +205,7 @@ pfslowtimo(arg) for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_slowtimo) (*pr->pr_slowtimo)(); - timeout(pfslowtimo, (void *)0, hz/2); + timeout(pfslowtimo, NULL, hz/2); } void @@ -216,5 +219,5 @@ pffasttimo(arg) for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_fasttimo) (*pr->pr_fasttimo)(); - timeout(pffasttimo, (void *)0, hz/5); + timeout(pffasttimo, NULL, hz/5); } diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index b71c634..62abfd5 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 + * @(#)uipc_mbuf.c 8.4 (Berkeley) 2/14/95 */ #include @@ -51,17 +51,13 @@ extern vm_map_t mb_map; struct mbuf *mbutl; char *mclrefcnt; +void mbinit() { int s; -#if CLBYTES < 4096 -#define NCL_INIT (4096/CLBYTES) -#else -#define NCL_INIT 1 -#endif s = splimp(); - if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0) + if (m_clalloc(max(4096/CLBYTES, 1), M_DONTWAIT) == 0) goto bad; splx(s); return; @@ -75,6 +71,7 @@ bad: * Must be called at splimp. */ /* ARGSUSED */ +int m_clalloc(ncl, nowait) register int ncl; int nowait; @@ -137,6 +134,7 @@ m_retryhdr(i, t) return (m); } +void m_reclaim() { register struct domain *dp; @@ -323,6 +321,7 @@ nospace: * Copy data from an mbuf chain starting "off" bytes from the beginning, * continuing for "len" bytes, into the indicated buffer. */ +void m_copydata(m, off, len, cp) register struct mbuf *m; register int off; @@ -358,6 +357,7 @@ m_copydata(m, off, len, cp) * Both chains must be of the same type (e.g. MT_DATA). * Any m_pkthdr is not updated. */ +void m_cat(m, n) register struct mbuf *m, *n; { @@ -378,6 +378,7 @@ m_cat(m, n) } } +void m_adj(mp, req_len) struct mbuf *mp; int req_len; @@ -603,8 +604,12 @@ m_devget(buf, totlen, off0, ifp, copy) cp = buf; epkt = cp + totlen; if (off) { - cp += off + 2 * sizeof(u_short); - totlen -= 2 * sizeof(u_short); + /* + * If 'off' is non-zero, packet is trailer-encapsulated, + * so we have to skip the type and length fields. + */ + cp += off + 2 * sizeof(u_int16_t); + totlen -= 2 * sizeof(u_int16_t); } MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == 0) diff --git a/sys/kern/uipc_proto.c b/sys/kern/uipc_proto.c index da9828a..e89a84c 100644 --- a/sys/kern/uipc_proto.c +++ b/sys/kern/uipc_proto.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)uipc_proto.c 8.1 (Berkeley) 6/10/93 + * @(#)uipc_proto.c 8.2 (Berkeley) 2/14/95 */ #include @@ -44,7 +44,7 @@ */ int uipc_usrreq(), raw_usrreq(); -void raw_init(),raw_input(),raw_ctlinput(); +void raw_init(), raw_input(), raw_ctlinput(); extern struct domain unixdomain; /* or at least forward */ struct protosw unixsw[] = { diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index ed09ee6..a9c5453 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94 + * @(#)uipc_socket.c 8.6 (Berkeley) 5/2/95 */ #include @@ -54,6 +54,7 @@ * switching out to the protocol specific routines. */ /*ARGSUSED*/ +int socreate(dom, aso, type, proto) int dom; struct socket **aso; @@ -79,9 +80,8 @@ socreate(dom, aso, type, proto) if (p->p_ucred->cr_uid == 0) so->so_state = SS_PRIV; so->so_proto = prp; - error = - (*prp->pr_usrreq)(so, PRU_ATTACH, - (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0); + error = (*prp->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0, + (struct mbuf *)(long)proto, (struct mbuf *)0); if (error) { so->so_state |= SS_NOFDREF; sofree(so); @@ -91,6 +91,7 @@ socreate(dom, aso, type, proto) return (0); } +int sobind(so, nam) struct socket *so; struct mbuf *nam; @@ -105,6 +106,7 @@ sobind(so, nam) return (error); } +int solisten(so, backlog) register struct socket *so; int backlog; @@ -127,6 +129,7 @@ solisten(so, backlog) return (0); } +int sofree(so) register struct socket *so; { @@ -148,6 +151,7 @@ sofree(so) * Initiate disconnect if connected. * Free socket when disconnect complete. */ +int soclose(so) register struct socket *so; { @@ -174,7 +178,7 @@ soclose(so) goto drop; while (so->so_state & SS_ISCONNECTED) if (error = tsleep((caddr_t)&so->so_timeo, - PSOCK | PCATCH, netcls, so->so_linger)) + PSOCK | PCATCH, netcls, so->so_linger * hz)) break; } } @@ -198,6 +202,7 @@ discard: /* * Must be called at splnet... */ +int soabort(so) struct socket *so; { @@ -207,6 +212,7 @@ soabort(so) (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); } +int soaccept(so, nam) register struct socket *so; struct mbuf *nam; @@ -223,6 +229,7 @@ soaccept(so, nam) return (error); } +int soconnect(so, nam) register struct socket *so; struct mbuf *nam; @@ -250,6 +257,7 @@ soconnect(so, nam) return (error); } +int soconnect2(so1, so2) register struct socket *so1; struct socket *so2; @@ -263,6 +271,7 @@ soconnect2(so1, so2) return (error); } +int sodisconnect(so) register struct socket *so; { @@ -302,6 +311,7 @@ bad: * must check for short counts if EINTR/ERESTART are returned. * Data and control buffers are freed on return. */ +int sosend(so, addr, uio, top, control, flags) register struct socket *so; struct mbuf *addr; @@ -477,6 +487,7 @@ out: * an mbuf **mp0 for use in returning the chain. The uio is then used * only for the count in uio_resid. */ +int soreceive(so, paddr, uio, mp0, controlp, flagsp) register struct socket *so; struct mbuf **paddr; @@ -503,8 +514,8 @@ soreceive(so, paddr, uio, mp0, controlp, flagsp) flags = 0; if (flags & MSG_OOB) { m = m_get(M_WAIT, MT_DATA); - error = (*pr->pr_usrreq)(so, PRU_RCVOOB, - m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0); + error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m, + (struct mbuf *)(long)(flags & MSG_PEEK), (struct mbuf *)0); if (error) goto bad; do { @@ -534,8 +545,8 @@ restart: * (subject to any timeout) if: * 1. the current count is less than the low water mark, or * 2. MSG_WAITALL is set, and it is possible to do the entire - * receive operation at once if we block (resid <= hiwat). - * 3. MSG_DONTWAIT is not set + * receive operation at once if we block (resid <= hiwat), or + * 3. MSG_DONTWAIT is not set. * If MSG_WAITALL is set but resid is larger than the receive buffer, * we have to do the receive in sections, and thus risk returning * a short count if a timeout or signal occurs after we start. @@ -757,7 +768,7 @@ dontblock: so->so_rcv.sb_mb = nextrecord; if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, - (struct mbuf *)flags, (struct mbuf *)0, + (struct mbuf *)(long)flags, (struct mbuf *)0, (struct mbuf *)0); } if (orig_resid == uio->uio_resid && orig_resid && @@ -775,6 +786,7 @@ release: return (error); } +int soshutdown(so, how) register struct socket *so; register int how; @@ -790,6 +802,7 @@ soshutdown(so, how) return (0); } +void sorflush(so) register struct socket *so; { @@ -811,6 +824,7 @@ sorflush(so) sbrelease(&asb); } +int sosetopt(so, level, optname, m0) register struct socket *so; int level, optname; @@ -893,7 +907,7 @@ sosetopt(so, level, optname, m0) goto bad; } tv = mtod(m, struct timeval *); - if (tv->tv_sec > SHRT_MAX / hz - hz) { + if (tv->tv_sec * hz + tv->tv_usec / tick > SHRT_MAX) { error = EDOM; goto bad; } @@ -927,6 +941,7 @@ bad: return (error); } +int sogetopt(so, level, optname, mp) register struct socket *so; int level, optname; @@ -998,7 +1013,7 @@ sogetopt(so, level, optname, mp) m->m_len = sizeof(struct timeval); mtod(m, struct timeval *)->tv_sec = val / hz; mtod(m, struct timeval *)->tv_usec = - (val % hz) / tick; + (val % hz) * tick; break; } @@ -1011,6 +1026,7 @@ sogetopt(so, level, optname, mp) } } +void sohasoutofband(so) register struct socket *so; { diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index d4af592..865108a 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93 + * @(#)uipc_socket2.c 8.2 (Berkeley) 2/14/95 */ #include @@ -85,6 +85,7 @@ u_long sb_max = SB_MAX; /* patchable */ * cause software-interrupt process scheduling. */ +void soisconnecting(so) register struct socket *so; { @@ -93,6 +94,7 @@ soisconnecting(so) so->so_state |= SS_ISCONNECTING; } +void soisconnected(so) register struct socket *so; { @@ -111,6 +113,7 @@ soisconnected(so) } } +void soisdisconnecting(so) register struct socket *so; { @@ -122,6 +125,7 @@ soisdisconnecting(so) sorwakeup(so); } +void soisdisconnected(so) register struct socket *so; { @@ -181,6 +185,7 @@ sonewconn1(head, connstatus) return (so); } +void soqinsque(head, so, q) register struct socket *head, *so; int q; @@ -202,6 +207,7 @@ soqinsque(head, so, q) *prev = so; } +int soqremque(so, q) register struct socket *so; int q; @@ -240,6 +246,7 @@ soqremque(so, q) * Data queued for reading in the socket may yet be read. */ +void socantsendmore(so) struct socket *so; { @@ -248,6 +255,7 @@ socantsendmore(so) sowwakeup(so); } +void socantrcvmore(so) struct socket *so; { @@ -259,6 +267,7 @@ socantrcvmore(so) /* * Wait for data to arrive at/drain from a socket buffer. */ +int sbwait(sb) struct sockbuf *sb; { @@ -273,6 +282,7 @@ sbwait(sb) * Lock a sockbuf already known to be locked; * return any error returned from sleep (EINTR). */ +int sb_lock(sb) register struct sockbuf *sb; { @@ -294,6 +304,7 @@ sb_lock(sb) * Do asynchronous notification via SIGIO * if the socket has the SS_ASYNC flag set. */ +void sowakeup(so, sb) register struct socket *so; register struct sockbuf *sb; @@ -346,6 +357,7 @@ sowakeup(so, sb) * should be released by calling sbrelease() when the socket is destroyed. */ +int soreserve(so, sndcc, rcvcc) register struct socket *so; u_long sndcc, rcvcc; @@ -373,6 +385,7 @@ bad: * Attempt to scale mbmax so that mbcnt doesn't become limiting * if buffering efficiency is near the normal case. */ +int sbreserve(sb, cc) struct sockbuf *sb; u_long cc; @@ -390,6 +403,7 @@ sbreserve(sb, cc) /* * Free mbufs held by a socket, and reserved mbuf space. */ +void sbrelease(sb) struct sockbuf *sb; { @@ -429,6 +443,7 @@ sbrelease(sb) * the mbuf chain is recorded in sb. Empty mbufs are * discarded and mbufs are compacted where possible. */ +void sbappend(sb, m) struct sockbuf *sb; struct mbuf *m; @@ -451,6 +466,7 @@ sbappend(sb, m) } #ifdef SOCKBUF_DEBUG +void sbcheck(sb) register struct sockbuf *sb; { @@ -477,6 +493,7 @@ sbcheck(sb) * As above, except the mbuf chain * begins a new record. */ +void sbappendrecord(sb, m0) register struct sockbuf *sb; register struct mbuf *m0; @@ -511,6 +528,7 @@ sbappendrecord(sb, m0) * is inserted at the beginning of the sockbuf, * but after any other OOB data. */ +void sbinsertoob(sb, m0) register struct sockbuf *sb; register struct mbuf *m0; @@ -555,6 +573,7 @@ sbinsertoob(sb, m0) * m0 must include a packet header with total length. * Returns 0 if no space in sockbuf or insufficient mbufs. */ +int sbappendaddr(sb, asa, m0, control) register struct sockbuf *sb; struct sockaddr *asa; @@ -597,9 +616,10 @@ panic("sbappendaddr"); return (1); } +int sbappendcontrol(sb, m0, control) struct sockbuf *sb; - struct mbuf *control, *m0; + struct mbuf *m0, *control; { register struct mbuf *m, *n; int space = 0; @@ -633,6 +653,7 @@ sbappendcontrol(sb, m0, control) * buffer sb following mbuf n. If n * is null, the buffer is presumed empty. */ +void sbcompress(sb, m, n) register struct sockbuf *sb; register struct mbuf *m, *n; @@ -681,6 +702,7 @@ sbcompress(sb, m, n) * Free all mbufs in a sockbuf. * Check that all resources are reclaimed. */ +void sbflush(sb) register struct sockbuf *sb; { @@ -696,6 +718,7 @@ sbflush(sb) /* * Drop data from (the front of) a sockbuf. */ +void sbdrop(sb, len) register struct sockbuf *sb; register int len; @@ -739,6 +762,7 @@ sbdrop(sb, len) * Drop a record off the front of a sockbuf * and move the next record to the front. */ +void sbdroprecord(sb) register struct sockbuf *sb; { diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 89b7ffd..800434c 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -30,10 +30,11 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 + * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95 */ #include +#include #include #include #include @@ -47,6 +48,9 @@ #include #endif +#include +#include + /* * System call interface to the socket abstraction. */ @@ -56,15 +60,15 @@ extern struct fileops socketops; -struct socket_args { - int domain; - int type; - int protocol; -}; +int socket(p, uap, retval) struct proc *p; - register struct socket_args *uap; - int *retval; + register struct socket_args /* { + syscallarg(int) domain; + syscallarg(int) type; + syscallarg(int) protocol; + } */ *uap; + register_t *retval; { struct filedesc *fdp = p->p_fd; struct socket *so; @@ -76,7 +80,8 @@ socket(p, uap, retval) fp->f_flag = FREAD|FWRITE; fp->f_type = DTYPE_SOCKET; fp->f_ops = &socketops; - if (error = socreate(uap->domain, &so, uap->type, uap->protocol)) { + if (error = socreate(SCARG(uap, domain), &so, SCARG(uap, type), + SCARG(uap, protocol))) { fdp->fd_ofiles[fd] = 0; ffree(fp); } else { @@ -86,96 +91,102 @@ socket(p, uap, retval) return (error); } -struct bind_args { - int s; - caddr_t name; - int namelen; -}; /* ARGSUSED */ +int bind(p, uap, retval) struct proc *p; - register struct bind_args *uap; - int *retval; + register struct bind_args /* { + syscallarg(int) s; + syscallarg(caddr_t) name; + syscallarg(int) namelen; + } */ *uap; + register_t *retval; { struct file *fp; struct mbuf *nam; int error; - if (error = getsock(p->p_fd, uap->s, &fp)) + if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) return (error); - if (error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME)) + if (error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), + MT_SONAME)) return (error); error = sobind((struct socket *)fp->f_data, nam); m_freem(nam); return (error); } -struct listen_args { - int s; - int backlog; -}; /* ARGSUSED */ +int listen(p, uap, retval) struct proc *p; - register struct listen_args *uap; - int *retval; + register struct listen_args /* { + syscallarg(int) s; + syscallarg(int) backlog; + } */ *uap; + register_t *retval; { struct file *fp; int error; - if (error = getsock(p->p_fd, uap->s, &fp)) + if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) return (error); - return (solisten((struct socket *)fp->f_data, uap->backlog)); + return (solisten((struct socket *)fp->f_data, SCARG(uap, backlog))); } -struct accept_args { - int s; - caddr_t name; - int *anamelen; -#ifdef COMPAT_OLDSOCK - int compat_43; /* pseudo */ -#endif -}; - #ifdef COMPAT_OLDSOCK +int accept(p, uap, retval) struct proc *p; - struct accept_args *uap; - int *retval; + struct accept_args /* { + syscallarg(int) s; + syscallarg(caddr_t) name; + syscallarg(int *) anamelen; + } */ *uap; + register_t *retval; { - uap->compat_43 = 0; - return (accept1(p, uap, retval)); + return (accept1(p, uap, retval, 0)); } -oaccept(p, uap, retval) +int +compat_43_accept(p, uap, retval) struct proc *p; - struct accept_args *uap; - int *retval; + struct accept_args /* { + syscallarg(int) s; + syscallarg(caddr_t) name; + syscallarg(int *) anamelen; + } */ *uap; + register_t *retval; { - uap->compat_43 = 1; - return (accept1(p, uap, retval)); + return (accept1(p, uap, retval, 1)); } #else /* COMPAT_OLDSOCK */ #define accept1 accept #endif -accept1(p, uap, retval) +int +accept1(p, uap, retval, compat_43) struct proc *p; - register struct accept_args *uap; - int *retval; + register struct accept_args /* { + syscallarg(int) s; + syscallarg(caddr_t) name; + syscallarg(int *) anamelen; + } */ *uap; + register_t *retval; + int compat_43; { struct file *fp; struct mbuf *nam; - int namelen, error, s; + int namelen, error, s, tmpfd; register struct socket *so; - if (uap->name && (error = copyin((caddr_t)uap->anamelen, + if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen), (caddr_t)&namelen, sizeof (namelen)))) return (error); - if (error = getsock(p->p_fd, uap->s, &fp)) + if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) return (error); s = splnet(); so = (struct socket *)fp->f_data; @@ -204,10 +215,11 @@ accept1(p, uap, retval) splx(s); return (error); } - if (error = falloc(p, &fp, retval)) { + if (error = falloc(p, &fp, &tmpfd)) { splx(s); return (error); } + *retval = tmpfd; { struct socket *aso = so->so_q; if (soqremque(aso, 1) == 0) panic("accept"); @@ -219,47 +231,49 @@ accept1(p, uap, retval) fp->f_data = (caddr_t)so; nam = m_get(M_WAIT, MT_SONAME); (void) soaccept(so, nam); - if (uap->name) { + if (SCARG(uap, name)) { #ifdef COMPAT_OLDSOCK - if (uap->compat_43) + if (compat_43) mtod(nam, struct osockaddr *)->sa_family = mtod(nam, struct sockaddr *)->sa_family; #endif if (namelen > nam->m_len) namelen = nam->m_len; /* SHOULD COPY OUT A CHAIN HERE */ - if ((error = copyout(mtod(nam, caddr_t), (caddr_t)uap->name, - (u_int)namelen)) == 0) + if ((error = copyout(mtod(nam, caddr_t), + (caddr_t)SCARG(uap, name), (u_int)namelen)) == 0) error = copyout((caddr_t)&namelen, - (caddr_t)uap->anamelen, sizeof (*uap->anamelen)); + (caddr_t)SCARG(uap, anamelen), + sizeof (*SCARG(uap, anamelen))); } m_freem(nam); splx(s); return (error); } -struct connect_args { - int s; - caddr_t name; - int namelen; -}; /* ARGSUSED */ +int connect(p, uap, retval) struct proc *p; - register struct connect_args *uap; - int *retval; + register struct connect_args /* { + syscallarg(int) s; + syscallarg(caddr_t) name; + syscallarg(int) namelen; + } */ *uap; + register_t *retval; { struct file *fp; register struct socket *so; struct mbuf *nam; int error, s; - if (error = getsock(p->p_fd, uap->s, &fp)) + if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) return (error); so = (struct socket *)fp->f_data; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) return (EALREADY); - if (error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME)) + if (error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), + MT_SONAME)) return (error); error = soconnect(so, nam); if (error) @@ -286,25 +300,27 @@ bad: return (error); } -struct socketpair_args { - int domain; - int type; - int protocol; - int *rsv; -}; +int socketpair(p, uap, retval) struct proc *p; - register struct socketpair_args *uap; - int retval[]; + register struct socketpair_args /* { + syscallarg(int) domain; + syscallarg(int) type; + syscallarg(int) protocol; + syscallarg(int *) rsv; + } */ *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; struct file *fp1, *fp2; struct socket *so1, *so2; int fd, error, sv[2]; - if (error = socreate(uap->domain, &so1, uap->type, uap->protocol)) + if (error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type), + SCARG(uap, protocol))) return (error); - if (error = socreate(uap->domain, &so2, uap->type, uap->protocol)) + if (error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type), + SCARG(uap, protocol))) goto free1; if (error = falloc(p, &fp1, &fd)) goto free2; @@ -322,14 +338,15 @@ socketpair(p, uap, retval) sv[1] = fd; if (error = soconnect2(so1, so2)) goto free4; - if (uap->type == SOCK_DGRAM) { + if (SCARG(uap, type) == SOCK_DGRAM) { /* * Datagram socket connection is asymmetric. */ if (error = soconnect2(so2, so1)) goto free4; } - error = copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); + error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv), + 2 * sizeof (int)); retval[0] = sv[0]; /* XXX ??? */ retval[1] = sv[1]; /* XXX ??? */ return (error); @@ -346,46 +363,46 @@ free1: return (error); } -struct sendto_args { - int s; - caddr_t buf; - size_t len; - int flags; - caddr_t to; - int tolen; -}; +int sendto(p, uap, retval) struct proc *p; - register struct sendto_args *uap; - int *retval; + register struct sendto_args /* { + syscallarg(int) s; + syscallarg(caddr_t) buf; + syscallarg(size_t) len; + syscallarg(int) flags; + syscallarg(caddr_t) to; + syscallarg(int) tolen; + } */ *uap; + register_t *retval; { struct msghdr msg; struct iovec aiov; - msg.msg_name = uap->to; - msg.msg_namelen = uap->tolen; + msg.msg_name = SCARG(uap, to); + msg.msg_namelen = SCARG(uap, tolen); msg.msg_iov = &aiov; msg.msg_iovlen = 1; msg.msg_control = 0; #ifdef COMPAT_OLDSOCK msg.msg_flags = 0; #endif - aiov.iov_base = uap->buf; - aiov.iov_len = uap->len; - return (sendit(p, uap->s, &msg, uap->flags, retval)); + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, len); + return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); } #ifdef COMPAT_OLDSOCK -struct osend_args { - int s; - caddr_t buf; - int len; - int flags; -}; -osend(p, uap, retval) +int +compat_43_send(p, uap, retval) struct proc *p; - register struct osend_args *uap; - int *retval; + register struct compat_43_send_args /* { + syscallarg(int) s; + syscallarg(caddr_t) buf; + syscallarg(int) len; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { struct msghdr msg; struct iovec aiov; @@ -394,29 +411,30 @@ osend(p, uap, retval) msg.msg_namelen = 0; msg.msg_iov = &aiov; msg.msg_iovlen = 1; - aiov.iov_base = uap->buf; - aiov.iov_len = uap->len; + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, len); msg.msg_control = 0; msg.msg_flags = 0; - return (sendit(p, uap->s, &msg, uap->flags, retval)); + return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); } #define MSG_COMPAT 0x8000 -struct osendmsg_args { - int s; - caddr_t msg; - int flags; -}; -osendmsg(p, uap, retval) +int +compat_43_sendmsg(p, uap, retval) struct proc *p; - register struct osendmsg_args *uap; - int *retval; + register struct compat_43_sendmsg_args /* { + syscallarg(int) s; + syscallarg(caddr_t) msg; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { struct msghdr msg; struct iovec aiov[UIO_SMALLIOV], *iov; int error; - if (error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr))) + if (error = copyin(SCARG(uap, msg), (caddr_t)&msg, + sizeof (struct omsghdr))) return (error); if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) @@ -431,7 +449,7 @@ osendmsg(p, uap, retval) goto done; msg.msg_flags = MSG_COMPAT; msg.msg_iov = iov; - error = sendit(p, uap->s, &msg, uap->flags, retval); + error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); done: if (iov != aiov) FREE(iov, M_IOV); @@ -439,21 +457,21 @@ done: } #endif -struct sendmsg_args { - int s; - caddr_t msg; - int flags; -}; +int sendmsg(p, uap, retval) struct proc *p; - register struct sendmsg_args *uap; - int *retval; + register struct sendmsg_args /* { + syscallarg(int) s; + syscallarg(caddr_t) msg; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { struct msghdr msg; struct iovec aiov[UIO_SMALLIOV], *iov; int error; - if (error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg))) + if (error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof (msg))) return (error); if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) @@ -471,18 +489,20 @@ sendmsg(p, uap, retval) #ifdef COMPAT_OLDSOCK msg.msg_flags = 0; #endif - error = sendit(p, uap->s, &msg, uap->flags, retval); + error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); done: if (iov != aiov) FREE(iov, M_IOV); return (error); } +int sendit(p, s, mp, flags, retsize) register struct proc *p; int s; register struct msghdr *mp; - int flags, *retsize; + int flags; + register_t *retsize; { struct file *fp; struct uio auio; @@ -505,10 +525,9 @@ sendit(p, s, mp, flags, retsize) auio.uio_resid = 0; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { - if (iov->iov_len < 0) - return (EINVAL); - if ((auio.uio_resid += iov->iov_len) < 0) + if (auio.uio_resid + iov->iov_len < auio.uio_resid) return (EINVAL); + auio.uio_resid += iov->iov_len; } if (mp->msg_name) { if (error = sockargs(&to, mp->msg_name, mp->msg_namelen, @@ -579,63 +598,71 @@ bad: return (error); } -struct recvfrom_args { - int s; - caddr_t buf; - size_t len; - int flags; - caddr_t from; - int *fromlenaddr; -}; - #ifdef COMPAT_OLDSOCK -orecvfrom(p, uap, retval) +int +compat_43_recvfrom(p, uap, retval) struct proc *p; - struct recvfrom_args *uap; - int *retval; + struct recvfrom_args /* { + syscallarg(int) s; + syscallarg(caddr_t) buf; + syscallarg(size_t) len; + syscallarg(int) flags; + syscallarg(caddr_t) from; + syscallarg(int *) fromlenaddr; + } */ *uap; + register_t *retval; { - uap->flags |= MSG_COMPAT; + SCARG(uap, flags) |= MSG_COMPAT; return (recvfrom(p, uap, retval)); } #endif +int recvfrom(p, uap, retval) struct proc *p; - register struct recvfrom_args *uap; - int *retval; + register struct recvfrom_args /* { + syscallarg(int) s; + syscallarg(caddr_t) buf; + syscallarg(size_t) len; + syscallarg(int) flags; + syscallarg(caddr_t) from; + syscallarg(int *) fromlenaddr; + } */ *uap; + register_t *retval; { struct msghdr msg; struct iovec aiov; int error; - if (uap->fromlenaddr) { - if (error = copyin((caddr_t)uap->fromlenaddr, + if (SCARG(uap, fromlenaddr)) { + if (error = copyin((caddr_t)SCARG(uap, fromlenaddr), (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen))) return (error); } else msg.msg_namelen = 0; - msg.msg_name = uap->from; + msg.msg_name = SCARG(uap, from); msg.msg_iov = &aiov; msg.msg_iovlen = 1; - aiov.iov_base = uap->buf; - aiov.iov_len = uap->len; + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, len); msg.msg_control = 0; - msg.msg_flags = uap->flags; - return (recvit(p, uap->s, &msg, (caddr_t)uap->fromlenaddr, retval)); + msg.msg_flags = SCARG(uap, flags); + return (recvit(p, SCARG(uap, s), &msg, + (caddr_t)SCARG(uap, fromlenaddr), retval)); } #ifdef COMPAT_OLDSOCK -struct orecv_args { - int s; - caddr_t buf; - int len; - int flags; -}; -orecv(p, uap, retval) +int +compat_43_recv(p, uap, retval) struct proc *p; - register struct orecv_args *uap; - int *retval; + register struct compat_43_recv_args /* { + syscallarg(int) s; + syscallarg(caddr_t) buf; + syscallarg(int) len; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { struct msghdr msg; struct iovec aiov; @@ -644,11 +671,11 @@ orecv(p, uap, retval) msg.msg_namelen = 0; msg.msg_iov = &aiov; msg.msg_iovlen = 1; - aiov.iov_base = uap->buf; - aiov.iov_len = uap->len; + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, len); msg.msg_control = 0; - msg.msg_flags = uap->flags; - return (recvit(p, uap->s, &msg, (caddr_t)0, retval)); + msg.msg_flags = SCARG(uap, flags); + return (recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)); } /* @@ -656,21 +683,21 @@ orecv(p, uap, retval) * overlays the new one, missing only the flags, and with the (old) access * rights where the control fields are now. */ -struct orecvmsg_args { - int s; - struct omsghdr *msg; - int flags; -}; -orecvmsg(p, uap, retval) +int +compat_43_recvmsg(p, uap, retval) struct proc *p; - register struct orecvmsg_args *uap; - int *retval; + register struct compat_43_recvmsg_args /* { + syscallarg(int) s; + syscallarg(struct omsghdr *) msg; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { struct msghdr msg; struct iovec aiov[UIO_SMALLIOV], *iov; int error; - if (error = copyin((caddr_t)uap->msg, (caddr_t)&msg, + if (error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg, sizeof (struct omsghdr))) return (error); if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { @@ -681,16 +708,17 @@ orecvmsg(p, uap, retval) M_WAITOK); } else iov = aiov; - msg.msg_flags = uap->flags | MSG_COMPAT; + msg.msg_flags = SCARG(uap, flags) | MSG_COMPAT; if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))) goto done; msg.msg_iov = iov; - error = recvit(p, uap->s, &msg, (caddr_t)&uap->msg->msg_namelen, retval); + error = recvit(p, SCARG(uap, s), &msg, + (caddr_t)&SCARG(uap, msg)->msg_namelen, retval); if (msg.msg_controllen && error == 0) error = copyout((caddr_t)&msg.msg_controllen, - (caddr_t)&uap->msg->msg_accrightslen, sizeof (int)); + (caddr_t)&SCARG(uap, msg)->msg_accrightslen, sizeof (int)); done: if (iov != aiov) FREE(iov, M_IOV); @@ -698,21 +726,22 @@ done: } #endif -struct recvmsg_args { - int s; - struct msghdr *msg; - int flags; -}; +int recvmsg(p, uap, retval) struct proc *p; - register struct recvmsg_args *uap; - int *retval; + register struct recvmsg_args /* { + syscallarg(int) s; + syscallarg(struct msghdr *) msg; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { struct msghdr msg; struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; register int error; - if (error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg))) + if (error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg, + sizeof (msg))) return (error); if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) @@ -723,18 +752,19 @@ recvmsg(p, uap, retval) } else iov = aiov; #ifdef COMPAT_OLDSOCK - msg.msg_flags = uap->flags &~ MSG_COMPAT; + msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT; #else - msg.msg_flags = uap->flags; + msg.msg_flags = SCARG(uap, flags); #endif uiov = msg.msg_iov; msg.msg_iov = iov; if (error = copyin((caddr_t)uiov, (caddr_t)iov, (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))) goto done; - if ((error = recvit(p, uap->s, &msg, (caddr_t)0, retval)) == 0) { + if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) { msg.msg_iov = uiov; - error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg)); + error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg), + sizeof(msg)); } done: if (iov != aiov) @@ -742,12 +772,13 @@ done: return (error); } +int recvit(p, s, mp, namelenp, retsize) register struct proc *p; int s; register struct msghdr *mp; caddr_t namelenp; - int *retsize; + register_t *retsize; { struct file *fp; struct uio auio; @@ -770,10 +801,9 @@ recvit(p, s, mp, namelenp, retsize) auio.uio_resid = 0; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { - if (iov->iov_len < 0) - return (EINVAL); - if ((auio.uio_resid += iov->iov_len) < 0) + if (auio.uio_resid + iov->iov_len < auio.uio_resid) return (EINVAL); + auio.uio_resid += iov->iov_len; } #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO)) { @@ -872,107 +902,107 @@ out: return (error); } -struct shutdown_args { - int s; - int how; -}; /* ARGSUSED */ +int shutdown(p, uap, retval) struct proc *p; - register struct shutdown_args *uap; - int *retval; + register struct shutdown_args /* { + syscallarg(int) s; + syscallarg(int) how; + } */ *uap; + register_t *retval; { struct file *fp; int error; - if (error = getsock(p->p_fd, uap->s, &fp)) + if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) return (error); - return (soshutdown((struct socket *)fp->f_data, uap->how)); + return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how))); } -struct setsockopt_args { - int s; - int level; - int name; - caddr_t val; - int valsize; -}; /* ARGSUSED */ +int setsockopt(p, uap, retval) struct proc *p; - register struct setsockopt_args *uap; - int *retval; + register struct setsockopt_args /* { + syscallarg(int) s; + syscallarg(int) level; + syscallarg(int) name; + syscallarg(caddr_t) val; + syscallarg(int) valsize; + } */ *uap; + register_t *retval; { struct file *fp; struct mbuf *m = NULL; int error; - if (error = getsock(p->p_fd, uap->s, &fp)) + if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) return (error); - if (uap->valsize > MLEN) + if (SCARG(uap, valsize) > MLEN) return (EINVAL); - if (uap->val) { + if (SCARG(uap, val)) { m = m_get(M_WAIT, MT_SOOPTS); if (m == NULL) return (ENOBUFS); - if (error = copyin(uap->val, mtod(m, caddr_t), - (u_int)uap->valsize)) { + if (error = copyin(SCARG(uap, val), mtod(m, caddr_t), + (u_int)SCARG(uap, valsize))) { (void) m_free(m); return (error); } - m->m_len = uap->valsize; + m->m_len = SCARG(uap, valsize); } - return (sosetopt((struct socket *)fp->f_data, uap->level, - uap->name, m)); + return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level), + SCARG(uap, name), m)); } -struct getsockopt_args { - int s; - int level; - int name; - caddr_t val; - int *avalsize; -}; /* ARGSUSED */ +int getsockopt(p, uap, retval) struct proc *p; - register struct getsockopt_args *uap; - int *retval; + register struct getsockopt_args /* { + syscallarg(int) s; + syscallarg(int) level; + syscallarg(int) name; + syscallarg(caddr_t) val; + syscallarg(int *) avalsize; + } */ *uap; + register_t *retval; { struct file *fp; struct mbuf *m = NULL; int valsize, error; - if (error = getsock(p->p_fd, uap->s, &fp)) + if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) return (error); - if (uap->val) { - if (error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, - sizeof (valsize))) + if (SCARG(uap, val)) { + if (error = copyin((caddr_t)SCARG(uap, avalsize), + (caddr_t)&valsize, sizeof (valsize))) return (error); } else valsize = 0; - if ((error = sogetopt((struct socket *)fp->f_data, uap->level, - uap->name, &m)) == 0 && uap->val && valsize && m != NULL) { + if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level), + SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize && + m != NULL) { if (valsize > m->m_len) valsize = m->m_len; - error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); + error = copyout(mtod(m, caddr_t), SCARG(uap, val), + (u_int)valsize); if (error == 0) error = copyout((caddr_t)&valsize, - (caddr_t)uap->avalsize, sizeof (valsize)); + (caddr_t)SCARG(uap, avalsize), sizeof (valsize)); } if (m != NULL) (void) m_free(m); return (error); } -struct pipe_args { - int dummy; -}; /* ARGSUSED */ +int pipe(p, uap, retval) struct proc *p; - struct pipe_args *uap; - int retval[]; + void *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; struct file *rf, *wf; @@ -1016,33 +1046,33 @@ free1: /* * Get socket name. */ -struct getsockname_args { - int fdes; - caddr_t asa; - int *alen; -#ifdef COMPAT_OLDSOCK - int compat_43; /* pseudo */ -#endif -}; #ifdef COMPAT_OLDSOCK +int getsockname(p, uap, retval) struct proc *p; - struct getsockname_args *uap; - int *retval; + struct getsockname_args /* { + syscallarg(int) fdes; + syscallarg(caddr_t) asa; + syscallarg(int *) alen; + } */ *uap; + register_t *retval; { - uap->compat_43 = 0; - return (getsockname1(p, uap, retval)); + return (getsockname1(p, uap, retval, 0)); } -ogetsockname(p, uap, retval) +int +compat_43_getsockname(p, uap, retval) struct proc *p; - struct getsockname_args *uap; - int *retval; + struct getsockname_args /* { + syscallarg(int) fdes; + syscallarg(caddr_t) asa; + syscallarg(int *) alen; + } */ *uap; + register_t *retval; { - uap->compat_43 = 1; - return (getsockname1(p, uap, retval)); + return (getsockname1(p, uap, retval, 1)); } #else /* COMPAT_OLDSOCK */ @@ -1050,19 +1080,26 @@ ogetsockname(p, uap, retval) #endif /* ARGSUSED */ -getsockname1(p, uap, retval) +int +getsockname1(p, uap, retval, compat_43) struct proc *p; - register struct getsockname_args *uap; - int *retval; + register struct getsockname_args /* { + syscallarg(int) fdes; + syscallarg(caddr_t) asa; + syscallarg(int *) alen; + } */ *uap; + register_t *retval; + int compat_43; { struct file *fp; register struct socket *so; struct mbuf *m; int len, error; - if (error = getsock(p->p_fd, uap->fdes, &fp)) + if (error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) return (error); - if (error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len))) + if (error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, + sizeof (len))) return (error); so = (struct socket *)fp->f_data; m = m_getclr(M_WAIT, MT_SONAME); @@ -1073,13 +1110,13 @@ getsockname1(p, uap, retval) if (len > m->m_len) len = m->m_len; #ifdef COMPAT_OLDSOCK - if (uap->compat_43) + if (compat_43) mtod(m, struct osockaddr *)->sa_family = mtod(m, struct sockaddr *)->sa_family; #endif - error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); + error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len); if (error == 0) - error = copyout((caddr_t)&len, (caddr_t)uap->alen, + error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof (len)); bad: m_freem(m); @@ -1089,34 +1126,33 @@ bad: /* * Get name of peer for connected socket. */ -struct getpeername_args { - int fdes; - caddr_t asa; - int *alen; -#ifdef COMPAT_OLDSOCK - int compat_43; /* pseudo */ -#endif -}; - #ifdef COMPAT_OLDSOCK +int getpeername(p, uap, retval) struct proc *p; - struct getpeername_args *uap; - int *retval; + struct getpeername_args /* { + syscallarg(int) fdes; + syscallarg(caddr_t) asa; + syscallarg(int *) alen; + } */ *uap; + register_t *retval; { - uap->compat_43 = 0; - return (getpeername1(p, uap, retval)); + return (getpeername1(p, uap, retval, 0)); } -ogetpeername(p, uap, retval) +int +compat_43_getpeername(p, uap, retval) struct proc *p; - struct getpeername_args *uap; - int *retval; + struct getpeername_args /* { + syscallarg(int) fdes; + syscallarg(caddr_t) asa; + syscallarg(int *) alen; + } */ *uap; + register_t *retval; { - uap->compat_43 = 1; - return (getpeername1(p, uap, retval)); + return (getpeername1(p, uap, retval, 1)); } #else /* COMPAT_OLDSOCK */ @@ -1124,22 +1160,29 @@ ogetpeername(p, uap, retval) #endif /* ARGSUSED */ -getpeername1(p, uap, retval) +int +getpeername1(p, uap, retval, compat_43) struct proc *p; - register struct getpeername_args *uap; - int *retval; + register struct getpeername_args /* { + syscallarg(int) fdes; + syscallarg(caddr_t) asa; + syscallarg(int *) alen; + } */ *uap; + register_t *retval; + int compat_43; { struct file *fp; register struct socket *so; struct mbuf *m; int len, error; - if (error = getsock(p->p_fd, uap->fdes, &fp)) + if (error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) return (error); so = (struct socket *)fp->f_data; if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) return (ENOTCONN); - if (error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len))) + if (error = + copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len))) return (error); m = m_getclr(M_WAIT, MT_SONAME); if (m == NULL) @@ -1149,18 +1192,20 @@ getpeername1(p, uap, retval) if (len > m->m_len) len = m->m_len; #ifdef COMPAT_OLDSOCK - if (uap->compat_43) + if (compat_43) mtod(m, struct osockaddr *)->sa_family = mtod(m, struct sockaddr *)->sa_family; #endif - if (error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len)) + if (error = + copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len)) goto bad; - error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); + error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof (len)); bad: m_freem(m); return (error); } +int sockargs(mp, buf, buflen, type) struct mbuf **mp; caddr_t buf; @@ -1183,23 +1228,24 @@ sockargs(mp, buf, buflen, type) return (ENOBUFS); m->m_len = buflen; error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); - if (error) + if (error) { (void) m_free(m); - else { - *mp = m; - if (type == MT_SONAME) { - sa = mtod(m, struct sockaddr *); + return (error); + } + *mp = m; + if (type == MT_SONAME) { + sa = mtod(m, struct sockaddr *); #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN - if (sa->sa_family == 0 && sa->sa_len < AF_MAX) - sa->sa_family = sa->sa_len; + if (sa->sa_family == 0 && sa->sa_len < AF_MAX) + sa->sa_family = sa->sa_len; #endif - sa->sa_len = buflen; - } + sa->sa_len = buflen; } - return (error); + return (0); } +int getsock(fdp, fdes, fpp) struct filedesc *fdp; int fdes; diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 94bf8f7..c6bcbfd 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 + * @(#)uipc_usrreq.c 8.9 (Berkeley) 5/14/95 */ #include @@ -61,6 +61,7 @@ struct sockaddr sun_noname = { sizeof(sun_noname), AF_UNIX }; ino_t unp_ino; /* prototype for fake inode numbers */ /*ARGSUSED*/ +int uipc_usrreq(so, req, m, nam, control) struct socket *so; int req; @@ -313,6 +314,7 @@ u_long unpdg_recvspace = 4*1024; int unp_rights; /* file descriptors in flight */ +int unp_attach(so) struct socket *so; { @@ -346,6 +348,7 @@ unp_attach(so) return (0); } +void unp_detach(unp) register struct unpcb *unp; { @@ -376,6 +379,7 @@ unp_detach(unp) } } +int unp_bind(unp, nam, p) struct unpcb *unp; struct mbuf *nam; @@ -388,7 +392,7 @@ unp_bind(unp, nam, p) struct nameidata nd; NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_SYSSPACE, - soun->sun_path, p); + soun->sun_path, p); if (unp->unp_vnode != NULL) return (EINVAL); if (nam->m_len == MLEN) { @@ -412,17 +416,18 @@ unp_bind(unp, nam, p) VATTR_NULL(&vattr); vattr.va_type = VSOCK; vattr.va_mode = ACCESSPERMS; - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); if (error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)) return (error); vp = nd.ni_vp; vp->v_socket = unp->unp_socket; unp->unp_vnode = vp; unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL); - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (0); } +int unp_connect(so, nam, p) struct socket *so; struct mbuf *nam; @@ -478,6 +483,7 @@ bad: return (error); } +int unp_connect2(so, so2) register struct socket *so; register struct socket *so2; @@ -509,6 +515,7 @@ unp_connect2(so, so2) return (0); } +void unp_disconnect(unp) struct unpcb *unp; { @@ -546,6 +553,7 @@ unp_disconnect(unp) } #ifdef notdef +void unp_abort(unp) struct unpcb *unp; { @@ -554,6 +562,7 @@ unp_abort(unp) } #endif +void unp_shutdown(unp) struct unpcb *unp; { @@ -564,6 +573,7 @@ unp_shutdown(unp) socantrcvmore(so); } +void unp_drop(unp, errno) struct unpcb *unp; int errno; @@ -587,6 +597,7 @@ unp_drain() } #endif +int unp_externalize(rights) struct mbuf *rights; { @@ -618,6 +629,7 @@ unp_externalize(rights) return (0); } +int unp_internalize(control, p) struct mbuf *control; struct proc *p; @@ -652,9 +664,9 @@ unp_internalize(control, p) } int unp_defer, unp_gcing; -int unp_mark(); extern struct domain unixdomain; +void unp_gc() { register struct file *fp, *nextfp; @@ -666,10 +678,10 @@ unp_gc() return; unp_gcing = 1; unp_defer = 0; - for (fp = filehead; fp; fp = fp->f_filef) + for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) fp->f_flag &= ~(FMARK|FDEFER); do { - for (fp = filehead; fp; fp = fp->f_filef) { + for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) { if (fp->f_count == 0) continue; if (fp->f_flag & FDEFER) { @@ -747,8 +759,9 @@ unp_gc() * 91/09/19, bsy@cs.cmu.edu */ extra_ref = malloc(nfiles * sizeof(struct file *), M_FILE, M_WAITOK); - for (nunref = 0, fp = filehead, fpp = extra_ref; fp; fp = nextfp) { - nextfp = fp->f_filef; + for (nunref = 0, fp = filehead.lh_first, fpp = extra_ref; fp != 0; + fp = nextfp) { + nextfp = fp->f_list.le_next; if (fp->f_count == 0) continue; if (fp->f_count == fp->f_msgcount && !(fp->f_flag & FMARK)) { @@ -760,23 +773,24 @@ unp_gc() for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) sorflush((struct socket *)(*fpp)->f_data); for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) - closef(*fpp); + closef(*fpp, (struct proc *)NULL); free((caddr_t)extra_ref, M_FILE); unp_gcing = 0; } +void unp_dispose(m) struct mbuf *m; { - int unp_discard(); if (m) unp_scan(m, unp_discard); } +void unp_scan(m0, op) register struct mbuf *m0; - int (*op)(); + void (*op) __P((struct file *)); { register struct mbuf *m; register struct file **rp; @@ -803,6 +817,7 @@ unp_scan(m0, op) } } +void unp_mark(fp) struct file *fp; { @@ -813,6 +828,7 @@ unp_mark(fp) fp->f_flag |= (FMARK|FDEFER); } +void unp_discard(fp) struct file *fp; { diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 4ccfd72..c20966b 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -1,7 +1,10 @@ /* - * Copyright (c) 1989, 1993 + * Copyright (c) 1989, 1993, 1995 * The Regents of the University of California. All rights reserved. * + * This code is derived from software contributed to Berkeley by + * Poul-Henning Kamp of the FreeBSD Project. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,7 +33,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)vfs_cache.c 8.1 (Berkeley) 6/10/93 + * from: vfs_cache.c,v 1.11 1995/03/12 02:01:20 phk Exp $ + * + * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95 */ #include @@ -51,6 +56,9 @@ * obtained from (vp, name) where vp refers to the directory * containing name. * + * If it is a "negative" entry, (i.e. for a name that is known NOT to + * exist) the vnode pointer will be NULL. + * * For simplicity (and economy of storage), names longer than * a maximum length of NCHNAMLEN are not cached; they occur * infrequently in any case, and are almost never of interest. @@ -63,266 +71,250 @@ /* * Structures associated with name cacheing. */ -struct namecache **nchashtbl; +#define NCHHASH(dvp, cnp) \ + (&nchashtbl[((dvp)->v_id + (cnp)->cn_hash) & nchash]) +LIST_HEAD(nchashhead, namecache) *nchashtbl; /* Hash Table */ u_long nchash; /* size of hash table - 1 */ long numcache; /* number of cache entries allocated */ -struct namecache *nchhead, **nchtail; /* LRU chain pointers */ +TAILQ_HEAD(, namecache) nclruhead; /* LRU chain */ struct nchstats nchstats; /* cache effectiveness statistics */ int doingcache = 1; /* 1 => enable the cache */ /* - * Look for a the name in the cache. We don't do this - * if the segment name is long, simply so the cache can avoid - * holding long names (which would either waste space, or + * Delete an entry from its hash list and move it to the front + * of the LRU list for immediate reuse. + */ +#define PURGE(ncp) { \ + LIST_REMOVE(ncp, nc_hash); \ + ncp->nc_hash.le_prev = 0; \ + TAILQ_REMOVE(&nclruhead, ncp, nc_lru); \ + TAILQ_INSERT_HEAD(&nclruhead, ncp, nc_lru); \ +} + +/* + * Move an entry that has been used to the tail of the LRU list + * so that it will be preserved for future use. + */ +#define TOUCH(ncp) { \ + if (ncp->nc_lru.tqe_next != 0) { \ + TAILQ_REMOVE(&nclruhead, ncp, nc_lru); \ + TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru); \ + } \ +} + +/* + * Lookup an entry in the cache + * + * We don't do this if the segment name is long, simply so the cache + * can avoid holding long names (which would either waste space, or * add greatly to the complexity). * - * Lookup is called with ni_dvp pointing to the directory to search, - * ni_ptr pointing to the name of the entry being sought, ni_namelen - * tells the length of the name, and ni_hash contains a hash of - * the name. If the lookup succeeds, the vnode is returned in ni_vp - * and a status of -1 is returned. If the lookup determines that - * the name does not exist (negative cacheing), a status of ENOENT - * is returned. If the lookup fails, a status of zero is returned. + * Lookup is called with dvp pointing to the directory to search, + * cnp pointing to the name of the entry being sought. If the lookup + * succeeds, the vnode is returned in *vpp, and a status of -1 is + * returned. If the lookup determines that the name does not exist + * (negative cacheing), a status of ENOENT is returned. If the lookup + * fails, a status of zero is returned. */ + int cache_lookup(dvp, vpp, cnp) struct vnode *dvp; struct vnode **vpp; struct componentname *cnp; { - register struct namecache *ncp, *ncq, **ncpp; + register struct namecache *ncp, *nnp; + register struct nchashhead *ncpp; - if (!doingcache) + if (!doingcache) { + cnp->cn_flags &= ~MAKEENTRY; return (0); + } if (cnp->cn_namelen > NCHNAMLEN) { nchstats.ncs_long++; cnp->cn_flags &= ~MAKEENTRY; return (0); } - ncpp = &nchashtbl[cnp->cn_hash & nchash]; - for (ncp = *ncpp; ncp; ncp = ncp->nc_forw) { + + ncpp = NCHHASH(dvp, cnp); + for (ncp = ncpp->lh_first; ncp != 0; ncp = nnp) { + nnp = ncp->nc_hash.le_next; + /* If one of the vp's went stale, don't bother anymore. */ + if ((ncp->nc_dvpid != ncp->nc_dvp->v_id) || + (ncp->nc_vp && ncp->nc_vpid != ncp->nc_vp->v_id)) { + nchstats.ncs_falsehits++; + PURGE(ncp); + continue; + } + /* Now that we know the vp's to be valid, is it ours ? */ if (ncp->nc_dvp == dvp && - ncp->nc_dvpid == dvp->v_id && ncp->nc_nlen == cnp->cn_namelen && !bcmp(ncp->nc_name, cnp->cn_nameptr, (u_int)ncp->nc_nlen)) break; } - if (ncp == NULL) { + + /* We failed to find an entry */ + if (ncp == 0) { nchstats.ncs_miss++; return (0); } - if (!(cnp->cn_flags & MAKEENTRY)) { + + /* We don't want to have an entry, so dump it */ + if ((cnp->cn_flags & MAKEENTRY) == 0) { nchstats.ncs_badhits++; - } else if (ncp->nc_vp == NULL) { - if (cnp->cn_nameiop != CREATE) { - nchstats.ncs_neghits++; - /* - * Move this slot to end of LRU chain, - * if not already there. - */ - if (ncp->nc_nxt) { - /* remove from LRU chain */ - *ncp->nc_prev = ncp->nc_nxt; - ncp->nc_nxt->nc_prev = ncp->nc_prev; - /* and replace at end of it */ - ncp->nc_nxt = NULL; - ncp->nc_prev = nchtail; - *nchtail = ncp; - nchtail = &ncp->nc_nxt; - } - return (ENOENT); - } - } else if (ncp->nc_vpid != ncp->nc_vp->v_id) { - nchstats.ncs_falsehits++; - } else { + PURGE(ncp); + return (0); + } + + /* We found a "positive" match, return the vnode */ + if (ncp->nc_vp) { nchstats.ncs_goodhits++; - /* - * move this slot to end of LRU chain, if not already there - */ - if (ncp->nc_nxt) { - /* remove from LRU chain */ - *ncp->nc_prev = ncp->nc_nxt; - ncp->nc_nxt->nc_prev = ncp->nc_prev; - /* and replace at end of it */ - ncp->nc_nxt = NULL; - ncp->nc_prev = nchtail; - *nchtail = ncp; - nchtail = &ncp->nc_nxt; - } + TOUCH(ncp); *vpp = ncp->nc_vp; return (-1); } + /* We found a negative match, and want to create it, so purge */ + if (cnp->cn_nameiop == CREATE) { + nchstats.ncs_badhits++; + PURGE(ncp); + return (0); + } + /* - * Last component and we are renaming or deleting, - * the cache entry is invalid, or otherwise don't - * want cache entry to exist. + * We found a "negative" match, ENOENT notifies client of this match. + * The nc_vpid field records whether this is a whiteout. */ - /* remove from LRU chain */ - if (ncq = ncp->nc_nxt) - ncq->nc_prev = ncp->nc_prev; - else - nchtail = ncp->nc_prev; - *ncp->nc_prev = ncq; - /* remove from hash chain */ - if (ncq = ncp->nc_forw) - ncq->nc_back = ncp->nc_back; - *ncp->nc_back = ncq; - /* and make a dummy hash chain */ - ncp->nc_forw = NULL; - ncp->nc_back = NULL; - /* insert at head of LRU list (first to grab) */ - if (ncq = nchhead) - ncq->nc_prev = &ncp->nc_nxt; - else - nchtail = &ncp->nc_nxt; - nchhead = ncp; - ncp->nc_nxt = ncq; - ncp->nc_prev = &nchhead; - return (0); + nchstats.ncs_neghits++; + TOUCH(ncp); + cnp->cn_flags |= ncp->nc_vpid; + return (ENOENT); } /* - * Add an entry to the cache + * Add an entry to the cache. */ +void cache_enter(dvp, vp, cnp) struct vnode *dvp; struct vnode *vp; struct componentname *cnp; { - register struct namecache *ncp, *ncq, **ncpp; + register struct namecache *ncp; + register struct nchashhead *ncpp; + + if (!doingcache) + return; #ifdef DIAGNOSTIC if (cnp->cn_namelen > NCHNAMLEN) panic("cache_enter: name too long"); #endif - if (!doingcache) - return; + /* - * Free the cache slot at head of lru chain. + * We allocate a new entry if we are less than the maximum + * allowed and the one at the front of the LRU list is in use. + * Otherwise we use the one at the front of the LRU list. */ - if (numcache < desiredvnodes) { + if (numcache < desiredvnodes && + ((ncp = nclruhead.tqh_first) == NULL || + ncp->nc_hash.le_prev != 0)) { + /* Add one more entry */ ncp = (struct namecache *) malloc((u_long)sizeof *ncp, M_CACHE, M_WAITOK); bzero((char *)ncp, sizeof *ncp); numcache++; - } else if (ncp = nchhead) { - /* remove from lru chain */ - if (ncq = ncp->nc_nxt) - ncq->nc_prev = ncp->nc_prev; - else - nchtail = ncp->nc_prev; - *ncp->nc_prev = ncq; - /* remove from old hash chain, if on one */ - if (ncp->nc_back) { - if (ncq = ncp->nc_forw) - ncq->nc_back = ncp->nc_back; - *ncp->nc_back = ncq; - ncp->nc_forw = NULL; - ncp->nc_back = NULL; + } else if (ncp = nclruhead.tqh_first) { + /* reuse an old entry */ + TAILQ_REMOVE(&nclruhead, ncp, nc_lru); + if (ncp->nc_hash.le_prev != 0) { + LIST_REMOVE(ncp, nc_hash); + ncp->nc_hash.le_prev = 0; } - } else + } else { + /* give up */ return; - /* grab the vnode we just found */ + } + + /* + * Fill in cache info, if vp is NULL this is a "negative" cache entry. + * For negative entries, we have to record whether it is a whiteout. + * the whiteout flag is stored in the nc_vpid field which is + * otherwise unused. + */ ncp->nc_vp = vp; if (vp) ncp->nc_vpid = vp->v_id; else - ncp->nc_vpid = 0; - /* fill in cache info */ + ncp->nc_vpid = cnp->cn_flags & ISWHITEOUT; ncp->nc_dvp = dvp; ncp->nc_dvpid = dvp->v_id; ncp->nc_nlen = cnp->cn_namelen; bcopy(cnp->cn_nameptr, ncp->nc_name, (unsigned)ncp->nc_nlen); - /* link at end of lru chain */ - ncp->nc_nxt = NULL; - ncp->nc_prev = nchtail; - *nchtail = ncp; - nchtail = &ncp->nc_nxt; - /* and insert on hash chain */ - ncpp = &nchashtbl[cnp->cn_hash & nchash]; - if (ncq = *ncpp) - ncq->nc_back = &ncp->nc_forw; - ncp->nc_forw = ncq; - ncp->nc_back = ncpp; - *ncpp = ncp; + TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru); + ncpp = NCHHASH(dvp, cnp); + LIST_INSERT_HEAD(ncpp, ncp, nc_hash); } /* * Name cache initialization, from vfs_init() when we are booting */ +void nchinit() { - nchtail = &nchhead; + TAILQ_INIT(&nclruhead); nchashtbl = hashinit(desiredvnodes, M_CACHE, &nchash); } /* - * Cache flush, a particular vnode; called when a vnode is renamed to - * hide entries that would now be invalid + * Invalidate a all entries to particular vnode. + * + * We actually just increment the v_id, that will do it. The entries will + * be purged by lookup as they get found. If the v_id wraps around, we + * need to ditch the entire cache, to avoid confusion. No valid vnode will + * ever have (v_id == 0). */ +void cache_purge(vp) struct vnode *vp; { - struct namecache *ncp, **ncpp; + struct namecache *ncp; + struct nchashhead *ncpp; vp->v_id = ++nextvnodeid; if (nextvnodeid != 0) return; for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) { - for (ncp = *ncpp; ncp; ncp = ncp->nc_forw) { - ncp->nc_vpid = 0; - ncp->nc_dvpid = 0; - } + while (ncp = ncpp->lh_first) + PURGE(ncp); } vp->v_id = ++nextvnodeid; } /* - * Cache flush, a whole filesystem; called when filesys is umounted to - * remove entries that would now be invalid + * Flush all entries referencing a particular filesystem. * - * The line "nxtcp = nchhead" near the end is to avoid potential problems - * if the cache lru chain is modified while we are dumping the - * inode. This makes the algorithm O(n^2), but do you think I care? + * Since we need to check it anyway, we will flush all the invalid + * entriess at the same time. */ +void cache_purgevfs(mp) struct mount *mp; { - register struct namecache *ncp, *nxtcp; + struct nchashhead *ncpp; + struct namecache *ncp, *nnp; - for (ncp = nchhead; ncp; ncp = nxtcp) { - if (ncp->nc_dvp == NULL || ncp->nc_dvp->v_mount != mp) { - nxtcp = ncp->nc_nxt; - continue; - } - /* free the resources we had */ - ncp->nc_vp = NULL; - ncp->nc_dvp = NULL; - /* remove from old hash chain, if on one */ - if (ncp->nc_back) { - if (nxtcp = ncp->nc_forw) - nxtcp->nc_back = ncp->nc_back; - *ncp->nc_back = nxtcp; - ncp->nc_forw = NULL; - ncp->nc_back = NULL; + /* Scan hash tables for applicable entries */ + for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) { + for (ncp = ncpp->lh_first; ncp != 0; ncp = nnp) { + nnp = ncp->nc_hash.le_next; + if (ncp->nc_dvpid != ncp->nc_dvp->v_id || + (ncp->nc_vp && ncp->nc_vpid != ncp->nc_vp->v_id) || + ncp->nc_dvp->v_mount == mp) { + PURGE(ncp); + } } - /* delete this entry from LRU chain */ - if (nxtcp = ncp->nc_nxt) - nxtcp->nc_prev = ncp->nc_prev; - else - nchtail = ncp->nc_prev; - *ncp->nc_prev = nxtcp; - /* cause rescan of list, it may have altered */ - /* also put the now-free entry at head of LRU */ - if (nxtcp = nchhead) - nxtcp->nc_prev = &ncp->nc_nxt; - else - nchtail = &ncp->nc_nxt; - nchhead = ncp; - ncp->nc_nxt = nxtcp; - ncp->nc_prev = &nchhead; } } diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index c34fbc3..e01d24f 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)vfs_cluster.c 8.7 (Berkeley) 2/13/94 + * @(#)vfs_cluster.c 8.10 (Berkeley) 3/28/95 */ #include @@ -43,16 +43,6 @@ #include #include -#ifdef DEBUG -#include -#include -int doreallocblks = 1; -struct ctldebug debug13 = { "doreallocblks", &doreallocblks }; -#else -/* XXX for cluster_write */ -#define doreallocblks 1 -#endif - /* * Local declarations */ @@ -135,7 +125,7 @@ cluster_read(vp, filesize, lblkno, size, cred, bpp) trace(TR_BREADHIT, pack(vp, size), lblkno); flags |= B_ASYNC; ioblkno = lblkno + (vp->v_ralen ? vp->v_ralen : 1); - alreadyincore = (int)incore(vp, ioblkno); + alreadyincore = incore(vp, ioblkno) != NULL; bp = NULL; } else { /* Block wasn't in cache, case 3, 4, 5. */ @@ -202,10 +192,12 @@ cluster_read(vp, filesize, lblkno, size, cred, bpp) ioblkno, NULL, &blkno, &num_ra)) || blkno == -1) goto skip_readahead; /* - * Adjust readahead as above + * Adjust readahead as above. + * Don't check alreadyincore, we know it is 0 from + * the previous conditional. */ if (num_ra) { - if (!alreadyincore && ioblkno <= vp->v_maxra) + if (ioblkno <= vp->v_maxra) vp->v_ralen = max(vp->v_ralen >> 1, 1); else if (num_ra > vp->v_ralen && lblkno != vp->v_lastr) @@ -318,17 +310,12 @@ cluster_rbuild(vp, filesize, bp, lbn, blkno, size, run, flags) inc = btodb(size); for (bn = blkno + inc, i = 1; i <= run; ++i, bn += inc) { - if (incore(vp, lbn + i)) { - if (i == 1) { - bp->b_saveaddr = b_save->bs_saveaddr; - bp->b_flags &= ~B_CALL; - bp->b_iodone = NULL; - allocbuf(bp, size); - free(b_save, M_SEGMENT); - } else - allocbuf(bp, size * i); + /* + * A component of the cluster is already in core, + * terminate the cluster early. + */ + if (incore(vp, lbn + i)) break; - } tbp = getblk(vp, lbn + i, 0, 0, 0); /* * getblk may return some memory in the buffer if there were @@ -341,8 +328,18 @@ cluster_rbuild(vp, filesize, bp, lbn, blkno, size, run, flags) if (tbp->b_bufsize != 0) { caddr_t bdata = (char *)tbp->b_data; - if (tbp->b_bufsize + size > MAXBSIZE) - panic("cluster_rbuild: too much memory"); + /* + * No room in the buffer to add another page, + * terminate the cluster early. + */ + if (tbp->b_bufsize + size > MAXBSIZE) { +#ifdef DIAGNOSTIC + if (tbp->b_bufsize != MAXBSIZE) + panic("cluster_rbuild: too much memory"); +#endif + brelse(tbp); + break; + } if (tbp->b_bufsize > size) { /* * XXX if the source and destination regions @@ -364,6 +361,20 @@ cluster_rbuild(vp, filesize, bp, lbn, blkno, size, run, flags) ++b_save->bs_nchildren; b_save->bs_children[i - 1] = tbp; } + /* + * The cluster may have been terminated early, adjust the cluster + * buffer size accordingly. If no cluster could be formed, + * deallocate the cluster save info. + */ + if (i <= run) { + if (i == 1) { + bp->b_saveaddr = b_save->bs_saveaddr; + bp->b_flags &= ~B_CALL; + bp->b_iodone = NULL; + free(b_save, M_SEGMENT); + } + allocbuf(bp, size * i); + } return(bp); } @@ -498,8 +509,7 @@ cluster_write(bp, filesize) * Otherwise try reallocating to make it sequential. */ cursize = vp->v_lastw - vp->v_cstart + 1; - if (!doreallocblks || - (lbn + 1) * bp->b_bcount != filesize || + if ((lbn + 1) * bp->b_bcount != filesize || lbn != vp->v_lastw + 1 || vp->v_clen <= cursize) { cluster_wbuild(vp, NULL, bp->b_bcount, vp->v_cstart, cursize, lbn); diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c index 2fe39eb..9b57797 100644 --- a/sys/kern/vfs_conf.c +++ b/sys/kern/vfs_conf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1989, 1993 + * Copyright (c) 1989, 1993, 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,144 +30,132 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)vfs_conf.c 8.8 (Berkeley) 3/31/94 + * @(#)vfs_conf.c 8.11 (Berkeley) 5/10/95 */ #include #include #include -#ifdef FFS -#include - /* - * This specifies the filesystem used to mount the root. - * This specification should be done by /etc/config. + * These define the root filesystem, device, and root filesystem type. */ -int (*mountroot)() = ffs_mountroot; -#endif +struct mount *rootfs; +struct vnode *rootvnode; +int (*mountroot)() = NULL; /* - * These define the root filesystem and device. + * Set up the initial array of known filesystem types. */ -struct mount *rootfs; -struct vnode *rootvnode; +extern struct vfsops ufs_vfsops; +extern int ffs_mountroot(); +extern struct vfsops lfs_vfsops; +extern int lfs_mountroot(); +extern struct vfsops mfs_vfsops; +extern int mfs_mountroot(); +extern struct vfsops cd9660_vfsops; +extern int cd9660_mountroot(); +extern struct vfsops msdos_vfsops; +extern struct vfsops adosfs_vfsops; +extern struct vfsops nfs_vfsops; +extern int nfs_mountroot(); +extern struct vfsops afs_vfsops; +extern struct vfsops procfs_vfsops; +extern struct vfsops null_vfsops; +extern struct vfsops union_vfsops; +extern struct vfsops umap_vfsops; +extern struct vfsops portal_vfsops; +extern struct vfsops fdesc_vfsops; +extern struct vfsops kernfs_vfsops; /* * Set up the filesystem operations for vnodes. - * The types are defined in mount.h. */ +static struct vfsconf vfsconflist[] = { + + /* Fast Filesystem */ #ifdef FFS -extern struct vfsops ufs_vfsops; -#define UFS_VFSOPS &ufs_vfsops -#else -#define UFS_VFSOPS NULL + { &ufs_vfsops, "ufs", 1, 0, MNT_LOCAL, ffs_mountroot, NULL }, #endif + /* Log-based Filesystem */ #ifdef LFS -extern struct vfsops lfs_vfsops; -#define LFS_VFSOPS &lfs_vfsops -#else -#define LFS_VFSOPS NULL + { &lfs_vfsops, "lfs", 5, 0, MNT_LOCAL, lfs_mountroot, NULL }, #endif + /* Memory-based Filesystem */ #ifdef MFS -extern struct vfsops mfs_vfsops; -#define MFS_VFSOPS &mfs_vfsops -#else -#define MFS_VFSOPS NULL + { &mfs_vfsops, "mfs", 3, 0, MNT_LOCAL, mfs_mountroot, NULL }, #endif -#ifdef NFS -extern struct vfsops nfs_vfsops; -#define NFS_VFSOPS &nfs_vfsops -#else -#define NFS_VFSOPS NULL + /* ISO9660 (aka CDROM) Filesystem */ +#ifdef CD9660 + { &cd9660_vfsops, "cd9660", 14, 0, MNT_LOCAL, cd9660_mountroot, NULL }, #endif -#ifdef FDESC -extern struct vfsops fdesc_vfsops; -#define FDESC_VFSOPS &fdesc_vfsops -#else -#define FDESC_VFSOPS NULL + /* MSDOS Filesystem */ +#ifdef MSDOS + { &msdos_vfsops, "msdos", 4, 0, MNT_LOCAL, NULL, NULL }, #endif -#ifdef PORTAL -extern struct vfsops portal_vfsops; -#define PORTAL_VFSOPS &portal_vfsops -#else -#define PORTAL_VFSOPS NULL + /* AmigaDOS Filesystem */ +#ifdef ADOSFS + { &adosfs_vfsops, "adosfs", 16, 0, MNT_LOCAL, NULL, NULL }, #endif -#ifdef NULLFS -extern struct vfsops null_vfsops; -#define NULL_VFSOPS &null_vfsops -#else -#define NULL_VFSOPS NULL + /* Sun-compatible Network Filesystem */ +#ifdef NFS + { &nfs_vfsops, "nfs", 2, 0, 0, nfs_mountroot, NULL }, #endif -#ifdef UMAPFS -extern struct vfsops umap_vfsops; -#define UMAP_VFSOPS &umap_vfsops -#else -#define UMAP_VFSOPS NULL + /* Andrew Filesystem */ +#ifdef AFS + { &afs_vfsops, "andrewfs", 13, 0, 0, afs_mountroot, NULL }, #endif -#ifdef KERNFS -extern struct vfsops kernfs_vfsops; -#define KERNFS_VFSOPS &kernfs_vfsops -#else -#define KERNFS_VFSOPS NULL + /* /proc Filesystem */ +#ifdef PROCFS + { &procfs_vfsops, "procfs", 12, 0, 0, NULL, NULL }, #endif -#ifdef PROCFS -extern struct vfsops procfs_vfsops; -#define PROCFS_VFSOPS &procfs_vfsops -#else -#define PROCFS_VFSOPS NULL + /* Loopback (Minimal) Filesystem Layer */ +#ifdef NULLFS + { &null_vfsops, "loopback", 9, 0, 0, NULL, NULL }, #endif -#ifdef AFS -extern struct vfsops afs_vfsops; -#define AFS_VFSOPS &afs_vfsops -#else -#define AFS_VFSOPS NULL + /* Union (translucent) Filesystem */ +#ifdef UNION + { &union_vfsops, "union", 15, 0, 0, NULL, NULL }, #endif -#ifdef CD9660 -extern struct vfsops cd9660_vfsops; -#define CD9660_VFSOPS &cd9660_vfsops -#else -#define CD9660_VFSOPS NULL + /* User/Group Identifer Remapping Filesystem */ +#ifdef UMAPFS + { &umap_vfsops, "umap", 10, 0, 0, NULL, NULL }, #endif -#ifdef UNION -extern struct vfsops union_vfsops; -#define UNION_VFSOPS &union_vfsops -#else -#define UNION_VFSOPS NULL + /* Portal Filesystem */ +#ifdef PORTAL + { &portal_vfsops, "portal", 8, 0, 0, NULL, NULL }, +#endif + + /* File Descriptor Filesystem */ +#ifdef FDESC + { &fdesc_vfsops, "fdesc", 7, 0, 0, NULL, NULL }, +#endif + + /* Kernel Information Filesystem */ +#ifdef KERNFS + { &kernfs_vfsops, "kernfs", 11, 0, 0, NULL, NULL }, #endif -struct vfsops *vfssw[] = { - NULL, /* 0 = MOUNT_NONE */ - UFS_VFSOPS, /* 1 = MOUNT_UFS */ - NFS_VFSOPS, /* 2 = MOUNT_NFS */ - MFS_VFSOPS, /* 3 = MOUNT_MFS */ - NULL, /* 4 = MOUNT_PC */ - LFS_VFSOPS, /* 5 = MOUNT_LFS */ - NULL, /* 6 = MOUNT_LOFS */ - FDESC_VFSOPS, /* 7 = MOUNT_FDESC */ - PORTAL_VFSOPS, /* 8 = MOUNT_PORTAL */ - NULL_VFSOPS, /* 9 = MOUNT_NULL */ - UMAP_VFSOPS, /* 10 = MOUNT_UMAP */ - KERNFS_VFSOPS, /* 11 = MOUNT_KERNFS */ - PROCFS_VFSOPS, /* 12 = MOUNT_PROCFS */ - AFS_VFSOPS, /* 13 = MOUNT_AFS */ - CD9660_VFSOPS, /* 14 = MOUNT_CD9660 */ - UNION_VFSOPS, /* 15 = MOUNT_UNION */ - 0 }; +/* + * Initially the size of the list, vfs_init will set maxvfsconf + * to the highest defined type number. + */ +int maxvfsconf = sizeof(vfsconflist) / sizeof (struct vfsconf); +struct vfsconf *vfsconf = vfsconflist; /* * diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index 1ce7347..b5abe58 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)vfs_init.c 8.3 (Berkeley) 1/4/94 + * @(#)vfs_init.c 8.5 (Berkeley) 5/11/95 */ @@ -211,7 +211,6 @@ vfs_op_init() */ extern struct vnodeops dead_vnodeops; extern struct vnodeops spec_vnodeops; -extern void vclean(); struct vattr va_null; /* @@ -219,7 +218,8 @@ struct vattr va_null; */ vfsinit() { - struct vfsops **vfsp; + struct vfsconf *vfsp; + int i, maxtypenum; /* * Initialize the vnode table @@ -238,9 +238,14 @@ vfsinit() * Initialize each file system type. */ vattr_null(&va_null); - for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) { - if (*vfsp == NULL) - continue; - (*(*vfsp)->vfs_init)(); + maxtypenum = 0; + for (vfsp = vfsconf, i = 1; i <= maxvfsconf; i++, vfsp++) { + if (i < maxvfsconf) + vfsp->vfc_next = vfsp + 1; + if (maxtypenum <= vfsp->vfc_typenum) + maxtypenum = vfsp->vfc_typenum + 1; + (*vfsp->vfc_vfsops->vfs_init)(vfsp); } + /* next vfc_typenum to be used */ + maxvfsconf = maxtypenum; } diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 0fa5aa1..826fbfe 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)vfs_lookup.c 8.4 (Berkeley) 2/16/94 + * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95 */ #include @@ -84,6 +84,7 @@ namei(ndp) struct uio auio; int error, linklen; struct componentname *cnp = &ndp->ni_cnd; + struct proc *p = cnp->cn_proc; ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred; #ifdef DIAGNOSTIC @@ -157,7 +158,7 @@ namei(ndp) return (0); } if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) - VOP_UNLOCK(ndp->ni_dvp); + VOP_UNLOCK(ndp->ni_dvp, 0, p); if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { error = ELOOP; break; @@ -255,6 +256,7 @@ lookup(ndp) int rdonly; /* lookup read-only flag bit */ int error = 0; struct componentname *cnp = &ndp->ni_cnd; + struct proc *p = cnp->cn_proc; /* * Setup: break out flag bits into variables. @@ -269,7 +271,7 @@ lookup(ndp) cnp->cn_flags &= ~ISSYMLINK; dp = ndp->ni_startdir; ndp->ni_startdir = NULLVP; - VOP_LOCK(dp); + vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); dirloop: /* @@ -318,21 +320,21 @@ dirloop: * e.g. like "/." or ".". */ if (cnp->cn_nameptr[0] == '\0') { - if (cnp->cn_nameiop != LOOKUP) { - error = EISDIR; - goto bad; - } if (dp->v_type != VDIR) { error = ENOTDIR; goto bad; } + if (cnp->cn_nameiop != LOOKUP) { + error = EISDIR; + goto bad; + } if (wantparent) { ndp->ni_dvp = dp; VREF(dp); } ndp->ni_vp = dp; if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF))) - VOP_UNLOCK(dp); + VOP_UNLOCK(dp, 0, p); if (cnp->cn_flags & SAVESTART) panic("lookup: SAVESTART"); return (0); @@ -363,7 +365,7 @@ dirloop: dp = dp->v_mount->mnt_vnodecovered; vput(tdp); VREF(dp); - VOP_LOCK(dp); + vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); } } @@ -372,6 +374,7 @@ dirloop: */ unionlookup: ndp->ni_dvp = dp; + ndp->ni_vp = NULL; if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) { #ifdef DIAGNOSTIC if (ndp->ni_vp != NULL) @@ -387,7 +390,7 @@ unionlookup: dp = dp->v_mount->mnt_vnodecovered; vput(tdp); VREF(dp); - VOP_LOCK(dp); + vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); goto unionlookup; } @@ -397,7 +400,7 @@ unionlookup: * If creating and at end of pathname, then can consider * allowing file to be created. */ - if (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY)) { + if (rdonly) { error = EROFS; goto bad; } @@ -429,31 +432,30 @@ unionlookup: dp = ndp->ni_vp; /* - * Check for symbolic link - */ - if ((dp->v_type == VLNK) && - ((cnp->cn_flags & FOLLOW) || *ndp->ni_next == '/')) { - cnp->cn_flags |= ISSYMLINK; - return (0); - } - - /* * Check to see if the vnode has been mounted on; * if so find the root of the mounted file system. */ while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && (cnp->cn_flags & NOCROSSMOUNT) == 0) { - if (mp->mnt_flag & MNT_MLOCK) { - mp->mnt_flag |= MNT_MWAIT; - sleep((caddr_t)mp, PVFS); + if (vfs_busy(mp, 0, 0, p)) continue; - } - if (error = VFS_ROOT(dp->v_mountedhere, &tdp)) + error = VFS_ROOT(mp, &tdp); + vfs_unbusy(mp, p); + if (error) goto bad2; vput(dp); ndp->ni_vp = dp = tdp; } + /* + * Check for symbolic link + */ + if ((dp->v_type == VLNK) && + ((cnp->cn_flags & FOLLOW) || *ndp->ni_next == '/')) { + cnp->cn_flags |= ISSYMLINK; + return (0); + } + nextname: /* * Not a symbolic link. If more pathname, @@ -469,19 +471,12 @@ nextname: goto dirloop; } /* - * Check for read-only file systems. + * Disallow directory write attempts on read-only file systems. */ - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { - /* - * Disallow directory write attempts on read-only - * file systems. - */ - if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || - (wantparent && - (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) { - error = EROFS; - goto bad2; - } + if (rdonly && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { + error = EROFS; + goto bad2; } if (cnp->cn_flags & SAVESTART) { ndp->ni_startdir = ndp->ni_dvp; @@ -490,12 +485,12 @@ nextname: if (!wantparent) vrele(ndp->ni_dvp); if ((cnp->cn_flags & LOCKLEAF) == 0) - VOP_UNLOCK(dp); + VOP_UNLOCK(dp, 0, p); return (0); bad2: if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0') - VOP_UNLOCK(ndp->ni_dvp); + VOP_UNLOCK(ndp->ni_dvp, 0, p); vrele(ndp->ni_dvp); bad: vput(dp); @@ -503,4 +498,148 @@ bad: return (error); } +/* + * relookup - lookup a path name component + * Used by lookup to re-aquire things. + */ +int +relookup(dvp, vpp, cnp) + struct vnode *dvp, **vpp; + struct componentname *cnp; +{ + struct proc *p = cnp->cn_proc; + struct vnode *dp = 0; /* the directory we are searching */ + int docache; /* == 0 do not cache last component */ + int wantparent; /* 1 => wantparent or lockparent flag */ + int rdonly; /* lookup read-only flag bit */ + int error = 0; +#ifdef NAMEI_DIAGNOSTIC + int newhash; /* DEBUG: check name hash */ + char *cp; /* DEBUG: check name ptr/len */ +#endif + + /* + * Setup: break out flag bits into variables. + */ + wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); + docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; + if (cnp->cn_nameiop == DELETE || + (wantparent && cnp->cn_nameiop != CREATE)) + docache = 0; + rdonly = cnp->cn_flags & RDONLY; + cnp->cn_flags &= ~ISSYMLINK; + dp = dvp; + vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); +/* dirloop: */ + /* + * Search a new directory. + * + * The cn_hash value is for use by vfs_cache. + * The last component of the filename is left accessible via + * cnp->cn_nameptr for callers that need the name. Callers needing + * the name set the SAVENAME flag. When done, they assume + * responsibility for freeing the pathname buffer. + */ +#ifdef NAMEI_DIAGNOSTIC + for (newhash = 0, cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++) + newhash += (unsigned char)*cp; + if (newhash != cnp->cn_hash) + panic("relookup: bad hash"); + if (cnp->cn_namelen != cp - cnp->cn_nameptr) + panic ("relookup: bad len"); + if (*cp != 0) + panic("relookup: not last component"); + printf("{%s}: ", cnp->cn_nameptr); +#endif + + /* + * Check for degenerate name (e.g. / or "") + * which is a way of talking about a directory, + * e.g. like "/." or ".". + */ + if (cnp->cn_nameptr[0] == '\0') { + if (cnp->cn_nameiop != LOOKUP || wantparent) { + error = EISDIR; + goto bad; + } + if (dp->v_type != VDIR) { + error = ENOTDIR; + goto bad; + } + if (!(cnp->cn_flags & LOCKLEAF)) + VOP_UNLOCK(dp, 0, p); + *vpp = dp; + if (cnp->cn_flags & SAVESTART) + panic("lookup: SAVESTART"); + return (0); + } + + if (cnp->cn_flags & ISDOTDOT) + panic ("relookup: lookup on dot-dot"); + + /* + * We now have a segment name to search for, and a directory to search. + */ + if (error = VOP_LOOKUP(dp, vpp, cnp)) { +#ifdef DIAGNOSTIC + if (*vpp != NULL) + panic("leaf should be empty"); +#endif + if (error != EJUSTRETURN) + goto bad; + /* + * If creating and at end of pathname, then can consider + * allowing file to be created. + */ + if (rdonly) { + error = EROFS; + goto bad; + } + /* ASSERT(dvp == ndp->ni_startdir) */ + if (cnp->cn_flags & SAVESTART) + VREF(dvp); + /* + * We return with ni_vp NULL to indicate that the entry + * doesn't currently exist, leaving a pointer to the + * (possibly locked) directory inode in ndp->ni_dvp. + */ + return (0); + } + dp = *vpp; + +#ifdef DIAGNOSTIC + /* + * Check for symbolic link + */ + if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW)) + panic ("relookup: symlink found.\n"); +#endif + + /* + * Disallow directory write attempts on read-only file systems. + */ + if (rdonly && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { + error = EROFS; + goto bad2; + } + /* ASSERT(dvp == ndp->ni_startdir) */ + if (cnp->cn_flags & SAVESTART) + VREF(dvp); + + if (!wantparent) + vrele(dvp); + if ((cnp->cn_flags & LOCKLEAF) == 0) + VOP_UNLOCK(dp, 0, p); + return (0); + +bad2: + if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) + VOP_UNLOCK(dvp, 0, p); + vrele(dvp); +bad: + vput(dp); + *vpp = NULL; + return (error); +} diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 9891fe6..f891e02 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)vfs_subr.c 8.13 (Berkeley) 4/18/94 + * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 */ /* @@ -75,107 +75,167 @@ int vttoif_tab[9] = { * Insq/Remq for the vnode usage lists. */ #define bufinsvn(bp, dp) LIST_INSERT_HEAD(dp, bp, b_vnbufs) -#define bufremvn(bp) { \ - LIST_REMOVE(bp, b_vnbufs); \ - (bp)->b_vnbufs.le_next = NOLIST; \ +#define bufremvn(bp) { \ + LIST_REMOVE(bp, b_vnbufs); \ + (bp)->b_vnbufs.le_next = NOLIST; \ } - TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */ struct mntlist mountlist; /* mounted filesystem list */ +struct simplelock mountlist_slock; +static struct simplelock mntid_slock; +struct simplelock mntvnode_slock; +struct simplelock vnode_free_list_slock; +static struct simplelock spechash_slock; /* * Initialize the vnode management data structures. */ +void vntblinit() { + simple_lock_init(&mntvnode_slock); + simple_lock_init(&mntid_slock); + simple_lock_init(&spechash_slock); TAILQ_INIT(&vnode_free_list); - TAILQ_INIT(&mountlist); + simple_lock_init(&vnode_free_list_slock); + CIRCLEQ_INIT(&mountlist); } /* - * Lock a filesystem. - * Used to prevent access to it while mounting and unmounting. + * Mark a mount point as busy. Used to synchronize access and to delay + * unmounting. Interlock is not released on failure. */ -vfs_lock(mp) - register struct mount *mp; +int +vfs_busy(mp, flags, interlkp, p) + struct mount *mp; + int flags; + struct simplelock *interlkp; + struct proc *p; { + int lkflags; - while(mp->mnt_flag & MNT_MLOCK) { + if (mp->mnt_flag & MNT_UNMOUNT) { + if (flags & LK_NOWAIT) + return (ENOENT); mp->mnt_flag |= MNT_MWAIT; + if (interlkp) + simple_unlock(interlkp); + /* + * Since all busy locks are shared except the exclusive + * lock granted when unmounting, the only place that a + * wakeup needs to be done is at the release of the + * exclusive lock at the end of dounmount. + */ sleep((caddr_t)mp, PVFS); + if (interlkp) + simple_lock(interlkp); + return (ENOENT); } - mp->mnt_flag |= MNT_MLOCK; + lkflags = LK_SHARED; + if (interlkp) + lkflags |= LK_INTERLOCK; + if (lockmgr(&mp->mnt_lock, lkflags, interlkp, p)) + panic("vfs_busy: unexpected lock failure"); return (0); } /* - * Unlock a locked filesystem. - * Panic if filesystem is not locked. + * Free a busy filesystem. */ void -vfs_unlock(mp) - register struct mount *mp; +vfs_unbusy(mp, p) + struct mount *mp; + struct proc *p; { - if ((mp->mnt_flag & MNT_MLOCK) == 0) - panic("vfs_unlock: not locked"); - mp->mnt_flag &= ~MNT_MLOCK; - if (mp->mnt_flag & MNT_MWAIT) { - mp->mnt_flag &= ~MNT_MWAIT; - wakeup((caddr_t)mp); - } + lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, p); } /* - * Mark a mount point as busy. - * Used to synchronize access and to delay unmounting. + * Lookup a filesystem type, and if found allocate and initialize + * a mount structure for it. + * + * Devname is usually updated by mount(8) after booting. */ -vfs_busy(mp) - register struct mount *mp; +int +vfs_rootmountalloc(fstypename, devname, mpp) + char *fstypename; + char *devname; + struct mount **mpp; { + struct proc *p = curproc; /* XXX */ + struct vfsconf *vfsp; + struct mount *mp; - while(mp->mnt_flag & MNT_MPBUSY) { - mp->mnt_flag |= MNT_MPWANT; - sleep((caddr_t)&mp->mnt_flag, PVFS); - } - if (mp->mnt_flag & MNT_UNMOUNT) - return (1); - mp->mnt_flag |= MNT_MPBUSY; + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) + if (!strcmp(vfsp->vfc_name, fstypename)) + break; + if (vfsp == NULL) + return (ENODEV); + mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); + bzero((char *)mp, (u_long)sizeof(struct mount)); + lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); + (void)vfs_busy(mp, LK_NOWAIT, 0, p); + LIST_INIT(&mp->mnt_vnodelist); + mp->mnt_vfc = vfsp; + mp->mnt_op = vfsp->vfc_vfsops; + mp->mnt_flag = MNT_RDONLY; + mp->mnt_vnodecovered = NULLVP; + vfsp->vfc_refcount++; + mp->mnt_stat.f_type = vfsp->vfc_typenum; + mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; + strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); + mp->mnt_stat.f_mntonname[0] = '/'; + (void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0); + *mpp = mp; return (0); } /* - * Free a busy filesystem. - * Panic if filesystem is not busy. + * Find an appropriate filesystem to use for the root. If a filesystem + * has not been preselected, walk through the list of known filesystems + * trying those that have mountroot routines, and try them until one + * works or we have tried them all. */ -vfs_unbusy(mp) - register struct mount *mp; +int +vfs_mountroot() { + struct vfsconf *vfsp; + extern int (*mountroot)(void); + int error; - if ((mp->mnt_flag & MNT_MPBUSY) == 0) - panic("vfs_unbusy: not busy"); - mp->mnt_flag &= ~MNT_MPBUSY; - if (mp->mnt_flag & MNT_MPWANT) { - mp->mnt_flag &= ~MNT_MPWANT; - wakeup((caddr_t)&mp->mnt_flag); + if (mountroot != NULL) + return ((*mountroot)()); + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) { + if (vfsp->vfc_mountroot == NULL) + continue; + if ((error = (*vfsp->vfc_mountroot)()) == 0) + return (0); + printf("%s_mountroot failed: %d\n", vfsp->vfc_name, error); } + return (ENODEV); } /* * Lookup a mount point by filesystem identifier. */ struct mount * -getvfs(fsid) +vfs_getvfs(fsid) fsid_t *fsid; { register struct mount *mp; - for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) { + simple_lock(&mountlist_slock); + for (mp = mountlist.cqh_first; mp != (void *)&mountlist; + mp = mp->mnt_list.cqe_next) { if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] && - mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) + mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) { + simple_unlock(&mountlist_slock); return (mp); + } } + simple_unlock(&mountlist_slock); return ((struct mount *)0); } @@ -183,33 +243,37 @@ getvfs(fsid) * Get a new unique fsid */ void -getnewfsid(mp, mtype) +vfs_getnewfsid(mp) struct mount *mp; - int mtype; { static u_short xxxfs_mntid; fsid_t tfsid; + int mtype; + simple_lock(&mntid_slock); + mtype = mp->mnt_vfc->vfc_typenum; mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0); mp->mnt_stat.f_fsid.val[1] = mtype; if (xxxfs_mntid == 0) ++xxxfs_mntid; tfsid.val[0] = makedev(nblkdev + mtype, xxxfs_mntid); tfsid.val[1] = mtype; - if (mountlist.tqh_first != NULL) { - while (getvfs(&tfsid)) { + if (mountlist.cqh_first != (void *)&mountlist) { + while (vfs_getvfs(&tfsid)) { tfsid.val[0]++; xxxfs_mntid++; } } mp->mnt_stat.f_fsid.val[0] = tfsid.val[0]; + simple_unlock(&mntid_slock); } /* * Set vnode attributes to VNOVAL */ -void vattr_null(vap) +void +vattr_null(vap) register struct vattr *vap; { @@ -229,31 +293,49 @@ void vattr_null(vap) * Routines having to do with the management of the vnode table. */ extern int (**dead_vnodeop_p)(); -extern void vclean(); +static void vclean __P((struct vnode *vp, int flag, struct proc *p)); +extern void vgonel __P((struct vnode *vp, struct proc *p)); long numvnodes; extern struct vattr va_null; /* * Return the next vnode from the free list. */ +int getnewvnode(tag, mp, vops, vpp) enum vtagtype tag; struct mount *mp; int (**vops)(); struct vnode **vpp; { - register struct vnode *vp; + struct proc *p = curproc; /* XXX */ + struct vnode *vp; int s; + int cnt; +top: + simple_lock(&vnode_free_list_slock); if ((vnode_free_list.tqh_first == NULL && numvnodes < 2 * desiredvnodes) || numvnodes < desiredvnodes) { + simple_unlock(&vnode_free_list_slock); vp = (struct vnode *)malloc((u_long)sizeof *vp, M_VNODE, M_WAITOK); bzero((char *)vp, sizeof *vp); numvnodes++; } else { - if ((vp = vnode_free_list.tqh_first) == NULL) { + for (vp = vnode_free_list.tqh_first; + vp != NULLVP; vp = vp->v_freelist.tqe_next) { + if (simple_lock_try(&vp->v_interlock)) + break; + } + /* + * Unless this is a bad time of the month, at most + * the first NCPUS items on the free list are + * locked, so this is close enough to being empty. + */ + if (vp == NULLVP) { + simple_unlock(&vnode_free_list_slock); tablefull("vnode"); *vpp = 0; return (ENFILE); @@ -263,9 +345,12 @@ getnewvnode(tag, mp, vops, vpp) TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); /* see comment on why 0xdeadb is set at end of vgone (below) */ vp->v_freelist.tqe_prev = (struct vnode **)0xdeadb; + simple_unlock(&vnode_free_list_slock); vp->v_lease = NULL; if (vp->v_type != VBAD) - vgone(vp); + vgonel(vp, p); + else + simple_unlock(&vp->v_interlock); #ifdef DIAGNOSTIC if (vp->v_data) panic("cleaned vnode isn't"); @@ -298,11 +383,13 @@ getnewvnode(tag, mp, vops, vpp) /* * Move a vnode from one mount queue to another. */ +void insmntque(vp, mp) - register struct vnode *vp; - register struct mount *mp; + struct vnode *vp; + struct mount *mp; { + simple_lock(&mntvnode_slock); /* * Delete from old mount point vnode list, if on one. */ @@ -311,14 +398,15 @@ insmntque(vp, mp) /* * Insert into list of vnodes for the new mount point, if available. */ - if ((vp->v_mount = mp) == NULL) - return; - LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes); + if ((vp->v_mount = mp) != NULL) + LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes); + simple_unlock(&mntvnode_slock); } /* * Update outstanding I/O count and do wakeup if requested. */ +void vwakeup(bp) register struct buf *bp; { @@ -326,12 +414,11 @@ vwakeup(bp) bp->b_flags &= ~B_WRITEINPROG; if (vp = bp->b_vp) { - vp->v_numoutput--; - if (vp->v_numoutput < 0) + if (--vp->v_numoutput < 0) panic("vwakeup: neg numoutput"); if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) { if (vp->v_numoutput < 0) - panic("vwakeup: neg numoutput"); + panic("vwakeup: neg numoutput 2"); vp->v_flag &= ~VBWAIT; wakeup((caddr_t)&vp->v_numoutput); } @@ -364,7 +451,7 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo) if ((blist = vp->v_cleanblkhd.lh_first) && flags & V_SAVEMETA) while (blist && blist->b_lblkno < 0) blist = blist->b_vnbufs.le_next; - if (!blist && (blist = vp->v_dirtyblkhd.lh_first) && + if (!blist && (blist = vp->v_dirtyblkhd.lh_first) && (flags & V_SAVEMETA)) while (blist && blist->b_lblkno < 0) blist = blist->b_vnbufs.le_next; @@ -411,6 +498,7 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo) /* * Associate a buffer with a vnode. */ +void bgetvp(vp, bp) register struct vnode *vp; register struct buf *bp; @@ -433,6 +521,7 @@ bgetvp(vp, bp) /* * Disassociate a buffer from a vnode. */ +void brelvp(bp) register struct buf *bp; { @@ -455,6 +544,7 @@ brelvp(bp) * Used to assign file specific control information * (indirect blocks) to the vnode to which they belong. */ +void reassignbuf(bp, newvp) register struct buf *bp; register struct vnode *newvp; @@ -486,6 +576,7 @@ reassignbuf(bp, newvp) * Used for root filesystem, argdev, and swap areas. * Also used for memory file system special devices. */ +int bdevvp(dev, vpp) dev_t dev; struct vnode **vpp; @@ -494,11 +585,13 @@ bdevvp(dev, vpp) struct vnode *nvp; int error; - if (dev == NODEV) - return (0); + if (dev == NODEV) { + *vpp = NULLVP; + return (ENODEV); + } error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp); if (error) { - *vpp = 0; + *vpp = NULLVP; return (error); } vp = nvp; @@ -525,7 +618,8 @@ checkalias(nvp, nvp_rdev, mp) dev_t nvp_rdev; struct mount *mp; { - register struct vnode *vp; + struct proc *p = curproc; /* XXX */ + struct vnode *vp; struct vnode **vpp; if (nvp->v_type != VBLK && nvp->v_type != VCHR) @@ -533,18 +627,23 @@ checkalias(nvp, nvp_rdev, mp) vpp = &speclisth[SPECHASH(nvp_rdev)]; loop: + simple_lock(&spechash_slock); for (vp = *vpp; vp; vp = vp->v_specnext) { if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type) continue; /* * Alias, but not in use, so flush it out. */ + simple_lock(&vp->v_interlock); if (vp->v_usecount == 0) { - vgone(vp); + simple_unlock(&spechash_slock); + vgonel(vp, p); goto loop; } - if (vget(vp, 1)) + if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) { + simple_unlock(&spechash_slock); goto loop; + } break; } if (vp == NULL || vp->v_tag != VT_NON) { @@ -554,16 +653,19 @@ loop: nvp->v_hashchain = vpp; nvp->v_specnext = *vpp; nvp->v_specflags = 0; + simple_unlock(&spechash_slock); *vpp = nvp; - if (vp != NULL) { + if (vp != NULLVP) { nvp->v_flag |= VALIASED; vp->v_flag |= VALIASED; vput(vp); } return (NULLVP); } - VOP_UNLOCK(vp); - vclean(vp, 0); + simple_unlock(&spechash_slock); + VOP_UNLOCK(vp, 0, p); + simple_lock(&vp->v_interlock); + vclean(vp, 0, p); vp->v_op = nvp->v_op; vp->v_tag = nvp->v_tag; nvp->v_type = VNON; @@ -579,76 +681,219 @@ loop: * indicate that the vnode is no longer usable (possibly having * been changed to a new file system type). */ -vget(vp, lockflag) - register struct vnode *vp; - int lockflag; +int +vget(vp, flags, p) + struct vnode *vp; + int flags; + struct proc *p; { + int error; /* * If the vnode is in the process of being cleaned out for * another use, we wait for the cleaning to finish and then - * return failure. Cleaning is determined either by checking - * that the VXLOCK flag is set, or that the use count is - * zero with the back pointer set to show that it has been - * removed from the free list by getnewvnode. The VXLOCK - * flag may not have been set yet because vclean is blocked in - * the VOP_LOCK call waiting for the VOP_INACTIVE to complete. + * return failure. Cleaning is determined by checking that + * the VXLOCK flag is set. */ - if ((vp->v_flag & VXLOCK) || - (vp->v_usecount == 0 && - vp->v_freelist.tqe_prev == (struct vnode **)0xdeadb)) { + if ((flags & LK_INTERLOCK) == 0) + simple_lock(&vp->v_interlock); + if (vp->v_flag & VXLOCK) { vp->v_flag |= VXWANT; - sleep((caddr_t)vp, PINOD); - return (1); + simple_unlock(&vp->v_interlock); + tsleep((caddr_t)vp, PINOD, "vget", 0); + return (ENOENT); } - if (vp->v_usecount == 0) + if (vp->v_usecount == 0) { + simple_lock(&vnode_free_list_slock); TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + simple_unlock(&vnode_free_list_slock); + } vp->v_usecount++; - if (lockflag) - VOP_LOCK(vp); + if (flags & LK_TYPE_MASK) { + if (error = vn_lock(vp, flags | LK_INTERLOCK, p)) + vrele(vp); + return (error); + } + simple_unlock(&vp->v_interlock); + return (0); +} + +/* + * Stubs to use when there is no locking to be done on the underlying object. + * A minimal shared lock is necessary to ensure that the underlying object + * is not revoked while an operation is in progress. So, an active shared + * count is maintained in an auxillary vnode lock structure. + */ +int +vop_nolock(ap) + struct vop_lock_args /* { + struct vnode *a_vp; + int a_flags; + struct proc *a_p; + } */ *ap; +{ +#ifdef notyet + /* + * This code cannot be used until all the non-locking filesystems + * (notably NFS) are converted to properly lock and release nodes. + * Also, certain vnode operations change the locking state within + * the operation (create, mknod, remove, link, rename, mkdir, rmdir, + * and symlink). Ideally these operations should not change the + * lock state, but should be changed to let the caller of the + * function unlock them. Otherwise all intermediate vnode layers + * (such as union, umapfs, etc) must catch these functions to do + * the necessary locking at their layer. Note that the inactive + * and lookup operations also change their lock state, but this + * cannot be avoided, so these two operations will always need + * to be handled in intermediate layers. + */ + struct vnode *vp = ap->a_vp; + int vnflags, flags = ap->a_flags; + + if (vp->v_vnlock == NULL) { + if ((flags & LK_TYPE_MASK) == LK_DRAIN) + return (0); + MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock), + M_VNODE, M_WAITOK); + lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0); + } + switch (flags & LK_TYPE_MASK) { + case LK_DRAIN: + vnflags = LK_DRAIN; + break; + case LK_EXCLUSIVE: + case LK_SHARED: + vnflags = LK_SHARED; + break; + case LK_UPGRADE: + case LK_EXCLUPGRADE: + case LK_DOWNGRADE: + return (0); + case LK_RELEASE: + default: + panic("vop_nolock: bad operation %d", flags & LK_TYPE_MASK); + } + if (flags & LK_INTERLOCK) + vnflags |= LK_INTERLOCK; + return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p)); +#else /* for now */ + /* + * Since we are not using the lock manager, we must clear + * the interlock here. + */ + if (ap->a_flags & LK_INTERLOCK) + simple_unlock(&ap->a_vp->v_interlock); return (0); +#endif +} + +/* + * Decrement the active use count. + */ +int +vop_nounlock(ap) + struct vop_unlock_args /* { + struct vnode *a_vp; + int a_flags; + struct proc *a_p; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + + if (vp->v_vnlock == NULL) + return (0); + return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL, ap->a_p)); } /* - * Vnode reference, just increment the count + * Return whether or not the node is in use. */ -void vref(vp) +int +vop_noislocked(ap) + struct vop_islocked_args /* { + struct vnode *a_vp; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + + if (vp->v_vnlock == NULL) + return (0); + return (lockstatus(vp->v_vnlock)); +} + +/* + * Vnode reference. + */ +void +vref(vp) struct vnode *vp; { + simple_lock(&vp->v_interlock); if (vp->v_usecount <= 0) panic("vref used where vget required"); vp->v_usecount++; + simple_unlock(&vp->v_interlock); } /* * vput(), just unlock and vrele() */ -void vput(vp) - register struct vnode *vp; +void +vput(vp) + struct vnode *vp; { + struct proc *p = curproc; /* XXX */ - VOP_UNLOCK(vp); - vrele(vp); +#ifdef DIGANOSTIC + if (vp == NULL) + panic("vput: null vp"); +#endif + simple_lock(&vp->v_interlock); + vp->v_usecount--; + if (vp->v_usecount > 0) { + simple_unlock(&vp->v_interlock); + VOP_UNLOCK(vp, 0, p); + return; + } +#ifdef DIAGNOSTIC + if (vp->v_usecount < 0 || vp->v_writecount != 0) { + vprint("vput: bad ref count", vp); + panic("vput: ref cnt"); + } +#endif + /* + * insert at tail of LRU list + */ + simple_lock(&vnode_free_list_slock); + TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); + simple_unlock(&vnode_free_list_slock); + simple_unlock(&vp->v_interlock); + VOP_INACTIVE(vp, p); } /* * Vnode release. * If count drops to zero, call inactive routine and return to freelist. */ -void vrele(vp) - register struct vnode *vp; +void +vrele(vp) + struct vnode *vp; { + struct proc *p = curproc; /* XXX */ #ifdef DIAGNOSTIC if (vp == NULL) panic("vrele: null vp"); #endif + simple_lock(&vp->v_interlock); vp->v_usecount--; - if (vp->v_usecount > 0) + if (vp->v_usecount > 0) { + simple_unlock(&vp->v_interlock); return; + } #ifdef DIAGNOSTIC - if (vp->v_usecount != 0 || vp->v_writecount != 0) { + if (vp->v_usecount < 0 || vp->v_writecount != 0) { vprint("vrele: bad ref count", vp); panic("vrele: ref cnt"); } @@ -656,31 +901,42 @@ void vrele(vp) /* * insert at tail of LRU list */ + simple_lock(&vnode_free_list_slock); TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); - VOP_INACTIVE(vp); + simple_unlock(&vnode_free_list_slock); + if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0) + VOP_INACTIVE(vp, p); } +#ifdef DIAGNOSTIC /* * Page or buffer structure gets a reference. */ -void vhold(vp) +void +vhold(vp) register struct vnode *vp; { + simple_lock(&vp->v_interlock); vp->v_holdcnt++; + simple_unlock(&vp->v_interlock); } /* * Page or buffer structure frees a reference. */ -void holdrele(vp) +void +holdrele(vp) register struct vnode *vp; { + simple_lock(&vp->v_interlock); if (vp->v_holdcnt <= 0) panic("holdrele: holdcnt"); vp->v_holdcnt--; + simple_unlock(&vp->v_interlock); } +#endif /* DIAGNOSTIC */ /* * Remove any vnodes in the vnode table belonging to mount point mp. @@ -695,16 +951,17 @@ int busyprt = 0; /* print out busy vnodes */ struct ctldebug debug1 = { "busyprt", &busyprt }; #endif +int vflush(mp, skipvp, flags) struct mount *mp; struct vnode *skipvp; int flags; { - register struct vnode *vp, *nvp; + struct proc *p = curproc; /* XXX */ + struct vnode *vp, *nvp; int busy = 0; - if ((mp->mnt_flag & MNT_MPBUSY) == 0) - panic("vflush: not busy"); + simple_lock(&mntvnode_slock); loop: for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) { if (vp->v_mount != mp) @@ -715,24 +972,32 @@ loop: */ if (vp == skipvp) continue; + + simple_lock(&vp->v_interlock); /* * Skip over a vnodes marked VSYSTEM. */ - if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) + if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) { + simple_unlock(&vp->v_interlock); continue; + } /* * If WRITECLOSE is set, only flush out regular file * vnodes open for writing. */ if ((flags & WRITECLOSE) && - (vp->v_writecount == 0 || vp->v_type != VREG)) + (vp->v_writecount == 0 || vp->v_type != VREG)) { + simple_unlock(&vp->v_interlock); continue; + } /* * With v_usecount == 0, all we need to do is clear * out the vnode data structures and we are done. */ if (vp->v_usecount == 0) { - vgone(vp); + simple_unlock(&mntvnode_slock); + vgonel(vp, p); + simple_lock(&mntvnode_slock); continue; } /* @@ -741,21 +1006,25 @@ loop: * anonymous device. For all other files, just kill them. */ if (flags & FORCECLOSE) { + simple_unlock(&mntvnode_slock); if (vp->v_type != VBLK && vp->v_type != VCHR) { - vgone(vp); + vgonel(vp, p); } else { - vclean(vp, 0); + vclean(vp, 0, p); vp->v_op = spec_vnodeop_p; insmntque(vp, (struct mount *)0); } + simple_lock(&mntvnode_slock); continue; } #ifdef DIAGNOSTIC if (busyprt) vprint("vflush: busy vnode", vp); #endif + simple_unlock(&vp->v_interlock); busy++; } + simple_unlock(&mntvnode_slock); if (busy) return (EBUSY); return (0); @@ -763,11 +1032,13 @@ loop: /* * Disassociate the underlying file system from a vnode. + * The vnode interlock is held on entry. */ -void -vclean(vp, flags) - register struct vnode *vp; +static void +vclean(vp, flags, p) + struct vnode *vp; int flags; + struct proc *p; { int active; @@ -778,15 +1049,7 @@ vclean(vp, flags) * race against ourselves to recycle it. */ if (active = vp->v_usecount) - VREF(vp); - /* - * Even if the count is zero, the VOP_INACTIVE routine may still - * have the object locked while it cleans it out. The VOP_LOCK - * ensures that the VOP_INACTIVE routine is done with its work. - * For active vnodes, it ensures that no other activity can - * occur while the underlying object is being cleaned out. - */ - VOP_LOCK(vp); + vp->v_usecount++; /* * Prevent the vnode from being recycled or * brought into use while we clean it out. @@ -795,31 +1058,48 @@ vclean(vp, flags) panic("vclean: deadlock"); vp->v_flag |= VXLOCK; /* - * Clean out any buffers associated with the vnode. + * Even if the count is zero, the VOP_INACTIVE routine may still + * have the object locked while it cleans it out. The VOP_LOCK + * ensures that the VOP_INACTIVE routine is done with its work. + * For active vnodes, it ensures that no other activity can + * occur while the underlying object is being cleaned out. */ - if (flags & DOCLOSE) - vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0); + VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, p); /* - * Any other processes trying to obtain this lock must first - * wait for VXLOCK to clear, then call the new lock operation. + * Clean out any buffers associated with the vnode. */ - VOP_UNLOCK(vp); + if (flags & DOCLOSE) + vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); /* * If purging an active vnode, it must be closed and - * deactivated before being reclaimed. + * deactivated before being reclaimed. Note that the + * VOP_INACTIVE will unlock the vnode. */ if (active) { if (flags & DOCLOSE) - VOP_CLOSE(vp, IO_NDELAY, NOCRED, NULL); - VOP_INACTIVE(vp); + VOP_CLOSE(vp, IO_NDELAY, NOCRED, p); + VOP_INACTIVE(vp, p); + } else { + /* + * Any other processes trying to obtain this lock must first + * wait for VXLOCK to clear, then call the new lock operation. + */ + VOP_UNLOCK(vp, 0, p); } /* * Reclaim the vnode. */ - if (VOP_RECLAIM(vp)) + if (VOP_RECLAIM(vp, p)) panic("vclean: cannot reclaim"); if (active) vrele(vp); + cache_purge(vp); + if (vp->v_vnlock) { + if ((vp->v_vnlock->lk_flags & LK_DRAINED) == 0) + vprint("vclean: lock not drained", vp); + FREE(vp->v_vnlock, M_VNODE); + vp->v_vnlock = NULL; + } /* * Done with purge, notify sleepers of the grim news. @@ -837,10 +1117,23 @@ vclean(vp, flags) * Eliminate all activity associated with the requested vnode * and with all vnodes aliased to the requested vnode. */ -void vgoneall(vp) - register struct vnode *vp; +int +vop_revoke(ap) + struct vop_revoke_args /* { + struct vnode *a_vp; + int a_flags; + } */ *ap; { - register struct vnode *vq; + struct vnode *vp, *vq; + struct proc *p = curproc; /* XXX */ + +#ifdef DIAGNOSTIC + if ((ap->a_flags & REVOKEALL) == 0) + panic("vop_revoke"); +#endif + + vp = ap->a_vp; + simple_lock(&vp->v_interlock); if (vp->v_flag & VALIASED) { /* @@ -849,41 +1142,86 @@ void vgoneall(vp) */ if (vp->v_flag & VXLOCK) { vp->v_flag |= VXWANT; - sleep((caddr_t)vp, PINOD); - return; + simple_unlock(&vp->v_interlock); + tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0); + return (0); } /* * Ensure that vp will not be vgone'd while we * are eliminating its aliases. */ vp->v_flag |= VXLOCK; + simple_unlock(&vp->v_interlock); while (vp->v_flag & VALIASED) { + simple_lock(&spechash_slock); for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type || vp == vq) continue; + simple_unlock(&spechash_slock); vgone(vq); break; } + if (vq == NULLVP) + simple_unlock(&spechash_slock); } /* * Remove the lock so that vgone below will * really eliminate the vnode after which time * vgone will awaken any sleepers. */ + simple_lock(&vp->v_interlock); vp->v_flag &= ~VXLOCK; } - vgone(vp); + vgonel(vp, p); + return (0); +} + +/* + * Recycle an unused vnode to the front of the free list. + * Release the passed interlock if the vnode will be recycled. + */ +int +vrecycle(vp, inter_lkp, p) + struct vnode *vp; + struct simplelock *inter_lkp; + struct proc *p; +{ + + simple_lock(&vp->v_interlock); + if (vp->v_usecount == 0) { + if (inter_lkp) + simple_unlock(inter_lkp); + vgonel(vp, p); + return (1); + } + simple_unlock(&vp->v_interlock); + return (0); } /* * Eliminate all activity associated with a vnode * in preparation for reuse. */ -void vgone(vp) - register struct vnode *vp; +void +vgone(vp) + struct vnode *vp; { - register struct vnode *vq; + struct proc *p = curproc; /* XXX */ + + simple_lock(&vp->v_interlock); + vgonel(vp, p); +} + +/* + * vgone, with the vp interlock held. + */ +void +vgonel(vp, p) + struct vnode *vp; + struct proc *p; +{ + struct vnode *vq; struct vnode *vx; /* @@ -892,24 +1230,25 @@ void vgone(vp) */ if (vp->v_flag & VXLOCK) { vp->v_flag |= VXWANT; - sleep((caddr_t)vp, PINOD); + simple_unlock(&vp->v_interlock); + tsleep((caddr_t)vp, PINOD, "vgone", 0); return; } /* * Clean out the filesystem specific data. */ - vclean(vp, DOCLOSE); + vclean(vp, DOCLOSE, p); /* * Delete from old mount point vnode list, if on one. */ - if (vp->v_mount != NULL) { - LIST_REMOVE(vp, v_mntvnodes); - vp->v_mount = NULL; - } + if (vp->v_mount != NULL) + insmntque(vp, (struct mount *)0); /* - * If special device, remove it from special device alias list. + * If special device, remove it from special device alias list + * if it is on one. */ - if (vp->v_type == VBLK || vp->v_type == VCHR) { + if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_specinfo != 0) { + simple_lock(&spechash_slock); if (*vp->v_hashchain == vp) { *vp->v_hashchain = vp->v_specnext; } else { @@ -938,6 +1277,7 @@ void vgone(vp) vx->v_flag &= ~VALIASED; vp->v_flag &= ~VALIASED; } + simple_unlock(&spechash_slock); FREE(vp->v_specinfo, M_VNODE); vp->v_specinfo = NULL; } @@ -954,11 +1294,14 @@ void vgone(vp) * getnewvnode after removing it from the freelist to ensure * that we do not try to move it here. */ - if (vp->v_usecount == 0 && - vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb && - vnode_free_list.tqh_first != vp) { - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); + if (vp->v_usecount == 0) { + simple_lock(&vnode_free_list_slock); + if ((vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb) && + vnode_free_list.tqh_first != vp) { + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); + } + simple_unlock(&vnode_free_list_slock); } vp->v_type = VBAD; } @@ -966,34 +1309,41 @@ void vgone(vp) /* * Lookup a vnode by device number. */ +int vfinddev(dev, type, vpp) dev_t dev; enum vtype type; struct vnode **vpp; { - register struct vnode *vp; + struct vnode *vp; + int rc = 0; + simple_lock(&spechash_slock); for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) { if (dev != vp->v_rdev || type != vp->v_type) continue; *vpp = vp; - return (1); + rc = 1; + break; } - return (0); + simple_unlock(&spechash_slock); + return (rc); } /* * Calculate the total number of references to a special device. */ +int vcount(vp) - register struct vnode *vp; + struct vnode *vp; { - register struct vnode *vq, *vnext; + struct vnode *vq, *vnext; int count; loop: if ((vp->v_flag & VALIASED) == 0) return (vp->v_usecount); + simple_lock(&spechash_slock); for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) { vnext = vq->v_specnext; if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type) @@ -1002,11 +1352,13 @@ loop: * Alias, but not in use, so flush it out. */ if (vq->v_usecount == 0 && vq != vp) { + simple_unlock(&spechash_slock); vgone(vq); goto loop; } count += vq->v_usecount; } + simple_unlock(&spechash_slock); return (count); } @@ -1016,6 +1368,7 @@ loop: static char *typename[] = { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" }; +void vprint(label, vp) char *label; register struct vnode *vp; @@ -1057,22 +1410,79 @@ vprint(label, vp) * List all of the locked vnodes in the system. * Called when debugging the kernel. */ +void printlockedvnodes() { - register struct mount *mp; - register struct vnode *vp; + struct proc *p = curproc; /* XXX */ + struct mount *mp, *nmp; + struct vnode *vp; printf("Locked vnodes\n"); - for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) { + simple_lock(&mountlist_slock); + for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { + if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { + nmp = mp->mnt_list.cqe_next; + continue; + } for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; - vp = vp->v_mntvnodes.le_next) + vp = vp->v_mntvnodes.le_next) { if (VOP_ISLOCKED(vp)) vprint((char *)0, vp); + } + simple_lock(&mountlist_slock); + nmp = mp->mnt_list.cqe_next; + vfs_unbusy(mp, p); } + simple_unlock(&mountlist_slock); } #endif +/* + * Top level filesystem related information gathering. + */ +int +vfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; + struct proc *p; +{ + struct ctldebug *cdp; + struct vfsconf *vfsp; + + /* all sysctl names at this level are at least name and field */ + if (namelen < 2) + return (ENOTDIR); /* overloaded */ + if (name[0] != VFS_GENERIC) { + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) + if (vfsp->vfc_typenum == name[0]) + break; + if (vfsp == NULL) + return (EOPNOTSUPP); + return ((*vfsp->vfc_vfsops->vfs_sysctl)(&name[1], namelen - 1, + oldp, oldlenp, newp, newlen, p)); + } + switch (name[1]) { + case VFS_MAXTYPENUM: + return (sysctl_rdint(oldp, oldlenp, newp, maxvfsconf)); + case VFS_CONF: + if (namelen < 3) + return (ENOTDIR); /* overloaded */ + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) + if (vfsp->vfc_typenum == name[2]) + break; + if (vfsp == NULL) + return (EOPNOTSUPP); + return (sysctl_rdstruct(oldp, oldlenp, newp, vfsp, + sizeof(struct vfsconf))); + } + return (EOPNOTSUPP); +} + int kinfo_vdebug = 1; int kinfo_vgetfailed; #define KINFO_VNODESLOP 10 @@ -1081,13 +1491,15 @@ int kinfo_vgetfailed; * Copyout address of vnode followed by vnode. */ /* ARGSUSED */ -sysctl_vnode(where, sizep) +int +sysctl_vnode(where, sizep, p) char *where; size_t *sizep; + struct proc *p; { - register struct mount *mp, *nmp; - struct vnode *vp; - register char *bp = where, *savebp; + struct mount *mp, *nmp; + struct vnode *nvp, *vp; + char *bp = where, *savebp; char *ewhere; int error; @@ -1099,37 +1511,49 @@ sysctl_vnode(where, sizep) } ewhere = where + *sizep; - for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) { - nmp = mp->mnt_list.tqe_next; - if (vfs_busy(mp)) + simple_lock(&mountlist_slock); + for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { + if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { + nmp = mp->mnt_list.cqe_next; continue; + } savebp = bp; again: + simple_lock(&mntvnode_slock); for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; - vp = vp->v_mntvnodes.le_next) { + vp = nvp) { /* * Check that the vp is still associated with * this filesystem. RACE: could have been * recycled onto the same filesystem. */ if (vp->v_mount != mp) { + simple_unlock(&mntvnode_slock); if (kinfo_vdebug) printf("kinfo: vp changed\n"); bp = savebp; goto again; } + nvp = vp->v_mntvnodes.le_next; if (bp + VPTRSZ + VNODESZ > ewhere) { + simple_unlock(&mntvnode_slock); *sizep = bp - where; return (ENOMEM); } + simple_unlock(&mntvnode_slock); if ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) || (error = copyout((caddr_t)vp, bp + VPTRSZ, VNODESZ))) return (error); bp += VPTRSZ + VNODESZ; + simple_lock(&mntvnode_slock); } - vfs_unbusy(mp); + simple_unlock(&mntvnode_slock); + simple_lock(&mountlist_slock); + nmp = mp->mnt_list.cqe_next; + vfs_unbusy(mp, p); } + simple_unlock(&mountlist_slock); *sizep = bp - where; return (0); @@ -1140,22 +1564,46 @@ again: */ int vfs_mountedon(vp) - register struct vnode *vp; + struct vnode *vp; { - register struct vnode *vq; + struct vnode *vq; + int error = 0; if (vp->v_specflags & SI_MOUNTEDON) return (EBUSY); if (vp->v_flag & VALIASED) { + simple_lock(&spechash_slock); for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type) continue; - if (vq->v_specflags & SI_MOUNTEDON) - return (EBUSY); + if (vq->v_specflags & SI_MOUNTEDON) { + error = EBUSY; + break; + } } + simple_unlock(&spechash_slock); + } + return (error); +} + +/* + * Unmount all filesystems. The list is traversed in reverse order + * of mounting to avoid dependencies. + */ +void +vfs_unmountall() +{ + struct mount *mp, *nmp; + struct proc *p = curproc; /* XXX */ + + /* + * Since this only runs when rebooting, it is not interlocked. + */ + for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) { + nmp = mp->mnt_list.cqe_prev; + (void) dounmount(mp, MNT_FORCE, p); } - return (0); } /* @@ -1221,9 +1669,21 @@ vfs_hang_addrlist(mp, nep, argp) } rn = (*rnh->rnh_addaddr)((caddr_t)saddr, (caddr_t)smask, rnh, np->netc_rnodes); - if (rn == 0 || np != (struct netcred *)rn) { /* already exists */ - error = EPERM; - goto out; + if (rn == 0) { + /* + * One of the reasons that rnh_addaddr may fail is that + * the entry already exists. To check for this case, we + * look up the entry to see if it is there. If so, we + * do not need to make a new entry but do return success. + */ + free(np, M_NETADDR); + rn = (*rnh->rnh_matchaddr)((caddr_t)saddr, rnh); + if (rn != 0 && (rn->rn_flags & RNF_ROOT) == 0 && + ((struct netcred *)rn)->netc_exflags == argp->ex_flags && + !bcmp((caddr_t)&((struct netcred *)rn)->netc_anon, + (caddr_t)&argp->ex_anon, sizeof(struct ucred))) + return (0); + return (EPERM); } np->netc_exflags = argp->ex_flags; np->netc_anon = argp->ex_anon; @@ -1246,7 +1706,7 @@ vfs_free_netcred(rn, w) free((caddr_t)rn, M_NETADDR); return (0); } - + /* * Free the net address hash lists that are hanging off the mount points. */ diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 345c7a7..0cf7680 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 + * @(#)vfs_syscalls.c 8.41 (Berkeley) 6/15/95 */ #include @@ -52,10 +52,13 @@ #include #include +#include + #include #include static int change_dir __P((struct nameidata *ndp, struct proc *p)); +static void checkdirs __P((struct vnode *olddp)); /* * Virtual File System System Calls @@ -64,36 +67,36 @@ static int change_dir __P((struct nameidata *ndp, struct proc *p)); /* * Mount a file system. */ -struct mount_args { - int type; - char *path; - int flags; - caddr_t data; -}; /* ARGSUSED */ +int mount(p, uap, retval) struct proc *p; - register struct mount_args *uap; - int *retval; + register struct mount_args /* { + syscallarg(char *) type; + syscallarg(char *) path; + syscallarg(int) flags; + syscallarg(caddr_t) data; + } */ *uap; + register_t *retval; { - register struct vnode *vp; - register struct mount *mp; + struct vnode *vp; + struct mount *mp; + struct vfsconf *vfsp; int error, flag; + struct vattr va; + u_long fstypenum; struct nameidata nd; + char fstypename[MFSNAMELEN]; /* - * Must be super user - */ - if (error = suser(p->p_ucred, &p->p_acflag)) - return (error); - /* * Get vnode to be covered */ - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; - if (uap->flags & MNT_UPDATE) { + if (SCARG(uap, flags) & MNT_UPDATE) { if ((vp->v_flag & VROOT) == 0) { vput(vp); return (EINVAL); @@ -104,63 +107,134 @@ mount(p, uap, retval) * We only allow the filesystem to be reloaded if it * is currently mounted read-only. */ - if ((uap->flags & MNT_RELOAD) && + if ((SCARG(uap, flags) & MNT_RELOAD) && ((mp->mnt_flag & MNT_RDONLY) == 0)) { vput(vp); return (EOPNOTSUPP); /* Needs translation */ } mp->mnt_flag |= - uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); - VOP_UNLOCK(vp); + SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); + /* + * Only root, or the user that did the original mount is + * permitted to update it. + */ + if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && + (error = suser(p->p_ucred, &p->p_acflag))) { + vput(vp); + return (error); + } + /* + * Do not allow NFS export by non-root users. Silently + * enforce MNT_NOSUID and MNT_NODEV for non-root users. + */ + if (p->p_ucred->cr_uid != 0) { + if (SCARG(uap, flags) & MNT_EXPORTED) { + vput(vp); + return (EPERM); + } + SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; + } + if (vfs_busy(mp, LK_NOWAIT, 0, p)) { + vput(vp); + return (EBUSY); + } + VOP_UNLOCK(vp, 0, p); goto update; } + /* + * If the user is not root, ensure that they own the directory + * onto which we are attempting to mount. + */ + if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) || + (va.va_uid != p->p_ucred->cr_uid && + (error = suser(p->p_ucred, &p->p_acflag)))) { + vput(vp); + return (error); + } + /* + * Do not allow NFS export by non-root users. Silently + * enforce MNT_NOSUID and MNT_NODEV for non-root users. + */ + if (p->p_ucred->cr_uid != 0) { + if (SCARG(uap, flags) & MNT_EXPORTED) { + vput(vp); + return (EPERM); + } + SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; + } if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) return (error); if (vp->v_type != VDIR) { vput(vp); return (ENOTDIR); } - if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) { - vput(vp); - return (ENODEV); - } - +#ifdef COMPAT_43 /* - * Allocate and initialize the file system. + * Historically filesystem types were identified by number. If we + * get an integer for the filesystem type instead of a string, we + * check to see if it matches one of the historic filesystem types. */ - mp = (struct mount *)malloc((u_long)sizeof(struct mount), - M_MOUNT, M_WAITOK); - bzero((char *)mp, (u_long)sizeof(struct mount)); - mp->mnt_op = vfssw[uap->type]; - if (error = vfs_lock(mp)) { - free((caddr_t)mp, M_MOUNT); + fstypenum = (u_long)SCARG(uap, type); + if (fstypenum < maxvfsconf) { + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) + if (vfsp->vfc_typenum == fstypenum) + break; + if (vfsp == NULL) { + vput(vp); + return (ENODEV); + } + strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN); + } else +#endif /* COMPAT_43 */ + if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) { vput(vp); return (error); } + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) + if (!strcmp(vfsp->vfc_name, fstypename)) + break; + if (vfsp == NULL) { + vput(vp); + return (ENODEV); + } if (vp->v_mountedhere != NULL) { - vfs_unlock(mp); - free((caddr_t)mp, M_MOUNT); vput(vp); return (EBUSY); } + + /* + * Allocate and initialize the filesystem. + */ + mp = (struct mount *)malloc((u_long)sizeof(struct mount), + M_MOUNT, M_WAITOK); + bzero((char *)mp, (u_long)sizeof(struct mount)); + lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); + (void)vfs_busy(mp, LK_NOWAIT, 0, p); + mp->mnt_op = vfsp->vfc_vfsops; + mp->mnt_vfc = vfsp; + vfsp->vfc_refcount++; + mp->mnt_stat.f_type = vfsp->vfc_typenum; + mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; + strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); vp->v_mountedhere = mp; mp->mnt_vnodecovered = vp; + mp->mnt_stat.f_owner = p->p_ucred->cr_uid; update: /* * Set the mount level flags. */ - if (uap->flags & MNT_RDONLY) + if (SCARG(uap, flags) & MNT_RDONLY) mp->mnt_flag |= MNT_RDONLY; else if (mp->mnt_flag & MNT_RDONLY) mp->mnt_flag |= MNT_WANTRDWR; mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC); - mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | - MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC); + mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC | + MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC); /* * Mount the filesystem. */ - error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p); + error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); if (mp->mnt_flag & MNT_UPDATE) { vrele(vp); if (mp->mnt_flag & MNT_WANTRDWR) @@ -169,6 +243,7 @@ update: (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR); if (error) mp->mnt_flag = flag; + vfs_unbusy(mp, p); return (error); } /* @@ -176,13 +251,18 @@ update: */ cache_purge(vp); if (!error) { - TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); - VOP_UNLOCK(vp); - vfs_unlock(mp); - error = VFS_START(mp, 0, p); + simple_lock(&mountlist_slock); + CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); + simple_unlock(&mountlist_slock); + checkdirs(vp); + VOP_UNLOCK(vp, 0, p); + vfs_unbusy(mp, p); + if (error = VFS_START(mp, 0, p)) + vrele(vp); } else { mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; - vfs_unlock(mp); + mp->mnt_vfc->vfc_refcount--; + vfs_unbusy(mp, p); free((caddr_t)mp, M_MOUNT); vput(vp); } @@ -190,56 +270,104 @@ update: } /* + * Scan all active processes to see if any of them have a current + * or root directory onto which the new filesystem has just been + * mounted. If so, replace them with the new mount point. + */ +static void +checkdirs(olddp) + struct vnode *olddp; +{ + struct filedesc *fdp; + struct vnode *newdp; + struct proc *p; + + if (olddp->v_usecount == 1) + return; + if (VFS_ROOT(olddp->v_mountedhere, &newdp)) + panic("mount: lost mount"); + for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { + fdp = p->p_fd; + if (fdp->fd_cdir == olddp) { + vrele(fdp->fd_cdir); + VREF(newdp); + fdp->fd_cdir = newdp; + } + if (fdp->fd_rdir == olddp) { + vrele(fdp->fd_rdir); + VREF(newdp); + fdp->fd_rdir = newdp; + } + } + if (rootvnode == olddp) { + vrele(rootvnode); + VREF(newdp); + rootvnode = newdp; + } + vput(newdp); +} + +/* * Unmount a file system. * * Note: unmount takes a path to the vnode mounted on as argument, * not special file (as before). */ -struct unmount_args { - char *path; - int flags; -}; /* ARGSUSED */ +int unmount(p, uap, retval) struct proc *p; - register struct unmount_args *uap; - int *retval; + register struct unmount_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct mount *mp; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; + mp = vp->v_mount; /* - * Unless this is a user mount, then must - * have suser privilege. + * Only root, or the user that did the original mount is + * permitted to unmount this filesystem. */ - if (((vp->v_mount->mnt_flag & MNT_USER) == 0) && + if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && (error = suser(p->p_ucred, &p->p_acflag))) { vput(vp); return (error); } /* + * Don't allow unmounting the root file system. + */ + if (mp->mnt_flag & MNT_ROOTFS) { + vput(vp); + return (EINVAL); + } + + /* * Must be the root of the filesystem */ if ((vp->v_flag & VROOT) == 0) { vput(vp); return (EINVAL); } - mp = vp->v_mount; vput(vp); - return (dounmount(mp, uap->flags, p)); + return (dounmount(mp, SCARG(uap, flags), p)); } /* * Do the actual file system unmount. */ +int dounmount(mp, flags, p) register struct mount *mp; int flags; @@ -248,71 +376,74 @@ dounmount(mp, flags, p) struct vnode *coveredvp; int error; - coveredvp = mp->mnt_vnodecovered; - if (vfs_busy(mp)) - return (EBUSY); + simple_lock(&mountlist_slock); mp->mnt_flag |= MNT_UNMOUNT; - if (error = vfs_lock(mp)) - return (error); - + lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p); mp->mnt_flag &=~ MNT_ASYNC; vnode_pager_umount(mp); /* release cached vnodes */ cache_purgevfs(mp); /* remove cache entries for this file sys */ - if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 || + if (((mp->mnt_flag & MNT_RDONLY) || + (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || (flags & MNT_FORCE)) error = VFS_UNMOUNT(mp, flags, p); - mp->mnt_flag &= ~MNT_UNMOUNT; - vfs_unbusy(mp); + simple_lock(&mountlist_slock); if (error) { - vfs_unlock(mp); - } else { + mp->mnt_flag &= ~MNT_UNMOUNT; + lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, + &mountlist_slock, p); + return (error); + } + CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); + if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { + coveredvp->v_mountedhere = (struct mount *)0; vrele(coveredvp); - TAILQ_REMOVE(&mountlist, mp, mnt_list); - mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; - vfs_unlock(mp); - if (mp->mnt_vnodelist.lh_first != NULL) - panic("unmount: dangling vnode"); - free((caddr_t)mp, M_MOUNT); } - return (error); + mp->mnt_vfc->vfc_refcount--; + if (mp->mnt_vnodelist.lh_first != NULL) + panic("unmount: dangling vnode"); + lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p); + if (mp->mnt_flag & MNT_MWAIT) + wakeup((caddr_t)mp); + free((caddr_t)mp, M_MOUNT); + return (0); } /* * Sync each mounted filesystem. */ -#ifdef DIAGNOSTIC +#ifdef DEBUG int syncprt = 0; struct ctldebug debug0 = { "syncprt", &syncprt }; #endif -struct sync_args { - int dummy; -}; /* ARGSUSED */ +int sync(p, uap, retval) struct proc *p; - struct sync_args *uap; - int *retval; + void *uap; + register_t *retval; { register struct mount *mp, *nmp; int asyncflag; - for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) { - nmp = mp->mnt_list.tqe_next; - /* - * The lock check below is to avoid races with mount - * and unmount. - */ - if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && - !vfs_busy(mp)) { + simple_lock(&mountlist_slock); + for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { + if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { + nmp = mp->mnt_list.cqe_next; + continue; + } + if ((mp->mnt_flag & MNT_RDONLY) == 0) { asyncflag = mp->mnt_flag & MNT_ASYNC; mp->mnt_flag &= ~MNT_ASYNC; VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); if (asyncflag) mp->mnt_flag |= MNT_ASYNC; - vfs_unbusy(mp); } + simple_lock(&mountlist_slock); + nmp = mp->mnt_list.cqe_next; + vfs_unbusy(mp, p); } + simple_unlock(&mountlist_slock); #ifdef DIAGNOSTIC if (syncprt) vfs_bufstats(); @@ -323,49 +454,50 @@ sync(p, uap, retval) /* * Change filesystem quotas. */ -struct quotactl_args { - char *path; - int cmd; - int uid; - caddr_t arg; -}; /* ARGSUSED */ +int quotactl(p, uap, retval) struct proc *p; - register struct quotactl_args *uap; - int *retval; + register struct quotactl_args /* { + syscallarg(char *) path; + syscallarg(int) cmd; + syscallarg(int) uid; + syscallarg(caddr_t) arg; + } */ *uap; + register_t *retval; { register struct mount *mp; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); mp = nd.ni_vp->v_mount; vrele(nd.ni_vp); - return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p)); + return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), + SCARG(uap, arg), p)); } /* * Get filesystem statistics. */ -struct statfs_args { - char *path; - struct statfs *buf; -}; /* ARGSUSED */ +int statfs(p, uap, retval) struct proc *p; - register struct statfs_args *uap; - int *retval; + register struct statfs_args /* { + syscallarg(char *) path; + syscallarg(struct statfs *) buf; + } */ *uap; + register_t *retval; { register struct mount *mp; register struct statfs *sp; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); mp = nd.ni_vp->v_mount; @@ -374,77 +506,89 @@ statfs(p, uap, retval) if (error = VFS_STATFS(mp, sp, p)) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); + return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); } /* * Get filesystem statistics. */ -struct fstatfs_args { - int fd; - struct statfs *buf; -}; /* ARGSUSED */ +int fstatfs(p, uap, retval) struct proc *p; - register struct fstatfs_args *uap; - int *retval; + register struct fstatfs_args /* { + syscallarg(int) fd; + syscallarg(struct statfs *) buf; + } */ *uap; + register_t *retval; { struct file *fp; struct mount *mp; register struct statfs *sp; int error; - if (error = getvnode(p->p_fd, uap->fd, &fp)) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); mp = ((struct vnode *)fp->f_data)->v_mount; sp = &mp->mnt_stat; if (error = VFS_STATFS(mp, sp, p)) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); + return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); } /* * Get statistics on all filesystems. */ -struct getfsstat_args { - struct statfs *buf; - long bufsize; - int flags; -}; +int getfsstat(p, uap, retval) struct proc *p; - register struct getfsstat_args *uap; - int *retval; + register struct getfsstat_args /* { + syscallarg(struct statfs *) buf; + syscallarg(long) bufsize; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { register struct mount *mp, *nmp; register struct statfs *sp; caddr_t sfsp; long count, maxcount, error; - maxcount = uap->bufsize / sizeof(struct statfs); - sfsp = (caddr_t)uap->buf; - for (count = 0, mp = mountlist.tqh_first; mp != NULL; mp = nmp) { - nmp = mp->mnt_list.tqe_next; - if (sfsp && count < maxcount && - ((mp->mnt_flag & MNT_MLOCK) == 0)) { + maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); + sfsp = (caddr_t)SCARG(uap, buf); + count = 0; + simple_lock(&mountlist_slock); + for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { + if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { + nmp = mp->mnt_list.cqe_next; + continue; + } + if (sfsp && count < maxcount) { sp = &mp->mnt_stat; /* * If MNT_NOWAIT is specified, do not refresh the * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. */ - if (((uap->flags & MNT_NOWAIT) == 0 || - (uap->flags & MNT_WAIT)) && - (error = VFS_STATFS(mp, sp, p))) + if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 || + (SCARG(uap, flags) & MNT_WAIT)) && + (error = VFS_STATFS(mp, sp, p))) { + simple_lock(&mountlist_slock); + nmp = mp->mnt_list.cqe_next; + vfs_unbusy(mp, p); continue; + } sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp))) return (error); sfsp += sizeof(*sp); } count++; + simple_lock(&mountlist_slock); + nmp = mp->mnt_list.cqe_next; + vfs_unbusy(mp, p); } + simple_unlock(&mountlist_slock); if (sfsp && count > maxcount) *retval = maxcount; else @@ -455,32 +599,45 @@ getfsstat(p, uap, retval) /* * Change current working directory to a given file descriptor. */ -struct fchdir_args { - int fd; -}; /* ARGSUSED */ +int fchdir(p, uap, retval) struct proc *p; - struct fchdir_args *uap; - int *retval; + struct fchdir_args /* { + syscallarg(int) fd; + } */ *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; - register struct vnode *vp; + struct vnode *vp, *tdp; + struct mount *mp; struct file *fp; int error; - if (error = getvnode(fdp, uap->fd, &fp)) + if (error = getvnode(fdp, SCARG(uap, fd), &fp)) return (error); vp = (struct vnode *)fp->f_data; - VOP_LOCK(vp); + VREF(vp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); if (vp->v_type != VDIR) error = ENOTDIR; else error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); - VOP_UNLOCK(vp); - if (error) + while (!error && (mp = vp->v_mountedhere) != NULL) { + if (vfs_busy(mp, 0, 0, p)) + continue; + error = VFS_ROOT(mp, &tdp); + vfs_unbusy(mp, p); + if (error) + break; + vput(vp); + vp = tdp; + } + if (error) { + vput(vp); return (error); - VREF(vp); + } + VOP_UNLOCK(vp, 0, p); vrele(fdp->fd_cdir); fdp->fd_cdir = vp; return (0); @@ -489,20 +646,21 @@ fchdir(p, uap, retval) /* * Change current working directory (``.''). */ -struct chdir_args { - char *path; -}; /* ARGSUSED */ +int chdir(p, uap, retval) struct proc *p; - struct chdir_args *uap; - int *retval; + struct chdir_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); if (error = change_dir(&nd, p)) return (error); vrele(fdp->fd_cdir); @@ -513,14 +671,14 @@ chdir(p, uap, retval) /* * Change notion of root (``/'') directory. */ -struct chroot_args { - char *path; -}; /* ARGSUSED */ +int chroot(p, uap, retval) struct proc *p; - struct chroot_args *uap; - int *retval; + struct chroot_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; int error; @@ -528,7 +686,8 @@ chroot(p, uap, retval) if (error = suser(p->p_ucred, &p->p_acflag)) return (error); - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); if (error = change_dir(&nd, p)) return (error); if (fdp->fd_rdir != NULL) @@ -555,9 +714,10 @@ change_dir(ndp, p) error = ENOTDIR; else error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); - VOP_UNLOCK(vp); if (error) - vrele(vp); + vput(vp); + else + VOP_UNLOCK(vp, 0, p); return (error); } @@ -565,15 +725,15 @@ change_dir(ndp, p) * Check permissions, allocate an open file structure, * and call the device open routine if any. */ -struct open_args { - char *path; - int flags; - int mode; -}; +int open(p, uap, retval) struct proc *p; - register struct open_args *uap; - int *retval; + register struct open_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { register struct filedesc *fdp = p->p_fd; register struct file *fp; @@ -588,16 +748,16 @@ open(p, uap, retval) if (error = falloc(p, &nfp, &indx)) return (error); fp = nfp; - flags = FFLAGS(uap->flags); - cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + flags = FFLAGS(SCARG(uap, flags)); + cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); p->p_dupfd = -indx - 1; /* XXX check for fdopen */ if (error = vn_open(&nd, flags, cmode)) { ffree(fp); if ((error == ENODEV || error == ENXIO) && - p->p_dupfd >= 0 && /* XXX from fdopen */ + p->p_dupfd >= 0 && /* XXX from fdopen */ (error = - dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { + dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { *retval = indx; return (0); } @@ -623,17 +783,17 @@ open(p, uap, retval) type = F_FLOCK; if ((flags & FNONBLOCK) == 0) type |= F_WAIT; - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { (void) vn_close(vp, fp->f_flag, fp->f_cred, p); ffree(fp); fdp->fd_ofiles[indx] = NULL; return (error); } - VOP_LOCK(vp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); fp->f_flag |= FHASLOCK; } - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); *retval = indx; return (0); } @@ -642,46 +802,51 @@ open(p, uap, retval) /* * Create a file. */ -struct ocreat_args { - char *path; - int mode; -}; -ocreat(p, uap, retval) +int +compat_43_creat(p, uap, retval) struct proc *p; - register struct ocreat_args *uap; - int *retval; + register struct compat_43_creat_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { - struct open_args openuap; - - openuap.path = uap->path; - openuap.mode = uap->mode; - openuap.flags = O_WRONLY | O_CREAT | O_TRUNC; - return (open(p, &openuap, retval)); + struct open_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + syscallarg(int) mode; + } */ nuap; + + SCARG(&nuap, path) = SCARG(uap, path); + SCARG(&nuap, mode) = SCARG(uap, mode); + SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; + return (open(p, &nuap, retval)); } #endif /* COMPAT_43 */ /* * Create a special file. */ -struct mknod_args { - char *path; - int mode; - int dev; -}; /* ARGSUSED */ +int mknod(p, uap, retval) struct proc *p; - register struct mknod_args *uap; - int *retval; + register struct mknod_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + syscallarg(int) dev; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; + int whiteout; struct nameidata nd; if (error = suser(p->p_ucred, &p->p_acflag)) return (error); - NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; @@ -689,10 +854,11 @@ mknod(p, uap, retval) error = EEXIST; else { VATTR_NULL(&vattr); - vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; - vattr.va_rdev = uap->dev; + vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; + vattr.va_rdev = SCARG(uap, dev); + whiteout = 0; - switch (uap->mode & S_IFMT) { + switch (SCARG(uap, mode) & S_IFMT) { case S_IFMT: /* used by badsect to flag bad sectors */ vattr.va_type = VBAD; break; @@ -702,14 +868,25 @@ mknod(p, uap, retval) case S_IFBLK: vattr.va_type = VBLK; break; + case S_IFWHT: + whiteout = 1; + break; default: error = EINVAL; break; } } if (!error) { - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); - error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + if (whiteout) { + error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); + if (error) + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + vput(nd.ni_dvp); + } else { + error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, + &nd.ni_cnd, &vattr); + } } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == vp) @@ -723,17 +900,17 @@ mknod(p, uap, retval) } /* - * Create named pipe. + * Create a named pipe. */ -struct mkfifo_args { - char *path; - int mode; -}; /* ARGSUSED */ +int mkfifo(p, uap, retval) struct proc *p; - register struct mkfifo_args *uap; - int *retval; + register struct mkfifo_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { struct vattr vattr; int error; @@ -742,7 +919,7 @@ mkfifo(p, uap, retval) #ifndef FIFO return (EOPNOTSUPP); #else - NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); if (nd.ni_vp != NULL) { @@ -756,8 +933,8 @@ mkfifo(p, uap, retval) } VATTR_NULL(&vattr); vattr.va_type = VFIFO; - vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask; - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); #endif /* FIFO */ } @@ -765,21 +942,21 @@ mkfifo(p, uap, retval) /* * Make a hard file link. */ -struct link_args { - char *path; - char *link; -}; /* ARGSUSED */ +int link(p, uap, retval) struct proc *p; - register struct link_args *uap; - int *retval; + register struct link_args /* { + syscallarg(char *) path; + syscallarg(char *) link; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct nameidata nd; int error; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; @@ -787,16 +964,15 @@ link(p, uap, retval) (error = suser(p->p_ucred, &p->p_acflag)) == 0) { nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT; - nd.ni_dirp = uap->link; + nd.ni_dirp = SCARG(uap, link); if ((error = namei(&nd)) == 0) { if (nd.ni_vp != NULL) error = EEXIST; if (!error) { - LEASE_CHECK(nd.ni_dvp, - p, p->p_ucred, LEASE_WRITE); - LEASE_CHECK(vp, - p, p->p_ucred, LEASE_WRITE); - error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, + LEASE_WRITE); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + error = VOP_LINK(vp, nd.ni_dvp, &nd.ni_cnd); } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) @@ -815,15 +991,15 @@ link(p, uap, retval) /* * Make a symbolic link. */ -struct symlink_args { - char *path; - char *link; -}; /* ARGSUSED */ +int symlink(p, uap, retval) struct proc *p; - register struct symlink_args *uap; - int *retval; + register struct symlink_args /* { + syscallarg(char *) path; + syscallarg(char *) link; + } */ *uap; + register_t *retval; { struct vattr vattr; char *path; @@ -831,9 +1007,9 @@ symlink(p, uap, retval) struct nameidata nd; MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); - if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL)) + if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) goto out; - NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p); + NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); if (error = namei(&nd)) goto out; if (nd.ni_vp) { @@ -848,7 +1024,7 @@ symlink(p, uap, retval) } VATTR_NULL(&vattr); vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); out: FREE(path, M_NAMEI); @@ -856,27 +1032,66 @@ out: } /* + * Delete a whiteout from the filesystem. + */ +/* ARGSUSED */ +int +undelete(p, uap, retval) + struct proc *p; + register struct undelete_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; +{ + int error; + struct nameidata nd; + + NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, + SCARG(uap, path), p); + error = namei(&nd); + if (error) + return (error); + + if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); + else + vput(nd.ni_dvp); + if (nd.ni_vp) + vrele(nd.ni_vp); + return (EEXIST); + } + + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + vput(nd.ni_dvp); + return (error); +} + +/* * Delete a name from the filesystem. */ -struct unlink_args { - char *path; -}; /* ARGSUSED */ +int unlink(p, uap, retval) struct proc *p; - struct unlink_args *uap; - int *retval; + struct unlink_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; { register struct vnode *vp; int error; struct nameidata nd; - NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); if (vp->v_type != VDIR || (error = suser(p->p_ucred, &p->p_acflag)) == 0) { @@ -890,7 +1105,7 @@ unlink(p, uap, retval) } if (!error) { - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); @@ -898,7 +1113,8 @@ unlink(p, uap, retval) vrele(nd.ni_dvp); else vput(nd.ni_dvp); - vput(vp); + if (vp != NULLVP) + vput(vp); } return (error); } @@ -906,16 +1122,16 @@ unlink(p, uap, retval) /* * Reposition read/write file offset. */ -struct lseek_args { - int fd; - int pad; - off_t offset; - int whence; -}; +int lseek(p, uap, retval) struct proc *p; - register struct lseek_args *uap; - int *retval; + register struct lseek_args /* { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) offset; + syscallarg(int) whence; + } */ *uap; + register_t *retval; { struct ucred *cred = p->p_ucred; register struct filedesc *fdp = p->p_fd; @@ -923,23 +1139,23 @@ lseek(p, uap, retval) struct vattr vattr; int error; - if ((u_int)uap->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[uap->fd]) == NULL) + if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) return (EBADF); if (fp->f_type != DTYPE_VNODE) return (ESPIPE); - switch (uap->whence) { + switch (SCARG(uap, whence)) { case L_INCR: - fp->f_offset += uap->offset; + fp->f_offset += SCARG(uap, offset); break; case L_XTND: if (error = VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p)) return (error); - fp->f_offset = uap->offset + vattr.va_size; + fp->f_offset = SCARG(uap, offset) + vattr.va_size; break; case L_SET: - fp->f_offset = uap->offset; + fp->f_offset = SCARG(uap, offset); break; default: return (EINVAL); @@ -952,23 +1168,28 @@ lseek(p, uap, retval) /* * Reposition read/write file offset. */ -struct olseek_args { - int fd; - long offset; - int whence; -}; -olseek(p, uap, retval) +int +compat_43_lseek(p, uap, retval) struct proc *p; - register struct olseek_args *uap; - int *retval; + register struct compat_43_lseek_args /* { + syscallarg(int) fd; + syscallarg(long) offset; + syscallarg(int) whence; + } */ *uap; + register_t *retval; { - struct lseek_args nuap; + struct lseek_args /* { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) offset; + syscallarg(int) whence; + } */ nuap; off_t qret; int error; - nuap.fd = uap->fd; - nuap.offset = uap->offset; - nuap.whence = uap->whence; + SCARG(&nuap, fd) = SCARG(uap, fd); + SCARG(&nuap, offset) = SCARG(uap, offset); + SCARG(&nuap, whence) = SCARG(uap, whence); error = lseek(p, &nuap, &qret); *(long *)retval = qret; return (error); @@ -978,14 +1199,14 @@ olseek(p, uap, retval) /* * Check access permissions. */ -struct access_args { - char *path; - int flags; -}; +int access(p, uap, retval) struct proc *p; - register struct access_args *uap; - int *retval; + register struct access_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { register struct ucred *cred = p->p_ucred; register struct vnode *vp; @@ -996,19 +1217,20 @@ access(p, uap, retval) t_gid = cred->cr_groups[0]; cred->cr_uid = p->p_cred->p_ruid; cred->cr_groups[0] = p->p_cred->p_rgid; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); if (error = namei(&nd)) goto out1; vp = nd.ni_vp; /* Flags == 0 means only check for existence. */ - if (uap->flags) { + if (SCARG(uap, flags)) { flags = 0; - if (uap->flags & R_OK) + if (SCARG(uap, flags) & R_OK) flags |= VREAD; - if (uap->flags & W_OK) + if (SCARG(uap, flags) & W_OK) flags |= VWRITE; - if (uap->flags & X_OK) + if (SCARG(uap, flags) & X_OK) flags |= VEXEC; if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) error = VOP_ACCESS(vp, flags, cred, p); @@ -1024,22 +1246,23 @@ out1: /* * Get file status; this version follows links. */ -struct ostat_args { - char *path; - struct ostat *ub; -}; /* ARGSUSED */ -ostat(p, uap, retval) +int +compat_43_stat(p, uap, retval) struct proc *p; - register struct ostat_args *uap; - int *retval; + register struct compat_43_stat_args /* { + syscallarg(char *) path; + syscallarg(struct ostat *) ub; + } */ *uap; + register_t *retval; { struct stat sb; struct ostat osb; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); if (error = namei(&nd)) return (error); error = vn_stat(nd.ni_vp, &sb, p); @@ -1047,43 +1270,74 @@ ostat(p, uap, retval) if (error) return (error); cvtstat(&sb, &osb); - error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); + error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); return (error); } /* * Get file status; this version does not follow links. */ -struct olstat_args { - char *path; - struct ostat *ub; -}; /* ARGSUSED */ -olstat(p, uap, retval) +int +compat_43_lstat(p, uap, retval) struct proc *p; - register struct olstat_args *uap; - int *retval; + register struct compat_43_lstat_args /* { + syscallarg(char *) path; + syscallarg(struct ostat *) ub; + } */ *uap; + register_t *retval; { - struct stat sb; + struct vnode *vp, *dvp; + struct stat sb, sb1; struct ostat osb; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, + SCARG(uap, path), p); if (error = namei(&nd)) return (error); - error = vn_stat(nd.ni_vp, &sb, p); - vput(nd.ni_vp); - if (error) - return (error); + /* + * For symbolic links, always return the attributes of its + * containing directory, except for mode, size, and links. + */ + vp = nd.ni_vp; + dvp = nd.ni_dvp; + if (vp->v_type != VLNK) { + if (dvp == vp) + vrele(dvp); + else + vput(dvp); + error = vn_stat(vp, &sb, p); + vput(vp); + if (error) + return (error); + } else { + error = vn_stat(dvp, &sb, p); + vput(dvp); + if (error) { + vput(vp); + return (error); + } + error = vn_stat(vp, &sb1, p); + vput(vp); + if (error) + return (error); + sb.st_mode &= ~S_IFDIR; + sb.st_mode |= S_IFLNK; + sb.st_nlink = sb1.st_nlink; + sb.st_size = sb1.st_size; + sb.st_blocks = sb1.st_blocks; + } cvtstat(&sb, &osb); - error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); + error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); return (error); } /* * Convert from an old to a new stat structure. */ +void cvtstat(st, ost) struct stat *st; struct ostat *ost; @@ -1113,43 +1367,44 @@ cvtstat(st, ost) /* * Get file status; this version follows links. */ -struct stat_args { - char *path; - struct stat *ub; -}; /* ARGSUSED */ +int stat(p, uap, retval) struct proc *p; - register struct stat_args *uap; - int *retval; + register struct stat_args /* { + syscallarg(char *) path; + syscallarg(struct stat *) ub; + } */ *uap; + register_t *retval; { struct stat sb; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); if (error = namei(&nd)) return (error); error = vn_stat(nd.ni_vp, &sb, p); vput(nd.ni_vp); if (error) return (error); - error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); + error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); return (error); } /* * Get file status; this version does not follow links. */ -struct lstat_args { - char *path; - struct stat *ub; -}; /* ARGSUSED */ +int lstat(p, uap, retval) struct proc *p; - register struct lstat_args *uap; - int *retval; + register struct lstat_args /* { + syscallarg(char *) path; + syscallarg(struct stat *) ub; + } */ *uap; + register_t *retval; { int error; struct vnode *vp, *dvp; @@ -1157,12 +1412,12 @@ lstat(p, uap, retval) struct nameidata nd; NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, - uap->path, p); + SCARG(uap, path), p); if (error = namei(&nd)) return (error); /* - * For symbolic links, always return the attributes of its - * containing directory, except for mode, size, and links. + * For symbolic links, always return the attributes of its containing + * directory, except for mode, size, inode number, and links. */ vp = nd.ni_vp; dvp = nd.ni_dvp; @@ -1191,31 +1446,33 @@ lstat(p, uap, retval) sb.st_nlink = sb1.st_nlink; sb.st_size = sb1.st_size; sb.st_blocks = sb1.st_blocks; + sb.st_ino = sb1.st_ino; } - error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); + error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); return (error); } /* * Get configurable pathname variables. */ -struct pathconf_args { - char *path; - int name; -}; /* ARGSUSED */ +int pathconf(p, uap, retval) struct proc *p; - register struct pathconf_args *uap; - int *retval; + register struct pathconf_args /* { + syscallarg(char *) path; + syscallarg(int) name; + } */ *uap; + register_t *retval; { int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); if (error = namei(&nd)) return (error); - error = VOP_PATHCONF(nd.ni_vp, uap->name, retval); + error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); vput(nd.ni_vp); return (error); } @@ -1223,16 +1480,16 @@ pathconf(p, uap, retval) /* * Return target name of a symbolic link. */ -struct readlink_args { - char *path; - char *buf; - int count; -}; /* ARGSUSED */ +int readlink(p, uap, retval) struct proc *p; - register struct readlink_args *uap; - int *retval; + register struct readlink_args /* { + syscallarg(char *) path; + syscallarg(char *) buf; + syscallarg(int) count; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct iovec aiov; @@ -1240,60 +1497,57 @@ readlink(p, uap, retval) int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; if (vp->v_type != VLNK) error = EINVAL; else { - aiov.iov_base = uap->buf; - aiov.iov_len = uap->count; + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, count); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; - auio.uio_resid = uap->count; + auio.uio_resid = SCARG(uap, count); error = VOP_READLINK(vp, &auio, p->p_ucred); } vput(vp); - *retval = uap->count - auio.uio_resid; + *retval = SCARG(uap, count) - auio.uio_resid; return (error); } /* * Change flags of a file given a path name. */ -struct chflags_args { - char *path; - int flags; -}; /* ARGSUSED */ +int chflags(p, uap, retval) struct proc *p; - register struct chflags_args *uap; - int *retval; + register struct chflags_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_flags = uap->flags; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VATTR_NULL(&vattr); + vattr.va_flags = SCARG(uap, flags); + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } @@ -1301,68 +1555,60 @@ chflags(p, uap, retval) /* * Change flags of a file given a file descriptor. */ -struct fchflags_args { - int fd; - int flags; -}; /* ARGSUSED */ +int fchflags(p, uap, retval) struct proc *p; - register struct fchflags_args *uap; - int *retval; + register struct fchflags_args /* { + syscallarg(int) fd; + syscallarg(int) flags; + } */ *uap; + register_t *retval; { struct vattr vattr; struct vnode *vp; struct file *fp; int error; - if (error = getvnode(p->p_fd, uap->fd, &fp)) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); vp = (struct vnode *)fp->f_data; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_flags = uap->flags; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } - VOP_UNLOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VATTR_NULL(&vattr); + vattr.va_flags = SCARG(uap, flags); + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); + VOP_UNLOCK(vp, 0, p); return (error); } /* * Change mode of a file given path name. */ -struct chmod_args { - char *path; - int mode; -}; /* ARGSUSED */ +int chmod(p, uap, retval) struct proc *p; - register struct chmod_args *uap; - int *retval; + register struct chmod_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_mode = uap->mode & ALLPERMS; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VATTR_NULL(&vattr); + vattr.va_mode = SCARG(uap, mode) & ALLPERMS; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } @@ -1370,70 +1616,62 @@ chmod(p, uap, retval) /* * Change mode of a file given a file descriptor. */ -struct fchmod_args { - int fd; - int mode; -}; /* ARGSUSED */ +int fchmod(p, uap, retval) struct proc *p; - register struct fchmod_args *uap; - int *retval; + register struct fchmod_args /* { + syscallarg(int) fd; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { struct vattr vattr; struct vnode *vp; struct file *fp; int error; - if (error = getvnode(p->p_fd, uap->fd, &fp)) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); vp = (struct vnode *)fp->f_data; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_mode = uap->mode & ALLPERMS; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } - VOP_UNLOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VATTR_NULL(&vattr); + vattr.va_mode = SCARG(uap, mode) & ALLPERMS; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); + VOP_UNLOCK(vp, 0, p); return (error); } /* * Set ownership given a path name. */ -struct chown_args { - char *path; - int uid; - int gid; -}; /* ARGSUSED */ +int chown(p, uap, retval) struct proc *p; - register struct chown_args *uap; - int *retval; + register struct chown_args /* { + syscallarg(char *) path; + syscallarg(int) uid; + syscallarg(int) gid; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_uid = uap->uid; - vattr.va_gid = uap->gid; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VATTR_NULL(&vattr); + vattr.va_uid = SCARG(uap, uid); + vattr.va_gid = SCARG(uap, gid); + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } @@ -1441,51 +1679,47 @@ chown(p, uap, retval) /* * Set ownership given a file descriptor. */ -struct fchown_args { - int fd; - int uid; - int gid; -}; /* ARGSUSED */ +int fchown(p, uap, retval) struct proc *p; - register struct fchown_args *uap; - int *retval; + register struct fchown_args /* { + syscallarg(int) fd; + syscallarg(int) uid; + syscallarg(int) gid; + } */ *uap; + register_t *retval; { struct vattr vattr; struct vnode *vp; struct file *fp; int error; - if (error = getvnode(p->p_fd, uap->fd, &fp)) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); vp = (struct vnode *)fp->f_data; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - VATTR_NULL(&vattr); - vattr.va_uid = uap->uid; - vattr.va_gid = uap->gid; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } - VOP_UNLOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VATTR_NULL(&vattr); + vattr.va_uid = SCARG(uap, uid); + vattr.va_gid = SCARG(uap, gid); + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); + VOP_UNLOCK(vp, 0, p); return (error); } /* * Set the access and modification times of a file. */ -struct utimes_args { - char *path; - struct timeval *tptr; -}; /* ARGSUSED */ +int utimes(p, uap, retval) struct proc *p; - register struct utimes_args *uap; - int *retval; + register struct utimes_args /* { + syscallarg(char *) path; + syscallarg(struct timeval *) tptr; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct timeval tv[2]; @@ -1494,27 +1728,24 @@ utimes(p, uap, retval) struct nameidata nd; VATTR_NULL(&vattr); - if (uap->tptr == NULL) { + if (SCARG(uap, tptr) == NULL) { microtime(&tv[0]); tv[1] = tv[0]; vattr.va_vaflags |= VA_UTIMES_NULL; - } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) + } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, + sizeof (tv))) return (error); - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - vattr.va_atime.ts_sec = tv[0].tv_sec; - vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; - vattr.va_mtime.ts_sec = tv[1].tv_sec; - vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + vattr.va_atime.ts_sec = tv[0].tv_sec; + vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; + vattr.va_mtime.ts_sec = tv[1].tv_sec; + vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); vput(vp); return (error); } @@ -1522,34 +1753,34 @@ utimes(p, uap, retval) /* * Truncate a file given its path name. */ -struct truncate_args { - char *path; - int pad; - off_t length; -}; /* ARGSUSED */ +int truncate(p, uap, retval) struct proc *p; - register struct truncate_args *uap; - int *retval; + register struct truncate_args /* { + syscallarg(char *) path; + syscallarg(int) pad; + syscallarg(off_t) length; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); if (vp->v_type == VDIR) error = EISDIR; else if ((error = vn_writechk(vp)) == 0 && (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { VATTR_NULL(&vattr); - vattr.va_size = uap->length; + vattr.va_size = SCARG(uap, length); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } vput(vp); @@ -1559,37 +1790,37 @@ truncate(p, uap, retval) /* * Truncate a file given a file descriptor. */ -struct ftruncate_args { - int fd; - int pad; - off_t length; -}; /* ARGSUSED */ +int ftruncate(p, uap, retval) struct proc *p; - register struct ftruncate_args *uap; - int *retval; + register struct ftruncate_args /* { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) length; + } */ *uap; + register_t *retval; { struct vattr vattr; struct vnode *vp; struct file *fp; int error; - if (error = getvnode(p->p_fd, uap->fd, &fp)) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); if ((fp->f_flag & FWRITE) == 0) return (EINVAL); vp = (struct vnode *)fp->f_data; - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); - VOP_LOCK(vp); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); if (vp->v_type == VDIR) error = EISDIR; else if ((error = vn_writechk(vp)) == 0) { VATTR_NULL(&vattr); - vattr.va_size = uap->length; + vattr.va_size = SCARG(uap, length); error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); } - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (error); } @@ -1597,40 +1828,48 @@ ftruncate(p, uap, retval) /* * Truncate a file given its path name. */ -struct otruncate_args { - char *path; - long length; -}; /* ARGSUSED */ -otruncate(p, uap, retval) +int +compat_43_truncate(p, uap, retval) struct proc *p; - register struct otruncate_args *uap; - int *retval; + register struct compat_43_truncate_args /* { + syscallarg(char *) path; + syscallarg(long) length; + } */ *uap; + register_t *retval; { - struct truncate_args nuap; - - nuap.path = uap->path; - nuap.length = uap->length; + struct truncate_args /* { + syscallarg(char *) path; + syscallarg(int) pad; + syscallarg(off_t) length; + } */ nuap; + + SCARG(&nuap, path) = SCARG(uap, path); + SCARG(&nuap, length) = SCARG(uap, length); return (truncate(p, &nuap, retval)); } /* * Truncate a file given a file descriptor. */ -struct oftruncate_args { - int fd; - long length; -}; /* ARGSUSED */ -oftruncate(p, uap, retval) +int +compat_43_ftruncate(p, uap, retval) struct proc *p; - register struct oftruncate_args *uap; - int *retval; + register struct compat_43_ftruncate_args /* { + syscallarg(int) fd; + syscallarg(long) length; + } */ *uap; + register_t *retval; { - struct ftruncate_args nuap; - - nuap.fd = uap->fd; - nuap.length = uap->length; + struct ftruncate_args /* { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) length; + } */ nuap; + + SCARG(&nuap, fd) = SCARG(uap, fd); + SCARG(&nuap, length) = SCARG(uap, length); return (ftruncate(p, &nuap, retval)); } #endif /* COMPAT_43 || COMPAT_SUNOS */ @@ -1638,25 +1877,25 @@ oftruncate(p, uap, retval) /* * Sync an open file. */ -struct fsync_args { - int fd; -}; /* ARGSUSED */ +int fsync(p, uap, retval) struct proc *p; - struct fsync_args *uap; - int *retval; + struct fsync_args /* { + syscallarg(int) fd; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct file *fp; int error; - if (error = getvnode(p->p_fd, uap->fd, &fp)) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); vp = (struct vnode *)fp->f_data; - VOP_LOCK(vp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (error); } @@ -1664,27 +1903,27 @@ fsync(p, uap, retval) * Rename files. Source and destination must either both be directories, * or both not be directories. If target is a directory, it must be empty. */ -struct rename_args { - char *from; - char *to; -}; /* ARGSUSED */ +int rename(p, uap, retval) struct proc *p; - register struct rename_args *uap; - int *retval; + register struct rename_args /* { + syscallarg(char *) from; + syscallarg(char *) to; + } */ *uap; + register_t *retval; { register struct vnode *tvp, *fvp, *tdvp; struct nameidata fromnd, tond; int error; NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, - uap->from, p); + SCARG(uap, from), p); if (error = namei(&fromnd)) return (error); fvp = fromnd.ni_vp; NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, - UIO_USERSPACE, uap->to, p); + UIO_USERSPACE, SCARG(uap, to), p); if (error = namei(&tond)) { VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); vrele(fromnd.ni_dvp); @@ -1716,11 +1955,11 @@ rename(p, uap, retval) error = -1; out: if (!error) { - LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); if (fromnd.ni_dvp != tdvp) - LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); if (tvp) - LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); } else { @@ -1749,22 +1988,22 @@ out1: /* * Make a directory file. */ -struct mkdir_args { - char *path; - int mode; -}; /* ARGSUSED */ +int mkdir(p, uap, retval) struct proc *p; - register struct mkdir_args *uap; - int *retval; + register struct mkdir_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; @@ -1779,8 +2018,8 @@ mkdir(p, uap, retval) } VATTR_NULL(&vattr); vattr.va_type = VDIR; - vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); if (!error) vput(nd.ni_vp); @@ -1790,20 +2029,21 @@ mkdir(p, uap, retval) /* * Remove a directory file. */ -struct rmdir_args { - char *path; -}; /* ARGSUSED */ +int rmdir(p, uap, retval) struct proc *p; - struct rmdir_args *uap; - int *retval; + struct rmdir_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; { register struct vnode *vp; int error; struct nameidata nd; - NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; @@ -1825,8 +2065,8 @@ rmdir(p, uap, retval) error = EBUSY; out: if (!error) { - LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); - LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); @@ -1843,16 +2083,16 @@ out: /* * Read a block of directory entries in a file system independent format. */ -struct ogetdirentries_args { - int fd; - char *buf; - u_int count; - long *basep; -}; -ogetdirentries(p, uap, retval) +int +compat_43_getdirentries(p, uap, retval) struct proc *p; - register struct ogetdirentries_args *uap; - int *retval; + register struct compat_43_getdirentries_args /* { + syscallarg(int) fd; + syscallarg(char *) buf; + syscallarg(u_int) count; + syscallarg(long *) basep; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct file *fp; @@ -1860,29 +2100,31 @@ ogetdirentries(p, uap, retval) struct iovec aiov, kiov; struct dirent *dp, *edp; caddr_t dirbuf; - int error, readcnt; + int error, eofflag, readcnt; long loff; - if (error = getvnode(p->p_fd, uap->fd, &fp)) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); if ((fp->f_flag & FREAD) == 0) return (EBADF); vp = (struct vnode *)fp->f_data; +unionread: if (vp->v_type != VDIR) return (EINVAL); - aiov.iov_base = uap->buf; - aiov.iov_len = uap->count; + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, count); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; - auio.uio_resid = uap->count; - VOP_LOCK(vp); + auio.uio_resid = SCARG(uap, count); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); loff = auio.uio_offset = fp->f_offset; # if (BYTE_ORDER != LITTLE_ENDIAN) if (vp->v_mount->mnt_maxsymlinklen <= 0) { - error = VOP_READDIR(vp, &auio, fp->f_cred); + error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, + (int *)0, (u_long *)0); fp->f_offset = auio.uio_offset; } else # endif @@ -1890,13 +2132,14 @@ ogetdirentries(p, uap, retval) kuio = auio; kuio.uio_iov = &kiov; kuio.uio_segflg = UIO_SYSSPACE; - kiov.iov_len = uap->count; - MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); + kiov.iov_len = SCARG(uap, count); + MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); kiov.iov_base = dirbuf; - error = VOP_READDIR(vp, &kuio, fp->f_cred); + error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, + (int *)0, (u_long *)0); fp->f_offset = kuio.uio_offset; if (error == 0) { - readcnt = uap->count - kuio.uio_resid; + readcnt = SCARG(uap, count) - kuio.uio_resid; edp = (struct dirent *)&dirbuf[readcnt]; for (dp = (struct dirent *)dirbuf; dp < edp; ) { # if (BYTE_ORDER == LITTLE_ENDIAN) @@ -1929,37 +2172,93 @@ ogetdirentries(p, uap, retval) } FREE(dirbuf, M_TEMP); } - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); if (error) return (error); - error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); - *retval = uap->count - auio.uio_resid; + +#ifdef UNION +{ + extern int (**union_vnodeop_p)(); + extern struct vnode *union_dircache __P((struct vnode*, struct proc*)); + + if ((SCARG(uap, count) == auio.uio_resid) && + (vp->v_op == union_vnodeop_p)) { + struct vnode *lvp; + + lvp = union_dircache(vp, p); + if (lvp != NULLVP) { + struct vattr va; + + /* + * If the directory is opaque, + * then don't show lower entries + */ + error = VOP_GETATTR(vp, &va, fp->f_cred, p); + if (va.va_flags & OPAQUE) { + vput(lvp); + lvp = NULL; + } + } + + if (lvp != NULLVP) { + error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); + if (error) { + vput(lvp); + return (error); + } + VOP_UNLOCK(lvp, 0, p); + fp->f_data = (caddr_t) lvp; + fp->f_offset = 0; + error = vn_close(vp, FREAD, fp->f_cred, p); + if (error) + return (error); + vp = lvp; + goto unionread; + } + } +} +#endif /* UNION */ + + if ((SCARG(uap, count) == auio.uio_resid) && + (vp->v_flag & VROOT) && + (vp->v_mount->mnt_flag & MNT_UNION)) { + struct vnode *tvp = vp; + vp = vp->v_mount->mnt_vnodecovered; + VREF(vp); + fp->f_data = (caddr_t) vp; + fp->f_offset = 0; + vrele(tvp); + goto unionread; + } + error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), + sizeof(long)); + *retval = SCARG(uap, count) - auio.uio_resid; return (error); } -#endif +#endif /* COMPAT_43 */ /* * Read a block of directory entries in a file system independent format. */ -struct getdirentries_args { - int fd; - char *buf; - u_int count; - long *basep; -}; +int getdirentries(p, uap, retval) struct proc *p; - register struct getdirentries_args *uap; - int *retval; + register struct getdirentries_args /* { + syscallarg(int) fd; + syscallarg(char *) buf; + syscallarg(u_int) count; + syscallarg(long *) basep; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct file *fp; struct uio auio; struct iovec aiov; long loff; - int error; + int error, eofflag; - if (error = getvnode(p->p_fd, uap->fd, &fp)) + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) return (error); if ((fp->f_flag & FREAD) == 0) return (EBADF); @@ -1967,53 +2266,67 @@ getdirentries(p, uap, retval) unionread: if (vp->v_type != VDIR) return (EINVAL); - aiov.iov_base = uap->buf; - aiov.iov_len = uap->count; + aiov.iov_base = SCARG(uap, buf); + aiov.iov_len = SCARG(uap, count); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; - auio.uio_resid = uap->count; - VOP_LOCK(vp); + auio.uio_resid = SCARG(uap, count); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); loff = auio.uio_offset = fp->f_offset; - error = VOP_READDIR(vp, &auio, fp->f_cred); + error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, + (int *)0, (u_long *)0); fp->f_offset = auio.uio_offset; - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); if (error) return (error); #ifdef UNION { extern int (**union_vnodeop_p)(); - extern struct vnode *union_lowervp __P((struct vnode *)); + extern struct vnode *union_dircache __P((struct vnode*, struct proc*)); - if ((uap->count == auio.uio_resid) && + if ((SCARG(uap, count) == auio.uio_resid) && (vp->v_op == union_vnodeop_p)) { - struct vnode *tvp = vp; + struct vnode *lvp; + + lvp = union_dircache(vp, p); + if (lvp != NULLVP) { + struct vattr va; - vp = union_lowervp(vp); - if (vp != NULLVP) { - VOP_LOCK(vp); - error = VOP_OPEN(vp, FREAD); - VOP_UNLOCK(vp); + /* + * If the directory is opaque, + * then don't show lower entries + */ + error = VOP_GETATTR(vp, &va, fp->f_cred, p); + if (va.va_flags & OPAQUE) { + vput(lvp); + lvp = NULL; + } + } + if (lvp != NULLVP) { + error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); if (error) { - vrele(vp); + vput(lvp); return (error); } - fp->f_data = (caddr_t) vp; + VOP_UNLOCK(lvp, 0, p); + fp->f_data = (caddr_t) lvp; fp->f_offset = 0; - error = vn_close(tvp, FREAD, fp->f_cred, p); + error = vn_close(vp, FREAD, fp->f_cred, p); if (error) return (error); + vp = lvp; goto unionread; } } } -#endif +#endif /* UNION */ - if ((uap->count == auio.uio_resid) && + if ((SCARG(uap, count) == auio.uio_resid) && (vp->v_flag & VROOT) && (vp->v_mount->mnt_flag & MNT_UNION)) { struct vnode *tvp = vp; @@ -2024,28 +2337,28 @@ unionread: vrele(tvp); goto unionread; } - error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)); - *retval = uap->count - auio.uio_resid; + error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), + sizeof(long)); + *retval = SCARG(uap, count) - auio.uio_resid; return (error); } /* * Set the mode mask for creation of filesystem nodes. */ -struct umask_args { - int newmask; -}; -mode_t /* XXX */ +int umask(p, uap, retval) struct proc *p; - struct umask_args *uap; - int *retval; + struct umask_args /* { + syscallarg(int) newmask; + } */ *uap; + register_t *retval; { register struct filedesc *fdp; fdp = p->p_fd; *retval = fdp->fd_cmask; - fdp->fd_cmask = uap->newmask & ALLPERMS; + fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; return (0); } @@ -2053,35 +2366,31 @@ umask(p, uap, retval) * Void all references to file by ripping underlying filesystem * away from vnode. */ -struct revoke_args { - char *path; -}; /* ARGSUSED */ +int revoke(p, uap, retval) struct proc *p; - register struct revoke_args *uap; - int *retval; + register struct revoke_args /* { + syscallarg(char *) path; + } */ *uap; + register_t *retval; { register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if (error = namei(&nd)) return (error); vp = nd.ni_vp; - if (vp->v_type != VCHR && vp->v_type != VBLK) { - error = EINVAL; - goto out; - } if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) goto out; if (p->p_ucred->cr_uid != vattr.va_uid && (error = suser(p->p_ucred, &p->p_acflag))) goto out; if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) - vgoneall(vp); + VOP_REVOKE(vp, REVOKEALL); out: vrele(vp); return (error); @@ -2090,6 +2399,7 @@ out: /* * Convert a user file descriptor to a kernel file entry. */ +int getvnode(fdp, fd, fpp) struct filedesc *fdp; struct file **fpp; diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index d104bb9..3cfc6fd 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94 + * @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95 */ #include @@ -82,7 +82,9 @@ vn_open(ndp, fmode, cmode) VATTR_NULL(vap); vap->va_type = VREG; vap->va_mode = cmode; - LEASE_CHECK(ndp->ni_dvp, p, cred, LEASE_WRITE); + if (fmode & O_EXCL) + vap->va_vaflags |= VA_EXCLUSIVE; + VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE); if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, vap)) return (error); @@ -129,9 +131,9 @@ vn_open(ndp, fmode, cmode) } } if (fmode & O_TRUNC) { - VOP_UNLOCK(vp); /* XXX */ - LEASE_CHECK(vp, p, cred, LEASE_WRITE); - VOP_LOCK(vp); /* XXX */ + VOP_UNLOCK(vp, 0, p); /* XXX */ + VOP_LEASE(vp, p, cred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */ VATTR_NULL(vap); vap->va_size = 0; if (error = VOP_SETATTR(vp, vap, cred, p)) @@ -149,25 +151,13 @@ bad: /* * Check for write permissions on the specified vnode. - * The read-only status of the file system is checked. - * Also, prototype text segments cannot be written. + * Prototype text segments cannot be written. */ vn_writechk(vp) register struct vnode *vp; { /* - * Disallow write attempts on read-only file systems; - * unless the file is a socket or a block or character - * device resident on the file system. - */ - if (vp->v_mount->mnt_flag & MNT_RDONLY) { - switch (vp->v_type) { - case VREG: case VDIR: case VLNK: - return (EROFS); - } - } - /* * If there's shared text associated with * the vnode, try to free it up once. If * we fail, we can't allow writing. @@ -215,7 +205,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) int error; if ((ioflg & IO_NODELOCKED) == 0) - VOP_LOCK(vp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; aiov.iov_base = base; @@ -236,7 +226,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) if (auio.uio_resid && error == 0) error = EIO; if ((ioflg & IO_NODELOCKED) == 0) - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (error); } @@ -248,17 +238,18 @@ vn_read(fp, uio, cred) struct uio *uio; struct ucred *cred; { - register struct vnode *vp = (struct vnode *)fp->f_data; + struct vnode *vp = (struct vnode *)fp->f_data; + struct proc *p = uio->uio_procp; int count, error; - LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_READ); - VOP_LOCK(vp); + VOP_LEASE(vp, p, cred, LEASE_READ); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); uio->uio_offset = fp->f_offset; count = uio->uio_resid; error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, cred); fp->f_offset += count - uio->uio_resid; - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (error); } @@ -270,15 +261,19 @@ vn_write(fp, uio, cred) struct uio *uio; struct ucred *cred; { - register struct vnode *vp = (struct vnode *)fp->f_data; - int count, error, ioflag = 0; + struct vnode *vp = (struct vnode *)fp->f_data; + struct proc *p = uio->uio_procp; + int count, error, ioflag = IO_UNIT; if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) ioflag |= IO_APPEND; if (fp->f_flag & FNONBLOCK) ioflag |= IO_NDELAY; - LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_WRITE); - VOP_LOCK(vp); + if ((fp->f_flag & O_FSYNC) || + (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))) + ioflag |= IO_SYNC; + VOP_LEASE(vp, p, cred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); uio->uio_offset = fp->f_offset; count = uio->uio_resid; error = VOP_WRITE(vp, uio, ioflag, cred); @@ -286,7 +281,7 @@ vn_write(fp, uio, cred) fp->f_offset = uio->uio_offset; else fp->f_offset += count - uio->uio_resid; - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); return (error); } @@ -345,7 +340,7 @@ vn_stat(vp, sb, p) sb->st_rdev = vap->va_rdev; sb->st_size = vap->va_size; sb->st_atimespec = vap->va_atime; - sb->st_mtimespec= vap->va_mtime; + sb->st_mtimespec = vap->va_mtime; sb->st_ctimespec = vap->va_ctime; sb->st_blksize = vap->va_blocksize; sb->st_flags = vap->va_flags; @@ -359,7 +354,7 @@ vn_stat(vp, sb, p) */ vn_ioctl(fp, com, data, p) struct file *fp; - int com; + u_long com; caddr_t data; struct proc *p; { @@ -389,6 +384,8 @@ vn_ioctl(fp, com, data, p) case VBLK: error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); if (error == 0 && com == TIOCSCTTY) { + if (p->p_session->s_ttyvp) + vrele(p->p_session->s_ttyvp); p->p_session->s_ttyvp = vp; VREF(vp); } @@ -410,6 +407,36 @@ vn_select(fp, which, p) } /* + * Check that the vnode is still valid, and if so + * acquire requested lock. + */ +int +vn_lock(vp, flags, p) + struct vnode *vp; + int flags; + struct proc *p; +{ + int error; + + do { + if ((flags & LK_INTERLOCK) == 0) + simple_lock(&vp->v_interlock); + if (vp->v_flag & VXLOCK) { + vp->v_flag |= VXWANT; + simple_unlock(&vp->v_interlock); + tsleep((caddr_t)vp, PINOD, "vn_lock", 0); + error = ENOENT; + } else { + error = VOP_LOCK(vp, flags | LK_INTERLOCK, p); + if (error == 0) + return (error); + } + flags &= ~LK_INTERLOCK; + } while (flags & LK_RETRY); + return (error); +} + +/* * File table vnode close routine. */ vn_closefile(fp, p) diff --git a/sys/kern/vnode_if.sh b/sys/kern/vnode_if.sh index e190fa0..8b74d83 100644 --- a/sys/kern/vnode_if.sh +++ b/sys/kern/vnode_if.sh @@ -1,8 +1,9 @@ #!/bin/sh - -# -# Copyright (c) 1992, 1993 -# The Regents of the University of California. All rights reserved. -# +copyright=' +/* + * Copyright (c) 1992, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: @@ -30,19 +31,17 @@ # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. -# -# @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 -# + * + * from: NetBSD: vnode_if.sh,v 1.7 1994/08/25 03:04:28 cgd Exp $ + */ +' +SCRIPT_ID='@(#)vnode_if.sh 8.7 (Berkeley) 5/11/95' # Script to produce VFS front-end sugar. # # usage: vnode_if.sh srcfile # (where srcfile is currently /sys/kern/vnode_if.src) # -# These awk scripts are not particularly well written, specifically they -# don't use arrays well and figure out the same information repeatedly. -# Please rewrite them if you actually understand how to use awk. Note, -# they use nawk extensions and gawk's toupper. if [ $# -ne 1 ] ; then echo 'usage: vnode_if.sh srcfile' @@ -50,118 +49,180 @@ if [ $# -ne 1 ] ; then fi # Name of the source file. -SRC=$1 +src=$1 # Names of the created files. -CFILE=vnode_if.c -HEADER=vnode_if.h +out_c=vnode_if.c +out_h=vnode_if.h + +# Awk program (must support nawk extensions) +# Use "awk" at Berkeley, "nawk" or "gawk" elsewhere. +awk=${AWK:-awk} + +# Does this awk have a "toupper" function? (i.e. is it GNU awk) +isgawk=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null` + +# If this awk does not define "toupper" then define our own. +if [ "$isgawk" = TRUE ] ; then + # GNU awk provides it. + toupper= +else + # Provide our own toupper() + toupper=' +function toupper(str) { + _toupper_cmd = "echo "str" |tr a-z A-Z" + _toupper_cmd | getline _toupper_str; + close(_toupper_cmd); + return _toupper_str; +}' +fi -# Awk program (must support nawk extensions and gawk's "toupper") -# Use "awk" at Berkeley, "gawk" elsewhere. -AWK=awk +# +# This is the common part of all awk programs that read $src +# This parses the input for one function into the arrays: +# argdir, argtype, argname, willrele +# and calls "doit()" to generate output for the function. +# +# Input to this parser is pre-processed slightly by sed +# so this awk parser doesn't have to work so hard. The +# changes done by the sed pre-processing step are: +# insert a space beween * and pointer name +# replace semicolons with spaces +# +sed_prep='s:\*\([^\*/]\):\* \1:g +s/;/ /' +awk_parser=' +# Comment line +/^#/ { next; } +# First line of description +/^vop_/ { + name=$1; + argc=0; + next; +} +# Last line of description +/^}/ { + doit(); + next; +} +# Middle lines of description +{ + argdir[argc] = $1; i=2; + if ($2 == "WILLRELE") { + willrele[argc] = 1; + i++; + } else + willrele[argc] = 0; + argtype[argc] = $i; i++; + while (i < NF) { + argtype[argc] = argtype[argc]" "$i; + i++; + } + argname[argc] = $i; + argc++; + next; +} +' -# Print out header information for vnode_if.h. -cat << END_OF_LEADING_COMMENT > $HEADER +# This is put after the copyright on each generated file. +warning=" /* - * This file is produced automatically. - * Do not modify anything in here by hand. + * Warning: This file is generated automatically. + * (Modifications made here may easily be lost!) * - * Created from @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 + * Created by the script: + * ${SCRIPT_ID} */ +" -extern struct vnodeop_desc vop_default_desc; -END_OF_LEADING_COMMENT - -# Awk script to take vnode_if.src and turn it into vnode_if.h. -$AWK ' - NF == 0 || $0 ~ "^#" { - next; - } - { - # Get the function name. - name = $1; - uname = toupper(name); +# Get rid of ugly spaces +space_elim='s:\([^/]\*\) :\1:g' - # Get the function arguments. - for (c1 = 0;; ++c1) { - if (getline <= 0) - exit - if ($0 ~ "^};") - break; - a[c1] = $0; - } +# +# Redirect stdout to the H file. +# +echo "$0: Creating $out_h" 1>&2 +exec > $out_h - # Print out the vop_F_args structure. - printf("struct %s_args {\n\tstruct vnodeop_desc *a_desc;\n", - name); - for (c2 = 0; c2 < c1; ++c2) { - c3 = split(a[c2], t); - printf("\t"); - if (t[2] ~ "WILLRELE") - c4 = 3; - else - c4 = 2; - for (; c4 < c3; ++c4) - printf("%s ", t[c4]); - beg = match(t[c3], "[^*]"); - printf("%sa_%s\n", - substr(t[c4], 0, beg - 1), substr(t[c4], beg)); - } - printf("};\n"); +# Begin stuff +echo "$copyright" +echo "$warning" +echo ' +extern struct vnodeop_desc vop_default_desc; +' + +# Body stuff +# This awk program needs toupper() so define it if necessary. +sed -e "$sed_prep" $src | $awk "$toupper"' +function doit() { + # Declare arg struct, descriptor. + printf("\nstruct %s_args {\n", name); + printf("\tstruct vnodeop_desc * a_desc;\n"); + for (i=0; i\n"); + argc=1; + argtype[0]="struct buf *"; + argname[0]="bp"; + arg0special="->b_vp"; + name="vop_strategy"; + doit(); + name="vop_bwrite"; + doit(); +} +'"$awk_parser" | sed -e "$space_elim" - # Print out extern declaration. - printf("extern struct vnodeop_desc %s_desc;\n", name); +# End stuff +echo ' +/* End of special cases. */' - # Print out inline struct. - printf("static inline int %s(", uname); - sep = ", "; - for (c2 = 0; c2 < c1; ++c2) { - if (c2 == c1 - 1) - sep = ")\n"; - c3 = split(a[c2], t); - beg = match(t[c3], "[^*]"); - end = match(t[c3], ";"); - printf("%s%s", substr(t[c3], beg, end - beg), sep); - } - for (c2 = 0; c2 < c1; ++c2) { - c3 = split(a[c2], t); - printf("\t"); - if (t[2] ~ "WILLRELE") - c4 = 3; - else - c4 = 2; - for (; c4 < c3; ++c4) - printf("%s ", t[c4]); - beg = match(t[c3], "[^*]"); - printf("%s%s\n", - substr(t[c4], 0, beg - 1), substr(t[c4], beg)); - } - printf("{\n\tstruct %s_args a;\n\n", name); - printf("\ta.a_desc = VDESC(%s);\n", name); - for (c2 = 0; c2 < c1; ++c2) { - c3 = split(a[c2], t); - printf("\t"); - beg = match(t[c3], "[^*]"); - end = match(t[c3], ";"); - printf("a.a_%s = %s\n", - substr(t[c3], beg, end - beg), substr(t[c3], beg)); - } - c1 = split(a[0], t); - beg = match(t[c1], "[^*]"); - end = match(t[c1], ";"); - printf("\treturn (VCALL(%s, VOFFSET(%s), &a));\n}\n", - substr(t[c1], beg, end - beg), name); - }' < $SRC >> $HEADER -# Print out header information for vnode_if.c. -cat << END_OF_LEADING_COMMENT > $CFILE -/* - * This file is produced automatically. - * Do not modify anything in here by hand. - * - * Created from @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 - */ +# +# Redirect stdout to the C file. +# +echo "$0: Creating $out_c" 1>&2 +exec > $out_c +# Begin stuff +echo "$copyright" +echo "$warning" +echo ' #include #include #include @@ -177,257 +238,107 @@ struct vnodeop_desc vop_default_desc = { VDESC_NO_OFFSET, NULL, }; - -END_OF_LEADING_COMMENT - -# Awk script to take vnode_if.src and turn it into vnode_if.c. -$AWK 'function kill_surrounding_ws (s) { - sub (/^[ \t]*/, "", s); - sub (/[ \t]*$/, "", s); - return s; - } - - function read_args() { - numargs = 0; - while (getline ln) { - if (ln ~ /}/) { - break; - }; - - # Delete comments, if any. - gsub (/\/\*.*\*\//, "", ln); - - # Delete leading/trailing space. - ln = kill_surrounding_ws(ln); - - # Pick off direction. - if (1 == sub(/^INOUT[ \t]+/, "", ln)) - dir = "INOUT"; - else if (1 == sub(/^IN[ \t]+/, "", ln)) - dir = "IN"; - else if (1 == sub(/^OUT[ \t]+/, "", ln)) - dir = "OUT"; - else - bail("No IN/OUT direction for \"" ln "\"."); - - # check for "WILLRELE" - if (1 == sub(/^WILLRELE[ \t]+/, "", ln)) { - rele = "WILLRELE"; - } else { - rele = "WONTRELE"; - }; - - # kill trailing ; - if (1 != sub (/;$/, "", ln)) { - bail("Missing end-of-line ; in \"" ln "\"."); - }; - - # pick off variable name - if (!(i = match(ln, /[A-Za-z0-9_]+$/))) { - bail("Missing var name \"a_foo\" in \"" ln "\"."); - }; - arg = substr (ln, i); - # Want to <>, but nawk cannot. - # Hack around this. - ln = substr(ln, 1, i-1); - - # what is left must be type - # (put clean it up some) - type = ln; - gsub (/[ \t]+/, " ", type); # condense whitespace - type = kill_surrounding_ws(type); - - # (boy this was easier in Perl) - - numargs++; - dirs[numargs] = dir; - reles[numargs] = rele; - types[numargs] = type; - args[numargs] = arg; +' + +# Body stuff +sed -e "$sed_prep" $src | $awk ' +function do_offset(typematch) { + for (i=0; i> $CFILE -# THINGS THAT DON'T WORK RIGHT YET. -# -# Two existing BSD vnodeops (bwrite and strategy) don't take any vnodes as -# arguments. This means that these operations can't function successfully -# through a bypass routine. -# -# Bwrite and strategy will be replaced when the VM page/buffer cache -# integration happens. -# -# To get around this problem for now we handle these ops as special cases. - -cat << END_OF_SPECIAL_CASES >> $HEADER -#include -struct vop_strategy_args { - struct vnodeop_desc *a_desc; - struct buf *a_bp; -}; -extern struct vnodeop_desc vop_strategy_desc; -static inline int VOP_STRATEGY(bp) - struct buf *bp; -{ - struct vop_strategy_args a; - - a.a_desc = VDESC(vop_strategy); - a.a_bp = bp; - return (VCALL((bp)->b_vp, VOFFSET(vop_strategy), &a)); + print ","; + # vp offsets + printf ("\t%s_vp_offsets,\n", name); + # vpp (if any) + do_offset("struct vnode **"); + # cred (if any) + do_offset("struct ucred *"); + # proc (if any) + do_offset("struct proc *"); + # componentname + do_offset("struct componentname *"); + # transport layer information + printf ("\tNULL,\n};\n"); +} +END { + printf("\n/* Special cases: */\n"); + argc=1; + argdir[0]="IN"; + argtype[0]="struct buf *"; + argname[0]="bp"; + willrele[0]=0; + name="vop_strategy"; + doit(); + name="vop_bwrite"; + doit(); } +'"$awk_parser" | sed -e "$space_elim" -struct vop_bwrite_args { - struct vnodeop_desc *a_desc; - struct buf *a_bp; -}; -extern struct vnodeop_desc vop_bwrite_desc; -static inline int VOP_BWRITE(bp) - struct buf *bp; -{ - struct vop_bwrite_args a; +# End stuff +echo ' +/* End of special cases. */' - a.a_desc = VDESC(vop_bwrite); - a.a_bp = bp; - return (VCALL((bp)->b_vp, VOFFSET(vop_bwrite), &a)); +# Add the vfs_op_descs array to the C file. +# Begin stuff +echo ' +struct vnodeop_desc *vfs_op_descs[] = { + &vop_default_desc, /* MUST BE FIRST */ + &vop_strategy_desc, /* XXX: SPECIAL CASE */ + &vop_bwrite_desc, /* XXX: SPECIAL CASE */ +' + +# Body stuff +sed -e "$sed_prep" $src | $awk ' +function doit() { + printf("\t&%s_desc,\n", name); } -END_OF_SPECIAL_CASES +'"$awk_parser" -cat << END_OF_SPECIAL_CASES >> $CFILE -int vop_strategy_vp_offsets[] = { - VDESC_NO_OFFSET -}; -struct vnodeop_desc vop_strategy_desc = { - 0, - "vop_strategy", - 0, - vop_strategy_vp_offsets, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - NULL, -}; -int vop_bwrite_vp_offsets[] = { - VDESC_NO_OFFSET -}; -struct vnodeop_desc vop_bwrite_desc = { - 0, - "vop_bwrite", - 0, - vop_bwrite_vp_offsets, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - NULL, +# End stuff +echo ' NULL }; -END_OF_SPECIAL_CASES +' -# Add the vfs_op_descs array to the C file. -$AWK ' - BEGIN { - printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n"); - printf("\t&vop_default_desc, /* MUST BE FIRST */\n"); - printf("\t&vop_strategy_desc, /* XXX: SPECIAL CASE */\n"); - printf("\t&vop_bwrite_desc, /* XXX: SPECIAL CASE */\n"); - } - END { - printf("\tNULL\n};\n"); - } - NF == 0 || $0 ~ "^#" { - next; - } - { - # Get the function name. - printf("\t&%s_desc,\n", $1); - - # Skip the function arguments. - for (;;) { - if (getline <= 0) - exit - if ($0 ~ "^};") - break; - } - }' < $SRC >> $CFILE +exit 0 +# Local Variables: +# tab-width: 4 +# End: diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index caee21d..1e32f29 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -30,7 +30,32 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# @(#)vnode_if.src 8.3 (Berkeley) 2/3/94 +# @(#)vnode_if.src 8.12 (Berkeley) 5/14/95 +# + +# +# Above each of the vop descriptors is a specification of the locking +# protocol used by each vop call. The first column is the name of +# the variable, the remaining three columns are in, out and error +# respectively. The "in" column defines the lock state on input, +# the "out" column defines the state on succesful return, and the +# "error" column defines the locking state on error exit. +# +# The locking value can take the following values: +# L: locked. +# U: unlocked/ +# -: not applicable. vnode does not yet (or no longer) exists. +# =: the same on input and output, may be either L or U. +# X: locked if not nil. +# + +# +#% lookup dvp L ? ? +#% lookup vpp - L - +# +# XXX - the lookup locking protocol defies simple description and depends +# on the flags and operation fields in the (cnp) structure. Note +# especially that *vpp may equal dvp and both may be locked. # vop_lookup { IN struct vnode *dvp; @@ -38,6 +63,10 @@ vop_lookup { IN struct componentname *cnp; }; +# +#% create dvp L U U +#% create vpp - L - +# vop_create { IN WILLRELE struct vnode *dvp; OUT struct vnode **vpp; @@ -45,6 +74,21 @@ vop_create { IN struct vattr *vap; }; +# +#% whiteout dvp L L L +#% whiteout cnp - - - +#% whiteout flag - - - +# +vop_whiteout { + IN WILLRELE struct vnode *dvp; + IN struct componentname *cnp; + IN int flags; +}; + +# +#% mknod dvp L U U +#% mknod vpp - X - +# vop_mknod { IN WILLRELE struct vnode *dvp; OUT WILLRELE struct vnode **vpp; @@ -52,6 +96,9 @@ vop_mknod { IN struct vattr *vap; }; +# +#% open vp L L L +# vop_open { IN struct vnode *vp; IN int mode; @@ -59,6 +106,9 @@ vop_open { IN struct proc *p; }; +# +#% close vp U U U +# vop_close { IN struct vnode *vp; IN int fflag; @@ -66,6 +116,9 @@ vop_close { IN struct proc *p; }; +# +#% access vp L L L +# vop_access { IN struct vnode *vp; IN int mode; @@ -73,6 +126,9 @@ vop_access { IN struct proc *p; }; +# +#% getattr vp = = = +# vop_getattr { IN struct vnode *vp; IN struct vattr *vap; @@ -80,6 +136,9 @@ vop_getattr { IN struct proc *p; }; +# +#% setattr vp L L L +# vop_setattr { IN struct vnode *vp; IN struct vattr *vap; @@ -87,6 +146,9 @@ vop_setattr { IN struct proc *p; }; +# +#% read vp L L L +# vop_read { IN struct vnode *vp; INOUT struct uio *uio; @@ -94,6 +156,9 @@ vop_read { IN struct ucred *cred; }; +# +#% write vp L L L +# vop_write { IN struct vnode *vp; INOUT struct uio *uio; @@ -101,16 +166,33 @@ vop_write { IN struct ucred *cred; }; +# +#% lease vp = = = +# +vop_lease { + IN struct vnode *vp; + IN struct proc *p; + IN struct ucred *cred; + IN int flag; +}; + +# +#% ioctl vp U U U +# vop_ioctl { IN struct vnode *vp; - IN int command; + IN u_long command; IN caddr_t data; IN int fflag; IN struct ucred *cred; IN struct proc *p; }; +# +#% select vp U U U +# # Needs work? (fflags) +# vop_select { IN struct vnode *vp; IN int which; @@ -119,6 +201,17 @@ vop_select { IN struct proc *p; }; +# +#% revoke vp U U U +# +vop_revoke { + IN struct vnode *vp; + IN int flags; +}; + +# +# XXX - not used +# vop_mmap { IN struct vnode *vp; IN int fflags; @@ -126,6 +219,9 @@ vop_mmap { IN struct proc *p; }; +# +#% fsync vp L L L +# vop_fsync { IN struct vnode *vp; IN struct ucred *cred; @@ -133,7 +229,10 @@ vop_fsync { IN struct proc *p; }; -# Needs word: Is newoff right? What's it mean? +# +# XXX - not used +# Needs work: Is newoff right? What's it mean? +# vop_seek { IN struct vnode *vp; IN off_t oldoff; @@ -141,18 +240,32 @@ vop_seek { IN struct ucred *cred; }; +# +#% remove dvp L U U +#% remove vp L U U +# vop_remove { IN WILLRELE struct vnode *dvp; IN WILLRELE struct vnode *vp; IN struct componentname *cnp; }; +# +#% link vp U U U +#% link tdvp L U U +# vop_link { IN WILLRELE struct vnode *vp; IN struct vnode *tdvp; IN struct componentname *cnp; }; +# +#% rename fdvp U U U +#% rename fvp U U U +#% rename tdvp L U U +#% rename tvp X U U +# vop_rename { IN WILLRELE struct vnode *fdvp; IN WILLRELE struct vnode *fvp; @@ -162,6 +275,10 @@ vop_rename { IN struct componentname *tcnp; }; +# +#% mkdir dvp L U U +#% mkdir vpp - L - +# vop_mkdir { IN WILLRELE struct vnode *dvp; OUT struct vnode **vpp; @@ -169,12 +286,24 @@ vop_mkdir { IN struct vattr *vap; }; +# +#% rmdir dvp L U U +#% rmdir vp L U U +# vop_rmdir { IN WILLRELE struct vnode *dvp; IN WILLRELE struct vnode *vp; IN struct componentname *cnp; }; +# +#% symlink dvp L U U +#% symlink vpp - U - +# +# XXX - note that the return vnode has already been VRELE'ed +# by the filesystem layer. To use it you must use vget, +# possibly with a further namei. +# vop_symlink { IN WILLRELE struct vnode *dvp; OUT WILLRELE struct vnode **vpp; @@ -183,39 +312,73 @@ vop_symlink { IN char *target; }; +# +#% readdir vp L L L +# vop_readdir { IN struct vnode *vp; INOUT struct uio *uio; IN struct ucred *cred; + INOUT int *eofflag; + OUT int *ncookies; + INOUT u_long **cookies; }; +# +#% readlink vp L L L +# vop_readlink { IN struct vnode *vp; INOUT struct uio *uio; IN struct ucred *cred; }; +# +#% abortop dvp = = = +# vop_abortop { IN struct vnode *dvp; IN struct componentname *cnp; }; +# +#% inactive vp L U U +# vop_inactive { IN struct vnode *vp; + IN struct proc *p; }; +# +#% reclaim vp U U U +# vop_reclaim { IN struct vnode *vp; + IN struct proc *p; }; +# +#% lock vp U L U +# vop_lock { IN struct vnode *vp; + IN int flags; + IN struct proc *p; }; +# +#% unlock vp L U L +# vop_unlock { IN struct vnode *vp; + IN int flags; + IN struct proc *p; }; +# +#% bmap vp L L L +#% bmap vpp - U - +# vop_bmap { IN struct vnode *vp; IN daddr_t bn; @@ -224,24 +387,39 @@ vop_bmap { OUT int *runp; }; +# +# Needs work: no vp? +# #vop_strategy { # IN struct buf *bp; #}; +# +#% print vp = = = +# vop_print { IN struct vnode *vp; }; +# +#% islocked vp = = = +# vop_islocked { IN struct vnode *vp; }; +# +#% pathconf vp L L L +# vop_pathconf { IN struct vnode *vp; IN int name; - OUT int *retval; + OUT register_t *retval; }; +# +#% advlock vp U U U +# vop_advlock { IN struct vnode *vp; IN caddr_t id; @@ -250,6 +428,9 @@ vop_advlock { IN int flags; }; +# +#% blkatoff vp L L L +# vop_blkatoff { IN struct vnode *vp; IN off_t offset; @@ -257,6 +438,9 @@ vop_blkatoff { OUT struct buf **bpp; }; +# +#% valloc pvp L L L +# vop_valloc { IN struct vnode *pvp; IN int mode; @@ -264,17 +448,26 @@ vop_valloc { OUT struct vnode **vpp; }; +# +#% reallocblks vp L L L +# vop_reallocblks { IN struct vnode *vp; IN struct cluster_save *buflist; }; +# +#% vfree pvp L L L +# vop_vfree { IN struct vnode *pvp; IN ino_t ino; IN int mode; }; +# +#% truncate vp L L L +# vop_truncate { IN struct vnode *vp; IN off_t length; @@ -283,6 +476,9 @@ vop_truncate { IN struct proc *p; }; +# +#% update vp L L L +# vop_update { IN struct vnode *vp; IN struct timeval *access; @@ -290,7 +486,9 @@ vop_update { IN int waitfor; }; +# # Needs work: no vp? +# #vop_bwrite { # IN struct buf *bp; #}; -- cgit v1.1