#include <endian.h>
#include <byteswap.h>
-static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
+void ignore_sigwinch_sig(void)
{
- struct uml_stat buf1, buf2;
- int err;
-
- if(from_cmdline == NULL) return(1);
- if(!strcmp(from_cmdline, from_cow)) return(1);
-
- err = os_stat_file(from_cmdline, &buf1);
- if(err < 0){
- printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
- return(1);
- }
- err = os_stat_file(from_cow, &buf2);
- if(err < 0){
- printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
- return(1);
- }
- if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
- return(1);
-
- printk("Backing file mismatch - \"%s\" requested,\n"
- "\"%s\" specified in COW header of \"%s\"\n",
- from_cmdline, from_cow, cow);
- return(0);
-}
-
-static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
-{
- unsigned long modtime;
- long long actual;
- int err;
-
- err = os_file_modtime(file, &modtime);
- if(err < 0){
- printk("Failed to get modification time of backing file "
- "\"%s\", err = %d\n", file, -err);
- return(err);
- }
-
- err = os_file_size(file, &actual);
- if(err < 0){
- printk("Failed to get size of backing file \"%s\", "
- "err = %d\n", file, -err);
- return(err);
- }
-
- if(actual != size){
- printk("Size mismatch (%ld vs %ld) of COW header vs backing "
- "file\n", size, actual);
- return(-EINVAL);
- }
- if(modtime != mtime){
- printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
- "file\n", mtime, modtime);
- return(-EINVAL);
- }
- return(0);
-}
-
-int read_cow_bitmap(int fd, void *buf, int offset, int len)
-{
- int err;
-
- err = os_seek_file(fd, offset);
- if(err < 0)
- return(err);
-
- err = os_read_file(fd, buf, len);
- if(err < 0)
- return(err);
-
- return(0);
-}
-
-int open_ubd_file(char *file, struct openflags *openflags,
- char **backing_file_out, int *bitmap_offset_out,
- unsigned long *bitmap_len_out, int *data_offset_out,
- int *create_cow_out)
-{
- time_t mtime;
- __u64 size;
- __u32 version, align;
- char *backing_file;
- int fd, err, sectorsize, same, mode = 0644;
-
- fd = os_open_file(file, *openflags, mode);
- if(fd < 0){
- if((fd == -ENOENT) && (create_cow_out != NULL))
- *create_cow_out = 1;
- if(!openflags->w ||
- ((errno != EROFS) && (errno != EACCES))) return(-errno);
- openflags->w = 0;
- fd = os_open_file(file, *openflags, mode);
- if(fd < 0)
- return(fd);
- }
-
- err = os_lock_file(fd, openflags->w);
- if(err < 0){
- printk("Failed to lock '%s', err = %d\n", file, -err);
- goto out_close;
- }
-
- if(backing_file_out == NULL) return(fd);
-
- err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
- &size, §orsize, &align, bitmap_offset_out);
- if(err && (*backing_file_out != NULL)){
- printk("Failed to read COW header from COW file \"%s\", "
- "errno = %d\n", file, -err);
- goto out_close;
- }
- if(err) return(fd);
-
- if(backing_file_out == NULL) return(fd);
-
- same = same_backing_files(*backing_file_out, backing_file, file);
-
- if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
- printk("Switching backing file to '%s'\n", *backing_file_out);
- err = write_cow_header(file, fd, *backing_file_out,
- sectorsize, align, &size);
- if(err){
- printk("Switch failed, errno = %d\n", -err);
- return(err);
- }
- }
- else {
- *backing_file_out = backing_file;
- err = backing_file_mismatch(*backing_file_out, size, mtime);
- if(err) goto out_close;
- }
-
- cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
- bitmap_len_out, data_offset_out);
-
- return(fd);
- out_close:
- os_close_file(fd);
- return(err);
-}
-
-int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
- int sectorsize, int alignment, int *bitmap_offset_out,
- unsigned long *bitmap_len_out, int *data_offset_out)
-{
- int err, fd;
-
- flags.c = 1;
- fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
- if(fd < 0){
- err = fd;
- printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
- -err);
- goto out;
- }
-
- err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
- bitmap_offset_out, bitmap_len_out,
- data_offset_out);
- if(!err)
- return(fd);
- os_close_file(fd);
- out:
- return(err);
-}
-
-/* XXX Just trivial wrappers around os_read_file and os_write_file */
-int read_ubd_fs(int fd, void *buffer, int len)
-{
- return(os_read_file(fd, buffer, len));
-}
-
-int write_ubd_fs(int fd, char *buffer, int len)
-{
- return(os_write_file(fd, buffer, len));
-}
-
-static int update_bitmap(struct io_thread_req *req)
-{
- int n;
-
- if(req->cow_offset == -1)
- return(0);
-
- n = os_seek_file(req->fds[1], req->cow_offset);
- if(n < 0){
- printk("do_io - bitmap lseek failed : err = %d\n", -n);
- return(1);
- }
-
- n = os_write_file(req->fds[1], &req->bitmap_words,
- sizeof(req->bitmap_words));
- if(n != sizeof(req->bitmap_words)){
- printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
- req->fds[1]);
- return(1);
- }
-
- return(0);
-}
-
-void do_io(struct io_thread_req *req)
-{
- char *buf;
- unsigned long len;
- int n, nsectors, start, end, bit;
- int err;
- __u64 off;
-
- if(req->op == UBD_MMAP){
- /* Touch the page to force the host to do any necessary IO to
- * get it into memory
- */
- n = *((volatile int *) req->buffer);
- req->error = update_bitmap(req);
- return;
- }
-
- nsectors = req->length / req->sectorsize;
- start = 0;
- do {
- bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
- end = start;
- while((end < nsectors) &&
- (ubd_test_bit(end, (unsigned char *)
- &req->sector_mask) == bit))
- end++;
-
- off = req->offset + req->offsets[bit] +
- start * req->sectorsize;
- len = (end - start) * req->sectorsize;
- buf = &req->buffer[start * req->sectorsize];
-
- err = os_seek_file(req->fds[bit], off);
- if(err < 0){
- printk("do_io - lseek failed : err = %d\n", -err);
- req->error = 1;
- return;
- }
- if(req->op == UBD_READ){
- n = 0;
- do {
- buf = &buf[n];
- len -= n;
- n = os_read_file(req->fds[bit], buf, len);
- if (n < 0) {
- printk("do_io - read failed, err = %d "
- "fd = %d\n", -n, req->fds[bit]);
- req->error = 1;
- return;
- }
- } while((n < len) && (n != 0));
- if (n < len) memset(&buf[n], 0, len - n);
- }
- else {
- n = os_write_file(req->fds[bit], buf, len);
- if(n != len){
- printk("do_io - write failed err = %d "
- "fd = %d\n", -n, req->fds[bit]);
- req->error = 1;
- return;
- }
- }
-
- start = end;
- } while(start < nsectors);
-
- req->error = update_bitmap(req);
-}
-
-/* Changed in start_io_thread, which is serialized by being called only
- * from ubd_init, which is an initcall.
- */
-int kernel_fd = -1;
-
-/* Only changed by the io thread */
-int io_count = 0;
-
-int io_thread(void *arg)
-{
- struct io_thread_req req;
- int n;
-
signal(SIGWINCH, SIG_IGN);
- while(1){
- n = os_read_file(kernel_fd, &req, sizeof(req));
- if(n != sizeof(req)){
- if(n < 0)
- printk("io_thread - read failed, fd = %d, "
- "err = %d\n", kernel_fd, -n);
- else {
- printk("io_thread - short read, fd = %d, "
- "length = %d\n", kernel_fd, n);
- }
- continue;
- }
- io_count++;
- do_io(&req);
- n = os_write_file(kernel_fd, &req, sizeof(req));
- if(n != sizeof(req))
- printk("io_thread - write failed, fd = %d, err = %d\n",
- kernel_fd, -n);
- }
}
int start_io_thread(unsigned long sp, int *fd_out)