cowfs is bootable now!

This commit is contained in:
Martin Willi
2007-08-06 11:42:32 +00:00
parent afc51a247f
commit 64a552ae2d
3 changed files with 94 additions and 55 deletions
+64 -28
View File
@@ -67,11 +67,17 @@ struct private_cowfs_t {
pthread_t thread; pthread_t thread;
}; };
/**
* get this pointer stored in fuse context
*/
static private_cowfs_t *get_this() static private_cowfs_t *get_this()
{ {
return (fuse_get_context())->private_data; return (fuse_get_context())->private_data;
} }
/**
* make a path relative
*/
static void rel(const char **path) static void rel(const char **path)
{ {
if (**path == '/') if (**path == '/')
@@ -85,7 +91,7 @@ static void rel(const char **path)
} }
/** /**
* get the filesystem to read something from * get the highest overlay in which path exists
*/ */
static int get_rd(const char *path) static int get_rd(const char *path)
{ {
@@ -103,7 +109,7 @@ static int get_rd(const char *path)
} }
/** /**
* get the filesystem to write something to * get the highest overlay available, to write something
*/ */
static int get_wr(const char *path) static int get_wr(const char *path)
{ {
@@ -116,7 +122,7 @@ static int get_wr(const char *path)
} }
/** /**
* create all directories need to create the file "path" * create full "path" at "wr" the same way they exist at "rd"
*/ */
static bool clone_path(int rd, int wr, const char *path) static bool clone_path(int rd, int wr, const char *path)
{ {
@@ -130,7 +136,7 @@ static bool clone_path(int rd, int wr, const char *path)
*pos = '\0'; *pos = '\0';
if (fstatat(wr, full, &st, 0) < 0) if (fstatat(wr, full, &st, 0) < 0)
{ {
/* TODO: handle symlinks! */ /* TODO: handle symlinks!? */
if (fstatat(rd, full, &st, 0) < 0) if (fstatat(rd, full, &st, 0) < 0)
{ {
return FALSE; return FALSE;
@@ -147,7 +153,7 @@ static bool clone_path(int rd, int wr, const char *path)
} }
/** /**
* copy a file from a readonly to a read-write overlay * copy a (special) file from a readonly to a read-write overlay
*/ */
static int copy(const char *path) static int copy(const char *path)
{ {
@@ -169,35 +175,44 @@ static int copy(const char *path)
{ {
return -1; return -1;
} }
from = openat(rd, path, O_RDONLY, st.st_mode);
if (from < 0)
{
return -1;
}
if (!clone_path(rd, wr, path)) if (!clone_path(rd, wr, path))
{ {
return -1; return -1;
} }
to = openat(wr, path, O_WRONLY | O_CREAT, st.st_mode); if (mknodat(wr, path, st.st_mode, st.st_rdev) < 0)
if (to < 0)
{ {
close(from);
return -1; return -1;
} }
while ((len = read(from, buf, sizeof(buf))) > 0) /* copy if no special file */
if (st.st_size)
{ {
if (write(to, buf, len) < len) from = openat(rd, path, O_RDONLY, st.st_mode);
if (from < 0)
{
return -1;
}
to = openat(wr, path, O_WRONLY , st.st_mode);
if (to < 0)
{
close(from);
return -1;
}
while ((len = read(from, buf, sizeof(buf))) > 0)
{
if (write(to, buf, len) < len)
{
/* TODO: only on len < 0 ? */
close(from);
close(to);
return -1;
}
}
close(from);
close(to);
if (len < 0)
{ {
close(from);
close(to);
return -1; return -1;
} }
}
close(from);
close(to);
if (len < 0)
{
return -1;
} }
return wr; return wr;
} }
@@ -423,10 +438,18 @@ static int cowfs_rmdir(const char *path)
*/ */
static int cowfs_symlink(const char *from, const char *to) static int cowfs_symlink(const char *from, const char *to)
{ {
rel(&to); int fd;
const char *fromrel = from;
/* TODO: relative from? */ rel(&to);
if (symlinkat(from, get_wr(to), to) < 0) rel(&fromrel);
fd = get_wr(to);
if (!clone_path(get_rd(fromrel), fd, fromrel))
{
return -errno;
}
if (symlinkat(from, fd, to) < 0)
{ {
return -errno; return -errno;
} }
@@ -466,11 +489,22 @@ static int cowfs_rename(const char *from, const char *to)
*/ */
static int cowfs_link(const char *from, const char *to) static int cowfs_link(const char *from, const char *to)
{ {
int rd, wr;
rel(&from); rel(&from);
rel(&to); rel(&to);
if (linkat(get_rd(from), from, get_wr(to), to, 0) < 0) rd = get_rd(from);
wr = get_wr(to);
if (!clone_path(rd, wr, to))
{
DBG1("cloning path '%s' failed", to);
return -errno;
}
if (linkat(rd, from, wr, to, 0) < 0)
{ {
DBG1("linking '%s' to '%s' failed", from, to);
return -errno; return -errno;
} }
return 0; return 0;
@@ -551,6 +585,7 @@ static int cowfs_truncate(const char *path, off_t size)
{ {
int fd; int fd;
struct stat st; struct stat st;
private_cowfs_t *this = get_this(); private_cowfs_t *this = get_this();
rel(&path); rel(&path);
@@ -653,6 +688,7 @@ static int cowfs_read(const char *path, char *buf, size_t size, off_t offset,
{ {
return -errno; return -errno;
} }
res = pread(file, buf, size, offset); res = pread(file, buf, size, offset);
if (res < 0) if (res < 0)
{ {
@@ -848,7 +884,7 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
this->host = strdup(host); this->host = strdup(host);
this->scen = NULL; this->scen = NULL;
if (pthread_create(&this->thread, NULL, (void*)fuse_loop_mt, this->fuse) != 0) if (pthread_create(&this->thread, NULL, (void*)fuse_loop, this->fuse) != 0)
{ {
DBG1("creating thread to handle FUSE failed"); DBG1("creating thread to handle FUSE failed");
fuse_unmount(mount, this->chan); fuse_unmount(mount, this->chan);
+19 -18
View File
@@ -96,25 +96,25 @@ static iterator_t* create_bridge_iterator(private_dumm_t *this)
*/ */
void signal_handler(int sig, siginfo_t *info, void *ucontext) void signal_handler(int sig, siginfo_t *info, void *ucontext)
{ {
private_dumm_t *this;
guest_t *guest;
iterator_t *iterator, *guests;
if (sig == SIGCHLD) if (sig == SIGCHLD)
{ {
iterator = instances->create_iterator(instances, TRUE); switch (info->si_code)
while (iterator->iterate(iterator, (void**)&this))
{ {
if (this->destroying) case CLD_EXITED:
case CLD_KILLED:
case CLD_DUMPED:
{ {
continue; private_dumm_t *this;
} guest_t *guest;
switch (info->si_code) iterator_t *iterator, *guests;
{
case CLD_EXITED: iterator = instances->create_iterator(instances, TRUE);
case CLD_KILLED: while (iterator->iterate(iterator, (void**)&this))
case CLD_DUMPED:
{ {
if (this->destroying)
{
continue;
}
guests = this->guests->create_iterator(this->guests, TRUE); guests = this->guests->create_iterator(this->guests, TRUE);
while (guests->iterate(guests, (void**)&guest)) while (guests->iterate(guests, (void**)&guest))
{ {
@@ -125,13 +125,14 @@ void signal_handler(int sig, siginfo_t *info, void *ucontext)
} }
} }
guests->destroy(guests); guests->destroy(guests);
break;
} }
default: iterator->destroy(iterator);
break; break;
} }
default:
break;
} }
iterator->destroy(iterator);
} }
/* SIGHUP is currently just ignored */ /* SIGHUP is currently just ignored */
} }
+10 -8
View File
@@ -170,10 +170,8 @@ static void stop(private_guest_t *this)
this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy)); this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy));
this->ifaces = linked_list_create(); this->ifaces = linked_list_create();
kill(this->pid, SIGINT); kill(this->pid, SIGINT);
while (this->state == GUEST_STOPPING) waitpid(this->pid, NULL, 0);
{ this->state = GUEST_STOPPED;
sched_yield();
}
} }
} }
@@ -208,7 +206,8 @@ static bool start(private_guest_t *this, char *kernel)
args[i++] = write_arg(&pos, &left, "mconsole=notify:%s", notify); args[i++] = write_arg(&pos, &left, "mconsole=notify:%s", notify);
/*args[i++] = write_arg(&pos, &left, "con=pts");*/ /*args[i++] = write_arg(&pos, &left, "con=pts");*/
args[i++] = write_arg(&pos, &left, "con0=null,fd:%d", this->bootlog); args[i++] = write_arg(&pos, &left, "con0=null,fd:%d", this->bootlog);
/*args[i++] = write_arg(&pos, &left, "con1=fd:0,fd:1");*/ //args[i++] = write_arg(&pos, &left, "con0=fd:0,fd:1");
//args[i++] = write_arg(&pos, &left, "con1=null,null");
args[i++] = write_arg(&pos, &left, "con2=null,null"); args[i++] = write_arg(&pos, &left, "con2=null,null");
args[i++] = write_arg(&pos, &left, "con3=null,null"); args[i++] = write_arg(&pos, &left, "con3=null,null");
args[i++] = write_arg(&pos, &left, "con4=null,null"); args[i++] = write_arg(&pos, &left, "con4=null,null");
@@ -221,8 +220,8 @@ static bool start(private_guest_t *this, char *kernel)
{ {
case 0: /* child, */ case 0: /* child, */
dup2(open("/dev/null", 0), 0); dup2(open("/dev/null", 0), 0);
dup2(open("/dev/null", 0), 1); dup2(this->bootlog, 1);
dup2(open("/dev/null", 0), 2); dup2(this->bootlog, 2);
execvp(args[0], args); execvp(args[0], args);
DBG1("starting UML kernel '%s' failed: %m", args[0]); DBG1("starting UML kernel '%s' failed: %m", args[0]);
exit(1); exit(1);
@@ -249,7 +248,10 @@ static bool start(private_guest_t *this, char *kernel)
*/ */
static void sigchild(private_guest_t *this) static void sigchild(private_guest_t *this)
{ {
waitpid(this->pid, NULL, WNOHANG); if (this->state != GUEST_STOPPING)
{ /* collect zombie if uml crashed */
waitpid(this->pid, NULL, WNOHANG);
}
DESTROY_IF(this->mconsole); DESTROY_IF(this->mconsole);
this->mconsole = NULL; this->mconsole = NULL;
this->state = GUEST_STOPPED; this->state = GUEST_STOPPED;