~ubuntu-branches/ubuntu/raring/aufs/raring

« back to all changes in this revision

Viewing changes to fs/aufs25/cpup.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2008-05-06 18:35:50 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080506183550-0b6c974kkgc46oeh
Tags: 0+20080506-1
* New upstream release, supports Kernel 2.6.25 (Closes: #479717)
* Fix building with older Kernels (Closes: #475042)
* Update the patches 01, 04 and 07 to also patch fs/aufs25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2005-2008 Junjiro 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
 * copy-up functions, see wbr_policy.c for copy-down
 
21
 *
 
22
 * $Id: cpup.c,v 1.4 2008/05/04 23:51:40 sfjro Exp $
 
23
 */
 
24
 
 
25
#include <linux/fs_stack.h>
 
26
#include <linux/uaccess.h>
 
27
#include "aufs.h"
 
28
 
 
29
/* violent cpup_attr_*() functions don't care inode lock */
 
30
void au_cpup_attr_timesizes(struct inode *inode)
 
31
{
 
32
        struct inode *h_inode;
 
33
 
 
34
        LKTRTrace("i%lu\n", inode->i_ino);
 
35
        //IMustLock(inode);
 
36
        h_inode = au_h_iptr(inode, au_ibstart(inode));
 
37
        AuDebugOn(!h_inode);
 
38
        //IMustLock(!h_inode);
 
39
 
 
40
        fsstack_copy_attr_times(inode, h_inode);
 
41
        spin_lock(&inode->i_lock);
 
42
        fsstack_copy_inode_size(inode, h_inode);
 
43
        spin_unlock(&inode->i_lock);
 
44
}
 
45
 
 
46
void au_cpup_attr_nlink(struct inode *inode)
 
47
{
 
48
        struct inode *h_inode;
 
49
 
 
50
        LKTRTrace("i%lu\n", inode->i_ino);
 
51
        //IMustLock(inode);
 
52
        AuDebugOn(!inode->i_mode);
 
53
 
 
54
        h_inode = au_h_iptr(inode, au_ibstart(inode));
 
55
        inode->i_nlink = h_inode->i_nlink;
 
56
 
 
57
        /*
 
58
         * fewer nlink makes find(1) noisy, but larger nlink doesn't.
 
59
         * it may includes whplink directory.
 
60
         */
 
61
        if (unlikely(S_ISDIR(h_inode->i_mode))) {
 
62
                aufs_bindex_t bindex, bend;
 
63
                bend = au_ibend(inode);
 
64
                for (bindex = au_ibstart(inode) + 1; bindex <= bend; bindex++) {
 
65
                        h_inode = au_h_iptr(inode, bindex);
 
66
                        if (h_inode)
 
67
                                au_add_nlink(inode, h_inode);
 
68
                }
 
69
        }
 
70
}
 
71
 
 
72
void au_cpup_attr_changeable(struct inode *inode)
 
73
{
 
74
        struct inode *h_inode;
 
75
 
 
76
        LKTRTrace("i%lu\n", inode->i_ino);
 
77
        //IMustLock(inode);
 
78
        h_inode = au_h_iptr(inode, au_ibstart(inode));
 
79
        AuDebugOn(!h_inode);
 
80
 
 
81
        inode->i_mode = h_inode->i_mode;
 
82
        inode->i_uid = h_inode->i_uid;
 
83
        inode->i_gid = h_inode->i_gid;
 
84
        au_cpup_attr_timesizes(inode);
 
85
 
 
86
        //??
 
87
        inode->i_flags = h_inode->i_flags;
 
88
}
 
89
 
 
90
void au_cpup_igen(struct inode *inode, struct inode *h_inode)
 
91
{
 
92
        inode->i_generation = h_inode->i_generation;
 
93
        au_ii(inode)->ii_hsb1 = h_inode->i_sb;
 
94
}
 
95
 
 
96
void au_cpup_attr_all(struct inode *inode)
 
97
{
 
98
        struct inode *h_inode;
 
99
 
 
100
        LKTRTrace("i%lu\n", inode->i_ino);
 
101
        //IMustLock(inode);
 
102
        h_inode = au_h_iptr(inode, au_ibstart(inode));
 
103
        AuDebugOn(!h_inode);
 
104
 
 
105
        au_cpup_attr_changeable(inode);
 
106
        if (inode->i_nlink > 0)
 
107
                au_cpup_attr_nlink(inode);
 
108
 
 
109
        switch (inode->i_mode & S_IFMT) {
 
110
        case S_IFBLK:
 
111
        case S_IFCHR:
 
112
                inode->i_rdev = au_h_rdev(h_inode, /*h_mnt*/NULL,
 
113
                                          /*h_dentry*/NULL);
 
114
        }
 
115
        inode->i_blkbits = h_inode->i_blkbits;
 
116
        au_cpup_igen(inode, h_inode);
 
117
}
 
118
 
 
119
/* ---------------------------------------------------------------------- */
 
120
 
 
121
/* Note: dt_dentry and dt_hidden_dentry are not dget/dput-ed */
 
122
 
 
123
/* keep the timestamps of the parent dir when cpup */
 
124
void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
 
125
                    struct dentry *h_dentry, struct au_hinode *hdir)
 
126
{
 
127
        struct inode *inode;
 
128
 
 
129
        LKTRTrace("%.*s, hdir %d\n", AuDLNPair(dentry), !!hdir);
 
130
        AuDebugOn(!dentry || !h_dentry || !h_dentry->d_inode);
 
131
 
 
132
        dt->dt_dentry = dentry;
 
133
        dt->dt_h_dentry = h_dentry;
 
134
        dt->dt_hdir = hdir;
 
135
        inode = h_dentry->d_inode;
 
136
        dt->dt_atime = inode->i_atime;
 
137
        dt->dt_mtime = inode->i_mtime;
 
138
        //smp_mb();
 
139
}
 
140
 
 
141
void au_dtime_revert(struct au_dtime *dt)
 
142
{
 
143
        struct iattr attr;
 
144
        int err;
 
145
        struct au_hin_ignore ign;
 
146
        struct vfsub_args vargs;
 
147
 
 
148
        LKTRTrace("%.*s\n", AuDLNPair(dt->dt_dentry));
 
149
 
 
150
        attr.ia_atime = dt->dt_atime;
 
151
        attr.ia_mtime = dt->dt_mtime;
 
152
        attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
 
153
                | ATTR_ATIME | ATTR_ATIME_SET;
 
154
 
 
155
        vfsub_args_init(&vargs, &ign,
 
156
                        au_opt_test_dlgt(au_mntflags(dt->dt_dentry->d_sb)), 0);
 
157
        if (unlikely(dt->dt_hdir))
 
158
                vfsub_ign_hinode(&vargs, IN_ATTRIB, dt->dt_hdir);
 
159
        err = vfsub_notify_change(dt->dt_h_dentry, &attr, &vargs);
 
160
        if (unlikely(err))
 
161
                AuWarn("restoring timestamps failed(%d). ignored\n", err);
 
162
}
 
163
 
 
164
/* ---------------------------------------------------------------------- */
 
165
 
 
166
static noinline_for_stack int
 
167
cpup_iattr(struct dentry *h_dst, struct dentry *h_src, int dlgt)
 
168
{
 
169
        int err, sbits;
 
170
        struct iattr ia;
 
171
        struct inode *h_isrc, *h_idst;
 
172
        struct vfsub_args vargs;
 
173
 
 
174
        LKTRTrace("%.*s\n", AuDLNPair(h_dst));
 
175
        h_idst = h_dst->d_inode;
 
176
        //IMustLock(h_idst);
 
177
        h_isrc = h_src->d_inode;
 
178
        //IMustLock(h_isrc);
 
179
 
 
180
        ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
 
181
                | ATTR_ATIME | ATTR_MTIME
 
182
                | ATTR_ATIME_SET | ATTR_MTIME_SET;
 
183
        ia.ia_mode = h_isrc->i_mode;
 
184
        ia.ia_uid = h_isrc->i_uid;
 
185
        ia.ia_gid = h_isrc->i_gid;
 
186
        ia.ia_atime = h_isrc->i_atime;
 
187
        ia.ia_mtime = h_isrc->i_mtime;
 
188
        sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
 
189
 
 
190
        vfsub_args_init(&vargs, NULL, dlgt, /*force_unlink*/0);
 
191
        err = vfsub_notify_change(h_dst, &ia, &vargs);
 
192
        //if (LktrCond) err = -1;
 
193
 
 
194
        /* is this nfs only? */
 
195
        if (!err && sbits && au_test_nfs(h_dst->d_sb)) {
 
196
                ia.ia_valid = ATTR_FORCE | ATTR_MODE;
 
197
                ia.ia_mode = h_isrc->i_mode;
 
198
                err = vfsub_notify_change(h_dst, &ia, &vargs);
 
199
        }
 
200
 
 
201
        if (!err)
 
202
                h_idst->i_flags = h_isrc->i_flags; //??
 
203
 
 
204
        AuTraceErr(err);
 
205
        return err;
 
206
}
 
207
 
 
208
/*
 
209
 * to support a sparse file which is opened with O_APPEND,
 
210
 * we need to close the file.
 
211
 */
 
212
static noinline_for_stack int
 
213
cpup_regular(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
 
214
             loff_t len)
 
215
{
 
216
        int err, i;
 
217
        struct super_block *sb;
 
218
        struct inode *h_inode;
 
219
        enum { SRC, DST };
 
220
        struct {
 
221
                aufs_bindex_t bindex;
 
222
                unsigned int flags;
 
223
                struct dentry *dentry;
 
224
                struct file *file;
 
225
                void *label, *label_file;
 
226
        } *h, hidden[] = {
 
227
                {
 
228
                        .bindex = bsrc,
 
229
                        .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
 
230
                        .file = NULL,
 
231
                        .label = &&out,
 
232
                        .label_file = &&out_src_file
 
233
                },
 
234
                {
 
235
                        .bindex = bdst,
 
236
                        .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
 
237
                        .file = NULL,
 
238
                        .label = &&out_src_file,
 
239
                        .label_file = &&out_dst_file
 
240
                }
 
241
        };
 
242
 
 
243
        LKTRTrace("dentry %.*s, bdst %d, bsrc %d, len %lld\n",
 
244
                  AuDLNPair(dentry), bdst, bsrc, len);
 
245
        AuDebugOn(bsrc <= bdst);
 
246
        AuDebugOn(!len);
 
247
        sb = dentry->d_sb;
 
248
        AuDebugOn(au_test_ro(sb, bdst, dentry->d_inode));
 
249
        /* bsrc branch can be ro/rw. */
 
250
 
 
251
        h = hidden;
 
252
        for (i = 0; i < 2; i++, h++) {
 
253
                h->dentry = au_h_dptr(dentry, h->bindex);
 
254
                AuDebugOn(!h->dentry);
 
255
                h_inode = h->dentry->d_inode;
 
256
                AuDebugOn(!h_inode || !S_ISREG(h_inode->i_mode));
 
257
                h->file = au_h_open(dentry, h->bindex, h->flags, /*file*/NULL);
 
258
                //if (LktrCond)
 
259
                //{fput(h->file);au_sbr_put(sb, h->bindex);h->file=ERR_PTR(-1);}
 
260
                err = PTR_ERR(h->file);
 
261
                if (IS_ERR(h->file))
 
262
                        goto *h->label;
 
263
                err = -EINVAL;
 
264
                if (unlikely(!h->file->f_op))
 
265
                        goto *h->label_file;
 
266
        }
 
267
 
 
268
        /* stop updating while we copyup */
 
269
        IMustLock(hidden[SRC].dentry->d_inode);
 
270
        err = au_copy_file(hidden[DST].file, hidden[SRC].file, len, sb);
 
271
 
 
272
 out_dst_file:
 
273
        fput(hidden[DST].file);
 
274
        au_sbr_put(sb, hidden[DST].bindex);
 
275
 out_src_file:
 
276
        fput(hidden[SRC].file);
 
277
        au_sbr_put(sb, hidden[SRC].bindex);
 
278
 out:
 
279
        AuTraceErr(err);
 
280
        return err;
 
281
}
 
282
 
 
283
static noinline_for_stack int
 
284
au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
 
285
                   aufs_bindex_t bsrc, loff_t len, struct inode *h_inode,
 
286
                   struct inode *h_dir, struct dentry *h_dst, int dlgt)
 
287
{
 
288
        int err, rerr;
 
289
        loff_t l;
 
290
        struct vfsub_args vargs;
 
291
 
 
292
        AuTraceEnter();
 
293
 
 
294
        err = 0;
 
295
        l = i_size_read(h_inode);
 
296
        if (len == -1 || l < len)
 
297
                len = l;
 
298
        if (len)
 
299
                err = cpup_regular(dentry, bdst, bsrc, len);
 
300
                //if (LktrCond) err = -1;
 
301
        if (!err)
 
302
                goto out; /* success */
 
303
 
 
304
        vfsub_args_init(&vargs, NULL, dlgt, 0);
 
305
        rerr = vfsub_unlink(h_dir, h_dst, &vargs);
 
306
        if (rerr) {
 
307
                AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
 
308
                        AuDLNPair(h_dst), err, rerr);
 
309
                err = -EIO;
 
310
        }
 
311
 
 
312
 out:
 
313
        AuTraceErr(err);
 
314
        return err;
 
315
}
 
316
 
 
317
static noinline_for_stack int
 
318
au_do_cpup_symlink(struct dentry *h_dst, struct dentry *h_src,
 
319
                   struct inode *h_dir, umode_t mode, int dlgt)
 
320
{
 
321
        int err, symlen;
 
322
        char *sym;
 
323
        mm_segment_t old_fs;
 
324
 
 
325
        AuTraceEnter();
 
326
 
 
327
        err = -ENOMEM;
 
328
        sym = __getname();
 
329
        //if (LktrCond) {__putname(sym); sym = NULL;}
 
330
        if (unlikely(!sym))
 
331
                goto out;
 
332
 
 
333
        old_fs = get_fs();
 
334
        set_fs(KERNEL_DS);
 
335
        symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
 
336
                                                PATH_MAX);
 
337
        err = symlen;
 
338
        //if (LktrCond) err = symlen = -1;
 
339
        set_fs(old_fs);
 
340
 
 
341
        if (symlen > 0) {
 
342
                sym[symlen] = 0;
 
343
                err = vfsub_symlink(h_dir, h_dst, sym, mode, dlgt);
 
344
                //if (LktrCond)
 
345
                //{vfs_unlink(h_dir, h_dst); err = -1;}
 
346
        }
 
347
        __putname(sym);
 
348
 
 
349
 out:
 
350
        AuTraceErr(err);
 
351
        return err;
 
352
}
 
353
 
 
354
/* return with hidden dst inode is locked */
 
355
static noinline_for_stack int
 
356
cpup_entry(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
 
357
           loff_t len, unsigned int flags, int dlgt)
 
358
{
 
359
        int err, isdir, hinotify;
 
360
        struct dentry *h_src, *h_dst, *h_parent, *parent;
 
361
        struct inode *h_inode, *h_dir;
 
362
        struct au_dtime dt;
 
363
        umode_t mode;
 
364
        struct super_block *sb;
 
365
        struct au_hinode *hgdir;
 
366
        const int do_dt = au_ftest_cpup(flags, DTIME);
 
367
        unsigned int mnt_flags;
 
368
 
 
369
        LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, dtime %u\n",
 
370
                  AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
 
371
                  do_dt);
 
372
        sb = dentry->d_sb;
 
373
        AuDebugOn(bdst >= bsrc || au_test_ro(sb, bdst, NULL));
 
374
        /* bsrc branch can be ro/rw. */
 
375
 
 
376
        h_src = au_h_dptr(dentry, bsrc);
 
377
        AuDebugOn(!h_src);
 
378
        h_inode = h_src->d_inode;
 
379
        AuDebugOn(!h_inode);
 
380
 
 
381
        /* stop referencing while we are creating */
 
382
        parent = dget_parent(dentry);
 
383
        h_dst = au_h_dptr(dentry, bdst);
 
384
        AuDebugOn(h_dst && h_dst->d_inode);
 
385
        h_parent = h_dst->d_parent; /* dir inode is locked */
 
386
        h_dir = h_parent->d_inode;
 
387
        IMustLock(h_dir);
 
388
 
 
389
        mnt_flags = au_mntflags(sb);
 
390
        hinotify = !!au_opt_test(mnt_flags, UDBA_INOTIFY);
 
391
        if (do_dt) {
 
392
                hgdir = NULL;
 
393
                if (unlikely(hinotify && !IS_ROOT(parent))) {
 
394
                        struct dentry *gparent;
 
395
                        gparent = dget_parent(parent);
 
396
                        hgdir = au_hi(gparent->d_inode, bdst);
 
397
                        dput(gparent);
 
398
                }
 
399
                au_dtime_store(&dt, parent, h_parent, hgdir);
 
400
        }
 
401
 
 
402
        isdir = 0;
 
403
        mode = h_inode->i_mode;
 
404
        switch (mode & S_IFMT) {
 
405
        case S_IFREG:
 
406
                /* stop updating while we are referencing */
 
407
                IMustLock(h_inode);
 
408
                err = au_h_create(h_dir, h_dst, mode | S_IWUSR, dlgt, NULL,
 
409
                                  au_nfsmnt(sb, bdst));
 
410
                //if (LktrCond) {vfs_unlink(h_dir, h_dst); err = -1;}
 
411
                if (!err)
 
412
                        err = au_do_cpup_regular(dentry, bdst, bsrc, len,
 
413
                                                 h_inode, h_dir, h_dst, dlgt);
 
414
                break;
 
415
        case S_IFDIR:
 
416
                isdir = 1;
 
417
                err = vfsub_mkdir(h_dir, h_dst, mode, dlgt);
 
418
                //if (LktrCond) {vfs_rmdir(h_dir, h_dst); err = -1;}
 
419
                if (!err) {
 
420
                        /* setattr case: dir is not locked */
 
421
                        if (0 && au_ibstart(parent->d_inode) == bdst)
 
422
                                au_cpup_attr_nlink(parent->d_inode);
 
423
                        au_cpup_attr_nlink(dentry->d_inode);
 
424
                }
 
425
                break;
 
426
        case S_IFLNK:
 
427
                err = au_do_cpup_symlink(h_dst, h_src, h_dir, mode, dlgt);
 
428
                break;
 
429
        case S_IFCHR:
 
430
        case S_IFBLK:
 
431
                AuDebugOn(!capable(CAP_MKNOD));
 
432
                /*FALLTHROUGH*/
 
433
        case S_IFIFO:
 
434
        case S_IFSOCK:
 
435
                err = vfsub_mknod(h_dir, h_dst, mode,
 
436
                                  au_h_rdev(h_inode, /*h_mnt*/NULL, h_src),
 
437
                                  dlgt);
 
438
                //if (LktrCond) {vfs_unlink(h_dir, h_dst); err = -1;}
 
439
                break;
 
440
        default:
 
441
                AuIOErr("Unknown inode type 0%o\n", mode);
 
442
                err = -EIO;
 
443
        }
 
444
 
 
445
        //todo: should it be always?
 
446
        if (unlikely(hinotify
 
447
                     && !isdir
 
448
                     && au_opt_test(mnt_flags, XINO)
 
449
                     && h_inode->i_nlink == 1
 
450
                     && bdst < bsrc))
 
451
                au_xino_write0(sb, bsrc, h_inode->i_ino, /*ino*/0);
 
452
                /* ignore this error */
 
453
 
 
454
        if (do_dt)
 
455
                au_dtime_revert(&dt);
 
456
        dput(parent);
 
457
        AuTraceErr(err);
 
458
        return err;
 
459
}
 
460
 
 
461
/*
 
462
 * copyup the @dentry from @bsrc to @bdst.
 
463
 * the caller must set the both of hidden dentries.
 
464
 * @len is for truncating when it is -1 copyup the entire file.
 
465
 */
 
466
int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
 
467
                   aufs_bindex_t bsrc, loff_t len, unsigned int flags)
 
468
{
 
469
        int err, rerr, isdir, dlgt, plink;
 
470
        struct dentry *h_src, *h_dst, *parent, *h_parent;
 
471
        struct inode *dst_inode, *h_dir, *inode;
 
472
        struct super_block *sb;
 
473
        aufs_bindex_t old_ibstart;
 
474
        struct au_dtime dt;
 
475
        struct vfsub_args vargs;
 
476
        struct au_hinode *hgdir;
 
477
        unsigned int mnt_flags;
 
478
 
 
479
        LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
 
480
                  AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
 
481
                  flags);
 
482
        sb = dentry->d_sb;
 
483
        AuDebugOn(bsrc <= bdst);
 
484
        h_dst = au_h_dptr(dentry, bdst);
 
485
        AuDebugOn(!h_dst || h_dst->d_inode);
 
486
        h_parent = h_dst->d_parent; /* dir inode is locked */
 
487
        h_dir = h_parent->d_inode;
 
488
        IMustLock(h_dir);
 
489
        h_src = au_h_dptr(dentry, bsrc);
 
490
        AuDebugOn(!h_src || !h_src->d_inode);
 
491
        inode = dentry->d_inode;
 
492
        IiMustWriteLock(inode);
 
493
        parent = dget_parent(dentry);
 
494
 
 
495
        mnt_flags = au_mntflags(sb);
 
496
        dlgt = !!au_opt_test_dlgt(mnt_flags);
 
497
        plink = !!au_opt_test(mnt_flags, PLINK);
 
498
        dst_inode = au_h_iptr(inode, bdst);
 
499
        if (unlikely(dst_inode)) {
 
500
                if (unlikely(!plink)) {
 
501
                        err = -EIO;
 
502
                        AuIOErr("i%lu exists on a upper branch "
 
503
                                "but plink is disabled\n", inode->i_ino);
 
504
                        goto out;
 
505
                }
 
506
 
 
507
                if (dst_inode->i_nlink) {
 
508
                        h_src = au_plink_lkup(sb, bdst, inode);
 
509
                        err = PTR_ERR(h_src);
 
510
                        if (IS_ERR(h_src))
 
511
                                goto out;
 
512
                        AuDebugOn(!h_src->d_inode);
 
513
                        err = vfsub_link(h_src, h_dir, h_dst, dlgt);
 
514
                        dput(h_src);
 
515
                        goto out;
 
516
                } else
 
517
                        //todo: cpup_wh_file
 
518
                        /* udba work */
 
519
                        au_update_brange(inode, 1);
 
520
        }
 
521
 
 
522
        old_ibstart = au_ibstart(inode);
 
523
        err = cpup_entry(dentry, bdst, bsrc, len, flags, dlgt);
 
524
        if (unlikely(err))
 
525
                goto out;
 
526
        dst_inode = h_dst->d_inode;
 
527
        mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
 
528
 
 
529
        //todo: test dlgt
 
530
        err = cpup_iattr(h_dst, h_src, dlgt);
 
531
        //if (LktrCond) err = -1;
 
532
#if 0 // xattr
 
533
        if (0 && !err)
 
534
                err = cpup_xattrs(h_src, h_dst);
 
535
#endif
 
536
        isdir = S_ISDIR(dst_inode->i_mode);
 
537
        if (!err) {
 
538
                if (bdst < old_ibstart)
 
539
                        au_set_ibstart(inode, bdst);
 
540
                au_set_h_iptr(inode, bdst, igrab(dst_inode),
 
541
                              au_hi_flags(inode, isdir));
 
542
                mutex_unlock(&dst_inode->i_mutex);
 
543
                if (!isdir
 
544
                    && h_src->d_inode->i_nlink > 1
 
545
                    && plink)
 
546
                        au_plink_append(sb, inode, h_dst, bdst);
 
547
                goto out; /* success */
 
548
        }
 
549
 
 
550
        /* revert */
 
551
        mutex_unlock(&dst_inode->i_mutex);
 
552
        hgdir = NULL;
 
553
        if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY)
 
554
                     && !IS_ROOT(parent))) {
 
555
                struct dentry *gparent;
 
556
                gparent = dget_parent(parent);
 
557
                hgdir = au_hi(gparent->d_inode, bdst);
 
558
                dput(gparent);
 
559
        }
 
560
        au_dtime_store(&dt, parent, h_parent, hgdir);
 
561
        vfsub_args_init(&vargs, NULL, dlgt, 0);
 
562
        if (!isdir)
 
563
                rerr = vfsub_unlink(h_dir, h_dst, &vargs);
 
564
        else
 
565
                rerr = vfsub_rmdir(h_dir, h_dst, &vargs);
 
566
        //rerr = -1;
 
567
        au_dtime_revert(&dt);
 
568
        if (rerr) {
 
569
                AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
 
570
                err = -EIO;
 
571
        }
 
572
 
 
573
 out:
 
574
        dput(parent);
 
575
        AuTraceErr(err);
 
576
        return err;
 
577
}
 
578
 
 
579
struct au_cpup_single_args {
 
580
        int *errp;
 
581
        struct dentry *dentry;
 
582
        aufs_bindex_t bdst, bsrc;
 
583
        loff_t len;
 
584
        unsigned int flags;
 
585
};
 
586
 
 
587
static void au_call_cpup_single(void *args)
 
588
{
 
589
        struct au_cpup_single_args *a = args;
 
590
        *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
 
591
                                  a->flags);
 
592
}
 
593
 
 
594
int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
 
595
                       aufs_bindex_t bsrc, loff_t len, unsigned int flags)
 
596
{
 
597
        int err, wkq_err;
 
598
        struct dentry *h_dentry;
 
599
        umode_t mode;
 
600
 
 
601
        LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
 
602
                  AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
 
603
                  flags);
 
604
 
 
605
        h_dentry = au_h_dptr(dentry, bsrc);
 
606
        mode = h_dentry->d_inode->i_mode & S_IFMT;
 
607
        if ((mode != S_IFCHR && mode != S_IFBLK)
 
608
            || capable(CAP_MKNOD))
 
609
                err = au_cpup_single(dentry, bdst, bsrc, len, flags);
 
610
        else {
 
611
                struct au_cpup_single_args args = {
 
612
                        .errp           = &err,
 
613
                        .dentry         = dentry,
 
614
                        .bdst           = bdst,
 
615
                        .bsrc           = bsrc,
 
616
                        .len            = len,
 
617
                        .flags          = flags
 
618
                };
 
619
                wkq_err = au_wkq_wait(au_call_cpup_single, &args, /*dlgt*/0);
 
620
                if (unlikely(wkq_err))
 
621
                        err = wkq_err;
 
622
        }
 
623
 
 
624
        AuTraceErr(err);
 
625
        return err;
 
626
}
 
627
 
 
628
/*
 
629
 * copyup the @dentry from the first active hidden branch to @bdst,
 
630
 * using au_cpup_single().
 
631
 */
 
632
int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
 
633
                   unsigned int flags)
 
634
{
 
635
        int err;
 
636
        struct inode *inode;
 
637
        aufs_bindex_t bsrc, bend;
 
638
 
 
639
        LKTRTrace("%.*s, bdst %d, len %Ld, flags 0x%x\n",
 
640
                  AuDLNPair(dentry), bdst, len, flags);
 
641
        inode = dentry->d_inode;
 
642
        AuDebugOn(!S_ISDIR(inode->i_mode) && au_dbstart(dentry) < bdst);
 
643
 
 
644
        bend = au_dbend(dentry);
 
645
        for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
 
646
                if (au_h_dptr(dentry, bsrc))
 
647
                        break;
 
648
        AuDebugOn(!au_h_dptr(dentry, bsrc));
 
649
 
 
650
        err = au_lkup_neg(dentry, bdst);
 
651
        //err = -1;
 
652
        if (!err) {
 
653
                err = au_cpup_single(dentry, bdst, bsrc, len, flags);
 
654
                if (!err)
 
655
                        return 0; /* success */
 
656
 
 
657
                /* revert */
 
658
                au_set_h_dptr(dentry, bdst, NULL);
 
659
                au_set_dbstart(dentry, bsrc);
 
660
        }
 
661
 
 
662
        AuTraceErr(err);
 
663
        return err;
 
664
}
 
665
 
 
666
struct au_cpup_simple_args {
 
667
        int *errp;
 
668
        struct dentry *dentry;
 
669
        aufs_bindex_t bdst;
 
670
        loff_t len;
 
671
        unsigned int flags;
 
672
};
 
673
 
 
674
static void au_call_cpup_simple(void *args)
 
675
{
 
676
        struct au_cpup_simple_args *a = args;
 
677
        *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
 
678
}
 
679
 
 
680
int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
 
681
                       unsigned int flags)
 
682
{
 
683
        int err, do_sio, dlgt, wkq_err;
 
684
        struct dentry *parent;
 
685
        struct inode *h_dir, *dir;
 
686
 
 
687
        LKTRTrace("%.*s, b%d, len %Ld, flags 0x%x\n",
 
688
                  AuDLNPair(dentry), bdst, len, flags);
 
689
 
 
690
        parent = dget_parent(dentry);
 
691
        dir = parent->d_inode;
 
692
        h_dir = au_h_iptr(dir, bdst);
 
693
        dlgt = !!au_opt_test_dlgt(au_mntflags(dir->i_sb));
 
694
        do_sio = au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE, dlgt);
 
695
        if (!do_sio) {
 
696
                /*
 
697
                 * testing CAP_MKNOD is for generic fs,
 
698
                 * but CAP_FSETID is for xfs only, currently.
 
699
                 */
 
700
                umode_t mode = dentry->d_inode->i_mode;
 
701
                do_sio = (((mode & (S_IFCHR | S_IFBLK))
 
702
                           && !capable(CAP_MKNOD))
 
703
                          || ((mode & (S_ISUID | S_ISGID))
 
704
                              && !capable(CAP_FSETID)));
 
705
        }
 
706
        if (!do_sio)
 
707
                err = au_cpup_simple(dentry, bdst, len, flags);
 
708
        else {
 
709
                struct au_cpup_simple_args args = {
 
710
                        .errp           = &err,
 
711
                        .dentry         = dentry,
 
712
                        .bdst           = bdst,
 
713
                        .len            = len,
 
714
                        .flags          = flags
 
715
                };
 
716
                wkq_err = au_wkq_wait(au_call_cpup_simple, &args, /*dlgt*/0);
 
717
                if (unlikely(wkq_err))
 
718
                        err = wkq_err;
 
719
        }
 
720
 
 
721
        dput(parent);
 
722
        AuTraceErr(err);
 
723
        return err;
 
724
}
 
725
 
 
726
/* ---------------------------------------------------------------------- */
 
727
 
 
728
static noinline_for_stack int
 
729
au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
 
730
              struct dentry *wh_dentry, struct file *file, loff_t len)
 
731
{
 
732
        int err;
 
733
        struct au_dinfo *dinfo;
 
734
        aufs_bindex_t bstart;
 
735
        struct dentry *h_d_bdst, *h_d_bstart;
 
736
 
 
737
        AuTraceEnter();
 
738
 
 
739
        dinfo = au_di(dentry);
 
740
        bstart = dinfo->di_bstart;
 
741
        h_d_bdst = dinfo->di_hdentry[0 + bdst].hd_dentry;
 
742
        dinfo->di_bstart = bdst;
 
743
        dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry;
 
744
        h_d_bstart = dinfo->di_hdentry[0 + bstart].hd_dentry;
 
745
        if (file)
 
746
                dinfo->di_hdentry[0 + bstart].hd_dentry
 
747
                        = au_h_fptr(file, au_fbstart(file))->f_dentry;
 
748
        err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME);
 
749
        //if (LktrCond) err = -1;
 
750
        if (!err && file) {
 
751
                err = au_reopen_nondir(file);
 
752
                //err = -1;
 
753
                dinfo->di_hdentry[0 + bstart].hd_dentry = h_d_bstart;
 
754
        }
 
755
        dinfo->di_hdentry[0 + bdst].hd_dentry = h_d_bdst;
 
756
        dinfo->di_bstart = bstart;
 
757
 
 
758
        AuTraceErr(err);
 
759
        return err;
 
760
}
 
761
 
 
762
/*
 
763
 * copyup the deleted file for writing.
 
764
 */
 
765
int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
 
766
               struct file *file)
 
767
{
 
768
        int err, dlgt;
 
769
        struct dentry *parent, *h_parent, *wh_dentry;
 
770
        struct super_block *sb;
 
771
        unsigned int mnt_flags;
 
772
        struct au_dtime dt;
 
773
        struct vfsub_args vargs;
 
774
        struct au_hinode *hgdir;
 
775
        struct au_ndx ndx = {
 
776
                .nd     = NULL,
 
777
                .flags  = 0,
 
778
                //.br   = NULL
 
779
        };
 
780
 
 
781
        LKTRTrace("%.*s, bdst %d, len %Lu\n", AuDLNPair(dentry), bdst, len);
 
782
        AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
 
783
                  || (file && !(file->f_mode & FMODE_WRITE)));
 
784
        DiMustWriteLock(dentry);
 
785
 
 
786
        parent = dget_parent(dentry);
 
787
        IiMustAnyLock(parent->d_inode);
 
788
        h_parent = au_h_dptr(parent, bdst);
 
789
        AuDebugOn(!h_parent);
 
790
 
 
791
        sb = parent->d_sb;
 
792
        mnt_flags = au_mntflags(sb);
 
793
        dlgt = 0;
 
794
        ndx.nfsmnt = au_nfsmnt(sb, bdst);
 
795
        if (unlikely(au_opt_test_dlgt(mnt_flags))) {
 
796
                dlgt = 1;
 
797
                au_fset_ndx(ndx.flags, DLGT);
 
798
        }
 
799
        wh_dentry = au_whtmp_lkup(h_parent, &dentry->d_name, &ndx);
 
800
        //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
 
801
        err = PTR_ERR(wh_dentry);
 
802
        if (IS_ERR(wh_dentry))
 
803
                goto out;
 
804
 
 
805
        hgdir = NULL;
 
806
        if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY)
 
807
                     && !IS_ROOT(parent))) {
 
808
                struct dentry *gparent;
 
809
                gparent = dget_parent(parent);
 
810
                hgdir = au_hi(gparent->d_inode, bdst);
 
811
                dput(gparent);
 
812
        }
 
813
        au_dtime_store(&dt, parent, h_parent, hgdir);
 
814
        err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
 
815
        if (unlikely(err))
 
816
                goto out_wh;
 
817
 
 
818
        AuDebugOn(!d_unhashed(dentry));
 
819
        /* dget first to force sillyrename on nfs */
 
820
        dget(wh_dentry);
 
821
        vfsub_args_init(&vargs, NULL, dlgt, 0);
 
822
        err = vfsub_unlink(h_parent->d_inode, wh_dentry, &vargs);
 
823
        //if (LktrCond) err = -1;
 
824
        if (unlikely(err)) {
 
825
                AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
 
826
                        AuDLNPair(wh_dentry), err);
 
827
                err = -EIO;
 
828
        }
 
829
        au_dtime_revert(&dt);
 
830
        au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
 
831
 
 
832
 out_wh:
 
833
        dput(wh_dentry);
 
834
 out:
 
835
        dput(parent);
 
836
        AuTraceErr(err);
 
837
        //au_debug_off();
 
838
        return err;
 
839
}
 
840
 
 
841
struct au_cpup_wh_args {
 
842
        int *errp;
 
843
        struct dentry *dentry;
 
844
        aufs_bindex_t bdst;
 
845
        loff_t len;
 
846
        struct file *file;
 
847
};
 
848
 
 
849
static void au_call_cpup_wh(void *args)
 
850
{
 
851
        struct au_cpup_wh_args *a = args;
 
852
        *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
 
853
}
 
854
 
 
855
int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
 
856
                   struct file *file)
 
857
{
 
858
        int err, wkq_err;
 
859
        struct dentry *parent;
 
860
        struct inode *dir, *h_dir;
 
861
 
 
862
        AuTraceEnter();
 
863
        parent = dget_parent(dentry);
 
864
        dir = parent->d_inode;
 
865
        IiMustAnyLock(dir);
 
866
        h_dir = au_h_iptr(dir, bdst);
 
867
 
 
868
        if (!au_test_h_perm_sio
 
869
            (h_dir, MAY_EXEC | MAY_WRITE,
 
870
             au_opt_test_dlgt(au_mntflags(dentry->d_sb))))
 
871
                err = au_cpup_wh(dentry, bdst, len, file);
 
872
        else {
 
873
                struct au_cpup_wh_args args = {
 
874
                        .errp   = &err,
 
875
                        .dentry = dentry,
 
876
                        .bdst   = bdst,
 
877
                        .len    = len,
 
878
                        .file   = file
 
879
                };
 
880
                wkq_err = au_wkq_wait(au_call_cpup_wh, &args, /*dlgt*/0);
 
881
                if (unlikely(wkq_err))
 
882
                        err = wkq_err;
 
883
        }
 
884
        dput(parent);
 
885
 
 
886
        AuTraceErr(err);
 
887
        return err;
 
888
}
 
889
 
 
890
/* ---------------------------------------------------------------------- */
 
891
 
 
892
/*
 
893
 * generic routine for both of copy-up and copy-down.
 
894
 * Although I've tried building a path by dcsub, I gave up this approach.
 
895
 * Since the ancestor directory may be moved/renamed during copy.
 
896
 */
 
897
/* cf. revalidate function in file.c */
 
898
int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked,
 
899
               int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
 
900
                         struct dentry *h_parent, void *arg),
 
901
               void *arg)
 
902
{
 
903
        int err, hinotify;
 
904
        struct super_block *sb;
 
905
        struct dentry *d, *parent, *h_parent, *gparent, *real_parent;
 
906
 
 
907
        LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
 
908
                  AuDLNPair(dentry), bdst, parent_ino(dentry), locked);
 
909
        sb = dentry->d_sb;
 
910
        AuDebugOn(au_test_ro(sb, bdst, NULL));
 
911
        err = 0;
 
912
        parent = dget_parent(dentry);
 
913
        IiMustWriteLock(parent->d_inode);
 
914
        if (unlikely(IS_ROOT(parent)))
 
915
                goto out;
 
916
        if (locked) {
 
917
                DiMustAnyLock(locked);
 
918
                IiMustAnyLock(locked->d_inode);
 
919
        }
 
920
 
 
921
        /* slow loop, keep it simple and stupid */
 
922
        real_parent = parent;
 
923
        hinotify = !!au_opt_test(au_mntflags(sb), UDBA_INOTIFY);
 
924
        while (1) {
 
925
                dput(parent);
 
926
                parent = dget_parent(dentry);
 
927
                h_parent = au_h_dptr(parent, bdst);
 
928
                if (h_parent)
 
929
                        goto out; /* success */
 
930
 
 
931
                /* find top dir which is needed to cpup */
 
932
                do {
 
933
                        d = parent;
 
934
                        dput(parent);
 
935
                        parent = dget_parent(d);
 
936
                        if (parent != locked) {
 
937
                                di_read_lock_parent3(parent, !AuLock_IR);
 
938
                                h_parent = au_h_dptr(parent, bdst);
 
939
                                di_read_unlock(parent, !AuLock_IR);
 
940
                        } else
 
941
                                h_parent = au_h_dptr(parent, bdst);
 
942
                } while (!h_parent);
 
943
 
 
944
                if (d != real_parent)
 
945
                        di_write_lock_child3(d);
 
946
 
 
947
                /* somebody else might create while we were sleeping */
 
948
                if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
 
949
                        struct inode *h_dir = h_parent->d_inode,
 
950
                                *dir = parent->d_inode;
 
951
 
 
952
                        if (au_h_dptr(d, bdst))
 
953
                                au_update_dbstart(d);
 
954
                        //AuDebugOn(au_dbstart(d) <= bdst);
 
955
                        if (parent != locked)
 
956
                                di_read_lock_parent3(parent, AuLock_IR);
 
957
                        gparent = NULL;
 
958
                        if (unlikely(hinotify && !IS_ROOT(parent))) {
 
959
                                gparent = dget_parent(parent);
 
960
                                if (gparent != locked)
 
961
                                        ii_read_lock_parent4(gparent->d_inode);
 
962
                                else {
 
963
                                        dput(gparent);
 
964
                                        gparent = NULL;
 
965
                                }
 
966
                        }
 
967
                        au_hdir_lock(h_dir, dir, bdst);
 
968
                        err = cp(d, bdst, h_parent, arg);
 
969
                        //if (LktrCond) err = -1;
 
970
                        au_hdir_unlock(h_dir, dir, bdst);
 
971
                        if (unlikely(gparent)) {
 
972
                                ii_read_unlock(gparent->d_inode);
 
973
                                dput(gparent);
 
974
                        }
 
975
                        if (parent != locked)
 
976
                                di_read_unlock(parent, AuLock_IR);
 
977
                }
 
978
 
 
979
                if (d != real_parent)
 
980
                        di_write_unlock(d);
 
981
                if (unlikely(err))
 
982
                        break;
 
983
        }
 
984
 
 
985
 out:
 
986
        dput(parent);
 
987
        AuTraceErr(err);
 
988
        return err;
 
989
}
 
990
 
 
991
static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
 
992
                       struct dentry *h_parent, void *arg)
 
993
{
 
994
        int err;
 
995
 
 
996
        err = au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
 
997
 
 
998
        AuTraceErr(err);
 
999
        return err;
 
1000
}
 
1001
 
 
1002
int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
 
1003
                 struct dentry *locked)
 
1004
{
 
1005
        int err;
 
1006
 
 
1007
        err = au_cp_dirs(dentry, bdst, locked, au_cpup_dir, NULL);
 
1008
 
 
1009
        AuTraceErr(err);
 
1010
        return err;
 
1011
}
 
1012
 
 
1013
int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
 
1014
                          struct dentry *locked)
 
1015
{
 
1016
        int err;
 
1017
        struct dentry *parent;
 
1018
        struct inode *dir;
 
1019
 
 
1020
        parent = dget_parent(dentry);
 
1021
        dir = parent->d_inode;
 
1022
        LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
 
1023
                  AuDLNPair(dentry), bdst, dir->i_ino, locked);
 
1024
        DiMustReadLock(parent);
 
1025
        IiMustReadLock(dir);
 
1026
 
 
1027
        err = 0;
 
1028
        if (au_h_iptr(dir, bdst))
 
1029
                goto out;
 
1030
 
 
1031
        di_read_unlock(parent, AuLock_IR);
 
1032
        di_write_lock_parent2(parent);
 
1033
        /* someone else might change our inode while we were sleeping */
 
1034
        if (unlikely(!au_h_iptr(dir, bdst)))
 
1035
                err = au_cpup_dirs(dentry, bdst, locked);
 
1036
        di_downgrade_lock(parent, AuLock_IR);
 
1037
 
 
1038
 out:
 
1039
        dput(parent);
 
1040
        AuTraceErr(err);
 
1041
        return err;
 
1042
}