More upstream changes from feisty

Ben Collins ben.collins at ubuntu.com
Thu Apr 19 00:51:34 UTC 2007


Looks like I missed some depth 2 files the first time trying to keep the
cruft out of the diff. This includes some extra DSDT-initramfs bits, and
some things that were done for apport (binfmt_elf changes, and
call_usermodehelper_pipe changes). Other misc things as well.

diff --git a/Documentation/dsdt-initrd.txt b/Documentation/dsdt-initrd.txt
new file mode 100644
index 0000000..45549eb
--- /dev/null
+++ b/Documentation/dsdt-initrd.txt
@@ -0,0 +1,98 @@
+ACPI Custom DSDT read from initramfs
+
+2003 by Markuss Gaugusch < dsdt at gaugusch dot org >
+Special thanks go to Thomas Renninger from SuSE, who updated the patch for
+2.6.0 and later modified it to read inside initramfs
+2004 - 2007 maintained by Eric Piel < eric dot piel at tremplin-utc dot net >
+
+This option is intended for people who would like to hack their DSDT and don't want
+to recompile their kernel after every change. It can also be useful to distros
+which offers pre-compiled kernels and want to allow their users to use a
+modified DSDT. In the Kernel config, enable the initial RAM filesystem support
+(in Device Drivers|Block Devices) and enable ACPI_CUSTOM_DSDT_INITRD at the ACPI
+options (General Setup|ACPI Support|Read custom DSDT from initrd).
+
+A custom DSDT (Differentiated System Description Table) is useful when your
+computer uses ACPI but problems occur due to broken implementation. Typically,
+your computer works but there are some troubles with the hardware detection or
+the power management. You can check that troubles come from errors in the DSDT by
+activating the ACPI debug option and reading the logs. This table is provided
+by the BIOS, therefore it might be a good idea to check for BIOS update on your
+vendor website before going any further. Errors are often caused by vendors
+testing their hardware only with Windows or because there is code which is
+executed only on a specific OS with a specific version and Linux hasn't been
+considered during the development.
+
+Before you run away from customising your DSDT, you should note that already
+corrected tables are available for a fair amount of computers on this web-page:
+http://acpi.sf.net/dsdt . If you are part of the unluckies who cannot find
+their hardware in this database, you can modify your DSDT by yourself. This
+process is less painful than it sounds. Download the Intel ASL 
+compiler/decompiler at http://www.intel.com/technology/IAPC/acpi/downloads.htm .
+As root, you then have to dump your DSDT and decompile it. By using the
+compiler messages as well as the kernel ACPI debug messages and the reference book
+(available at the Intel website and also at http://www.acpi.info), it is quite
+easy to obtain a fully working table.
+
+Once your new DSDT is ready you'll have to add it to an initrd so that the
+kernel can read the table at the very beginning of the boot. As the file has
+to be accessed very early during the boot process the initrd has to be an
+initramfs. The file is contained into the initramfs under the name /DSDT.aml .
+To obtain such an initrd, you might have to modify your mkinitrd script or you
+can add it later to the initrd with the script appended to this document. The
+command will look like:
+initrd-add-dsdt initrd.img my-dsdt.aml
+
+In case you don't use any initrd, the possibilities you have are to either start
+using one (try mkinitrd or yaird), or use the "Include Custom DSDT" configure
+option to directly include your DSDT inside the kernel.
+
+The message "Looking for DSDT in initramfs..." will tell you if the DSDT was
+found or not. If you need to update your DSDT, generate a new initrd and
+perform the steps above. Don't forget that with Lilo, you'll have to re-run it.
+
+
+======================= Here starts initrd-add-dsdt ===============================
+#!/bin/bash
+# Adds a DSDT file to the initrd (if it's an initramfs)
+# first argument is the name of archive
+# second argurment is the name of the file to add
+# The file will be copied as /DSDT.aml
+
+# 20060126: fix "Premature end of file" with some old cpio (Roland Robic)
+# 20060205: this time it should really work
+
+# check the arguments
+if [ $# -ne 2 ]; then
+	program_name=$(basename $0)
+	echo "\
+$program_name: too few arguments
+Usage: $program_name initrd-name.img DSDT-to-add.aml
+Adds a DSDT file to an initrd (in initramfs format)
+
+  initrd-name.img: filename of the initrd in initramfs format
+  DSDT-to-add.aml: filename of the DSDT file to add
+  " 1>&2
+    exit 1
+fi
+
+# we should check it's an initramfs
+
+tempcpio=$(mktemp -d)
+# cleanup on exit, hangup, interrupt, quit, termination
+trap 'rm -rf $tempcpio' 0 1 2 3 15
+
+# extract the archive
+gunzip -c "$1" > "$tempcpio"/initramfs.cpio || exit 1
+
+# copy the DSDT file at the root of the directory so that we can call it "/DSDT.aml"
+cp -f "$2" "$tempcpio"/DSDT.aml
+
+# add the file
+cd "$tempcpio"
+(echo DSDT.aml | cpio --quiet -H newc -o -A -O "$tempcpio"/initramfs.cpio) || exit 1
+cd "$OLDPWD"
+
+# re-compress the archive
+gzip -c "$tempcpio"/initramfs.cpio > "$1"
+
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 65c6a3c..0b45f4b 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -510,11 +510,19 @@ static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int c
 	return err;
 }
 
-static inline int blk_send_start_stop(request_queue_t *q, struct gendisk *bd_disk, int data)
+static inline int blk_send_start_stop(request_queue_t *q,
+				      struct gendisk *bd_disk, int data)
 {
 	return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
 }
 
+static inline int blk_send_allow_medium_removal(request_queue_t *q,
+						struct gendisk *bd_disk)
+{
+	return __blk_send_generic(q, bd_disk,
+				  GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, 0);
+}
+
 int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
 {
 	request_queue_t *q;
@@ -639,7 +647,11 @@ int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd,
 			err = blk_send_start_stop(q, bd_disk, 0x03);
 			break;
 		case CDROMEJECT:
-			err = blk_send_start_stop(q, bd_disk, 0x02);
+			err = 0;
+
+			err |= blk_send_allow_medium_removal(q, bd_disk);
+			err |= blk_send_start_stop(q, bd_disk, 0x01);
+			err |= blk_send_start_stop(q, bd_disk, 0x02);
 			break;
 		default:
 			err = -ENOTTY;
diff --git a/drivers/Makefile b/drivers/Makefile
index f28dcb4..3b1d03f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -27,6 +27,9 @@ obj-$(CONFIG_FB_INTEL)          += video/intelfb/
 
 obj-y				+= serial/
 obj-$(CONFIG_PARPORT)		+= parport/
+obj-$(CONFIG_GAMEPORT)		+= input/gameport/
+# load keyboard early so speakup can be quieted
+obj-$(CONFIG_INPUT)		+= input/
 obj-y				+= base/ block/ misc/ mfd/ net/ media/
 obj-$(CONFIG_NUBUS)		+= nubus/
 obj-$(CONFIG_ATM)		+= atm/
@@ -53,8 +56,6 @@ obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_PCI)		+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/gadget/
 obj-$(CONFIG_SERIO)		+= input/serio/
-obj-$(CONFIG_GAMEPORT)		+= input/gameport/
-obj-$(CONFIG_INPUT)		+= input/
 obj-$(CONFIG_I2O)		+= message/
 obj-$(CONFIG_RTC_LIB)		+= rtc/
 obj-$(CONFIG_I2C)		+= i2c/
diff --git a/fs/block_dev.c b/fs/block_dev.c
index fc7028b..61971a9 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -661,34 +661,12 @@ void bd_forget(struct inode *inode)
 
 int bd_claim(struct block_device *bdev, void *holder)
 {
-	int res;
+	int res = -EBUSY;
 	spin_lock(&bdev_lock);
-
-	/* first decide result */
-	if (bdev->bd_holder == holder)
-		res = 0;	 /* already a holder */
-	else if (bdev->bd_holder != NULL)
-		res = -EBUSY; 	 /* held by someone else */
-	else if (bdev->bd_contains == bdev)
-		res = 0;  	 /* is a whole device which isn't held */
-
-	else if (bdev->bd_contains->bd_holder == bd_claim)
-		res = 0; 	 /* is a partition of a device that is being partitioned */
-	else if (bdev->bd_contains->bd_holder != NULL)
-		res = -EBUSY;	 /* is a partition of a held device */
-	else
-		res = 0;	 /* is a partition of an un-held device */
-
-	/* now impose change */
-	if (res==0) {
-		/* note that for a whole device bd_holders
-		 * will be incremented twice, and bd_holder will
-		 * be set to bd_claim before being set to holder
-		 */
-		bdev->bd_contains->bd_holders ++;
-		bdev->bd_contains->bd_holder = bd_claim;
-		bdev->bd_holders++;
+	if (!bdev->bd_holder || bdev->bd_holder == holder) {
 		bdev->bd_holder = holder;
+		bdev->bd_holders++;
+		res = 0;
 	}
 	spin_unlock(&bdev_lock);
 	return res;
@@ -699,8 +677,6 @@ EXPORT_SYMBOL(bd_claim);
 void bd_release(struct block_device *bdev)
 {
 	spin_lock(&bdev_lock);
-	if (!--bdev->bd_contains->bd_holders)
-		bdev->bd_contains->bd_holder = NULL;
 	if (!--bdev->bd_holders)
 		bdev->bd_holder = NULL;
 	spin_unlock(&bdev_lock);
diff --git a/fs/dcache.c b/fs/dcache.c
index d68631f..0374f45 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1747,7 +1747,7 @@ shouldnt_be_hashed:
  *
  * "buflen" should be positive. Caller holds the dcache_lock.
  */
-static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
+char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
 			struct dentry *root, struct vfsmount *rootmnt,
 			char *buffer, int buflen)
 {
@@ -2139,3 +2139,4 @@ EXPORT_SYMBOL(have_submounts);
 EXPORT_SYMBOL(names_cachep);
 EXPORT_SYMBOL(shrink_dcache_parent);
 EXPORT_SYMBOL(shrink_dcache_sb);
+EXPORT_SYMBOL(__d_path);
diff --git a/fs/exec.c b/fs/exec.c
index 11fe93f..f441769 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1343,8 +1343,16 @@ static void format_corename(char *corename, const char *pattern, long signr)
 	 *
 	 * If core_pattern does not include a %p (as is the default)
 	 * and core_uses_pid is set, then .%pid will be appended to
-	 * the filename */
-	if (!pid_in_pattern
+	 * the filename, unless we are using a pipe, where it makes no
+	 * sense. */
+	if (corename[0] == '|') {
+		static int printed;
+
+		if (core_uses_pid && !printed) {
+			printk(KERN_WARNING "core: core_uses_pid set with piped core, ignoring\n");
+			printed = 1;
+		}
+	} else if (!pid_in_pattern
             && (core_uses_pid || atomic_read(&current->mm->mm_users) != 1)) {
 		rc = snprintf(out_ptr, out_end - out_ptr,
 			      ".%d", current->tgid);
@@ -1454,9 +1462,23 @@ fail:
 	return core_waiters;
 }
 
+#define CORE_ENV_MAX_ARGS	8
+
 int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 {
 	char corename[CORENAME_MAX_SIZE + 1];
+	char *core_argv[2];
+	char *core_envp[CORE_ENV_MAX_ARGS + 1];
+	/* Gotta love scope... */
+	char core_pid[CORENAME_MAX_SIZE + 1];
+	char core_uid[CORENAME_MAX_SIZE + 1];
+	char core_gid[CORENAME_MAX_SIZE + 1];
+	char core_signal[CORENAME_MAX_SIZE + 1];
+	char core_time[CORENAME_MAX_SIZE + 1];
+	char core_hostname[CORENAME_MAX_SIZE + 1];
+	char core_comm[CORENAME_MAX_SIZE + 1];
+	char core_rlim[CORENAME_MAX_SIZE + 1];
+	int old_rlim = -1;
 	struct mm_struct *mm = current->mm;
 	struct linux_binfmt * binfmt;
 	struct inode * inode;
@@ -1464,7 +1486,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	int retval = 0;
 	int fsuid = current->fsuid;
 	int flag = 0;
-	int ispipe = 0;
+	struct subprocess_info *sub_info = NULL;
 
 	binfmt = current->binfmt;
 	if (!binfmt || !binfmt->core_dump)
@@ -1490,14 +1512,27 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	if (retval < 0)
 		goto fail;
 
+	/* For piped core's, we rely on the script to limit what it writes
+	 * out. Since we aren't writing directly to the fs, we shouldn't
+	 * worry too much (and pipe should infer we always want to do the
+	 * core). We tell the script the original value for rlim_cur via
+	 * env, so it can make intelligent decisions. */
+	if (core_pattern[0] == '|') {
+		old_rlim = current->signal->rlim[RLIMIT_CORE].rlim_cur;
+		current->signal->rlim[RLIMIT_CORE].rlim_cur =
+			1024 * 1024 * 1024;
+	}
+
 	/*
 	 * Clear any false indication of pending signals that might
 	 * be seen by the filesystem code called to write the core file.
 	 */
 	clear_thread_flag(TIF_SIGPENDING);
 
-	if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
+	if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump &&
+	    core_pattern[0] != '|') {
 		goto fail_unlock;
+	}
 
 	/*
 	 * lock_kernel() because format_corename() is controlled by sysctl, which
@@ -1507,13 +1542,47 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	format_corename(corename, core_pattern, signr);
 	unlock_kernel();
  	if (corename[0] == '|') {
+		int i = 0;
+		struct timeval tv;
+
+#define CORE_ENV_ADD(__buf, __fmt, __arg)		\
+do {							\
+if (i < CORE_ENV_MAX_ARGS ) {				\
+	snprintf(__buf, sizeof(__buf), __fmt, __arg);	\
+	core_envp[i++] = __buf;				\
+} else							\
+	WARN_ON(1);					\
+} while(0)
+
+		/* Create the env */
+		CORE_ENV_ADD(core_pid, "CORE_PID=%d", current->tgid);
+		CORE_ENV_ADD(core_uid, "CORE_UID=%d", current->uid);
+		CORE_ENV_ADD(core_gid, "CORE_GID=%d", current->gid);
+		CORE_ENV_ADD(core_signal, "CORE_SIGNAL=%ld", signr);
+		CORE_ENV_ADD(core_comm, "CORE_EXECUTABLE=%s", current->comm);
+		CORE_ENV_ADD(core_rlim, "CORE_REAL_RLIM=%d", old_rlim);
+
+		do_gettimeofday(&tv);
+		CORE_ENV_ADD(core_time, "CORE_TIME=%lu", tv.tv_sec);
+
+		down_read(&uts_sem);
+		CORE_ENV_ADD(core_hostname, "CORE_HOSTNAME=%s", utsname()->nodename);
+		up_read(&uts_sem);
+
+#undef CORE_ENV_ADD
+
+		core_envp[i] = NULL;
+
+		core_argv[0] = corename+1;
+		core_argv[1] = NULL;
+
 		/* SIGPIPE can happen, but it's just never processed */
- 		if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) {
+ 		if (call_usermodehelper_pipe(core_argv[0], core_argv,
+					     core_envp, &file, &sub_info)) {
  			printk(KERN_INFO "Core dump to %s pipe failed\n",
 			       corename);
  			goto fail_unlock;
  		}
-		ispipe = 1;
  	} else
  		file = filp_open(corename,
 				 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
@@ -1523,18 +1592,18 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	inode = file->f_path.dentry->d_inode;
 	if (inode->i_nlink > 1)
 		goto close_fail;	/* multiple links - don't dump */
-	if (!ispipe && d_unhashed(file->f_path.dentry))
+	if (!sub_info && d_unhashed(file->f_path.dentry))
 		goto close_fail;
 
 	/* AK: actually i see no reason to not allow this for named pipes etc.,
 	   but keep the previous behaviour for now. */
-	if (!ispipe && !S_ISREG(inode->i_mode))
+	if (!sub_info && !S_ISREG(inode->i_mode))
 		goto close_fail;
 	if (!file->f_op)
 		goto close_fail;
 	if (!file->f_op->write)
 		goto close_fail;
-	if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
+	if (!sub_info && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
 		goto close_fail;
 
 	retval = binfmt->core_dump(signr, regs, file);
@@ -1543,9 +1612,13 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 		current->signal->group_exit_code |= 0x80;
 close_fail:
 	filp_close(file, NULL);
+	if (sub_info)
+		finish_usermodehelper_pipe(sub_info);
 fail_unlock:
 	current->fsuid = fsuid;
 	complete_all(&mm->core_done);
+	if (old_rlim >= 0)
+		current->signal->rlim[RLIMIT_CORE].rlim_cur = old_rlim;
 fail:
 	return retval;
 }
diff --git a/fs/namei.c b/fs/namei.c
index e4f108f..5a2e89a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1292,8 +1292,8 @@ static struct dentry *lookup_hash(struct nameidata *nd)
 	return __lookup_hash(&nd->last, nd->dentry, nd);
 }
 
-/* SMP-safe */
-struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
+struct dentry *lookup_one_len_nd(const char *name, struct dentry *base,
+				  int len, struct nameidata *nd)
 {
 	unsigned long hash;
 	struct qstr this;
@@ -1313,7 +1313,7 @@ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
 	}
 	this.hash = end_name_hash(hash);
 
-	return __lookup_hash(&this, base, NULL);
+	return __lookup_hash(&this, base, nd);
 access:
 	return ERR_PTR(-EACCES);
 }
@@ -2757,7 +2757,7 @@ EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
 EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(lock_rename);
-EXPORT_SYMBOL(lookup_one_len);
+EXPORT_SYMBOL(lookup_one_len_nd);
 EXPORT_SYMBOL(page_follow_link_light);
 EXPORT_SYMBOL(page_put_link);
 EXPORT_SYMBOL(page_readlink);
diff --git a/fs/namespace.c b/fs/namespace.c
index 5ef336c..694de5c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -37,7 +37,8 @@ static int event;
 static struct list_head *mount_hashtable __read_mostly;
 static int hash_mask __read_mostly, hash_bits __read_mostly;
 static struct kmem_cache *mnt_cache __read_mostly;
-static struct rw_semaphore namespace_sem;
+struct rw_semaphore namespace_sem;
+EXPORT_SYMBOL_GPL(namespace_sem);
 
 /* /sys/fs */
 decl_subsys(fs, NULL, NULL);
diff --git a/init/Kconfig b/init/Kconfig
index a3f83e2..bd17062 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -91,6 +91,15 @@ config LOCALVERSION_AUTO
 	  Note: This requires Perl, and a git repository, but not necessarily
 	  the git or cogito tools to be installed.
 
+config VERSION_SIGNATURE
+	string "Arbitrary version signature"
+	help
+	  This string will be created in a file, /proc/version_signature. It
+	  is useful in determining arbitrary data about your kernel. For instance,
+	  if you have several kernels of the same version, but need to keep track
+	  of a revision of the same kernel, but not affect it's ability to load
+	  compatible modules, this is the easiest way to do that.
+
 config SWAP
 	bool "Support for paging of anonymous memory (swap)"
 	depends on MMU && BLOCK
diff --git a/init/initramfs.c b/init/initramfs.c
index 4fa0f79..1d7e951 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -526,6 +526,26 @@ static void __init free_initrd(void)
 
 #endif
 
+/* Tries to read the initramfs if it's already there, for ACPI Table Overiding */
+void __init early_populate_rootfs(void)
+{
+	char *err = unpack_to_rootfs(__initramfs_start,
+			 __initramfs_end - __initramfs_start, 0);
+	if (err)
+		return;
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start) {
+		printk(KERN_INFO "Early unpacking initramfs...");
+		err = unpack_to_rootfs((char *)initrd_start,
+			initrd_end - initrd_start, 0);
+		if (err)
+			return;
+		printk(" done\n");
+	}
+#endif
+	return;
+}
+
 static int __init populate_rootfs(void)
 {
 	char *err = unpack_to_rootfs(__initramfs_start,
diff --git a/init/main.c b/init/main.c
index 8b4a7d7..02b3dea 100644
--- a/init/main.c
+++ b/init/main.c
@@ -96,8 +96,10 @@ extern void free_initmem(void);
 extern void prepare_namespace(void);
 #ifdef	CONFIG_ACPI
 extern void acpi_early_init(void);
+extern void early_populate_rootfs(void);
 #else
 static inline void acpi_early_init(void) { }
+static inline void early_populate_rootfs(void) { }
 #endif
 #ifndef CONFIG_DEBUG_RODATA
 static inline void mark_rodata_ro(void) { }
@@ -614,6 +616,7 @@ asmlinkage void __init start_kernel(void)
 
 	check_bugs();
 
+	early_populate_rootfs(); /* For DSDT override from initramfs */
 	acpi_early_init(); /* before LAPIC and SMP init */
 
 	/* Do the rest non-__init'ed, we're now alive */
diff --git a/init/version.c b/init/version.c
index 6c01ec1..7cb1c97 100644
--- a/init/version.c
+++ b/init/version.c
@@ -37,7 +37,11 @@ EXPORT_SYMBOL_GPL(init_uts_ns);
 /* FIXED STRINGS! Don't touch! */
 const char linux_banner[] =
 	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
-	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION
+#ifdef CONFIG_VERSION_SIGNATURE
+        " (" CONFIG_VERSION_SIGNATURE ")"
+#endif
+	"\n";
 
 const char linux_proc_banner[] =
 	"%s version %s"
diff --git a/kernel/audit.c b/kernel/audit.c
index d9b690a..e82e0e8 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -956,8 +956,7 @@ static inline int audit_expand(struct audit_buffer *ab, int extra)
  * will be called a second time.  Currently, we assume that a printk
  * can't format message larger than 1024 bytes, so we don't either.
  */
-static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
-			      va_list args)
+void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
 {
 	int len, avail;
 	struct sk_buff *skb;
@@ -1213,3 +1212,6 @@ EXPORT_SYMBOL(audit_log_start);
 EXPORT_SYMBOL(audit_log_end);
 EXPORT_SYMBOL(audit_log_format);
 EXPORT_SYMBOL(audit_log);
+EXPORT_SYMBOL_GPL(audit_log_vformat);
+EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
+EXPORT_SYMBOL_GPL(audit_log_d_path);
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 3a7379a..407210b 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -290,23 +290,32 @@ int call_usermodehelper_keys(char *path, char **argv, char **envp,
 EXPORT_SYMBOL(call_usermodehelper_keys);
 
 int call_usermodehelper_pipe(char *path, char **argv, char **envp,
-			     struct file **filp)
+			     struct file **filp, struct subprocess_info **sub_info)
 {
-	DECLARE_COMPLETION(done);
-	struct subprocess_info sub_info = {
-		.work		= __WORK_INITIALIZER(sub_info.work,
-						     __call_usermodehelper),
-		.complete	= &done,
-		.path		= path,
-		.argv		= argv,
-		.envp		= envp,
-		.retval		= 0,
-	};
 	struct file *f;
+	struct subprocess_info *sinfo;
 
 	if (!khelper_wq)
 		return -EBUSY;
 
+	sinfo = kzalloc(sizeof(struct subprocess_info), GFP_KERNEL);
+	if (!sinfo)
+		return -ENOMEM;
+
+	sinfo->complete = kmalloc(sizeof(struct completion), GFP_KERNEL);
+	if (!sinfo->complete) {
+		kfree(sinfo);
+		return -ENOMEM;
+	}
+
+	*sub_info = sinfo;
+	INIT_WORK(&sinfo->work, __call_usermodehelper);
+	init_completion(sinfo->complete);
+	sinfo->path = path;
+	sinfo->argv = argv;
+	sinfo->envp = envp;
+	sinfo->wait = 1;
+
 	if (path[0] == '\0')
 		return 0;
 
@@ -320,14 +329,23 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
 		free_write_pipe(*filp);
 		return PTR_ERR(f);
 	}
-	sub_info.stdin = f;
+	sinfo->stdin = f;
 
-	queue_work(khelper_wq, &sub_info.work);
-	wait_for_completion(&done);
-	return sub_info.retval;
+	queue_work(khelper_wq, &sinfo->work);
+	return 0;
 }
 EXPORT_SYMBOL(call_usermodehelper_pipe);
 
+int finish_usermodehelper_pipe(struct subprocess_info *sub_info)
+{
+	wait_for_completion(sub_info->complete);
+	kfree(sub_info->complete);
+	kfree(sub_info);
+
+	return sub_info->retval;
+}
+EXPORT_SYMBOL(finish_usermodehelper_pipe);
+
 void __init usermodehelper_init(void)
 {
 	khelper_wq = create_singlethread_workqueue("khelper");


-- 
Ubuntu:    http://www.ubuntu.com/
Linux1394: http://www.linux1394.org/





More information about the kernel-team mailing list