Commit 32a3d848 authored by Al Viro's avatar Al Viro Committed by Miklos Szeredi

ovl: clean up kstat usage

FWIW, there's a bit of abuse of struct kstat in overlayfs object
creation paths - for one thing, it ends up with a very small subset
of struct kstat (mode + rdev), for another it also needs link in
case of symlinks and ends up passing it separately.

IMO it would be better to introduce a separate object for that.

In principle, we might even lift that thing into general API and switch
 ->mkdir()/->mknod()/->symlink() to identical calling conventions.  Hell
knows, perhaps ->create() as well...
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 9aba6521
...@@ -238,10 +238,15 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, ...@@ -238,10 +238,15 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
struct inode *udir = upperdir->d_inode; struct inode *udir = upperdir->d_inode;
struct dentry *newdentry = NULL; struct dentry *newdentry = NULL;
struct dentry *upper = NULL; struct dentry *upper = NULL;
umode_t mode = stat->mode;
int err; int err;
const struct cred *old_creds = NULL; const struct cred *old_creds = NULL;
struct cred *new_creds = NULL; struct cred *new_creds = NULL;
struct cattr cattr = {
/* Can't properly set mode on creation because of the umask */
.mode = stat->mode & S_IFMT,
.rdev = stat->rdev,
.link = link
};
newdentry = ovl_lookup_temp(workdir, dentry); newdentry = ovl_lookup_temp(workdir, dentry);
err = PTR_ERR(newdentry); err = PTR_ERR(newdentry);
...@@ -261,10 +266,7 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, ...@@ -261,10 +266,7 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
if (new_creds) if (new_creds)
old_creds = override_creds(new_creds); old_creds = override_creds(new_creds);
/* Can't properly set mode on creation because of the umask */ err = ovl_create_real(wdir, newdentry, &cattr, NULL, true);
stat->mode &= S_IFMT;
err = ovl_create_real(wdir, newdentry, stat, link, NULL, true);
stat->mode = mode;
if (new_creds) { if (new_creds) {
revert_creds(old_creds); revert_creds(old_creds);
......
...@@ -82,8 +82,7 @@ static struct dentry *ovl_whiteout(struct dentry *workdir, ...@@ -82,8 +82,7 @@ static struct dentry *ovl_whiteout(struct dentry *workdir,
} }
int ovl_create_real(struct inode *dir, struct dentry *newdentry, int ovl_create_real(struct inode *dir, struct dentry *newdentry,
struct kstat *stat, const char *link, struct cattr *attr, struct dentry *hardlink, bool debug)
struct dentry *hardlink, bool debug)
{ {
int err; int err;
...@@ -93,13 +92,13 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry, ...@@ -93,13 +92,13 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry,
if (hardlink) { if (hardlink) {
err = ovl_do_link(hardlink, dir, newdentry, debug); err = ovl_do_link(hardlink, dir, newdentry, debug);
} else { } else {
switch (stat->mode & S_IFMT) { switch (attr->mode & S_IFMT) {
case S_IFREG: case S_IFREG:
err = ovl_do_create(dir, newdentry, stat->mode, debug); err = ovl_do_create(dir, newdentry, attr->mode, debug);
break; break;
case S_IFDIR: case S_IFDIR:
err = ovl_do_mkdir(dir, newdentry, stat->mode, debug); err = ovl_do_mkdir(dir, newdentry, attr->mode, debug);
break; break;
case S_IFCHR: case S_IFCHR:
...@@ -107,11 +106,11 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry, ...@@ -107,11 +106,11 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry,
case S_IFIFO: case S_IFIFO:
case S_IFSOCK: case S_IFSOCK:
err = ovl_do_mknod(dir, newdentry, err = ovl_do_mknod(dir, newdentry,
stat->mode, stat->rdev, debug); attr->mode, attr->rdev, debug);
break; break;
case S_IFLNK: case S_IFLNK:
err = ovl_do_symlink(dir, newdentry, link, debug); err = ovl_do_symlink(dir, newdentry, attr->link, debug);
break; break;
default: default:
...@@ -190,8 +189,7 @@ static bool ovl_type_merge(struct dentry *dentry) ...@@ -190,8 +189,7 @@ static bool ovl_type_merge(struct dentry *dentry)
} }
static int ovl_create_upper(struct dentry *dentry, struct inode *inode, static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
struct kstat *stat, const char *link, struct cattr *attr, struct dentry *hardlink)
struct dentry *hardlink)
{ {
struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
struct inode *udir = upperdir->d_inode; struct inode *udir = upperdir->d_inode;
...@@ -199,7 +197,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, ...@@ -199,7 +197,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
int err; int err;
if (!hardlink && !IS_POSIXACL(udir)) if (!hardlink && !IS_POSIXACL(udir))
stat->mode &= ~current_umask(); attr->mode &= ~current_umask();
inode_lock_nested(udir, I_MUTEX_PARENT); inode_lock_nested(udir, I_MUTEX_PARENT);
newdentry = lookup_one_len(dentry->d_name.name, upperdir, newdentry = lookup_one_len(dentry->d_name.name, upperdir,
...@@ -207,7 +205,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, ...@@ -207,7 +205,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
err = PTR_ERR(newdentry); err = PTR_ERR(newdentry);
if (IS_ERR(newdentry)) if (IS_ERR(newdentry))
goto out_unlock; goto out_unlock;
err = ovl_create_real(udir, newdentry, stat, link, hardlink, false); err = ovl_create_real(udir, newdentry, attr, hardlink, false);
if (err) if (err)
goto out_dput; goto out_dput;
...@@ -282,7 +280,8 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, ...@@ -282,7 +280,8 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
if (IS_ERR(opaquedir)) if (IS_ERR(opaquedir))
goto out_unlock; goto out_unlock;
err = ovl_create_real(wdir, opaquedir, &stat, NULL, NULL, true); err = ovl_create_real(wdir, opaquedir,
&(struct cattr){.mode = stat.mode}, NULL, true);
if (err) if (err)
goto out_dput; goto out_dput;
...@@ -382,7 +381,7 @@ static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name, ...@@ -382,7 +381,7 @@ static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name,
} }
static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
struct kstat *stat, const char *link, struct cattr *cattr,
struct dentry *hardlink) struct dentry *hardlink)
{ {
struct dentry *workdir = ovl_workdir(dentry); struct dentry *workdir = ovl_workdir(dentry);
...@@ -399,7 +398,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, ...@@ -399,7 +398,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
if (!hardlink) { if (!hardlink) {
err = posix_acl_create(dentry->d_parent->d_inode, err = posix_acl_create(dentry->d_parent->d_inode,
&stat->mode, &default_acl, &acl); &cattr->mode, &default_acl, &acl);
if (err) if (err)
return err; return err;
} }
...@@ -419,7 +418,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, ...@@ -419,7 +418,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
if (IS_ERR(upper)) if (IS_ERR(upper))
goto out_dput; goto out_dput;
err = ovl_create_real(wdir, newdentry, stat, link, hardlink, true); err = ovl_create_real(wdir, newdentry, cattr, hardlink, true);
if (err) if (err)
goto out_dput2; goto out_dput2;
...@@ -427,10 +426,11 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, ...@@ -427,10 +426,11 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
* mode could have been mutilated due to umask (e.g. sgid directory) * mode could have been mutilated due to umask (e.g. sgid directory)
*/ */
if (!hardlink && if (!hardlink &&
!S_ISLNK(stat->mode) && newdentry->d_inode->i_mode != stat->mode) { !S_ISLNK(cattr->mode) &&
newdentry->d_inode->i_mode != cattr->mode) {
struct iattr attr = { struct iattr attr = {
.ia_valid = ATTR_MODE, .ia_valid = ATTR_MODE,
.ia_mode = stat->mode, .ia_mode = cattr->mode,
}; };
inode_lock(newdentry->d_inode); inode_lock(newdentry->d_inode);
err = notify_change(newdentry, &attr, NULL); err = notify_change(newdentry, &attr, NULL);
...@@ -450,7 +450,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, ...@@ -450,7 +450,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
goto out_cleanup; goto out_cleanup;
} }
if (!hardlink && S_ISDIR(stat->mode)) { if (!hardlink && S_ISDIR(cattr->mode)) {
err = ovl_set_opaque(dentry, newdentry); err = ovl_set_opaque(dentry, newdentry);
if (err) if (err)
goto out_cleanup; goto out_cleanup;
...@@ -487,8 +487,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, ...@@ -487,8 +487,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
} }
static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
struct kstat *stat, const char *link, struct cattr *attr, struct dentry *hardlink)
struct dentry *hardlink)
{ {
int err; int err;
const struct cred *old_cred; const struct cred *old_cred;
...@@ -506,7 +505,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, ...@@ -506,7 +505,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
override_cred->fsgid = inode->i_gid; override_cred->fsgid = inode->i_gid;
if (!hardlink) { if (!hardlink) {
err = security_dentry_create_files_as(dentry, err = security_dentry_create_files_as(dentry,
stat->mode, &dentry->d_name, old_cred, attr->mode, &dentry->d_name, old_cred,
override_cred); override_cred);
if (err) { if (err) {
put_cred(override_cred); put_cred(override_cred);
...@@ -517,11 +516,11 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, ...@@ -517,11 +516,11 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
put_cred(override_cred); put_cred(override_cred);
if (!ovl_dentry_is_whiteout(dentry)) if (!ovl_dentry_is_whiteout(dentry))
err = ovl_create_upper(dentry, inode, stat, link, err = ovl_create_upper(dentry, inode, attr,
hardlink); hardlink);
else else
err = ovl_create_over_whiteout(dentry, inode, stat, err = ovl_create_over_whiteout(dentry, inode, attr,
link, hardlink); hardlink);
} }
out_revert_creds: out_revert_creds:
revert_creds(old_cred); revert_creds(old_cred);
...@@ -540,8 +539,9 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev, ...@@ -540,8 +539,9 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
{ {
int err; int err;
struct inode *inode; struct inode *inode;
struct kstat stat = { struct cattr attr = {
.rdev = rdev, .rdev = rdev,
.link = link,
}; };
err = ovl_want_write(dentry); err = ovl_want_write(dentry);
...@@ -554,9 +554,9 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev, ...@@ -554,9 +554,9 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
goto out_drop_write; goto out_drop_write;
inode_init_owner(inode, dentry->d_parent->d_inode, mode); inode_init_owner(inode, dentry->d_parent->d_inode, mode);
stat.mode = inode->i_mode; attr.mode = inode->i_mode;
err = ovl_create_or_link(dentry, inode, &stat, link, NULL); err = ovl_create_or_link(dentry, inode, &attr, NULL);
if (err) if (err)
iput(inode); iput(inode);
...@@ -610,7 +610,7 @@ static int ovl_link(struct dentry *old, struct inode *newdir, ...@@ -610,7 +610,7 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
inode = d_inode(old); inode = d_inode(old);
ihold(inode); ihold(inode);
err = ovl_create_or_link(new, inode, NULL, NULL, ovl_dentry_upper(old)); err = ovl_create_or_link(new, inode, NULL, ovl_dentry_upper(old));
if (err) if (err)
iput(inode); iput(inode);
......
...@@ -212,8 +212,13 @@ static inline void ovl_copyattr(struct inode *from, struct inode *to) ...@@ -212,8 +212,13 @@ static inline void ovl_copyattr(struct inode *from, struct inode *to)
/* dir.c */ /* dir.c */
extern const struct inode_operations ovl_dir_inode_operations; extern const struct inode_operations ovl_dir_inode_operations;
struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry); struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry);
struct cattr {
dev_t rdev;
umode_t mode;
const char *link;
};
int ovl_create_real(struct inode *dir, struct dentry *newdentry, int ovl_create_real(struct inode *dir, struct dentry *newdentry,
struct kstat *stat, const char *link, struct cattr *attr,
struct dentry *hardlink, bool debug); struct dentry *hardlink, bool debug);
void ovl_cleanup(struct inode *dir, struct dentry *dentry); void ovl_cleanup(struct inode *dir, struct dentry *dentry);
......
...@@ -354,12 +354,9 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt, ...@@ -354,12 +354,9 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt,
strlen(OVL_WORKDIR_NAME)); strlen(OVL_WORKDIR_NAME));
if (!IS_ERR(work)) { if (!IS_ERR(work)) {
struct kstat stat = {
.mode = S_IFDIR | 0,
};
struct iattr attr = { struct iattr attr = {
.ia_valid = ATTR_MODE, .ia_valid = ATTR_MODE,
.ia_mode = stat.mode, .ia_mode = S_IFDIR | 0,
}; };
if (work->d_inode) { if (work->d_inode) {
...@@ -373,7 +370,9 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt, ...@@ -373,7 +370,9 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt,
goto retry; goto retry;
} }
err = ovl_create_real(dir, work, &stat, NULL, NULL, true); err = ovl_create_real(dir, work,
&(struct cattr){.mode = S_IFDIR | 0},
NULL, true);
if (err) if (err)
goto out_dput; goto out_dput;
......
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