2 * Copyright (C) 2005-2013 Junjiro R. Okajima
4 * This program, aufs is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <linux/seq_file.h>
26 #ifdef CONFIG_AUFS_FS_MODULE
27 /* this entry violates the "one line per file" policy of sysfs */
28 static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
33 /* this file is generated at compiling */
37 err = snprintf(buf, PAGE_SIZE, conf);
38 if (unlikely(err >= PAGE_SIZE))
43 static struct kobj_attribute au_config_attr = __ATTR_RO(config);
46 static struct attribute *au_attr[] = {
47 #ifdef CONFIG_AUFS_FS_MODULE
50 NULL, /* need to NULL terminate the list of attributes */
53 static struct attribute_group sysaufs_attr_group_body = {
57 struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
59 /* ---------------------------------------------------------------------- */
61 int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
68 if (au_opt_test(au_mntflags(sb), XINO)) {
69 err = au_xino_path(seq, au_sbi(sb)->si_xib);
76 * the lifetime of branch is independent from the entry under sysfs.
77 * sysfs handles the lifetime of the entry, and never call ->show() after it is
80 static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
81 aufs_bindex_t bindex, int idx)
89 AuDbg("b%d\n", bindex);
93 di_read_lock_parent(root, !AuLock_IR);
94 br = au_sbr(sb, bindex);
98 path.mnt = au_br_mnt(br);
99 path.dentry = au_h_dptr(root, bindex);
100 au_seq_path(seq, &path);
101 di_read_unlock(root, !AuLock_IR);
102 perm = au_optstr_br_perm(br->br_perm);
104 err = seq_printf(seq, "=%s\n", perm);
112 err = seq_printf(seq, "%d\n", br->br_id);
113 di_read_unlock(root, !AuLock_IR);
122 /* ---------------------------------------------------------------------- */
124 static struct seq_file *au_seq(char *p, ssize_t len)
126 struct seq_file *seq;
128 seq = kzalloc(sizeof(*seq), GFP_NOFS);
130 /* mutex_init(&seq.lock); */
133 return seq; /* success */
136 seq = ERR_PTR(-ENOMEM);
140 #define SysaufsBr_PREFIX "br"
141 #define SysaufsBrid_PREFIX "brid"
143 /* todo: file size may exceed PAGE_SIZE */
144 ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
151 struct au_sbinfo *sbinfo;
152 struct super_block *sb;
153 struct seq_file *seq;
155 struct attribute **cattr;
157 sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
161 * prevent a race condition between sysfs and aufs.
162 * for instance, sysfs_file_read() calls sysfs_get_active_two() which
163 * prohibits maintaining the sysfs entries.
164 * hew we acquire read lock after sysfs_get_active_two().
165 * on the other hand, the remount process may maintain the sysfs/aufs
166 * entries after acquiring write lock.
167 * it can cause a deadlock.
168 * simply we gave up processing read here.
171 if (unlikely(!si_noflush_read_trylock(sb)))
174 seq = au_seq(buf, PAGE_SIZE);
179 name = (void *)attr->name;
180 cattr = sysaufs_si_attrs;
182 if (!strcmp(name, (*cattr)->name)) {
183 err = container_of(*cattr, struct sysaufs_si_attr, attr)
190 if (!strncmp(name, SysaufsBrid_PREFIX,
191 sizeof(SysaufsBrid_PREFIX) - 1)) {
192 idx = AuBrSysfs_BRID;
193 name += sizeof(SysaufsBrid_PREFIX) - 1;
194 } else if (!strncmp(name, SysaufsBr_PREFIX,
195 sizeof(SysaufsBr_PREFIX) - 1)) {
197 name += sizeof(SysaufsBr_PREFIX) - 1;
201 err = kstrtol(name, 10, &l);
205 err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx);
214 if (unlikely(err == PAGE_SIZE))
224 /* ---------------------------------------------------------------------- */
226 void sysaufs_br_init(struct au_branch *br)
229 struct au_brsysfs *br_sysfs;
230 struct attribute *attr;
232 br_sysfs = br->br_sysfs;
233 for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
234 attr = &br_sysfs->attr;
235 sysfs_attr_init(attr);
236 attr->name = br_sysfs->name;
237 attr->mode = S_IRUGO;
242 void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
244 struct au_branch *br;
245 struct kobject *kobj;
246 struct au_brsysfs *br_sysfs;
250 dbgaufs_brs_del(sb, bindex);
255 kobj = &au_sbi(sb)->si_kobj;
257 for (; bindex <= bend; bindex++) {
258 br = au_sbr(sb, bindex);
259 br_sysfs = br->br_sysfs;
260 for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
261 sysfs_remove_file(kobj, &br_sysfs->attr);
267 void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
271 struct kobject *kobj;
272 struct au_branch *br;
273 struct au_brsysfs *br_sysfs;
275 dbgaufs_brs_add(sb, bindex);
280 kobj = &au_sbi(sb)->si_kobj;
282 for (; bindex <= bend; bindex++) {
283 br = au_sbr(sb, bindex);
284 br_sysfs = br->br_sysfs;
285 snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name),
286 SysaufsBr_PREFIX "%d", bindex);
287 snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name),
288 SysaufsBrid_PREFIX "%d", bindex);
289 for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
290 err = sysfs_create_file(kobj, &br_sysfs->attr);
292 pr_warn("failed %s under sysfs(%d)\n",
293 br_sysfs->name, err);