]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - arch/um/drivers/ubd_kern.c
[PATCH] uml: audio driver formatting
[mirror_ubuntu-zesty-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
LT
830static struct mc_device ubd_mc = {
831 .name = "ubd",
832 .config = ubd_config,
833 .get_config = ubd_get_config,
29d56cfe 834 .id = ubd_id,
1da177e4
LT
835 .remove = ubd_remove,
836};
837
d8d7c28e 838static int __init ubd_mc_init(void)
1da177e4
LT
839{
840 mconsole_register_dev(&ubd_mc);
841 return 0;
842}
843
844__initcall(ubd_mc_init);
845
d8d7c28e
PBG
846static int __init ubd0_init(void)
847{
848 struct ubd *ubd_dev = &ubd_devs[0];
849
850 if(ubd_dev->file == NULL)
851 ubd_dev->file = "root_fs";
852 return(0);
853}
854
855__initcall(ubd0_init);
856
3ae5eaec
RK
857static struct platform_driver ubd_driver = {
858 .driver = {
859 .name = DRIVER_NAME,
860 },
1da177e4
LT
861};
862
d8d7c28e 863static int __init ubd_init(void)
1da177e4 864{
f28169d2
JD
865 char *error;
866 int i, err;
1da177e4 867
1da177e4
LT
868 if (register_blkdev(MAJOR_NR, "ubd"))
869 return -1;
870
871 ubd_queue = blk_init_queue(do_ubd_request, &ubd_io_lock);
872 if (!ubd_queue) {
873 unregister_blkdev(MAJOR_NR, "ubd");
874 return -1;
875 }
876
877 if (fake_major != MAJOR_NR) {
878 char name[sizeof("ubd_nnn\0")];
879
880 snprintf(name, sizeof(name), "ubd_%d", fake_major);
1da177e4
LT
881 if (register_blkdev(fake_major, "ubd"))
882 return -1;
883 }
3ae5eaec 884 platform_driver_register(&ubd_driver);
f28169d2
JD
885 for (i = 0; i < MAX_DEV; i++){
886 err = ubd_add(i, &error);
887 if(err)
888 printk(KERN_ERR "Failed to initialize ubd device %d :"
889 "%s\n", i, error);
890 }
1da177e4
LT
891 return 0;
892}
893
894late_initcall(ubd_init);
895
d8d7c28e 896static int __init ubd_driver_init(void){
91acb21f
JD
897 unsigned long stack;
898 int err;
899
900 /* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/
901 if(global_openflags.s){
902 printk(KERN_INFO "ubd: Synchronous mode\n");
903 /* Letting ubd=sync be like using ubd#s= instead of ubd#= is
904 * enough. So use anyway the io thread. */
905 }
906 stack = alloc_stack(0, 0);
6c29256c 907 io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
91acb21f
JD
908 &thread_fd);
909 if(io_pid < 0){
6c29256c 910 printk(KERN_ERR
91acb21f
JD
911 "ubd : Failed to start I/O thread (errno = %d) - "
912 "falling back to synchronous I/O\n", -io_pid);
913 io_pid = -1;
914 return(0);
915 }
6c29256c 916 err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
7d314e34 917 IRQF_DISABLED, "ubd", ubd_devs);
91acb21f
JD
918 if(err != 0)
919 printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
f4c57a78 920 return 0;
91acb21f
JD
921}
922
923device_initcall(ubd_driver_init);
924
1da177e4
LT
925static int ubd_open(struct inode *inode, struct file *filp)
926{
927 struct gendisk *disk = inode->i_bdev->bd_disk;
7d314e34 928 struct ubd *ubd_dev = disk->private_data;
1da177e4
LT
929 int err = 0;
930
7d314e34
PBG
931 if(ubd_dev->count == 0){
932 err = ubd_open_dev(ubd_dev);
1da177e4
LT
933 if(err){
934 printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
7d314e34 935 disk->disk_name, ubd_dev->file, -err);
1da177e4
LT
936 goto out;
937 }
938 }
7d314e34
PBG
939 ubd_dev->count++;
940 set_disk_ro(disk, !ubd_dev->openflags.w);
2c49be99
PBG
941
942 /* This should no more be needed. And it didn't work anyway to exclude
943 * read-write remounting of filesystems.*/
7d314e34 944 /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){
5f75a4f8 945 if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev);
1da177e4 946 err = -EROFS;
2c49be99 947 }*/
1da177e4
LT
948 out:
949 return(err);
950}
951
952static int ubd_release(struct inode * inode, struct file * file)
953{
954 struct gendisk *disk = inode->i_bdev->bd_disk;
7d314e34 955 struct ubd *ubd_dev = disk->private_data;
1da177e4 956
7d314e34 957 if(--ubd_dev->count == 0)
5f75a4f8 958 ubd_close_dev(ubd_dev);
1da177e4
LT
959 return(0);
960}
961
91acb21f
JD
962static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
963 __u64 *cow_offset, unsigned long *bitmap,
964 __u64 bitmap_offset, unsigned long *bitmap_words,
965 __u64 bitmap_len)
1da177e4 966{
91acb21f
JD
967 __u64 sector = io_offset >> 9;
968 int i, update_bitmap = 0;
969
970 for(i = 0; i < length >> 9; i++){
971 if(cow_mask != NULL)
972 ubd_set_bit(i, (unsigned char *) cow_mask);
973 if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
974 continue;
1da177e4 975
91acb21f
JD
976 update_bitmap = 1;
977 ubd_set_bit(sector + i, (unsigned char *) bitmap);
978 }
979
980 if(!update_bitmap)
981 return;
1da177e4 982
91acb21f 983 *cow_offset = sector / (sizeof(unsigned long) * 8);
1da177e4 984
91acb21f
JD
985 /* This takes care of the case where we're exactly at the end of the
986 * device, and *cow_offset + 1 is off the end. So, just back it up
987 * by one word. Thanks to Lynn Kerby for the fix and James McMechan
988 * for the original diagnosis.
989 */
990 if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
991 sizeof(unsigned long) - 1))
992 (*cow_offset)--;
993
994 bitmap_words[0] = bitmap[*cow_offset];
995 bitmap_words[1] = bitmap[*cow_offset + 1];
996
997 *cow_offset *= sizeof(unsigned long);
998 *cow_offset += bitmap_offset;
999}
1000
1001static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
1002 __u64 bitmap_offset, __u64 bitmap_len)
1003{
1004 __u64 sector = req->offset >> 9;
1005 int i;
1006
1007 if(req->length > (sizeof(req->sector_mask) * 8) << 9)
1008 panic("Operation too long");
1009
1010 if(req->op == UBD_READ) {
1011 for(i = 0; i < req->length >> 9; i++){
1012 if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
6c29256c 1013 ubd_set_bit(i, (unsigned char *)
91acb21f
JD
1014 &req->sector_mask);
1015 }
1016 }
1017 else cowify_bitmap(req->offset, req->length, &req->sector_mask,
1018 &req->cow_offset, bitmap, bitmap_offset,
1019 req->bitmap_words, bitmap_len);
1da177e4
LT
1020}
1021
1da177e4 1022/* Called with ubd_io_lock held */
91acb21f 1023static int prepare_request(struct request *req, struct io_thread_req *io_req)
1da177e4
LT
1024{
1025 struct gendisk *disk = req->rq_disk;
7d314e34 1026 struct ubd *ubd_dev = disk->private_data;
91acb21f
JD
1027 __u64 offset;
1028 int len;
1029
2c49be99 1030 /* This should be impossible now */
7d314e34 1031 if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){
6c29256c 1032 printk("Write attempted on readonly ubd device %s\n",
1da177e4 1033 disk->disk_name);
91acb21f 1034 end_request(req, 0);
1da177e4
LT
1035 return(1);
1036 }
1037
91acb21f
JD
1038 offset = ((__u64) req->sector) << 9;
1039 len = req->current_nr_sectors << 9;
1040
7d314e34
PBG
1041 io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd;
1042 io_req->fds[1] = ubd_dev->fd;
91acb21f 1043 io_req->cow_offset = -1;
1da177e4
LT
1044 io_req->offset = offset;
1045 io_req->length = len;
1046 io_req->error = 0;
91acb21f
JD
1047 io_req->sector_mask = 0;
1048
1049 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
1da177e4 1050 io_req->offsets[0] = 0;
7d314e34 1051 io_req->offsets[1] = ubd_dev->cow.data_offset;
91acb21f 1052 io_req->buffer = req->buffer;
1da177e4
LT
1053 io_req->sectorsize = 1 << 9;
1054
7d314e34
PBG
1055 if(ubd_dev->cow.file != NULL)
1056 cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset,
1057 ubd_dev->cow.bitmap_len);
91acb21f 1058
1da177e4
LT
1059 return(0);
1060}
1061
1062/* Called with ubd_io_lock held */
1063static void do_ubd_request(request_queue_t *q)
1064{
1065 struct io_thread_req io_req;
1066 struct request *req;
91acb21f
JD
1067 int err, n;
1068
1069 if(thread_fd == -1){
1070 while((req = elv_next_request(q)) != NULL){
1071 err = prepare_request(req, &io_req);
1072 if(!err){
1073 do_io(&io_req);
1074 __ubd_finish(req, io_req.error);
1075 }
1076 }
1077 }
1078 else {
1079 if(do_ubd || (req = elv_next_request(q)) == NULL)
1080 return;
1081 err = prepare_request(req, &io_req);
1082 if(!err){
2fe30a34 1083 do_ubd = 1;
91acb21f
JD
1084 n = os_write_file(thread_fd, (char *) &io_req,
1085 sizeof(io_req));
1086 if(n != sizeof(io_req))
1087 printk("write to io thread failed, "
1088 "errno = %d\n", -n);
1da177e4
LT
1089 }
1090 }
1091}
1092
a885c8c4
CH
1093static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1094{
7d314e34 1095 struct ubd *ubd_dev = bdev->bd_disk->private_data;
a885c8c4
CH
1096
1097 geo->heads = 128;
1098 geo->sectors = 32;
7d314e34 1099 geo->cylinders = ubd_dev->size / (128 * 32 * 512);
a885c8c4
CH
1100 return 0;
1101}
1102
1da177e4
LT
1103static int ubd_ioctl(struct inode * inode, struct file * file,
1104 unsigned int cmd, unsigned long arg)
1105{
7d314e34 1106 struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data;
1da177e4
LT
1107 struct hd_driveid ubd_id = {
1108 .cyls = 0,
1109 .heads = 128,
1110 .sectors = 32,
1111 };
1112
1113 switch (cmd) {
1da177e4 1114 struct cdrom_volctrl volume;
1da177e4 1115 case HDIO_GET_IDENTITY:
7d314e34 1116 ubd_id.cyls = ubd_dev->size / (128 * 32 * 512);
1da177e4
LT
1117 if(copy_to_user((char __user *) arg, (char *) &ubd_id,
1118 sizeof(ubd_id)))
1119 return(-EFAULT);
1120 return(0);
1121
1122 case CDROMVOLREAD:
1123 if(copy_from_user(&volume, (char __user *) arg, sizeof(volume)))
1124 return(-EFAULT);
1125 volume.channel0 = 255;
1126 volume.channel1 = 255;
1127 volume.channel2 = 255;
1128 volume.channel3 = 255;
1129 if(copy_to_user((char __user *) arg, &volume, sizeof(volume)))
1130 return(-EFAULT);
1131 return(0);
1132 }
1133 return(-EINVAL);
1134}
1135
4833aff7 1136static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
1da177e4
LT
1137{
1138 struct uml_stat buf1, buf2;
1139 int err;
1140
4833aff7
PBG
1141 if(from_cmdline == NULL)
1142 return 0;
1143 if(!strcmp(from_cmdline, from_cow))
1144 return 0;
1da177e4
LT
1145
1146 err = os_stat_file(from_cmdline, &buf1);
1147 if(err < 0){
1148 printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
4833aff7 1149 return 0;
1da177e4
LT
1150 }
1151 err = os_stat_file(from_cow, &buf2);
1152 if(err < 0){
1153 printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
4833aff7 1154 return 1;
1da177e4
LT
1155 }
1156 if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
4833aff7 1157 return 0;
1da177e4
LT
1158
1159 printk("Backing file mismatch - \"%s\" requested,\n"
1160 "\"%s\" specified in COW header of \"%s\"\n",
1161 from_cmdline, from_cow, cow);
4833aff7 1162 return 1;
1da177e4
LT
1163}
1164
1165static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
1166{
1167 unsigned long modtime;
fe1db50c 1168 unsigned long long actual;
1da177e4
LT
1169 int err;
1170
1171 err = os_file_modtime(file, &modtime);
1172 if(err < 0){
1173 printk("Failed to get modification time of backing file "
1174 "\"%s\", err = %d\n", file, -err);
1175 return(err);
1176 }
1177
1178 err = os_file_size(file, &actual);
1179 if(err < 0){
1180 printk("Failed to get size of backing file \"%s\", "
1181 "err = %d\n", file, -err);
1182 return(err);
1183 }
1184
1185 if(actual != size){
1186 /*__u64 can be a long on AMD64 and with %lu GCC complains; so
1187 * the typecast.*/
1188 printk("Size mismatch (%llu vs %llu) of COW header vs backing "
1189 "file\n", (unsigned long long) size, actual);
1190 return(-EINVAL);
1191 }
1192 if(modtime != mtime){
1193 printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
1194 "file\n", mtime, modtime);
1195 return(-EINVAL);
1196 }
1197 return(0);
1198}
1199
1200int read_cow_bitmap(int fd, void *buf, int offset, int len)
1201{
1202 int err;
1203
1204 err = os_seek_file(fd, offset);
1205 if(err < 0)
1206 return(err);
1207
1208 err = os_read_file(fd, buf, len);
1209 if(err < 0)
1210 return(err);
1211
1212 return(0);
1213}
1214
6c29256c 1215int open_ubd_file(char *file, struct openflags *openflags, int shared,
1da177e4
LT
1216 char **backing_file_out, int *bitmap_offset_out,
1217 unsigned long *bitmap_len_out, int *data_offset_out,
1218 int *create_cow_out)
1219{
1220 time_t mtime;
1221 unsigned long long size;
1222 __u32 version, align;
1223 char *backing_file;
4833aff7 1224 int fd, err, sectorsize, asked_switch, mode = 0644;
1da177e4
LT
1225
1226 fd = os_open_file(file, *openflags, mode);
a374a48f
PBG
1227 if (fd < 0) {
1228 if ((fd == -ENOENT) && (create_cow_out != NULL))
1da177e4 1229 *create_cow_out = 1;
a374a48f
PBG
1230 if (!openflags->w ||
1231 ((fd != -EROFS) && (fd != -EACCES)))
1232 return fd;
1da177e4
LT
1233 openflags->w = 0;
1234 fd = os_open_file(file, *openflags, mode);
a374a48f
PBG
1235 if (fd < 0)
1236 return fd;
1da177e4
LT
1237 }
1238
6c29256c
JD
1239 if(shared)
1240 printk("Not locking \"%s\" on the host\n", file);
1241 else {
1242 err = os_lock_file(fd, openflags->w);
1243 if(err < 0){
1244 printk("Failed to lock '%s', err = %d\n", file, -err);
1245 goto out_close;
1246 }
1da177e4
LT
1247 }
1248
d6e05edc 1249 /* Successful return case! */
a374a48f
PBG
1250 if(backing_file_out == NULL)
1251 return(fd);
1da177e4
LT
1252
1253 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
1254 &size, &sectorsize, &align, bitmap_offset_out);
1255 if(err && (*backing_file_out != NULL)){
1256 printk("Failed to read COW header from COW file \"%s\", "
1257 "errno = %d\n", file, -err);
1258 goto out_close;
1259 }
a374a48f
PBG
1260 if(err)
1261 return(fd);
1da177e4 1262
4833aff7 1263 asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
1da177e4 1264
4833aff7
PBG
1265 /* Allow switching only if no mismatch. */
1266 if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) {
1da177e4
LT
1267 printk("Switching backing file to '%s'\n", *backing_file_out);
1268 err = write_cow_header(file, fd, *backing_file_out,
1269 sectorsize, align, &size);
a374a48f 1270 if (err) {
1da177e4 1271 printk("Switch failed, errno = %d\n", -err);
4833aff7 1272 goto out_close;
1da177e4 1273 }
a374a48f 1274 } else {
1da177e4
LT
1275 *backing_file_out = backing_file;
1276 err = backing_file_mismatch(*backing_file_out, size, mtime);
a374a48f
PBG
1277 if (err)
1278 goto out_close;
1da177e4
LT
1279 }
1280
1281 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
1282 bitmap_len_out, data_offset_out);
1283
a374a48f 1284 return fd;
1da177e4
LT
1285 out_close:
1286 os_close_file(fd);
a374a48f 1287 return err;
1da177e4
LT
1288}
1289
1290int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
1291 int sectorsize, int alignment, int *bitmap_offset_out,
1292 unsigned long *bitmap_len_out, int *data_offset_out)
1293{
1294 int err, fd;
1295
1296 flags.c = 1;
6c29256c 1297 fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL);
1da177e4
LT
1298 if(fd < 0){
1299 err = fd;
1300 printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
1301 -err);
1302 goto out;
1303 }
1304
1305 err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
1306 bitmap_offset_out, bitmap_len_out,
1307 data_offset_out);
1308 if(!err)
1309 return(fd);
1310 os_close_file(fd);
1311 out:
1312 return(err);
1313}
1314
91acb21f 1315static int update_bitmap(struct io_thread_req *req)
1da177e4 1316{
91acb21f 1317 int n;
1da177e4 1318
91acb21f
JD
1319 if(req->cow_offset == -1)
1320 return(0);
1da177e4 1321
91acb21f
JD
1322 n = os_seek_file(req->fds[1], req->cow_offset);
1323 if(n < 0){
1324 printk("do_io - bitmap lseek failed : err = %d\n", -n);
1325 return(1);
1326 }
1da177e4 1327
91acb21f
JD
1328 n = os_write_file(req->fds[1], &req->bitmap_words,
1329 sizeof(req->bitmap_words));
1330 if(n != sizeof(req->bitmap_words)){
1331 printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
1332 req->fds[1]);
1333 return(1);
1334 }
1da177e4 1335
91acb21f
JD
1336 return(0);
1337}
1da177e4 1338
91acb21f
JD
1339void do_io(struct io_thread_req *req)
1340{
1341 char *buf;
1342 unsigned long len;
1343 int n, nsectors, start, end, bit;
1344 int err;
1345 __u64 off;
1346
1347 nsectors = req->length / req->sectorsize;
1348 start = 0;
1349 do {
1350 bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
1351 end = start;
1352 while((end < nsectors) &&
1353 (ubd_test_bit(end, (unsigned char *)
1354 &req->sector_mask) == bit))
1355 end++;
1356
1357 off = req->offset + req->offsets[bit] +
1358 start * req->sectorsize;
1359 len = (end - start) * req->sectorsize;
1360 buf = &req->buffer[start * req->sectorsize];
1361
1362 err = os_seek_file(req->fds[bit], off);
1363 if(err < 0){
1364 printk("do_io - lseek failed : err = %d\n", -err);
1365 req->error = 1;
1366 return;
1367 }
1368 if(req->op == UBD_READ){
1369 n = 0;
1370 do {
1371 buf = &buf[n];
1372 len -= n;
1373 n = os_read_file(req->fds[bit], buf, len);
1374 if (n < 0) {
1375 printk("do_io - read failed, err = %d "
1376 "fd = %d\n", -n, req->fds[bit]);
1377 req->error = 1;
1378 return;
1379 }
1380 } while((n < len) && (n != 0));
1381 if (n < len) memset(&buf[n], 0, len - n);
1382 } else {
1383 n = os_write_file(req->fds[bit], buf, len);
1384 if(n != len){
1385 printk("do_io - write failed err = %d "
1386 "fd = %d\n", -n, req->fds[bit]);
1387 req->error = 1;
1388 return;
1389 }
1390 }
1391
1392 start = end;
1393 } while(start < nsectors);
1da177e4 1394
91acb21f 1395 req->error = update_bitmap(req);
1da177e4 1396}
91acb21f
JD
1397
1398/* Changed in start_io_thread, which is serialized by being called only
1399 * from ubd_init, which is an initcall.
1400 */
1401int kernel_fd = -1;
1402
d8d7c28e
PBG
1403/* Only changed by the io thread. XXX: currently unused. */
1404static int io_count = 0;
91acb21f
JD
1405
1406int io_thread(void *arg)
1407{
1408 struct io_thread_req req;
1409 int n;
1410
1411 ignore_sigwinch_sig();
1412 while(1){
1413 n = os_read_file(kernel_fd, &req, sizeof(req));
1414 if(n != sizeof(req)){
1415 if(n < 0)
1416 printk("io_thread - read failed, fd = %d, "
1417 "err = %d\n", kernel_fd, -n);
1418 else {
1419 printk("io_thread - short read, fd = %d, "
1420 "length = %d\n", kernel_fd, n);
1421 }
1422 continue;
1423 }
1424 io_count++;
1425 do_io(&req);
1426 n = os_write_file(kernel_fd, &req, sizeof(req));
1427 if(n != sizeof(req))
1428 printk("io_thread - write failed, fd = %d, err = %d\n",
1429 kernel_fd, -n);
1430 }
91acb21f 1431
1b57e9c2
JD
1432 return 0;
1433}