Overlayfs: implement show_options This is useful because of the stacking nature of overlayfs. Users like to find out (via /proc/mounts) which lower/upper directory were used at mount time. Signed-off-by: Erez Zadok <ezk@xxxxxxxxxxxxx> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index be3c4a9..ff55a00 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -15,12 +15,19 @@ #include <linux/slab.h> #include <linux/parser.h> #include <linux/module.h> +#include <linux/seq_file.h> #include "overlayfs.h" MODULE_AUTHOR("Miklos Szeredi <miklos@xxxxxxxxxx>"); MODULE_DESCRIPTION("Overlay filesystem"); MODULE_LICENSE("GPL"); +struct ovl_config { + char *lowerdir; + char *upperdir; +}; + +/* private information held for overlayfs's superblock */ struct ovl_fs { /* * Keep "double reference" on upper dentries, so that @@ -28,8 +35,11 @@ struct ovl_fs { */ struct vfsmount *upper_mnt; struct vfsmount *lower_mnt; + /* pathnames of lower and upper dirs, for show_options */ + struct ovl_config config; }; +/* private information held for every overlayfs dentry */ struct ovl_entry { struct dentry *__upperdentry; struct dentry *lowerdentry; @@ -363,6 +373,8 @@ static void ovl_put_super(struct super_block *sb) mntput(ufs->upper_mnt); mntput(ufs->lower_mnt); + kfree(ufs->config.lowerdir); + kfree(ufs->config.upperdir); kfree(ufs); } @@ -404,15 +416,27 @@ static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf) return path.dentry->d_sb->s_op->statfs(path.dentry, buf); } +/** + * ovl_show_options + * + * Prints the mount options for a given superblock. + * Returns zero; does not fail. + */ +static int ovl_show_options(struct seq_file *m, struct vfsmount *mnt) +{ + struct super_block *sb = mnt->mnt_sb; + struct ovl_fs *ufs = sb->s_fs_info; + + seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir); + seq_printf(m, ",upperdir=%s", ufs->config.upperdir); + return 0; +} + static const struct super_operations ovl_super_operations = { .put_super = ovl_put_super, .remount_fs = ovl_remount_fs, .statfs = ovl_statfs, -}; - -struct ovl_config { - char *lowerdir; - char *upperdir; + .show_options = ovl_show_options, }; enum { @@ -472,37 +496,36 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) struct dentry *root_dentry; struct ovl_entry *oe; struct ovl_fs *ufs; - struct ovl_config config; int err; - err = ovl_parse_opt((char *) data, &config); - if (err) + err = -ENOMEM; + ufs = kmalloc(sizeof(struct ovl_fs), GFP_KERNEL); + if (!ufs) goto out; + err = ovl_parse_opt((char *) data, &ufs->config); + if (err) + goto out_free_ufs; + err = -EINVAL; - if (!config.upperdir || !config.lowerdir) { + if (!ufs->config.upperdir || !ufs->config.lowerdir) { printk(KERN_ERR "overlayfs: missing upperdir or lowerdir\n"); goto out_free_config; } - err = -ENOMEM; - ufs = kmalloc(sizeof(struct ovl_fs), GFP_KERNEL); - if (!ufs) - goto out_free_config; - oe = ovl_alloc_entry(); if (oe == NULL) - goto out_free_ufs; + goto out_free_config; root_inode = ovl_new_inode(sb, S_IFDIR, oe); if (!root_inode) goto out_free_oe; - err = kern_path(config.upperdir, LOOKUP_FOLLOW, &upperpath); + err = kern_path(ufs->config.upperdir, LOOKUP_FOLLOW, &upperpath); if (err) goto out_put_root; - err = kern_path(config.lowerdir, LOOKUP_FOLLOW, &lowerpath); + err = kern_path(ufs->config.lowerdir, LOOKUP_FOLLOW, &lowerpath); if (err) goto out_put_upperpath; @@ -566,11 +589,11 @@ out_put_root: iput(root_inode); out_free_oe: kfree(oe); +out_free_config: + kfree(ufs->config.lowerdir); + kfree(ufs->config.upperdir); out_free_ufs: kfree(ufs); -out_free_config: - kfree(config.lowerdir); - kfree(config.upperdir); out: return err; } -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html