code: plan9front

Download patch

ref: 9ebd6f860e9d551e8b1c8f0a0c62bb4c1aa2c268
parent: ce86e64ee0d3b2e5e44319d654f8a05ca8a47b7e
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sat Apr 27 12:26:55 EDT 2024

ext4srv: reduce the number of options, align more with existing filesystems

Also provide saner defaults (block size 4k instead of 1k).
Cache write back is always enabled now as well.

--- a/sys/man/4/ext4srv
+++ b/sys/man/4/ext4srv
@@ -4,34 +4,29 @@
 .SH SYNOPSIS
 .B ext4srv
 [
-.B -Crs
+.B -Ss
 ] [
+.B -f
+.I file
+] [
 .B -g
 .I groupfile
 ] [
-.B -R
-.I uid
+.B -n
+.I srvname
 ] [
-.I service
-]
-.PP
-.B ext4srv
-.B -M
+.B -r
 .I (2|3|4)
-[
-.B -L
-.I label
 ] [
 .B -b
 .I blksize
 ] [
-.B -N
-.I numinodes
-] [
 .B -I
 .I inodesize
+] [
+.B -L
+.I label
 ]
-.I device
 .SH DESCRIPTION
 .I Ext4srv
 is a file server that interprets the Linux Second, Third and Fourth
@@ -43,13 +38,12 @@
 .PP
 .I Ext4srv
 posts a file descriptor named
-.I service
+.I srvname
 (default
 .BR ext4 )
 in the
 .B /srv
-directory.
-To access an ext4 file system on a device, use
+directory.  To access an ext4 file system on a device, use
 .B mount
 with the
 .I spec
@@ -56,7 +50,8 @@
 argument
 (see
 .IR bind (1))
-the name of the file holding the raw ext4 file system, typically the disk or partition.
+the name of the file holding the raw ext4 file system, typically the
+disk or partition.
 If
 .I spec
 is undefined in the
@@ -68,60 +63,52 @@
 .PP
 Normally
 .I ext4srv
-creates a pipe to act as the communications channel between
-itself and its clients.
+creates a pipe to act as the communications channel between itself and
+its clients.
 The
 .B -s
 flag instructs
 .I ext4srv
-to use its standard input and output instead.
-This flag also prevents the creation of an explicit service file in
+to use its standard input and output instead.  This flag also prevents
+the creation of an explicit service file in
 .BR /srv .
 .PP
-The
-.B -r
-flag (recommended) makes the file system read-only.
+By default,
+.I ext4srv
+will try to parse and use
+.I /etc/group
+file for permission checks, if available on the mounted filesystem.
 The optional
 .B -g
-flags specify Unix-format group file that give the mapping between the
-numeric user- and group-ID numbers in the ext4 file system and the
-strings reported by Plan 9 status inquiries.
+flag specifies Unix-format group file that gives the mapping between
+the numeric user- and group-ID numbers in the Extended file system and
+the strings reported by Plan 9 status inquiries.  The file is assumed
+to reside on the filesystem where
+.I ext4srv
+executable is running, not the one to be mounted.
 .PP
 With
-.B -R
-option the filesystem can be mounted in "root" mode, allowing full access regardless
-of permissions. The usual
-.I uid
-in this case is
-.IR 0 .
-.SH MKFS
-A different mode of
-.I ext4srv
-is enabled with
-.B -M
-option that accepts the file system version
-.RI ( 2
-for
-.I ext2
-and so on).
-In this mode filesystem is initialized on the specified
-.I device
-and all existing data on it is destroyed.
+.B -S
+option the filesystem can be mounted in "root" mode, allowing full
+access, regardless of permissions.
 .PP
-Additional options may be specified, for example
-.B -L
-may be used to set the filesystem label.
+With
+.B -r
+option the filesystem will be reamed - the old data erased and the
+file reformatted as specified.  An optional label can be specified
+with
+.BR -L ,
+block size (default is 4096 bytes) with
+.B -b
+and
+inode size (default is 256 bytes) with
+.BR -I .
 .SH SOURCE
 .B /sys/src/cmd/ext4srv
-.SH BUGS
-Yes.
-.PP
-Permission checking is very basic and may not be complete.
+.SH NOTES
 Symlinks are not resolved.
-There may be many bugs.
-It is advisable to use
-.I ext4srv
-in read-only mode whenever possible.
+.SH BUGS
+There may be bugs - no refunds.
 .SH HISTORY
 .I Ext4srv
 first appeared in 9front (February, 2024).
--- a/sys/src/cmd/ext4srv/common.h
+++ b/sys/src/cmd/ext4srv/common.h
@@ -3,14 +3,10 @@
 
 struct Opts {
 	char *group;
-	int cachewb;
 	int asroot;
-	int rdonly;
-
-	int fstype;
+	int ream;
 	int blksz;
 	int inodesz;
-	u32int ninode;
 	char *label;
 };
 
--- a/sys/src/cmd/ext4srv/ext4srv.c
+++ b/sys/src/cmd/ext4srv/ext4srv.c
@@ -30,23 +30,17 @@
 enum {
 	Adir,
 	Afile,
+
+	Root = 0,
 };
 
 static Opts opts = {
-	.group = nil,
-	.cachewb = 0,
-	.asroot = 0,
-	.rdonly = 0,
-
-	.fstype = -1,
-	.blksz = 1024,
 	.label = "",
-	.inodesz = 256,
-	.ninode = 0,
 };
-static u32int Root;
 static u8int zero[65536];
-static char *srvname = "ext4";
+static char *srvname;
+static char *device;
+static Part *devpart;
 
 static int
 haveperm(Aux *a, int p, struct ext4_inode *inodeout)
@@ -115,27 +109,31 @@
 static void
 rattach(Req *r)
 {
-	char err[ERRMAX];
 	Aux *a;
 
 	if((a = calloc(1, sizeof(*a))) == nil)
 		respond(r, "memory");
-	else if((a->p = openpart(r->ifcall.aname, &opts)) == nil){
-		free(a);
-		rerrstr(err, sizeof(err));
-		respond(r, err);
-	}else{
-		if(opts.asroot || findgroup(&a->p->groups, r->ifcall.uname, &a->uid) == nil)
-			a->uid = Root;
-
-		incref(a->p);
-		a->type = Adir;
-		a->path = estrdup9p("");
-		r->ofcall.qid = a->p->qidmask;
-		r->fid->qid = a->p->qidmask;
-		r->fid->aux = a;
-		respond(r, nil);
+	if(r->ifcall.aname && *r->ifcall.aname){
+		if((a->p = openpart(r->ifcall.aname, &opts)) == nil){
+			free(a);
+			responderror(r);
+			return;
+		}
+	}else if((a->p = devpart) == nil){
+		respond(r, "no file specified");
+		return;
 	}
+
+	if(opts.asroot || findgroup(&a->p->groups, r->ifcall.uname, &a->uid) == nil)
+		a->uid = Root;
+
+	incref(a->p);
+	a->type = Adir;
+	a->path = estrdup9p("");
+	r->ofcall.qid = a->p->qidmask;
+	r->fid->qid = a->p->qidmask;
+	r->fid->aux = a;
+	respond(r, nil);
 }
 
 static u32int
@@ -573,7 +571,7 @@
 
 	wrperm = haveperm(a, OWRITE, &inode);
 	uid = ext4_inode_get_uid(&inode);
-	isowner = uid == Root || a->uid == uid;
+	isowner = a->uid == Root || a->uid == uid;
 
 	/* permission to truncate */
 	isdir = ext4_inode_type(a->p->sb, &inode) == EXT4_INODE_MODE_DIRECTORY;
@@ -876,8 +874,9 @@
 static void
 usage(void)
 {
-	fprint(2, "usage: %s [-Crs] [-g groupfile] [-R uid] [srvname]\n", argv0);
-	fprint(2, "mkfs:  %s -M (2|3|4) [-L label] [-b blksize] [-N numinodes] [-I inodesize] device\n", argv0);
+	fprint(2,
+		"usage: %s [-Ss] [-f file] [-g groupfile] [-n srvname] [-r (2|3|4)]"
+		" [-b blksize] [-I inodesize] [-L label]\n", argv0);
 	threadexitsall("usage");
 }
 
@@ -891,20 +890,19 @@
 	rfork(RFNOTEG);
 
 	stdio = 0;
+	device = nil;
 	ARGBEGIN{
 	case 'D':
 		chatty9p++;
-nomkfs:
-		if(opts.fstype > 0)
-			usage();
-		opts.fstype = 0;
 		break;
 	case 'd':
 		ext4_dmask_set(strtoul(EARGF(usage()), nil, 0));
 		break;
-	case 'C':
-		opts.cachewb = 1;
-		goto nomkfs;
+	case 'f':
+		if(device != nil)
+			usage();
+		device = EARGF(usage());
+		break;
 	case 'g':
 		gr = EARGF(usage());
 		if((f = open(gr, OREAD)) < 0)
@@ -919,70 +917,62 @@
 			sysfatal("%s: read failed", gr);
 		close(f);
 		opts.group[sz] = 0;
-		goto nomkfs;
-	case 'R':
-		opts.asroot = 1;
-		Root = atoll(EARGF(usage()));
-		goto nomkfs;
-	case 'r':
-		opts.rdonly = 1;
-		goto nomkfs;
+		break;
+	case 'n':
+		if(stdio != 0)
+			usage();
+		srvname = EARGF(usage());
+		break;
 	case 's':
 		stdio = 1;
-		goto nomkfs;
-	case 'M':
-		if(!opts.fstype)
+		if(srvname != nil)
 			usage();
-		opts.fstype = atoi(EARGF(usage()));
-		if(opts.fstype < 2 || opts.fstype > 4)
-			usage();
 		break;
+	case 'S':
+		opts.asroot = 1;
+		break;
 
 	case 'b':
 		opts.blksz = atoi(EARGF(usage()));
 		if(opts.blksz != 1024 && opts.blksz != 2048 && opts.blksz != 4096)
 			usage();
-yesmkfs:
-		if(opts.fstype < 1)
-			usage();
 		break;
-	case 'L':
-		opts.label = EARGF(usage());
-		goto yesmkfs;
 	case 'I':
 		opts.inodesz = atoi(EARGF(usage()));
 		if(opts.inodesz < 128 || ((opts.inodesz-1) & opts.inodesz) != 0)
 			usage();
-		goto yesmkfs;
-	case 'N':
-		opts.ninode = atoi(EARGF(usage()));
-		if(opts.ninode < 1)
+		break;
+	case 'L':
+		opts.label = EARGF(usage());
+		break;
+	case 'r':
+		if(opts.ream > 0)
 			usage();
-		goto yesmkfs;
+		opts.ream = atoi(EARGF(usage()));
+		if(opts.ream < 2 || opts.ream > 4)
+			usage();
+		break;
 
 	default:
 		usage();
 	}ARGEND
 
-	if(opts.fstype > 1){
-		if(argc != 1)
-			usage();
-		if(openpart(argv[0], &opts) == nil)
-			sysfatal("%r");
-		closeallparts();
-		threadexitsall(nil);
-	}else{
-		if(!stdio && argc == 1)
-			srvname = *argv;
-		else if(argc != 0)
-			usage();
+	if(argc != 0)
+		usage();
 
-		if(stdio){
-			fs.infd = 0;
-			fs.outfd = 1;
-			threadsrv(&fs);
-		}else
-			threadpostsrv(&fs, srvname);
-		threadexits(nil);
+	if(device == nil && opts.ream > 1)
+		usage();
+	if(device != nil && (devpart = openpart(device, &opts)) == nil)
+		sysfatal("%r");
+
+	if(stdio){
+		fs.infd = 0;
+		fs.outfd = 1;
+		threadsrv(&fs);
+	}else{
+		if(srvname == nil)
+			srvname = "ext4";
+		threadpostsrv(&fs, srvname);
 	}
+	threadexits(nil);
 }
--- a/sys/src/cmd/ext4srv/part.c
+++ b/sys/src/cmd/ext4srv/part.c
@@ -154,16 +154,12 @@
 readfile(Part *p, char *path, usize *sz)
 {
 	usize n, got;
-	char *s, *d;
 	ext4_file f;
+	char *d;
 	int r;
 
 	d = nil;
-	while(*path == '/')
-		path++;
-	s = smprint("/%s", path);
-	r = ext4_fopen2(&p->mp, &f, s, O_RDONLY);
-	free(s);
+	r = ext4_fopen2(&p->mp, &f, path, O_RDONLY);
 
 	if(r == 0){
 		*sz = ext4_fsize(&f);
@@ -203,7 +199,7 @@
 	int r;
 
 	mp = &p->mp;
-	if(ext4_mount(mp, &p->bdev, opts->rdonly) < 0){
+	if(ext4_mount(mp, &p->bdev, 0) < 0){
 		werrstr("mount: %r");
 		goto error;
 	}
@@ -219,8 +215,7 @@
 		werrstr("journal: %r");
 		goto error;
 	}
-	if(opts->cachewb)
-		ext4_cache_write_back(mp, 1);
+	ext4_cache_write_back(mp, 1);
 
 	if(ext4_get_sblock(mp, &p->sb) < 0){
 		werrstr("sblock: %r");
@@ -230,7 +225,7 @@
 	r = 0;
 	if(opts->group != nil){
 		r = loadgroups(&p->groups, opts->group);
-	}else if((gr = readfile(p, "/etc/group", &sz)) != nil){
+	}else if((gr = readfile(p, "etc/group", &sz)) != nil){
 		gr[sz] = 0;
 		r = loadgroups(&p->groups, gr);
 		free(gr);
@@ -307,19 +302,18 @@
 		p->partdev = (char*)(p+1) + blksz;
 		strcpy(p->partdev, dev);
 
-		if(opts->fstype > 1){
+		if(opts->ream > 1){
 			memset(&fs, 0, sizeof(fs));
 			memset(&info, 0, sizeof(info));
 			info.block_size = opts->blksz;
 			snprint(info.label, sizeof(info.label), opts->label);
 			info.inode_size = opts->inodesz;
-			info.inodes = opts->ninode;
-			info.journal = opts->fstype > 2;
+			info.journal = opts->ream > 2;
 			for(i = 0; i < 16; i += 4){
 				rn = truerand();
 				memcpy(info.uuid+i, &rn, 4);
 			}
-			if(ext4_mkfs(&fs, &p->bdev, &info, opts->fstype) < 0){
+			if(ext4_mkfs(&fs, &p->bdev, &info, opts->ream) < 0){
 				werrstr("mkfs: %r");
 				goto error;
 			}