Remove the Big Kernel Lock:
adfs,appletalk,i810,ufs,usbip: Refactor locking hpfs: Disable HPFS_FS svn path=/dists/trunk/linux-2.6/; revision=17064
This commit is contained in:
parent
93ba30a46d
commit
3698777391
|
@ -5,6 +5,9 @@ linux-2.6 (2.6.38~rc8-1~experimental.2) UNRELEASED; urgency=low
|
|||
* 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@decadent.org.uk> Sat, 12 Mar 2011 08:57:58 +0000
|
||||
|
||||
|
|
|
@ -3109,7 +3109,7 @@ CONFIG_HFSPLUS_FS=m
|
|||
##
|
||||
## file: fs/hpfs/Kconfig
|
||||
##
|
||||
CONFIG_HPFS_FS=m
|
||||
# CONFIG_HPFS_FS is not set
|
||||
|
||||
##
|
||||
## file: fs/isofs/Kconfig
|
||||
|
@ -3399,6 +3399,7 @@ CONFIG_XFS_RT=y
|
|||
## 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_TIMER_STATS=y
|
|||
# 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
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
From: Arnd Bergmann <arnd@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@arndb.de>
|
||||
Acked-by: Russell King <rmk@arm.linux.org.uk>
|
||||
Cc: Stuart Swales <stuart.swales.croftnuisk@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
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
From: Arnd Bergmann <arnd@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@arndb.de>
|
||||
Acked-by: David S. Miller <davem@davemloft.net>
|
||||
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
|
||||
Cc: David Miller <davem@davemloft.net>
|
||||
Cc: netdev@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
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
From: Arnd Bergmann <arnd@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@arndb.de>
|
||||
Cc: dri-devel@lists.freedesktop.org
|
||||
Signed-off-by: Dave Airlie <airlied@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
|
||||
|
|
@ -0,0 +1,609 @@
|
|||
From: Arnd Bergmann <arnd@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@arndb.de>
|
||||
Cc: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
Cc: Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>
|
||||
Cc: Max Vozeler <max@vozeler.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@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
|
||||
|
|
@ -0,0 +1,695 @@
|
|||
From: Arnd Bergmann <arnd@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@arndb.de>
|
||||
Tested-by: Nick Bowler <nbowler@elliptictech.com>
|
||||
Cc: Evgeniy Dushistov <dushistov@mail.ru>
|
||||
Cc: Nick Piggin <npiggin@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
|
||||
|
|
@ -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
|
Loading…
Reference in New Issue