ovl: fold copy-up helpers into callers
Now that the workdir and tmpfile copy up modes have been untagled, the functions become simple enough that the helpers can be folded into the callers. Add new helpers where there is any duplication remaining: preparing creds for creating the object. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
b10cdcdc20
commit
6b52243f63
|
@ -490,59 +490,32 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct dentry *ovl_get_workdir_temp(struct ovl_copy_up_ctx *c)
|
||||
{
|
||||
int err;
|
||||
struct dentry *temp;
|
||||
const struct cred *old_creds = NULL;
|
||||
struct cred *new_creds = NULL;
|
||||
struct ovl_cattr cattr = {
|
||||
/* Can't properly set mode on creation because of the umask */
|
||||
.mode = c->stat.mode & S_IFMT,
|
||||
.rdev = c->stat.rdev,
|
||||
.link = c->link
|
||||
struct ovl_cu_creds {
|
||||
const struct cred *old;
|
||||
struct cred *new;
|
||||
};
|
||||
|
||||
err = security_inode_copy_up(c->dentry, &new_creds);
|
||||
if (err < 0)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (new_creds)
|
||||
old_creds = override_creds(new_creds);
|
||||
|
||||
temp = ovl_create_temp(c->workdir, &cattr);
|
||||
|
||||
if (new_creds) {
|
||||
revert_creds(old_creds);
|
||||
put_cred(new_creds);
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move temp file from workdir into place on upper dir.
|
||||
* Used when copying up directories and when upper fs doesn't support O_TMPFILE.
|
||||
*
|
||||
* Caller must hold ovl_lock_rename_workdir().
|
||||
*/
|
||||
static int ovl_rename_temp(struct ovl_copy_up_ctx *c, struct dentry *temp,
|
||||
struct dentry **newdentry)
|
||||
static int ovl_prep_cu_creds(struct dentry *dentry, struct ovl_cu_creds *cc)
|
||||
{
|
||||
int err;
|
||||
struct dentry *upper;
|
||||
struct inode *udir = d_inode(c->destdir);
|
||||
|
||||
upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len);
|
||||
if (IS_ERR(upper))
|
||||
return PTR_ERR(upper);
|
||||
|
||||
err = ovl_do_rename(d_inode(c->workdir), temp, udir, upper, 0);
|
||||
if (!err)
|
||||
*newdentry = dget(temp);
|
||||
dput(upper);
|
||||
|
||||
cc->old = cc->new = NULL;
|
||||
err = security_inode_copy_up(dentry, &cc->new);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (cc->new)
|
||||
cc->old = override_creds(cc->new);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ovl_revert_cu_creds(struct ovl_cu_creds *cc)
|
||||
{
|
||||
if (cc->new) {
|
||||
revert_creds(cc->old);
|
||||
put_cred(cc->new);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -552,15 +525,28 @@ static int ovl_rename_temp(struct ovl_copy_up_ctx *c, struct dentry *temp,
|
|||
static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct dentry *newdentry = NULL;
|
||||
struct dentry *temp;
|
||||
struct inode *udir = d_inode(c->destdir), *wdir = d_inode(c->workdir);
|
||||
struct dentry *temp, *upper;
|
||||
struct ovl_cu_creds cc;
|
||||
int err;
|
||||
struct ovl_cattr cattr = {
|
||||
/* Can't properly set mode on creation because of the umask */
|
||||
.mode = c->stat.mode & S_IFMT,
|
||||
.rdev = c->stat.rdev,
|
||||
.link = c->link
|
||||
};
|
||||
|
||||
err = ovl_lock_rename_workdir(c->workdir, c->destdir);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
temp = ovl_get_workdir_temp(c);
|
||||
err = ovl_prep_cu_creds(c->dentry, &cc);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
temp = ovl_create_temp(c->workdir, &cattr);
|
||||
ovl_revert_cu_creds(&cc);
|
||||
|
||||
err = PTR_ERR(temp);
|
||||
if (IS_ERR(temp))
|
||||
goto unlock;
|
||||
|
@ -575,102 +561,75 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
err = ovl_rename_temp(c, temp, &newdentry);
|
||||
upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len);
|
||||
err = PTR_ERR(upper);
|
||||
if (IS_ERR(upper))
|
||||
goto cleanup;
|
||||
|
||||
err = ovl_do_rename(wdir, temp, udir, upper, 0);
|
||||
dput(upper);
|
||||
if (err)
|
||||
goto cleanup;
|
||||
|
||||
if (!c->metacopy)
|
||||
ovl_set_upperdata(d_inode(c->dentry));
|
||||
inode = d_inode(c->dentry);
|
||||
ovl_inode_update(inode, newdentry);
|
||||
ovl_inode_update(inode, temp);
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
ovl_set_flag(OVL_WHITEOUTS, inode);
|
||||
out_dput:
|
||||
dput(temp);
|
||||
unlock:
|
||||
unlock_rename(c->workdir, c->destdir);
|
||||
|
||||
return err;
|
||||
|
||||
cleanup:
|
||||
ovl_cleanup(d_inode(c->workdir), temp);
|
||||
goto out_dput;
|
||||
}
|
||||
|
||||
static struct dentry *ovl_get_tmpfile(struct ovl_copy_up_ctx *c)
|
||||
{
|
||||
int err;
|
||||
struct dentry *temp;
|
||||
const struct cred *old_creds = NULL;
|
||||
struct cred *new_creds = NULL;
|
||||
|
||||
err = security_inode_copy_up(c->dentry, &new_creds);
|
||||
if (err < 0)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (new_creds)
|
||||
old_creds = override_creds(new_creds);
|
||||
|
||||
temp = ovl_do_tmpfile(c->workdir, c->stat.mode);
|
||||
|
||||
if (new_creds) {
|
||||
revert_creds(old_creds);
|
||||
put_cred(new_creds);
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/* Link O_TMPFILE into place on upper dir */
|
||||
static int ovl_link_tmpfile(struct ovl_copy_up_ctx *c, struct dentry *temp,
|
||||
struct dentry **newdentry)
|
||||
{
|
||||
int err;
|
||||
struct dentry *upper;
|
||||
struct inode *udir = d_inode(c->destdir);
|
||||
|
||||
inode_lock_nested(udir, I_MUTEX_PARENT);
|
||||
|
||||
upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len);
|
||||
err = PTR_ERR(upper);
|
||||
if (IS_ERR(upper))
|
||||
ovl_cleanup(wdir, temp);
|
||||
dput(temp);
|
||||
goto unlock;
|
||||
|
||||
err = ovl_do_link(temp, udir, upper);
|
||||
if (!err)
|
||||
*newdentry = dget(upper);
|
||||
dput(upper);
|
||||
|
||||
unlock:
|
||||
inode_unlock(udir);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Copyup using O_TMPFILE which does not require cross dir locking */
|
||||
static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
|
||||
{
|
||||
struct dentry *newdentry = NULL;
|
||||
struct dentry *temp;
|
||||
struct inode *udir = d_inode(c->destdir);
|
||||
struct dentry *temp, *upper;
|
||||
struct ovl_cu_creds cc;
|
||||
int err;
|
||||
|
||||
temp = ovl_get_tmpfile(c);
|
||||
err = ovl_prep_cu_creds(c->dentry, &cc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
temp = ovl_do_tmpfile(c->workdir, c->stat.mode);
|
||||
ovl_revert_cu_creds(&cc);
|
||||
|
||||
if (IS_ERR(temp))
|
||||
return PTR_ERR(temp);
|
||||
|
||||
err = ovl_copy_up_inode(c, temp);
|
||||
if (err)
|
||||
goto out;
|
||||
goto out_dput;
|
||||
|
||||
inode_lock_nested(udir, I_MUTEX_PARENT);
|
||||
|
||||
upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len);
|
||||
err = PTR_ERR(upper);
|
||||
if (!IS_ERR(upper)) {
|
||||
err = ovl_do_link(temp, udir, upper);
|
||||
dput(upper);
|
||||
}
|
||||
inode_unlock(udir);
|
||||
|
||||
err = ovl_link_tmpfile(c, temp, &newdentry);
|
||||
if (err)
|
||||
goto out;
|
||||
goto out_dput;
|
||||
|
||||
if (!c->metacopy)
|
||||
ovl_set_upperdata(d_inode(c->dentry));
|
||||
ovl_inode_update(d_inode(c->dentry), newdentry);
|
||||
ovl_inode_update(d_inode(c->dentry), temp);
|
||||
|
||||
out:
|
||||
return 0;
|
||||
|
||||
out_dput:
|
||||
dput(temp);
|
||||
return err;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue