shithub: unionfs

Download patch

ref: c1eed337afadb15156a5364767c3e3755586e537
parent: ee1d11532120bbac4e12e0fed95cf2c1b69bff81
author: kvik <kvik@a-b.xyz>
date: Thu Aug 5 14:01:43 EDT 2021

Implement Tflush handling

This patch implements Tflush message handling for Topen,
Tread, and Twrite requests.  These are the most common things
you'd happen to flush, but it's worth noting that unionfs,
being a proxying server, does potentially blocking system
calls while handling most of the requests.  At some point I'll
add that, perhaps when I figure out some more imaginative way
of doing it.

--- a/unionfs.c
+++ b/unionfs.c
@@ -83,6 +83,16 @@
 	a->muid = estrdup(b->muid);
 }
 
+int
+catchflush(void*, char *note)
+{
+	if(strcmp(note, "flush") == 0){
+		atnotify(catchflush, 0);
+		return 1;
+	}
+	return 0;
+}
+
 void
 fsattach(Req *r)
 {
@@ -186,6 +196,8 @@
 	R = &r->ofcall;
 	f = r->fid->aux;
 
+	f->pid = getpid();
+	atnotify(catchflush, 1);
 	srvrelease(&thefs);
 	if(f->mode & DMDIR){
 		f->mtpt = mtptgrab();
@@ -208,12 +220,16 @@
 		if((f->fd = open(s_to_c(f->realpath), T->mode)) == -1)
 			goto error;
 	R->iounit = iounit(f->fd);
-	respond(r, nil);
+	if(f->flushed == 0)
+		respond(r, nil);
 	srvacquire(&thefs);
+	atnotify(catchflush, 0);
 	return;
 error:
-	responderror(r);
+	if(f->flushed == 0)
+		responderror(r);
 	srvacquire(&thefs);
+	atnotify(catchflush, 0);
 }
 
 void
@@ -257,6 +273,8 @@
 	R = &r->ofcall;
 	f = r->fid->aux;
 
+	f->pid = getpid();
+	atnotify(catchflush, 1);
 	srvrelease(&thefs);
 	if(f->mode&DMDIR){
 		if(T->offset == 0){
@@ -273,12 +291,16 @@
 			goto error;
 		r->ofcall.count = n;
 	}
-	respond(r, nil);
+	if(f->flushed == 0)
+		respond(r, nil);
 	srvacquire(&thefs);
+	atnotify(catchflush, 0);
 	return;
 error:
-	responderror(r);
+	if(f->flushed == 0)
+		responderror(r);
 	srvacquire(&thefs);
+	atnotify(catchflush, 0);
 }
 
 void
@@ -292,15 +314,40 @@
 	f = r->fid->aux;
 	
 	srvrelease(&thefs);
+	atnotify(catchflush, 1);
 	if((R->count = pwrite(f->fd, T->data, T->count, T->offset)) != T->count){
-		responderror(r);
+		if(f->flushed == 0)
+			responderror(r);
 		goto done;
 	}
-	respond(r, nil);
+	if(f->flushed == 0)
+		respond(r, nil);
 done:
 	srvacquire(&thefs);
+	atnotify(catchflush, 0);
 }
 
+void
+fsflush(Req *r)
+{
+	FILE *f = r->oldreq->fid->aux;
+	
+	if(f->pid == 0){
+		respond(r, nil);
+		return;
+	}
+	switch(r->oldreq->type){
+	case Topen:
+	case Tread:
+	case Twrite:
+		f->flushed = 1;
+		while(postnote(PNPROC, f->pid, "flush") != 0)
+			sleep(100);
+		respond(r->oldreq, "interrupted");
+	}
+	respond(r, nil);
+}
+
 int
 mkdirp(char *path)
 {
@@ -505,6 +552,7 @@
 	thefs.write = fswrite;
 	thefs.stat = fsstat;
 	thefs.wstat = fswstat;
+	thefs.flush = fsflush;
 	thefs.destroyfid = destroyfid;
 	if(stdio == 0){
 		postmountsrv(&thefs, srvname, mountat, mflag);
--- a/unionfs.h
+++ b/unionfs.h
@@ -23,6 +23,9 @@
 	int fd;
 	Mtpt *mtpt;
 	Dirlist *dl;
+	
+	int pid;
+	int flushed;
 };
 
 struct Mtpt {