ovl: check if upper fs supports RENAME_WHITEOUT
As with other required upper fs features, we only warn if support is missing to avoid breaking existing sub-optimal setups. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
bccece1ead
commit
cad218ab33
@ -42,7 +42,7 @@ int ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *ovl_lookup_temp(struct dentry *workdir)
|
struct dentry *ovl_lookup_temp(struct dentry *workdir)
|
||||||
{
|
{
|
||||||
struct dentry *temp;
|
struct dentry *temp;
|
||||||
char name[20];
|
char name[20];
|
||||||
|
@ -453,6 +453,7 @@ struct ovl_cattr {
|
|||||||
struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
|
struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
|
||||||
struct ovl_cattr *attr);
|
struct ovl_cattr *attr);
|
||||||
int ovl_cleanup(struct inode *dir, struct dentry *dentry);
|
int ovl_cleanup(struct inode *dir, struct dentry *dentry);
|
||||||
|
struct dentry *ovl_lookup_temp(struct dentry *workdir);
|
||||||
struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr);
|
struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr);
|
||||||
|
|
||||||
/* file.c */
|
/* file.c */
|
||||||
|
@ -1071,6 +1071,66 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns 1 if RENAME_WHITEOUT is supported, 0 if not supported and
|
||||||
|
* negative values if error is encountered.
|
||||||
|
*/
|
||||||
|
static int ovl_check_rename_whiteout(struct dentry *workdir)
|
||||||
|
{
|
||||||
|
struct inode *dir = d_inode(workdir);
|
||||||
|
struct dentry *temp;
|
||||||
|
struct dentry *dest;
|
||||||
|
struct dentry *whiteout;
|
||||||
|
struct name_snapshot name;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
inode_lock_nested(dir, I_MUTEX_PARENT);
|
||||||
|
|
||||||
|
temp = ovl_create_temp(workdir, OVL_CATTR(S_IFREG | 0));
|
||||||
|
err = PTR_ERR(temp);
|
||||||
|
if (IS_ERR(temp))
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
dest = ovl_lookup_temp(workdir);
|
||||||
|
err = PTR_ERR(dest);
|
||||||
|
if (IS_ERR(dest)) {
|
||||||
|
dput(temp);
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Name is inline and stable - using snapshot as a copy helper */
|
||||||
|
take_dentry_name_snapshot(&name, temp);
|
||||||
|
err = ovl_do_rename(dir, temp, dir, dest, RENAME_WHITEOUT);
|
||||||
|
if (err) {
|
||||||
|
if (err == -EINVAL)
|
||||||
|
err = 0;
|
||||||
|
goto cleanup_temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
whiteout = lookup_one_len(name.name.name, workdir, name.name.len);
|
||||||
|
err = PTR_ERR(whiteout);
|
||||||
|
if (IS_ERR(whiteout))
|
||||||
|
goto cleanup_temp;
|
||||||
|
|
||||||
|
err = ovl_is_whiteout(whiteout);
|
||||||
|
|
||||||
|
/* Best effort cleanup of whiteout and temp file */
|
||||||
|
if (err)
|
||||||
|
ovl_cleanup(dir, whiteout);
|
||||||
|
dput(whiteout);
|
||||||
|
|
||||||
|
cleanup_temp:
|
||||||
|
ovl_cleanup(dir, temp);
|
||||||
|
release_dentry_name_snapshot(&name);
|
||||||
|
dput(temp);
|
||||||
|
dput(dest);
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
inode_unlock(dir);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
|
static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
|
||||||
struct path *workpath)
|
struct path *workpath)
|
||||||
{
|
{
|
||||||
@ -1116,6 +1176,15 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
|
|||||||
else
|
else
|
||||||
pr_warn("upper fs does not support tmpfile.\n");
|
pr_warn("upper fs does not support tmpfile.\n");
|
||||||
|
|
||||||
|
|
||||||
|
/* Check if upper/work fs supports RENAME_WHITEOUT */
|
||||||
|
err = ovl_check_rename_whiteout(ofs->workdir);
|
||||||
|
if (err < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
pr_warn("upper fs does not support RENAME_WHITEOUT.\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if upper/work fs supports trusted.overlay.* xattr
|
* Check if upper/work fs supports trusted.overlay.* xattr
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user