]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - arch/um/drivers/ubd_kern.c
Merge branches 'pxa-ian' and 'pxa-xm270' into pxa
[mirror_ubuntu-artful-kernel.git] / arch / um / drivers / ubd_kern.c
CommitLineData
6c29256c 1/*
1da177e4
LT
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6/* 2001-09-28...2002-04-17
7 * Partition stuff by James_McMechan@hotmail.com
8 * old style ubd by setting UBD_SHIFT to 0
9 * 2002-09-27...2002-10-18 massive tinkering for 2.5
10 * partitions have changed in 2.5
11 * 2003-01-29 more tinkering for 2.5.59-1
12 * This should now address the sysfs problems and has
13 * the symlink for devfs to allow for booting with
14 * the common /dev/ubd/discX/... names rather than
15 * only /dev/ubdN/discN this version also has lots of
16 * clean ups preparing for ubd-many.
17 * James McMechan
18 */
19
20#define MAJOR_NR UBD_MAJOR
21#define UBD_SHIFT 4
22
e16f5350 23#include "linux/kernel.h"
1da177e4
LT
24#include "linux/module.h"
25#include "linux/blkdev.h"
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
1da177e4
LT
101static int ubd_open(struct inode * inode, struct file * filp);
102static int ubd_release(struct inode * inode, struct file * file);
103static int ubd_ioctl(struct inode * inode, struct file * file,
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,
111 .open = ubd_open,
112 .release = ubd_release,
113 .ioctl = ubd_ioctl,
a885c8c4 114 .getgeo = ubd_getgeo,
1da177e4
LT
115};
116
1da177e4
LT
117/* Protected by ubd_lock */
118static int fake_major = MAJOR_NR;
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
JD
301 mutex_lock(&ubd_lock);
302 if(fake_major != MAJOR_NR){
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;
1da177e4 454
4898b53a 455static void ubd_end_request(struct request *req, int bytes, int error)
1da177e4 456{
4898b53a 457 blk_end_request(req, error, bytes);
1da177e4
LT
458}
459
33f775ee
PBG
460/* Callable only from interrupt context - otherwise you need to do
461 * spin_lock_irq()/spin_lock_irqsave() */
a0044bdf 462static inline void ubd_finish(struct request *req, int bytes)
1da177e4 463{
a0044bdf 464 if(bytes < 0){
4898b53a 465 ubd_end_request(req, 0, -EIO);
a0044bdf
JD
466 return;
467 }
4898b53a 468 ubd_end_request(req, bytes, 0);
1da177e4
LT
469}
470
a0044bdf
JD
471static LIST_HEAD(restart);
472
2fe30a34 473/* XXX - move this inside ubd_intr. */
62f96cb0 474/* Called without dev->lock held, and only in interrupt context. */
91acb21f 475static void ubd_handler(void)
1da177e4 476{
2adcec21 477 struct io_thread_req *req;
62f96cb0 478 struct request *rq;
a0044bdf
JD
479 struct ubd *ubd;
480 struct list_head *list, *next_ele;
481 unsigned long flags;
91acb21f
JD
482 int n;
483
a0044bdf 484 while(1){
a6ea4cce
JD
485 n = os_read_file(thread_fd, &req,
486 sizeof(struct io_thread_req *));
a0044bdf
JD
487 if(n != sizeof(req)){
488 if(n == -EAGAIN)
489 break;
490 printk(KERN_ERR "spurious interrupt in ubd_handler, "
491 "err = %d\n", -n);
492 return;
493 }
62f96cb0 494
2adcec21
JD
495 rq = req->req;
496 rq->nr_sectors -= req->length >> 9;
a0044bdf
JD
497 if(rq->nr_sectors == 0)
498 ubd_finish(rq, rq->hard_nr_sectors << 9);
2adcec21 499 kfree(req);
a0044bdf 500 }
62f96cb0 501 reactivate_fd(thread_fd, UBD_IRQ);
a0044bdf
JD
502
503 list_for_each_safe(list, next_ele, &restart){
504 ubd = container_of(list, struct ubd, restart);
505 list_del_init(&ubd->restart);
506 spin_lock_irqsave(&ubd->lock, flags);
507 do_ubd_request(ubd->queue);
508 spin_unlock_irqrestore(&ubd->lock, flags);
509 }
1da177e4
LT
510}
511
7bea96fd 512static irqreturn_t ubd_intr(int irq, void *dev)
1da177e4 513{
91acb21f 514 ubd_handler();
dc764e50 515 return IRQ_HANDLED;
91acb21f 516}
09ace81c 517
91acb21f
JD
518/* Only changed by ubd_init, which is an initcall. */
519static int io_pid = -1;
09ace81c 520
5dc62b1b 521static void kill_io_thread(void)
91acb21f 522{
6c29256c 523 if(io_pid != -1)
91acb21f 524 os_kill_process(io_pid, 1);
09ace81c 525}
1da177e4 526
91acb21f
JD
527__uml_exitcall(kill_io_thread);
528
d8d7c28e 529static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
1da177e4
LT
530{
531 char *file;
532
7d314e34 533 file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
dc764e50 534 return os_file_size(file, size_out);
1da177e4
LT
535}
536
5dc62b1b
WC
537static int read_cow_bitmap(int fd, void *buf, int offset, int len)
538{
539 int err;
540
541 err = os_seek_file(fd, offset);
542 if (err < 0)
543 return err;
544
545 err = os_read_file(fd, buf, len);
546 if (err < 0)
547 return err;
548
549 return 0;
550}
551
552static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
553{
554 unsigned long modtime;
555 unsigned long long actual;
556 int err;
557
558 err = os_file_modtime(file, &modtime);
559 if (err < 0) {
560 printk(KERN_ERR "Failed to get modification time of backing "
561 "file \"%s\", err = %d\n", file, -err);
562 return err;
563 }
564
565 err = os_file_size(file, &actual);
566 if (err < 0) {
567 printk(KERN_ERR "Failed to get size of backing file \"%s\", "
568 "err = %d\n", file, -err);
569 return err;
570 }
571
572 if (actual != size) {
573 /*__u64 can be a long on AMD64 and with %lu GCC complains; so
574 * the typecast.*/
575 printk(KERN_ERR "Size mismatch (%llu vs %llu) of COW header "
576 "vs backing file\n", (unsigned long long) size, actual);
577 return -EINVAL;
578 }
579 if (modtime != mtime) {
580 printk(KERN_ERR "mtime mismatch (%ld vs %ld) of COW header vs "
581 "backing file\n", mtime, modtime);
582 return -EINVAL;
583 }
584 return 0;
585}
586
587static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
588{
589 struct uml_stat buf1, buf2;
590 int err;
591
592 if (from_cmdline == NULL)
593 return 0;
594 if (!strcmp(from_cmdline, from_cow))
595 return 0;
596
597 err = os_stat_file(from_cmdline, &buf1);
598 if (err < 0) {
599 printk(KERN_ERR "Couldn't stat '%s', err = %d\n", from_cmdline,
600 -err);
601 return 0;
602 }
603 err = os_stat_file(from_cow, &buf2);
604 if (err < 0) {
605 printk(KERN_ERR "Couldn't stat '%s', err = %d\n", from_cow,
606 -err);
607 return 1;
608 }
609 if ((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
610 return 0;
611
612 printk(KERN_ERR "Backing file mismatch - \"%s\" requested, "
613 "\"%s\" specified in COW header of \"%s\"\n",
614 from_cmdline, from_cow, cow);
615 return 1;
616}
617
618static int open_ubd_file(char *file, struct openflags *openflags, int shared,
619 char **backing_file_out, int *bitmap_offset_out,
620 unsigned long *bitmap_len_out, int *data_offset_out,
621 int *create_cow_out)
622{
623 time_t mtime;
624 unsigned long long size;
625 __u32 version, align;
626 char *backing_file;
627 int fd, err, sectorsize, asked_switch, mode = 0644;
628
629 fd = os_open_file(file, *openflags, mode);
630 if (fd < 0) {
631 if ((fd == -ENOENT) && (create_cow_out != NULL))
632 *create_cow_out = 1;
633 if (!openflags->w ||
634 ((fd != -EROFS) && (fd != -EACCES)))
635 return fd;
636 openflags->w = 0;
637 fd = os_open_file(file, *openflags, mode);
638 if (fd < 0)
639 return fd;
640 }
641
642 if (shared)
643 printk(KERN_INFO "Not locking \"%s\" on the host\n", file);
644 else {
645 err = os_lock_file(fd, openflags->w);
646 if (err < 0) {
647 printk(KERN_ERR "Failed to lock '%s', err = %d\n",
648 file, -err);
649 goto out_close;
650 }
651 }
652
653 /* Successful return case! */
654 if (backing_file_out == NULL)
655 return fd;
656
657 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
658 &size, &sectorsize, &align, bitmap_offset_out);
659 if (err && (*backing_file_out != NULL)) {
660 printk(KERN_ERR "Failed to read COW header from COW file "
661 "\"%s\", errno = %d\n", file, -err);
662 goto out_close;
663 }
664 if (err)
665 return fd;
666
667 asked_switch = path_requires_switch(*backing_file_out, backing_file,
668 file);
669
670 /* Allow switching only if no mismatch. */
671 if (asked_switch && !backing_file_mismatch(*backing_file_out, size,
672 mtime)) {
673 printk(KERN_ERR "Switching backing file to '%s'\n",
674 *backing_file_out);
675 err = write_cow_header(file, fd, *backing_file_out,
676 sectorsize, align, &size);
677 if (err) {
678 printk(KERN_ERR "Switch failed, errno = %d\n", -err);
679 goto out_close;
680 }
681 } else {
682 *backing_file_out = backing_file;
683 err = backing_file_mismatch(*backing_file_out, size, mtime);
684 if (err)
685 goto out_close;
686 }
687
688 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
689 bitmap_len_out, data_offset_out);
690
691 return fd;
692 out_close:
693 os_close_file(fd);
694 return err;
695}
696
697static int create_cow_file(char *cow_file, char *backing_file,
698 struct openflags flags,
699 int sectorsize, int alignment, int *bitmap_offset_out,
700 unsigned long *bitmap_len_out, int *data_offset_out)
701{
702 int err, fd;
703
704 flags.c = 1;
705 fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL);
706 if (fd < 0) {
707 err = fd;
708 printk(KERN_ERR "Open of COW file '%s' failed, errno = %d\n",
709 cow_file, -err);
710 goto out;
711 }
712
713 err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
714 bitmap_offset_out, bitmap_len_out,
715 data_offset_out);
716 if (!err)
717 return fd;
718 os_close_file(fd);
719 out:
720 return err;
721}
722
5f75a4f8 723static void ubd_close_dev(struct ubd *ubd_dev)
1da177e4 724{
7d314e34
PBG
725 os_close_file(ubd_dev->fd);
726 if(ubd_dev->cow.file == NULL)
1da177e4
LT
727 return;
728
7d314e34
PBG
729 os_close_file(ubd_dev->cow.fd);
730 vfree(ubd_dev->cow.bitmap);
731 ubd_dev->cow.bitmap = NULL;
1da177e4
LT
732}
733
7d314e34 734static int ubd_open_dev(struct ubd *ubd_dev)
1da177e4
LT
735{
736 struct openflags flags;
737 char **back_ptr;
738 int err, create_cow, *create_ptr;
0bf16bff 739 int fd;
1da177e4 740
7d314e34 741 ubd_dev->openflags = ubd_dev->boot_openflags;
1da177e4 742 create_cow = 0;
7d314e34
PBG
743 create_ptr = (ubd_dev->cow.file != NULL) ? &create_cow : NULL;
744 back_ptr = ubd_dev->no_cow ? NULL : &ubd_dev->cow.file;
0bf16bff
PBG
745
746 fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared,
7d314e34
PBG
747 back_ptr, &ubd_dev->cow.bitmap_offset,
748 &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset,
6c29256c 749 create_ptr);
1da177e4 750
0bf16bff
PBG
751 if((fd == -ENOENT) && create_cow){
752 fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file,
7d314e34
PBG
753 ubd_dev->openflags, 1 << 9, PAGE_SIZE,
754 &ubd_dev->cow.bitmap_offset,
755 &ubd_dev->cow.bitmap_len,
756 &ubd_dev->cow.data_offset);
0bf16bff 757 if(fd >= 0){
1da177e4 758 printk(KERN_INFO "Creating \"%s\" as COW file for "
7d314e34 759 "\"%s\"\n", ubd_dev->file, ubd_dev->cow.file);
1da177e4
LT
760 }
761 }
762
0bf16bff 763 if(fd < 0){
7d314e34 764 printk("Failed to open '%s', errno = %d\n", ubd_dev->file,
0bf16bff
PBG
765 -fd);
766 return fd;
1da177e4 767 }
0bf16bff 768 ubd_dev->fd = fd;
1da177e4 769
7d314e34 770 if(ubd_dev->cow.file != NULL){
f4768ffd
JD
771 blk_queue_max_sectors(ubd_dev->queue, 8 * sizeof(long));
772
1da177e4 773 err = -ENOMEM;
da2486ba 774 ubd_dev->cow.bitmap = vmalloc(ubd_dev->cow.bitmap_len);
7d314e34 775 if(ubd_dev->cow.bitmap == NULL){
1da177e4
LT
776 printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
777 goto error;
778 }
779 flush_tlb_kernel_vm();
780
7d314e34
PBG
781 err = read_cow_bitmap(ubd_dev->fd, ubd_dev->cow.bitmap,
782 ubd_dev->cow.bitmap_offset,
783 ubd_dev->cow.bitmap_len);
1da177e4
LT
784 if(err < 0)
785 goto error;
786
7d314e34 787 flags = ubd_dev->openflags;
1da177e4 788 flags.w = 0;
7d314e34 789 err = open_ubd_file(ubd_dev->cow.file, &flags, ubd_dev->shared, NULL,
6c29256c 790 NULL, NULL, NULL, NULL);
1da177e4 791 if(err < 0) goto error;
7d314e34 792 ubd_dev->cow.fd = err;
1da177e4 793 }
dc764e50 794 return 0;
1da177e4 795 error:
7d314e34 796 os_close_file(ubd_dev->fd);
dc764e50 797 return err;
1da177e4
LT
798}
799
2e3f5251
JD
800static void ubd_device_release(struct device *dev)
801{
802 struct ubd *ubd_dev = dev->driver_data;
803
804 blk_cleanup_queue(ubd_dev->queue);
805 *ubd_dev = ((struct ubd) DEFAULT_UBD);
806}
807
5f75a4f8 808static int ubd_disk_register(int major, u64 size, int unit,
b8831a1d 809 struct gendisk **disk_out)
1da177e4
LT
810{
811 struct gendisk *disk;
1da177e4
LT
812
813 disk = alloc_disk(1 << UBD_SHIFT);
814 if(disk == NULL)
dc764e50 815 return -ENOMEM;
1da177e4
LT
816
817 disk->major = major;
818 disk->first_minor = unit << UBD_SHIFT;
819 disk->fops = &ubd_blops;
820 set_capacity(disk, size / 512);
ce7b0f46 821 if(major == MAJOR_NR)
1da177e4 822 sprintf(disk->disk_name, "ubd%c", 'a' + unit);
ce7b0f46 823 else
1da177e4 824 sprintf(disk->disk_name, "ubd_fake%d", unit);
1da177e4
LT
825
826 /* sysfs register (not for ide fake devices) */
827 if (major == MAJOR_NR) {
7d314e34
PBG
828 ubd_devs[unit].pdev.id = unit;
829 ubd_devs[unit].pdev.name = DRIVER_NAME;
2e3f5251
JD
830 ubd_devs[unit].pdev.dev.release = ubd_device_release;
831 ubd_devs[unit].pdev.dev.driver_data = &ubd_devs[unit];
7d314e34
PBG
832 platform_device_register(&ubd_devs[unit].pdev);
833 disk->driverfs_dev = &ubd_devs[unit].pdev.dev;
1da177e4
LT
834 }
835
7d314e34 836 disk->private_data = &ubd_devs[unit];
62f96cb0 837 disk->queue = ubd_devs[unit].queue;
1da177e4
LT
838 add_disk(disk);
839
840 *disk_out = disk;
841 return 0;
842}
843
844#define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9))
845
f28169d2 846static int ubd_add(int n, char **error_out)
1da177e4 847{
7d314e34 848 struct ubd *ubd_dev = &ubd_devs[n];
f28169d2 849 int err = 0;
1da177e4 850
7d314e34 851 if(ubd_dev->file == NULL)
ec7cf783 852 goto out;
1da177e4 853
7d314e34 854 err = ubd_file_size(ubd_dev, &ubd_dev->size);
f28169d2
JD
855 if(err < 0){
856 *error_out = "Couldn't determine size of device's file";
80c13749 857 goto out;
f28169d2 858 }
1da177e4 859
7d314e34 860 ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
1da177e4 861
a0044bdf 862 INIT_LIST_HEAD(&ubd_dev->restart);
4f40c055 863 sg_init_table(ubd_dev->sg, MAX_SG);
a0044bdf 864
62f96cb0
JD
865 err = -ENOMEM;
866 ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock);
867 if (ubd_dev->queue == NULL) {
868 *error_out = "Failed to initialize device queue";
80c13749 869 goto out;
62f96cb0
JD
870 }
871 ubd_dev->queue->queuedata = ubd_dev;
872
a0044bdf 873 blk_queue_max_hw_segments(ubd_dev->queue, MAX_SG);
62f96cb0
JD
874 err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
875 if(err){
876 *error_out = "Failed to register device";
877 goto out_cleanup;
878 }
6c29256c 879
1da177e4 880 if(fake_major != MAJOR_NR)
5f75a4f8 881 ubd_disk_register(fake_major, ubd_dev->size, n,
62f96cb0 882 &fake_gendisk[n]);
1da177e4 883
83380cc1
JD
884 /*
885 * Perhaps this should also be under the "if (fake_major)" above
886 * using the fake_disk->disk_name
887 */
1da177e4
LT
888 if (fake_ide)
889 make_ide_entries(ubd_gendisk[n]->disk_name);
890
ec7cf783 891 err = 0;
ec7cf783
JD
892out:
893 return err;
62f96cb0
JD
894
895out_cleanup:
896 blk_cleanup_queue(ubd_dev->queue);
897 goto out;
1da177e4
LT
898}
899
f28169d2 900static int ubd_config(char *str, char **error_out)
1da177e4 901{
e7f6552f 902 int n, ret;
1da177e4 903
f28169d2
JD
904 /* This string is possibly broken up and stored, so it's only
905 * freed if ubd_setup_common fails, or if only general options
906 * were set.
907 */
970d6e3a 908 str = kstrdup(str, GFP_KERNEL);
e7f6552f 909 if (str == NULL) {
f28169d2
JD
910 *error_out = "Failed to allocate memory";
911 return -ENOMEM;
1da177e4 912 }
f28169d2
JD
913
914 ret = ubd_setup_common(str, &n, error_out);
915 if (ret)
e7f6552f 916 goto err_free;
f28169d2 917
e7f6552f
PBG
918 if (n == -1) {
919 ret = 0;
d8d7c28e 920 goto err_free;
1da177e4 921 }
1da177e4 922
dc764e50 923 mutex_lock(&ubd_lock);
f28169d2 924 ret = ubd_add(n, error_out);
e7f6552f 925 if (ret)
7d314e34 926 ubd_devs[n].file = NULL;
dc764e50 927 mutex_unlock(&ubd_lock);
1da177e4 928
e7f6552f 929out:
dc764e50 930 return ret;
e7f6552f
PBG
931
932err_free:
933 kfree(str);
934 goto out;
1da177e4
LT
935}
936
937static int ubd_get_config(char *name, char *str, int size, char **error_out)
938{
7d314e34 939 struct ubd *ubd_dev;
1da177e4
LT
940 int n, len = 0;
941
942 n = parse_unit(&name);
943 if((n >= MAX_DEV) || (n < 0)){
944 *error_out = "ubd_get_config : device number out of range";
dc764e50 945 return -1;
1da177e4
LT
946 }
947
7d314e34 948 ubd_dev = &ubd_devs[n];
d7fb2c38 949 mutex_lock(&ubd_lock);
1da177e4 950
7d314e34 951 if(ubd_dev->file == NULL){
1da177e4
LT
952 CONFIG_CHUNK(str, size, len, "", 1);
953 goto out;
954 }
955
7d314e34 956 CONFIG_CHUNK(str, size, len, ubd_dev->file, 0);
1da177e4 957
7d314e34 958 if(ubd_dev->cow.file != NULL){
1da177e4 959 CONFIG_CHUNK(str, size, len, ",", 0);
7d314e34 960 CONFIG_CHUNK(str, size, len, ubd_dev->cow.file, 1);
1da177e4
LT
961 }
962 else CONFIG_CHUNK(str, size, len, "", 1);
963
964 out:
d7fb2c38 965 mutex_unlock(&ubd_lock);
dc764e50 966 return len;
1da177e4
LT
967}
968
29d56cfe
JD
969static int ubd_id(char **str, int *start_out, int *end_out)
970{
dc764e50 971 int n;
29d56cfe
JD
972
973 n = parse_unit(str);
dc764e50
JD
974 *start_out = 0;
975 *end_out = MAX_DEV - 1;
976 return n;
29d56cfe
JD
977}
978
f28169d2 979static int ubd_remove(int n, char **error_out)
1da177e4 980{
2e3f5251 981 struct gendisk *disk = ubd_gendisk[n];
7d314e34 982 struct ubd *ubd_dev;
29d56cfe 983 int err = -ENODEV;
1da177e4 984
d7fb2c38 985 mutex_lock(&ubd_lock);
1da177e4 986
7d314e34 987 ubd_dev = &ubd_devs[n];
1da177e4 988
7d314e34 989 if(ubd_dev->file == NULL)
29d56cfe 990 goto out;
1da177e4 991
29d56cfe
JD
992 /* you cannot remove a open disk */
993 err = -EBUSY;
7d314e34 994 if(ubd_dev->count > 0)
1da177e4
LT
995 goto out;
996
dc764e50 997 ubd_gendisk[n] = NULL;
b47d2deb
JD
998 if(disk != NULL){
999 del_gendisk(disk);
1000 put_disk(disk);
1001 }
1da177e4
LT
1002
1003 if(fake_gendisk[n] != NULL){
1004 del_gendisk(fake_gendisk[n]);
1005 put_disk(fake_gendisk[n]);
1006 fake_gendisk[n] = NULL;
1007 }
1008
1da177e4 1009 err = 0;
2e3f5251 1010 platform_device_unregister(&ubd_dev->pdev);
29d56cfe 1011out:
d7fb2c38 1012 mutex_unlock(&ubd_lock);
29d56cfe 1013 return err;
1da177e4
LT
1014}
1015
f28169d2 1016/* All these are called by mconsole in process context and without
b8831a1d 1017 * ubd-specific locks. The structure itself is const except for .list.
f28169d2 1018 */
1da177e4 1019static struct mc_device ubd_mc = {
84f48d4f 1020 .list = LIST_HEAD_INIT(ubd_mc.list),
1da177e4
LT
1021 .name = "ubd",
1022 .config = ubd_config,
dc764e50 1023 .get_config = ubd_get_config,
29d56cfe 1024 .id = ubd_id,
1da177e4
LT
1025 .remove = ubd_remove,
1026};
1027
d8d7c28e 1028static int __init ubd_mc_init(void)
1da177e4
LT
1029{
1030 mconsole_register_dev(&ubd_mc);
1031 return 0;
1032}
1033
1034__initcall(ubd_mc_init);
1035
d8d7c28e
PBG
1036static int __init ubd0_init(void)
1037{
1038 struct ubd *ubd_dev = &ubd_devs[0];
1039
b8831a1d 1040 mutex_lock(&ubd_lock);
d8d7c28e
PBG
1041 if(ubd_dev->file == NULL)
1042 ubd_dev->file = "root_fs";
b8831a1d
JD
1043 mutex_unlock(&ubd_lock);
1044
dc764e50 1045 return 0;
d8d7c28e
PBG
1046}
1047
1048__initcall(ubd0_init);
1049
b8831a1d 1050/* Used in ubd_init, which is an initcall */
3ae5eaec
RK
1051static struct platform_driver ubd_driver = {
1052 .driver = {
1053 .name = DRIVER_NAME,
1054 },
1da177e4
LT
1055};
1056
d8d7c28e 1057static int __init ubd_init(void)
1da177e4 1058{
f28169d2
JD
1059 char *error;
1060 int i, err;
1da177e4 1061
1da177e4
LT
1062 if (register_blkdev(MAJOR_NR, "ubd"))
1063 return -1;
1064
1da177e4
LT
1065 if (fake_major != MAJOR_NR) {
1066 char name[sizeof("ubd_nnn\0")];
1067
1068 snprintf(name, sizeof(name), "ubd_%d", fake_major);
1da177e4
LT
1069 if (register_blkdev(fake_major, "ubd"))
1070 return -1;
1071 }
3ae5eaec 1072 platform_driver_register(&ubd_driver);
dc764e50 1073 mutex_lock(&ubd_lock);
f28169d2
JD
1074 for (i = 0; i < MAX_DEV; i++){
1075 err = ubd_add(i, &error);
1076 if(err)
1077 printk(KERN_ERR "Failed to initialize ubd device %d :"
1078 "%s\n", i, error);
1079 }
dc764e50 1080 mutex_unlock(&ubd_lock);
1da177e4
LT
1081 return 0;
1082}
1083
1084late_initcall(ubd_init);
1085
d8d7c28e 1086static int __init ubd_driver_init(void){
91acb21f
JD
1087 unsigned long stack;
1088 int err;
1089
1090 /* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/
1091 if(global_openflags.s){
1092 printk(KERN_INFO "ubd: Synchronous mode\n");
1093 /* Letting ubd=sync be like using ubd#s= instead of ubd#= is
1094 * enough. So use anyway the io thread. */
1095 }
1096 stack = alloc_stack(0, 0);
6c29256c 1097 io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
91acb21f
JD
1098 &thread_fd);
1099 if(io_pid < 0){
6c29256c 1100 printk(KERN_ERR
91acb21f
JD
1101 "ubd : Failed to start I/O thread (errno = %d) - "
1102 "falling back to synchronous I/O\n", -io_pid);
1103 io_pid = -1;
dc764e50 1104 return 0;
91acb21f 1105 }
6c29256c 1106 err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
7d314e34 1107 IRQF_DISABLED, "ubd", ubd_devs);
91acb21f
JD
1108 if(err != 0)
1109 printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
f4c57a78 1110 return 0;
91acb21f
JD
1111}
1112
1113device_initcall(ubd_driver_init);
1114
1da177e4
LT
1115static int ubd_open(struct inode *inode, struct file *filp)
1116{
1117 struct gendisk *disk = inode->i_bdev->bd_disk;
7d314e34 1118 struct ubd *ubd_dev = disk->private_data;
1da177e4
LT
1119 int err = 0;
1120
7d314e34
PBG
1121 if(ubd_dev->count == 0){
1122 err = ubd_open_dev(ubd_dev);
1da177e4
LT
1123 if(err){
1124 printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
7d314e34 1125 disk->disk_name, ubd_dev->file, -err);
1da177e4
LT
1126 goto out;
1127 }
1128 }
7d314e34
PBG
1129 ubd_dev->count++;
1130 set_disk_ro(disk, !ubd_dev->openflags.w);
2c49be99
PBG
1131
1132 /* This should no more be needed. And it didn't work anyway to exclude
1133 * read-write remounting of filesystems.*/
7d314e34 1134 /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){
5f75a4f8 1135 if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev);
1da177e4 1136 err = -EROFS;
2c49be99 1137 }*/
1da177e4 1138 out:
dc764e50 1139 return err;
1da177e4
LT
1140}
1141
1142static int ubd_release(struct inode * inode, struct file * file)
1143{
1144 struct gendisk *disk = inode->i_bdev->bd_disk;
7d314e34 1145 struct ubd *ubd_dev = disk->private_data;
1da177e4 1146
7d314e34 1147 if(--ubd_dev->count == 0)
5f75a4f8 1148 ubd_close_dev(ubd_dev);
dc764e50 1149 return 0;
1da177e4
LT
1150}
1151
91acb21f
JD
1152static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
1153 __u64 *cow_offset, unsigned long *bitmap,
1154 __u64 bitmap_offset, unsigned long *bitmap_words,
1155 __u64 bitmap_len)
1da177e4 1156{
91acb21f
JD
1157 __u64 sector = io_offset >> 9;
1158 int i, update_bitmap = 0;
1159
1160 for(i = 0; i < length >> 9; i++){
1161 if(cow_mask != NULL)
1162 ubd_set_bit(i, (unsigned char *) cow_mask);
1163 if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
1164 continue;
1da177e4 1165
91acb21f
JD
1166 update_bitmap = 1;
1167 ubd_set_bit(sector + i, (unsigned char *) bitmap);
1168 }
1169
1170 if(!update_bitmap)
1171 return;
1da177e4 1172
91acb21f 1173 *cow_offset = sector / (sizeof(unsigned long) * 8);
1da177e4 1174
91acb21f
JD
1175 /* This takes care of the case where we're exactly at the end of the
1176 * device, and *cow_offset + 1 is off the end. So, just back it up
1177 * by one word. Thanks to Lynn Kerby for the fix and James McMechan
1178 * for the original diagnosis.
1179 */
6d074242
JO
1180 if (*cow_offset == (DIV_ROUND_UP(bitmap_len,
1181 sizeof(unsigned long)) - 1))
91acb21f
JD
1182 (*cow_offset)--;
1183
1184 bitmap_words[0] = bitmap[*cow_offset];
1185 bitmap_words[1] = bitmap[*cow_offset + 1];
1186
1187 *cow_offset *= sizeof(unsigned long);
1188 *cow_offset += bitmap_offset;
1189}
1190
1191static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
1192 __u64 bitmap_offset, __u64 bitmap_len)
1193{
1194 __u64 sector = req->offset >> 9;
1195 int i;
1196
1197 if(req->length > (sizeof(req->sector_mask) * 8) << 9)
1198 panic("Operation too long");
1199
1200 if(req->op == UBD_READ) {
1201 for(i = 0; i < req->length >> 9; i++){
1202 if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
6c29256c 1203 ubd_set_bit(i, (unsigned char *)
91acb21f 1204 &req->sector_mask);
dc764e50 1205 }
91acb21f
JD
1206 }
1207 else cowify_bitmap(req->offset, req->length, &req->sector_mask,
1208 &req->cow_offset, bitmap, bitmap_offset,
1209 req->bitmap_words, bitmap_len);
1da177e4
LT
1210}
1211
62f96cb0 1212/* Called with dev->lock held */
a0044bdf
JD
1213static void prepare_request(struct request *req, struct io_thread_req *io_req,
1214 unsigned long long offset, int page_offset,
1215 int len, struct page *page)
1da177e4
LT
1216{
1217 struct gendisk *disk = req->rq_disk;
7d314e34 1218 struct ubd *ubd_dev = disk->private_data;
91acb21f 1219
62f96cb0 1220 io_req->req = req;
a0044bdf
JD
1221 io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd :
1222 ubd_dev->fd;
7d314e34 1223 io_req->fds[1] = ubd_dev->fd;
91acb21f 1224 io_req->cow_offset = -1;
1da177e4
LT
1225 io_req->offset = offset;
1226 io_req->length = len;
1227 io_req->error = 0;
91acb21f
JD
1228 io_req->sector_mask = 0;
1229
1230 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
1da177e4 1231 io_req->offsets[0] = 0;
7d314e34 1232 io_req->offsets[1] = ubd_dev->cow.data_offset;
a0044bdf 1233 io_req->buffer = page_address(page) + page_offset;
1da177e4
LT
1234 io_req->sectorsize = 1 << 9;
1235
7d314e34 1236 if(ubd_dev->cow.file != NULL)
a0044bdf
JD
1237 cowify_req(io_req, ubd_dev->cow.bitmap,
1238 ubd_dev->cow.bitmap_offset, ubd_dev->cow.bitmap_len);
91acb21f 1239
1da177e4
LT
1240}
1241
62f96cb0 1242/* Called with dev->lock held */
165125e1 1243static void do_ubd_request(struct request_queue *q)
1da177e4 1244{
2adcec21 1245 struct io_thread_req *io_req;
1da177e4 1246 struct request *req;
0a6d3a2a 1247 int n, last_sectors;
a0044bdf
JD
1248
1249 while(1){
2a9529a0 1250 struct ubd *dev = q->queuedata;
a0044bdf
JD
1251 if(dev->end_sg == 0){
1252 struct request *req = elv_next_request(q);
1253 if(req == NULL)
1254 return;
1255
1256 dev->request = req;
1257 blkdev_dequeue_request(req);
1258 dev->start_sg = 0;
1259 dev->end_sg = blk_rq_map_sg(q, req, dev->sg);
1260 }
1261
1262 req = dev->request;
0a6d3a2a 1263 last_sectors = 0;
a0044bdf
JD
1264 while(dev->start_sg < dev->end_sg){
1265 struct scatterlist *sg = &dev->sg[dev->start_sg];
1266
0a6d3a2a 1267 req->sector += last_sectors;
2adcec21 1268 io_req = kmalloc(sizeof(struct io_thread_req),
990c5587 1269 GFP_ATOMIC);
2adcec21
JD
1270 if(io_req == NULL){
1271 if(list_empty(&dev->restart))
1272 list_add(&dev->restart, &restart);
1273 return;
1274 }
1275 prepare_request(req, io_req,
a0044bdf 1276 (unsigned long long) req->sector << 9,
45711f1a 1277 sg->offset, sg->length, sg_page(sg));
a0044bdf 1278
0a6d3a2a 1279 last_sectors = sg->length >> 9;
a6ea4cce
JD
1280 n = os_write_file(thread_fd, &io_req,
1281 sizeof(struct io_thread_req *));
2adcec21 1282 if(n != sizeof(struct io_thread_req *)){
a0044bdf
JD
1283 if(n != -EAGAIN)
1284 printk("write to io thread failed, "
1285 "errno = %d\n", -n);
1286 else if(list_empty(&dev->restart))
1287 list_add(&dev->restart, &restart);
12429bf9 1288 kfree(io_req);
a0044bdf
JD
1289 return;
1290 }
1291
a0044bdf 1292 dev->start_sg++;
1da177e4 1293 }
a0044bdf
JD
1294 dev->end_sg = 0;
1295 dev->request = NULL;
1da177e4
LT
1296 }
1297}
1298
a885c8c4
CH
1299static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1300{
7d314e34 1301 struct ubd *ubd_dev = bdev->bd_disk->private_data;
a885c8c4
CH
1302
1303 geo->heads = 128;
1304 geo->sectors = 32;
7d314e34 1305 geo->cylinders = ubd_dev->size / (128 * 32 * 512);
a885c8c4
CH
1306 return 0;
1307}
1308
1da177e4
LT
1309static int ubd_ioctl(struct inode * inode, struct file * file,
1310 unsigned int cmd, unsigned long arg)
1311{
7d314e34 1312 struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data;
1da177e4
LT
1313 struct hd_driveid ubd_id = {
1314 .cyls = 0,
1315 .heads = 128,
1316 .sectors = 32,
1317 };
1318
1319 switch (cmd) {
1da177e4 1320 struct cdrom_volctrl volume;
1da177e4 1321 case HDIO_GET_IDENTITY:
7d314e34 1322 ubd_id.cyls = ubd_dev->size / (128 * 32 * 512);
1da177e4
LT
1323 if(copy_to_user((char __user *) arg, (char *) &ubd_id,
1324 sizeof(ubd_id)))
dc764e50
JD
1325 return -EFAULT;
1326 return 0;
b8831a1d 1327
1da177e4
LT
1328 case CDROMVOLREAD:
1329 if(copy_from_user(&volume, (char __user *) arg, sizeof(volume)))
dc764e50 1330 return -EFAULT;
1da177e4
LT
1331 volume.channel0 = 255;
1332 volume.channel1 = 255;
1333 volume.channel2 = 255;
1334 volume.channel3 = 255;
1335 if(copy_to_user((char __user *) arg, &volume, sizeof(volume)))
dc764e50
JD
1336 return -EFAULT;
1337 return 0;
1da177e4 1338 }
dc764e50 1339 return -EINVAL;
1da177e4
LT
1340}
1341
91acb21f 1342static int update_bitmap(struct io_thread_req *req)
1da177e4 1343{
91acb21f 1344 int n;
1da177e4 1345
91acb21f 1346 if(req->cow_offset == -1)
dc764e50 1347 return 0;
1da177e4 1348
91acb21f
JD
1349 n = os_seek_file(req->fds[1], req->cow_offset);
1350 if(n < 0){
1351 printk("do_io - bitmap lseek failed : err = %d\n", -n);
dc764e50 1352 return 1;
91acb21f 1353 }
1da177e4 1354
a6ea4cce
JD
1355 n = os_write_file(req->fds[1], &req->bitmap_words,
1356 sizeof(req->bitmap_words));
91acb21f
JD
1357 if(n != sizeof(req->bitmap_words)){
1358 printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
1359 req->fds[1]);
dc764e50 1360 return 1;
91acb21f 1361 }
1da177e4 1362
dc764e50 1363 return 0;
91acb21f 1364}
1da177e4 1365
5dc62b1b 1366static void do_io(struct io_thread_req *req)
91acb21f
JD
1367{
1368 char *buf;
1369 unsigned long len;
1370 int n, nsectors, start, end, bit;
1371 int err;
1372 __u64 off;
1373
1374 nsectors = req->length / req->sectorsize;
1375 start = 0;
1376 do {
1377 bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
1378 end = start;
1379 while((end < nsectors) &&
1380 (ubd_test_bit(end, (unsigned char *)
1381 &req->sector_mask) == bit))
1382 end++;
1383
1384 off = req->offset + req->offsets[bit] +
1385 start * req->sectorsize;
1386 len = (end - start) * req->sectorsize;
1387 buf = &req->buffer[start * req->sectorsize];
1388
1389 err = os_seek_file(req->fds[bit], off);
1390 if(err < 0){
1391 printk("do_io - lseek failed : err = %d\n", -err);
1392 req->error = 1;
1393 return;
1394 }
1395 if(req->op == UBD_READ){
1396 n = 0;
1397 do {
1398 buf = &buf[n];
1399 len -= n;
a6ea4cce 1400 n = os_read_file(req->fds[bit], buf, len);
91acb21f
JD
1401 if (n < 0) {
1402 printk("do_io - read failed, err = %d "
1403 "fd = %d\n", -n, req->fds[bit]);
1404 req->error = 1;
1405 return;
1406 }
1407 } while((n < len) && (n != 0));
1408 if (n < len) memset(&buf[n], 0, len - n);
1409 } else {
a6ea4cce 1410 n = os_write_file(req->fds[bit], buf, len);
91acb21f
JD
1411 if(n != len){
1412 printk("do_io - write failed err = %d "
1413 "fd = %d\n", -n, req->fds[bit]);
1414 req->error = 1;
1415 return;
1416 }
1417 }
1418
1419 start = end;
1420 } while(start < nsectors);
1da177e4 1421
91acb21f 1422 req->error = update_bitmap(req);
1da177e4 1423}
91acb21f
JD
1424
1425/* Changed in start_io_thread, which is serialized by being called only
1426 * from ubd_init, which is an initcall.
1427 */
1428int kernel_fd = -1;
1429
d8d7c28e
PBG
1430/* Only changed by the io thread. XXX: currently unused. */
1431static int io_count = 0;
91acb21f
JD
1432
1433int io_thread(void *arg)
1434{
2adcec21 1435 struct io_thread_req *req;
91acb21f
JD
1436 int n;
1437
1438 ignore_sigwinch_sig();
1439 while(1){
a6ea4cce 1440 n = os_read_file(kernel_fd, &req,
2adcec21
JD
1441 sizeof(struct io_thread_req *));
1442 if(n != sizeof(struct io_thread_req *)){
91acb21f
JD
1443 if(n < 0)
1444 printk("io_thread - read failed, fd = %d, "
1445 "err = %d\n", kernel_fd, -n);
1446 else {
1447 printk("io_thread - short read, fd = %d, "
1448 "length = %d\n", kernel_fd, n);
1449 }
1450 continue;
1451 }
1452 io_count++;
2adcec21 1453 do_io(req);
a6ea4cce 1454 n = os_write_file(kernel_fd, &req,
2adcec21
JD
1455 sizeof(struct io_thread_req *));
1456 if(n != sizeof(struct io_thread_req *))
91acb21f
JD
1457 printk("io_thread - write failed, fd = %d, err = %d\n",
1458 kernel_fd, -n);
1459 }
91acb21f 1460
1b57e9c2
JD
1461 return 0;
1462}