Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: fs: brlock vfsmount_lock fs: scale files_lock lglock: introduce special lglock and brlock spin locks tty: fix fu_list abuse fs: cleanup files_lock locking fs: remove extra lookup in __lookup_hash fs: fs_struct rwlock to spinlock apparmor: use task path helpers fs: dentry allocation consolidation fs: fix do_lookup false negative mbcache: Limit the maximum number of cache entries hostfs ->follow_link() braino hostfs: dumb (and usually harmless) tpyo - strncpy instead of strlcpy remove SWRITE* I/O types kill BH_Ordered flag vfs: update ctime when changing the file's permission by setfacl cramfs: only unlock new inodes fix reiserfs_evict_inode end_writeback second call
This commit is contained in:
@@ -32,7 +32,6 @@ enum bh_state_bits {
|
||||
BH_Delay, /* Buffer is not yet allocated on disk */
|
||||
BH_Boundary, /* Block is followed by a discontiguity */
|
||||
BH_Write_EIO, /* I/O error on write */
|
||||
BH_Ordered, /* ordered write */
|
||||
BH_Eopnotsupp, /* operation not supported (barrier) */
|
||||
BH_Unwritten, /* Buffer is allocated on disk but not written */
|
||||
BH_Quiet, /* Buffer Error Prinks to be quiet */
|
||||
@@ -125,7 +124,6 @@ BUFFER_FNS(Async_Write, async_write)
|
||||
BUFFER_FNS(Delay, delay)
|
||||
BUFFER_FNS(Boundary, boundary)
|
||||
BUFFER_FNS(Write_EIO, write_io_error)
|
||||
BUFFER_FNS(Ordered, ordered)
|
||||
BUFFER_FNS(Eopnotsupp, eopnotsupp)
|
||||
BUFFER_FNS(Unwritten, unwritten)
|
||||
|
||||
@@ -183,6 +181,8 @@ void unlock_buffer(struct buffer_head *bh);
|
||||
void __lock_buffer(struct buffer_head *bh);
|
||||
void ll_rw_block(int, int, struct buffer_head * bh[]);
|
||||
int sync_dirty_buffer(struct buffer_head *bh);
|
||||
int __sync_dirty_buffer(struct buffer_head *bh, int rw);
|
||||
void write_dirty_buffer(struct buffer_head *bh, int rw);
|
||||
int submit_bh(int, struct buffer_head *);
|
||||
void write_boundary_block(struct block_device *bdev,
|
||||
sector_t bblock, unsigned blocksize);
|
||||
|
||||
@@ -125,9 +125,6 @@ struct inodes_stat_t {
|
||||
* block layer could (in theory) choose to ignore this
|
||||
* request if it runs into resource problems.
|
||||
* WRITE A normal async write. Device will be plugged.
|
||||
* SWRITE Like WRITE, but a special case for ll_rw_block() that
|
||||
* tells it to lock the buffer first. Normally a buffer
|
||||
* must be locked before doing IO.
|
||||
* WRITE_SYNC_PLUG Synchronous write. Identical to WRITE, but passes down
|
||||
* the hint that someone will be waiting on this IO
|
||||
* shortly. The device must still be unplugged explicitly,
|
||||
@@ -138,9 +135,6 @@ struct inodes_stat_t {
|
||||
* immediately after submission. The write equivalent
|
||||
* of READ_SYNC.
|
||||
* WRITE_ODIRECT_PLUG Special case write for O_DIRECT only.
|
||||
* SWRITE_SYNC
|
||||
* SWRITE_SYNC_PLUG Like WRITE_SYNC/WRITE_SYNC_PLUG, but locks the buffer.
|
||||
* See SWRITE.
|
||||
* WRITE_BARRIER Like WRITE_SYNC, but tells the block layer that all
|
||||
* previously submitted writes must be safely on storage
|
||||
* before this one is started. Also guarantees that when
|
||||
@@ -155,7 +149,6 @@ struct inodes_stat_t {
|
||||
#define READ 0
|
||||
#define WRITE RW_MASK
|
||||
#define READA RWA_MASK
|
||||
#define SWRITE (WRITE | READA)
|
||||
|
||||
#define READ_SYNC (READ | REQ_SYNC | REQ_UNPLUG)
|
||||
#define READ_META (READ | REQ_META)
|
||||
@@ -165,8 +158,6 @@ struct inodes_stat_t {
|
||||
#define WRITE_META (WRITE | REQ_META)
|
||||
#define WRITE_BARRIER (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \
|
||||
REQ_HARDBARRIER)
|
||||
#define SWRITE_SYNC_PLUG (SWRITE | REQ_SYNC | REQ_NOIDLE)
|
||||
#define SWRITE_SYNC (SWRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG)
|
||||
|
||||
/*
|
||||
* These aren't really reads or writes, they pass down information about
|
||||
@@ -929,6 +920,9 @@ struct file {
|
||||
#define f_vfsmnt f_path.mnt
|
||||
const struct file_operations *f_op;
|
||||
spinlock_t f_lock; /* f_ep_links, f_flags, no IRQ */
|
||||
#ifdef CONFIG_SMP
|
||||
int f_sb_list_cpu;
|
||||
#endif
|
||||
atomic_long_t f_count;
|
||||
unsigned int f_flags;
|
||||
fmode_t f_mode;
|
||||
@@ -953,9 +947,6 @@ struct file {
|
||||
unsigned long f_mnt_write_state;
|
||||
#endif
|
||||
};
|
||||
extern spinlock_t files_lock;
|
||||
#define file_list_lock() spin_lock(&files_lock);
|
||||
#define file_list_unlock() spin_unlock(&files_lock);
|
||||
|
||||
#define get_file(x) atomic_long_inc(&(x)->f_count)
|
||||
#define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1)
|
||||
@@ -1346,7 +1337,11 @@ struct super_block {
|
||||
|
||||
struct list_head s_inodes; /* all inodes */
|
||||
struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */
|
||||
#ifdef CONFIG_SMP
|
||||
struct list_head __percpu *s_files;
|
||||
#else
|
||||
struct list_head s_files;
|
||||
#endif
|
||||
/* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */
|
||||
struct list_head s_dentry_lru; /* unused dentry lru */
|
||||
int s_nr_dentry_unused; /* # of dentry on lru */
|
||||
@@ -2197,8 +2192,6 @@ static inline void insert_inode_hash(struct inode *inode) {
|
||||
__insert_inode_hash(inode, inode->i_ino);
|
||||
}
|
||||
|
||||
extern void file_move(struct file *f, struct list_head *list);
|
||||
extern void file_kill(struct file *f);
|
||||
#ifdef CONFIG_BLOCK
|
||||
extern void submit_bio(int, struct bio *);
|
||||
extern int bdev_read_only(struct block_device *);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
struct fs_struct {
|
||||
int users;
|
||||
rwlock_t lock;
|
||||
spinlock_t lock;
|
||||
int umask;
|
||||
int in_exec;
|
||||
struct path root, pwd;
|
||||
@@ -23,29 +23,29 @@ extern int unshare_fs_struct(void);
|
||||
|
||||
static inline void get_fs_root(struct fs_struct *fs, struct path *root)
|
||||
{
|
||||
read_lock(&fs->lock);
|
||||
spin_lock(&fs->lock);
|
||||
*root = fs->root;
|
||||
path_get(root);
|
||||
read_unlock(&fs->lock);
|
||||
spin_unlock(&fs->lock);
|
||||
}
|
||||
|
||||
static inline void get_fs_pwd(struct fs_struct *fs, struct path *pwd)
|
||||
{
|
||||
read_lock(&fs->lock);
|
||||
spin_lock(&fs->lock);
|
||||
*pwd = fs->pwd;
|
||||
path_get(pwd);
|
||||
read_unlock(&fs->lock);
|
||||
spin_unlock(&fs->lock);
|
||||
}
|
||||
|
||||
static inline void get_fs_root_and_pwd(struct fs_struct *fs, struct path *root,
|
||||
struct path *pwd)
|
||||
{
|
||||
read_lock(&fs->lock);
|
||||
spin_lock(&fs->lock);
|
||||
*root = fs->root;
|
||||
path_get(root);
|
||||
*pwd = fs->pwd;
|
||||
path_get(pwd);
|
||||
read_unlock(&fs->lock);
|
||||
spin_unlock(&fs->lock);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_FS_STRUCT_H */
|
||||
|
||||
172
include/linux/lglock.h
Normal file
172
include/linux/lglock.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Specialised local-global spinlock. Can only be declared as global variables
|
||||
* to avoid overhead and keep things simple (and we don't want to start using
|
||||
* these inside dynamically allocated structures).
|
||||
*
|
||||
* "local/global locks" (lglocks) can be used to:
|
||||
*
|
||||
* - Provide fast exclusive access to per-CPU data, with exclusive access to
|
||||
* another CPU's data allowed but possibly subject to contention, and to
|
||||
* provide very slow exclusive access to all per-CPU data.
|
||||
* - Or to provide very fast and scalable read serialisation, and to provide
|
||||
* very slow exclusive serialisation of data (not necessarily per-CPU data).
|
||||
*
|
||||
* Brlocks are also implemented as a short-hand notation for the latter use
|
||||
* case.
|
||||
*
|
||||
* Copyright 2009, 2010, Nick Piggin, Novell Inc.
|
||||
*/
|
||||
#ifndef __LINUX_LGLOCK_H
|
||||
#define __LINUX_LGLOCK_H
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/percpu.h>
|
||||
|
||||
/* can make br locks by using local lock for read side, global lock for write */
|
||||
#define br_lock_init(name) name##_lock_init()
|
||||
#define br_read_lock(name) name##_local_lock()
|
||||
#define br_read_unlock(name) name##_local_unlock()
|
||||
#define br_write_lock(name) name##_global_lock_online()
|
||||
#define br_write_unlock(name) name##_global_unlock_online()
|
||||
|
||||
#define DECLARE_BRLOCK(name) DECLARE_LGLOCK(name)
|
||||
#define DEFINE_BRLOCK(name) DEFINE_LGLOCK(name)
|
||||
|
||||
|
||||
#define lg_lock_init(name) name##_lock_init()
|
||||
#define lg_local_lock(name) name##_local_lock()
|
||||
#define lg_local_unlock(name) name##_local_unlock()
|
||||
#define lg_local_lock_cpu(name, cpu) name##_local_lock_cpu(cpu)
|
||||
#define lg_local_unlock_cpu(name, cpu) name##_local_unlock_cpu(cpu)
|
||||
#define lg_global_lock(name) name##_global_lock()
|
||||
#define lg_global_unlock(name) name##_global_unlock()
|
||||
#define lg_global_lock_online(name) name##_global_lock_online()
|
||||
#define lg_global_unlock_online(name) name##_global_unlock_online()
|
||||
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
#define LOCKDEP_INIT_MAP lockdep_init_map
|
||||
|
||||
#define DEFINE_LGLOCK_LOCKDEP(name) \
|
||||
struct lock_class_key name##_lock_key; \
|
||||
struct lockdep_map name##_lock_dep_map; \
|
||||
EXPORT_SYMBOL(name##_lock_dep_map)
|
||||
|
||||
#else
|
||||
#define LOCKDEP_INIT_MAP(a, b, c, d)
|
||||
|
||||
#define DEFINE_LGLOCK_LOCKDEP(name)
|
||||
#endif
|
||||
|
||||
|
||||
#define DECLARE_LGLOCK(name) \
|
||||
extern void name##_lock_init(void); \
|
||||
extern void name##_local_lock(void); \
|
||||
extern void name##_local_unlock(void); \
|
||||
extern void name##_local_lock_cpu(int cpu); \
|
||||
extern void name##_local_unlock_cpu(int cpu); \
|
||||
extern void name##_global_lock(void); \
|
||||
extern void name##_global_unlock(void); \
|
||||
extern void name##_global_lock_online(void); \
|
||||
extern void name##_global_unlock_online(void); \
|
||||
|
||||
#define DEFINE_LGLOCK(name) \
|
||||
\
|
||||
DEFINE_PER_CPU(arch_spinlock_t, name##_lock); \
|
||||
DEFINE_LGLOCK_LOCKDEP(name); \
|
||||
\
|
||||
void name##_lock_init(void) { \
|
||||
int i; \
|
||||
LOCKDEP_INIT_MAP(&name##_lock_dep_map, #name, &name##_lock_key, 0); \
|
||||
for_each_possible_cpu(i) { \
|
||||
arch_spinlock_t *lock; \
|
||||
lock = &per_cpu(name##_lock, i); \
|
||||
*lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; \
|
||||
} \
|
||||
} \
|
||||
EXPORT_SYMBOL(name##_lock_init); \
|
||||
\
|
||||
void name##_local_lock(void) { \
|
||||
arch_spinlock_t *lock; \
|
||||
preempt_disable(); \
|
||||
rwlock_acquire_read(&name##_lock_dep_map, 0, 0, _THIS_IP_); \
|
||||
lock = &__get_cpu_var(name##_lock); \
|
||||
arch_spin_lock(lock); \
|
||||
} \
|
||||
EXPORT_SYMBOL(name##_local_lock); \
|
||||
\
|
||||
void name##_local_unlock(void) { \
|
||||
arch_spinlock_t *lock; \
|
||||
rwlock_release(&name##_lock_dep_map, 1, _THIS_IP_); \
|
||||
lock = &__get_cpu_var(name##_lock); \
|
||||
arch_spin_unlock(lock); \
|
||||
preempt_enable(); \
|
||||
} \
|
||||
EXPORT_SYMBOL(name##_local_unlock); \
|
||||
\
|
||||
void name##_local_lock_cpu(int cpu) { \
|
||||
arch_spinlock_t *lock; \
|
||||
preempt_disable(); \
|
||||
rwlock_acquire_read(&name##_lock_dep_map, 0, 0, _THIS_IP_); \
|
||||
lock = &per_cpu(name##_lock, cpu); \
|
||||
arch_spin_lock(lock); \
|
||||
} \
|
||||
EXPORT_SYMBOL(name##_local_lock_cpu); \
|
||||
\
|
||||
void name##_local_unlock_cpu(int cpu) { \
|
||||
arch_spinlock_t *lock; \
|
||||
rwlock_release(&name##_lock_dep_map, 1, _THIS_IP_); \
|
||||
lock = &per_cpu(name##_lock, cpu); \
|
||||
arch_spin_unlock(lock); \
|
||||
preempt_enable(); \
|
||||
} \
|
||||
EXPORT_SYMBOL(name##_local_unlock_cpu); \
|
||||
\
|
||||
void name##_global_lock_online(void) { \
|
||||
int i; \
|
||||
preempt_disable(); \
|
||||
rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \
|
||||
for_each_online_cpu(i) { \
|
||||
arch_spinlock_t *lock; \
|
||||
lock = &per_cpu(name##_lock, i); \
|
||||
arch_spin_lock(lock); \
|
||||
} \
|
||||
} \
|
||||
EXPORT_SYMBOL(name##_global_lock_online); \
|
||||
\
|
||||
void name##_global_unlock_online(void) { \
|
||||
int i; \
|
||||
rwlock_release(&name##_lock_dep_map, 1, _RET_IP_); \
|
||||
for_each_online_cpu(i) { \
|
||||
arch_spinlock_t *lock; \
|
||||
lock = &per_cpu(name##_lock, i); \
|
||||
arch_spin_unlock(lock); \
|
||||
} \
|
||||
preempt_enable(); \
|
||||
} \
|
||||
EXPORT_SYMBOL(name##_global_unlock_online); \
|
||||
\
|
||||
void name##_global_lock(void) { \
|
||||
int i; \
|
||||
preempt_disable(); \
|
||||
rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \
|
||||
for_each_online_cpu(i) { \
|
||||
arch_spinlock_t *lock; \
|
||||
lock = &per_cpu(name##_lock, i); \
|
||||
arch_spin_lock(lock); \
|
||||
} \
|
||||
} \
|
||||
EXPORT_SYMBOL(name##_global_lock); \
|
||||
\
|
||||
void name##_global_unlock(void) { \
|
||||
int i; \
|
||||
rwlock_release(&name##_lock_dep_map, 1, _RET_IP_); \
|
||||
for_each_online_cpu(i) { \
|
||||
arch_spinlock_t *lock; \
|
||||
lock = &per_cpu(name##_lock, i); \
|
||||
arch_spin_unlock(lock); \
|
||||
} \
|
||||
preempt_enable(); \
|
||||
} \
|
||||
EXPORT_SYMBOL(name##_global_unlock);
|
||||
#endif
|
||||
@@ -329,6 +329,13 @@ struct tty_struct {
|
||||
struct tty_port *port;
|
||||
};
|
||||
|
||||
/* Each of a tty's open files has private_data pointing to tty_file_private */
|
||||
struct tty_file_private {
|
||||
struct tty_struct *tty;
|
||||
struct file *file;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/* tty magic number */
|
||||
#define TTY_MAGIC 0x5401
|
||||
|
||||
@@ -458,6 +465,7 @@ extern void proc_clear_tty(struct task_struct *p);
|
||||
extern struct tty_struct *get_current_tty(void);
|
||||
extern void tty_default_fops(struct file_operations *fops);
|
||||
extern struct tty_struct *alloc_tty_struct(void);
|
||||
extern void tty_add_file(struct tty_struct *tty, struct file *file);
|
||||
extern void free_tty_struct(struct tty_struct *tty);
|
||||
extern void initialize_tty_struct(struct tty_struct *tty,
|
||||
struct tty_driver *driver, int idx);
|
||||
@@ -470,6 +478,7 @@ extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty);
|
||||
extern struct tty_struct *tty_pair_get_pty(struct tty_struct *tty);
|
||||
|
||||
extern struct mutex tty_mutex;
|
||||
extern spinlock_t tty_files_lock;
|
||||
|
||||
extern void tty_write_unlock(struct tty_struct *tty);
|
||||
extern int tty_write_lock(struct tty_struct *tty, int ndelay);
|
||||
|
||||
Reference in New Issue
Block a user