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