diff options
-rw-r--r-- | fs/overlayfs/super.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index c1abd66527ce..6d02ca31bb90 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -860,6 +860,41 @@ out: | |||
860 | return err; | 860 | return err; |
861 | } | 861 | } |
862 | 862 | ||
863 | static int ovl_get_workpath(struct ovl_fs *ufs, struct path *upperpath, | ||
864 | struct path *workpath) | ||
865 | { | ||
866 | int err; | ||
867 | |||
868 | err = ovl_mount_dir(ufs->config.workdir, workpath); | ||
869 | if (err) | ||
870 | goto out; | ||
871 | |||
872 | err = -EINVAL; | ||
873 | if (upperpath->mnt != workpath->mnt) { | ||
874 | pr_err("overlayfs: workdir and upperdir must reside under the same mount\n"); | ||
875 | goto out; | ||
876 | } | ||
877 | if (!ovl_workdir_ok(workpath->dentry, upperpath->dentry)) { | ||
878 | pr_err("overlayfs: workdir and upperdir must be separate subtrees\n"); | ||
879 | goto out; | ||
880 | } | ||
881 | |||
882 | err = -EBUSY; | ||
883 | if (ovl_inuse_trylock(workpath->dentry)) { | ||
884 | ufs->workdir_locked = true; | ||
885 | } else if (ufs->config.index) { | ||
886 | pr_err("overlayfs: workdir is in-use by another mount, mount with '-o index=off' to override exclusive workdir protection.\n"); | ||
887 | goto out; | ||
888 | } else { | ||
889 | pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); | ||
890 | } | ||
891 | |||
892 | ufs->workbasedir = workpath->dentry; | ||
893 | err = 0; | ||
894 | out: | ||
895 | return err; | ||
896 | } | ||
897 | |||
863 | static int ovl_fill_super(struct super_block *sb, void *data, int silent) | 898 | static int ovl_fill_super(struct super_block *sb, void *data, int silent) |
864 | { | 899 | { |
865 | struct path upperpath = { }; | 900 | struct path upperpath = { }; |
@@ -907,31 +942,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
907 | if (err) | 942 | if (err) |
908 | goto out_unlock_upperdentry; | 943 | goto out_unlock_upperdentry; |
909 | 944 | ||
910 | err = ovl_mount_dir(ufs->config.workdir, &workpath); | 945 | err = ovl_get_workpath(ufs, &upperpath, &workpath); |
911 | if (err) | 946 | if (err) |
912 | goto out_unlock_upperdentry; | 947 | goto out_unlock_workdentry; |
913 | |||
914 | err = -EINVAL; | ||
915 | if (upperpath.mnt != workpath.mnt) { | ||
916 | pr_err("overlayfs: workdir and upperdir must reside under the same mount\n"); | ||
917 | goto out_put_workpath; | ||
918 | } | ||
919 | if (!ovl_workdir_ok(workpath.dentry, upperpath.dentry)) { | ||
920 | pr_err("overlayfs: workdir and upperdir must be separate subtrees\n"); | ||
921 | goto out_put_workpath; | ||
922 | } | ||
923 | |||
924 | err = -EBUSY; | ||
925 | if (ovl_inuse_trylock(workpath.dentry)) { | ||
926 | ufs->workdir_locked = true; | ||
927 | } else if (ufs->config.index) { | ||
928 | pr_err("overlayfs: workdir is in-use by another mount, mount with '-o index=off' to override exclusive workdir protection.\n"); | ||
929 | goto out_put_workpath; | ||
930 | } else { | ||
931 | pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); | ||
932 | } | ||
933 | 948 | ||
934 | ufs->workbasedir = workpath.dentry; | ||
935 | sb->s_stack_depth = upperpath.mnt->mnt_sb->s_stack_depth; | 949 | sb->s_stack_depth = upperpath.mnt->mnt_sb->s_stack_depth; |
936 | } | 950 | } |
937 | err = -ENOMEM; | 951 | err = -ENOMEM; |
@@ -1203,7 +1217,6 @@ out_free_lowertmp: | |||
1203 | out_unlock_workdentry: | 1217 | out_unlock_workdentry: |
1204 | if (ufs->workdir_locked) | 1218 | if (ufs->workdir_locked) |
1205 | ovl_inuse_unlock(workpath.dentry); | 1219 | ovl_inuse_unlock(workpath.dentry); |
1206 | out_put_workpath: | ||
1207 | path_put(&workpath); | 1220 | path_put(&workpath); |
1208 | out_unlock_upperdentry: | 1221 | out_unlock_upperdentry: |
1209 | if (ufs->upperdir_locked) | 1222 | if (ufs->upperdir_locked) |