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

« back to all changes in this revision

Viewing changes to fs/aufs/cpup.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: cpup.c,v 1.40 2007/06/04 02:17:34 sfjro Exp $ */
 
19
/* $Id: cpup.c,v 1.58 2007/11/26 01:34:04 sfjro Exp $ */
20
20
 
21
 
#include <asm/uaccess.h>
22
21
#include "aufs.h"
23
22
 
24
23
/* violent cpup_attr_*() functions don't care inode lock */
25
24
void au_cpup_attr_timesizes(struct inode *inode)
26
25
{
27
 
        struct inode *hidden_inode;
 
26
        struct inode *h_inode;
28
27
 
29
28
        LKTRTrace("i%lu\n", inode->i_ino);
30
29
        //IMustLock(inode);
31
 
        hidden_inode = au_h_iptr(inode);
32
 
        AuDebugOn(!hidden_inode);
33
 
        //IMustLock(!hidden_inode);
 
30
        h_inode = au_h_iptr(inode);
 
31
        AuDebugOn(!h_inode);
 
32
        //IMustLock(!h_inode);
34
33
 
35
 
        inode->i_atime = hidden_inode->i_atime;
36
 
        inode->i_mtime = hidden_inode->i_mtime;
37
 
        inode->i_ctime = hidden_inode->i_ctime;
 
34
        inode->i_atime = h_inode->i_atime;
 
35
        inode->i_mtime = h_inode->i_mtime;
 
36
        inode->i_ctime = h_inode->i_ctime;
38
37
        spin_lock(&inode->i_lock);
39
 
        i_size_write(inode, i_size_read(hidden_inode));
40
 
        inode->i_blocks = hidden_inode->i_blocks;
 
38
        i_size_write(inode, i_size_read(h_inode));
 
39
        inode->i_blocks = h_inode->i_blocks;
41
40
        spin_unlock(&inode->i_lock);
42
41
}
43
42
 
67
66
        }
68
67
}
69
68
 
70
 
void au_cpup_attr_changable(struct inode *inode)
 
69
void au_cpup_attr_changeable(struct inode *inode)
71
70
{
72
 
        struct inode *hidden_inode;
 
71
        struct inode *h_inode;
73
72
 
74
73
        LKTRTrace("i%lu\n", inode->i_ino);
75
74
        //IMustLock(inode);
76
 
        hidden_inode = au_h_iptr(inode);
77
 
        AuDebugOn(!hidden_inode);
 
75
        h_inode = au_h_iptr(inode);
 
76
        AuDebugOn(!h_inode);
78
77
 
79
 
        inode->i_mode = hidden_inode->i_mode;
80
 
        inode->i_uid = hidden_inode->i_uid;
81
 
        inode->i_gid = hidden_inode->i_gid;
 
78
        inode->i_mode = h_inode->i_mode;
 
79
        inode->i_uid = h_inode->i_uid;
 
80
        inode->i_gid = h_inode->i_gid;
82
81
        au_cpup_attr_timesizes(inode);
83
82
 
84
83
        //??
85
 
        inode->i_flags = hidden_inode->i_flags;
 
84
        inode->i_flags = h_inode->i_flags;
86
85
}
87
86
 
88
87
void au_cpup_igen(struct inode *inode, struct inode *h_inode)
93
92
 
94
93
void au_cpup_attr_all(struct inode *inode)
95
94
{
96
 
        struct inode *hidden_inode;
 
95
        struct inode *h_inode;
97
96
 
98
97
        LKTRTrace("i%lu\n", inode->i_ino);
99
98
        //IMustLock(inode);
100
 
        hidden_inode = au_h_iptr(inode);
101
 
        AuDebugOn(!hidden_inode);
 
99
        h_inode = au_h_iptr(inode);
 
100
        AuDebugOn(!h_inode);
102
101
 
103
 
        au_cpup_attr_changable(inode);
 
102
        au_cpup_attr_changeable(inode);
104
103
        if (inode->i_nlink > 0)
105
104
                au_cpup_attr_nlink(inode);
106
105
 
107
106
        switch (inode->i_mode & S_IFMT) {
108
107
        case S_IFBLK:
109
108
        case S_IFCHR:
110
 
                inode->i_rdev = hidden_inode->i_rdev;
 
109
                inode->i_rdev = h_inode->i_rdev;
111
110
        }
112
 
        inode->i_blkbits = hidden_inode->i_blkbits;
113
 
        au_cpup_attr_blksize(inode, hidden_inode);
114
 
        au_cpup_igen(inode, hidden_inode);
 
111
        inode->i_blkbits = h_inode->i_blkbits;
 
112
        au_cpup_attr_blksize(inode, h_inode);
 
113
        au_cpup_igen(inode, h_inode);
115
114
}
116
115
 
117
116
/* ---------------------------------------------------------------------- */
119
118
/* Note: dt_dentry and dt_hidden_dentry are not dget/dput-ed */
120
119
 
121
120
/* keep the timestamps of the parent dir when cpup */
122
 
void dtime_store(struct dtime *dt, struct dentry *dentry,
123
 
                 struct dentry *hidden_dentry)
 
121
void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
 
122
                    aufs_bindex_t bindex, struct dentry *h_dentry)
124
123
{
125
124
        struct inode *inode;
126
125
 
127
 
        TraceEnter();
128
 
        AuDebugOn(!dentry || !hidden_dentry || !hidden_dentry->d_inode);
 
126
        AuTraceEnter();
 
127
        AuDebugOn(!dentry || !h_dentry || !h_dentry->d_inode);
129
128
 
130
129
        dt->dt_dentry = dentry;
131
 
        dt->dt_h_dentry = hidden_dentry;
132
 
        inode = hidden_dentry->d_inode;
 
130
        dt->dt_h_dentry = h_dentry;
 
131
        dt->dt_bindex = bindex;
 
132
        inode = h_dentry->d_inode;
133
133
        dt->dt_atime = inode->i_atime;
134
134
        dt->dt_mtime = inode->i_mtime;
135
135
        //smp_mb();
136
136
}
137
137
 
138
 
// todo: remove extra parameter
139
 
void dtime_revert(struct dtime *dt, int h_parent_is_locked)
 
138
void au_dtime_revert(struct au_dtime *dt)
140
139
{
141
140
        struct iattr attr;
142
141
        int err;
143
 
        struct dentry *dentry;
 
142
        struct dentry *parent;
 
143
        struct aufs_hin_ignore ign;
 
144
        struct vfsub_args vargs;
144
145
 
145
 
        LKTRTrace("h_parent locked %d\n", h_parent_is_locked);
 
146
        LKTRTrace("%.*s\n", AuDLNPair(dt->dt_dentry));
146
147
 
147
148
        attr.ia_atime = dt->dt_atime;
148
149
        attr.ia_mtime = dt->dt_mtime;
149
150
        attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
150
151
                | ATTR_ATIME | ATTR_ATIME_SET;
151
 
        //smp_mb();
152
 
        dentry = NULL;
153
 
        if (!h_parent_is_locked /* && !IS_ROOT(dt->dt_dentry) */)
154
 
                dentry = dt->dt_dentry;
155
 
        err = vfsub_notify_change(dt->dt_h_dentry, &attr,
156
 
                                  need_dlgt(dt->dt_dentry->d_sb));
 
152
 
 
153
        vfsub_args_init(&vargs, &ign, au_need_dlgt(dt->dt_dentry->d_sb), 0);
 
154
        if (unlikely(au_flag_test_udba_inotify(dt->dt_dentry->d_sb)
 
155
                     && !IS_ROOT(dt->dt_dentry))) {
 
156
                parent = dget_parent(dt->dt_dentry);
 
157
                vfsub_ign_hinode(&vargs, IN_ATTRIB,
 
158
                                 itohi(parent->d_inode, dt->dt_bindex));
 
159
                err = vfsub_notify_change(dt->dt_h_dentry, &attr, &vargs);
 
160
                dput(parent);
 
161
        } else
 
162
                err = vfsub_notify_change(dt->dt_h_dentry, &attr, &vargs);
157
163
        if (unlikely(err))
158
 
                Warn("restoring timestamps failed(%d). ignored\n", err);
 
164
                AuWarn("restoring timestamps failed(%d). ignored\n", err);
159
165
}
160
166
 
161
167
/* ---------------------------------------------------------------------- */
162
168
 
163
 
static int cpup_iattr(struct dentry *hidden_dst, struct dentry *hidden_src,
164
 
                      int dlgt)
 
169
static int cpup_iattr(struct dentry *h_dst, struct dentry *h_src, int dlgt)
165
170
{
166
 
        int err;
 
171
        int err, sbits;
167
172
        struct iattr ia;
168
 
        struct inode *hidden_isrc, *hidden_idst;
 
173
        struct inode *h_isrc, *h_idst;
 
174
        struct vfsub_args vargs;
169
175
 
170
 
        LKTRTrace("%.*s\n", DLNPair(hidden_dst));
171
 
        hidden_idst = hidden_dst->d_inode;
172
 
        //IMustLock(hidden_idst);
173
 
        hidden_isrc = hidden_src->d_inode;
174
 
        //IMustLock(hidden_isrc);
 
176
        LKTRTrace("%.*s\n", AuDLNPair(h_dst));
 
177
        h_idst = h_dst->d_inode;
 
178
        //IMustLock(h_idst);
 
179
        h_isrc = h_src->d_inode;
 
180
        //IMustLock(h_isrc);
175
181
 
176
182
        ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
177
183
                | ATTR_ATIME | ATTR_MTIME
178
184
                | ATTR_ATIME_SET | ATTR_MTIME_SET;
179
 
        ia.ia_mode = hidden_isrc->i_mode;
180
 
        ia.ia_uid = hidden_isrc->i_uid;
181
 
        ia.ia_gid = hidden_isrc->i_gid;
182
 
        ia.ia_atime = hidden_isrc->i_atime;
183
 
        ia.ia_mtime = hidden_isrc->i_mtime;
184
 
        err = vfsub_notify_change(hidden_dst, &ia, dlgt);
 
185
        ia.ia_mode = h_isrc->i_mode;
 
186
        ia.ia_uid = h_isrc->i_uid;
 
187
        ia.ia_gid = h_isrc->i_gid;
 
188
        ia.ia_atime = h_isrc->i_atime;
 
189
        ia.ia_mtime = h_isrc->i_mtime;
 
190
        sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
 
191
 
 
192
        vfsub_args_init(&vargs, NULL, dlgt, /*force_unlink*/0);
 
193
        err = vfsub_notify_change(h_dst, &ia, &vargs);
185
194
        //if (LktrCond) err = -1;
 
195
 
 
196
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 
197
        /* is this nfs only? */
 
198
        if (!err && sbits && au_test_nfs(h_dst->d_sb)) {
 
199
                ia.ia_valid = ATTR_FORCE | ATTR_MODE;
 
200
                ia.ia_mode = h_isrc->i_mode;
 
201
                err = vfsub_notify_change(h_dst, &ia, &vargs);
 
202
        }
 
203
#endif
186
204
        if (!err)
187
 
                hidden_idst->i_flags = hidden_isrc->i_flags; //??
 
205
                h_idst->i_flags = h_isrc->i_flags; //??
188
206
 
189
 
        TraceErr(err);
 
207
        AuTraceErr(err);
190
208
        return err;
191
209
}
192
210
 
197
215
static int cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
198
216
                        aufs_bindex_t bsrc, loff_t len)
199
217
{
200
 
        int err, i, sparse;
 
218
        int err, i;
201
219
        struct super_block *sb;
202
 
        struct inode *hidden_inode;
203
 
        enum {SRC, DST};
 
220
        struct inode *h_inode;
 
221
        enum { SRC, DST };
204
222
        struct {
205
223
                aufs_bindex_t bindex;
206
224
                unsigned int flags;
225
243
        };
226
244
 
227
245
        LKTRTrace("dentry %.*s, bdst %d, bsrc %d, len %lld\n",
228
 
                  DLNPair(dentry), bdst, bsrc, len);
 
246
                  AuDLNPair(dentry), bdst, bsrc, len);
229
247
        AuDebugOn(bsrc <= bdst);
230
248
        AuDebugOn(!len);
231
249
        sb = dentry->d_sb;
232
 
        AuDebugOn(test_ro(sb, bdst, dentry->d_inode));
233
 
        // bsrc branch can be ro/rw.
 
250
        AuDebugOn(au_test_ro(sb, bdst, dentry->d_inode));
 
251
        /* bsrc branch can be ro/rw. */
234
252
 
235
253
        h = hidden;
236
254
        for (i = 0; i < 2; i++, h++) {
237
255
                h->dentry = au_h_dptr_i(dentry, h->bindex);
238
256
                AuDebugOn(!h->dentry);
239
 
                hidden_inode = h->dentry->d_inode;
240
 
                AuDebugOn(!hidden_inode || !S_ISREG(hidden_inode->i_mode));
241
 
                h->file = hidden_open(dentry, h->bindex, h->flags);
 
257
                h_inode = h->dentry->d_inode;
 
258
                AuDebugOn(!h_inode || !S_ISREG(h_inode->i_mode));
 
259
                h->file = au_h_open(dentry, h->bindex, h->flags, /*file*/NULL);
242
260
                //if (LktrCond)
243
 
                //{fput(h->file); sbr_put(sb, h->bindex); h->file = ERR_PTR(-1);}
 
261
                //{fput(h->file);sbr_put(sb, h->bindex);h->file=ERR_PTR(-1);}
244
262
                err = PTR_ERR(h->file);
245
263
                if (IS_ERR(h->file))
246
264
                        goto *h->label;
251
269
 
252
270
        /* stop updating while we copyup */
253
271
        IMustLock(hidden[SRC].dentry->d_inode);
254
 
        sparse = 0;
255
 
        err = au_copy_file(hidden[DST].file, hidden[SRC].file, len, sb,
256
 
                           &sparse);
257
 
 
258
 
        /* sparse file: update i_blocks next time */
259
 
        if (unlikely(!err && sparse))
260
 
                d_drop(dentry);
 
272
        err = au_copy_file(hidden[DST].file, hidden[SRC].file, len, sb);
261
273
 
262
274
 out_dst_file:
263
275
        fput(hidden[DST].file);
266
278
        fput(hidden[SRC].file);
267
279
        sbr_put(sb, hidden[SRC].bindex);
268
280
 out:
269
 
        TraceErr(err);
 
281
        AuTraceErr(err);
270
282
        return err;
271
283
}
272
284
 
273
 
// unnecessary?
274
 
unsigned int au_flags_cpup(unsigned int init, struct dentry *parent)
275
 
{
276
 
        if (unlikely(parent && IS_ROOT(parent)))
277
 
                init |= CPUP_LOCKED_GHDIR;
278
 
        return init;
279
 
}
280
 
 
281
285
/* return with hidden dst inode is locked */
282
286
static int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
283
 
                      aufs_bindex_t bsrc, loff_t len, unsigned int flags,
284
 
                      int dlgt)
 
287
                      aufs_bindex_t bsrc, loff_t len,
 
288
                      struct au_cpup_flags *flags, int dlgt)
285
289
{
286
 
        int err, isdir, symlen;
287
 
        struct dentry *hidden_src, *hidden_dst, *hidden_parent, *parent;
288
 
        struct inode *hidden_inode, *hidden_dir, *dir;
289
 
        struct dtime dt;
 
290
        int err, symlen;
 
291
        struct dentry *h_src, *h_dst, *h_parent, *parent;
 
292
        struct inode *h_inode, *h_dir, *dir;
 
293
        struct au_dtime dt;
290
294
        umode_t mode;
291
295
        char *sym;
292
296
        mm_segment_t old_fs;
293
 
        const int do_dt = flags & CPUP_DTIME;
294
297
        struct super_block *sb;
 
298
        struct vfsub_args vargs;
 
299
        const int do_dt = flags->dtime;
295
300
 
296
 
        LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
297
 
                  DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
298
 
                  flags);
 
301
        LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, dtime %u\n",
 
302
                  AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
 
303
                  do_dt);
299
304
        sb = dentry->d_sb;
300
 
        AuDebugOn(bdst >= bsrc || test_ro(sb, bdst, NULL));
301
 
        // bsrc branch can be ro/rw.
 
305
        AuDebugOn(bdst >= bsrc || au_test_ro(sb, bdst, NULL));
 
306
        /* bsrc branch can be ro/rw. */
302
307
 
303
 
        hidden_src = au_h_dptr_i(dentry, bsrc);
304
 
        AuDebugOn(!hidden_src);
305
 
        hidden_inode = hidden_src->d_inode;
306
 
        AuDebugOn(!hidden_inode);
 
308
        h_src = au_h_dptr_i(dentry, bsrc);
 
309
        AuDebugOn(!h_src);
 
310
        h_inode = h_src->d_inode;
 
311
        AuDebugOn(!h_inode);
307
312
 
308
313
        /* stop refrencing while we are creating */
309
314
        parent = dget_parent(dentry);
310
315
        dir = parent->d_inode;
311
 
        hidden_dst = au_h_dptr_i(dentry, bdst);
312
 
        AuDebugOn(hidden_dst && hidden_dst->d_inode);
313
 
        hidden_parent = dget_parent(hidden_dst);
314
 
        hidden_dir = hidden_parent->d_inode;
315
 
        IMustLock(hidden_dir);
 
316
        h_dst = au_h_dptr_i(dentry, bdst);
 
317
        AuDebugOn(h_dst && h_dst->d_inode);
 
318
        h_parent = h_dst->d_parent; /* dir inode is locked */
 
319
        h_dir = h_parent->d_inode;
 
320
        IMustLock(h_dir);
316
321
 
317
322
        if (do_dt)
318
 
                dtime_store(&dt, parent, hidden_parent);
 
323
                au_dtime_store(&dt, parent, bdst, h_parent);
319
324
 
320
 
        isdir = 0;
321
 
        mode = hidden_inode->i_mode;
 
325
        mode = h_inode->i_mode;
322
326
        switch (mode & S_IFMT) {
323
327
        case S_IFREG:
324
328
                /* stop updating while we are referencing */
325
 
                IMustLock(hidden_inode);
326
 
                err = vfsub_create(hidden_dir, hidden_dst, mode | S_IWUSR, NULL,
327
 
                                   dlgt);
328
 
                //if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
 
329
                IMustLock(h_inode);
 
330
                err = au_h_create(h_dir, h_dst, mode | S_IWUSR, dlgt, NULL,
 
331
                                  au_nfsmnt(sb, bdst));
 
332
                //if (LktrCond) {vfs_unlink(h_dir, h_dst); err = -1;}
329
333
                if (!err) {
330
 
                        loff_t l = i_size_read(hidden_inode);
 
334
                        loff_t l = i_size_read(h_inode);
331
335
                        if (len == -1 || l < len)
332
336
                                len = l;
333
337
                        if (len) {
336
340
                        }
337
341
                        if (unlikely(err)) {
338
342
                                int rerr;
339
 
                                rerr = vfsub_unlink(hidden_dir, hidden_dst,
340
 
                                                    dlgt);
 
343
                                vfsub_args_init(&vargs, NULL, dlgt, 0);
 
344
                                rerr = vfsub_unlink(h_dir, h_dst, &vargs);
341
345
                                if (rerr) {
342
 
                                        IOErr("failed unlinking cpup-ed %.*s"
343
 
                                              "(%d, %d)\n",
344
 
                                              DLNPair(hidden_dst), err, rerr);
 
346
                                        AuIOErr("failed unlinking cpup-ed %.*s"
 
347
                                                "(%d, %d)\n",
 
348
                                                AuDLNPair(h_dst), err, rerr);
345
349
                                        err = -EIO;
346
350
                                }
347
351
                        }
348
352
                }
349
353
                break;
350
354
        case S_IFDIR:
351
 
                isdir = 1;
352
 
                err = vfsub_mkdir(hidden_dir, hidden_dst, mode, dlgt);
353
 
                //if (LktrCond) {vfs_rmdir(hidden_dir, hidden_dst); err = -1;}
 
355
                err = vfsub_mkdir(h_dir, h_dst, mode, dlgt);
 
356
                //if (LktrCond) {vfs_rmdir(h_dir, h_dst); err = -1;}
354
357
                if (!err) {
355
358
                        /* setattr case: dir is not locked */
356
359
                        if (0 && ibstart(dir) == bdst)
366
369
                        break;
367
370
                old_fs = get_fs();
368
371
                set_fs(KERNEL_DS);
369
 
                err = symlen = hidden_inode->i_op->readlink
370
 
                        (hidden_src, (char __user*)sym, PATH_MAX);
 
372
                symlen = h_inode->i_op->readlink(h_src, (char __user *)sym,
 
373
                                                 PATH_MAX);
 
374
                err = symlen;
371
375
                //if (LktrCond) err = symlen = -1;
372
376
                set_fs(old_fs);
373
377
                if (symlen > 0) {
374
378
                        sym[symlen] = 0;
375
 
                        err = vfsub_symlink(hidden_dir, hidden_dst, sym, mode,
376
 
                                            dlgt);
 
379
                        err = vfsub_symlink(h_dir, h_dst, sym, mode, dlgt);
377
380
                        //if (LktrCond)
378
 
                        //{vfs_unlink(hidden_dir, hidden_dst); err = -1;}
 
381
                        //{vfs_unlink(h_dir, h_dst); err = -1;}
379
382
                }
380
383
                __putname(sym);
381
384
                break;
385
388
                /*FALLTHROUGH*/
386
389
        case S_IFIFO:
387
390
        case S_IFSOCK:
388
 
                err = vfsub_mknod(hidden_dir, hidden_dst, mode,
389
 
                                  hidden_inode->i_rdev, dlgt);
390
 
                //if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
 
391
                err = vfsub_mknod(h_dir, h_dst, mode, h_inode->i_rdev, dlgt);
 
392
                //if (LktrCond) {vfs_unlink(h_dir, h_dst); err = -1;}
391
393
                break;
392
394
        default:
393
 
                IOErr("Unknown inode type 0%o\n", mode);
 
395
                AuIOErr("Unknown inode type 0%o\n", mode);
394
396
                err = -EIO;
395
397
        }
396
398
 
397
399
        if (do_dt)
398
 
                dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
 
400
                au_dtime_revert(&dt);
399
401
        dput(parent);
400
 
        dput(hidden_parent);
401
 
        TraceErr(err);
 
402
        AuTraceErr(err);
402
403
        return err;
403
404
}
404
405
 
407
408
 * the caller must set the both of hidden dentries.
408
409
 * @len is for trucating when it is -1 copyup the entire file.
409
410
 */
410
 
int cpup_single(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
411
 
                loff_t len, unsigned int flags)
 
411
int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
 
412
                   aufs_bindex_t bsrc, loff_t len, struct au_cpup_flags *flags)
412
413
{
413
414
        int err, rerr, isdir, dlgt;
414
 
        struct dentry *hidden_src, *hidden_dst, *parent, *h_parent;
415
 
        struct inode *dst_inode, *hidden_dir, *inode, *src_inode;
 
415
        struct dentry *h_src, *h_dst, *parent, *h_parent;
 
416
        struct inode *dst_inode, *h_dir, *inode, *src_inode, *dir;
416
417
        struct super_block *sb;
417
418
        aufs_bindex_t old_ibstart;
418
 
        struct dtime dt;
 
419
        struct au_dtime dt;
 
420
        struct vfsub_args vargs;
 
421
        struct aufs_sbinfo *sbinfo;
419
422
 
420
 
        LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
421
 
                  DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
422
 
                  flags);
 
423
        LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, dtime %u\n",
 
424
                  AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
 
425
                  flags->dtime);
423
426
        sb = dentry->d_sb;
424
427
        AuDebugOn(bsrc <= bdst);
425
 
        hidden_dst = au_h_dptr_i(dentry, bdst);
426
 
        AuDebugOn(!hidden_dst || hidden_dst->d_inode);
427
 
        h_parent = dget_parent(hidden_dst);
428
 
        hidden_dir = h_parent->d_inode;
429
 
        IMustLock(hidden_dir);
430
 
        hidden_src = au_h_dptr_i(dentry, bsrc);
431
 
        AuDebugOn(!hidden_src || !hidden_src->d_inode);
 
428
        h_dst = au_h_dptr_i(dentry, bdst);
 
429
        AuDebugOn(!h_dst || h_dst->d_inode);
 
430
        h_parent = h_dst->d_parent; /* dir inode is locked */
 
431
        h_dir = h_parent->d_inode;
 
432
        IMustLock(h_dir);
 
433
        h_src = au_h_dptr_i(dentry, bsrc);
 
434
        AuDebugOn(!h_src || !h_src->d_inode);
432
435
        inode = dentry->d_inode;
433
436
        IiMustWriteLock(inode);
 
437
        parent = dget_parent(dentry);
 
438
        dir = parent->d_inode;
434
439
 
435
 
        dlgt = need_dlgt(sb);
 
440
        sbinfo = stosi(sb);
 
441
        dlgt = au_need_dlgt(sb);
436
442
        dst_inode = au_h_iptr_i(inode, bdst);
437
443
        if (unlikely(dst_inode)) {
438
 
                if (unlikely(!au_flag_test(sb, AuFlag_PLINK))) {
 
444
                if (unlikely(!AuFlag(sbinfo, f_plink))) {
439
445
                        err = -EIO;
440
 
                        IOErr("i%lu exists on a upper branch "
441
 
                              "but plink is disabled\n", inode->i_ino);
 
446
                        AuIOErr("i%lu exists on a upper branch "
 
447
                                "but plink is disabled\n", inode->i_ino);
442
448
                        goto out;
443
449
                }
444
450
 
445
451
                if (dst_inode->i_nlink) {
446
 
                        hidden_src = lkup_plink(sb, bdst, inode);
447
 
                        err = PTR_ERR(hidden_src);
448
 
                        if (IS_ERR(hidden_src))
 
452
                        h_src = au_lkup_plink(sb, bdst, inode);
 
453
                        err = PTR_ERR(h_src);
 
454
                        if (IS_ERR(h_src))
449
455
                                goto out;
450
 
                        AuDebugOn(!hidden_src->d_inode);
451
 
                        // vfs_link() does lock the inode
452
 
                        err = vfsub_link(hidden_src, hidden_dir, hidden_dst,
453
 
                                         dlgt);
454
 
                        dput(hidden_src);
 
456
                        AuDebugOn(!h_src->d_inode);
 
457
                        err = vfsub_link(h_src, h_dir, h_dst, dlgt);
 
458
                        dput(h_src);
455
459
                        goto out;
456
460
                } else
 
461
                        //todo: cpup_wh_file
457
462
                        /* udba work */
458
463
                        au_update_brange(inode, 1);
459
464
        }
462
467
        err = cpup_entry(dentry, bdst, bsrc, len, flags, dlgt);
463
468
        if (unlikely(err))
464
469
                goto out;
465
 
        dst_inode = hidden_dst->d_inode;
466
 
        hi_lock_child2(dst_inode);
 
470
        dst_inode = h_dst->d_inode;
 
471
        vfsub_i_lock_nested(dst_inode, AuLsc_I_CHILD2);
467
472
 
468
473
        //todo: test dlgt
469
 
        err = cpup_iattr(hidden_dst, hidden_src, dlgt);
 
474
        err = cpup_iattr(h_dst, h_src, dlgt);
470
475
        //if (LktrCond) err = -1;
471
476
#if 0 // xattr
472
477
        if (0 && !err)
473
 
                err = cpup_xattrs(hidden_src, hidden_dst);
 
478
                err = cpup_xattrs(h_src, h_dst);
474
479
#endif
475
480
        isdir = S_ISDIR(dst_inode->i_mode);
476
481
        if (!err) {
478
483
                        set_ibstart(inode, bdst);
479
484
                set_h_iptr(inode, bdst, igrab(dst_inode),
480
485
                           au_hi_flags(inode, isdir));
481
 
                i_unlock(dst_inode);
482
 
                src_inode = hidden_src->d_inode;
483
 
                if (!isdir) {
484
 
                        if (src_inode->i_nlink > 1
485
 
                            && au_flag_test(sb, AuFlag_PLINK))
486
 
                                append_plink(sb, inode, hidden_dst, bdst);
487
 
                        else {
488
 
                                /* braces are added to stop a warning */
489
 
                                ;//xino_write0(sb, bsrc, src_inode->i_ino);
490
 
                                /* ignore this error */
491
 
                        }
492
 
                }
 
486
                vfsub_i_unlock(dst_inode);
 
487
                src_inode = h_src->d_inode;
 
488
                if (!isdir
 
489
                    && src_inode->i_nlink > 1
 
490
                    && AuFlag(sbinfo, f_plink))
 
491
                        au_append_plink(sb, inode, h_dst, bdst);
493
492
                goto out; /* success */
494
493
        }
495
494
 
496
495
        /* revert */
497
 
        i_unlock(dst_inode);
498
 
        parent = dget_parent(dentry);
499
 
        dtime_store(&dt, parent, h_parent);
500
 
        dput(parent);
 
496
        vfsub_i_unlock(dst_inode);
 
497
        au_dtime_store(&dt, parent, bdst, h_parent);
 
498
        vfsub_args_init(&vargs, NULL, dlgt, 0);
501
499
        if (!isdir)
502
 
                rerr = vfsub_unlink(hidden_dir, hidden_dst, dlgt);
 
500
                rerr = vfsub_unlink(h_dir, h_dst, &vargs);
503
501
        else
504
 
                rerr = vfsub_rmdir(hidden_dir, hidden_dst, dlgt);
 
502
                rerr = vfsub_rmdir(h_dir, h_dst, &vargs);
505
503
        //rerr = -1;
506
 
        dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
 
504
        au_dtime_revert(&dt);
507
505
        if (rerr) {
508
 
                IOErr("failed removing broken entry(%d, %d)\n", err, rerr);
 
506
                AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
509
507
                err = -EIO;
510
508
        }
511
509
 
512
510
 out:
513
 
        dput(h_parent);
514
 
        TraceErr(err);
 
511
        dput(parent);
 
512
        AuTraceErr(err);
515
513
        return err;
516
514
}
517
515
 
518
 
struct cpup_single_args {
 
516
struct au_cpup_single_args {
519
517
        int *errp;
520
518
        struct dentry *dentry;
521
519
        aufs_bindex_t bdst, bsrc;
522
520
        loff_t len;
523
 
        unsigned int flags;
 
521
        struct au_cpup_flags *flags;
524
522
};
525
523
 
526
 
static void call_cpup_single(void *args)
 
524
static void au_call_cpup_single(void *args)
527
525
{
528
 
        struct cpup_single_args *a = args;
529
 
        *a->errp = cpup_single(a->dentry, a->bdst, a->bsrc, a->len, a->flags);
 
526
        struct au_cpup_single_args *a = args;
 
527
        *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
 
528
                                  a->flags);
530
529
}
531
530
 
532
 
int sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
533
 
                    aufs_bindex_t bsrc, loff_t len, unsigned int flags)
 
531
int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
 
532
                       aufs_bindex_t bsrc, loff_t len,
 
533
                       struct au_cpup_flags *flags)
534
534
{
535
535
        int err, wkq_err;
536
 
        struct dentry *hidden_dentry;
 
536
        struct dentry *h_dentry;
537
537
        umode_t mode;
538
538
 
539
 
        LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
540
 
                  DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
541
 
                  flags);
 
539
        LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, dtime %u\n",
 
540
                  AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
 
541
                  flags->dtime);
542
542
 
543
 
        hidden_dentry = au_h_dptr_i(dentry, bsrc);
544
 
        mode = hidden_dentry->d_inode->i_mode & S_IFMT;
 
543
        h_dentry = au_h_dptr_i(dentry, bsrc);
 
544
        mode = h_dentry->d_inode->i_mode & S_IFMT;
545
545
        if ((mode != S_IFCHR && mode != S_IFBLK)
546
546
            || capable(CAP_MKNOD))
547
 
                err = cpup_single(dentry, bdst, bsrc, len, flags);
 
547
                err = au_cpup_single(dentry, bdst, bsrc, len, flags);
548
548
        else {
549
 
                struct cpup_single_args args = {
550
 
                        .errp   = &err,
551
 
                        .dentry = dentry,
552
 
                        .bdst   = bdst,
553
 
                        .bsrc   = bsrc,
554
 
                        .len    = len,
555
 
                        .flags  = flags
 
549
                struct au_cpup_single_args args = {
 
550
                        .errp           = &err,
 
551
                        .dentry         = dentry,
 
552
                        .bdst           = bdst,
 
553
                        .bsrc           = bsrc,
 
554
                        .len            = len,
 
555
                        .flags          = flags
556
556
                };
557
 
                wkq_err = au_wkq_wait(call_cpup_single, &args, /*dlgt*/0);
 
557
                wkq_err = au_wkq_wait(au_call_cpup_single, &args, /*dlgt*/0);
558
558
                if (unlikely(wkq_err))
559
559
                        err = wkq_err;
560
560
        }
561
561
 
562
 
        TraceErr(err);
 
562
        AuTraceErr(err);
563
563
        return err;
564
564
}
565
565
 
566
566
/*
567
567
 * copyup the @dentry from the first active hidden branch to @bdst,
568
 
 * using cpup_single().
 
568
 * using au_cpup_single().
569
569
 */
570
 
int cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
571
 
                unsigned int flags)
 
570
int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
 
571
                   struct au_cpup_flags *flags)
572
572
{
573
573
        int err;
574
574
        struct inode *inode;
575
575
        aufs_bindex_t bsrc, bend;
576
576
 
577
 
        LKTRTrace("%.*s, bdst %d, len %Ld, flags 0x%x\n",
578
 
                  DLNPair(dentry), bdst, len, flags);
 
577
        LKTRTrace("%.*s, bdst %d, len %Ld, dtime %u\n",
 
578
                  AuDLNPair(dentry), bdst, len, flags->dtime);
579
579
        inode = dentry->d_inode;
580
580
        AuDebugOn(!S_ISDIR(inode->i_mode) && dbstart(dentry) < bdst);
581
581
 
585
585
                        break;
586
586
        AuDebugOn(!au_h_dptr_i(dentry, bsrc));
587
587
 
588
 
        err = lkup_neg(dentry, bdst);
 
588
        err = au_lkup_neg(dentry, bdst);
589
589
        //err = -1;
590
590
        if (!err) {
591
 
                err = cpup_single(dentry, bdst, bsrc, len, flags);
 
591
                err = au_cpup_single(dentry, bdst, bsrc, len, flags);
592
592
                if (!err)
593
593
                        return 0; /* success */
594
594
 
597
597
                set_dbstart(dentry, bsrc);
598
598
        }
599
599
 
600
 
        TraceErr(err);
 
600
        AuTraceErr(err);
601
601
        return err;
602
602
}
603
603
 
604
 
struct cpup_simple_args {
 
604
struct au_cpup_simple_args {
605
605
        int *errp;
606
606
        struct dentry *dentry;
607
607
        aufs_bindex_t bdst;
608
608
        loff_t len;
609
 
        unsigned int flags;
 
609
        struct au_cpup_flags *flags;
610
610
};
611
611
 
612
 
static void call_cpup_simple(void *args)
 
612
static void au_call_cpup_simple(void *args)
613
613
{
614
 
        struct cpup_simple_args *a = args;
615
 
        *a->errp = cpup_simple(a->dentry, a->bdst, a->len, a->flags);
 
614
        struct au_cpup_simple_args *a = args;
 
615
        *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
616
616
}
617
617
 
618
 
int sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
619
 
                    unsigned int flags)
 
618
int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
 
619
                       struct au_cpup_flags *flags)
620
620
{
621
621
        int err, do_sio, dlgt, wkq_err;
622
622
        struct dentry *parent;
623
 
        struct inode *hidden_dir, *dir;
 
623
        struct inode *h_dir, *dir;
624
624
 
625
 
        LKTRTrace("%.*s, b%d, len %Ld, flags 0x%x\n",
626
 
                  DLNPair(dentry), bdst, len, flags);
 
625
        LKTRTrace("%.*s, b%d, len %Ld, dtime %u\n",
 
626
                  AuDLNPair(dentry), bdst, len, flags->dtime);
627
627
 
628
628
        parent = dget_parent(dentry);
629
629
        dir = parent->d_inode;
630
 
        hidden_dir = au_h_iptr_i(dir, bdst);
631
 
        dlgt = need_dlgt(dir->i_sb);
632
 
        do_sio = au_test_perm(hidden_dir, MAY_EXEC | MAY_WRITE, dlgt);
 
630
        h_dir = au_h_iptr_i(dir, bdst);
 
631
        dlgt = au_need_dlgt(dir->i_sb);
 
632
        do_sio = au_test_perm(h_dir, MAY_EXEC | MAY_WRITE, dlgt);
633
633
        if (!do_sio) {
634
634
                umode_t mode = dentry->d_inode->i_mode & S_IFMT;
635
635
                do_sio = ((mode == S_IFCHR || mode == S_IFBLK)
636
636
                          && !capable(CAP_MKNOD));
637
637
        }
638
638
        if (!do_sio)
639
 
                err = cpup_simple(dentry, bdst, len, flags);
640
 
        else {
641
 
                struct cpup_simple_args args = {
 
639
                err = au_cpup_simple(dentry, bdst, len, flags);
 
640
        else {
 
641
                struct au_cpup_simple_args args = {
 
642
                        .errp           = &err,
 
643
                        .dentry         = dentry,
 
644
                        .bdst           = bdst,
 
645
                        .len            = len,
 
646
                        .flags          = flags
 
647
                };
 
648
                wkq_err = au_wkq_wait(au_call_cpup_simple, &args, /*dlgt*/0);
 
649
                if (unlikely(wkq_err))
 
650
                        err = wkq_err;
 
651
        }
 
652
 
 
653
        dput(parent);
 
654
        AuTraceErr(err);
 
655
        return err;
 
656
}
 
657
 
 
658
/* ---------------------------------------------------------------------- */
 
659
 
 
660
/*
 
661
 * copyup the deleted file for writing.
 
662
 */
 
663
int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
 
664
               struct file *file)
 
665
{
 
666
        int err;
 
667
        struct dentry *parent, *h_parent, *wh_dentry, *h_dentry_bdst,
 
668
                *h_dentry_bstart;
 
669
        struct inode *h_dir;
 
670
        struct super_block *sb;
 
671
        struct au_dtime dt;
 
672
        struct aufs_dinfo *dinfo;
 
673
        aufs_bindex_t bstart;
 
674
        struct vfsub_args vargs;
 
675
        struct aufs_ndx ndx = {
 
676
                .nd     = NULL,
 
677
                //.br   = NULL
 
678
        };
 
679
        struct au_cpup_flags cflags = {
 
680
                .dtime = 0
 
681
        };
 
682
 
 
683
        LKTRTrace("%.*s, bdst %d, len %Lu\n", AuDLNPair(dentry), bdst, len);
 
684
        AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
 
685
                  || (file && !(file->f_mode & FMODE_WRITE)));
 
686
        DiMustWriteLock(dentry);
 
687
 
 
688
        parent = dget_parent(dentry);
 
689
        IiMustAnyLock(parent->d_inode);
 
690
        h_parent = au_h_dptr_i(parent, bdst);
 
691
        AuDebugOn(!h_parent);
 
692
        h_dir = h_parent->d_inode;
 
693
        AuDebugOn(!h_dir);
 
694
 
 
695
        sb = parent->d_sb;
 
696
        ndx.nfsmnt = au_nfsmnt(sb, bdst);
 
697
        ndx.dlgt = au_need_dlgt(sb);
 
698
        wh_dentry = lkup_whtmp(h_parent, &dentry->d_name, &ndx);
 
699
        //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
 
700
        err = PTR_ERR(wh_dentry);
 
701
        if (IS_ERR(wh_dentry))
 
702
                goto out;
 
703
 
 
704
        au_dtime_store(&dt, parent, bdst, h_parent);
 
705
        dinfo = dtodi(dentry);
 
706
        bstart = dinfo->di_bstart;
 
707
        h_dentry_bdst = dinfo->di_hdentry[0 + bdst].hd_dentry;
 
708
        dinfo->di_bstart = bdst;
 
709
        dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry;
 
710
        h_dentry_bstart = dinfo->di_hdentry[0 + bstart].hd_dentry;
 
711
        if (file)
 
712
                dinfo->di_hdentry[0 + bstart].hd_dentry
 
713
                        = au_h_fptr(file)->f_dentry;
 
714
        err = au_cpup_single(dentry, bdst, bstart, len, &cflags);
 
715
        //if (LktrCond) err = -1;
 
716
        if (!err && file) {
 
717
                err = au_reopen_nondir(file);
 
718
                //err = -1;
 
719
                dinfo->di_hdentry[0 + bstart].hd_dentry = h_dentry_bstart;
 
720
        }
 
721
        dinfo->di_hdentry[0 + bdst].hd_dentry = h_dentry_bdst;
 
722
        dinfo->di_bstart = bstart;
 
723
        if (unlikely(err))
 
724
                goto out_wh;
 
725
 
 
726
        AuDebugOn(!d_unhashed(dentry));
 
727
        /* dget first to force sillyrename on nfs */
 
728
        dget(wh_dentry);
 
729
        vfsub_args_init(&vargs, NULL, ndx.dlgt, 0);
 
730
        err = vfsub_unlink(h_dir, wh_dentry, &vargs);
 
731
        //if (LktrCond) err = -1;
 
732
        if (unlikely(err)) {
 
733
                AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
 
734
                        AuDLNPair(wh_dentry), err);
 
735
                err = -EIO;
 
736
        }
 
737
        au_dtime_revert(&dt);
 
738
        set_hi_wh(dentry->d_inode, bdst, wh_dentry);
 
739
 
 
740
 out_wh:
 
741
        dput(wh_dentry);
 
742
 out:
 
743
        dput(parent);
 
744
        AuTraceErr(err);
 
745
        //au_debug_off();
 
746
        return err;
 
747
}
 
748
 
 
749
struct au_cpup_wh_args {
 
750
        int *errp;
 
751
        struct dentry *dentry;
 
752
        aufs_bindex_t bdst;
 
753
        loff_t len;
 
754
        struct file *file;
 
755
};
 
756
 
 
757
static void au_call_cpup_wh(void *args)
 
758
{
 
759
        struct au_cpup_wh_args *a = args;
 
760
        *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
 
761
}
 
762
 
 
763
int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
 
764
                   struct file *file)
 
765
{
 
766
        int err, wkq_err;
 
767
        struct dentry *parent;
 
768
        struct inode *dir, *h_dir;
 
769
 
 
770
        AuTraceEnter();
 
771
        parent = dget_parent(dentry);
 
772
        dir = parent->d_inode;
 
773
        IiMustAnyLock(dir);
 
774
        h_dir = au_h_iptr_i(dir, bdst);
 
775
 
 
776
        if (!au_test_perm(h_dir, MAY_EXEC | MAY_WRITE,
 
777
                          au_need_dlgt(dentry->d_sb)))
 
778
                err = au_cpup_wh(dentry, bdst, len, file);
 
779
        else {
 
780
                struct au_cpup_wh_args args = {
642
781
                        .errp   = &err,
643
782
                        .dentry = dentry,
644
783
                        .bdst   = bdst,
645
784
                        .len    = len,
646
 
                        .flags  = flags
 
785
                        .file   = file
647
786
                };
648
 
                wkq_err = au_wkq_wait(call_cpup_simple, &args, /*dlgt*/0);
 
787
                wkq_err = au_wkq_wait(au_call_cpup_wh, &args, /*dlgt*/0);
649
788
                if (unlikely(wkq_err))
650
789
                        err = wkq_err;
651
790
        }
652
 
 
653
791
        dput(parent);
654
 
        TraceErr(err);
 
792
 
 
793
        AuTraceErr(err);
655
794
        return err;
656
795
}
657
796
 
658
 
//todo: dcsub
 
797
/* ---------------------------------------------------------------------- */
 
798
 
 
799
/*
 
800
 * generic routine for both of copy-up and copy-down.
 
801
 * Although I've tried building a path by dcsub, I gave up this approach.
 
802
 * Since the ancestor directory may be moved/renamed during cpup.
 
803
 */
659
804
/* cf. revalidate function in file.c */
660
 
int cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked)
 
805
int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked,
 
806
               int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
 
807
                         struct dentry *h_parent, void *arg),
 
808
               void *arg)
661
809
{
662
810
        int err;
663
811
        struct super_block *sb;
664
 
        struct dentry *d, *parent, *hidden_parent;
 
812
        struct dentry *d, *parent, *h_parent, *gparent, *real_parent;
665
813
        unsigned int udba;
666
814
 
667
815
        LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
668
 
                  DLNPair(dentry), bdst, parent_ino(dentry), locked);
 
816
                  AuDLNPair(dentry), bdst, parent_ino(dentry), locked);
669
817
        sb = dentry->d_sb;
670
 
        AuDebugOn(test_ro(sb, bdst, NULL));
671
 
        parent = dentry->d_parent;
 
818
        AuDebugOn(au_test_ro(sb, bdst, NULL));
 
819
        err = 0;
 
820
        parent = dget_parent(dentry);
672
821
        IiMustWriteLock(parent->d_inode);
673
822
        if (unlikely(IS_ROOT(parent)))
674
 
                return 0;
 
823
                goto out;
675
824
        if (locked) {
676
825
                DiMustAnyLock(locked);
677
826
                IiMustAnyLock(locked->d_inode);
678
827
        }
679
828
 
680
829
        /* slow loop, keep it simple and stupid */
681
 
        err = 0;
682
 
        udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
 
830
        real_parent = parent;
 
831
        udba = au_flag_test_udba_inotify(sb);
683
832
        while (1) {
684
 
                parent = dentry->d_parent; // dget_parent()
685
 
                hidden_parent = au_h_dptr_i(parent, bdst);
686
 
                if (hidden_parent)
687
 
                        return 0; /* success */
 
833
                dput(parent);
 
834
                parent = dget_parent(dentry);
 
835
                h_parent = au_h_dptr_i(parent, bdst);
 
836
                if (h_parent)
 
837
                        goto out; /* success */
688
838
 
689
839
                /* find top dir which is needed to cpup */
690
840
                do {
691
841
                        d = parent;
692
 
                        parent = d->d_parent; // dget_parent()
693
 
                        if (parent != locked)
694
 
                                di_read_lock_parent3(parent, !AUFS_I_RLOCK);
695
 
                        hidden_parent = au_h_dptr_i(parent, bdst);
696
 
                        if (parent != locked)
697
 
                                di_read_unlock(parent, !AUFS_I_RLOCK);
698
 
                } while (!hidden_parent);
 
842
                        dput(parent);
 
843
                        parent = dget_parent(d);
 
844
                        if (parent != locked) {
 
845
                                di_read_lock_parent3(parent, !AuLock_IR);
 
846
                                h_parent = au_h_dptr_i(parent, bdst);
 
847
                                di_read_unlock(parent, !AuLock_IR);
 
848
                        } else
 
849
                                h_parent = au_h_dptr_i(parent, bdst);
 
850
                } while (!h_parent);
699
851
 
700
 
                if (d != dentry->d_parent)
 
852
                if (d != real_parent)
701
853
                        di_write_lock_child3(d);
702
854
 
703
855
                /* somebody else might create while we were sleeping */
704
856
                if (!au_h_dptr_i(d, bdst) || !au_h_dptr_i(d, bdst)->d_inode) {
705
 
                        struct inode *h_dir = hidden_parent->d_inode,
706
 
                                *dir = parent->d_inode,
707
 
                                *h_gdir, *gdir;
 
857
                        struct inode *h_dir = h_parent->d_inode,
 
858
                                *dir = parent->d_inode;
708
859
 
709
860
                        if (au_h_dptr_i(d, bdst))
710
861
                                au_update_dbstart(d);
711
862
                        //AuDebugOn(dbstart(d) <= bdst);
712
863
                        if (parent != locked)
713
 
                                di_read_lock_parent3(parent, AUFS_I_RLOCK);
714
 
                        h_gdir = gdir = NULL;
 
864
                                di_read_lock_parent3(parent, AuLock_IR);
 
865
                        gparent = NULL;
715
866
                        if (unlikely(udba && !IS_ROOT(parent))) {
716
 
                                gdir = parent->d_parent->d_inode;
717
 
                                h_gdir = hidden_parent->d_parent->d_inode;
718
 
                                hgdir_lock(h_gdir, gdir, bdst);
 
867
                                gparent = dget_parent(parent);
 
868
                                if (gparent != locked)
 
869
                                        ii_read_lock_parent4(gparent->d_inode);
 
870
                                else {
 
871
                                        dput(gparent);
 
872
                                        gparent = NULL;
 
873
                                }
719
874
                        }
720
875
                        hdir_lock(h_dir, dir, bdst);
721
 
                        err = sio_cpup_simple(d, bdst, -1,
722
 
                                              au_flags_cpup(CPUP_DTIME,
723
 
                                                            parent));
 
876
                        err = cp(d, bdst, h_parent, arg);
724
877
                        //if (LktrCond) err = -1;
725
878
                        hdir_unlock(h_dir, dir, bdst);
726
 
                        if (unlikely(gdir))
727
 
                                hdir_unlock(h_gdir, gdir, bdst);
 
879
                        if (unlikely(gparent)) {
 
880
                                ii_read_unlock(gparent->d_inode);
 
881
                                dput(gparent);
 
882
                        }
728
883
                        if (parent != locked)
729
 
                                di_read_unlock(parent, AUFS_I_RLOCK);
 
884
                                di_read_unlock(parent, AuLock_IR);
730
885
                }
731
886
 
732
 
                if (d != dentry->d_parent)
 
887
                if (d != real_parent)
733
888
                        di_write_unlock(d);
734
889
                if (unlikely(err))
735
890
                        break;
736
891
        }
737
892
 
738
 
// out:
739
 
        TraceErr(err);
740
 
        return err;
741
 
}
742
 
 
743
 
int test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
744
 
                       struct dentry *locked)
 
893
 out:
 
894
        dput(parent);
 
895
        AuTraceErr(err);
 
896
        return err;
 
897
}
 
898
 
 
899
static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
 
900
                       struct dentry *h_parent, void *arg)
 
901
{
 
902
        int err;
 
903
        struct au_cpup_flags cflags = {
 
904
                .dtime = 1
 
905
        };
 
906
 
 
907
        err = au_sio_cpup_simple(dentry, bdst, -1, &cflags);
 
908
 
 
909
        AuTraceErr(err);
 
910
        return err;
 
911
}
 
912
 
 
913
int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
 
914
                 struct dentry *locked)
 
915
{
 
916
        int err;
 
917
 
 
918
        err = au_cp_dirs(dentry, bdst, locked, au_cpup_dir, NULL);
 
919
 
 
920
        AuTraceErr(err);
 
921
        return err;
 
922
}
 
923
 
 
924
int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
 
925
                          struct dentry *locked)
745
926
{
746
927
        int err;
747
928
        struct dentry *parent;
748
929
        struct inode *dir;
749
930
 
750
 
        parent = dentry->d_parent;
 
931
        parent = dget_parent(dentry);
751
932
        dir = parent->d_inode;
752
933
        LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
753
 
                  DLNPair(dentry), bdst, dir->i_ino, locked);
 
934
                  AuDLNPair(dentry), bdst, dir->i_ino, locked);
754
935
        DiMustReadLock(parent);
755
936
        IiMustReadLock(dir);
756
937
 
 
938
        err = 0;
757
939
        if (au_h_iptr_i(dir, bdst))
758
 
                return 0;
 
940
                goto out;
759
941
 
760
 
        err = 0;
761
 
        di_read_unlock(parent, AUFS_I_RLOCK);
 
942
        di_read_unlock(parent, AuLock_IR);
762
943
        di_write_lock_parent(parent);
763
 
        if (au_h_iptr_i(dir, bdst))
764
 
                goto out;
765
 
 
766
 
        err = cpup_dirs(dentry, bdst, locked);
 
944
        /* someone else might change our inode while we were sleeping */
 
945
        if (unlikely(!au_h_iptr_i(dir, bdst)))
 
946
                err = au_cpup_dirs(dentry, bdst, locked);
 
947
        di_downgrade_lock(parent, AuLock_IR);
767
948
 
768
949
 out:
769
 
        di_downgrade_lock(parent, AUFS_I_RLOCK);
770
 
        TraceErr(err);
 
950
        dput(parent);
 
951
        AuTraceErr(err);
771
952
        return err;
772
953
}