2005-04-17 02:20:36 +04:00
/*
2007-09-20 12:31:38 +04:00
* fs / sysfs / bin . c - sysfs binary file implementation
2005-04-17 02:20:36 +04:00
*
* Copyright ( c ) 2003 Patrick Mochel
* Copyright ( c ) 2003 Matthew Wilcox
* Copyright ( c ) 2004 Silicon Graphics , Inc .
2007-09-20 12:31:38 +04:00
* Copyright ( c ) 2007 SUSE Linux Products GmbH
* Copyright ( c ) 2007 Tejun Heo < teheo @ suse . de >
*
* This file is released under the GPLv2 .
*
* Please see Documentation / filesystems / sysfs . txt for more information .
2005-04-17 02:20:36 +04:00
*/
# undef DEBUG
# include <linux/errno.h>
# include <linux/fs.h>
2006-07-11 10:05:25 +04:00
# include <linux/kernel.h>
2005-04-17 02:20:36 +04:00
# include <linux/kobject.h>
# include <linux/module.h>
# include <linux/slab.h>
2007-07-26 18:53:53 +04:00
# include <linux/mutex.h>
2009-03-04 22:57:20 +03:00
# include <linux/mm.h>
2005-04-17 02:20:36 +04:00
# include <asm/uaccess.h>
# include "sysfs.h"
2009-03-04 22:57:20 +03:00
/*
* There ' s one bin_buffer for each open file .
*
* filp - > private_data points to bin_buffer and
* sysfs_dirent - > s_bin_attr . buffers points to a the bin_buffer s
* sysfs_dirent - > s_bin_attr . buffers is protected by sysfs_bin_lock
*/
static DEFINE_MUTEX ( sysfs_bin_lock ) ;
2007-06-13 22:45:16 +04:00
struct bin_buffer {
2009-03-04 22:57:20 +03:00
struct mutex mutex ;
void * buffer ;
int mmapped ;
2009-09-27 22:29:37 +04:00
const struct vm_operations_struct * vm_ops ;
2009-03-04 22:57:20 +03:00
struct file * file ;
struct hlist_node list ;
2007-06-13 22:45:16 +04:00
} ;
2005-04-17 02:20:36 +04:00
static int
2010-05-13 05:28:57 +04:00
fill_read ( struct file * file , char * buffer , loff_t off , size_t count )
2005-04-17 02:20:36 +04:00
{
2010-05-13 05:28:57 +04:00
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
2007-09-20 11:05:11 +04:00
struct bin_attribute * attr = attr_sd - > s_bin_attr . bin_attr ;
struct kobject * kobj = attr_sd - > s_parent - > s_dir . kobj ;
2007-06-13 22:45:16 +04:00
int rc ;
/* need attr_sd for attr, its parent for kobj */
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2007-06-13 22:45:16 +04:00
return - ENODEV ;
2005-04-17 02:20:36 +04:00
2007-06-13 22:45:16 +04:00
rc = - EIO ;
if ( attr - > read )
2010-05-13 05:28:57 +04:00
rc = attr - > read ( file , kobj , attr , buffer , off , count ) ;
2005-04-17 02:20:36 +04:00
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2007-06-13 22:45:16 +04:00
return rc ;
2005-04-17 02:20:36 +04:00
}
static ssize_t
2007-06-13 22:45:13 +04:00
read ( struct file * file , char __user * userbuf , size_t bytes , loff_t * off )
2005-04-17 02:20:36 +04:00
{
2007-06-13 22:45:16 +04:00
struct bin_buffer * bb = file - > private_data ;
2010-05-13 05:28:57 +04:00
int size = file - > f_path . dentry - > d_inode - > i_size ;
2005-04-17 02:20:36 +04:00
loff_t offs = * off ;
2007-06-13 22:45:13 +04:00
int count = min_t ( size_t , bytes , PAGE_SIZE ) ;
sysfs: fix deadlock
On Thu, Sep 11, 2008 at 10:27:10AM +0200, Ingo Molnar wrote:
> and it's working fine on most boxes. One testbox found this new locking
> scenario:
>
> PM: Adding info for No Bus:vcsa7
> EDAC DEBUG: MC0: i82860_check()
>
> =======================================================
> [ INFO: possible circular locking dependency detected ]
> 2.6.27-rc6-tip #1
> -------------------------------------------------------
> X/4873 is trying to acquire lock:
> (&bb->mutex){--..}, at: [<c020ba20>] mmap+0x40/0xa0
>
> but task is already holding lock:
> (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> which lock already depends on the new lock.
>
>
> the existing dependency chain (in reverse order) is:
>
> -> #1 (&mm->mmap_sem){----}:
> [<c017dc96>] validate_chain+0xa96/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c01aa8fb>] might_fault+0x6b/0x90
> [<c040b618>] copy_to_user+0x38/0x60
> [<c020bcfb>] read+0xfb/0x170
> [<c01c09a5>] vfs_read+0x95/0x110
> [<c01c1443>] sys_pread64+0x63/0x80
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> -> #0 (&bb->mutex){--..}:
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> other info that might help us debug this:
>
> 1 lock held by X/4873:
> #0: (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> stack backtrace:
> Pid: 4873, comm: X Not tainted 2.6.27-rc6-tip #1
> [<c017cd09>] print_circular_bug_tail+0x79/0xc0
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017a5b5>] ? trace_hardirqs_off_caller+0x15/0xb0
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01afb88>] ? arch_get_unmapped_area_topdown+0xf8/0x160
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<c0120000>] ? __switch_to+0x130/0x220
> =======================
> evbug.c: Event. Dev: input3, Type: 20, Code: 0, Value: 500
> warning: `sudo' uses deprecated v2 capabilities in a way that may be insecure.
>
> i've attached the config.
>
> at first sight it looks like a genuine bug in fs/sysfs/bin.c?
Yes, it is a real bug by the looks. bin.c takes bb->mutex under mmap_sem
when it is mmapped, and then does its copy_*_user under bb->mutex too.
Here is a basic fix for the sysfs lor.
From: Nick Piggin <npiggin@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-09-12 13:24:11 +04:00
char * temp ;
2005-04-17 02:20:36 +04:00
2009-01-21 02:51:16 +03:00
if ( ! bytes )
return 0 ;
2005-04-17 02:20:36 +04:00
if ( size ) {
if ( offs > size )
return 0 ;
if ( offs + count > size )
count = size - offs ;
}
sysfs: fix deadlock
On Thu, Sep 11, 2008 at 10:27:10AM +0200, Ingo Molnar wrote:
> and it's working fine on most boxes. One testbox found this new locking
> scenario:
>
> PM: Adding info for No Bus:vcsa7
> EDAC DEBUG: MC0: i82860_check()
>
> =======================================================
> [ INFO: possible circular locking dependency detected ]
> 2.6.27-rc6-tip #1
> -------------------------------------------------------
> X/4873 is trying to acquire lock:
> (&bb->mutex){--..}, at: [<c020ba20>] mmap+0x40/0xa0
>
> but task is already holding lock:
> (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> which lock already depends on the new lock.
>
>
> the existing dependency chain (in reverse order) is:
>
> -> #1 (&mm->mmap_sem){----}:
> [<c017dc96>] validate_chain+0xa96/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c01aa8fb>] might_fault+0x6b/0x90
> [<c040b618>] copy_to_user+0x38/0x60
> [<c020bcfb>] read+0xfb/0x170
> [<c01c09a5>] vfs_read+0x95/0x110
> [<c01c1443>] sys_pread64+0x63/0x80
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> -> #0 (&bb->mutex){--..}:
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> other info that might help us debug this:
>
> 1 lock held by X/4873:
> #0: (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> stack backtrace:
> Pid: 4873, comm: X Not tainted 2.6.27-rc6-tip #1
> [<c017cd09>] print_circular_bug_tail+0x79/0xc0
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017a5b5>] ? trace_hardirqs_off_caller+0x15/0xb0
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01afb88>] ? arch_get_unmapped_area_topdown+0xf8/0x160
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<c0120000>] ? __switch_to+0x130/0x220
> =======================
> evbug.c: Event. Dev: input3, Type: 20, Code: 0, Value: 500
> warning: `sudo' uses deprecated v2 capabilities in a way that may be insecure.
>
> i've attached the config.
>
> at first sight it looks like a genuine bug in fs/sysfs/bin.c?
Yes, it is a real bug by the looks. bin.c takes bb->mutex under mmap_sem
when it is mmapped, and then does its copy_*_user under bb->mutex too.
Here is a basic fix for the sysfs lor.
From: Nick Piggin <npiggin@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-09-12 13:24:11 +04:00
temp = kmalloc ( count , GFP_KERNEL ) ;
if ( ! temp )
return - ENOMEM ;
2007-06-13 22:45:16 +04:00
mutex_lock ( & bb - > mutex ) ;
2010-05-13 05:28:57 +04:00
count = fill_read ( file , bb - > buffer , offs , count ) ;
sysfs: fix deadlock
On Thu, Sep 11, 2008 at 10:27:10AM +0200, Ingo Molnar wrote:
> and it's working fine on most boxes. One testbox found this new locking
> scenario:
>
> PM: Adding info for No Bus:vcsa7
> EDAC DEBUG: MC0: i82860_check()
>
> =======================================================
> [ INFO: possible circular locking dependency detected ]
> 2.6.27-rc6-tip #1
> -------------------------------------------------------
> X/4873 is trying to acquire lock:
> (&bb->mutex){--..}, at: [<c020ba20>] mmap+0x40/0xa0
>
> but task is already holding lock:
> (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> which lock already depends on the new lock.
>
>
> the existing dependency chain (in reverse order) is:
>
> -> #1 (&mm->mmap_sem){----}:
> [<c017dc96>] validate_chain+0xa96/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c01aa8fb>] might_fault+0x6b/0x90
> [<c040b618>] copy_to_user+0x38/0x60
> [<c020bcfb>] read+0xfb/0x170
> [<c01c09a5>] vfs_read+0x95/0x110
> [<c01c1443>] sys_pread64+0x63/0x80
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> -> #0 (&bb->mutex){--..}:
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> other info that might help us debug this:
>
> 1 lock held by X/4873:
> #0: (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> stack backtrace:
> Pid: 4873, comm: X Not tainted 2.6.27-rc6-tip #1
> [<c017cd09>] print_circular_bug_tail+0x79/0xc0
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017a5b5>] ? trace_hardirqs_off_caller+0x15/0xb0
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01afb88>] ? arch_get_unmapped_area_topdown+0xf8/0x160
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<c0120000>] ? __switch_to+0x130/0x220
> =======================
> evbug.c: Event. Dev: input3, Type: 20, Code: 0, Value: 500
> warning: `sudo' uses deprecated v2 capabilities in a way that may be insecure.
>
> i've attached the config.
>
> at first sight it looks like a genuine bug in fs/sysfs/bin.c?
Yes, it is a real bug by the looks. bin.c takes bb->mutex under mmap_sem
when it is mmapped, and then does its copy_*_user under bb->mutex too.
Here is a basic fix for the sysfs lor.
From: Nick Piggin <npiggin@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-09-12 13:24:11 +04:00
if ( count < 0 ) {
mutex_unlock ( & bb - > mutex ) ;
goto out_free ;
}
2005-04-17 02:20:36 +04:00
sysfs: fix deadlock
On Thu, Sep 11, 2008 at 10:27:10AM +0200, Ingo Molnar wrote:
> and it's working fine on most boxes. One testbox found this new locking
> scenario:
>
> PM: Adding info for No Bus:vcsa7
> EDAC DEBUG: MC0: i82860_check()
>
> =======================================================
> [ INFO: possible circular locking dependency detected ]
> 2.6.27-rc6-tip #1
> -------------------------------------------------------
> X/4873 is trying to acquire lock:
> (&bb->mutex){--..}, at: [<c020ba20>] mmap+0x40/0xa0
>
> but task is already holding lock:
> (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> which lock already depends on the new lock.
>
>
> the existing dependency chain (in reverse order) is:
>
> -> #1 (&mm->mmap_sem){----}:
> [<c017dc96>] validate_chain+0xa96/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c01aa8fb>] might_fault+0x6b/0x90
> [<c040b618>] copy_to_user+0x38/0x60
> [<c020bcfb>] read+0xfb/0x170
> [<c01c09a5>] vfs_read+0x95/0x110
> [<c01c1443>] sys_pread64+0x63/0x80
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> -> #0 (&bb->mutex){--..}:
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> other info that might help us debug this:
>
> 1 lock held by X/4873:
> #0: (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> stack backtrace:
> Pid: 4873, comm: X Not tainted 2.6.27-rc6-tip #1
> [<c017cd09>] print_circular_bug_tail+0x79/0xc0
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017a5b5>] ? trace_hardirqs_off_caller+0x15/0xb0
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01afb88>] ? arch_get_unmapped_area_topdown+0xf8/0x160
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<c0120000>] ? __switch_to+0x130/0x220
> =======================
> evbug.c: Event. Dev: input3, Type: 20, Code: 0, Value: 500
> warning: `sudo' uses deprecated v2 capabilities in a way that may be insecure.
>
> i've attached the config.
>
> at first sight it looks like a genuine bug in fs/sysfs/bin.c?
Yes, it is a real bug by the looks. bin.c takes bb->mutex under mmap_sem
when it is mmapped, and then does its copy_*_user under bb->mutex too.
Here is a basic fix for the sysfs lor.
From: Nick Piggin <npiggin@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-09-12 13:24:11 +04:00
memcpy ( temp , bb - > buffer , count ) ;
mutex_unlock ( & bb - > mutex ) ;
if ( copy_to_user ( userbuf , temp , count ) ) {
2007-06-13 22:45:16 +04:00
count = - EFAULT ;
sysfs: fix deadlock
On Thu, Sep 11, 2008 at 10:27:10AM +0200, Ingo Molnar wrote:
> and it's working fine on most boxes. One testbox found this new locking
> scenario:
>
> PM: Adding info for No Bus:vcsa7
> EDAC DEBUG: MC0: i82860_check()
>
> =======================================================
> [ INFO: possible circular locking dependency detected ]
> 2.6.27-rc6-tip #1
> -------------------------------------------------------
> X/4873 is trying to acquire lock:
> (&bb->mutex){--..}, at: [<c020ba20>] mmap+0x40/0xa0
>
> but task is already holding lock:
> (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> which lock already depends on the new lock.
>
>
> the existing dependency chain (in reverse order) is:
>
> -> #1 (&mm->mmap_sem){----}:
> [<c017dc96>] validate_chain+0xa96/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c01aa8fb>] might_fault+0x6b/0x90
> [<c040b618>] copy_to_user+0x38/0x60
> [<c020bcfb>] read+0xfb/0x170
> [<c01c09a5>] vfs_read+0x95/0x110
> [<c01c1443>] sys_pread64+0x63/0x80
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> -> #0 (&bb->mutex){--..}:
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> other info that might help us debug this:
>
> 1 lock held by X/4873:
> #0: (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> stack backtrace:
> Pid: 4873, comm: X Not tainted 2.6.27-rc6-tip #1
> [<c017cd09>] print_circular_bug_tail+0x79/0xc0
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017a5b5>] ? trace_hardirqs_off_caller+0x15/0xb0
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01afb88>] ? arch_get_unmapped_area_topdown+0xf8/0x160
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<c0120000>] ? __switch_to+0x130/0x220
> =======================
> evbug.c: Event. Dev: input3, Type: 20, Code: 0, Value: 500
> warning: `sudo' uses deprecated v2 capabilities in a way that may be insecure.
>
> i've attached the config.
>
> at first sight it looks like a genuine bug in fs/sysfs/bin.c?
Yes, it is a real bug by the looks. bin.c takes bb->mutex under mmap_sem
when it is mmapped, and then does its copy_*_user under bb->mutex too.
Here is a basic fix for the sysfs lor.
From: Nick Piggin <npiggin@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-09-12 13:24:11 +04:00
goto out_free ;
2007-06-13 22:45:16 +04:00
}
2005-04-17 02:20:36 +04:00
2007-06-13 22:45:13 +04:00
pr_debug ( " offs = %lld, *off = %lld, count = %d \n " , offs , * off , count ) ;
2005-04-17 02:20:36 +04:00
* off = offs + count ;
sysfs: fix deadlock
On Thu, Sep 11, 2008 at 10:27:10AM +0200, Ingo Molnar wrote:
> and it's working fine on most boxes. One testbox found this new locking
> scenario:
>
> PM: Adding info for No Bus:vcsa7
> EDAC DEBUG: MC0: i82860_check()
>
> =======================================================
> [ INFO: possible circular locking dependency detected ]
> 2.6.27-rc6-tip #1
> -------------------------------------------------------
> X/4873 is trying to acquire lock:
> (&bb->mutex){--..}, at: [<c020ba20>] mmap+0x40/0xa0
>
> but task is already holding lock:
> (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> which lock already depends on the new lock.
>
>
> the existing dependency chain (in reverse order) is:
>
> -> #1 (&mm->mmap_sem){----}:
> [<c017dc96>] validate_chain+0xa96/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c01aa8fb>] might_fault+0x6b/0x90
> [<c040b618>] copy_to_user+0x38/0x60
> [<c020bcfb>] read+0xfb/0x170
> [<c01c09a5>] vfs_read+0x95/0x110
> [<c01c1443>] sys_pread64+0x63/0x80
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> -> #0 (&bb->mutex){--..}:
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> other info that might help us debug this:
>
> 1 lock held by X/4873:
> #0: (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> stack backtrace:
> Pid: 4873, comm: X Not tainted 2.6.27-rc6-tip #1
> [<c017cd09>] print_circular_bug_tail+0x79/0xc0
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017a5b5>] ? trace_hardirqs_off_caller+0x15/0xb0
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01afb88>] ? arch_get_unmapped_area_topdown+0xf8/0x160
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<c0120000>] ? __switch_to+0x130/0x220
> =======================
> evbug.c: Event. Dev: input3, Type: 20, Code: 0, Value: 500
> warning: `sudo' uses deprecated v2 capabilities in a way that may be insecure.
>
> i've attached the config.
>
> at first sight it looks like a genuine bug in fs/sysfs/bin.c?
Yes, it is a real bug by the looks. bin.c takes bb->mutex under mmap_sem
when it is mmapped, and then does its copy_*_user under bb->mutex too.
Here is a basic fix for the sysfs lor.
From: Nick Piggin <npiggin@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-09-12 13:24:11 +04:00
out_free :
kfree ( temp ) ;
2005-04-17 02:20:36 +04:00
return count ;
}
static int
2010-05-13 05:28:57 +04:00
flush_write ( struct file * file , char * buffer , loff_t offset , size_t count )
2005-04-17 02:20:36 +04:00
{
2010-05-13 05:28:57 +04:00
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
2007-09-20 11:05:11 +04:00
struct bin_attribute * attr = attr_sd - > s_bin_attr . bin_attr ;
struct kobject * kobj = attr_sd - > s_parent - > s_dir . kobj ;
2007-06-13 22:45:16 +04:00
int rc ;
/* need attr_sd for attr, its parent for kobj */
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2007-06-13 22:45:16 +04:00
return - ENODEV ;
2005-04-17 02:20:36 +04:00
2007-06-13 22:45:16 +04:00
rc = - EIO ;
if ( attr - > write )
2010-05-13 05:28:57 +04:00
rc = attr - > write ( file , kobj , attr , buffer , offset , count ) ;
2005-04-17 02:20:36 +04:00
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2007-06-13 22:45:16 +04:00
return rc ;
2005-04-17 02:20:36 +04:00
}
2007-06-13 22:45:13 +04:00
static ssize_t write ( struct file * file , const char __user * userbuf ,
size_t bytes , loff_t * off )
2005-04-17 02:20:36 +04:00
{
2007-06-13 22:45:16 +04:00
struct bin_buffer * bb = file - > private_data ;
2010-05-13 05:28:57 +04:00
int size = file - > f_path . dentry - > d_inode - > i_size ;
2005-04-17 02:20:36 +04:00
loff_t offs = * off ;
2007-06-13 22:45:13 +04:00
int count = min_t ( size_t , bytes , PAGE_SIZE ) ;
sysfs: fix deadlock
On Thu, Sep 11, 2008 at 10:27:10AM +0200, Ingo Molnar wrote:
> and it's working fine on most boxes. One testbox found this new locking
> scenario:
>
> PM: Adding info for No Bus:vcsa7
> EDAC DEBUG: MC0: i82860_check()
>
> =======================================================
> [ INFO: possible circular locking dependency detected ]
> 2.6.27-rc6-tip #1
> -------------------------------------------------------
> X/4873 is trying to acquire lock:
> (&bb->mutex){--..}, at: [<c020ba20>] mmap+0x40/0xa0
>
> but task is already holding lock:
> (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> which lock already depends on the new lock.
>
>
> the existing dependency chain (in reverse order) is:
>
> -> #1 (&mm->mmap_sem){----}:
> [<c017dc96>] validate_chain+0xa96/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c01aa8fb>] might_fault+0x6b/0x90
> [<c040b618>] copy_to_user+0x38/0x60
> [<c020bcfb>] read+0xfb/0x170
> [<c01c09a5>] vfs_read+0x95/0x110
> [<c01c1443>] sys_pread64+0x63/0x80
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> -> #0 (&bb->mutex){--..}:
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> other info that might help us debug this:
>
> 1 lock held by X/4873:
> #0: (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> stack backtrace:
> Pid: 4873, comm: X Not tainted 2.6.27-rc6-tip #1
> [<c017cd09>] print_circular_bug_tail+0x79/0xc0
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017a5b5>] ? trace_hardirqs_off_caller+0x15/0xb0
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01afb88>] ? arch_get_unmapped_area_topdown+0xf8/0x160
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<c0120000>] ? __switch_to+0x130/0x220
> =======================
> evbug.c: Event. Dev: input3, Type: 20, Code: 0, Value: 500
> warning: `sudo' uses deprecated v2 capabilities in a way that may be insecure.
>
> i've attached the config.
>
> at first sight it looks like a genuine bug in fs/sysfs/bin.c?
Yes, it is a real bug by the looks. bin.c takes bb->mutex under mmap_sem
when it is mmapped, and then does its copy_*_user under bb->mutex too.
Here is a basic fix for the sysfs lor.
From: Nick Piggin <npiggin@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-09-12 13:24:11 +04:00
char * temp ;
2005-04-17 02:20:36 +04:00
2009-01-21 02:51:16 +03:00
if ( ! bytes )
return 0 ;
2005-04-17 02:20:36 +04:00
if ( size ) {
if ( offs > size )
return 0 ;
if ( offs + count > size )
count = size - offs ;
}
2009-04-08 11:07:30 +04:00
temp = memdup_user ( userbuf , count ) ;
if ( IS_ERR ( temp ) )
return PTR_ERR ( temp ) ;
2005-04-17 02:20:36 +04:00
sysfs: fix deadlock
On Thu, Sep 11, 2008 at 10:27:10AM +0200, Ingo Molnar wrote:
> and it's working fine on most boxes. One testbox found this new locking
> scenario:
>
> PM: Adding info for No Bus:vcsa7
> EDAC DEBUG: MC0: i82860_check()
>
> =======================================================
> [ INFO: possible circular locking dependency detected ]
> 2.6.27-rc6-tip #1
> -------------------------------------------------------
> X/4873 is trying to acquire lock:
> (&bb->mutex){--..}, at: [<c020ba20>] mmap+0x40/0xa0
>
> but task is already holding lock:
> (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> which lock already depends on the new lock.
>
>
> the existing dependency chain (in reverse order) is:
>
> -> #1 (&mm->mmap_sem){----}:
> [<c017dc96>] validate_chain+0xa96/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c01aa8fb>] might_fault+0x6b/0x90
> [<c040b618>] copy_to_user+0x38/0x60
> [<c020bcfb>] read+0xfb/0x170
> [<c01c09a5>] vfs_read+0x95/0x110
> [<c01c1443>] sys_pread64+0x63/0x80
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> -> #0 (&bb->mutex){--..}:
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> other info that might help us debug this:
>
> 1 lock held by X/4873:
> #0: (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> stack backtrace:
> Pid: 4873, comm: X Not tainted 2.6.27-rc6-tip #1
> [<c017cd09>] print_circular_bug_tail+0x79/0xc0
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017a5b5>] ? trace_hardirqs_off_caller+0x15/0xb0
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01afb88>] ? arch_get_unmapped_area_topdown+0xf8/0x160
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<c0120000>] ? __switch_to+0x130/0x220
> =======================
> evbug.c: Event. Dev: input3, Type: 20, Code: 0, Value: 500
> warning: `sudo' uses deprecated v2 capabilities in a way that may be insecure.
>
> i've attached the config.
>
> at first sight it looks like a genuine bug in fs/sysfs/bin.c?
Yes, it is a real bug by the looks. bin.c takes bb->mutex under mmap_sem
when it is mmapped, and then does its copy_*_user under bb->mutex too.
Here is a basic fix for the sysfs lor.
From: Nick Piggin <npiggin@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-09-12 13:24:11 +04:00
mutex_lock ( & bb - > mutex ) ;
memcpy ( bb - > buffer , temp , count ) ;
2010-05-13 05:28:57 +04:00
count = flush_write ( file , bb - > buffer , offs , count ) ;
sysfs: fix deadlock
On Thu, Sep 11, 2008 at 10:27:10AM +0200, Ingo Molnar wrote:
> and it's working fine on most boxes. One testbox found this new locking
> scenario:
>
> PM: Adding info for No Bus:vcsa7
> EDAC DEBUG: MC0: i82860_check()
>
> =======================================================
> [ INFO: possible circular locking dependency detected ]
> 2.6.27-rc6-tip #1
> -------------------------------------------------------
> X/4873 is trying to acquire lock:
> (&bb->mutex){--..}, at: [<c020ba20>] mmap+0x40/0xa0
>
> but task is already holding lock:
> (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> which lock already depends on the new lock.
>
>
> the existing dependency chain (in reverse order) is:
>
> -> #1 (&mm->mmap_sem){----}:
> [<c017dc96>] validate_chain+0xa96/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c01aa8fb>] might_fault+0x6b/0x90
> [<c040b618>] copy_to_user+0x38/0x60
> [<c020bcfb>] read+0xfb/0x170
> [<c01c09a5>] vfs_read+0x95/0x110
> [<c01c1443>] sys_pread64+0x63/0x80
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> -> #0 (&bb->mutex){--..}:
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<ffffffff>] 0xffffffff
>
> other info that might help us debug this:
>
> 1 lock held by X/4873:
> #0: (&mm->mmap_sem){----}, at: [<c0125a1e>] sys_mmap2+0x8e/0xc0
>
> stack backtrace:
> Pid: 4873, comm: X Not tainted 2.6.27-rc6-tip #1
> [<c017cd09>] print_circular_bug_tail+0x79/0xc0
> [<c017d8b7>] validate_chain+0x6b7/0xf50
> [<c017a5b5>] ? trace_hardirqs_off_caller+0x15/0xb0
> [<c017ef2b>] __lock_acquire+0x2cb/0x5b0
> [<c017f299>] lock_acquire+0x89/0xc0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f2ab>] __mutex_lock_common+0xab/0x3c0
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c0d6f698>] mutex_lock_nested+0x38/0x50
> [<c020ba20>] ? mmap+0x40/0xa0
> [<c020ba20>] mmap+0x40/0xa0
> [<c01b111e>] mmap_region+0x14e/0x450
> [<c01afb88>] ? arch_get_unmapped_area_topdown+0xf8/0x160
> [<c01b170f>] do_mmap_pgoff+0x2ef/0x310
> [<c0125a3d>] sys_mmap2+0xad/0xc0
> [<c012146f>] sysenter_do_call+0x12/0x43
> [<c0120000>] ? __switch_to+0x130/0x220
> =======================
> evbug.c: Event. Dev: input3, Type: 20, Code: 0, Value: 500
> warning: `sudo' uses deprecated v2 capabilities in a way that may be insecure.
>
> i've attached the config.
>
> at first sight it looks like a genuine bug in fs/sysfs/bin.c?
Yes, it is a real bug by the looks. bin.c takes bb->mutex under mmap_sem
when it is mmapped, and then does its copy_*_user under bb->mutex too.
Here is a basic fix for the sysfs lor.
From: Nick Piggin <npiggin@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2008-09-12 13:24:11 +04:00
mutex_unlock ( & bb - > mutex ) ;
2005-04-17 02:20:36 +04:00
if ( count > 0 )
* off = offs + count ;
2007-06-13 22:45:16 +04:00
2009-07-08 14:17:34 +04:00
kfree ( temp ) ;
2005-04-17 02:20:36 +04:00
return count ;
}
2009-03-04 22:57:20 +03:00
static void bin_vma_open ( struct vm_area_struct * vma )
{
struct file * file = vma - > vm_file ;
struct bin_buffer * bb = file - > private_data ;
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
2010-09-20 11:57:03 +04:00
if ( ! bb - > vm_ops )
2009-03-04 22:57:20 +03:00
return ;
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2009-03-04 22:57:20 +03:00
return ;
2010-09-20 11:57:03 +04:00
if ( bb - > vm_ops - > open )
bb - > vm_ops - > open ( vma ) ;
2009-03-04 22:57:20 +03:00
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2009-03-04 22:57:20 +03:00
}
static int bin_fault ( struct vm_area_struct * vma , struct vm_fault * vmf )
{
struct file * file = vma - > vm_file ;
struct bin_buffer * bb = file - > private_data ;
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
int ret ;
2010-09-20 11:57:03 +04:00
if ( ! bb - > vm_ops )
2009-03-04 22:57:20 +03:00
return VM_FAULT_SIGBUS ;
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2009-03-04 22:57:20 +03:00
return VM_FAULT_SIGBUS ;
2010-09-20 11:57:03 +04:00
ret = VM_FAULT_SIGBUS ;
if ( bb - > vm_ops - > fault )
ret = bb - > vm_ops - > fault ( vma , vmf ) ;
2009-03-04 22:57:20 +03:00
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2009-03-04 22:57:20 +03:00
return ret ;
}
2009-04-01 02:23:24 +04:00
static int bin_page_mkwrite ( struct vm_area_struct * vma , struct vm_fault * vmf )
2009-03-04 22:57:20 +03:00
{
struct file * file = vma - > vm_file ;
struct bin_buffer * bb = file - > private_data ;
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
int ret ;
2009-03-23 04:41:27 +03:00
if ( ! bb - > vm_ops )
2009-04-01 02:23:24 +04:00
return VM_FAULT_SIGBUS ;
2009-03-04 22:57:20 +03:00
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2009-04-01 02:23:24 +04:00
return VM_FAULT_SIGBUS ;
2009-03-04 22:57:20 +03:00
2010-09-20 11:57:03 +04:00
ret = 0 ;
if ( bb - > vm_ops - > page_mkwrite )
ret = bb - > vm_ops - > page_mkwrite ( vma , vmf ) ;
2009-03-04 22:57:20 +03:00
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2009-03-04 22:57:20 +03:00
return ret ;
}
static int bin_access ( struct vm_area_struct * vma , unsigned long addr ,
void * buf , int len , int write )
{
struct file * file = vma - > vm_file ;
struct bin_buffer * bb = file - > private_data ;
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
int ret ;
2010-09-20 11:57:03 +04:00
if ( ! bb - > vm_ops )
2009-03-04 22:57:20 +03:00
return - EINVAL ;
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2009-03-04 22:57:20 +03:00
return - EINVAL ;
2010-09-20 11:57:03 +04:00
ret = - EINVAL ;
if ( bb - > vm_ops - > access )
ret = bb - > vm_ops - > access ( vma , addr , buf , len , write ) ;
2009-03-04 22:57:20 +03:00
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2009-03-04 22:57:20 +03:00
return ret ;
}
2009-03-23 04:41:27 +03:00
# ifdef CONFIG_NUMA
static int bin_set_policy ( struct vm_area_struct * vma , struct mempolicy * new )
{
struct file * file = vma - > vm_file ;
struct bin_buffer * bb = file - > private_data ;
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
int ret ;
2010-09-20 11:57:03 +04:00
if ( ! bb - > vm_ops )
2009-03-23 04:41:27 +03:00
return 0 ;
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2009-03-23 04:41:27 +03:00
return - EINVAL ;
2010-09-20 11:57:03 +04:00
ret = 0 ;
if ( bb - > vm_ops - > set_policy )
ret = bb - > vm_ops - > set_policy ( vma , new ) ;
2009-03-23 04:41:27 +03:00
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2009-03-23 04:41:27 +03:00
return ret ;
}
static struct mempolicy * bin_get_policy ( struct vm_area_struct * vma ,
unsigned long addr )
{
struct file * file = vma - > vm_file ;
struct bin_buffer * bb = file - > private_data ;
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
struct mempolicy * pol ;
2010-09-20 11:57:03 +04:00
if ( ! bb - > vm_ops )
2009-03-23 04:41:27 +03:00
return vma - > vm_policy ;
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2009-03-23 04:41:27 +03:00
return vma - > vm_policy ;
2010-09-20 11:57:03 +04:00
pol = vma - > vm_policy ;
if ( bb - > vm_ops - > get_policy )
pol = bb - > vm_ops - > get_policy ( vma , addr ) ;
2009-03-23 04:41:27 +03:00
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2009-03-23 04:41:27 +03:00
return pol ;
}
static int bin_migrate ( struct vm_area_struct * vma , const nodemask_t * from ,
const nodemask_t * to , unsigned long flags )
{
struct file * file = vma - > vm_file ;
struct bin_buffer * bb = file - > private_data ;
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
int ret ;
2010-09-20 11:57:03 +04:00
if ( ! bb - > vm_ops )
2009-03-23 04:41:27 +03:00
return 0 ;
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2009-03-23 04:41:27 +03:00
return 0 ;
2010-09-20 11:57:03 +04:00
ret = 0 ;
if ( bb - > vm_ops - > migrate )
ret = bb - > vm_ops - > migrate ( vma , from , to , flags ) ;
2009-03-23 04:41:27 +03:00
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2009-03-23 04:41:27 +03:00
return ret ;
}
# endif
2009-09-27 22:29:37 +04:00
static const struct vm_operations_struct bin_vm_ops = {
2009-03-04 22:57:20 +03:00
. open = bin_vma_open ,
. fault = bin_fault ,
. page_mkwrite = bin_page_mkwrite ,
. access = bin_access ,
2009-03-23 04:41:27 +03:00
# ifdef CONFIG_NUMA
. set_policy = bin_set_policy ,
. get_policy = bin_get_policy ,
. migrate = bin_migrate ,
# endif
2009-03-04 22:57:20 +03:00
} ;
2005-04-17 02:20:36 +04:00
static int mmap ( struct file * file , struct vm_area_struct * vma )
{
2007-06-13 22:45:16 +04:00
struct bin_buffer * bb = file - > private_data ;
2007-06-13 22:45:15 +04:00
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
2007-09-20 11:05:11 +04:00
struct bin_attribute * attr = attr_sd - > s_bin_attr . bin_attr ;
struct kobject * kobj = attr_sd - > s_parent - > s_dir . kobj ;
2007-06-13 22:45:16 +04:00
int rc ;
2005-04-17 02:20:36 +04:00
2007-06-13 22:45:16 +04:00
mutex_lock ( & bb - > mutex ) ;
2007-06-13 22:45:16 +04:00
/* need attr_sd for attr, its parent for kobj */
2009-03-04 22:57:20 +03:00
rc = - ENODEV ;
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2009-03-04 22:57:20 +03:00
goto out_unlock ;
2007-06-13 22:45:16 +04:00
rc = - EINVAL ;
2009-03-04 22:57:20 +03:00
if ( ! attr - > mmap )
goto out_put ;
2007-06-13 22:45:16 +04:00
2010-05-13 05:28:57 +04:00
rc = attr - > mmap ( file , kobj , attr , vma ) ;
2009-03-04 22:57:20 +03:00
if ( rc )
goto out_put ;
2007-06-13 22:45:16 +04:00
2009-03-23 04:41:27 +03:00
/*
* PowerPC ' s pci_mmap of legacy_mem uses shmem_zero_setup ( )
* to satisfy versions of X which crash if the mmap fails : that
* substitutes a new vm_file , and we don ' t then want bin_vm_ops .
*/
if ( vma - > vm_file ! = file )
2009-03-04 22:57:20 +03:00
goto out_put ;
rc = - EINVAL ;
2009-03-23 04:41:27 +03:00
if ( bb - > mmapped & & bb - > vm_ops ! = vma - > vm_ops )
2009-03-04 22:57:20 +03:00
goto out_put ;
2010-09-20 11:56:27 +04:00
/*
* It is not possible to successfully wrap close .
* So error if someone is trying to use close .
*/
rc = - EINVAL ;
if ( vma - > vm_ops & & vma - > vm_ops - > close )
goto out_put ;
2009-03-04 22:57:20 +03:00
rc = 0 ;
bb - > mmapped = 1 ;
2009-03-23 04:41:27 +03:00
bb - > vm_ops = vma - > vm_ops ;
vma - > vm_ops = & bin_vm_ops ;
2009-03-04 22:57:20 +03:00
out_put :
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2009-03-04 22:57:20 +03:00
out_unlock :
2007-06-13 22:45:16 +04:00
mutex_unlock ( & bb - > mutex ) ;
return rc ;
2005-04-17 02:20:36 +04:00
}
static int open ( struct inode * inode , struct file * file )
{
2007-06-13 22:45:15 +04:00
struct sysfs_dirent * attr_sd = file - > f_path . dentry - > d_fsdata ;
2007-09-20 11:05:11 +04:00
struct bin_attribute * attr = attr_sd - > s_bin_attr . bin_attr ;
2007-06-13 22:45:16 +04:00
struct bin_buffer * bb = NULL ;
2007-06-13 22:45:16 +04:00
int error ;
2005-04-17 02:20:36 +04:00
2007-09-20 11:05:10 +04:00
/* binary file operations requires both @sd and its parent */
2010-02-12 02:18:38 +03:00
if ( ! sysfs_get_active ( attr_sd ) )
2007-06-13 22:45:16 +04:00
return - ENODEV ;
2005-04-17 02:20:36 +04:00
error = - EACCES ;
if ( ( file - > f_mode & FMODE_WRITE ) & & ! ( attr - > write | | attr - > mmap ) )
2007-06-13 22:45:17 +04:00
goto err_out ;
2005-04-17 02:20:36 +04:00
if ( ( file - > f_mode & FMODE_READ ) & & ! ( attr - > read | | attr - > mmap ) )
2007-06-13 22:45:17 +04:00
goto err_out ;
2005-04-17 02:20:36 +04:00
error = - ENOMEM ;
2007-06-13 22:45:16 +04:00
bb = kzalloc ( sizeof ( * bb ) , GFP_KERNEL ) ;
if ( ! bb )
2007-06-13 22:45:17 +04:00
goto err_out ;
2005-04-17 02:20:36 +04:00
2007-06-13 22:45:16 +04:00
bb - > buffer = kmalloc ( PAGE_SIZE , GFP_KERNEL ) ;
if ( ! bb - > buffer )
2007-06-13 22:45:17 +04:00
goto err_out ;
2007-06-13 22:45:16 +04:00
mutex_init ( & bb - > mutex ) ;
2009-03-04 22:57:20 +03:00
bb - > file = file ;
2007-06-13 22:45:16 +04:00
file - > private_data = bb ;
2009-03-04 22:57:20 +03:00
mutex_lock ( & sysfs_bin_lock ) ;
hlist_add_head ( & bb - > list , & attr_sd - > s_bin_attr . buffers ) ;
mutex_unlock ( & sysfs_bin_lock ) ;
2007-09-20 11:05:10 +04:00
/* open succeeded, put active references */
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2007-06-13 22:45:16 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
2007-06-13 22:45:17 +04:00
err_out :
2010-02-12 02:18:38 +03:00
sysfs_put_active ( attr_sd ) ;
2007-06-13 22:45:16 +04:00
kfree ( bb ) ;
2005-04-17 02:20:36 +04:00
return error ;
}
static int release ( struct inode * inode , struct file * file )
{
2007-06-13 22:45:16 +04:00
struct bin_buffer * bb = file - > private_data ;
2005-04-17 02:20:36 +04:00
2009-03-04 22:57:20 +03:00
mutex_lock ( & sysfs_bin_lock ) ;
hlist_del ( & bb - > list ) ;
mutex_unlock ( & sysfs_bin_lock ) ;
2007-06-13 22:45:16 +04:00
kfree ( bb - > buffer ) ;
kfree ( bb ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2006-03-28 13:56:42 +04:00
const struct file_operations bin_fops = {
2005-04-17 02:20:36 +04:00
. read = read ,
. write = write ,
. mmap = mmap ,
. llseek = generic_file_llseek ,
. open = open ,
. release = release ,
} ;
2009-03-04 22:57:20 +03:00
void unmap_bin_file ( struct sysfs_dirent * attr_sd )
{
struct bin_buffer * bb ;
struct hlist_node * tmp ;
if ( sysfs_type ( attr_sd ) ! = SYSFS_KOBJ_BIN_ATTR )
return ;
mutex_lock ( & sysfs_bin_lock ) ;
hlist_for_each_entry ( bb , tmp , & attr_sd - > s_bin_attr . buffers , list ) {
struct inode * inode = bb - > file - > f_path . dentry - > d_inode ;
unmap_mapping_range ( inode - > i_mapping , 0 , 0 , 1 ) ;
}
mutex_unlock ( & sysfs_bin_lock ) ;
}
2005-04-17 02:20:36 +04:00
/**
* sysfs_create_bin_file - create binary file for object .
* @ kobj : object .
* @ attr : attribute descriptor .
*/
2009-12-18 16:34:20 +03:00
int sysfs_create_bin_file ( struct kobject * kobj ,
const struct bin_attribute * attr )
2005-04-17 02:20:36 +04:00
{
2007-06-13 23:27:22 +04:00
BUG_ON ( ! kobj | | ! kobj - > sd | | ! attr ) ;
2005-04-17 02:20:36 +04:00
2007-06-13 23:27:22 +04:00
return sysfs_add_file ( kobj - > sd , & attr - > attr , SYSFS_KOBJ_BIN_ATTR ) ;
2005-04-17 02:20:36 +04:00
}
/**
* sysfs_remove_bin_file - remove binary file for object .
* @ kobj : object .
* @ attr : attribute descriptor .
*/
2009-12-18 16:34:20 +03:00
void sysfs_remove_bin_file ( struct kobject * kobj ,
const struct bin_attribute * attr )
2005-04-17 02:20:36 +04:00
{
2010-03-30 22:31:26 +04:00
sysfs_hash_and_remove ( kobj - > sd , NULL , attr - > attr . name ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL_GPL ( sysfs_create_bin_file ) ;
EXPORT_SYMBOL_GPL ( sysfs_remove_bin_file ) ;