[kernel] r17064 - in dists/trunk/linux-2.6/debian: . config patches/features/all patches/series

Ben Hutchings benh at alioth.debian.org
Sun Mar 13 00:52:36 UTC 2011


Author: benh
Date: Sun Mar 13 00:52:31 2011
New Revision: 17064

Log:
Remove the Big Kernel Lock:

adfs,appletalk,i810,ufs,usbip: Refactor locking
hpfs: Disable HPFS_FS

Added:
   dists/trunk/linux-2.6/debian/patches/features/all/adfs-remove-the-big-kernel-lock.patch
   dists/trunk/linux-2.6/debian/patches/features/all/appletalk-remove-the-BKL.patch
   dists/trunk/linux-2.6/debian/patches/features/all/drm-i810-remove-the-BKL.patch
   dists/trunk/linux-2.6/debian/patches/features/all/staging-usbip-convert-to-kthread.patch
   dists/trunk/linux-2.6/debian/patches/features/all/ufs-remove-the-BKL.patch
   dists/trunk/linux-2.6/debian/patches/series/1~experimental.2
Modified:
   dists/trunk/linux-2.6/debian/changelog
   dists/trunk/linux-2.6/debian/config/config

Modified: dists/trunk/linux-2.6/debian/changelog
==============================================================================
--- dists/trunk/linux-2.6/debian/changelog	Sun Mar 13 00:46:28 2011	(r17063)
+++ dists/trunk/linux-2.6/debian/changelog	Sun Mar 13 00:52:31 2011	(r17064)
@@ -5,6 +5,9 @@
   * Move linux-base to separate source package
   * net/can: Enable CAN_SLCAN as module (Closes: #617629)
   * sound: Enable SND_ALOOP as module (Closes: #617869)
+  * Remove the Big Kernel Lock:
+    - adfs,appletalk,i810,ufs,usbip: Refactor locking
+    - hpfs: Disable HPFS_FS
 
  -- Ben Hutchings <ben at decadent.org.uk>  Sat, 12 Mar 2011 08:57:58 +0000
 

Modified: dists/trunk/linux-2.6/debian/config/config
==============================================================================
--- dists/trunk/linux-2.6/debian/config/config	Sun Mar 13 00:46:28 2011	(r17063)
+++ dists/trunk/linux-2.6/debian/config/config	Sun Mar 13 00:52:31 2011	(r17064)
@@ -3109,7 +3109,7 @@
 ##
 ## file: fs/hpfs/Kconfig
 ##
-CONFIG_HPFS_FS=m
+# CONFIG_HPFS_FS is not set
 
 ##
 ## file: fs/isofs/Kconfig
@@ -3399,6 +3399,7 @@
 ## file: init/Kconfig
 ##
 CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCK_KERNEL is not set
 CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
 ## choice: Kernel compression mode
@@ -3583,6 +3584,7 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_BKL is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_SPARSE_RCU_POINTER is not set

Added: dists/trunk/linux-2.6/debian/patches/features/all/adfs-remove-the-big-kernel-lock.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/trunk/linux-2.6/debian/patches/features/all/adfs-remove-the-big-kernel-lock.patch	Sun Mar 13 00:52:31 2011	(r17064)
@@ -0,0 +1,188 @@
+From: Arnd Bergmann <arnd at arndb.de>
+Date: Sat, 22 Jan 2011 20:05:05 +0100
+Subject: [PATCH] adfs: remove the big kernel lock
+
+commit 4688a066ecf60086ea82f68edb3b036b567d2c08 upstream.
+
+According to Russell King, adfs was written to not require the big
+kernel lock, and all inode updates are done under adfs_dir_lock.
+
+All other metadata in adfs is read-only and does not require locking.
+The use of the BKL is the result of various pushdowns from the VFS
+operations.
+
+Signed-off-by: Arnd Bergmann <arnd at arndb.de>
+Acked-by: Russell King <rmk at arm.linux.org.uk>
+Cc: Stuart Swales <stuart.swales.croftnuisk at gmail.com>
+---
+ fs/adfs/Kconfig |    1 -
+ fs/adfs/dir.c   |    6 ------
+ fs/adfs/inode.c |    6 ------
+ fs/adfs/super.c |   13 +------------
+ 4 files changed, 1 insertions(+), 25 deletions(-)
+
+diff --git a/fs/adfs/Kconfig b/fs/adfs/Kconfig
+index 1dd5f34..e55182a 100644
+--- a/fs/adfs/Kconfig
++++ b/fs/adfs/Kconfig
+@@ -1,7 +1,6 @@
+ config ADFS_FS
+ 	tristate "ADFS file system support (EXPERIMENTAL)"
+ 	depends on BLOCK && EXPERIMENTAL
+-	depends on BKL # need to fix
+ 	help
+ 	  The Acorn Disc Filing System is the standard file system of the
+ 	  RiscOS operating system which runs on Acorn's ARM-based Risc PC
+diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
+index 3b4a764..3d83075a 100644
+--- a/fs/adfs/dir.c
++++ b/fs/adfs/dir.c
+@@ -9,7 +9,6 @@
+  *
+  *  Common directory handling for ADFS
+  */
+-#include <linux/smp_lock.h>
+ #include "adfs.h"
+ 
+ /*
+@@ -27,8 +26,6 @@ adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ 	struct adfs_dir dir;
+ 	int ret = 0;
+ 
+-	lock_kernel();	
+-
+ 	if (filp->f_pos >> 32)
+ 		goto out;
+ 
+@@ -70,7 +67,6 @@ free_out:
+ 	ops->free(&dir);
+ 
+ out:
+-	unlock_kernel();
+ 	return ret;
+ }
+ 
+@@ -276,7 +272,6 @@ adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+ 	struct object_info obj;
+ 	int error;
+ 
+-	lock_kernel();
+ 	error = adfs_dir_lookup_byname(dir, &dentry->d_name, &obj);
+ 	if (error == 0) {
+ 		error = -EACCES;
+@@ -288,7 +283,6 @@ adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+ 		if (inode)
+ 			error = 0;
+ 	}
+-	unlock_kernel();
+ 	d_add(dentry, inode);
+ 	return ERR_PTR(error);
+ }
+diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
+index 65794b8..09fe401 100644
+--- a/fs/adfs/inode.c
++++ b/fs/adfs/inode.c
+@@ -7,7 +7,6 @@
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  */
+-#include <linux/smp_lock.h>
+ #include <linux/buffer_head.h>
+ #include <linux/writeback.h>
+ #include "adfs.h"
+@@ -316,8 +315,6 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
+ 	unsigned int ia_valid = attr->ia_valid;
+ 	int error;
+ 	
+-	lock_kernel();
+-
+ 	error = inode_change_ok(inode, attr);
+ 
+ 	/*
+@@ -359,7 +356,6 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
+ 	if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MODE))
+ 		mark_inode_dirty(inode);
+ out:
+-	unlock_kernel();
+ 	return error;
+ }
+ 
+@@ -374,7 +370,6 @@ int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
+ 	struct object_info obj;
+ 	int ret;
+ 
+-	lock_kernel();
+ 	obj.file_id	= inode->i_ino;
+ 	obj.name_len	= 0;
+ 	obj.parent_id	= ADFS_I(inode)->parent_id;
+@@ -384,6 +379,5 @@ int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
+ 	obj.size	= inode->i_size;
+ 
+ 	ret = adfs_dir_update(sb, &obj, wbc->sync_mode == WB_SYNC_ALL);
+-	unlock_kernel();
+ 	return ret;
+ }
+diff --git a/fs/adfs/super.c b/fs/adfs/super.c
+index 2d79540..06d7388 100644
+--- a/fs/adfs/super.c
++++ b/fs/adfs/super.c
+@@ -14,7 +14,6 @@
+ #include <linux/mount.h>
+ #include <linux/seq_file.h>
+ #include <linux/slab.h>
+-#include <linux/smp_lock.h>
+ #include <linux/statfs.h>
+ #include "adfs.h"
+ #include "dir_f.h"
+@@ -120,15 +119,11 @@ static void adfs_put_super(struct super_block *sb)
+ 	int i;
+ 	struct adfs_sb_info *asb = ADFS_SB(sb);
+ 
+-	lock_kernel();
+-
+ 	for (i = 0; i < asb->s_map_size; i++)
+ 		brelse(asb->s_map[i].dm_bh);
+ 	kfree(asb->s_map);
+ 	kfree(asb);
+ 	sb->s_fs_info = NULL;
+-
+-	unlock_kernel();
+ }
+ 
+ static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
+@@ -359,15 +354,11 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
+ 	struct adfs_sb_info *asb;
+ 	struct inode *root;
+ 
+-	lock_kernel();
+-
+ 	sb->s_flags |= MS_NODIRATIME;
+ 
+ 	asb = kzalloc(sizeof(*asb), GFP_KERNEL);
+-	if (!asb) {
+-		unlock_kernel();
++	if (!asb)
+ 		return -ENOMEM;
+-	}
+ 	sb->s_fs_info = asb;
+ 
+ 	/* set default options */
+@@ -485,7 +476,6 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
+ 		adfs_error(sb, "get root inode failed\n");
+ 		goto error;
+ 	}
+-	unlock_kernel();
+ 	return 0;
+ 
+ error_free_bh:
+@@ -493,7 +483,6 @@ error_free_bh:
+ error:
+ 	sb->s_fs_info = NULL;
+ 	kfree(asb);
+-	unlock_kernel();
+ 	return -EINVAL;
+ }
+ 
+-- 
+1.7.4.1
+

Added: dists/trunk/linux-2.6/debian/patches/features/all/appletalk-remove-the-BKL.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/trunk/linux-2.6/debian/patches/features/all/appletalk-remove-the-BKL.patch	Sun Mar 13 00:52:31 2011	(r17064)
@@ -0,0 +1,189 @@
+From: Arnd Bergmann <arnd at arndb.de>
+Date: Sun, 23 Jan 2011 00:21:11 +0100
+Subject: [PATCH] appletalk: remove the BKL
+
+commit 60d9f461a20ba59219fdcdc30cbf8e3a4ad3f625 upstream.
+
+This changes appletalk to use lock_sock instead of
+lock_kernel for serialization. I tried to make sure
+that we don't hold the socket lock during sleeping
+functions, but I did not try to prove whether the
+locks are necessary in the first place.
+
+Compile-tested only.
+
+Signed-off-by: Arnd Bergmann <arnd at arndb.de>
+Acked-by: David S. Miller <davem at davemloft.net>
+Cc: Arnaldo Carvalho de Melo <acme at ghostprotocols.net>
+Cc: David Miller <davem at davemloft.net>
+Cc: netdev at vger.kernel.org
+---
+ drivers/net/appletalk/Kconfig |    1 -
+ net/appletalk/ddp.c           |   40 ++++++++++++++++------------------------
+ 2 files changed, 16 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
+index 0b376a9..f5a8916 100644
+--- a/drivers/net/appletalk/Kconfig
++++ b/drivers/net/appletalk/Kconfig
+@@ -3,7 +3,6 @@
+ #
+ config ATALK
+ 	tristate "Appletalk protocol support"
+-	depends on BKL # waiting to be removed from net/appletalk/ddp.c
+ 	select LLC
+ 	---help---
+ 	  AppleTalk is the protocol that Apple computers can use to communicate
+diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
+index c410b93..3d4f4b0 100644
+--- a/net/appletalk/ddp.c
++++ b/net/appletalk/ddp.c
+@@ -54,7 +54,6 @@
+ #include <linux/capability.h>
+ #include <linux/module.h>
+ #include <linux/if_arp.h>
+-#include <linux/smp_lock.h>
+ #include <linux/termios.h>	/* For TIOCOUTQ/INQ */
+ #include <linux/compat.h>
+ #include <linux/slab.h>
+@@ -1052,13 +1051,13 @@ static int atalk_release(struct socket *sock)
+ {
+ 	struct sock *sk = sock->sk;
+ 
+-	lock_kernel();
++	lock_sock(sk);
+ 	if (sk) {
+ 		sock_orphan(sk);
+ 		sock->sk = NULL;
+ 		atalk_destroy_socket(sk);
+ 	}
+-	unlock_kernel();
++	release_sock(sk);
+ 	return 0;
+ }
+ 
+@@ -1143,7 +1142,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 	if (addr->sat_family != AF_APPLETALK)
+ 		return -EAFNOSUPPORT;
+ 
+-	lock_kernel();
++	lock_sock(sk);
+ 	if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) {
+ 		struct atalk_addr *ap = atalk_find_primary();
+ 
+@@ -1179,7 +1178,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ 	sock_reset_flag(sk, SOCK_ZAPPED);
+ 	err = 0;
+ out:
+-	unlock_kernel();
++	release_sock(sk);
+ 	return err;
+ }
+ 
+@@ -1215,7 +1214,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
+ #endif
+ 	}
+ 
+-	lock_kernel();
++	lock_sock(sk);
+ 	err = -EBUSY;
+ 	if (sock_flag(sk, SOCK_ZAPPED))
+ 		if (atalk_autobind(sk) < 0)
+@@ -1233,7 +1232,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
+ 	sk->sk_state = TCP_ESTABLISHED;
+ 	err = 0;
+ out:
+-	unlock_kernel();
++	release_sock(sk);
+ 	return err;
+ }
+ 
+@@ -1249,7 +1248,7 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
+ 	struct atalk_sock *at = at_sk(sk);
+ 	int err;
+ 
+-	lock_kernel();
++	lock_sock(sk);
+ 	err = -ENOBUFS;
+ 	if (sock_flag(sk, SOCK_ZAPPED))
+ 		if (atalk_autobind(sk) < 0)
+@@ -1277,17 +1276,7 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
+ 	memcpy(uaddr, &sat, sizeof(sat));
+ 
+ out:
+-	unlock_kernel();
+-	return err;
+-}
+-
+-static unsigned int atalk_poll(struct file *file, struct socket *sock,
+-			   poll_table *wait)
+-{
+-	int err;
+-	lock_kernel();
+-	err = datagram_poll(file, sock, wait);
+-	unlock_kernel();
++	release_sock(sk);
+ 	return err;
+ }
+ 
+@@ -1596,7 +1585,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
+ 	if (len > DDP_MAXSZ)
+ 		return -EMSGSIZE;
+ 
+-	lock_kernel();
++	lock_sock(sk);
+ 	if (usat) {
+ 		err = -EBUSY;
+ 		if (sock_flag(sk, SOCK_ZAPPED))
+@@ -1651,7 +1640,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
+ 			sk, size, dev->name);
+ 
+ 	size += dev->hard_header_len;
++	release_sock(sk);
+ 	skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err);
++	lock_sock(sk);
+ 	if (!skb)
+ 		goto out;
+ 
+@@ -1738,7 +1729,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
+ 	SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len);
+ 
+ out:
+-	unlock_kernel();
++	release_sock(sk);
+ 	return err ? : len;
+ }
+ 
+@@ -1753,9 +1744,10 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
+ 	int err = 0;
+ 	struct sk_buff *skb;
+ 
+-	lock_kernel();
+ 	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+ 						flags & MSG_DONTWAIT, &err);
++	lock_sock(sk);
++
+ 	if (!skb)
+ 		goto out;
+ 
+@@ -1787,7 +1779,7 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
+ 	skb_free_datagram(sk, skb);	/* Free the datagram. */
+ 
+ out:
+-	unlock_kernel();
++	release_sock(sk);
+ 	return err ? : copied;
+ }
+ 
+@@ -1887,7 +1879,7 @@ static const struct proto_ops atalk_dgram_ops = {
+ 	.socketpair	= sock_no_socketpair,
+ 	.accept		= sock_no_accept,
+ 	.getname	= atalk_getname,
+-	.poll		= atalk_poll,
++	.poll		= datagram_poll,
+ 	.ioctl		= atalk_ioctl,
+ #ifdef CONFIG_COMPAT
+ 	.compat_ioctl	= atalk_compat_ioctl,
+-- 
+1.7.4.1
+

Added: dists/trunk/linux-2.6/debian/patches/features/all/drm-i810-remove-the-BKL.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/trunk/linux-2.6/debian/patches/features/all/drm-i810-remove-the-BKL.patch	Sun Mar 13 00:52:31 2011	(r17064)
@@ -0,0 +1,125 @@
+From: Arnd Bergmann <arnd at arndb.de>
+Date: Tue, 25 Jan 2011 23:17:15 +0100
+Subject: [PATCH] drm/i810: remove the BKL
+
+commit 1f692a14cbfbeb11f9a9c16f25c8ecb8ab50d3d5 upstream.
+
+SMP i810 systems were practically nonexistent and the configuration
+was not officially supported by Intel at the time when Pentium-III
+was common.
+
+With this change, it is still possible to build a distribution kernel
+that has support for SMP and includes the i810 driver without the BKL.
+As a precaution, check for the theoretical SMP case at run time and
+refuse to load the driver.
+
+We also need to disable CONFIG_PREEMPT builds for this driver.
+
+Signed-off-by: Arnd Bergmann <arnd at arndb.de>
+Cc: dri-devel at lists.freedesktop.org
+Signed-off-by: Dave Airlie <airlied at redhat.com>
+---
+ drivers/gpu/drm/Kconfig         |    4 ++--
+ drivers/gpu/drm/i810/i810_dma.c |   18 +-----------------
+ drivers/gpu/drm/i810/i810_drv.c |    6 +++++-
+ 3 files changed, 8 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
+index 4458876..a6feb78c 100644
+--- a/drivers/gpu/drm/Kconfig
++++ b/drivers/gpu/drm/Kconfig
+@@ -73,8 +73,8 @@ source "drivers/gpu/drm/radeon/Kconfig"
+ 
+ config DRM_I810
+ 	tristate "Intel I810"
+-	# BKL usage in order to avoid AB-BA deadlocks, may become BROKEN_ON_SMP
+-	depends on DRM && AGP && AGP_INTEL && BKL
++	# !PREEMPT because of missing ioctl locking
++	depends on DRM && AGP && AGP_INTEL && (!PREEMPT || BROKEN)
+ 	help
+ 	  Choose this option if you have an Intel I810 graphics card.  If M is
+ 	  selected, the module will be called i810.  AGP support is required
+diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
+index ff33e53..8f371e8 100644
+--- a/drivers/gpu/drm/i810/i810_dma.c
++++ b/drivers/gpu/drm/i810/i810_dma.c
+@@ -37,7 +37,6 @@
+ #include <linux/interrupt.h>	/* For task queue support */
+ #include <linux/delay.h>
+ #include <linux/slab.h>
+-#include <linux/smp_lock.h>
+ #include <linux/pagemap.h>
+ 
+ #define I810_BUF_FREE		2
+@@ -94,7 +93,6 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+ 	struct drm_buf *buf;
+ 	drm_i810_buf_priv_t *buf_priv;
+ 
+-	lock_kernel();
+ 	dev = priv->minor->dev;
+ 	dev_priv = dev->dev_private;
+ 	buf = dev_priv->mmap_buffer;
+@@ -104,7 +102,6 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+ 	vma->vm_file = filp;
+ 
+ 	buf_priv->currently_mapped = I810_BUF_MAPPED;
+-	unlock_kernel();
+ 
+ 	if (io_remap_pfn_range(vma, vma->vm_start,
+ 			       vma->vm_pgoff,
+@@ -116,7 +113,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+ static const struct file_operations i810_buffer_fops = {
+ 	.open = drm_open,
+ 	.release = drm_release,
+-	.unlocked_ioctl = i810_ioctl,
++	.unlocked_ioctl = drm_ioctl,
+ 	.mmap = i810_mmap_buffers,
+ 	.fasync = drm_fasync,
+ 	.llseek = noop_llseek,
+@@ -1242,19 +1239,6 @@ int i810_driver_dma_quiescent(struct drm_device *dev)
+ 	return 0;
+ }
+ 
+-/*
+- * call the drm_ioctl under the big kernel lock because
+- * to lock against the i810_mmap_buffers function.
+- */
+-long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+-{
+-	int ret;
+-	lock_kernel();
+-	ret = drm_ioctl(file, cmd, arg);
+-	unlock_kernel();
+-	return ret;
+-}
+-
+ struct drm_ioctl_desc i810_ioctls[] = {
+ 	DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+ 	DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
+diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c
+index 88bcd33..0152fa2 100644
+--- a/drivers/gpu/drm/i810/i810_drv.c
++++ b/drivers/gpu/drm/i810/i810_drv.c
+@@ -57,7 +57,7 @@ static struct drm_driver driver = {
+ 		 .owner = THIS_MODULE,
+ 		 .open = drm_open,
+ 		 .release = drm_release,
+-		 .unlocked_ioctl = i810_ioctl,
++		 .unlocked_ioctl = drm_ioctl,
+ 		 .mmap = drm_mmap,
+ 		 .poll = drm_poll,
+ 		 .fasync = drm_fasync,
+@@ -79,6 +79,10 @@ static struct drm_driver driver = {
+ 
+ static int __init i810_init(void)
+ {
++	if (num_possible_cpus() > 1) {
++		pr_err("drm/i810 does not support SMP\n");
++		return -EINVAL;
++	}
+ 	driver.num_ioctls = i810_max_ioctl;
+ 	return drm_init(&driver);
+ }
+-- 
+1.7.4.1
+

Added: dists/trunk/linux-2.6/debian/patches/features/all/staging-usbip-convert-to-kthread.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/trunk/linux-2.6/debian/patches/features/all/staging-usbip-convert-to-kthread.patch	Sun Mar 13 00:52:31 2011	(r17064)
@@ -0,0 +1,609 @@
+From: Arnd Bergmann <arnd at arndb.de>
+Date: Wed, 2 Mar 2011 00:13:05 +0100
+Subject: [PATCH] staging/usbip: convert to kthread
+
+commit 9720b4bc76a83807c68e00c62bfba575251bb73e upstream.
+
+usbip has its own infrastructure for managing kernel
+threads, similar to kthread. By changing it to use
+the standard functions, we can simplify the code
+and get rid of one of the last BKL users at the
+same time.
+
+Includes changes suggested by Max Vozeler.
+
+Signed-off-by: Arnd Bergmann <arnd at arndb.de>
+Cc: Greg Kroah-Hartman <gregkh at suse.de>
+Cc: Takahiro Hirofuchi <hirofuchi at users.sourceforge.net>
+Cc: Max Vozeler <max at vozeler.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ drivers/staging/usbip/Kconfig        |    2 +-
+ drivers/staging/usbip/stub.h         |    4 +-
+ drivers/staging/usbip/stub_dev.c     |   12 ++--
+ drivers/staging/usbip/stub_rx.c      |   13 ++---
+ drivers/staging/usbip/stub_tx.c      |   17 +++---
+ drivers/staging/usbip/usbip_common.c |  105 ----------------------------------
+ drivers/staging/usbip/usbip_common.h |   20 +------
+ drivers/staging/usbip/usbip_event.c  |   38 ++++--------
+ drivers/staging/usbip/vhci.h         |    4 +-
+ drivers/staging/usbip/vhci_hcd.c     |   10 ++-
+ drivers/staging/usbip/vhci_rx.c      |   16 ++---
+ drivers/staging/usbip/vhci_sysfs.c   |    9 +--
+ drivers/staging/usbip/vhci_tx.c      |   17 +++---
+ 13 files changed, 64 insertions(+), 203 deletions(-)
+
+diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig
+index b11ec37..2c1d10a 100644
+--- a/drivers/staging/usbip/Kconfig
++++ b/drivers/staging/usbip/Kconfig
+@@ -1,6 +1,6 @@
+ config USB_IP_COMMON
+ 	tristate "USB IP support (EXPERIMENTAL)"
+-	depends on USB && NET && EXPERIMENTAL && BKL
++	depends on USB && NET && EXPERIMENTAL
+ 	default N
+ 	---help---
+ 	  This enables pushing USB packets over IP to allow remote
+diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h
+index d732679..6004fcd 100644
+--- a/drivers/staging/usbip/stub.h
++++ b/drivers/staging/usbip/stub.h
+@@ -95,13 +95,13 @@ extern struct kmem_cache *stub_priv_cache;
+ 
+ /* stub_tx.c */
+ void stub_complete(struct urb *);
+-void stub_tx_loop(struct usbip_task *);
++int stub_tx_loop(void *data);
+ 
+ /* stub_dev.c */
+ extern struct usb_driver stub_driver;
+ 
+ /* stub_rx.c */
+-void stub_rx_loop(struct usbip_task *);
++int stub_rx_loop(void *data);
+ void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32);
+ 
+ /* stub_main.c */
+diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
+index a7ce51c..8214c35 100644
+--- a/drivers/staging/usbip/stub_dev.c
++++ b/drivers/staging/usbip/stub_dev.c
+@@ -18,6 +18,7 @@
+  */
+ 
+ #include <linux/slab.h>
++#include <linux/kthread.h>
+ 
+ #include "usbip_common.h"
+ #include "stub.h"
+@@ -138,7 +139,8 @@ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
+ 
+ 		spin_unlock(&sdev->ud.lock);
+ 
+-		usbip_start_threads(&sdev->ud);
++		sdev->ud.tcp_rx = kthread_run(stub_rx_loop, &sdev->ud, "stub_rx");
++		sdev->ud.tcp_tx = kthread_run(stub_tx_loop, &sdev->ud, "stub_tx");
+ 
+ 		spin_lock(&sdev->ud.lock);
+ 		sdev->ud.status = SDEV_ST_USED;
+@@ -218,7 +220,8 @@ static void stub_shutdown_connection(struct usbip_device *ud)
+ 	}
+ 
+ 	/* 1. stop threads */
+-	usbip_stop_threads(ud);
++	kthread_stop(ud->tcp_rx);
++	kthread_stop(ud->tcp_tx);
+ 
+ 	/* 2. close the socket */
+ 	/*
+@@ -336,9 +339,6 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev,
+ 	 */
+ 	sdev->devid     = (busnum << 16) | devnum;
+ 
+-	usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop);
+-	usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop);
+-
+ 	sdev->ud.side = USBIP_STUB;
+ 	sdev->ud.status = SDEV_ST_AVAILABLE;
+ 	/* sdev->ud.lock = SPIN_LOCK_UNLOCKED; */
+@@ -543,7 +543,7 @@ static void stub_disconnect(struct usb_interface *interface)
+ 	stub_remove_files(&interface->dev);
+ 
+ 	/*If usb reset called from event handler*/
+-	if (busid_priv->sdev->ud.eh.thread == current) {
++	if (busid_priv->sdev->ud.eh == current) {
+ 		busid_priv->interf_count--;
+ 		return;
+ 	}
+diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
+index ae6ac82..6445f12 100644
+--- a/drivers/staging/usbip/stub_rx.c
++++ b/drivers/staging/usbip/stub_rx.c
+@@ -18,6 +18,7 @@
+  */
+ 
+ #include <linux/slab.h>
++#include <linux/kthread.h>
+ 
+ #include "usbip_common.h"
+ #include "stub.h"
+@@ -616,19 +617,15 @@ static void stub_rx_pdu(struct usbip_device *ud)
+ 
+ }
+ 
+-void stub_rx_loop(struct usbip_task *ut)
++int stub_rx_loop(void *data)
+ {
+-	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx);
+-
+-	while (1) {
+-		if (signal_pending(current)) {
+-			usbip_dbg_stub_rx("signal caught!\n");
+-			break;
+-		}
++	struct usbip_device *ud = data;
+ 
++	while (!kthread_should_stop()) {
+ 		if (usbip_event_happened(ud))
+ 			break;
+ 
+ 		stub_rx_pdu(ud);
+ 	}
++	return 0;
+ }
+diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c
+index d7136e2..5523f25 100644
+--- a/drivers/staging/usbip/stub_tx.c
++++ b/drivers/staging/usbip/stub_tx.c
+@@ -18,6 +18,7 @@
+  */
+ 
+ #include <linux/slab.h>
++#include <linux/kthread.h>
+ 
+ #include "usbip_common.h"
+ #include "stub.h"
+@@ -333,17 +334,12 @@ static int stub_send_ret_unlink(struct stub_device *sdev)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-void stub_tx_loop(struct usbip_task *ut)
++int stub_tx_loop(void *data)
+ {
+-	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx);
++	struct usbip_device *ud = data;
+ 	struct stub_device *sdev = container_of(ud, struct stub_device, ud);
+ 
+-	while (1) {
+-		if (signal_pending(current)) {
+-			usbip_dbg_stub_tx("signal catched\n");
+-			break;
+-		}
+-
++	while (!kthread_should_stop()) {
+ 		if (usbip_event_happened(ud))
+ 			break;
+ 
+@@ -369,6 +365,9 @@ void stub_tx_loop(struct usbip_task *ut)
+ 
+ 		wait_event_interruptible(sdev->tx_waitq,
+ 				(!list_empty(&sdev->priv_tx) ||
+-				 !list_empty(&sdev->unlink_tx)));
++				 !list_empty(&sdev->unlink_tx) ||
++				 kthread_should_stop()));
+ 	}
++
++	return 0;
+ }
+diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
+index 210ef16..337abc4 100644
+--- a/drivers/staging/usbip/usbip_common.c
++++ b/drivers/staging/usbip/usbip_common.c
+@@ -18,7 +18,6 @@
+  */
+ 
+ #include <linux/kernel.h>
+-#include <linux/smp_lock.h>
+ #include <linux/file.h>
+ #include <linux/tcp.h>
+ #include <linux/in.h>
+@@ -349,110 +348,6 @@ void usbip_dump_header(struct usbip_header *pdu)
+ }
+ EXPORT_SYMBOL_GPL(usbip_dump_header);
+ 
+-
+-/*-------------------------------------------------------------------------*/
+-/* thread routines */
+-
+-int usbip_thread(void *param)
+-{
+-	struct usbip_task *ut = param;
+-
+-	if (!ut)
+-		return -EINVAL;
+-
+-	lock_kernel();
+-	daemonize(ut->name);
+-	allow_signal(SIGKILL);
+-	ut->thread = current;
+-	unlock_kernel();
+-
+-	/* srv.rb must wait for rx_thread starting */
+-	complete(&ut->thread_done);
+-
+-	/* start of while loop */
+-	ut->loop_ops(ut);
+-
+-	/* end of loop */
+-	ut->thread = NULL;
+-
+-	complete_and_exit(&ut->thread_done, 0);
+-}
+-
+-static void stop_rx_thread(struct usbip_device *ud)
+-{
+-	if (ud->tcp_rx.thread != NULL) {
+-		send_sig(SIGKILL, ud->tcp_rx.thread, 1);
+-		wait_for_completion(&ud->tcp_rx.thread_done);
+-		usbip_udbg("rx_thread for ud %p has finished\n", ud);
+-	}
+-}
+-
+-static void stop_tx_thread(struct usbip_device *ud)
+-{
+-	if (ud->tcp_tx.thread != NULL) {
+-		send_sig(SIGKILL, ud->tcp_tx.thread, 1);
+-		wait_for_completion(&ud->tcp_tx.thread_done);
+-		usbip_udbg("tx_thread for ud %p has finished\n", ud);
+-	}
+-}
+-
+-int usbip_start_threads(struct usbip_device *ud)
+-{
+-	/*
+-	 * threads are invoked per one device (per one connection).
+-	 */
+-	struct task_struct *th;
+-	int err = 0;
+-
+-	th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
+-	if (IS_ERR(th)) {
+-		printk(KERN_WARNING
+-			"Unable to start control thread\n");
+-		err = PTR_ERR(th);
+-		goto ust_exit;
+-	}
+-
+-	th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
+-	if (IS_ERR(th)) {
+-		printk(KERN_WARNING
+-			"Unable to start control thread\n");
+-		err = PTR_ERR(th);
+-		goto tx_thread_err;
+-	}
+-
+-	/* confirm threads are starting */
+-	wait_for_completion(&ud->tcp_rx.thread_done);
+-	wait_for_completion(&ud->tcp_tx.thread_done);
+-
+-	return 0;
+-
+-tx_thread_err:
+-	stop_rx_thread(ud);
+-
+-ust_exit:
+-	return err;
+-}
+-EXPORT_SYMBOL_GPL(usbip_start_threads);
+-
+-void usbip_stop_threads(struct usbip_device *ud)
+-{
+-	/* kill threads related to this sdev, if v.c. exists */
+-	stop_rx_thread(ud);
+-	stop_tx_thread(ud);
+-}
+-EXPORT_SYMBOL_GPL(usbip_stop_threads);
+-
+-void usbip_task_init(struct usbip_task *ut, char *name,
+-		void (*loop_ops)(struct usbip_task *))
+-{
+-	ut->thread = NULL;
+-	init_completion(&ut->thread_done);
+-	ut->name = name;
+-	ut->loop_ops = loop_ops;
+-}
+-EXPORT_SYMBOL_GPL(usbip_task_init);
+-
+-
+ /*-------------------------------------------------------------------------*/
+ /* socket routines */
+ 
+diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
+index d280e23..9f809c3 100644
+--- a/drivers/staging/usbip/usbip_common.h
++++ b/drivers/staging/usbip/usbip_common.h
+@@ -307,13 +307,6 @@ void usbip_dump_header(struct usbip_header *pdu);
+ 
+ struct usbip_device;
+ 
+-struct usbip_task {
+-	struct task_struct *thread;
+-	struct completion thread_done;
+-	char *name;
+-	void (*loop_ops)(struct usbip_task *);
+-};
+-
+ enum usbip_side {
+ 	USBIP_VHCI,
+ 	USBIP_STUB,
+@@ -346,8 +339,8 @@ struct usbip_device {
+ 
+ 	struct socket *tcp_socket;
+ 
+-	struct usbip_task tcp_rx;
+-	struct usbip_task tcp_tx;
++	struct task_struct *tcp_rx;
++	struct task_struct *tcp_tx;
+ 
+ 	/* event handler */
+ #define USBIP_EH_SHUTDOWN	(1 << 0)
+@@ -367,7 +360,7 @@ struct usbip_device {
+ #define	VDEV_EVENT_ERROR_MALLOC	(USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)
+ 
+ 	unsigned long event;
+-	struct usbip_task eh;
++	struct task_struct *eh;
+ 	wait_queue_head_t eh_waitq;
+ 
+ 	struct eh_ops {
+@@ -378,13 +371,6 @@ struct usbip_device {
+ };
+ 
+ 
+-void usbip_task_init(struct usbip_task *ut, char *,
+-				void (*loop_ops)(struct usbip_task *));
+-
+-int usbip_start_threads(struct usbip_device *ud);
+-void usbip_stop_threads(struct usbip_device *ud);
+-int usbip_thread(void *param);
+-
+ void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
+ 								int pack);
+ 
+diff --git a/drivers/staging/usbip/usbip_event.c b/drivers/staging/usbip/usbip_event.c
+index af3832b..f4b287e 100644
+--- a/drivers/staging/usbip/usbip_event.c
++++ b/drivers/staging/usbip/usbip_event.c
+@@ -62,55 +62,43 @@ static int event_handler(struct usbip_device *ud)
+ 	return 0;
+ }
+ 
+-static void event_handler_loop(struct usbip_task *ut)
++static int event_handler_loop(void *data)
+ {
+-	struct usbip_device *ud = container_of(ut, struct usbip_device, eh);
++	struct usbip_device *ud = data;
+ 
+-	while (1) {
+-		if (signal_pending(current)) {
+-			usbip_dbg_eh("signal catched!\n");
+-			break;
+-		}
++	while (!kthread_should_stop()) {
++		wait_event_interruptible(ud->eh_waitq,
++					usbip_event_happened(ud) ||
++					kthread_should_stop());
++		usbip_dbg_eh("wakeup\n");
+ 
+ 		if (event_handler(ud) < 0)
+ 			break;
+-
+-		wait_event_interruptible(ud->eh_waitq,
+-					usbip_event_happened(ud));
+-		usbip_dbg_eh("wakeup\n");
+ 	}
++	return 0;
+ }
+ 
+ int usbip_start_eh(struct usbip_device *ud)
+ {
+-	struct usbip_task *eh = &ud->eh;
+-	struct task_struct *th;
+-
+ 	init_waitqueue_head(&ud->eh_waitq);
+ 	ud->event = 0;
+ 
+-	usbip_task_init(eh, "usbip_eh", event_handler_loop);
+-
+-	th = kthread_run(usbip_thread, (void *)eh, "usbip");
+-	if (IS_ERR(th)) {
++	ud->eh = kthread_run(event_handler_loop, ud, "usbip_eh");
++	if (IS_ERR(ud->eh)) {
+ 		printk(KERN_WARNING
+ 			"Unable to start control thread\n");
+-		return PTR_ERR(th);
++		return PTR_ERR(ud->eh);
+ 	}
+-
+-	wait_for_completion(&eh->thread_done);
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(usbip_start_eh);
+ 
+ void usbip_stop_eh(struct usbip_device *ud)
+ {
+-	struct usbip_task *eh = &ud->eh;
+-
+-	if (eh->thread == current)
++	if (ud->eh == current)
+ 		return; /* do not wait for myself */
+ 
+-	wait_for_completion(&eh->thread_done);
++	kthread_stop(ud->eh);
+ 	usbip_dbg_eh("usbip_eh has finished\n");
+ }
+ EXPORT_SYMBOL_GPL(usbip_stop_eh);
+diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h
+index afc3b1a..d3f1e5f 100644
+--- a/drivers/staging/usbip/vhci.h
++++ b/drivers/staging/usbip/vhci.h
+@@ -113,8 +113,8 @@ extern struct attribute_group dev_attr_group;
+ /* vhci_hcd.c */
+ void rh_port_connect(int rhport, enum usb_device_speed speed);
+ void rh_port_disconnect(int rhport);
+-void vhci_rx_loop(struct usbip_task *ut);
+-void vhci_tx_loop(struct usbip_task *ut);
++int vhci_rx_loop(void *data);
++int vhci_tx_loop(void *data);
+ 
+ struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev,
+ 					    __u32 seqnum);
+diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
+index a35fe61..36ae9fb 100644
+--- a/drivers/staging/usbip/vhci_hcd.c
++++ b/drivers/staging/usbip/vhci_hcd.c
+@@ -18,6 +18,7 @@
+  */
+ 
+ #include <linux/slab.h>
++#include <linux/kthread.h>
+ 
+ #include "usbip_common.h"
+ #include "vhci.h"
+@@ -874,7 +875,10 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
+ 		kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
+ 	}
+ 
+-	usbip_stop_threads(&vdev->ud);
++	/* kill threads related to this sdev, if v.c. exists */
++	kthread_stop(vdev->ud.tcp_rx);
++	kthread_stop(vdev->ud.tcp_tx);
++
+ 	usbip_uinfo("stop threads\n");
+ 
+ 	/* active connection is closed */
+@@ -945,8 +949,8 @@ static void vhci_device_init(struct vhci_device *vdev)
+ {
+ 	memset(vdev, 0, sizeof(*vdev));
+ 
+-	usbip_task_init(&vdev->ud.tcp_rx, "vhci_rx", vhci_rx_loop);
+-	usbip_task_init(&vdev->ud.tcp_tx, "vhci_tx", vhci_tx_loop);
++	vdev->ud.tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
++	vdev->ud.tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
+ 
+ 	vdev->ud.side   = USBIP_VHCI;
+ 	vdev->ud.status = VDEV_ST_NULL;
+diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
+index bf69914..09bf235 100644
+--- a/drivers/staging/usbip/vhci_rx.c
++++ b/drivers/staging/usbip/vhci_rx.c
+@@ -18,6 +18,7 @@
+  */
+ 
+ #include <linux/slab.h>
++#include <linux/kthread.h>
+ 
+ #include "usbip_common.h"
+ #include "vhci.h"
+@@ -269,22 +270,17 @@ static void vhci_rx_pdu(struct usbip_device *ud)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-void vhci_rx_loop(struct usbip_task *ut)
++int vhci_rx_loop(void *data)
+ {
+-	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx);
+-
+-
+-	while (1) {
+-		if (signal_pending(current)) {
+-			usbip_dbg_vhci_rx("signal catched!\n");
+-			break;
+-		}
++	struct usbip_device *ud = data;
+ 
+ 
++	while (!kthread_should_stop()) {
+ 		if (usbip_event_happened(ud))
+ 			break;
+ 
+ 		vhci_rx_pdu(ud);
+ 	}
+-}
+ 
++	return 0;
++}
+diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
+index f6e34e0..3f2459f 100644
+--- a/drivers/staging/usbip/vhci_sysfs.c
++++ b/drivers/staging/usbip/vhci_sysfs.c
+@@ -220,16 +220,13 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
+ 	vdev->ud.tcp_socket = socket;
+ 	vdev->ud.status     = VDEV_ST_NOTASSIGNED;
+ 
++	wake_up_process(vdev->ud.tcp_rx);
++	wake_up_process(vdev->ud.tcp_tx);
++
+ 	spin_unlock(&vdev->ud.lock);
+ 	spin_unlock(&the_controller->lock);
+ 	/* end the lock */
+ 
+-	/*
+-	 * this function will sleep, so should be out of the lock. but, it's ok
+-	 * because we already marked vdev as being used. really?
+-	 */
+-	usbip_start_threads(&vdev->ud);
+-
+ 	rh_port_connect(rhport, speed);
+ 
+ 	return count;
+diff --git a/drivers/staging/usbip/vhci_tx.c b/drivers/staging/usbip/vhci_tx.c
+index e1c1f71..d9ab49d 100644
+--- a/drivers/staging/usbip/vhci_tx.c
++++ b/drivers/staging/usbip/vhci_tx.c
+@@ -18,6 +18,7 @@
+  */
+ 
+ #include <linux/slab.h>
++#include <linux/kthread.h>
+ 
+ #include "usbip_common.h"
+ #include "vhci.h"
+@@ -215,17 +216,12 @@ static int vhci_send_cmd_unlink(struct vhci_device *vdev)
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+-void vhci_tx_loop(struct usbip_task *ut)
++int vhci_tx_loop(void *data)
+ {
+-	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx);
++	struct usbip_device *ud = data;
+ 	struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+ 
+-	while (1) {
+-		if (signal_pending(current)) {
+-			usbip_uinfo("vhci_tx signal catched\n");
+-			break;
+-		}
+-
++	while (!kthread_should_stop()) {
+ 		if (vhci_send_cmd_submit(vdev) < 0)
+ 			break;
+ 
+@@ -234,8 +230,11 @@ void vhci_tx_loop(struct usbip_task *ut)
+ 
+ 		wait_event_interruptible(vdev->waitq_tx,
+ 				(!list_empty(&vdev->priv_tx) ||
+-				 !list_empty(&vdev->unlink_tx)));
++				 !list_empty(&vdev->unlink_tx) ||
++				 kthread_should_stop()));
+ 
+ 		usbip_dbg_vhci_tx("pending urbs ?, now wake up\n");
+ 	}
++
++	return 0;
+ }
+-- 
+1.7.4.1
+

Added: dists/trunk/linux-2.6/debian/patches/features/all/ufs-remove-the-BKL.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/trunk/linux-2.6/debian/patches/features/all/ufs-remove-the-BKL.patch	Sun Mar 13 00:52:31 2011	(r17064)
@@ -0,0 +1,695 @@
+From: Arnd Bergmann <arnd at arndb.de>
+Date: Mon, 24 Jan 2011 10:14:12 +0100
+Subject: [PATCH] ufs: remove the BKL
+
+commit 788257d6101d986ac8f2741aaa35974af47f574c upstream.
+
+This introduces a new per-superblock mutex in UFS to replace
+the big kernel lock. I have been careful to avoid nested
+calls to lock_ufs and to get the lock order right with
+respect to other mutexes, in particular lock_super.
+
+I did not make any attempt to prove that the big kernel
+lock is not needed in a particular place in the code,
+which is very possible.
+
+The mutex has a significant performance impact, so it is only
+used on SMP or PREEMPT configurations.
+
+As Nick Piggin noticed, any allocation inside of the lock
+may end up deadlocking when we get to ufs_getfrag_block
+in the reclaim task, so we now use GFP_NOFS.
+
+Signed-off-by: Arnd Bergmann <arnd at arndb.de>
+Tested-by: Nick Bowler <nbowler at elliptictech.com>
+Cc: Evgeniy Dushistov <dushistov at mail.ru>
+Cc: Nick Piggin <npiggin at gmail.com>
+---
+ fs/ufs/Kconfig    |    1 -
+ fs/ufs/inode.c    |   78 ++++++++++++++--------------------------------------
+ fs/ufs/namei.c    |   35 +++++++++++------------
+ fs/ufs/super.c    |   64 +++++++++++++++++++++++++------------------
+ fs/ufs/truncate.c |    5 +--
+ fs/ufs/ufs.h      |    6 +++-
+ fs/ufs/util.c     |    2 +-
+ 7 files changed, 83 insertions(+), 108 deletions(-)
+
+diff --git a/fs/ufs/Kconfig b/fs/ufs/Kconfig
+index 30c8f22..e4f10a4 100644
+--- a/fs/ufs/Kconfig
++++ b/fs/ufs/Kconfig
+@@ -1,7 +1,6 @@
+ config UFS_FS
+ 	tristate "UFS file system support (read only)"
+ 	depends on BLOCK
+-	depends on BKL # probably fixable
+ 	help
+ 	  BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
+ 	  OpenBSD and NeXTstep) use a file system called UFS. Some System V
+diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
+index 2b251f2..03c255f 100644
+--- a/fs/ufs/inode.c
++++ b/fs/ufs/inode.c
+@@ -34,7 +34,6 @@
+ #include <linux/stat.h>
+ #include <linux/string.h>
+ #include <linux/mm.h>
+-#include <linux/smp_lock.h>
+ #include <linux/buffer_head.h>
+ #include <linux/writeback.h>
+ 
+@@ -43,7 +42,7 @@
+ #include "swab.h"
+ #include "util.h"
+ 
+-static u64 ufs_frag_map(struct inode *inode, sector_t frag);
++static u64 ufs_frag_map(struct inode *inode, sector_t frag, bool needs_lock);
+ 
+ static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t offsets[4])
+ {
+@@ -82,7 +81,7 @@ static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t off
+  * the begining of the filesystem.
+  */
+ 
+-static u64 ufs_frag_map(struct inode *inode, sector_t frag)
++static u64 ufs_frag_map(struct inode *inode, sector_t frag, bool needs_lock)
+ {
+ 	struct ufs_inode_info *ufsi = UFS_I(inode);
+ 	struct super_block *sb = inode->i_sb;
+@@ -107,7 +106,8 @@ static u64 ufs_frag_map(struct inode *inode, sector_t frag)
+ 
+ 	p = offsets;
+ 
+-	lock_kernel();
++	if (needs_lock)
++		lock_ufs(sb);
+ 	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
+ 		goto ufs2;
+ 
+@@ -152,7 +152,8 @@ ufs2:
+ 	ret = temp + (u64) (frag & uspi->s_fpbmask);
+ 
+ out:
+-	unlock_kernel();
++	if (needs_lock)
++		unlock_ufs(sb);
+ 	return ret;
+ }
+ 
+@@ -415,14 +416,16 @@ out:
+ int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
+ {
+ 	struct super_block * sb = inode->i_sb;
+-	struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi;
++	struct ufs_sb_info * sbi = UFS_SB(sb);
++	struct ufs_sb_private_info * uspi = sbi->s_uspi;
+ 	struct buffer_head * bh;
+ 	int ret, err, new;
+ 	unsigned long ptr,phys;
+ 	u64 phys64 = 0;
++	bool needs_lock = (sbi->mutex_owner != current);
+ 	
+ 	if (!create) {
+-		phys64 = ufs_frag_map(inode, fragment);
++		phys64 = ufs_frag_map(inode, fragment, needs_lock);
+ 		UFSD("phys64 = %llu\n", (unsigned long long)phys64);
+ 		if (phys64)
+ 			map_bh(bh_result, sb, phys64);
+@@ -436,7 +439,8 @@ int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head
+ 	ret = 0;
+ 	bh = NULL;
+ 
+-	lock_kernel();
++	if (needs_lock)
++		lock_ufs(sb);
+ 
+ 	UFSD("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment);
+ 	if (fragment >
+@@ -498,7 +502,9 @@ out:
+ 		set_buffer_new(bh_result);
+ 	map_bh(bh_result, sb, phys);
+ abort:
+-	unlock_kernel();
++	if (needs_lock)
++		unlock_ufs(sb);
++
+ 	return err;
+ 
+ abort_too_big:
+@@ -506,48 +512,6 @@ abort_too_big:
+ 	goto abort;
+ }
+ 
+-static struct buffer_head *ufs_getfrag(struct inode *inode,
+-				       unsigned int fragment,
+-				       int create, int *err)
+-{
+-	struct buffer_head dummy;
+-	int error;
+-
+-	dummy.b_state = 0;
+-	dummy.b_blocknr = -1000;
+-	error = ufs_getfrag_block(inode, fragment, &dummy, create);
+-	*err = error;
+-	if (!error && buffer_mapped(&dummy)) {
+-		struct buffer_head *bh;
+-		bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
+-		if (buffer_new(&dummy)) {
+-			memset(bh->b_data, 0, inode->i_sb->s_blocksize);
+-			set_buffer_uptodate(bh);
+-			mark_buffer_dirty(bh);
+-		}
+-		return bh;
+-	}
+-	return NULL;
+-}
+-
+-struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment,
+-	int create, int * err)
+-{
+-	struct buffer_head * bh;
+-
+-	UFSD("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment);
+-	bh = ufs_getfrag (inode, fragment, create, err);
+-	if (!bh || buffer_uptodate(bh)) 		
+-		return bh;
+-	ll_rw_block (READ, 1, &bh);
+-	wait_on_buffer (bh);
+-	if (buffer_uptodate(bh))
+-		return bh;
+-	brelse (bh);
+-	*err = -EIO;
+-	return NULL;
+-}
+-
+ static int ufs_writepage(struct page *page, struct writeback_control *wbc)
+ {
+ 	return block_write_full_page(page,ufs_getfrag_block,wbc);
+@@ -900,9 +864,9 @@ static int ufs_update_inode(struct inode * inode, int do_sync)
+ int ufs_write_inode(struct inode *inode, struct writeback_control *wbc)
+ {
+ 	int ret;
+-	lock_kernel();
++	lock_ufs(inode->i_sb);
+ 	ret = ufs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+-	unlock_kernel();
++	unlock_ufs(inode->i_sb);
+ 	return ret;
+ }
+ 
+@@ -922,22 +886,22 @@ void ufs_evict_inode(struct inode * inode)
+ 	if (want_delete) {
+ 		loff_t old_i_size;
+ 		/*UFS_I(inode)->i_dtime = CURRENT_TIME;*/
+-		lock_kernel();
++		lock_ufs(inode->i_sb);
+ 		mark_inode_dirty(inode);
+ 		ufs_update_inode(inode, IS_SYNC(inode));
+ 		old_i_size = inode->i_size;
+ 		inode->i_size = 0;
+ 		if (inode->i_blocks && ufs_truncate(inode, old_i_size))
+ 			ufs_warning(inode->i_sb, __func__, "ufs_truncate failed\n");
+-		unlock_kernel();
++		unlock_ufs(inode->i_sb);
+ 	}
+ 
+ 	invalidate_inode_buffers(inode);
+ 	end_writeback(inode);
+ 
+ 	if (want_delete) {
+-		lock_kernel();
++		lock_ufs(inode->i_sb);
+ 		ufs_free_inode (inode);
+-		unlock_kernel();
++		unlock_ufs(inode->i_sb);
+ 	}
+ }
+diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
+index 12f39b9..205030a 100644
+--- a/fs/ufs/namei.c
++++ b/fs/ufs/namei.c
+@@ -29,7 +29,6 @@
+ 
+ #include <linux/time.h>
+ #include <linux/fs.h>
+-#include <linux/smp_lock.h>
+ 
+ #include "ufs_fs.h"
+ #include "ufs.h"
+@@ -55,16 +54,16 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, stru
+ 	if (dentry->d_name.len > UFS_MAXNAMLEN)
+ 		return ERR_PTR(-ENAMETOOLONG);
+ 
+-	lock_kernel();
++	lock_ufs(dir->i_sb);
+ 	ino = ufs_inode_by_name(dir, &dentry->d_name);
+ 	if (ino) {
+ 		inode = ufs_iget(dir->i_sb, ino);
+ 		if (IS_ERR(inode)) {
+-			unlock_kernel();
++			unlock_ufs(dir->i_sb);
+ 			return ERR_CAST(inode);
+ 		}
+ 	}
+-	unlock_kernel();
++	unlock_ufs(dir->i_sb);
+ 	d_add(dentry, inode);
+ 	return NULL;
+ }
+@@ -93,9 +92,9 @@ static int ufs_create (struct inode * dir, struct dentry * dentry, int mode,
+ 		inode->i_fop = &ufs_file_operations;
+ 		inode->i_mapping->a_ops = &ufs_aops;
+ 		mark_inode_dirty(inode);
+-		lock_kernel();
++		lock_ufs(dir->i_sb);
+ 		err = ufs_add_nondir(dentry, inode);
+-		unlock_kernel();
++		unlock_ufs(dir->i_sb);
+ 	}
+ 	UFSD("END: err=%d\n", err);
+ 	return err;
+@@ -115,9 +114,9 @@ static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t
+ 		init_special_inode(inode, mode, rdev);
+ 		ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev);
+ 		mark_inode_dirty(inode);
+-		lock_kernel();
++		lock_ufs(dir->i_sb);
+ 		err = ufs_add_nondir(dentry, inode);
+-		unlock_kernel();
++		unlock_ufs(dir->i_sb);
+ 	}
+ 	return err;
+ }
+@@ -133,7 +132,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
+ 	if (l > sb->s_blocksize)
+ 		goto out_notlocked;
+ 
+-	lock_kernel();
++	lock_ufs(dir->i_sb);
+ 	inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
+ 	err = PTR_ERR(inode);
+ 	if (IS_ERR(inode))
+@@ -156,7 +155,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
+ 
+ 	err = ufs_add_nondir(dentry, inode);
+ out:
+-	unlock_kernel();
++	unlock_ufs(dir->i_sb);
+ out_notlocked:
+ 	return err;
+ 
+@@ -172,9 +171,9 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
+ 	struct inode *inode = old_dentry->d_inode;
+ 	int error;
+ 
+-	lock_kernel();
++	lock_ufs(dir->i_sb);
+ 	if (inode->i_nlink >= UFS_LINK_MAX) {
+-		unlock_kernel();
++		unlock_ufs(dir->i_sb);
+ 		return -EMLINK;
+ 	}
+ 
+@@ -183,7 +182,7 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
+ 	ihold(inode);
+ 
+ 	error = ufs_add_nondir(dentry, inode);
+-	unlock_kernel();
++	unlock_ufs(dir->i_sb);
+ 	return error;
+ }
+ 
+@@ -195,7 +194,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+ 	if (dir->i_nlink >= UFS_LINK_MAX)
+ 		goto out;
+ 
+-	lock_kernel();
++	lock_ufs(dir->i_sb);
+ 	inode_inc_link_count(dir);
+ 
+ 	inode = ufs_new_inode(dir, S_IFDIR|mode);
+@@ -216,7 +215,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+ 	err = ufs_add_link(dentry, inode);
+ 	if (err)
+ 		goto out_fail;
+-	unlock_kernel();
++	unlock_ufs(dir->i_sb);
+ 
+ 	d_instantiate(dentry, inode);
+ out:
+@@ -228,7 +227,7 @@ out_fail:
+ 	iput (inode);
+ out_dir:
+ 	inode_dec_link_count(dir);
+-	unlock_kernel();
++	unlock_ufs(dir->i_sb);
+ 	goto out;
+ }
+ 
+@@ -259,7 +258,7 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
+ 	struct inode * inode = dentry->d_inode;
+ 	int err= -ENOTEMPTY;
+ 
+-	lock_kernel();
++	lock_ufs(dir->i_sb);
+ 	if (ufs_empty_dir (inode)) {
+ 		err = ufs_unlink(dir, dentry);
+ 		if (!err) {
+@@ -268,7 +267,7 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
+ 			inode_dec_link_count(dir);
+ 		}
+ 	}
+-	unlock_kernel();
++	unlock_ufs(dir->i_sb);
+ 	return err;
+ }
+ 
+diff --git a/fs/ufs/super.c b/fs/ufs/super.c
+index 2c61ac5..7693d62 100644
+--- a/fs/ufs/super.c
++++ b/fs/ufs/super.c
+@@ -84,7 +84,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/init.h>
+ #include <linux/parser.h>
+-#include <linux/smp_lock.h>
+ #include <linux/buffer_head.h>
+ #include <linux/vfs.h>
+ #include <linux/log2.h>
+@@ -96,6 +95,26 @@
+ #include "swab.h"
+ #include "util.h"
+ 
++void lock_ufs(struct super_block *sb)
++{
++#if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT)
++	struct ufs_sb_info *sbi = UFS_SB(sb);
++
++	mutex_lock(&sbi->mutex);
++	sbi->mutex_owner = current;
++#endif
++}
++
++void unlock_ufs(struct super_block *sb)
++{
++#if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT)
++	struct ufs_sb_info *sbi = UFS_SB(sb);
++
++	sbi->mutex_owner = NULL;
++	mutex_unlock(&sbi->mutex);
++#endif
++}
++
+ static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation)
+ {
+ 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+@@ -313,7 +332,6 @@ void ufs_panic (struct super_block * sb, const char * function,
+ 	struct ufs_super_block_first * usb1;
+ 	va_list args;
+ 	
+-	lock_kernel();
+ 	uspi = UFS_SB(sb)->s_uspi;
+ 	usb1 = ubh_get_usb_first(uspi);
+ 	
+@@ -521,7 +539,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
+ 	 */
+ 	size = uspi->s_cssize;
+ 	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
+-	base = space = kmalloc(size, GFP_KERNEL);
++	base = space = kmalloc(size, GFP_NOFS);
+ 	if (!base)
+ 		goto failed; 
+ 	sbi->s_csp = (struct ufs_csum *)space;
+@@ -546,7 +564,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
+ 	 * Read cylinder group (we read only first fragment from block
+ 	 * at this time) and prepare internal data structures for cg caching.
+ 	 */
+-	if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL)))
++	if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_NOFS)))
+ 		goto failed;
+ 	for (i = 0; i < uspi->s_ncg; i++) 
+ 		sbi->s_ucg[i] = NULL;
+@@ -564,7 +582,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
+ 		ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data);
+ 	}
+ 	for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
+-		if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL)))
++		if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_NOFS)))
+ 			goto failed;
+ 		sbi->s_cgno[i] = UFS_CGNO_EMPTY;
+ 	}
+@@ -646,8 +664,6 @@ static void ufs_put_super_internal(struct super_block *sb)
+ 	
+ 	UFSD("ENTER\n");
+ 
+-	lock_kernel();
+-
+ 	ufs_put_cstotal(sb);
+ 	size = uspi->s_cssize;
+ 	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
+@@ -676,8 +692,6 @@ static void ufs_put_super_internal(struct super_block *sb)
+ 	kfree (sbi->s_ucg);
+ 	kfree (base);
+ 
+-	unlock_kernel();
+-
+ 	UFSD("EXIT\n");
+ }
+ 
+@@ -696,8 +710,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
+ 	unsigned maxsymlen;
+ 	int ret = -EINVAL;
+ 
+-	lock_kernel();
+-
+ 	uspi = NULL;
+ 	ubh = NULL;
+ 	flags = 0;
+@@ -718,6 +730,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
+ 		goto failed;
+ 	}
+ #endif
++	mutex_init(&sbi->mutex);
+ 	/*
+ 	 * Set default mount options
+ 	 * Parse mount options
+@@ -1165,7 +1178,6 @@ magic_found:
+ 			goto failed;
+ 
+ 	UFSD("EXIT\n");
+-	unlock_kernel();
+ 	return 0;
+ 
+ dalloc_failed:
+@@ -1177,12 +1189,10 @@ failed:
+ 	kfree(sbi);
+ 	sb->s_fs_info = NULL;
+ 	UFSD("EXIT (FAILED)\n");
+-	unlock_kernel();
+ 	return ret;
+ 
+ failed_nomem:
+ 	UFSD("EXIT (NOMEM)\n");
+-	unlock_kernel();
+ 	return -ENOMEM;
+ }
+ 
+@@ -1193,8 +1203,8 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
+ 	struct ufs_super_block_third * usb3;
+ 	unsigned flags;
+ 
++	lock_ufs(sb);
+ 	lock_super(sb);
+-	lock_kernel();
+ 
+ 	UFSD("ENTER\n");
+ 
+@@ -1213,8 +1223,8 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
+ 	sb->s_dirt = 0;
+ 
+ 	UFSD("EXIT\n");
+-	unlock_kernel();
+ 	unlock_super(sb);
++	unlock_ufs(sb);
+ 
+ 	return 0;
+ }
+@@ -1256,7 +1266,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
+ 	unsigned new_mount_opt, ufstype;
+ 	unsigned flags;
+ 
+-	lock_kernel();
++	lock_ufs(sb);
+ 	lock_super(sb);
+ 	uspi = UFS_SB(sb)->s_uspi;
+ 	flags = UFS_SB(sb)->s_flags;
+@@ -1272,7 +1282,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
+ 	ufs_set_opt (new_mount_opt, ONERROR_LOCK);
+ 	if (!ufs_parse_options (data, &new_mount_opt)) {
+ 		unlock_super(sb);
+-		unlock_kernel();
++		unlock_ufs(sb);
+ 		return -EINVAL;
+ 	}
+ 	if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) {
+@@ -1280,14 +1290,14 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
+ 	} else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
+ 		printk("ufstype can't be changed during remount\n");
+ 		unlock_super(sb);
+-		unlock_kernel();
++		unlock_ufs(sb);
+ 		return -EINVAL;
+ 	}
+ 
+ 	if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
+ 		UFS_SB(sb)->s_mount_opt = new_mount_opt;
+ 		unlock_super(sb);
+-		unlock_kernel();
++		unlock_ufs(sb);
+ 		return 0;
+ 	}
+ 	
+@@ -1313,7 +1323,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
+ 		printk("ufs was compiled with read-only support, "
+ 		"can't be mounted as read-write\n");
+ 		unlock_super(sb);
+-		unlock_kernel();
++		unlock_ufs(sb);
+ 		return -EINVAL;
+ #else
+ 		if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 
+@@ -1323,13 +1333,13 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
+ 		    ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
+ 			printk("this ufstype is read-only supported\n");
+ 			unlock_super(sb);
+-			unlock_kernel();
++			unlock_ufs(sb);
+ 			return -EINVAL;
+ 		}
+ 		if (!ufs_read_cylinder_structures(sb)) {
+ 			printk("failed during remounting\n");
+ 			unlock_super(sb);
+-			unlock_kernel();
++			unlock_ufs(sb);
+ 			return -EPERM;
+ 		}
+ 		sb->s_flags &= ~MS_RDONLY;
+@@ -1337,7 +1347,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
+ 	}
+ 	UFS_SB(sb)->s_mount_opt = new_mount_opt;
+ 	unlock_super(sb);
+-	unlock_kernel();
++	unlock_ufs(sb);
+ 	return 0;
+ }
+ 
+@@ -1371,7 +1381,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 	struct ufs_super_block_third *usb3;
+ 	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
+ 
+-	lock_kernel();
++	lock_ufs(sb);
+ 
+ 	usb1 = ubh_get_usb_first(uspi);
+ 	usb2 = ubh_get_usb_second(uspi);
+@@ -1395,7 +1405,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
+ 	buf->f_fsid.val[0] = (u32)id;
+ 	buf->f_fsid.val[1] = (u32)(id >> 32);
+ 
+-	unlock_kernel();
++	unlock_ufs(sb);
+ 
+ 	return 0;
+ }
+@@ -1405,7 +1415,7 @@ static struct kmem_cache * ufs_inode_cachep;
+ static struct inode *ufs_alloc_inode(struct super_block *sb)
+ {
+ 	struct ufs_inode_info *ei;
+-	ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_KERNEL);
++	ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_NOFS);
+ 	if (!ei)
+ 		return NULL;
+ 	ei->vfs_inode.i_version = 1;
+diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
+index a58f915..e56a4f5 100644
+--- a/fs/ufs/truncate.c
++++ b/fs/ufs/truncate.c
+@@ -40,7 +40,6 @@
+ #include <linux/time.h>
+ #include <linux/stat.h>
+ #include <linux/string.h>
+-#include <linux/smp_lock.h>
+ #include <linux/buffer_head.h>
+ #include <linux/blkdev.h>
+ #include <linux/sched.h>
+@@ -467,7 +466,6 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size)
+ 
+ 	block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block);
+ 
+-	lock_kernel();
+ 	while (1) {
+ 		retry = ufs_trunc_direct(inode);
+ 		retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK,
+@@ -487,7 +485,6 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size)
+ 
+ 	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+ 	ufsi->i_lastfrag = DIRECT_FRAGMENT;
+-	unlock_kernel();
+ 	mark_inode_dirty(inode);
+ out:
+ 	UFSD("EXIT: err %d\n", err);
+@@ -510,7 +507,9 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr)
+ 		/* XXX(truncate): truncate_setsize should be called last */
+ 		truncate_setsize(inode, attr->ia_size);
+ 
++		lock_ufs(inode->i_sb);
+ 		error = ufs_truncate(inode, old_i_size);
++		unlock_ufs(inode->i_sb);
+ 		if (error)
+ 			return error;
+ 	}
+diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h
+index c08782e..5be2755 100644
+--- a/fs/ufs/ufs.h
++++ b/fs/ufs/ufs.h
+@@ -18,6 +18,8 @@ struct ufs_sb_info {
+ 	unsigned s_cgno[UFS_MAX_GROUP_LOADED];
+ 	unsigned short s_cg_loaded;
+ 	unsigned s_mount_opt;
++	struct mutex mutex;
++	struct task_struct *mutex_owner;
+ };
+ 
+ struct ufs_inode_info {
+@@ -109,7 +111,6 @@ extern struct inode *ufs_iget(struct super_block *, unsigned long);
+ extern int ufs_write_inode (struct inode *, struct writeback_control *);
+ extern int ufs_sync_inode (struct inode *);
+ extern void ufs_evict_inode (struct inode *);
+-extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
+ extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create);
+ 
+ /* namei.c */
+@@ -154,4 +155,7 @@ static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b)
+ 	return do_div(b, uspi->s_fpg);
+ }
+ 
++extern void lock_ufs(struct super_block *sb);
++extern void unlock_ufs(struct super_block *sb);
++
+ #endif /* _UFS_UFS_H */
+diff --git a/fs/ufs/util.c b/fs/ufs/util.c
+index d2c36d5..95425b5 100644
+--- a/fs/ufs/util.c
++++ b/fs/ufs/util.c
+@@ -27,7 +27,7 @@ struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
+ 	if (count > UFS_MAXFRAG)
+ 		return NULL;
+ 	ubh = (struct ufs_buffer_head *)
+-		kmalloc (sizeof (struct ufs_buffer_head), GFP_KERNEL);
++		kmalloc (sizeof (struct ufs_buffer_head), GFP_NOFS);
+ 	if (!ubh)
+ 		return NULL;
+ 	ubh->fragment = fragment;
+-- 
+1.7.4.1
+

Added: dists/trunk/linux-2.6/debian/patches/series/1~experimental.2
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.2	Sun Mar 13 00:52:31 2011	(r17064)
@@ -0,0 +1,5 @@
++ features/all/adfs-remove-the-big-kernel-lock.patch
++ features/all/appletalk-remove-the-BKL.patch
++ features/all/drm-i810-remove-the-BKL.patch
++ features/all/staging-usbip-convert-to-kthread.patch
++ features/all/ufs-remove-the-BKL.patch



More information about the Kernel-svn-changes mailing list