9front - general discussion about 9front
 help / color / mirror / Atom feed
From: Jacob Moody <moody@mail.posixcafe.org>
To: 9front@9front.org
Subject: Re: [9front] [PATCH] private /srv attach option
Date: Wed, 8 Jun 2022 08:48:42 -0600	[thread overview]
Message-ID: <27178dc6-eefd-7b5a-c243-467331d31e10@posixcafe.org> (raw)
In-Reply-To: <fa5b5eb1-bf4e-ba56-6922-1f3bca25824e@posixcafe.org>

Another iteration on this:

Scrapped the attach option.
This uses a /new child directory for getting a fresh instance.
The new instance is alloted on walks to this dir, but due
to our fid clone conventions you can safely interact
with the file without worrying about it nuking your /srv.

Only other change from the previous patch is that we ensure
that each private session has unique qid paths.

This makes the convention for getting a private /srv:

bind /srv/new /srv

This patch might need a bit more tidying, but in general I am
pretty happy with this interface.


Thanks,
moody

----
diff 1b5ea51ee1203952900fafc0def48985d900f7a7 uncommitted
--- a//sys/src/9/port/devsrv.c
+++ b//sys/src/9/port/devsrv.c
@@ -5,6 +5,7 @@
 #include	"fns.h"
 #include	"../port/error.h"

+#include	"netif.h"

 typedef struct Srv Srv;
 struct Srv
@@ -17,16 +18,29 @@
 	ulong	path;
 };

-static QLock	srvlk;
-static Srv	*srv;
-static int	qidpath;
+typedef struct Fid Fid;
+struct Fid
+{
+	int	ref;
+	QLock 	lk;
+	Srv 	*tail;
+	ulong 	nextpath;
+};

+struct {
+	QLock;
+	ulong path;
+} sessions;
+
+static Fid	global;
+
 static Srv*
-srvlookup(char *name, ulong qidpath)
+srvlookup(Fid *f, char *name, ulong qidpath)
 {
 	Srv *sp;

-	for(sp = srv; sp != nil; sp = sp->link) {
+	qidpath = NETTYPE(qidpath);
+	for(sp = f->tail; sp != nil; sp = sp->link) {
 		if(sp->path == qidpath || (name != nil && strcmp(sp->name, name) == 0))
 			return sp;
 	}
@@ -38,28 +52,57 @@
 {
 	Srv *sp;
 	Qid q;
+	Fid *f;
+	ulong id;

 	if(s == DEVDOTDOT){
-		devdir(c, c->qid, "#s", 0, eve, 0555, dp);
+		devdir(c, c->qid, "#s", 0, eve, 0555|DMDIR, dp);
 		return 1;
 	}

-	qlock(&srvlk);
-	if(name != nil)
-		sp = srvlookup(name, -1);
-	else {
-		for(sp = srv; sp != nil && s > 0; sp = sp->link)
+	f = c->aux;
+	qlock(&f->lk);
+	id = NETID(c->qid.path);
+
+	if(name != nil){
+		if(strcmp(name, "new") == 0){
+			if(f != &global && --f->ref == 0){
+				qunlock(&f->lk);
+				free(f);
+			} else
+				qunlock(&f->lk);
+			f = smalloc(sizeof *f);
+			qlock(&sessions);
+			id = ++sessions.path;
+			qunlock(&sessions);
+			f->ref = 1;
+			f->nextpath = 2;
+			mkqid(&q, NETQID(id, 1), 0, QTDIR);
+			devdir(c, q, "new", 0, eve, 0555|DMDIR, dp);
+			c->aux = f;
+			return 1;
+		}
+		sp = srvlookup(f, name, -1);
+	} else {
+		if(s == 0){
+			mkqid(&q, NETQID(id, 1), 0, QTDIR);
+			devdir(c, q, "new", 0, eve, 0555|DMDIR, dp);
+			qunlock(&f->lk);
+			return 1;
+		}
+		s -= 1;
+		for(sp = f->tail; sp != nil && s > 0; sp = sp->link)
 			s--;
 	}
 	if(sp == nil || (name != nil && (strlen(sp->name) >= sizeof(up->genbuf)))) {
-		qunlock(&srvlk);
+		qunlock(&f->lk);
 		return -1;
 	}
-	mkqid(&q, sp->path, 0, QTFILE);
+	mkqid(&q, NETQID(id, sp->path), 0, QTFILE);
 	/* make sure name string continues to exist after we release lock */
 	kstrcpy(up->genbuf, sp->name, sizeof up->genbuf);
 	devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp);
-	qunlock(&srvlk);
+	qunlock(&f->lk);
 	return 1;
 }

@@ -66,19 +109,38 @@
 static void
 srvinit(void)
 {
-	qidpath = 1;
+	global.nextpath = 2;
 }

 static Chan*
 srvattach(char *spec)
 {
-	return devattach('s', spec);
+	Chan *c;
+
+	c = devattach('s', spec);
+	c->aux = &global;
+	return c;
 }

 static Walkqid*
 srvwalk(Chan *c, Chan *nc, char **name, int nname)
 {
-	return devwalk(c, nc, name, nname, 0, 0, srvgen);
+	Walkqid *wq;
+	Fid *f;
+
+	wq =  devwalk(c, nc, name, nname, 0, 0, srvgen);
+	if(wq == nil || wq->clone == nil || wq->clone == c)
+		return wq;
+
+	f = c->aux;
+	/* global doesn't ref count */
+	if(f == &global)
+		return wq;
+
+	qlock(&f->lk);
+	f->ref++;
+	qunlock(&f->lk);
+	return wq;
 }

 static int
@@ -91,11 +153,13 @@
 srvname(Chan *c)
 {
 	Srv *sp;
+	Fid *f;
 	char *s;

 	s = nil;
-	qlock(&srvlk);
-	for(sp = srv; sp != nil; sp = sp->link) {
+	f = &global;
+	qlock(&f->lk);
+	for(sp = f->tail; sp != nil; sp = sp->link) {
 		if(sp->chan == c){
 			s = malloc(3+strlen(sp->name)+1);
 			if(s != nil)
@@ -103,7 +167,7 @@
 			break;
 		}
 	}
-	qunlock(&srvlk);
+	qunlock(&f->lk);
 	return s;
 }

@@ -111,6 +175,7 @@
 srvopen(Chan *c, int omode)
 {
 	Srv *sp;
+	Fid *f;
 	Chan *nc;

 	if(c->qid.type == QTDIR){
@@ -123,13 +188,14 @@
 		c->offset = 0;
 		return c;
 	}
-	qlock(&srvlk);
+	f = c->aux;
+	qlock(&f->lk);
 	if(waserror()){
-		qunlock(&srvlk);
+		qunlock(&f->lk);
 		nexterror();
 	}

-	sp = srvlookup(nil, c->qid.path);
+	sp = srvlookup(f, nil, c->qid.path);
 	if(sp == nil || sp->chan == nil)
 		error(Eshutdown);

@@ -144,7 +210,7 @@
 	nc = sp->chan;
 	incref(nc);

-	qunlock(&srvlk);
+	qunlock(&f->lk);
 	poperror();

 	cclose(c);
@@ -155,6 +221,7 @@
 srvcreate(Chan *c, char *name, int omode, ulong perm)
 {
 	Srv *sp;
+	Fid *f;

 	if(openmode(omode) != OWRITE)
 		error(Eperm);
@@ -162,31 +229,32 @@
 	if(strlen(name) >= sizeof(up->genbuf))
 		error(Etoolong);

+	f = c->aux;
 	sp = smalloc(sizeof *sp);
 	kstrdup(&sp->name, name);
 	kstrdup(&sp->owner, up->user);

-	qlock(&srvlk);
+	qlock(&f->lk);
 	if(waserror()){
-		qunlock(&srvlk);
+		qunlock(&f->lk);
 		free(sp->owner);
 		free(sp->name);
 		free(sp);
 		nexterror();
 	}
-	if(srvlookup(name, -1) != nil)
+	if(srvlookup(f, name, -1) != nil)
 		error(Eexist);

 	sp->perm = perm&0777;
-	sp->path = qidpath++;
+	sp->path = f->nextpath++;

-	c->qid.path = sp->path;
+	c->qid.path = NETQID(NETID(c->qid.path), sp->path);
 	c->qid.type = QTFILE;

-	sp->link = srv;
-	srv = sp;
+	sp->link = f->tail;
+	f->tail = sp;

-	qunlock(&srvlk);
+	qunlock(&f->lk);
 	poperror();

 	c->flag |= COPEN;
@@ -199,18 +267,21 @@
 srvremove(Chan *c)
 {
 	Srv *sp, **l;
+	Fid *f;

 	if(c->qid.type == QTDIR)
 		error(Eperm);

-	qlock(&srvlk);
+	f = c->aux;
+
+	qlock(&f->lk);
 	if(waserror()){
-		qunlock(&srvlk);
+		qunlock(&f->lk);
 		nexterror();
 	}
-	l = &srv;
+	l = &f->tail;
 	for(sp = *l; sp != nil; sp = *l) {
-		if(sp->path == c->qid.path)
+		if(sp->path == NETTYPE(c->qid.path))
 			break;
 		l = &sp->link;
 	}
@@ -232,7 +303,15 @@
 	*l = sp->link;
 	sp->link = nil;

-	qunlock(&srvlk);
+	if(f != &global){
+		f->ref--;
+		if(f->ref <= 0)
+			free(f);
+		else
+			qunlock(&f->lk);
+	} else
+		qunlock(&f->lk);
+
 	poperror();

 	if(sp->chan != nil)
@@ -247,6 +326,7 @@
 {
 	char *strs;
 	Srv *sp;
+	Fid *f;
 	Dir d;

 	if(c->qid.type & QTDIR)
@@ -261,13 +341,15 @@
 	if(n == 0)
 		error(Eshortstat);

-	qlock(&srvlk);
+	f = c->aux;
+
+	qlock(&f->lk);
 	if(waserror()){
-		qunlock(&srvlk);
+		qunlock(&f->lk);
 		nexterror();
 	}

-	sp = srvlookup(nil, c->qid.path);
+	sp = srvlookup(f, nil, c->qid.path);
 	if(sp == nil)
 		error(Enonexist);

@@ -286,7 +368,7 @@
 	if(d.mode != ~0UL)
 		sp->perm = d.mode & 0777;

-	qunlock(&srvlk);
+	qunlock(&f->lk);
 	poperror();

 	free(strs);
@@ -298,16 +380,32 @@
 static void
 srvclose(Chan *c)
 {
+	Fid *f;
+
 	/*
 	 * in theory we need to override any changes in removability
 	 * since open, but since all that's checked is the owner,
 	 * which is immutable, all is well.
 	 */
-	if(c->flag & CRCLOSE){
+	if((c->flag & COPEN) && (c->flag & CRCLOSE)){
 		if(waserror())
-			return;
+			goto ref;
+
 		srvremove(c);
 		poperror();
+	} else {
+
+ref:
+		f = c->aux;
+
+		if(f != &global){
+			qlock(&f->lk);
+			f->ref--;
+			if(f->ref <= 0)
+				free(f);
+			else
+				qunlock(&f->lk);
+		}
 	}
 }

@@ -322,6 +420,7 @@
 srvwrite(Chan *c, void *va, long n, vlong)
 {
 	Srv *sp;
+	Fid *f;
 	Chan *c1;
 	int fd;
 	char buf[32];
@@ -334,15 +433,17 @@

 	c1 = fdtochan(fd, -1, 0, 1);	/* error check and inc ref */

-	qlock(&srvlk);
+	f = c->aux;
+
+	qlock(&f->lk);
 	if(waserror()) {
-		qunlock(&srvlk);
+		qunlock(&f->lk);
 		cclose(c1);
 		nexterror();
 	}
 	if(c1->qid.type & QTAUTH)
 		error("cannot post auth file in srv");
-	sp = srvlookup(nil, c->qid.path);
+	sp = srvlookup(f, nil, c->qid.path);
 	if(sp == nil)
 		error(Enonexist);

@@ -351,7 +452,7 @@

 	sp->chan = c1;

-	qunlock(&srvlk);
+	qunlock(&f->lk);
 	poperror();
 	return n;
 }
@@ -381,11 +482,13 @@
 srvrenameuser(char *old, char *new)
 {
 	Srv *sp;
+	Fid *f;

-	qlock(&srvlk);
-	for(sp = srv; sp != nil; sp = sp->link) {
+	f = &global;
+	qlock(&f->lk);
+	for(sp = f->tail; sp != nil; sp = sp->link) {
 		if(sp->owner != nil && strcmp(old, sp->owner) == 0)
 			kstrdup(&sp->owner, new);
 	}
-	qunlock(&srvlk);
+	qunlock(&f->lk);
 }

  reply	other threads:[~2022-06-08 14:50 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-30 11:50 Jacob Moody
2022-05-30 14:44 ` ori
2022-05-30 17:26   ` Jacob Moody
2022-05-30 20:04     ` ori
2022-05-31  7:03       ` hiro
2022-05-31 15:09         ` Jacob Moody
2022-05-31 16:04           ` Jacob Moody
2022-06-08 14:48             ` Jacob Moody [this message]
2022-06-22 15:22               ` cinap_lenrek
2022-05-30 14:56 ` ori
2022-07-10 21:47 ` ori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=27178dc6-eefd-7b5a-c243-467331d31e10@posixcafe.org \
    --to=moody@mail.posixcafe.org \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).