diff options
Diffstat (limited to 'fs/overlayfs')
| -rw-r--r-- | fs/overlayfs/file.c | 23 | ||||
| -rw-r--r-- | fs/overlayfs/inode.c | 10 | ||||
| -rw-r--r-- | fs/overlayfs/super.c | 26 |
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 | ||
| 334 | static 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 | |||
| 337 | static long ovl_real_ioctl(struct file *file, unsigned int cmd, | 353 | static 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 | ||
| 507 | const 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; |
| 1006 | out: | 1007 | out: |
| 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; |
