1 /* inode.c: /proc/openprom handling routines
3 * Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com)
4 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
7 #include <linux/module.h>
8 #include <linux/types.h>
9 #include <linux/string.h>
11 #include <linux/init.h>
12 #include <linux/slab.h>
13 #include <linux/seq_file.h>
14 #include <linux/magic.h>
16 #include <asm/openprom.h>
17 #include <asm/oplib.h>
19 #include <linux/uaccess.h>
21 static DEFINE_MUTEX(op_mutex
);
23 #define OPENPROM_ROOT_INO 0
31 struct device_node
*node
;
32 struct property
*prop
;
35 struct op_inode_info
{
36 struct inode vfs_inode
;
37 enum op_inode_type type
;
38 union op_inode_data u
;
41 static struct inode
*openprom_iget(struct super_block
*sb
, ino_t ino
);
43 static inline struct op_inode_info
*OP_I(struct inode
*inode
)
45 return container_of(inode
, struct op_inode_info
, vfs_inode
);
48 static int is_string(unsigned char *p
, int len
)
52 for (i
= 0; i
< len
; i
++) {
53 unsigned char val
= p
[i
];
56 (val
>= ' ' && val
<= '~'))
65 static int property_show(struct seq_file
*f
, void *v
)
67 struct property
*prop
= f
->private;
74 if (is_string(pval
, len
)) {
78 seq_printf(f
, "%s", (char *) pval
);
80 /* Skip over the NULL byte too. */
92 seq_printf(f
, "%02x.",
93 *(unsigned char *) pval
);
96 *(unsigned char *) pval
);
104 seq_printf(f
, "%08x.",
105 *(unsigned int *) pval
);
107 seq_printf(f
, "%08x",
108 *(unsigned int *) pval
);
118 static void *property_start(struct seq_file
*f
, loff_t
*pos
)
125 static void *property_next(struct seq_file
*f
, void *v
, loff_t
*pos
)
131 static void property_stop(struct seq_file
*f
, void *v
)
136 static const struct seq_operations property_op
= {
137 .start
= property_start
,
138 .next
= property_next
,
139 .stop
= property_stop
,
140 .show
= property_show
143 static int property_open(struct inode
*inode
, struct file
*file
)
145 struct op_inode_info
*oi
= OP_I(inode
);
148 BUG_ON(oi
->type
!= op_inode_prop
);
150 ret
= seq_open(file
, &property_op
);
152 struct seq_file
*m
= file
->private_data
;
153 m
->private = oi
->u
.prop
;
158 static const struct file_operations openpromfs_prop_ops
= {
159 .open
= property_open
,
162 .release
= seq_release
,
165 static int openpromfs_readdir(struct file
*, struct dir_context
*);
167 static const struct file_operations openprom_operations
= {
168 .read
= generic_read_dir
,
169 .iterate_shared
= openpromfs_readdir
,
170 .llseek
= generic_file_llseek
,
173 static struct dentry
*openpromfs_lookup(struct inode
*, struct dentry
*, unsigned int);
175 static const struct inode_operations openprom_inode_operations
= {
176 .lookup
= openpromfs_lookup
,
179 static struct dentry
*openpromfs_lookup(struct inode
*dir
, struct dentry
*dentry
, unsigned int flags
)
181 struct op_inode_info
*ent_oi
, *oi
= OP_I(dir
);
182 struct device_node
*dp
, *child
;
183 struct property
*prop
;
184 enum op_inode_type ent_type
;
185 union op_inode_data ent_data
;
191 BUG_ON(oi
->type
!= op_inode_node
);
195 name
= dentry
->d_name
.name
;
196 len
= dentry
->d_name
.len
;
198 mutex_lock(&op_mutex
);
202 int n
= strlen(child
->path_component_name
);
205 !strncmp(child
->path_component_name
, name
, len
)) {
206 ent_type
= op_inode_node
;
207 ent_data
.node
= child
;
208 ino
= child
->unique_id
;
211 child
= child
->sibling
;
214 prop
= dp
->properties
;
216 int n
= strlen(prop
->name
);
218 if (len
== n
&& !strncmp(prop
->name
, name
, len
)) {
219 ent_type
= op_inode_prop
;
220 ent_data
.prop
= prop
;
221 ino
= prop
->unique_id
;
228 mutex_unlock(&op_mutex
);
229 return ERR_PTR(-ENOENT
);
232 inode
= openprom_iget(dir
->i_sb
, ino
);
233 mutex_unlock(&op_mutex
);
235 return ERR_CAST(inode
);
236 ent_oi
= OP_I(inode
);
237 ent_oi
->type
= ent_type
;
238 ent_oi
->u
= ent_data
;
242 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
243 inode
->i_op
= &openprom_inode_operations
;
244 inode
->i_fop
= &openprom_operations
;
248 if (!strcmp(dp
->name
, "options") && (len
== 17) &&
249 !strncmp (name
, "security-password", 17))
250 inode
->i_mode
= S_IFREG
| S_IRUSR
| S_IWUSR
;
252 inode
->i_mode
= S_IFREG
| S_IRUGO
;
253 inode
->i_fop
= &openpromfs_prop_ops
;
255 inode
->i_size
= ent_oi
->u
.prop
->length
;
259 d_add(dentry
, inode
);
263 static int openpromfs_readdir(struct file
*file
, struct dir_context
*ctx
)
265 struct inode
*inode
= file_inode(file
);
266 struct op_inode_info
*oi
= OP_I(inode
);
267 struct device_node
*dp
= oi
->u
.node
;
268 struct device_node
*child
;
269 struct property
*prop
;
272 mutex_lock(&op_mutex
);
275 if (!dir_emit(ctx
, ".", 1, inode
->i_ino
, DT_DIR
))
280 if (!dir_emit(ctx
, "..", 2,
281 (dp
->parent
== NULL
?
283 dp
->parent
->unique_id
), DT_DIR
))
289 /* First, the children nodes as directories. */
292 child
= child
->sibling
;
297 child
->path_component_name
,
298 strlen(child
->path_component_name
),
299 child
->unique_id
, DT_DIR
))
303 child
= child
->sibling
;
306 /* Next, the properties as files. */
307 prop
= dp
->properties
;
313 if (!dir_emit(ctx
, prop
->name
, strlen(prop
->name
),
314 prop
->unique_id
, DT_REG
))
322 mutex_unlock(&op_mutex
);
326 static struct kmem_cache
*op_inode_cachep
;
328 static struct inode
*openprom_alloc_inode(struct super_block
*sb
)
330 struct op_inode_info
*oi
;
332 oi
= kmem_cache_alloc(op_inode_cachep
, GFP_KERNEL
);
336 return &oi
->vfs_inode
;
339 static void openprom_i_callback(struct rcu_head
*head
)
341 struct inode
*inode
= container_of(head
, struct inode
, i_rcu
);
342 kmem_cache_free(op_inode_cachep
, OP_I(inode
));
345 static void openprom_destroy_inode(struct inode
*inode
)
347 call_rcu(&inode
->i_rcu
, openprom_i_callback
);
350 static struct inode
*openprom_iget(struct super_block
*sb
, ino_t ino
)
354 inode
= iget_locked(sb
, ino
);
356 return ERR_PTR(-ENOMEM
);
357 if (inode
->i_state
& I_NEW
) {
358 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= current_time(inode
);
359 if (inode
->i_ino
== OPENPROM_ROOT_INO
) {
360 inode
->i_op
= &openprom_inode_operations
;
361 inode
->i_fop
= &openprom_operations
;
362 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
364 unlock_new_inode(inode
);
369 static int openprom_remount(struct super_block
*sb
, int *flags
, char *data
)
372 *flags
|= MS_NOATIME
;
376 static const struct super_operations openprom_sops
= {
377 .alloc_inode
= openprom_alloc_inode
,
378 .destroy_inode
= openprom_destroy_inode
,
379 .statfs
= simple_statfs
,
380 .remount_fs
= openprom_remount
,
383 static int openprom_fill_super(struct super_block
*s
, void *data
, int silent
)
385 struct inode
*root_inode
;
386 struct op_inode_info
*oi
;
389 s
->s_flags
|= MS_NOATIME
;
390 s
->s_blocksize
= 1024;
391 s
->s_blocksize_bits
= 10;
392 s
->s_magic
= OPENPROM_SUPER_MAGIC
;
393 s
->s_op
= &openprom_sops
;
395 root_inode
= openprom_iget(s
, OPENPROM_ROOT_INO
);
396 if (IS_ERR(root_inode
)) {
397 ret
= PTR_ERR(root_inode
);
401 oi
= OP_I(root_inode
);
402 oi
->type
= op_inode_node
;
403 oi
->u
.node
= of_find_node_by_path("/");
405 s
->s_root
= d_make_root(root_inode
);
407 goto out_no_root_dentry
;
413 printk("openprom_fill_super: get root inode failed\n");
417 static struct dentry
*openprom_mount(struct file_system_type
*fs_type
,
418 int flags
, const char *dev_name
, void *data
)
420 return mount_single(fs_type
, flags
, data
, openprom_fill_super
);
423 static struct file_system_type openprom_fs_type
= {
424 .owner
= THIS_MODULE
,
425 .name
= "openpromfs",
426 .mount
= openprom_mount
,
427 .kill_sb
= kill_anon_super
,
429 MODULE_ALIAS_FS("openpromfs");
431 static void op_inode_init_once(void *data
)
433 struct op_inode_info
*oi
= (struct op_inode_info
*) data
;
435 inode_init_once(&oi
->vfs_inode
);
438 static int __init
init_openprom_fs(void)
442 op_inode_cachep
= kmem_cache_create("op_inode_cache",
443 sizeof(struct op_inode_info
),
445 (SLAB_RECLAIM_ACCOUNT
|
446 SLAB_MEM_SPREAD
| SLAB_ACCOUNT
),
448 if (!op_inode_cachep
)
451 err
= register_filesystem(&openprom_fs_type
);
453 kmem_cache_destroy(op_inode_cachep
);
458 static void __exit
exit_openprom_fs(void)
460 unregister_filesystem(&openprom_fs_type
);
462 * Make sure all delayed rcu free inodes are flushed before we
466 kmem_cache_destroy(op_inode_cachep
);
469 module_init(init_openprom_fs
)
470 module_exit(exit_openprom_fs
)
471 MODULE_LICENSE("GPL");