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_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
50 printk("Backing file mismatch - \"%s\" requested,\n"
51 "\"%s\" specified in COW header of \"%s\"\n",
52 from_cmdline, from_cow, cow);
56 static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
58 unsigned long modtime;
62 err = os_file_modtime(file, &modtime);
64 printk("Failed to get modification time of backing file "
65 "\"%s\", err = %d\n", file, -err);
69 err = os_file_size(file, &actual);
71 printk("Failed to get size of backing file \"%s\", "
72 "err = %d\n", file, -err);
77 printk("Size mismatch (%ld vs %ld) of COW header vs backing "
78 "file\n", size, actual);
82 printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
83 "file\n", mtime, modtime);
89 int read_cow_bitmap(int fd, void *buf, int offset, int len)
93 err = os_seek_file(fd, offset);
97 err = os_read_file(fd, buf, len);
104 int open_ubd_file(char *file, struct openflags *openflags,
105 char **backing_file_out, int *bitmap_offset_out,
106 unsigned long *bitmap_len_out, int *data_offset_out,
111 __u32 version, align;
113 int fd, err, sectorsize, same, mode = 0644;
115 fd = os_open_file(file, *openflags, mode);
117 if((fd == -ENOENT) && (create_cow_out != NULL))
120 ((errno != EROFS) && (errno != EACCES))) return(-errno);
122 fd = os_open_file(file, *openflags, mode);
127 err = os_lock_file(fd, openflags->w);
129 printk("Failed to lock '%s', err = %d\n", file, -err);
133 if(backing_file_out == NULL) return(fd);
135 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
136 &size, §orsize, &align, bitmap_offset_out);
137 if(err && (*backing_file_out != NULL)){
138 printk("Failed to read COW header from COW file \"%s\", "
139 "errno = %d\n", file, -err);
144 if(backing_file_out == NULL) return(fd);
146 same = same_backing_files(*backing_file_out, backing_file, file);
148 if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
149 printk("Switching backing file to '%s'\n", *backing_file_out);
150 err = write_cow_header(file, fd, *backing_file_out,
151 sectorsize, align, &size);
153 printk("Switch failed, errno = %d\n", -err);
158 *backing_file_out = backing_file;
159 err = backing_file_mismatch(*backing_file_out, size, mtime);
160 if(err) goto out_close;
163 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
164 bitmap_len_out, data_offset_out);
172 int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
173 int sectorsize, int alignment, int *bitmap_offset_out,
174 unsigned long *bitmap_len_out, int *data_offset_out)
179 fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
182 printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
187 err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
188 bitmap_offset_out, bitmap_len_out,
197 /* XXX Just trivial wrappers around os_read_file and os_write_file */
198 int read_ubd_fs(int fd, void *buffer, int len)
200 return(os_read_file(fd, buffer, len));
203 int write_ubd_fs(int fd, char *buffer, int len)
205 return(os_write_file(fd, buffer, len));
208 static int update_bitmap(struct io_thread_req *req)
212 if(req->cow_offset == -1)
215 n = os_seek_file(req->fds[1], req->cow_offset);
217 printk("do_io - bitmap lseek failed : err = %d\n", -n);
221 n = os_write_file(req->fds[1], &req->bitmap_words,
222 sizeof(req->bitmap_words));
223 if(n != sizeof(req->bitmap_words)){
224 printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
232 void do_io(struct io_thread_req *req)
236 int n, nsectors, start, end, bit;
240 if(req->op == UBD_MMAP){
241 /* Touch the page to force the host to do any necessary IO to
244 n = *((volatile int *) req->buffer);
245 req->error = update_bitmap(req);
249 nsectors = req->length / req->sectorsize;
252 bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
254 while((end < nsectors) &&
255 (ubd_test_bit(end, (unsigned char *)
256 &req->sector_mask) == bit))
259 off = req->offset + req->offsets[bit] +
260 start * req->sectorsize;
261 len = (end - start) * req->sectorsize;
262 buf = &req->buffer[start * req->sectorsize];
264 err = os_seek_file(req->fds[bit], off);
266 printk("do_io - lseek failed : err = %d\n", -err);
270 if(req->op == UBD_READ){
275 n = os_read_file(req->fds[bit], buf, len);
277 printk("do_io - read failed, err = %d "
278 "fd = %d\n", -n, req->fds[bit]);
282 } while((n < len) && (n != 0));
283 if (n < len) memset(&buf[n], 0, len - n);
286 n = os_write_file(req->fds[bit], buf, len);
288 printk("do_io - write failed err = %d "
289 "fd = %d\n", -n, req->fds[bit]);
296 } while(start < nsectors);
298 req->error = update_bitmap(req);
301 /* Changed in start_io_thread, which is serialized by being called only
302 * from ubd_init, which is an initcall.
306 /* Only changed by the io thread */
309 int io_thread(void *arg)
311 struct io_thread_req req;
314 signal(SIGWINCH, SIG_IGN);
316 n = os_read_file(kernel_fd, &req, sizeof(req));
317 if(n != sizeof(req)){
319 printk("io_thread - read failed, fd = %d, "
320 "err = %d\n", kernel_fd, -n);
322 printk("io_thread - short read, fd = %d, "
323 "length = %d\n", kernel_fd, n);
329 n = os_write_file(kernel_fd, &req, sizeof(req));
331 printk("io_thread - write failed, fd = %d, err = %d\n",
336 int start_io_thread(unsigned long sp, int *fd_out)
338 int pid, fds[2], err;
340 err = os_pipe(fds, 1, 1);
342 printk("start_io_thread - os_pipe failed, err = %d\n", -err);
349 pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
352 printk("start_io_thread - clone failed : errno = %d\n", errno);
359 os_close_file(fds[0]);
360 os_close_file(fds[1]);
368 * Overrides for Emacs so that we follow Linus's tabbing style.
369 * Emacs will notice this stuff at the end of the file and automatically
370 * adjust the settings for this buffer only. This must remain at the end
372 * ---------------------------------------------------------------------------
374 * c-file-style: "linux"