1 /* $Id: inode.c,v 1.15 2001/11/12 09:43:39 davem Exp $
2 * openpromfs.c: /proc/openprom handling routines
4 * Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com)
5 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
8 #include <linux/module.h>
9 #include <linux/types.h>
10 #include <linux/string.h>
12 #include <linux/openprom_fs.h>
13 #include <linux/init.h>
14 #include <linux/slab.h>
15 #include <linux/smp_lock.h>
17 #include <asm/openprom.h>
18 #include <asm/oplib.h>
19 #include <asm/uaccess.h>
21 #define ALIASES_NNODES 64
32 #define OPP_STRING 0x10
33 #define OPP_STRINGLIST 0x20
34 #define OPP_BINARY 0x40
35 #define OPP_HEXSTRING 0x80
36 #define OPP_DIRTY 0x01
37 #define OPP_QUOTED 0x02
38 #define OPP_NOTQUOTED 0x04
39 #define OPP_ASCIIZ 0x08
47 static openpromfs_node
*nodes
;
50 static u16 first_prop
;
51 static u16 options
= 0xffff;
52 static u16 aliases
= 0xffff;
53 static int aliases_nodes
;
54 static char *alias_names
[ALIASES_NNODES
];
56 #define OPENPROM_ROOT_INO 16
57 #define OPENPROM_FIRST_INO OPENPROM_ROOT_INO
58 #define NODE(ino) nodes[ino - OPENPROM_FIRST_INO]
59 #define NODE2INO(node) (node + OPENPROM_FIRST_INO)
60 #define NODEP2INO(no) (no + OPENPROM_FIRST_INO + last_node)
62 static int openpromfs_create (struct inode
*, struct dentry
*, int, struct nameidata
*);
63 static int openpromfs_readdir(struct file
*, void *, filldir_t
);
64 static struct dentry
*openpromfs_lookup(struct inode
*, struct dentry
*dentry
, struct nameidata
*nd
);
65 static int openpromfs_unlink (struct inode
*, struct dentry
*dentry
);
67 static inline u16
ptr_nod(void *p
)
69 return (long)p
& 0xFFFF;
72 static ssize_t
nodenum_read(struct file
*file
, char __user
*buf
,
73 size_t count
, loff_t
*ppos
)
75 struct inode
*inode
= file
->f_dentry
->d_inode
;
78 if (count
< 0 || !inode
->u
.generic_ip
)
80 sprintf (buffer
, "%8.8lx\n", (long)inode
->u
.generic_ip
);
83 if (count
> 9 - file
->f_pos
)
84 count
= 9 - file
->f_pos
;
85 if (copy_to_user(buf
, buffer
+ file
->f_pos
, count
))
91 static ssize_t
property_read(struct file
*filp
, char __user
*buf
,
92 size_t count
, loff_t
*ppos
)
94 struct inode
*inode
= filp
->f_dentry
->d_inode
;
99 openprom_property
*op
;
102 if (!filp
->private_data
) {
103 node
= nodes
[ptr_nod(inode
->u
.generic_ip
)].node
;
104 i
= ((u32
)(long)inode
->u
.generic_ip
) >> 16;
105 if (ptr_nod(inode
->u
.generic_ip
) == aliases
) {
106 if (i
>= aliases_nodes
)
111 for (p
= prom_firstprop (node
, buffer
);
113 p
= prom_nextprop (node
, p
, buffer
), i
--)
117 i
= prom_getproplen (node
, p
);
119 if (ptr_nod(inode
->u
.generic_ip
) == aliases
)
126 filp
->private_data
= kmalloc (sizeof (openprom_property
)
127 + (j
= strlen (p
)) + 2 * i
,
129 if (!filp
->private_data
)
131 op
= filp
->private_data
;
133 op
->alloclen
= 2 * i
;
134 strcpy (op
->name
, p
);
135 op
->value
= (char *)(((unsigned long)(op
->name
+ j
+ 4)) & ~3);
137 if (k
&& prom_getproperty (node
, p
, op
->value
, i
) < 0)
141 for (s
= NULL
, p
= op
->value
; p
< op
->value
+ k
; p
++) {
142 if ((*p
>= ' ' && *p
<= '~') || *p
== '\n') {
143 op
->flag
|= OPP_STRING
;
147 if (p
> op
->value
&& !*p
&& s
== p
- 1) {
148 if (p
< op
->value
+ k
- 1)
149 op
->flag
|= OPP_STRINGLIST
;
151 op
->flag
|= OPP_ASCIIZ
;
155 op
->flag
|= (OPP_STRING
|OPP_ASCIIZ
);
158 op
->flag
&= ~(OPP_STRING
|OPP_STRINGLIST
);
160 op
->flag
|= OPP_HEXSTRING
;
162 op
->flag
|= OPP_BINARY
;
165 if (op
->flag
& OPP_STRINGLIST
)
166 op
->flag
&= ~(OPP_STRING
);
167 if (op
->flag
& OPP_ASCIIZ
)
171 op
= filp
->private_data
;
172 if (!count
|| !(op
->len
|| (op
->flag
& OPP_ASCIIZ
)))
174 if (*ppos
>= 0xffffff || count
>= 0xffffff)
176 if (op
->flag
& OPP_STRINGLIST
) {
177 for (k
= 0, p
= op
->value
; p
< op
->value
+ op
->len
; p
++)
180 i
= op
->len
+ 4 * k
+ 3;
181 } else if (op
->flag
& OPP_STRING
) {
183 } else if (op
->flag
& OPP_BINARY
) {
184 i
= (op
->len
* 9) >> 2;
186 i
= (op
->len
<< 1) + 1;
189 if (k
>= i
) return 0;
190 if (count
> i
- k
) count
= i
- k
;
191 if (op
->flag
& OPP_STRING
) {
193 if (put_user('\'', buf
))
199 if (k
+ count
>= i
- 2)
205 if (copy_to_user(buf
+ k
- *ppos
,
206 op
->value
+ k
- 1, j
))
213 if (put_user('\'', &buf
[k
++ - *ppos
]))
217 if (put_user('\n', &buf
[k
++ - *ppos
]))
220 } else if (op
->flag
& OPP_STRINGLIST
) {
223 tmp
= kmalloc (i
, GFP_KERNEL
);
229 for (p
= op
->value
; p
< op
->value
+ op
->len
; p
++) {
239 if (copy_to_user(buf
, tmp
+ k
, count
))
245 } else if (op
->flag
& OPP_BINARY
) {
248 int first_off
, last_cnt
;
250 first
= ((u32
*)op
->value
) + k
/ 9;
252 last
= ((u32
*)op
->value
) + (k
+ count
- 1) / 9;
253 last_cnt
= (k
+ count
) % 9;
254 if (!last_cnt
) last_cnt
= 9;
257 sprintf (buffer
, "%08x.", *first
);
258 if (copy_to_user(buf
, buffer
+ first_off
,
259 last_cnt
- first_off
))
261 buf
+= last_cnt
- first_off
;
263 for (q
= first
; q
<= last
; q
++) {
264 sprintf (buffer
, "%08x.", *q
);
266 if (copy_to_user(buf
, buffer
+ first_off
,
269 buf
+= 9 - first_off
;
270 } else if (q
== last
) {
271 if (copy_to_user(buf
, buffer
, last_cnt
))
275 if (copy_to_user(buf
, buffer
, 9))
282 if (last
== (u32
*)(op
->value
+ op
->len
- 4) && last_cnt
== 9) {
283 if (put_user('\n', (buf
- 1)))
289 } else if (op
->flag
& OPP_HEXSTRING
) {
292 if ((k
< i
- 1) && (k
& 1)) {
293 sprintf (buffer
, "%02x",
294 (unsigned char) *(op
->value
+ (k
>> 1)) & 0xff);
295 if (put_user(buffer
[1], &buf
[k
++ - *ppos
]))
300 for (; (count
> 1) && (k
< i
- 1); k
+= 2) {
301 sprintf (buffer
, "%02x",
302 (unsigned char) *(op
->value
+ (k
>> 1)) & 0xff);
303 if (copy_to_user(buf
+ k
- *ppos
, buffer
, 2))
308 if (count
&& (k
< i
- 1)) {
309 sprintf (buffer
, "%02x",
310 (unsigned char) *(op
->value
+ (k
>> 1)) & 0xff);
311 if (put_user(buffer
[0], &buf
[k
++ - *ppos
]))
317 if (put_user('\n', &buf
[k
++ - *ppos
]))
326 static ssize_t
property_write(struct file
*filp
, const char __user
*buf
,
327 size_t count
, loff_t
*ppos
)
333 openprom_property
*op
;
335 if (*ppos
>= 0xffffff || count
>= 0xffffff)
337 if (!filp
->private_data
) {
338 i
= property_read (filp
, NULL
, 0, NULL
);
343 op
= filp
->private_data
;
344 if (!(op
->flag
& OPP_STRING
)) {
346 int first_off
, last_cnt
;
352 for (i
= 0; i
< count
; i
++, j
++) {
356 if (get_user(ctmp
, &buf
[i
]))
360 if (op
->flag
& OPP_BINARY
)
363 goto write_try_string
;
372 if (get_user(ctmp
, &buf
[i
]))
375 (ctmp
> '9' && ctmp
< 'A') ||
376 (ctmp
> 'F' && ctmp
< 'a') ||
378 if (op
->flag
& OPP_BINARY
)
381 goto write_try_string
;
385 op
->flag
|= OPP_BINARY
;
387 i
= ((count
+ k
+ 8) / 9) << 2;
388 if (op
->alloclen
<= i
) {
389 b
= kmalloc (sizeof (openprom_property
) + 2 * i
,
393 memcpy (b
, filp
->private_data
,
394 sizeof (openprom_property
)
395 + strlen (op
->name
) + op
->alloclen
);
396 memset (b
+ sizeof (openprom_property
)
397 + strlen (op
->name
) + op
->alloclen
,
398 0, 2 * i
- op
->alloclen
);
401 b
= filp
->private_data
;
402 filp
->private_data
= op
;
405 first
= ((u32
*)op
->value
) + (k
/ 9);
407 last
= (u32
*)(op
->value
+ i
);
408 last_cnt
= (k
+ count
) % 9;
409 if (first
+ 1 == last
) {
410 memset (tmp
, '0', 8);
411 if (copy_from_user(tmp
+ first_off
, buf
,
412 (count
+ first_off
> 8) ?
413 8 - first_off
: count
))
417 for (j
= 0; j
< first_off
; j
++)
419 for (j
= 8 - count
- first_off
; j
> 0; j
--)
424 *first
|= simple_strtoul (tmp
, NULL
, 16);
425 op
->flag
|= OPP_DIRTY
;
428 op
->flag
|= OPP_DIRTY
;
429 for (q
= first
; q
< last
; q
++) {
432 memset (tmp
, '0', 8);
433 if (copy_from_user(tmp
+ first_off
,
438 for (j
= 0; j
< first_off
; j
++)
441 *q
|= simple_strtoul (tmp
,NULL
,16);
444 } else if ((q
== last
- 1) && last_cnt
446 memset (tmp
, '0', 8);
447 if (copy_from_user(tmp
, buf
, last_cnt
))
450 for (j
= 0; j
< 8 - last_cnt
; j
++)
453 *q
|= simple_strtoul (tmp
, NULL
, 16);
456 char tchars
[2 * sizeof(long) + 1];
458 if (copy_from_user(tchars
, buf
, sizeof(tchars
) - 1))
460 tchars
[sizeof(tchars
) - 1] = '\0';
461 *q
= simple_strtoul (tchars
, NULL
, 16);
474 if (!(op
->flag
& OPP_BINARY
)) {
475 if (!(op
->flag
& (OPP_QUOTED
| OPP_NOTQUOTED
))) {
478 /* No way, if somebody starts writing from the middle,
479 * we don't know whether he uses quotes around or not
483 if (get_user(ctmp
, buf
))
486 op
->flag
|= OPP_QUOTED
;
491 op
->flag
|= OPP_STRING
;
495 op
->flag
|= OPP_NOTQUOTED
;
497 op
->flag
|= OPP_STRING
;
498 if (op
->alloclen
<= count
+ *ppos
) {
499 b
= kmalloc (sizeof (openprom_property
)
500 + 2 * (count
+ *ppos
), GFP_KERNEL
);
503 memcpy (b
, filp
->private_data
,
504 sizeof (openprom_property
)
505 + strlen (op
->name
) + op
->alloclen
);
506 memset (b
+ sizeof (openprom_property
)
507 + strlen (op
->name
) + op
->alloclen
,
508 0, 2*(count
- *ppos
) - op
->alloclen
);
510 op
->alloclen
= 2*(count
+ *ppos
);
511 b
= filp
->private_data
;
512 filp
->private_data
= op
;
515 p
= op
->value
+ *ppos
- ((op
->flag
& OPP_QUOTED
) ? 1 : 0);
516 if (copy_from_user(p
, buf
, count
))
518 op
->flag
|= OPP_DIRTY
;
519 for (i
= 0; i
< count
; i
++, p
++)
525 op
->len
= p
- op
->value
;
527 if ((p
> op
->value
) && (op
->flag
& OPP_QUOTED
)
528 && (*(p
- 1) == '\''))
531 if (p
- op
->value
> op
->len
)
532 op
->len
= p
- op
->value
;
539 int property_release (struct inode
*inode
, struct file
*filp
)
541 openprom_property
*op
= filp
->private_data
;
548 node
= nodes
[ptr_nod(inode
->u
.generic_ip
)].node
;
549 if (ptr_nod(inode
->u
.generic_ip
) == aliases
) {
550 if ((op
->flag
& OPP_DIRTY
) && (op
->flag
& OPP_STRING
)) {
552 int i
= (op
->value
- op
->name
) - strlen (op
->name
) - 1;
553 op
->value
[op
->len
] = 0;
554 *(op
->value
- 1) = ' ';
556 for (p
= op
->value
- i
- 2; p
>= op
->name
; p
--)
560 memcpy (p
- 8, "nvalias ", 8);
563 } else if (op
->flag
& OPP_DIRTY
) {
564 if (op
->flag
& OPP_STRING
) {
565 op
->value
[op
->len
] = 0;
566 error
= prom_setprop (node
, op
->name
,
567 op
->value
, op
->len
+ 1);
569 printk (KERN_WARNING
"openpromfs: "
570 "Couldn't write property %s\n",
572 } else if ((op
->flag
& OPP_BINARY
) || !op
->len
) {
573 error
= prom_setprop (node
, op
->name
,
576 printk (KERN_WARNING
"openpromfs: "
577 "Couldn't write property %s\n",
580 printk (KERN_WARNING
"openpromfs: "
581 "Unknown property type of %s\n",
586 kfree (filp
->private_data
);
590 static const struct file_operations openpromfs_prop_ops
= {
591 .read
= property_read
,
592 .write
= property_write
,
593 .release
= property_release
,
596 static const struct file_operations openpromfs_nodenum_ops
= {
597 .read
= nodenum_read
,
600 static const struct file_operations openprom_operations
= {
601 .read
= generic_read_dir
,
602 .readdir
= openpromfs_readdir
,
605 static struct inode_operations openprom_alias_inode_operations
= {
606 .create
= openpromfs_create
,
607 .lookup
= openpromfs_lookup
,
608 .unlink
= openpromfs_unlink
,
611 static struct inode_operations openprom_inode_operations
= {
612 .lookup
= openpromfs_lookup
,
615 static int lookup_children(u16 n
, const char * name
, int len
)
619 for (; n
!= 0xffff; n
= nodes
[n
].next
) {
620 node
= nodes
[n
].child
;
621 if (node
!= 0xffff) {
626 while (node
!= 0xffff) {
627 if (prom_getname (nodes
[node
].node
,
631 && !strncmp (buffer
, name
, len
))
632 return NODE2INO(node
);
633 p
= strchr (buffer
, '@');
634 if (p
&& (len
== p
- buffer
)
635 && !strncmp (buffer
, name
, len
))
636 return NODE2INO(node
);
638 node
= nodes
[node
].next
;
642 ret
= lookup_children (nodes
[n
].child
, name
, len
);
648 static struct dentry
*openpromfs_lookup(struct inode
* dir
, struct dentry
*dentry
, struct nameidata
*nd
)
652 #define OPFSL_PROPERTY 1
653 #define OPFSL_NODENUM 2
666 name
= dentry
->d_name
.name
;
667 len
= dentry
->d_name
.len
;
669 if (name
[0] == '.' && len
== 5 && !strncmp (name
+ 1, "node", 4)) {
670 ino
= NODEP2INO(NODE(dir
->i_ino
).first_prop
);
671 type
= OPFSL_NODENUM
;
674 u16 node
= NODE(dir
->i_ino
).child
;
675 while (node
!= 0xffff) {
676 if (prom_getname (nodes
[node
].node
, buffer
, 128) >= 0) {
678 if (len
== i
&& !strncmp (buffer
, name
, len
)) {
679 ino
= NODE2INO(node
);
683 p
= strchr (buffer
, '@');
684 if (p
&& (len
== p
- buffer
)
685 && !strncmp (buffer
, name
, len
)) {
686 ino
= NODE2INO(node
);
691 node
= nodes
[node
].next
;
694 n
= NODE(dir
->i_ino
).node
;
695 dirnode
= dir
->i_ino
- OPENPROM_FIRST_INO
;
697 int j
= NODEP2INO(NODE(dir
->i_ino
).first_prop
);
698 if (dirnode
!= aliases
) {
699 for (p
= prom_firstprop (n
, buffer2
);
701 p
= prom_nextprop (n
, p
, buffer2
)) {
703 if ((len
== strlen (p
))
704 && !strncmp (p
, name
, len
)) {
706 type
= OPFSL_PROPERTY
;
712 for (k
= 0; k
< aliases_nodes
; k
++) {
715 && (len
== strlen (alias_names
[k
]))
716 && !strncmp (alias_names
[k
], name
, len
)) {
718 type
= OPFSL_PROPERTY
;
725 ino
= lookup_children (NODE(dir
->i_ino
).child
, name
, len
);
730 return ERR_PTR(-ENOENT
);
733 inode
= iget (dir
->i_sb
, ino
);
736 return ERR_PTR(-EINVAL
);
739 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
740 if (ino
== OPENPROM_FIRST_INO
+ aliases
) {
741 inode
->i_mode
|= S_IWUSR
;
742 inode
->i_op
= &openprom_alias_inode_operations
;
744 inode
->i_op
= &openprom_inode_operations
;
745 inode
->i_fop
= &openprom_operations
;
749 inode
->i_mode
= S_IFREG
| S_IRUGO
;
750 inode
->i_fop
= &openpromfs_nodenum_ops
;
752 inode
->u
.generic_ip
= (void *)(long)(n
);
755 if ((dirnode
== options
) && (len
== 17)
756 && !strncmp (name
, "security-password", 17))
757 inode
->i_mode
= S_IFREG
| S_IRUSR
| S_IWUSR
;
759 inode
->i_mode
= S_IFREG
| S_IRUGO
;
760 if (dirnode
== options
|| dirnode
== aliases
) {
761 if (len
!= 4 || strncmp (name
, "name", 4))
762 inode
->i_mode
|= S_IWUSR
;
765 inode
->i_fop
= &openpromfs_prop_ops
;
767 if (inode
->i_size
< 0)
769 inode
->u
.generic_ip
= (void *)(long)(((u16
)dirnode
) |
770 (((u16
)(ino
- NODEP2INO(NODE(dir
->i_ino
).first_prop
) - 1)) << 16));
777 d_add(dentry
, inode
);
781 static int openpromfs_readdir(struct file
* filp
, void * dirent
, filldir_t filldir
)
783 struct inode
*inode
= filp
->f_dentry
->d_inode
;
798 if (filldir(dirent
, ".", 1, i
, ino
, DT_DIR
) < 0) goto out
;
803 if (filldir(dirent
, "..", 2, i
,
804 (NODE(ino
).parent
== 0xffff) ?
805 OPENPROM_ROOT_INO
: NODE2INO(NODE(ino
).parent
), DT_DIR
) < 0)
812 node
= NODE(ino
).child
;
813 while (i
&& node
!= 0xffff) {
814 node
= nodes
[node
].next
;
817 while (node
!= 0xffff) {
818 if (prom_getname (nodes
[node
].node
, buffer
, 128) < 0)
820 if (filldir(dirent
, buffer
, strlen(buffer
),
821 filp
->f_pos
, NODE2INO(node
), DT_DIR
) < 0)
824 node
= nodes
[node
].next
;
826 j
= NODEP2INO(NODE(ino
).first_prop
);
828 if (filldir(dirent
, ".node", 5, filp
->f_pos
, j
, DT_REG
) < 0)
834 if (ino
== OPENPROM_FIRST_INO
+ aliases
) {
835 for (j
++; i
< aliases_nodes
; i
++, j
++) {
836 if (alias_names
[i
]) {
837 if (filldir (dirent
, alias_names
[i
],
838 strlen (alias_names
[i
]),
839 filp
->f_pos
, j
, DT_REG
) < 0) goto out
;
844 for (p
= prom_firstprop (n
, buffer2
);
846 p
= prom_nextprop (n
, p
, buffer2
)) {
850 if (filldir(dirent
, p
, strlen(p
),
851 filp
->f_pos
, j
, DT_REG
) < 0)
863 static int openpromfs_create (struct inode
*dir
, struct dentry
*dentry
, int mode
,
864 struct nameidata
*nd
)
871 if (dentry
->d_name
.len
> 256)
873 p
= kmalloc (dentry
->d_name
.len
+ 1, GFP_KERNEL
);
876 strncpy (p
, dentry
->d_name
.name
, dentry
->d_name
.len
);
877 p
[dentry
->d_name
.len
] = 0;
879 if (aliases_nodes
== ALIASES_NNODES
) {
884 alias_names
[aliases_nodes
++] = p
;
885 inode
= iget (dir
->i_sb
,
886 NODEP2INO(NODE(dir
->i_ino
).first_prop
) + aliases_nodes
);
891 inode
->i_mode
= S_IFREG
| S_IRUGO
| S_IWUSR
;
892 inode
->i_fop
= &openpromfs_prop_ops
;
894 if (inode
->i_size
< 0) inode
->i_size
= 0;
895 inode
->u
.generic_ip
= (void *)(long)(((u16
)aliases
) |
896 (((u16
)(aliases_nodes
- 1)) << 16));
898 d_instantiate(dentry
, inode
);
902 static int openpromfs_unlink (struct inode
*dir
, struct dentry
*dentry
)
909 name
= dentry
->d_name
.name
;
910 len
= dentry
->d_name
.len
;
912 for (i
= 0; i
< aliases_nodes
; i
++)
913 if ((strlen (alias_names
[i
]) == len
)
914 && !strncmp (name
, alias_names
[i
], len
)) {
918 alias_names
[i
] = NULL
;
920 strcpy (buffer
, "nvunalias ");
921 memcpy (buffer
+ 10, name
, len
);
922 buffer
[10 + len
] = 0;
929 /* {{{ init section */
930 static int __init
check_space (u16 n
)
934 if ((1 << alloced
) * PAGE_SIZE
< (n
+ 2) * sizeof(openpromfs_node
)) {
935 pages
= __get_free_pages (GFP_KERNEL
, alloced
+ 1);
940 memcpy ((char *)pages
, nodes
,
941 (1 << alloced
) * PAGE_SIZE
);
942 free_pages ((unsigned long)nodes
, alloced
);
945 nodes
= (openpromfs_node
*)pages
;
950 static u16 __init
get_nodes (u16 parent
, u32 node
)
953 u16 n
= last_node
++, i
;
956 if (check_space (n
) < 0)
958 nodes
[n
].parent
= parent
;
959 nodes
[n
].node
= node
;
960 nodes
[n
].next
= 0xffff;
961 nodes
[n
].child
= 0xffff;
962 nodes
[n
].first_prop
= first_prop
++;
967 if ((j
= prom_getproperty (node
, "name", buffer
, 8)) >= 0) {
969 if (!strcmp (buffer
, "options"))
971 else if (!strcmp (buffer
, "aliases"))
976 for (p
= prom_firstprop (node
, buffer
);
977 p
&& p
!= (char *)-1 && *p
;
978 p
= prom_nextprop (node
, p
, buffer
))
982 for (p
= prom_firstprop (node
, buffer
);
983 p
&& p
!= (char *)-1 && *p
;
984 p
= prom_nextprop (node
, p
, buffer
)) {
985 if (aliases_nodes
== ALIASES_NNODES
)
987 for (i
= 0; i
< aliases_nodes
; i
++)
988 if (!strcmp (p
, alias_names
[i
]))
990 if (i
< aliases_nodes
)
992 q
= kmalloc (strlen (p
) + 1, GFP_KERNEL
);
996 alias_names
[aliases_nodes
++] = q
;
998 first_prop
+= ALIASES_NNODES
;
1000 node
= prom_getchild (node
);
1002 parent
= get_nodes (n
, node
);
1003 if (parent
== 0xffff)
1005 nodes
[n
].child
= parent
;
1006 while ((node
= prom_getsibling (node
)) != 0) {
1007 i
= get_nodes (n
, node
);
1010 nodes
[parent
].next
= i
;
1017 static void openprom_read_inode(struct inode
* inode
)
1019 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
1020 if (inode
->i_ino
== OPENPROM_ROOT_INO
) {
1021 inode
->i_op
= &openprom_inode_operations
;
1022 inode
->i_fop
= &openprom_operations
;
1023 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
1027 static int openprom_remount(struct super_block
*sb
, int *flags
, char *data
)
1029 *flags
|= MS_NOATIME
;
1033 static struct super_operations openprom_sops
= {
1034 .read_inode
= openprom_read_inode
,
1035 .statfs
= simple_statfs
,
1036 .remount_fs
= openprom_remount
,
1039 static int openprom_fill_super(struct super_block
*s
, void *data
, int silent
)
1041 struct inode
* root_inode
;
1043 s
->s_flags
|= MS_NOATIME
;
1044 s
->s_blocksize
= 1024;
1045 s
->s_blocksize_bits
= 10;
1046 s
->s_magic
= OPENPROM_SUPER_MAGIC
;
1047 s
->s_op
= &openprom_sops
;
1049 root_inode
= iget(s
, OPENPROM_ROOT_INO
);
1052 s
->s_root
= d_alloc_root(root_inode
);
1058 printk("openprom_fill_super: get root inode failed\n");
1063 static int openprom_get_sb(struct file_system_type
*fs_type
,
1064 int flags
, const char *dev_name
, void *data
, struct vfsmount
*mnt
)
1066 return get_sb_single(fs_type
, flags
, data
, openprom_fill_super
, mnt
);
1069 static struct file_system_type openprom_fs_type
= {
1070 .owner
= THIS_MODULE
,
1071 .name
= "openpromfs",
1072 .get_sb
= openprom_get_sb
,
1073 .kill_sb
= kill_anon_super
,
1076 static int __init
init_openprom_fs(void)
1078 nodes
= (openpromfs_node
*)__get_free_pages(GFP_KERNEL
, 0);
1080 printk (KERN_WARNING
"openpromfs: can't get free page\n");
1083 if (get_nodes (0xffff, prom_root_node
) == 0xffff) {
1084 printk (KERN_WARNING
"openpromfs: couldn't setup tree\n");
1087 nodes
[last_node
].first_prop
= first_prop
;
1088 return register_filesystem(&openprom_fs_type
);
1091 static void __exit
exit_openprom_fs(void)
1094 unregister_filesystem(&openprom_fs_type
);
1095 free_pages ((unsigned long)nodes
, alloced
);
1096 for (i
= 0; i
< aliases_nodes
; i
++)
1097 kfree (alias_names
[i
]);
1101 module_init(init_openprom_fs
)
1102 module_exit(exit_openprom_fs
)
1103 MODULE_LICENSE("GPL");