]>
Commit | Line | Data |
---|---|---|
b6450630 SF |
1 | /* |
2 | * Copyright (C) 2005-2017 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 | * file and vm operations | |
20 | */ | |
21 | ||
22 | #include <linux/aio.h> | |
23 | #include <linux/fs_stack.h> | |
24 | #include <linux/mman.h> | |
25 | #include <linux/security.h> | |
26 | #include "aufs.h" | |
27 | ||
28 | int au_do_open_nondir(struct file *file, int flags, struct file *h_file) | |
29 | { | |
30 | int err; | |
31 | aufs_bindex_t bindex; | |
32 | struct dentry *dentry, *h_dentry; | |
33 | struct au_finfo *finfo; | |
34 | struct inode *h_inode; | |
35 | ||
36 | FiMustWriteLock(file); | |
37 | ||
38 | err = 0; | |
39 | dentry = file->f_path.dentry; | |
40 | AuDebugOn(IS_ERR_OR_NULL(dentry)); | |
41 | finfo = au_fi(file); | |
42 | memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); | |
43 | atomic_set(&finfo->fi_mmapped, 0); | |
44 | bindex = au_dbtop(dentry); | |
45 | if (!h_file) { | |
46 | h_dentry = au_h_dptr(dentry, bindex); | |
47 | err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); | |
48 | if (unlikely(err)) | |
49 | goto out; | |
50 | h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); | |
51 | } else { | |
52 | h_dentry = h_file->f_path.dentry; | |
53 | err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); | |
54 | if (unlikely(err)) | |
55 | goto out; | |
56 | get_file(h_file); | |
57 | } | |
58 | if (IS_ERR(h_file)) | |
59 | err = PTR_ERR(h_file); | |
60 | else { | |
61 | if ((flags & __O_TMPFILE) | |
62 | && !(flags & O_EXCL)) { | |
63 | h_inode = file_inode(h_file); | |
64 | spin_lock(&h_inode->i_lock); | |
65 | h_inode->i_state |= I_LINKABLE; | |
66 | spin_unlock(&h_inode->i_lock); | |
67 | } | |
68 | au_set_fbtop(file, bindex); | |
69 | au_set_h_fptr(file, bindex, h_file); | |
70 | au_update_figen(file); | |
71 | /* todo: necessary? */ | |
72 | /* file->f_ra = h_file->f_ra; */ | |
73 | } | |
74 | ||
75 | out: | |
76 | return err; | |
77 | } | |
78 | ||
79 | static int aufs_open_nondir(struct inode *inode __maybe_unused, | |
80 | struct file *file) | |
81 | { | |
82 | int err; | |
83 | struct super_block *sb; | |
84 | struct au_do_open_args args = { | |
85 | .open = au_do_open_nondir | |
86 | }; | |
87 | ||
88 | AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n", | |
89 | file, vfsub_file_flags(file), file->f_mode); | |
90 | ||
91 | sb = file->f_path.dentry->d_sb; | |
92 | si_read_lock(sb, AuLock_FLUSH); | |
93 | err = au_do_open(file, &args); | |
94 | si_read_unlock(sb); | |
95 | return err; | |
96 | } | |
97 | ||
98 | int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file) | |
99 | { | |
100 | struct au_finfo *finfo; | |
101 | aufs_bindex_t bindex; | |
102 | ||
103 | finfo = au_fi(file); | |
104 | au_sphl_del(&finfo->fi_hlist, | |
105 | &au_sbi(file->f_path.dentry->d_sb)->si_files); | |
106 | bindex = finfo->fi_btop; | |
107 | if (bindex >= 0) | |
108 | au_set_h_fptr(file, bindex, NULL); | |
109 | ||
110 | au_finfo_fin(file); | |
111 | return 0; | |
112 | } | |
113 | ||
114 | /* ---------------------------------------------------------------------- */ | |
115 | ||
116 | static int au_do_flush_nondir(struct file *file, fl_owner_t id) | |
117 | { | |
118 | int err; | |
119 | struct file *h_file; | |
120 | ||
121 | err = 0; | |
122 | h_file = au_hf_top(file); | |
123 | if (h_file) | |
124 | err = vfsub_flush(h_file, id); | |
125 | return err; | |
126 | } | |
127 | ||
128 | static int aufs_flush_nondir(struct file *file, fl_owner_t id) | |
129 | { | |
130 | return au_do_flush(file, id, au_do_flush_nondir); | |
131 | } | |
132 | ||
133 | /* ---------------------------------------------------------------------- */ | |
134 | /* | |
135 | * read and write functions acquire [fdi]_rwsem once, but release before | |
136 | * mmap_sem. This is because to stop a race condition between mmap(2). | |
137 | * Releasing these aufs-rwsem should be safe, no branch-mamagement (by keeping | |
138 | * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in | |
139 | * read functions after [fdi]_rwsem are released, but it should be harmless. | |
140 | */ | |
141 | ||
142 | /* Callers should call au_read_post() or fput() in the end */ | |
143 | struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc) | |
144 | { | |
145 | struct file *h_file; | |
146 | int err; | |
147 | ||
148 | err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc); | |
149 | if (!err) { | |
150 | di_read_unlock(file->f_path.dentry, AuLock_IR); | |
151 | h_file = au_hf_top(file); | |
152 | get_file(h_file); | |
153 | if (!keep_fi) | |
154 | fi_read_unlock(file); | |
155 | } else | |
156 | h_file = ERR_PTR(err); | |
157 | ||
158 | return h_file; | |
159 | } | |
160 | ||
161 | static void au_read_post(struct inode *inode, struct file *h_file) | |
162 | { | |
163 | /* update without lock, I don't think it a problem */ | |
164 | fsstack_copy_attr_atime(inode, file_inode(h_file)); | |
165 | fput(h_file); | |
166 | } | |
167 | ||
168 | struct au_write_pre { | |
169 | /* input */ | |
170 | unsigned int lsc; | |
171 | ||
172 | /* output */ | |
173 | blkcnt_t blks; | |
174 | aufs_bindex_t btop; | |
175 | }; | |
176 | ||
177 | /* | |
178 | * return with iinfo is write-locked | |
179 | * callers should call au_write_post() or iinfo_write_unlock() + fput() in the | |
180 | * end | |
181 | */ | |
182 | static struct file *au_write_pre(struct file *file, int do_ready, | |
183 | struct au_write_pre *wpre) | |
184 | { | |
185 | struct file *h_file; | |
186 | struct dentry *dentry; | |
187 | int err; | |
188 | unsigned int lsc; | |
189 | struct au_pin pin; | |
190 | ||
191 | lsc = 0; | |
192 | if (wpre) | |
193 | lsc = wpre->lsc; | |
194 | err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc); | |
195 | h_file = ERR_PTR(err); | |
196 | if (unlikely(err)) | |
197 | goto out; | |
198 | ||
199 | dentry = file->f_path.dentry; | |
200 | if (do_ready) { | |
201 | err = au_ready_to_write(file, -1, &pin); | |
202 | if (unlikely(err)) { | |
203 | h_file = ERR_PTR(err); | |
204 | di_write_unlock(dentry); | |
205 | goto out_fi; | |
206 | } | |
207 | } | |
208 | ||
209 | di_downgrade_lock(dentry, /*flags*/0); | |
210 | if (wpre) | |
211 | wpre->btop = au_fbtop(file); | |
212 | h_file = au_hf_top(file); | |
213 | get_file(h_file); | |
214 | if (wpre) | |
215 | wpre->blks = file_inode(h_file)->i_blocks; | |
216 | if (do_ready) | |
217 | au_unpin(&pin); | |
218 | di_read_unlock(dentry, /*flags*/0); | |
219 | ||
220 | out_fi: | |
221 | fi_write_unlock(file); | |
222 | out: | |
223 | return h_file; | |
224 | } | |
225 | ||
226 | static void au_write_post(struct inode *inode, struct file *h_file, | |
227 | struct au_write_pre *wpre, ssize_t written) | |
228 | { | |
229 | struct inode *h_inode; | |
230 | ||
231 | au_cpup_attr_timesizes(inode); | |
232 | AuDebugOn(au_ibtop(inode) != wpre->btop); | |
233 | h_inode = file_inode(h_file); | |
234 | inode->i_mode = h_inode->i_mode; | |
235 | ii_write_unlock(inode); | |
236 | /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */ | |
237 | if (written > 0) | |
238 | au_fhsm_wrote(inode->i_sb, wpre->btop, | |
239 | /*force*/h_inode->i_blocks > wpre->blks); | |
240 | fput(h_file); | |
241 | } | |
242 | ||
243 | static ssize_t aufs_read(struct file *file, char __user *buf, size_t count, | |
244 | loff_t *ppos) | |
245 | { | |
246 | ssize_t err; | |
247 | struct inode *inode; | |
248 | struct file *h_file; | |
249 | struct super_block *sb; | |
250 | ||
251 | inode = file_inode(file); | |
252 | sb = inode->i_sb; | |
253 | si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); | |
254 | ||
255 | h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); | |
256 | err = PTR_ERR(h_file); | |
257 | if (IS_ERR(h_file)) | |
258 | goto out; | |
259 | ||
260 | /* filedata may be obsoleted by concurrent copyup, but no problem */ | |
261 | err = vfsub_read_u(h_file, buf, count, ppos); | |
262 | /* todo: necessary? */ | |
263 | /* file->f_ra = h_file->f_ra; */ | |
264 | au_read_post(inode, h_file); | |
265 | ||
266 | out: | |
267 | si_read_unlock(sb); | |
268 | return err; | |
269 | } | |
270 | ||
271 | /* | |
272 | * todo: very ugly | |
273 | * it locks both of i_mutex and si_rwsem for read in safe. | |
274 | * if the plink maintenance mode continues forever (that is the problem), | |
275 | * may loop forever. | |
276 | */ | |
277 | static void au_mtx_and_read_lock(struct inode *inode) | |
278 | { | |
279 | int err; | |
280 | struct super_block *sb = inode->i_sb; | |
281 | ||
282 | while (1) { | |
283 | inode_lock(inode); | |
284 | err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); | |
285 | if (!err) | |
286 | break; | |
287 | inode_unlock(inode); | |
288 | si_read_lock(sb, AuLock_NOPLMW); | |
289 | si_read_unlock(sb); | |
290 | } | |
291 | } | |
292 | ||
293 | static ssize_t aufs_write(struct file *file, const char __user *ubuf, | |
294 | size_t count, loff_t *ppos) | |
295 | { | |
296 | ssize_t err; | |
297 | struct au_write_pre wpre; | |
298 | struct inode *inode; | |
299 | struct file *h_file; | |
300 | char __user *buf = (char __user *)ubuf; | |
301 | ||
302 | inode = file_inode(file); | |
303 | au_mtx_and_read_lock(inode); | |
304 | ||
305 | wpre.lsc = 0; | |
306 | h_file = au_write_pre(file, /*do_ready*/1, &wpre); | |
307 | err = PTR_ERR(h_file); | |
308 | if (IS_ERR(h_file)) | |
309 | goto out; | |
310 | ||
311 | err = vfsub_write_u(h_file, buf, count, ppos); | |
312 | au_write_post(inode, h_file, &wpre, err); | |
313 | ||
314 | out: | |
315 | si_read_unlock(inode->i_sb); | |
316 | inode_unlock(inode); | |
317 | return err; | |
318 | } | |
319 | ||
320 | static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio, | |
321 | struct iov_iter *iov_iter) | |
322 | { | |
323 | ssize_t err; | |
324 | struct file *file; | |
325 | ssize_t (*iter)(struct kiocb *, struct iov_iter *); | |
326 | ||
327 | err = security_file_permission(h_file, rw); | |
328 | if (unlikely(err)) | |
329 | goto out; | |
330 | ||
331 | err = -ENOSYS; | |
332 | iter = NULL; | |
333 | if (rw == MAY_READ) | |
334 | iter = h_file->f_op->read_iter; | |
335 | else if (rw == MAY_WRITE) | |
336 | iter = h_file->f_op->write_iter; | |
337 | ||
338 | file = kio->ki_filp; | |
339 | kio->ki_filp = h_file; | |
340 | if (iter) { | |
341 | lockdep_off(); | |
342 | err = iter(kio, iov_iter); | |
343 | lockdep_on(); | |
344 | } else | |
345 | /* currently there is no such fs */ | |
346 | WARN_ON_ONCE(1); | |
347 | kio->ki_filp = file; | |
348 | ||
349 | out: | |
350 | return err; | |
351 | } | |
352 | ||
353 | static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) | |
354 | { | |
355 | ssize_t err; | |
356 | struct file *file, *h_file; | |
357 | struct inode *inode; | |
358 | struct super_block *sb; | |
359 | ||
360 | file = kio->ki_filp; | |
361 | inode = file_inode(file); | |
362 | sb = inode->i_sb; | |
363 | si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); | |
364 | ||
365 | h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0); | |
366 | err = PTR_ERR(h_file); | |
367 | if (IS_ERR(h_file)) | |
368 | goto out; | |
369 | ||
370 | if (0 && au_test_loopback_kthread()) { | |
371 | au_warn_loopback(h_file->f_path.dentry->d_sb); | |
372 | if (file->f_mapping != h_file->f_mapping) { | |
373 | file->f_mapping = h_file->f_mapping; | |
374 | smp_mb(); /* unnecessary? */ | |
375 | } | |
376 | } | |
377 | fi_read_unlock(file); | |
378 | ||
379 | err = au_do_iter(h_file, MAY_READ, kio, iov_iter); | |
380 | /* todo: necessary? */ | |
381 | /* file->f_ra = h_file->f_ra; */ | |
382 | au_read_post(inode, h_file); | |
383 | ||
384 | out: | |
385 | si_read_unlock(sb); | |
386 | return err; | |
387 | } | |
388 | ||
389 | static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter) | |
390 | { | |
391 | ssize_t err; | |
392 | struct au_write_pre wpre; | |
393 | struct inode *inode; | |
394 | struct file *file, *h_file; | |
395 | ||
396 | file = kio->ki_filp; | |
397 | inode = file_inode(file); | |
398 | au_mtx_and_read_lock(inode); | |
399 | ||
400 | wpre.lsc = 0; | |
401 | h_file = au_write_pre(file, /*do_ready*/1, &wpre); | |
402 | err = PTR_ERR(h_file); | |
403 | if (IS_ERR(h_file)) | |
404 | goto out; | |
405 | ||
406 | err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter); | |
407 | au_write_post(inode, h_file, &wpre, err); | |
408 | ||
409 | out: | |
410 | si_read_unlock(inode->i_sb); | |
411 | inode_unlock(inode); | |
412 | return err; | |
413 | } | |
414 | ||
415 | static ssize_t aufs_splice_read(struct file *file, loff_t *ppos, | |
416 | struct pipe_inode_info *pipe, size_t len, | |
417 | unsigned int flags) | |
418 | { | |
419 | ssize_t err; | |
420 | struct file *h_file; | |
421 | struct inode *inode; | |
422 | struct super_block *sb; | |
423 | ||
424 | inode = file_inode(file); | |
425 | sb = inode->i_sb; | |
426 | si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); | |
427 | ||
428 | h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); | |
429 | err = PTR_ERR(h_file); | |
430 | if (IS_ERR(h_file)) | |
431 | goto out; | |
432 | ||
433 | err = vfsub_splice_to(h_file, ppos, pipe, len, flags); | |
434 | /* todo: necessasry? */ | |
435 | /* file->f_ra = h_file->f_ra; */ | |
436 | au_read_post(inode, h_file); | |
437 | ||
438 | out: | |
439 | si_read_unlock(sb); | |
440 | return err; | |
441 | } | |
442 | ||
443 | static ssize_t | |
444 | aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos, | |
445 | size_t len, unsigned int flags) | |
446 | { | |
447 | ssize_t err; | |
448 | struct au_write_pre wpre; | |
449 | struct inode *inode; | |
450 | struct file *h_file; | |
451 | ||
452 | inode = file_inode(file); | |
453 | au_mtx_and_read_lock(inode); | |
454 | ||
455 | wpre.lsc = 0; | |
456 | h_file = au_write_pre(file, /*do_ready*/1, &wpre); | |
457 | err = PTR_ERR(h_file); | |
458 | if (IS_ERR(h_file)) | |
459 | goto out; | |
460 | ||
461 | err = vfsub_splice_from(pipe, h_file, ppos, len, flags); | |
462 | au_write_post(inode, h_file, &wpre, err); | |
463 | ||
464 | out: | |
465 | si_read_unlock(inode->i_sb); | |
466 | inode_unlock(inode); | |
467 | return err; | |
468 | } | |
469 | ||
470 | static long aufs_fallocate(struct file *file, int mode, loff_t offset, | |
471 | loff_t len) | |
472 | { | |
473 | long err; | |
474 | struct au_write_pre wpre; | |
475 | struct inode *inode; | |
476 | struct file *h_file; | |
477 | ||
478 | inode = file_inode(file); | |
479 | au_mtx_and_read_lock(inode); | |
480 | ||
481 | wpre.lsc = 0; | |
482 | h_file = au_write_pre(file, /*do_ready*/1, &wpre); | |
483 | err = PTR_ERR(h_file); | |
484 | if (IS_ERR(h_file)) | |
485 | goto out; | |
486 | ||
487 | lockdep_off(); | |
488 | err = vfs_fallocate(h_file, mode, offset, len); | |
489 | lockdep_on(); | |
490 | au_write_post(inode, h_file, &wpre, /*written*/1); | |
491 | ||
492 | out: | |
493 | si_read_unlock(inode->i_sb); | |
494 | inode_unlock(inode); | |
495 | return err; | |
496 | } | |
497 | ||
498 | static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos, | |
499 | struct file *dst, loff_t dst_pos, | |
500 | size_t len, unsigned int flags) | |
501 | { | |
502 | ssize_t err; | |
503 | struct au_write_pre wpre; | |
504 | enum { SRC, DST }; | |
505 | struct { | |
506 | struct inode *inode; | |
507 | struct file *h_file; | |
508 | struct super_block *h_sb; | |
509 | } a[2]; | |
510 | #define a_src a[SRC] | |
511 | #define a_dst a[DST] | |
512 | ||
513 | err = -EINVAL; | |
514 | a_src.inode = file_inode(src); | |
515 | if (unlikely(!S_ISREG(a_src.inode->i_mode))) | |
516 | goto out; | |
517 | a_dst.inode = file_inode(dst); | |
518 | if (unlikely(!S_ISREG(a_dst.inode->i_mode))) | |
519 | goto out; | |
520 | ||
521 | au_mtx_and_read_lock(a_dst.inode); | |
522 | /* | |
523 | * in order to match the order in di_write_lock2_{child,parent}(), | |
524 | * use f_path.dentry for this comparision. | |
525 | */ | |
526 | if (src->f_path.dentry < dst->f_path.dentry) { | |
527 | a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1); | |
528 | err = PTR_ERR(a_src.h_file); | |
529 | if (IS_ERR(a_src.h_file)) | |
530 | goto out_si; | |
531 | ||
532 | wpre.lsc = AuLsc_FI_2; | |
533 | a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); | |
534 | err = PTR_ERR(a_dst.h_file); | |
535 | if (IS_ERR(a_dst.h_file)) { | |
536 | au_read_post(a_src.inode, a_src.h_file); | |
537 | goto out_si; | |
538 | } | |
539 | } else { | |
540 | wpre.lsc = AuLsc_FI_1; | |
541 | a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); | |
542 | err = PTR_ERR(a_dst.h_file); | |
543 | if (IS_ERR(a_dst.h_file)) | |
544 | goto out_si; | |
545 | ||
546 | a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2); | |
547 | err = PTR_ERR(a_src.h_file); | |
548 | if (IS_ERR(a_src.h_file)) { | |
549 | au_write_post(a_dst.inode, a_dst.h_file, &wpre, | |
550 | /*written*/0); | |
551 | goto out_si; | |
552 | } | |
553 | } | |
554 | ||
555 | err = -EXDEV; | |
556 | a_src.h_sb = file_inode(a_src.h_file)->i_sb; | |
557 | a_dst.h_sb = file_inode(a_dst.h_file)->i_sb; | |
558 | if (unlikely(a_src.h_sb != a_dst.h_sb)) { | |
559 | AuDbgFile(src); | |
560 | AuDbgFile(dst); | |
561 | goto out_file; | |
562 | } | |
563 | ||
564 | err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file, | |
565 | dst_pos, len, flags); | |
566 | ||
567 | out_file: | |
568 | au_write_post(a_dst.inode, a_dst.h_file, &wpre, err); | |
569 | fi_read_unlock(src); | |
570 | au_read_post(a_src.inode, a_src.h_file); | |
571 | out_si: | |
572 | si_read_unlock(a_dst.inode->i_sb); | |
573 | inode_unlock(a_dst.inode); | |
574 | out: | |
575 | return err; | |
576 | #undef a_src | |
577 | #undef a_dst | |
578 | } | |
579 | ||
580 | /* ---------------------------------------------------------------------- */ | |
581 | ||
582 | /* | |
583 | * The locking order around current->mmap_sem. | |
584 | * - in most and regular cases | |
585 | * file I/O syscall -- aufs_read() or something | |
586 | * -- si_rwsem for read -- mmap_sem | |
587 | * (Note that [fdi]i_rwsem are released before mmap_sem). | |
588 | * - in mmap case | |
589 | * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem | |
590 | * This AB-BA order is definitly bad, but is not a problem since "si_rwsem for | |
591 | * read" allows muliple processes to acquire it and [fdi]i_rwsem are not held in | |
592 | * file I/O. Aufs needs to stop lockdep in aufs_mmap() though. | |
593 | * It means that when aufs acquires si_rwsem for write, the process should never | |
594 | * acquire mmap_sem. | |
595 | * | |
596 | * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a | |
597 | * problem either since any directory is not able to be mmap-ed. | |
598 | * The similar scenario is applied to aufs_readlink() too. | |
599 | */ | |
600 | ||
601 | #if 0 /* stop calling security_file_mmap() */ | |
602 | /* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */ | |
603 | #define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b) | |
604 | ||
605 | static unsigned long au_arch_prot_conv(unsigned long flags) | |
606 | { | |
607 | /* currently ppc64 only */ | |
608 | #ifdef CONFIG_PPC64 | |
609 | /* cf. linux/arch/powerpc/include/asm/mman.h */ | |
610 | AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO); | |
611 | return AuConv_VM_PROT(flags, SAO); | |
612 | #else | |
613 | AuDebugOn(arch_calc_vm_prot_bits(-1)); | |
614 | return 0; | |
615 | #endif | |
616 | } | |
617 | ||
618 | static unsigned long au_prot_conv(unsigned long flags) | |
619 | { | |
620 | return AuConv_VM_PROT(flags, READ) | |
621 | | AuConv_VM_PROT(flags, WRITE) | |
622 | | AuConv_VM_PROT(flags, EXEC) | |
623 | | au_arch_prot_conv(flags); | |
624 | } | |
625 | ||
626 | /* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */ | |
627 | #define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b) | |
628 | ||
629 | static unsigned long au_flag_conv(unsigned long flags) | |
630 | { | |
631 | return AuConv_VM_MAP(flags, GROWSDOWN) | |
632 | | AuConv_VM_MAP(flags, DENYWRITE) | |
633 | | AuConv_VM_MAP(flags, LOCKED); | |
634 | } | |
635 | #endif | |
636 | ||
637 | static int aufs_mmap(struct file *file, struct vm_area_struct *vma) | |
638 | { | |
639 | int err; | |
640 | const unsigned char wlock | |
641 | = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED); | |
642 | struct super_block *sb; | |
643 | struct file *h_file; | |
644 | struct inode *inode; | |
645 | ||
646 | AuDbgVmRegion(file, vma); | |
647 | ||
648 | inode = file_inode(file); | |
649 | sb = inode->i_sb; | |
650 | lockdep_off(); | |
651 | si_read_lock(sb, AuLock_NOPLMW); | |
652 | ||
653 | h_file = au_write_pre(file, wlock, /*wpre*/NULL); | |
654 | lockdep_on(); | |
655 | err = PTR_ERR(h_file); | |
656 | if (IS_ERR(h_file)) | |
657 | goto out; | |
658 | ||
659 | err = 0; | |
660 | au_set_mmapped(file); | |
661 | au_vm_file_reset(vma, h_file); | |
662 | /* | |
663 | * we cannot call security_mmap_file() here since it may acquire | |
664 | * mmap_sem or i_mutex. | |
665 | * | |
666 | * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags), | |
667 | * au_flag_conv(vma->vm_flags)); | |
668 | */ | |
669 | if (!err) | |
670 | err = call_mmap(h_file, vma); | |
671 | if (!err) { | |
672 | au_vm_prfile_set(vma, file); | |
673 | fsstack_copy_attr_atime(inode, file_inode(h_file)); | |
674 | goto out_fput; /* success */ | |
675 | } | |
676 | au_unset_mmapped(file); | |
677 | au_vm_file_reset(vma, file); | |
678 | ||
679 | out_fput: | |
680 | lockdep_off(); | |
681 | ii_write_unlock(inode); | |
682 | lockdep_on(); | |
683 | fput(h_file); | |
684 | out: | |
685 | lockdep_off(); | |
686 | si_read_unlock(sb); | |
687 | lockdep_on(); | |
688 | AuTraceErr(err); | |
689 | return err; | |
690 | } | |
691 | ||
692 | /* ---------------------------------------------------------------------- */ | |
693 | ||
694 | static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end, | |
695 | int datasync) | |
696 | { | |
697 | int err; | |
698 | struct au_write_pre wpre; | |
699 | struct inode *inode; | |
700 | struct file *h_file; | |
701 | ||
702 | err = 0; /* -EBADF; */ /* posix? */ | |
703 | if (unlikely(!(file->f_mode & FMODE_WRITE))) | |
704 | goto out; | |
705 | ||
706 | inode = file_inode(file); | |
707 | au_mtx_and_read_lock(inode); | |
708 | ||
709 | wpre.lsc = 0; | |
710 | h_file = au_write_pre(file, /*do_ready*/1, &wpre); | |
711 | err = PTR_ERR(h_file); | |
712 | if (IS_ERR(h_file)) | |
713 | goto out_unlock; | |
714 | ||
715 | err = vfsub_fsync(h_file, &h_file->f_path, datasync); | |
716 | au_write_post(inode, h_file, &wpre, /*written*/0); | |
717 | ||
718 | out_unlock: | |
719 | si_read_unlock(inode->i_sb); | |
720 | inode_unlock(inode); | |
721 | out: | |
722 | return err; | |
723 | } | |
724 | ||
725 | static int aufs_fasync(int fd, struct file *file, int flag) | |
726 | { | |
727 | int err; | |
728 | struct file *h_file; | |
729 | struct super_block *sb; | |
730 | ||
731 | sb = file->f_path.dentry->d_sb; | |
732 | si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); | |
733 | ||
734 | h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); | |
735 | err = PTR_ERR(h_file); | |
736 | if (IS_ERR(h_file)) | |
737 | goto out; | |
738 | ||
739 | if (h_file->f_op->fasync) | |
740 | err = h_file->f_op->fasync(fd, h_file, flag); | |
741 | fput(h_file); /* instead of au_read_post() */ | |
742 | ||
743 | out: | |
744 | si_read_unlock(sb); | |
745 | return err; | |
746 | } | |
747 | ||
748 | static int aufs_setfl(struct file *file, unsigned long arg) | |
749 | { | |
750 | int err; | |
751 | struct file *h_file; | |
752 | struct super_block *sb; | |
753 | ||
754 | sb = file->f_path.dentry->d_sb; | |
755 | si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); | |
756 | ||
757 | h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); | |
758 | err = PTR_ERR(h_file); | |
759 | if (IS_ERR(h_file)) | |
760 | goto out; | |
761 | ||
762 | /* stop calling h_file->fasync */ | |
763 | arg |= vfsub_file_flags(file) & FASYNC; | |
764 | err = setfl(/*unused fd*/-1, h_file, arg); | |
765 | fput(h_file); /* instead of au_read_post() */ | |
766 | ||
767 | out: | |
768 | si_read_unlock(sb); | |
769 | return err; | |
770 | } | |
771 | ||
772 | /* ---------------------------------------------------------------------- */ | |
773 | ||
774 | /* no one supports this operation, currently */ | |
775 | #if 0 | |
776 | static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset, | |
777 | size_t len, loff_t *pos, int more) | |
778 | { | |
779 | } | |
780 | #endif | |
781 | ||
782 | /* ---------------------------------------------------------------------- */ | |
783 | ||
784 | const struct file_operations aufs_file_fop = { | |
785 | .owner = THIS_MODULE, | |
786 | ||
787 | .llseek = default_llseek, | |
788 | ||
789 | .read = aufs_read, | |
790 | .write = aufs_write, | |
791 | .read_iter = aufs_read_iter, | |
792 | .write_iter = aufs_write_iter, | |
793 | ||
794 | #ifdef CONFIG_AUFS_POLL | |
795 | .poll = aufs_poll, | |
796 | #endif | |
797 | .unlocked_ioctl = aufs_ioctl_nondir, | |
798 | #ifdef CONFIG_COMPAT | |
799 | .compat_ioctl = aufs_compat_ioctl_nondir, | |
800 | #endif | |
801 | .mmap = aufs_mmap, | |
802 | .open = aufs_open_nondir, | |
803 | .flush = aufs_flush_nondir, | |
804 | .release = aufs_release_nondir, | |
805 | .fsync = aufs_fsync_nondir, | |
806 | .fasync = aufs_fasync, | |
807 | /* .sendpage = aufs_sendpage, */ | |
808 | .setfl = aufs_setfl, | |
809 | .splice_write = aufs_splice_write, | |
810 | .splice_read = aufs_splice_read, | |
811 | #if 0 | |
812 | .aio_splice_write = aufs_aio_splice_write, | |
813 | .aio_splice_read = aufs_aio_splice_read, | |
814 | #endif | |
815 | .fallocate = aufs_fallocate, | |
816 | .copy_file_range = aufs_copy_file_range | |
817 | }; |