aboutsummaryrefslogtreecommitdiffstats
path: root/fs/overlayfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/overlayfs')
-rw-r--r--fs/overlayfs/file.c23
-rw-r--r--fs/overlayfs/inode.c10
-rw-r--r--fs/overlayfs/super.c26
3 files changed, 44 insertions, 15 deletions
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
index 32e9282893c9..aeaefd2a551b 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)
131 if (IS_ERR(realfile)) 131 if (IS_ERR(realfile))
132 return PTR_ERR(realfile); 132 return PTR_ERR(realfile);
133 133
134 /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO */
135 file->f_mapping = realfile->f_mapping;
136
137 file->private_data = realfile; 134 file->private_data = realfile;
138 135
139 return 0; 136 return 0;
@@ -334,6 +331,25 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len
334 return ret; 331 return ret;
335} 332}
336 333
334static int ovl_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
335{
336 struct fd real;
337 const struct cred *old_cred;
338 int ret;
339
340 ret = ovl_real_fdget(file, &real);
341 if (ret)
342 return ret;
343
344 old_cred = ovl_override_creds(file_inode(file)->i_sb);
345 ret = vfs_fadvise(real.file, offset, len, advice);
346 revert_creds(old_cred);
347
348 fdput(real);
349
350 return ret;
351}
352
337static long ovl_real_ioctl(struct file *file, unsigned int cmd, 353static long ovl_real_ioctl(struct file *file, unsigned int cmd,
338 unsigned long arg) 354 unsigned long arg)
339{ 355{
@@ -502,6 +518,7 @@ const struct file_operations ovl_file_operations = {
502 .fsync = ovl_fsync, 518 .fsync = ovl_fsync,
503 .mmap = ovl_mmap, 519 .mmap = ovl_mmap,
504 .fallocate = ovl_fallocate, 520 .fallocate = ovl_fallocate,
521 .fadvise = ovl_fadvise,
505 .unlocked_ioctl = ovl_ioctl, 522 .unlocked_ioctl = ovl_ioctl,
506 .compat_ioctl = ovl_compat_ioctl, 523 .compat_ioctl = ovl_compat_ioctl,
507 524
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index e0bb217c01e2..b6ac545b5a32 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,
467 return -EOPNOTSUPP; 467 return -EOPNOTSUPP;
468 468
469 old_cred = ovl_override_creds(inode->i_sb); 469 old_cred = ovl_override_creds(inode->i_sb);
470
471 if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC)
472 filemap_write_and_wait(realinode->i_mapping);
473
470 err = realinode->i_op->fiemap(realinode, fieinfo, start, len); 474 err = realinode->i_op->fiemap(realinode, fieinfo, start, len);
471 revert_creds(old_cred); 475 revert_creds(old_cred);
472 476
@@ -500,6 +504,11 @@ static const struct inode_operations ovl_special_inode_operations = {
500 .update_time = ovl_update_time, 504 .update_time = ovl_update_time,
501}; 505};
502 506
507const struct address_space_operations ovl_aops = {
508 /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO */
509 .direct_IO = noop_direct_IO,
510};
511
503/* 512/*
504 * It is possible to stack overlayfs instance on top of another 513 * It is possible to stack overlayfs instance on top of another
505 * overlayfs instance as lower layer. We need to annonate the 514 * 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,
571 case S_IFREG: 580 case S_IFREG:
572 inode->i_op = &ovl_file_inode_operations; 581 inode->i_op = &ovl_file_inode_operations;
573 inode->i_fop = &ovl_file_operations; 582 inode->i_fop = &ovl_file_operations;
583 inode->i_mapping->a_ops = &ovl_aops;
574 break; 584 break;
575 585
576 case S_IFDIR: 586 case S_IFDIR:
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)
982 if (err) 982 if (err)
983 goto out; 983 goto out;
984 984
985 err = -EBUSY;
986 if (ovl_inuse_trylock(upperpath->dentry)) {
987 ofs->upperdir_locked = true;
988 } else if (ofs->config.index) {
989 pr_err("overlayfs: upperdir is in-use by another mount, mount with '-o index=off' to override exclusive upperdir protection.\n");
990 goto out;
991 } else {
992 pr_warn("overlayfs: upperdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n");
993 }
994
995 upper_mnt = clone_private_mount(upperpath); 985 upper_mnt = clone_private_mount(upperpath);
996 err = PTR_ERR(upper_mnt); 986 err = PTR_ERR(upper_mnt);
997 if (IS_ERR(upper_mnt)) { 987 if (IS_ERR(upper_mnt)) {
@@ -1002,6 +992,17 @@ static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath)
1002 /* Don't inherit atime flags */ 992 /* Don't inherit atime flags */
1003 upper_mnt->mnt_flags &= ~(MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME); 993 upper_mnt->mnt_flags &= ~(MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME);
1004 ofs->upper_mnt = upper_mnt; 994 ofs->upper_mnt = upper_mnt;
995
996 err = -EBUSY;
997 if (ovl_inuse_trylock(ofs->upper_mnt->mnt_root)) {
998 ofs->upperdir_locked = true;
999 } else if (ofs->config.index) {
1000 pr_err("overlayfs: upperdir is in-use by another mount, mount with '-o index=off' to override exclusive upperdir protection.\n");
1001 goto out;
1002 } else {
1003 pr_warn("overlayfs: upperdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n");
1004 }
1005
1005 err = 0; 1006 err = 0;
1006out: 1007out:
1007 return err; 1008 return err;
@@ -1101,8 +1102,10 @@ static int ovl_get_workdir(struct ovl_fs *ofs, struct path *upperpath)
1101 goto out; 1102 goto out;
1102 } 1103 }
1103 1104
1105 ofs->workbasedir = dget(workpath.dentry);
1106
1104 err = -EBUSY; 1107 err = -EBUSY;
1105 if (ovl_inuse_trylock(workpath.dentry)) { 1108 if (ovl_inuse_trylock(ofs->workbasedir)) {
1106 ofs->workdir_locked = true; 1109 ofs->workdir_locked = true;
1107 } else if (ofs->config.index) { 1110 } else if (ofs->config.index) {
1108 pr_err("overlayfs: workdir is in-use by another mount, mount with '-o index=off' to override exclusive workdir protection.\n"); 1111 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)
1111 pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); 1114 pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n");
1112 } 1115 }
1113 1116
1114 ofs->workbasedir = dget(workpath.dentry);
1115 err = ovl_make_workdir(ofs, &workpath); 1117 err = ovl_make_workdir(ofs, &workpath);
1116 if (err) 1118 if (err)
1117 goto out; 1119 goto out;