Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs changes from Al Viro. "A lot of misc stuff. The obvious groups: * Miklos' atomic_open series; kills the damn abuse of ->d_revalidate() by NFS, which was the major stumbling block for all work in that area. * ripping security_file_mmap() and dealing with deadlocks in the area; sanitizing the neighborhood of vm_mmap()/vm_munmap() in general. * ->encode_fh() switched to saner API; insane fake dentry in mm/cleancache.c gone. * assorted annotations in fs (endianness, __user) * parts of Artem's ->s_dirty work (jff2 and reiserfs parts) * ->update_time() work from Josef. * other bits and pieces all over the place. Normally it would've been in two or three pull requests, but signal.git stuff had eaten a lot of time during this cycle ;-/" Fix up trivial conflicts in Documentation/filesystems/vfs.txt (the 'truncate_range' inode method was removed by the VM changes, the VFS update adds an 'update_time()' method), and in fs/btrfs/ulist.[ch] (due to sparse fix added twice, with other changes nearby). * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (95 commits) nfs: don't open in ->d_revalidate vfs: retry last component if opening stale dentry vfs: nameidata_to_filp(): don't throw away file on error vfs: nameidata_to_filp(): inline __dentry_open() vfs: do_dentry_open(): don't put filp vfs: split __dentry_open() vfs: do_last() common post lookup vfs: do_last(): add audit_inode before open vfs: do_last(): only return EISDIR for O_CREAT vfs: do_last(): check LOOKUP_DIRECTORY vfs: do_last(): make ENOENT exit RCU safe vfs: make follow_link check RCU safe vfs: do_last(): use inode variable vfs: do_last(): inline walk_component() vfs: do_last(): make exit RCU safe vfs: split do_lookup() Btrfs: move over to use ->update_time fs: introduce inode operation ->update_time reiserfs: get rid of resierfs_sync_super reiserfs: mark the superblock as dirty a bit later ...
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#define ENOIOCTLCMD 515 /* No ioctl command */
|
||||
#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
|
||||
#define EPROBE_DEFER 517 /* Driver requests probe retry */
|
||||
#define EOPENSTALE 518 /* open found a stale dentry */
|
||||
|
||||
/* Defined for the NFSv3 protocol */
|
||||
#define EBADHANDLE 521 /* Illegal NFS file handle */
|
||||
|
@@ -165,8 +165,8 @@ struct fid {
|
||||
*/
|
||||
|
||||
struct export_operations {
|
||||
int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
|
||||
int connectable);
|
||||
int (*encode_fh)(struct inode *inode, __u32 *fh, int *max_len,
|
||||
struct inode *parent);
|
||||
struct dentry * (*fh_to_dentry)(struct super_block *sb, struct fid *fid,
|
||||
int fh_len, int fh_type);
|
||||
struct dentry * (*fh_to_parent)(struct super_block *sb, struct fid *fid,
|
||||
|
@@ -1692,6 +1692,7 @@ struct inode_operations {
|
||||
int (*removexattr) (struct dentry *, const char *);
|
||||
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
|
||||
u64 len);
|
||||
int (*update_time)(struct inode *, struct timespec *, int);
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct seq_file;
|
||||
@@ -1850,6 +1851,13 @@ static inline void inode_inc_iversion(struct inode *inode)
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
|
||||
enum file_time_flags {
|
||||
S_ATIME = 1,
|
||||
S_MTIME = 2,
|
||||
S_CTIME = 4,
|
||||
S_VERSION = 8,
|
||||
};
|
||||
|
||||
extern void touch_atime(struct path *);
|
||||
static inline void file_accessed(struct file *file)
|
||||
{
|
||||
@@ -2583,7 +2591,7 @@ extern int inode_change_ok(const struct inode *, struct iattr *);
|
||||
extern int inode_newsize_ok(const struct inode *, loff_t offset);
|
||||
extern void setattr_copy(struct inode *inode, const struct iattr *attr);
|
||||
|
||||
extern void file_update_time(struct file *file);
|
||||
extern int file_update_time(struct file *file);
|
||||
|
||||
extern int generic_show_options(struct seq_file *m, struct dentry *root);
|
||||
extern void save_mount_options(struct super_block *sb, char *options);
|
||||
|
@@ -60,7 +60,7 @@
|
||||
#define FS_EVENTS_POSS_ON_CHILD (FS_ACCESS | FS_MODIFY | FS_ATTRIB |\
|
||||
FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN |\
|
||||
FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\
|
||||
FS_DELETE)
|
||||
FS_DELETE | FS_OPEN_PERM | FS_ACCESS_PERM)
|
||||
|
||||
#define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO)
|
||||
|
||||
|
@@ -23,28 +23,17 @@
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/notifier.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 br_lock_init(name) lg_lock_init(name, #name)
|
||||
#define br_read_lock(name) lg_local_lock(name)
|
||||
#define br_read_unlock(name) lg_local_unlock(name)
|
||||
#define br_write_lock(name) lg_global_lock(name)
|
||||
#define br_write_unlock(name) lg_global_unlock(name)
|
||||
|
||||
#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
|
||||
|
||||
@@ -59,142 +48,26 @@
|
||||
#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); \
|
||||
struct lglock {
|
||||
arch_spinlock_t __percpu *lock;
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
struct lock_class_key lock_key;
|
||||
struct lockdep_map lock_dep_map;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define DEFINE_LGLOCK(name) \
|
||||
\
|
||||
DEFINE_SPINLOCK(name##_cpu_lock); \
|
||||
cpumask_t name##_cpus __read_mostly; \
|
||||
DEFINE_PER_CPU(arch_spinlock_t, name##_lock); \
|
||||
DEFINE_LGLOCK_LOCKDEP(name); \
|
||||
\
|
||||
static int \
|
||||
name##_lg_cpu_callback(struct notifier_block *nb, \
|
||||
unsigned long action, void *hcpu) \
|
||||
{ \
|
||||
switch (action & ~CPU_TASKS_FROZEN) { \
|
||||
case CPU_UP_PREPARE: \
|
||||
spin_lock(&name##_cpu_lock); \
|
||||
cpu_set((unsigned long)hcpu, name##_cpus); \
|
||||
spin_unlock(&name##_cpu_lock); \
|
||||
break; \
|
||||
case CPU_UP_CANCELED: case CPU_DEAD: \
|
||||
spin_lock(&name##_cpu_lock); \
|
||||
cpu_clear((unsigned long)hcpu, name##_cpus); \
|
||||
spin_unlock(&name##_cpu_lock); \
|
||||
} \
|
||||
return NOTIFY_OK; \
|
||||
} \
|
||||
static struct notifier_block name##_lg_cpu_notifier = { \
|
||||
.notifier_call = name##_lg_cpu_callback, \
|
||||
}; \
|
||||
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; \
|
||||
} \
|
||||
register_hotcpu_notifier(&name##_lg_cpu_notifier); \
|
||||
get_online_cpus(); \
|
||||
for_each_online_cpu(i) \
|
||||
cpu_set(i, name##_cpus); \
|
||||
put_online_cpus(); \
|
||||
} \
|
||||
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; \
|
||||
spin_lock(&name##_cpu_lock); \
|
||||
rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \
|
||||
for_each_cpu(i, &name##_cpus) { \
|
||||
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_cpu(i, &name##_cpus) { \
|
||||
arch_spinlock_t *lock; \
|
||||
lock = &per_cpu(name##_lock, i); \
|
||||
arch_spin_unlock(lock); \
|
||||
} \
|
||||
spin_unlock(&name##_cpu_lock); \
|
||||
} \
|
||||
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_possible_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_possible_cpu(i) { \
|
||||
arch_spinlock_t *lock; \
|
||||
lock = &per_cpu(name##_lock, i); \
|
||||
arch_spin_unlock(lock); \
|
||||
} \
|
||||
preempt_enable(); \
|
||||
} \
|
||||
EXPORT_SYMBOL(name##_global_unlock);
|
||||
DEFINE_LGLOCK_LOCKDEP(name); \
|
||||
DEFINE_PER_CPU(arch_spinlock_t, name ## _lock) \
|
||||
= __ARCH_SPIN_LOCK_UNLOCKED; \
|
||||
struct lglock name = { .lock = &name ## _lock }
|
||||
|
||||
void lg_lock_init(struct lglock *lg, char *name);
|
||||
void lg_local_lock(struct lglock *lg);
|
||||
void lg_local_unlock(struct lglock *lg);
|
||||
void lg_local_lock_cpu(struct lglock *lg, int cpu);
|
||||
void lg_local_unlock_cpu(struct lglock *lg, int cpu);
|
||||
void lg_global_lock(struct lglock *lg);
|
||||
void lg_global_unlock(struct lglock *lg);
|
||||
|
||||
#endif
|
||||
|
@@ -1392,7 +1392,7 @@ extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned lo
|
||||
extern unsigned long mmap_region(struct file *file, unsigned long addr,
|
||||
unsigned long len, unsigned long flags,
|
||||
vm_flags_t vm_flags, unsigned long pgoff);
|
||||
extern unsigned long do_mmap(struct file *, unsigned long,
|
||||
extern unsigned long do_mmap_pgoff(struct file *, unsigned long,
|
||||
unsigned long, unsigned long,
|
||||
unsigned long, unsigned long);
|
||||
extern int do_munmap(struct mm_struct *, unsigned long, size_t);
|
||||
|
@@ -86,9 +86,9 @@ extern int cap_inode_setxattr(struct dentry *dentry, const char *name,
|
||||
extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
|
||||
extern int cap_inode_need_killpriv(struct dentry *dentry);
|
||||
extern int cap_inode_killpriv(struct dentry *dentry);
|
||||
extern int cap_file_mmap(struct file *file, unsigned long reqprot,
|
||||
unsigned long prot, unsigned long flags,
|
||||
unsigned long addr, unsigned long addr_only);
|
||||
extern int cap_mmap_addr(unsigned long addr);
|
||||
extern int cap_mmap_file(struct file *file, unsigned long reqprot,
|
||||
unsigned long prot, unsigned long flags);
|
||||
extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags);
|
||||
extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5);
|
||||
@@ -586,15 +586,17 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
|
||||
* simple integer value. When @arg represents a user space pointer, it
|
||||
* should never be used by the security module.
|
||||
* Return 0 if permission is granted.
|
||||
* @file_mmap :
|
||||
* @mmap_addr :
|
||||
* Check permissions for a mmap operation at @addr.
|
||||
* @addr contains virtual address that will be used for the operation.
|
||||
* Return 0 if permission is granted.
|
||||
* @mmap_file :
|
||||
* Check permissions for a mmap operation. The @file may be NULL, e.g.
|
||||
* if mapping anonymous memory.
|
||||
* @file contains the file structure for file to map (may be NULL).
|
||||
* @reqprot contains the protection requested by the application.
|
||||
* @prot contains the protection that will be applied by the kernel.
|
||||
* @flags contains the operational flags.
|
||||
* @addr contains virtual address that will be used for the operation.
|
||||
* @addr_only contains a boolean: 0 if file-backed VMA, otherwise 1.
|
||||
* Return 0 if permission is granted.
|
||||
* @file_mprotect:
|
||||
* Check permissions before changing memory access permissions.
|
||||
@@ -1481,10 +1483,10 @@ struct security_operations {
|
||||
void (*file_free_security) (struct file *file);
|
||||
int (*file_ioctl) (struct file *file, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
int (*file_mmap) (struct file *file,
|
||||
int (*mmap_addr) (unsigned long addr);
|
||||
int (*mmap_file) (struct file *file,
|
||||
unsigned long reqprot, unsigned long prot,
|
||||
unsigned long flags, unsigned long addr,
|
||||
unsigned long addr_only);
|
||||
unsigned long flags);
|
||||
int (*file_mprotect) (struct vm_area_struct *vma,
|
||||
unsigned long reqprot,
|
||||
unsigned long prot);
|
||||
@@ -1743,9 +1745,9 @@ int security_file_permission(struct file *file, int mask);
|
||||
int security_file_alloc(struct file *file);
|
||||
void security_file_free(struct file *file);
|
||||
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
||||
int security_file_mmap(struct file *file, unsigned long reqprot,
|
||||
unsigned long prot, unsigned long flags,
|
||||
unsigned long addr, unsigned long addr_only);
|
||||
int security_mmap_file(struct file *file, unsigned long prot,
|
||||
unsigned long flags);
|
||||
int security_mmap_addr(unsigned long addr);
|
||||
int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
|
||||
unsigned long prot);
|
||||
int security_file_lock(struct file *file, unsigned int cmd);
|
||||
@@ -2181,13 +2183,15 @@ static inline int security_file_ioctl(struct file *file, unsigned int cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_file_mmap(struct file *file, unsigned long reqprot,
|
||||
unsigned long prot,
|
||||
unsigned long flags,
|
||||
unsigned long addr,
|
||||
unsigned long addr_only)
|
||||
static inline int security_mmap_file(struct file *file, unsigned long prot,
|
||||
unsigned long flags)
|
||||
{
|
||||
return cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_mmap_addr(unsigned long addr)
|
||||
{
|
||||
return cap_mmap_addr(addr);
|
||||
}
|
||||
|
||||
static inline int security_file_mprotect(struct vm_area_struct *vma,
|
||||
|
@@ -25,7 +25,7 @@ typedef __kernel_dev_t dev_t;
|
||||
typedef __kernel_ino_t ino_t;
|
||||
typedef __kernel_mode_t mode_t;
|
||||
typedef unsigned short umode_t;
|
||||
typedef __kernel_nlink_t nlink_t;
|
||||
typedef __u32 nlink_t;
|
||||
typedef __kernel_off_t off_t;
|
||||
typedef __kernel_pid_t pid_t;
|
||||
typedef __kernel_daddr_t daddr_t;
|
||||
|
Reference in New Issue
Block a user