]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/aufs/mvdown.c
UBUNTU: SAUCE: Import aufs driver
[mirror_ubuntu-bionic-kernel.git] / fs / aufs / mvdown.c
1 /*
2 * Copyright (C) 2011-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 * move-down, opposite of copy-up
20 */
21
22 #include "aufs.h"
23
24 struct au_mvd_args {
25 struct {
26 struct super_block *h_sb;
27 struct dentry *h_parent;
28 struct au_hinode *hdir;
29 struct inode *h_dir, *h_inode;
30 struct au_pin pin;
31 } info[AUFS_MVDOWN_NARRAY];
32
33 struct aufs_mvdown mvdown;
34 struct dentry *dentry, *parent;
35 struct inode *inode, *dir;
36 struct super_block *sb;
37 aufs_bindex_t bopq, bwh, bfound;
38 unsigned char rename_lock;
39 };
40
41 #define mvd_errno mvdown.au_errno
42 #define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex
43 #define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid
44 #define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex
45 #define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid
46
47 #define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb
48 #define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent
49 #define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir
50 #define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir
51 #define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode
52 #define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin
53
54 #define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb
55 #define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent
56 #define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir
57 #define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir
58 #define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode
59 #define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin
60
61 #define AU_MVD_PR(flag, ...) do { \
62 if (flag) \
63 pr_err(__VA_ARGS__); \
64 } while (0)
65
66 static int find_lower_writable(struct au_mvd_args *a)
67 {
68 struct super_block *sb;
69 aufs_bindex_t bindex, bbot;
70 struct au_branch *br;
71
72 sb = a->sb;
73 bindex = a->mvd_bsrc;
74 bbot = au_sbbot(sb);
75 if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER)
76 for (bindex++; bindex <= bbot; bindex++) {
77 br = au_sbr(sb, bindex);
78 if (au_br_fhsm(br->br_perm)
79 && !sb_rdonly(au_br_sb(br)))
80 return bindex;
81 }
82 else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER))
83 for (bindex++; bindex <= bbot; bindex++) {
84 br = au_sbr(sb, bindex);
85 if (!au_br_rdonly(br))
86 return bindex;
87 }
88 else
89 for (bindex++; bindex <= bbot; bindex++) {
90 br = au_sbr(sb, bindex);
91 if (!sb_rdonly(au_br_sb(br))) {
92 if (au_br_rdonly(br))
93 a->mvdown.flags
94 |= AUFS_MVDOWN_ROLOWER_R;
95 return bindex;
96 }
97 }
98
99 return -1;
100 }
101
102 /* make the parent dir on bdst */
103 static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a)
104 {
105 int err;
106
107 err = 0;
108 a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc);
109 a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst);
110 a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc);
111 a->mvd_h_dst_parent = NULL;
112 if (au_dbbot(a->parent) >= a->mvd_bdst)
113 a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
114 if (!a->mvd_h_dst_parent) {
115 err = au_cpdown_dirs(a->dentry, a->mvd_bdst);
116 if (unlikely(err)) {
117 AU_MVD_PR(dmsg, "cpdown_dirs failed\n");
118 goto out;
119 }
120 a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
121 }
122
123 out:
124 AuTraceErr(err);
125 return err;
126 }
127
128 /* lock them all */
129 static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a)
130 {
131 int err;
132 struct dentry *h_trap;
133
134 a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
135 a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
136 err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst,
137 au_opt_udba(a->sb),
138 AuPin_MNT_WRITE | AuPin_DI_LOCKED);
139 AuTraceErr(err);
140 if (unlikely(err)) {
141 AU_MVD_PR(dmsg, "pin_dst failed\n");
142 goto out;
143 }
144
145 if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
146 a->rename_lock = 0;
147 au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
148 AuLsc_DI_PARENT, AuLsc_I_PARENT3,
149 au_opt_udba(a->sb),
150 AuPin_MNT_WRITE | AuPin_DI_LOCKED);
151 err = au_do_pin(&a->mvd_pin_src);
152 AuTraceErr(err);
153 a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
154 if (unlikely(err)) {
155 AU_MVD_PR(dmsg, "pin_src failed\n");
156 goto out_dst;
157 }
158 goto out; /* success */
159 }
160
161 a->rename_lock = 1;
162 au_pin_hdir_unlock(&a->mvd_pin_dst);
163 err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
164 au_opt_udba(a->sb),
165 AuPin_MNT_WRITE | AuPin_DI_LOCKED);
166 AuTraceErr(err);
167 a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
168 if (unlikely(err)) {
169 AU_MVD_PR(dmsg, "pin_src failed\n");
170 au_pin_hdir_lock(&a->mvd_pin_dst);
171 goto out_dst;
172 }
173 au_pin_hdir_unlock(&a->mvd_pin_src);
174 h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
175 a->mvd_h_dst_parent, a->mvd_hdir_dst);
176 if (h_trap) {
177 err = (h_trap != a->mvd_h_src_parent);
178 if (err)
179 err = (h_trap != a->mvd_h_dst_parent);
180 }
181 BUG_ON(err); /* it should never happen */
182 if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) {
183 err = -EBUSY;
184 AuTraceErr(err);
185 vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
186 a->mvd_h_dst_parent, a->mvd_hdir_dst);
187 au_pin_hdir_lock(&a->mvd_pin_src);
188 au_unpin(&a->mvd_pin_src);
189 au_pin_hdir_lock(&a->mvd_pin_dst);
190 goto out_dst;
191 }
192 goto out; /* success */
193
194 out_dst:
195 au_unpin(&a->mvd_pin_dst);
196 out:
197 AuTraceErr(err);
198 return err;
199 }
200
201 static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a)
202 {
203 if (!a->rename_lock)
204 au_unpin(&a->mvd_pin_src);
205 else {
206 vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
207 a->mvd_h_dst_parent, a->mvd_hdir_dst);
208 au_pin_hdir_lock(&a->mvd_pin_src);
209 au_unpin(&a->mvd_pin_src);
210 au_pin_hdir_lock(&a->mvd_pin_dst);
211 }
212 au_unpin(&a->mvd_pin_dst);
213 }
214
215 /* copy-down the file */
216 static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a)
217 {
218 int err;
219 struct au_cp_generic cpg = {
220 .dentry = a->dentry,
221 .bdst = a->mvd_bdst,
222 .bsrc = a->mvd_bsrc,
223 .len = -1,
224 .pin = &a->mvd_pin_dst,
225 .flags = AuCpup_DTIME | AuCpup_HOPEN
226 };
227
228 AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst);
229 if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
230 au_fset_cpup(cpg.flags, OVERWRITE);
231 if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER)
232 au_fset_cpup(cpg.flags, RWDST);
233 err = au_sio_cpdown_simple(&cpg);
234 if (unlikely(err))
235 AU_MVD_PR(dmsg, "cpdown failed\n");
236
237 AuTraceErr(err);
238 return err;
239 }
240
241 /*
242 * unlink the whiteout on bdst if exist which may be created by UDBA while we
243 * were sleeping
244 */
245 static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a)
246 {
247 int err;
248 struct path h_path;
249 struct au_branch *br;
250 struct inode *delegated;
251
252 br = au_sbr(a->sb, a->mvd_bdst);
253 h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br);
254 err = PTR_ERR(h_path.dentry);
255 if (IS_ERR(h_path.dentry)) {
256 AU_MVD_PR(dmsg, "wh_lkup failed\n");
257 goto out;
258 }
259
260 err = 0;
261 if (d_is_positive(h_path.dentry)) {
262 h_path.mnt = au_br_mnt(br);
263 delegated = NULL;
264 err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path,
265 &delegated, /*force*/0);
266 if (unlikely(err == -EWOULDBLOCK)) {
267 pr_warn("cannot retry for NFSv4 delegation"
268 " for an internal unlink\n");
269 iput(delegated);
270 }
271 if (unlikely(err))
272 AU_MVD_PR(dmsg, "wh_unlink failed\n");
273 }
274 dput(h_path.dentry);
275
276 out:
277 AuTraceErr(err);
278 return err;
279 }
280
281 /*
282 * unlink the topmost h_dentry
283 */
284 static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a)
285 {
286 int err;
287 struct path h_path;
288 struct inode *delegated;
289
290 h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc);
291 h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc);
292 delegated = NULL;
293 err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0);
294 if (unlikely(err == -EWOULDBLOCK)) {
295 pr_warn("cannot retry for NFSv4 delegation"
296 " for an internal unlink\n");
297 iput(delegated);
298 }
299 if (unlikely(err))
300 AU_MVD_PR(dmsg, "unlink failed\n");
301
302 AuTraceErr(err);
303 return err;
304 }
305
306 /* Since mvdown succeeded, we ignore an error of this function */
307 static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a)
308 {
309 int err;
310 struct au_branch *br;
311
312 a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED;
313 br = au_sbr(a->sb, a->mvd_bsrc);
314 err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs);
315 if (!err) {
316 br = au_sbr(a->sb, a->mvd_bdst);
317 a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id;
318 err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs);
319 }
320 if (!err)
321 a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED;
322 else
323 AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err);
324 }
325
326 /*
327 * copy-down the file and unlink the bsrc file.
328 * - unlink the bdst whout if exist
329 * - copy-down the file (with whtmp name and rename)
330 * - unlink the bsrc file
331 */
332 static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a)
333 {
334 int err;
335
336 err = au_do_mkdir(dmsg, a);
337 if (!err)
338 err = au_do_lock(dmsg, a);
339 if (unlikely(err))
340 goto out;
341
342 /*
343 * do not revert the activities we made on bdst since they should be
344 * harmless in aufs.
345 */
346
347 err = au_do_cpdown(dmsg, a);
348 if (!err)
349 err = au_do_unlink_wh(dmsg, a);
350 if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER))
351 err = au_do_unlink(dmsg, a);
352 if (unlikely(err))
353 goto out_unlock;
354
355 AuDbg("%pd2, 0x%x, %d --> %d\n",
356 a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst);
357 if (find_lower_writable(a) < 0)
358 a->mvdown.flags |= AUFS_MVDOWN_BOTTOM;
359
360 if (a->mvdown.flags & AUFS_MVDOWN_STFS)
361 au_do_stfs(dmsg, a);
362
363 /* maintain internal array */
364 if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) {
365 au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL);
366 au_set_dbtop(a->dentry, a->mvd_bdst);
367 au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
368 au_set_ibtop(a->inode, a->mvd_bdst);
369 } else {
370 /* hide the lower */
371 au_set_h_dptr(a->dentry, a->mvd_bdst, NULL);
372 au_set_dbbot(a->dentry, a->mvd_bsrc);
373 au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0);
374 au_set_ibbot(a->inode, a->mvd_bsrc);
375 }
376 if (au_dbbot(a->dentry) < a->mvd_bdst)
377 au_set_dbbot(a->dentry, a->mvd_bdst);
378 if (au_ibbot(a->inode) < a->mvd_bdst)
379 au_set_ibbot(a->inode, a->mvd_bdst);
380
381 out_unlock:
382 au_do_unlock(dmsg, a);
383 out:
384 AuTraceErr(err);
385 return err;
386 }
387
388 /* ---------------------------------------------------------------------- */
389
390 /* make sure the file is idle */
391 static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a)
392 {
393 int err, plinked;
394
395 err = 0;
396 plinked = !!au_opt_test(au_mntflags(a->sb), PLINK);
397 if (au_dbtop(a->dentry) == a->mvd_bsrc
398 && au_dcount(a->dentry) == 1
399 && atomic_read(&a->inode->i_count) == 1
400 /* && a->mvd_h_src_inode->i_nlink == 1 */
401 && (!plinked || !au_plink_test(a->inode))
402 && a->inode->i_nlink == 1)
403 goto out;
404
405 err = -EBUSY;
406 AU_MVD_PR(dmsg,
407 "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n",
408 a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry),
409 atomic_read(&a->inode->i_count), a->inode->i_nlink,
410 a->mvd_h_src_inode->i_nlink,
411 plinked, plinked ? au_plink_test(a->inode) : 0);
412
413 out:
414 AuTraceErr(err);
415 return err;
416 }
417
418 /* make sure the parent dir is fine */
419 static int au_mvd_args_parent(const unsigned char dmsg,
420 struct au_mvd_args *a)
421 {
422 int err;
423 aufs_bindex_t bindex;
424
425 err = 0;
426 if (unlikely(au_alive_dir(a->parent))) {
427 err = -ENOENT;
428 AU_MVD_PR(dmsg, "parent dir is dead\n");
429 goto out;
430 }
431
432 a->bopq = au_dbdiropq(a->parent);
433 bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst);
434 AuDbg("b%d\n", bindex);
435 if (unlikely((bindex >= 0 && bindex < a->mvd_bdst)
436 || (a->bopq != -1 && a->bopq < a->mvd_bdst))) {
437 err = -EINVAL;
438 a->mvd_errno = EAU_MVDOWN_OPAQUE;
439 AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n",
440 a->bopq, a->mvd_bdst);
441 }
442
443 out:
444 AuTraceErr(err);
445 return err;
446 }
447
448 static int au_mvd_args_intermediate(const unsigned char dmsg,
449 struct au_mvd_args *a)
450 {
451 int err;
452 struct au_dinfo *dinfo, *tmp;
453
454 /* lookup the next lower positive entry */
455 err = -ENOMEM;
456 tmp = au_di_alloc(a->sb, AuLsc_DI_TMP);
457 if (unlikely(!tmp))
458 goto out;
459
460 a->bfound = -1;
461 a->bwh = -1;
462 dinfo = au_di(a->dentry);
463 au_di_cp(tmp, dinfo);
464 au_di_swap(tmp, dinfo);
465
466 /* returns the number of positive dentries */
467 err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1,
468 /* AuLkup_IGNORE_PERM */ 0);
469 if (!err)
470 a->bwh = au_dbwh(a->dentry);
471 else if (err > 0)
472 a->bfound = au_dbtop(a->dentry);
473
474 au_di_swap(tmp, dinfo);
475 au_rw_write_unlock(&tmp->di_rwsem);
476 au_di_free(tmp);
477 if (unlikely(err < 0))
478 AU_MVD_PR(dmsg, "failed look-up lower\n");
479
480 /*
481 * here, we have these cases.
482 * bfound == -1
483 * no positive dentry under bsrc. there are more sub-cases.
484 * bwh < 0
485 * there no whiteout, we can safely move-down.
486 * bwh <= bsrc
487 * impossible
488 * bsrc < bwh && bwh < bdst
489 * there is a whiteout on RO branch. cannot proceed.
490 * bwh == bdst
491 * there is a whiteout on the RW target branch. it should
492 * be removed.
493 * bdst < bwh
494 * there is a whiteout somewhere unrelated branch.
495 * -1 < bfound && bfound <= bsrc
496 * impossible.
497 * bfound < bdst
498 * found, but it is on RO branch between bsrc and bdst. cannot
499 * proceed.
500 * bfound == bdst
501 * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return
502 * error.
503 * bdst < bfound
504 * found, after we create the file on bdst, it will be hidden.
505 */
506
507 AuDebugOn(a->bfound == -1
508 && a->bwh != -1
509 && a->bwh <= a->mvd_bsrc);
510 AuDebugOn(-1 < a->bfound
511 && a->bfound <= a->mvd_bsrc);
512
513 err = -EINVAL;
514 if (a->bfound == -1
515 && a->mvd_bsrc < a->bwh
516 && a->bwh != -1
517 && a->bwh < a->mvd_bdst) {
518 a->mvd_errno = EAU_MVDOWN_WHITEOUT;
519 AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n",
520 a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh);
521 goto out;
522 } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) {
523 a->mvd_errno = EAU_MVDOWN_UPPER;
524 AU_MVD_PR(dmsg, "bdst %d, bfound %d\n",
525 a->mvd_bdst, a->bfound);
526 goto out;
527 }
528
529 err = 0; /* success */
530
531 out:
532 AuTraceErr(err);
533 return err;
534 }
535
536 static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a)
537 {
538 int err;
539
540 err = 0;
541 if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
542 && a->bfound == a->mvd_bdst)
543 err = -EEXIST;
544 AuTraceErr(err);
545 return err;
546 }
547
548 static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a)
549 {
550 int err;
551 struct au_branch *br;
552
553 err = -EISDIR;
554 if (unlikely(S_ISDIR(a->inode->i_mode)))
555 goto out;
556
557 err = -EINVAL;
558 if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER))
559 a->mvd_bsrc = au_ibtop(a->inode);
560 else {
561 a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid);
562 if (unlikely(a->mvd_bsrc < 0
563 || (a->mvd_bsrc < au_dbtop(a->dentry)
564 || au_dbbot(a->dentry) < a->mvd_bsrc
565 || !au_h_dptr(a->dentry, a->mvd_bsrc))
566 || (a->mvd_bsrc < au_ibtop(a->inode)
567 || au_ibbot(a->inode) < a->mvd_bsrc
568 || !au_h_iptr(a->inode, a->mvd_bsrc)))) {
569 a->mvd_errno = EAU_MVDOWN_NOUPPER;
570 AU_MVD_PR(dmsg, "no upper\n");
571 goto out;
572 }
573 }
574 if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) {
575 a->mvd_errno = EAU_MVDOWN_BOTTOM;
576 AU_MVD_PR(dmsg, "on the bottom\n");
577 goto out;
578 }
579 a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc);
580 br = au_sbr(a->sb, a->mvd_bsrc);
581 err = au_br_rdonly(br);
582 if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) {
583 if (unlikely(err))
584 goto out;
585 } else if (!(vfsub_native_ro(a->mvd_h_src_inode)
586 || IS_APPEND(a->mvd_h_src_inode))) {
587 if (err)
588 a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R;
589 /* go on */
590 } else
591 goto out;
592
593 err = -EINVAL;
594 if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) {
595 a->mvd_bdst = find_lower_writable(a);
596 if (unlikely(a->mvd_bdst < 0)) {
597 a->mvd_errno = EAU_MVDOWN_BOTTOM;
598 AU_MVD_PR(dmsg, "no writable lower branch\n");
599 goto out;
600 }
601 } else {
602 a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid);
603 if (unlikely(a->mvd_bdst < 0
604 || au_sbbot(a->sb) < a->mvd_bdst)) {
605 a->mvd_errno = EAU_MVDOWN_NOLOWERBR;
606 AU_MVD_PR(dmsg, "no lower brid\n");
607 goto out;
608 }
609 }
610
611 err = au_mvd_args_busy(dmsg, a);
612 if (!err)
613 err = au_mvd_args_parent(dmsg, a);
614 if (!err)
615 err = au_mvd_args_intermediate(dmsg, a);
616 if (!err)
617 err = au_mvd_args_exist(dmsg, a);
618 if (!err)
619 AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst);
620
621 out:
622 AuTraceErr(err);
623 return err;
624 }
625
626 int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg)
627 {
628 int err, e;
629 unsigned char dmsg;
630 struct au_mvd_args *args;
631 struct inode *inode;
632
633 inode = d_inode(dentry);
634 err = -EPERM;
635 if (unlikely(!capable(CAP_SYS_ADMIN)))
636 goto out;
637
638 err = -ENOMEM;
639 args = kmalloc(sizeof(*args), GFP_NOFS);
640 if (unlikely(!args))
641 goto out;
642
643 err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown));
644 if (!err)
645 err = !access_ok(VERIFY_WRITE, uarg, sizeof(*uarg));
646 if (unlikely(err)) {
647 err = -EFAULT;
648 AuTraceErr(err);
649 goto out_free;
650 }
651 AuDbg("flags 0x%x\n", args->mvdown.flags);
652 args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R);
653 args->mvdown.au_errno = 0;
654 args->dentry = dentry;
655 args->inode = inode;
656 args->sb = dentry->d_sb;
657
658 err = -ENOENT;
659 dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG);
660 args->parent = dget_parent(dentry);
661 args->dir = d_inode(args->parent);
662 inode_lock_nested(args->dir, I_MUTEX_PARENT);
663 dput(args->parent);
664 if (unlikely(args->parent != dentry->d_parent)) {
665 AU_MVD_PR(dmsg, "parent dir is moved\n");
666 goto out_dir;
667 }
668
669 inode_lock_nested(inode, I_MUTEX_CHILD);
670 err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW);
671 if (unlikely(err))
672 goto out_inode;
673
674 di_write_lock_parent(args->parent);
675 err = au_mvd_args(dmsg, args);
676 if (unlikely(err))
677 goto out_parent;
678
679 err = au_do_mvdown(dmsg, args);
680 if (unlikely(err))
681 goto out_parent;
682
683 au_cpup_attr_timesizes(args->dir);
684 au_cpup_attr_timesizes(inode);
685 if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER))
686 au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst));
687 /* au_digen_dec(dentry); */
688
689 out_parent:
690 di_write_unlock(args->parent);
691 aufs_read_unlock(dentry, AuLock_DW);
692 out_inode:
693 inode_unlock(inode);
694 out_dir:
695 inode_unlock(args->dir);
696 out_free:
697 e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown));
698 if (unlikely(e))
699 err = -EFAULT;
700 kfree(args);
701 out:
702 AuTraceErr(err);
703 return err;
704 }