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