SunOS-4.1.4/sys/rfs/netboot.c
/* @(#)netboot.c 1.1 94/10/31 SMI */
/* Copyright (c) 1984 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/* #ident "@(#)kern-port:nudnix/netboot.c 10.20" */
/*
* System call to start file sharing.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/signal.h>
#include <sys/stream.h>
#include <sys/user.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/debug.h>
#include <sys/file.h>
#include <rfs/rfs_misc.h>
#include <rfs/sema.h>
#include <rfs/comm.h>
#include <rfs/nserve.h>
#include <rfs/rfs_mnt.h>
#include <rfs/message.h>
#include <rfs/adv.h>
#include <rfs/recover.h>
#include <rfs/rdebug.h>
#include <rfs/rfs_serve.h>
#include <rfs/idtab.h>
#include <rfs/cirmgr.h>
extern struct proc *rfsdp;
extern struct vnode *rfs_cdir;
extern int msgflag;
extern rcvd_t rd_recover;
extern struct vnode *rootdir; /* pointer to root vnode--set during system init */
extern int bootstate; /* DU_UP, DU_DOWN, or */
/* DU_INTER */
extern comminit(), gdp_init(), auth_init();
extern void commdinit();
extern void recover_init();
extern struct proc *rec_proc; /* sleep address for recovery */
extern int rec_flag; /* set KILL bit to kill recovery */
rfstart ()
{
struct serv_proc *sp;
extern int gdp_init ();
register int s;
extern int maxserve;
extern void recovery();
extern void rfdaemon();
DUPRINT1(DB_RFSTART, "rfstart system call\n");
if (!suser())
return;
while (bootstate & DU_INTER) {
(void) sleep((caddr_t) &bootstate, PREMOTE);
}
/*
* This is a critical section. Only one process at a time
* can execute this code.
*/
if (bootstate == DU_UP) {
DUPRINT1 (DB_RFSTART, "rfstart: system already booted\n");
u.u_error = EEXIST;
wakeup((caddr_t) &bootstate);
return;
}
bootstate = DU_INTER; /* RFS in an intermediate state */
/* Allocate memory for RFS data structures */
rfs_memalloc();
if (comminit() == RFS_FAILURE) {
u.u_error = EAGAIN;
bootstate = DU_DOWN;
wakeup((caddr_t) &bootstate);
return;
}
DUPRINT1(DB_RFSTART, "comm initialized\n");
auth_init();
gdp_init();
if (u.u_error) {
DUPRINT2 (DB_RFSTART, "rfstart u.u_error %d\n", u.u_error);
commdinit();
bootstate=DU_DOWN;
wakeup((caddr_t) &bootstate);
return;
}
DUPRINT1(DB_RFSTART, "gdp initialized\n");
recover_init();
DUPRINT1(DB_RFSTART, "rfstart: recovery initialized\n");
/* start recovery process */
kern_proc(recovery, 0);
/* start daemon process */
kern_proc(rfdaemon, 0);
/* now allow advertise calls, set all sysid's in proc table */
s = splrf();
for (sp = &serv_proc[0]; sp < &serv_proc[maxserve]; sp++)
sp->s_sysid = 0;
(void) splx(s);
/*
* bootstate set when rfdaemon is running -- see rfadmin.c
*/
return;
}
/*
* Release various unneeded resources for the kernel procs.
*/
netmemfree()
{
int i;
VN_RELE(u.u_cdir);
u.u_cdir = rootdir;
VN_HOLD(u.u_cdir);
if (u.u_rdir) {
VN_RELE(u.u_rdir);
}
u.u_rdir = NULL;
for (i = 0; i < u.u_lastfile; i++)
if (u.u_ofile[i] != NULL) {
closef(u.u_ofile[i]);
u.u_ofile[i] = NULL;
u.u_pofile[i] = 0;
}
}
/*
* System call to stop file sharing - if everything is quiet.
*/
rfstop()
{
register struct rfsmnt *mp;
register struct srmnt *sp;
register struct advertise *ap;
DUPRINT1(DB_RFSTART, "rfstop system call\n");
if (!suser())
return;
/*
* Begin critical section. As in rfstart, only one process at a time
* through this section of code.
*/
while (bootstate & DU_INTER) {
(void) sleep((caddr_t) &bootstate, PREMOTE);
}
if (bootstate == DU_DOWN) {
DUPRINT1(DB_RFSTART, "rfstop: system already stopped\n");
u.u_error = ENONET;
wakeup((caddr_t) &bootstate);
return;
}
bootstate &= ~DU_MASK;
bootstate |= DU_INTER;
/*
* can't stop if anything is remotely mounted
* (starting at rfsmount[1] means we're not looking at root)
*
* If any local proc has an SD (cdir, rdir, open file) that points
* into a remotely mounted filesystem, it will not be possible to
* unmount that filesystem. (See rumount.)
*/
for (mp = rfsmount; mp < (struct rfsmnt *)&rfsmount[nrfsmount]; mp++) {
if (mp->rm_flags & RINUSE) {
DUPRINT1 (DB_RFSTART,
"rfstop: can't stop with remote mounts.\n");
u.u_error = EBUSY;
bootstate=DU_UP;
wakeup((caddr_t) &bootstate);
return;
}
}
/* can't stop if this machine has clients */
for (sp = srmount; sp < &srmount[nsrmount]; sp++) {
if (sp->sr_flags != MFREE) {
DUPRINT1 (DB_RFSTART,
"rfstop: can't stop with clients.\n");
u.u_error = ESRMNT;
bootstate=DU_UP;
wakeup((caddr_t) &bootstate);
return;
}
}
/* can't stop if anything is advertised */
/* adv table locked above */
for (ap = advertise; ap < &advertise[nadvertise]; ap++) {
if (ap->a_flags != A_FREE) {
DUPRINT1 (DB_RFSTART,
"rfstop: can't stop with advertised resources.\n");
u.u_error = EADV;
bootstate = DU_UP;
wakeup((caddr_t) &bootstate);
return;
}
}
DUPRINT1(DB_RFSTART, "rfstop: taking down links \n");
kill_gdp(); /* cut all connections */
commdinit();
/* kill daemons - bootstate goes to DOWN after both die */
DUPRINT1(DB_RFSTART, "rfstop: killing daemons \n");
msgflag |= RFSKILL;
wakeup ((caddr_t) &rd_recover->rd_qslp);
rec_flag |= RFSKILL;
wakeup ((caddr_t) &rec_proc);
/* Wait til all rfs processes are down, free mem and set state DOWN */
while ((bootstate & DU_ALL_DOWN) != DU_ALL_DOWN) {
DUPRINT2(DB_RFSTART, "rfstop coming down : bootstate %x\n",
bootstate);
(void) sleep((caddr_t) &bootstate, PREMOTE);
}
rfs_memfree();
bootstate = DU_DOWN;
wakeup((caddr_t) &bootstate);
DUPRINT1(DB_RFSTART, "rfstop: done\n");
}