]>
Commit | Line | Data |
---|---|---|
68184a5a JR |
1 | From aa88a112a579b0122e62eff87d581fcca11ad805 Mon Sep 17 00:00:00 2001 |
2 | From: Erez Zadok <ezk@fsl.cs.sunysb.edu> | |
3 | Date: Mon, 23 May 2011 20:59:20 -0400 | |
4 | Subject: [PATCH 06/13] overlayfs: implement show_options | |
5 | Patch-mainline: not yet | |
6 | ||
7 | This is useful because of the stacking nature of overlayfs. Users like to | |
8 | find out (via /proc/mounts) which lower/upper directory were used at mount | |
9 | time. | |
10 | ||
11 | Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu> | |
12 | Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> | |
13 | --- | |
14 | fs/overlayfs/super.c | 63 ++++++++++++++++++++++++++++++++++----------------- | |
15 | 1 file changed, 43 insertions(+), 20 deletions(-) | |
16 | ||
c06a8ce3 AM |
17 | --- a/fs/overlayfs/super.c |
18 | +++ b/fs/overlayfs/super.c | |
68184a5a JR |
19 | @@ -18,6 +18,7 @@ |
20 | #include <linux/cred.h> | |
21 | #include <linux/sched.h> | |
22 | #include <linux/statfs.h> | |
23 | +#include <linux/seq_file.h> | |
24 | #include "overlayfs.h" | |
25 | ||
26 | MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); | |
27 | @@ -26,12 +27,21 @@ MODULE_LICENSE("GPL"); | |
28 | ||
29 | #define OVERLAYFS_SUPER_MAGIC 0x794c764f | |
30 | ||
31 | +struct ovl_config { | |
32 | + char *lowerdir; | |
33 | + char *upperdir; | |
34 | +}; | |
35 | + | |
36 | +/* private information held for overlayfs's superblock */ | |
37 | struct ovl_fs { | |
38 | struct vfsmount *upper_mnt; | |
39 | struct vfsmount *lower_mnt; | |
40 | long lower_namelen; | |
41 | + /* pathnames of lower and upper dirs, for show_options */ | |
42 | + struct ovl_config config; | |
43 | }; | |
44 | ||
45 | +/* private information held for every overlayfs dentry */ | |
46 | struct ovl_entry { | |
47 | /* | |
48 | * Keep "double reference" on upper dentries, so that | |
c06a8ce3 | 49 | @@ -389,6 +399,8 @@ static void ovl_put_super(struct super_b |
68184a5a JR |
50 | mntput(ufs->upper_mnt); |
51 | mntput(ufs->lower_mnt); | |
52 | ||
53 | + kfree(ufs->config.lowerdir); | |
54 | + kfree(ufs->config.upperdir); | |
55 | kfree(ufs); | |
56 | } | |
57 | ||
c06a8ce3 | 58 | @@ -437,15 +449,27 @@ static int ovl_statfs(struct dentry *den |
68184a5a JR |
59 | return err; |
60 | } | |
61 | ||
62 | +/** | |
63 | + * ovl_show_options | |
64 | + * | |
65 | + * Prints the mount options for a given superblock. | |
66 | + * Returns zero; does not fail. | |
67 | + */ | |
68 | +static int ovl_show_options(struct seq_file *m, struct dentry *dentry) | |
69 | +{ | |
70 | + struct super_block *sb = dentry->d_sb; | |
71 | + struct ovl_fs *ufs = sb->s_fs_info; | |
72 | + | |
73 | + seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir); | |
74 | + seq_printf(m, ",upperdir=%s", ufs->config.upperdir); | |
75 | + return 0; | |
76 | +} | |
77 | + | |
78 | static const struct super_operations ovl_super_operations = { | |
79 | .put_super = ovl_put_super, | |
80 | .remount_fs = ovl_remount_fs, | |
81 | .statfs = ovl_statfs, | |
82 | -}; | |
83 | - | |
84 | -struct ovl_config { | |
85 | - char *lowerdir; | |
86 | - char *upperdir; | |
87 | + .show_options = ovl_show_options, | |
88 | }; | |
89 | ||
90 | enum { | |
c06a8ce3 | 91 | @@ -505,34 +529,33 @@ static int ovl_fill_super(struct super_b |
68184a5a JR |
92 | struct dentry *root_dentry; |
93 | struct ovl_entry *oe; | |
94 | struct ovl_fs *ufs; | |
95 | - struct ovl_config config; | |
96 | struct kstatfs statfs; | |
97 | int err; | |
98 | ||
99 | - err = ovl_parse_opt((char *) data, &config); | |
100 | - if (err) | |
101 | + err = -ENOMEM; | |
102 | + ufs = kmalloc(sizeof(struct ovl_fs), GFP_KERNEL); | |
103 | + if (!ufs) | |
104 | goto out; | |
105 | ||
106 | + err = ovl_parse_opt((char *) data, &ufs->config); | |
107 | + if (err) | |
108 | + goto out_free_ufs; | |
109 | + | |
110 | err = -EINVAL; | |
111 | - if (!config.upperdir || !config.lowerdir) { | |
112 | + if (!ufs->config.upperdir || !ufs->config.lowerdir) { | |
c06a8ce3 | 113 | pr_err("overlayfs: missing upperdir or lowerdir\n"); |
68184a5a JR |
114 | goto out_free_config; |
115 | } | |
116 | ||
117 | - err = -ENOMEM; | |
118 | - ufs = kmalloc(sizeof(struct ovl_fs), GFP_KERNEL); | |
119 | - if (!ufs) | |
120 | - goto out_free_config; | |
121 | - | |
122 | oe = ovl_alloc_entry(); | |
123 | if (oe == NULL) | |
124 | - goto out_free_ufs; | |
125 | + goto out_free_config; | |
126 | ||
127 | - err = kern_path(config.upperdir, LOOKUP_FOLLOW, &upperpath); | |
128 | + err = kern_path(ufs->config.upperdir, LOOKUP_FOLLOW, &upperpath); | |
129 | if (err) | |
130 | goto out_free_oe; | |
131 | ||
132 | - err = kern_path(config.lowerdir, LOOKUP_FOLLOW, &lowerpath); | |
133 | + err = kern_path(ufs->config.lowerdir, LOOKUP_FOLLOW, &lowerpath); | |
134 | if (err) | |
135 | goto out_put_upperpath; | |
136 | ||
c06a8ce3 | 137 | @@ -616,11 +639,11 @@ static int ovl_fill_super(struct super_b |
68184a5a JR |
138 | path_put(&upperpath); |
139 | out_free_oe: | |
140 | kfree(oe); | |
141 | +out_free_config: | |
142 | + kfree(ufs->config.lowerdir); | |
143 | + kfree(ufs->config.upperdir); | |
144 | out_free_ufs: | |
145 | kfree(ufs); | |
146 | -out_free_config: | |
147 | - kfree(config.lowerdir); | |
148 | - kfree(config.upperdir); | |
149 | out: | |
150 | return err; | |
151 | } |