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