~ubuntu-branches/ubuntu/vivid/aufs/vivid

« back to all changes in this revision

Viewing changes to fs/aufs/i_op_del.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2007-12-15 23:32:51 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20071215233251-2vgs2lmg8mai5d9e
Tags: 0+20071211-1ubuntu1
* Merge from debian unstable (LP: #175705), remaining changes:
  - Fix for Ubuntu Kernels (updated)
* patches/01_vserver.dpatch: Removed
* patches/06_ubuntu.dpatch: Added (update of ubuntu patch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
17
 */
18
18
 
19
 
/* $Id: i_op_del.c,v 1.38 2007/06/04 02:17:35 sfjro Exp $ */
 
19
/* $Id: i_op_del.c,v 1.55 2007/11/19 01:07:10 sfjro Exp $ */
20
20
 
21
21
#include "aufs.h"
22
22
 
25
25
 * plus: wh is necessary
26
26
 * minus: error
27
27
 */
28
 
int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
29
 
                   struct dentry *locked)
 
28
int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
 
29
                      struct dentry *locked)
30
30
{
31
31
        int need_wh, err;
32
32
        aufs_bindex_t bstart;
33
 
        struct dentry *hidden_dentry;
 
33
        struct dentry *h_dentry;
34
34
        struct super_block *sb;
35
35
 
36
36
        LKTRTrace("%.*s, isdir %d, *bcpup %d, locked %p\n",
37
 
                  DLNPair(dentry), isdir, *bcpup, locked);
 
37
                  AuDLNPair(dentry), isdir, *bcpup, locked);
38
38
        sb = dentry->d_sb;
39
39
 
40
40
        bstart = dbstart(dentry);
41
41
        LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
42
 
        hidden_dentry = au_h_dptr(dentry);
 
42
        h_dentry = au_h_dptr(dentry);
43
43
        if (*bcpup < 0) {
44
44
                *bcpup = bstart;
45
 
                if (test_ro(sb, bstart, dentry->d_inode)) {
46
 
                        *bcpup = err = find_rw_parent_br(dentry, bstart);
47
 
                        //*bcpup = err = find_rw_br(sb, bstart);
 
45
                if (au_test_ro(sb, bstart, dentry->d_inode)) {
 
46
                        err = AuWbrCopyup(stosi(sb), dentry);
 
47
                        *bcpup = err;
48
48
                        //err = -1;
49
49
                        if (unlikely(err < 0))
50
50
                                goto out;
51
51
                }
52
52
        } else
53
53
                AuDebugOn(bstart < *bcpup
54
 
                          || test_ro(sb, *bcpup, dentry->d_inode));
 
54
                          || au_test_ro(sb, *bcpup, dentry->d_inode));
55
55
        LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
56
56
 
57
57
        if (*bcpup != bstart) {
58
 
                err = cpup_dirs(dentry, *bcpup, locked);
 
58
                err = au_cpup_dirs(dentry, *bcpup, locked);
59
59
                //err = -1;
60
60
                if (unlikely(err))
61
61
                        goto out;
68
68
                        bdiropq = dbdiropq(dentry);
69
69
                        set_dbdiropq(dentry, -1);
70
70
                }
71
 
                err = need_wh = lkup_dentry(dentry, bstart + 1, /*type*/0);
 
71
                need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
 
72
                                         /*nd*/NULL);
 
73
                err = need_wh;
72
74
                //err = -1;
73
75
                if (isdir)
74
76
                        set_dbdiropq(dentry, bdiropq);
78
80
                if (!need_wh && old_bend != new_bend) {
79
81
                        set_h_dptr(dentry, new_bend, NULL);
80
82
                        set_dbend(dentry, old_bend);
81
 
#if 0
 
83
#if 0 // remove this?
82
84
                } else if (!au_h_dptr_i(dentry, new_bend)->d_inode) {
83
85
                        LKTRTrace("negative\n");
84
86
                        set_h_dptr(dentry, new_bend, NULL);
91
93
        err = need_wh;
92
94
 
93
95
 out:
94
 
        TraceErr(err);
 
96
        AuTraceErr(err);
95
97
        return err;
96
98
}
97
99
 
98
100
static struct dentry *
99
101
lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
100
 
                    struct dtime *dt)
 
102
                    struct au_dtime *dt)
101
103
{
102
104
        struct dentry *wh_dentry;
103
105
        int err, need_wh;
104
 
        struct dentry *hidden_parent, *parent;
 
106
        struct dentry *h_parent, *parent;
105
107
        struct inode *dir, *h_dir;
106
 
        struct lkup_args lkup;
107
 
 
108
 
        LKTRTrace("%.*s, isdir %d\n", DLNPair(dentry), isdir);
109
 
 
110
 
        err = need_wh = wr_dir_need_wh(dentry, isdir, bcpup, NULL);
 
108
        struct aufs_ndx ndx;
 
109
 
 
110
        LKTRTrace("%.*s, isdir %d\n", AuDLNPair(dentry), isdir);
 
111
 
 
112
        need_wh = au_wr_dir_need_wh(dentry, isdir, bcpup, NULL);
 
113
        err = need_wh;
111
114
        //err = -1;
112
115
        wh_dentry = ERR_PTR(err);
113
116
        if (unlikely(err < 0))
114
117
                goto out;
115
118
 
116
 
        parent = dget_parent(dentry);
 
119
        parent = dentry->d_parent; /* dir inode is locked */
117
120
        dir = parent->d_inode;
118
 
        hidden_parent = au_h_dptr_i(parent, *bcpup);
119
 
        h_dir = hidden_parent->d_inode;
 
121
        IMustLock(dir);
 
122
        h_parent = au_h_dptr_i(parent, *bcpup);
 
123
        h_dir = h_parent->d_inode;
120
124
        hdir_lock(h_dir, dir, *bcpup);
121
 
        dtime_store(dt, parent, hidden_parent);
 
125
        au_dtime_store(dt, parent, *bcpup, h_parent);
122
126
        wh_dentry = NULL;
123
127
        if (!need_wh)
124
 
                goto out_dput; /* success, no need to create whiteout */
 
128
                goto out; /* success, no need to create whiteout */
125
129
 
126
 
        lkup.nfsmnt = au_nfsmnt(dentry->d_sb, *bcpup);
127
 
        lkup.dlgt = need_dlgt(dentry->d_sb);
128
 
        wh_dentry = simple_create_wh(dentry, *bcpup, hidden_parent, &lkup);
 
130
        ndx.nfsmnt = au_nfsmnt(dentry->d_sb, *bcpup);
 
131
        ndx.dlgt = au_need_dlgt(dentry->d_sb);
 
132
        ndx.nd = NULL;
 
133
        //ndx.br = NULL;
 
134
        wh_dentry = simple_create_wh(dir, dentry, *bcpup, h_parent, &ndx);
129
135
        //wh_dentry = ERR_PTR(-1);
130
136
        if (!IS_ERR(wh_dentry))
131
 
                goto out_dput; /* success */
 
137
                goto out; /* success */
132
138
        /* returns with the parent is locked and wh_dentry is DGETed */
133
139
 
134
140
        hdir_unlock(h_dir, dir, *bcpup);
135
141
 
136
 
 out_dput:
137
 
        dput(parent);
138
142
 out:
139
 
        TraceErrPtr(wh_dentry);
 
143
        AuTraceErrPtr(wh_dentry);
140
144
        return wh_dentry;
141
145
}
142
146
 
145
149
{
146
150
        int rmdir_later, err;
147
151
        struct dentry *hidden_dentry;
148
 
 
149
 
        LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
150
 
 
151
 
        err = rename_whtmp(dentry, bindex);
 
152
        struct inode *inode, *h_inode;
 
153
 
 
154
        LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex);
 
155
 
 
156
        inode = NULL;
 
157
        h_inode = NULL;
 
158
        if (unlikely(au_flag_test_udba_inotify(dentry->d_sb))) {
 
159
                inode = dentry->d_inode;
 
160
                h_inode = au_h_iptr_i(inode, bindex);
 
161
                hdir2_lock(h_inode, inode, bindex);
 
162
        }
 
163
        err = rename_whtmp(dir, dentry, bindex, /*noself*/1);
 
164
        if (unlikely(inode))
 
165
                hdir_unlock(h_inode, inode, bindex);
152
166
        //err = -1;
153
 
#if 0
154
 
        //todo: bug
155
 
        if (unlikely(err)) {
156
 
                au_direval_inc(dentry->d_parent);
157
 
                return err;
158
 
        }
159
 
#endif
 
167
        if (unlikely(err))
 
168
                goto out;
160
169
 
161
170
        hidden_dentry = au_h_dptr_i(dentry, bindex);
162
 
        if (!au_is_nfs(hidden_dentry->d_sb)) {
 
171
        if (!au_test_nfs(hidden_dentry->d_sb)) {
163
172
                const int dirwh = stosi(dentry->d_sb)->si_dirwh;
164
173
                rmdir_later = (dirwh <= 1);
165
174
                if (!rmdir_later)
166
 
                        rmdir_later = is_longer_wh(whlist, bindex, dirwh);
 
175
                        rmdir_later = nhash_test_longer_wh(whlist, bindex,
 
176
                                                           dirwh);
167
177
                if (rmdir_later)
168
178
                        return rmdir_later;
169
179
        }
170
180
 
171
 
        err = rmdir_whtmp(hidden_dentry, whlist, bindex, dir, dentry->d_inode);
 
181
        err = rmdir_whtmp(hidden_dentry, whlist, bindex, dir, dentry->d_inode,
 
182
                          /*noself*/1);
172
183
        //err = -1;
173
184
        if (unlikely(err)) {
174
 
                IOErr("rmdir %.*s, b%d failed, %d. ignored\n",
175
 
                      DLNPair(hidden_dentry), bindex, err);
 
185
                AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
 
186
                        AuDLNPair(hidden_dentry), bindex, err);
176
187
                err = 0;
177
188
        }
178
 
        TraceErr(err);
 
189
 
 
190
 out:
 
191
        AuTraceErr(err);
179
192
        return err;
180
193
}
181
194
 
182
195
static void epilog(struct inode *dir, struct dentry *dentry,
183
196
                   aufs_bindex_t bindex)
184
197
{
 
198
        //todo: unnecessary?
185
199
        d_drop(dentry);
186
200
        dentry->d_inode->i_ctime = dir->i_ctime;
 
201
 
187
202
        if (atomic_read(&dentry->d_count) == 1) {
188
203
                set_h_dptr(dentry, dbstart(dentry), NULL);
189
204
                au_update_dbstart(dentry);
193
208
        dir->i_version++;
194
209
}
195
210
 
 
211
struct revert_flags {
 
212
        unsigned int    dlgt:1;
 
213
};
 
214
 
196
215
static int do_revert(int err, struct dentry *wh_dentry, struct dentry *dentry,
197
 
                     aufs_bindex_t bwh, struct dtime *dt, int dlgt)
 
216
                     aufs_bindex_t bwh, struct au_dtime *dt,
 
217
                     struct revert_flags *flags)
198
218
{
199
219
        int rerr;
200
 
        struct dentry *parent;
 
220
        struct inode *dir;
201
221
 
202
 
        parent = dget_parent(wh_dentry);
203
 
        rerr = au_unlink_wh_dentry(parent->d_inode, wh_dentry, dentry, dlgt);
204
 
        dput(parent);
 
222
        dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
 
223
        IMustLock(dir);
 
224
        rerr = au_unlink_wh_dentry(dir, wh_dentry, dentry, dir, !!flags->dlgt);
205
225
        //rerr = -1;
206
226
        if (!rerr) {
207
227
                set_dbwh(dentry, bwh);
208
 
                dtime_revert(dt, !CPUP_LOCKED_GHDIR);
 
228
                au_dtime_revert(dt);
209
229
                return 0;
210
230
        }
211
231
 
212
 
        IOErr("%.*s reverting whiteout failed(%d, %d)\n",
213
 
              DLNPair(dentry), err, rerr);
 
232
        AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
 
233
                AuDLNPair(dentry), err, rerr);
214
234
        return -EIO;
215
235
}
216
236
 
219
239
int aufs_unlink(struct inode *dir, struct dentry *dentry)
220
240
{
221
241
        int err, dlgt;
222
 
        struct inode *inode, *hidden_dir;
223
 
        struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
224
 
        struct dtime dt;
 
242
        struct inode *inode, *h_dir;
 
243
        struct dentry *parent, *wh_dentry, *h_dentry;
 
244
        struct au_dtime dt;
225
245
        aufs_bindex_t bwh, bindex, bstart;
226
246
        struct super_block *sb;
 
247
        struct vfsub_args vargs;
227
248
 
228
 
        LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
 
249
        LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
229
250
        IMustLock(dir);
230
251
        inode = dentry->d_inode;
231
252
        if (unlikely(!inode))
232
 
                return -ENOENT; // possible?
 
253
                return -ENOENT; /* possible? */
233
254
        IMustLock(inode);
234
255
 
235
 
        aufs_read_lock(dentry, AUFS_D_WLOCK);
236
 
        parent = dget_parent(dentry);
 
256
        aufs_read_lock(dentry, AuLock_DW);
 
257
        parent = dentry->d_parent; /* dir inode is locked */
237
258
        di_write_lock_parent(parent);
238
259
 
239
260
        bstart = dbstart(dentry);
246
267
                goto out;
247
268
 
248
269
        sb = dir->i_sb;
249
 
        dlgt = need_dlgt(sb);
250
 
        hidden_dentry = au_h_dptr(dentry);
251
 
        dget(hidden_dentry);
252
 
        hidden_parent = dget_parent(hidden_dentry);
253
 
        hidden_dir = hidden_parent->d_inode;
 
270
        dlgt = au_need_dlgt(sb);
 
271
        h_dentry = au_h_dptr(dentry);
 
272
        dget(h_dentry);
254
273
 
255
274
        if (bindex == bstart) {
256
 
                err = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
 
275
                vfsub_args_init(&vargs, NULL, dlgt, 0);
 
276
                h_dir = h_dentry->d_parent->d_inode; /* dir inode is locked */
 
277
                IMustLock(h_dir);
 
278
                err = vfsub_unlink(h_dir, h_dentry, &vargs);
257
279
                //err = -1;
258
280
        } else {
259
 
                AuDebugOn(!wh_dentry);
260
 
                dput(hidden_parent);
261
 
                hidden_parent = dget_parent(wh_dentry);
262
 
                AuDebugOn(hidden_parent != au_h_dptr_i(parent, bindex));
263
 
                hidden_dir = hidden_parent->d_inode;
264
 
                IMustLock(hidden_dir);
 
281
                /* dir inode is locked */
 
282
                AuDebugOn(!wh_dentry
 
283
                          || wh_dentry->d_parent != au_h_dptr_i(parent,
 
284
                                                                bindex));
 
285
                h_dir = wh_dentry->d_parent->d_inode;
 
286
                IMustLock(h_dir);
265
287
                err = 0;
266
288
        }
267
289
 
268
290
        if (!err) {
269
291
                inode->i_nlink--;
 
292
#if 0 //todo: update plink
 
293
                if (unlikely(!inode->i_nlink
 
294
                             && au_test_plink(sb, inode)
 
295
                             /* && atomic_read(&inode->i_count) == 2) */)) {
 
296
                        au_debug_on();
 
297
                        DbgInode(inode);
 
298
                        au_debug_off();
 
299
                }
 
300
#endif
270
301
                epilog(dir, dentry, bindex);
271
 
#if 0
272
 
                xino_write0(sb, bstart, hidden_dentry->d_inode->i_ino);
273
 
                /* ignore this error */
274
 
#endif
275
302
                goto out_unlock; /* success */
276
303
        }
277
304
 
278
305
        /* revert */
279
306
        if (wh_dentry) {
280
307
                int rerr;
281
 
                rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, dlgt);
 
308
                struct revert_flags rev_flags = {
 
309
                        .dlgt   = dlgt
 
310
                };
 
311
                rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, &rev_flags);
282
312
                if (rerr)
283
313
                        err = rerr;
284
314
        }
285
315
 
286
316
 out_unlock:
287
 
        hdir_unlock(hidden_dir, dir, bindex);
 
317
        hdir_unlock(h_dir, dir, bindex);
288
318
        dput(wh_dentry);
289
 
        dput(hidden_parent);
290
 
        dput(hidden_dentry);
 
319
        dput(h_dentry);
291
320
 out:
292
321
        di_write_unlock(parent);
293
 
        dput(parent);
294
 
        aufs_read_unlock(dentry, AUFS_D_WLOCK);
295
 
        TraceErr(err);
 
322
        aufs_read_unlock(dentry, AuLock_DW);
 
323
        AuTraceErr(err);
296
324
        return err;
297
325
}
298
326
 
299
327
int aufs_rmdir(struct inode *dir, struct dentry *dentry)
300
328
{
301
329
        int err, rmdir_later;
302
 
        struct inode *inode, *hidden_dir;
303
 
        struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
304
 
        struct dtime dt;
 
330
        struct inode *inode, *h_dir;
 
331
        struct dentry *parent, *wh_dentry, *h_dentry;
 
332
        struct au_dtime dt;
305
333
        aufs_bindex_t bwh, bindex, bstart;
306
334
        struct rmdir_whtmp_args *args;
307
335
        struct aufs_nhash *whlist;
308
336
        struct super_block *sb;
309
337
 
310
 
        LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
 
338
        LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
311
339
        IMustLock(dir);
312
340
        inode = dentry->d_inode;
313
341
        if (unlikely(!inode))
314
 
                return -ENOENT; // possible?
 
342
                return -ENOENT; /* possible? */
315
343
        IMustLock(inode);
316
344
 
317
 
        whlist = nhash_new(GFP_KERNEL);
 
345
        whlist = nhash_new(GFP_TEMPORARY);
318
346
        err = PTR_ERR(whlist);
319
347
        if (IS_ERR(whlist))
320
348
                goto out;
321
349
 
322
350
        err = -ENOMEM;
323
 
        args = kmalloc(sizeof(*args), GFP_KERNEL);
 
351
        args = kmalloc(sizeof(*args), GFP_TEMPORARY);
324
352
        //args = NULL;
325
353
        if (unlikely(!args))
326
354
                goto out_whlist;
327
355
 
328
 
        aufs_read_lock(dentry, AUFS_D_WLOCK);
329
 
        parent = dget_parent(dentry);
 
356
        aufs_read_lock(dentry, AuLock_DW);
 
357
        parent = dentry->d_parent; /* dir inode is locked */
330
358
        di_write_lock_parent(parent);
331
 
        err = test_empty(dentry, whlist);
 
359
        err = au_test_empty(dentry, whlist);
332
360
        //err = -1;
333
361
        if (unlikely(err))
334
362
                goto out_args;
342
370
        if (IS_ERR(wh_dentry))
343
371
                goto out_args;
344
372
 
345
 
        hidden_dentry = au_h_dptr(dentry);
346
 
        dget(hidden_dentry);
347
 
        hidden_parent = dget_parent(hidden_dentry);
348
 
        hidden_dir = hidden_parent->d_inode;
 
373
        h_dentry = au_h_dptr(dentry);
 
374
        dget(h_dentry);
349
375
 
350
376
        rmdir_later = 0;
351
377
        if (bindex == bstart) {
352
 
                IMustLock(hidden_dir);
 
378
                h_dir = h_dentry->d_parent->d_inode; /* dir inode is locked */
 
379
                IMustLock(h_dir);
353
380
                err = renwh_and_rmdir(dentry, bstart, whlist, dir);
354
381
                //err = -1;
355
382
                if (err > 0) {
357
384
                        err = 0;
358
385
                }
359
386
        } else {
360
 
                AuDebugOn(!wh_dentry);
361
 
                dput(hidden_parent);
362
 
                hidden_parent = dget_parent(wh_dentry);;
363
 
                AuDebugOn(hidden_parent != au_h_dptr_i(parent, bindex));
364
 
                hidden_dir = hidden_parent->d_inode;
365
 
                IMustLock(hidden_dir);
 
387
                /* dir inode is locked */
 
388
                AuDebugOn(!wh_dentry
 
389
                          || wh_dentry->d_parent != au_h_dptr_i(parent,
 
390
                                                                bindex));
 
391
                h_dir = wh_dentry->d_parent->d_inode;
 
392
                IMustLock(h_dir);
366
393
                err = 0;
367
394
        }
368
395
 
376
403
                epilog(dir, dentry, bindex);
377
404
 
378
405
                if (rmdir_later) {
379
 
                        kick_rmdir_whtmp(hidden_dentry, whlist, bstart, dir,
380
 
                                         inode, args);
 
406
                        kick_rmdir_whtmp(h_dentry, whlist, bstart, dir,
 
407
                                         inode, /*noself*/1, args);
381
408
                        args = NULL;
382
409
                }
383
410
 
384
 
#if 0
385
 
                bend = dbend(dentry);
386
 
                for (bi = bstart; bi <= bend; bi++) {
387
 
                        struct dentry *hd;
388
 
                        hd = au_h_dptr_i(dentry, bi);
389
 
                        if (hd && hd->d_inode)
390
 
                                xino_write0(sb, bi, hd->d_inode->i_ino);
391
 
                        /* ignore this error */
392
 
                }
393
 
#endif
394
 
 
395
411
                goto out_unlock; /* success */
396
412
        }
397
413
 
399
415
        LKTRLabel(revert);
400
416
        if (wh_dentry) {
401
417
                int rerr;
402
 
                rerr = do_revert(err, wh_dentry, dentry, bwh, &dt,
403
 
                                 need_dlgt(sb));
 
418
                struct revert_flags rev_flags = {
 
419
                        .dlgt   = au_need_dlgt(sb)
 
420
                };
 
421
                rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, &rev_flags);
404
422
                if (rerr)
405
423
                        err = rerr;
406
424
        }
407
425
 
408
426
 out_unlock:
409
 
        hdir_unlock(hidden_dir, dir, bindex);
 
427
        hdir_unlock(h_dir, dir, bindex);
410
428
        dput(wh_dentry);
411
 
        dput(hidden_parent);
412
 
        dput(hidden_dentry);
 
429
        dput(h_dentry);
413
430
 out_args:
414
431
        di_write_unlock(parent);
415
 
        dput(parent);
416
 
        aufs_read_unlock(dentry, AUFS_D_WLOCK);
 
432
        aufs_read_unlock(dentry, AuLock_DW);
417
433
        kfree(args);
418
434
 out_whlist:
419
435
        nhash_del(whlist);
420
436
 out:
421
 
        TraceErr(err);
 
437
        AuTraceErr(err);
422
438
        return err;
423
439
}