9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] convS2M improvement (plus a localhost interface)
@ 1997-11-03  7:57 G.David
  0 siblings, 0 replies; only message in thread
From: G.David @ 1997-11-03  7:57 UTC (permalink / raw)


From: beto@ncube.com
>Hi,
>
>I've modified convS2M to avoid having to copy the
>data during a read reply. The idea is to set the Fcall data
>pointer to point to the right place within the
>reply message.

You saw that in /sys/src/fs/port/fcall.c too!  Don't forget
the change in Twrite also.

>The server needs to know the data offset for a read reply,
>but some macro definitions will solve the problem.
>
>	p->reply.data = (char *) p->rbp->wptr+8;
>
>With this enhancement a 9P server does not have to copy
>data for reads.

And for writes, the number is 16.

Remember, inside the cpu kernel everything is done with
function calls and streams.  Conv[SM]2[MS] are only used
in authentication and the mnt driver.

Having said that, a big problem is devmnt.  Because of the
need for the header and the atomic writes of 9P, the data
has to be copied from user space to form the RPC message
for writes and there is no way to map it into the RPC
message for reads.  I think this is true for any user
of conv[SM]2[MS].

[In the file server, there is no user space.  Messages are
copied to/from the buffer cache, but writes to disk are not
copied again.]

>P.S.
>This is not scatter/gatther but it's so simple :-)

I think there are other problems like all the copying done
in stream.c.  There is a flag on streamwrite(), docopy,
that is just ignored now with a comment:

/*
 * docopy will be used if I can ever figure out when to
 * avoid copying data -- presotto
 */

It would *not* be easy to fix that one (which is why the
comment is there and not the code) since one of the
features of streams is to buffer data.  To use that flag
the write call would have to be pushed through the
stack before the return.  Of course, that is another
feature of streams; to push data through the stack without
a context switch, but if you can't, perhaps then copy it?

[On write, if there is a blocked read at the "end" and it
wants enough data to hold the entire write, "doit".  Imagine
streams that add data, like IP, the "if it will fit" would
be "interesting".]

Eventually, the data has to be copied somewhere.  The goal
would be to only do it once.  During a user space write that
goes straight to the mnt driver, the data gets copied at
least 3 times!  User space to RPC (convS2M).  RPC to protocol
stream block (streamwrite()).  RPC stream block to ethernet
device (etherwrite()).  (With the protocols, it could happen
a few more times because of copyb/pullup/expandb.) A read is
no better or worse.

In "Plan 9: The Documents" Introduction, page 20, 5th paragraph
I quote:

"What would we do differently next time?  Some elements of the
implementation are unsatisfactory.  Using streams to implement
network interfaces in the kernel allows protocols to be connected
together dynamically, such as to attach the same TTY driver
to TCP, URP, and IL connections, but Plan 9 makes no use of the
configurability.  (It was exploited, however, in the research
UNIX system for which streams were invented.)  Replacing streams
by static I/O queues would simplify the code and make it faster."

We know Plan9 version 1 and 2 have streams.  I think Plan9
version 3 (in progress) still has them.  I found a use for
them last week while on "vacation".  I had a laptop with no
ethernet interface needing to write/test network based
applications.  I wrote a quick little "localhost" interface
that worked well.  In /rc/bin/termrc, add the "if not":

if (test -e /net/ether0/clone) ip/ipconfig
if not {
	ip/loconfig `{ndb/query sys pc ip}
# the binds are necessary since there were no interfaces
# when /lib/namespace was evaluated
	bind -b '#Iudp' /net
	bind -b '#Itcp' /net
	bind -b '#Iil' /net
}

If you don't specify an address, it defaults to 127.0.0.1.
Source to loconfig.c is at the end.  (BTW, it works on the
4 disk set, even though you would have to write network
apps yourself.)

As far as scatter/gather goes, unless many transfers
are < MAXFDATA, readv/writev wouldn't do much good.

David Butler
gdb@dbSystems.com
======================= loconfig.c ====================
/*
 * I put this code is in the public domain.
 * Long Live Plan9.  David Butler gdb@dbSystems.com
 *
 * Create a "local" interface.  Once this is done,
 * bind '#I...' to /net and go.
 *
 * I don't do a "push permanent" so a kill of loconfig
 * will remove the interface.  You can create as many
 * as you want (well, there is a limit, look at the
 * kernel source.)
 */
#include <u.h>
#include <libc.h>
#include <ip.h>

static void
error(char *s)
{
	print("%s: %r\n", s);
	exits(s);
}

void
main(int argc, char *argv[])
{
	static char buf[1600];
	uchar addr[4];
	int fd, n;

	if (--argc) {
		/*
		 * this doesn't work very well.
		 * parseip() doesn't return < 0
		 * for anything I can tell
		 * I'll fix that some day...
		 */
		if (parseip(addr, argv[1]) < 0) {
			print("%s: invalid ip address %s\n",
			  argv[0], argv[1]);
			exits("parseip");
		}
	} else {
		parseip(addr, "127.0.0.1");
	}
	if ((n = rfork(
	  RFPROC|RFNOWAIT|RFCFDG|RFCNAMEG|RFCENVG|RFNOTEG))
	  < 0) {
		error("fork");
	}
	if (n) {
		exits(0);
	}
	fmtinstall('I', eipconv);
	if (bind("#c", "/dev", MREPL) < 0) {
		error("bind"); /* can't see it yet */
	}
	if (open("/dev/cons", OREAD)) {
		error("open stdin"); /* still can't see it ... */
	}
	if (open("/dev/cons", OWRITE) != 1) {
		error("open stdout"); /* still can't see it ... */
	}
	if (dup(1, 2) < 0) {
		error("open stderr"); /* Now, it can be seen */
	}
	if (bind("#|", "/net", MREPL) < 0) {
		error("bind");
	}
	if ((n = open("/net/ctl", ORDWR)) < 0) {
		error("openc");
	}
	strcpy(buf, "push internet");
	if (write(n, buf, strlen(buf)) != strlen(buf)) {
		error(buf);
	}
	sprint(buf, "setip %I 255.255.255.255", addr);
	if (write(n, buf, strlen(buf)) != strlen(buf)) {
		error(buf);
	}
	if ((fd = open("/net/data1", ORDWR)) < 0) {
		error("opend");
	}
	while ((n = read(fd, buf, sizeof(buf))) >= 0) {
		write(fd, buf, n);
	}
}

END of loconfig.c




^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~1997-11-03  7:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-11-03  7:57 [9fans] convS2M improvement (plus a localhost interface) G.David

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).