diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-21 18:38:14 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-21 18:38:14 -0400 |
| commit | fd9be4ce2e1eb407a8152f823698cc0d652bbec8 (patch) | |
| tree | b1cc279fa5b1f90995253f007564f001aa20c743 /include/linux | |
| parent | b1af9ccce9cff5b48c37424dbdbb3aa9021915db (diff) | |
| parent | ad775f5a8faa5845377f093ca11caf577404add9 (diff) | |
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
...
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/file.h | 1 | ||||
| -rw-r--r-- | include/linux/fs.h | 52 | ||||
| -rw-r--r-- | include/linux/mount.h | 11 |
3 files changed, 63 insertions, 1 deletions
diff --git a/include/linux/file.h b/include/linux/file.h index 7239baac81a9..653477021e4c 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
| @@ -61,6 +61,7 @@ extern struct kmem_cache *filp_cachep; | |||
| 61 | 61 | ||
| 62 | extern void __fput(struct file *); | 62 | extern void __fput(struct file *); |
| 63 | extern void fput(struct file *); | 63 | extern void fput(struct file *); |
| 64 | extern void drop_file_write_access(struct file *file); | ||
| 64 | 65 | ||
| 65 | struct file_operations; | 66 | struct file_operations; |
| 66 | struct vfsmount; | 67 | struct vfsmount; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index b84b848431f2..d1eeea669d2c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -776,6 +776,9 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index) | |||
| 776 | index < ra->start + ra->size); | 776 | index < ra->start + ra->size); |
| 777 | } | 777 | } |
| 778 | 778 | ||
| 779 | #define FILE_MNT_WRITE_TAKEN 1 | ||
| 780 | #define FILE_MNT_WRITE_RELEASED 2 | ||
| 781 | |||
| 779 | struct file { | 782 | struct file { |
| 780 | /* | 783 | /* |
| 781 | * fu_list becomes invalid after file_free is called and queued via | 784 | * fu_list becomes invalid after file_free is called and queued via |
| @@ -810,6 +813,9 @@ struct file { | |||
| 810 | spinlock_t f_ep_lock; | 813 | spinlock_t f_ep_lock; |
| 811 | #endif /* #ifdef CONFIG_EPOLL */ | 814 | #endif /* #ifdef CONFIG_EPOLL */ |
| 812 | struct address_space *f_mapping; | 815 | struct address_space *f_mapping; |
| 816 | #ifdef CONFIG_DEBUG_WRITECOUNT | ||
| 817 | unsigned long f_mnt_write_state; | ||
| 818 | #endif | ||
| 813 | }; | 819 | }; |
| 814 | extern spinlock_t files_lock; | 820 | extern spinlock_t files_lock; |
| 815 | #define file_list_lock() spin_lock(&files_lock); | 821 | #define file_list_lock() spin_lock(&files_lock); |
| @@ -818,6 +824,49 @@ extern spinlock_t files_lock; | |||
| 818 | #define get_file(x) atomic_inc(&(x)->f_count) | 824 | #define get_file(x) atomic_inc(&(x)->f_count) |
| 819 | #define file_count(x) atomic_read(&(x)->f_count) | 825 | #define file_count(x) atomic_read(&(x)->f_count) |
| 820 | 826 | ||
| 827 | #ifdef CONFIG_DEBUG_WRITECOUNT | ||
| 828 | static inline void file_take_write(struct file *f) | ||
| 829 | { | ||
| 830 | WARN_ON(f->f_mnt_write_state != 0); | ||
| 831 | f->f_mnt_write_state = FILE_MNT_WRITE_TAKEN; | ||
| 832 | } | ||
| 833 | static inline void file_release_write(struct file *f) | ||
| 834 | { | ||
| 835 | f->f_mnt_write_state |= FILE_MNT_WRITE_RELEASED; | ||
| 836 | } | ||
| 837 | static inline void file_reset_write(struct file *f) | ||
| 838 | { | ||
| 839 | f->f_mnt_write_state = 0; | ||
| 840 | } | ||
| 841 | static inline void file_check_state(struct file *f) | ||
| 842 | { | ||
| 843 | /* | ||
| 844 | * At this point, either both or neither of these bits | ||
| 845 | * should be set. | ||
| 846 | */ | ||
| 847 | WARN_ON(f->f_mnt_write_state == FILE_MNT_WRITE_TAKEN); | ||
| 848 | WARN_ON(f->f_mnt_write_state == FILE_MNT_WRITE_RELEASED); | ||
| 849 | } | ||
| 850 | static inline int file_check_writeable(struct file *f) | ||
| 851 | { | ||
| 852 | if (f->f_mnt_write_state == FILE_MNT_WRITE_TAKEN) | ||
| 853 | return 0; | ||
| 854 | printk(KERN_WARNING "writeable file with no " | ||
| 855 | "mnt_want_write()\n"); | ||
| 856 | WARN_ON(1); | ||
| 857 | return -EINVAL; | ||
| 858 | } | ||
| 859 | #else /* !CONFIG_DEBUG_WRITECOUNT */ | ||
| 860 | static inline void file_take_write(struct file *filp) {} | ||
| 861 | static inline void file_release_write(struct file *filp) {} | ||
| 862 | static inline void file_reset_write(struct file *filp) {} | ||
| 863 | static inline void file_check_state(struct file *filp) {} | ||
| 864 | static inline int file_check_writeable(struct file *filp) | ||
| 865 | { | ||
| 866 | return 0; | ||
| 867 | } | ||
| 868 | #endif /* CONFIG_DEBUG_WRITECOUNT */ | ||
| 869 | |||
| 821 | #define MAX_NON_LFS ((1UL<<31) - 1) | 870 | #define MAX_NON_LFS ((1UL<<31) - 1) |
| 822 | 871 | ||
| 823 | /* Page cache limit. The filesystems should put that into their s_maxbytes | 872 | /* 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); | |||
| 1735 | extern struct file *create_write_pipe(void); | 1784 | extern struct file *create_write_pipe(void); |
| 1736 | extern void free_write_pipe(struct file *); | 1785 | extern void free_write_pipe(struct file *); |
| 1737 | 1786 | ||
| 1738 | extern int open_namei(int dfd, const char *, int, int, struct nameidata *); | 1787 | extern struct file *do_filp_open(int dfd, const char *pathname, |
| 1788 | int open_flag, int mode); | ||
| 1739 | extern int may_open(struct nameidata *, int, int); | 1789 | extern int may_open(struct nameidata *, int, int); |
| 1740 | 1790 | ||
| 1741 | extern int kernel_read(struct file *, unsigned long, char *, unsigned long); | 1791 | extern int kernel_read(struct file *, unsigned long, char *, unsigned long); |
diff --git a/include/linux/mount.h b/include/linux/mount.h index 5ee2df217cdf..d6600e3f7e45 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
| 16 | #include <linux/list.h> | 16 | #include <linux/list.h> |
| 17 | #include <linux/nodemask.h> | ||
| 17 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
| 18 | #include <asm/atomic.h> | 19 | #include <asm/atomic.h> |
| 19 | 20 | ||
| @@ -28,8 +29,10 @@ struct mnt_namespace; | |||
| 28 | #define MNT_NOATIME 0x08 | 29 | #define MNT_NOATIME 0x08 |
| 29 | #define MNT_NODIRATIME 0x10 | 30 | #define MNT_NODIRATIME 0x10 |
| 30 | #define MNT_RELATIME 0x20 | 31 | #define MNT_RELATIME 0x20 |
| 32 | #define MNT_READONLY 0x40 /* does the user want this to be r/o? */ | ||
| 31 | 33 | ||
| 32 | #define MNT_SHRINKABLE 0x100 | 34 | #define MNT_SHRINKABLE 0x100 |
| 35 | #define MNT_IMBALANCED_WRITE_COUNT 0x200 /* just for debugging */ | ||
| 33 | 36 | ||
| 34 | #define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */ | 37 | #define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */ |
| 35 | #define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */ | 38 | #define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */ |
| @@ -62,6 +65,11 @@ struct vfsmount { | |||
| 62 | int mnt_expiry_mark; /* true if marked for expiry */ | 65 | int mnt_expiry_mark; /* true if marked for expiry */ |
| 63 | int mnt_pinned; | 66 | int mnt_pinned; |
| 64 | int mnt_ghosts; | 67 | int mnt_ghosts; |
| 68 | /* | ||
| 69 | * This value is not stable unless all of the mnt_writers[] spinlocks | ||
| 70 | * are held, and all mnt_writer[]s on this mount have 0 as their ->count | ||
| 71 | */ | ||
| 72 | atomic_t __mnt_writers; | ||
| 65 | }; | 73 | }; |
| 66 | 74 | ||
| 67 | static inline struct vfsmount *mntget(struct vfsmount *mnt) | 75 | static inline struct vfsmount *mntget(struct vfsmount *mnt) |
| @@ -71,9 +79,12 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt) | |||
| 71 | return mnt; | 79 | return mnt; |
| 72 | } | 80 | } |
| 73 | 81 | ||
| 82 | extern int mnt_want_write(struct vfsmount *mnt); | ||
| 83 | extern void mnt_drop_write(struct vfsmount *mnt); | ||
| 74 | extern void mntput_no_expire(struct vfsmount *mnt); | 84 | extern void mntput_no_expire(struct vfsmount *mnt); |
| 75 | extern void mnt_pin(struct vfsmount *mnt); | 85 | extern void mnt_pin(struct vfsmount *mnt); |
| 76 | extern void mnt_unpin(struct vfsmount *mnt); | 86 | extern void mnt_unpin(struct vfsmount *mnt); |
| 87 | extern int __mnt_is_readonly(struct vfsmount *mnt); | ||
| 77 | 88 | ||
| 78 | static inline void mntput(struct vfsmount *mnt) | 89 | static inline void mntput(struct vfsmount *mnt) |
| 79 | { | 90 | { |
