Commit 253be9ad authored by J. R. Okajima's avatar J. R. Okajima
Browse files

aufs: copy-up 5/7, simple interface



Because the copy-up operation is big and has many parameters and
functions, consolidate them in this commit.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent f63b4f2f
...@@ -725,7 +725,6 @@ out: ...@@ -725,7 +725,6 @@ out:
* aufs doesn't touch the credential so * aufs doesn't touch the credential so
* security_inode_copy_up{,_xattr}() are unnecessary. * security_inode_copy_up{,_xattr}() are unnecessary.
*/ */
/* re-commit later */ __maybe_unused
static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
{ {
int err, rerr; int err, rerr;
...@@ -904,6 +903,45 @@ static void au_call_cpup_single(void *args) ...@@ -904,6 +903,45 @@ static void au_call_cpup_single(void *args)
} }
#endif #endif
/*
* prevent SIGXFSZ in copy-up.
* testing CAP_MKNOD is for generic fs,
* but CAP_FSETID is for xfs only, currently.
*/
static int au_cpup_sio_test(struct au_pin *pin, umode_t mode)
{
int do_sio;
struct super_block *sb;
struct inode *h_dir;
do_sio = 0;
sb = au_pinned_parent(pin)->d_sb;
if (!au_wkq_test()
&& (!au_sbi(sb)->si_plink_maint_pid
|| au_plink_maint(sb, AuLock_NOPLM))) {
switch (mode & S_IFMT) {
case S_IFREG:
/* no condition about RLIMIT_FSIZE and the file size */
do_sio = 1;
break;
case S_IFCHR:
case S_IFBLK:
do_sio = !capable(CAP_MKNOD);
break;
}
if (!do_sio)
do_sio = ((mode & (S_ISUID | S_ISGID))
&& !capable(CAP_FSETID));
/* this workaround may be removed in the future */
if (!do_sio) {
h_dir = au_pinned_h_dir(pin);
do_sio = h_dir->i_mode & S_ISVTX;
}
}
return do_sio;
}
#if 0 /* reserved */ #if 0 /* reserved */
int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
{ {
...@@ -927,3 +965,100 @@ int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) ...@@ -927,3 +965,100 @@ int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
return err; return err;
} }
#endif #endif
/*
* copyup the @dentry from the first active lower branch to @bdst,
* using au_cpup_single().
*/
static int au_cpup_simple(struct au_cp_generic *cpg)
{
int err;
unsigned int flags_orig;
struct dentry *dentry;
AuDebugOn(cpg->bsrc < 0);
dentry = cpg->dentry;
DiMustWriteLock(dentry);
err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1);
if (!err) {
flags_orig = cpg->flags;
au_fset_cpup(cpg->flags, RENAME);
err = au_cpup_single(cpg, NULL);
cpg->flags = flags_orig;
if (!err)
return 0; /* success */
/* revert */
au_set_h_dptr(dentry, cpg->bdst, NULL);
au_set_dbtop(dentry, cpg->bsrc);
}
return err;
}
struct au_cpup_simple_args {
int *errp;
struct au_cp_generic *cpg;
};
static void au_call_cpup_simple(void *args)
{
struct au_cpup_simple_args *a = args;
au_pin_hdir_acquire_nest(a->cpg->pin);
*a->errp = au_cpup_simple(a->cpg);
au_pin_hdir_release(a->cpg->pin);
}
static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
{
int err, wkq_err;
struct dentry *dentry, *parent;
struct file *h_file;
struct inode *h_dir;
dentry = cpg->dentry;
h_file = NULL;
parent = dget_parent(dentry);
h_dir = au_h_iptr(d_inode(parent), cpg->bdst);
if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
&& !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
err = au_cpup_simple(cpg);
else {
struct au_cpup_simple_args args = {
.errp = &err,
.cpg = cpg
};
wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
if (unlikely(wkq_err))
err = wkq_err;
}
dput(parent);
return err;
}
int au_sio_cpup_simple(struct au_cp_generic *cpg)
{
aufs_bindex_t bsrc, bbot;
struct dentry *dentry, *h_dentry;
if (cpg->bsrc < 0) {
dentry = cpg->dentry;
bbot = au_dbbot(dentry);
for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) {
h_dentry = au_h_dptr(dentry, bsrc);
if (h_dentry) {
AuDebugOn(d_is_negative(h_dentry));
break;
}
}
AuDebugOn(bsrc > bbot);
cpg->bsrc = bsrc;
}
AuDebugOn(cpg->bsrc <= cpg->bdst);
return au_do_sio_cpup_simple(cpg);
}
...@@ -47,6 +47,7 @@ struct au_cp_generic { ...@@ -47,6 +47,7 @@ struct au_cp_generic {
do { (flags) &= ~AuCpup_##name; } while (0) do { (flags) &= ~AuCpup_##name; } while (0)
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);
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
......
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