cowfs is bootable now!
This commit is contained in:
+64
-28
@@ -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
@@ -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
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user