Discussion:
a 9P session between debian client and Plan 9 server side
(too old to reply)
Kin Loo
2012-01-03 10:49:43 UTC
Permalink
Hi, this time I want to try a 9P session in debian. The following code
is running at Plan 9 and file operations (cat, touch, echo>, and rm)
for the Plan 9 client function as expected:

#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <auth.h>
#include <9p.h>

typedef struct Ramfile Ramfile;
struct Ramfile {
char *data;
int ndata;
};

void
fsread(Req *r)
{
Ramfile *rf;
int count;
long offset;

count = r->ifcall.count;
offset = r->ifcall.offset;
rf = r->fid->file->aux;

if(offset >= rf->ndata) {
r->ofcall.count = 0;
respond(r, nil);
return;
}
if(offset+count >= rf->ndata)
count = rf->ndata - offset;

memmove(r->ofcall.data, rf->data, count);
r->ofcall.count = count;
respond(r, nil);
}

void
fswrite(Req *r)
{
Ramfile *rf;
int count;
long offset;

rf = r->fid->file->aux;
count = r->ifcall.count;
offset = r->ifcall.offset;

void *v;
if(offset+count >= rf->ndata) {
v = realloc(rf->data, offset+count);
if(v == nil) {
respond(r, "realloc bad");
return;
}

rf->ndata = offset+count;
rf->data = v;
r->fid->file->length = rf->ndata;
}

memmove(rf->data, r->ifcall.data, count);
r->ofcall.count = count;
respond(r, nil);
}

void
fscreate(Req *r)
{
Ramfile *rf;
File *f;

f = createfile(r->fid->file, r->ifcall.name, r->fid->uid, r-
ifcall.perm, nil);
if(f) {
rf = emalloc9p(sizeof *rf);
f->aux = rf;
r->fid->file = f;
r->ofcall.qid = f->qid;
respond(r, nil);
return;
}

respond(r, "bad file creation");
}

Srv fs = {
.read = fsread,
.write = fswrite,
.create = fscreate,
};


void
usage(void)
{
fprint(2, "usage: %s [-s srvname] [-m mtpt]\n", argv0);
exits("usage");
}

void
main(int argc, char **argv)
{
char *srvname;
char *mtpt;
Tree *tree;

srvname = "memfs";
mtpt = nil;
tree = alloctree(nil, nil, DMDIR|0777, nil);
fs.tree = tree;
ARGBEGIN{
case 'm':
mtpt = EARGF(usage());
break;
case 's':
srvname = ARGF();
break;
default:
usage();
}ARGEND;

if(argc)
usage();

Ramfile *rf;
rf = emalloc9p(sizeof *rf);
createfile(tree->root, "foo", nil, 0666, rf);

if(srvname || mtpt)
postmountsrv(&fs, srvname, mtpt, MREPL|MCREATE);

exits(0);
}


In Plan 9, it announces an address through TCP:

longy# aux/listen1 -tv tcp!*!1114 /bin/exportfs -S /srv/memfs &

Now I drop lines in debian console and cd to mount point:

***@debian:~$ sudo mount -t 9p 192.168.1.180 /tmp/memfs/ -o
port=1114
***@debian:~$ cd /tmp/memfs
***@debian:/tmp/memfs$ ls -l
total 1
-rw-rw-rw- 1 4294967294 4294967294 6 Jan 3 08:52 foo
***@debian:/tmp/memfs$ echo abcd >foo
bash: foo: Operation not permitted
***@debian:/tmp/memfs$ touch junk
touch: cannot touch `junk': Unknown error 526
***@debian:/tmp/memfs$

CATing and RMing files are OK. But why I cannot create and write to
9P file in linux?

Thanks,
kin
Yaroslav
2012-01-03 12:50:14 UTC
Permalink
  longy# aux/listen1 -tv tcp!*!1114 /bin/exportfs -S /srv/memfs &
Try exportfs -d and check /tmp/exportdb for hints.
andrey mirtchovski
2012-01-03 14:59:06 UTC
Permalink
You should add the '-d' flag which sets the chatty9p global variable
to something greater than zero. chatty9p is documented in the man page
for the 9p library. It will give you a full dump of everything that
the linux side is trying to do.

What's happening in your case is that you're using overwrite instead
of append. Linux, being smart as it is, breaks '>' into a truncate +
write, which in 9p parlance is wstat + write. You don't have wstat
implemented for your file server, so you're getting "operation not
permitted" (the actual ename you will see is 'wstat prohibited').

Try with '>>' instead, it'll work.

andrey
Kin Loo
2012-01-05 10:07:59 UTC
Permalink
Now I start the server with -D flag and try ''echo hello >>foo" on
Linux. The server side on Plan 9 say:

<-5- Twalk tag 1 fid 408 newfid 437 nwname 1 0:foo
-5-> Rwalk tag 1 nwqid 1 0:(0000000000000000 0 )
<-5- Tstat tag 1 fid 437
-5-> Rstat tag 1 stat 'foo' 'bootes' 'bootes' 'unknown' q
(0000000000000000 0 ) m 0666 at 1325748319 mt 1325748319 l 0 t
0 d 0
<-5- Tclunk tag 1 fid 437
-5-> Rclunk tag 1
<-5- Twalk tag 2 fid 408 newfid 437 nwname 1 0:foo
-5-> Rwalk tag 2 nwqid 1 0:(0000000000000000 0 )
<-5- Tstat tag 2 fid 437
-5-> Rstat tag 2 stat 'foo' 'bootes' 'bootes' 'unknown' q
(0000000000000000 0 ) m 0666 at 1325748319 mt 1325748319 l 0 t 0 d 0
<-5- Tclunk tag 2 fid 437
-5-> Rclunk tag 2
<-5- Twalk tag 2 fid 408 newfid 438 nwname 1 0:foo
-5-> Rwalk tag 2 nwqid 1 0:(0000000000000000 0 )
<-5- Topen tag 2 fid 438 mode 1
fid mode is 0x1
-5-> Ropen tag 2 qid (0000000000000000 0 ) iounit 0
<-5- Tstat tag 2 fid 438
-5-> Rstat tag 2 stat 'foo' 'bootes' 'bootes' 'unknown' q
(0000000000000000 0 ) m 0666 at 1325748319 mt 1325748319 l 0 t 0 d 0
<-5- Twrite tag 6 fid 438 offset 0 count 6 'hello'
-5-> Rwrite tag 6 count 6
<-5- Tclunk tag 6 fid 438
-5-> Rclunk tag 6

I will read more 9P examples in order to implement a wstat. Thank you
Yaroslav and Andrey, it is worth to learn from you.

Loading...