Commit 377c9279 authored by J. R. Okajima's avatar J. R. Okajima
Browse files

aufs: copy-up 6/7, directories



Copy-up the ancestors of the target.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent 253be9ad
...@@ -1062,3 +1062,119 @@ int au_sio_cpup_simple(struct au_cp_generic *cpg) ...@@ -1062,3 +1062,119 @@ int au_sio_cpup_simple(struct au_cp_generic *cpg)
AuDebugOn(cpg->bsrc <= cpg->bdst); AuDebugOn(cpg->bsrc <= cpg->bdst);
return au_do_sio_cpup_simple(cpg); return au_do_sio_cpup_simple(cpg);
} }
/* ---------------------------------------------------------------------- */
/*
* generic routine for both of copy-up and copy-down.
*/
/* cf. revalidate function in file.c */
int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
struct au_pin *pin,
struct dentry *h_parent, void *arg),
void *arg)
{
int err;
struct au_pin pin;
struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry;
err = 0;
parent = dget_parent(dentry);
if (IS_ROOT(parent))
goto out;
au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
AuPin_MNT_WRITE);
/* do not use au_dpage */
real_parent = parent;
while (1) {
dput(parent);
parent = dget_parent(dentry);
h_parent = au_h_dptr(parent, bdst);
if (h_parent)
goto out; /* success */
/* find top dir which is necessary to cpup */
do {
d = parent;
dput(parent);
parent = dget_parent(d);
di_read_lock_parent3(parent, !AuLock_IR);
h_parent = au_h_dptr(parent, bdst);
di_read_unlock(parent, !AuLock_IR);
} while (!h_parent);
if (d != real_parent)
di_write_lock_child3(d);
/* somebody else might create while we were sleeping */
h_dentry = au_h_dptr(d, bdst);
if (!h_dentry || d_is_negative(h_dentry)) {
if (h_dentry)
au_update_dbtop(d);
au_pin_set_dentry(&pin, d);
err = au_do_pin(&pin);
if (!err) {
err = cp(d, bdst, &pin, h_parent, arg);
au_unpin(&pin);
}
}
if (d != real_parent)
di_write_unlock(d);
if (unlikely(err))
break;
}
out:
dput(parent);
return err;
}
static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
struct au_pin *pin,
struct dentry *h_parent __maybe_unused,
void *arg __maybe_unused)
{
struct au_cp_generic cpg = {
.dentry = dentry,
.bdst = bdst,
.bsrc = -1,
.len = 0,
.pin = pin,
.flags = AuCpup_DTIME
};
return au_sio_cpup_simple(&cpg);
}
int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
{
return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
}
int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
{
int err;
struct dentry *parent;
struct inode *dir;
parent = dget_parent(dentry);
dir = d_inode(parent);
err = 0;
if (au_h_iptr(dir, bdst))
goto out;
di_read_unlock(parent, AuLock_IR);
di_write_lock_parent(parent);
/* someone else might change our inode while we were sleeping */
if (!au_h_iptr(dir, bdst))
err = au_cpup_dirs(dentry, bdst);
di_downgrade_lock(parent, AuLock_IR);
out:
dput(parent);
return err;
}
...@@ -49,6 +49,14 @@ struct au_cp_generic { ...@@ -49,6 +49,14 @@ struct au_cp_generic {
int au_copy_file(struct file *dst, struct file *src, loff_t len); int au_copy_file(struct file *dst, struct file *src, loff_t len);
int au_sio_cpup_simple(struct au_cp_generic *cpg); int au_sio_cpup_simple(struct au_cp_generic *cpg);
int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
struct au_pin *pin,
struct dentry *h_parent, void *arg),
void *arg);
int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* keep timestamps when copyup */ /* keep timestamps when copyup */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment