summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcvs-fast-export <cvs-fast-export>2002-07-21 22:06:46 +0000
committercvs-fast-export <cvs-fast-export>2002-07-21 22:06:46 +0000
commit77fef6c99d083f485c94d757c34a359dee107b18 (patch)
tree36a7617c7076430a8e5a433b5974ac95573e372d
parent8ef331c2a7c80ea47f2d4a144e4bbcc9676a68fe (diff)
downloaduml-history-v_2_4_18_42.tar.gz
Synthetic commit for tag v_2_4_18_42v_2_4_18_42
-rw-r--r--arch/um/drivers/harddog.c192
-rw-r--r--arch/um/drivers/port.c190
-rw-r--r--arch/um/drivers/ubd.c924
3 files changed, 0 insertions, 1306 deletions
diff --git a/arch/um/drivers/harddog.c b/arch/um/drivers/harddog.c
deleted file mode 100644
index e2214e1..0000000
--- a/arch/um/drivers/harddog.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/* UML hardware watchdog, shamelessly stolen from:
- *
- * SoftDog 0.05: A Software Watchdog Device
- *
- * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- * http://www.redhat.com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
- * warranty for any of this software. This material is provided
- * "AS-IS" and at no charge.
- *
- * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
- *
- * Software only watchdog driver. Unlike its big brother the WDT501P
- * driver this won't always recover a failed machine.
- *
- * 03/96: Angelo Haritsis <ah@doc.ic.ac.uk> :
- * Modularised.
- * Added soft_margin; use upon insmod to change the timer delay.
- * NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate
- * minors.
- *
- * 19980911 Alan Cox
- * Made SMP safe for 2.3.x
- *
- * 20011127 Joel Becker (jlbec@evilplan.org>
- * Added soft_noboot; Allows testing the softdog trigger without
- * requiring a recompile.
- * Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
- */
-
-#include <linux/module.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include "helper.h"
-#include "mconsole.h"
-
-MODULE_LICENSE("GPL");
-
-static int timer_alive;
-
-static int harddog_in_fd = -1;
-static int harddog_out_fd = -1;
-
-/*
- * Allow only one person to hold it open
- */
-
-extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock);
-
-static int harddog_open(struct inode *inode, struct file *file)
-{
- int err;
- char *sock = NULL;
-
- if(timer_alive)
- return -EBUSY;
-#ifdef CONFIG_HARDDOG_NOWAYOUT
- MOD_INC_USE_COUNT;
-#endif
-
-#ifdef CONFIG_MCONSOLE
- sock = mconsole_notify_socket();
-#endif
- err = start_watchdog(&harddog_in_fd, &harddog_out_fd, sock);
- if(err) return(err);
-
- timer_alive = 1;
- return 0;
-}
-
-extern void stop_watchdog(int in_fd, int out_fd);
-
-static int harddog_release(struct inode *inode, struct file *file)
-{
- /*
- * Shut off the timer.
- */
- lock_kernel();
-
- stop_watchdog(harddog_in_fd, harddog_out_fd);
- harddog_in_fd = -1;
- harddog_out_fd = -1;
-
- timer_alive=0;
- unlock_kernel();
- return 0;
-}
-
-extern int ping_watchdog(int fd);
-
-static ssize_t harddog_write(struct file *file, const char *data, size_t len,
- loff_t *ppos)
-{
- /* Can't seek (pwrite) on this device */
- if (ppos != &file->f_pos)
- return -ESPIPE;
-
- /*
- * Refresh the timer.
- */
- if(len)
- return(ping_watchdog(harddog_out_fd));
- return 0;
-}
-
-static int harddog_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- static struct watchdog_info ident = {
- WDIOF_SETTIMEOUT,
- 0,
- "UML Hardware Watchdog"
- };
- switch (cmd) {
- default:
- return -ENOTTY;
- case WDIOC_GETSUPPORT:
- if(copy_to_user((struct harddog_info *)arg, &ident,
- sizeof(ident)))
- return -EFAULT;
- return 0;
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- return put_user(0,(int *)arg);
- case WDIOC_KEEPALIVE:
- return(ping_watchdog(harddog_out_fd));
- }
-}
-
-static struct file_operations harddog_fops = {
- owner: THIS_MODULE,
- write: harddog_write,
- ioctl: harddog_ioctl,
- open: harddog_open,
- release: harddog_release,
-};
-
-static struct miscdevice harddog_miscdev = {
- minor: WATCHDOG_MINOR,
- name: "watchdog",
- fops: &harddog_fops,
-};
-
-static char banner[] __initdata = KERN_INFO "UML Watchdog Timer\n";
-
-static int __init harddog_init(void)
-{
- int ret;
-
- ret = misc_register(&harddog_miscdev);
-
- if (ret)
- return ret;
-
- printk(banner);
-
- return(0);
-}
-
-static void __exit harddog_exit(void)
-{
- misc_deregister(&harddog_miscdev);
-}
-
-module_init(harddog_init);
-module_exit(harddog_exit);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/port.c b/arch/um/drivers/port.c
deleted file mode 100644
index 556c174..0000000
--- a/arch/um/drivers/port.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <termios.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "chan_user.h"
-#include "port.h"
-#include "helper.h"
-#include "os.h"
-
-struct port_chan {
- int raw;
- struct termios tt;
- void *kernel_data;
-};
-
-void *port_init(char *str, int device, struct chan_opts *opts)
-{
- struct port_chan *data;
- void *kern_data;
- char *end;
- int port;
-
- if(*str != ':'){
- printk("port_init : channel type 'port' must specify a "
- "port number\n");
- return(NULL);
- }
- str++;
- port = strtoul(str, &end, 0);
- if(*end != '\0'){
- printk("port_init : couldn't parse port '%s'\n", str);
- return(NULL);
- }
-
- if((kern_data = port_data(port)) == NULL) return(NULL);
-
- if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
- *data = ((struct port_chan) { raw : opts->raw,
- kernel_data : kern_data });
-
- return(data);
-}
-
-int port_open(int input, int output, int primary, void *d)
-{
- struct port_chan *data = d;
- int fd;
-
- fd = port_wait(data->kernel_data);
- if((fd >= 0) && data->raw){
- tcgetattr(fd, &data->tt);
- raw(fd, 0);
- }
- return(fd);
-}
-
-void port_close(int fd, void *d)
-{
- struct port_chan *data = d;
-
- port_remove_dev(data->kernel_data);
- close(fd);
-}
-
-int port_console_write(int fd, const char *buf, int n, void *d)
-{
- struct port_chan *data = d;
-
- return(generic_console_write(fd, buf, n, &data->tt));
-}
-
-void port_free(void *d)
-{
- struct port_chan *data = d;
-
- port_kern_free(data->kernel_data);
- kfree(data);
-}
-
-struct chan_ops port_ops = {
- init: port_init,
- open: port_open,
- close: generic_close,
- read: generic_read,
- write: generic_write,
- console_write: port_console_write,
- window_size: generic_window_size,
- free: port_free,
- winch: 1,
-};
-
-int port_listen_fd(int port)
-{
- struct sockaddr_in addr;
- int fd, err;
-
- fd = socket(PF_INET, SOCK_STREAM, 0);
- if(fd == -1) return(-errno);
-
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){
- err = -errno;
- goto out;
- }
-
- if(listen(fd, 1) < 0){
- err = -errno;
- goto out;
- }
-
- return(fd);
- out:
- os_close_file(fd);
- return(err);
-}
-
-struct port_pre_exec_data {
- int sock_fd;
- int pipe_fd;
-};
-
-void port_pre_exec(void *arg)
-{
- struct port_pre_exec_data *data = arg;
-
- dup2(data->sock_fd, 0);
- dup2(data->sock_fd, 1);
- dup2(data->sock_fd, 2);
- close(data->sock_fd);
- dup2(data->pipe_fd, 3);
- shutdown(3, SHUT_RD);
- close(data->pipe_fd);
-}
-
-int port_connection(int fd, int *socket)
-{
- int new, err;
- char *argv[] = { "/usr/sbin/in.telnetd", "-L",
- "/usr/lib/uml/port-helper", NULL };
- struct port_pre_exec_data data;
-
- if((new = accept(fd, NULL, 0)) < 0) return(-errno);
-
- err = os_pipe(socket, 0);
- if(err) goto out_close;
-
- data = ((struct port_pre_exec_data)
- { sock_fd : new,
- pipe_fd : socket[1] });
-
- err = run_helper(port_pre_exec, &data, argv, NULL);
- if(err < 0) goto out_shutdown;
-
- return(new);
-
- out_shutdown:
- shutdown(socket[0], SHUT_RDWR);
- close(socket[0]);
- shutdown(socket[1], SHUT_RDWR);
- close(socket[1]);
- out_close:
- close(new);
- return(err);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/ubd.c b/arch/um/drivers/ubd.c
deleted file mode 100644
index 197071d..0000000
--- a/arch/um/drivers/ubd.c
+++ /dev/null
@@ -1,924 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-/* 2001-09-28...2002-04-17
- * Partition stuff by James_McMechan@hotmail.com
- * old style ubd by setting UBD_SHIFT to 0
- */
-
-#define MAJOR_NR UBD_MAJOR
-#define UBD_SHIFT 4
-
-#include "linux/config.h"
-#include "linux/blk.h"
-#include "linux/blkdev.h"
-#include "linux/hdreg.h"
-#include "linux/init.h"
-#include "linux/devfs_fs_kernel.h"
-#include "linux/cdrom.h"
-#include "linux/proc_fs.h"
-#include "linux/ctype.h"
-#include "linux/capability.h"
-#include "linux/mm.h"
-#include "linux/vmalloc.h"
-#include "linux/blkpg.h"
-#include "linux/genhd.h"
-#include "asm/segment.h"
-#include "asm/uaccess.h"
-#include "asm/irq.h"
-#include "asm/types.h"
-#include "user_util.h"
-#include "mem_user.h"
-#include "kern_util.h"
-#include "kern.h"
-#include "mconsole_kern.h"
-#include "init.h"
-#include "irq_user.h"
-#include "ubd_user.h"
-#include "2_5compat.h"
-#include "os.h"
-
-static int ubd_open(struct inode * inode, struct file * filp);
-static int ubd_release(struct inode * inode, struct file * file);
-static int ubd_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd, unsigned long arg);
-static int ubd_revalidate(kdev_t rdev);
-
-#define MAX_DEV (8)
-#define MAX_MINOR (MAX_DEV << UBD_SHIFT)
-
-/* block size in bytes */
-static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE };
-
-/* number of bytes per sector */
-static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 };
-
-/* device size in KB */
-static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 };
-
-static struct block_device_operations ubd_blops = {
- open: ubd_open,
- release: ubd_release,
- ioctl: ubd_ioctl,
- revalidate: ubd_revalidate,
-};
-
-static struct hd_struct ubd_part[MAX_MINOR] =
- { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } };
-
-static request_queue_t *ubd_queue;
-
-static int fake_major = 0;
-
-#define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \
-{ \
- major : maj, \
- major_name : name, \
- minor_shift : shift, \
- max_p : 1 << shift, \
- part : parts, \
- sizes : bsizes, \
- nr_real : max, \
- real_devices : NULL, \
- next : NULL, \
- fops : blops, \
- de_arr : NULL, \
- flags : 0 \
-}
-
-static struct gendisk ubd_gendisk = INIT_GENDISK(MAJOR_NR, "ubd", ubd_part,
- UBD_SHIFT, sizes, MAX_DEV,
- &ubd_blops);
-static struct gendisk fake_gendisk = INIT_GENDISK(0, "ubd", ubd_part,
- UBD_SHIFT, sizes, MAX_DEV,
- &ubd_blops);
-
-#ifdef CONFIG_BLK_DEV_UBD_SYNC
-#define OPEN_FLAGS ((struct openflags) { r : 1, w : 1, s : 1, c : 0 })
-#else
-#define OPEN_FLAGS ((struct openflags) { r : 1, w : 1, s : 0, c : 0 })
-#endif
-
-static struct openflags global_openflags = OPEN_FLAGS;
-
-struct cow {
- char *file;
- int fd;
- unsigned long *bitmap;
- unsigned long bitmap_len;
- int bitmap_offset;
- int data_offset;
-};
-
-struct ubd {
- char *file;
- int is_dir;
- int count;
- int fd;
- __u64 size;
- struct openflags boot_openflags;
- struct openflags openflags;
- devfs_handle_t real;
- devfs_handle_t fake;
- struct cow cow;
-};
-
-#define DEFAULT_COW { \
- file: NULL, \
- fd: -1, \
- bitmap: NULL, \
- bitmap_offset: 0, \
- data_offset: 0, \
-}
-
-#define DEFAULT_UBD { \
- file: NULL, \
- is_dir: 0, \
- count: 0, \
- fd: -1, \
- size: -1, \
- boot_openflags: OPEN_FLAGS, \
- openflags: OPEN_FLAGS, \
- real: NULL, \
- fake: NULL, \
- cow: DEFAULT_COW, \
-}
-
-struct ubd ubd_dev[MAX_DEV] = {
-{
- file: "root_fs",
- is_dir: 0,
- count: 0,
- fd: -1,
- size: 0,
- boot_openflags: OPEN_FLAGS,
- openflags: OPEN_FLAGS,
- real: NULL,
- fake: NULL,
- cow: DEFAULT_COW,
-},
-[ 1 ... MAX_DEV - 1 ] = DEFAULT_UBD
-};
-
-static struct hd_driveid ubd_id = {
- cyls: 0,
- heads: 128,
- sectors: 32,
-};
-
-static int fake_ide = 0;
-static struct proc_dir_entry *proc_ide_root = NULL;
-static struct proc_dir_entry *proc_ide = NULL;
-
-static void make_proc_ide(void)
-{
- proc_ide_root = proc_mkdir("ide", 0);
- proc_ide = proc_mkdir("ide0", proc_ide_root);
-}
-
-static int proc_ide_read_media(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- int len;
-
- strcpy(page, "disk\n");
- len = strlen("disk\n");
- len -= off;
- if (len < count){
- *eof = 1;
- if (len <= 0) return 0;
- }
- else len = count;
- *start = page + off;
- return len;
-
-}
-
-static void make_ide_entries(char *dev_name)
-{
- struct proc_dir_entry *dir, *ent;
- char name[64];
-
- if(!fake_ide) return;
- if(proc_ide_root == NULL) make_proc_ide();
- dir = proc_mkdir(dev_name, proc_ide);
- ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir);
- if(!ent) return;
- ent->nlink = 1;
- ent->data = NULL;
- ent->read_proc = proc_ide_read_media;
- ent->write_proc = NULL;
- sprintf(name,"ide0/%s", dev_name);
- proc_symlink(dev_name, proc_ide_root, name);
-}
-
-static int fake_ide_setup(char *str)
-{
- fake_ide = 1;
- return(1);
-}
-
-__setup("fake_ide", fake_ide_setup);
-
-__uml_help(fake_ide_setup,
-"fake_ide\n"
-" Create ide0 entries that map onto ubd devices.\n\n"
-);
-
-static int ubd_setup_common(char *str, int *index_out)
-{
- struct openflags flags = global_openflags;
- char *backing_file;
- int n;
-
- if(index_out) *index_out = -1;
- n = *str++;
- if(n == '='){
- char *end;
- int major;
-
- if(!strcmp(str, "sync")){
- global_openflags.s = 1;
- return(0);
- }
- major = simple_strtoul(str, &end, 0);
- if(*end != '\0'){
- printk(KERN_ERR
- "ubd_setup : didn't parse major number\n");
- return(1);
- }
- fake_gendisk.major = major;
- fake_major = major;
- printk(KERN_INFO "Setting extra ubd major number to %d\n",
- major);
- return(0);
- }
-
- if(n < '0'){
- printk(KERN_ERR "ubd_setup : index out of range\n"); }
-
- if((n >= '0') && (n <= '9')) n -= '0';
- else if((n >= 'a') && (n <= 'z')) n -= 'a';
- else {
- printk(KERN_ERR "ubd_setup : device syntax invalid\n");
- return(1);
- }
- if(n >= MAX_DEV){
- printk(KERN_ERR "ubd_setup : index out of range "
- "(%d devices)\n", MAX_DEV);
- return(1);
- }
- if(index_out) *index_out = n;
-
- if (*str == 'r'){
- flags.w = 0;
- str++;
- }
- if (*str == 's'){
- flags.s = 1;
- str++;
- }
- if(*str++ != '='){
- printk(KERN_ERR "ubd_setup : Expected '='\n");
- return(1);
- }
- backing_file = strchr(str, ',');
- if(backing_file){
- *backing_file = '\0';
- backing_file++;
- }
- ubd_dev[n].file = str;
- ubd_dev[n].cow.file = backing_file;
- ubd_dev[n].boot_openflags = flags;
- return(0);
-}
-
-static int ubd_setup(char *str)
-{
- ubd_setup_common(str, NULL);
- return(1);
-}
-
-__setup("ubd", ubd_setup);
-__uml_help(ubd_setup,
-"ubd<n>=<filename>\n"
-" This is used to associate a device with a file in the underlying\n"
-" filesystem. Usually, there is a filesystem in the file, but \n"
-" that's not required. Swap devices containing swap files can be\n"
-" specified like this. Also, a file which doesn't contain a\n"
-" filesystem can have its contents read in the virtual \n"
-" machine by running dd on the device. n must be in the range\n"
-" 0 to 7. Appending an 'r' to the number will cause that device\n"
-" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n"
-" an 's' (has to be _after_ 'r', if there is one) will cause data\n"
-" to be written to disk on the host immediately.\n\n"
-);
-
-static int fakehd(char *str)
-{
- printk(KERN_INFO
- "fakehd : Changing ubd_gendisk.major_name to \"hd\".\n");
- ubd_gendisk.major_name = "hd";
- return(1);
-}
-
-__setup("fakehd", fakehd);
-__uml_help(fakehd,
-"fakehd\n"
-" Change the ubd device name to \"hd\".\n\n"
-);
-
-static void do_ubd_request(request_queue_t * q);
-
-int thread_fd = -1;
-
-int intr_count = 0;
-
-static void ubd_finish(int error)
-{
- int nsect;
-
- if(error){
- end_request(0);
- return;
- }
- nsect = CURRENT->current_nr_sectors;
- CURRENT->sector += nsect;
- CURRENT->buffer += nsect << 9;
- CURRENT->errors = 0;
- CURRENT->nr_sectors -= nsect;
- CURRENT->current_nr_sectors = 0;
- end_request(1);
-}
-
-static void ubd_handler(void)
-{
- struct io_thread_req req;
- int n;
-
- DEVICE_INTR = NULL;
- intr_count++;
- n = read_ubd_fs(thread_fd, &req, sizeof(req));
- if(n != sizeof(req)){
- printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
- "errno = %d\n", os_getpid(), -n);
- spin_lock(&REQUEST_LOCK);
- end_request(0);
- spin_unlock(&REQUEST_LOCK);
- return;
- }
-
- if((req.offset != ((__u64) (CURRENT->sector)) << 9) ||
- (req.length != (CURRENT->current_nr_sectors) << 9))
- panic("I/O op mismatch");
-
- spin_lock(&REQUEST_LOCK);
- ubd_finish(req.error);
- reactivate_fd(thread_fd, UBD_IRQ);
- do_ubd_request(ubd_queue);
- spin_unlock(&REQUEST_LOCK);
-}
-
-static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
-{
- ubd_handler();
-}
-
-static int io_pid = -1;
-
-void kill_io_thread(void)
-{
- if(io_pid != -1) kill(io_pid, SIGKILL);
-}
-
-__uml_exitcall(kill_io_thread);
-
-int sync = 0;
-
-devfs_handle_t ubd_dir_handle;
-devfs_handle_t ubd_fake_dir_handle;
-
-static int ubd_add(int n)
-{
- char name[sizeof("nnnnnn\0")], dev_name[sizeof("ubd0x")];
-
- if(ubd_dev[n].file == NULL) return(-1);
- sprintf(name, "%d", n);
- ubd_dev[n].real = devfs_register(ubd_dir_handle, name,
- DEVFS_FL_REMOVABLE, MAJOR_NR,
- n << UBD_SHIFT,
- S_IFBLK | S_IRUSR | S_IWUSR |
- S_IRGRP |S_IWGRP,
- &ubd_blops, NULL);
- if(fake_major != 0){
- ubd_dev[n].fake = devfs_register(ubd_fake_dir_handle, name,
- DEVFS_FL_REMOVABLE,
- fake_major, n << UBD_SHIFT,
- S_IFBLK | S_IRUSR |
- S_IWUSR | S_IRGRP | S_IWGRP,
- &ubd_blops, NULL);
- }
- if(!strcmp(ubd_gendisk.major_name, "ubd")){
- sprintf(dev_name, "%s%d", ubd_gendisk.major_name, n);
- }
- else sprintf(dev_name, "%s%c", ubd_gendisk.major_name,
- n + 'a');
- make_ide_entries(dev_name);
- ubd_revalidate(MKDEV(MAJOR_NR, n << UBD_SHIFT));
- return(0);
-}
-
-static int ubd_config(char *str)
-{
- int n, err;
-
- str = uml_strdup(str);
- if(str == NULL){
- printk(KERN_ERR "ubd_config failed to strdup string\n");
- return(1);
- }
- err = ubd_setup_common(str, &n);
- if(err){
- kfree(str);
- return(-1);
- }
- if(n != -1) ubd_add(n);
- return(0);
-}
-
-static int ubd_remove(char *str)
-{
- struct ubd *dev;
- int n;
-
- if(!isdigit(*str)) return(-1);
- n = *str - '0';
- if(n > MAX_DEV) return(-1);
- dev = &ubd_dev[n];
- if(dev->file == NULL) return(0);
- if(dev->count > 0) return(-1);
- if(dev->real != NULL) devfs_unregister(dev->real);
- if(dev->fake != NULL) devfs_unregister(dev->fake);
- *dev = ((struct ubd) DEFAULT_UBD);
- return(0);
-}
-
-static struct mc_device ubd_mc = {
- name: "ubd",
- config: ubd_config,
- remove: ubd_remove,
-};
-
-int ubd_mc_init(void)
-{
- mconsole_register_dev(&ubd_mc);
- return(0);
-}
-
-__initcall(ubd_mc_init);
-
-static request_queue_t *ubd_get_queue(kdev_t device)
-{
- return(ubd_queue);
-}
-
-int ubd_init(void)
-{
- unsigned long stack;
- int i, err;
-
- ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL);
- if (devfs_register_blkdev(MAJOR_NR, "ubd", &ubd_blops)) {
- printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR);
- return -1;
- }
- ubd_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
- INIT_QUEUE(ubd_queue, DEVICE_REQUEST, &ubd_lock);
- INIT_ELV(ubd_queue, &ubd_queue->elevator);
- read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
- blksize_size[MAJOR_NR] = blk_sizes;
- blk_size[MAJOR_NR] = sizes;
- INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes);
- add_gendisk(&ubd_gendisk);
- if (fake_major != 0){
- char name[sizeof("ubd_nnn\0")];
-
- snprintf(name, sizeof(name), "ubd_%d", fake_major);
- ubd_fake_dir_handle = devfs_mk_dir(NULL, name, NULL);
- if(devfs_register_blkdev(fake_major, "ubd", &ubd_blops)) {
- printk(KERN_ERR "ubd: unable to get major %d\n",
- fake_major);
- return -1;
- }
- blk_dev[fake_major].queue = ubd_get_queue;
- read_ahead[fake_major] = 8; /* 8 sector (4kB) read-ahead */
- blksize_size[fake_major] = blk_sizes;
- blk_size[fake_major] = sizes;
- INIT_HARDSECT(hardsect_size, fake_major, hardsect_sizes);
- add_gendisk(&fake_gendisk);
- }
- for(i=0;i<MAX_DEV;i++) ubd_add(i);
- if(sync){
- printk(KERN_INFO "ubd : Synchronous mode\n");
- return(0);
- }
- stack = alloc_stack(0);
- io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
- &thread_fd);
- if(io_pid < 0){
- printk(KERN_ERR
- "ubd : Failed to start I/O thread (errno = %d) - "
- "falling back to synchronous I/O\n", -io_pid);
- return(0);
- }
- err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
- SA_INTERRUPT, "ubd", ubd_dev);
- if(err != 0) printk(KERN_ERR
- "um_request_irq failed - errno = %d\n", -err);
- return(err);
-}
-
-__initcall(ubd_init);
-
-static void ubd_close(struct ubd *dev)
-{
- close_fd(dev->fd);
- if(dev->cow.file != NULL) {
- close_fd(dev->cow.fd);
- vfree(dev->cow.bitmap);
- dev->cow.bitmap = NULL;
- }
-}
-
-static int ubd_open_dev(struct ubd *dev)
-{
- struct openflags flags;
- int err, n, create_cow, *create_ptr;
-
- create_cow = 0;
- create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
- dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file,
- &dev->cow.bitmap_offset, &dev->cow.bitmap_len,
- &dev->cow.data_offset, create_ptr);
-
- if((dev->fd == -ENOENT) && create_cow){
- n = dev - ubd_dev;
- dev->fd = create_cow_file(dev->file, dev->cow.file,
- dev->openflags, 1 << 9,
- &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", dev->file, dev->cow.file);
- }
- }
-
- if(dev->fd < 0) return(dev->fd);
-
- if(dev->cow.file != NULL){
- err = -ENOMEM;
- dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
- if(dev->cow.bitmap == NULL) goto error;
- flush_tlb_kernel_vm();
-
- err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
- dev->cow.bitmap_offset,
- dev->cow.bitmap_len);
- if(err) goto error;
-
- flags = dev->openflags;
- flags.w = 0;
- err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL,
- NULL, NULL);
- if(err < 0) goto error;
- dev->cow.fd = err;
- }
- return(0);
- error:
- close_fd(dev->fd);
- return(err);
-}
-
-static int ubd_file_size(struct ubd *dev, __u64 *size_out)
-{
- char *file;
-
- file = dev->cow.file ? dev->cow.file : dev->file;
- return(os_file_size(file, size_out));
-}
-
-static int ubd_open(struct inode *inode, struct file *filp)
-{
- struct ubd *dev;
- int n, offset, err;
-
- n = DEVICE_NR(inode->i_rdev);
- dev = &ubd_dev[n];
- if(n > MAX_DEV)
- return -ENODEV;
- offset = n << UBD_SHIFT;
- if(ubd_is_dir(dev->file)){
- dev->is_dir = 1;
- return(0);
- }
- if(dev->count == 0){
- dev->openflags = dev->boot_openflags;
- /* XXX This error is wrong when errno isn't stored in
- * dev->fd
- */
- if(ubd_open_dev(dev) < 0){
- printk(KERN_ERR "ubd%d: Can't open \"%s\": "
- "errno = %d\n", n, dev->file, -dev->fd);
- }
- if(dev->fd < 0)
- return -ENODEV;
- err = ubd_file_size(dev, &dev->size);
- if(err) return(err);
- sizes[offset] = dev->size / BLOCK_SIZE;
- ubd_part[offset].nr_sects = dev->size / hardsect_sizes[offset];
- }
- dev->count++;
- if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){
- if(--dev->count == 0) ubd_close(dev);
- return -EROFS;
- }
- return(0);
-}
-
-static int ubd_release(struct inode * inode, struct file * file)
-{
- int n, offset;
-
- n = DEVICE_NR(inode->i_rdev);
- offset = n << UBD_SHIFT;
- if(n > MAX_DEV)
- return -ENODEV;
- if(--ubd_dev[n].count == 0){
- ubd_close(&ubd_dev[n]);
- sizes[offset] = 0;
- ubd_part[offset].nr_sects = 0;
- }
- return(0);
-}
-
-int cow_read = 0;
-int cow_write = 0;
-
-void cowify_req(struct io_thread_req *req, struct ubd *dev)
-{
- int i, update_bitmap, sector = req->offset >> 9;
-
- if(req->length > (sizeof(req->sector_mask) * 8) << 9)
- panic("Operation too long");
- if(req->op == UBD_READ) {
- for(i = 0; i < req->length >> 9; i++){
- if(ubd_test_bit(sector + i, (unsigned char *)
- dev->cow.bitmap)){
- ubd_set_bit(i, (unsigned char *)
- &req->sector_mask);
- cow_read++;
- }
- }
- }
- else {
- update_bitmap = 0;
- for(i = 0; i < req->length >> 9; i++){
- cow_write++;
- ubd_set_bit(i, (unsigned char *)
- &req->sector_mask);
- if(!ubd_test_bit(sector + i, (unsigned char *)
- dev->cow.bitmap))
- update_bitmap = 1;
- ubd_set_bit(sector + i, (unsigned char *)
- dev->cow.bitmap);
- }
- if(update_bitmap){
- req->cow_offset = sector / (sizeof(unsigned long) * 8);
- req->bitmap_words[0] =
- dev->cow.bitmap[req->cow_offset];
- req->bitmap_words[1] =
- dev->cow.bitmap[req->cow_offset + 1];
- req->cow_offset *= sizeof(unsigned long);
- req->cow_offset += dev->cow.bitmap_offset;
- }
- }
-}
-
-static int prepare_request(struct request *req, struct io_thread_req *io_req)
-{
- struct ubd *dev;
- __u64 block;
- int nsect, minor, n;
-
- if(req->rq_status == RQ_INACTIVE) return(1);
-
- minor = MINOR(req->rq_dev);
- n = minor >> UBD_SHIFT;
- dev = &ubd_dev[n];
- if(dev->is_dir){
- strcpy(req->buffer, "HOSTFS:");
- strcat(req->buffer, dev->file);
- end_request(1);
- return(1);
- }
- if(IS_WRITE(req) && !dev->openflags.w){
- printk("Write attempted on readonly ubd device %d\n", n);
- end_request(0);
- return(1);
- }
-
- req->sector += ubd_part[minor].start_sect;
- block = req->sector;
- nsect = req->current_nr_sectors;
-
- io_req->op = (req->cmd == READ) ? UBD_READ : UBD_WRITE;
- io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
- io_req->fds[1] = dev->fd;
- io_req->offsets[0] = 0;
- io_req->offsets[1] = dev->cow.data_offset;
- io_req->offset = ((__u64) block) << 9;
- io_req->length = nsect << 9;
- io_req->buffer = req->buffer;
- io_req->sectorsize = 1 << 9;
- io_req->sector_mask = 0;
- io_req->cow_offset = -1;
- io_req->error = 0;
-
- if(dev->cow.file != NULL) cowify_req(io_req, dev);
- return(0);
-}
-
-static void do_ubd_request(request_queue_t *q)
-{
- struct io_thread_req io_req;
- struct request *req;
- int err, n;
-
- if(thread_fd == -1){
- while(!list_empty(&q->queue_head)){
- req = blkdev_entry_next_request(&q->queue_head);
- err = prepare_request(req, &io_req);
- if(!err){
- do_io(&io_req);
- ubd_finish(io_req.error);
- }
- }
- }
- else {
- if(DEVICE_INTR || list_empty(&q->queue_head)) return;
- req = blkdev_entry_next_request(&q->queue_head);
- err = prepare_request(req, &io_req);
- if(!err){
- SET_INTR(ubd_handler);
- n = write_ubd_fs(thread_fd, (char *) &io_req,
- sizeof(io_req));
- if(n != sizeof(io_req))
- printk("write to io thread failed, "
- "errno = %d\n", -n);
- }
- }
-}
-
-static int ubd_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- struct hd_geometry *loc = (struct hd_geometry *) arg;
- struct ubd *dev;
- int n, minor, err;
-
- if(!inode) return(-EINVAL);
- minor = MINOR(inode->i_rdev);
- n = minor >> UBD_SHIFT;
- if(n > MAX_DEV)
- return(-EINVAL);
- dev = &ubd_dev[n];
- switch (cmd) {
- struct hd_geometry g;
- struct cdrom_volctrl volume;
- case HDIO_GETGEO:
- if(!loc) return(-EINVAL);
- g.heads = 128;
- g.sectors = 32;
- g.cylinders = dev->size / (128 * 32 * hardsect_sizes[minor]);
- g.start = 2;
- return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
- case BLKGETSIZE: /* Return device size */
- if(!arg) return(-EINVAL);
- err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
- if(err)
- return(err);
- put_user(ubd_part[minor].nr_sects, (long *) arg);
- return(0);
- case BLKRRPART: /* Re-read partition tables */
- return(ubd_revalidate(inode->i_rdev));
-
- case HDIO_SET_UNMASKINTR:
- if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
- if((arg > 1) || (minor & 0x3F)) return(-EINVAL);
- return(0);
-
- case HDIO_GET_UNMASKINTR:
- if(!arg) return(-EINVAL);
- err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
- if(err)
- return(err);
- return(0);
-
- case HDIO_GET_MULTCOUNT:
- if(!arg) return(-EINVAL);
- err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
- if(err)
- return(err);
- return(0);
-
- case HDIO_SET_MULTCOUNT:
- if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
- if(MINOR(inode->i_rdev) & 0x3F) return(-EINVAL);
- return(0);
-
- case HDIO_GET_IDENTITY:
- ubd_id.cyls = dev->size / (128 * 32 * hardsect_sizes[minor]);
- if(copy_to_user((char *) arg, (char *) &ubd_id,
- sizeof(ubd_id)))
- return(-EFAULT);
- return(0);
-
- case CDROMVOLREAD:
- if(copy_from_user(&volume, (char *) arg, sizeof(volume)))
- return(-EFAULT);
- volume.channel0 = 255;
- volume.channel1 = 255;
- volume.channel2 = 255;
- volume.channel3 = 255;
- if(copy_to_user((char *) arg, &volume, sizeof(volume)))
- return(-EFAULT);
- return(0);
-
- default:
- return blk_ioctl(inode->i_rdev, cmd, arg);
- }
-}
-
-static int ubd_revalidate(kdev_t rdev)
-{
- int i, n, offset, err, pcount = 1 << UBD_SHIFT;
- struct ubd *dev;
- struct hd_struct *part;
-
- n = DEVICE_NR(rdev);
- offset = n << UBD_SHIFT;
- dev = &ubd_dev[n];
- part = &ubd_part[offset];
-
- /* clear all old partition counts */
- for(i = 1; i < pcount; i++) {
- part[i].start_sect = 0;
- part[i].nr_sects = 0;
- }
-
- /* If it already has been opened we can check the partitions
- * directly
- */
- if(dev->count){
- part->start_sect = 0;
- register_disk(&ubd_gendisk, MKDEV(MAJOR_NR, offset), pcount,
- &ubd_blops, part->nr_sects);
- }
- else if(dev->file){
- if(ubd_open_dev(dev) < 0){
- printk(KERN_ERR "unable to open %s for validation\n",
- dev->file);
- return 1;
- }
-
- /* have to recompute sizes since we opened it */
- err = ubd_file_size(dev, &dev->size);
- if(err) {
- ubd_close(dev);
- return 1;
- }
- part->start_sect = 0;
- part->nr_sects = dev->size / hardsect_sizes[offset];
- register_disk(&ubd_gendisk, MKDEV(MAJOR_NR, offset), pcount,
- &ubd_blops, part->nr_sects);
-
- /* we are done so close it */
- ubd_close(dev);
- }
- else return(1);
- return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */