summaryrefslogtreecommitdiff
path: root/fs/overlayfs
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@redhat.com>2018-05-11 18:49:33 +0300
committerMiklos Szeredi <mszeredi@redhat.com>2018-07-20 10:56:17 +0300
commit997336f2c3053b74ec8c9d2d368ddd960f2fc8b6 (patch)
treea66cb2bb959049f180195aaedb482e9556832833 /fs/overlayfs
parentd1e6f6a94d6cefed2b6f7a222853ebcd2805b43b (diff)
downloadlinux-997336f2c3053b74ec8c9d2d368ddd960f2fc8b6.tar.xz
ovl: Do not do metadata only copy-up for truncate operation
truncate should copy up full file (and not do metacopy only), otherwise it will be broken. For example, use truncate to increase size of a file so that any read beyong existing size will return null bytes. If we don't copy up full file, then we end up opening lower file and read from it only reads upto the old size (and not new size after truncate). Hence to avoid such situations, copy up data as well when file size changes. So far it was being done by d_real(O_WRONLY) call in truncate() path. Now that patch has been reverted. So force full copy up in ovl_setattr() if size of file is changing. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs')
-rw-r--r--fs/overlayfs/inode.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 7c7092aaf9b4..e0bb217c01e2 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -19,6 +19,7 @@
int ovl_setattr(struct dentry *dentry, struct iattr *attr)
{
int err;
+ bool full_copy_up = false;
struct dentry *upperdentry;
const struct cred *old_cred;
@@ -36,9 +37,15 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
err = -ETXTBSY;
if (atomic_read(&realinode->i_writecount) < 0)
goto out_drop_write;
+
+ /* Truncate should trigger data copy up as well */
+ full_copy_up = true;
}
- err = ovl_copy_up(dentry);
+ if (!full_copy_up)
+ err = ovl_copy_up(dentry);
+ else
+ err = ovl_copy_up_with_data(dentry);
if (!err) {
struct inode *winode = NULL;