2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com)
4 * Licensed under the GPL
13 #include <netinet/in.h>
15 #include <sys/socket.h>
17 #include <sys/param.h>
18 #include "asm/types.h"
19 #include "user_util.h"
20 #include "kern_util.h"
29 static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
31 struct uml_stat buf1, buf2;
34 if(from_cmdline == NULL) return(1);
35 if(!strcmp(from_cmdline, from_cow)) return(1);
37 err = os_stat_file(from_cmdline, &buf1);
39 printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
42 err = os_stat_file(from_cow, &buf2);
44 printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
47 if((buf1.ust_major == buf2.ust_major) &&
48 (buf1.ust_minor == buf2.ust_minor) &&
49 (buf1.ust_ino == buf2.ust_ino))
52 printk("Backing file mismatch - \"%s\" requested,\n"
53 "\"%s\" specified in COW header of \"%s\"\n",
54 from_cmdline, from_cow, cow);
58 static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
60 unsigned long modtime;
64 err = os_file_modtime(file, &modtime);
66 printk("Failed to get modification time of backing file "
67 "\"%s\", err = %d\n", file, -err);
71 err = os_file_size(file, &actual);
73 printk("Failed to get size of backing file \"%s\", "
74 "err = %d\n", file, -err);
79 printk("Size mismatch (%ld vs %ld) of COW header vs backing "
80 "file\n", size, actual);
84 printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
85 "file\n", mtime, modtime);
91 int read_cow_bitmap(int fd, void *buf, int offset, int len)
95 err = os_seek_file(fd, offset);
99 err = os_read_file(fd, buf, len);
106 int open_ubd_file(char *file, struct openflags *openflags,
107 char **backing_file_out, int *bitmap_offset_out,
108 unsigned long *bitmap_len_out, int *data_offset_out,
113 __u32 version, align;
115 int fd, err, sectorsize, same, mode = 0644;
117 fd = os_open_file(file, *openflags, mode);
119 if((fd == -ENOENT) && (create_cow_out != NULL))
122 ((errno != EROFS) && (errno != EACCES))) return(-errno);
124 fd = os_open_file(file, *openflags, mode);
129 err = os_lock_file(fd, openflags->w);
131 printk("Failed to lock '%s', err = %d\n", file, -err);
135 if(backing_file_out == NULL) return(fd);
137 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
138 &size, §orsize, &align, bitmap_offset_out);
139 if(err && (*backing_file_out != NULL)){
140 printk("Failed to read COW header from COW file \"%s\", "
141 "errno = %d\n", file, -err);
146 if(backing_file_out == NULL) return(fd);
148 same = same_backing_files(*backing_file_out, backing_file, file);
150 if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
151 printk("Switching backing file to '%s'\n", *backing_file_out);
152 err = write_cow_header(file, fd, *backing_file_out,
153 sectorsize, align, &size);
155 printk("Switch failed, errno = %d\n", -err);
160 *backing_file_out = backing_file;
161 err = backing_file_mismatch(*backing_file_out, size, mtime);
162 if(err) goto out_close;
165 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
166 bitmap_len_out, data_offset_out);
174 int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
175 int sectorsize, int alignment, int *bitmap_offset_out,
176 unsigned long *bitmap_len_out, int *data_offset_out)
181 fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
184 printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
189 err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
190 bitmap_offset_out, bitmap_len_out,
200 /* XXX Just trivial wrappers around os_read_file and os_write_file */
201 int read_ubd_fs(int fd, void *buffer, int len)
203 return(os_read_file(fd, buffer, len));
206 int write_ubd_fs(int fd, char *buffer, int len)
208 return(os_write_file(fd, buffer, len));
211 static int update_bitmap(struct io_thread_req *req)
215 if(req->cow_offset == -1)
218 n = os_seek_file(req->fds[1], req->cow_offset);
220 printk("do_io - bitmap lseek failed : err = %d\n", -n);
224 n = os_write_file(req->fds[1], &req->bitmap_words,
225 sizeof(req->bitmap_words));
226 if(n != sizeof(req->bitmap_words)){
227 printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
235 void do_io(struct io_thread_req *req)
239 int n, nsectors, start, end, bit;
243 if(req->op == UBD_MMAP){
244 /* Touch the page to force the host to do any necessary IO to
247 n = *((volatile int *) req->buffer);
248 req->error = update_bitmap(req);
252 nsectors = req->length / req->sectorsize;
255 bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
257 while((end < nsectors) &&
258 (ubd_test_bit(end, (unsigned char *)
259 &req->sector_mask) == bit))
262 off = req->offset + req->offsets[bit] +
263 start * req->sectorsize;
264 len = (end - start) * req->sectorsize;
265 buf = &req->buffer[start * req->sectorsize];
267 err = os_seek_file(req->fds[bit], off);
269 printk("do_io - lseek failed : err = %d\n", -err);
273 if(req->op == UBD_READ){
278 n = os_read_file(req->fds[bit], buf, len);
280 printk("do_io - read failed, err = %d "
281 "fd = %d\n", -n, req->fds[bit]);
285 } while((n < len) && (n != 0));
286 if (n < len) memset(&buf[n], 0, len - n);
289 n = os_write_file(req->fds[bit], buf, len);
291 printk("do_io - write failed err = %d "
292 "fd = %d\n", -n, req->fds[bit]);
299 } while(start < nsectors);
301 req->error = update_bitmap(req);
304 /* Changed in start_io_thread, which is serialized by being called only
305 * from ubd_init, which is an initcall.
309 /* Only changed by the io thread */
312 int io_thread(void *arg)
314 struct io_thread_req req;
317 signal(SIGWINCH, SIG_IGN);
319 n = os_read_file(kernel_fd, &req, sizeof(req));
320 if(n != sizeof(req)){
322 printk("io_thread - read failed, fd = %d, "
323 "err = %d\n", kernel_fd, -n);
325 printk("io_thread - short read, fd = %d, "
326 "length = %d\n", kernel_fd, n);
332 n = os_write_file(kernel_fd, &req, sizeof(req));
334 printk("io_thread - write failed, fd = %d, err = %d\n",
339 int start_io_thread(unsigned long sp, int *fd_out)
341 int pid, fds[2], err;
343 err = os_pipe(fds, 1, 1);
345 printk("start_io_thread - os_pipe failed, err = %d\n", -err);
352 pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
355 printk("start_io_thread - clone failed : errno = %d\n", errno);
362 os_close_file(fds[0]);
363 os_close_file(fds[1]);
371 * Overrides for Emacs so that we follow Linus's tabbing style.
372 * Emacs will notice this stuff at the end of the file and automatically
373 * adjust the settings for this buffer only. This must remain at the end
375 * ---------------------------------------------------------------------------
377 * c-file-style: "linux"