venti: allow plan 9 partitions as disk subnames
This commit is contained in:
parent
cb29a5fce6
commit
304ab920ad
1 changed files with 105 additions and 192 deletions
|
|
@ -19,6 +19,8 @@
|
||||||
u32int maxblocksize;
|
u32int maxblocksize;
|
||||||
int readonly;
|
int readonly;
|
||||||
|
|
||||||
|
int findsubpart(Part *part, char *name);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
strtoullsuf(char *p, char **pp, int rad, u64int *u)
|
strtoullsuf(char *p, char **pp, int rad, u64int *u)
|
||||||
{
|
{
|
||||||
|
|
@ -56,17 +58,21 @@ strtoullsuf(char *p, char **pp, int rad, u64int *u)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parsepart(char *name, char **file, u64int *lo, u64int *hi)
|
parsepart(char *name, char **file, char **subpart, u64int *lo, u64int *hi)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
*file = estrdup(name);
|
*file = estrdup(name);
|
||||||
if((p = strrchr(*file, ':')) == nil){
|
*lo = 0;
|
||||||
*lo = 0;
|
*hi = 0;
|
||||||
*hi = 0;
|
*subpart = nil;
|
||||||
|
if((p = strrchr(*file, ':')) == nil)
|
||||||
|
return 0;
|
||||||
|
*p++ = 0;
|
||||||
|
if(isalpha(*p)){
|
||||||
|
*subpart = p;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*p++ = 0;
|
|
||||||
if(*p == '-')
|
if(*p == '-')
|
||||||
*lo = 0;
|
*lo = 0;
|
||||||
else{
|
else{
|
||||||
|
|
@ -93,11 +99,13 @@ initpart(char *name, int mode)
|
||||||
{
|
{
|
||||||
Part *part;
|
Part *part;
|
||||||
Dir *dir;
|
Dir *dir;
|
||||||
char *file;
|
char *file, *subname;
|
||||||
u64int lo, hi;
|
u64int lo, hi;
|
||||||
|
|
||||||
if(parsepart(name, &file, &lo, &hi) < 0)
|
if(parsepart(name, &file, &subname, &lo, &hi) < 0){
|
||||||
|
werrstr("cannot parse name %s", name);
|
||||||
return nil;
|
return nil;
|
||||||
|
}
|
||||||
trace(TraceDisk, "initpart %s file %s lo 0x%llx hi 0x%llx", name, file, lo, hi);
|
trace(TraceDisk, "initpart %s file %s lo 0x%llx hi 0x%llx", name, file, lo, hi);
|
||||||
part = MKZ(Part);
|
part = MKZ(Part);
|
||||||
part->name = estrdup(name);
|
part->name = estrdup(name);
|
||||||
|
|
@ -124,7 +132,7 @@ initpart(char *name, int mode)
|
||||||
fprint(2, "warning: %s opened for reading only\n", name);
|
fprint(2, "warning: %s opened for reading only\n", name);
|
||||||
}
|
}
|
||||||
part->offset = lo;
|
part->offset = lo;
|
||||||
dir = dirfstat(part->fd);
|
dir = dirstat(file); /* no dirfstat; need name to identify disk devices */
|
||||||
if(dir == nil){
|
if(dir == nil){
|
||||||
freepart(part);
|
freepart(part);
|
||||||
seterr(EOk, "can't stat partition='%s': %r", file);
|
seterr(EOk, "can't stat partition='%s': %r", file);
|
||||||
|
|
@ -155,6 +163,11 @@ initpart(char *name, int mode)
|
||||||
part->fsblocksize = sfs.f_bsize;
|
part->fsblocksize = sfs.f_bsize;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if(subname && findsubpart(part, subname) < 0){
|
||||||
|
werrstr("cannot find subpartition %s", subname);
|
||||||
|
freepart(part);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
free(dir);
|
free(dir);
|
||||||
return part;
|
return part;
|
||||||
}
|
}
|
||||||
|
|
@ -464,206 +477,106 @@ readfile(char *name)
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search for the Plan 9 partition with the given name.
|
||||||
|
* This lets you write things like /dev/ad4:arenas
|
||||||
|
* if you move a disk from a Plan 9 system to a FreeBSD system.
|
||||||
|
*
|
||||||
|
* God I hope I never write this code again.
|
||||||
|
*/
|
||||||
#ifndef PLAN9PORT
|
#define MAGIC "plan9 partitions"
|
||||||
static int
|
static int
|
||||||
sdreset(Part *part)
|
tryplan9part(Part *part, char *name)
|
||||||
{
|
{
|
||||||
char *name, *p;
|
uchar buf[512];
|
||||||
int i, fd, xfd[3], rv;
|
char *line[40], *f[4];
|
||||||
static QLock resetlk;
|
int i, n;
|
||||||
Dir *d, *dd;
|
vlong start, end;
|
||||||
|
|
||||||
fprint(2, "sdreset %s\n", part->name);
|
/*
|
||||||
name = emalloc(strlen(part->filename)+20);
|
* Partition table in second sector.
|
||||||
strcpy(name, part->filename);
|
* Could also look on 2nd last sector and last sector,
|
||||||
p = strrchr(name, '/');
|
* but those disks died out long before venti came along.
|
||||||
if(p)
|
*/
|
||||||
p++;
|
if(readpart(part, 512, buf, 512) != 512)
|
||||||
else
|
|
||||||
p = name;
|
|
||||||
|
|
||||||
strcpy(p, "ctl");
|
|
||||||
d = dirstat(name);
|
|
||||||
if(d == nil){
|
|
||||||
free(name);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/* Plan 9 partition table is just text strings */
|
||||||
* We don't need multiple people resetting the disk.
|
if(strncmp((char*)buf, "part ", 5) != 0)
|
||||||
*/
|
return -1;
|
||||||
qlock(&resetlk);
|
|
||||||
if((fd = open(name, OWRITE)) < 0)
|
|
||||||
goto error;
|
|
||||||
dd = dirfstat(fd);
|
|
||||||
if(d && dd && d->qid.vers != dd->qid.vers){
|
|
||||||
fprint(2, "sdreset %s: got scooped\n", part->name);
|
|
||||||
/* Someone else got here first. */
|
|
||||||
if(access(part->filename, AEXIST) >= 0)
|
|
||||||
goto ok;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
buf[511] = 0;
|
||||||
* Write "reset" to the ctl file to cause the chipset
|
n = getfields((char*)buf, line, 40, 1, "\n");
|
||||||
* to reinitialize itself (specific to sdmv driver).
|
for(i=0; i<n; i++){
|
||||||
* Ignore error in case using other disk.
|
if(getfields(line[i], f, 4, 1, " ") != 4)
|
||||||
*/
|
break;
|
||||||
fprint(2, "sdreset %s: reset ctl\n", part->name);
|
if(strcmp(f[0], "part") != 0)
|
||||||
write(fd, "reset", 5);
|
break;
|
||||||
|
if(strcmp(f[1], name) == 0){
|
||||||
if(access(part->filename, AEXIST) >= 0)
|
start = 512*strtoll(f[2], 0, 0);
|
||||||
goto ok;
|
end = 512*strtoll(f[3], 0, 0);
|
||||||
|
if(start < end && end <= part->size){
|
||||||
/*
|
part->offset += start;
|
||||||
* Re-run fdisk and prep. Don't use threadwaitchan
|
part->size = end - start;
|
||||||
* to avoid coordinating for it. Reopen ctl because
|
return 0;
|
||||||
* we reset the disk.
|
}
|
||||||
*/
|
|
||||||
strcpy(p, "ctl");
|
|
||||||
close(fd);
|
|
||||||
if((fd = open(name, OWRITE)) < 0)
|
|
||||||
goto error;
|
|
||||||
strcpy(p, "data");
|
|
||||||
xfd[0] = open("/dev/null", OREAD);
|
|
||||||
xfd[1] = dup(fd, -1);
|
|
||||||
xfd[2] = dup(2, -1);
|
|
||||||
fprint(2, "sdreset %s: run fdisk %s\n", part->name, name);
|
|
||||||
if(threadspawnl(xfd, "/bin/disk/fdisk", "disk/fdisk", "-p", name, nil) < 0){
|
|
||||||
close(xfd[0]);
|
|
||||||
close(xfd[1]);
|
|
||||||
close(xfd[2]);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
strcpy(p, "plan9");
|
|
||||||
for(i=0; i<=20; i++){
|
|
||||||
sleep(i*100);
|
|
||||||
if(access(part->filename, AEXIST) >= 0)
|
|
||||||
goto ok;
|
|
||||||
if(access(name, AEXIST) >= 0)
|
|
||||||
goto prep;
|
|
||||||
}
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
prep:
|
|
||||||
strcpy(p, "ctl");
|
|
||||||
close(fd);
|
|
||||||
if((fd = open(name, OWRITE)) < 0)
|
|
||||||
goto error;
|
|
||||||
strcpy(p, "plan9");
|
|
||||||
xfd[0] = open("/dev/null", OREAD);
|
|
||||||
xfd[1] = dup(fd, -1);
|
|
||||||
xfd[2] = dup(2, -1);
|
|
||||||
fprint(2, "sdreset %s: run prep\n", part->name);
|
|
||||||
if(threadspawnl(xfd, "/bin/disk/prep", "disk/prep", "-p", name, nil) < 0){
|
|
||||||
close(xfd[0]);
|
|
||||||
close(xfd[1]);
|
|
||||||
close(xfd[2]);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
for(i=0; i<=20; i++){
|
|
||||||
sleep(i*100);
|
|
||||||
if(access(part->filename, AEXIST) >= 0)
|
|
||||||
goto ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
|
||||||
fprint(2, "sdreset %s: error: %r\n", part->name);
|
|
||||||
rv = -1;
|
|
||||||
if(fd >= 0)
|
|
||||||
close(fd);
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ok:
|
|
||||||
fprint(2, "sdreset %s: all okay\n", part->name);
|
|
||||||
rv = 0;
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
free(name);
|
|
||||||
qunlock(&resetlk);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
reopen(Part *part)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fprint(2, "reopen %s\n", part->filename);
|
|
||||||
if((fd = open(part->filename, ORDWR)) < 0){
|
|
||||||
if(access(part->filename, AEXIST) < 0){
|
|
||||||
sdreset(part);
|
|
||||||
fd = open(part->filename, ORDWR);
|
|
||||||
}
|
|
||||||
if(fd < 0){
|
|
||||||
fprint(2, "reopen %s: %r\n", part->filename);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(fd != part->fd){
|
return -1;
|
||||||
dup(fd, part->fd);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct Spawn Spawn;
|
#define GSHORT(p) (((p)[1]<<8)|(p)[0])
|
||||||
struct Spawn
|
#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
|
||||||
|
|
||||||
|
typedef struct Dospart Dospart;
|
||||||
|
struct Dospart
|
||||||
{
|
{
|
||||||
Channel *c;
|
uchar flag; /* active flag */
|
||||||
int fd[3];
|
uchar shead; /* starting head */
|
||||||
char *file;
|
uchar scs[2]; /* starting cylinder/sector */
|
||||||
char **argv;
|
uchar type; /* partition type */
|
||||||
|
uchar ehead; /* ending head */
|
||||||
|
uchar ecs[2]; /* ending cylinder/sector */
|
||||||
|
uchar offset[4]; /* starting sector */
|
||||||
|
uchar size[4]; /* length in sectors */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
spawnproc(void *v)
|
|
||||||
{
|
|
||||||
int i, *fd;
|
|
||||||
Spawn *s;
|
|
||||||
|
|
||||||
rfork(RFFDG);
|
|
||||||
s = v;
|
|
||||||
fd = s->fd;
|
|
||||||
for(i=0; i<3; i++)
|
|
||||||
dup(fd[i], i);
|
|
||||||
if(fd[0] > 2)
|
|
||||||
close(fd[0]);
|
|
||||||
if(fd[1] > 2 && fd[1] != fd[0])
|
|
||||||
close(fd[1]);
|
|
||||||
if(fd[2] > 2 && fd[2] != fd[1] && fd[2] != fd[0])
|
|
||||||
close(fd[2]);
|
|
||||||
procexec(s->c, s->file, s->argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
int
|
||||||
threadspawnl(int fd[3], char *file, char *argv0, ...)
|
findsubpart(Part *part, char *name)
|
||||||
{
|
{
|
||||||
int pid;
|
int i;
|
||||||
Spawn s;
|
uchar buf[512];
|
||||||
|
u64int size;
|
||||||
|
Dospart *dp;
|
||||||
|
|
||||||
|
/* See if this is a Plan 9 partition. */
|
||||||
|
if(tryplan9part(part, name) >= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
s.c = chancreate(sizeof(void*), 0);
|
/* Otherwise try for an MBR and then narrow to Plan 9 partition. */
|
||||||
memmove(s.fd, fd, sizeof(s.fd));
|
if(readpart(part, 0, buf, 512) != 512)
|
||||||
s.file = file;
|
|
||||||
s.argv = &argv0;
|
|
||||||
vtproc(spawnproc, &s);
|
|
||||||
pid = recvul(s.c);
|
|
||||||
if(pid < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
close(fd[0]);
|
if(buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
|
||||||
if(fd[1] != fd[0])
|
return -1;
|
||||||
close(fd[1]);
|
dp = (Dospart*)(buf+0x1BE);
|
||||||
if(fd[2] != fd[1] && fd[2] != fd[0])
|
size = part->size;
|
||||||
close(fd[2]);
|
for(i=0; i<4; i++){
|
||||||
return pid;
|
if(dp[i].type == '9'){
|
||||||
|
part->offset = 512LL*GLONG(dp[i].offset);
|
||||||
|
part->size = 512LL*GLONG(dp[i].size);
|
||||||
|
if(tryplan9part(part, name) >= 0)
|
||||||
|
return 0;
|
||||||
|
part->offset = 0;
|
||||||
|
part->size = size;
|
||||||
|
}
|
||||||
|
/* Not implementing extended partitions - enough is enough. */
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue