]>
Commit | Line | Data |
---|---|---|
e14748e8 SF |
1 | /* |
2 | * Copyright (C) 2005-2016 Junjiro R. Okajima | |
3 | * | |
4 | * This program, aufs is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | */ | |
17 | ||
18 | /* | |
19 | * sub-routines for VFS | |
20 | */ | |
21 | ||
22 | #ifndef __AUFS_VFSUB_H__ | |
23 | #define __AUFS_VFSUB_H__ | |
24 | ||
25 | #ifdef __KERNEL__ | |
26 | ||
27 | #include <linux/fs.h> | |
28 | #include <linux/mount.h> | |
29 | #include <linux/posix_acl.h> | |
30 | #include <linux/xattr.h> | |
31 | #include "debug.h" | |
32 | ||
33 | /* copied from linux/fs/internal.h */ | |
34 | /* todo: BAD approach!! */ | |
35 | extern void __mnt_drop_write(struct vfsmount *); | |
36 | extern int open_check_o_direct(struct file *f); | |
37 | ||
38 | /* ---------------------------------------------------------------------- */ | |
39 | ||
40 | /* lock subclass for lower inode */ | |
41 | /* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */ | |
42 | /* reduce? gave up. */ | |
43 | enum { | |
44 | AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */ | |
45 | AuLsc_I_PARENT, /* lower inode, parent first */ | |
46 | AuLsc_I_PARENT2, /* copyup dirs */ | |
47 | AuLsc_I_PARENT3, /* copyup wh */ | |
48 | AuLsc_I_CHILD, | |
49 | AuLsc_I_CHILD2, | |
50 | AuLsc_I_End | |
51 | }; | |
52 | ||
53 | /* to debug easier, do not make them inlined functions */ | |
54 | #define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx)) | |
55 | #define IMustLock(i) AuDebugOn(!inode_is_locked(i)) | |
56 | ||
57 | /* ---------------------------------------------------------------------- */ | |
58 | ||
59 | static inline void vfsub_drop_nlink(struct inode *inode) | |
60 | { | |
61 | AuDebugOn(!inode->i_nlink); | |
62 | drop_nlink(inode); | |
63 | } | |
64 | ||
65 | static inline void vfsub_dead_dir(struct inode *inode) | |
66 | { | |
67 | AuDebugOn(!S_ISDIR(inode->i_mode)); | |
68 | inode->i_flags |= S_DEAD; | |
69 | clear_nlink(inode); | |
70 | } | |
71 | ||
72 | static inline int vfsub_native_ro(struct inode *inode) | |
73 | { | |
74 | return (inode->i_sb->s_flags & MS_RDONLY) | |
75 | || IS_RDONLY(inode) | |
76 | /* || IS_APPEND(inode) */ | |
77 | || IS_IMMUTABLE(inode); | |
78 | } | |
79 | ||
80 | #ifdef CONFIG_AUFS_BR_FUSE | |
81 | int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb); | |
82 | #else | |
83 | AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb); | |
84 | #endif | |
85 | ||
86 | int vfsub_sync_filesystem(struct super_block *h_sb, int wait); | |
87 | ||
88 | /* ---------------------------------------------------------------------- */ | |
89 | ||
90 | int vfsub_update_h_iattr(struct path *h_path, int *did); | |
91 | struct file *vfsub_dentry_open(struct path *path, int flags); | |
92 | struct file *vfsub_filp_open(const char *path, int oflags, int mode); | |
93 | struct vfsub_aopen_args { | |
94 | struct file *file; | |
95 | unsigned int open_flag; | |
96 | umode_t create_mode; | |
97 | int *opened; | |
98 | }; | |
99 | struct au_branch; | |
100 | int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, | |
101 | struct vfsub_aopen_args *args, struct au_branch *br); | |
102 | int vfsub_kern_path(const char *name, unsigned int flags, struct path *path); | |
103 | ||
104 | struct dentry *vfsub_lookup_one_len_unlocked(const char *name, | |
105 | struct dentry *parent, int len); | |
106 | struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, | |
107 | int len); | |
108 | ||
109 | struct vfsub_lkup_one_args { | |
110 | struct dentry **errp; | |
111 | struct qstr *name; | |
112 | struct dentry *parent; | |
113 | }; | |
114 | ||
115 | static inline struct dentry *vfsub_lkup_one(struct qstr *name, | |
116 | struct dentry *parent) | |
117 | { | |
118 | return vfsub_lookup_one_len(name->name, parent, name->len); | |
119 | } | |
120 | ||
121 | void vfsub_call_lkup_one(void *args); | |
122 | ||
123 | /* ---------------------------------------------------------------------- */ | |
124 | ||
125 | static inline int vfsub_mnt_want_write(struct vfsmount *mnt) | |
126 | { | |
127 | int err; | |
128 | ||
129 | lockdep_off(); | |
130 | err = mnt_want_write(mnt); | |
131 | lockdep_on(); | |
132 | return err; | |
133 | } | |
134 | ||
135 | static inline void vfsub_mnt_drop_write(struct vfsmount *mnt) | |
136 | { | |
137 | lockdep_off(); | |
138 | mnt_drop_write(mnt); | |
139 | lockdep_on(); | |
140 | } | |
141 | ||
142 | #if 0 /* reserved */ | |
143 | static inline void vfsub_mnt_drop_write_file(struct file *file) | |
144 | { | |
145 | lockdep_off(); | |
146 | mnt_drop_write_file(file); | |
147 | lockdep_on(); | |
148 | } | |
149 | #endif | |
150 | ||
151 | /* ---------------------------------------------------------------------- */ | |
152 | ||
153 | struct au_hinode; | |
154 | struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, | |
155 | struct dentry *d2, struct au_hinode *hdir2); | |
156 | void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, | |
157 | struct dentry *d2, struct au_hinode *hdir2); | |
158 | ||
159 | int vfsub_create(struct inode *dir, struct path *path, int mode, | |
160 | bool want_excl); | |
161 | int vfsub_symlink(struct inode *dir, struct path *path, | |
162 | const char *symname); | |
163 | int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev); | |
164 | int vfsub_link(struct dentry *src_dentry, struct inode *dir, | |
165 | struct path *path, struct inode **delegated_inode); | |
166 | int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry, | |
167 | struct inode *hdir, struct path *path, | |
168 | struct inode **delegated_inode, unsigned int flags); | |
169 | int vfsub_mkdir(struct inode *dir, struct path *path, int mode); | |
170 | int vfsub_rmdir(struct inode *dir, struct path *path); | |
171 | ||
172 | /* ---------------------------------------------------------------------- */ | |
173 | ||
174 | ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, | |
175 | loff_t *ppos); | |
176 | ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, | |
177 | loff_t *ppos); | |
178 | ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, | |
179 | loff_t *ppos); | |
180 | ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, | |
181 | loff_t *ppos); | |
182 | int vfsub_flush(struct file *file, fl_owner_t id); | |
183 | int vfsub_iterate_dir(struct file *file, struct dir_context *ctx); | |
184 | ||
185 | static inline loff_t vfsub_f_size_read(struct file *file) | |
186 | { | |
187 | return i_size_read(file_inode(file)); | |
188 | } | |
189 | ||
190 | static inline unsigned int vfsub_file_flags(struct file *file) | |
191 | { | |
192 | unsigned int flags; | |
193 | ||
194 | spin_lock(&file->f_lock); | |
195 | flags = file->f_flags; | |
196 | spin_unlock(&file->f_lock); | |
197 | ||
198 | return flags; | |
199 | } | |
200 | ||
201 | static inline int vfsub_file_execed(struct file *file) | |
202 | { | |
203 | /* todo: direct access f_flags */ | |
204 | return !!(vfsub_file_flags(file) & __FMODE_EXEC); | |
205 | } | |
206 | ||
207 | #if 0 /* reserved */ | |
208 | static inline void vfsub_file_accessed(struct file *h_file) | |
209 | { | |
210 | file_accessed(h_file); | |
211 | vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/ | |
212 | } | |
213 | #endif | |
214 | ||
215 | #if 0 /* reserved */ | |
216 | static inline void vfsub_touch_atime(struct vfsmount *h_mnt, | |
217 | struct dentry *h_dentry) | |
218 | { | |
219 | struct path h_path = { | |
220 | .dentry = h_dentry, | |
221 | .mnt = h_mnt | |
222 | }; | |
223 | touch_atime(&h_path); | |
224 | vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/ | |
225 | } | |
226 | #endif | |
227 | ||
228 | static inline int vfsub_update_time(struct inode *h_inode, struct timespec *ts, | |
229 | int flags) | |
230 | { | |
231 | return update_time(h_inode, ts, flags); | |
232 | /* no vfsub_update_h_iattr() since we don't have struct path */ | |
233 | } | |
234 | ||
235 | #ifdef CONFIG_FS_POSIX_ACL | |
236 | static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode) | |
237 | { | |
238 | int err; | |
239 | ||
240 | err = posix_acl_chmod(h_inode, h_mode); | |
241 | if (err == -EOPNOTSUPP) | |
242 | err = 0; | |
243 | return err; | |
244 | } | |
245 | #else | |
246 | AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode); | |
247 | #endif | |
248 | ||
249 | long vfsub_splice_to(struct file *in, loff_t *ppos, | |
250 | struct pipe_inode_info *pipe, size_t len, | |
251 | unsigned int flags); | |
252 | long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, | |
253 | loff_t *ppos, size_t len, unsigned int flags); | |
254 | ||
255 | static inline long vfsub_truncate(struct path *path, loff_t length) | |
256 | { | |
257 | long err; | |
258 | ||
259 | lockdep_off(); | |
260 | err = vfs_truncate(path, length); | |
261 | lockdep_on(); | |
262 | return err; | |
263 | } | |
264 | ||
265 | int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, | |
266 | struct file *h_file); | |
267 | int vfsub_fsync(struct file *file, struct path *path, int datasync); | |
268 | ||
269 | /* ---------------------------------------------------------------------- */ | |
270 | ||
271 | static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin) | |
272 | { | |
273 | loff_t err; | |
274 | ||
275 | lockdep_off(); | |
276 | err = vfs_llseek(file, offset, origin); | |
277 | lockdep_on(); | |
278 | return err; | |
279 | } | |
280 | ||
281 | /* ---------------------------------------------------------------------- */ | |
282 | ||
283 | int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode); | |
284 | int vfsub_sio_rmdir(struct inode *dir, struct path *path); | |
285 | int vfsub_sio_notify_change(struct path *path, struct iattr *ia, | |
286 | struct inode **delegated_inode); | |
287 | int vfsub_notify_change(struct path *path, struct iattr *ia, | |
288 | struct inode **delegated_inode); | |
289 | int vfsub_unlink(struct inode *dir, struct path *path, | |
290 | struct inode **delegated_inode, int force); | |
291 | ||
292 | /* ---------------------------------------------------------------------- */ | |
293 | ||
294 | static inline int vfsub_setxattr(struct dentry *dentry, const char *name, | |
295 | const void *value, size_t size, int flags) | |
296 | { | |
297 | int err; | |
298 | ||
299 | lockdep_off(); | |
300 | err = vfs_setxattr(dentry, name, value, size, flags); | |
301 | lockdep_on(); | |
302 | ||
303 | return err; | |
304 | } | |
305 | ||
306 | static inline int vfsub_removexattr(struct dentry *dentry, const char *name) | |
307 | { | |
308 | int err; | |
309 | ||
310 | lockdep_off(); | |
311 | err = vfs_removexattr(dentry, name); | |
312 | lockdep_on(); | |
313 | ||
314 | return err; | |
315 | } | |
316 | ||
317 | #endif /* __KERNEL__ */ | |
318 | #endif /* __AUFS_VFSUB_H__ */ |