📄 nfs_vfsops.c
字号:
/* @(#)nfs_vfsops.c 1.1 92/07/30 SMI *//* * Copyright (c) 1986 by Sun Microsystems, Inc. */#include <sys/param.h>#include "boot/systm.h"#include <sys/user.h>#include <sys/vfs.h>#include "boot/vnode.h"#include <sys/pathname.h>#include <sys/uio.h>#include <sys/socket.h>#include <sys/kernel.h>#include <netinet/in.h>#include <rpc/types.h>#include <rpc/xdr.h>#include <rpc/auth.h>#include <rpc/clnt.h>#include <rpc/pmap_rmt.h>#include <rpc/pmap_prot.h>#include <rpcsvc/bootparam.h>#include "boot/nfs.h"#include <nfs/nfs_clnt.h>#include <nfs/rnode.h>#include <sys/mount.h>#include <net/if.h>#include <net/if_arp.h>#include <netinet/if_ether.h>#include <net/route.h>#include <rpcsvc/mount.h>#include <sys/bootconf.h>#include <sys/ioctl.h>#include <stand/saio.h>extern struct ifnet *if_ifwithaf();extern int verbosemode;struct vnode *nfsrootvp();struct vnode *makenfsnode();int nfsmntno;#ifdef NFSDEBUGstatic int nfsdebug = 10;#endif#undef NFS_RETRIES#define NFS_RETRIES 10 /* times to retry request *//* * nfs vfs operations. */int nfs_root();int nfs_statfs();int nfs_mountroot();extern int nfs_badop();struct vfsops nfs_vfsops = { nfs_badop, /* nfs_mount, */ nfs_badop, /* nfs_unmount, */ nfs_root, /* nfs_root, */ nfs_statfs, nfs_badop, /* nfs_sync, */ nfs_badop, nfs_mountroot, nfs_badop, /* nfs_swapvp, */};/* * Fake up a user structure. */#undef u;extern struct user u;int ethernet_started = 0;/* * Called by vfs_mountroot when nfs is going to be mounted as root */nfs_mountroot(vfsp, vpp, name) struct vfs *vfsp; struct vnode **vpp; char *name;{ struct sockaddr_in root_sin; struct vnode *rtvp; char *root_path; char root_hostname[MAXHOSTNAMELEN+1]; char root_name[MAXHOSTNAMELEN+1]; fhandle_t root_fhandle; int rc; enum clnt_stat status; int error; /* * Extra code to ensure that we open the * ethernet device and initialise the inet * tables. */ if (ethernet_started == 0) { ethersetup(); domaininit(); ip_init(); ethernet_started = 1; } /* * Ensure that the routing table entry * gets made. */ error = whoami(); if (error != 0) { printf ("Boot: bad dialog with bootparam server: "); errno_print(error); printf("(errno 0x%x\n", error); return (error); } strcpy(root_name, "root"); getfsname("root", root_name); if (root_name[0] == (char)0) { strcpy(root_name, "root"); printf("root name: root\n"); } root_path = kmem_alloc(MAX_MACHINE_NAME + 1); do { rc = getfile(root_name, root_hostname, (struct sockaddr *)&root_sin, root_path); } while (rc == ETIMEDOUT);#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfs_mountroot: root_path '%s'\n", root_path);#endif /* NFSDEBUG */ if (rc) { kmem_free(root_path, MAX_MACHINE_NAME + 1); return (rc); } rc = mountrpc(&root_sin, root_path, &root_fhandle); if (rc) { printf("Boot: NFS mount of '%s:%s' failed\n", root_hostname, root_path); kmem_free(root_path, MAX_MACHINE_NAME + 1); return (rc); } rtvp = nfsrootvp(vfsp, &root_sin, &root_fhandle, root_hostname); if (rtvp) {#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfs_mountroot: rtvp 0x%x\n", rtvp);#endif /* NFSDEBUG */ if (rc = vfs_add((struct vnode *)0, vfsp, 0)) { kmem_free(root_path, MAX_MACHINE_NAME + 1); return (rc); } vfs_unlock(rtvp->v_vfsp); *vpp = rtvp; { register char *nm; (void) strcpy(name, root_hostname); for (nm = name; *nm; nm++) ; *nm++ = ':'; (void) strcpy(nm, root_path); } kmem_free(root_path, MAX_MACHINE_NAME + 1); return (0); } printf ("Boot: root file system already mounted\n"); kmem_free(root_path, MAX_MACHINE_NAME + 1); return (EBUSY);}/* * pmapper remote-call-service interface. * This routine is used to call the pmapper remote call service * which will look up a service program in the port maps, and then * remotely call that routine with the given parameters. This allows * programs to do a lookup and call in one step.*/static enum clnt_statpmap_rmtcall(call_addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, resp_addr) struct sockaddr_in *call_addr; u_long prog, vers, proc; xdrproc_t xdrargs, xdrres; caddr_t argsp, resp; struct timeval tout; struct sockaddr_in *resp_addr;{ register CLIENT *client; struct rmtcallargs a; struct rmtcallres r; enum clnt_stat stat, clntkudp_callit_addr(); u_long port; call_addr->sin_port = htons(PMAPPORT); client = clntkudp_create(call_addr, PMAPPROG, PMAPVERS, 10, u.u_cred); if (client != (CLIENT *)NULL) { a.prog = prog; a.vers = vers; a.proc = proc; a.args_ptr = argsp; a.xdr_args = xdrargs; r.port_ptr = &port; r.results_ptr = resp; r.xdr_results = xdrres; if (verbosemode) { printf("call portmapper: "); printf("to "); inet_print(call_addr->sin_addr); printf(" port %d: prog %d vers %d proc %d\n", call_addr->sin_port, a.prog, a.vers, a.proc); } stat = clntkudp_callit_addr(client, PMAPPROC_CALLIT, xdr_rmtcall_args, (caddr_t)&a, xdr_rmtcallres, (caddr_t)&r, tout, resp_addr, 1); if (verbosemode) { printf("portmapper reply "); clntstat_print(stat); printf("\n"); } resp_addr->sin_port = port; CLNT_DESTROY(client); } else { printf("Boot: remote call failed - "); printf("couldn't create client handle\n"); } return (stat);}struct clntstat { long status; char *name;} clntstat[] = { RPC_SUCCESS, "succeeded", RPC_CANTENCODEARGS, "failed: can't encode arguments", RPC_CANTDECODERES, "failed: can't decode results", RPC_CANTSEND, "failed: failure in sending call", RPC_CANTRECV, "failed: failure in receiving result", RPC_TIMEDOUT, "timed out", RPC_INTR, "failed: call interrupted", RPC_VERSMISMATCH, "failed: rpc versions not compatible", RPC_AUTHERROR, "failed: authentication error", RPC_PROGUNAVAIL, "failed: program not available", RPC_PROGVERSMISMATCH, "failed: program version mismatched", RPC_PROCUNAVAIL, "failed: procedure unavailable", RPC_CANTDECODEARGS, "failed: decode arguments error", RPC_SYSTEMERROR, "failed: RPC_SYSTEMERROR", RPC_UNKNOWNHOST, "failed: unknown host name", RPC_UNKNOWNPROTO, "failed: unknown protocol", RPC_PMAPFAILURE, "failed: the pmapper failed in its call", RPC_PROGNOTREGISTERED, "failed: remote program is not registered", RPC_FAILED, "failed: RPC_FAILED", -1, ""};clntstat_print(stat)long stat;{ int i; char *name = "failed: unknown status"; for (i = 0; clntstat[i].status != -1; i++) if (stat == clntstat[i].status) { name = clntstat[i].name; break; } printf(name); printf(" (status %d)", stat);}static struct sockaddr_in bootparam_addr;extern struct in_addr my_in_addr;extern struct ether_addr destetheraddr;static intwhoami(){ struct sockaddr_in sa; struct ifnet *ifp; struct bp_whoami_arg arg; struct bp_whoami_res res; struct timeval tv; ip_addr_t *ip; struct in_addr *ip1; struct in_addr *inp; enum clnt_stat status; int error; struct rtentry rtentry; struct sockaddr_in *sin; enum clnt_stat callrpc(); int msg; bzero(&sa, sizeof sa); ifp = if_ifwithaf(AF_INET); if (ifp == 0) { printf ("Boot: cannot open INET interface\n"); return (EHOSTUNREACH); } if (!address_known(ifp)) { revarp_myaddr(ifp); } /* * Set interface broadcast address to 255.255.255.255 */ ip1 = &(((struct sockaddr_in *) &(ifp->if_addrlist->ifa_broadaddr))->sin_addr); ip1->s_addr = 0xFFFFFFFF; sa = *((struct sockaddr_in *)&(ifp->if_addrlist->ifa_broadaddr)); arg.client_address.address_type = IP_ADDR_TYPE; ip = &arg.client_address.bp_address.ip_addr; inp = &((struct sockaddr_in *)&(ifp->if_addrlist->ifa_addr))->sin_addr; ip->net = inp->s_net; ip->host = inp->s_host; ip->lh = inp->s_lh; ip->impno = inp->s_impno; /* initial timeout before displaying warning msg */ tv.tv_sec = 4; tv.tv_usec = 0; hostnamelen = 0; res.client_name = (bp_machine_name_t) kmem_alloc(MAX_MACHINE_NAME + 1); if (res.client_name == NULL) { printf ("Boot: out of memory\n"); return (ENOMEM); } res.domain_name = (bp_machine_name_t) kmem_alloc(MAX_MACHINE_NAME + 1); if (res.domain_name == NULL) { printf ("Boot: out of memory\n"); return (ENOMEM); } for (;;) { msg = 0; status = pmap_rmtcall(&sa, (u_long)BOOTPARAMPROG, (u_long)BOOTPARAMVERS, BOOTPARAMPROC_WHOAMI, xdr_bp_whoami_arg, (char *)&arg, xdr_bp_whoami_res, (char *)&res, tv, &bootparam_addr); if (status == RPC_TIMEDOUT) { if (msg == 0) { printf("%s%s\n", "No bootparam server", " responding; still trying"); msg = 1; } tv.tv_sec = 60; continue; } break; } if (status != RPC_SUCCESS) { printf("Boot: RPC call "); clntstat_print(status); printf("\n"); return (EIO); /* generic errno */ } if (verbosemode) { printf("got machine_name %s ", res.client_name); printf("domain_name %s ", res.domain_name); printf("router_address "); inet_print(res.router_address.bp_address.ip_addr); printf("\n"); } if (msg) printf("Bootparam response received\n"); (void) set_ether_addr(bootparam_addr.sin_addr, (struct ether_addr *) &destetheraddr); hostnamelen = strlen(res.client_name); if (hostnamelen > sizeof hostname) { printf("Boot: hostname returned by bootparam server is too long"); printf("Boot: hostname '%s'\n", res.client_name); return (ENAMETOOLONG); } if (hostnamelen > 0) { bcopy(res.client_name, hostname, hostnamelen); hostname[hostnamelen] = '\0'; } else { printf("Boot: null host name returned by bootparam server\n"); return (ENXIO); } kmem_free(res.client_name, MAX_MACHINE_NAME); printf("hostname: %s\n", hostname); domainnamelen = strlen(res.domain_name); if (domainnamelen > sizeof domainname) { printf("Boot: domainname returned by bootparam server is too long"); printf("Boot: domainname '%s'\n", res.domain_name); return (ENAMETOOLONG); } if (domainnamelen > 0) { bcopy(res.domain_name, domainname, domainnamelen); printf("domainname: %s\n", domainname); } else { printf("Boot: null domain name returned by bootparam server\n"); } kmem_free(res.domain_name, MAX_MACHINE_NAME); if (res.router_address.address_type == IP_ADDR_TYPE) { sin = (struct sockaddr_in *) &rtentry.rt_dst; bzero(sin, sizeof *sin); sin->sin_family = AF_INET; sin = (struct sockaddr_in *) &rtentry.rt_gateway; bzero(sin, sizeof *sin); sin->sin_family = AF_INET; sin->sin_addr.s_net = res.router_address.bp_address.ip_addr.net;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -