2 * Copyright (C) 2005-2017 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, see <http://www.gnu.org/licenses/>.
22 #include <linux/compat.h>
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
)
87 au_br_perm_str_t perm
;
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 err
= au_seq_path(seq
, &path
);
102 au_optstr_br_perm(&perm
, br
->br_perm
);
103 seq_printf(seq
, "=%s\n", perm
.a
);
107 seq_printf(seq
, "%d\n", br
->br_id
);
110 di_read_unlock(root
, !AuLock_IR
);
111 if (unlikely(err
|| seq_has_overflowed(seq
)))
117 /* ---------------------------------------------------------------------- */
119 static struct seq_file
*au_seq(char *p
, ssize_t len
)
121 struct seq_file
*seq
;
123 seq
= kzalloc(sizeof(*seq
), GFP_NOFS
);
125 /* mutex_init(&seq.lock); */
128 return seq
; /* success */
131 seq
= ERR_PTR(-ENOMEM
);
135 #define SysaufsBr_PREFIX "br"
136 #define SysaufsBrid_PREFIX "brid"
138 /* todo: file size may exceed PAGE_SIZE */
139 ssize_t
sysaufs_si_show(struct kobject
*kobj
, struct attribute
*attr
,
146 struct au_sbinfo
*sbinfo
;
147 struct super_block
*sb
;
148 struct seq_file
*seq
;
150 struct attribute
**cattr
;
152 sbinfo
= container_of(kobj
, struct au_sbinfo
, si_kobj
);
156 * prevent a race condition between sysfs and aufs.
157 * for instance, sysfs_file_read() calls sysfs_get_active_two() which
158 * prohibits maintaining the sysfs entries.
159 * hew we acquire read lock after sysfs_get_active_two().
160 * on the other hand, the remount process may maintain the sysfs/aufs
161 * entries after acquiring write lock.
162 * it can cause a deadlock.
163 * simply we gave up processing read here.
166 if (unlikely(!si_noflush_read_trylock(sb
)))
169 seq
= au_seq(buf
, PAGE_SIZE
);
174 name
= (void *)attr
->name
;
175 cattr
= sysaufs_si_attrs
;
177 if (!strcmp(name
, (*cattr
)->name
)) {
178 err
= container_of(*cattr
, struct sysaufs_si_attr
, attr
)
185 if (!strncmp(name
, SysaufsBrid_PREFIX
,
186 sizeof(SysaufsBrid_PREFIX
) - 1)) {
187 idx
= AuBrSysfs_BRID
;
188 name
+= sizeof(SysaufsBrid_PREFIX
) - 1;
189 } else if (!strncmp(name
, SysaufsBr_PREFIX
,
190 sizeof(SysaufsBr_PREFIX
) - 1)) {
192 name
+= sizeof(SysaufsBr_PREFIX
) - 1;
196 err
= kstrtol(name
, 10, &l
);
200 err
= sysaufs_si_br(seq
, sb
, (aufs_bindex_t
)l
, idx
);
209 if (unlikely(err
== PAGE_SIZE
))
219 /* ---------------------------------------------------------------------- */
221 static int au_brinfo(struct super_block
*sb
, union aufs_brinfo __user
*arg
)
225 aufs_bindex_t bindex
, bbot
;
228 struct seq_file
*seq
;
229 struct au_branch
*br
;
231 si_read_lock(sb
, AuLock_FLUSH
);
238 buf
= (void *)__get_free_page(GFP_NOFS
);
242 seq
= au_seq(buf
, PAGE_SIZE
);
247 sz
= sizeof(*arg
) - offsetof(union aufs_brinfo
, path
);
248 for (bindex
= 0; bindex
<= bbot
; bindex
++, arg
++) {
249 err
= !access_ok(VERIFY_WRITE
, arg
, sizeof(*arg
));
253 br
= au_sbr(sb
, bindex
);
255 BUILD_BUG_ON(sizeof(brid
) != sizeof(arg
->id
));
256 err
= __put_user(brid
, &arg
->id
);
260 BUILD_BUG_ON(sizeof(br
->br_perm
) != sizeof(arg
->perm
));
261 err
= __put_user(br
->br_perm
, &arg
->perm
);
265 err
= au_seq_path(seq
, &br
->br_path
);
269 if (!seq_has_overflowed(seq
)) {
270 err
= copy_to_user(arg
->path
, seq
->buf
, seq
->count
);
285 free_page((unsigned long)buf
);
291 long au_brinfo_ioctl(struct file
*file
, unsigned long arg
)
293 return au_brinfo(file
->f_path
.dentry
->d_sb
, (void __user
*)arg
);
297 long au_brinfo_compat_ioctl(struct file
*file
, unsigned long arg
)
299 return au_brinfo(file
->f_path
.dentry
->d_sb
, compat_ptr(arg
));
303 /* ---------------------------------------------------------------------- */
305 void sysaufs_br_init(struct au_branch
*br
)
308 struct au_brsysfs
*br_sysfs
;
309 struct attribute
*attr
;
311 br_sysfs
= br
->br_sysfs
;
312 for (i
= 0; i
< ARRAY_SIZE(br
->br_sysfs
); i
++) {
313 attr
= &br_sysfs
->attr
;
314 sysfs_attr_init(attr
);
315 attr
->name
= br_sysfs
->name
;
316 attr
->mode
= S_IRUGO
;
321 void sysaufs_brs_del(struct super_block
*sb
, aufs_bindex_t bindex
)
323 struct au_branch
*br
;
324 struct kobject
*kobj
;
325 struct au_brsysfs
*br_sysfs
;
329 dbgaufs_brs_del(sb
, bindex
);
334 kobj
= &au_sbi(sb
)->si_kobj
;
336 for (; bindex
<= bbot
; bindex
++) {
337 br
= au_sbr(sb
, bindex
);
338 br_sysfs
= br
->br_sysfs
;
339 for (i
= 0; i
< ARRAY_SIZE(br
->br_sysfs
); i
++) {
340 sysfs_remove_file(kobj
, &br_sysfs
->attr
);
346 void sysaufs_brs_add(struct super_block
*sb
, aufs_bindex_t bindex
)
350 struct kobject
*kobj
;
351 struct au_branch
*br
;
352 struct au_brsysfs
*br_sysfs
;
354 dbgaufs_brs_add(sb
, bindex
);
359 kobj
= &au_sbi(sb
)->si_kobj
;
361 for (; bindex
<= bbot
; bindex
++) {
362 br
= au_sbr(sb
, bindex
);
363 br_sysfs
= br
->br_sysfs
;
364 snprintf(br_sysfs
[AuBrSysfs_BR
].name
, sizeof(br_sysfs
->name
),
365 SysaufsBr_PREFIX
"%d", bindex
);
366 snprintf(br_sysfs
[AuBrSysfs_BRID
].name
, sizeof(br_sysfs
->name
),
367 SysaufsBrid_PREFIX
"%d", bindex
);
368 for (i
= 0; i
< ARRAY_SIZE(br
->br_sysfs
); i
++) {
369 err
= sysfs_create_file(kobj
, &br_sysfs
->attr
);
371 pr_warn("failed %s under sysfs(%d)\n",
372 br_sysfs
->name
, err
);