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