]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - fs/aufs/i_op_del.c
UBUNTU: SAUCE: Import aufs driver
[mirror_ubuntu-hirsute-kernel.git] / fs / aufs / i_op_del.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2005-2020 Junjiro R. Okajima
4 *
5 * This program, aufs is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /*
20 * inode operations (del entry)
21 */
22
23 #include <linux/iversion.h>
24 #include "aufs.h"
25
26 /*
27 * decide if a new whiteout for @dentry is necessary or not.
28 * when it is necessary, prepare the parent dir for the upper branch whose
29 * branch index is @bcpup for creation. the actual creation of the whiteout will
30 * be done by caller.
31 * return value:
32 * 0: wh is unnecessary
33 * plus: wh is necessary
34 * minus: error
35 */
36 int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
37 {
38 int need_wh, err;
39 aufs_bindex_t btop;
40 struct super_block *sb;
41
42 sb = dentry->d_sb;
43 btop = au_dbtop(dentry);
44 if (*bcpup < 0) {
45 *bcpup = btop;
46 if (au_test_ro(sb, btop, d_inode(dentry))) {
47 err = AuWbrCopyup(au_sbi(sb), dentry);
48 *bcpup = err;
49 if (unlikely(err < 0))
50 goto out;
51 }
52 } else
53 AuDebugOn(btop < *bcpup
54 || au_test_ro(sb, *bcpup, d_inode(dentry)));
55 AuDbg("bcpup %d, btop %d\n", *bcpup, btop);
56
57 if (*bcpup != btop) {
58 err = au_cpup_dirs(dentry, *bcpup);
59 if (unlikely(err))
60 goto out;
61 need_wh = 1;
62 } else {
63 struct au_dinfo *dinfo, *tmp;
64
65 need_wh = -ENOMEM;
66 dinfo = au_di(dentry);
67 tmp = au_di_alloc(sb, AuLsc_DI_TMP);
68 if (tmp) {
69 au_di_cp(tmp, dinfo);
70 au_di_swap(tmp, dinfo);
71 /* returns the number of positive dentries */
72 need_wh = au_lkup_dentry(dentry, btop + 1,
73 /* AuLkup_IGNORE_PERM */ 0);
74 au_di_swap(tmp, dinfo);
75 au_rw_write_unlock(&tmp->di_rwsem);
76 au_di_free(tmp);
77 }
78 }
79 AuDbg("need_wh %d\n", need_wh);
80 err = need_wh;
81
82 out:
83 return err;
84 }
85
86 /*
87 * simple tests for the del-entry operations.
88 * following the checks in vfs, plus the parent-child relationship.
89 */
90 int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
91 struct dentry *h_parent, int isdir)
92 {
93 int err;
94 umode_t h_mode;
95 struct dentry *h_dentry, *h_latest;
96 struct inode *h_inode;
97
98 h_dentry = au_h_dptr(dentry, bindex);
99 if (d_really_is_positive(dentry)) {
100 err = -ENOENT;
101 if (unlikely(d_is_negative(h_dentry)))
102 goto out;
103 h_inode = d_inode(h_dentry);
104 if (unlikely(!h_inode->i_nlink))
105 goto out;
106
107 h_mode = h_inode->i_mode;
108 if (!isdir) {
109 err = -EISDIR;
110 if (unlikely(S_ISDIR(h_mode)))
111 goto out;
112 } else if (unlikely(!S_ISDIR(h_mode))) {
113 err = -ENOTDIR;
114 goto out;
115 }
116 } else {
117 /* rename(2) case */
118 err = -EIO;
119 if (unlikely(d_is_positive(h_dentry)))
120 goto out;
121 }
122
123 err = -ENOENT;
124 /* expected parent dir is locked */
125 if (unlikely(h_parent != h_dentry->d_parent))
126 goto out;
127 err = 0;
128
129 /*
130 * rmdir a dir may break the consistency on some filesystem.
131 * let's try heavy test.
132 */
133 err = -EACCES;
134 if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)
135 && au_test_h_perm(d_inode(h_parent),
136 MAY_EXEC | MAY_WRITE)))
137 goto out;
138
139 h_latest = au_sio_lkup_one(&dentry->d_name, h_parent);
140 err = -EIO;
141 if (IS_ERR(h_latest))
142 goto out;
143 if (h_latest == h_dentry)
144 err = 0;
145 dput(h_latest);
146
147 out:
148 return err;
149 }
150
151 /*
152 * decide the branch where we operate for @dentry. the branch index will be set
153 * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent
154 * dir for reverting.
155 * when a new whiteout is necessary, create it.
156 */
157 static struct dentry*
158 lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
159 struct au_dtime *dt, struct au_pin *pin)
160 {
161 struct dentry *wh_dentry;
162 struct super_block *sb;
163 struct path h_path;
164 int err, need_wh;
165 unsigned int udba;
166 aufs_bindex_t bcpup;
167
168 need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
169 wh_dentry = ERR_PTR(need_wh);
170 if (unlikely(need_wh < 0))
171 goto out;
172
173 sb = dentry->d_sb;
174 udba = au_opt_udba(sb);
175 bcpup = *rbcpup;
176 err = au_pin(pin, dentry, bcpup, udba,
177 AuPin_DI_LOCKED | AuPin_MNT_WRITE);
178 wh_dentry = ERR_PTR(err);
179 if (unlikely(err))
180 goto out;
181
182 h_path.dentry = au_pinned_h_parent(pin);
183 if (udba != AuOpt_UDBA_NONE
184 && au_dbtop(dentry) == bcpup) {
185 err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
186 wh_dentry = ERR_PTR(err);
187 if (unlikely(err))
188 goto out_unpin;
189 }
190
191 h_path.mnt = au_sbr_mnt(sb, bcpup);
192 au_dtime_store(dt, au_pinned_parent(pin), &h_path);
193 wh_dentry = NULL;
194 if (!need_wh)
195 goto out; /* success, no need to create whiteout */
196
197 wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
198 if (IS_ERR(wh_dentry))
199 goto out_unpin;
200
201 /* returns with the parent is locked and wh_dentry is dget-ed */
202 goto out; /* success */
203
204 out_unpin:
205 au_unpin(pin);
206 out:
207 return wh_dentry;
208 }
209
210 /*
211 * when removing a dir, rename it to a unique temporary whiteout-ed name first
212 * in order to be revertible and save time for removing many child whiteouts
213 * under the dir.
214 * returns 1 when there are too many child whiteout and caller should remove
215 * them asynchronously. returns 0 when the number of children is enough small to
216 * remove now or the branch fs is a remote fs.
217 * otherwise return an error.
218 */
219 static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
220 struct au_nhash *whlist, struct inode *dir)
221 {
222 int rmdir_later, err, dirwh;
223 struct dentry *h_dentry;
224 struct super_block *sb;
225 struct inode *inode;
226
227 sb = dentry->d_sb;
228 SiMustAnyLock(sb);
229 h_dentry = au_h_dptr(dentry, bindex);
230 err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
231 if (unlikely(err))
232 goto out;
233
234 /* stop monitoring */
235 inode = d_inode(dentry);
236 au_hn_free(au_hi(inode, bindex));
237
238 if (!au_test_fs_remote(h_dentry->d_sb)) {
239 dirwh = au_sbi(sb)->si_dirwh;
240 rmdir_later = (dirwh <= 1);
241 if (!rmdir_later)
242 rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
243 dirwh);
244 if (rmdir_later)
245 return rmdir_later;
246 }
247
248 err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
249 if (unlikely(err)) {
250 AuIOErr("rmdir %pd, b%d failed, %d. ignored\n",
251 h_dentry, bindex, err);
252 err = 0;
253 }
254
255 out:
256 AuTraceErr(err);
257 return err;
258 }
259
260 /*
261 * final procedure for deleting a entry.
262 * maintain dentry and iattr.
263 */
264 static void epilog(struct inode *dir, struct dentry *dentry,
265 aufs_bindex_t bindex)
266 {
267 struct inode *inode;
268
269 inode = d_inode(dentry);
270 d_drop(dentry);
271 inode->i_ctime = dir->i_ctime;
272
273 au_dir_ts(dir, bindex);
274 inode_inc_iversion(dir);
275 }
276
277 /*
278 * when an error happened, remove the created whiteout and revert everything.
279 */
280 static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
281 aufs_bindex_t bwh, struct dentry *wh_dentry,
282 struct dentry *dentry, struct au_dtime *dt)
283 {
284 int rerr;
285 struct path h_path = {
286 .dentry = wh_dentry,
287 .mnt = au_sbr_mnt(dir->i_sb, bindex)
288 };
289
290 rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
291 if (!rerr) {
292 au_set_dbwh(dentry, bwh);
293 au_dtime_revert(dt);
294 return 0;
295 }
296
297 AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr);
298 return -EIO;
299 }
300
301 /* ---------------------------------------------------------------------- */
302
303 int aufs_unlink(struct inode *dir, struct dentry *dentry)
304 {
305 int err;
306 aufs_bindex_t bwh, bindex, btop;
307 struct inode *inode, *h_dir, *delegated;
308 struct dentry *parent, *wh_dentry;
309 /* to reduce stack size */
310 struct {
311 struct au_dtime dt;
312 struct au_pin pin;
313 struct path h_path;
314 } *a;
315
316 IMustLock(dir);
317
318 err = -ENOMEM;
319 a = kmalloc(sizeof(*a), GFP_NOFS);
320 if (unlikely(!a))
321 goto out;
322
323 err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
324 if (unlikely(err))
325 goto out_free;
326 err = au_d_hashed_positive(dentry);
327 if (unlikely(err))
328 goto out_unlock;
329 inode = d_inode(dentry);
330 IMustLock(inode);
331 err = -EISDIR;
332 if (unlikely(d_is_dir(dentry)))
333 goto out_unlock; /* possible? */
334
335 btop = au_dbtop(dentry);
336 bwh = au_dbwh(dentry);
337 bindex = -1;
338 parent = dentry->d_parent; /* dir inode is locked */
339 di_write_lock_parent(parent);
340 wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt,
341 &a->pin);
342 err = PTR_ERR(wh_dentry);
343 if (IS_ERR(wh_dentry))
344 goto out_parent;
345
346 a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop);
347 a->h_path.dentry = au_h_dptr(dentry, btop);
348 dget(a->h_path.dentry);
349 if (bindex == btop) {
350 h_dir = au_pinned_h_dir(&a->pin);
351 delegated = NULL;
352 err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0);
353 if (unlikely(err == -EWOULDBLOCK)) {
354 pr_warn("cannot retry for NFSv4 delegation"
355 " for an internal unlink\n");
356 iput(delegated);
357 }
358 } else {
359 /* dir inode is locked */
360 h_dir = d_inode(wh_dentry->d_parent);
361 IMustLock(h_dir);
362 err = 0;
363 }
364
365 if (!err) {
366 vfsub_drop_nlink(inode);
367 epilog(dir, dentry, bindex);
368
369 /* update target timestamps */
370 if (bindex == btop) {
371 vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
372 /*ignore*/
373 inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
374 } else
375 /* todo: this timestamp may be reverted later */
376 inode->i_ctime = h_dir->i_ctime;
377 goto out_unpin; /* success */
378 }
379
380 /* revert */
381 if (wh_dentry) {
382 int rerr;
383
384 rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
385 &a->dt);
386 if (rerr)
387 err = rerr;
388 }
389
390 out_unpin:
391 au_unpin(&a->pin);
392 dput(wh_dentry);
393 dput(a->h_path.dentry);
394 out_parent:
395 di_write_unlock(parent);
396 out_unlock:
397 aufs_read_unlock(dentry, AuLock_DW);
398 out_free:
399 au_kfree_rcu(a);
400 out:
401 return err;
402 }
403
404 int aufs_rmdir(struct inode *dir, struct dentry *dentry)
405 {
406 int err, rmdir_later;
407 aufs_bindex_t bwh, bindex, btop;
408 struct inode *inode;
409 struct dentry *parent, *wh_dentry, *h_dentry;
410 struct au_whtmp_rmdir *args;
411 /* to reduce stack size */
412 struct {
413 struct au_dtime dt;
414 struct au_pin pin;
415 } *a;
416
417 IMustLock(dir);
418
419 err = -ENOMEM;
420 a = kmalloc(sizeof(*a), GFP_NOFS);
421 if (unlikely(!a))
422 goto out;
423
424 err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
425 if (unlikely(err))
426 goto out_free;
427 err = au_alive_dir(dentry);
428 if (unlikely(err))
429 goto out_unlock;
430 inode = d_inode(dentry);
431 IMustLock(inode);
432 err = -ENOTDIR;
433 if (unlikely(!d_is_dir(dentry)))
434 goto out_unlock; /* possible? */
435
436 err = -ENOMEM;
437 args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
438 if (unlikely(!args))
439 goto out_unlock;
440
441 parent = dentry->d_parent; /* dir inode is locked */
442 di_write_lock_parent(parent);
443 err = au_test_empty(dentry, &args->whlist);
444 if (unlikely(err))
445 goto out_parent;
446
447 btop = au_dbtop(dentry);
448 bwh = au_dbwh(dentry);
449 bindex = -1;
450 wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt,
451 &a->pin);
452 err = PTR_ERR(wh_dentry);
453 if (IS_ERR(wh_dentry))
454 goto out_parent;
455
456 h_dentry = au_h_dptr(dentry, btop);
457 dget(h_dentry);
458 rmdir_later = 0;
459 if (bindex == btop) {
460 err = renwh_and_rmdir(dentry, btop, &args->whlist, dir);
461 if (err > 0) {
462 rmdir_later = err;
463 err = 0;
464 }
465 } else {
466 /* stop monitoring */
467 au_hn_free(au_hi(inode, btop));
468
469 /* dir inode is locked */
470 IMustLock(d_inode(wh_dentry->d_parent));
471 err = 0;
472 }
473
474 if (!err) {
475 vfsub_dead_dir(inode);
476 au_set_dbdiropq(dentry, -1);
477 epilog(dir, dentry, bindex);
478
479 if (rmdir_later) {
480 au_whtmp_kick_rmdir(dir, btop, h_dentry, args);
481 args = NULL;
482 }
483
484 goto out_unpin; /* success */
485 }
486
487 /* revert */
488 AuLabel(revert);
489 if (wh_dentry) {
490 int rerr;
491
492 rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
493 &a->dt);
494 if (rerr)
495 err = rerr;
496 }
497
498 out_unpin:
499 au_unpin(&a->pin);
500 dput(wh_dentry);
501 dput(h_dentry);
502 out_parent:
503 di_write_unlock(parent);
504 if (args)
505 au_whtmp_rmdir_free(args);
506 out_unlock:
507 aufs_read_unlock(dentry, AuLock_DW);
508 out_free:
509 au_kfree_rcu(a);
510 out:
511 AuTraceErr(err);
512 return err;
513 }