⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfsroot.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 3 页
字号:
	printk("local=%s, ", IN_NTOA(myaddr.sin_addr.s_addr));	printk("server=%s, ", IN_NTOA(server.sin_addr.s_addr));	printk("gw=%s, ", IN_NTOA(gateway.sin_addr.s_addr));	printk("mask=%s, ", IN_NTOA(netmask.sin_addr.s_addr));	printk("host=%s, domain=%s\n",		system_utsname.nodename[0] ? system_utsname.nodename : "none",		system_utsname.domainname[0] ? system_utsname.domainname : "none");	printk(KERN_NOTICE "Root-NFS: Mounting %s on server %s as root\n",		nfs_path, nfs_data.hostname);	printk(KERN_NOTICE "Root-NFS:     rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",		nfs_data.rsize, nfs_data.wsize, nfs_data.timeo, nfs_data.retrans);	printk(KERN_NOTICE "Root-NFS:     acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n",		nfs_data.acregmin, nfs_data.acregmax,		nfs_data.acdirmin, nfs_data.acdirmax);	printk(KERN_NOTICE "Root-NFS:     port = %d, flags = %08x\n",		nfs_port, nfs_data.flags);#undef IN_NTOA}#endif/* *  Decode any IP configuration options in the "nfsaddrs" kernel command *  line parameter. It consists of option fields separated by colons in *  the following order: * *  <client-ip>:<server-ip>:<gw-ip>:<netmask>:<host name>:<device>:<bootp|rarp> * *  Any of the fields can be empty which means to use a default value: *	<client-ip>	- address given by BOOTP or RARP *	<server-ip>	- address of host returning BOOTP or RARP packet *	<gw-ip>		- none, or the address returned by BOOTP *	<netmask>	- automatically determined from <client-ip>, or the *			  one returned by BOOTP *	<host name>	- <client-ip> in ASCII notation, or the name returned *			  by BOOTP *	<device>	- use all available devices for RARP and the first *			  one for BOOTP *	<bootp|rarp>	- use both protocols to determine my own address */static void root_nfs_addrs(char *addrs){	char *cp, *ip, *dp;	int num = 0;	/* Clear all addresses and strings */	myaddr.sin_family = server.sin_family = rarp_serv.sin_family =	    gateway.sin_family = netmask.sin_family = AF_INET;	myaddr.sin_addr.s_addr = server.sin_addr.s_addr = rarp_serv.sin_addr.s_addr =	    gateway.sin_addr.s_addr = netmask.sin_addr.s_addr = INADDR_NONE;	system_utsname.nodename[0] = '\0';	system_utsname.domainname[0] = '\0';	user_dev_name[0] = '\0';	bootp_flag = rarp_flag = 1;	/* The following is just a shortcut for automatic IP configuration */	if (!strcmp(addrs, "bootp")) {		rarp_flag = 0;		return;	} else if (!strcmp(addrs, "rarp")) {		bootp_flag = 0;		return;	} else if (!strcmp(addrs, "both")) {		return;	}	/* Parse the whole string */	ip = addrs;	while (ip && *ip) {		if ((cp = strchr(ip, ':')))			*cp++ = '\0';		if (strlen(ip) > 0) {#ifdef NFSROOT_DEBUG			printk(KERN_NOTICE "Root-NFS: Config string num %d is \"%s\"\n",								num, ip);#endif			switch (num) {			case 0:				if ((myaddr.sin_addr.s_addr = in_aton(ip)) == INADDR_ANY)					myaddr.sin_addr.s_addr = INADDR_NONE;				break;			case 1:				if ((server.sin_addr.s_addr = in_aton(ip)) == INADDR_ANY)					server.sin_addr.s_addr = INADDR_NONE;				break;			case 2:				if ((gateway.sin_addr.s_addr = in_aton(ip)) == INADDR_ANY)					gateway.sin_addr.s_addr = INADDR_NONE;				break;			case 3:				if ((netmask.sin_addr.s_addr = in_aton(ip)) == INADDR_ANY)					netmask.sin_addr.s_addr = INADDR_NONE;				break;			case 4:				if ((dp = strchr(ip, '.'))) {					*dp++ = '\0';					strncpy(system_utsname.domainname, dp, __NEW_UTS_LEN);					system_utsname.domainname[__NEW_UTS_LEN] = '\0';				}				strncpy(system_utsname.nodename, ip, __NEW_UTS_LEN);				system_utsname.nodename[__NEW_UTS_LEN] = '\0';				break;			case 5:				strncpy(user_dev_name, ip, IFNAMSIZ);				user_dev_name[IFNAMSIZ-1] = '\0';				break;			case 6:				if (!strcmp(ip, "rarp"))					bootp_flag = 0;				else if (!strcmp(ip, "bootp"))					rarp_flag = 0;				else if (strcmp(ip, "both"))					bootp_flag = rarp_flag = 0;				break;			default:				break;			}		}		ip = cp;		num++;	}	rarp_serv = server;}/* *  Set the interface address and configure a route to the server. */static int root_nfs_setup(void){	struct rtentry route;	/* Set the default system name in case none was previously found */	if (!system_utsname.nodename[0]) {		strncpy(system_utsname.nodename, in_ntoa(myaddr.sin_addr.s_addr), __NEW_UTS_LEN);		system_utsname.nodename[__NEW_UTS_LEN] = '\0';	}	/* Set the correct netmask */	if (netmask.sin_addr.s_addr == INADDR_NONE)		netmask.sin_addr.s_addr = ip_get_mask(myaddr.sin_addr.s_addr);	/* Setup the device correctly */	root_dev->family     = myaddr.sin_family;	root_dev->pa_addr    = myaddr.sin_addr.s_addr;	root_dev->pa_mask    = netmask.sin_addr.s_addr;	root_dev->pa_brdaddr = root_dev->pa_addr | ~root_dev->pa_mask;	root_dev->pa_dstaddr = 0;	/*	 * Now add a route to the server. If there is no gateway given,	 * the server is on the same subnet, so we establish only a route to	 * the local network. Otherwise we create a route to the gateway (the	 * same local network router as in the former case) and then setup a	 * gatewayed default route. Note that this gives sufficient network	 * setup even for full system operation in all common cases.	 */	memset(&route, 0, sizeof(route));	/* Local subnet route */	route.rt_dev = root_dev->name;	route.rt_mss = root_dev->mtu;	route.rt_flags = RTF_UP;	*((struct sockaddr_in *) &(route.rt_dst)) = myaddr;	(((struct sockaddr_in *) &(route.rt_dst)))->sin_addr.s_addr &= netmask.sin_addr.s_addr;	*((struct sockaddr_in *) &(route.rt_genmask)) = netmask;	if (ip_rt_new(&route)) {		printk(KERN_ERR "Root-NFS: Adding of local route failed!\n");		return -1;	}	if (gateway.sin_addr.s_addr != INADDR_NONE) {	/* Default route */		(((struct sockaddr_in *) &(route.rt_dst)))->sin_addr.s_addr = INADDR_ANY;		(((struct sockaddr_in *) &(route.rt_genmask)))->sin_addr.s_addr = INADDR_ANY;		*((struct sockaddr_in *) &(route.rt_gateway)) = gateway;		route.rt_flags |= RTF_GATEWAY;		if ((gateway.sin_addr.s_addr ^ myaddr.sin_addr.s_addr) & netmask.sin_addr.s_addr) {			printk(KERN_ERR "Root-NFS: Gateway not on local network!\n");			return -1;		}		if (ip_rt_new(&route)) {			printk(KERN_ERR "Root-NFS: Adding of default route failed!\n");			return -1;		}	} else if ((server.sin_addr.s_addr ^ myaddr.sin_addr.s_addr) & netmask.sin_addr.s_addr) {		printk(KERN_ERR "Root-NFS: Boot server not on local network and no default gateway configured!\n");		return -1;	}	return 0;}/* *  Get the necessary IP addresses and prepare for mounting the required *  NFS filesystem. */int nfs_root_init(char *nfsname, char *nfsaddrs){	/*	 * Decode IP addresses and other configuration info contained	 * in the nfsaddrs string (which came from the kernel command	 * line).	 */	root_nfs_addrs(nfsaddrs);	/*	 * Setup all network devices	 */	if (root_dev_open() < 0)		return -1;	/*	 * If the config information is insufficient (e.g., our IP address or	 * IP address of the boot server is missing or we have multiple network	 * interfaces and no default was set), use BOOTP or RARP to get the	 * missing values.	 *	 * Note that we don't try to set up correct routes for multiple	 * interfaces (could be solved by trying icmp echo requests), because	 * it's only necessary in the rare case of multiple ethernet devices	 * in the (diskless) system and if the server is on another subnet.	 * If only one interface is installed, the routing is obvious.	 */	if ((myaddr.sin_addr.s_addr == INADDR_NONE ||	     server.sin_addr.s_addr == INADDR_NONE ||	     (open_base != NULL && open_base->next != NULL))#ifdef CONFIG_RNFS_DYNAMIC		&& root_auto_config() < 0#endif	   ) {		root_dev_close();		return -1;	}	if (root_dev == NULL) {		if (open_base != NULL && open_base->next == NULL) {			root_dev = open_base->dev;		} else {			printk(KERN_ERR "Root-NFS: Multiple devices and no server\n");			root_dev_close();			return -1;		}	}	/*	 * Close all network devices except the device which connects to	 * server	 */	root_dev_close();	/*	 * Decode the root directory path name and NFS options from	 * the kernel command line. This has to go here in order to	 * be able to use the client IP address for the remote root	 * directory (necessary for pure RARP booting).	 */	if (root_nfs_name(nfsname) < 0)		return -1;	/*	 * Setup devices and routes. The server directory is actually	 * mounted after init() has been started.	 */	if (root_nfs_setup() < 0)		return -1;#ifdef NFSROOT_DEBUG	root_nfs_print();#endif	return 0;}/***************************************************************************	       Routines to actually mount the root directory ***************************************************************************/static struct file  *nfs_file;		/* File descriptor pointing to inode */static struct inode *nfs_sock_inode;	/* Inode containing socket */static int *rpc_packet = NULL;		/* RPC packet *//* *  Open a UDP socket. */static int root_nfs_open(void){	/* Open the socket */	if ((nfs_data.fd = sys_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {		printk(KERN_ERR "Root-NFS: Cannot open UDP socket for NFS!\n");		return -1;	}	nfs_file = current->files->fd[nfs_data.fd];	nfs_sock_inode = nfs_file->f_inode;	return 0;}/* *  Close the UDP file descriptor. If nfs_read_super is successful, it *  increases the reference count, so we can simply close the file, and *  the socket keeps open. */static void root_nfs_close(void){	/*	 * The following close doesn't touch the server structure, which	 * now contains a file pointer pointing into nowhere. The system	 * _should_ crash as soon as someone tries to select on the root	 * filesystem. Haven't tried it yet - we can still change it back	 * to the old way of keeping a static copy of all important data	 * structures, including their pointers. At least this should be	 * checked out _carefully_ before going into a public release	 * kernel.  -  GK	 */	sys_close(nfs_data.fd);}/* *  Find a suitable listening port and bind to it */static int root_nfs_bind(void){	int res = -1;	short port = STARTPORT;	struct sockaddr_in *sin = &myaddr;	int i;	if (nfs_sock_inode->u.socket_i.ops->bind) {		for (i = 0; i < NPORTS && res < 0; i++) {			sin->sin_port = htons(port++);			if (port > ENDPORT) {				port = STARTPORT;			}			res = nfs_sock_inode->u.socket_i.ops->bind(&nfs_sock_inode->u.socket_i,						(struct sockaddr *)sin,						sizeof(struct sockaddr_in));		}	}	if (res < 0) {		printk(KERN_ERR "Root-NFS: Cannot find a suitable listening port\n");		root_nfs_close();		return -1;	}#ifdef NFSROOT_DEBUG	printk(KERN_NOTICE "Root-NFS: Binding to listening port %d\n", port);#endif	return 0;}/* *  Send an RPC request and wait for the answer */static int *root_nfs_call(int *end){	struct socket *sock;	int dummylen;	static struct nfs_server s = {		0,			/* struct file *	 */		0,			/* struct rsock *	 */		{		    0, "",		},			/* toaddr		 */		0,			/* lock			 */		NULL,			/* wait queue		 */		NFS_MOUNT_SOFT,		/* flags		 */		0, 0,			/* rsize, wsize		 */		0,			/* timeo		 */		0,			/* retrans		 */		3 * HZ, 60 * HZ, 30 * HZ, 60 * HZ, "\0"	};	s.file = nfs_file;	sock = &((nfs_file->f_inode)->u.socket_i);	/* Extract the other end of the socket into s->toaddr */	sock->ops->getname(sock, &(s.toaddr), &dummylen, 1);	((struct sockaddr_in *) &s.toaddr)->sin_port   = server.sin_port;	((struct sockaddr_in *) &s.toaddr)->sin_family = server.sin_family;	((struct sockaddr_in *) &s.toaddr)->sin_addr.s_addr = server.sin_addr.s_addr;	s.rsock = rpc_makesock(nfs_file);	s.flags = nfs_data.flags;	s.rsize = nfs_data.rsize;	s.wsize = nfs_data.wsize;	s.timeo = nfs_data.timeo * HZ / 10;	s.retrans = nfs_data.retrans;	strcpy(s.hostname, nfs_data.hostname);	/*	 * First connect the UDP socket to a server port, then send the	 * packet out, and finally check whether the answer is OK.	 */	if (nfs_sock_inode->u.socket_i.ops->connect &&	    nfs_sock_inode->u.socket_i.ops->connect(&nfs_sock_inode->u.socket_i,						(struct sockaddr *) &server,						sizeof(struct sockaddr_in),						nfs_file->f_flags) < 0)		return NULL;	if (nfs_rpc_call(&s, rpc_packet, end, nfs_data.wsize) < 0)		return NULL;	return rpc_verify(rpc_packet);}/* *  Create an RPC packet header */static int *root_nfs_header(int proc, int program, int version){	int groups[] = { 0, NOGROUP };	if (rpc_packet == NULL) {		if (!(rpc_packet = kmalloc(nfs_data.wsize + 1024, GFP_NFS))) {			printk(KERN_ERR "Root-NFS: Cannot allocate UDP buffer\n");			return NULL;		}	}	return rpc_header(rpc_packet, proc, program, version, 0, 0, groups);}/* *  Query server portmapper for the port of a daemon program */static int root_nfs_get_port(int program, int version){	int *p;	/* Prepare header for portmap request */	server.sin_port = htons(NFS_PMAP_PORT);	p = root_nfs_header(NFS_PMAP_PROC, NFS_PMAP_PROGRAM, NFS_PMAP_VERSION);	if (!p)		return -1;	/* Set arguments for portmapper */	*p++ = htonl(program);	*p++ = htonl(version);	*p++ = htonl(IPPROTO_UDP);	*p++ = 0;	/* Send request to server portmapper */	if ((p = root_nfs_call(p)) == NULL)		return -1;	return ntohl(*p);}/* *  Get portnumbers for mountd and nfsd from server */static int root_nfs_ports(void){	int port;	if (nfs_port < 0) {		if ((port = root_nfs_get_port(NFS_NFS_PROGRAM, NFS_NFS_VERSION)) < 0) {			printk(KERN_ERR "Root-NFS: Unable to get nfsd port number from server, using default\n");			port = NFS_NFS_PORT;		}		nfs_port = port;#ifdef NFSROOT_DEBUG		printk(KERN_NOTICE "Root-NFS: Portmapper on server returned %d as nfsd port\n", port);#endif	}	if ((port = root_nfs_get_port(NFS_MOUNT_PROGRAM, NFS_MOUNT_VERSION)) < 0) {		printk(KERN_ERR "Root-NFS: Unable to get mountd port number from server, using default\n");		port = NFS_MOUNT_PORT;	}	server.sin_port = htons(port);#ifdef NFSROOT_DEBUG	printk(KERN_NOTICE "Root-NFS: Portmapper on server returned %d as mountd port\n", port);#endif	return 0;}/* *  Get a file handle from the server for the directory which is to be *  mounted */static int root_nfs_get_handle(void){	int len, status, *p;	/* Prepare header for mountd request */	p = root_nfs_header(NFS_MOUNT_PROC, NFS_MOUNT_PROGRAM, NFS_MOUNT_VERSION);	if (!p) {		root_nfs_close();		return -1;	}	/* Set arguments for mountd */	len = strlen(nfs_path);	*p++ = htonl(len);	memcpy(p, nfs_path, len);	len = (len + 3) >> 2;	p[len] = 0;	p += len;	/* Send request to server mountd */	if ((p = root_nfs_call(p)) == NULL) {		root_nfs_close();		return -1;	}	status = ntohl(*p++);	if (status == 0) {		nfs_data.root = *((struct nfs_fh *) p);		printk(KERN_NOTICE "Root-NFS: Got file handle for %s via RPC\n", nfs_path);	} else {		printk(KERN_ERR "Root-NFS: Server returned error %d while mounting %s\n",			status, nfs_path);		root_nfs_close();		return -1;	}	return 0;}/* *  Now actually mount the given directory */static int root_nfs_do_mount(struct super_block *sb){	/* First connect to the nfsd port on the server */	server.sin_port = htons(nfs_port);	nfs_data.addr = server;	if (nfs_sock_inode->u.socket_i.ops->connect &&	    nfs_sock_inode->u.socket_i.ops->connect(&nfs_sock_inode->u.socket_i,						(struct sockaddr *) &server,						sizeof(struct sockaddr_in),						nfs_file->f_flags) < 0) {		root_nfs_close();		return -1;	}	/* Now (finally ;-)) read the super block for mounting */	if (nfs_read_super(sb, &nfs_data, 1) == NULL) {		root_nfs_close();		return -1;	}	return 0;}/* *  Get the NFS port numbers and file handle, and then read the super- *  block for mounting. */int nfs_root_mount(struct super_block *sb){	if (root_nfs_open() < 0)		return -1;	if (root_nfs_bind() < 0)		return -1;	if (root_nfs_ports() < 0)		return -1;	if (root_nfs_get_handle() < 0)		return -1;	if (root_nfs_do_mount(sb) < 0)		return -1;	root_nfs_close();	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -