aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2014-10-23 18:14:38 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2014-10-23 18:14:38 -0400
commitcc2596392af3b1404421aaef828a255303c46f93 (patch)
tree5cce84e37ebeb3c0a73395af34081e080d51f0fa /fs
parente9be9d5e76e34872f0c37d72e25bc27fe9e2c54c (diff)
overlayfs: add statfs support
Add support for statfs to the overlayfs filesystem. As the upper layer is the target of all write operations assume that the space in that filesystem is the space in the overlayfs. There will be some inaccuracy as overwriting a file will copy it up and consume space we were not expecting, but it is better than nothing. Use the upper layer dentry and mount from the overlayfs root inode, passing the statfs call to that filesystem. Signed-off-by: Andy Whitcroft <apw@canonical.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r--fs/overlayfs/super.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 227710aad781..aaf562b9f937 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -16,17 +16,21 @@
16#include <linux/parser.h> 16#include <linux/parser.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/sched.h> 18#include <linux/sched.h>
19#include <linux/statfs.h>
19#include "overlayfs.h" 20#include "overlayfs.h"
20 21
21MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); 22MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
22MODULE_DESCRIPTION("Overlay filesystem"); 23MODULE_DESCRIPTION("Overlay filesystem");
23MODULE_LICENSE("GPL"); 24MODULE_LICENSE("GPL");
24 25
26#define OVERLAYFS_SUPER_MAGIC 0x794c764f
27
25/* private information held for overlayfs's superblock */ 28/* private information held for overlayfs's superblock */
26struct ovl_fs { 29struct ovl_fs {
27 struct vfsmount *upper_mnt; 30 struct vfsmount *upper_mnt;
28 struct vfsmount *lower_mnt; 31 struct vfsmount *lower_mnt;
29 struct dentry *workdir; 32 struct dentry *workdir;
33 long lower_namelen;
30}; 34};
31 35
32struct ovl_dir_cache; 36struct ovl_dir_cache;
@@ -383,8 +387,35 @@ static void ovl_put_super(struct super_block *sb)
383 kfree(ufs); 387 kfree(ufs);
384} 388}
385 389
390/**
391 * ovl_statfs
392 * @sb: The overlayfs super block
393 * @buf: The struct kstatfs to fill in with stats
394 *
395 * Get the filesystem statistics. As writes always target the upper layer
396 * filesystem pass the statfs to the same filesystem.
397 */
398static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf)
399{
400 struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
401 struct dentry *root_dentry = dentry->d_sb->s_root;
402 struct path path;
403 int err;
404
405 ovl_path_upper(root_dentry, &path);
406
407 err = vfs_statfs(&path, buf);
408 if (!err) {
409 buf->f_namelen = max(buf->f_namelen, ofs->lower_namelen);
410 buf->f_type = OVERLAYFS_SUPER_MAGIC;
411 }
412
413 return err;
414}
415
386static const struct super_operations ovl_super_operations = { 416static const struct super_operations ovl_super_operations = {
387 .put_super = ovl_put_super, 417 .put_super = ovl_put_super,
418 .statfs = ovl_statfs,
388}; 419};
389 420
390struct ovl_config { 421struct ovl_config {
@@ -556,6 +587,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
556 struct ovl_entry *oe; 587 struct ovl_entry *oe;
557 struct ovl_fs *ufs; 588 struct ovl_fs *ufs;
558 struct ovl_config config; 589 struct ovl_config config;
590 struct kstatfs statfs;
559 int err; 591 int err;
560 592
561 err = ovl_parse_opt((char *) data, &config); 593 err = ovl_parse_opt((char *) data, &config);
@@ -617,6 +649,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
617 goto out_put_workpath; 649 goto out_put_workpath;
618 } 650 }
619 651
652 err = vfs_statfs(&lowerpath, &statfs);
653 if (err) {
654 pr_err("overlayfs: statfs failed on lowerpath\n");
655 goto out_put_workpath;
656 }
657 ufs->lower_namelen = statfs.f_namelen;
658
620 ufs->upper_mnt = clone_private_mount(&upperpath); 659 ufs->upper_mnt = clone_private_mount(&upperpath);
621 err = PTR_ERR(ufs->upper_mnt); 660 err = PTR_ERR(ufs->upper_mnt);
622 if (IS_ERR(ufs->upper_mnt)) { 661 if (IS_ERR(ufs->upper_mnt)) {
@@ -669,6 +708,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
669 708
670 root_dentry->d_fsdata = oe; 709 root_dentry->d_fsdata = oe;
671 710
711 sb->s_magic = OVERLAYFS_SUPER_MAGIC;
672 sb->s_op = &ovl_super_operations; 712 sb->s_op = &ovl_super_operations;
673 sb->s_root = root_dentry; 713 sb->s_root = root_dentry;
674 sb->s_fs_info = ufs; 714 sb->s_fs_info = ufs;