diff options
Diffstat (limited to 'fs/overlayfs')
| -rw-r--r-- | fs/overlayfs/copy_up.c | 2 | ||||
| -rw-r--r-- | fs/overlayfs/file.c | 25 | ||||
| -rw-r--r-- | fs/overlayfs/inode.c | 10 | ||||
| -rw-r--r-- | fs/overlayfs/namei.c | 2 | ||||
| -rw-r--r-- | fs/overlayfs/overlayfs.h | 4 | ||||
| -rw-r--r-- | fs/overlayfs/super.c | 26 | ||||
| -rw-r--r-- | fs/overlayfs/util.c | 3 | 
7 files changed, 52 insertions, 20 deletions
| diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 296037afecdb..1cc797a08a5b 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -141,7 +141,7 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)  	}  	/* Try to use clone_file_range to clone up within the same fs */ -	error = vfs_clone_file_range(old_file, 0, new_file, 0, len); +	error = do_clone_file_range(old_file, 0, new_file, 0, len);  	if (!error)  		goto out;  	/* Couldn't clone, so now we try to copy the data */ diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 32e9282893c9..986313da0c88 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -131,9 +131,6 @@ static int ovl_open(struct inode *inode, struct file *file)  	if (IS_ERR(realfile))  		return PTR_ERR(realfile); -	/* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO */ -	file->f_mapping = realfile->f_mapping; -  	file->private_data = realfile;  	return 0; @@ -243,8 +240,10 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)  		goto out_unlock;  	old_cred = ovl_override_creds(file_inode(file)->i_sb); +	file_start_write(real.file);  	ret = vfs_iter_write(real.file, iter, &iocb->ki_pos,  			     ovl_iocb_to_rwf(iocb)); +	file_end_write(real.file);  	revert_creds(old_cred);  	/* Update size */ @@ -334,6 +333,25 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len  	return ret;  } +static int ovl_fadvise(struct file *file, loff_t offset, loff_t len, int advice) +{ +	struct fd real; +	const struct cred *old_cred; +	int ret; + +	ret = ovl_real_fdget(file, &real); +	if (ret) +		return ret; + +	old_cred = ovl_override_creds(file_inode(file)->i_sb); +	ret = vfs_fadvise(real.file, offset, len, advice); +	revert_creds(old_cred); + +	fdput(real); + +	return ret; +} +  static long ovl_real_ioctl(struct file *file, unsigned int cmd,  			   unsigned long arg)  { @@ -502,6 +520,7 @@ const struct file_operations ovl_file_operations = {  	.fsync		= ovl_fsync,  	.mmap		= ovl_mmap,  	.fallocate	= ovl_fallocate, +	.fadvise	= ovl_fadvise,  	.unlocked_ioctl	= ovl_ioctl,  	.compat_ioctl	= ovl_compat_ioctl, diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index e0bb217c01e2..3b7ed5d2279c 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -467,6 +467,10 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,  		return -EOPNOTSUPP;  	old_cred = ovl_override_creds(inode->i_sb); + +	if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC) +		filemap_write_and_wait(realinode->i_mapping); +  	err = realinode->i_op->fiemap(realinode, fieinfo, start, len);  	revert_creds(old_cred); @@ -500,6 +504,11 @@ static const struct inode_operations ovl_special_inode_operations = {  	.update_time	= ovl_update_time,  }; +static const struct address_space_operations ovl_aops = { +	/* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO */ +	.direct_IO		= noop_direct_IO, +}; +  /*   * It is possible to stack overlayfs instance on top of another   * overlayfs instance as lower layer. We need to annonate the @@ -571,6 +580,7 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev,  	case S_IFREG:  		inode->i_op = &ovl_file_inode_operations;  		inode->i_fop = &ovl_file_operations; +		inode->i_mapping->a_ops = &ovl_aops;  		break;  	case S_IFDIR: diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index f28711846dd6..9c0ca6a7becf 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -686,7 +686,7 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,  			index = NULL;  			goto out;  		} -		pr_warn_ratelimited("overlayfs: failed inode index lookup (ino=%lu, key=%*s, err=%i);\n" +		pr_warn_ratelimited("overlayfs: failed inode index lookup (ino=%lu, key=%.*s, err=%i);\n"  				    "overlayfs: mount with '-o index=off' to disable inodes index.\n",  				    d_inode(origin)->i_ino, name.len, name.name,  				    err); diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index f61839e1054c..a3c0d9584312 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -152,8 +152,8 @@ static inline int ovl_do_setxattr(struct dentry *dentry, const char *name,  				  const void *value, size_t size, int flags)  {  	int err = vfs_setxattr(dentry, name, value, size, flags); -	pr_debug("setxattr(%pd2, \"%s\", \"%*s\", 0x%x) = %i\n", -		 dentry, name, (int) size, (char *) value, flags, err); +	pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, 0x%x) = %i\n", +		 dentry, name, min((int)size, 48), value, size, flags, err);  	return err;  } diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 2e0fc93c2c06..30adc9d408a0 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -982,16 +982,6 @@ static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath)  	if (err)  		goto out; -	err = -EBUSY; -	if (ovl_inuse_trylock(upperpath->dentry)) { -		ofs->upperdir_locked = true; -	} else if (ofs->config.index) { -		pr_err("overlayfs: upperdir is in-use by another mount, mount with '-o index=off' to override exclusive upperdir protection.\n"); -		goto out; -	} else { -		pr_warn("overlayfs: upperdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); -	} -  	upper_mnt = clone_private_mount(upperpath);  	err = PTR_ERR(upper_mnt);  	if (IS_ERR(upper_mnt)) { @@ -1002,6 +992,17 @@ static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath)  	/* Don't inherit atime flags */  	upper_mnt->mnt_flags &= ~(MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME);  	ofs->upper_mnt = upper_mnt; + +	err = -EBUSY; +	if (ovl_inuse_trylock(ofs->upper_mnt->mnt_root)) { +		ofs->upperdir_locked = true; +	} else if (ofs->config.index) { +		pr_err("overlayfs: upperdir is in-use by another mount, mount with '-o index=off' to override exclusive upperdir protection.\n"); +		goto out; +	} else { +		pr_warn("overlayfs: upperdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); +	} +  	err = 0;  out:  	return err; @@ -1101,8 +1102,10 @@ static int ovl_get_workdir(struct ovl_fs *ofs, struct path *upperpath)  		goto out;  	} +	ofs->workbasedir = dget(workpath.dentry); +  	err = -EBUSY; -	if (ovl_inuse_trylock(workpath.dentry)) { +	if (ovl_inuse_trylock(ofs->workbasedir)) {  		ofs->workdir_locked = true;  	} else if (ofs->config.index) {  		pr_err("overlayfs: workdir is in-use by another mount, mount with '-o index=off' to override exclusive workdir protection.\n"); @@ -1111,7 +1114,6 @@ static int ovl_get_workdir(struct ovl_fs *ofs, struct path *upperpath)  		pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n");  	} -	ofs->workbasedir = dget(workpath.dentry);  	err = ovl_make_workdir(ofs, &workpath);  	if (err)  		goto out; diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 8cfb62cc8672..ace4fe4c39a9 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -683,7 +683,7 @@ static void ovl_cleanup_index(struct dentry *dentry)  	struct dentry *upperdentry = ovl_dentry_upper(dentry);  	struct dentry *index = NULL;  	struct inode *inode; -	struct qstr name; +	struct qstr name = { };  	int err;  	err = ovl_get_index_name(lowerdentry, &name); @@ -726,6 +726,7 @@ static void ovl_cleanup_index(struct dentry *dentry)  		goto fail;  out: +	kfree(name.name);  	dput(index);  	return; |