diff options
author | Dave Hansen <haveblue@us.ibm.com> | 2008-02-15 17:37:30 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-19 00:25:32 -0400 |
commit | 8366025eb80dfa0d8d94b286d53027081c280ef1 (patch) | |
tree | 052c9244cd9d763ad8467bb95b25d903d58b7f11 | |
parent | a70e65df8812c52252fa07a2eb92a46451a4427f (diff) |
[PATCH] r/o bind mounts: stub functions
This patch adds two function mnt_want_write() and mnt_drop_write(). These are
used like a lock pair around and fs operations that might cause a write to the
filesystem.
Before these can become useful, we must first cover each place in the VFS
where writes are performed with a want/drop pair. When that is complete, we
can actually introduce code that will safely check the counts before allowing
r/w<->r/o transitions to occur.
Acked-by: Serge Hallyn <serue@us.ibm.com>
Acked-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/namespace.c | 54 | ||||
-rw-r--r-- | include/linux/mount.h | 3 |
2 files changed, 57 insertions, 0 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 94f026ec990a..066b393578c1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -80,6 +80,60 @@ struct vfsmount *alloc_vfsmnt(const char *name) | |||
80 | return mnt; | 80 | return mnt; |
81 | } | 81 | } |
82 | 82 | ||
83 | /* | ||
84 | * Most r/o checks on a fs are for operations that take | ||
85 | * discrete amounts of time, like a write() or unlink(). | ||
86 | * We must keep track of when those operations start | ||
87 | * (for permission checks) and when they end, so that | ||
88 | * we can determine when writes are able to occur to | ||
89 | * a filesystem. | ||
90 | */ | ||
91 | /** | ||
92 | * mnt_want_write - get write access to a mount | ||
93 | * @mnt: the mount on which to take a write | ||
94 | * | ||
95 | * This tells the low-level filesystem that a write is | ||
96 | * about to be performed to it, and makes sure that | ||
97 | * writes are allowed before returning success. When | ||
98 | * the write operation is finished, mnt_drop_write() | ||
99 | * must be called. This is effectively a refcount. | ||
100 | */ | ||
101 | int mnt_want_write(struct vfsmount *mnt) | ||
102 | { | ||
103 | if (__mnt_is_readonly(mnt)) | ||
104 | return -EROFS; | ||
105 | return 0; | ||
106 | } | ||
107 | EXPORT_SYMBOL_GPL(mnt_want_write); | ||
108 | |||
109 | /** | ||
110 | * mnt_drop_write - give up write access to a mount | ||
111 | * @mnt: the mount on which to give up write access | ||
112 | * | ||
113 | * Tells the low-level filesystem that we are done | ||
114 | * performing writes to it. Must be matched with | ||
115 | * mnt_want_write() call above. | ||
116 | */ | ||
117 | void mnt_drop_write(struct vfsmount *mnt) | ||
118 | { | ||
119 | } | ||
120 | EXPORT_SYMBOL_GPL(mnt_drop_write); | ||
121 | |||
122 | /* | ||
123 | * __mnt_is_readonly: check whether a mount is read-only | ||
124 | * @mnt: the mount to check for its write status | ||
125 | * | ||
126 | * This shouldn't be used directly ouside of the VFS. | ||
127 | * It does not guarantee that the filesystem will stay | ||
128 | * r/w, just that it is right *now*. This can not and | ||
129 | * should not be used in place of IS_RDONLY(inode). | ||
130 | */ | ||
131 | int __mnt_is_readonly(struct vfsmount *mnt) | ||
132 | { | ||
133 | return (mnt->mnt_sb->s_flags & MS_RDONLY); | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(__mnt_is_readonly); | ||
136 | |||
83 | int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) | 137 | int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) |
84 | { | 138 | { |
85 | mnt->mnt_sb = sb; | 139 | mnt->mnt_sb = sb; |
diff --git a/include/linux/mount.h b/include/linux/mount.h index 5ee2df217cdf..2eecd2c8c760 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h | |||
@@ -71,9 +71,12 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt) | |||
71 | return mnt; | 71 | return mnt; |
72 | } | 72 | } |
73 | 73 | ||
74 | extern int mnt_want_write(struct vfsmount *mnt); | ||
75 | extern void mnt_drop_write(struct vfsmount *mnt); | ||
74 | extern void mntput_no_expire(struct vfsmount *mnt); | 76 | extern void mntput_no_expire(struct vfsmount *mnt); |
75 | extern void mnt_pin(struct vfsmount *mnt); | 77 | extern void mnt_pin(struct vfsmount *mnt); |
76 | extern void mnt_unpin(struct vfsmount *mnt); | 78 | extern void mnt_unpin(struct vfsmount *mnt); |
79 | extern int __mnt_is_readonly(struct vfsmount *mnt); | ||
77 | 80 | ||
78 | static inline void mntput(struct vfsmount *mnt) | 81 | static inline void mntput(struct vfsmount *mnt) |
79 | { | 82 | { |