Merge master.kernel.org:/pub/scm/linux/kernel/git/mingo/mutex-2.6
This commit is contained in:
@@ -87,7 +87,7 @@ struct ext3_inode_info {
|
||||
#ifdef CONFIG_EXT3_FS_XATTR
|
||||
/*
|
||||
* Extended attributes can be read independently of the main file
|
||||
* data. Taking i_sem even when reading would cause contention
|
||||
* data. Taking i_mutex even when reading would cause contention
|
||||
* between readers of EAs and writers of regular file data, so
|
||||
* instead we synchronize on xattr_sem when reading or changing
|
||||
* EAs.
|
||||
|
||||
@@ -219,6 +219,7 @@ extern int dir_notify_enable;
|
||||
#include <linux/prio_tree.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/semaphore.h>
|
||||
@@ -484,7 +485,7 @@ struct inode {
|
||||
unsigned long i_blocks;
|
||||
unsigned short i_bytes;
|
||||
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
|
||||
struct semaphore i_sem;
|
||||
struct mutex i_mutex;
|
||||
struct rw_semaphore i_alloc_sem;
|
||||
struct inode_operations *i_op;
|
||||
struct file_operations *i_fop; /* former ->i_op->default_file_ops */
|
||||
@@ -820,7 +821,7 @@ struct super_block {
|
||||
unsigned long s_magic;
|
||||
struct dentry *s_root;
|
||||
struct rw_semaphore s_umount;
|
||||
struct semaphore s_lock;
|
||||
struct mutex s_lock;
|
||||
int s_count;
|
||||
int s_syncing;
|
||||
int s_need_sync_fs;
|
||||
@@ -892,13 +893,13 @@ static inline int has_fs_excl(void)
|
||||
static inline void lock_super(struct super_block * sb)
|
||||
{
|
||||
get_fs_excl();
|
||||
down(&sb->s_lock);
|
||||
mutex_lock(&sb->s_lock);
|
||||
}
|
||||
|
||||
static inline void unlock_super(struct super_block * sb)
|
||||
{
|
||||
put_fs_excl();
|
||||
up(&sb->s_lock);
|
||||
mutex_unlock(&sb->s_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1191,7 +1192,7 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc);
|
||||
* directory. The name should be stored in the @name (with the
|
||||
* understanding that it is already pointing to a a %NAME_MAX+1 sized
|
||||
* buffer. get_name() should return %0 on success, a negative error code
|
||||
* or error. @get_name will be called without @parent->i_sem held.
|
||||
* or error. @get_name will be called without @parent->i_mutex held.
|
||||
*
|
||||
* get_parent:
|
||||
* @get_parent should find the parent directory for the given @child which
|
||||
@@ -1213,7 +1214,7 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc);
|
||||
* nfsd_find_fh_dentry() in either the @obj or @parent parameters.
|
||||
*
|
||||
* Locking rules:
|
||||
* get_parent is called with child->d_inode->i_sem down
|
||||
* get_parent is called with child->d_inode->i_mutex down
|
||||
* get_name is not (which is possibly inconsistent)
|
||||
*/
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/bio.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/completion.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
@@ -638,7 +639,7 @@ typedef struct ide_drive_s {
|
||||
int crc_count; /* crc counter to reduce drive speed */
|
||||
struct list_head list;
|
||||
struct device gendev;
|
||||
struct semaphore gendev_rel_sem; /* to deal with device release() */
|
||||
struct completion gendev_rel_comp; /* to deal with device release() */
|
||||
} ide_drive_t;
|
||||
|
||||
#define to_ide_device(dev)container_of(dev, ide_drive_t, gendev)
|
||||
@@ -794,7 +795,7 @@ typedef struct hwif_s {
|
||||
unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */
|
||||
|
||||
struct device gendev;
|
||||
struct semaphore gendev_rel_sem; /* To deal with device release() */
|
||||
struct completion gendev_rel_comp; /* To deal with device release() */
|
||||
|
||||
void *hwif_data; /* extra hwif data */
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
#include <asm/semaphore.h>
|
||||
|
||||
struct jffs2_inode_info {
|
||||
/* We need an internal semaphore similar to inode->i_sem.
|
||||
/* We need an internal mutex similar to inode->i_mutex.
|
||||
Unfortunately, we can't used the existing one, because
|
||||
either the GC would deadlock, or we'd have to release it
|
||||
before letting GC proceed. Or we'd have to put ugliness
|
||||
into the GC code so it didn't attempt to obtain the i_sem
|
||||
into the GC code so it didn't attempt to obtain the i_mutex
|
||||
for the inode(s) which are already locked */
|
||||
struct semaphore sem;
|
||||
|
||||
|
||||
@@ -286,6 +286,15 @@ extern void dump_stack(void);
|
||||
1; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Check at compile time that 'function' is a certain type, or is a pointer
|
||||
* to that type (needs to use typedef for the function type.)
|
||||
*/
|
||||
#define typecheck_fn(type,function) \
|
||||
({ typeof(type) __tmp = function; \
|
||||
(void)__tmp; \
|
||||
})
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#define SI_LOAD_SHIFT 16
|
||||
|
||||
@@ -58,9 +58,9 @@ struct loop_device {
|
||||
struct bio *lo_bio;
|
||||
struct bio *lo_biotail;
|
||||
int lo_state;
|
||||
struct semaphore lo_sem;
|
||||
struct completion lo_done;
|
||||
struct completion lo_bh_done;
|
||||
struct semaphore lo_ctl_mutex;
|
||||
struct semaphore lo_bh_mutex;
|
||||
int lo_pending;
|
||||
|
||||
request_queue_t *lo_queue;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/prio_tree.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
struct mempolicy;
|
||||
struct anon_vma;
|
||||
@@ -1024,6 +1025,9 @@ static inline void vm_stat_account(struct mm_struct *mm,
|
||||
static inline void
|
||||
kernel_map_pages(struct page *page, int numpages, int enable)
|
||||
{
|
||||
if (!PageHighMem(page) && !enable)
|
||||
mutex_debug_check_no_locks_freed(page_address(page),
|
||||
page_address(page + numpages));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
21
include/linux/mutex-debug.h
Normal file
21
include/linux/mutex-debug.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef __LINUX_MUTEX_DEBUG_H
|
||||
#define __LINUX_MUTEX_DEBUG_H
|
||||
|
||||
/*
|
||||
* Mutexes - debugging helpers:
|
||||
*/
|
||||
|
||||
#define __DEBUG_MUTEX_INITIALIZER(lockname) \
|
||||
, .held_list = LIST_HEAD_INIT(lockname.held_list), \
|
||||
.name = #lockname , .magic = &lockname
|
||||
|
||||
#define mutex_init(sem) __mutex_init(sem, __FUNCTION__)
|
||||
|
||||
extern void FASTCALL(mutex_destroy(struct mutex *lock));
|
||||
|
||||
extern void mutex_debug_show_all_locks(void);
|
||||
extern void mutex_debug_show_held_locks(struct task_struct *filter);
|
||||
extern void mutex_debug_check_no_locks_held(struct task_struct *task);
|
||||
extern void mutex_debug_check_no_locks_freed(const void *from, const void *to);
|
||||
|
||||
#endif
|
||||
119
include/linux/mutex.h
Normal file
119
include/linux/mutex.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Mutexes: blocking mutual exclusion locks
|
||||
*
|
||||
* started by Ingo Molnar:
|
||||
*
|
||||
* Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
|
||||
*
|
||||
* This file contains the main data structure and API definitions.
|
||||
*/
|
||||
#ifndef __LINUX_MUTEX_H
|
||||
#define __LINUX_MUTEX_H
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
|
||||
/*
|
||||
* Simple, straightforward mutexes with strict semantics:
|
||||
*
|
||||
* - only one task can hold the mutex at a time
|
||||
* - only the owner can unlock the mutex
|
||||
* - multiple unlocks are not permitted
|
||||
* - recursive locking is not permitted
|
||||
* - a mutex object must be initialized via the API
|
||||
* - a mutex object must not be initialized via memset or copying
|
||||
* - task may not exit with mutex held
|
||||
* - memory areas where held locks reside must not be freed
|
||||
* - held mutexes must not be reinitialized
|
||||
* - mutexes may not be used in irq contexts
|
||||
*
|
||||
* These semantics are fully enforced when DEBUG_MUTEXES is
|
||||
* enabled. Furthermore, besides enforcing the above rules, the mutex
|
||||
* debugging code also implements a number of additional features
|
||||
* that make lock debugging easier and faster:
|
||||
*
|
||||
* - uses symbolic names of mutexes, whenever they are printed in debug output
|
||||
* - point-of-acquire tracking, symbolic lookup of function names
|
||||
* - list of all locks held in the system, printout of them
|
||||
* - owner tracking
|
||||
* - detects self-recursing locks and prints out all relevant info
|
||||
* - detects multi-task circular deadlocks and prints out all affected
|
||||
* locks and tasks (and only those tasks)
|
||||
*/
|
||||
struct mutex {
|
||||
/* 1: unlocked, 0: locked, negative: locked, possible waiters */
|
||||
atomic_t count;
|
||||
spinlock_t wait_lock;
|
||||
struct list_head wait_list;
|
||||
#ifdef CONFIG_DEBUG_MUTEXES
|
||||
struct thread_info *owner;
|
||||
struct list_head held_list;
|
||||
unsigned long acquire_ip;
|
||||
const char *name;
|
||||
void *magic;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the control structure for tasks blocked on mutex,
|
||||
* which resides on the blocked task's kernel stack:
|
||||
*/
|
||||
struct mutex_waiter {
|
||||
struct list_head list;
|
||||
struct task_struct *task;
|
||||
#ifdef CONFIG_DEBUG_MUTEXES
|
||||
struct mutex *lock;
|
||||
void *magic;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_MUTEXES
|
||||
# include <linux/mutex-debug.h>
|
||||
#else
|
||||
# define __DEBUG_MUTEX_INITIALIZER(lockname)
|
||||
# define mutex_init(mutex) __mutex_init(mutex, NULL)
|
||||
# define mutex_destroy(mutex) do { } while (0)
|
||||
# define mutex_debug_show_all_locks() do { } while (0)
|
||||
# define mutex_debug_show_held_locks(p) do { } while (0)
|
||||
# define mutex_debug_check_no_locks_held(task) do { } while (0)
|
||||
# define mutex_debug_check_no_locks_freed(from, to) do { } while (0)
|
||||
#endif
|
||||
|
||||
#define __MUTEX_INITIALIZER(lockname) \
|
||||
{ .count = ATOMIC_INIT(1) \
|
||||
, .wait_lock = SPIN_LOCK_UNLOCKED \
|
||||
, .wait_list = LIST_HEAD_INIT(lockname.wait_list) \
|
||||
__DEBUG_MUTEX_INITIALIZER(lockname) }
|
||||
|
||||
#define DEFINE_MUTEX(mutexname) \
|
||||
struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
|
||||
|
||||
extern void fastcall __mutex_init(struct mutex *lock, const char *name);
|
||||
|
||||
/***
|
||||
* mutex_is_locked - is the mutex locked
|
||||
* @lock: the mutex to be queried
|
||||
*
|
||||
* Returns 1 if the mutex is locked, 0 if unlocked.
|
||||
*/
|
||||
static inline int fastcall mutex_is_locked(struct mutex *lock)
|
||||
{
|
||||
return atomic_read(&lock->count) != 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* See kernel/mutex.c for detailed documentation of these APIs.
|
||||
* Also see Documentation/mutex-design.txt.
|
||||
*/
|
||||
extern void fastcall mutex_lock(struct mutex *lock);
|
||||
extern int fastcall mutex_lock_interruptible(struct mutex *lock);
|
||||
/*
|
||||
* NOTE: mutex_trylock() follows the spin_trylock() convention,
|
||||
* not the down_trylock() convention!
|
||||
*/
|
||||
extern int fastcall mutex_trylock(struct mutex *lock);
|
||||
extern void fastcall mutex_unlock(struct mutex *lock);
|
||||
|
||||
#endif
|
||||
@@ -294,7 +294,7 @@ fill_post_wcc(struct svc_fh *fhp)
|
||||
/*
|
||||
* Lock a file handle/inode
|
||||
* NOTE: both fh_lock and fh_unlock are done "by hand" in
|
||||
* vfs.c:nfsd_rename as it needs to grab 2 i_sem's at once
|
||||
* vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
|
||||
* so, any changes here should be reflected there.
|
||||
*/
|
||||
static inline void
|
||||
@@ -317,7 +317,7 @@ fh_lock(struct svc_fh *fhp)
|
||||
}
|
||||
|
||||
inode = dentry->d_inode;
|
||||
down(&inode->i_sem);
|
||||
mutex_lock(&inode->i_mutex);
|
||||
fill_pre_wcc(fhp);
|
||||
fhp->fh_locked = 1;
|
||||
}
|
||||
@@ -333,7 +333,7 @@ fh_unlock(struct svc_fh *fhp)
|
||||
|
||||
if (fhp->fh_locked) {
|
||||
fill_post_wcc(fhp);
|
||||
up(&fhp->fh_dentry->d_inode->i_sem);
|
||||
mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
|
||||
fhp->fh_locked = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ struct pipe_inode_info {
|
||||
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */
|
||||
#define PIPE_SIZE PAGE_SIZE
|
||||
|
||||
#define PIPE_SEM(inode) (&(inode).i_sem)
|
||||
#define PIPE_MUTEX(inode) (&(inode).i_mutex)
|
||||
#define PIPE_WAIT(inode) (&(inode).i_pipe->wait)
|
||||
#define PIPE_READERS(inode) ((inode).i_pipe->readers)
|
||||
#define PIPE_WRITERS(inode) ((inode).i_pipe->writers)
|
||||
|
||||
@@ -1857,7 +1857,7 @@ void padd_item(char *item, int total_length, int length);
|
||||
#define GET_BLOCK_CREATE 1 /* add anything you need to find block */
|
||||
#define GET_BLOCK_NO_HOLE 2 /* return -ENOENT for file holes */
|
||||
#define GET_BLOCK_READ_DIRECT 4 /* read the tail if indirect item not found */
|
||||
#define GET_BLOCK_NO_ISEM 8 /* i_sem is not held, don't preallocate */
|
||||
#define GET_BLOCK_NO_IMUX 8 /* i_mutex is not held, don't preallocate */
|
||||
#define GET_BLOCK_NO_DANGLE 16 /* don't leave any transactions running */
|
||||
|
||||
int restart_transaction(struct reiserfs_transaction_handle *th,
|
||||
|
||||
@@ -817,6 +817,11 @@ struct task_struct {
|
||||
/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
|
||||
spinlock_t proc_lock;
|
||||
|
||||
#ifdef CONFIG_DEBUG_MUTEXES
|
||||
/* mutex deadlock detection */
|
||||
struct mutex_waiter *blocked_on;
|
||||
#endif
|
||||
|
||||
/* journalling filesystem info */
|
||||
void *journal_info;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user