commit aa2edae702f0f8b592f415d80c8c21bed635cd67
parent 3160b80b68361796fa8fc9ce898f7a215e7e0d41
Author: Dimitris Papastamos <dimitris.papastamos@arm.com>
Date: Tue, 16 Apr 2019 10:52:56 +0100
Merge "[dev] Add mount()"
Diffstat:
8 files changed, 199 insertions(+), 151 deletions(-)
diff --git a/drivers/dev.c b/drivers/dev.c
@@ -10,8 +10,8 @@
#define NR_MPOINTS 4
struct mpoint {
- Chan *where;
Chan *new;
+ Chan *old;
};
static Chan fdset[NR_CHANS];
@@ -140,20 +140,20 @@ buf2chan(Chan *c, void *dst, void *src, int nbytes, unsigned long long len)
static Chan *
mntpoint(Chan *c)
{
- Chan *cw;
+ Chan *cn;
struct mpoint *mp;
for (mp = mpoints; mp < &mpoints[NR_MPOINTS]; mp++) {
- if ((cw = mp->where) == NULL)
+ if ((cn = mp->new) == NULL)
continue;
- if (cw->type == c->type && cw->qid == c->qid)
- return mp->new;
+ if (cn->type == c->type && cn->qid == c->qid)
+ return mp->old;
}
return NULL;
}
-static Chan *
+Chan *
devattach(int id, int dev)
{
Chan *c;
@@ -295,6 +295,20 @@ dirread(Chan *c,
return cnt;
}
+void
+mkentry(Chan *c, Dir *dir,
+ const char *name, unsigned long long length, Qid qid, unsigned mode)
+{
+ strcpy(dir->name, name);
+ dir->length = length;
+ dir->qid = qid;
+ dir->mode = mode;
+ if (qid & CHDIR)
+ dir->mode |= O_DIR;
+ dir->type = c->type;
+ dir->dev = c->dev;
+}
+
int
devgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
{
@@ -304,15 +318,7 @@ devgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
return 0;
dp = &tab[n];
- strcpy(dir->name, dp->name);
- dir->length = dp->length;
- dir->qid = dp->qid;
- dir->mode = dp->perm;
- if (dp->qid & CHDIR)
- dir->mode |= O_DIR;
- dir->type = c->type;
- dir->dev = c->dev;
-
+ mkentry(c, dir, dp->name, dp->length, dp->qid, dp->perm);
return 1;
}
@@ -372,6 +378,13 @@ write(int fd, void *buf, int n)
}
int
+devmount(Chan *c, char *spec)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+int
devwrite(Chan *c, void *buf, int n)
{
errno = EINVAL;
@@ -412,44 +425,81 @@ seek(int fd, long long off, int whence)
return devseek(c, off,whence);
}
-int
-bind(char *new, char *where)
+static int
+addmntpoint(Chan *c, char *new)
{
int i;
+ Chan *cn;
struct mpoint *mp;
- Chan *cw, *cn;
- if ((cw = namec(where, O_READ)) == NULL)
+ if ((cn = namec(new, O_READ)) == NULL)
goto err0;
- if ((cw->qid & CHDIR) == 0) {
+ if ((cn->qid & CHDIR) == 0) {
errno = ENOTDIR;
goto err1;
}
- if ((cn = namec(new, O_BIND)) == NULL)
- goto err1;
-
for (i = NR_MPOINTS-1; i >= 0; i--) {
mp = &mpoints[i];
- if (!mp->where)
+ if (!mp->new)
break;
}
if (i < 0) {
errno = ENOMEM;
- goto err2;
+ goto err1;
}
- mp->where = cw;
mp->new = cn;
+ mp->old = c;
return 0;
-err2:
+err1:
chanclose(cn);
+err0:
+ return -1;
+}
+
+int
+bind(char *old, char *new)
+{
+ Chan *c;
+
+ if ((c = namec(old, O_BIND)) == NULL)
+ return -1;
+
+ if (addmntpoint(c, new) < 0) {
+ chanclose(c);
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+mount(char *srv, char *where, char *spec)
+{
+ Chan *cs, *c;
+
+ if ((cs = namec(srv, O_RDWR)) == NULL)
+ goto err0;
+
+ c = devtab[cs->type]->mount(cs, spec);
+ if (!c)
+ goto err1;
+
+ if (addmntpoint(c, where) < 0)
+ goto err2;
+ chanclose(cs);
+
+ return 0;
+
+err2:
+ chanclose(c);
err1:
- chanclose(cw);
+ chanclose(cs);
err0:
return -1;
}
diff --git a/drivers/devar.c b/drivers/devar.c
@@ -7,7 +7,8 @@
#include <rcode/9p.h>
#include <rcode/dev.h>
-#define NR_ARS 2
+#define NR_ARS 2
+#define NR_FILES 10
#define ARMAG "!<arch>\n" /* ar "magic number" */
#define SARMAG 8 /* strlen(ARMAG); */
@@ -16,24 +17,22 @@
struct ar_hdr {
- char ar_name[SARNAM]; /* name */
- char ar_date[12]; /* modification time */
- char ar_uid[6]; /* user id */
- char ar_gid[6]; /* group id */
- char ar_mode[8]; /* octal file permissions */
- char ar_size[10]; /* size in bytes */
- char ar_fmag[2]; /* consistency check */
+ char ar_name[SARNAM]; /* name */
+ char ar_date[12]; /* modification time */
+ char ar_uid[6]; /* user id */
+ char ar_gid[6]; /* group id */
+ char ar_mode[8]; /* octal file permissions */
+ char ar_size[10]; /* size in bytes */
+ char ar_fmag[2]; /* consistency check */
};
-enum Oarqid {
- Qarfs,
- Qctl,
-};
-
-static Dirtab arfstab[NR_ARS+1] = {
- {"ctl", Qctl, 0, O_READ | O_WRITE},
+struct arfile {
+ Chan *c;
+ long offset[NR_FILES];
+ long size[NR_FILES];
};
+static struct arfile archives[NR_ARS];
static int nars;
static int
@@ -42,17 +41,17 @@ gethdr(Chan *c, struct ar_hdr *hdr)
int n, ch, i;
n = devtab[c->type]->read(c, hdr, sizeof(*hdr));
- if (n == 0)
- return 0;
+ if (n <= 0)
+ return n;
+
if (n != sizeof(*hdr) || strncmp(hdr->ar_fmag, ARFMAG, 2) != 0) {
- errno = EFAULT; /* TODO: Put correct value */
+ errno = EINVAL;
return -1;
}
- /* TODO: Check if we do the same loop and we accept not null strings */
for (i = SARNAM-1; i >= 0; i--) {
ch = hdr->ar_name[i];
- if (ch != ' ' && ch !='/')
+ if (ch != ' ' && ch != '/')
break;
hdr->ar_name[i] = '\0';
}
@@ -60,48 +59,34 @@ gethdr(Chan *c, struct ar_hdr *hdr)
return 1;
}
-/*
- * TODO: This is broken, because we have a channel to
- * talk with the dev, but we need an offset
- * in the underlying dev.
- */
static int
argen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
{
- Qid qid;
- int len, r;
+ int i, r, len;
Chan nc;
- char buf[SARMAG];
struct ar_hdr hdr;
+ struct arfile *ar;
- qid = (c->qid & ~CHDIR) - 1;
- if (qid > nars)
+ if (c->dev >= nars)
panic("argen");
- clone(arfstab[qid].data, &nc);
- nc.offset = c->offset;
+ clone(archives[c->dev].c, &nc);
+ ar = &archives[nc.dev];
- if (nc.offset == 0) {
- r = devtab[nc.type]->read(&nc, buf, SARMAG);
- if (r != SARMAG || strncmp(buf, ARMAG, SARMAG)) {
- errno = EFAULT;
+ for (i = 0; i <= n; i++) {
+ if (ar->offset[i] == -1)
+ return 0;
+ if (devseek(&nc, ar->offset[i], RSEEK_SET) < 0)
return -1;
- }
+ if ((r = gethdr(&nc, &hdr)) <= 0)
+ return r;
}
- if ((r = gethdr(&nc, &hdr)) <= 0)
- return r;
- devseek(&nc, atol(hdr.ar_size), 1);
+ if ((len = strlen(hdr.ar_name)) >= NAMELEN) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
- if ((len = strlen(hdr.ar_name)) >= NAMELEN)
- return 0;
- memcpy(dir->name, hdr.ar_name, len);
- dir->name[len] = '\0';
- dir->length = atol(hdr.ar_size);
- dir->qid = (n + 1) * (NR_ARS+1) + qid;
- dir->mode = O_READ;
- dir->type = c->type;
- dir->dev = c->dev;
- c->offset = nc.offset;
+ mkentry(c, dir, hdr.ar_name, atol(hdr.ar_size), n, O_READ);
return 1;
}
@@ -109,94 +94,101 @@ argen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
static int
arwalk(Chan *c, const char *name)
{
- switch (c->qid & ~CHDIR) {
- case Qarfs:
- return devwalk(c, name, arfstab, nars+1, devgen);
- default:
- return devwalk(c, name, NULL, 0, argen);
- }
+ return devwalk(c, name, NULL, 0, argen);
}
static int
-ardirread(Chan *c, unsigned char *buf, int nbytes)
+arread(Chan *c, void *buf, int n)
{
- int n, cnt;
- Dir dir;
+ long off;
+ Chan cs;
+ struct arfile *ar;
- for (cnt = 0; nbytes >= DIRLEN; cnt += n) {
- switch (argen(c, NULL, 0, nbytes, &dir)) {
- case 0:
- return cnt;
- case -1:
- return (cnt > 0) ? cnt : -1;
- default:
- n = dirtop9(&dir, buf + cnt, nbytes);
- nbytes -= n;
- }
- }
+ if (c->qid == CHDIR)
+ return dirread(c, buf, n, NULL, 0, argen);
- return cnt;
-}
+ if (c->dev >= nars || (c->qid & CHDIR))
+ panic("arread1");
+ ar = &archives[c->dev];
-static int
-arread(Chan *c, void *buf, int n)
-{
- Qid qid;
- Chan nc;
+ if (c->qid >= NR_FILES || ar->offset[c->qid] == -1)
+ panic("arread2");
+ clone(ar->c, &cs);
- switch (c->qid & ~CHDIR) {
- case Qarfs:
- return dirread(c, buf, n, arfstab, nars+1, devgen);
- case Qctl:
- errno = EFAULT; /* TODO: Put a correct value */
+ if (c->offset >= ar->size)
+ return 0;
+
+ off = ar->offset[c->qid] + c->offset + sizeof(struct ar_hdr);
+ if (devseek(&cs, off, RSEEK_SET) < 0)
return -1;
- default:
- if (c->qid & CHDIR)
- return ardirread(c, buf, n);
- else {
- qid = c->qid % (NR_ARS + 1);
- clone(arfstab[qid].data, &nc);
- nc.offset = c->offset;
- n = devtab[nc.type]->read(&nc, buf, n);
- c->offset += n;
- return n;
- }
- }
+
+ n = devtab[cs.type]->read(&cs, buf, n);
+ c->offset += n;
+
+ return n;
}
-int
-arnew(char *name)
+static Chan *
+armount(Chan *c, char *spec)
{
- Qid qid;
- Chan *c;
- char *base;
- Dirtab *dp;
-
- base = strrchr(name, '/');
- base = (base) ? base+1 : name;
+ int r, n;
+ long len, offhdr;
+ Chan *cspec;
+ char buf[SARMAG];
+ struct ar_hdr hdr;
+ struct arfile *ar;
- if (nars >= NR_ARS || strlen(base) >= NAMELEN) {
+ if (nars == NR_ARS) {
errno = ENOMEM;
- return -1;
+ return NULL;
}
+ ar = &archives[nars];
- if ((c = namec(name, O_READ)) == NULL)
- return -1;
+ for (n = 0; n < NR_FILES; n++)
+ ar->offset[n] = -1;
+
+ if ((cspec = namec(spec, O_READ)) < 0)
+ return NULL;
+ ar->c = cspec;
- qid = ++nars + Qctl;
- dp = &arfstab[qid-1];
- dp->qid = CHDIR | qid;
- dp->perm = O_READ;
- dp->length = 0;
- dp->data = c;
- strcpy(dp->name, base);
+ r = devtab[cspec->type]->read(cspec, buf, SARMAG);
+ if (r < 0)
+ goto err;
+ if (r != SARMAG || strncmp(buf, ARMAG, SARMAG)) {
+ errno = EINVAL;
+ goto err;
+ }
+
+ for (n = 0; n < NR_FILES; n++) {
+ offhdr = cspec->offset;
+ switch (gethdr(cspec, &hdr)) {
+ case 0:
+ return devattach('R', nars++);
+ case -1:
+ goto err;
+ default:
+ ar->offset[n] = offhdr;
+ len = atol(hdr.ar_size);
+ ar->size[n] = len;
+ if ((len % 2) != 0)
+ len++;
+
+ if (devseek(cspec, len, RSEEK_CUR) < 0)
+ goto err;
+ break;
+ }
+ }
+ errno = ENOMEM;
- return 0;
+err:
+ chanclose(cspec);
+ return NULL;
}
const Dev ardevtab = {
- .id = 'r',
+ .id = 'R',
.walk = arwalk,
.read = arread,
.write = devwrite,
+ .mount = armount,
};
diff --git a/drivers/devroot.c b/drivers/devroot.c
@@ -1,8 +1,8 @@
#include <rcode/rcode.h>
#include <rcode/9p.h>
+#include <rcode/dev.h>
#include <libk.h>
-#include <rcode/dev.h>
enum Orootqid {
Qroot,
@@ -103,4 +103,5 @@ const Dev rootdevtab = {
.walk = rootwalk,
.read = rootread,
.write = devwrite,
+ .mount = devmount,
};
diff --git a/drivers/devuart.c b/drivers/devuart.c
@@ -247,4 +247,5 @@ const Dev uartdevtab = {
.walk = uartwalk,
.read = uartread,
.write = uartwrite,
+ .mount = devmount,
};
diff --git a/include/rcode/dev.h b/include/rcode/dev.h
@@ -1,6 +1,6 @@
#include <stddef.h>
-#define NR_CHANS 8
+#define NR_CHANS 20
#define NR_UARTS 2
#define NR_BINDS 4
#define NODEV 255
@@ -25,6 +25,7 @@ struct dev {
int (*walk)(Chan *c, const char *name);
int (*read)(Chan *c, void *buf, int n);
int (*write)(Chan *c, void *buf, int n);
+ Chan *(*mount)(Chan *c, char *spec);
};
struct chan {
@@ -41,6 +42,7 @@ struct attr {
};
+extern Chan *devattach(int id, int dev);
extern int devseek(Chan *c, long long off, int whence);
extern Chan * namec(const char *name, int mode);
extern Chan *clone(Chan *c, Chan *nc);
@@ -48,7 +50,11 @@ extern void chanclose(Chan *c);
extern int buf2chan(Chan *c,
void *dst, void *src,
int nbytes, unsigned long long len);
+extern void mkentry(Chan *c, Dir *dir,
+ const char *name,
+ unsigned long long length, Qid qid, unsigned mode);
+extern int devmount(Chan *c, char *spec);
extern void devlink(void);
extern int devwrite(Chan *c, void *buf, int n);
extern int devgen(Chan *c,
diff --git a/include/rcode/rcode.h b/include/rcode/rcode.h
@@ -102,6 +102,7 @@ extern void idev(void);
extern void dumpregs(struct trapframe *fp);
/* driver functions */
+extern int mount(char *srv, char *mnt, char *spec);
extern int create(const char *name, int flags);
extern int open(const char *name, int flags);
extern int close(int fd);
diff --git a/scripts/rules.mk b/scripts/rules.mk
@@ -8,6 +8,7 @@ LIBDIR = $(PROJECTDIR)/lib
BINDIR = $(PROJECTDIR)/bin
TARGETDIR = $(PROJECTDIR)/target/$(MODE)
DRVDIR = $(PROJECTDIR)/drivers
+FSDIR = $(PROJECTDIR)/fs
SRCDIR = $(PROJECTDIR)/src
SCRIPTDIR = $(PROJECTDIR)/scripts
CONFDIR = $(PROJECTDIR)/config
diff --git a/target/hosted/rom.c b/target/hosted/rom.c
@@ -47,8 +47,6 @@ imach(void)
framep = &trapframe;
}
-extern int arnew(char *file);
-
static void
namespace(void)
{
@@ -56,9 +54,7 @@ namespace(void)
goto error;
if (bind("#t0", "/dev/cons") < 0)
goto error;
- if (bind("#r", "/arfs") < 0)
- goto error;
- if (arnew("/blobs/example.a") < 0)
+ if (mount("#R", "/arfs", "/blobs/example.a") < 0)
goto error;
return;