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
);
360 os_close_file(fds
[0]);
361 os_close_file(fds
[1]);
369 * Overrides for Emacs so that we follow Linus's tabbing style.
370 * Emacs will notice this stuff at the end of the file and automatically
371 * adjust the settings for this buffer only. This must remain at the end
373 * ---------------------------------------------------------------------------
375 * c-file-style: "linux"