code: mafs

Download patch

ref: 7288138f121ce4bb74c3678c5f4d3817a68b995f
parent: 52e1939db1bfb60e7c9101c03068f6c2cfa27fa0
author: 9ferno <gophone2015@gmail.com>
date: Tue Nov 8 02:34:26 EST 2022

jumbo writes

--- a/dev.c
+++ b/dev.c
@@ -31,13 +31,19 @@
 }
 
 int
-devwrite(u64 blkno, void *b)
+devwrites(u64 blkno, void *b, u64 n)
 {
-	int n;
+	int wn;
 
-	if((n = pwrite(devfd, b, Rawblocksize, blkno*Rawblocksize)) != Rawblocksize)
+	if((wn = pwrite(devfd, b, n*Rawblocksize, blkno*Rawblocksize)) != n*Rawblocksize)
 		panic("devwrite failed: %r\n");
-	return n;
+	return wn;
+}
+
+int
+devwrite(u64 blkno, void *b)
+{
+	return devwrites(blkno, b, 1);
 }
 
 /* obsoleted, a hack for more efficient logging */
--- a/docs/mafs.ms
+++ b/docs/mafs.ms
@@ -1182,25 +1182,20 @@
 .fi
 .sp
 Starting mafs on a 2MB byte file. The below commands create a disk.file to use as a disk. Mount /n/mafs_disk.file for the file system.
-.nf
 .sp
+.nf
 	dd -if /dev/zero -of disk.file -bs 512 -count 4096;
-.br
 	mount -c <{disk/mafs -s -r mafs_disk.file -m 1 -n mafs_disk.file \\
 		  <[0=1]} /n/mafs_disk.file
 .fi
 .sp
 Starting mafs on a RAM file. The below commands create a ramfs filesystem to use as a disk.
-.nf
 .sp
+.nf
 	ramfs -m /n/mafs_ramfs
-.br
 	touch /n/mafs_ramfs/file
-.br
 	dd -if /dev/zero -of /n/mafs_ramfs/file -count 700 -bs 1m
-.br
 	disk/mafs -r mafs_ramfs_file /n/mafs_ramfs/file
-.br
 	mount -c /srv/mafs_ramfs_file /n/mafs_ramfs_file
 .fi
 .sp
--- a/fns.h
+++ b/fns.h
@@ -11,6 +11,7 @@
 int	devread(u64 blkno, void *b);
 u64	devsize(void);
 int	devwrite(u64 blkno, void *b);
+int	devwrites(u64 blkno, void *b, u64 n);
 
 /* show blocks */
 void	showblock(int fd, u8 *buf);
--- a/writer.c
+++ b/writer.c
@@ -71,39 +71,6 @@
 	return b;
 }
 
-Wbuf *
-getwrite(void)
-{
-	Wbuf *b;
-
-	qlock(&drts.lck);
-	if(drts.n == 0){
-		if(stopwrites){
-			qunlock(&drts.lck);
-			return nil;
-		}
-		rsleep(&drts.isempty);
-		if(drts.n == 0 && stopwrites){
-			qunlock(&drts.lck);
-			return nil;
-		}
-	}
-	/* using canwlock() here as getbuf() could
-		have wlock()'ed the Iobuf too */
-	if(drts.head != nil){
-		b = pluck(drts.head);
-		if(drts.n == npendingwrites-1)
-			rwakeup(&drts.isfull);
-		if(chatty9p > 4 && b!=nil){
-			dprint("getwrite done b->blkno %llud\n", b->blkno);
-		stats();
-		}
-	}else
-		b = nil;
-	qunlock(&drts.lck);
-	return b;
-}
-
 /* the Iobuf should be wlock()'ed at entry */
 void
 putwrite(Iobuf *b)
@@ -154,33 +121,103 @@
 	incref(dirties) only happens with a wlock() in putwrite().
  */
 void
-dowrite(Wbuf *p)
+dowrite(void)
 {
-	u64 n;
+	Wbuf *b, *blks[128];
+	u64 prevblkno, startblkno, n, wn, i;
+	u8 full, *jumbo;
 
-	if(chatty9p > 4){
-		dprint("dowrite p->blkno %llud\n", p->blkno);
-		stats();
+	full = 0;
+	qlock(&drts.lck);
+	if(drts.n == 0){
+		if(stopwrites){
+			qunlock(&drts.lck);
+			return;
+		}
+		rsleep(&drts.isempty);
+		if(drts.n == 0 && stopwrites){
+			qunlock(&drts.lck);
+			return;
+		}
 	}
-	if(chatty9p > 4)
-		dprint("dowrite p->blkno %llud locked\n", p->blkno);
-	if((n = devwrite(p->blkno, p->payload)) != Rawblocksize){
-		dprint("%s\n", errstring[Esystem]);
-		panic("error writing block %llud: %llud bytes: %r\n",
-				p->blkno, n);
+	/* using canwlock() here as getbuf() could
+		have wlock()'ed the Iobuf too */
+	if(drts.head != nil){
+		if(drts.n == npendingwrites-1)
+			full = 1;
+		if(drts.n > 1){
+			/* trying to write consecutive blocks with a write() call */
+			n = 1;
+			prevblkno = startblkno = drts.head->blkno;
+			for(b = drts.head->next;
+					b != nil && b->blkno == prevblkno+1 && n < 128;
+					b = b->next){
+				prevblkno=b->blkno;
+				n++;
+			}
+			if(n > 1){
+				if(chatty9p > 4){
+					if(b != nil)
+					dprint("getwrite jumbo drts.n %llud > 1 n %llud start %llud next %llud\n",
+							drts.n, n, startblkno, b->blkno);
+					else
+					dprint("getwrite jumbo drts.n %llud > 1 n %llud start %llud\n",
+							drts.n, n, startblkno);
+				}
+				jumbo = emalloc9p(n*Rawblocksize);
+				for(i = 0; i < n; i++){
+					b = pluck(drts.head);
+					memcpy(jumbo+(i*Rawblocksize), b->payload, Rawblocksize);
+					blks[i] = b;
+					if(chatty9p > 4 && b!=nil)
+						dprint("getwrite done b->blkno %llud\n", b->blkno);
+				}
+				if((wn = devwrites(startblkno, jumbo, n)) != n*Rawblocksize){
+					dprint("%s\n", errstring[Esystem]);
+					panic("error writing block %llud: %llud bytes, written %llud: %r\n",
+							b->blkno, n, wn);
+				}
+				for(i = 0; i < n; i++){
+					b = blks[i];
+					blks[i] = 0;
+					if(chatty9p > 4)
+						dprint("dowrite %llud wunlock()'ed\n", b->blkno);
+					decref(&b->iobuf->dirties);
+					freememunit(b->payload);
+					free(b);
+				}
+				free(jumbo);
+				qunlock(&drts.lck);
+				return;
+			}
+			goto single;
+		}else{
+single:
+			b = pluck(drts.head);
+			if(chatty9p > 4 && b!=nil)
+				dprint("getwrite done b->blkno %llud\n", b->blkno);
+			if((n = devwrite(b->blkno, b->payload)) != Rawblocksize){
+				dprint("%s\n", errstring[Esystem]);
+				panic("error writing block %llud: %llud bytes: %r\n",
+						b->blkno, n);
+			}
+			if(chatty9p > 4)
+				dprint("dowrite %llud wunlock()'ed\n", b->blkno);
+			decref(&b->iobuf->dirties);
+			freememunit(b->payload);
+			free(b);
+		}
+		if(full)
+			rwakeup(&drts.isfull);
+		if(chatty9p > 4 && b!=nil)
+			stats();
 	}
-	n = p->blkno;
-	if(chatty9p > 4)
-	dprint("dowrite %llud wunlock()'ed\n", n);
-	decref(&p->iobuf->dirties);
-	freememunit(p->payload);
-	free(p);
+	qunlock(&drts.lck);
 }
 
 void
 initwriter(void)
 {
-	Wbuf *b;
 	char name[Namelen];
 
 	// set the locks used by the Rendezes
@@ -201,9 +238,7 @@
 	snprint(name, Namelen, "%s writer", service);
 	procsetname(name);
 	while(stopwrites == 0 || drts.n > 0){
-		b=getwrite();
-		if(b != nil)
-			dowrite(b);
+		dowrite();
 	}
 	if(chatty9p > 4)
 	dprint("%s process exited\n", name);