--- zzzz-none-000/linux-2.6.19.2/arch/um/drivers/ubd_kern.c 2007-01-10 19:10:37.000000000 +0000 +++ davinci-8020-5505/linux-2.6.19.2/arch/um/drivers/ubd_kern.c 2007-01-11 07:38:19.000000000 +0000 @@ -106,15 +106,10 @@ #define DRIVER_NAME "uml-blkdev" -/* Can be taken in interrupt context, and is passed to the block layer to lock - * the request queue. Kernel side code knows that. */ static DEFINE_SPINLOCK(ubd_io_lock); +static DEFINE_SPINLOCK(ubd_lock); -static DEFINE_MUTEX(ubd_lock); - -/* XXX - this made sense in 2.4 days, now it's only used as a boolean, and - * probably it doesn't make sense even for that. */ -static int do_ubd; +static void (*do_ubd)(void); static int ubd_open(struct inode * inode, struct file * filp); static int ubd_release(struct inode * inode, struct file * file); @@ -122,7 +117,7 @@ unsigned int cmd, unsigned long arg); static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); -#define MAX_DEV (16) +#define MAX_DEV (8) static struct block_device_operations ubd_blops = { .owner = THIS_MODULE, @@ -155,9 +150,8 @@ static struct openflags global_openflags = OPEN_FLAGS; struct cow { - /* backing file name */ + /* This is the backing file, actually */ char *file; - /* backing file fd */ int fd; unsigned long *bitmap; unsigned long bitmap_len; @@ -166,16 +160,14 @@ }; struct ubd { - /* name (and fd, below) of the file opened for writing, either the - * backing or the cow file. */ char *file; int count; int fd; __u64 size; struct openflags boot_openflags; struct openflags openflags; - unsigned shared:1; - unsigned no_cow:1; + int shared; + int no_cow; struct cow cow; struct platform_device pdev; }; @@ -200,7 +192,18 @@ .cow = DEFAULT_COW, \ } -struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; +struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; + +static int ubd0_init(void) +{ + struct ubd *dev = &ubd_dev[0]; + + if(dev->file == NULL) + dev->file = "root_fs"; + return(0); +} + +__initcall(ubd0_init); /* Only changed by fake_ide_setup which is a setup */ static int fake_ide = 0; @@ -274,7 +277,7 @@ return(-1); *ptr = end; } - else if (('a' <= *str) && (*str <= 'z')) { + else if (('a' <= *str) && (*str <= 'h')) { n = *str - 'a'; str++; *ptr = str; @@ -282,13 +285,9 @@ return(n); } -/* If *index_out == -1 at exit, the passed option was a general one; - * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it - * should not be freed on exit. - */ static int ubd_setup_common(char *str, int *index_out) { - struct ubd *ubd_dev; + struct ubd *dev; struct openflags flags = global_openflags; char *backing_file; int n, err, i; @@ -312,7 +311,7 @@ } err = 1; - mutex_lock(&ubd_lock); + spin_lock(&ubd_lock); if(fake_major != MAJOR_NR){ printk(KERN_ERR "Can't assign a fake major twice\n"); goto out1; @@ -324,7 +323,7 @@ major); err = 0; out1: - mutex_unlock(&ubd_lock); + spin_unlock(&ubd_lock); return(err); } @@ -341,10 +340,10 @@ } err = 1; - mutex_lock(&ubd_lock); + spin_lock(&ubd_lock); - ubd_dev = &ubd_devs[n]; - if(ubd_dev->file != NULL){ + dev = &ubd_dev[n]; + if(dev->file != NULL){ printk(KERN_ERR "ubd_setup : device already configured\n"); goto out; } @@ -361,10 +360,10 @@ flags.s = 1; break; case 'd': - ubd_dev->no_cow = 1; + dev->no_cow = 1; break; case 'c': - ubd_dev->shared = 1; + dev->shared = 1; break; case '=': str++; @@ -391,7 +390,7 @@ } if(backing_file){ - if(ubd_dev->no_cow) + if(dev->no_cow) printk(KERN_ERR "Can't specify both 'd' and a " "cow file\n"); else { @@ -399,11 +398,11 @@ backing_file++; } } - ubd_dev->file = str; - ubd_dev->cow.file = backing_file; - ubd_dev->boot_openflags = flags; + dev->file = str; + dev->cow.file = backing_file; + dev->boot_openflags = flags; out: - mutex_unlock(&ubd_lock); + spin_unlock(&ubd_lock); return(err); } @@ -473,9 +472,8 @@ /* Changed by ubd_handler, which is serialized because interrupts only * happen on CPU 0. - * XXX: currently unused. */ -static int intr_count = 0; +int intr_count = 0; /* call ubd_finish if you need to serialize */ static void __ubd_finish(struct request *req, int error) @@ -495,8 +493,6 @@ end_request(req, 1); } -/* Callable only from interrupt context - otherwise you need to do - * spin_lock_irq()/spin_lock_irqsave() */ static inline void ubd_finish(struct request *req, int error) { spin_lock(&ubd_io_lock); @@ -504,15 +500,14 @@ spin_unlock(&ubd_io_lock); } -/* XXX - move this inside ubd_intr. */ -/* Called without ubd_io_lock held, and only in interrupt context. */ +/* Called without ubd_io_lock held */ static void ubd_handler(void) { struct io_thread_req req; struct request *rq = elv_next_request(ubd_queue); int n; - do_ubd = 0; + do_ubd = NULL; intr_count++; n = os_read_file(thread_fd, &req, sizeof(req)); if(n != sizeof(req)){ @@ -526,9 +521,7 @@ ubd_finish(rq, req.error); reactivate_fd(thread_fd, UBD_IRQ); - spin_lock(&ubd_io_lock); do_ubd_request(ubd_queue); - spin_unlock(&ubd_io_lock); } static irqreturn_t ubd_intr(int irq, void *dev) @@ -548,90 +541,87 @@ __uml_exitcall(kill_io_thread); -static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) +static int ubd_file_size(struct ubd *dev, __u64 *size_out) { char *file; - file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; + file = dev->cow.file ? dev->cow.file : dev->file; return(os_file_size(file, size_out)); } -static void ubd_close_dev(struct ubd *ubd_dev) +static void ubd_close(struct ubd *dev) { - os_close_file(ubd_dev->fd); - if(ubd_dev->cow.file == NULL) + os_close_file(dev->fd); + if(dev->cow.file == NULL) return; - os_close_file(ubd_dev->cow.fd); - vfree(ubd_dev->cow.bitmap); - ubd_dev->cow.bitmap = NULL; + os_close_file(dev->cow.fd); + vfree(dev->cow.bitmap); + dev->cow.bitmap = NULL; } -static int ubd_open_dev(struct ubd *ubd_dev) +static int ubd_open_dev(struct ubd *dev) { struct openflags flags; char **back_ptr; int err, create_cow, *create_ptr; - int fd; - ubd_dev->openflags = ubd_dev->boot_openflags; + dev->openflags = dev->boot_openflags; create_cow = 0; - create_ptr = (ubd_dev->cow.file != NULL) ? &create_cow : NULL; - back_ptr = ubd_dev->no_cow ? NULL : &ubd_dev->cow.file; - - fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared, - back_ptr, &ubd_dev->cow.bitmap_offset, - &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset, + create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; + back_ptr = dev->no_cow ? NULL : &dev->cow.file; + dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared, + back_ptr, &dev->cow.bitmap_offset, + &dev->cow.bitmap_len, &dev->cow.data_offset, create_ptr); - if((fd == -ENOENT) && create_cow){ - fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file, - ubd_dev->openflags, 1 << 9, PAGE_SIZE, - &ubd_dev->cow.bitmap_offset, - &ubd_dev->cow.bitmap_len, - &ubd_dev->cow.data_offset); - if(fd >= 0){ + if((dev->fd == -ENOENT) && create_cow){ + dev->fd = create_cow_file(dev->file, dev->cow.file, + dev->openflags, 1 << 9, PAGE_SIZE, + &dev->cow.bitmap_offset, + &dev->cow.bitmap_len, + &dev->cow.data_offset); + if(dev->fd >= 0){ printk(KERN_INFO "Creating \"%s\" as COW file for " - "\"%s\"\n", ubd_dev->file, ubd_dev->cow.file); + "\"%s\"\n", dev->file, dev->cow.file); } } - if(fd < 0){ - printk("Failed to open '%s', errno = %d\n", ubd_dev->file, - -fd); - return fd; + if(dev->fd < 0){ + printk("Failed to open '%s', errno = %d\n", dev->file, + -dev->fd); + return(dev->fd); } - ubd_dev->fd = fd; - if(ubd_dev->cow.file != NULL){ + if(dev->cow.file != NULL){ err = -ENOMEM; - ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len); - if(ubd_dev->cow.bitmap == NULL){ + dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); + if(dev->cow.bitmap == NULL){ printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); goto error; } flush_tlb_kernel_vm(); - err = read_cow_bitmap(ubd_dev->fd, ubd_dev->cow.bitmap, - ubd_dev->cow.bitmap_offset, - ubd_dev->cow.bitmap_len); + err = read_cow_bitmap(dev->fd, dev->cow.bitmap, + dev->cow.bitmap_offset, + dev->cow.bitmap_len); if(err < 0) goto error; - flags = ubd_dev->openflags; + flags = dev->openflags; flags.w = 0; - err = open_ubd_file(ubd_dev->cow.file, &flags, ubd_dev->shared, NULL, + err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL, NULL, NULL, NULL, NULL); if(err < 0) goto error; - ubd_dev->cow.fd = err; + dev->cow.fd = err; } return(0); error: - os_close_file(ubd_dev->fd); + os_close_file(dev->fd); return(err); } -static int ubd_disk_register(int major, u64 size, int unit, +static int ubd_new_disk(int major, u64 size, int unit, struct gendisk **disk_out) { @@ -652,13 +642,13 @@ /* sysfs register (not for ide fake devices) */ if (major == MAJOR_NR) { - ubd_devs[unit].pdev.id = unit; - ubd_devs[unit].pdev.name = DRIVER_NAME; - platform_device_register(&ubd_devs[unit].pdev); - disk->driverfs_dev = &ubd_devs[unit].pdev.dev; + ubd_dev[unit].pdev.id = unit; + ubd_dev[unit].pdev.name = DRIVER_NAME; + platform_device_register(&ubd_dev[unit].pdev); + disk->driverfs_dev = &ubd_dev[unit].pdev.dev; } - disk->private_data = &ubd_devs[unit]; + disk->private_data = &ubd_dev[unit]; disk->queue = ubd_queue; add_disk(disk); @@ -670,25 +660,25 @@ static int ubd_add(int n) { - struct ubd *ubd_dev = &ubd_devs[n]; + struct ubd *dev = &ubd_dev[n]; int err; err = -ENODEV; - if(ubd_dev->file == NULL) + if(dev->file == NULL) goto out; - err = ubd_file_size(ubd_dev, &ubd_dev->size); + err = ubd_file_size(dev, &dev->size); if(err < 0) goto out; - ubd_dev->size = ROUND_BLOCK(ubd_dev->size); + dev->size = ROUND_BLOCK(dev->size); - err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); + err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); if(err) goto out; if(fake_major != MAJOR_NR) - ubd_disk_register(fake_major, ubd_dev->size, n, + ubd_new_disk(fake_major, dev->size, n, &fake_gendisk[n]); /* perhaps this should also be under the "if (fake_major)" above */ @@ -703,41 +693,32 @@ static int ubd_config(char *str) { - int n, ret; + int n, err; str = kstrdup(str, GFP_KERNEL); - if (str == NULL) { + if(str == NULL){ printk(KERN_ERR "ubd_config failed to strdup string\n"); - ret = 1; - goto out; + return(1); } - ret = ubd_setup_common(str, &n); - if (ret) { - ret = -1; - goto err_free; - } - if (n == -1) { - ret = 0; - goto err_free; + err = ubd_setup_common(str, &n); + if(err){ + kfree(str); + return(-1); } + if(n == -1) return(0); - mutex_lock(&ubd_lock); - ret = ubd_add(n); - if (ret) - ubd_devs[n].file = NULL; - mutex_unlock(&ubd_lock); - -out: - return ret; + spin_lock(&ubd_lock); + err = ubd_add(n); + if(err) + ubd_dev[n].file = NULL; + spin_unlock(&ubd_lock); -err_free: - kfree(str); - goto out; + return(err); } static int ubd_get_config(char *name, char *str, int size, char **error_out) { - struct ubd *ubd_dev; + struct ubd *dev; int n, len = 0; n = parse_unit(&name); @@ -746,24 +727,24 @@ return(-1); } - ubd_dev = &ubd_devs[n]; - mutex_lock(&ubd_lock); + dev = &ubd_dev[n]; + spin_lock(&ubd_lock); - if(ubd_dev->file == NULL){ + if(dev->file == NULL){ CONFIG_CHUNK(str, size, len, "", 1); goto out; } - CONFIG_CHUNK(str, size, len, ubd_dev->file, 0); + CONFIG_CHUNK(str, size, len, dev->file, 0); - if(ubd_dev->cow.file != NULL){ + if(dev->cow.file != NULL){ CONFIG_CHUNK(str, size, len, ",", 0); - CONFIG_CHUNK(str, size, len, ubd_dev->cow.file, 1); + CONFIG_CHUNK(str, size, len, dev->cow.file, 1); } else CONFIG_CHUNK(str, size, len, "", 1); out: - mutex_unlock(&ubd_lock); + spin_unlock(&ubd_lock); return(len); } @@ -779,22 +760,22 @@ static int ubd_remove(int n) { - struct ubd *ubd_dev; + struct ubd *dev; int err = -ENODEV; - mutex_lock(&ubd_lock); + spin_lock(&ubd_lock); if(ubd_gendisk[n] == NULL) goto out; - ubd_dev = &ubd_devs[n]; + dev = &ubd_dev[n]; - if(ubd_dev->file == NULL) + if(dev->file == NULL) goto out; /* you cannot remove a open disk */ err = -EBUSY; - if(ubd_dev->count > 0) + if(dev->count > 0) goto out; del_gendisk(ubd_gendisk[n]); @@ -807,15 +788,14 @@ fake_gendisk[n] = NULL; } - platform_device_unregister(&ubd_dev->pdev); - *ubd_dev = ((struct ubd) DEFAULT_UBD); + platform_device_unregister(&dev->pdev); + *dev = ((struct ubd) DEFAULT_UBD); err = 0; out: - mutex_unlock(&ubd_lock); + spin_unlock(&ubd_lock); return err; } -/* All these are called by mconsole in process context and without ubd-specific locks. */ static struct mc_device ubd_mc = { .name = "ubd", .config = ubd_config, @@ -824,7 +804,7 @@ .remove = ubd_remove, }; -static int __init ubd_mc_init(void) +static int ubd_mc_init(void) { mconsole_register_dev(&ubd_mc); return 0; @@ -832,24 +812,13 @@ __initcall(ubd_mc_init); -static int __init ubd0_init(void) -{ - struct ubd *ubd_dev = &ubd_devs[0]; - - if(ubd_dev->file == NULL) - ubd_dev->file = "root_fs"; - return(0); -} - -__initcall(ubd0_init); - static struct platform_driver ubd_driver = { .driver = { .name = DRIVER_NAME, }, }; -static int __init ubd_init(void) +int ubd_init(void) { int i; @@ -877,7 +846,7 @@ late_initcall(ubd_init); -static int __init ubd_driver_init(void){ +int ubd_driver_init(void){ unsigned long stack; int err; @@ -898,7 +867,7 @@ return(0); } err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, - IRQF_DISABLED, "ubd", ubd_devs); + IRQF_DISABLED, "ubd", ubd_dev); if(err != 0) printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); return 0; @@ -909,24 +878,24 @@ static int ubd_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct ubd *ubd_dev = disk->private_data; + struct ubd *dev = disk->private_data; int err = 0; - if(ubd_dev->count == 0){ - err = ubd_open_dev(ubd_dev); + if(dev->count == 0){ + err = ubd_open_dev(dev); if(err){ printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", - disk->disk_name, ubd_dev->file, -err); + disk->disk_name, dev->file, -err); goto out; } } - ubd_dev->count++; - set_disk_ro(disk, !ubd_dev->openflags.w); + dev->count++; + set_disk_ro(disk, !dev->openflags.w); /* This should no more be needed. And it didn't work anyway to exclude * read-write remounting of filesystems.*/ - /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){ - if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); + /*if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ + if(--dev->count == 0) ubd_close(dev); err = -EROFS; }*/ out: @@ -936,10 +905,10 @@ static int ubd_release(struct inode * inode, struct file * file) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct ubd *ubd_dev = disk->private_data; + struct ubd *dev = disk->private_data; - if(--ubd_dev->count == 0) - ubd_close_dev(ubd_dev); + if(--dev->count == 0) + ubd_close(dev); return(0); } @@ -1007,12 +976,12 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) { struct gendisk *disk = req->rq_disk; - struct ubd *ubd_dev = disk->private_data; + struct ubd *dev = disk->private_data; __u64 offset; int len; /* This should be impossible now */ - if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){ + if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ printk("Write attempted on readonly ubd device %s\n", disk->disk_name); end_request(req, 0); @@ -1022,8 +991,8 @@ offset = ((__u64) req->sector) << 9; len = req->current_nr_sectors << 9; - io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd; - io_req->fds[1] = ubd_dev->fd; + io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; + io_req->fds[1] = dev->fd; io_req->cow_offset = -1; io_req->offset = offset; io_req->length = len; @@ -1032,13 +1001,13 @@ io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; io_req->offsets[0] = 0; - io_req->offsets[1] = ubd_dev->cow.data_offset; + io_req->offsets[1] = dev->cow.data_offset; io_req->buffer = req->buffer; io_req->sectorsize = 1 << 9; - if(ubd_dev->cow.file != NULL) - cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset, - ubd_dev->cow.bitmap_len); + if(dev->cow.file != NULL) + cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, + dev->cow.bitmap_len); return(0); } @@ -1064,7 +1033,7 @@ return; err = prepare_request(req, &io_req); if(!err){ - do_ubd = 1; + do_ubd = ubd_handler; n = os_write_file(thread_fd, (char *) &io_req, sizeof(io_req)); if(n != sizeof(io_req)) @@ -1076,18 +1045,18 @@ static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) { - struct ubd *ubd_dev = bdev->bd_disk->private_data; + struct ubd *dev = bdev->bd_disk->private_data; geo->heads = 128; geo->sectors = 32; - geo->cylinders = ubd_dev->size / (128 * 32 * 512); + geo->cylinders = dev->size / (128 * 32 * 512); return 0; } static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data; + struct ubd *dev = inode->i_bdev->bd_disk->private_data; struct hd_driveid ubd_id = { .cyls = 0, .heads = 128, @@ -1097,7 +1066,7 @@ switch (cmd) { struct cdrom_volctrl volume; case HDIO_GET_IDENTITY: - ubd_id.cyls = ubd_dev->size / (128 * 32 * 512); + ubd_id.cyls = dev->size / (128 * 32 * 512); if(copy_to_user((char __user *) arg, (char *) &ubd_id, sizeof(ubd_id))) return(-EFAULT); @@ -1384,8 +1353,8 @@ */ int kernel_fd = -1; -/* Only changed by the io thread. XXX: currently unused. */ -static int io_count = 0; +/* Only changed by the io thread */ +int io_count = 0; int io_thread(void *arg) {