[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