Skip to content

Commit

Permalink
ovl: Open file with data except for the case of fsync
Browse files Browse the repository at this point in the history
ovl_open() should open file which contains data and not open metacopy
inode.  With the introduction of metacopy inodes, with current
implementaion we will end up opening metacopy inode as well.

But there can be certain circumstances like ovl_fsync() where we want to
allow opening a metacopy inode instead.

Hence, change ovl_open_realfile() and and add extra parameter which
specifies whether to allow opening metacopy inode or not.  If this
parameter is false, we look for data inode and open that.

This should allow covering both the cases.

Signed-off-by: Vivek Goyal <[email protected]>
Reviewed-by: Amir Goldstein <[email protected]>
Signed-off-by: Miklos Szeredi <[email protected]>
  • Loading branch information
rhvgoyal authored and Miklos Szeredi committed Jul 20, 2018
1 parent 4823d49 commit 8c444d2
Showing 1 changed file with 30 additions and 9 deletions.
39 changes: 30 additions & 9 deletions fs/overlayfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,20 @@
#include <linux/uio.h>
#include "overlayfs.h"

static struct file *ovl_open_realfile(const struct file *file)
static char ovl_whatisit(struct inode *inode, struct inode *realinode)
{
if (realinode != ovl_inode_upper(inode))
return 'l';
if (ovl_has_upperdata(inode))
return 'u';
else
return 'm';
}

static struct file *ovl_open_realfile(const struct file *file,
struct inode *realinode)
{
struct inode *inode = file_inode(file);
struct inode *upperinode = ovl_inode_upper(inode);
struct inode *realinode = upperinode ?: ovl_inode_lower(inode);
struct file *realfile;
const struct cred *old_cred;

Expand All @@ -27,7 +36,7 @@ static struct file *ovl_open_realfile(const struct file *file)
revert_creds(old_cred);

pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
file, file, upperinode ? 'u' : 'l', file->f_flags,
file, file, ovl_whatisit(inode, realinode), file->f_flags,
realfile, IS_ERR(realfile) ? 0 : realfile->f_flags);

return realfile;
Expand Down Expand Up @@ -71,17 +80,24 @@ static int ovl_change_flags(struct file *file, unsigned int flags)
return 0;
}

static int ovl_real_fdget(const struct file *file, struct fd *real)
static int ovl_real_fdget_meta(const struct file *file, struct fd *real,
bool allow_meta)
{
struct inode *inode = file_inode(file);
struct inode *realinode;

real->flags = 0;
real->file = file->private_data;

if (allow_meta)
realinode = ovl_inode_real(inode);
else
realinode = ovl_inode_realdata(inode);

/* Has it been copied up since we'd opened it? */
if (unlikely(file_inode(real->file) != ovl_inode_real(inode))) {
if (unlikely(file_inode(real->file) != realinode)) {
real->flags = FDPUT_FPUT;
real->file = ovl_open_realfile(file);
real->file = ovl_open_realfile(file, realinode);

return PTR_ERR_OR_ZERO(real->file);
}
Expand All @@ -93,6 +109,11 @@ static int ovl_real_fdget(const struct file *file, struct fd *real)
return 0;
}

static int ovl_real_fdget(const struct file *file, struct fd *real)
{
return ovl_real_fdget_meta(file, real, false);
}

static int ovl_open(struct inode *inode, struct file *file)
{
struct dentry *dentry = file_dentry(file);
Expand All @@ -106,7 +127,7 @@ static int ovl_open(struct inode *inode, struct file *file)
/* No longer need these flags, so don't pass them on to underlying fs */
file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

realfile = ovl_open_realfile(file);
realfile = ovl_open_realfile(file, ovl_inode_realdata(inode));
if (IS_ERR(realfile))
return PTR_ERR(realfile);

Expand Down Expand Up @@ -243,7 +264,7 @@ static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
const struct cred *old_cred;
int ret;

ret = ovl_real_fdget(file, &real);
ret = ovl_real_fdget_meta(file, &real, !datasync);
if (ret)
return ret;

Expand Down

0 comments on commit 8c444d2

Please sign in to comment.