sys/nfs/nfs_vfsops.c
/*
 * Mount a remote root fs via. nfs. This depends on the info in the
 * nfs_diskless structure that has been filled in properly by some primary
 * bootstrap.
 * It goes something like this:
 * - do enough of "ifconfig" by calling ifioctl() so that the system
 *   can talk to the server
 * - If nfs_diskless.mygateway is filled in, use that address as
 *   a default gateway.
 * - hand craft the swap nfs vnode hanging off a fake mount point
 *	if swdevt[0].sw_dev == NODEV
 * - build the rootfs mount point and call mountnfs() to do the rest.
 */
Mount a remote root fs via. nfs. This depends on the info in the
nfs_diskless structure that has been filled in properly by some primary
bootstrap.
It goes something like this:
- do enough of "ifconfig" by calling ifioctl() so that the system
can talk to the server
- If nfs_diskless.mygateway is filled in, use that address as
a default gateway.
- hand craft the swap nfs vnode hanging off a fake mount point
if swdevt[0].sw_dev == NODEV
- build the rootfs mount point and call mountnfs() to do the rest.
Mount a remote root fs via . nfs . This depends on the info in the nfs_diskless structure that has been filled in properly by some primary bootstrap . It goes something like this : - do enough of " ifconfig " by calling ifioctl () so that the system can talk to the server - If nfs_diskless . mygateway is filled in use that address as a default gateway . - hand craft the swap nfs vnode hanging off a fake mount point if swdevt [ 0 ] . sw_dev == NODEV - build the rootfs mount point and call mountnfs () to do the rest .
int
nfs_mountroot()
{
	struct mount *mp, *swap_mp;
	struct nfs_diskless *nd = &nfs_diskless;
	struct socket *so;
	struct vnode *vp;
	struct proc *p = curproc;		
	int error, i;
	u_long l;
	char buf[128];
	if (time.tv_sec == 0)
		time.tv_sec = 1;
	splnet();
#ifdef notyet
	proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid);
	proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid);
	if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) >
		NGROUPS)
		proc0.p_ucred->cr_ngroups = NGROUPS;
	for (i = 0; i < proc0.p_ucred->cr_ngroups; i++)
	    proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]);
#endif
	error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0);
	if (error) {
		printf("nfs_mountroot: socreate(%04x): %d",
			nd->myif.ifra_addr.sa_family, error);
		return (error);
	}
	for (i = strlen(nd->myif.ifra_name) - 1;
		nd->myif.ifra_name[i] >= '0' && 
		nd->myif.ifra_name[i] <= '9';
		nd->myif.ifra_name[i] ++) {
		error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p);
		if(!error) 
			break;
	}
	if (error) {
		printf("nfs_mountroot: SIOCAIFADDR: %d", error);
		return (error);
	}
	soclose(so);
	if (nd->mygateway.sin_len != 0) {
		struct sockaddr_in mask, sin;
		bzero((caddr_t)&mask, sizeof(mask));
		sin = mask;
		sin.sin_family = AF_INET;
		sin.sin_len = sizeof(sin);
		error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
		    (struct sockaddr *)&nd->mygateway,
		    (struct sockaddr *)&mask,
		    RTF_UP | RTF_GATEWAY, (struct rtentry **)0);
		if (error) {
			printf("nfs_mountroot: RTM_ADD: %d", error);
			return (error);
		}
	}
	swap_mp = NULL;
	if (nd->swap_nblks) {
		nd->swap_args.fh = nd->swap_fh;
		nd->swap_args.fhsize = NFSX_V2FH;
		l = ntohl(nd->swap_saddr.sin_addr.s_addr);
		sprintf(buf,"%ld.%ld.%ld.%ld:%s",
			(l >> 24) & 0xff, (l >> 16) & 0xff,
			(l >>  8) & 0xff, (l >>  0) & 0xff,nd->swap_hostnam);
		printf("NFS SWAP: %s\n",buf);
		if (error = nfs_mountdiskless(buf, "/swap", 0,
		    &nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp))
			return (error);
		vfs_unbusy(swap_mp, p);
		for (i=0;swdevt[i].sw_dev != NODEV;i++) ;
		vp->v_type = VREG;
		vp->v_flag = 0;
		swapdev_vp = vp;
		VREF(vp);
		swdevt[i].sw_vp = vp;
		swdevt[i].sw_nblks = nd->swap_nblks*2;
		if (!swdevt[i].sw_nblks) {
			swdevt[i].sw_nblks = 2048;
			printf("defaulting to %d kbyte.\n",
				swdevt[i].sw_nblks/2);
		} else
			printf("using %d kbyte.\n",swdevt[i].sw_nblks/2);
	}
	nd->root_args.fh = nd->root_fh;
	nd->root_args.fhsize = NFSX_V2FH;
	l = ntohl(nd->swap_saddr.sin_addr.s_addr);
	sprintf(buf,"%ld.%ld.%ld.%ld:%s",
		(l >> 24) & 0xff, (l >> 16) & 0xff,
		(l >>  8) & 0xff, (l >>  0) & 0xff,nd->root_hostnam);
	printf("NFS ROOT: %s\n",buf);
	if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
	    &nd->root_saddr, &nd->root_args, p, &vp, &mp)) {
		if (swap_mp) {
			mp->mnt_vfc->vfc_refcount--;
			free(swap_mp, M_MOUNT);
		}
		return (error);
	}
	simple_lock(&mountlist_slock);
	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
	simple_unlock(&mountlist_slock);
	rootvp = vp;
	vfs_unbusy(mp, p);
	bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
	hostname[MAXHOSTNAMELEN - 1] = '\0';
	for (i = 0; i < MAXHOSTNAMELEN; i++)
		if (hostname[i] == '\0')
			break;
	hostnamelen = i;
	inittodr(ntohl(nd->root_time));
	return (0);
}
int nfs_mountroot ( ) { struct mount * mp , * swap_mp ; struct nfs_diskless * nd = & nfs_diskless ; struct socket * so ; struct vnode * vp ; struct proc * p = curproc ; int error , i ; u_long l ; char buf [ 128 ] ; if ( time . tv_sec == 0 ) time . tv_sec = 1 ; splnet ( ) ; #ifdef notyet proc0 . p_ucred -> cr_uid = ntohl ( nd -> swap_ucred . cr_uid ) ; proc0 . p_ucred -> cr_gid = ntohl ( nd -> swap_ucred . cr_gid ) ; if ( ( proc0 . p_ucred -> cr_ngroups = ntohs ( nd -> swap_ucred . cr_ngroups ) ) > NGROUPS ) proc0 . p_ucred -> cr_ngroups = NGROUPS ; for ( i = 0 ; i < proc0 . p_ucred -> cr_ngroups ; i ++ ) proc0 . p_ucred -> cr_groups [ i ] = ntohl ( nd -> swap_ucred . cr_groups [ i ] ) ; #endif error = socreate ( nd -> myif . ifra_addr . sa_family , & so , SOCK_DGRAM , 0 ) ; if ( error ) { printf ( " " , nd -> myif . ifra_addr . sa_family , error ) ; return ( error ) ; } for ( i = strlen ( nd -> myif . ifra_name ) - 1 ; nd -> myif . ifra_name [ i ] >= ' ' && nd -> myif . ifra_name [ i ] <= ' ' ; nd -> myif . ifra_name [ i ] ++ ) { error = ifioctl ( so , SIOCAIFADDR , ( caddr_t ) & nd -> myif , p ) ; if ( ! error ) break ; } if ( error ) { printf ( " " , error ) ; return ( error ) ; } soclose ( so ) ; if ( nd -> mygateway . sin_len != 0 ) { struct sockaddr_in mask , sin ; bzero ( ( caddr_t ) & mask , sizeof ( mask ) ) ; sin = mask ; sin . sin_family = AF_INET ; sin . sin_len = sizeof ( sin ) ; error = rtrequest ( RTM_ADD , ( struct sockaddr * ) & sin , ( struct sockaddr * ) & nd -> mygateway , ( struct sockaddr * ) & mask , RTF_UP | RTF_GATEWAY , ( struct rtentry * * ) 0 ) ; if ( error ) { printf ( " " , error ) ; return ( error ) ; } } swap_mp = NULL ; if ( nd -> swap_nblks ) { nd -> swap_args . fh = nd -> swap_fh ; nd -> swap_args . fhsize = NFSX_V2FH ; l = ntohl ( nd -> swap_saddr . sin_addr . s_addr ) ; sprintf ( buf , " " , ( l >> 24 ) & 0xff , ( l >> 16 ) & 0xff , ( l >> 8 ) & 0xff , ( l >> 0 ) & 0xff , nd -> swap_hostnam ) ; printf ( " \n " , buf ) ; if ( error = nfs_mountdiskless ( buf , " " , 0 , & nd -> swap_saddr , & nd -> swap_args , p , & vp , & swap_mp ) ) return ( error ) ; vfs_unbusy ( swap_mp , p ) ; for ( i = 0 ; swdevt [ i ] . sw_dev != NODEV ; i ++ ) ; vp -> v_type = VREG ; vp -> v_flag = 0 ; swapdev_vp = vp ; VREF ( vp ) ; swdevt [ i ] . sw_vp = vp ; swdevt [ i ] . sw_nblks = nd -> swap_nblks * 2 ; if ( ! swdevt [ i ] . sw_nblks ) { swdevt [ i ] . sw_nblks = 2048 ; printf ( " \n " , swdevt [ i ] . sw_nblks / 2 ) ; } else printf ( " \n " , swdevt [ i ] . sw_nblks / 2 ) ; } nd -> root_args . fh = nd -> root_fh ; nd -> root_args . fhsize = NFSX_V2FH ; l = ntohl ( nd -> swap_saddr . sin_addr . s_addr ) ; sprintf ( buf , " " , ( l >> 24 ) & 0xff , ( l >> 16 ) & 0xff , ( l >> 8 ) & 0xff , ( l >> 0 ) & 0xff , nd -> root_hostnam ) ; printf ( " \n " , buf ) ; if ( error = nfs_mountdiskless ( buf , " " , MNT_RDONLY , & nd -> root_saddr , & nd -> root_args , p , & vp , & mp ) ) { if ( swap_mp ) { mp -> mnt_vfc -> vfc_refcount -- ; free ( swap_mp , M_MOUNT ) ; } return ( error ) ; } simple_lock ( & mountlist_slock ) ; CIRCLEQ_INSERT_TAIL ( & mountlist , mp , mnt_list ) ; simple_unlock ( & mountlist_slock ) ; rootvp = vp ; vfs_unbusy ( mp , p ) ; bcopy ( nd -> my_hostnam , hostname , MAXHOSTNAMELEN ) ; hostname [ MAXHOSTNAMELEN - 1 ] = ' \0 ' ; for ( i = 0 ; i < MAXHOSTNAMELEN ; i ++ ) if ( hostname [ i ] == ' \0 ' ) break ; hostnamelen = i ; inittodr ( ntohl ( nd -> root_time ) ) ; return ( 0 ) ; }
Mount a remote root fs via.
Mount a remote root fs via .
/* XXX */ /*
	 * XXX time must be non-zero when we init the interface or else
	 * the arp code will wedge...
	 */ /* 
	 * XXX splnet, so networks will receive...
	 */ /* Set up swap credentials. */ /*
	 * Do enough of ifconfig(8) so that the critical net interface can
	 * talk to the server.
	 */ /*
	 * We might not have been told the right interface, so we pass
	 * over the first ten interfaces of the same kind, until we get
	 * one of them configured.
	 */ /*
	 * If the gateway field is filled in, set it as the default route.
	 */ /*
		 * Create a fake mount point just for the swap vnode so that the
		 * swap file can be on a different server from the rootfs.
		 */ /*
		 * If using nfsv3_diskless, replace NFSX_V2FH with
		 * nd->swap_fhsize.
		 */ /*
		 * Since the swap file is not the root dir of a file system,
		 * hack it to a regular file.
		 */ /*
	 * Create the rootfs mount point.
	 */ /*
	 * If using nfsv3_diskless, replace NFSX_V2FH with nd->root_fhsize.
	 */ /*
	 * This is not really an nfs issue, but it is much easier to
	 * set hostname here and then let the "/etc/rc.xxx" files
	 * mount the right /var based upon its preset value.
	 */