]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - arch/um/drivers/ubd_kern.c
[PATCH] uml: remove code controlled by non-existent config option
[mirror_ubuntu-artful-kernel.git] / arch / um / drivers / ubd_kern.c
CommitLineData
6c29256c 1/*
1da177e4
LT
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6/* 2001-09-28...2002-04-17
7 * Partition stuff by James_McMechan@hotmail.com
8 * old style ubd by setting UBD_SHIFT to 0
9 * 2002-09-27...2002-10-18 massive tinkering for 2.5
10 * partitions have changed in 2.5
11 * 2003-01-29 more tinkering for 2.5.59-1
12 * This should now address the sysfs problems and has
13 * the symlink for devfs to allow for booting with
14 * the common /dev/ubd/discX/... names rather than
15 * only /dev/ubdN/discN this version also has lots of
16 * clean ups preparing for ubd-many.
17 * James McMechan
18 */
19
20#define MAJOR_NR UBD_MAJOR
21#define UBD_SHIFT 4
22
1da177e4
LT
23#include "linux/module.h"
24#include "linux/blkdev.h"
25#include "linux/hdreg.h"
26#include "linux/init.h"
1da177e4
LT
27#include "linux/cdrom.h"
28#include "linux/proc_fs.h"
29#include "linux/ctype.h"
30#include "linux/capability.h"
31#include "linux/mm.h"
32#include "linux/vmalloc.h"
33#include "linux/blkpg.h"
34#include "linux/genhd.h"
35#include "linux/spinlock.h"
d052d1be 36#include "linux/platform_device.h"
1da177e4
LT
37#include "asm/segment.h"
38#include "asm/uaccess.h"
39#include "asm/irq.h"
40#include "asm/types.h"
41#include "asm/tlbflush.h"
42#include "user_util.h"
43#include "mem_user.h"
44#include "kern_util.h"
45#include "kern.h"
46#include "mconsole_kern.h"
47#include "init.h"
48#include "irq_user.h"
49#include "irq_kern.h"
50#include "ubd_user.h"
1da177e4
LT
51#include "os.h"
52#include "mem.h"
53#include "mem_kern.h"
54#include "cow.h"
55
7b9014c1 56enum ubd_req { UBD_READ, UBD_WRITE };
1da177e4
LT
57
58struct io_thread_req {
91acb21f 59 enum ubd_req op;
1da177e4
LT
60 int fds[2];
61 unsigned long offsets[2];
62 unsigned long long offset;
63 unsigned long length;
64 char *buffer;
65 int sectorsize;
91acb21f
JD
66 unsigned long sector_mask;
67 unsigned long long cow_offset;
68 unsigned long bitmap_words[2];
1da177e4
LT
69 int error;
70};
71
6c29256c 72extern int open_ubd_file(char *file, struct openflags *openflags, int shared,
1da177e4
LT
73 char **backing_file_out, int *bitmap_offset_out,
74 unsigned long *bitmap_len_out, int *data_offset_out,
75 int *create_cow_out);
76extern int create_cow_file(char *cow_file, char *backing_file,
77 struct openflags flags, int sectorsize,
78 int alignment, int *bitmap_offset_out,
79 unsigned long *bitmap_len_out,
80 int *data_offset_out);
81extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
91acb21f 82extern void do_io(struct io_thread_req *req);
1da177e4 83
91acb21f 84static inline int ubd_test_bit(__u64 bit, unsigned char *data)
1da177e4
LT
85{
86 __u64 n;
87 int bits, off;
88
91acb21f 89 bits = sizeof(data[0]) * 8;
1da177e4
LT
90 n = bit / bits;
91 off = bit % bits;
91acb21f 92 return((data[n] & (1 << off)) != 0);
1da177e4
LT
93}
94
91acb21f 95static inline void ubd_set_bit(__u64 bit, unsigned char *data)
1da177e4
LT
96{
97 __u64 n;
98 int bits, off;
99
91acb21f 100 bits = sizeof(data[0]) * 8;
1da177e4
LT
101 n = bit / bits;
102 off = bit % bits;
91acb21f 103 data[n] |= (1 << off);
1da177e4
LT
104}
105/*End stuff from ubd_user.h*/
106
107#define DRIVER_NAME "uml-blkdev"
108
33f775ee
PBG
109/* Can be taken in interrupt context, and is passed to the block layer to lock
110 * the request queue. Kernel side code knows that. */
1da177e4 111static DEFINE_SPINLOCK(ubd_io_lock);
d7fb2c38
PBG
112
113static DEFINE_MUTEX(ubd_lock);
1da177e4 114
2fe30a34
PBG
115/* XXX - this made sense in 2.4 days, now it's only used as a boolean, and
116 * probably it doesn't make sense even for that. */
117static int do_ubd;
91acb21f 118
1da177e4
LT
119static int ubd_open(struct inode * inode, struct file * filp);
120static int ubd_release(struct inode * inode, struct file * file);
121static int ubd_ioctl(struct inode * inode, struct file * file,
122 unsigned int cmd, unsigned long arg);
a885c8c4 123static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
1da177e4 124
97d88ac8 125#define MAX_DEV (16)
1da177e4 126
1da177e4
LT
127static struct block_device_operations ubd_blops = {
128 .owner = THIS_MODULE,
129 .open = ubd_open,
130 .release = ubd_release,
131 .ioctl = ubd_ioctl,
a885c8c4 132 .getgeo = ubd_getgeo,
1da177e4
LT
133};
134
135/* Protected by the queue_lock */
136static request_queue_t *ubd_queue;
137
138/* Protected by ubd_lock */
139static int fake_major = MAJOR_NR;
140
141static struct gendisk *ubd_gendisk[MAX_DEV];
142static struct gendisk *fake_gendisk[MAX_DEV];
6c29256c 143
1da177e4
LT
144#ifdef CONFIG_BLK_DEV_UBD_SYNC
145#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \
146 .cl = 1 })
147#else
148#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0, \
149 .cl = 1 })
150#endif
151
152/* Not protected - changed only in ubd_setup_common and then only to
153 * to enable O_SYNC.
154 */
155static struct openflags global_openflags = OPEN_FLAGS;
156
157struct cow {
2a9d32f6 158 /* backing file name */
1da177e4 159 char *file;
2a9d32f6 160 /* backing file fd */
1da177e4
LT
161 int fd;
162 unsigned long *bitmap;
163 unsigned long bitmap_len;
164 int bitmap_offset;
165 int data_offset;
166};
167
168struct ubd {
2a9d32f6
PBG
169 /* name (and fd, below) of the file opened for writing, either the
170 * backing or the cow file. */
1da177e4
LT
171 char *file;
172 int count;
173 int fd;
174 __u64 size;
175 struct openflags boot_openflags;
176 struct openflags openflags;
84e945e3
PBG
177 unsigned shared:1;
178 unsigned no_cow:1;
1da177e4
LT
179 struct cow cow;
180 struct platform_device pdev;
1da177e4
LT
181};
182
183#define DEFAULT_COW { \
184 .file = NULL, \
185 .fd = -1, \
186 .bitmap = NULL, \
187 .bitmap_offset = 0, \
188 .data_offset = 0, \
189}
190
191#define DEFAULT_UBD { \
192 .file = NULL, \
193 .count = 0, \
194 .fd = -1, \
195 .size = -1, \
196 .boot_openflags = OPEN_FLAGS, \
197 .openflags = OPEN_FLAGS, \
198 .no_cow = 0, \
6c29256c 199 .shared = 0, \
1da177e4 200 .cow = DEFAULT_COW, \
1da177e4
LT
201}
202
7d314e34 203struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
1da177e4 204
1da177e4
LT
205/* Only changed by fake_ide_setup which is a setup */
206static int fake_ide = 0;
207static struct proc_dir_entry *proc_ide_root = NULL;
208static struct proc_dir_entry *proc_ide = NULL;
209
210static void make_proc_ide(void)
211{
212 proc_ide_root = proc_mkdir("ide", NULL);
213 proc_ide = proc_mkdir("ide0", proc_ide_root);
214}
215
216static int proc_ide_read_media(char *page, char **start, off_t off, int count,
217 int *eof, void *data)
218{
219 int len;
220
221 strcpy(page, "disk\n");
222 len = strlen("disk\n");
223 len -= off;
224 if (len < count){
225 *eof = 1;
226 if (len <= 0) return 0;
227 }
228 else len = count;
229 *start = page + off;
230 return len;
231}
232
233static void make_ide_entries(char *dev_name)
234{
235 struct proc_dir_entry *dir, *ent;
236 char name[64];
237
238 if(proc_ide_root == NULL) make_proc_ide();
239
240 dir = proc_mkdir(dev_name, proc_ide);
241 if(!dir) return;
242
243 ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir);
244 if(!ent) return;
245 ent->nlink = 1;
246 ent->data = NULL;
247 ent->read_proc = proc_ide_read_media;
248 ent->write_proc = NULL;
249 sprintf(name,"ide0/%s", dev_name);
250 proc_symlink(dev_name, proc_ide_root, name);
251}
252
253static int fake_ide_setup(char *str)
254{
255 fake_ide = 1;
256 return(1);
257}
258
259__setup("fake_ide", fake_ide_setup);
260
261__uml_help(fake_ide_setup,
262"fake_ide\n"
263" Create ide0 entries that map onto ubd devices.\n\n"
264);
265
266static int parse_unit(char **ptr)
267{
268 char *str = *ptr, *end;
269 int n = -1;
270
271 if(isdigit(*str)) {
272 n = simple_strtoul(str, &end, 0);
273 if(end == str)
274 return(-1);
275 *ptr = end;
276 }
97d88ac8 277 else if (('a' <= *str) && (*str <= 'z')) {
1da177e4
LT
278 n = *str - 'a';
279 str++;
280 *ptr = str;
281 }
282 return(n);
283}
284
d8d7c28e
PBG
285/* If *index_out == -1 at exit, the passed option was a general one;
286 * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it
287 * should not be freed on exit.
288 */
f28169d2 289static int ubd_setup_common(char *str, int *index_out, char **error_out)
1da177e4 290{
7d314e34 291 struct ubd *ubd_dev;
1da177e4
LT
292 struct openflags flags = global_openflags;
293 char *backing_file;
294 int n, err, i;
295
296 if(index_out) *index_out = -1;
297 n = *str;
298 if(n == '='){
299 char *end;
300 int major;
301
302 str++;
1da177e4
LT
303 if(!strcmp(str, "sync")){
304 global_openflags = of_sync(global_openflags);
f28169d2 305 return 0;
1da177e4
LT
306 }
307 major = simple_strtoul(str, &end, 0);
308 if((*end != '\0') || (end == str)){
f28169d2
JD
309 *error_out = "Didn't parse major number";
310 return -EINVAL;
1da177e4
LT
311 }
312
f28169d2
JD
313 err = -EINVAL;
314 mutex_lock(&ubd_lock);
315 if(fake_major != MAJOR_NR){
316 *error_out = "Can't assign a fake major twice";
317 goto out1;
318 }
6c29256c 319
f28169d2 320 fake_major = major;
1da177e4
LT
321
322 printk(KERN_INFO "Setting extra ubd major number to %d\n",
323 major);
f28169d2
JD
324 err = 0;
325 out1:
326 mutex_unlock(&ubd_lock);
327 return err;
1da177e4
LT
328 }
329
330 n = parse_unit(&str);
331 if(n < 0){
f28169d2
JD
332 *error_out = "Couldn't parse device number";
333 return -EINVAL;
1da177e4
LT
334 }
335 if(n >= MAX_DEV){
f28169d2
JD
336 *error_out = "Device number out of range";
337 return 1;
1da177e4
LT
338 }
339
f28169d2 340 err = -EBUSY;
d7fb2c38 341 mutex_lock(&ubd_lock);
1da177e4 342
7d314e34
PBG
343 ubd_dev = &ubd_devs[n];
344 if(ubd_dev->file != NULL){
f28169d2 345 *error_out = "Device is already configured";
1da177e4
LT
346 goto out;
347 }
348
349 if (index_out)
350 *index_out = n;
351
f28169d2 352 err = -EINVAL;
6c29256c 353 for (i = 0; i < sizeof("rscd="); i++) {
1da177e4
LT
354 switch (*str) {
355 case 'r':
356 flags.w = 0;
357 break;
358 case 's':
359 flags.s = 1;
360 break;
361 case 'd':
7d314e34 362 ubd_dev->no_cow = 1;
1da177e4 363 break;
6c29256c 364 case 'c':
7d314e34 365 ubd_dev->shared = 1;
6c29256c 366 break;
1da177e4
LT
367 case '=':
368 str++;
369 goto break_loop;
370 default:
f28169d2
JD
371 *error_out = "Expected '=' or flag letter "
372 "(r, s, c, or d)";
1da177e4
LT
373 goto out;
374 }
375 str++;
376 }
377
f28169d2
JD
378 if (*str == '=')
379 *error_out = "Too many flags specified";
380 else
381 *error_out = "Missing '='";
1da177e4
LT
382 goto out;
383
384break_loop:
1da177e4
LT
385 backing_file = strchr(str, ',');
386
f28169d2 387 if (backing_file == NULL)
1da177e4 388 backing_file = strchr(str, ':');
1da177e4 389
f28169d2
JD
390 if(backing_file != NULL){
391 if(ubd_dev->no_cow){
392 *error_out = "Can't specify both 'd' and a cow file";
393 goto out;
394 }
1da177e4
LT
395 else {
396 *backing_file = '\0';
397 backing_file++;
398 }
399 }
f28169d2 400 err = 0;
7d314e34
PBG
401 ubd_dev->file = str;
402 ubd_dev->cow.file = backing_file;
403 ubd_dev->boot_openflags = flags;
1da177e4 404out:
d7fb2c38 405 mutex_unlock(&ubd_lock);
f28169d2 406 return err;
1da177e4
LT
407}
408
409static int ubd_setup(char *str)
410{
f28169d2
JD
411 char *error;
412 int err;
413
414 err = ubd_setup_common(str, NULL, &error);
415 if(err)
416 printk(KERN_ERR "Failed to initialize device with \"%s\" : "
417 "%s\n", str, error);
418 return 1;
1da177e4
LT
419}
420
421__setup("ubd", ubd_setup);
422__uml_help(ubd_setup,
423"ubd<n><flags>=<filename>[(:|,)<filename2>]\n"
424" This is used to associate a device with a file in the underlying\n"
425" filesystem. When specifying two filenames, the first one is the\n"
426" COW name and the second is the backing file name. As separator you can\n"
427" use either a ':' or a ',': the first one allows writing things like;\n"
428" ubd0=~/Uml/root_cow:~/Uml/root_backing_file\n"
429" while with a ',' the shell would not expand the 2nd '~'.\n"
f28169d2 430" When using only one filename, UML will detect whether to treat it like\n"
1da177e4
LT
431" a COW file or a backing file. To override this detection, add the 'd'\n"
432" flag:\n"
433" ubd0d=BackingFile\n"
434" Usually, there is a filesystem in the file, but \n"
435" that's not required. Swap devices containing swap files can be\n"
436" specified like this. Also, a file which doesn't contain a\n"
437" filesystem can have its contents read in the virtual \n"
438" machine by running 'dd' on the device. <n> must be in the range\n"
439" 0 to 7. Appending an 'r' to the number will cause that device\n"
440" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n"
441" an 's' will cause data to be written to disk on the host immediately.\n\n"
442);
443
444static int udb_setup(char *str)
445{
446 printk("udb%s specified on command line is almost certainly a ubd -> "
447 "udb TYPO\n", str);
448 return(1);
449}
450
451__setup("udb", udb_setup);
452__uml_help(udb_setup,
453"udb\n"
0894e27e
JD
454" This option is here solely to catch ubd -> udb typos, which can be\n"
455" to impossible to catch visually unless you specifically look for\n"
456" them. The only result of any option starting with 'udb' is an error\n"
1da177e4
LT
457" in the boot output.\n\n"
458);
459
460static int fakehd_set = 0;
461static int fakehd(char *str)
462{
463 printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
464 fakehd_set = 1;
465 return 1;
466}
467
468__setup("fakehd", fakehd);
469__uml_help(fakehd,
470"fakehd\n"
471" Change the ubd device name to \"hd\".\n\n"
472);
473
474static void do_ubd_request(request_queue_t * q);
91acb21f
JD
475
476/* Only changed by ubd_init, which is an initcall. */
477int thread_fd = -1;
1da177e4
LT
478
479/* Changed by ubd_handler, which is serialized because interrupts only
480 * happen on CPU 0.
d8d7c28e 481 * XXX: currently unused.
1da177e4 482 */
d8d7c28e 483static int intr_count = 0;
1da177e4 484
91acb21f
JD
485/* call ubd_finish if you need to serialize */
486static void __ubd_finish(struct request *req, int error)
1da177e4 487{
91acb21f
JD
488 int nsect;
489
490 if(error){
491 end_request(req, 0);
492 return;
1da177e4 493 }
91acb21f
JD
494 nsect = req->current_nr_sectors;
495 req->sector += nsect;
496 req->buffer += nsect << 9;
497 req->errors = 0;
498 req->nr_sectors -= nsect;
499 req->current_nr_sectors = 0;
500 end_request(req, 1);
1da177e4
LT
501}
502
33f775ee
PBG
503/* Callable only from interrupt context - otherwise you need to do
504 * spin_lock_irq()/spin_lock_irqsave() */
91acb21f 505static inline void ubd_finish(struct request *req, int error)
1da177e4 506{
91acb21f
JD
507 spin_lock(&ubd_io_lock);
508 __ubd_finish(req, error);
509 spin_unlock(&ubd_io_lock);
1da177e4
LT
510}
511
2fe30a34 512/* XXX - move this inside ubd_intr. */
33f775ee 513/* Called without ubd_io_lock held, and only in interrupt context. */
91acb21f 514static void ubd_handler(void)
1da177e4 515{
91acb21f
JD
516 struct io_thread_req req;
517 struct request *rq = elv_next_request(ubd_queue);
518 int n;
519
2fe30a34 520 do_ubd = 0;
91acb21f
JD
521 intr_count++;
522 n = os_read_file(thread_fd, &req, sizeof(req));
523 if(n != sizeof(req)){
524 printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
525 "err = %d\n", os_getpid(), -n);
526 spin_lock(&ubd_io_lock);
527 end_request(rq, 0);
528 spin_unlock(&ubd_io_lock);
529 return;
530 }
6c29256c 531
91acb21f
JD
532 ubd_finish(rq, req.error);
533 reactivate_fd(thread_fd, UBD_IRQ);
33f775ee 534 spin_lock(&ubd_io_lock);
91acb21f 535 do_ubd_request(ubd_queue);
33f775ee 536 spin_unlock(&ubd_io_lock);
1da177e4
LT
537}
538
7bea96fd 539static irqreturn_t ubd_intr(int irq, void *dev)
1da177e4 540{
91acb21f
JD
541 ubd_handler();
542 return(IRQ_HANDLED);
543}
09ace81c 544
91acb21f
JD
545/* Only changed by ubd_init, which is an initcall. */
546static int io_pid = -1;
09ace81c 547
91acb21f
JD
548void kill_io_thread(void)
549{
6c29256c 550 if(io_pid != -1)
91acb21f 551 os_kill_process(io_pid, 1);
09ace81c 552}
1da177e4 553
91acb21f
JD
554__uml_exitcall(kill_io_thread);
555
d8d7c28e 556static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
1da177e4
LT
557{
558 char *file;
559
7d314e34 560 file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
1da177e4
LT
561 return(os_file_size(file, size_out));
562}
563
5f75a4f8 564static void ubd_close_dev(struct ubd *ubd_dev)
1da177e4 565{
7d314e34
PBG
566 os_close_file(ubd_dev->fd);
567 if(ubd_dev->cow.file == NULL)
1da177e4
LT
568 return;
569
7d314e34
PBG
570 os_close_file(ubd_dev->cow.fd);
571 vfree(ubd_dev->cow.bitmap);
572 ubd_dev->cow.bitmap = NULL;
1da177e4
LT
573}
574
7d314e34 575static int ubd_open_dev(struct ubd *ubd_dev)
1da177e4
LT
576{
577 struct openflags flags;
578 char **back_ptr;
579 int err, create_cow, *create_ptr;
0bf16bff 580 int fd;
1da177e4 581
7d314e34 582 ubd_dev->openflags = ubd_dev->boot_openflags;
1da177e4 583 create_cow = 0;
7d314e34
PBG
584 create_ptr = (ubd_dev->cow.file != NULL) ? &create_cow : NULL;
585 back_ptr = ubd_dev->no_cow ? NULL : &ubd_dev->cow.file;
0bf16bff
PBG
586
587 fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared,
7d314e34
PBG
588 back_ptr, &ubd_dev->cow.bitmap_offset,
589 &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset,
6c29256c 590 create_ptr);
1da177e4 591
0bf16bff
PBG
592 if((fd == -ENOENT) && create_cow){
593 fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file,
7d314e34
PBG
594 ubd_dev->openflags, 1 << 9, PAGE_SIZE,
595 &ubd_dev->cow.bitmap_offset,
596 &ubd_dev->cow.bitmap_len,
597 &ubd_dev->cow.data_offset);
0bf16bff 598 if(fd >= 0){
1da177e4 599 printk(KERN_INFO "Creating \"%s\" as COW file for "
7d314e34 600 "\"%s\"\n", ubd_dev->file, ubd_dev->cow.file);
1da177e4
LT
601 }
602 }
603
0bf16bff 604 if(fd < 0){
7d314e34 605 printk("Failed to open '%s', errno = %d\n", ubd_dev->file,
0bf16bff
PBG
606 -fd);
607 return fd;
1da177e4 608 }
0bf16bff 609 ubd_dev->fd = fd;
1da177e4 610
7d314e34 611 if(ubd_dev->cow.file != NULL){
1da177e4 612 err = -ENOMEM;
7d314e34
PBG
613 ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len);
614 if(ubd_dev->cow.bitmap == NULL){
1da177e4
LT
615 printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
616 goto error;
617 }
618 flush_tlb_kernel_vm();
619
7d314e34
PBG
620 err = read_cow_bitmap(ubd_dev->fd, ubd_dev->cow.bitmap,
621 ubd_dev->cow.bitmap_offset,
622 ubd_dev->cow.bitmap_len);
1da177e4
LT
623 if(err < 0)
624 goto error;
625
7d314e34 626 flags = ubd_dev->openflags;
1da177e4 627 flags.w = 0;
7d314e34 628 err = open_ubd_file(ubd_dev->cow.file, &flags, ubd_dev->shared, NULL,
6c29256c 629 NULL, NULL, NULL, NULL);
1da177e4 630 if(err < 0) goto error;
7d314e34 631 ubd_dev->cow.fd = err;
1da177e4
LT
632 }
633 return(0);
634 error:
7d314e34 635 os_close_file(ubd_dev->fd);
1da177e4
LT
636 return(err);
637}
638
5f75a4f8 639static int ubd_disk_register(int major, u64 size, int unit,
1da177e4
LT
640 struct gendisk **disk_out)
641
642{
643 struct gendisk *disk;
1da177e4
LT
644
645 disk = alloc_disk(1 << UBD_SHIFT);
646 if(disk == NULL)
647 return(-ENOMEM);
648
649 disk->major = major;
650 disk->first_minor = unit << UBD_SHIFT;
651 disk->fops = &ubd_blops;
652 set_capacity(disk, size / 512);
ce7b0f46 653 if(major == MAJOR_NR)
1da177e4 654 sprintf(disk->disk_name, "ubd%c", 'a' + unit);
ce7b0f46 655 else
1da177e4 656 sprintf(disk->disk_name, "ubd_fake%d", unit);
1da177e4
LT
657
658 /* sysfs register (not for ide fake devices) */
659 if (major == MAJOR_NR) {
7d314e34
PBG
660 ubd_devs[unit].pdev.id = unit;
661 ubd_devs[unit].pdev.name = DRIVER_NAME;
662 platform_device_register(&ubd_devs[unit].pdev);
663 disk->driverfs_dev = &ubd_devs[unit].pdev.dev;
1da177e4
LT
664 }
665
7d314e34 666 disk->private_data = &ubd_devs[unit];
1da177e4
LT
667 disk->queue = ubd_queue;
668 add_disk(disk);
669
670 *disk_out = disk;
671 return 0;
672}
673
674#define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9))
675
f28169d2 676static int ubd_add(int n, char **error_out)
1da177e4 677{
7d314e34 678 struct ubd *ubd_dev = &ubd_devs[n];
f28169d2 679 int err = 0;
1da177e4 680
7d314e34 681 if(ubd_dev->file == NULL)
ec7cf783 682 goto out;
1da177e4 683
7d314e34 684 err = ubd_file_size(ubd_dev, &ubd_dev->size);
f28169d2
JD
685 if(err < 0){
686 *error_out = "Couldn't determine size of device's file";
80c13749 687 goto out;
f28169d2 688 }
1da177e4 689
7d314e34 690 ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
1da177e4 691
5f75a4f8 692 err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
6c29256c 693 if(err)
80c13749 694 goto out;
6c29256c 695
1da177e4 696 if(fake_major != MAJOR_NR)
5f75a4f8 697 ubd_disk_register(fake_major, ubd_dev->size, n,
1da177e4
LT
698 &fake_gendisk[n]);
699
700 /* perhaps this should also be under the "if (fake_major)" above */
701 /* using the fake_disk->disk_name and also the fakehd_set name */
702 if (fake_ide)
703 make_ide_entries(ubd_gendisk[n]->disk_name);
704
ec7cf783 705 err = 0;
ec7cf783
JD
706out:
707 return err;
1da177e4
LT
708}
709
f28169d2 710static int ubd_config(char *str, char **error_out)
1da177e4 711{
e7f6552f 712 int n, ret;
1da177e4 713
f28169d2
JD
714 /* This string is possibly broken up and stored, so it's only
715 * freed if ubd_setup_common fails, or if only general options
716 * were set.
717 */
970d6e3a 718 str = kstrdup(str, GFP_KERNEL);
e7f6552f 719 if (str == NULL) {
f28169d2
JD
720 *error_out = "Failed to allocate memory";
721 return -ENOMEM;
1da177e4 722 }
f28169d2
JD
723
724 ret = ubd_setup_common(str, &n, error_out);
725 if (ret)
e7f6552f 726 goto err_free;
f28169d2 727
e7f6552f
PBG
728 if (n == -1) {
729 ret = 0;
d8d7c28e 730 goto err_free;
1da177e4 731 }
1da177e4 732
d7fb2c38 733 mutex_lock(&ubd_lock);
f28169d2 734 ret = ubd_add(n, error_out);
e7f6552f 735 if (ret)
7d314e34 736 ubd_devs[n].file = NULL;
d7fb2c38 737 mutex_unlock(&ubd_lock);
1da177e4 738
e7f6552f
PBG
739out:
740 return ret;
741
742err_free:
743 kfree(str);
744 goto out;
1da177e4
LT
745}
746
747static int ubd_get_config(char *name, char *str, int size, char **error_out)
748{
7d314e34 749 struct ubd *ubd_dev;
1da177e4
LT
750 int n, len = 0;
751
752 n = parse_unit(&name);
753 if((n >= MAX_DEV) || (n < 0)){
754 *error_out = "ubd_get_config : device number out of range";
755 return(-1);
756 }
757
7d314e34 758 ubd_dev = &ubd_devs[n];
d7fb2c38 759 mutex_lock(&ubd_lock);
1da177e4 760
7d314e34 761 if(ubd_dev->file == NULL){
1da177e4
LT
762 CONFIG_CHUNK(str, size, len, "", 1);
763 goto out;
764 }
765
7d314e34 766 CONFIG_CHUNK(str, size, len, ubd_dev->file, 0);
1da177e4 767
7d314e34 768 if(ubd_dev->cow.file != NULL){
1da177e4 769 CONFIG_CHUNK(str, size, len, ",", 0);
7d314e34 770 CONFIG_CHUNK(str, size, len, ubd_dev->cow.file, 1);
1da177e4
LT
771 }
772 else CONFIG_CHUNK(str, size, len, "", 1);
773
774 out:
d7fb2c38 775 mutex_unlock(&ubd_lock);
1da177e4
LT
776 return(len);
777}
778
29d56cfe
JD
779static int ubd_id(char **str, int *start_out, int *end_out)
780{
781 int n;
782
783 n = parse_unit(str);
784 *start_out = 0;
785 *end_out = MAX_DEV - 1;
786 return n;
787}
788
f28169d2 789static int ubd_remove(int n, char **error_out)
1da177e4 790{
7d314e34 791 struct ubd *ubd_dev;
29d56cfe 792 int err = -ENODEV;
1da177e4 793
d7fb2c38 794 mutex_lock(&ubd_lock);
1da177e4 795
29d56cfe
JD
796 if(ubd_gendisk[n] == NULL)
797 goto out;
1da177e4 798
7d314e34 799 ubd_dev = &ubd_devs[n];
1da177e4 800
7d314e34 801 if(ubd_dev->file == NULL)
29d56cfe 802 goto out;
1da177e4 803
29d56cfe
JD
804 /* you cannot remove a open disk */
805 err = -EBUSY;
7d314e34 806 if(ubd_dev->count > 0)
1da177e4
LT
807 goto out;
808
809 del_gendisk(ubd_gendisk[n]);
810 put_disk(ubd_gendisk[n]);
811 ubd_gendisk[n] = NULL;
812
813 if(fake_gendisk[n] != NULL){
814 del_gendisk(fake_gendisk[n]);
815 put_disk(fake_gendisk[n]);
816 fake_gendisk[n] = NULL;
817 }
818
7d314e34
PBG
819 platform_device_unregister(&ubd_dev->pdev);
820 *ubd_dev = ((struct ubd) DEFAULT_UBD);
1da177e4 821 err = 0;
29d56cfe 822out:
d7fb2c38 823 mutex_unlock(&ubd_lock);
29d56cfe 824 return err;
1da177e4
LT
825}
826
f28169d2
JD
827/* All these are called by mconsole in process context and without
828 * ubd-specific locks.
829 */
1da177e4 830static struct mc_device ubd_mc = {
84f48d4f 831 .list = LIST_HEAD_INIT(ubd_mc.list),
1da177e4
LT
832 .name = "ubd",
833 .config = ubd_config,
834 .get_config = ubd_get_config,
29d56cfe 835 .id = ubd_id,
1da177e4
LT
836 .remove = ubd_remove,
837};
838
d8d7c28e 839static int __init ubd_mc_init(void)
1da177e4
LT
840{
841 mconsole_register_dev(&ubd_mc);
842 return 0;
843}
844
845__initcall(ubd_mc_init);
846
d8d7c28e
PBG
847static int __init ubd0_init(void)
848{
849 struct ubd *ubd_dev = &ubd_devs[0];
850
851 if(ubd_dev->file == NULL)
852 ubd_dev->file = "root_fs";
853 return(0);
854}
855
856__initcall(ubd0_init);
857
3ae5eaec
RK
858static struct platform_driver ubd_driver = {
859 .driver = {
860 .name = DRIVER_NAME,
861 },
1da177e4
LT
862};
863
d8d7c28e 864static int __init ubd_init(void)
1da177e4 865{
f28169d2
JD
866 char *error;
867 int i, err;
1da177e4 868
1da177e4
LT
869 if (register_blkdev(MAJOR_NR, "ubd"))
870 return -1;
871
872 ubd_queue = blk_init_queue(do_ubd_request, &ubd_io_lock);
873 if (!ubd_queue) {
874 unregister_blkdev(MAJOR_NR, "ubd");
875 return -1;
876 }
877
878 if (fake_major != MAJOR_NR) {
879 char name[sizeof("ubd_nnn\0")];
880
881 snprintf(name, sizeof(name), "ubd_%d", fake_major);
1da177e4
LT
882 if (register_blkdev(fake_major, "ubd"))
883 return -1;
884 }
3ae5eaec 885 platform_driver_register(&ubd_driver);
f28169d2
JD
886 for (i = 0; i < MAX_DEV; i++){
887 err = ubd_add(i, &error);
888 if(err)
889 printk(KERN_ERR "Failed to initialize ubd device %d :"
890 "%s\n", i, error);
891 }
1da177e4
LT
892 return 0;
893}
894
895late_initcall(ubd_init);
896
d8d7c28e 897static int __init ubd_driver_init(void){
91acb21f
JD
898 unsigned long stack;
899 int err;
900
901 /* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/
902 if(global_openflags.s){
903 printk(KERN_INFO "ubd: Synchronous mode\n");
904 /* Letting ubd=sync be like using ubd#s= instead of ubd#= is
905 * enough. So use anyway the io thread. */
906 }
907 stack = alloc_stack(0, 0);
6c29256c 908 io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
91acb21f
JD
909 &thread_fd);
910 if(io_pid < 0){
6c29256c 911 printk(KERN_ERR
91acb21f
JD
912 "ubd : Failed to start I/O thread (errno = %d) - "
913 "falling back to synchronous I/O\n", -io_pid);
914 io_pid = -1;
915 return(0);
916 }
6c29256c 917 err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
7d314e34 918 IRQF_DISABLED, "ubd", ubd_devs);
91acb21f
JD
919 if(err != 0)
920 printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
f4c57a78 921 return 0;
91acb21f
JD
922}
923
924device_initcall(ubd_driver_init);
925
1da177e4
LT
926static int ubd_open(struct inode *inode, struct file *filp)
927{
928 struct gendisk *disk = inode->i_bdev->bd_disk;
7d314e34 929 struct ubd *ubd_dev = disk->private_data;
1da177e4
LT
930 int err = 0;
931
7d314e34
PBG
932 if(ubd_dev->count == 0){
933 err = ubd_open_dev(ubd_dev);
1da177e4
LT
934 if(err){
935 printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
7d314e34 936 disk->disk_name, ubd_dev->file, -err);
1da177e4
LT
937 goto out;
938 }
939 }
7d314e34
PBG
940 ubd_dev->count++;
941 set_disk_ro(disk, !ubd_dev->openflags.w);
2c49be99
PBG
942
943 /* This should no more be needed. And it didn't work anyway to exclude
944 * read-write remounting of filesystems.*/
7d314e34 945 /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){
5f75a4f8 946 if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev);
1da177e4 947 err = -EROFS;
2c49be99 948 }*/
1da177e4
LT
949 out:
950 return(err);
951}
952
953static int ubd_release(struct inode * inode, struct file * file)
954{
955 struct gendisk *disk = inode->i_bdev->bd_disk;
7d314e34 956 struct ubd *ubd_dev = disk->private_data;
1da177e4 957
7d314e34 958 if(--ubd_dev->count == 0)
5f75a4f8 959 ubd_close_dev(ubd_dev);
1da177e4
LT
960 return(0);
961}
962
91acb21f
JD
963static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
964 __u64 *cow_offset, unsigned long *bitmap,
965 __u64 bitmap_offset, unsigned long *bitmap_words,
966 __u64 bitmap_len)
1da177e4 967{
91acb21f
JD
968 __u64 sector = io_offset >> 9;
969 int i, update_bitmap = 0;
970
971 for(i = 0; i < length >> 9; i++){
972 if(cow_mask != NULL)
973 ubd_set_bit(i, (unsigned char *) cow_mask);
974 if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
975 continue;
1da177e4 976
91acb21f
JD
977 update_bitmap = 1;
978 ubd_set_bit(sector + i, (unsigned char *) bitmap);
979 }
980
981 if(!update_bitmap)
982 return;
1da177e4 983
91acb21f 984 *cow_offset = sector / (sizeof(unsigned long) * 8);
1da177e4 985
91acb21f
JD
986 /* This takes care of the case where we're exactly at the end of the
987 * device, and *cow_offset + 1 is off the end. So, just back it up
988 * by one word. Thanks to Lynn Kerby for the fix and James McMechan
989 * for the original diagnosis.
990 */
991 if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
992 sizeof(unsigned long) - 1))
993 (*cow_offset)--;
994
995 bitmap_words[0] = bitmap[*cow_offset];
996 bitmap_words[1] = bitmap[*cow_offset + 1];
997
998 *cow_offset *= sizeof(unsigned long);
999 *cow_offset += bitmap_offset;
1000}
1001
1002static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
1003 __u64 bitmap_offset, __u64 bitmap_len)
1004{
1005 __u64 sector = req->offset >> 9;
1006 int i;
1007
1008 if(req->length > (sizeof(req->sector_mask) * 8) << 9)
1009 panic("Operation too long");
1010
1011 if(req->op == UBD_READ) {
1012 for(i = 0; i < req->length >> 9; i++){
1013 if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
6c29256c 1014 ubd_set_bit(i, (unsigned char *)
91acb21f
JD
1015 &req->sector_mask);
1016 }
1017 }
1018 else cowify_bitmap(req->offset, req->length, &req->sector_mask,
1019 &req->cow_offset, bitmap, bitmap_offset,
1020 req->bitmap_words, bitmap_len);
1da177e4
LT
1021}
1022
1da177e4 1023/* Called with ubd_io_lock held */
91acb21f 1024static int prepare_request(struct request *req, struct io_thread_req *io_req)
1da177e4
LT
1025{
1026 struct gendisk *disk = req->rq_disk;
7d314e34 1027 struct ubd *ubd_dev = disk->private_data;
91acb21f
JD
1028 __u64 offset;
1029 int len;
1030
2c49be99 1031 /* This should be impossible now */
7d314e34 1032 if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){
6c29256c 1033 printk("Write attempted on readonly ubd device %s\n",
1da177e4 1034 disk->disk_name);
91acb21f 1035 end_request(req, 0);
1da177e4
LT
1036 return(1);
1037 }
1038
91acb21f
JD
1039 offset = ((__u64) req->sector) << 9;
1040 len = req->current_nr_sectors << 9;
1041
7d314e34
PBG
1042 io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd;
1043 io_req->fds[1] = ubd_dev->fd;
91acb21f 1044 io_req->cow_offset = -1;
1da177e4
LT
1045 io_req->offset = offset;
1046 io_req->length = len;
1047 io_req->error = 0;
91acb21f
JD
1048 io_req->sector_mask = 0;
1049
1050 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
1da177e4 1051 io_req->offsets[0] = 0;
7d314e34 1052 io_req->offsets[1] = ubd_dev->cow.data_offset;
91acb21f 1053 io_req->buffer = req->buffer;
1da177e4
LT
1054 io_req->sectorsize = 1 << 9;
1055
7d314e34
PBG
1056 if(ubd_dev->cow.file != NULL)
1057 cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset,
1058 ubd_dev->cow.bitmap_len);
91acb21f 1059
1da177e4
LT
1060 return(0);
1061}
1062
1063/* Called with ubd_io_lock held */
1064static void do_ubd_request(request_queue_t *q)
1065{
1066 struct io_thread_req io_req;
1067 struct request *req;
91acb21f
JD
1068 int err, n;
1069
1070 if(thread_fd == -1){
1071 while((req = elv_next_request(q)) != NULL){
1072 err = prepare_request(req, &io_req);
1073 if(!err){
1074 do_io(&io_req);
1075 __ubd_finish(req, io_req.error);
1076 }
1077 }
1078 }
1079 else {
1080 if(do_ubd || (req = elv_next_request(q)) == NULL)
1081 return;
1082 err = prepare_request(req, &io_req);
1083 if(!err){
2fe30a34 1084 do_ubd = 1;
91acb21f
JD
1085 n = os_write_file(thread_fd, (char *) &io_req,
1086 sizeof(io_req));
1087 if(n != sizeof(io_req))
1088 printk("write to io thread failed, "
1089 "errno = %d\n", -n);
1da177e4
LT
1090 }
1091 }
1092}
1093
a885c8c4
CH
1094static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1095{
7d314e34 1096 struct ubd *ubd_dev = bdev->bd_disk->private_data;
a885c8c4
CH
1097
1098 geo->heads = 128;
1099 geo->sectors = 32;
7d314e34 1100 geo->cylinders = ubd_dev->size / (128 * 32 * 512);
a885c8c4
CH
1101 return 0;
1102}
1103
1da177e4
LT
1104static int ubd_ioctl(struct inode * inode, struct file * file,
1105 unsigned int cmd, unsigned long arg)
1106{
7d314e34 1107 struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data;
1da177e4
LT
1108 struct hd_driveid ubd_id = {
1109 .cyls = 0,
1110 .heads = 128,
1111 .sectors = 32,
1112 };
1113
1114 switch (cmd) {
1da177e4 1115 struct cdrom_volctrl volume;
1da177e4 1116 case HDIO_GET_IDENTITY:
7d314e34 1117 ubd_id.cyls = ubd_dev->size / (128 * 32 * 512);
1da177e4
LT
1118 if(copy_to_user((char __user *) arg, (char *) &ubd_id,
1119 sizeof(ubd_id)))
1120 return(-EFAULT);
1121 return(0);
1122
1123 case CDROMVOLREAD:
1124 if(copy_from_user(&volume, (char __user *) arg, sizeof(volume)))
1125 return(-EFAULT);
1126 volume.channel0 = 255;
1127 volume.channel1 = 255;
1128 volume.channel2 = 255;
1129 volume.channel3 = 255;
1130 if(copy_to_user((char __user *) arg, &volume, sizeof(volume)))
1131 return(-EFAULT);
1132 return(0);
1133 }
1134 return(-EINVAL);
1135}
1136
4833aff7 1137static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
1da177e4
LT
1138{
1139 struct uml_stat buf1, buf2;
1140 int err;
1141
4833aff7
PBG
1142 if(from_cmdline == NULL)
1143 return 0;
1144 if(!strcmp(from_cmdline, from_cow))
1145 return 0;
1da177e4
LT
1146
1147 err = os_stat_file(from_cmdline, &buf1);
1148 if(err < 0){
1149 printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
4833aff7 1150 return 0;
1da177e4
LT
1151 }
1152 err = os_stat_file(from_cow, &buf2);
1153 if(err < 0){
1154 printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
4833aff7 1155 return 1;
1da177e4
LT
1156 }
1157 if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
4833aff7 1158 return 0;
1da177e4
LT
1159
1160 printk("Backing file mismatch - \"%s\" requested,\n"
1161 "\"%s\" specified in COW header of \"%s\"\n",
1162 from_cmdline, from_cow, cow);
4833aff7 1163 return 1;
1da177e4
LT
1164}
1165
1166static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
1167{
1168 unsigned long modtime;
fe1db50c 1169 unsigned long long actual;
1da177e4
LT
1170 int err;
1171
1172 err = os_file_modtime(file, &modtime);
1173 if(err < 0){
1174 printk("Failed to get modification time of backing file "
1175 "\"%s\", err = %d\n", file, -err);
1176 return(err);
1177 }
1178
1179 err = os_file_size(file, &actual);
1180 if(err < 0){
1181 printk("Failed to get size of backing file \"%s\", "
1182 "err = %d\n", file, -err);
1183 return(err);
1184 }
1185
1186 if(actual != size){
1187 /*__u64 can be a long on AMD64 and with %lu GCC complains; so
1188 * the typecast.*/
1189 printk("Size mismatch (%llu vs %llu) of COW header vs backing "
1190 "file\n", (unsigned long long) size, actual);
1191 return(-EINVAL);
1192 }
1193 if(modtime != mtime){
1194 printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
1195 "file\n", mtime, modtime);
1196 return(-EINVAL);
1197 }
1198 return(0);
1199}
1200
1201int read_cow_bitmap(int fd, void *buf, int offset, int len)
1202{
1203 int err;
1204
1205 err = os_seek_file(fd, offset);
1206 if(err < 0)
1207 return(err);
1208
1209 err = os_read_file(fd, buf, len);
1210 if(err < 0)
1211 return(err);
1212
1213 return(0);
1214}
1215
6c29256c 1216int open_ubd_file(char *file, struct openflags *openflags, int shared,
1da177e4
LT
1217 char **backing_file_out, int *bitmap_offset_out,
1218 unsigned long *bitmap_len_out, int *data_offset_out,
1219 int *create_cow_out)
1220{
1221 time_t mtime;
1222 unsigned long long size;
1223 __u32 version, align;
1224 char *backing_file;
4833aff7 1225 int fd, err, sectorsize, asked_switch, mode = 0644;
1da177e4
LT
1226
1227 fd = os_open_file(file, *openflags, mode);
a374a48f
PBG
1228 if (fd < 0) {
1229 if ((fd == -ENOENT) && (create_cow_out != NULL))
1da177e4 1230 *create_cow_out = 1;
a374a48f
PBG
1231 if (!openflags->w ||
1232 ((fd != -EROFS) && (fd != -EACCES)))
1233 return fd;
1da177e4
LT
1234 openflags->w = 0;
1235 fd = os_open_file(file, *openflags, mode);
a374a48f
PBG
1236 if (fd < 0)
1237 return fd;
1da177e4
LT
1238 }
1239
6c29256c
JD
1240 if(shared)
1241 printk("Not locking \"%s\" on the host\n", file);
1242 else {
1243 err = os_lock_file(fd, openflags->w);
1244 if(err < 0){
1245 printk("Failed to lock '%s', err = %d\n", file, -err);
1246 goto out_close;
1247 }
1da177e4
LT
1248 }
1249
d6e05edc 1250 /* Successful return case! */
a374a48f
PBG
1251 if(backing_file_out == NULL)
1252 return(fd);
1da177e4
LT
1253
1254 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
1255 &size, &sectorsize, &align, bitmap_offset_out);
1256 if(err && (*backing_file_out != NULL)){
1257 printk("Failed to read COW header from COW file \"%s\", "
1258 "errno = %d\n", file, -err);
1259 goto out_close;
1260 }
a374a48f
PBG
1261 if(err)
1262 return(fd);
1da177e4 1263
4833aff7 1264 asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
1da177e4 1265
4833aff7
PBG
1266 /* Allow switching only if no mismatch. */
1267 if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) {
1da177e4
LT
1268 printk("Switching backing file to '%s'\n", *backing_file_out);
1269 err = write_cow_header(file, fd, *backing_file_out,
1270 sectorsize, align, &size);
a374a48f 1271 if (err) {
1da177e4 1272 printk("Switch failed, errno = %d\n", -err);
4833aff7 1273 goto out_close;
1da177e4 1274 }
a374a48f 1275 } else {
1da177e4
LT
1276 *backing_file_out = backing_file;
1277 err = backing_file_mismatch(*backing_file_out, size, mtime);
a374a48f
PBG
1278 if (err)
1279 goto out_close;
1da177e4
LT
1280 }
1281
1282 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
1283 bitmap_len_out, data_offset_out);
1284
a374a48f 1285 return fd;
1da177e4
LT
1286 out_close:
1287 os_close_file(fd);
a374a48f 1288 return err;
1da177e4
LT
1289}
1290
1291int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
1292 int sectorsize, int alignment, int *bitmap_offset_out,
1293 unsigned long *bitmap_len_out, int *data_offset_out)
1294{
1295 int err, fd;
1296
1297 flags.c = 1;
6c29256c 1298 fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL);
1da177e4
LT
1299 if(fd < 0){
1300 err = fd;
1301 printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
1302 -err);
1303 goto out;
1304 }
1305
1306 err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
1307 bitmap_offset_out, bitmap_len_out,
1308 data_offset_out);
1309 if(!err)
1310 return(fd);
1311 os_close_file(fd);
1312 out:
1313 return(err);
1314}
1315
91acb21f 1316static int update_bitmap(struct io_thread_req *req)
1da177e4 1317{
91acb21f 1318 int n;
1da177e4 1319
91acb21f
JD
1320 if(req->cow_offset == -1)
1321 return(0);
1da177e4 1322
91acb21f
JD
1323 n = os_seek_file(req->fds[1], req->cow_offset);
1324 if(n < 0){
1325 printk("do_io - bitmap lseek failed : err = %d\n", -n);
1326 return(1);
1327 }
1da177e4 1328
91acb21f
JD
1329 n = os_write_file(req->fds[1], &req->bitmap_words,
1330 sizeof(req->bitmap_words));
1331 if(n != sizeof(req->bitmap_words)){
1332 printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
1333 req->fds[1]);
1334 return(1);
1335 }
1da177e4 1336
91acb21f
JD
1337 return(0);
1338}
1da177e4 1339
91acb21f
JD
1340void do_io(struct io_thread_req *req)
1341{
1342 char *buf;
1343 unsigned long len;
1344 int n, nsectors, start, end, bit;
1345 int err;
1346 __u64 off;
1347
1348 nsectors = req->length / req->sectorsize;
1349 start = 0;
1350 do {
1351 bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
1352 end = start;
1353 while((end < nsectors) &&
1354 (ubd_test_bit(end, (unsigned char *)
1355 &req->sector_mask) == bit))
1356 end++;
1357
1358 off = req->offset + req->offsets[bit] +
1359 start * req->sectorsize;
1360 len = (end - start) * req->sectorsize;
1361 buf = &req->buffer[start * req->sectorsize];
1362
1363 err = os_seek_file(req->fds[bit], off);
1364 if(err < 0){
1365 printk("do_io - lseek failed : err = %d\n", -err);
1366 req->error = 1;
1367 return;
1368 }
1369 if(req->op == UBD_READ){
1370 n = 0;
1371 do {
1372 buf = &buf[n];
1373 len -= n;
1374 n = os_read_file(req->fds[bit], buf, len);
1375 if (n < 0) {
1376 printk("do_io - read failed, err = %d "
1377 "fd = %d\n", -n, req->fds[bit]);
1378 req->error = 1;
1379 return;
1380 }
1381 } while((n < len) && (n != 0));
1382 if (n < len) memset(&buf[n], 0, len - n);
1383 } else {
1384 n = os_write_file(req->fds[bit], buf, len);
1385 if(n != len){
1386 printk("do_io - write failed err = %d "
1387 "fd = %d\n", -n, req->fds[bit]);
1388 req->error = 1;
1389 return;
1390 }
1391 }
1392
1393 start = end;
1394 } while(start < nsectors);
1da177e4 1395
91acb21f 1396 req->error = update_bitmap(req);
1da177e4 1397}
91acb21f
JD
1398
1399/* Changed in start_io_thread, which is serialized by being called only
1400 * from ubd_init, which is an initcall.
1401 */
1402int kernel_fd = -1;
1403
d8d7c28e
PBG
1404/* Only changed by the io thread. XXX: currently unused. */
1405static int io_count = 0;
91acb21f
JD
1406
1407int io_thread(void *arg)
1408{
1409 struct io_thread_req req;
1410 int n;
1411
1412 ignore_sigwinch_sig();
1413 while(1){
1414 n = os_read_file(kernel_fd, &req, sizeof(req));
1415 if(n != sizeof(req)){
1416 if(n < 0)
1417 printk("io_thread - read failed, fd = %d, "
1418 "err = %d\n", kernel_fd, -n);
1419 else {
1420 printk("io_thread - short read, fd = %d, "
1421 "length = %d\n", kernel_fd, n);
1422 }
1423 continue;
1424 }
1425 io_count++;
1426 do_io(&req);
1427 n = os_write_file(kernel_fd, &req, sizeof(req));
1428 if(n != sizeof(req))
1429 printk("io_thread - write failed, fd = %d, err = %d\n",
1430 kernel_fd, -n);
1431 }
91acb21f 1432
1b57e9c2
JD
1433 return 0;
1434}