|
@@ -9,6 +9,7 @@
|
|
|
|
|
|
#include <linux/fs.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/namei.h>
|
|
#include <linux/namei.h>
|
|
|
|
+#include <linux/pagemap.h>
|
|
#include <linux/xattr.h>
|
|
#include <linux/xattr.h>
|
|
#include <linux/security.h>
|
|
#include <linux/security.h>
|
|
#include <linux/mount.h>
|
|
#include <linux/mount.h>
|
|
@@ -24,12 +25,11 @@ MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
|
|
MODULE_DESCRIPTION("Overlay filesystem");
|
|
MODULE_DESCRIPTION("Overlay filesystem");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_LICENSE("GPL");
|
|
|
|
|
|
-#define OVERLAYFS_SUPER_MAGIC 0x794c7630
|
|
|
|
-
|
|
|
|
struct ovl_config {
|
|
struct ovl_config {
|
|
char *lowerdir;
|
|
char *lowerdir;
|
|
char *upperdir;
|
|
char *upperdir;
|
|
char *workdir;
|
|
char *workdir;
|
|
|
|
+ bool default_permissions;
|
|
};
|
|
};
|
|
|
|
|
|
/* private information held for overlayfs's superblock */
|
|
/* private information held for overlayfs's superblock */
|
|
@@ -154,6 +154,18 @@ struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper)
|
|
return realdentry;
|
|
return realdentry;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+struct vfsmount *ovl_entry_mnt_real(struct ovl_entry *oe, struct inode *inode,
|
|
|
|
+ bool is_upper)
|
|
|
|
+{
|
|
|
|
+ if (is_upper) {
|
|
|
|
+ struct ovl_fs *ofs = inode->i_sb->s_fs_info;
|
|
|
|
+
|
|
|
|
+ return ofs->upper_mnt;
|
|
|
|
+ } else {
|
|
|
|
+ return oe->numlower ? oe->lowerstack[0].mnt : NULL;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry)
|
|
struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry)
|
|
{
|
|
{
|
|
struct ovl_entry *oe = dentry->d_fsdata;
|
|
struct ovl_entry *oe = dentry->d_fsdata;
|
|
@@ -161,6 +173,13 @@ struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry)
|
|
return oe->cache;
|
|
return oe->cache;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+bool ovl_is_default_permissions(struct inode *inode)
|
|
|
|
+{
|
|
|
|
+ struct ovl_fs *ofs = inode->i_sb->s_fs_info;
|
|
|
|
+
|
|
|
|
+ return ofs->config.default_permissions;
|
|
|
|
+}
|
|
|
|
+
|
|
void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache)
|
|
void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache)
|
|
{
|
|
{
|
|
struct ovl_entry *oe = dentry->d_fsdata;
|
|
struct ovl_entry *oe = dentry->d_fsdata;
|
|
@@ -594,6 +613,8 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
|
|
seq_show_option(m, "upperdir", ufs->config.upperdir);
|
|
seq_show_option(m, "upperdir", ufs->config.upperdir);
|
|
seq_show_option(m, "workdir", ufs->config.workdir);
|
|
seq_show_option(m, "workdir", ufs->config.workdir);
|
|
}
|
|
}
|
|
|
|
+ if (ufs->config.default_permissions)
|
|
|
|
+ seq_puts(m, ",default_permissions");
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -618,6 +639,7 @@ enum {
|
|
OPT_LOWERDIR,
|
|
OPT_LOWERDIR,
|
|
OPT_UPPERDIR,
|
|
OPT_UPPERDIR,
|
|
OPT_WORKDIR,
|
|
OPT_WORKDIR,
|
|
|
|
+ OPT_DEFAULT_PERMISSIONS,
|
|
OPT_ERR,
|
|
OPT_ERR,
|
|
};
|
|
};
|
|
|
|
|
|
@@ -625,6 +647,7 @@ static const match_table_t ovl_tokens = {
|
|
{OPT_LOWERDIR, "lowerdir=%s"},
|
|
{OPT_LOWERDIR, "lowerdir=%s"},
|
|
{OPT_UPPERDIR, "upperdir=%s"},
|
|
{OPT_UPPERDIR, "upperdir=%s"},
|
|
{OPT_WORKDIR, "workdir=%s"},
|
|
{OPT_WORKDIR, "workdir=%s"},
|
|
|
|
+ {OPT_DEFAULT_PERMISSIONS, "default_permissions"},
|
|
{OPT_ERR, NULL}
|
|
{OPT_ERR, NULL}
|
|
};
|
|
};
|
|
|
|
|
|
@@ -685,6 +708,10 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case OPT_DEFAULT_PERMISSIONS:
|
|
|
|
+ config->default_permissions = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
default:
|
|
default:
|
|
pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p);
|
|
pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -910,6 +937,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
|
}
|
|
}
|
|
|
|
|
|
sb->s_stack_depth = 0;
|
|
sb->s_stack_depth = 0;
|
|
|
|
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
|
|
if (ufs->config.upperdir) {
|
|
if (ufs->config.upperdir) {
|
|
if (!ufs->config.workdir) {
|
|
if (!ufs->config.workdir) {
|
|
pr_err("overlayfs: missing 'workdir'\n");
|
|
pr_err("overlayfs: missing 'workdir'\n");
|
|
@@ -1053,6 +1081,9 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
|
|
|
root_dentry->d_fsdata = oe;
|
|
root_dentry->d_fsdata = oe;
|
|
|
|
|
|
|
|
+ ovl_copyattr(ovl_dentry_real(root_dentry)->d_inode,
|
|
|
|
+ root_dentry->d_inode);
|
|
|
|
+
|
|
sb->s_magic = OVERLAYFS_SUPER_MAGIC;
|
|
sb->s_magic = OVERLAYFS_SUPER_MAGIC;
|
|
sb->s_op = &ovl_super_operations;
|
|
sb->s_op = &ovl_super_operations;
|
|
sb->s_root = root_dentry;
|
|
sb->s_root = root_dentry;
|