Commit 827ff063 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://jdike.stearns.org:5000/updates-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 31bb1aff 268a7aa4
ARCH_DIR = arch/um
OS := $(shell uname -s)
include $(ARCH_DIR)/Makefile-$(SUBARCH)
include $(ARCH_DIR)/Makefile-os-$(OS)
EXTRAVERSION := $(EXTRAVERSION)-1um
include/linux/version.h: arch/$(ARCH)/Makefile
......@@ -59,17 +56,18 @@ ARCH_SYMLINKS = include/asm-um/arch arch/um/include/sysdep arch/um/os \
GEN_HEADERS = $(ARCH_DIR)/include/task.h
include $(ARCH_DIR)/Makefile-$(SUBARCH)
include $(ARCH_DIR)/Makefile-os-$(OS)
$(ARCH_DIR)/vmlinux.lds.S :
touch $@
prepare: $(ARCH_SYMLINKS) $(GEN_HEADERS)
LDFLAGS_vmlinux = -r $(ARCH_DIR)/main.o
vmlinux: $(ARCH_DIR)/main.o
$(ARCH_DIR)/uml.lds.s : $(ARCH_DIR)/uml.lds.S scripts FORCE
$(call if_changed_dep,as_s_S)
......
......@@ -8,6 +8,9 @@ CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
ELF_ARCH = $(SUBARCH)
ELF_FORMAT = elf32-$(SUBARCH)
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
LDFLAGS_BLOB := --format binary --oformat elf32-i386
SYS_DIR := $(ARCH_DIR)/include/sysdep-i386
SYS_UTIL_DIR := $(ARCH_DIR)/sys-i386/util
......@@ -21,11 +24,14 @@ $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
$< > $@
$(SYS_UTIL_DIR)/mk_sc $(SYS_UTIL_DIR)/mk_thread: $(SYS_UTIL_DIR) FORCE ;
$(SYS_UTIL_DIR)/mk_sc: FORCE ;
@$(call descend,$(SYS_UTIL_DIR),$@)
$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) FORCE ;
@$(call descend,$(SYS_UTIL_DIR),$@)
$(SYS_UTIL_DIR): include/asm FORCE
@$(call descend,$@,)
sysclean :
rm -f $(SYS_HEADERS)
@$(call descend,$(SYS_DIR),clean)
......@@ -219,13 +219,16 @@ CONFIG_EXT2_FS=y
# CONFIG_INTERMEZZO_FS is not set
# CONFIG_NFS_FS is not set
# CONFIG_NFS_V3 is not set
# CONFIG_NFS_V4 is not set
# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set
# CONFIG_NFSD_V4 is not set
# CONFIG_NFSD_TCP is not set
# CONFIG_SUNRPC is not set
# CONFIG_LOCKD is not set
# CONFIG_EXPORTFS is not set
# CONFIG_CIFS is not set
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
# CONFIG_NCPFS_PACKET_SIGNING is not set
......@@ -236,6 +239,7 @@ CONFIG_EXT2_FS=y
# CONFIG_NCPFS_SMALLDOS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
# CONFIG_AFS_FS is not set
# CONFIG_ZISOFS_FS is not set
#
......@@ -332,7 +336,9 @@ CONFIG_SCSI_DEBUG=y
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_PARTITIONS is not set
# CONFIG_MTD_CONCAT is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
#
# User Modules And Translation Layers
......@@ -362,6 +368,8 @@ CONFIG_MTD_BLOCK=y
# Mapping drivers for chip access
#
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_PCI is not set
# CONFIG_MTD_PCMCIA is not set
#
# Self-contained MTD device drivers
......
......@@ -15,7 +15,7 @@ CHAN_OBJS := chan_kern.o chan_user.o line.o
# So, what this does is figure out by hand (crudely) what file -lpcap really
# is and just use it.
PCAP = $(shell for f in echo {/lib,/usr/lib}/libpcap.{a,so}; do \
PCAP = $(shell for f in echo {/lib,/usr/lib}/libpcap.a; do \
[ -f $$f ] && echo $$f ; done | head -1)
slip-objs := slip_kern.o slip_user.o
......@@ -47,7 +47,7 @@ obj-$(CONFIG_NULL_CHAN) += null.o
obj-$(CONFIG_PORT_CHAN) += port.o
obj-$(CONFIG_PTY_CHAN) += pty.o
obj-$(CONFIG_TTY_CHAN) += tty.o
obj-$(CONFIG_XTERM_CHAN) += xterm.o
obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
obj-$(CONFIG_UML_WATCHDOG) += harddog.o
CFLAGS_pcap_user.o = -I/usr/include/pcap
......
......@@ -111,6 +111,8 @@ void mconsole_version(struct mc_request *req)
remove <dev> - Remove a device from UML
sysrq <letter> - Performs the SysRq action controlled by the letter
cad - invoke the Ctl-Alt-Del handler
stop - pause the UML; it will do nothing until it receives a 'go'
go - continue the UML after a 'stop'
"
void mconsole_help(struct mc_request *req)
......
......@@ -20,6 +20,7 @@
struct port_list {
struct list_head list;
int has_connection;
struct semaphore sem;
int port;
int fd;
......@@ -49,28 +50,32 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
struct connection *conn = data;
int fd;
list_del(&conn->list);
fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
if(fd < 0){
if(fd == -EAGAIN)
return;
printk("os_rcv_fd returned %d\n", -fd);
os_close_file(conn->fd);
}
list_del(&conn->list);
conn->fd = fd;
list_add(&conn->list, &conn->port->connections);
up(&conn->port->sem);
}
static void port_interrupt(int irq, void *data, struct pt_regs *regs)
static int port_accept(struct port_list *port)
{
struct port_list *port = data;
struct connection *conn;
int fd, socket[2], pid;
int fd, socket[2], pid, ret = 0;
fd = port_connection(port->fd, socket, &pid);
if(fd < 0){
printk("port_connection returned %d\n", -fd);
if(fd != -EAGAIN)
printk("port_connection returned %d\n", -fd);
goto out;
}
......@@ -94,6 +99,7 @@ static void port_interrupt(int irq, void *data, struct pt_regs *regs)
}
list_add(&conn->list, &port->pending);
ret = 1;
goto out;
out_free:
......@@ -102,17 +108,45 @@ static void port_interrupt(int irq, void *data, struct pt_regs *regs)
os_close_file(fd);
if(pid != -1) os_kill_process(pid);
out:
reactivate_fd(port->fd, ACCEPT_IRQ);
return(ret);
}
DECLARE_MUTEX(ports_sem);
struct list_head ports = LIST_HEAD_INIT(ports);
void port_work_proc(void *unused)
{
struct port_list *port;
struct list_head *ele;
unsigned long flags;
local_irq_save(flags);
list_for_each(ele, &ports){
port = list_entry(ele, struct port_list, list);
if(!port->has_connection)
continue;
reactivate_fd(port->fd, ACCEPT_IRQ);
while(port_accept(port)) ;
port->has_connection = 0;
}
local_irq_restore(flags);
}
DECLARE_WORK(port_work, port_work_proc, NULL);
static void port_interrupt(int irq, void *data, struct pt_regs *regs)
{
struct port_list *port = data;
port->has_connection = 1;
schedule_work(&port_work);
}
void *port_data(int port_num)
{
struct list_head *ele;
struct port_list *port;
struct port_dev *dev;
struct port_dev *dev = NULL;
int fd;
down(&ports_sem);
......@@ -140,13 +174,14 @@ void *port_data(int port_num)
}
*port = ((struct port_list)
{ list : LIST_HEAD_INIT(port->list),
sem : __SEMAPHORE_INITIALIZER(port->sem, 0),
lock : SPIN_LOCK_UNLOCKED,
port : port_num,
fd : fd,
pending : LIST_HEAD_INIT(port->pending),
connections : LIST_HEAD_INIT(port->connections) });
{ list : LIST_HEAD_INIT(port->list),
has_connection : 0,
sem : __SEMAPHORE_INITIALIZER(port->sem, 0),
lock : SPIN_LOCK_UNLOCKED,
port : port_num,
fd : fd,
pending : LIST_HEAD_INIT(port->pending),
connections : LIST_HEAD_INIT(port->connections) });
list_add(&port->list, &ports);
found:
......@@ -159,8 +194,7 @@ void *port_data(int port_num)
*dev = ((struct port_dev) { port : port,
fd : -1,
helper_pid : -1 });
up(&ports_sem);
return(dev);
goto out;
out_free:
kfree(port);
......@@ -168,7 +202,7 @@ void *port_data(int port_num)
os_close_file(fd);
out:
up(&ports_sem);
return(NULL);
return(dev);
}
void port_remove_dev(void *d)
......
......@@ -44,6 +44,7 @@ static struct chan_opts opts = {
xterm_title: "Serial Line #%d",
raw: 1,
tramp_stack : 0,
in_kernel : 1,
};
static struct line_driver driver = {
......
......@@ -75,6 +75,7 @@ static struct chan_opts opts = {
xterm_title: "Virtual Console #%d",
raw: 1,
tramp_stack : 0,
in_kernel : 1,
};
static struct line_driver driver = {
......
......@@ -6,12 +6,15 @@
/* 2001-09-28...2002-04-17
* Partition stuff by James_McMechan@hotmail.com
* old style ubd by setting UBD_SHIFT to 0
* 2002-09-27...2002-10-18 massive tinkering for 2.5
* partitions have changed in 2.5
*/
#define MAJOR_NR UBD_MAJOR
#define UBD_SHIFT 4
#include "linux/config.h"
#include "linux/module.h"
#include "linux/blk.h"
#include "linux/blkdev.h"
#include "linux/hdreg.h"
......@@ -51,15 +54,17 @@ 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(struct gendisk *disk);
#define MAX_DEV (8)
#define MAX_MINOR (MAX_DEV << UBD_SHIFT)
#define DEVICE_NR(n) (minor(n) >> UBD_SHIFT)
static struct block_device_operations ubd_blops = {
.owner = THIS_MODULE,
.open = ubd_open,
.release = ubd_release,
.ioctl = ubd_ioctl,
.revalidate_disk= ubd_revalidate,
};
/* Protected by the queue_lock */
......@@ -169,8 +174,6 @@ 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);
......@@ -415,88 +418,135 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
return(os_file_size(file, size_out));
}
/* Initialized in an initcall, and unchanged thereafter */
devfs_handle_t ubd_dir_handle;
devfs_handle_t ubd_fake_dir_handle;
static void ubd_close(struct ubd *dev)
{
os_close_file(dev->fd);
if(dev->cow.file == NULL)
return;
static int ubd_add(int n)
os_close_file(dev->cow.fd);
vfree(dev->cow.bitmap);
dev->cow.bitmap = NULL;
}
static int ubd_open_dev(struct ubd *dev)
{
devfs_handle_t real, fake;
char name[sizeof("nnnnnn\0")];
struct ubd *dev = &ubd_dev[n];
struct gendisk *disk, *fake_disk = NULL;
u64 size;
struct openflags flags;
int err, n, create_cow, *create_ptr;
if (!dev->file)
goto out;
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);
disk = alloc_disk(1 << UBD_SHIFT);
if (!disk)
return -1;
disk->major = MAJOR_NR;
disk->first_minor = n << UBD_SHIFT;
disk->fops = &ubd_blops;
if (fakehd_set)
sprintf(disk->disk_name, "hd%c", n + 'a');
else
sprintf(disk->disk_name, "ubd%d", n);
if (fake_major) {
fake_disk = alloc_disk(1 << UBD_SHIFT);
if (!fake_disk) {
put_disk(disk);
return -1;
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);
}
fake_disk->major = fake_major;
fake_disk->first_minor = n << UBD_SHIFT;
fake_disk->fops = &ubd_blops;
sprintf(fake_disk->disk_name, "ubd%d", n);
fake_gendisk[n] = fake_disk;
}
ubd_gendisk[n] = disk;
if(dev->fd < 0) return(dev->fd);
if (!dev->is_dir && ubd_file_size(dev, &size) == 0) {
set_capacity(disk, size/512);
if (fake_major)
set_capacity(fake_disk, size/512);
}
sprintf(name, "%d", 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(real == NULL)
goto out;
ubd_dev[n].real = real;
if (fake_major) {
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(fake == NULL)
goto out_unregister;
ubd_dev[n].fake = fake;
fake_disk->private_data = &ubd_dev[n];
fake_disk->queue = &ubd_queue;
add_disk(fake_disk);
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;
}
disk->private_data = &ubd_dev[n];
return(0);
error:
os_close_file(dev->fd);
return(err);
}
static int ubd_new_disk(int major, u64 size, char *name, int unit,
struct gendisk **disk_out, devfs_handle_t dir_handle,
devfs_handle_t *handle_out)
{
char devfs_name[sizeof("nnnnnn\0")];
struct gendisk *disk;
int minor = unit << UBD_SHIFT;
disk = alloc_disk(1 << UBD_SHIFT);
if(disk == NULL)
return(-ENOMEM);
disk->major = major;
disk->first_minor = minor;
disk->fops = &ubd_blops;
set_capacity(disk, size / 512);
/* needs to be ubd -> /dev/ubd/discX/disc */
sprintf(disk->disk_name, "ubd");
*disk_out = disk;
/* /dev/ubd/N style names */
sprintf(devfs_name, "%d", unit);
*handle_out = devfs_register(dir_handle, devfs_name,
DEVFS_FL_REMOVABLE, major, minor,
S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &ubd_blops, NULL);
disk->private_data = &ubd_dev[unit];
disk->queue = &ubd_queue;
add_disk(disk);
make_ide_entries(disk->disk_name);
return(0);
}
out_unregister:
devfs_unregister(real);
ubd_dev[n].real = NULL;
out:
return(-1);
/* Initialized in an initcall, and unchanged thereafter */
devfs_handle_t ubd_dir_handle;
devfs_handle_t ubd_fake_dir_handle;
static int ubd_add(int n)
{
struct ubd *dev = &ubd_dev[n];
int err;
if (!dev->file || dev->is_dir)
return(-ENODEV);
if (ubd_open_dev(dev))
return(-ENODEV);
err = ubd_file_size(dev, &dev->size);
if(err)
return(err);
err = ubd_new_disk(MAJOR_NR, dev->size, "ubd", n, &ubd_gendisk[n],
ubd_dir_handle, &dev->real);
if(err)
return(err);
if(fake_major)
ubd_new_disk(fake_major, dev->size, "ubd%d", n,
&fake_gendisk[n], ubd_fake_dir_handle,
&dev->fake);
/* perhaps this should also be under the "if (fake_major)" above */
/* using the fake_disk->disk_name and also the fakehd_set name */
if (fake_ide)
make_ide_entries(ubd_gendisk[n]->disk_name);
ubd_close(dev);
return 0;
}
static int ubd_config(char *str)
......@@ -527,34 +577,39 @@ static int ubd_config(char *str)
static int ubd_remove(char *str)
{
struct ubd *dev;
int n, err;
int n, err = -ENODEV;
if(!isdigit(*str))
return(err); /* it should be a number 0-7/a-h */
if(!isdigit(*str))
return(-1);
n = *str - '0';
if(n > MAX_DEV)
return(-1);
return(err);
dev = &ubd_dev[n];
if(dev->count > 0)
return(-EBUSY); /* you cannot remove a open disk */
err = 0;
spin_lock(&ubd_lock);
if(ubd_gendisk[n] == NULL)
goto out;
del_gendisk(ubd_gendisk[n]);
put_disk(ubd_gendisk[n]);
ubd_gendisk[n] = NULL;
if (fake_major) {
if(dev->real != NULL)
devfs_unregister(dev->real);
if(fake_gendisk[n] != NULL){
del_gendisk(fake_gendisk[n]);
put_disk(fake_gendisk[n]);
fake_gendisk[n] = NULL;
if(dev->fake != NULL)
devfs_unregister(dev->fake);
}
if(dev->file == NULL)
goto out;
err = -1;
if(dev->count > 0)
goto out;
if(dev->real != NULL)
devfs_unregister(dev->real);
if(dev->fake != NULL)
devfs_unregister(dev->fake);
*dev = ((struct ubd) DEFAULT_UBD);
err = 0;
out:
......@@ -563,9 +618,9 @@ static int ubd_remove(char *str)
}
static struct mc_device ubd_mc = {
name: "ubd",
config: ubd_config,
remove: ubd_remove,
.name = "ubd",
.config = ubd_config,
.remove = ubd_remove,
};
static int ubd_mc_init(void)
......@@ -585,8 +640,10 @@ int ubd_init(void)
printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR);
return -1;
}
blk_init_queue(&ubd_queue, do_ubd_request, &ubd_io_lock);
elevator_init(&ubd_queue, &elevator_noop);
if(fake_major != 0){
char name[sizeof("ubd_nnn\0")];
......@@ -631,81 +688,23 @@ int ubd_driver_init(void){
device_initcall(ubd_driver_init);
static void ubd_close(struct ubd *dev)
{
os_close_file(dev->fd);
if(dev->cow.file != NULL) {
os_close_file(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:
os_close_file(dev->fd);
return(err);
}
static int ubd_open(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ubd *dev = disk->private_data;
int err;
int err = -EISDIR;
if(dev->is_dir == 1)
goto out;
err = 0;
if(dev->count == 0){
dev->openflags = dev->boot_openflags;
err = ubd_open_dev(dev);
if(err){
printk(KERN_ERR "%s: Can't open \"%s\": "
"errno = %d\n", disk->disk_name, dev->file, -err);
printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
disk->disk_name, dev->file, -err);
goto out;
}
}
......@@ -722,7 +721,8 @@ static int ubd_release(struct inode * inode, struct file * file)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ubd *dev = disk->private_data;
if(dev->count == 0)
if(--dev->count == 0)
ubd_close(dev);
return(0);
}
......@@ -772,7 +772,7 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
__u64 block;
int nsect;
if (req->rq_status == RQ_INACTIVE) return(1);
if(req->rq_status == RQ_INACTIVE) return(1);
if(dev->is_dir){
strcpy(req->buffer, "HOSTFS:");
......@@ -784,7 +784,8 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
}
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
printk("Write attempted on readonly ubd device %s\n", disk->disk_name);
printk("Write attempted on readonly ubd device %s\n",
disk->disk_name);
spin_lock(&ubd_io_lock);
end_request(req, 0);
spin_unlock(&ubd_io_lock);
......@@ -848,7 +849,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
struct hd_geometry *loc = (struct hd_geometry *) arg;
struct ubd *dev = inode->i_bdev->bd_disk->private_data;
int err;
struct ubd *dev;
struct hd_driveid ubd_id = {
.cyls = 0,
.heads = 128,
......@@ -868,7 +868,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
case HDIO_SET_UNMASKINTR:
if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
if((arg > 1) || inode->i_bdev->bd_contains != inode->i_bdev)
if((arg > 1) || (inode->i_bdev->bd_contains != inode->i_bdev))
return(-EINVAL);
return(0);
......@@ -888,7 +888,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
case HDIO_SET_MULTCOUNT:
if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
if (inode->i_bdev->bd_contains != inode->i_bdev)
if(inode->i_bdev->bd_contains != inode->i_bdev)
return(-EINVAL);
return(0);
......@@ -913,27 +913,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
return(-EINVAL);
}
static int ubd_revalidate(struct gendisk *disk)
{
__u64 size;
int err;
struct ubd *dev = disk->private_data;
err = 0;
spin_lock(&ubd_lock);
if(dev->is_dir)
goto out;
err = ubd_file_size(dev, &size);
if (!err) {
set_capacity(disk, size / 512);
dev->size = size;
}
out:
spin_unlock(&ubd_lock);
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
......
......@@ -19,6 +19,7 @@
#include "user_util.h"
#include "user.h"
#include "os.h"
#include "xterm.h"
struct xterm_chan {
int pid;
......@@ -28,6 +29,7 @@ struct xterm_chan {
int raw;
struct termios tt;
unsigned long stack;
int direct_rcv;
};
void *xterm_init(char *str, int device, struct chan_opts *opts)
......@@ -40,7 +42,8 @@ void *xterm_init(char *str, int device, struct chan_opts *opts)
device : device,
title : opts->xterm_title,
raw : opts->raw,
stack : opts->tramp_stack } );
stack : opts->tramp_stack,
direct_rcv : !opts->in_kernel } );
return(data);
}
......@@ -84,7 +87,7 @@ int xterm_open(int input, int output, int primary, void *d)
{
struct xterm_chan *data = d;
unsigned long stack;
int pid, fd, new;
int pid, fd, new, err;
char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
"/usr/lib/uml/port-helper", "-uml-socket",
......@@ -105,21 +108,30 @@ int xterm_open(int input, int output, int primary, void *d)
fd = create_unix_socket(file, sizeof(file));
if(fd < 0){
printk("xterm_open : create_unix_socket failed, errno = %d\n",
errno);
return(-errno);
-fd);
return(-fd);
}
sprintf(title, data->title, data->device);
stack = data->stack;
pid = run_helper(NULL, NULL, argv, &stack);
if(pid < 0){
printk("xterm_open : run_helper failed\n");
return(-1);
printk("xterm_open : run_helper failed, errno = %d\n", -pid);
return(pid);
}
if(data->stack == 0) free_stack(stack, 0);
new = os_rcv_fd(fd, &data->helper_pid);
if(data->direct_rcv)
new = os_rcv_fd(fd, &data->helper_pid);
else {
if((err = os_set_fd_block(fd, 0)) != 0){
printk("xterm_open : failed to set descriptor "
"non-blocking, errno = %d\n", err);
return(err);
}
new = xterm_fd(fd, &data->helper_pid);
}
if(new < 0){
printk("xterm_open : os_rcv_fd failed, errno = %d\n", -new);
return(new);
......
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __XTERM_H__
#define __XTERM_H__
extern int xterm_fd(int socket, int *pid_out);
#endif
/*
* 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:
*/
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include "linux/errno.h"
#include "linux/slab.h"
#include "asm/semaphore.h"
#include "asm/irq.h"
#include "irq_user.h"
#include "kern_util.h"
#include "os.h"
#include "xterm.h"
struct xterm_wait {
struct semaphore sem;
int fd;
int pid;
int new_fd;
};
static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
{
struct xterm_wait *xterm = data;
xterm->new_fd = os_rcv_fd(xterm->fd, &xterm->pid);
if(xterm->new_fd == -EAGAIN)
return;
up(&xterm->sem);
}
int xterm_fd(int socket, int *pid_out)
{
struct xterm_wait *data;
int err, ret;
data = kmalloc(sizeof(*data), GFP_KERNEL);
if(data == NULL){
printk(KERN_ERR "xterm_fd - failed to allocate semaphore\n");
return(-ENOMEM);
}
*data = ((struct xterm_wait)
{ sem : __SEMAPHORE_INITIALIZER(data->sem, 0),
fd : socket,
pid : -1,
new_fd : -1 });
err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
"xterm", data);
if(err){
printk(KERN_ERR "Failed to get IRQ for xterm, err = %d\n",
err);
return(err);
}
down(&data->sem);
free_irq(XTERM_IRQ, data);
ret = data->new_fd;
*pid_out = data->pid;
kfree(data);
return(ret);
}
/*
* 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:
*/
......@@ -13,6 +13,7 @@ struct chan_opts {
char *xterm_title;
int raw;
unsigned long tramp_stack;
int in_kernel;
};
enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
......
......@@ -6,6 +6,7 @@
#ifndef __KERN_UTIL_H__
#define __KERN_UTIL_H__
#include "linux/threads.h"
#include "sysdep/ptrace.h"
extern int ncpus;
......@@ -14,6 +15,7 @@ extern char *gdb_init;
extern int kmalloc_ok;
extern int timer_irq_inited;
extern int jail;
extern struct task_struct *idle_threads[NR_CPUS];
#define ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
#define ROUND_UP(addr) ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
......
EXTRA_TARGETS := unmap_fin.o
obj-y = config.o exec_kern.o exec_user.o exitcode.o frame_kern.o frame.o \
......@@ -51,6 +50,9 @@ arch/um/kernel/unmap.o: arch/um/kernel/unmap.c
arch/um/kernel/unmap_fin.o : arch/um/kernel/unmap.o
ld -r -o $@ $< -lc -L/usr/lib
# This has to be separate because it needs be compiled with frame pointers
# regardless of how the rest of the kernel is built.
arch/um/kernel/frame.o: arch/um/kernel/frame.c
$(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $<
......
......@@ -209,7 +209,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
out_unlock:
irq_unlock(flags);
out_free:
kfree(new_fd);
out:
return(err);
......
#include "linux/config.h"
#include "linux/module.h"
#include "linux/string.h"
#include "linux/smp_lock.h"
#include "linux/spinlock.h"
#include <linux/highmem.h>
#include "asm/current.h"
#include "asm/delay.h"
#include "asm/processor.h"
......@@ -36,12 +40,15 @@ EXPORT_SYMBOL(page_mem_map);
EXPORT_SYMBOL(get_signals);
EXPORT_SYMBOL(page_to_phys);
EXPORT_SYMBOL(phys_to_page);
EXPORT_SYMBOL(high_physmem);
EXPORT_SYMBOL(os_open_file);
EXPORT_SYMBOL(os_read_file);
EXPORT_SYMBOL(os_write_file);
EXPORT_SYMBOL(os_seek_file);
EXPORT_SYMBOL(os_pipe);
EXPORT_SYMBOL(os_file_type);
EXPORT_SYMBOL(os_close_file);
EXPORT_SYMBOL(helper_wait);
EXPORT_SYMBOL(os_shutdown_socket);
EXPORT_SYMBOL(os_connect_socket);
......@@ -58,3 +65,23 @@ EXPORT_SYMBOL(sys_lseek);
EXPORT_SYMBOL(sys_read);
EXPORT_SYMBOL(sys_wait4);
#ifdef CONFIG_SMP
/* required for SMP */
extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
EXPORT_SYMBOL_NOVERS(__write_lock_failed);
extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
EXPORT_SYMBOL_NOVERS(__read_lock_failed);
#endif
#ifdef CONFIG_HIGHMEM
EXPORT_SYMBOL(kmap);
EXPORT_SYMBOL(kunmap);
EXPORT_SYMBOL(kmap_atomic);
EXPORT_SYMBOL(kunmap_atomic);
EXPORT_SYMBOL(kmap_atomic_to_page);
#endif
......@@ -767,8 +767,8 @@ void set_thread_sc(void *sc)
int smp_sigio_handler(void)
{
int cpu = current->thread_info->cpu;
#ifdef CONFIG_SMP
int cpu = current->thread_info->cpu;
IPI_handler(cpu);
if(cpu != 0)
return(1);
......
/*
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
* Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
......@@ -9,6 +9,20 @@
#include "kern.h"
#include "os.h"
#ifdef CONFIG_SMP
static void kill_idlers(int me)
{
struct task_struct *p;
int i;
for(i = 0; i < sizeof(idle_threads)/sizeof(idle_threads[0]); i++){
p = idle_threads[i];
if((p != NULL) && (p->thread.extern_pid != me))
os_kill_process(p->thread.extern_pid);
}
}
#endif
static void kill_off_processes(void)
{
struct task_struct *p;
......@@ -21,6 +35,9 @@ static void kill_off_processes(void)
}
if(init_task.thread.extern_pid != me)
os_kill_process(init_task.thread.extern_pid);
#ifdef CONFIG_SMP
kill_idlers(me);
#endif
}
void uml_cleanup(void)
......
......@@ -84,13 +84,13 @@ void unblock_signals(void)
#define SIGIO_BIT 0
#define SIGVTALRM_BIT 1
static int disable_mask(sigset_t *mask)
static int enable_mask(sigset_t *mask)
{
int sigs;
sigs = sigismember(mask, SIGIO) ? 1 << SIGIO_BIT : 0;
sigs |= sigismember(mask, SIGVTALRM) ? 1 << SIGVTALRM_BIT : 0;
sigs |= sigismember(mask, SIGALRM) ? 1 << SIGVTALRM_BIT : 0;
sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
return(sigs);
}
......@@ -100,30 +100,28 @@ int get_signals(void)
if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
panic("Failed to get signal mask");
return(disable_mask(&mask));
return(enable_mask(&mask));
}
int set_signals(int disable)
int set_signals(int enable)
{
sigset_t mask;
int ret;
sigemptyset(&mask);
if(!(disable & (1 << SIGIO_BIT)))
if(enable & (1 << SIGIO_BIT))
sigaddset(&mask, SIGIO);
if(!(disable & (1 << SIGVTALRM_BIT))){
if(enable & (1 << SIGVTALRM_BIT)){
sigaddset(&mask, SIGVTALRM);
sigaddset(&mask, SIGALRM);
}
if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
panic("Failed to enable signals");
ret = disable_mask(&mask);
ret = enable_mask(&mask);
sigemptyset(&mask);
if(disable & (1 << SIGIO_BIT))
if((enable & (1 << SIGIO_BIT)) == 0)
sigaddset(&mask, SIGIO);
if(disable & (1 << SIGVTALRM_BIT)){
if((enable & (1 << SIGVTALRM_BIT)) == 0){
sigaddset(&mask, SIGVTALRM);
sigaddset(&mask, SIGALRM);
}
......
......@@ -47,6 +47,9 @@ int num_reschedules_sent = 0;
/* Small, random number, never changed */
unsigned long cache_decay_ticks = 5;
/* Not changed after boot */
struct task_struct *idle_threads[NR_CPUS];
void smp_send_reschedule(int cpu)
{
write(cpu_data[cpu].ipi_pipe[1], "R", 1);
......@@ -142,6 +145,7 @@ static struct task_struct *idle_thread(int cpu)
cpu_tasks[cpu] = ((struct cpu_task)
{ .pid = new_task->thread.extern_pid,
.task = new_task } );
idle_threads[cpu] = new_task;
write(new_task->thread.switch_pipe[1], &c, sizeof(c));
return(new_task);
}
......
......@@ -85,6 +85,7 @@ extern syscall_handler_t sys_setgroups16;
extern syscall_handler_t sys_symlink;
extern syscall_handler_t sys_lstat;
extern syscall_handler_t sys_readlink;
extern syscall_handler_t sys_swapon;
extern syscall_handler_t sys_uselib;
extern syscall_handler_t sys_reboot;
extern syscall_handler_t old_readdir;
......@@ -111,6 +112,7 @@ extern syscall_handler_t sys_ni_syscall;
extern syscall_handler_t sys_vhangup;
extern syscall_handler_t sys_ni_syscall;
extern syscall_handler_t sys_ni_syscall;
extern syscall_handler_t sys_swapoff;
extern syscall_handler_t sys_sysinfo;
extern syscall_handler_t sys_ipc;
extern syscall_handler_t sys_fsync;
......@@ -229,6 +231,11 @@ extern syscall_handler_t sys_io_getevents;
extern syscall_handler_t sys_io_submit;
extern syscall_handler_t sys_io_cancel;
extern syscall_handler_t sys_exit_group;
extern syscall_handler_t sys_lookup_dcookie;
extern syscall_handler_t sys_epoll_create;
extern syscall_handler_t sys_epoll_ctl;
extern syscall_handler_t sys_epoll_wait;
extern syscall_handler_t sys_remap_file_pages;
#if CONFIG_NFSD
#define NFSSERVCTL sys_nfsserctl
......@@ -240,7 +247,7 @@ extern syscall_handler_t um_mount;
extern syscall_handler_t um_time;
extern syscall_handler_t um_stime;
#define LAST_GENERIC_SYSCALL __NR_exit_group
#define LAST_GENERIC_SYSCALL __NR_remap_file_pages
#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
#define LAST_SYSCALL LAST_GENERIC_SYSCALL
......@@ -479,6 +486,11 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_alloc_hugepages ] = sys_ni_syscall,
[ __NR_free_hugepages ] = sys_ni_syscall,
[ __NR_exit_group ] = sys_exit_group,
[ __NR_lookup_dcookie ] = sys_lookup_dcookie,
[ __NR_sys_epoll_create ] = sys_epoll_create,
[ __NR_sys_epoll_ctl ] = sys_epoll_ctl,
[ __NR_sys_epoll_wait ] = sys_epoll_wait,
[ __NR_remap_file_pages ] = sys_remap_file_pages,
ARCH_SYSCALLS
[ LAST_SYSCALL + 1 ... NR_syscalls ] =
......
......@@ -76,6 +76,16 @@ void show_trace(unsigned long * stack)
printk("\n");
}
/*
* The architecture-independent dump_stack generator
*/
void dump_stack(void)
{
unsigned long stack;
show_trace(&stack);
}
void show_trace_task(struct task_struct *tsk)
{
unsigned long esp = PT_REGS_SP(&tsk->thread.regs);
......
......@@ -211,6 +211,7 @@ static struct chan_opts opts = {
xterm_title : "UML kernel debugger",
raw : 0,
tramp_stack : 0,
in_kernel : 0,
};
/* Accessed by the tracing thread, which automatically serializes access */
......
......@@ -5,9 +5,11 @@
obj-y = file.o process.o tty.o
USER_OBJS := $(foreach file,$(obj-y),arch/um/os-Linux/$(file))
include $(TOPDIR)/Rules.make
$(obj-y) : %.o: %.c
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
clean :
......
......@@ -283,10 +283,9 @@ int os_rcv_fd(int fd, int *helper_pid_out)
msg.msg_flags = 0;
n = recvmsg(fd, &msg, 0);
if(n < 0){
printk("rcv_fd : recvmsg failed - errno = %d\n", errno);
return(-1);
}
if(n < 0)
return(-errno);
else if(n != sizeof(iov.iov_len))
*helper_pid_out = -1;
......
obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o old-checksum.o \
obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o \
ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
obj-$(CONFIG_HIGHMEM) += highmem.o
export-objs = ksyms.o
USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/sys-i386/$(file))
SYMLINKS = semaphore.c old-checksum.c checksum.S extable.c
SYMLINKS = semaphore.c checksum.S extable.c highmem.c
include $(TOPDIR)/Rules.make
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
arch/um/sys-i386/checksum.S arch/um/sys-i386/old-checksum.c:
arch/um/sys-i386/checksum.S:
-rm -f $@
-ln -s $(TOPDIR)/arch/i386/lib/$(notdir $@) $@
......@@ -25,6 +27,9 @@ arch/um/sys-i386/extable.c:
-rm -f $@
-ln -s $(TOPDIR)/arch/i386/mm/$(notdir $@) $@
arch/um/sys-i386/highmem.c:
-rm -f $@
-ln -s $(TOPDIR)/arch/i386/mm/$(notdir $@) $@
clean:
$(MAKE) -C util clean
......
......@@ -65,7 +65,7 @@ SECTIONS
.uml.postsetup.init : { *(.uml.postsetup.init) }
__uml_postsetup_end = .;
__setup_start = .;
.setup.init : { *(.setup.init) }
.init.setup : { *(.init.setup) }
__setup_end = .;
__per_cpu_start = . ;
.data.percpu : { *(.data.percpu) }
......@@ -92,6 +92,11 @@ SECTIONS
.uml.exitcall : { *(.uml.exitcall.exit) }
__uml_exitcall_end = .;
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
.data.init : { *(.data.init) }
.data :
{
......
......@@ -23,8 +23,9 @@ struct task_struct;
#define WINCH_IRQ 10
#define SIGIO_WRITE_IRQ 11
#define TELNETD_IRQ 12
#define XTERM_IRQ 13
#define LAST_IRQ TELNETD_IRQ
#define LAST_IRQ XTERM_IRQ
#define NR_IRQS (LAST_IRQ + 1)
extern int um_request_irq(unsigned int irq, int fd, int type,
......
......@@ -18,9 +18,9 @@
extern void *switch_to(void *prev, void *next, void *last);
extern int set_signals(int enable);
extern int get_signals(void);
extern void block_signals(void);
extern void unblock_signals(void);
extern int get_signals(void);
#define local_save_flags(flags) do { (flags) = get_signals(); } while(0)
#define local_irq_restore(flags) do { set_signals(flags); } while(0)
......@@ -31,11 +31,11 @@ extern int get_signals(void);
#define local_irq_enable() unblock_signals()
#define local_irq_disable() block_signals()
#define irqs_disabled() \
({ \
unsigned long flags; \
local_save_flags(flags); \
(flags != 0); \
#define irqs_disabled() \
({ \
unsigned long flags; \
local_save_flags(flags); \
(flags == 0); \
})
#endif
......@@ -23,7 +23,7 @@ extern long sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
struct timeval *tvp);
extern long sys_lseek(unsigned int fildes, unsigned long offset, int whence);
extern long sys_read(unsigned int fildes, char *buf, int len);
extern long sys_write(unsigned int fildes, char *buf, int len);
extern long sys_write(int fildes, const char *buf, size_t len);
#ifdef __KERNEL_SYSCALLS__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment