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