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