Merge branch 'ro-bind.b6' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'ro-bind.b6' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (24 commits) [PATCH] r/o bind mounts: debugging for missed calls [PATCH] r/o bind mounts: honor mount writer counts at remount [PATCH] r/o bind mounts: track numbers of writers to mounts [PATCH] r/o bind mounts: check mnt instead of superblock directly [PATCH] r/o bind mounts: elevate count for xfs timestamp updates [PATCH] r/o bind mounts: make access() use new r/o helper [PATCH] r/o bind mounts: write counts for truncate() [PATCH] r/o bind mounts: elevate write count for chmod/chown callers [PATCH] r/o bind mounts: elevate write count for open()s [PATCH] r/o bind mounts: elevate write count for ioctls() [PATCH] r/o bind mounts: write count for file_update_time() [PATCH] r/o bind mounts: elevate write count for do_utimes() [PATCH] r/o bind mounts: write counts for touch_atime() [PATCH] r/o bind mounts: elevate write count for ncp_ioctl() [PATCH] r/o bind mounts: elevate write count for xattr_permission() callers [PATCH] r/o bind mounts: get write access for vfs_rename() callers [PATCH] r/o bind mounts: write counts for link/symlink [PATCH] r/o bind mounts: get callers of vfs_mknod/create/mkdir() [PATCH] r/o bind mounts: elevate write count for rmdir and unlink. [PATCH] r/o bind mounts: drop write during emergency remount ...
This commit is contained in:
commit
fd9be4ce2e
31 changed files with 1256 additions and 351 deletions
|
@ -61,6 +61,7 @@ extern struct kmem_cache *filp_cachep;
|
|||
|
||||
extern void __fput(struct file *);
|
||||
extern void fput(struct file *);
|
||||
extern void drop_file_write_access(struct file *file);
|
||||
|
||||
struct file_operations;
|
||||
struct vfsmount;
|
||||
|
|
|
@ -776,6 +776,9 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
|
|||
index < ra->start + ra->size);
|
||||
}
|
||||
|
||||
#define FILE_MNT_WRITE_TAKEN 1
|
||||
#define FILE_MNT_WRITE_RELEASED 2
|
||||
|
||||
struct file {
|
||||
/*
|
||||
* fu_list becomes invalid after file_free is called and queued via
|
||||
|
@ -810,6 +813,9 @@ struct file {
|
|||
spinlock_t f_ep_lock;
|
||||
#endif /* #ifdef CONFIG_EPOLL */
|
||||
struct address_space *f_mapping;
|
||||
#ifdef CONFIG_DEBUG_WRITECOUNT
|
||||
unsigned long f_mnt_write_state;
|
||||
#endif
|
||||
};
|
||||
extern spinlock_t files_lock;
|
||||
#define file_list_lock() spin_lock(&files_lock);
|
||||
|
@ -818,6 +824,49 @@ extern spinlock_t files_lock;
|
|||
#define get_file(x) atomic_inc(&(x)->f_count)
|
||||
#define file_count(x) atomic_read(&(x)->f_count)
|
||||
|
||||
#ifdef CONFIG_DEBUG_WRITECOUNT
|
||||
static inline void file_take_write(struct file *f)
|
||||
{
|
||||
WARN_ON(f->f_mnt_write_state != 0);
|
||||
f->f_mnt_write_state = FILE_MNT_WRITE_TAKEN;
|
||||
}
|
||||
static inline void file_release_write(struct file *f)
|
||||
{
|
||||
f->f_mnt_write_state |= FILE_MNT_WRITE_RELEASED;
|
||||
}
|
||||
static inline void file_reset_write(struct file *f)
|
||||
{
|
||||
f->f_mnt_write_state = 0;
|
||||
}
|
||||
static inline void file_check_state(struct file *f)
|
||||
{
|
||||
/*
|
||||
* At this point, either both or neither of these bits
|
||||
* should be set.
|
||||
*/
|
||||
WARN_ON(f->f_mnt_write_state == FILE_MNT_WRITE_TAKEN);
|
||||
WARN_ON(f->f_mnt_write_state == FILE_MNT_WRITE_RELEASED);
|
||||
}
|
||||
static inline int file_check_writeable(struct file *f)
|
||||
{
|
||||
if (f->f_mnt_write_state == FILE_MNT_WRITE_TAKEN)
|
||||
return 0;
|
||||
printk(KERN_WARNING "writeable file with no "
|
||||
"mnt_want_write()\n");
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
#else /* !CONFIG_DEBUG_WRITECOUNT */
|
||||
static inline void file_take_write(struct file *filp) {}
|
||||
static inline void file_release_write(struct file *filp) {}
|
||||
static inline void file_reset_write(struct file *filp) {}
|
||||
static inline void file_check_state(struct file *filp) {}
|
||||
static inline int file_check_writeable(struct file *filp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_WRITECOUNT */
|
||||
|
||||
#define MAX_NON_LFS ((1UL<<31) - 1)
|
||||
|
||||
/* Page cache limit. The filesystems should put that into their s_maxbytes
|
||||
|
@ -1735,7 +1784,8 @@ extern struct file *create_read_pipe(struct file *f);
|
|||
extern struct file *create_write_pipe(void);
|
||||
extern void free_write_pipe(struct file *);
|
||||
|
||||
extern int open_namei(int dfd, const char *, int, int, struct nameidata *);
|
||||
extern struct file *do_filp_open(int dfd, const char *pathname,
|
||||
int open_flag, int mode);
|
||||
extern int may_open(struct nameidata *, int, int);
|
||||
|
||||
extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/nodemask.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
|
@ -28,8 +29,10 @@ struct mnt_namespace;
|
|||
#define MNT_NOATIME 0x08
|
||||
#define MNT_NODIRATIME 0x10
|
||||
#define MNT_RELATIME 0x20
|
||||
#define MNT_READONLY 0x40 /* does the user want this to be r/o? */
|
||||
|
||||
#define MNT_SHRINKABLE 0x100
|
||||
#define MNT_IMBALANCED_WRITE_COUNT 0x200 /* just for debugging */
|
||||
|
||||
#define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */
|
||||
#define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */
|
||||
|
@ -62,6 +65,11 @@ struct vfsmount {
|
|||
int mnt_expiry_mark; /* true if marked for expiry */
|
||||
int mnt_pinned;
|
||||
int mnt_ghosts;
|
||||
/*
|
||||
* This value is not stable unless all of the mnt_writers[] spinlocks
|
||||
* are held, and all mnt_writer[]s on this mount have 0 as their ->count
|
||||
*/
|
||||
atomic_t __mnt_writers;
|
||||
};
|
||||
|
||||
static inline struct vfsmount *mntget(struct vfsmount *mnt)
|
||||
|
@ -71,9 +79,12 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt)
|
|||
return mnt;
|
||||
}
|
||||
|
||||
extern int mnt_want_write(struct vfsmount *mnt);
|
||||
extern void mnt_drop_write(struct vfsmount *mnt);
|
||||
extern void mntput_no_expire(struct vfsmount *mnt);
|
||||
extern void mnt_pin(struct vfsmount *mnt);
|
||||
extern void mnt_unpin(struct vfsmount *mnt);
|
||||
extern int __mnt_is_readonly(struct vfsmount *mnt);
|
||||
|
||||
static inline void mntput(struct vfsmount *mnt)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue