source "fs/Kconfig.binfmt"
-config EXTERNFS
- tristate "Support for host-based filesystems"
-
config HOSTFS
tristate "Host filesystem"
help
If you'd like to be able to work with files stored on the host,
say Y or M here; otherwise say N.
-config HUMFS
- tristate 'Usable host filesystem'
- depends on EXTERNFS
-
config HPPFS
tristate "HoneyPot ProcFS (EXPERIMENTAL)"
depends on BROKEN
help
- hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
+ hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
entries to be overridden, removed, or fabricated from the host.
Its purpose is to allow a UML to appear to be a physical machine
by removing or changing anything in /proc which gives away the
bool "Highmem support"
depends on BROKEN
-config PROC_MM
- bool "/proc/mm support"
-
config KERNEL_STACK_ORDER
int "Kernel stack size order"
default 2
$(ARCH_DIR)/kernel/skas/util: scripts_basic FORCE
$(Q)$(MAKE) $(build)=$@
-define archhelp
- echo '* linux - Binary kernel image (./linux)'
-endef
+export SUBARCH USER_CFLAGS OS
endif
endif
-ifeq ($(CONFIG_MODE_SKAS),y)
- ifneq ($(CONFIG_MODE_TT),y)
- START = 0x8048000
- endif
-endif
-
CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
ARCH_USER_CFLAGS :=
SYS_HEADERS := $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
-sys_prepare: $(SYS_DIR)/sc.h
-
prepare: $(SYS_HEADERS)
-filechk_$(SYS_DIR)/sc.h := $(SYS_UTIL_DIR)/mk_sc
-
$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
$(call filechk,gen_header)
CONFIG_MODE_SKAS=y
CONFIG_NET=y
CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_EXTERNFS=y
+CONFIG_BINFMT_MISC=m
CONFIG_HOSTFS=y
-CONFIG_HUMFS=y
-CONFIG_HPPFS=y
CONFIG_MCONSOLE=y
# CONFIG_HOST_2G_2G is not set
# CONFIG_SMP is not set
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
-# CONFIG_NE2000 is not set
#
# Ethernet (1000 Mbit)
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-CONFIG_JFFS_FS=y
-CONFIG_JFFS_FS_VERBOSE=0
-# CONFIG_JFFS_PROC_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
-#
-# Linux VServer
-#
-CONFIG_VSERVER_LEGACY=y
-CONFIG_PROC_SECURE=y
-# CONFIG_VSERVER_HARDCPU is not set
-# CONFIG_INOXID_NONE is not set
-# CONFIG_INOXID_GID16 is not set
-CONFIG_INOXID_GID24=y
-# CONFIG_INOXID_GID32 is not set
-# CONFIG_INOXID_MAGIC is not set
-
#
# Security options
#
kfree(data);
}
-void generic_close(int fd, void *unused)
-{
- os_close_file(fd);
-}
-
-int generic_read(int fd, char *c_out, void *unused)
-{
- int n;
-
- n = os_read_file(fd, c_out, sizeof(*c_out));
-
- if(n == -EAGAIN)
- return(0);
- else if(n == 0)
- return(-EIO);
- return(n);
-}
-
-/* XXX Trivial wrapper around os_write_file */
-
-int generic_write(int fd, const char *buf, int n, void *unused)
-{
- return(os_write_file(fd, buf, n));
-}
-
-int generic_window_size(int fd, void *unused, unsigned short *rows_out,
- unsigned short *cols_out)
-{
- int rows, cols;
- int ret;
-
- ret = os_window_size(fd, &rows, &cols);
- if(ret < 0)
- return(ret);
-
- ret = ((*rows_out != rows) || (*cols_out != cols));
-
- *rows_out = rows;
- *cols_out = cols;
-
- return(ret);
-}
-
-void generic_free(void *data)
-{
- kfree(data);
-}
-
static void tty_receive_char(struct tty_struct *tty, char ch)
{
if(tty == NULL) return;
+++ /dev/null
-#define COW_MAJOR 60
-#define MAJOR_NR COW_MAJOR
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/stat.h>
-#include <linux/vmalloc.h>
-#include <linux/blkdev.h>
-#include <linux/blk.h>
-#include <linux/fs.h>
-#include <linux/genhd.h>
-#include <linux/devfs_fs.h>
-#include <asm/uaccess.h>
-#include "2_5compat.h"
-#include "cow.h"
-#include "ubd_user.h"
-
-#define COW_SHIFT 4
-
-struct cow {
- int count;
- char *cow_path;
- dev_t cow_dev;
- struct block_device *cow_bdev;
- char *backing_path;
- dev_t backing_dev;
- struct block_device *backing_bdev;
- int sectorsize;
- unsigned long *bitmap;
- unsigned long bitmap_len;
- int bitmap_offset;
- int data_offset;
- devfs_handle_t devfs;
- struct semaphore sem;
- struct semaphore io_sem;
- atomic_t working;
- spinlock_t io_lock;
- struct buffer_head *bh;
- struct buffer_head *bhtail;
- void *end_io;
-};
-
-#define DEFAULT_COW { \
- .count = 0, \
- .cow_path = NULL, \
- .cow_dev = 0, \
- .backing_path = NULL, \
- .backing_dev = 0, \
- .bitmap = NULL, \
- .bitmap_len = 0, \
- .bitmap_offset = 0, \
- .data_offset = 0, \
- .devfs = NULL, \
- .working = ATOMIC_INIT(0), \
- .io_lock = SPIN_LOCK_UNLOCKED, \
-}
-
-#define MAX_DEV (8)
-#define MAX_MINOR (MAX_DEV << COW_SHIFT)
-
-struct cow cow_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_COW };
-
-/* Not modified by this driver */
-static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE };
-static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 };
-
-/* Protected by cow_lock */
-static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 };
-
-static struct hd_struct cow_part[MAX_MINOR] =
- { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } };
-
-/* Protected by io_request_lock */
-static request_queue_t *cow_queue;
-
-static int cow_open(struct inode *inode, struct file *filp);
-static int cow_release(struct inode * inode, struct file * file);
-static int cow_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd, unsigned long arg);
-static int cow_revalidate(kdev_t rdev);
-
-static struct block_device_operations cow_blops = {
- .open = cow_open,
- .release = cow_release,
- .ioctl = cow_ioctl,
- .revalidate = cow_revalidate,
-};
-
-/* Initialized in an initcall, and unchanged thereafter */
-devfs_handle_t cow_dir_handle;
-
-#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 spinlock_t cow_lock = SPIN_LOCK_UNLOCKED;
-
-static struct gendisk cow_gendisk = INIT_GENDISK(MAJOR_NR, "cow", cow_part,
- COW_SHIFT, sizes, MAX_DEV,
- &cow_blops);
-
-static int cow_add(int n)
-{
- struct cow *dev = &cow_dev[n];
- char name[sizeof("nnnnnn\0")];
- int err = -ENODEV;
-
- if(dev->cow_path == NULL)
- goto out;
-
- sprintf(name, "%d", n);
- dev->devfs = devfs_register(cow_dir_handle, name, DEVFS_FL_REMOVABLE,
- MAJOR_NR, n << COW_SHIFT, S_IFBLK |
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- &cow_blops, NULL);
-
- init_MUTEX_LOCKED(&dev->sem);
- init_MUTEX(&dev->io_sem);
-
- return(0);
-
- out:
- return(err);
-}
-
-/*
- * Add buffer_head to back of pending list
- */
-static void cow_add_bh(struct cow *cow, struct buffer_head *bh)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cow->io_lock, flags);
- if(cow->bhtail != NULL){
- cow->bhtail->b_reqnext = bh;
- cow->bhtail = bh;
- }
- else {
- cow->bh = bh;
- cow->bhtail = bh;
- }
- spin_unlock_irqrestore(&cow->io_lock, flags);
-}
-
-/*
-* Grab first pending buffer
-*/
-static struct buffer_head *cow_get_bh(struct cow *cow)
-{
- struct buffer_head *bh;
-
- spin_lock_irq(&cow->io_lock);
- bh = cow->bh;
- if(bh != NULL){
- if(bh == cow->bhtail)
- cow->bhtail = NULL;
- cow->bh = bh->b_reqnext;
- bh->b_reqnext = NULL;
- }
- spin_unlock_irq(&cow->io_lock);
-
- return(bh);
-}
-
-static void cow_handle_bh(struct cow *cow, struct buffer_head *bh,
- struct buffer_head **cow_bh, int ncow_bh)
-{
- int i;
-
- if(ncow_bh > 0)
- ll_rw_block(WRITE, ncow_bh, cow_bh);
-
- for(i = 0; i < ncow_bh ; i++){
- wait_on_buffer(cow_bh[i]);
- brelse(cow_bh[i]);
- }
-
- ll_rw_block(WRITE, 1, &bh);
- brelse(bh);
-}
-
-static struct buffer_head *cow_new_bh(struct cow *dev, int sector)
-{
- struct buffer_head *bh;
-
- sector = (dev->bitmap_offset + sector / 8) / dev->sectorsize;
- bh = getblk(dev->cow_dev, sector, dev->sectorsize);
- memcpy(bh->b_data, dev->bitmap + sector / (8 * sizeof(dev->bitmap[0])),
- dev->sectorsize);
- return(bh);
-}
-
-/* Copied from loop.c, needed to avoid deadlocking in make_request. */
-
-static int cow_thread(void *data)
-{
- struct cow *dev = data;
- struct buffer_head *bh;
-
- daemonize();
- exit_files(current);
-
- sprintf(current->comm, "cow%d", dev - cow_dev);
-
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- flush_signals(current);
- spin_unlock_irq(¤t->sigmask_lock);
-
- atomic_inc(&dev->working);
-
- current->policy = SCHED_OTHER;
- current->nice = -20;
-
- current->flags |= PF_NOIO;
-
- /*
- * up sem, we are running
- */
- up(&dev->sem);
-
- for(;;){
- int start, len, nbh, i, update_bitmap = 0;
- struct buffer_head *cow_bh[2];
-
- down_interruptible(&dev->io_sem);
- /*
- * could be upped because of tear-down, not because of
- * pending work
- */
- if(!atomic_read(&dev->working))
- break;
-
- bh = cow_get_bh(dev);
- if(bh == NULL){
- printk(KERN_ERR "cow: missing bh\n");
- continue;
- }
-
- start = bh->b_blocknr * bh->b_size / dev->sectorsize;
- len = bh->b_size / dev->sectorsize;
- for(i = 0; i < len ; i++){
- if(ubd_test_bit(start + i,
- (unsigned char *) dev->bitmap))
- continue;
-
- update_bitmap = 1;
- ubd_set_bit(start + i, (unsigned char *) dev->bitmap);
- }
-
- cow_bh[0] = NULL;
- cow_bh[1] = NULL;
- nbh = 0;
- if(update_bitmap){
- cow_bh[0] = cow_new_bh(dev, start);
- nbh++;
- if(start / dev->sectorsize !=
- (start + len) / dev->sectorsize){
- cow_bh[1] = cow_new_bh(dev, start + len);
- nbh++;
- }
- }
-
- bh->b_dev = dev->cow_dev;
- bh->b_blocknr += dev->data_offset / dev->sectorsize;
-
- cow_handle_bh(dev, bh, cow_bh, nbh);
-
- /*
- * upped both for pending work and tear-down, lo_pending
- * will hit zero then
- */
- if(atomic_dec_and_test(&dev->working))
- break;
- }
-
- up(&dev->sem);
- return(0);
-}
-
-static int cow_make_request(request_queue_t *q, int rw, struct buffer_head *bh)
-{
- struct cow *dev;
- int n, minor;
-
- minor = MINOR(bh->b_rdev);
- n = minor >> COW_SHIFT;
- dev = &cow_dev[n];
-
- dev->end_io = NULL;
- if(ubd_test_bit(bh->b_rsector, (unsigned char *) dev->bitmap)){
- bh->b_rdev = dev->cow_dev;
- bh->b_rsector += dev->data_offset / dev->sectorsize;
- }
- else if(rw == WRITE){
- bh->b_dev = dev->cow_dev;
- bh->b_blocknr += dev->data_offset / dev->sectorsize;
-
- cow_add_bh(dev, bh);
- up(&dev->io_sem);
- return(0);
- }
- else {
- bh->b_rdev = dev->backing_dev;
- }
-
- return(1);
-}
-
-int cow_init(void)
-{
- int i;
-
- cow_dir_handle = devfs_mk_dir (NULL, "cow", NULL);
- if (devfs_register_blkdev(MAJOR_NR, "cow", &cow_blops)) {
- printk(KERN_ERR "cow: unable to get major %d\n", MAJOR_NR);
- return -1;
- }
- 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);
-
- cow_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
- blk_init_queue(cow_queue, NULL);
- INIT_ELV(cow_queue, &cow_queue->elevator);
- blk_queue_make_request(cow_queue, cow_make_request);
-
- add_gendisk(&cow_gendisk);
-
- for(i=0;i<MAX_DEV;i++)
- cow_add(i);
-
- return(0);
-}
-
-__initcall(cow_init);
-
-static int reader(__u64 start, char *buf, int count, void *arg)
-{
- dev_t dev = *((dev_t *) arg);
- struct buffer_head *bh;
- __u64 block;
- int cur, offset, left, n, blocksize = get_hardsect_size(dev);
-
- if(blocksize == 0)
- panic("Zero blocksize");
-
- block = start / blocksize;
- offset = start % blocksize;
- left = count;
- cur = 0;
- while(left > 0){
- n = (left > blocksize) ? blocksize : left;
-
- bh = bread(dev, block, (n < 512) ? 512 : n);
- if(bh == NULL)
- return(-EIO);
-
- n -= offset;
- memcpy(&buf[cur], bh->b_data + offset, n);
- block++;
- left -= n;
- cur += n;
- offset = 0;
- brelse(bh);
- }
-
- return(count);
-}
-
-static int cow_open(struct inode *inode, struct file *filp)
-{
- int (*dev_ioctl)(struct inode *, struct file *, unsigned int,
- unsigned long);
- mm_segment_t fs;
- struct cow *dev;
- __u64 size;
- __u32 version, align;
- time_t mtime;
- char *backing_file;
- int n, offset, err = 0;
-
- n = DEVICE_NR(inode->i_rdev);
- if(n >= MAX_DEV)
- return(-ENODEV);
- dev = &cow_dev[n];
- offset = n << COW_SHIFT;
-
- spin_lock(&cow_lock);
-
- if(dev->count == 0){
- dev->cow_dev = name_to_kdev_t(dev->cow_path);
- if(dev->cow_dev == 0){
- printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
- "failed\n", dev->cow_path);
- err = -ENODEV;
- }
-
- dev->backing_dev = name_to_kdev_t(dev->backing_path);
- if(dev->backing_dev == 0){
- printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
- "failed\n", dev->backing_path);
- err = -ENODEV;
- }
-
- if(err)
- goto out;
-
- dev->cow_bdev = bdget(dev->cow_dev);
- if(dev->cow_bdev == NULL){
- printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n",
- dev->cow_path);
- err = -ENOMEM;
- }
- dev->backing_bdev = bdget(dev->backing_dev);
- if(dev->backing_bdev == NULL){
- printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n",
- dev->backing_path);
- err = -ENOMEM;
- }
-
- if(err)
- goto out;
-
- err = blkdev_get(dev->cow_bdev, FMODE_READ|FMODE_WRITE, 0,
- BDEV_RAW);
- if(err){
- printk("cow_open - blkdev_get of COW device failed, "
- "error = %d\n", err);
- goto out;
- }
-
- err = blkdev_get(dev->backing_bdev, FMODE_READ, 0, BDEV_RAW);
- if(err){
- printk("cow_open - blkdev_get of backing device "
- "failed, error = %d\n", err);
- goto out;
- }
-
- err = read_cow_header(reader, &dev->cow_dev, &version,
- &backing_file, &mtime, &size,
- &dev->sectorsize, &align,
- &dev->bitmap_offset);
- if(err){
- printk(KERN_ERR "cow_open - read_cow_header failed, "
- "err = %d\n", err);
- goto out;
- }
-
- cow_sizes(version, size, dev->sectorsize, align,
- dev->bitmap_offset, &dev->bitmap_len,
- &dev->data_offset);
- dev->bitmap = (void *) vmalloc(dev->bitmap_len);
- if(dev->bitmap == NULL){
- err = -ENOMEM;
- printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
- goto out;
- }
- flush_tlb_kernel_vm();
-
- err = reader(dev->bitmap_offset, (char *) dev->bitmap,
- dev->bitmap_len, &dev->cow_dev);
- if(err < 0){
- printk(KERN_ERR "Failed to read COW bitmap\n");
- vfree(dev->bitmap);
- goto out;
- }
-
- dev_ioctl = dev->backing_bdev->bd_op->ioctl;
- fs = get_fs();
- set_fs(KERNEL_DS);
- err = (*dev_ioctl)(inode, filp, BLKGETSIZE,
- (unsigned long) &sizes[offset]);
- set_fs(fs);
- if(err){
- printk(KERN_ERR "cow_open - BLKGETSIZE failed, "
- "error = %d\n", err);
- goto out;
- }
-
- kernel_thread(cow_thread, dev,
- CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- down(&dev->sem);
- }
- dev->count++;
- out:
- spin_unlock(&cow_lock);
- return(err);
-}
-
-static int cow_release(struct inode * inode, struct file * file)
-{
- struct cow *dev;
- int n, err;
-
- n = DEVICE_NR(inode->i_rdev);
- if(n >= MAX_DEV)
- return(-ENODEV);
- dev = &cow_dev[n];
-
- spin_lock(&cow_lock);
-
- if(--dev->count > 0)
- goto out;
-
- err = blkdev_put(dev->cow_bdev, BDEV_RAW);
- if(err)
- printk("cow_release - blkdev_put of cow device failed, "
- "error = %d\n", err);
- bdput(dev->cow_bdev);
- dev->cow_bdev = 0;
-
- err = blkdev_put(dev->backing_bdev, BDEV_RAW);
- if(err)
- printk("cow_release - blkdev_put of backing device failed, "
- "error = %d\n", err);
- bdput(dev->backing_bdev);
- dev->backing_bdev = 0;
-
- out:
- spin_unlock(&cow_lock);
- return(0);
-}
-
-static int cow_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- struct cow *dev;
- int (*dev_ioctl)(struct inode *, struct file *, unsigned int,
- unsigned long);
- int n;
-
- n = DEVICE_NR(inode->i_rdev);
- if(n >= MAX_DEV)
- return(-ENODEV);
- dev = &cow_dev[n];
-
- dev_ioctl = dev->backing_bdev->bd_op->ioctl;
- return((*dev_ioctl)(inode, file, cmd, arg));
-}
-
-static int cow_revalidate(kdev_t rdev)
-{
- printk(KERN_ERR "Need to implement cow_revalidate\n");
- return(0);
-}
-
-static int parse_unit(char **ptr)
-{
- char *str = *ptr, *end;
- int n = -1;
-
- if(isdigit(*str)) {
- n = simple_strtoul(str, &end, 0);
- if(end == str)
- return(-1);
- *ptr = end;
- }
- else if (('a' <= *str) && (*str <= 'h')) {
- n = *str - 'a';
- str++;
- *ptr = str;
- }
- return(n);
-}
-
-static int cow_setup(char *str)
-{
- struct cow *dev;
- char *cow_name, *backing_name;
- int unit;
-
- unit = parse_unit(&str);
- if(unit < 0){
- printk(KERN_ERR "cow_setup - Couldn't parse unit number\n");
- return(1);
- }
-
- if(*str != '='){
- printk(KERN_ERR "cow_setup - Missing '=' after unit "
- "number\n");
- return(1);
- }
- str++;
-
- cow_name = str;
- backing_name = strchr(str, ',');
- if(backing_name == NULL){
- printk(KERN_ERR "cow_setup - missing backing device name\n");
- return(0);
- }
- *backing_name = '\0';
- backing_name++;
-
- spin_lock(&cow_lock);
-
- dev = &cow_dev[unit];
- dev->cow_path = cow_name;
- dev->backing_path = backing_name;
-
- spin_unlock(&cow_lock);
- return(0);
-}
-
-__setup("cow", cow_setup);
-
-/*
- * 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:
- */
int sectorsize;
};
-/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
* case other systems have different values for MAXPATHLEN
*/
#define PATH_LEN_V3 4096
-/* Changes from V2 -
+/* Changes from V2 -
* PATH_LEN_V3 as described above
* Explicitly specify field bit lengths for systems with different
* lengths for the usual C types. Not sure whether char or
#define DIV_ROUND(x, len) (((x) + (len) - 1) / (len))
#define ROUND_UP(x, align) DIV_ROUND(x, align) * (align)
-void cow_sizes(int version, __u64 size, int sectorsize, int align,
- int bitmap_offset, unsigned long *bitmap_len_out,
+void cow_sizes(int version, __u64 size, int sectorsize, int align,
+ int bitmap_offset, unsigned long *bitmap_len_out,
int *data_offset_out)
{
if(version < 3){
*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
*data_offset_out = bitmap_offset + *bitmap_len_out;
- *data_offset_out = (*data_offset_out + sectorsize - 1) /
+ *data_offset_out = (*data_offset_out + sectorsize - 1) /
sectorsize;
*data_offset_out *= sectorsize;
}
int remaining;
if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
- cow_printf("absolutize : unable to get cwd - errno = %d\n",
+ cow_printf("absolutize : unable to get cwd - errno = %d\n",
errno);
return(-1);
}
*slash = '\0';
if(chdir(from)){
*slash = '/';
- cow_printf("absolutize : Can't cd to '%s' - "
+ cow_printf("absolutize : Can't cd to '%s' - "
"errno = %d\n", from, errno);
return(-1);
}
return(0);
}
-int write_cow_header(char *cow_file, int fd, char *backing_file,
+int write_cow_header(char *cow_file, int fd, char *backing_file,
int sectorsize, int alignment, long long *size)
{
struct cow_header_v3 *header;
err = -EINVAL;
if(strlen(backing_file) > sizeof(header->backing_file) - 1){
cow_printf("Backing file name \"%s\" is too long - names are "
- "limited to %d characters\n", backing_file,
+ "limited to %d characters\n", backing_file,
sizeof(header->backing_file) - 1);
goto out_free;
}
- if(absolutize(header->backing_file, sizeof(header->backing_file),
+ if(absolutize(header->backing_file, sizeof(header->backing_file),
backing_file))
goto out_free;
/* XXX Need to sanity-check the values read from the header */
-int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
- __u32 *version_out, char **backing_file_out,
- time_t *mtime_out, __u64 *size_out,
- int *sectorsize_out, __u32 *align_out,
+int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
+ __u32 *version_out, char **backing_file_out,
+ time_t *mtime_out, __u64 *size_out,
+ int *sectorsize_out, __u32 *align_out,
int *bitmap_offset_out)
{
union cow_header *header;
}
else {
cow_printf("read_cow_header - invalid COW version\n");
- goto out;
+ goto out;
}
err = -ENOMEM;
*backing_file_out = cow_strdup(file);
}
int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
- int alignment, int *bitmap_offset_out,
+ int alignment, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out)
{
__u64 size, offset;
char zero = 0;
int err;
- err = write_cow_header(cow_file, fd, backing_file, sectorsize,
+ err = write_cow_header(cow_file, fd, backing_file, sectorsize,
alignment, &size);
- if(err)
+ if(err)
goto out;
-
+
*bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment);
cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out,
bitmap_len_out, data_offset_out);
goto out;
}
- /* does not really matter how much we write it is just to set EOF
+ /* does not really matter how much we write it is just to set EOF
* this also sets the entire COW bitmap
- * to zero without having to allocate it
+ * to zero without having to allocate it
*/
err = cow_write_file(fd, &zero, sizeof(zero));
if(err != sizeof(zero)){
printk("hostaudio: release called\n");
#endif
- os_close_file(state->fd);
+ os_close_file(state->fd);
kfree(state);
return(0);
printk("hostmixer: release called\n");
#endif
- os_close_file(state->fd);
+ os_close_file(state->fd);
kfree(state);
return(0);
*/
#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "hostaudio.h"
ssize_t hostaudio_read_user(struct hostaudio_state *state, char *buffer,
size_t count, loff_t *ppos)
{
+ ssize_t ret;
+
#ifdef DEBUG
printk("hostaudio: read_user called, count = %d\n", count);
#endif
- return(os_read_file(state->fd, buffer, count));
+ ret = read(state->fd, buffer, count);
+
+ if(ret < 0) return(-errno);
+ return(ret);
}
ssize_t hostaudio_write_user(struct hostaudio_state *state, const char *buffer,
size_t count, loff_t *ppos)
{
+ ssize_t ret;
+
#ifdef DEBUG
printk("hostaudio: write_user called, count = %d\n", count);
#endif
- return(os_write_file(state->fd, buffer, count));
+ ret = write(state->fd, buffer, count);
+
+ if(ret < 0) return(-errno);
+ return(ret);
}
int hostaudio_ioctl_user(struct hostaudio_state *state, unsigned int cmd,
unsigned long arg)
{
+ int ret;
#ifdef DEBUG
printk("hostaudio: ioctl_user called, cmd = %u\n", cmd);
#endif
- return(os_ioctl_generic(state->fd, cmd, arg));
+ ret = ioctl(state->fd, cmd, arg);
+
+ if(ret < 0) return(-errno);
+ return(ret);
}
int hostaudio_open_user(struct hostaudio_state *state, int r, int w, char *dsp)
printk("hostaudio: open_user called\n");
#endif
- state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
+ state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
+
+ if(state->fd >= 0) return(0);
- if(state->fd < 0) {
- printk("hostaudio_open_user failed to open '%s', err = %d\n",
- dsp, -state->fd);
- return(state->fd);
- }
+ printk("hostaudio_open_user failed to open '%s', errno = %d\n",
+ dsp, errno);
- return(0);
+ return(-errno);
}
int hostaudio_release_user(struct hostaudio_state *state)
#ifdef DEBUG
printk("hostaudio: release called\n");
#endif
- if(state->fd >= 0){
- os_close_file(state->fd);
- state->fd = -1;
- }
+ if(state->fd >= 0){
+ close(state->fd);
+ state->fd=-1;
+ }
return(0);
}
int hostmixer_ioctl_mixdev_user(struct hostmixer_state *state,
unsigned int cmd, unsigned long arg)
{
+ int ret;
#ifdef DEBUG
printk("hostmixer: ioctl_user called cmd = %u\n",cmd);
#endif
- return(os_ioctl_generic(state->fd, cmd, arg));
+ ret = ioctl(state->fd, cmd, arg);
+ if(ret < 0)
+ return(-errno);
+ return(ret);
}
int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, int w,
state->fd = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
- if(state->fd < 0) {
- printk("hostaudio_open_mixdev_user failed to open '%s', "
- "err = %d\n", mixer, state->fd);
- return(state->fd);
- }
+ if(state->fd >= 0) return(0);
+
+ printk("hostaudio_open_mixdev_user failed to open '%s', errno = %d\n",
+ mixer, errno);
- return(0);
+ return(-errno);
}
int hostmixer_release_mixdev_user(struct hostmixer_state *state)
#endif
if(state->fd >= 0){
- os_close_file(state->fd);
+ close(state->fd);
state->fd = -1;
}
os_close_file(fds[1]);
read_output(fds[0], output, output_len);
+
CATCH_EINTR(err = waitpid(pid, NULL, 0));
return(pid);
}
io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
&thread_fd);
if(io_pid < 0){
- io_pid = -1;
printk(KERN_ERR
"ubd : Failed to start I/O thread (errno = %d) - "
"falling back to synchronous I/O\n", -io_pid);
-#include <asm-generic/vmlinux.lds.h>
-
OUTPUT_FORMAT(ELF_FORMAT)
OUTPUT_ARCH(ELF_ARCH)
ENTRY(_start)
jiffies = jiffies_64;
+SEARCH_DIR("/usr/local/i686-pc-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
SECTIONS
{
. = START + SIZEOF_HEADERS;
.interp : { *(.interp) }
+ . = ALIGN(4096);
__binary_start = .;
. = ALIGN(4096); /* Init code and data */
_stext = .;
__init_begin = .;
- .init.text : {
- _sinittext = .;
- *(.init.text)
- _einittext = .;
- }
+ .text.init : { *(.text.init) }
. = ALIGN(4096);
} =0x90909090
.plt : { *(.plt) }
.text : {
- *(.text)
- SCHED_TEXT
- *(.stub .text.* .gnu.linkonce.t.*)
+ *(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0x90909090
#include "asm/common.lds.S"
- init.data : { *(.init.data) }
+ .data.init : { *(.data.init) }
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
+++ /dev/null
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __FILEHANDLE_H__
-#define __FILEHANDLE_H__
-
-#include "linux/list.h"
-#include "linux/fs.h"
-#include "os.h"
-
-struct file_handle {
- struct list_head list;
- int fd;
- char *(*get_name)(struct inode *);
- struct inode *inode;
- struct openflags flags;
-};
-
-extern struct file_handle bad_filehandle;
-
-extern int open_file(char *name, struct openflags flags, int mode);
-extern void *open_dir(char *file);
-extern int open_filehandle(char *name, struct openflags flags, int mode,
- struct file_handle *fh);
-extern int read_file(struct file_handle *fh, unsigned long long offset,
- char *buf, int len);
-extern int write_file(struct file_handle *fh, unsigned long long offset,
- const char *buf, int len);
-extern int truncate_file(struct file_handle *fh, unsigned long long size);
-extern int close_file(struct file_handle *fh);
-extern void not_reclaimable(struct file_handle *fh);
-extern void is_reclaimable(struct file_handle *fh,
- char *(name_proc)(struct inode *),
- struct inode *inode);
-extern int filehandle_fd(struct file_handle *fh);
-extern int make_pipe(struct file_handle *fhs);
-
-#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:
- */
#define __uml_postsetup_call __attribute__ ((unused,__section__ (".uml.postsetup.init")))
#define __uml_exit_call __attribute__ ((unused,__section__ (".uml.exitcall.exit")))
-#ifndef __KERNEL__
-
-#define __initcall(fn) static initcall_t __initcall_##fn __init_call = fn
-#define __exitcall(fn) static exitcall_t __exitcall_##fn __exit_call = fn
-
-#define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
-#define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit")))
-
-#endif
-
#endif /* _LINUX_UML_INIT_H */
/*
unsigned int a : 1; /* O_APPEND */
unsigned int e : 1; /* O_EXCL */
unsigned int cl : 1; /* FD_CLOEXEC */
- unsigned int d : 1; /* O_DIRECT */
};
#define OPENFLAGS() ((struct openflags) { .r = 0, .w = 0, .s = 0, .c = 0, \
- .t = 0, .a = 0, .e = 0, .cl = 0, \
- .d = 0 })
+ .t = 0, .a = 0, .e = 0, .cl = 0 })
static inline struct openflags of_read(struct openflags flags)
{
extern int os_seek_file(int fd, __u64 offset);
extern int os_open_file(char *file, struct openflags flags, int mode);
-extern void *os_open_dir(char *dir, int *err_out);
-extern int os_seek_dir(void *stream, unsigned long long pos);
-extern int os_read_dir(void *stream, unsigned long long *ino_out,
- char **name_out);
-extern int os_tell_dir(void *stream);
-extern int os_close_dir(void *stream);
-extern int os_remove_file(const char *file);
-extern int os_move_file(const char *from, const char *to);
-extern int os_truncate_file(const char *file, unsigned long long len);
-extern int os_truncate_fd(int fd, unsigned long long len);
extern int os_read_file(int fd, void *buf, int len);
extern int os_write_file(int fd, const void *buf, int count);
extern int os_file_size(char *file, long long *size_out);
+++ /dev/null
-/* Automatically generated by arch/um/kernel/skas/util/mk_ptregs */
-
-#ifndef __SKAS_PT_REGS_
-#define __SKAS_PT_REGS_
-
-#define HOST_FRAME_SIZE 17
-#define HOST_FP_SIZE 27
-#define HOST_XFP_SIZE 128
-#define HOST_IP 12
-#define HOST_SP 15
-#define HOST_EFLAGS 14
-#define HOST_EAX 6
-#define HOST_EBX 0
-#define HOST_ECX 1
-#define HOST_EDX 2
-#define HOST_ESI 3
-#define HOST_EDI 4
-#define HOST_EBP 5
-#define HOST_CS 13
-#define HOST_SS 16
-#define HOST_DS 7
-#define HOST_FS 9
-#define HOST_ES 8
-#define HOST_GS 10
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/slab.h"
-#include "linux/list.h"
-#include "linux/spinlock.h"
-#include "linux/fs.h"
-#include "linux/errno.h"
-#include "filehandle.h"
-#include "os.h"
-#include "kern_util.h"
-
-static spinlock_t open_files_lock = SPIN_LOCK_UNLOCKED;
-static struct list_head open_files = LIST_HEAD_INIT(open_files);
-
-#define NUM_RECLAIM 128
-
-static void reclaim_fds(void)
-{
- struct file_handle *victim;
- int closed = NUM_RECLAIM;
-
- spin_lock(&open_files_lock);
- while(!list_empty(&open_files) && closed--){
- victim = list_entry(open_files.prev, struct file_handle, list);
- os_close_file(victim->fd);
- victim->fd = -1;
- list_del_init(&victim->list);
- }
- spin_unlock(&open_files_lock);
-}
-
-int open_file(char *name, struct openflags flags, int mode)
-{
- int fd;
-
- fd = os_open_file(name, flags, mode);
- if(fd != -EMFILE)
- return(fd);
-
- reclaim_fds();
- fd = os_open_file(name, flags, mode);
-
- return(fd);
-}
-
-void *open_dir(char *file)
-{
- void *dir;
- int err;
-
- dir = os_open_dir(file, &err);
- if(dir != NULL)
- return(dir);
- if(err != -EMFILE)
- return(ERR_PTR(err));
-
- reclaim_fds();
-
- dir = os_open_dir(file, &err);
- if(dir == NULL)
- dir = ERR_PTR(err);
-
- return(dir);
-}
-
-void not_reclaimable(struct file_handle *fh)
-{
- char *name;
-
- if(fh->get_name == NULL)
- return;
-
- if(list_empty(&fh->list)){
- name = (*fh->get_name)(fh->inode);
- if(name != NULL){
- fh->fd = open_file(name, fh->flags, 0);
- kfree(name);
- }
- else printk("File descriptor %d has no name\n", fh->fd);
- }
- else {
- spin_lock(&open_files_lock);
- list_del_init(&fh->list);
- spin_unlock(&open_files_lock);
- }
-}
-
-void is_reclaimable(struct file_handle *fh, char *(name_proc)(struct inode *),
- struct inode *inode)
-{
- fh->get_name = name_proc;
- fh->inode = inode;
-
- spin_lock(&open_files_lock);
- list_add(&fh->list, &open_files);
- spin_unlock(&open_files_lock);
-}
-
-static int active_handle(struct file_handle *fh)
-{
- int fd;
- char *name;
-
- if(!list_empty(&fh->list))
- list_move(&fh->list, &open_files);
-
- if(fh->fd != -1)
- return(0);
-
- if(fh->inode == NULL)
- return(-ENOENT);
-
- name = (*fh->get_name)(fh->inode);
- if(name == NULL)
- return(-ENOMEM);
-
- fd = open_file(name, fh->flags, 0);
- kfree(name);
- if(fd < 0)
- return(fd);
-
- fh->fd = fd;
- is_reclaimable(fh, fh->get_name, fh->inode);
-
- return(0);
-}
-
-int filehandle_fd(struct file_handle *fh)
-{
- int err;
-
- err = active_handle(fh);
- if(err)
- return(err);
-
- return(fh->fd);
-}
-
-static void init_fh(struct file_handle *fh, int fd, struct openflags flags)
-{
- flags.c = 0;
- *fh = ((struct file_handle) { .list = LIST_HEAD_INIT(fh->list),
- .fd = fd,
- .get_name = NULL,
- .inode = NULL,
- .flags = flags });
-}
-
-int open_filehandle(char *name, struct openflags flags, int mode,
- struct file_handle *fh)
-{
- int fd;
-
- fd = open_file(name, flags, mode);
- if(fd < 0)
- return(fd);
-
- init_fh(fh, fd, flags);
- return(0);
-}
-
-int close_file(struct file_handle *fh)
-{
- spin_lock(&open_files_lock);
- list_del(&fh->list);
- spin_unlock(&open_files_lock);
-
- os_close_file(fh->fd);
-
- fh->fd = -1;
- return(0);
-}
-
-int read_file(struct file_handle *fh, unsigned long long offset, char *buf,
- int len)
-{
- int err;
-
- err = active_handle(fh);
- if(err)
- return(err);
-
- err = os_seek_file(fh->fd, offset);
- if(err)
- return(err);
-
- return(os_read_file(fh->fd, buf, len));
-}
-
-int write_file(struct file_handle *fh, unsigned long long offset,
- const char *buf, int len)
-{
- int err;
-
- err = active_handle(fh);
- if(err)
- return(err);
-
- if(offset != -1)
- err = os_seek_file(fh->fd, offset);
- if(err)
- return(err);
-
- return(os_write_file(fh->fd, buf, len));
-}
-
-int truncate_file(struct file_handle *fh, unsigned long long size)
-{
- int err;
-
- err = active_handle(fh);
- if(err)
- return(err);
-
- return(os_truncate_fd(fh->fd, size));
-}
-
-int make_pipe(struct file_handle *fhs)
-{
- int fds[2], err;
-
- err = os_pipe(fds, 1, 1);
- if(err && (err != -EMFILE))
- return(err);
-
- if(err){
- reclaim_fds();
- err = os_pipe(fds, 1, 1);
- }
- if(err)
- return(err);
-
- init_fh(&fhs[0], fds[0], OPENFLAGS());
- init_fh(&fhs[1], fds[1], OPENFLAGS());
- 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:
- */
CATCH_EINTR(n = waitpid(pid, NULL, 0));
pid = -errno;
}
- err = pid;
- out_close:
- os_close_file(fds[0]);
- out_free:
- if(stack_out == NULL)
- free_stack(stack, 0);
+ if(stack_out == NULL) free_stack(stack, 0);
else *stack_out = stack;
return(pid);
{
int flags = altstack ? SA_ONSTACK : 0;
- set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
#include "linux/capability.h"
#include "linux/vmalloc.h"
#include "linux/spinlock.h"
-#include "linux/vs_cvirt.h"
#include "linux/proc_fs.h"
#include "linux/ptrace.h"
-#include "linux/vs_cvirt.h"
-
#include "asm/unistd.h"
#include "asm/mman.h"
#include "asm/segment.h"
read_unlock(&tasklist_lock);
if (!child)
goto out;
- if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
- goto out_tsk;
ret = -EPERM;
if (pid == 1) /* you may not mess with init */
--- /dev/null
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <sched.h>
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+#include "user.h"
+#include "kern_util.h"
+#include "user_util.h"
+#include "os.h"
+#include "time_user.h"
+
+static int user_thread_tramp(void *arg)
+{
+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
+ panic("user_thread_tramp - PTRACE_TRACEME failed, "
+ "errno = %d\n", errno);
+ enable_timer();
+ os_stop_process(os_getpid());
+ return(0);
+}
+
+int user_thread(unsigned long stack, int flags)
+{
+ int pid, status, err;
+
+ pid = clone(user_thread_tramp, (void *) stack_sp(stack),
+ flags | CLONE_FILES | SIGCHLD, NULL);
+ if(pid < 0){
+ printk("user_thread - clone failed, errno = %d\n", errno);
+ return(pid);
+ }
+
+ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+ if(err < 0){
+ printk("user_thread - waitpid failed, errno = %d\n", errno);
+ return(-errno);
+ }
+
+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){
+ printk("user_thread - trampoline didn't stop, status = %d\n",
+ status);
+ return(-EINVAL);
+ }
+
+ return(pid);
+}
+
+/*
+ * 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) 2004 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
-#ifndef AIO_H__
-#define AIO_H__
+#ifndef __SKAS_MMU_H
+#define __SKAS_MMU_H
-enum aio_type { AIO_READ, AIO_WRITE, AIO_MMAP };
+#include "linux/list.h"
+#include "linux/spinlock.h"
-struct aio_thread_reply {
- void *data;
- int err;
+struct mmu_context_skas {
+ int mm_fd;
};
-struct aio_context {
- int reply_fd;
-};
-
-#define INIT_AIO_CONTEXT { .reply_fd = -1 }
-
-extern int submit_aio(enum aio_type type, int fd, char *buf, int len,
- unsigned long long offset, int reply_fd, void *data);
-
#endif
/*
--- /dev/null
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MODE_SKAS_H__
+#define __MODE_SKAS_H__
+
+extern unsigned long exec_regs[];
+extern unsigned long exec_fp_regs[];
+extern unsigned long exec_fpx_regs[];
+extern int have_fpx_regs;
+
+extern void user_time_init_skas(void);
+extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs,
+ void *from_ptr);
+extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
+ union uml_pt_regs *regs,
+ unsigned long fault_addr, int fault_type);
+extern void sig_handler_common_skas(int sig, void *sc_ptr);
+extern void halt_skas(void);
+extern void reboot_skas(void);
+extern void kill_off_processes_skas(void);
+extern int is_skas_winch(int pid, int fd, void *data);
+
+#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:
+ */
--- /dev/null
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_MODE_KERN_H__
+#define __SKAS_MODE_KERN_H__
+
+#include "linux/sched.h"
+#include "asm/page.h"
+#include "asm/ptrace.h"
+
+extern void flush_thread_skas(void);
+extern void *switch_to_skas(void *prev, void *next);
+extern void start_thread_skas(struct pt_regs *regs, unsigned long eip,
+ unsigned long esp);
+extern int copy_thread_skas(int nr, unsigned long clone_flags,
+ unsigned long sp, unsigned long stack_top,
+ struct task_struct *p, struct pt_regs *regs);
+extern void release_thread_skas(struct task_struct *task);
+extern void exit_thread_skas(void);
+extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
+extern void init_idle_skas(void);
+extern void flush_tlb_kernel_range_skas(unsigned long start,
+ unsigned long end);
+extern void flush_tlb_kernel_vm_skas(void);
+extern void __flush_tlb_one_skas(unsigned long addr);
+extern void flush_tlb_range_skas(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
+extern void flush_tlb_mm_skas(struct mm_struct *mm);
+extern void force_flush_all_skas(void);
+extern long execute_syscall_skas(void *r);
+extern void before_mem_skas(unsigned long unused);
+extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
+ unsigned long *task_size_out);
+extern int start_uml_skas(void);
+extern int external_pid_skas(struct task_struct *task);
+extern int thread_pid_skas(struct task_struct *task);
+
+#define kmem_end_skas (host_task_size - 1024 * 1024)
+
+#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:
+ */
--- /dev/null
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_UACCESS_H
+#define __SKAS_UACCESS_H
+
+#include "asm/errno.h"
+
+#define access_ok_skas(type, addr, size) \
+ ((segment_eq(get_fs(), KERNEL_DS)) || \
+ (((unsigned long) (addr) < TASK_SIZE) && \
+ ((unsigned long) (addr) + (size) <= TASK_SIZE)))
+
+static inline int verify_area_skas(int type, const void * addr,
+ unsigned long size)
+{
+ return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
+}
+
+extern int copy_from_user_skas(void *to, const void *from, int n);
+extern int copy_to_user_skas(void *to, const void *from, int n);
+extern int strncpy_from_user_skas(char *dst, const char *src, int count);
+extern int __clear_user_skas(void *mem, int len);
+extern int clear_user_skas(void *mem, int len);
+extern int strnlen_user_skas(const void *str, int len);
+
+#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:
+ */
#include "linux/unistd.h"
#include "linux/slab.h"
#include "linux/utime.h"
-#include <linux/vs_cvirt.h>
-
#include "asm/mman.h"
#include "asm/uaccess.h"
#include "asm/ipc.h"
}
/* common code for old and new mmaps */
-long do_mmap2(struct mm_struct *mm, unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags, unsigned long fd,
- unsigned long pgoff)
+static inline long do_mmap2(
+ unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
{
int error = -EBADF;
struct file * file = NULL;
goto out;
}
- down_write(&mm->mmap_sem);
- error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff);
- up_write(&mm->mmap_sem);
+ down_write(¤t->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(¤t->mm->mmap_sem);
if (file)
fput(file);
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
- return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff);
+ return do_mmap2(addr, len, prot, flags, fd, pgoff);
}
/*
if (offset & ~PAGE_MASK)
goto out;
- err = do_mmap2(current->mm, addr, len, prot, flags, fd,
- offset >> PAGE_SHIFT);
+ err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
out:
return err;
}
if (!name)
return -EFAULT;
down_read(&uts_sem);
- err=copy_to_user(name, vx_new_utsname(), sizeof (*name));
+ err=copy_to_user(name, &system_utsname, sizeof (*name));
up_read(&uts_sem);
return err?-EFAULT:0;
}
long sys_olduname(struct oldold_utsname * name)
{
long error;
- struct new_utsname *ptr;
if (!name)
return -EFAULT;
down_read(&uts_sem);
- ptr = vx_new_utsname();
- error = __copy_to_user(&name->sysname,ptr->sysname,
+ error = __copy_to_user(&name->sysname,&system_utsname.sysname,
__OLD_UTS_LEN);
error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
- error |= __copy_to_user(&name->nodename,ptr->nodename,
+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename,
__OLD_UTS_LEN);
error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
- error |= __copy_to_user(&name->release,ptr->release,
+ error |= __copy_to_user(&name->release,&system_utsname.release,
__OLD_UTS_LEN);
error |= __put_user(0,name->release+__OLD_UTS_LEN);
- error |= __copy_to_user(&name->version,ptr->version,
+ error |= __copy_to_user(&name->version,&system_utsname.version,
__OLD_UTS_LEN);
error |= __put_user(0,name->version+__OLD_UTS_LEN);
- error |= __copy_to_user(&name->machine,ptr->machine,
+ error |= __copy_to_user(&name->machine,&system_utsname.machine,
__OLD_UTS_LEN);
error |= __put_user(0,name->machine+__OLD_UTS_LEN);
--- /dev/null
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __TT_MMU_H
+#define __TT_MMU_H
+
+struct mmu_context_tt {
+};
+
+#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:
+ */
--- /dev/null
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MODE_TT_H__
+#define __MODE_TT_H__
+
+#include "sysdep/ptrace.h"
+
+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
+
+extern int tracing_pid;
+
+extern int tracer(int (*init_proc)(void *), void *sp);
+extern void user_time_init_tt(void);
+extern int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data);
+extern int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr,
+ void *data);
+extern void sig_handler_common_tt(int sig, void *sc);
+extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
+extern void reboot_tt(void);
+extern void halt_tt(void);
+extern int is_tracer_winch(int pid, int fd, void *data);
+extern void kill_off_processes_tt(void);
+
+#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:
+ */
--- /dev/null
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __TT_MODE_KERN_H__
+#define __TT_MODE_KERN_H__
+
+#include "linux/sched.h"
+#include "asm/page.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+
+extern void *switch_to_tt(void *prev, void *next);
+extern void flush_thread_tt(void);
+extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
+ unsigned long esp);
+extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
+ unsigned long stack_top, struct task_struct *p,
+ struct pt_regs *regs);
+extern void release_thread_tt(struct task_struct *task);
+extern void exit_thread_tt(void);
+extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
+extern void init_idle_tt(void);
+extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
+extern void flush_tlb_kernel_vm_tt(void);
+extern void __flush_tlb_one_tt(unsigned long addr);
+extern void flush_tlb_range_tt(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
+extern void flush_tlb_mm_tt(struct mm_struct *mm);
+extern void force_flush_all_tt(void);
+extern long execute_syscall_tt(void *r);
+extern void before_mem_tt(unsigned long brk_start);
+extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
+ unsigned long *task_size_out);
+extern int start_uml_tt(void);
+extern int external_pid_tt(struct task_struct *task);
+extern int thread_pid_tt(struct task_struct *task);
+
+#define kmem_end_tt (host_task_size - ABOVE_KMEM)
+
+#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:
+ */
--- /dev/null
+/*
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __TT_UACCESS_H
+#define __TT_UACCESS_H
+
+#include "linux/string.h"
+#include "linux/sched.h"
+#include "asm/processor.h"
+#include "asm/errno.h"
+#include "asm/current.h"
+#include "asm/a.out.h"
+#include "uml_uaccess.h"
+
+#define ABOVE_KMEM (16 * 1024 * 1024)
+
+extern unsigned long end_vm;
+extern unsigned long uml_physmem;
+
+#define under_task_size(addr, size) \
+ (((unsigned long) (addr) < TASK_SIZE) && \
+ (((unsigned long) (addr) + (size)) < TASK_SIZE))
+
+#define is_stack(addr, size) \
+ (((unsigned long) (addr) < STACK_TOP) && \
+ ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \
+ (((unsigned long) (addr) + (size)) <= STACK_TOP))
+
+#define access_ok_tt(type, addr, size) \
+ ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \
+ (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \
+ (under_task_size(addr, size) || is_stack(addr, size))))
+
+static inline int verify_area_tt(int type, const void * addr,
+ unsigned long size)
+{
+ return(access_ok_tt(type, addr, size) ? 0 : -EFAULT);
+}
+
+extern unsigned long get_fault_addr(void);
+
+extern int __do_copy_from_user(void *to, const void *from, int n,
+ void **fault_addr, void **fault_catcher);
+extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
+ void **fault_addr, void **fault_catcher);
+extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
+ void **fault_catcher);
+extern int __do_strnlen_user(const char *str, unsigned long n,
+ void **fault_addr, void **fault_catcher);
+
+extern int copy_from_user_tt(void *to, const void *from, int n);
+extern int copy_to_user_tt(void *to, const void *from, int n);
+extern int strncpy_from_user_tt(char *dst, const char *src, int count);
+extern int __clear_user_tt(void *mem, int len);
+extern int clear_user_tt(void *mem, int len);
+extern int strnlen_user_tt(const void *str, int len);
+
+#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:
+ */
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <utime.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <sys/ioctl.h>
+#include "user_util.h"
+#include "mem_user.h"
+#include "uml-config.h"
+
+/* Had to steal this from linux/module.h because that file can't be included
+ * since this includes various user-level headers.
+ */
+
+struct module_symbol
+{
+ unsigned long value;
+ const char *name;
+};
+
+/* Indirect stringification. */
+
+#define __MODULE_STRING_1(x) #x
+#define __MODULE_STRING(x) __MODULE_STRING_1(x)
+
+#if !defined(__AUTOCONF_INCLUDED__)
+
+#define __EXPORT_SYMBOL(sym,str) error config_must_be_included_before_module
+#define EXPORT_SYMBOL(var) error config_must_be_included_before_module
+#define EXPORT_SYMBOL_NOVERS(var) error config_must_be_included_before_module
+
+#elif !defined(UML_CONFIG_MODULES)
+
+#define __EXPORT_SYMBOL(sym,str)
+#define EXPORT_SYMBOL(var)
+#define EXPORT_SYMBOL_NOVERS(var)
+
+#else
+
+#define __EXPORT_SYMBOL(sym, str) \
+const char __kstrtab_##sym[] \
+__attribute__((section(".kstrtab"))) = str; \
+const struct module_symbol __ksymtab_##sym \
+__attribute__((section("__ksymtab"))) = \
+{ (unsigned long)&sym, __kstrtab_##sym }
+
+#if defined(__MODVERSIONS__) || !defined(UML_CONFIG_MODVERSIONS)
+#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var))
+#else
+#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var)))
+#endif
+
+#define EXPORT_SYMBOL_NOVERS(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var))
+
+#endif
+
+EXPORT_SYMBOL(__errno_location);
+
+EXPORT_SYMBOL(access);
+EXPORT_SYMBOL(open);
+EXPORT_SYMBOL(open64);
+EXPORT_SYMBOL(close);
+EXPORT_SYMBOL(read);
+EXPORT_SYMBOL(write);
+EXPORT_SYMBOL(dup2);
+EXPORT_SYMBOL(__xstat);
+EXPORT_SYMBOL(__lxstat);
+EXPORT_SYMBOL(__lxstat64);
+EXPORT_SYMBOL(lseek);
+EXPORT_SYMBOL(lseek64);
+EXPORT_SYMBOL(chown);
+EXPORT_SYMBOL(truncate);
+EXPORT_SYMBOL(utime);
+EXPORT_SYMBOL(chmod);
+EXPORT_SYMBOL(rename);
+EXPORT_SYMBOL(__xmknod);
+
+EXPORT_SYMBOL(symlink);
+EXPORT_SYMBOL(link);
+EXPORT_SYMBOL(unlink);
+EXPORT_SYMBOL(readlink);
+
+EXPORT_SYMBOL(mkdir);
+EXPORT_SYMBOL(rmdir);
+EXPORT_SYMBOL(opendir);
+EXPORT_SYMBOL(readdir);
+EXPORT_SYMBOL(closedir);
+EXPORT_SYMBOL(seekdir);
+EXPORT_SYMBOL(telldir);
+
+EXPORT_SYMBOL(ioctl);
+
+extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes,
+ __off64_t __offset);
+extern ssize_t pwrite64 (int __fd, __const void *__buf, size_t __n,
+ __off64_t __offset);
+EXPORT_SYMBOL(pread64);
+EXPORT_SYMBOL(pwrite64);
+
+EXPORT_SYMBOL(statfs);
+EXPORT_SYMBOL(statfs64);
+
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(getuid);
+
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(strstr);
+
+EXPORT_SYMBOL(find_iomem);
#include <asm-generic/vmlinux.lds.h>
-
+
OUTPUT_FORMAT(ELF_FORMAT)
OUTPUT_ARCH(ELF_ARCH)
ENTRY(_start)
SECTIONS
{
-#include "asm/common.lds.S"
+ . = START + SIZEOF_HEADERS;
+
+ __binary_start = .;
+#ifdef MODE_TT
+ .thread_private : {
+ __start_thread_private = .;
+ errno = .;
+ . += 4;
+ arch/um/kernel/tt/unmap_fin.o (.data)
+ __end_thread_private = .;
+ }
+ . = ALIGN(4096);
+ .remap : { arch/um/kernel/tt/unmap_fin.o (.text) }
+#endif
+
+ . = ALIGN(4096); /* Init code and data */
+ _stext = .;
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+ . = ALIGN(4096);
+ .text :
+ {
+ *(.text)
+ SCHED_TEXT
+ LOCK_TEXT
+ *(.fixup)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t*)
+ }
+
+ #include "asm/common.lds.S"
+
+ init.data : { *(init.data) }
+ .data :
+ {
+ . = ALIGN(KERNEL_STACK_SIZE); /* init_task */
+ *(.data.init_task)
+ *(.data)
+ *(.gnu.linkonce.d*)
+ CONSTRUCTORS
+ }
+ .data1 : { *(.data1) }
+ .ctors :
+ {
+ *(.ctors)
+ }
+ .dtors :
+ {
+ *(.dtors)
+ }
+
+ .got : { *(.got.plt) *(.got) }
+ .dynamic : { *(.dynamic) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+ _edata = .;
+ PROVIDE (edata = .);
+ . = ALIGN(0x1000);
+ .sbss :
+ {
+ __bss_start = .;
+ PROVIDE(_bss_start = .);
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
}
#include <stdlib.h>
#include <string.h>
#include <signal.h>
-#include <errno.h>
#include <sys/resource.h>
#include <sys/mman.h>
#include <sys/user.h>
#include "kern_util.h"
#include "mem_user.h"
#include "signal_user.h"
-#include "time_user.h"
-#include "irq_user.h"
#include "user.h"
#include "init.h"
#include "mode.h"
set_stklim();
- new_argv = malloc((argc + 1) * sizeof(char *));
- if(new_argv == NULL){
+ if((new_argv = malloc((argc + 1) * sizeof(char *))) == NULL){
perror("Mallocing argv");
exit(1);
}
for(i=0;i<argc;i++){
- new_argv[i] = strdup(argv[i]);
- if(new_argv[i] == NULL){
+ if((new_argv[i] = strdup(argv[i])) == NULL){
perror("Mallocing an arg");
exit(1);
}
/* Reboot */
if(ret){
- int err;
-
printf("\n");
-
- /* Let any pending signals fire, then disable them. This
- * ensures that they won't be delivered after the exec, when
- * they are definitely not expected.
- */
- unblock_signals();
- disable_timer();
- err = deactivate_all_fds();
- if(err)
- printf("deactivate_all_fds failed, errno = %d\n", -err);
-
execvp(new_argv[0], new_argv);
perror("Failed to exec kernel");
ret = 1;
void *__wrap_malloc(int size)
{
- void *ret;
-
- if(!CAN_KMALLOC())
+ if(CAN_KMALLOC())
+ return(um_kmalloc(size));
+ else
return(__real_malloc(size));
- else if(size <= PAGE_SIZE) /* finding contiguos pages is hard */
- ret = um_kmalloc(size);
- else ret = um_vmalloc(size);
-
- /* glibc people insist that if malloc fails, errno should be
- * set by malloc as well. So we do.
- */
- if(ret == NULL)
- errno = ENOMEM;
-
- return(ret);
}
void *__wrap_calloc(int n, int size)
extern void __real_free(void *);
-extern unsigned long high_physmem;
-
void __wrap_free(void *ptr)
{
- unsigned long addr = (unsigned long) ptr;
-
- /* We need to know how the allocation happened, so it can be correctly
- * freed. This is done by seeing what region of memory the pointer is
- * in -
- * physical memory - kmalloc/kfree
- * kernel virtual memory - vmalloc/vfree
- * anywhere else - malloc/free
- * If kmalloc is not yet possible, then the kernel memory regions
- * may not be set up yet, and the variables not set up. So,
- * free is called.
- *
- * CAN_KMALLOC is checked because it would be bad to free a buffer
- * with kmalloc/vmalloc after they have been turned off during
- * shutdown.
- */
-
- if((addr >= uml_physmem) && (addr < high_physmem)){
- if(CAN_KMALLOC())
- kfree(ptr);
- }
- else if((addr >= start_vm) && (addr < end_vm)){
- if(CAN_KMALLOC())
- vfree(ptr);
- }
+ if(CAN_KMALLOC()) kfree(ptr);
else __real_free(ptr);
}
+++ /dev/null
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <errno.h>
-#include <sched.h>
-#include <sys/syscall.h>
-#include "os.h"
-#include "helper.h"
-#include "aio.h"
-#include "init.h"
-#include "user.h"
-#include "mode.h"
-
-struct aio_thread_req {
- enum aio_type type;
- int io_fd;
- unsigned long long offset;
- char *buf;
- int len;
- int reply_fd;
- void *data;
-};
-
-static int aio_req_fd_r = -1;
-static int aio_req_fd_w = -1;
-
-#if defined(HAVE_AIO_ABI)
-#include <linux/aio_abi.h>
-
-/* If we have the headers, we are going to build with AIO enabled.
- * If we don't have aio in libc, we define the necessary stubs here.
- */
-
-#if !defined(HAVE_AIO_LIBC)
-
-#define __NR_io_setup 245
-#define __NR_io_getevents 247
-#define __NR_io_submit 248
-
-static long io_setup(int n, aio_context_t *ctxp)
-{
- return(syscall(__NR_io_setup, n, ctxp));
-}
-
-static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
-{
- return(syscall(__NR_io_submit, ctx, nr, iocbpp));
-}
-
-static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
- struct io_event *events, struct timespec *timeout)
-{
- return(syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout));
-}
-
-#endif
-
-/* The AIO_MMAP cases force the mmapped page into memory here
- * rather than in whatever place first touches the data. I used
- * to do this by touching the page, but that's delicate because
- * gcc is prone to optimizing that away. So, what's done here
- * is we read from the descriptor from which the page was
- * mapped. The caller is required to pass an offset which is
- * inside the page that was mapped. Thus, when the read
- * returns, we know that the page is in the page cache, and
- * that it now backs the mmapped area.
- */
-
-static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
- int len, unsigned long long offset, void *data)
-{
- struct iocb iocb, *iocbp = &iocb;
- char c;
- int err;
-
- iocb = ((struct iocb) { .aio_data = (unsigned long) data,
- .aio_reqprio = 0,
- .aio_fildes = fd,
- .aio_buf = (unsigned long) buf,
- .aio_nbytes = len,
- .aio_offset = offset,
- .aio_reserved1 = 0,
- .aio_reserved2 = 0,
- .aio_reserved3 = 0 });
-
- switch(type){
- case AIO_READ:
- iocb.aio_lio_opcode = IOCB_CMD_PREAD;
- err = io_submit(ctx, 1, &iocbp);
- break;
- case AIO_WRITE:
- iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
- err = io_submit(ctx, 1, &iocbp);
- break;
- case AIO_MMAP:
- iocb.aio_lio_opcode = IOCB_CMD_PREAD;
- iocb.aio_buf = (unsigned long) &c;
- iocb.aio_nbytes = sizeof(c);
- err = io_submit(ctx, 1, &iocbp);
- break;
- default:
- printk("Bogus op in do_aio - %d\n", type);
- err = -EINVAL;
- break;
- }
- if(err > 0)
- err = 0;
-
- return(err);
-}
-
-static aio_context_t ctx = 0;
-
-static int aio_thread(void *arg)
-{
- struct aio_thread_reply reply;
- struct io_event event;
- int err, n, reply_fd;
-
- signal(SIGWINCH, SIG_IGN);
-
- while(1){
- n = io_getevents(ctx, 1, 1, &event, NULL);
- if(n < 0){
- if(errno == EINTR)
- continue;
- printk("aio_thread - io_getevents failed, "
- "errno = %d\n", errno);
- }
- else {
- reply = ((struct aio_thread_reply)
- { .data = (void *) event.data,
- .err = event.res });
- reply_fd =
- ((struct aio_context *) event.data)->reply_fd;
- err = os_write_file(reply_fd, &reply, sizeof(reply));
- if(err != sizeof(reply))
- printk("not_aio_thread - write failed, "
- "fd = %d, err = %d\n",
- aio_req_fd_r, -err);
- }
- }
- return(0);
-}
-
-#endif
-
-static int do_not_aio(struct aio_thread_req *req)
-{
- char c;
- int err;
-
- switch(req->type){
- case AIO_READ:
- err = os_seek_file(req->io_fd, req->offset);
- if(err)
- goto out;
-
- err = os_read_file(req->io_fd, req->buf, req->len);
- break;
- case AIO_WRITE:
- err = os_seek_file(req->io_fd, req->offset);
- if(err)
- goto out;
-
- err = os_write_file(req->io_fd, req->buf, req->len);
- break;
- case AIO_MMAP:
- err = os_seek_file(req->io_fd, req->offset);
- if(err)
- goto out;
-
- err = os_read_file(req->io_fd, &c, sizeof(c));
- break;
- default:
- printk("do_not_aio - bad request type : %d\n", req->type);
- err = -EINVAL;
- break;
- }
-
- out:
- return(err);
-}
-
-static int not_aio_thread(void *arg)
-{
- struct aio_thread_req req;
- struct aio_thread_reply reply;
- int err;
-
- signal(SIGWINCH, SIG_IGN);
- while(1){
- err = os_read_file(aio_req_fd_r, &req, sizeof(req));
- if(err != sizeof(req)){
- if(err < 0)
- printk("not_aio_thread - read failed, fd = %d, "
- "err = %d\n", aio_req_fd_r, -err);
- else {
- printk("not_aio_thread - short read, fd = %d, "
- "length = %d\n", aio_req_fd_r, err);
- }
- continue;
- }
- err = do_not_aio(&req);
- reply = ((struct aio_thread_reply) { .data = req.data,
- .err = err });
- err = os_write_file(req.reply_fd, &reply, sizeof(reply));
- if(err != sizeof(reply))
- printk("not_aio_thread - write failed, fd = %d, "
- "err = %d\n", aio_req_fd_r, -err);
- }
-}
-
-static int aio_pid = -1;
-
-static int init_aio_24(void)
-{
- unsigned long stack;
- int fds[2], err;
-
- err = os_pipe(fds, 1, 1);
- if(err)
- goto out;
-
- aio_req_fd_w = fds[0];
- aio_req_fd_r = fds[1];
- err = run_helper_thread(not_aio_thread, NULL,
- CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
- if(err < 0)
- goto out_close_pipe;
-
- aio_pid = err;
- goto out;
-
- out_close_pipe:
- os_close_file(fds[0]);
- os_close_file(fds[1]);
- aio_req_fd_w = -1;
- aio_req_fd_r = -1;
- out:
- return(0);
-}
-
-#ifdef HAVE_AIO_ABI
-#define DEFAULT_24_AIO 0
-static int init_aio_26(void)
-{
- unsigned long stack;
- int err;
-
- if(io_setup(256, &ctx)){
- printk("aio_thread failed to initialize context, err = %d\n",
- errno);
- return(-errno);
- }
-
- err = run_helper_thread(aio_thread, NULL,
- CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
- if(err < 0)
- return(-errno);
-
- aio_pid = err;
- err = 0;
- out:
- return(err);
-}
-
-int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
- unsigned long long offset, int reply_fd, void *data)
-{
- struct aio_thread_reply reply;
- int err;
-
- ((struct aio_context *) data)->reply_fd = reply_fd;
-
- err = do_aio(ctx, type, io_fd, buf, len, offset, data);
- if(err){
- reply = ((struct aio_thread_reply) { .data = data,
- .err = err });
- err = os_write_file(reply_fd, &reply, sizeof(reply));
- if(err != sizeof(reply))
- printk("submit_aio_26 - write failed, "
- "fd = %d, err = %d\n", reply_fd, -err);
- else err = 0;
- }
-
- return(err);
-}
-
-#else
-#define DEFAULT_24_AIO 1
-static int init_aio_26(void)
-{
- return(-ENOSYS);
-}
-
-int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
- unsigned long long offset, int reply_fd, void *data)
-{
- return(-ENOSYS);
-}
-#endif
-
-static int aio_24 = DEFAULT_24_AIO;
-
-static int __init set_aio_24(char *name, int *add)
-{
- aio_24 = 1;
- return(0);
-}
-
-__uml_setup("aio=2.4", set_aio_24,
-"aio=2.4\n"
-" This is used to force UML to use 2.4-style AIO even when 2.6 AIO is\n"
-" available. 2.4 AIO is a single thread that handles one request at a\n"
-" time, synchronously. 2.6 AIO is a thread which uses 2.5 AIO interface\n"
-" to handle an arbitrary number of pending requests. 2.6 AIO is not\n"
-" available in tt mode, on 2.4 hosts, or when UML is built with\n"
-" /usr/include/linux/aio_abi no available.\n\n"
-);
-
-static int init_aio(void)
-{
- int err;
-
- CHOOSE_MODE(({
- if(!aio_24){
- printk("Disabling 2.6 AIO in tt mode\n");
- aio_24 = 1;
- } }), (void) 0);
-
- if(!aio_24){
- err = init_aio_26();
- if(err && (errno == ENOSYS)){
- printk("2.6 AIO not supported on the host - "
- "reverting to 2.4 AIO\n");
- aio_24 = 1;
- }
- else return(err);
- }
-
- if(aio_24)
- return(init_aio_24());
-
- return(0);
-}
-
-__initcall(init_aio);
-
-static void exit_aio(void)
-{
- if(aio_pid != -1)
- os_kill_process(aio_pid, 1);
-}
-
-__uml_exitcall(exit_aio);
-
-int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
- unsigned long long offset, int reply_fd, void *data)
-{
- struct aio_thread_req req = { .type = type,
- .io_fd = io_fd,
- .offset = offset,
- .buf = buf,
- .len = len,
- .reply_fd = reply_fd,
- .data = data,
- };
- int err;
-
- err = os_write_file(aio_req_fd_w, &req, sizeof(req));
- if(err == sizeof(req))
- err = 0;
-
- return(err);
-}
-
-int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
- unsigned long long offset, int reply_fd, void *data)
-{
- if(aio_24)
- return(submit_aio_24(type, io_fd, buf, len, offset, reply_fd,
- data));
- else {
- return(submit_aio_26(type, io_fd, buf, len, offset, reply_fd,
- data));
- }
-}
-
-/*
- * 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:
- */
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/uio.h>
-#include <sys/utsname.h>
-#include <sys/vfs.h>
#include "os.h"
#include "user.h"
#include "kern_util.h"
if(flags.c) f |= O_CREAT;
if(flags.t) f |= O_TRUNC;
if(flags.e) f |= O_EXCL;
- if(flags.d) f |= O_DIRECT;
fd = open64(file, f, mode);
if(fd < 0)
+++ /dev/null
-#include <linux/bitops.h>
-#include <linux/module.h>
-
-/**
- * find_next_bit - find the first set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-int find_next_bit(const unsigned long *addr, int size, int offset)
-{
- const unsigned long *p = addr + (offset >> 5);
- int set = 0, bit = offset & 31, res;
-
- if (bit) {
- /*
- * Look for nonzero in the first 32 bits:
- */
- __asm__("bsfl %1,%0\n\t"
- "jne 1f\n\t"
- "movl $32, %0\n"
- "1:"
- : "=r" (set)
- : "r" (*p >> bit));
- if (set < (32 - bit))
- return set + offset;
- set = 32 - bit;
- p++;
- }
- /*
- * No set bit yet, search remaining full words for a bit
- */
- res = find_first_bit (p, size - 32 * (p - addr));
- return (offset + set + res);
-}
-EXPORT_SYMBOL(find_next_bit);
-
-/**
- * find_next_zero_bit - find the first zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-int find_next_zero_bit(const unsigned long *addr, int size, int offset)
-{
- unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
- int set = 0, bit = offset & 31, res;
-
- if (bit) {
- /*
- * Look for zero in the first 32 bits.
- */
- __asm__("bsfl %1,%0\n\t"
- "jne 1f\n\t"
- "movl $32, %0\n"
- "1:"
- : "=r" (set)
- : "r" (~(*p >> bit)));
- if (set < (32 - bit))
- return set + offset;
- set = 32 - bit;
- p++;
- }
- /*
- * No zero yet, search remaining full bytes for a zero
- */
- res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
- return (offset + set + res);
-}
-EXPORT_SYMBOL(find_next_zero_bit);
--- /dev/null
+/*
+ * linux/arch/i386/mm/extable.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+
+/* Simple binary search */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value)
+{
+ while (first <= last) {
+ const struct exception_table_entry *mid;
+ long diff;
+
+ mid = (last - first) / 2 + first;
+ diff = mid->insn - value;
+ if (diff == 0)
+ return mid;
+ else if (diff < 0)
+ first = mid+1;
+ else
+ last = mid-1;
+ }
+ return NULL;
+}
+++ /dev/null
-/*
- * i386 semaphore implementation.
- *
- * (C) Copyright 1999 Linus Torvalds
- *
- * Portions Copyright 1999 Red Hat, Inc.
- *
- * 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.
- *
- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@redhat.com>
- */
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <asm/semaphore.h>
-
-/*
- * Semaphores are implemented using a two-way counter:
- * The "count" variable is decremented for each process
- * that tries to acquire the semaphore, while the "sleeping"
- * variable is a count of such acquires.
- *
- * Notably, the inline "up()" and "down()" functions can
- * efficiently test if they need to do any extra work (up
- * needs to do something only if count was negative before
- * the increment operation.
- *
- * "sleeping" and the contention routine ordering is protected
- * by the spinlock in the semaphore's waitqueue head.
- *
- * Note that these functions are only called when there is
- * contention on the lock, and as such all this is the
- * "non-critical" part of the whole semaphore business. The
- * critical part is the inline stuff in <asm/semaphore.h>
- * where we want to avoid any extra jumps and calls.
- */
-
-/*
- * Logic:
- * - only on a boundary condition do we need to care. When we go
- * from a negative count to a non-negative, we wake people up.
- * - when we go from a non-negative count to a negative do we
- * (a) synchronize with the "sleeper" count and (b) make sure
- * that we're on the wakeup list before we synchronize so that
- * we cannot lose wakeup events.
- */
-
-asmlinkage void __up(struct semaphore *sem)
-{
- wake_up(&sem->wait);
-}
-
-asmlinkage void __sched __down(struct semaphore * sem)
-{
- struct task_struct *tsk = current;
- DECLARE_WAITQUEUE(wait, tsk);
- unsigned long flags;
-
- tsk->state = TASK_UNINTERRUPTIBLE;
- spin_lock_irqsave(&sem->wait.lock, flags);
- add_wait_queue_exclusive_locked(&sem->wait, &wait);
-
- sem->sleepers++;
- for (;;) {
- int sleepers = sem->sleepers;
-
- /*
- * Add "everybody else" into it. They aren't
- * playing, because we own the spinlock in
- * the wait_queue_head.
- */
- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
- sem->sleepers = 0;
- break;
- }
- sem->sleepers = 1; /* us - see -1 above */
- spin_unlock_irqrestore(&sem->wait.lock, flags);
-
- schedule();
-
- spin_lock_irqsave(&sem->wait.lock, flags);
- tsk->state = TASK_UNINTERRUPTIBLE;
- }
- remove_wait_queue_locked(&sem->wait, &wait);
- wake_up_locked(&sem->wait);
- spin_unlock_irqrestore(&sem->wait.lock, flags);
- tsk->state = TASK_RUNNING;
-}
-
-asmlinkage int __sched __down_interruptible(struct semaphore * sem)
-{
- int retval = 0;
- struct task_struct *tsk = current;
- DECLARE_WAITQUEUE(wait, tsk);
- unsigned long flags;
-
- tsk->state = TASK_INTERRUPTIBLE;
- spin_lock_irqsave(&sem->wait.lock, flags);
- add_wait_queue_exclusive_locked(&sem->wait, &wait);
-
- sem->sleepers++;
- for (;;) {
- int sleepers = sem->sleepers;
-
- /*
- * With signals pending, this turns into
- * the trylock failure case - we won't be
- * sleeping, and we* can't get the lock as
- * it has contention. Just correct the count
- * and exit.
- */
- if (signal_pending(current)) {
- retval = -EINTR;
- sem->sleepers = 0;
- atomic_add(sleepers, &sem->count);
- break;
- }
-
- /*
- * Add "everybody else" into it. They aren't
- * playing, because we own the spinlock in
- * wait_queue_head. The "-1" is because we're
- * still hoping to get the semaphore.
- */
- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
- sem->sleepers = 0;
- break;
- }
- sem->sleepers = 1; /* us - see -1 above */
- spin_unlock_irqrestore(&sem->wait.lock, flags);
-
- schedule();
-
- spin_lock_irqsave(&sem->wait.lock, flags);
- tsk->state = TASK_INTERRUPTIBLE;
- }
- remove_wait_queue_locked(&sem->wait, &wait);
- wake_up_locked(&sem->wait);
- spin_unlock_irqrestore(&sem->wait.lock, flags);
-
- tsk->state = TASK_RUNNING;
- return retval;
-}
-
-/*
- * Trylock failed - make sure we correct for
- * having decremented the count.
- *
- * We could have done the trylock with a
- * single "cmpxchg" without failure cases,
- * but then it wouldn't work on a 386.
- */
-asmlinkage int __down_trylock(struct semaphore * sem)
-{
- int sleepers;
- unsigned long flags;
-
- spin_lock_irqsave(&sem->wait.lock, flags);
- sleepers = sem->sleepers + 1;
- sem->sleepers = 0;
-
- /*
- * Add "everybody else" and us into it. They aren't
- * playing, because we own the spinlock in the
- * wait_queue_head.
- */
- if (!atomic_add_negative(sleepers, &sem->count)) {
- wake_up_locked(&sem->wait);
- }
-
- spin_unlock_irqrestore(&sem->wait.lock, flags);
- return 1;
-}
-
-
-/*
- * The semaphore operations have a special calling sequence that
- * allow us to do a simpler in-line version of them. These routines
- * need to convert that sequence back into the C sequence when
- * there is contention on the semaphore.
- *
- * %ecx contains the semaphore pointer on entry. Save the C-clobbered
- * registers (%eax, %edx and %ecx) except %eax when used as a return
- * value..
- */
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __down_failed\n"
-"__down_failed:\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "pushl %ebp\n\t"
- "movl %esp,%ebp\n\t"
-#endif
- "pushl %eax\n\t"
- "pushl %edx\n\t"
- "pushl %ecx\n\t"
- "call __down\n\t"
- "popl %ecx\n\t"
- "popl %edx\n\t"
- "popl %eax\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "movl %ebp,%esp\n\t"
- "popl %ebp\n\t"
-#endif
- "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __down_failed_interruptible\n"
-"__down_failed_interruptible:\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "pushl %ebp\n\t"
- "movl %esp,%ebp\n\t"
-#endif
- "pushl %edx\n\t"
- "pushl %ecx\n\t"
- "call __down_interruptible\n\t"
- "popl %ecx\n\t"
- "popl %edx\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "movl %ebp,%esp\n\t"
- "popl %ebp\n\t"
-#endif
- "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __down_failed_trylock\n"
-"__down_failed_trylock:\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "pushl %ebp\n\t"
- "movl %esp,%ebp\n\t"
-#endif
- "pushl %edx\n\t"
- "pushl %ecx\n\t"
- "call __down_trylock\n\t"
- "popl %ecx\n\t"
- "popl %edx\n\t"
-#if defined(CONFIG_FRAME_POINTER)
- "movl %ebp,%esp\n\t"
- "popl %ebp\n\t"
-#endif
- "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __up_wakeup\n"
-"__up_wakeup:\n\t"
- "pushl %eax\n\t"
- "pushl %edx\n\t"
- "pushl %ecx\n\t"
- "call __up\n\t"
- "popl %ecx\n\t"
- "popl %edx\n\t"
- "popl %eax\n\t"
- "ret"
-);
-
-/*
- * rw spinlock fallbacks
- */
-#if defined(CONFIG_SMP)
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __write_lock_failed\n"
-"__write_lock_failed:\n\t"
- LOCK "addl $" RW_LOCK_BIAS_STR ",(%eax)\n"
-"1: rep; nop\n\t"
- "cmpl $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
- "jne 1b\n\t"
- LOCK "subl $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
- "jnz __write_lock_failed\n\t"
- "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __read_lock_failed\n"
-"__read_lock_failed:\n\t"
- LOCK "incl (%eax)\n"
-"1: rep; nop\n\t"
- "cmpl $1,(%eax)\n\t"
- "js 1b\n\t"
- LOCK "decl (%eax)\n\t"
- "js __read_lock_failed\n\t"
- "ret"
-);
-#endif
-host-progs := mk_sc mk_thread
-always := $(host-progs)
hostprogs-y := mk_sc mk_thread
always := $(hostprogs-y)
{
. = START + SIZEOF_HEADERS;
+ . = ALIGN(4096);
__binary_start = .;
#ifdef MODE_TT
.thread_private : {
. = ALIGN(4096); /* Init code and data */
_stext = .;
__init_begin = .;
- .init.text : {
- _sinittext = .;
- *(.init.text)
- _einittext = .;
- }
+ .text.init : { *(.text.init) }
. = ALIGN(4096);
.text :
{
*(.text)
- SCHED_TEXT
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
#include "asm/common.lds.S"
- init.data : { *(init.data) }
+ .data.init : { *(.data.init) }
.data :
{
. = ALIGN(KERNEL_STACK_SIZE); /* init_task */
obj-$(CONFIG_XFS_FS) += xfs/
obj-$(CONFIG_AFS_FS) += afs/
obj-$(CONFIG_BEFS_FS) += befs/
-obj-$(CONFIG_EXTERNFS) += hostfs/
obj-$(CONFIG_RCFS_FS) += rcfs/
obj-$(CONFIG_HOSTFS) += hostfs/
obj-$(CONFIG_HPPFS) += hppfs/
+++ /dev/null
-/*
- * Copyright (C) 2000 - 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include <linux/stddef.h>
-#include <linux/fs.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/blkdev.h>
-#include <linux/statfs.h>
-#include <asm/uaccess.h>
-#include "hostfs.h"
-#include "kern_util.h"
-#include "kern.h"
-#include "user_util.h"
-#include "2_5compat.h"
-#include "mem.h"
-#include "filehandle.h"
-
-struct externfs {
- struct list_head list;
- struct externfs_mount_ops *mount_ops;
- struct file_system_type type;
-};
-
-static inline struct externfs_inode *EXTERNFS_I(struct inode *inode)
-{
- return(container_of(inode, struct externfs_inode, vfs_inode));
-}
-
-#define file_externfs_i(file) EXTERNFS_I((file)->f_dentry->d_inode)
-
-int externfs_d_delete(struct dentry *dentry)
-{
- return(1);
-}
-
-struct dentry_operations externfs_dentry_ops = {
-};
-
-#define EXTERNFS_SUPER_MAGIC 0x00c0ffee
-
-static struct inode_operations externfs_iops;
-static struct inode_operations externfs_dir_iops;
-static struct address_space_operations externfs_link_aops;
-
-static char *dentry_name(struct dentry *dentry, int extra)
-{
- struct dentry *parent;
- char *name;
- int len;
-
- len = 0;
- parent = dentry;
- while(parent->d_parent != parent){
- len += parent->d_name.len + 1;
- parent = parent->d_parent;
- }
-
- name = kmalloc(len + extra + 1, GFP_KERNEL);
- if(name == NULL) return(NULL);
-
- name[len] = '\0';
- parent = dentry;
- while(parent->d_parent != parent){
- len -= parent->d_name.len + 1;
- name[len] = '/';
- strncpy(&name[len + 1], parent->d_name.name,
- parent->d_name.len);
- parent = parent->d_parent;
- }
-
- return(name);
-}
-
-char *inode_name(struct inode *ino, int extra)
-{
- struct dentry *dentry;
-
- dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
- return(dentry_name(dentry, extra));
-}
-
-char *inode_name_prefix(struct inode *inode, char *prefix)
-{
- int len;
- char *name;
-
- len = strlen(prefix);
- name = inode_name(inode, len);
- if(name == NULL)
- return(name);
-
- memmove(&name[len], name, strlen(name) + 1);
- memcpy(name, prefix, strlen(prefix));
- return(name);
-}
-
-static int read_name(struct inode *ino, char *name)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- /* The non-int inode fields are copied into ints by stat_file and
- * then copied into the inode because passing the actual pointers
- * in and having them treated as int * breaks on big-endian machines
- */
- dev_t i_rdev;
- int err;
- int i_mode, i_nlink, i_blksize;
- unsigned long atime, mtime, ctime;
- unsigned long long i_size;
- unsigned long long i_ino;
- unsigned long long i_blocks;
-
- err = (*ops->stat_file)(name, ino->i_sb->s_fs_info, &i_rdev, &i_ino,
- &i_mode, &i_nlink, &ino->i_uid, &ino->i_gid,
- &i_size, &atime, &mtime, &ctime, &i_blksize,
- &i_blocks);
- if(err) return(err);
-
- ino->i_atime.tv_sec = atime;
- ino->i_atime.tv_nsec = 0;
-
- ino->i_ctime.tv_sec = ctime;
- ino->i_ctime.tv_nsec = 0;
-
- ino->i_mtime.tv_sec = mtime;
- ino->i_mtime.tv_nsec = 0;
-
- ino->i_ino = i_ino;
- ino->i_rdev = i_rdev;
- ino->i_mode = i_mode;
- ino->i_nlink = i_nlink;
- ino->i_size = i_size;
- ino->i_blksize = i_blksize;
- ino->i_blocks = i_blocks;
- return(0);
-}
-
-static char *follow_link(char *link,
- int (*do_read_link)(char *path, int uid, int gid,
- char *buf, int size,
- struct externfs_data *ed),
- int uid, int gid, struct externfs_data *ed)
-{
- int len, n;
- char *name, *resolved, *end;
-
- len = 64;
- while(1){
- n = -ENOMEM;
- name = kmalloc(len, GFP_KERNEL);
- if(name == NULL)
- goto out;
-
- n = (*do_read_link)(link, uid, gid, name, len, ed);
- if(n < len)
- break;
- len *= 2;
- kfree(name);
- }
- if(n < 0)
- goto out_free;
-
- if(*name == '/')
- return(name);
-
- end = strrchr(link, '/');
- if(end == NULL)
- return(name);
-
- *(end + 1) = '\0';
- len = strlen(link) + strlen(name) + 1;
-
- resolved = kmalloc(len, GFP_KERNEL);
- if(resolved == NULL){
- n = -ENOMEM;
- goto out_free;
- }
-
- sprintf(resolved, "%s%s", link, name);
- kfree(name);
- return(resolved);
-
- out_free:
- kfree(name);
- out:
- return(ERR_PTR(n));
-}
-
-static int read_inode(struct inode *ino)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- struct externfs_data *ed = ino->i_sb->s_fs_info;
- char *name, *new;
- int err = 0, type;
-
- /* Unfortunately, we are called from iget() when we don't have a dentry
- * allocated yet.
- */
- if(list_empty(&ino->i_dentry))
- goto out;
-
- err = -ENOMEM;
- name = inode_name(ino, 0);
- if(name == NULL)
- goto out;
-
- type = (*ops->file_type)(name, NULL, ed);
- if(type < 0){
- err = type;
- goto out_free;
- }
-
- if(type == OS_TYPE_SYMLINK){
- new = follow_link(name, ops->read_link, current->fsuid,
- current->fsgid, ed);
- if(IS_ERR(new)){
- err = PTR_ERR(new);
- goto out_free;
- }
- kfree(name);
- name = new;
- }
-
- err = read_name(ino, name);
- out_free:
- kfree(name);
- out:
- return(err);
-}
-
-int externfs_statfs(struct super_block *sb, struct kstatfs *sf)
-{
- /* do_statfs uses struct statfs64 internally, but the linux kernel
- * struct statfs still has 32-bit versions for most of these fields,
- * so we convert them here
- */
- int err;
- long long f_blocks;
- long long f_bfree;
- long long f_bavail;
- long long f_files;
- long long f_ffree;
- struct externfs_data *ed = sb->s_fs_info;
-
- err = (*ed->file_ops->statfs)(&sf->f_bsize, &f_blocks, &f_bfree,
- &f_bavail, &f_files, &f_ffree,
- &sf->f_fsid, sizeof(sf->f_fsid),
- &sf->f_namelen, sf->f_spare, ed);
- if(err)
- return(err);
-
- sf->f_blocks = f_blocks;
- sf->f_bfree = f_bfree;
- sf->f_bavail = f_bavail;
- sf->f_files = f_files;
- sf->f_ffree = f_ffree;
- sf->f_type = EXTERNFS_SUPER_MAGIC;
- return(0);
-}
-
-static struct inode *externfs_alloc_inode(struct super_block *sb)
-{
- struct externfs_data *ed = sb->s_fs_info;
- struct externfs_inode *ext;
-
- ext = (*ed->mount_ops->init_file)(ed);
- if(ext == NULL)
- return(NULL);
-
- *ext = ((struct externfs_inode) { .ops = ed->file_ops });
-
- inode_init_once(&ext->vfs_inode);
- return(&ext->vfs_inode);
-}
-
-static void externfs_destroy_inode(struct inode *inode)
-{
- struct externfs_inode *ext = EXTERNFS_I(inode);
-
- (*ext->ops->close_file)(ext, inode->i_size);
-}
-
-static void externfs_read_inode(struct inode *inode)
-{
- read_inode(inode);
-}
-
-static struct super_operations externfs_sbops = {
- .alloc_inode = externfs_alloc_inode,
- .destroy_inode = externfs_destroy_inode,
- .read_inode = externfs_read_inode,
- .statfs = externfs_statfs,
-};
-
-int externfs_readdir(struct file *file, void *ent, filldir_t filldir)
-{
- void *dir;
- char *name;
- unsigned long long next, ino;
- int error, len;
- struct externfs_file_ops *ops = file_externfs_i(file)->ops;
- struct externfs_data *ed = file->f_dentry->d_inode->i_sb->s_fs_info;
-
- name = dentry_name(file->f_dentry, 0);
- if(name == NULL)
- return(-ENOMEM);
-
- dir = (*ops->open_dir)(name, current->fsuid, current->fsgid, ed);
- kfree(name);
- if(IS_ERR(dir))
- return(PTR_ERR(dir));
-
- next = file->f_pos;
- while((name = (*ops->read_dir)(dir, &next, &ino, &len, ed)) != NULL){
- error = (*filldir)(ent, name, len, file->f_pos, ino,
- DT_UNKNOWN);
- if(error)
- break;
- file->f_pos = next;
- }
- (*ops->close_dir)(dir, ed);
- return(0);
-}
-
-int externfs_file_open(struct inode *ino, struct file *file)
-{
- ino->i_nlink++;
- return(0);
-}
-
-int externfs_fsync(struct file *file, struct dentry *dentry, int datasync)
-{
- struct externfs_file_ops *ops = file_externfs_i(file)->ops;
- struct inode *inode = dentry->d_inode;
- struct externfs_data *ed = inode->i_sb->s_fs_info;
-
- return((*ops->truncate_file)(EXTERNFS_I(inode), inode->i_size, ed));
-}
-
-static struct file_operations externfs_file_fops = {
- .llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
- .mmap = generic_file_mmap,
- .open = externfs_file_open,
- .release = NULL,
- .fsync = externfs_fsync,
-};
-
-static struct file_operations externfs_dir_fops = {
- .readdir = externfs_readdir,
- .read = generic_read_dir,
-};
-
-struct wp_info {
- struct page *page;
- int count;
- unsigned long long start;
- unsigned long long size;
- int (*truncate)(struct externfs_inode *ext, __u64 size,
- struct externfs_data *ed);
- struct externfs_inode *ei;
- struct externfs_data *ed;
-};
-
-static void externfs_finish_writepage(char *buffer, int res, void *arg)
-{
- struct wp_info *wp = arg;
-
- if(res == wp->count){
- ClearPageError(wp->page);
- if(wp->start + res > wp->size)
- (*wp->truncate)(wp->ei, wp->size, wp->ed);
- }
- else {
- SetPageError(wp->page);
- ClearPageUptodate(wp->page);
- }
-
- kunmap(wp->page);
- unlock_page(wp->page);
- kfree(wp);
-}
-
-int externfs_writepage(struct page *page, struct writeback_control *wbc)
-{
- struct address_space *mapping = page->mapping;
- struct inode *inode = mapping->host;
- struct externfs_file_ops *ops = EXTERNFS_I(inode)->ops;
- struct wp_info *wp;
- struct externfs_data *ed = inode->i_sb->s_fs_info;
- char *buffer;
- unsigned long long base;
- int count = PAGE_CACHE_SIZE;
- int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
- int err, offset;
-
- base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
-
- /* If we are entirely outside the file, then return an error */
- err = -EIO;
- offset = inode->i_size & (PAGE_CACHE_SIZE-1);
- if (page->index > end_index ||
- ((page->index == end_index) && !offset))
- goto out_unlock;
-
- err = -ENOMEM;
- wp = kmalloc(sizeof(*wp), GFP_KERNEL);
- if(wp == NULL)
- goto out_unlock;
-
- *wp = ((struct wp_info) { .page = page,
- .count = count,
- .start = base,
- .size = inode->i_size,
- .truncate = ops->truncate_file,
- .ei = EXTERNFS_I(inode),
- .ed = ed });
-
- buffer = kmap(page);
- err = (*ops->write_file)(EXTERNFS_I(inode), base, buffer, 0,
- count, externfs_finish_writepage, wp, ed);
-
- return err;
-
- out_unlock:
- unlock_page(page);
- return(err);
-}
-
-static void externfs_finish_readpage(char *buffer, int res, void *arg)
-{
- struct page *page = arg;
- struct inode *inode;
-
- if(res < 0){
- SetPageError(page);
- goto out;
- }
-
- inode = page->mapping->host;
- if(inode->i_size >> PAGE_CACHE_SHIFT == page->index)
- res = inode->i_size % PAGE_CACHE_SIZE;
-
- memset(&buffer[res], 0, PAGE_CACHE_SIZE - res);
-
- flush_dcache_page(page);
- SetPageUptodate(page);
- if (PageError(page))
- ClearPageError(page);
- out:
- kunmap(page);
- unlock_page(page);
-}
-
-static int externfs_readpage(struct file *file, struct page *page)
-{
- struct inode *ino = page->mapping->host;
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- struct externfs_data *ed = ino->i_sb->s_fs_info;
- char *buffer;
- long long start;
- int err = 0;
-
- start = (long long) page->index << PAGE_CACHE_SHIFT;
- buffer = kmap(page);
-
- if(ops->map_file_page != NULL){
- /* XXX What happens when PAGE_SIZE != PAGE_CACHE_SIZE? */
- err = (*ops->map_file_page)(file_externfs_i(file), start,
- buffer, file->f_mode & FMODE_WRITE,
- ed);
- if(!err)
- err = PAGE_CACHE_SIZE;
- }
- else err = (*ops->read_file)(file_externfs_i(file), start, buffer,
- PAGE_CACHE_SIZE, 0, 0,
- externfs_finish_readpage, page, ed);
-
- if(err > 0)
- err = 0;
- return(err);
-}
-
-struct writepage_info {
- struct semaphore sem;
- int res;
-};
-
-static void externfs_finish_prepare(char *buffer, int res, void *arg)
-{
- struct writepage_info *wp = arg;
-
- wp->res = res;
- up(&wp->sem);
-}
-
-int externfs_prepare_write(struct file *file, struct page *page,
- unsigned int from, unsigned int to)
-{
- struct address_space *mapping = page->mapping;
- struct inode *inode = mapping->host;
- struct externfs_file_ops *ops = EXTERNFS_I(inode)->ops;
- struct externfs_data *ed = inode->i_sb->s_fs_info;
- char *buffer;
- long long start;
- int err;
- struct writepage_info wp;
-
- if(PageUptodate(page))
- return(0);
-
- start = (long long) page->index << PAGE_CACHE_SHIFT;
- buffer = kmap(page);
-
- if(ops->map_file_page != NULL){
- err = (*ops->map_file_page)(file_externfs_i(file), start,
- buffer, file->f_mode & FMODE_WRITE,
- ed);
- goto out;
-
- }
-
- init_MUTEX_LOCKED(&wp.sem);
- err = (*ops->read_file)(file_externfs_i(file), start, buffer,
- PAGE_CACHE_SIZE, from, to,
- externfs_finish_prepare, &wp, ed);
- down(&wp.sem);
- if(err < 0)
- goto out;
-
- err = wp.res;
- if(err < 0)
- goto out;
-
- if(from > 0)
- memset(buffer, 0, from);
- if(to < PAGE_CACHE_SIZE)
- memset(buffer + to, 0, PAGE_CACHE_SIZE - to);
-
- SetPageUptodate(page);
- err = 0;
- out:
- kunmap(page);
- return(err);
-}
-
-static int externfs_commit_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
-{
- struct address_space *mapping = page->mapping;
- struct inode *inode = mapping->host;
- struct externfs_file_ops *ops = EXTERNFS_I(inode)->ops;
- unsigned long long size;
- long long start;
- int err;
-
- start = (long long) (page->index << PAGE_CACHE_SHIFT);
-
- if(ops->map_file_page != NULL)
- err = to - from;
- else {
- size = start + to;
- if(size > inode->i_size){
- inode->i_size = size;
- mark_inode_dirty(inode);
- }
- }
-
- set_page_dirty(page);
- return(to - from);
-}
-
-static int externfs_removepage(struct page *page, int gfpmask)
-{
- physmem_remove_mapping(page_address(page));
- return(0);
-}
-
-static struct address_space_operations externfs_aops = {
- .writepage = externfs_writepage,
- .readpage = externfs_readpage,
- .releasepage = externfs_removepage,
-/* .set_page_dirty = __set_page_dirty_nobuffers, */
- .prepare_write = externfs_prepare_write,
- .commit_write = externfs_commit_write
-};
-
-static int init_inode(struct inode *inode, struct dentry *dentry)
-{
- char *name = NULL;
- int type, err = -ENOMEM, rdev;
- struct externfs_inode *ext = EXTERNFS_I(inode);
- struct externfs_file_ops *ops = ext->ops;
- struct externfs_data *ed = inode->i_sb->s_fs_info;
-
- if(dentry){
- name = dentry_name(dentry, 0);
- if(name == NULL)
- goto out;
- type = (*ops->file_type)(name, &rdev, ed);
- }
- else type = OS_TYPE_DIR;
-
- err = 0;
- if(type == OS_TYPE_SYMLINK)
- inode->i_op = &page_symlink_inode_operations;
- else if(type == OS_TYPE_DIR)
- inode->i_op = &externfs_dir_iops;
- else inode->i_op = &externfs_iops;
-
- if(type == OS_TYPE_DIR) inode->i_fop = &externfs_dir_fops;
- else inode->i_fop = &externfs_file_fops;
-
- if(type == OS_TYPE_SYMLINK)
- inode->i_mapping->a_ops = &externfs_link_aops;
- else inode->i_mapping->a_ops = &externfs_aops;
-
- switch (type) {
- case OS_TYPE_CHARDEV:
- init_special_inode(inode, S_IFCHR, rdev);
- break;
- case OS_TYPE_BLOCKDEV:
- init_special_inode(inode, S_IFBLK, rdev);
- break;
- case OS_TYPE_FIFO:
- init_special_inode(inode, S_IFIFO, 0);
- break;
- case OS_TYPE_SOCK:
- init_special_inode(inode, S_IFSOCK, 0);
- break;
- case OS_TYPE_SYMLINK:
- inode->i_mode = S_IFLNK | S_IRWXUGO;
- }
-
- err = (*ops->open_file)(ext, name, current->fsuid, current->fsgid,
- inode, ed);
- if((err != -EISDIR) && (err != -ENOENT) && (err != -ENXIO))
- goto out_put;
-
- err = 0;
-
- out_free:
- kfree(name);
- out:
- return(err);
-
- out_put:
- iput(inode);
- goto out_free;
-}
-
-int externfs_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata *nd)
-{
- struct externfs_inode *ext = EXTERNFS_I(dir);
- struct externfs_file_ops *ops = ext->ops;
- struct inode *inode;
- struct externfs_data *ed = dir->i_sb->s_fs_info;
- char *name;
- int err = -ENOMEM;
-
- inode = iget(dir->i_sb, 0);
- if(inode == NULL)
- goto out;
-
- err = init_inode(inode, dentry);
- if(err)
- goto out_put;
-
- err = -ENOMEM;
- name = dentry_name(dentry, 0);
- if(name == NULL)
- goto out_put;
-
- err = (*ops->create_file)(ext, name, mode, current->fsuid,
- current->fsuid, inode, ed);
- if(err)
- goto out_free;
-
- err = read_name(inode, name);
- if(err)
- goto out_rm;
-
- inode->i_nlink++;
- d_instantiate(dentry, inode);
- kfree(name);
- out:
- return(err);
-
- out_rm:
- (*ops->unlink_file)(name, ed);
- out_free:
- kfree(name);
- out_put:
- inode->i_nlink = 0;
- iput(inode);
- goto out;
-}
-
-struct dentry *externfs_lookup(struct inode *ino, struct dentry *dentry,
- struct nameidata *nd)
-{
- struct inode *inode;
- char *name;
- int err = -ENOMEM;
-
- inode = iget(ino->i_sb, 0);
- if(inode == NULL)
- goto out;
-
- err = init_inode(inode, dentry);
- if(err)
- goto out_put;
-
- err = -ENOMEM;
- name = dentry_name(dentry, 0);
- if(name == NULL)
- goto out_put;
-
- err = read_name(inode, name);
- kfree(name);
- if(err){
- if(err != -ENOENT)
- goto out_put;
-
- inode->i_nlink = 0;
- iput(inode);
- inode = NULL;
- }
- d_add(dentry, inode);
- dentry->d_op = &externfs_dentry_ops;
- return(NULL);
-
- out_put:
- inode->i_nlink = 0;
- iput(inode);
- out:
- return(ERR_PTR(err));
-}
-
-static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
-{
- char *file;
- int len;
-
- file = inode_name(ino, dentry->d_name.len + 1);
- if(file == NULL) return(NULL);
- strcat(file, "/");
- len = strlen(file);
- strncat(file, dentry->d_name.name, dentry->d_name.len);
- file[len + dentry->d_name.len] = '\0';
- return(file);
-}
-
-int externfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- struct externfs_data *ed = ino->i_sb->s_fs_info;
- char *from_name, *to_name;
- int err = -ENOMEM;
-
- from_name = inode_dentry_name(ino, from);
- if(from_name == NULL)
- goto out;
-
- to_name = dentry_name(to, 0);
- if(to_name == NULL)
- goto out_free_from;
-
- err = (*ops->link_file)(to_name, from_name, current->fsuid,
- current->fsgid, ed);
- if(err)
- goto out_free_to;
-
- d_instantiate(from, to->d_inode);
- to->d_inode->i_nlink++;
- atomic_inc(&to->d_inode->i_count);
-
- out_free_to:
- kfree(to_name);
- out_free_from:
- kfree(from_name);
- out:
- return(err);
-}
-
-int externfs_unlink(struct inode *ino, struct dentry *dentry)
-{
- struct inode *inode;
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- struct externfs_data *ed = ino->i_sb->s_fs_info;
- char *file;
- int err;
-
- file = inode_dentry_name(ino, dentry);
- if(file == NULL)
- return(-ENOMEM);
-
- inode = dentry->d_inode;
- if((inode->i_nlink == 1) && (ops->invisible != NULL))
- (*ops->invisible)(EXTERNFS_I(inode));
-
- err = (*ops->unlink_file)(file, ed);
- kfree(file);
-
- inode->i_nlink--;
-
- return(err);
-}
-
-int externfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- struct inode *inode;
- struct externfs_data *ed = ino->i_sb->s_fs_info;
- char *file;
- int err;
-
- file = inode_dentry_name(ino, dentry);
- if(file == NULL)
- return(-ENOMEM);
- err = (*ops->make_symlink)(file, to, current->fsuid, current->fsgid,
- ed);
- kfree(file);
- if(err)
- goto out;
-
- err = -ENOMEM;
- inode = iget(ino->i_sb, 0);
- if(inode == NULL)
- goto out;
-
- err = init_inode(inode, dentry);
- if(err)
- goto out_put;
-
- d_instantiate(dentry, inode);
- inode->i_nlink++;
- out:
- return(err);
-
- out_put:
- iput(inode);
- goto out;
-}
-
-int externfs_make_dir(struct inode *ino, struct dentry *dentry, int mode)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- struct inode *inode;
- struct externfs_data *ed = ino->i_sb->s_fs_info;
- char *file;
- int err = -ENOMEM;
-
- file = inode_dentry_name(ino, dentry);
- if(file == NULL)
- goto out;
- err = (*ops->make_dir)(file, mode, current->fsuid, current->fsgid, ed);
-
- err = -ENOMEM;
- inode = iget(ino->i_sb, 0);
- if(inode == NULL)
- goto out_free;
-
- err = init_inode(inode, dentry);
- if(err)
- goto out_put;
-
- err = read_name(inode, file);
- if(err)
- goto out_put;
-
- kfree(file);
- d_instantiate(dentry, inode);
- inode->i_nlink = 2;
- inode->i_mode = S_IFDIR | mode;
-
- ino->i_nlink++;
- out:
- return(err);
- out_put:
- inode->i_nlink = 0;
- iput(inode);
- out_free:
- kfree(file);
- goto out;
-}
-
-int externfs_remove_dir(struct inode *ino, struct dentry *dentry)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- struct externfs_data *ed = ino->i_sb->s_fs_info;
- char *file;
- int err;
-
- file = inode_dentry_name(ino, dentry);
- if(file == NULL)
- return(-ENOMEM);
- err = (*ops->remove_dir)(file, current->fsuid, current->fsgid, ed);
- kfree(file);
-
- dentry->d_inode->i_nlink = 0;
- ino->i_nlink--;
- return(err);
-}
-
-int externfs_make_node(struct inode *dir, struct dentry *dentry, int mode,
- dev_t dev)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(dir)->ops;
- struct externfs_data *ed = dir->i_sb->s_fs_info;
- struct inode *inode;
- char *name;
- int err = -ENOMEM;
-
- inode = iget(dir->i_sb, 0);
- if(inode == NULL)
- goto out;
-
- err = init_inode(inode, dentry);
- if(err)
- goto out_put;
-
- err = -ENOMEM;
- name = dentry_name(dentry, 0);
- if(name == NULL)
- goto out_put;
-
- init_special_inode(inode, mode, dev);
- err = (*ops->make_node)(name, mode & S_IRWXUGO, current->fsuid,
- current->fsgid, mode & S_IFMT, MAJOR(dev),
- MINOR(dev), ed);
- if(err)
- goto out_free;
-
- err = read_name(inode, name);
- if(err)
- goto out_rm;
-
- inode->i_nlink++;
- d_instantiate(dentry, inode);
- kfree(name);
- out:
- return(err);
-
- out_rm:
- (*ops->unlink_file)(name, ed);
- out_free:
- kfree(name);
- out_put:
- inode->i_nlink = 0;
- iput(inode);
- goto out;
-}
-
-int externfs_rename(struct inode *from_ino, struct dentry *from,
- struct inode *to_ino, struct dentry *to)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(from_ino)->ops;
- struct externfs_data *ed = from_ino->i_sb->s_fs_info;
- char *from_name, *to_name;
- int err;
-
- from_name = inode_dentry_name(from_ino, from);
- if(from_name == NULL)
- return(-ENOMEM);
- to_name = inode_dentry_name(to_ino, to);
- if(to_name == NULL){
- kfree(from_name);
- return(-ENOMEM);
- }
- err = (*ops->rename_file)(from_name, to_name, ed);
- kfree(from_name);
- kfree(to_name);
-
- from_ino->i_nlink--;
- to_ino->i_nlink++;
- return(err);
-}
-
-void externfs_truncate(struct inode *ino)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- struct externfs_data *ed = ino->i_sb->s_fs_info;
-
- (*ops->truncate_file)(EXTERNFS_I(ino), ino->i_size, ed);
-}
-
-int externfs_permission(struct inode *ino, int desired, struct nameidata *nd)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- struct externfs_data *ed = ino->i_sb->s_fs_info;
- char *name;
- int r = 0, w = 0, x = 0, err;
-
- if(ops->access_file == NULL)
- return(vfs_permission(ino, desired));
-
- if(desired & MAY_READ) r = 1;
- if(desired & MAY_WRITE) w = 1;
- if(desired & MAY_EXEC) x = 1;
- name = inode_name(ino, 0);
- if(name == NULL)
- return(-ENOMEM);
-
- err = (*ops->access_file)(name, r, w, x, current->fsuid,
- current->fsgid, ed);
- kfree(name);
-
- if(!err)
- err = vfs_permission(ino, desired);
- return(err);
-}
-
-int externfs_setattr(struct dentry *dentry, struct iattr *attr)
-{
- struct externfs_file_ops *ops = EXTERNFS_I(dentry->d_inode)->ops;
- struct externfs_data *ed = dentry->d_inode->i_sb->s_fs_info;
- struct externfs_iattr attrs;
- char *name;
- int err;
-
- attrs.ia_valid = 0;
- if(attr->ia_valid & ATTR_MODE){
- attrs.ia_valid |= EXTERNFS_ATTR_MODE;
- attrs.ia_mode = attr->ia_mode;
- }
- if(attr->ia_valid & ATTR_UID){
- attrs.ia_valid |= EXTERNFS_ATTR_UID;
- attrs.ia_uid = attr->ia_uid;
- }
- if(attr->ia_valid & ATTR_GID){
- attrs.ia_valid |= EXTERNFS_ATTR_GID;
- attrs.ia_gid = attr->ia_gid;
- }
- if(attr->ia_valid & ATTR_SIZE){
- attrs.ia_valid |= EXTERNFS_ATTR_SIZE;
- attrs.ia_size = attr->ia_size;
- }
- if(attr->ia_valid & ATTR_ATIME){
- attrs.ia_valid |= EXTERNFS_ATTR_ATIME;
- attrs.ia_atime = attr->ia_atime.tv_sec;
- }
- if(attr->ia_valid & ATTR_MTIME){
- attrs.ia_valid |= EXTERNFS_ATTR_MTIME;
- attrs.ia_mtime = attr->ia_mtime.tv_sec;
- }
- if(attr->ia_valid & ATTR_CTIME){
- attrs.ia_valid |= EXTERNFS_ATTR_CTIME;
- attrs.ia_ctime = attr->ia_ctime.tv_sec;
- }
- if(attr->ia_valid & ATTR_ATIME_SET){
- attrs.ia_valid |= EXTERNFS_ATTR_ATIME_SET;
- attrs.ia_atime = attr->ia_atime.tv_sec;
- }
- if(attr->ia_valid & ATTR_MTIME_SET){
- attrs.ia_valid |= EXTERNFS_ATTR_MTIME_SET;
- }
- name = dentry_name(dentry, 0);
- if(name == NULL)
- return(-ENOMEM);
- err = (*ops->set_attr)(name, &attrs, ed);
- kfree(name);
- if(err)
- return(err);
-
- return(inode_setattr(dentry->d_inode, attr));
-}
-
-int externfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
-{
- generic_fillattr(dentry->d_inode, stat);
- return(0);
-}
-
-static struct inode_operations externfs_iops = {
- .create = externfs_create,
- .link = externfs_link,
- .unlink = externfs_unlink,
- .symlink = externfs_symlink,
- .mkdir = externfs_make_dir,
- .rmdir = externfs_remove_dir,
- .mknod = externfs_make_node,
- .rename = externfs_rename,
- .truncate = externfs_truncate,
- .permission = externfs_permission,
- .setattr = externfs_setattr,
- .getattr = externfs_getattr,
-};
-
-static struct inode_operations externfs_dir_iops = {
- .create = externfs_create,
- .lookup = externfs_lookup,
- .link = externfs_link,
- .unlink = externfs_unlink,
- .symlink = externfs_symlink,
- .mkdir = externfs_make_dir,
- .rmdir = externfs_remove_dir,
- .mknod = externfs_make_node,
- .rename = externfs_rename,
- .truncate = externfs_truncate,
- .permission = externfs_permission,
- .setattr = externfs_setattr,
- .getattr = externfs_getattr,
-};
-
-int externfs_link_readpage(struct file *file, struct page *page)
-{
- struct inode *ino = page->mapping->host;
- struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
- struct externfs_data *ed = ino->i_sb->s_fs_info;
- char *buffer, *name;
- long long start;
- int err;
-
- start = page->index << PAGE_CACHE_SHIFT;
- buffer = kmap(page);
- name = inode_name(ino, 0);
- if(name == NULL)
- return(-ENOMEM);
-
- err = (*ops->read_link)(name, current->fsuid, current->fsgid, buffer,
- PAGE_CACHE_SIZE, ed);
-
- kfree(name);
- if(err == PAGE_CACHE_SIZE)
- err = -E2BIG;
- else if(err > 0){
- flush_dcache_page(page);
- SetPageUptodate(page);
- if (PageError(page)) ClearPageError(page);
- err = 0;
- }
- kunmap(page);
- unlock_page(page);
- return(err);
-}
-
-static int externfs_flushpage(struct page *page, unsigned long offset)
-{
- return(externfs_writepage(page, NULL));
-}
-
-struct externfs_data *inode_externfs_info(struct inode *inode)
-{
- return(inode->i_sb->s_fs_info);
-}
-
-static struct address_space_operations externfs_link_aops = {
- .readpage = externfs_link_readpage,
- .releasepage = externfs_removepage,
- .invalidatepage = externfs_flushpage,
-};
-
-DECLARE_MUTEX(externfs_sem);
-struct list_head externfses = LIST_HEAD_INIT(externfses);
-
-static struct externfs *find_externfs(struct file_system_type *type)
-{
- struct list_head *ele;
- struct externfs *fs;
-
- down(&externfs_sem);
- list_for_each(ele, &externfses){
- fs = list_entry(ele, struct externfs, list);
- if(&fs->type == type)
- goto out;
- }
- fs = NULL;
- out:
- up(&externfs_sem);
- return(fs);
-}
-
-#define DEFAULT_ROOT "/"
-
-char *host_root_filename(char *mount_arg)
-{
- char *root = DEFAULT_ROOT;
-
- if((mount_arg != NULL) && (*mount_arg != '\0'))
- root = mount_arg;
-
- return(uml_strdup(root));
-}
-
-static int externfs_fill_sb(struct super_block *sb, void *data, int silent)
-{
- struct externfs *fs;
- struct inode *root_inode;
- struct externfs_data *sb_data;
- int err = -EINVAL;
-
- sb->s_blocksize = 1024;
- sb->s_blocksize_bits = 10;
- sb->s_magic = EXTERNFS_SUPER_MAGIC;
- sb->s_op = &externfs_sbops;
-
- fs = find_externfs(sb->s_type);
- if(fs == NULL){
- printk("Couldn't find externfs for filesystem '%s'\n",
- sb->s_type->name);
- goto out;
- }
-
- sb_data = (*fs->mount_ops->mount)(data);
- if(IS_ERR(sb_data)){
- err = PTR_ERR(sb_data);
- goto out;
- }
-
- sb->s_fs_info = sb_data;
- sb_data->mount_ops = fs->mount_ops;
-
- root_inode = iget(sb, 0);
- if(root_inode == NULL)
- goto out;
-
- err = init_inode(root_inode, NULL);
- if(err)
- goto out_put;
-
- err = -ENOMEM;
- sb->s_root = d_alloc_root(root_inode);
- if(sb->s_root == NULL)
- goto out_put;
-
- err = read_inode(root_inode);
- if(err)
- goto out_put;
-
- out:
- return(err);
-
- out_put:
- iput(root_inode);
- goto out;
-}
-
-struct super_block *externfs_read_super(struct file_system_type *type,
- int flags, const char *dev_name,
- void *data)
-{
- return(get_sb_nodev(type, flags, data, externfs_fill_sb));
-}
-
-void init_externfs(struct externfs_data *ed, struct externfs_file_ops *ops)
-{
- ed->file_ops = ops;
-}
-
-int register_externfs(char *name, struct externfs_mount_ops *mount_ops)
-{
- struct externfs *new;
- int err = -ENOMEM;
-
- new = kmalloc(sizeof(*new), GFP_KERNEL);
- if(new == NULL)
- goto out;
-
- memset(new, 0, sizeof(*new));
- *new = ((struct externfs) { .list = LIST_HEAD_INIT(new->list),
- .mount_ops = mount_ops,
- .type = { .name = name,
- .get_sb = externfs_read_super,
- .kill_sb = kill_anon_super,
- .fs_flags = 0,
- .owner = THIS_MODULE } });
- list_add(&new->list, &externfses);
-
- err = register_filesystem(&new->type);
- if(err)
- goto out_del;
- return(0);
-
- out_del:
- list_del(&new->list);
- kfree(new);
- out:
- return(err);
-}
-
-void unregister_externfs(char *name)
-{
- struct list_head *ele;
- struct externfs *fs;
-
- down(&externfs_sem);
- list_for_each(ele, &externfses){
- fs = list_entry(ele, struct externfs, list);
- if(!strcmp(fs->type.name, name)){
- list_del(ele);
- up(&externfs_sem);
- return;
- }
- }
- up(&externfs_sem);
- printk("Unregister_externfs - filesystem '%s' not found\n", name);
-}
-
-/*
- * 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:
- */
+++ /dev/null
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/stddef.h"
-#include "linux/string.h"
-#include "linux/errno.h"
-#include "linux/types.h"
-#include "linux/slab.h"
-#include "linux/fs.h"
-#include "asm/fcntl.h"
-#include "hostfs.h"
-#include "filehandle.h"
-
-extern int append;
-
-char *get_path(const char *path[], char *buf, int size)
-{
- const char **s;
- char *p;
- int new = 1;
-
- for(s = path; *s != NULL; s++){
- new += strlen(*s);
- if((*(s + 1) != NULL) && (strlen(*s) > 0) &&
- ((*s)[strlen(*s) - 1] != '/'))
- new++;
- }
-
- if(new > size){
- buf = kmalloc(new, GFP_KERNEL);
- if(buf == NULL)
- return(NULL);
- }
-
- p = buf;
- for(s = path; *s != NULL; s++){
- strcpy(p, *s);
- p += strlen(*s);
- if((*(s + 1) != NULL) && (strlen(*s) > 0) &&
- ((*s)[strlen(*s) - 1] != '/'))
- strcpy(p++, "/");
- }
-
- return(buf);
-}
-
-void free_path(const char *buf, char *tmp)
-{
- if((buf != tmp) && (buf != NULL))
- kfree((char *) buf);
-}
-
-int host_open_file(const char *path[], int r, int w, struct file_handle *fh)
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- int mode = 0, err;
- struct openflags flags = OPENFLAGS();
-
- if (r)
- flags = of_read(flags);
- if (w)
- flags = of_write(flags);
- if(append)
- flags = of_append(flags);
-
- err = -ENOMEM;
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = open_filehandle(file, flags, mode, fh);
- out:
- free_path(file, tmp);
- return(err);
-}
-
-void *host_open_dir(const char *path[])
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- void *dir = ERR_PTR(-ENOMEM);
-
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- dir = open_dir(file);
- out:
- free_path(file, tmp);
- return(dir);
-}
-
-char *host_read_dir(void *stream, unsigned long long *pos,
- unsigned long long *ino_out, int *len_out)
-{
- int err;
- char *name;
-
- err = os_seek_dir(stream, *pos);
- if(err)
- return(ERR_PTR(err));
-
- err = os_read_dir(stream, ino_out, &name);
- if(err)
- return(ERR_PTR(err));
-
- if(name == NULL)
- return(NULL);
-
- *len_out = strlen(name);
- *pos = os_tell_dir(stream);
- return(name);
-}
-
-int host_file_type(const char *path[], int *rdev)
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- struct uml_stat buf;
- int ret;
-
- ret = -ENOMEM;
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- if(rdev != NULL){
- ret = os_lstat_file(file, &buf);
- if(ret)
- goto out;
- *rdev = MKDEV(buf.ust_rmajor, buf.ust_rminor);
- }
-
- ret = os_file_type(file);
- out:
- free_path(file, tmp);
- return(ret);
-}
-
-int host_create_file(const char *path[], int mode, struct file_handle *fh)
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- int err = -ENOMEM;
-
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = open_filehandle(file, of_create(of_rdwr(OPENFLAGS())), mode, fh);
- out:
- free_path(file, tmp);
- return(err);
-}
-
-static int do_stat_file(const char *path, int *dev_out,
- unsigned long long *inode_out, int *mode_out,
- int *nlink_out, int *uid_out, int *gid_out,
- unsigned long long *size_out, unsigned long *atime_out,
- unsigned long *mtime_out, unsigned long *ctime_out,
- int *blksize_out, unsigned long long *blocks_out)
-{
- struct uml_stat buf;
- int err;
-
- err = os_lstat_file(path, &buf);
- if(err < 0)
- return(err);
-
- if(dev_out != NULL) *dev_out = MKDEV(buf.ust_major, buf.ust_minor);
- if(inode_out != NULL) *inode_out = buf.ust_ino;
- if(mode_out != NULL) *mode_out = buf.ust_mode;
- if(nlink_out != NULL) *nlink_out = buf.ust_nlink;
- if(uid_out != NULL) *uid_out = buf.ust_uid;
- if(gid_out != NULL) *gid_out = buf.ust_gid;
- if(size_out != NULL) *size_out = buf.ust_size;
- if(atime_out != NULL) *atime_out = buf.ust_atime;
- if(mtime_out != NULL) *mtime_out = buf.ust_mtime;
- if(ctime_out != NULL) *ctime_out = buf.ust_ctime;
- if(blksize_out != NULL) *blksize_out = buf.ust_blksize;
- if(blocks_out != NULL) *blocks_out = buf.ust_blocks;
-
- return(0);
-}
-
-int host_stat_file(const char *path[], int *dev_out,
- unsigned long long *inode_out, int *mode_out,
- int *nlink_out, int *uid_out, int *gid_out,
- unsigned long long *size_out, unsigned long *atime_out,
- unsigned long *mtime_out, unsigned long *ctime_out,
- int *blksize_out, unsigned long long *blocks_out)
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- int err;
-
- err = -ENOMEM;
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = do_stat_file(file, dev_out, inode_out, mode_out, nlink_out,
- uid_out, gid_out, size_out, atime_out, mtime_out,
- ctime_out, blksize_out, blocks_out);
- out:
- free_path(file, tmp);
- return(err);
-}
-
-int host_set_attr(const char *path[], struct externfs_iattr *attrs)
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- unsigned long time;
- int err = 0, ma;
-
- if(append && (attrs->ia_valid & EXTERNFS_ATTR_SIZE))
- return(-EPERM);
-
- err = -ENOMEM;
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- if(attrs->ia_valid & EXTERNFS_ATTR_MODE){
- err = os_set_file_perms(file, attrs->ia_mode);
- if(err < 0)
- goto out;
- }
- if(attrs->ia_valid & EXTERNFS_ATTR_UID){
- err = os_set_file_owner(file, attrs->ia_uid, -1);
- if(err < 0)
- goto out;
- }
- if(attrs->ia_valid & EXTERNFS_ATTR_GID){
- err = os_set_file_owner(file, -1, attrs->ia_gid);
- if(err < 0)
- goto out;
- }
- if(attrs->ia_valid & EXTERNFS_ATTR_SIZE){
- err = os_truncate_file(file, attrs->ia_size);
- if(err < 0)
- goto out;
- }
- ma = EXTERNFS_ATTR_ATIME_SET | EXTERNFS_ATTR_MTIME_SET;
- if((attrs->ia_valid & ma) == ma){
- err = os_set_file_time(file, attrs->ia_atime, attrs->ia_mtime);
- if(err)
- goto out;
- }
- else {
- if(attrs->ia_valid & EXTERNFS_ATTR_ATIME_SET){
- err = do_stat_file(file, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, &time,
- NULL, NULL, NULL);
- if(err != 0)
- goto out;
-
- err = os_set_file_time(file, attrs->ia_atime, time);
- if(err)
- goto out;
- }
- if(attrs->ia_valid & EXTERNFS_ATTR_MTIME_SET){
- err = do_stat_file(file, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, &time, NULL,
- NULL, NULL, NULL);
- if(err != 0)
- goto out;
-
- err = os_set_file_time(file, time, attrs->ia_mtime);
- if(err)
- goto out;
- }
- }
- if(attrs->ia_valid & EXTERNFS_ATTR_CTIME) ;
- if(attrs->ia_valid & (EXTERNFS_ATTR_ATIME | EXTERNFS_ATTR_MTIME)){
- err = do_stat_file(file, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, &attrs->ia_atime,
- &attrs->ia_mtime, NULL, NULL, NULL);
- if(err != 0)
- goto out;
- }
-
- err = 0;
- out:
- free_path(file, tmp);
- return(err);
-}
-
-int host_make_symlink(const char *from[], const char *to)
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- int err = -ENOMEM;
-
- file = get_path(from, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = os_make_symlink(to, file);
- out:
- free_path(file, tmp);
- return(err);
-}
-
-int host_unlink_file(const char *path[])
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- int err = -ENOMEM;
-
- if(append)
- return(-EPERM);
-
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = os_remove_file(file);
- out:
- free_path(file, tmp);
- return(err);
-}
-
-int host_make_dir(const char *path[], int mode)
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- int err = -ENOMEM;
-
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = os_make_dir(file, mode);
- out:
- free_path(file, tmp);
- return(err);
-}
-
-int host_remove_dir(const char *path[])
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- int err = -ENOMEM;
-
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = os_remove_dir(file);
- out:
- free_path(file, tmp);
- return(err);
-}
-
-int host_link_file(const char *to[], const char *from[])
-{
- char from_tmp[HOSTFS_BUFSIZE], *f, to_tmp[HOSTFS_BUFSIZE], *t;
- int err = -ENOMEM;
-
- f = get_path(from, from_tmp, sizeof(from_tmp));
- t = get_path(to, to_tmp, sizeof(to_tmp));
- if((f == NULL) || (t == NULL))
- goto out;
-
- err = os_link_file(t, f);
- out:
- free_path(f, from_tmp);
- free_path(t, to_tmp);
- return(err);
-}
-
-int host_read_link(const char *path[], char *buf, int size)
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- int n = -ENOMEM;
-
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- n = os_read_symlink(file, buf, size);
- if(n < size)
- buf[n] = '\0';
- out:
- free_path(file, tmp);
- return(n);
-}
-
-int host_rename_file(const char *from[], const char *to[])
-{
- char from_tmp[HOSTFS_BUFSIZE], *f, to_tmp[HOSTFS_BUFSIZE], *t;
- int err = -ENOMEM;
-
- f = get_path(from, from_tmp, sizeof(from_tmp));
- t = get_path(to, to_tmp, sizeof(to_tmp));
- if((f == NULL) || (t == NULL))
- goto out;
-
- err = os_move_file(f, t);
- out:
- free_path(f, from_tmp);
- free_path(t, to_tmp);
- return(err);
-}
-
-int host_stat_fs(const char *path[], long *bsize_out, long long *blocks_out,
- long long *bfree_out, long long *bavail_out,
- long long *files_out, long long *ffree_out, void *fsid_out,
- int fsid_size, long *namelen_out, long *spare_out)
-{
- char tmp[HOSTFS_BUFSIZE], *file;
- int err = -ENOMEM;
-
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = os_stat_filesystem(file, bsize_out, blocks_out, bfree_out,
- bavail_out, files_out, ffree_out, fsid_out,
- fsid_size, namelen_out, spare_out);
- out:
- free_path(file, tmp);
- return(err);
-}
-
-char *generic_host_read_dir(void *stream, unsigned long long *pos,
- unsigned long long *ino_out, int *len_out,
- void *mount)
-{
- return(host_read_dir(stream, pos, ino_out, len_out));
-}
-
-int generic_host_truncate_file(struct file_handle *fh, __u64 size, void *m)
-{
- return(truncate_file(fh, size));
-}
-
-/*
- * 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:
- */
+++ /dev/null
-/*
- * Copyright (C) 2000 - 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/stddef.h"
-#include "linux/string.h"
-#include "linux/types.h"
-#include "linux/errno.h"
-#include "linux/slab.h"
-#include "linux/init.h"
-#include "linux/fs.h"
-#include "linux/stat.h"
-#include "hostfs.h"
-#include "kern.h"
-#include "init.h"
-#include "kern_util.h"
-#include "filehandle.h"
-#include "os.h"
-
-/* Changed in hostfs_args before the kernel starts running */
-static char *jail_dir = "/";
-int append = 0;
-
-static int __init hostfs_args(char *options, int *add)
-{
- char *ptr;
-
- ptr = strchr(options, ',');
- if(ptr != NULL)
- *ptr++ = '\0';
- if(*options != '\0')
- jail_dir = options;
-
- options = ptr;
- while(options){
- ptr = strchr(options, ',');
- if(ptr != NULL)
- *ptr++ = '\0';
- if(*options != '\0'){
- if(!strcmp(options, "append"))
- append = 1;
- else printf("hostfs_args - unsupported option - %s\n",
- options);
- }
- options = ptr;
- }
- return(0);
-}
-
-__uml_setup("hostfs=", hostfs_args,
-"hostfs=<root dir>,<flags>,...\n"
-" This is used to set hostfs parameters. The root directory argument\n"
-" is used to confine all hostfs mounts to within the specified directory\n"
-" tree on the host. If this isn't specified, then a user inside UML can\n"
-" mount anything on the host that's accessible to the user that's running\n"
-" it.\n"
-" The only flag currently supported is 'append', which specifies that all\n"
-" files opened by hostfs will be opened in append mode.\n\n"
-);
-
-struct hostfs_data {
- struct externfs_data ext;
- char *mount;
-};
-
-struct hostfs_file {
- struct externfs_inode ext;
- struct file_handle fh;
-};
-
-static int hostfs_access_file(char *file, int uid, int w, int x, int gid,
- int r, struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
- char tmp[HOSTFS_BUFSIZE];
- int err, mode = 0;
-
- if(r) mode = OS_ACC_R_OK;
- if(w) mode |= OS_ACC_W_OK;
- if(x) mode |= OS_ACC_X_OK;
-
- err = -ENOMEM;
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = os_access(file, mode);
- free_path(file, tmp);
- out:
- return(err);
-}
-
-static int hostfs_make_node(const char *file, int mode, int uid, int gid,
- int type, int major, int minor,
- struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
- char tmp[HOSTFS_BUFSIZE];
- int err = -ENOMEM;
-
- file = get_path(path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- /* XXX Pass type in an OS-independent way */
- mode |= type;
-
- err = os_make_dev(file, mode, major, minor);
- free_path(file, tmp);
- out:
- return(err);
-}
-
-static int hostfs_stat_file(const char *file, struct externfs_data *ed,
- dev_t *dev_out, unsigned long long *inode_out,
- int *mode_out, int *nlink_out, int *uid_out,
- int *gid_out, unsigned long long *size_out,
- unsigned long *atime_out, unsigned long *mtime_out,
- unsigned long *ctime_out, int *blksize_out,
- unsigned long long *blocks_out)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
-
- /* XXX Why pretend everything is owned by root? */
- *uid_out = 0;
- *gid_out = 0;
- return(host_stat_file(path, dev_out, inode_out, mode_out, nlink_out,
- NULL, NULL, size_out, atime_out, mtime_out,
- ctime_out, blksize_out, blocks_out));
-}
-
-static int hostfs_file_type(const char *file, int *rdev,
- struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
-
- return(host_file_type(path, rdev));
-}
-
-static char *hostfs_name(struct inode *inode)
-{
- struct externfs_data *ed = inode_externfs_info(inode);
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
-
- return(inode_name_prefix(inode, mount));
-}
-
-static struct externfs_inode *hostfs_init_file(struct externfs_data *ed)
-{
- struct hostfs_file *hf;
-
- hf = kmalloc(sizeof(*hf), GFP_KERNEL);
- if(hf == NULL)
- return(NULL);
-
- hf->fh.fd = -1;
- return(&hf->ext);
-}
-
-static int hostfs_open_file(struct externfs_inode *ext, char *file,
- int uid, int gid, struct inode *inode,
- struct externfs_data *ed)
-{
- struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext);
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
- int err;
-
- err = host_open_file(path, 1, 1, &hf->fh);
- if(err == -EISDIR)
- goto out;
-
- if(err == -EACCES)
- err = host_open_file(path, 1, 0, &hf->fh);
-
- if(err)
- goto out;
-
- is_reclaimable(&hf->fh, hostfs_name, inode);
- out:
- return(err);
-}
-
-static void *hostfs_open_dir(char *file, int uid, int gid,
- struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
-
- return(host_open_dir(path));
-}
-
-static void hostfs_close_dir(void *stream, struct externfs_data *ed)
-{
- os_close_dir(stream);
-}
-
-static char *hostfs_read_dir(void *stream, unsigned long long *pos,
- unsigned long long *ino_out, int *len_out,
- struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
-
- return(generic_host_read_dir(stream, pos, ino_out, len_out, mount));
-}
-
-static int hostfs_read_file(struct externfs_inode *ext,
- unsigned long long offset, char *buf, int len,
- int ignore_start, int ignore_end,
- void (*completion)(char *, int, void *), void *arg,
- struct externfs_data *ed)
-{
- struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext);
- int err = 0;
-
- if(ignore_start != 0){
- err = read_file(&hf->fh, offset, buf, ignore_start);
- if(err < 0)
- goto out;
- }
-
- if(ignore_end != len)
- err = read_file(&hf->fh, offset + ignore_end, buf + ignore_end,
- len - ignore_end);
-
- out:
-
- (*completion)(buf, err, arg);
- if (err > 0)
- err = 0;
- return(err);
-}
-
-static int hostfs_write_file(struct externfs_inode *ext,
- unsigned long long offset, const char *buf,
- int start, int len,
- void (*completion)(char *, int, void *),
- void *arg, struct externfs_data *ed)
-{
- struct file_handle *fh;
- int err;
-
- fh = &container_of(ext, struct hostfs_file, ext)->fh;
- err = write_file(fh, offset + start, buf + start, len);
-
- (*completion)((char *) buf, err, arg);
- if (err > 0)
- err = 0;
-
- return(err);
-}
-
-static int hostfs_create_file(struct externfs_inode *ext, char *file, int mode,
- int uid, int gid, struct inode *inode,
- struct externfs_data *ed)
-{
- struct hostfs_file *hf = container_of(ext, struct hostfs_file,
- ext);
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
- int err = -ENOMEM;
-
- err = host_create_file(path, mode, &hf->fh);
- if(err)
- goto out;
-
- is_reclaimable(&hf->fh, hostfs_name, inode);
- out:
- return(err);
-}
-
-static int hostfs_set_attr(const char *file, struct externfs_iattr *attrs,
- struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
-
- return(host_set_attr(path, attrs));
-}
-
-static int hostfs_make_symlink(const char *from, const char *to, int uid,
- int gid, struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, from, NULL };
-
- return(host_make_symlink(path, to));
-}
-
-static int hostfs_link_file(const char *to, const char *from, int uid, int gid,
- struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *to_path[] = { jail_dir, mount, to, NULL };
- const char *from_path[] = { jail_dir, mount, from, NULL };
-
- return(host_link_file(to_path, from_path));
-}
-
-static int hostfs_unlink_file(const char *file, struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
-
- return(host_unlink_file(path));
-}
-
-static int hostfs_make_dir(const char *file, int mode, int uid, int gid,
- struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
-
- return(host_make_dir(path, mode));
-}
-
-static int hostfs_remove_dir(const char *file, int uid, int gid,
- struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
-
- return(host_remove_dir(path));
-}
-
-static int hostfs_read_link(char *file, int uid, int gid, char *buf, int size,
- struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, file, NULL };
-
- return(host_read_link(path, buf, size));
-}
-
-static int hostfs_rename_file(char *from, char *to, struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *to_path[] = { jail_dir, mount, to, NULL };
- const char *from_path[] = { jail_dir, mount, from, NULL };
-
- return(host_rename_file(from_path, to_path));
-}
-
-static int hostfs_stat_fs(long *bsize_out, long long *blocks_out,
- long long *bfree_out, long long *bavail_out,
- long long *files_out, long long *ffree_out,
- void *fsid_out, int fsid_size, long *namelen_out,
- long *spare_out, struct externfs_data *ed)
-{
- char *mount = container_of(ed, struct hostfs_data, ext)->mount;
- const char *path[] = { jail_dir, mount, NULL };
-
- return(host_stat_fs(path, bsize_out, blocks_out, bfree_out, bavail_out,
- files_out, ffree_out, fsid_out, fsid_size,
- namelen_out, spare_out));
-}
-
-void hostfs_close_file(struct externfs_inode *ext,
- unsigned long long size)
-{
- struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext);
-
- if(hf->fh.fd != -1){
- truncate_file(&hf->fh, size);
- close_file(&hf->fh);
- }
-
- kfree(hf);
-}
-
-int hostfs_truncate_file(struct externfs_inode *ext, __u64 size,
- struct externfs_data *ed)
-{
- struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext);
-
- return(truncate_file(&hf->fh, size));
-}
-
-static struct externfs_file_ops hostfs_file_ops = {
- .stat_file = hostfs_stat_file,
- .file_type = hostfs_file_type,
- .access_file = hostfs_access_file,
- .open_file = hostfs_open_file,
- .open_dir = hostfs_open_dir,
- .read_dir = hostfs_read_dir,
- .read_file = hostfs_read_file,
- .write_file = hostfs_write_file,
- .map_file_page = NULL,
- .close_file = hostfs_close_file,
- .close_dir = hostfs_close_dir,
- .invisible = NULL,
- .create_file = hostfs_create_file,
- .set_attr = hostfs_set_attr,
- .make_symlink = hostfs_make_symlink,
- .unlink_file = hostfs_unlink_file,
- .make_dir = hostfs_make_dir,
- .remove_dir = hostfs_remove_dir,
- .make_node = hostfs_make_node,
- .link_file = hostfs_link_file,
- .read_link = hostfs_read_link,
- .rename_file = hostfs_rename_file,
- .statfs = hostfs_stat_fs,
- .truncate_file = hostfs_truncate_file
-};
-
-static struct externfs_data *mount_fs(char *mount_arg)
-{
- struct hostfs_data *hd;
- int err = -ENOMEM;
-
- hd = kmalloc(sizeof(*hd), GFP_KERNEL);
- if(hd == NULL)
- goto out;
-
- hd->mount = host_root_filename(mount_arg);
- if(hd->mount == NULL)
- goto out_free;
-
- init_externfs(&hd->ext, &hostfs_file_ops);
-
- return(&hd->ext);
-
- out_free:
- kfree(hd);
- out:
- return(ERR_PTR(err));
-}
-
-static struct externfs_mount_ops hostfs_mount_ops = {
- .init_file = hostfs_init_file,
- .mount = mount_fs,
-};
-
-static int __init init_hostfs(void)
-{
- return(register_externfs("hostfs", &hostfs_mount_ops));
-}
-
-static void __exit exit_hostfs(void)
-{
- unregister_externfs("hostfs");
-}
-
-__initcall(init_hostfs);
-__exitcall(exit_hostfs);
-
-#if 0
-module_init(init_hostfs)
-module_exit(exit_hostfs)
-MODULE_LICENSE("GPL");
-#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:
- */
+++ /dev/null
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/kdev_t.h>
-#include "linux/init.h"
-#include "linux/workqueue.h"
-#include <asm/irq.h>
-#include "hostfs.h"
-#include "mem.h"
-#include "os.h"
-#include "mode.h"
-#include "aio.h"
-#include "irq_user.h"
-#include "irq_kern.h"
-#include "filehandle.h"
-#include "metadata.h"
-
-#define HUMFS_VERSION 2
-
-static int humfs_stat_file(const char *path, struct externfs_data *ed,
- dev_t *dev_out, unsigned long long *inode_out,
- int *mode_out, int *nlink_out, int *uid_out,
- int *gid_out, unsigned long long *size_out,
- unsigned long *atime_out, unsigned long *mtime_out,
- unsigned long *ctime_out, int *blksize_out,
- unsigned long long *blocks_out)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path[3] = { mount->data, path, NULL };
- int err, mode, perms, major, minor;
- char type;
-
- err = host_stat_file(data_path, NULL, inode_out, mode_out,
- nlink_out, NULL, NULL, size_out, atime_out,
- mtime_out, ctime_out, blksize_out, blocks_out);
- if(err)
- return(err);
-
- err = (*mount->meta->ownerships)(path, &perms, uid_out, gid_out,
- &type, &major, &minor, mount);
- if(err)
- return(err);
-
- *mode_out = (*mode_out & ~S_IRWXUGO) | perms;
-
- mode = 0;
- switch(type){
- case 'c':
- mode = S_IFCHR;
- *dev_out = MKDEV(major, minor);
- break;
- case 'b':
- mode = S_IFBLK;
- *dev_out = MKDEV(major, minor);
- break;
- case 's':
- mode = S_IFSOCK;
- break;
- default:
- break;
- }
-
- if(mode != 0)
- *mode_out = (*mode_out & ~S_IFMT) | mode;
-
- return(0);
-}
-
-static int meta_type(const char *path, int *dev_out, void *m)
-{
- struct humfs *mount = m;
- int err, type, maj, min;
- char c;
-
- err = (*mount->meta->ownerships)(path, NULL, NULL, NULL, &c, &maj,
- &min, mount);
- if(err)
- return(err);
-
- if(c == 0)
- return(0);
-
- if(dev_out)
- *dev_out = MKDEV(maj, min);
-
- switch(c){
- case 'c':
- type = OS_TYPE_CHARDEV;
- break;
- case 'b':
- type = OS_TYPE_BLOCKDEV;
- break;
- case 'p':
- type = OS_TYPE_FIFO;
- break;
- case 's':
- type = OS_TYPE_SOCK;
- break;
- default:
- type = -EINVAL;
- break;
- }
-
- return(type);
-}
-
-static int humfs_file_type(const char *path, int *dev_out,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path[3] = { mount->data, path, NULL };
- int type;
-
- type = meta_type(path, dev_out, mount);
- if(type != 0)
- return(type);
-
- return(host_file_type(data_path, dev_out));
-}
-
-static char *humfs_data_name(struct inode *inode)
-{
- struct externfs_data *ed = inode_externfs_info(inode);
- struct humfs *mount = container_of(ed, struct humfs, ext);
-
- return(inode_name_prefix(inode, mount->data));
-}
-
-static struct externfs_inode *humfs_init_file(struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- struct humfs_file *hf;
-
- hf = (*mount->meta->init_file)();
- if(hf == NULL)
- return(NULL);
-
- hf->data.fd = -1;
- return(&hf->ext);
-}
-
-static int humfs_open_file(struct externfs_inode *ext, char *path, int uid,
- int gid, struct inode *inode,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- struct humfs_file *hf = container_of(ext, struct humfs_file, ext);
- const char *data_path[3] = { mount->data, path, NULL };
- struct openflags flags;
- char tmp[HOSTFS_BUFSIZE], *file;
- int err = -ENOMEM;
-
- file = get_path(data_path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- flags = of_rdwr(OPENFLAGS());
- if(mount->direct)
- flags = of_direct(flags);
-
- if(path == NULL)
- path = "";
- err = (*mount->meta->open_file)(hf, path, inode, mount);
- if(err)
- goto out_free;
-
- err = open_filehandle(file, flags, 0, &hf->data);
- if(err == -EISDIR)
- goto out;
- else if(err == -EPERM){
- flags = of_set_rw(flags, 1, 0);
- err = open_filehandle(file, flags, 0, &hf->data);
- }
-
- if(err)
- goto out_close;
-
- hf->mount = mount;
- is_reclaimable(&hf->data, humfs_data_name, inode);
-
- out_free:
- free_path(file, tmp);
- out:
- return(err);
-
- out_close:
- (*mount->meta->close_file)(hf);
- goto out_free;
-}
-
-static void *humfs_open_dir(char *path, int uid, int gid,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path[3] = { mount->data, path, NULL };
-
- return(host_open_dir(data_path));
-}
-
-static void humfs_close_dir(void *stream, struct externfs_data *ed)
-{
- os_close_dir(stream);
-}
-
-static char *humfs_read_dir(void *stream, unsigned long long *pos,
- unsigned long long *ino_out, int *len_out,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
-
- return(generic_host_read_dir(stream, pos, ino_out, len_out, mount));
-}
-
-LIST_HEAD(humfs_replies);
-
-struct humfs_aio {
- struct aio_context aio;
- struct list_head list;
- void (*completion)(char *, int, void *);
- char *buf;
- int real_len;
- int err;
- void *data;
-};
-
-static int humfs_reply_fd = -1;
-
-struct humfs_aio last_task_aio, last_intr_aio;
-struct humfs_aio *last_task_aio_ptr, *last_intr_aio_ptr;
-
-void humfs_work_proc(void *unused)
-{
- struct humfs_aio *aio;
- unsigned long flags;
-
- while(!list_empty(&humfs_replies)){
- local_irq_save(flags);
- aio = list_entry(humfs_replies.next, struct humfs_aio, list);
-
- last_task_aio = *aio;
- last_task_aio_ptr = aio;
-
- list_del(&aio->list);
- local_irq_restore(flags);
-
- if(aio->err >= 0)
- aio->err = aio->real_len;
- (*aio->completion)(aio->buf, aio->err, aio->data);
- kfree(aio);
- }
-}
-
-DECLARE_WORK(humfs_work, humfs_work_proc, NULL);
-
-static irqreturn_t humfs_interrupt(int irq, void *dev_id,
- struct pt_regs *unused)
-{
- struct aio_thread_reply reply;
- struct humfs_aio *aio;
- int err, fd = (int) dev_id;
-
- while(1){
- err = os_read_file(fd, &reply, sizeof(reply));
- if(err < 0){
- if(err == -EAGAIN)
- break;
- printk("humfs_interrupt - read returned err %d\n",
- -err);
- return(IRQ_HANDLED);
- }
- aio = reply.data;
- aio->err = reply.err;
- list_add(&aio->list, &humfs_replies);
- last_intr_aio = *aio;
- last_intr_aio_ptr = aio;
- }
-
- if(!list_empty(&humfs_replies))
- schedule_work(&humfs_work);
- reactivate_fd(fd, HUMFS_IRQ);
- return(IRQ_HANDLED);
-}
-
-static int init_humfs_aio(void)
-{
- int fds[2], err;
-
- err = os_pipe(fds, 1, 1);
- if(err){
- printk("init_humfs_aio - pipe failed, err = %d\n", -err);
- goto out;
- }
-
- err = um_request_irq(HUMFS_IRQ, fds[0], IRQ_READ, humfs_interrupt,
- SA_INTERRUPT | SA_SAMPLE_RANDOM, "humfs",
- (void *) fds[0]);
- if(err){
- printk("init_humfs_aio - : um_request_irq failed, err = %d\n",
- err);
- goto out_close;
- }
-
- humfs_reply_fd = fds[1];
- goto out;
-
- out_close:
- os_close_file(fds[0]);
- os_close_file(fds[1]);
- out:
- return(0);
-}
-
-__initcall(init_humfs_aio);
-
-static int humfs_aio(enum aio_type type, int fd, unsigned long long offset,
- char *buf, int len, int real_len,
- void (*completion)(char *, int, void *), void *arg)
-{
- struct humfs_aio *aio;
- int err = -ENOMEM;
-
- aio = kmalloc(sizeof(*aio), GFP_KERNEL);
- if(aio == NULL)
- goto out;
- *aio = ((struct humfs_aio) { .aio = INIT_AIO_CONTEXT,
- .list = LIST_HEAD_INIT(aio->list),
- .completion= completion,
- .buf = buf,
- .err = 0,
- .real_len = real_len,
- .data = arg });
-
- err = submit_aio(type, fd, buf, len, offset, humfs_reply_fd, aio);
- if(err)
- (*completion)(buf, err, arg);
-
- out:
- return(err);
-}
-
-static int humfs_read_file(struct externfs_inode *ext,
- unsigned long long offset, char *buf, int len,
- int ignore_start, int ignore_end,
- void (*completion)(char *, int, void *), void *arg,
- struct externfs_data *ed)
-{
- struct humfs_file *hf = container_of(ext, struct humfs_file, ext);
- int fd = filehandle_fd(&hf->data);
-
- if(fd < 0){
- (*completion)(buf, fd, arg);
- return(fd);
- }
-
- return(humfs_aio(AIO_READ, fd, offset, buf, len, len, completion,
- arg));
-}
-
-static int humfs_write_file(struct externfs_inode *ext,
- unsigned long long offset,
- const char *buf, int start, int len,
- void (*completion)(char *, int, void *), void *arg,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- struct humfs_file *hf = container_of(ext, struct humfs_file, ext);
- int err, orig_len = len, fd = filehandle_fd(&hf->data);
-
- if(fd < 0){
- (*completion)((char *) buf, fd, arg);
- return(fd);
- }
-
- if(mount->direct)
- len = PAGE_SIZE;
- else {
- offset += start;
- buf += start;
- }
-
- err = humfs_aio(AIO_WRITE, fd, offset, (char *) buf, len, orig_len,
- completion, arg);
-
- if(err < 0)
- return(err);
-
- if(mount->direct)
- err = orig_len;
-
- return(err);
-}
-
-static int humfs_map_file_page(struct externfs_inode *ext,
- unsigned long long offset, char *buf, int w,
- struct externfs_data *ed)
-{
- struct humfs_file *hf = container_of(ext, struct humfs_file, ext);
- unsigned long long size, need;
- int err, fd = filehandle_fd(&hf->data);
-
- if(fd < 0)
- return(fd);
-
- err = os_fd_size(fd, &size);
- if(err)
- return(err);
-
- need = offset + PAGE_SIZE;
- if(size < need){
- err = os_truncate_fd(fd, need);
- if(err)
- return(err);
- }
-
- return(physmem_subst_mapping(buf, fd, offset, w));
-}
-
-static void humfs_close_file(struct externfs_inode *ext,
- unsigned long long size)
-{
- struct humfs_file *hf = container_of(ext, struct humfs_file, ext);
- int fd;
-
- if(hf->data.fd == -1)
- return;
-
- fd = filehandle_fd(&hf->data);
- physmem_forget_descriptor(fd);
- truncate_file(&hf->data, size);
- close_file(&hf->data);
-
- (*hf->mount->meta->close_file)(hf);
-}
-
-/* XXX Assumes that you can't make a normal file */
-
-static int humfs_make_node(const char *path, int mode, int uid, int gid,
- int type, int major, int minor,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- struct file_handle fh;
- const char *data_path[3] = { mount->data, path, NULL };
- int err;
- char t;
-
- err = host_create_file(data_path, S_IRWXUGO, &fh);
- if(err)
- goto out;
-
- close_file(&fh);
-
- switch(type){
- case S_IFCHR:
- t = 'c';
- break;
- case S_IFBLK:
- t = 'b';
- break;
- case S_IFIFO:
- t = 'p';
- break;
- case S_IFSOCK:
- t = 's';
- break;
- default:
- err = -EINVAL;
- printk("make_node - bad node type : %d\n", type);
- goto out_rm;
- }
-
- err = (*mount->meta->make_node)(path, mode, uid, gid, t, major, minor,
- mount);
- if(err)
- goto out_rm;
-
- out:
- return(err);
-
- out_rm:
- host_unlink_file(data_path);
- goto out;
-}
-
-static int humfs_create_file(struct externfs_inode *ext, char *path, int mode,
- int uid, int gid, struct inode *inode,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- struct humfs_file *hf = container_of(ext, struct humfs_file, ext);
- const char *data_path[3] = { mount->data, path, NULL };
- int err;
-
- err = (*mount->meta->create_file)(hf, path, mode, uid, gid, inode,
- mount);
- if(err)
- goto out;
-
- err = host_create_file(data_path, S_IRWXUGO, &hf->data);
- if(err)
- goto out_rm;
-
-
- is_reclaimable(&hf->data, humfs_data_name, inode);
-
- return(0);
-
- out_rm:
- (*mount->meta->remove_file)(path, mount);
- (*mount->meta->close_file)(hf);
- out:
- return(err);
-}
-
-static int humfs_set_attr(const char *path, struct externfs_iattr *attrs,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path[3] = { mount->data, path, NULL };
- int (*chown)(const char *, int, int, int, struct humfs *);
- int err;
-
- chown = mount->meta->change_ownerships;
- if(attrs->ia_valid & EXTERNFS_ATTR_MODE){
- err = (*chown)(path, attrs->ia_mode, -1, -1, mount);
- if(err)
- return(err);
- }
- if(attrs->ia_valid & EXTERNFS_ATTR_UID){
- err = (*chown)(path, -1, attrs->ia_uid, -1, mount);
- if(err)
- return(err);
- }
- if(attrs->ia_valid & EXTERNFS_ATTR_GID){
- err = (*chown)(path, -1, -1, attrs->ia_gid, mount);
- if(err)
- return(err);
- }
-
- attrs->ia_valid &= ~(EXTERNFS_ATTR_MODE | EXTERNFS_ATTR_UID |
- EXTERNFS_ATTR_GID);
-
- return(host_set_attr(data_path, attrs));
-}
-
-static int humfs_make_symlink(const char *from, const char *to, int uid,
- int gid, struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- struct humfs_file *hf;
- const char *data_path[3] = { mount->data, from, NULL };
- int err = -ENOMEM;
-
- hf = (*mount->meta->init_file)();
- if(hf == NULL)
- goto out;
-
- err = (*mount->meta->create_file)(hf, from, S_IRWXUGO, uid, gid, NULL,
- mount);
- if(err)
- goto out_close;
-
- err = host_make_symlink(data_path, to);
- if(err)
- (*mount->meta->remove_file)(from, mount);
-
- out_close:
- (*mount->meta->close_file)(hf);
- out:
- return(err);
-}
-
-static int humfs_link_file(const char *to, const char *from, int uid, int gid,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path_from[3] = { mount->data, from, NULL };
- const char *data_path_to[3] = { mount->data, to, NULL };
- int err;
-
- err = (*mount->meta->create_link)(to, from, mount);
- if(err)
- return(err);
-
- err = host_link_file(data_path_to, data_path_from);
- if(err)
- (*mount->meta->remove_file)(from, mount);
-
- return(err);
-}
-
-static int humfs_unlink_file(const char *path, struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path[3] = { mount->data, path, NULL };
- int err;
-
- err = (*mount->meta->remove_file)(path, mount);
- if (err)
- return err;
-
- (*mount->meta->remove_file)(path, mount);
- return(host_unlink_file(data_path));
-}
-
-static void humfs_invisible(struct externfs_inode *ext)
-{
- struct humfs_file *hf = container_of(ext, struct humfs_file, ext);
- struct humfs *mount = hf->mount;
-
- (*mount->meta->invisible)(hf);
- not_reclaimable(&hf->data);
-}
-
-static int humfs_make_dir(const char *path, int mode, int uid, int gid,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path[3] = { mount->data, path, NULL };
- int err;
-
- err = (*mount->meta->create_dir)(path, mode, uid, gid, mount);
- if(err)
- return(err);
-
- err = host_make_dir(data_path, S_IRWXUGO);
- if(err)
- (*mount->meta->remove_dir)(path, mount);
-
- return(err);
-}
-
-static int humfs_remove_dir(const char *path, int uid, int gid,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path[3] = { mount->data, path, NULL };
- int err;
-
- err = host_remove_dir(data_path);
- if (err)
- return err;
-
- (*mount->meta->remove_dir)(path, mount);
-
- return(err);
-}
-
-static int humfs_read_link(char *file, int uid, int gid, char *buf, int size,
- struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path[3] = { mount->data, file, NULL };
-
- return(host_read_link(data_path, buf, size));
-}
-
-struct humfs *inode_humfs_info(struct inode *inode)
-{
- return(container_of(inode_externfs_info(inode), struct humfs, ext));
-}
-
-static int humfs_rename_file(char *from, char *to, struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path_from[3] = { mount->data, from, NULL };
- const char *data_path_to[3] = { mount->data, to, NULL };
- int err;
-
- err = (*mount->meta->rename_file)(from, to, mount);
- if(err)
- return(err);
-
- err = host_rename_file(data_path_from, data_path_to);
- if(err)
- (*mount->meta->rename_file)(to, from, mount);
-
- return(err);
-}
-
-static int humfs_stat_fs(long *bsize_out, long long *blocks_out,
- long long *bfree_out, long long *bavail_out,
- long long *files_out, long long *ffree_out,
- void *fsid_out, int fsid_size, long *namelen_out,
- long *spare_out, struct externfs_data *ed)
-{
- struct humfs *mount = container_of(ed, struct humfs, ext);
- const char *data_path[3] = { mount->data, NULL };
- int err;
-
- /* XXX Needs to maintain this info as metadata */
- err = host_stat_fs(data_path, bsize_out, blocks_out, bfree_out,
- bavail_out, files_out, ffree_out, fsid_out,
- fsid_size, namelen_out, spare_out);
- if(err)
- return(err);
-
- *blocks_out = mount->total / *bsize_out;
- *bfree_out = (mount->total - mount->used) / *bsize_out;
- *bavail_out = (mount->total - mount->used) / *bsize_out;
- return(0);
-}
-
-int humfs_truncate_file(struct externfs_inode *ext, __u64 size,
- struct externfs_data *ed)
-{
- struct humfs_file *hf = container_of(ext, struct humfs_file, ext);
-
- return(truncate_file(&hf->data, size));
-}
-
-char *humfs_path(char *dir, char *file)
-{
- int need_slash, len = strlen(dir) + strlen(file);
- char *new;
-
- need_slash = (dir[strlen(dir) - 1] != '/');
- if(need_slash)
- len++;
-
- new = kmalloc(len + 1, GFP_KERNEL);
- if(new == NULL)
- return(NULL);
-
- strcpy(new, dir);
- if(need_slash)
- strcat(new, "/");
- strcat(new, file);
-
- return(new);
-}
-
-DECLARE_MUTEX(meta_sem);
-struct list_head metas = LIST_HEAD_INIT(metas);
-
-static struct humfs_meta_ops *find_meta(const char *name)
-{
- struct list_head *ele;
- struct humfs_meta_ops *m;
-
- down(&meta_sem);
- list_for_each(ele, &metas){
- m = list_entry(ele, struct humfs_meta_ops, list);
- if(!strcmp(m->name, name))
- goto out;
- }
- m = NULL;
- out:
- up(&meta_sem);
- return(m);
-}
-
-void register_meta(struct humfs_meta_ops *ops)
-{
- down(&meta_sem);
- list_add(&ops->list, &metas);
- up(&meta_sem);
-}
-
-void unregister_meta(struct humfs_meta_ops *ops)
-{
- down(&meta_sem);
- list_del(&ops->list);
- up(&meta_sem);
-}
-
-static struct humfs *read_superblock(char *root)
-{
- struct humfs *mount;
- struct humfs_meta_ops *meta = NULL;
- struct file_handle *fh;
- const char *path[] = { root, "superblock", NULL };
- u64 used, total;
- char meta_buf[33], line[HOSTFS_BUFSIZE], *newline;
- unsigned long long pos;
- int version, i, n, err;
-
- fh = kmalloc(sizeof(*fh), GFP_KERNEL);
- if(fh == NULL)
- return(ERR_PTR(-ENOMEM));
-
- err = host_open_file(path, 1, 0, fh);
- if(err){
- printk("Failed to open %s/%s, errno = %d\n", path[0],
- path[1], err);
- return(ERR_PTR(err));
- }
-
- used = 0;
- total = 0;
- pos = 0;
- i = 0;
- while(1){
- n = read_file(fh, pos, &line[i], sizeof(line) - i - 1);
- if((n == 0) && (i == 0))
- break;
- if(n < 0)
- return(ERR_PTR(n));
-
- pos += n;
- if(n > 0)
- line[n + i] = '\0';
-
- newline = strchr(line, '\n');
- if(newline == NULL){
- printk("read_superblock - line too long : '%s'\n",
- line);
- return(ERR_PTR(-EINVAL));
- }
- newline++;
-
- if(sscanf(line, "version %d\n", &version) == 1){
- if(version != HUMFS_VERSION){
- printk("humfs version mismatch - want version "
- "%d, got version %d.\n", HUMFS_VERSION,
- version);
- return(ERR_PTR(-EINVAL));
- }
- }
- else if(sscanf(line, "used %Lu\n", &used) == 1) ;
- else if(sscanf(line, "total %Lu\n", &total) == 1) ;
- else if(sscanf(line, "metadata %32s\n", meta_buf) == 1){
- meta = find_meta(meta_buf);
- if(meta == NULL){
- printk("read_superblock - meta api \"%s\" not "
- "registered\n", meta_buf);
- return(ERR_PTR(-EINVAL));
- }
- }
-
- else {
- printk("read_superblock - bogus line : '%s'\n", line);
- return(ERR_PTR(-EINVAL));
- }
-
- i = newline - line;
- memmove(line, newline, sizeof(line) - i);
- i = strlen(line);
- }
-
- if(used == 0){
- printk("read_superblock - used not specified or set to "
- "zero\n");
- return(ERR_PTR(-EINVAL));
- }
- if(total == 0){
- printk("read_superblock - total not specified or set to "
- "zero\n");
- return(ERR_PTR(-EINVAL));
- }
- if(used > total){
- printk("read_superblock - used is greater than total\n");
- return(ERR_PTR(-EINVAL));
- }
-
- if(meta == NULL){
- meta = find_meta("shadow_fs");
- }
-
- if(meta == NULL){
- printk("read_superblock - valid meta api was not specified\n");
- return(ERR_PTR(-EINVAL));
- }
-
- mount = (*meta->init_mount)(root);
- if(IS_ERR(mount))
- return(mount);
-
- *mount = ((struct humfs) { .total = total,
- .used = used,
- .meta = meta });
- return(mount);
-}
-
-struct externfs_file_ops humfs_no_mmap_file_ops = {
- .stat_file = humfs_stat_file,
- .file_type = humfs_file_type,
- .access_file = NULL,
- .open_file = humfs_open_file,
- .open_dir = humfs_open_dir,
- .read_dir = humfs_read_dir,
- .read_file = humfs_read_file,
- .write_file = humfs_write_file,
- .map_file_page = NULL,
- .close_file = humfs_close_file,
- .close_dir = humfs_close_dir,
- .invisible = humfs_invisible,
- .create_file = humfs_create_file,
- .set_attr = humfs_set_attr,
- .make_symlink = humfs_make_symlink,
- .unlink_file = humfs_unlink_file,
- .make_dir = humfs_make_dir,
- .remove_dir = humfs_remove_dir,
- .make_node = humfs_make_node,
- .link_file = humfs_link_file,
- .read_link = humfs_read_link,
- .rename_file = humfs_rename_file,
- .statfs = humfs_stat_fs,
- .truncate_file = humfs_truncate_file
-};
-
-struct externfs_file_ops humfs_mmap_file_ops = {
- .stat_file = humfs_stat_file,
- .file_type = humfs_file_type,
- .access_file = NULL,
- .open_file = humfs_open_file,
- .open_dir = humfs_open_dir,
- .invisible = humfs_invisible,
- .read_dir = humfs_read_dir,
- .read_file = humfs_read_file,
- .write_file = humfs_write_file,
- .map_file_page = humfs_map_file_page,
- .close_file = humfs_close_file,
- .close_dir = humfs_close_dir,
- .create_file = humfs_create_file,
- .set_attr = humfs_set_attr,
- .make_symlink = humfs_make_symlink,
- .unlink_file = humfs_unlink_file,
- .make_dir = humfs_make_dir,
- .remove_dir = humfs_remove_dir,
- .make_node = humfs_make_node,
- .link_file = humfs_link_file,
- .read_link = humfs_read_link,
- .rename_file = humfs_rename_file,
- .statfs = humfs_stat_fs,
- .truncate_file = humfs_truncate_file
-};
-
-static struct externfs_data *mount_fs(char *mount_arg)
-{
- char *root, *data, *flags;
- struct humfs *mount;
- struct externfs_file_ops *file_ops;
- int err, do_mmap = 0;
-
- if(mount_arg == NULL){
- printk("humfs - no host directory specified\n");
- return(NULL);
- }
-
- flags = strchr((char *) mount_arg, ',');
- if(flags != NULL){
- do {
- *flags++ = '\0';
-
- if(!strcmp(flags, "mmap"))
- do_mmap = 1;
-
- flags = strchr(flags, ',');
- } while(flags != NULL);
- }
-
- err = -ENOMEM;
- root = host_root_filename(mount_arg);
- if(root == NULL)
- goto err;
-
- mount = read_superblock(root);
- if(IS_ERR(mount)){
- err = PTR_ERR(mount);
- goto err_free_root;
- }
-
- data = humfs_path(root, "data/");
- if(data == NULL)
- goto err_free_mount;
-
- if(CHOOSE_MODE(do_mmap, 0)){
- printk("humfs doesn't support mmap in tt mode\n");
- do_mmap = 0;
- }
-
- mount->data = data;
- mount->mmap = do_mmap;
-
- file_ops = do_mmap ? &humfs_mmap_file_ops : &humfs_no_mmap_file_ops;
- init_externfs(&mount->ext, file_ops);
-
- return(&mount->ext);
-
- err_free_mount:
- kfree(mount);
- err_free_root:
- kfree(root);
- err:
- return(NULL);
-}
-
-struct externfs_mount_ops humfs_mount_ops = {
- .init_file = humfs_init_file,
- .mount = mount_fs,
-};
-
-static int __init init_humfs(void)
-{
- return(register_externfs("humfs", &humfs_mount_ops));
-}
-
-static void __exit exit_humfs(void)
-{
- unregister_externfs("humfs");
-}
-
-__initcall(init_humfs);
-__exitcall(exit_humfs);
-
-/*
- * 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:
- */
+++ /dev/null
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include <linux/slab.h>
-#include <linux/init.h>
-#include "hostfs.h"
-#include "metadata.h"
-#include "kern_util.h"
-
-#define METADATA_FILE_PATH(meta) (meta)->root, "file_metadata"
-#define METADATA_DIR_PATH(meta) (meta)->root, "dir_metadata"
-
-struct meta_fs {
- struct humfs humfs;
- char *root;
-};
-
-struct meta_file {
- struct humfs_file humfs;
- struct file_handle fh;
-};
-
-static int meta_file_path(const char *path, struct meta_fs *meta,
- const char *path_out[])
-{
- const char *data_path[] = { meta->root, "data", path, NULL };
- char data_tmp[HOSTFS_BUFSIZE];
- char *data_file = get_path(data_path, data_tmp, sizeof(data_tmp));
-
- if(data_file == NULL)
- return(-ENOMEM);
-
- path_out[0] = meta->root;
- path_out[2] = path;
- if(os_file_type(data_file) == OS_TYPE_DIR){
- path_out[1] = "dir_metadata";
- path_out[3] = "metadata";
- path_out[4] = NULL;
- }
- else {
- path_out[1] = "file_metadata";
- path_out[3] = NULL;
- }
-
- return(0);
-}
-
-static int open_meta_file(const char *path, struct humfs *humfs,
- struct file_handle *fh)
-{
- struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs);
- const char *meta_path[5];
- char meta_tmp[HOSTFS_BUFSIZE];
- char *meta_file;
- int err;
-
- err = meta_file_path(path, meta, meta_path);
- if(err)
- goto out;
-
- meta_file = get_path(meta_path, meta_tmp, sizeof(meta_tmp));
- if(meta_file == NULL)
- goto out;
-
- err = open_filehandle(meta_file, of_rdwr(OPENFLAGS()), 0, fh);
-
- out:
- return(err);
-}
-
-static char *meta_fs_name(struct inode *inode)
-{
- struct humfs *mount = inode_humfs_info(inode);
- struct meta_fs *meta = container_of(mount, struct meta_fs, humfs);
- const char *metadata_path[5];
- char tmp[HOSTFS_BUFSIZE], *name, *file;
-
- if(meta_file_path("", meta, metadata_path))
- return(NULL);
-
- file = get_path(metadata_path, tmp, sizeof(tmp));
- if(file == NULL)
- return(NULL);
-
- name = inode_name_prefix(inode, file);
-
- free_path(file, tmp);
- return(name);
-}
-
-static void metafs_invisible(struct humfs_file *hf)
-{
- struct meta_file *mf = container_of(hf, struct meta_file, humfs);
-
- not_reclaimable(&mf->fh);
-}
-
-static struct humfs_file *metafs_init_file(void)
-{
- struct meta_file *mf;
- int err = -ENOMEM;
-
- mf = kmalloc(sizeof(*mf), GFP_KERNEL);
- if(mf == NULL)
- return(ERR_PTR(err));
-
- return(&mf->humfs);
-}
-
-static int metafs_open_file(struct humfs_file *hf, const char *path,
- struct inode *inode, struct humfs *humfs)
-{
- struct meta_file *mf = container_of(hf, struct meta_file, humfs);
- int err;
-
- err = open_meta_file(path, humfs, &mf->fh);
- if(err)
- return(err);
-
- is_reclaimable(&mf->fh, meta_fs_name, inode);
-
- return(0);
-}
-
-static void metafs_close_file(struct humfs_file *hf)
-{
- struct meta_file *meta = container_of(hf, struct meta_file, humfs);
-
- close_file(&meta->fh);
- kfree(meta);
-}
-
-static int metafs_create_file(struct humfs_file *hf, const char *path,
- int mode, int uid, int gid, struct inode *inode,
- struct humfs *humfs)
-{
- struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs);
- struct meta_file *mf = container_of(hf, struct meta_file, humfs);
- char tmp[HOSTFS_BUFSIZE];
- const char *metadata_path[] = { METADATA_FILE_PATH(meta), path, NULL };
- char *file = get_path(metadata_path, tmp, sizeof(tmp));
- char buf[sizeof("mmmm uuuuuuuuuu gggggggggg")];
- int err = -ENOMEM;
-
- if(file == NULL)
- goto out;
-
- err = open_filehandle(file, of_write(of_create(OPENFLAGS())), 0644,
- &mf->fh);
- if(err)
- goto out_free_path;
-
- if(inode != NULL)
- is_reclaimable(&mf->fh, meta_fs_name, inode);
-
- sprintf(buf, "%d %d %d\n", mode & S_IRWXUGO, uid, gid);
- err = write_file(&mf->fh, 0, buf, strlen(buf));
- if(err < 0)
- goto out_rm;
-
- free_path(file, tmp);
- return(0);
-
- out_rm:
- close_file(&mf->fh);
- os_remove_file(file);
- out_free_path:
- free_path(file, tmp);
- out:
- return(err);
-}
-
-static int metafs_create_link(const char *to, const char *from,
- struct humfs *humfs)
-{
- struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs);
- const char *path_to[] = { METADATA_FILE_PATH(meta), to, NULL };
- const char *path_from[] = { METADATA_FILE_PATH(meta), from, NULL };
-
- return(host_link_file(path_to, path_from));
-}
-
-static int metafs_remove_file(const char *path, struct humfs *humfs)
-{
- struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs);
- char tmp[HOSTFS_BUFSIZE];
- const char *metadata_path[] = { METADATA_FILE_PATH(meta), path, NULL };
- char *file = get_path(metadata_path, tmp, sizeof(tmp));
- int err = -ENOMEM;
-
- if(file == NULL)
- goto out;
-
- err = os_remove_file(file);
-
- out:
- free_path(file, tmp);
- return(err);
-}
-
-static int metafs_create_directory(const char *path, int mode, int uid,
- int gid, struct humfs *humfs)
-{
- struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs);
- char tmp[HOSTFS_BUFSIZE];
- const char *dir_path[] = { METADATA_DIR_PATH(meta), path, NULL, NULL };
- const char *file_path[] = { METADATA_FILE_PATH(meta), path, NULL,
- NULL };
- char *file, dir_meta[sizeof("mmmm uuuuuuuuuu gggggggggg\n")];
- int err, fd;
-
- err = host_make_dir(dir_path, 0755);
- if(err)
- goto out;
-
- err = host_make_dir(file_path, 0755);
- if(err)
- goto out_rm;
-
- /* This to make the index independent of the number of elements in
- * METADATA_DIR_PATH().
- */
- dir_path[sizeof(dir_path) / sizeof(dir_path[0]) - 2] = "metadata";
-
- err = -ENOMEM;
- file = get_path(dir_path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- fd = os_open_file(file, of_create(of_rdwr(OPENFLAGS())), 0644);
- if(fd < 0){
- err = fd;
- goto out_free;
- }
-
- sprintf(dir_meta, "%d %d %d\n", mode & S_IRWXUGO, uid, gid);
- err = os_write_file(fd, dir_meta, strlen(dir_meta));
- if(err > 0)
- err = 0;
-
- os_close_file(fd);
-
- out_free:
- free_path(file, tmp);
- out_rm:
- host_remove_dir(dir_path);
- out:
- return(err);
-}
-
-static int metafs_remove_directory(const char *path, struct humfs *humfs)
-{
- struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs);
- char tmp[HOSTFS_BUFSIZE], *file;
- const char *dir_path[] = { METADATA_DIR_PATH(meta), path, "metadata",
- NULL };
- const char *file_path[] = { METADATA_FILE_PATH(meta), path, NULL };
- char *slash;
- int err;
-
- err = -ENOMEM;
- file = get_path(dir_path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = os_remove_file(file);
- if(err)
- goto out_free;
-
- slash = strrchr(file, '/');
- if(slash == NULL){
- printk("remove_shadow_directory failed to find last slash\n");
- goto out_free;
- }
- *slash = '\0';
- err = os_remove_dir(file);
- free_path(file, tmp);
-
- file = get_path(file_path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = os_remove_dir(file);
- if(err)
- goto out_free;
-
- out:
- return(err);
- out_free:
- free_path(file, tmp);
- goto out;
-}
-
-static int metafs_make_node(const char *path, int mode, int uid, int gid,
- int type, int maj, int min, struct humfs *humfs)
-{
- struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs);
- struct file_handle fh;
- char tmp[HOSTFS_BUFSIZE];
- const char *metadata_path[] = { METADATA_FILE_PATH(meta), path, NULL };
- int err;
- char buf[sizeof("mmmm uuuuuuuuuu gggggggggg x nnn mmm\n")], *file;
-
- sprintf(buf, "%d %d %d %c %d %d\n", mode & S_IRWXUGO, uid, gid, type,
- maj, min);
-
- err = -ENOMEM;
- file = get_path(metadata_path, tmp, sizeof(tmp));
- if(file == NULL)
- goto out;
-
- err = open_filehandle(file,
- of_create(of_rdwr(OPENFLAGS())), 0644, &fh);
- if(err)
- goto out_free;
-
- err = write_file(&fh, 0, buf, strlen(buf));
- if(err > 0)
- err = 0;
-
- close_file(&fh);
-
- out_free:
- free_path(file, tmp);
- out:
- return(err);
-}
-
-static int metafs_ownerships(const char *path, int *mode_out, int *uid_out,
- int *gid_out, char *type_out, int *maj_out,
- int *min_out, struct humfs *humfs)
-{
- struct file_handle fh;
- char buf[sizeof("mmmm uuuuuuuuuu gggggggggg x nnn mmm\n")];
- int err, n, mode, uid, gid, maj, min;
- char type;
-
- err = open_meta_file(path, humfs, &fh);
- if(err)
- goto out;
-
- err = os_read_file(fh.fd, buf, sizeof(buf) - 1);
- if(err < 0)
- goto out_close;
-
- buf[err] = '\0';
- err = 0;
-
- n = sscanf(buf, "%d %d %d %c %d %d", &mode, &uid, &gid, &type, &maj,
- &min);
- if(n == 3){
- maj = -1;
- min = -1;
- type = 0;
- err = 0;
- }
- else if(n != 6)
- err = -EINVAL;
-
- if(mode_out != NULL)
- *mode_out = mode;
- if(uid_out != NULL)
- *uid_out = uid;
- if(gid_out != NULL)
- *gid_out = uid;
- if(type_out != NULL)
- *type_out = type;
- if(maj_out != NULL)
- *maj_out = maj;
- if(min_out != NULL)
- *min_out = min;
-
- out_close:
- close_file(&fh);
- out:
- return(err);
-}
-
-static int metafs_change_ownerships(const char *path, int mode, int uid,
- int gid, struct humfs *humfs)
-{
- struct file_handle fh;
- char type;
- char buf[sizeof("mmmm uuuuuuuuuu gggggggggg x nnn mmm\n")];
- int err = -ENOMEM, old_mode, old_uid, old_gid, n, maj, min;
-
- err = open_meta_file(path, humfs, &fh);
- if(err)
- goto out;
-
- err = read_file(&fh, 0, buf, sizeof(buf) - 1);
- if(err < 0)
- goto out_close;
-
- buf[err] = '\0';
-
- n = sscanf(buf, "%d %d %d %c %d %d\n", &old_mode, &old_uid, &old_gid,
- &type, &maj, &min);
- if((n != 3) && (n != 6)){
- err = -EINVAL;
- goto out_close;
- }
-
- if(mode == -1)
- mode = old_mode;
- if(uid == -1)
- uid = old_uid;
- if(gid == -1)
- gid = old_gid;
-
- if(n == 3)
- sprintf(buf, "%d %d %d\n", mode & S_IRWXUGO, uid, gid);
- else
- sprintf(buf, "%d %d %d %c %d %d\n", mode & S_IRWXUGO, uid, gid,
- type, maj, min);
-
- err = write_file(&fh, 0, buf, strlen(buf));
- if(err > 0)
- err = 0;
-
- err = truncate_file(&fh, strlen(buf));
-
- out_close:
- close_file(&fh);
- out:
- return(err);
-}
-
-static int metafs_rename_file(const char *from, const char *to,
- struct humfs *humfs)
-{
- struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs);
- const char *metadata_path_from[5], *metadata_path_to[5];
- int err;
-
- err = meta_file_path(from, meta, metadata_path_from);
- if(err)
- return(err);
-
- err = meta_file_path(to, meta, metadata_path_to);
- if(err)
- return(err);
-
- return(host_rename_file(metadata_path_from, metadata_path_to));
-}
-
-static struct humfs *metafs_init_mount(char *root)
-{
- struct meta_fs *meta;
- int err = -ENOMEM;
-
- meta = kmalloc(sizeof(*meta), GFP_KERNEL);
- if(meta == NULL)
- goto out;
-
- meta->root = uml_strdup(root);
- if(meta->root == NULL)
- goto out_free_meta;
-
- return(&meta->humfs);
-
- out_free_meta:
- kfree(meta);
- out:
- return(ERR_PTR(err));
-}
-
-static void metafs_free_mount(struct humfs *humfs)
-{
- struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs);
-
- kfree(meta);
-}
-
-struct humfs_meta_ops hum_fs_meta_fs_ops = {
- .list = LIST_HEAD_INIT(hum_fs_meta_fs_ops.list),
- .name = "shadow_fs",
- .init_file = metafs_init_file,
- .open_file = metafs_open_file,
- .close_file = metafs_close_file,
- .ownerships = metafs_ownerships,
- .make_node = metafs_make_node,
- .create_file = metafs_create_file,
- .create_link = metafs_create_link,
- .remove_file = metafs_remove_file,
- .create_dir = metafs_create_directory,
- .remove_dir = metafs_remove_directory,
- .change_ownerships = metafs_change_ownerships,
- .rename_file = metafs_rename_file,
- .invisible = metafs_invisible,
- .init_mount = metafs_init_mount,
- .free_mount = metafs_free_mount,
-};
-
-static int __init init_meta_fs(void)
-{
- register_meta(&hum_fs_meta_fs_ops);
- return(0);
-}
-
-static void __exit exit_meta_fs(void)
-{
- unregister_meta(&hum_fs_meta_fs_ops);
-}
-
-__initcall(init_meta_fs);
-__exitcall(exit_meta_fs);
-
-/*
- * 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:
- */
+++ /dev/null
-/*
- * Copyright (C) 2004 Piotr Neuman (sikkh@wp.pl) and
- * Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_FS_METADATA
-#define __UM_FS_METADATA
-
-#include "linux/fs.h"
-#include "linux/list.h"
-#include "os.h"
-#include "hostfs.h"
-
-struct humfs {
- struct externfs_data ext;
- __u64 used;
- __u64 total;
- char *data;
- int mmap;
- int direct;
- struct humfs_meta_ops *meta;
-};
-
-struct humfs_file {
- struct humfs *mount;
- struct file_handle data;
- struct externfs_inode ext;
-};
-
-struct humfs_meta_ops {
- struct list_head list;
- char *name;
- struct humfs_file *(*init_file)(void);
- int (*open_file)(struct humfs_file *hf, const char *path,
- struct inode *inode, struct humfs *humfs);
- int (*create_file)(struct humfs_file *hf, const char *path, int mode,
- int uid, int gid, struct inode *inode,
- struct humfs *humfs);
- void (*close_file)(struct humfs_file *humfs);
- int (*ownerships)(const char *path, int *mode_out, int *uid_out,
- int *gid_out, char *type_out, int *maj_out,
- int *min_out, struct humfs *humfs);
- int (*make_node)(const char *path, int mode, int uid, int gid,
- int type, int major, int minor, struct humfs *humfs);
- int (*create_link)(const char *to, const char *from,
- struct humfs *humfs);
- int (*remove_file)(const char *path, struct humfs *humfs);
- int (*create_dir)(const char *path, int mode, int uid, int gid,
- struct humfs *humfs);
- int (*remove_dir)(const char *path, struct humfs *humfs);
- int (*change_ownerships)(const char *path, int mode, int uid, int gid,
- struct humfs *humfs);
- int (*rename_file)(const char *from, const char *to,
- struct humfs *humfs);
- void (*invisible)(struct humfs_file *hf);
- struct humfs *(*init_mount)(char *root);
- void (*free_mount)(struct humfs *humfs);
-};
-
-extern void register_meta(struct humfs_meta_ops *ops);
-extern void unregister_meta(struct humfs_meta_ops *ops);
-
-extern char *humfs_path(char *dir, char *file);
-extern char *humfs_name(struct inode *inode, char *prefix);
-extern struct humfs *inode_humfs_info(struct inode *inode);
-
-#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:
- */
--- /dev/null
+#ifndef _ASM_UM_CPUMASK_H
+#define _ASM_UM_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _ASM_UM_CPUMASK_H */
--- /dev/null
+#ifndef _UM_INIT_H
+#define _UM_INIT_H
+
+#ifdef notdef
+#define __init
+#define __initdata
+#define __initfunc(__arginit) __arginit
+#define __cacheline_aligned
+#endif
+
+#endif
#define SIGIO_WRITE_IRQ 11
#define TELNETD_IRQ 12
#define XTERM_IRQ 13
-#define HUMFS_IRQ 14
-
-#define LAST_IRQ HUMFS_IRQ
+
+#define LAST_IRQ XTERM_IRQ
#define NR_IRQS (LAST_IRQ + 1)
#endif
-#ifndef __UM_MODULE_H
-#define __UM_MODULE_H
+#ifndef __UM_MODULE_I386_H
+#define __UM_MODULE_I386_H
/* UML is simple */
struct mod_arch_specific
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Rel Elf32_Rel
+#define Elf_Rela Elf32_Rela
+#define ELF_R_TYPE(X) ELF32_R_TYPE(X)
+#define ELF_R_SYM(X) ELF32_R_SYM(X)
#endif
/*
- * Copyright (C) 2000 - 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
*/
extern unsigned long task_size;
-#undef TASK_SIZE
#define TASK_SIZE (task_size)
/* This decides where the kernel will search for a free chunk of vm
--- /dev/null
+#ifndef __UM_SMPLOCK_H
+#define __UM_SMPLOCK_H
+
+#include "asm/arch/smplock.h"
+
+#endif
--- /dev/null
+#ifndef __UM_SPINLOCK_H
+#define __UM_SPINLOCK_H
+
+#include "asm/arch/spinlock.h"
+
+#endif
extern struct page *
FASTCALL(__alloc_pages(unsigned int, unsigned int, struct zonelist *));
-static inline struct page * alloc_pages_node(int nid, unsigned int gfp_mask,
- unsigned int order)
+
+static inline struct page *alloc_pages_node(int nid, unsigned int gfp_mask,
+ unsigned int order)
{
if (unlikely(order >= MAX_ORDER))
return NULL;
- return __alloc_pages(gfp_mask, order,
+ return __alloc_pages(gfp_mask, order,
NODE_DATA(nid)->node_zonelists + (gfp_mask & GFP_ZONEMASK));
}
+++ /dev/null
-/*
- * include/linux/ghash.h -- generic hashing with fuzzy retrieval
- *
- * (C) 1997 Thomas Schoebel-Theuer
- *
- * The algorithms implemented here seem to be a completely new invention,
- * and I'll publish the fundamentals in a paper.
- */
-
-#ifndef _GHASH_H
-#define _GHASH_H
-/* HASHSIZE _must_ be a power of two!!! */
-
-
-#define DEF_HASH_FUZZY_STRUCTS(NAME,HASHSIZE,TYPE) \
-\
-struct NAME##_table {\
- TYPE * hashtable[HASHSIZE];\
- TYPE * sorted_list;\
- int nr_entries;\
-};\
-\
-struct NAME##_ptrs {\
- TYPE * next_hash;\
- TYPE * prev_hash;\
- TYPE * next_sorted;\
- TYPE * prev_sorted;\
-};
-
-#define DEF_HASH_FUZZY(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\
-\
-LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
-{\
- int ix = HASHFN(elem->KEY);\
- TYPE ** base = &tbl->hashtable[ix];\
- TYPE * ptr = *base;\
- TYPE * prev = NULL;\
-\
- tbl->nr_entries++;\
- while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {\
- base = &ptr->PTRS.next_hash;\
- prev = ptr;\
- ptr = *base;\
- }\
- elem->PTRS.next_hash = ptr;\
- elem->PTRS.prev_hash = prev;\
- if(ptr) {\
- ptr->PTRS.prev_hash = elem;\
- }\
- *base = elem;\
-\
- ptr = prev;\
- if(!ptr) {\
- ptr = tbl->sorted_list;\
- prev = NULL;\
- } else {\
- prev = ptr->PTRS.prev_sorted;\
- }\
- while(ptr) {\
- TYPE * next = ptr->PTRS.next_hash;\
- if(next && KEYCMP(next->KEY, elem->KEY)) {\
- prev = ptr;\
- ptr = next;\
- } else if(KEYCMP(ptr->KEY, elem->KEY)) {\
- prev = ptr;\
- ptr = ptr->PTRS.next_sorted;\
- } else\
- break;\
- }\
- elem->PTRS.next_sorted = ptr;\
- elem->PTRS.prev_sorted = prev;\
- if(ptr) {\
- ptr->PTRS.prev_sorted = elem;\
- }\
- if(prev) {\
- prev->PTRS.next_sorted = elem;\
- } else {\
- tbl->sorted_list = elem;\
- }\
-}\
-\
-LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
-{\
- TYPE * next = elem->PTRS.next_hash;\
- TYPE * prev = elem->PTRS.prev_hash;\
-\
- tbl->nr_entries--;\
- if(next)\
- next->PTRS.prev_hash = prev;\
- if(prev)\
- prev->PTRS.next_hash = next;\
- else {\
- int ix = HASHFN(elem->KEY);\
- tbl->hashtable[ix] = next;\
- }\
-\
- next = elem->PTRS.next_sorted;\
- prev = elem->PTRS.prev_sorted;\
- if(next)\
- next->PTRS.prev_sorted = prev;\
- if(prev)\
- prev->PTRS.next_sorted = next;\
- else\
- tbl->sorted_list = next;\
-}\
-\
-LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\
-{\
- int ix = hashfn(pos);\
- TYPE * ptr = tbl->hashtable[ix];\
- while(ptr && KEYCMP(ptr->KEY, pos))\
- ptr = ptr->PTRS.next_hash;\
- if(ptr && !KEYEQ(ptr->KEY, pos))\
- ptr = NULL;\
- return ptr;\
-}\
-\
-LINKAGE TYPE * find_##NAME##_hash_fuzzy(struct NAME##_table * tbl, KEYTYPE pos)\
-{\
- int ix;\
- int offset;\
- TYPE * ptr;\
- TYPE * next;\
-\
- ptr = tbl->sorted_list;\
- if(!ptr || KEYCMP(pos, ptr->KEY))\
- return NULL;\
- ix = HASHFN(pos);\
- offset = HASHSIZE;\
- do {\
- offset >>= 1;\
- next = tbl->hashtable[(ix+offset) & ((HASHSIZE)-1)];\
- if(next && (KEYCMP(next->KEY, pos) || KEYEQ(next->KEY, pos))\
- && KEYCMP(ptr->KEY, next->KEY))\
- ptr = next;\
- } while(offset);\
-\
- for(;;) {\
- next = ptr->PTRS.next_hash;\
- if(next) {\
- if(KEYCMP(next->KEY, pos)) {\
- ptr = next;\
- continue;\
- }\
- }\
- next = ptr->PTRS.next_sorted;\
- if(next && KEYCMP(next->KEY, pos)) {\
- ptr = next;\
- continue;\
- }\
- return ptr;\
- }\
- return NULL;\
-}
-
-/* LINKAGE - empty or "static", depending on whether you want the definitions to
- * be public or not
- * NAME - a string to stick in names to make this hash table type distinct from
- * any others
- * HASHSIZE - number of buckets
- * TYPE - type of data contained in the buckets - must be a structure, one
- * field is of type NAME_ptrs, another is the hash key
- * PTRS - TYPE must contain a field of type NAME_ptrs, PTRS is the name of that
- * field
- * KEYTYPE - type of the key field within TYPE
- * KEY - name of the key field within TYPE
- * KEYCMP - pointer to function that compares KEYTYPEs to each other - the
- * prototype is int KEYCMP(KEYTYPE, KEYTYPE), it returns zero for equal,
- * non-zero for not equal
- * HASHFN - the hash function - the prototype is int HASHFN(KEYTYPE),
- * it returns a number in the range 0 ... HASHSIZE - 1
- * Call DEF_HASH_STRUCTS, define your hash table as a NAME_table, then call
- * DEF_HASH.
- */
-
-#define DEF_HASH_STRUCTS(NAME,HASHSIZE,TYPE) \
-\
-struct NAME##_table {\
- TYPE * hashtable[HASHSIZE];\
- int nr_entries;\
-};\
-\
-struct NAME##_ptrs {\
- TYPE * next_hash;\
- TYPE * prev_hash;\
-};
-
-#define DEF_HASH(LINKAGE,NAME,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,HASHFN)\
-\
-LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
-{\
- int ix = HASHFN(elem->KEY);\
- TYPE ** base = &tbl->hashtable[ix];\
- TYPE * ptr = *base;\
- TYPE * prev = NULL;\
-\
- tbl->nr_entries++;\
- while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {\
- base = &ptr->PTRS.next_hash;\
- prev = ptr;\
- ptr = *base;\
- }\
- elem->PTRS.next_hash = ptr;\
- elem->PTRS.prev_hash = prev;\
- if(ptr) {\
- ptr->PTRS.prev_hash = elem;\
- }\
- *base = elem;\
-}\
-\
-LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
-{\
- TYPE * next = elem->PTRS.next_hash;\
- TYPE * prev = elem->PTRS.prev_hash;\
-\
- tbl->nr_entries--;\
- if(next)\
- next->PTRS.prev_hash = prev;\
- if(prev)\
- prev->PTRS.next_hash = next;\
- else {\
- int ix = HASHFN(elem->KEY);\
- tbl->hashtable[ix] = next;\
- }\
-}\
-\
-LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\
-{\
- int ix = HASHFN(pos);\
- TYPE * ptr = tbl->hashtable[ix];\
- while(ptr && KEYCMP(ptr->KEY, pos))\
- ptr = ptr->PTRS.next_hash;\
- return ptr;\
-}
-
-#endif
*/
typedef int (*shrinker_t)(int nr_to_scan, unsigned int gfp_mask);
-asmlinkage long do_mprotect(struct mm_struct *mm, unsigned long start,
- size_t len, unsigned long prot);
-
/*
* Add an aging callback. The int is the number of 'seeks' it takes
* to recreate one of the objects that these functions age.
return get_unmapped_area_prot(file, addr, len, pgoff, flags, 0);
}
-extern unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file *file,
- unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flag,
- unsigned long pgoff);
+extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long prot,
+ unsigned long flag, unsigned long pgoff);
static inline unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
if ((offset + PAGE_ALIGN(len)) < offset)
goto out;
if (!(offset & ~PAGE_MASK))
- ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flag,
- offset >> PAGE_SHIFT);
+ ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
out:
return ret;
}
+++ /dev/null
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __PROC_MM_H
-#define __PROC_MM_H
-
-#include "linux/sched.h"
-
-#define MM_MMAP 54
-#define MM_MUNMAP 55
-#define MM_MPROTECT 56
-#define MM_COPY_SEGMENTS 57
-
-struct mm_mmap {
- unsigned long addr;
- unsigned long len;
- unsigned long prot;
- unsigned long flags;
- unsigned long fd;
- unsigned long offset;
-};
-
-struct mm_munmap {
- unsigned long addr;
- unsigned long len;
-};
-
-struct mm_mprotect {
- unsigned long addr;
- unsigned long len;
- unsigned int prot;
-};
-
-struct proc_mm_op {
- int op;
- union {
- struct mm_mmap mmap;
- struct mm_munmap munmap;
- struct mm_mprotect mprotect;
- int copy_segments;
- } u;
-};
-
-extern struct mm_struct *proc_mm_get_mm(int fd);
-
-#endif
obj-$(CONFIG_OOM_PANIC) += oom_panic.o
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o
-obj-$(CONFIG_PROC_MM) += proc_mm.o
obj-$(CONFIG_NUMA) += mempolicy.o
obj-$(CONFIG_SHMEM) += shmem.o
obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
* The caller must hold down_write(current->mm->mmap_sem).
*/
-unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file,
- unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long pgoff)
+unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
+ unsigned long len, unsigned long prot,
+ unsigned long flags, unsigned long pgoff)
{
+ struct mm_struct * mm = current->mm;
struct vm_area_struct * vma, * prev;
struct inode *inode;
unsigned int vm_flags;