119
118
/* Note: dt_dentry and dt_hidden_dentry are not dget/dput-ed */
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)
125
124
struct inode *inode;
128
AuDebugOn(!dentry || !hidden_dentry || !hidden_dentry->d_inode);
127
AuDebugOn(!dentry || !h_dentry || !h_dentry->d_inode);
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;
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)
141
140
struct iattr attr;
143
struct dentry *dentry;
142
struct dentry *parent;
143
struct aufs_hin_ignore ign;
144
struct vfsub_args vargs;
145
LKTRTrace("h_parent locked %d\n", h_parent_is_locked);
146
LKTRTrace("%.*s\n", AuDLNPair(dt->dt_dentry));
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;
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));
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);
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);
161
167
/* ---------------------------------------------------------------------- */
163
static int cpup_iattr(struct dentry *hidden_dst, struct dentry *hidden_src,
169
static int cpup_iattr(struct dentry *h_dst, struct dentry *h_src, int dlgt)
168
struct inode *hidden_isrc, *hidden_idst;
173
struct inode *h_isrc, *h_idst;
174
struct vfsub_args vargs;
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;
179
h_isrc = h_src->d_inode;
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));
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;
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);
187
hidden_idst->i_flags = hidden_isrc->i_flags; //??
205
h_idst->i_flags = h_isrc->i_flags; //??
266
278
fput(hidden[SRC].file);
267
279
sbr_put(sb, hidden[SRC].bindex);
274
unsigned int au_flags_cpup(unsigned int init, struct dentry *parent)
276
if (unlikely(parent && IS_ROOT(parent)))
277
init |= CPUP_LOCKED_GHDIR;
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,
287
aufs_bindex_t bsrc, loff_t len,
288
struct au_cpup_flags *flags, int dlgt)
286
int err, isdir, symlen;
287
struct dentry *hidden_src, *hidden_dst, *hidden_parent, *parent;
288
struct inode *hidden_inode, *hidden_dir, *dir;
291
struct dentry *h_src, *h_dst, *h_parent, *parent;
292
struct inode *h_inode, *h_dir, *dir;
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;
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,
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,
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. */
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);
310
h_inode = h_src->d_inode;
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;
318
dtime_store(&dt, parent, hidden_parent);
323
au_dtime_store(&dt, parent, bdst, h_parent);
321
mode = hidden_inode->i_mode;
325
mode = h_inode->i_mode;
322
326
switch (mode & S_IFMT) {
324
328
/* stop updating while we are referencing */
325
IMustLock(hidden_inode);
326
err = vfsub_create(hidden_dir, hidden_dst, mode | S_IWUSR, NULL,
328
//if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
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;}
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)
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.
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)
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;
420
struct vfsub_args vargs;
421
struct aufs_sbinfo *sbinfo;
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,
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,
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;
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;
435
dlgt = need_dlgt(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))) {
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);
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);
450
AuDebugOn(!hidden_src->d_inode);
451
// vfs_link() does lock the inode
452
err = vfsub_link(hidden_src, hidden_dir, hidden_dst,
456
AuDebugOn(!h_src->d_inode);
457
err = vfsub_link(h_src, h_dir, h_dst, dlgt);
458
463
au_update_brange(inode, 1);
478
483
set_ibstart(inode, bdst);
479
484
set_h_iptr(inode, bdst, igrab(dst_inode),
480
485
au_hi_flags(inode, isdir));
482
src_inode = hidden_src->d_inode;
484
if (src_inode->i_nlink > 1
485
&& au_flag_test(sb, AuFlag_PLINK))
486
append_plink(sb, inode, hidden_dst, bdst);
488
/* braces are added to stop a warning */
489
;//xino_write0(sb, bsrc, src_inode->i_ino);
490
/* ignore this error */
486
vfsub_i_unlock(dst_inode);
487
src_inode = h_src->d_inode;
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 */
498
parent = dget_parent(dentry);
499
dtime_store(&dt, parent, h_parent);
496
vfsub_i_unlock(dst_inode);
497
au_dtime_store(&dt, parent, bdst, h_parent);
498
vfsub_args_init(&vargs, NULL, dlgt, 0);
502
rerr = vfsub_unlink(hidden_dir, hidden_dst, dlgt);
500
rerr = vfsub_unlink(h_dir, h_dst, &vargs);
504
rerr = vfsub_rmdir(hidden_dir, hidden_dst, dlgt);
502
rerr = vfsub_rmdir(h_dir, h_dst, &vargs);
506
dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
504
au_dtime_revert(&dt);
508
IOErr("failed removing broken entry(%d, %d)\n", err, rerr);
506
AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
518
struct cpup_single_args {
516
struct au_cpup_single_args {
520
518
struct dentry *dentry;
521
519
aufs_bindex_t bdst, bsrc;
521
struct au_cpup_flags *flags;
526
static void call_cpup_single(void *args)
524
static void au_call_cpup_single(void *args)
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,
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)
535
535
int err, wkq_err;
536
struct dentry *hidden_dentry;
536
struct dentry *h_dentry;
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,
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,
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);
549
struct cpup_single_args args = {
549
struct au_cpup_single_args args = {
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))
567
567
* copyup the @dentry from the first active hidden branch to @bdst,
568
* using cpup_single().
568
* using au_cpup_single().
570
int cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
570
int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
571
struct au_cpup_flags *flags)
574
574
struct inode *inode;
575
575
aufs_bindex_t bsrc, bend;
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);
597
597
set_dbstart(dentry, bsrc);
604
struct cpup_simple_args {
604
struct au_cpup_simple_args {
606
606
struct dentry *dentry;
607
607
aufs_bindex_t bdst;
609
struct au_cpup_flags *flags;
612
static void call_cpup_simple(void *args)
612
static void au_call_cpup_simple(void *args)
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);
618
int sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
618
int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
619
struct au_cpup_flags *flags)
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;
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);
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);
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));
639
err = cpup_simple(dentry, bdst, len, flags);
641
struct cpup_simple_args args = {
639
err = au_cpup_simple(dentry, bdst, len, flags);
641
struct au_cpup_simple_args args = {
648
wkq_err = au_wkq_wait(au_call_cpup_simple, &args, /*dlgt*/0);
649
if (unlikely(wkq_err))
658
/* ---------------------------------------------------------------------- */
661
* copyup the deleted file for writing.
663
int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
667
struct dentry *parent, *h_parent, *wh_dentry, *h_dentry_bdst,
670
struct super_block *sb;
672
struct aufs_dinfo *dinfo;
673
aufs_bindex_t bstart;
674
struct vfsub_args vargs;
675
struct aufs_ndx ndx = {
679
struct au_cpup_flags cflags = {
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);
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;
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))
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;
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;
717
err = au_reopen_nondir(file);
719
dinfo->di_hdentry[0 + bstart].hd_dentry = h_dentry_bstart;
721
dinfo->di_hdentry[0 + bdst].hd_dentry = h_dentry_bdst;
722
dinfo->di_bstart = bstart;
726
AuDebugOn(!d_unhashed(dentry));
727
/* dget first to force sillyrename on nfs */
729
vfsub_args_init(&vargs, NULL, ndx.dlgt, 0);
730
err = vfsub_unlink(h_dir, wh_dentry, &vargs);
731
//if (LktrCond) err = -1;
733
AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
734
AuDLNPair(wh_dentry), err);
737
au_dtime_revert(&dt);
738
set_hi_wh(dentry->d_inode, bdst, wh_dentry);
749
struct au_cpup_wh_args {
751
struct dentry *dentry;
757
static void au_call_cpup_wh(void *args)
759
struct au_cpup_wh_args *a = args;
760
*a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
763
int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
767
struct dentry *parent;
768
struct inode *dir, *h_dir;
771
parent = dget_parent(dentry);
772
dir = parent->d_inode;
774
h_dir = au_h_iptr_i(dir, bdst);
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);
780
struct au_cpup_wh_args args = {
643
782
.dentry = dentry,
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))
797
/* ---------------------------------------------------------------------- */
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.
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),
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;
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));
820
parent = dget_parent(dentry);
672
821
IiMustWriteLock(parent->d_inode);
673
822
if (unlikely(IS_ROOT(parent)))
676
825
DiMustAnyLock(locked);
677
826
IiMustAnyLock(locked->d_inode);
680
829
/* slow loop, keep it simple and stupid */
682
udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
830
real_parent = parent;
831
udba = au_flag_test_udba_inotify(sb);
684
parent = dentry->d_parent; // dget_parent()
685
hidden_parent = au_h_dptr_i(parent, bdst);
687
return 0; /* success */
834
parent = dget_parent(dentry);
835
h_parent = au_h_dptr_i(parent, bdst);
837
goto out; /* success */
689
839
/* find top dir which is needed to cpup */
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);
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);
849
h_parent = au_h_dptr_i(parent, bdst);
700
if (d != dentry->d_parent)
852
if (d != real_parent)
701
853
di_write_lock_child3(d);
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,
857
struct inode *h_dir = h_parent->d_inode,
858
*dir = parent->d_inode;
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);
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);
720
875
hdir_lock(h_dir, dir, bdst);
721
err = sio_cpup_simple(d, bdst, -1,
722
au_flags_cpup(CPUP_DTIME,
876
err = cp(d, bdst, h_parent, arg);
724
877
//if (LktrCond) err = -1;
725
878
hdir_unlock(h_dir, dir, bdst);
727
hdir_unlock(h_gdir, gdir, bdst);
879
if (unlikely(gparent)) {
880
ii_read_unlock(gparent->d_inode);
728
883
if (parent != locked)
729
di_read_unlock(parent, AUFS_I_RLOCK);
884
di_read_unlock(parent, AuLock_IR);
732
if (d != dentry->d_parent)
887
if (d != real_parent)
733
888
di_write_unlock(d);
734
889
if (unlikely(err))
743
int test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
744
struct dentry *locked)
899
static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
900
struct dentry *h_parent, void *arg)
903
struct au_cpup_flags cflags = {
907
err = au_sio_cpup_simple(dentry, bdst, -1, &cflags);
913
int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
914
struct dentry *locked)
918
err = au_cp_dirs(dentry, bdst, locked, au_cpup_dir, NULL);
924
int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
925
struct dentry *locked)
747
928
struct dentry *parent;
748
929
struct inode *dir;
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);
757
939
if (au_h_iptr_i(dir, bdst))
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))
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);
769
di_downgrade_lock(parent, AUFS_I_RLOCK);