linux-um archives
 help / color / mirror / Atom feed
From: "Steve Schmidtke" <steve_schmidtke@hotmail.com>
To: User-mode-linux-devel@lists.sourceforge.net
Subject: [uml-devel] filemap feature 2.4.22-5um
Date: Tue, 14 Oct 2003 03:54:18 +0000	[thread overview]
Message-ID: <BAY7-F67zjLYL23VZvZ0000e11f@hotmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 4543 bytes --]

This patch adds filemap support to 2.4.22-5um.  The function of this patch 
is an awkard and convoluted solution to an arcane problem.  Unless you know 
this is what you need, you may just want to skip this post.

Filemaping is a method of mapping open file descriptors to arbitrary file 
names within a UML.  Once a file name has been mapped, all UML file requests 
on that name act upon the open file descriptor.  The main purpose of filemap 
is to support empty chroot environments, allowing the UML to access files, 
such as /proc/cpuinfo and virtual memory files, without requiring those 
files to be present within the chroot directory.

The filemap boot string syntax lookes like this:

  filemap=<table>,<table specific syntax>

There are two tables available, "file" and "vm".  "file" type filemaps 
handle fd/filename pairs, while "vm" type filemaps handle pools of fd's that 
represent virtual memory files.

For example, a "file" table boot string may look like this:

  filemap=file,12,/proc/cpuinfo

which redirects the UML to file descriptor 12 when accessing the file
/proc/cpuinfo.  In this case, file descriptor 12 must be opened beforehand, 
possibly like this on the UMLs command line:

  12</proc/cpuinfo

A "vm" table filemap boot string may look like this:

  filemap=vm,20-23

which will set up a pool of file descriptors (20, 21, 22, and 23) to be mete 
out to the UML as it requests virtual memory files.

Here are some example command lines using filemaps:

  chroot /home/uml /bin/linux mem=32M \
  filemap=file,11,/proc/cpuinfo 11</proc/cpuinfo

The above line tells the chrooted UML to use file descriptor 11 whenever 
accessing /proc/cpuinfo (which it only ever reads).

  chroot /cdrom /linux mem=16M filemap=vm,20-21 \
  20<>/dev/shm/vm1 21<>/dev/shm/vm2

This invocation tells the chrooted UML to use file descriptors 20 and 21 for 
(some of) its virtual memory files.  How do you know how many to specify?  
The number is proportional to how much memory you have given the UML. Start 
with booting the UML with a bunch of zero length files, and review how many 
end up with non-zero file sizes.  Adjust to suit.  Note the above examples 
read+write redirection on the vm files.

  umlwrap -bind=22,/dev/shm/mconsole1 -dir=/home/uml -- \
  /bin/linux mem=48M uml_dir=/uml/ umid=um1 filemap=22,/uml/um1/pid \
  22</dev/shm/pid filemap=22,/uml/um1/mconsole

Here, a hypothetical chroot helper opens a bound unix socket on file 
descriptor 21.  The chrooted UML will pick up the fd as its mconsole socket 
(by way of a crafty command line).  Note that the method used to tell 
uml_mconsole to open a socket in /dev/shm/ is beyond the scope of this 
example.  Also note that the umid pid file has been filemaped as well -- the 
umid directory does not have to exist for things to work.

In fact, there is no writable media necessary within the chroot to run UML 
at all.  The only file necessary to be present is the staticly linked linux 
binary.

One final example to put it all together:

  umlwrap -bind=15,/dev/shm/mconsole-$$ -connect=17,/tmp/uml.ctl \
  -dir=/home/uml -user=guest -- /bin/linux mem=64M \
  uml_dir=/uml/ umid=um$$ ubd0=/disk.cow,/disk.dat \
  eth0=daemon con=null con0=fd:0,fd:1 \
  filemap=file,10,/proc/cpuinfo 10</proc/cpuinfo \
  filemap=file,11,/disk.dat 11</mnt/backing.dat \
  filemap=file,12,/disk.cow 12<>/home/uml/cow-$$.cow \
  filemap=file,15,/uml/um$$/mconsole \
  filemap=file,16,/uml/um$$/pid 16</dev/shm/pid-$$ \
  filemap=file,17,/tmp/uml.ctl \
  filemap=vm,20-23 20<>/dev/shm/vm-$$.0 21<>/dev/shm/vm-$$.1 \
  22<>/dev/shm/vm-$$.2 23<>/dev/shm/vm-$$.3 \

Ugly, isn't it.  If you find a nicer way to do this let me know.  Notice how 
networking is carried out here via the daemon transport, connecting to the 
/tmp/uml.ctl socket run by uml_switch.  Your mileage may vary.

Other filemap issues I know about:

- Reboots may not work as expected.  Best is to shutdown and restart.
- A given file may be corrupted if access to it is not serialized.
- Hostfs accessed files are NOT filemapped.  See above.
- Directories cannot be filemapped.
- Vm files are visible and persistent!  Bug or feature:  you decide.
- Notify feature of mconsole is not supported.  Why so complicated?
- You can bet this patch won't make it into Jeff's official source tree.  
I'm cool with that.

Enjoy!

Steve Schmidtke

_________________________________________________________________
The new MSN 8: advanced junk mail protection and 2 months FREE*  
http://join.msn.com/?page=features/junkmail

[-- Attachment #2: filemap5-01.diff --]
[-- Type: application/octet-stream, Size: 21754 bytes --]

diff -Naur linux-2.4.22-5um.orig/arch/um/include/filemap.h linux-2.4.22-5um.new/arch/um/include/filemap.h
--- linux-2.4.22-5um.orig/arch/um/include/filemap.h	Wed Dec 31 19:00:00 1969
+++ linux-2.4.22-5um.new/arch/um/include/filemap.h	Thu Sep 25 20:29:17 2003
@@ -0,0 +1,13 @@
+/* 
+ * Copyright (C) 2003 Steve Schmidtke 
+ * Licensed under the GPL
+ */
+
+#ifndef __FILEMAP_H__
+#define __FILEMAP_H__
+
+extern int filemap_access(const char* table_name, const char* file_name);
+extern int filemap_aquire(const char* table_name, const char* file_name);
+extern int filemap_release(const char* table_name, int fd);
+
+#endif
diff -Naur linux-2.4.22-5um.orig/arch/um/kernel/Makefile linux-2.4.22-5um.new/arch/um/kernel/Makefile
--- linux-2.4.22-5um.orig/arch/um/kernel/Makefile	Thu Sep 25 19:29:45 2003
+++ linux-2.4.22-5um.new/arch/um/kernel/Makefile	Thu Sep 25 20:29:17 2003
@@ -11,7 +11,7 @@
 	sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
 	syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \
 	time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \
-	um_arch.o umid.o user_syms.o user_util.o
+	um_arch.o umid.o user_syms.o user_util.o filemap.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
 obj-$(CONFIG_GPROF) += gprof_syms.o
@@ -29,7 +29,7 @@
 # building anything in export-objs
 
 USER_OBJS = $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \
-	process.o tempfile.o time.o umid.o user_util.o 
+	process.o tempfile.o time.o umid.o user_util.o filemap.o
 
 DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__
 DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__
diff -Naur linux-2.4.22-5um.orig/arch/um/kernel/filemap.c linux-2.4.22-5um.new/arch/um/kernel/filemap.c
--- linux-2.4.22-5um.orig/arch/um/kernel/filemap.c	Wed Dec 31 19:00:00 1969
+++ linux-2.4.22-5um.new/arch/um/kernel/filemap.c	Thu Sep 25 20:29:17 2003
@@ -0,0 +1,655 @@
+/* 
+ * Copyright (C) 2003 Steve Schmidtke 
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h> 
+#include <string.h> 
+#include <unistd.h> 
+#include <errno.h> 
+#include "init.h"
+#include "sys/types.h"
+#include "unistd.h"
+#include "fcntl.h"
+
+#define STRFD_ISEND(c)  ((c == '\0') || (c == ',') || (c == '-'))
+
+struct filemap_entry {
+	struct filemap_entry* next;
+	char* name;
+	int fd;
+	int count;
+	int cf; /* initial close on exec flag */
+};  
+
+struct filemap_ops {
+	int (*parse)(void* table, char* str);
+	int (*access)(void* table, char* filename);
+	int (*aquire)(void* table, char* filename);
+	int (*release)(void* table, int fd);
+	int (*shutdown)(void* table);
+};
+
+struct filemap_table {
+	char* name;
+	struct filemap_entry* entries;
+	struct filemap_ops* ops;
+};
+
+static struct filemap_entry* filemap_entry_alloc(void)
+{
+	return(malloc(sizeof(struct filemap_entry)));
+}
+
+/* FIXME: the os_* versions of these routines below may recurse? */
+
+static void seek_file(int fd, off_t offset)
+{
+	lseek(fd, offset, SEEK_SET);
+}
+
+static int get_close_on_exec(int fd, int* close_on_exec)
+{
+	int ret;
+
+	do {
+		ret = fcntl(fd, F_GETFD);
+	} while(ret<0 && errno==EINTR) ;
+
+	if(ret < 0)
+		return(-errno);
+
+	*close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0;
+
+	return(ret);
+}
+
+static int set_close_on_exec(int fd, int close_on_exec)
+{
+	int flag, err;
+
+	if(close_on_exec) flag = FD_CLOEXEC;
+	else flag = 0;
+
+	do {
+		err = fcntl(fd, F_SETFD, flag);
+	} while(err<0 && errno==EINTR) ;
+
+	if(err < 0)
+		return(-errno);
+
+	return(err);
+}
+
+/*
+ * Add a fd (and filename) to a table in the db.
+ */
+static int filemap_add_entry(struct filemap_table* table,
+    int fdesc, char* file_name)
+{
+	struct filemap_entry* entry;
+	struct filemap_entry* dup;
+	int coeflag;
+	int err;
+
+	if((table == NULL) || (fdesc < 0)) {
+		return(-EINVAL);
+	}
+
+	dup = NULL;
+	for(entry = table->entries; entry; entry = entry->next) {
+		if(!dup && (fdesc == entry->fd)) {
+			dup = entry;
+		}
+	}
+
+	if(dup) {
+		coeflag = dup->cf;
+	} else {
+		err = get_close_on_exec(fdesc, &coeflag);
+		if(err < 0) {
+			printk("filemap_add_entry: get close-on-exec flag"
+				" failed errno=%d fd=%d name=%s\n",
+				err, fdesc, file_name);
+			return(err);
+		}
+
+		/* by default, exec calls should close filemaps */ 
+		err = set_close_on_exec(fdesc, 1);
+		if(err < 0) {
+			printk("filemap_add_entry: set close-on-exec flag"
+				" failed errno=%d fd=%d name=%s\n",
+				err, fdesc, file_name);
+			return(err);
+		}
+	}
+
+	entry = filemap_entry_alloc();
+	if(entry == NULL) {
+		printk("filemap_add_entry: alloc failed fd=%d, name=%s\n",
+			fdesc, file_name);
+		return(-ENOMEM);
+	}
+
+	printk("installing filemap: table=%s fd=%d, c-o-e=%d name=%s\n",
+		table->name, fdesc, coeflag, file_name);
+
+	*entry = ((struct filemap_entry) {
+			.next	= table->entries,
+			.name	= file_name,
+			.fd	= fdesc,
+			.count	= 0,
+			.cf	= coeflag
+	});
+
+	table->entries = entry;
+
+	return(0);
+}
+
+/*
+ * Find the matching filename in the db and return the filemap entry. 
+ */
+static struct filemap_entry* filemap_lookup_name(struct filemap_table* table,
+    const char* file_name)
+{
+	struct filemap_entry* entry;
+
+	for(entry = table->entries; entry; entry = entry->next) {
+		if(strcmp(file_name, entry->name) == 0) {
+			return(entry);
+		}
+	}
+
+	return(NULL);
+}
+
+/*
+ * Find a fresh file descriptor in a file pool
+ */
+static struct filemap_entry* filemap_lookup_unused(struct filemap_table* table)
+{
+	struct filemap_entry* entry;
+
+	for(entry = table->entries; entry; entry = entry->next) {
+		if(entry->count == 0) {
+			return(entry);
+		}
+	}
+
+	return(NULL);
+}
+
+/*
+ * Find a matching fd in the db and return a filemap entry. 
+ */
+static struct filemap_entry* filemap_lookup_fd(struct filemap_table* table,
+    const int fd)
+{
+	struct filemap_entry* entry;
+
+	for(entry = table->entries; entry; entry = entry->next) {
+		if(fd == entry->fd) {
+			return(entry);
+		}
+	}
+
+	return(NULL);
+}
+
+/*
+ * set the filemapped file as pristine as possible
+ */
+static int filemap_scrub(struct filemap_entry* entry)
+{
+	int err;
+
+	err = set_close_on_exec(entry->fd, entry->cf);
+	if(err < 0) {
+		printk("filemap_scrub: reset close-on-exec flag failed"
+			" err=%d fd=%d c-o-e=%d name=%s\n",
+			err, entry->fd, entry->cf, entry->name);
+		return(err);
+	}
+
+	return(0);
+}
+
+/* 
+ * Return a disposable file descriptor for the one provided.
+ * dup() is used to guard against a close of the fd that was passed
+ * in.  This is not ideal as concurrent uses of the same file may
+ * wreak havoc with the shared position pointer, etc. between the
+ * duplicated file descriptors.
+ */ 
+static int filemap_newfd(int oldfd)
+{
+	int newfd, err;
+
+	if(oldfd < 0)
+		return(-EINVAL);
+
+	do {
+		newfd = dup(oldfd);
+	} while(newfd<0 && errno==EINTR) ;
+
+	if(newfd < 0)
+		return(-errno);
+
+	err = set_close_on_exec(newfd, 0);
+	if(err < 0) {
+		printk("filemap_newfd: clear close-on-exec flag failed"
+			" err=%d fd=%d\n", err, newfd);
+		return(err);
+	}
+
+	return(newfd);
+}
+
+/*
+ * parse the setup string for a file descriptor (number) and
+ * return * a pointer on the next argument in the setup string.
+ */
+static __init char* set_fdesc(char* str, int* fd)
+{
+	char* end;
+	int num;
+
+	if((str==NULL) || (*str=='\0'))
+		return(NULL);
+
+	if(*str == ',')
+		return(str);
+
+	num = strtoul(str, &end, 10);
+	if((end == str) || !STRFD_ISEND(*end)) {
+		printk("filemap: set_fd - invalid value '%s'\n", str);
+		goto endout;
+	}
+
+	*fd = num;
+
+endout:
+	while(!STRFD_ISEND(*end)) end++;
+	if(*end == '\0')
+		 return(NULL);
+
+	return(end);
+}
+
+
+/************************************************
+ *** Routines to support 'pool' type filemaps ***
+ ************************************************/
+
+static int fm_pool_parse(void* data, char* str)
+{
+	struct filemap_table* table = data;
+	char* end;
+	unsigned int count;
+	int fdfirst, fdlast, err;
+
+	end = set_fdesc(str, &fdfirst);
+	if(*end == '-') {
+		end = set_fdesc(end+1, &fdlast);
+	} else {
+		fdlast = fdfirst;
+	}
+
+	/* NOTE: add_entry loop must interate first -> last *inclusive* */
+
+	if(fdfirst < fdlast) count = fdlast - fdfirst;
+	else count = fdfirst - fdlast;
+
+	do { 
+		err = filemap_add_entry(table, fdfirst, NULL);
+		if(err < 0) {
+			printk("WARNING: filemap error %d on '%s':'%s'\n",
+			    err, table->name, str);
+			return(err);
+		}
+
+		if(fdfirst < fdlast) fdfirst++;
+		else fdfirst--;
+	} while(count--) ;
+
+	return(0);
+}
+
+static int fm_pool_access(void* data, char* file_name)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	entry = filemap_lookup_unused(table);
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	entry->count++;
+
+	return(entry->fd);
+}
+
+static int fm_pool_aquire(void* data, char* file_name)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+	int fd;
+
+	entry = filemap_lookup_unused(table);
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	fd = filemap_newfd(entry->fd);
+	if(fd < 0)
+		return(fd);
+
+	entry->count++;
+
+	/* make sure this "new" file is rewound */
+	seek_file(fd, 0);
+
+	return(fd);
+}
+
+static int fm_pool_release(void* data, int fd)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	/* the lookup_fd will always fail if the returned fd from _aquire is
+	 * a dup of the real fd.  This is OK: the caller will close the dup */
+	entry=filemap_lookup_fd(table, fd); 
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	if(entry->count > 0)
+		entry->count--;
+
+	return(0);
+}
+
+static int fm_pool_shutdown(void* data)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	for(entry = table->entries; entry; entry = entry->next) {
+		filemap_scrub(entry);
+	}
+
+	return(0);
+}
+
+static struct filemap_ops fm_ops_pool = {
+	.parse        = fm_pool_parse,
+	.access       = fm_pool_access,
+	.aquire       = fm_pool_aquire,
+	.release      = fm_pool_release,
+	.shutdown     = fm_pool_shutdown,
+};
+
+
+/************************************************
+ *** Routines to support 'file' type filemaps ***
+ ************************************************/
+
+static int fm_file_parse(void* data, char* str)
+{
+	struct filemap_table* table = data;
+	char* file_name;
+	int fd, err;
+
+	file_name = set_fdesc(str, &fd);
+	if(*file_name == ',')
+		file_name++;
+
+	err = filemap_add_entry(table, fd, file_name);
+	if(err < 0) {
+		printk("WARNING: filemap error %d on '%s':'%s'\n",
+		    err, table->name, str);
+		return(err);
+	}
+
+	return(0);
+}
+
+static int fm_file_access(void* data, char* file_name)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	entry = filemap_lookup_name(table, file_name);
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	return(entry->fd);
+}
+
+static int fm_file_aquire(void* data, char* file_name)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+	int fd;
+
+	entry = filemap_lookup_name(table, file_name);
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	fd = filemap_newfd(entry->fd);
+	if(fd < 0)
+		return(fd);
+
+	/* make sure this "new" file is rewound */
+	seek_file(fd, 0);
+
+	return(fd);
+}
+
+static int fm_file_release(void* data, int fd)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	/* the lookup_fd will always fail if the returned fd from _aquire is
+	 * a dup of the real fd.  This is OK: the caller will close the dup */
+	entry = filemap_lookup_fd(table, fd);
+
+	if(entry == NULL)
+		return(-ENOENT);
+
+	return(0);
+}
+
+static int fm_file_shutdown(void* data)
+{
+	struct filemap_table* table = data;
+	struct filemap_entry* entry;
+
+	for(entry = table->entries; entry; entry = entry->next) {
+		filemap_scrub(entry);
+	}
+
+	return(0);
+}
+
+static struct filemap_ops fm_ops_file = {
+	.parse        = fm_file_parse,
+	.access       = fm_file_access,
+	.aquire       = fm_file_aquire,
+	.release      = fm_file_release,
+	.shutdown     = fm_file_shutdown,
+};
+
+
+/***********************
+ *** Filemap Tables  ***
+ ***********************/
+
+static struct filemap_table filemap_tables[] = {
+	{
+		.name    = "file",
+		.entries = NULL,
+		.ops     = &fm_ops_file,
+	},
+	{
+		.name    = "vm",
+		.entries = NULL,
+		.ops     = &fm_ops_pool,
+	},
+};
+
+static struct filemap_table* filemap_get_table(const char* table_name)
+{
+	struct filemap_table* table;
+	int i;
+
+	i = 0;
+
+	while(i < sizeof(filemap_tables)/sizeof(filemap_tables[0])) {
+		table = &filemap_tables[i];
+
+		if(strcmp(table_name, table->name) == 0)
+			return(table);
+
+		i++;
+	}
+
+	return(NULL);
+}
+
+
+/**********************************
+ *** Filemap Interface Routines ***
+ **********************************/
+
+/*
+ * Return THE file descriptor for the given filename from the db table.
+ * This is a raw interface for functions, like stat() wrappers that promise
+ * not to do IO, close the fd, or otherwise fiddle with the file state.
+ */
+int filemap_access(const char* table_name, char* file_name)
+{
+	struct filemap_table* table;
+	int fd;
+
+	table = filemap_get_table(table_name);
+
+	if(table == NULL) {
+		printk("ERROR: unknown filemap table '%s'\n", table_name);
+		return(0);
+	}
+
+	fd = table->ops->access(table, file_name);
+
+	return(fd);
+}
+
+/*
+ * Return A NEW file descriptor for the given filename from the db.
+ * Assume the modes of the file descriptor was set up to match what is
+ * being asked for.
+ */
+int filemap_aquire(const char* table_name, char* file_name)
+{
+	struct filemap_table* table;
+	int fd;
+
+	table = filemap_get_table(table_name);
+
+	if(table == NULL) {
+		printk("ERROR: unknown filemap table '%s'\n", table_name);
+		return(0);
+	}
+
+	fd = table->ops->aquire(table, file_name);
+
+	return(fd);
+}
+
+/*
+ * "Release" the file descriptor.  Do nothing - if not in the db,
+ * return -ENOENT.  The caller would want to use the close() system
+ * call on the fd in that event.
+ */
+int filemap_release(const char* table_name, const int fd)
+{
+	struct filemap_table* table;
+	int err;
+
+	table = filemap_get_table(table_name);
+
+	if(table == NULL) {
+		printk("ERROR: unknown filemap table '%s'\n", table_name);
+		return(-ENOENT); /* the caller expects ENOENT */ 
+	}
+
+	err = table->ops->release(table, fd);
+
+	return(err);
+}
+
+/*
+ * Do any table cleanup necessary before power cycle
+ */
+static void filemap_shutdown(void)
+{
+	struct filemap_table* table;
+	int i;
+
+	i = 0;
+
+	while(i < sizeof(filemap_tables)/sizeof(filemap_tables[0]))
+	{
+		table = &filemap_tables[i];
+
+		table->ops->shutdown(table);
+
+		i++;
+	}
+}
+
+__uml_exitcall(filemap_shutdown);
+
+static int __init parse_filemap(char* str, int* add)
+{
+	struct filemap_table* table;
+	char* table_name;
+	int err;
+
+	*add = 0;
+
+	table_name = str;
+	while(*str && *str != ',') str++;
+	if(*str == ',') *str++ = '\0';
+
+	table = filemap_get_table(table_name);
+
+	if(table == NULL) {
+		printk("ERROR: unknown filemap table '%s'\n", table_name);
+		return(0);
+	}
+
+	err = table->ops->parse(table, str);
+	if(err < 0) {
+		printk("ERROR: filemap parse error %d on '%s':'%s'\n",
+		    err, table_name, str);
+		return(0);
+	}
+
+	return(0);
+}
+
+__uml_setup("filemap=", parse_filemap,
+"filemap=<table>,<fd>[-<fd>][,<filename>]\n"
+"    Map <filename> to <fd> (already opened) into db table named <table>.\n"
+"    Common tables: file=normal files, vm=virtual memory. Examples for bash:\n"
+"    ./linux ubd0=fs.cow,fs.dat filemap=file,10,fs.dat 10</cdrom2/fs.dat\n"
+"    ./linux filemap=file,11,/proc/cpuinfo 11</proc/cpuinfo\n"
+"    ./linux filemap=vm,20-21 20<>/dev/shm/vm-$$.1 21<>/dev/shm/vm-$$.2\n"
+);
diff -Naur linux-2.4.22-5um.orig/arch/um/kernel/mem_user.c linux-2.4.22-5um.new/arch/um/kernel/mem_user.c
--- linux-2.4.22-5um.orig/arch/um/kernel/mem_user.c	Thu Sep 25 19:29:45 2003
+++ linux-2.4.22-5um.new/arch/um/kernel/mem_user.c	Thu Sep 25 20:29:17 2003
@@ -47,6 +47,8 @@
 #include "tempfile.h"
 #include "kern_constants.h"
 
+#include "filemap.h"
+
 extern struct mem_region physmem_region;
 
 #define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
@@ -56,6 +58,12 @@
 	int fd, err;
 	char zero;
 
+	fd = filemap_aquire("vm",NULL);
+	if(fd >= 0) {
+		ftruncate(fd, len); /* use 0 instead of len to zero contents */
+		goto sizefile;
+	}
+
 	fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
 	if(fd < 0) {
 		os_print_error(fd, "make_tempfile");
@@ -66,6 +74,8 @@
 		os_print_error(err, "change_mode");
 		exit(1);
 	}
+
+sizefile:
 	err = os_seek_file(fd, len);
 	if(err < 0){
 		os_print_error(err, "seek_file");
diff -Naur linux-2.4.22-5um.orig/arch/um/kernel/umid.c linux-2.4.22-5um.new/arch/um/kernel/umid.c
--- linux-2.4.22-5um.orig/arch/um/kernel/umid.c	Thu Sep 25 19:29:45 2003
+++ linux-2.4.22-5um.new/arch/um/kernel/umid.c	Thu Sep 25 20:29:17 2003
@@ -19,6 +19,8 @@
 #include "user_util.h"
 #include "choose-mode.h"
 
+#include "filemap.h"
+
 #define UMID_LEN 64
 #define UML_DIR "~/.uml/"
 
@@ -68,8 +70,24 @@
 {
 	int n;
 
-	if(!umid_inited && make_umid(printk)) return(-1);
+	if(umid_inited) {
+		char path[MAXPATHLEN + 1];   /* XXX use buf instead? */
+
+		n = snprintf(path, sizeof(path), "%s%s/%s",
+			     uml_dir, umid, name);
+		if((n < 0) || (n >= sizeof(path)))
+			return(-1);
+
+		/* just test for existence in the filemap file table */
+		if(filemap_access("file", path) >= 0) {
+			goto handle_name;
+		}
+	} 
+
+	if(make_umid(printk))
+		return(-1);
 
+handle_name:
 	n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
 	if(n > len){
 		printk("umid_file_name : buffer too short\n");
diff -Naur linux-2.4.22-5um.orig/arch/um/os-Linux/file.c linux-2.4.22-5um.new/arch/um/os-Linux/file.c
--- linux-2.4.22-5um.orig/arch/um/os-Linux/file.c	Thu Sep 25 19:29:45 2003
+++ linux-2.4.22-5um.new/arch/um/os-Linux/file.c	Thu Sep 25 20:29:17 2003
@@ -19,6 +19,8 @@
 #include "user.h"
 #include "kern_util.h"
 
+#include "filemap.h"
+
 static void copy_stat(struct uml_stat *dst, struct stat64 *src)
 {
 	*dst = ((struct uml_stat) {
@@ -57,12 +59,22 @@
 int os_stat_file(const char *file_name, struct uml_stat *ubuf)
 {
 	struct stat64 sbuf;
-	int err;
+	int fd, err;
+
+	fd = filemap_access("file", file_name);
+	if(fd >= 0) {
+		do {
+			err = fstat64(fd, &sbuf);
+		} while((err < 0) && (errno == EINTR)) ;
+
+		goto did_stat;
+	}
 
 	do {
 		err = stat64(file_name, &sbuf);
 	} while((err < 0) && (errno == EINTR)) ;
 
+did_stat:
 	if(err < 0) 
 		return(-errno);
 
@@ -74,6 +86,26 @@
 int os_access(const char* file, int mode)
 {
 	int amode, err;
+	int fd, flags;
+
+	fd = filemap_access("file", file);
+	if(fd >= 0) {
+		do {
+			flags = fcntl(fd, F_GETFL);
+		} while((flags < 0) && (errno == EINTR)) ;
+	
+		if(flags < 0)
+			return(-errno);
+
+		if(mode & OS_ACC_X_OK)
+			return(-EACCES); /* XXX not executable not true? */
+		if((mode & OS_ACC_W_OK) && !(flags&O_RDWR || flags&O_WRONLY))
+			return(-EACCES);
+		if((mode & OS_ACC_R_OK) && (flags&O_WRONLY))
+			return(-EACCES);
+
+		return(0);
+	}
 
 	amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
 	      (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
@@ -257,6 +289,12 @@
 {
 	int fd, f = 0;
 
+	fd = filemap_aquire("file", file);
+	if(fd >= 0) {
+		printk("filemap aquire: fd=%d, file=%s\n", fd, file);
+		goto setfd;
+	}
+
 	if(flags.r && flags.w) f = O_RDWR;
 	else if(flags.r) f = O_RDONLY;
 	else if(flags.w) f = O_WRONLY;
@@ -271,6 +309,7 @@
 	if(fd < 0)
 		return(-errno);
 
+setfd:
 	if(flags.cl && fcntl(fd, F_SETFD, 1)){
 		os_close_file(fd);
 		return(-errno);
@@ -300,6 +339,13 @@
 
 void os_close_file(int fd)
 {
+#if 0
+	/* filemapped files will return something other than -ENOENT */
+	if(filemap_release("file", fd) != -ENOENT) {
+		return;
+	}
+#endif
+
 	close(fd);
 }
 
@@ -574,6 +620,12 @@
 	struct sockaddr_un addr;
 	int sock, err;
 
+	sock = filemap_aquire("file", file);
+	if(sock >= 0) {
+		printk("filemap aquire: fd=%d, file=%s\n", sock, file);
+		goto setfd;
+	}
+
 	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 	if (sock < 0){
 		printk("create_unix_socket - socket failed, errno = %d\n",
@@ -581,13 +633,6 @@
 		return(-errno);
 	}
 
-	if(close_on_exec) {
-		err = os_set_exec_close(sock, 1);
-		if(err < 0)
-			printk("create_unix_socket : close_on_exec failed, "
-		       "err = %d", -err);
-	}
-
 	addr.sun_family = AF_UNIX;
 
 	/* XXX Be more careful about overflow */
@@ -598,6 +643,14 @@
 		printk("create_listening_socket - bind failed, errno = %d\n",
 		       errno);
 		return(-errno);
+	}
+
+setfd:
+	if(close_on_exec) {
+		err = os_set_exec_close(sock, 1);
+		if(err < 0)
+			printk("create_unix_socket : close_on_exec failed, "
+		       "err = %d", -err);
 	}
 
 	return(sock);
diff -Naur linux-2.4.22-5um.orig/arch/um/drivers/daemon_user.c linux-2.4.22-5um.new/arch/um/drivers/daemon_user.c
--- linux-2.4.22-5um.orig/arch/um/drivers/daemon_user.c	Thu Sep 25 19:29:45 2003
+++ linux-2.4.22-5um.new/arch/um/drivers/daemon_user.c	Thu Sep 25 20:29:17 2003
@@ -18,6 +18,8 @@
 #include "user.h"
 #include "os.h"
 
+#include "filemap.h"
+
 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
 
 enum request_type { REQ_NEW_CONTROL };
@@ -53,6 +55,13 @@
 	struct request_v3 req;
 	int fd, n, err;
 
+	pri->control = filemap_aquire("file", ctl_addr->sun_path);
+	if(pri->control >= 0) {
+		printk("filemap aquire: fd=%d, file=%s\n",
+		       pri->control, ctl_addr->sun_path);
+		goto have_control;
+	}
+
 	pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
 	if(pri->control < 0){
 		printk("daemon_open : control socket failed, errno = %d\n", 
@@ -68,6 +77,7 @@
 		goto out;
 	}
 
+have_control:
 	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
 	if(fd < 0){
 		printk("daemon_open : data socket failed, errno = %d\n", 

             reply	other threads:[~2003-10-14  3:54 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-10-14  3:54 Steve Schmidtke [this message]
2003-10-13  5:15 ` [uml-devel] filemap feature 2.4.22-5um Jeff Dike
2003-10-14  6:19 ` Doug Dumitru
2003-10-17 17:14 ` Adam Heath
  -- strict thread matches above, loose matches on Subject: below --
2003-10-14 14:08 Steve Schmidtke
2003-10-14 22:58 Steve Schmidtke
2003-10-15  8:43 ` azu
2003-10-15 20:13 ` Jeff Dike
2003-10-18  1:31 Steve Schmidtke
2003-10-18 12:37 ` Henrik Nordstrom
2003-10-18 21:57   ` Goetz Bock
2003-10-18 22:29     ` Henrik Nordstrom
2003-10-18 14:27 ` Adam Heath
2003-10-18 16:34 BlaisorBlade
2003-10-18 17:15 Steve Schmidtke

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BAY7-F67zjLYL23VZvZ0000e11f@hotmail.com \
    --to=steve_schmidtke@hotmail.com \
    --cc=User-mode-linux-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox