Skip to content

Commit

Permalink
ovl: add flag for upper in ovl_entry
Browse files Browse the repository at this point in the history
For rename, we need to ensure that an upper alias exists for hard links
before attempting the operation.  Introduce a flag in ovl_entry to track
the state of the upper alias.

Signed-off-by: Miklos Szeredi <[email protected]>
  • Loading branch information
Miklos Szeredi committed Jul 4, 2017
1 parent 23f0ab1 commit 55acc66
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 2 deletions.
1 change: 1 addition & 0 deletions fs/overlayfs/copy_up.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ static int ovl_copy_up_locked(struct ovl_copy_up_ctx *c)
if (err)
goto out_cleanup;

ovl_dentry_set_upper_alias(c->dentry);
ovl_inode_update(d_inode(c->dentry), newdentry);
out:
dput(temp);
Expand Down
1 change: 1 addition & 0 deletions fs/overlayfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
struct dentry *newdentry, bool hardlink)
{
ovl_dentry_version_inc(dentry->d_parent);
ovl_dentry_set_upper_alias(dentry);
if (!hardlink) {
ovl_inode_update(inode, newdentry);
ovl_copyattr(newdentry->d_inode, inode);
Expand Down
4 changes: 3 additions & 1 deletion fs/overlayfs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr);
dentry->d_fsdata = oe;

if (index && !upperdentry)
if (upperdentry)
ovl_dentry_set_upper_alias(dentry);
else if (index)
upperdentry = dget(index);

if (upperdentry || ctr) {
Expand Down
2 changes: 2 additions & 0 deletions fs/overlayfs/overlayfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache);
bool ovl_dentry_is_opaque(struct dentry *dentry);
bool ovl_dentry_is_whiteout(struct dentry *dentry);
void ovl_dentry_set_opaque(struct dentry *dentry);
bool ovl_dentry_has_upper_alias(struct dentry *dentry);
void ovl_dentry_set_upper_alias(struct dentry *dentry);
bool ovl_redirect_dir(struct super_block *sb);
const char *ovl_dentry_get_redirect(struct dentry *dentry);
void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect);
Expand Down
5 changes: 4 additions & 1 deletion fs/overlayfs/ovl_entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ struct ovl_fs {
/* private information held for every overlayfs dentry */
struct ovl_entry {
union {
bool opaque;
struct {
unsigned long has_upper;
bool opaque;
};
struct rcu_head rcu;
};
unsigned numlower;
Expand Down
1 change: 1 addition & 0 deletions fs/overlayfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
kfree(lowertmp);

if (upperpath.dentry) {
oe->has_upper = true;
if (ovl_is_impuredir(upperpath.dentry))
ovl_set_flag(OVL_IMPURE, d_inode(root_dentry));
}
Expand Down
19 changes: 19 additions & 0 deletions fs/overlayfs/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,25 @@ void ovl_dentry_set_opaque(struct dentry *dentry)
oe->opaque = true;
}

/*
* For hard links it's possible for ovl_dentry_upper() to return positive, while
* there's no actual upper alias for the inode. Copy up code needs to know
* about the existence of the upper alias, so it can't use ovl_dentry_upper().
*/
bool ovl_dentry_has_upper_alias(struct dentry *dentry)
{
struct ovl_entry *oe = dentry->d_fsdata;

return oe->has_upper;
}

void ovl_dentry_set_upper_alias(struct dentry *dentry)
{
struct ovl_entry *oe = dentry->d_fsdata;

oe->has_upper = true;
}

bool ovl_redirect_dir(struct super_block *sb)
{
struct ovl_fs *ofs = sb->s_fs_info;
Expand Down

0 comments on commit 55acc66

Please sign in to comment.