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