aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2014-12-12 18:59:51 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2014-12-12 18:59:51 -0500
commit53a08cb9b8bccfe58f1228c7c27baf34a83da78b (patch)
treeb3019e8ea9ea3c98a198184ac4f207a11339cc4e
parentab508822cab4c84f07373cd6ad107a1fd1362831 (diff)
ovl: make upperdir optional
Make "upperdir=" mount option optional. If "upperdir=" is not given, then the "workdir=" option is also optional (and ignored if given). Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r--fs/overlayfs/super.c83
1 files changed, 47 insertions, 36 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 592370ff453a..35bb0adf10cf 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -516,8 +516,10 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
516 struct ovl_fs *ufs = sb->s_fs_info; 516 struct ovl_fs *ufs = sb->s_fs_info;
517 517
518 seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir); 518 seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir);
519 seq_printf(m, ",upperdir=%s", ufs->config.upperdir); 519 if (ufs->config.upperdir) {
520 seq_printf(m, ",workdir=%s", ufs->config.workdir); 520 seq_printf(m, ",upperdir=%s", ufs->config.upperdir);
521 seq_printf(m, ",workdir=%s", ufs->config.workdir);
522 }
521 return 0; 523 return 0;
522} 524}
523 525
@@ -768,8 +770,8 @@ static bool ovl_workdir_ok(struct dentry *workdir, struct dentry *upperdir)
768static int ovl_fill_super(struct super_block *sb, void *data, int silent) 770static int ovl_fill_super(struct super_block *sb, void *data, int silent)
769{ 771{
770 struct path lowerpath; 772 struct path lowerpath;
771 struct path upperpath; 773 struct path upperpath = { NULL, NULL };
772 struct path workpath; 774 struct path workpath = { NULL, NULL };
773 struct dentry *root_dentry; 775 struct dentry *root_dentry;
774 struct ovl_entry *oe; 776 struct ovl_entry *oe;
775 struct ovl_fs *ufs; 777 struct ovl_fs *ufs;
@@ -786,31 +788,38 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
786 if (err) 788 if (err)
787 goto out_free_config; 789 goto out_free_config;
788 790
789 /* FIXME: workdir is not needed for a R/O mount */
790 err = -EINVAL; 791 err = -EINVAL;
791 if (!ufs->config.upperdir || !ufs->config.lowerdir || 792 if (!ufs->config.lowerdir) {
792 !ufs->config.workdir) { 793 pr_err("overlayfs: missing 'lowerdir'\n");
793 pr_err("overlayfs: missing upperdir or lowerdir or workdir\n");
794 goto out_free_config; 794 goto out_free_config;
795 } 795 }
796 796
797 err = ovl_mount_dir(ufs->config.upperdir, &upperpath); 797 sb->s_stack_depth = 0;
798 if (err) 798 if (ufs->config.upperdir) {
799 goto out_free_config; 799 /* FIXME: workdir is not needed for a R/O mount */
800 if (!ufs->config.workdir) {
801 pr_err("overlayfs: missing 'workdir'\n");
802 goto out_free_config;
803 }
800 804
801 err = ovl_mount_dir(ufs->config.workdir, &workpath); 805 err = ovl_mount_dir(ufs->config.upperdir, &upperpath);
802 if (err) 806 if (err)
803 goto out_put_upperpath; 807 goto out_free_config;
804 808
805 if (upperpath.mnt != workpath.mnt) { 809 err = ovl_mount_dir(ufs->config.workdir, &workpath);
806 pr_err("overlayfs: workdir and upperdir must reside under the same mount\n"); 810 if (err)
807 goto out_put_workpath; 811 goto out_put_upperpath;
808 } 812
809 if (!ovl_workdir_ok(workpath.dentry, upperpath.dentry)) { 813 if (upperpath.mnt != workpath.mnt) {
810 pr_err("overlayfs: workdir and upperdir must be separate subtrees\n"); 814 pr_err("overlayfs: workdir and upperdir must reside under the same mount\n");
811 goto out_put_workpath; 815 goto out_put_workpath;
816 }
817 if (!ovl_workdir_ok(workpath.dentry, upperpath.dentry)) {
818 pr_err("overlayfs: workdir and upperdir must be separate subtrees\n");
819 goto out_put_workpath;
820 }
821 sb->s_stack_depth = upperpath.mnt->mnt_sb->s_stack_depth;
812 } 822 }
813 sb->s_stack_depth = upperpath.mnt->mnt_sb->s_stack_depth;
814 823
815 err = ovl_lower_dir(ufs->config.lowerdir, &lowerpath, 824 err = ovl_lower_dir(ufs->config.lowerdir, &lowerpath,
816 &ufs->lower_namelen, &sb->s_stack_depth); 825 &ufs->lower_namelen, &sb->s_stack_depth);
@@ -824,19 +833,21 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
824 goto out_put_lowerpath; 833 goto out_put_lowerpath;
825 } 834 }
826 835
827 ufs->upper_mnt = clone_private_mount(&upperpath); 836 if (ufs->config.upperdir) {
828 err = PTR_ERR(ufs->upper_mnt); 837 ufs->upper_mnt = clone_private_mount(&upperpath);
829 if (IS_ERR(ufs->upper_mnt)) { 838 err = PTR_ERR(ufs->upper_mnt);
830 pr_err("overlayfs: failed to clone upperpath\n"); 839 if (IS_ERR(ufs->upper_mnt)) {
831 goto out_put_lowerpath; 840 pr_err("overlayfs: failed to clone upperpath\n");
832 } 841 goto out_put_lowerpath;
842 }
833 843
834 ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry); 844 ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry);
835 err = PTR_ERR(ufs->workdir); 845 err = PTR_ERR(ufs->workdir);
836 if (IS_ERR(ufs->workdir)) { 846 if (IS_ERR(ufs->workdir)) {
837 pr_err("overlayfs: failed to create directory %s/%s\n", 847 pr_err("overlayfs: failed to create directory %s/%s\n",
838 ufs->config.workdir, OVL_WORKDIR_NAME); 848 ufs->config.workdir, OVL_WORKDIR_NAME);
839 goto out_put_upper_mnt; 849 goto out_put_upper_mnt;
850 }
840 } 851 }
841 852
842 ufs->lower_mnt = kcalloc(1, sizeof(struct vfsmount *), GFP_KERNEL); 853 ufs->lower_mnt = kcalloc(1, sizeof(struct vfsmount *), GFP_KERNEL);
@@ -858,8 +869,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
858 ufs->lower_mnt[0] = mnt; 869 ufs->lower_mnt[0] = mnt;
859 ufs->numlower = 1; 870 ufs->numlower = 1;
860 871
861 /* If the upper fs is r/o, we mark overlayfs r/o too */ 872 /* If the upper fs is r/o or nonexistent, we mark overlayfs r/o too */
862 if (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY) 873 if (!ufs->upper_mnt || (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY))
863 sb->s_flags |= MS_RDONLY; 874 sb->s_flags |= MS_RDONLY;
864 875
865 sb->s_d_op = &ovl_dentry_operations; 876 sb->s_d_op = &ovl_dentry_operations;