diff options
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/anon_inodes.h | 3 | ||||
-rw-r--r-- | include/linux/binfmts.h | 3 | ||||
-rw-r--r-- | include/linux/compat.h | 2 | ||||
-rw-r--r-- | include/linux/coredump.h | 10 | ||||
-rw-r--r-- | include/linux/dcache.h | 104 | ||||
-rw-r--r-- | include/linux/elf.h | 6 | ||||
-rw-r--r-- | include/linux/elfcore.h | 7 | ||||
-rw-r--r-- | include/linux/fs.h | 106 | ||||
-rw-r--r-- | include/linux/lglock.h | 10 | ||||
-rw-r--r-- | include/linux/mount.h | 2 | ||||
-rw-r--r-- | include/linux/namei.h | 2 | ||||
-rw-r--r-- | include/linux/pid_namespace.h | 1 |
12 files changed, 185 insertions, 71 deletions
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h index cf573c22b81e..8013a45242fe 100644 --- a/include/linux/anon_inodes.h +++ b/include/linux/anon_inodes.h @@ -13,9 +13,6 @@ struct file_operations; struct file *anon_inode_getfile(const char *name, const struct file_operations *fops, void *priv, int flags); -struct file *anon_inode_getfile_private(const char *name, - const struct file_operations *fops, - void *priv, int flags); int anon_inode_getfd(const char *name, const struct file_operations *fops, void *priv, int flags); diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index e8112ae50531..790d3305a5a7 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -56,11 +56,12 @@ struct linux_binprm { /* Function parameter for binfmt->coredump */ struct coredump_params { - siginfo_t *siginfo; + const siginfo_t *siginfo; struct pt_regs *regs; struct file *file; unsigned long limit; unsigned long mm_flags; + loff_t written; }; /* diff --git a/include/linux/compat.h b/include/linux/compat.h index 345da00a86e0..78cdf51ff5ba 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -362,7 +362,7 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask, long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, unsigned long bitmap_size); int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from); -int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from); +int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from); int get_compat_sigevent(struct sigevent *event, const struct compat_sigevent __user *u_event); long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig, diff --git a/include/linux/coredump.h b/include/linux/coredump.h index a98f1ca60407..d016a121a8c4 100644 --- a/include/linux/coredump.h +++ b/include/linux/coredump.h @@ -10,12 +10,14 @@ * These are the only things you should do on a core-file: use only these * functions to write out all the necessary info. */ -extern int dump_write(struct file *file, const void *addr, int nr); -extern int dump_seek(struct file *file, loff_t off); +struct coredump_params; +extern int dump_skip(struct coredump_params *cprm, size_t nr); +extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); +extern int dump_align(struct coredump_params *cprm, int align); #ifdef CONFIG_COREDUMP -extern void do_coredump(siginfo_t *siginfo); +extern void do_coredump(const siginfo_t *siginfo); #else -static inline void do_coredump(siginfo_t *siginfo) {} +static inline void do_coredump(const siginfo_t *siginfo) {} #endif #endif /* _LINUX_COREDUMP_H */ diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 59066e0b4ff1..57e87e749a48 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -169,13 +169,13 @@ struct dentry_operations { */ /* d_flags entries */ -#define DCACHE_OP_HASH 0x0001 -#define DCACHE_OP_COMPARE 0x0002 -#define DCACHE_OP_REVALIDATE 0x0004 -#define DCACHE_OP_DELETE 0x0008 -#define DCACHE_OP_PRUNE 0x0010 +#define DCACHE_OP_HASH 0x00000001 +#define DCACHE_OP_COMPARE 0x00000002 +#define DCACHE_OP_REVALIDATE 0x00000004 +#define DCACHE_OP_DELETE 0x00000008 +#define DCACHE_OP_PRUNE 0x00000010 -#define DCACHE_DISCONNECTED 0x0020 +#define DCACHE_DISCONNECTED 0x00000020 /* This dentry is possibly not currently connected to the dcache tree, in * which case its parent will either be itself, or will have this flag as * well. nfsd will not use a dentry with this bit set, but will first @@ -186,30 +186,38 @@ struct dentry_operations { * dentry into place and return that dentry rather than the passed one, * typically using d_splice_alias. */ -#define DCACHE_REFERENCED 0x0040 /* Recently used, don't discard. */ -#define DCACHE_RCUACCESS 0x0080 /* Entry has ever been RCU-visible */ +#define DCACHE_REFERENCED 0x00000040 /* Recently used, don't discard. */ +#define DCACHE_RCUACCESS 0x00000080 /* Entry has ever been RCU-visible */ -#define DCACHE_CANT_MOUNT 0x0100 -#define DCACHE_GENOCIDE 0x0200 -#define DCACHE_SHRINK_LIST 0x0400 +#define DCACHE_CANT_MOUNT 0x00000100 +#define DCACHE_GENOCIDE 0x00000200 +#define DCACHE_SHRINK_LIST 0x00000400 -#define DCACHE_OP_WEAK_REVALIDATE 0x0800 +#define DCACHE_OP_WEAK_REVALIDATE 0x00000800 -#define DCACHE_NFSFS_RENAMED 0x1000 +#define DCACHE_NFSFS_RENAMED 0x00001000 /* this dentry has been "silly renamed" and has to be deleted on the last * dput() */ -#define DCACHE_COOKIE 0x2000 /* For use by dcookie subsystem */ -#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x4000 +#define DCACHE_COOKIE 0x00002000 /* For use by dcookie subsystem */ +#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x00004000 /* Parent inode is watched by some fsnotify listener */ -#define DCACHE_MOUNTED 0x10000 /* is a mountpoint */ -#define DCACHE_NEED_AUTOMOUNT 0x20000 /* handle automount on this dir */ -#define DCACHE_MANAGE_TRANSIT 0x40000 /* manage transit from this dirent */ +#define DCACHE_DENTRY_KILLED 0x00008000 + +#define DCACHE_MOUNTED 0x00010000 /* is a mountpoint */ +#define DCACHE_NEED_AUTOMOUNT 0x00020000 /* handle automount on this dir */ +#define DCACHE_MANAGE_TRANSIT 0x00040000 /* manage transit from this dirent */ #define DCACHE_MANAGED_DENTRY \ (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) -#define DCACHE_LRU_LIST 0x80000 -#define DCACHE_DENTRY_KILLED 0x100000 +#define DCACHE_LRU_LIST 0x00080000 + +#define DCACHE_ENTRY_TYPE 0x00700000 +#define DCACHE_MISS_TYPE 0x00000000 /* Negative dentry */ +#define DCACHE_DIRECTORY_TYPE 0x00100000 /* Normal directory */ +#define DCACHE_AUTODIR_TYPE 0x00200000 /* Lookupless directory (presumed automount) */ +#define DCACHE_SYMLINK_TYPE 0x00300000 /* Symlink */ +#define DCACHE_FILE_TYPE 0x00400000 /* Other file type */ extern seqlock_t rename_lock; @@ -224,6 +232,7 @@ static inline int dname_external(const struct dentry *dentry) extern void d_instantiate(struct dentry *, struct inode *); extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *); extern struct dentry * d_materialise_unique(struct dentry *, struct inode *); +extern int d_instantiate_no_diralias(struct dentry *, struct inode *); extern void __d_drop(struct dentry *dentry); extern void d_drop(struct dentry *dentry); extern void d_delete(struct dentry *); @@ -393,6 +402,61 @@ static inline bool d_mountpoint(const struct dentry *dentry) return dentry->d_flags & DCACHE_MOUNTED; } +/* + * Directory cache entry type accessor functions. + */ +static inline void __d_set_type(struct dentry *dentry, unsigned type) +{ + dentry->d_flags = (dentry->d_flags & ~DCACHE_ENTRY_TYPE) | type; +} + +static inline void __d_clear_type(struct dentry *dentry) +{ + __d_set_type(dentry, DCACHE_MISS_TYPE); +} + +static inline void d_set_type(struct dentry *dentry, unsigned type) +{ + spin_lock(&dentry->d_lock); + __d_set_type(dentry, type); + spin_unlock(&dentry->d_lock); +} + +static inline unsigned __d_entry_type(const struct dentry *dentry) +{ + return dentry->d_flags & DCACHE_ENTRY_TYPE; +} + +static inline bool d_is_directory(const struct dentry *dentry) +{ + return __d_entry_type(dentry) == DCACHE_DIRECTORY_TYPE; +} + +static inline bool d_is_autodir(const struct dentry *dentry) +{ + return __d_entry_type(dentry) == DCACHE_AUTODIR_TYPE; +} + +static inline bool d_is_symlink(const struct dentry *dentry) +{ + return __d_entry_type(dentry) == DCACHE_SYMLINK_TYPE; +} + +static inline bool d_is_file(const struct dentry *dentry) +{ + return __d_entry_type(dentry) == DCACHE_FILE_TYPE; +} + +static inline bool d_is_negative(const struct dentry *dentry) +{ + return __d_entry_type(dentry) == DCACHE_MISS_TYPE; +} + +static inline bool d_is_positive(const struct dentry *dentry) +{ + return !d_is_negative(dentry); +} + extern int sysctl_vfs_cache_pressure; static inline unsigned long vfs_pressure_ratio(unsigned long val) diff --git a/include/linux/elf.h b/include/linux/elf.h index 40a3c0e01b2b..67a5fa7830c4 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -39,13 +39,13 @@ extern Elf64_Dyn _DYNAMIC []; /* Optional callbacks to write extra ELF notes. */ struct file; +struct coredump_params; #ifndef ARCH_HAVE_EXTRA_ELF_NOTES static inline int elf_coredump_extra_notes_size(void) { return 0; } -static inline int elf_coredump_extra_notes_write(struct file *file, - loff_t *foffset) { return 0; } +static inline int elf_coredump_extra_notes_write(struct coredump_params *cprm) { return 0; } #else extern int elf_coredump_extra_notes_size(void); -extern int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset); +extern int elf_coredump_extra_notes_write(struct coredump_params *cprm); #endif #endif /* _LINUX_ELF_H */ diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h index cdd3d13efce7..698d51a0eea3 100644 --- a/include/linux/elfcore.h +++ b/include/linux/elfcore.h @@ -6,6 +6,8 @@ #include <asm/elf.h> #include <uapi/linux/elfcore.h> +struct coredump_params; + static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *regs) { #ifdef ELF_CORE_COPY_REGS @@ -63,10 +65,9 @@ static inline int elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregse */ extern Elf_Half elf_core_extra_phdrs(void); extern int -elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size, - unsigned long limit); +elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset); extern int -elf_core_write_extra_data(struct file *file, size_t *size, unsigned long limit); +elf_core_write_extra_data(struct coredump_params *cprm); extern size_t elf_core_extra_data_size(void); #endif /* _LINUX_ELFCORE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 955dff5da56a..bf5d574ebdf4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -623,10 +623,13 @@ static inline int inode_unhashed(struct inode *inode) * 0: the object of the current VFS operation * 1: parent * 2: child/target - * 3: quota file + * 3: xattr + * 4: second non-directory + * The last is for certain operations (such as rename) which lock two + * non-directories at once. * * The locking order between these classes is - * parent -> child -> normal -> xattr -> quota + * parent -> child -> normal -> xattr -> second non-directory */ enum inode_i_mutex_lock_class { @@ -634,9 +637,12 @@ enum inode_i_mutex_lock_class I_MUTEX_PARENT, I_MUTEX_CHILD, I_MUTEX_XATTR, - I_MUTEX_QUOTA + I_MUTEX_NONDIR2 }; +void lock_two_nondirectories(struct inode *, struct inode*); +void unlock_two_nondirectories(struct inode *, struct inode*); + /* * NOTE: in a 32bit arch with a preemptable kernel and * an UP compile the i_size_read/write must be atomic @@ -764,12 +770,7 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index) #define FILE_MNT_WRITE_RELEASED 2 struct file { - /* - * fu_list becomes invalid after file_free is called and queued via - * fu_rcuhead for RCU freeing - */ union { - struct list_head fu_list; struct llist_node fu_llist; struct rcu_head fu_rcuhead; } f_u; @@ -783,9 +784,6 @@ struct file { * Must not be taken from IRQ context. */ spinlock_t f_lock; -#ifdef CONFIG_SMP - int f_sb_list_cpu; -#endif atomic_long_t f_count; unsigned int f_flags; fmode_t f_mode; @@ -882,6 +880,7 @@ static inline int file_check_writeable(struct file *filp) #define FL_POSIX 1 #define FL_FLOCK 2 +#define FL_DELEG 4 /* NFSv4 delegation */ #define FL_ACCESS 8 /* not trying to lock, just looking */ #define FL_EXISTS 16 /* when unlocking, test for existence */ #define FL_LEASE 32 /* lease held on this file */ @@ -1023,7 +1022,7 @@ extern int vfs_test_lock(struct file *, struct file_lock *); extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *); extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl); extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); -extern int __break_lease(struct inode *inode, unsigned int flags); +extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type); extern void lease_get_mtime(struct inode *, struct timespec *time); extern int generic_setlease(struct file *, long, struct file_lock **); extern int vfs_setlease(struct file *, long, struct file_lock **); @@ -1132,7 +1131,7 @@ static inline int flock_lock_file_wait(struct file *filp, return -ENOLCK; } -static inline int __break_lease(struct inode *inode, unsigned int mode) +static inline int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) { return 0; } @@ -1264,11 +1263,6 @@ struct super_block { struct list_head s_inodes; /* all inodes */ struct hlist_bl_head s_anon; /* anonymous dentries for (nfs) exporting */ -#ifdef CONFIG_SMP - struct list_head __percpu *s_files; -#else - struct list_head s_files; -#endif struct list_head s_mounts; /* list of mounts; _not_ for fs use */ struct block_device *s_bdev; struct backing_dev_info *s_bdi; @@ -1330,6 +1324,7 @@ struct super_block { */ struct list_lru s_dentry_lru ____cacheline_aligned_in_smp; struct list_lru s_inode_lru ____cacheline_aligned_in_smp; + struct rcu_head rcu; }; extern struct timespec current_fs_time(struct super_block *sb); @@ -1458,10 +1453,10 @@ extern int vfs_create(struct inode *, struct dentry *, umode_t, bool); extern int vfs_mkdir(struct inode *, struct dentry *, umode_t); extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t); extern int vfs_symlink(struct inode *, struct dentry *, const char *); -extern int vfs_link(struct dentry *, struct inode *, struct dentry *); +extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **); extern int vfs_rmdir(struct inode *, struct dentry *); -extern int vfs_unlink(struct inode *, struct dentry *); -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); +extern int vfs_unlink(struct inode *, struct dentry *, struct inode **); +extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **); /* * VFS dentry helper functions. @@ -1875,6 +1870,17 @@ extern struct dentry *mount_pseudo(struct file_system_type *, char *, (((fops) && try_module_get((fops)->owner) ? (fops) : NULL)) #define fops_put(fops) \ do { if (fops) module_put((fops)->owner); } while(0) +/* + * This one is to be used *ONLY* from ->open() instances. + * fops must be non-NULL, pinned down *and* module dependencies + * should be sufficient to pin the caller down as well. + */ +#define replace_fops(f, fops) \ + do { \ + struct file *__file = (f); \ + fops_put(__file->f_op); \ + BUG_ON(!(__file->f_op = (fops))); \ + } while(0) extern int register_filesystem(struct file_system_type *); extern int unregister_filesystem(struct file_system_type *); @@ -1899,6 +1905,9 @@ extern bool fs_fully_visible(struct file_system_type *); extern int current_umask(void); +extern void ihold(struct inode * inode); +extern void iput(struct inode *); + /* /sys/fs */ extern struct kobject *fs_kobj; @@ -1955,9 +1964,39 @@ static inline int locks_verify_truncate(struct inode *inode, static inline int break_lease(struct inode *inode, unsigned int mode) { if (inode->i_flock) - return __break_lease(inode, mode); + return __break_lease(inode, mode, FL_LEASE); + return 0; +} + +static inline int break_deleg(struct inode *inode, unsigned int mode) +{ + if (inode->i_flock) + return __break_lease(inode, mode, FL_DELEG); return 0; } + +static inline int try_break_deleg(struct inode *inode, struct inode **delegated_inode) +{ + int ret; + + ret = break_deleg(inode, O_WRONLY|O_NONBLOCK); + if (ret == -EWOULDBLOCK && delegated_inode) { + *delegated_inode = inode; + ihold(inode); + } + return ret; +} + +static inline int break_deleg_wait(struct inode **delegated_inode) +{ + int ret; + + ret = break_deleg(*delegated_inode, O_WRONLY); + iput(*delegated_inode); + *delegated_inode = NULL; + return ret; +} + #else /* !CONFIG_FILE_LOCKING */ static inline int locks_mandatory_locked(struct inode *inode) { @@ -1997,6 +2036,22 @@ static inline int break_lease(struct inode *inode, unsigned int mode) return 0; } +static inline int break_deleg(struct inode *inode, unsigned int mode) +{ + return 0; +} + +static inline int try_break_deleg(struct inode *inode, struct inode **delegated_inode) +{ + return 0; +} + +static inline int break_deleg_wait(struct inode **delegated_inode) +{ + BUG(); + return 0; +} + #endif /* CONFIG_FILE_LOCKING */ /* fs/open.c */ @@ -2223,7 +2278,7 @@ extern void emergency_remount(void); #ifdef CONFIG_BLOCK extern sector_t bmap(struct inode *, sector_t); #endif -extern int notify_change(struct dentry *, struct iattr *); +extern int notify_change(struct dentry *, struct iattr *, struct inode **); extern int inode_permission(struct inode *, int); extern int generic_permission(struct inode *, int); @@ -2337,8 +2392,6 @@ extern loff_t vfs_llseek(struct file *file, loff_t offset, int whence); extern int inode_init_always(struct super_block *, struct inode *); extern void inode_init_once(struct inode *); extern void address_space_init_once(struct address_space *mapping); -extern void ihold(struct inode * inode); -extern void iput(struct inode *); extern struct inode * igrab(struct inode *); extern ino_t iunique(struct super_block *, ino_t); extern int inode_needs_sync(struct inode *inode); @@ -2507,8 +2560,10 @@ extern int __page_symlink(struct inode *inode, const char *symname, int len, int nofs); extern int page_symlink(struct inode *inode, const char *symname, int len); extern const struct inode_operations page_symlink_inode_operations; +extern void kfree_put_link(struct dentry *, struct nameidata *, void *); extern int generic_readlink(struct dentry *, char __user *, int); extern void generic_fillattr(struct inode *, struct kstat *); +int vfs_getattr_nosec(struct path *path, struct kstat *stat); extern int vfs_getattr(struct path *, struct kstat *); void __inode_add_bytes(struct inode *inode, loff_t bytes); void inode_add_bytes(struct inode *inode, loff_t bytes); @@ -2567,6 +2622,7 @@ extern int simple_write_begin(struct file *file, struct address_space *mapping, extern int simple_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata); +extern struct inode *alloc_anon_inode(struct super_block *); extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags); extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); diff --git a/include/linux/lglock.h b/include/linux/lglock.h index 0d24e932db0b..96549abe8842 100644 --- a/include/linux/lglock.h +++ b/include/linux/lglock.h @@ -25,16 +25,6 @@ #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) 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 DEFINE_BRLOCK(name) DEFINE_LGLOCK(name) -#define DEFINE_STATIC_BRLOCK(name) DEFINE_STATIC_LGLOCK(name) - #ifdef CONFIG_DEBUG_LOCK_ALLOC #define LOCKDEP_INIT_MAP lockdep_init_map #else diff --git a/include/linux/mount.h b/include/linux/mount.h index 38cd98f112a0..371d346fa270 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -49,6 +49,8 @@ struct mnt_namespace; #define MNT_LOCK_READONLY 0x400000 #define MNT_LOCKED 0x800000 +#define MNT_DOOMED 0x1000000 +#define MNT_SYNC_UMOUNT 0x2000000 struct vfsmount { struct dentry *mnt_root; /* root of the mounted tree */ diff --git a/include/linux/namei.h b/include/linux/namei.h index 8e47bc7a1665..492de72560fa 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -16,7 +16,7 @@ struct nameidata { struct path root; struct inode *inode; /* path.dentry.d_inode */ unsigned int flags; - unsigned seq; + unsigned seq, m_seq; int last_type; unsigned depth; char *saved_names[MAX_NESTED_LINKS + 1]; diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index e2772666f004..7246ef3d4455 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -23,6 +23,7 @@ struct bsd_acct_struct; struct pid_namespace { struct kref kref; struct pidmap pidmap[PIDMAP_ENTRIES]; + struct rcu_head rcu; int last_pid; unsigned int nr_hashed; struct task_struct *child_reaper; |