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