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