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