[Prev][Next][Index][Thread]

Netboot tweaks




I'm looking for a few good beta testers for a faster netboot.  This
one's a bit smarter about fetching packets off the net - instead of
doing a serial "request, wait, request, wait" it batches up the
requests together to improve life.  On our test machines (100Mbit), it 
reduces the netboot time to about 70% of the pre-patch time.

A patch to oskit.../boot/net/* is included.  If you use it, please let 
me know if you encounter any problems.  If you experience packet loss, 
edit boot/net/rpc.c and change the line:

#define BUFMAX 4

to 

#define BUFMAX 2

and see if it's better.  4 should be just peachy - the oskit drivers
will actually buffer 100 packets by default - but if your NFS server
is overloaded, it could hit it too fast.  If all is well with it,
it'll go out in the next release.  I've been using it here for two
weeks without problems.

   -Dave
--
work: danderse@cs.utah.edu                     me:  angio@pobox.com
      University of Utah                            http://www.angio.net/
      Computer Science - Flux Research Group


Index: GNUmakerules
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/GNUmakerules,v
retrieving revision 1.34
retrieving revision 1.35
diff -r1.34 -r1.35
41c41
< 	echo >$@ "char version[] = \"NetBoot metakernel v2.5.1\";"
---
> 	echo >$@ "char version[] = \"NetBoot metakernel v2.6.0\";"
Index: await.c
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/await.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -r1.12 -r1.13
84c84
< 			   (ntohl(rpc->u.reply.id) == ival) &&
---
> 			   (!ival || (ntohl(rpc->u.reply.id) == ival)) &&
Index: getkernel_net.c
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/getkernel_net.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -r1.9 -r1.10
2c2
<  * Copyright (c) 1996-1998 University of Utah and the Flux Group.
---
>  * Copyright (c) 1996-1999 University of Utah and the Flux Group.
39a40
> 	int readahead;
46a48
> 		readahead = (size / NFS_READ_SIZE) - 1;
48c50
< 			     offset, chunk_size, bufp);
---
> 			     offset, chunk_size, bufp, readahead);
Index: rpc.c
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/rpc.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -r1.7 -r1.8
23a24,31
> #undef min
> #define min(a,b)	((a) < (b)? (a) : (b))
> 
> #define BUFMAX 4
> 
> struct rpc_buf read_cache[BUFMAX];
> int read_cache_size = 0;
> 
28a37
> 	int i;
29a39,43
> 	for (i = 0; i < BUFMAX; i++) {
> 		read_cache[i].valid = 0;
> 		read_cache[i].offset = 0;
> 		read_cache[i].len = 0;
> 	}
131a146,170
> CHECK_READ_CACHE:  Determine if a block is in the read cache
> 
> ***************************************************************************/
> 
> int
> check_read_cache(offset, len, buffer)
> {
> 	int i;
> 	struct rpc_buf *cache;
> 	int rlen = 0;
> 	
> 	for (i = 0; i < BUFMAX; i++) {
> 		cache = &(read_cache[i]);
> 		if (cache->valid &&
> 		    cache->offset == offset &&
> 		    cache->len    >= len) {
> 			memcpy(buffer, cache->buffer, len);
> 			rlen = len;
> 		}
> 	}
> 	return rlen;
> }
> 
> /***************************************************************************
> 
136c175,176
< nfs_read(int server, int port, char *fh, int offset, int len, char *buffer)
---
> nfs_read(int server, int port, char *fh, int offset, int len, char *buffer,
> 	 int readahead)
142,146c182,269
< 	rpcptr = netsprintf(buf.u.data,
< 		"%L%L%L%L%L%L%L%L%L%S%L%L%L%L%L%L%L%M%L%L%L",
< 		rpc_id, MSG_CALL, 2, PROG_NFS, 2, NFS_READ,
< 		1, hostnamelen + 28,0,hostname,0,0,2,0,0,0,0,
< 		32, fh, offset, len, 0);
---
> 	int     i, curoff, pktcount = 0;
> 	int     saved_rpc_id;
> 	int     rid;
> 	struct rpc_buf *cache;
> 
> 	rlen = check_read_cache(offset, len, buffer);
> 	if (rlen) {
> 		return rlen;
> 	}
> 
> 	/*
> 	 * Since the cache is purely readahead, fill 'er up if we
> 	 * miss.  It's not going to be as efficient as it could
> 	 * in the face of packet loss, but we're not doing
> 	 * this in a particularly smart way anyway. :)
> 	 */
> 
> 	readahead = min(readahead, BUFMAX);
> 	saved_rpc_id = rpc_id;
> 
> 	if (readahead < 1) readahead = 1;
> 	
> 	curoff = offset;
> 	while (readahead) {
> 		cache = &(read_cache[rpc_id - saved_rpc_id]);
> 		cache->valid = 0;
> 		cache->offset = curoff;
> 		cache->len = len;
> 		cache->id  = rpc_id;
> 		
> 		rpcptr = netsprintf(buf.u.data,
> 		        "%L%L%L%L%L%L%L%L%L%S%L%L%L%L%L%L%L%M%L%L%L",
> 			rpc_id, MSG_CALL, 2, PROG_NFS, 2, NFS_READ,
> 		        1, hostnamelen + 28,0,hostname,0,0,2,0,0,0,0,
> 		        32, fh, curoff, len, 0);
> 		curoff += len;
> 		readahead--;
> 		pktcount++;
> 		rpc_id++;
> 		udp_transmit(arptable[server].ipaddr, RPC_SOCKET,
> 			port, rpcptr - (char *)&buf, &buf);
> 	}
> 	
> 	while (pktcount) {
> 		if (await_reply(AWAIT_RPC, 0, NULL)) {
> 			rpc = (struct rpc_t *)&packet[ETHER_HDR_SIZE];
> 			if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
> 				rpc->u.reply.astatus || rpc->u.reply.data[0]) {
> 				printf("%s\n", rpc_strerror(rpc));
> 				return(-(ntohl(rpc->u.reply.data[0])));
> 			} else {
> 				rid = ntohl(rpc->u.reply.id);
> 				cache = NULL;
> 				for (i = 0; i < BUFMAX; i++) {
> 					if (read_cache[i].id == rid) {
> 						cache = &(read_cache[i]);
> 					}
> 				}
> 				if (cache == NULL) {
> #if 0
> 					printf("unexpected reply id 0x%lx\n",
> 					       rid);
> #endif
> 					continue;
> 				}
> 				rlen = ntohl(rpc->u.reply.data[18]);
> 				if (len < rlen) rlen = len;
> 				if (len > rlen) netprintf("short read\r\n");
> 				memcpy(cache->buffer, &rpc->u.reply.data[19],
> 				       rlen);
> 				cache->valid = 1;
> 			}
> 		}
> 		pktcount--;
> 	}
> 
> 	rlen = check_read_cache(offset, len, buffer);
> 	if (rlen) {
> 		return rlen;
> 	}
> 
> 	/*
> 	 * Okay - fall back to normal behavior.  We missed the
> 	 * packet somehow.
> 	 */
> 
> 	printf("nfs_read: lost packet\n");
> 
147a271,275
> 		rpcptr = netsprintf(buf.u.data,
> 		        "%L%L%L%L%L%L%L%L%L%S%L%L%L%L%L%L%L%M%L%L%L",
> 			rpc_id, MSG_CALL, 2, PROG_NFS, 2, NFS_READ,
> 		        1, hostnamelen + 28,0,hostname,0,0,2,0,0,0,0,
> 		        32, fh, offset, len, 0);
160a289
> 				
Index: rpc.h
===================================================================
RCS file: /n/fast/usr/lsrc/flux/CVS/oskit/boot/net/rpc.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -r1.3 -r1.4
33a34,42
> struct rpc_buf {
> 	int valid;
> 	int sent;		   /* Is the request on the wire? */
> 	unsigned long offset;
> 	unsigned long len;
> 	unsigned long id;
> 	char buffer[1400];
> };
> 
63c72,73
< int nfs_read(int server, int port, char *fh, int offset, int len, char *buffer);
---
> int nfs_read(int server, int port, char *fh, int offset, int len,
> 	     char *buffer, int readahead);