aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2015-06-22 07:53:48 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2015-06-22 07:53:48 -0400
commit7c03b5d45b8eebf0111125053d8fe887cc262ba6 (patch)
treead8008cde20dea6cae41dd0613d1d72833d15a0b
parenta6f15d9a756571babbb2b2cd4fdd1b64a5de232b (diff)
ovl: allow distributed fs as lower layer
Allow filesystems with .d_revalidate as lower layer(s), but not as upper layer. For local filesystems the rule was that modifications on the layers directly while being part of the overlay results in undefined behavior. This can easily be extended to distributed filesystems: we assume the tree used as lower layer is static, which means ->d_revalidate() should always return "1". If that is not the case, return -ESTALE, don't try to work around the modification. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r--fs/overlayfs/super.c113
1 files changed, 88 insertions, 25 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index de9d2ee68ccf..8a08c582bc22 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -273,10 +273,57 @@ static void ovl_dentry_release(struct dentry *dentry)
273 } 273 }
274} 274}
275 275
276static int ovl_dentry_revalidate(struct dentry *dentry, unsigned int flags)
277{
278 struct ovl_entry *oe = dentry->d_fsdata;
279 unsigned int i;
280 int ret = 1;
281
282 for (i = 0; i < oe->numlower; i++) {
283 struct dentry *d = oe->lowerstack[i].dentry;
284
285 if (d->d_flags & DCACHE_OP_REVALIDATE) {
286 ret = d->d_op->d_revalidate(d, flags);
287 if (ret < 0)
288 return ret;
289 if (!ret) {
290 if (!(flags & LOOKUP_RCU))
291 d_invalidate(d);
292 return -ESTALE;
293 }
294 }
295 }
296 return 1;
297}
298
299static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
300{
301 struct ovl_entry *oe = dentry->d_fsdata;
302 unsigned int i;
303 int ret = 1;
304
305 for (i = 0; i < oe->numlower; i++) {
306 struct dentry *d = oe->lowerstack[i].dentry;
307
308 if (d->d_flags & DCACHE_OP_WEAK_REVALIDATE) {
309 ret = d->d_op->d_weak_revalidate(d, flags);
310 if (ret <= 0)
311 break;
312 }
313 }
314 return ret;
315}
316
276static const struct dentry_operations ovl_dentry_operations = { 317static const struct dentry_operations ovl_dentry_operations = {
277 .d_release = ovl_dentry_release, 318 .d_release = ovl_dentry_release,
278}; 319};
279 320
321static const struct dentry_operations ovl_reval_dentry_operations = {
322 .d_release = ovl_dentry_release,
323 .d_revalidate = ovl_dentry_revalidate,
324 .d_weak_revalidate = ovl_dentry_weak_revalidate,
325};
326
280static struct ovl_entry *ovl_alloc_entry(unsigned int numlower) 327static struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
281{ 328{
282 size_t size = offsetof(struct ovl_entry, lowerstack[numlower]); 329 size_t size = offsetof(struct ovl_entry, lowerstack[numlower]);
@@ -288,6 +335,20 @@ static struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
288 return oe; 335 return oe;
289} 336}
290 337
338static bool ovl_dentry_remote(struct dentry *dentry)
339{
340 return dentry->d_flags &
341 (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
342}
343
344static bool ovl_dentry_weird(struct dentry *dentry)
345{
346 return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT |
347 DCACHE_MANAGE_TRANSIT |
348 DCACHE_OP_HASH |
349 DCACHE_OP_COMPARE);
350}
351
291static inline struct dentry *ovl_lookup_real(struct dentry *dir, 352static inline struct dentry *ovl_lookup_real(struct dentry *dir,
292 struct qstr *name) 353 struct qstr *name)
293{ 354{
@@ -303,9 +364,9 @@ static inline struct dentry *ovl_lookup_real(struct dentry *dir,
303 } else if (!dentry->d_inode) { 364 } else if (!dentry->d_inode) {
304 dput(dentry); 365 dput(dentry);
305 dentry = NULL; 366 dentry = NULL;
306 } else if (dentry->d_flags & DCACHE_MANAGED_DENTRY) { 367 } else if (ovl_dentry_weird(dentry)) {
307 dput(dentry); 368 dput(dentry);
308 /* Don't support traversing automounts */ 369 /* Don't support traversing automounts and other weirdness */
309 dentry = ERR_PTR(-EREMOTE); 370 dentry = ERR_PTR(-EREMOTE);
310 } 371 }
311 return dentry; 372 return dentry;
@@ -354,6 +415,11 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
354 goto out; 415 goto out;
355 416
356 if (this) { 417 if (this) {
418 if (unlikely(ovl_dentry_remote(this))) {
419 dput(this);
420 err = -EREMOTE;
421 goto out;
422 }
357 if (ovl_is_whiteout(this)) { 423 if (ovl_is_whiteout(this)) {
358 dput(this); 424 dput(this);
359 this = NULL; 425 this = NULL;
@@ -698,25 +764,6 @@ static void ovl_unescape(char *s)
698 } 764 }
699} 765}
700 766
701static bool ovl_is_allowed_fs_type(struct dentry *root)
702{
703 const struct dentry_operations *dop = root->d_op;
704
705 /*
706 * We don't support:
707 * - autofs
708 * - filesystems with revalidate (FIXME for lower layer)
709 * - filesystems with case insensitive names
710 */
711 if (dop &&
712 (dop->d_manage ||
713 dop->d_revalidate || dop->d_weak_revalidate ||
714 dop->d_compare || dop->d_hash)) {
715 return false;
716 }
717 return true;
718}
719
720static int ovl_mount_dir_noesc(const char *name, struct path *path) 767static int ovl_mount_dir_noesc(const char *name, struct path *path)
721{ 768{
722 int err = -EINVAL; 769 int err = -EINVAL;
@@ -731,7 +778,7 @@ static int ovl_mount_dir_noesc(const char *name, struct path *path)
731 goto out; 778 goto out;
732 } 779 }
733 err = -EINVAL; 780 err = -EINVAL;
734 if (!ovl_is_allowed_fs_type(path->dentry)) { 781 if (ovl_dentry_weird(path->dentry)) {
735 pr_err("overlayfs: filesystem on '%s' not supported\n", name); 782 pr_err("overlayfs: filesystem on '%s' not supported\n", name);
736 goto out_put; 783 goto out_put;
737 } 784 }
@@ -755,13 +802,21 @@ static int ovl_mount_dir(const char *name, struct path *path)
755 if (tmp) { 802 if (tmp) {
756 ovl_unescape(tmp); 803 ovl_unescape(tmp);
757 err = ovl_mount_dir_noesc(tmp, path); 804 err = ovl_mount_dir_noesc(tmp, path);
805
806 if (!err)
807 if (ovl_dentry_remote(path->dentry)) {
808 pr_err("overlayfs: filesystem on '%s' not supported as upperdir\n",
809 tmp);
810 path_put(path);
811 err = -EINVAL;
812 }
758 kfree(tmp); 813 kfree(tmp);
759 } 814 }
760 return err; 815 return err;
761} 816}
762 817
763static int ovl_lower_dir(const char *name, struct path *path, long *namelen, 818static int ovl_lower_dir(const char *name, struct path *path, long *namelen,
764 int *stack_depth) 819 int *stack_depth, bool *remote)
765{ 820{
766 int err; 821 int err;
767 struct kstatfs statfs; 822 struct kstatfs statfs;
@@ -778,6 +833,9 @@ static int ovl_lower_dir(const char *name, struct path *path, long *namelen,
778 *namelen = max(*namelen, statfs.f_namelen); 833 *namelen = max(*namelen, statfs.f_namelen);
779 *stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth); 834 *stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth);
780 835
836 if (ovl_dentry_remote(path->dentry))
837 *remote = true;
838
781 return 0; 839 return 0;
782 840
783out_put: 841out_put:
@@ -831,6 +889,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
831 unsigned int numlower; 889 unsigned int numlower;
832 unsigned int stacklen = 0; 890 unsigned int stacklen = 0;
833 unsigned int i; 891 unsigned int i;
892 bool remote = false;
834 int err; 893 int err;
835 894
836 err = -ENOMEM; 895 err = -ENOMEM;
@@ -904,7 +963,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
904 lower = lowertmp; 963 lower = lowertmp;
905 for (numlower = 0; numlower < stacklen; numlower++) { 964 for (numlower = 0; numlower < stacklen; numlower++) {
906 err = ovl_lower_dir(lower, &stack[numlower], 965 err = ovl_lower_dir(lower, &stack[numlower],
907 &ufs->lower_namelen, &sb->s_stack_depth); 966 &ufs->lower_namelen, &sb->s_stack_depth,
967 &remote);
908 if (err) 968 if (err)
909 goto out_put_lowerpath; 969 goto out_put_lowerpath;
910 970
@@ -962,7 +1022,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
962 if (!ufs->upper_mnt) 1022 if (!ufs->upper_mnt)
963 sb->s_flags |= MS_RDONLY; 1023 sb->s_flags |= MS_RDONLY;
964 1024
965 sb->s_d_op = &ovl_dentry_operations; 1025 if (remote)
1026 sb->s_d_op = &ovl_reval_dentry_operations;
1027 else
1028 sb->s_d_op = &ovl_dentry_operations;
966 1029
967 err = -ENOMEM; 1030 err = -ENOMEM;
968 oe = ovl_alloc_entry(numlower); 1031 oe = ovl_alloc_entry(numlower);