Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* inode.c: /proc/openprom handling routines
  3 *
  4 * Copyright (C) 1996-1999 Jakub Jelinek  (jakub@redhat.com)
  5 * Copyright (C) 1998      Eddie C. Dost  (ecd@skynet.be)
  6 */
  7
  8#include <linux/module.h>
  9#include <linux/types.h>
 10#include <linux/string.h>
 11#include <linux/fs.h>
 12#include <linux/fs_context.h>
 13#include <linux/init.h>
 14#include <linux/slab.h>
 15#include <linux/seq_file.h>
 16#include <linux/magic.h>
 17
 18#include <asm/openprom.h>
 19#include <asm/oplib.h>
 20#include <asm/prom.h>
 21#include <linux/uaccess.h>
 22
 23static DEFINE_MUTEX(op_mutex);
 24
 25#define OPENPROM_ROOT_INO	0
 26
 27enum op_inode_type {
 28	op_inode_node,
 29	op_inode_prop,
 30};
 31
 32union op_inode_data {
 33	struct device_node	*node;
 34	struct property		*prop;
 35};
 36
 37struct op_inode_info {
 38	struct inode		vfs_inode;
 39	enum op_inode_type	type;
 40	union op_inode_data	u;
 41};
 42
 43static struct inode *openprom_iget(struct super_block *sb, ino_t ino);
 44
 45static inline struct op_inode_info *OP_I(struct inode *inode)
 46{
 47	return container_of(inode, struct op_inode_info, vfs_inode);
 48}
 49
 50static int is_string(unsigned char *p, int len)
 51{
 52	int i;
 53
 54	for (i = 0; i < len; i++) {
 55		unsigned char val = p[i];
 56
 57		if ((i && !val) ||
 58		    (val >= ' ' && val <= '~'))
 59			continue;
 60
 61		return 0;
 62	}
 63
 64	return 1;
 65}
 66
 67static int property_show(struct seq_file *f, void *v)
 68{
 69	struct property *prop = f->private;
 70	void *pval;
 71	int len;
 72
 73	len = prop->length;
 74	pval = prop->value;
 75
 76	if (is_string(pval, len)) {
 77		while (len > 0) {
 78			int n = strlen(pval);
 79
 80			seq_printf(f, "%s", (char *) pval);
 81
 82			/* Skip over the NULL byte too.  */
 83			pval += n + 1;
 84			len -= n + 1;
 85
 86			if (len > 0)
 87				seq_printf(f, " + ");
 88		}
 89	} else {
 90		if (len & 3) {
 91			while (len) {
 92				len--;
 93				if (len)
 94					seq_printf(f, "%02x.",
 95						   *(unsigned char *) pval);
 96				else
 97					seq_printf(f, "%02x",
 98						   *(unsigned char *) pval);
 99				pval++;
100			}
101		} else {
102			while (len >= 4) {
103				len -= 4;
104
105				if (len)
106					seq_printf(f, "%08x.",
107						   *(unsigned int *) pval);
108				else
109					seq_printf(f, "%08x",
110						   *(unsigned int *) pval);
111				pval += 4;
112			}
113		}
114	}
115	seq_printf(f, "\n");
116
117	return 0;
118}
119
120static void *property_start(struct seq_file *f, loff_t *pos)
121{
122	if (*pos == 0)
123		return pos;
124	return NULL;
125}
126
127static void *property_next(struct seq_file *f, void *v, loff_t *pos)
128{
129	(*pos)++;
130	return NULL;
131}
132
133static void property_stop(struct seq_file *f, void *v)
134{
135	/* Nothing to do */
136}
137
138static const struct seq_operations property_op = {
139	.start		= property_start,
140	.next		= property_next,
141	.stop		= property_stop,
142	.show		= property_show
143};
144
145static int property_open(struct inode *inode, struct file *file)
146{
147	struct op_inode_info *oi = OP_I(inode);
148	int ret;
149
150	BUG_ON(oi->type != op_inode_prop);
151
152	ret = seq_open(file, &property_op);
153	if (!ret) {
154		struct seq_file *m = file->private_data;
155		m->private = oi->u.prop;
156	}
157	return ret;
158}
159
160static const struct file_operations openpromfs_prop_ops = {
161	.open		= property_open,
162	.read		= seq_read,
163	.llseek		= seq_lseek,
164	.release	= seq_release,
165};
166
167static int openpromfs_readdir(struct file *, struct dir_context *);
168
169static const struct file_operations openprom_operations = {
170	.read		= generic_read_dir,
171	.iterate_shared	= openpromfs_readdir,
172	.llseek		= generic_file_llseek,
173};
174
175static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, unsigned int);
176
177static const struct inode_operations openprom_inode_operations = {
178	.lookup		= openpromfs_lookup,
179};
180
181static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
182{
183	struct op_inode_info *ent_oi, *oi = OP_I(dir);
184	struct device_node *dp, *child;
185	struct property *prop;
186	enum op_inode_type ent_type;
187	union op_inode_data ent_data;
188	const char *name;
189	struct inode *inode;
190	unsigned int ino;
191	int len;
192	
193	BUG_ON(oi->type != op_inode_node);
194
195	dp = oi->u.node;
196
197	name = dentry->d_name.name;
198	len = dentry->d_name.len;
199
200	mutex_lock(&op_mutex);
201
202	child = dp->child;
203	while (child) {
204		const char *node_name = kbasename(child->full_name);
205		int n = strlen(node_name);
206
207		if (len == n &&
208		    !strncmp(node_name, name, len)) {
209			ent_type = op_inode_node;
210			ent_data.node = child;
211			ino = child->unique_id;
212			goto found;
213		}
214		child = child->sibling;
215	}
216
217	prop = dp->properties;
218	while (prop) {
219		int n = strlen(prop->name);
220
221		if (len == n && !strncmp(prop->name, name, len)) {
222			ent_type = op_inode_prop;
223			ent_data.prop = prop;
224			ino = prop->unique_id;
225			goto found;
226		}
227
228		prop = prop->next;
229	}
230
231	mutex_unlock(&op_mutex);
232	return ERR_PTR(-ENOENT);
233
234found:
235	inode = openprom_iget(dir->i_sb, ino);
236	mutex_unlock(&op_mutex);
237	if (IS_ERR(inode))
238		return ERR_CAST(inode);
239	if (inode->i_state & I_NEW) {
240		simple_inode_init_ts(inode);
241		ent_oi = OP_I(inode);
242		ent_oi->type = ent_type;
243		ent_oi->u = ent_data;
244
245		switch (ent_type) {
246		case op_inode_node:
247			inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
248			inode->i_op = &openprom_inode_operations;
249			inode->i_fop = &openprom_operations;
250			set_nlink(inode, 2);
251			break;
252		case op_inode_prop:
253			if (of_node_name_eq(dp, "options") && (len == 17) &&
254			    !strncmp (name, "security-password", 17))
255				inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
256			else
257				inode->i_mode = S_IFREG | S_IRUGO;
258			inode->i_fop = &openpromfs_prop_ops;
259			set_nlink(inode, 1);
260			inode->i_size = ent_oi->u.prop->length;
261			break;
262		}
263		unlock_new_inode(inode);
264	}
265
266	return d_splice_alias(inode, dentry);
267}
268
269static int openpromfs_readdir(struct file *file, struct dir_context *ctx)
270{
271	struct inode *inode = file_inode(file);
272	struct op_inode_info *oi = OP_I(inode);
273	struct device_node *dp = oi->u.node;
274	struct device_node *child;
275	struct property *prop;
276	int i;
277
278	mutex_lock(&op_mutex);
279	
280	if (ctx->pos == 0) {
281		if (!dir_emit(ctx, ".", 1, inode->i_ino, DT_DIR))
282			goto out;
283		ctx->pos = 1;
284	}
285	if (ctx->pos == 1) {
286		if (!dir_emit(ctx, "..", 2,
287			    (dp->parent == NULL ?
288			     OPENPROM_ROOT_INO :
289			     dp->parent->unique_id), DT_DIR))
290			goto out;
291		ctx->pos = 2;
292	}
293	i = ctx->pos - 2;
294
295	/* First, the children nodes as directories.  */
296	child = dp->child;
297	while (i && child) {
298		child = child->sibling;
299		i--;
300	}
301	while (child) {
302		if (!dir_emit(ctx,
303			    kbasename(child->full_name),
304			    strlen(kbasename(child->full_name)),
305			    child->unique_id, DT_DIR))
306			goto out;
307
308		ctx->pos++;
309		child = child->sibling;
310	}
311
312	/* Next, the properties as files.  */
313	prop = dp->properties;
314	while (i && prop) {
315		prop = prop->next;
316		i--;
317	}
318	while (prop) {
319		if (!dir_emit(ctx, prop->name, strlen(prop->name),
320			    prop->unique_id, DT_REG))
321			goto out;
322
323		ctx->pos++;
324		prop = prop->next;
325	}
326
327out:
328	mutex_unlock(&op_mutex);
329	return 0;
330}
331
332static struct kmem_cache *op_inode_cachep;
333
334static struct inode *openprom_alloc_inode(struct super_block *sb)
335{
336	struct op_inode_info *oi;
337
338	oi = alloc_inode_sb(sb, op_inode_cachep, GFP_KERNEL);
339	if (!oi)
340		return NULL;
341
342	return &oi->vfs_inode;
343}
344
345static void openprom_free_inode(struct inode *inode)
346{
347	kmem_cache_free(op_inode_cachep, OP_I(inode));
348}
349
350static struct inode *openprom_iget(struct super_block *sb, ino_t ino)
351{
352	struct inode *inode = iget_locked(sb, ino);
 
 
353	if (!inode)
354		inode = ERR_PTR(-ENOMEM);
 
 
 
 
 
 
 
 
 
355	return inode;
356}
357
358static int openpromfs_reconfigure(struct fs_context *fc)
359{
360	sync_filesystem(fc->root->d_sb);
361	fc->sb_flags |= SB_NOATIME;
362	return 0;
363}
364
365static const struct super_operations openprom_sops = {
366	.alloc_inode	= openprom_alloc_inode,
367	.free_inode	= openprom_free_inode,
368	.statfs		= simple_statfs,
 
369};
370
371static int openprom_fill_super(struct super_block *s, struct fs_context *fc)
372{
373	struct inode *root_inode;
374	struct op_inode_info *oi;
375	int ret;
376
377	s->s_flags |= SB_NOATIME;
378	s->s_blocksize = 1024;
379	s->s_blocksize_bits = 10;
380	s->s_magic = OPENPROM_SUPER_MAGIC;
381	s->s_op = &openprom_sops;
382	s->s_time_gran = 1;
383	root_inode = openprom_iget(s, OPENPROM_ROOT_INO);
384	if (IS_ERR(root_inode)) {
385		ret = PTR_ERR(root_inode);
386		goto out_no_root;
387	}
388
389	simple_inode_init_ts(root_inode);
390	root_inode->i_op = &openprom_inode_operations;
391	root_inode->i_fop = &openprom_operations;
392	root_inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
393	oi = OP_I(root_inode);
394	oi->type = op_inode_node;
395	oi->u.node = of_find_node_by_path("/");
396	unlock_new_inode(root_inode);
397
398	s->s_root = d_make_root(root_inode);
399	if (!s->s_root)
400		goto out_no_root_dentry;
401	return 0;
402
403out_no_root_dentry:
404	ret = -ENOMEM;
405out_no_root:
406	printk("openprom_fill_super: get root inode failed\n");
407	return ret;
408}
409
410static int openpromfs_get_tree(struct fs_context *fc)
411{
412	return get_tree_single(fc, openprom_fill_super);
413}
414
415static const struct fs_context_operations openpromfs_context_ops = {
416	.get_tree	= openpromfs_get_tree,
417	.reconfigure	= openpromfs_reconfigure,
418};
419
420static int openpromfs_init_fs_context(struct fs_context *fc)
421{
422	fc->ops = &openpromfs_context_ops;
423	return 0;
424}
425
426static struct file_system_type openprom_fs_type = {
427	.owner		= THIS_MODULE,
428	.name		= "openpromfs",
429	.init_fs_context = openpromfs_init_fs_context,
430	.kill_sb	= kill_anon_super,
431};
432MODULE_ALIAS_FS("openpromfs");
433
434static void op_inode_init_once(void *data)
435{
436	struct op_inode_info *oi = (struct op_inode_info *) data;
437
438	inode_init_once(&oi->vfs_inode);
439}
440
441static int __init init_openprom_fs(void)
442{
443	int err;
444
445	op_inode_cachep = kmem_cache_create("op_inode_cache",
446					    sizeof(struct op_inode_info),
447					    0,
448					    (SLAB_RECLAIM_ACCOUNT |
449					     SLAB_ACCOUNT),
450					    op_inode_init_once);
451	if (!op_inode_cachep)
452		return -ENOMEM;
453
454	err = register_filesystem(&openprom_fs_type);
455	if (err)
456		kmem_cache_destroy(op_inode_cachep);
457
458	return err;
459}
460
461static void __exit exit_openprom_fs(void)
462{
463	unregister_filesystem(&openprom_fs_type);
464	/*
465	 * Make sure all delayed rcu free inodes are flushed before we
466	 * destroy cache.
467	 */
468	rcu_barrier();
469	kmem_cache_destroy(op_inode_cachep);
470}
471
472module_init(init_openprom_fs)
473module_exit(exit_openprom_fs)
474MODULE_DESCRIPTION("OpenPROM filesystem support");
475MODULE_LICENSE("GPL");
v5.9
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* inode.c: /proc/openprom handling routines
  3 *
  4 * Copyright (C) 1996-1999 Jakub Jelinek  (jakub@redhat.com)
  5 * Copyright (C) 1998      Eddie C. Dost  (ecd@skynet.be)
  6 */
  7
  8#include <linux/module.h>
  9#include <linux/types.h>
 10#include <linux/string.h>
 11#include <linux/fs.h>
 12#include <linux/fs_context.h>
 13#include <linux/init.h>
 14#include <linux/slab.h>
 15#include <linux/seq_file.h>
 16#include <linux/magic.h>
 17
 18#include <asm/openprom.h>
 19#include <asm/oplib.h>
 20#include <asm/prom.h>
 21#include <linux/uaccess.h>
 22
 23static DEFINE_MUTEX(op_mutex);
 24
 25#define OPENPROM_ROOT_INO	0
 26
 27enum op_inode_type {
 28	op_inode_node,
 29	op_inode_prop,
 30};
 31
 32union op_inode_data {
 33	struct device_node	*node;
 34	struct property		*prop;
 35};
 36
 37struct op_inode_info {
 38	struct inode		vfs_inode;
 39	enum op_inode_type	type;
 40	union op_inode_data	u;
 41};
 42
 43static struct inode *openprom_iget(struct super_block *sb, ino_t ino);
 44
 45static inline struct op_inode_info *OP_I(struct inode *inode)
 46{
 47	return container_of(inode, struct op_inode_info, vfs_inode);
 48}
 49
 50static int is_string(unsigned char *p, int len)
 51{
 52	int i;
 53
 54	for (i = 0; i < len; i++) {
 55		unsigned char val = p[i];
 56
 57		if ((i && !val) ||
 58		    (val >= ' ' && val <= '~'))
 59			continue;
 60
 61		return 0;
 62	}
 63
 64	return 1;
 65}
 66
 67static int property_show(struct seq_file *f, void *v)
 68{
 69	struct property *prop = f->private;
 70	void *pval;
 71	int len;
 72
 73	len = prop->length;
 74	pval = prop->value;
 75
 76	if (is_string(pval, len)) {
 77		while (len > 0) {
 78			int n = strlen(pval);
 79
 80			seq_printf(f, "%s", (char *) pval);
 81
 82			/* Skip over the NULL byte too.  */
 83			pval += n + 1;
 84			len -= n + 1;
 85
 86			if (len > 0)
 87				seq_printf(f, " + ");
 88		}
 89	} else {
 90		if (len & 3) {
 91			while (len) {
 92				len--;
 93				if (len)
 94					seq_printf(f, "%02x.",
 95						   *(unsigned char *) pval);
 96				else
 97					seq_printf(f, "%02x",
 98						   *(unsigned char *) pval);
 99				pval++;
100			}
101		} else {
102			while (len >= 4) {
103				len -= 4;
104
105				if (len)
106					seq_printf(f, "%08x.",
107						   *(unsigned int *) pval);
108				else
109					seq_printf(f, "%08x",
110						   *(unsigned int *) pval);
111				pval += 4;
112			}
113		}
114	}
115	seq_printf(f, "\n");
116
117	return 0;
118}
119
120static void *property_start(struct seq_file *f, loff_t *pos)
121{
122	if (*pos == 0)
123		return pos;
124	return NULL;
125}
126
127static void *property_next(struct seq_file *f, void *v, loff_t *pos)
128{
129	(*pos)++;
130	return NULL;
131}
132
133static void property_stop(struct seq_file *f, void *v)
134{
135	/* Nothing to do */
136}
137
138static const struct seq_operations property_op = {
139	.start		= property_start,
140	.next		= property_next,
141	.stop		= property_stop,
142	.show		= property_show
143};
144
145static int property_open(struct inode *inode, struct file *file)
146{
147	struct op_inode_info *oi = OP_I(inode);
148	int ret;
149
150	BUG_ON(oi->type != op_inode_prop);
151
152	ret = seq_open(file, &property_op);
153	if (!ret) {
154		struct seq_file *m = file->private_data;
155		m->private = oi->u.prop;
156	}
157	return ret;
158}
159
160static const struct file_operations openpromfs_prop_ops = {
161	.open		= property_open,
162	.read		= seq_read,
163	.llseek		= seq_lseek,
164	.release	= seq_release,
165};
166
167static int openpromfs_readdir(struct file *, struct dir_context *);
168
169static const struct file_operations openprom_operations = {
170	.read		= generic_read_dir,
171	.iterate_shared	= openpromfs_readdir,
172	.llseek		= generic_file_llseek,
173};
174
175static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, unsigned int);
176
177static const struct inode_operations openprom_inode_operations = {
178	.lookup		= openpromfs_lookup,
179};
180
181static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
182{
183	struct op_inode_info *ent_oi, *oi = OP_I(dir);
184	struct device_node *dp, *child;
185	struct property *prop;
186	enum op_inode_type ent_type;
187	union op_inode_data ent_data;
188	const char *name;
189	struct inode *inode;
190	unsigned int ino;
191	int len;
192	
193	BUG_ON(oi->type != op_inode_node);
194
195	dp = oi->u.node;
196
197	name = dentry->d_name.name;
198	len = dentry->d_name.len;
199
200	mutex_lock(&op_mutex);
201
202	child = dp->child;
203	while (child) {
204		const char *node_name = kbasename(child->full_name);
205		int n = strlen(node_name);
206
207		if (len == n &&
208		    !strncmp(node_name, name, len)) {
209			ent_type = op_inode_node;
210			ent_data.node = child;
211			ino = child->unique_id;
212			goto found;
213		}
214		child = child->sibling;
215	}
216
217	prop = dp->properties;
218	while (prop) {
219		int n = strlen(prop->name);
220
221		if (len == n && !strncmp(prop->name, name, len)) {
222			ent_type = op_inode_prop;
223			ent_data.prop = prop;
224			ino = prop->unique_id;
225			goto found;
226		}
227
228		prop = prop->next;
229	}
230
231	mutex_unlock(&op_mutex);
232	return ERR_PTR(-ENOENT);
233
234found:
235	inode = openprom_iget(dir->i_sb, ino);
236	mutex_unlock(&op_mutex);
237	if (IS_ERR(inode))
238		return ERR_CAST(inode);
239	ent_oi = OP_I(inode);
240	ent_oi->type = ent_type;
241	ent_oi->u = ent_data;
242
243	switch (ent_type) {
244	case op_inode_node:
245		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
246		inode->i_op = &openprom_inode_operations;
247		inode->i_fop = &openprom_operations;
248		set_nlink(inode, 2);
249		break;
250	case op_inode_prop:
251		if (of_node_name_eq(dp, "options") && (len == 17) &&
252		    !strncmp (name, "security-password", 17))
253			inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
254		else
255			inode->i_mode = S_IFREG | S_IRUGO;
256		inode->i_fop = &openpromfs_prop_ops;
257		set_nlink(inode, 1);
258		inode->i_size = ent_oi->u.prop->length;
259		break;
 
 
 
 
260	}
261
262	return d_splice_alias(inode, dentry);
263}
264
265static int openpromfs_readdir(struct file *file, struct dir_context *ctx)
266{
267	struct inode *inode = file_inode(file);
268	struct op_inode_info *oi = OP_I(inode);
269	struct device_node *dp = oi->u.node;
270	struct device_node *child;
271	struct property *prop;
272	int i;
273
274	mutex_lock(&op_mutex);
275	
276	if (ctx->pos == 0) {
277		if (!dir_emit(ctx, ".", 1, inode->i_ino, DT_DIR))
278			goto out;
279		ctx->pos = 1;
280	}
281	if (ctx->pos == 1) {
282		if (!dir_emit(ctx, "..", 2,
283			    (dp->parent == NULL ?
284			     OPENPROM_ROOT_INO :
285			     dp->parent->unique_id), DT_DIR))
286			goto out;
287		ctx->pos = 2;
288	}
289	i = ctx->pos - 2;
290
291	/* First, the children nodes as directories.  */
292	child = dp->child;
293	while (i && child) {
294		child = child->sibling;
295		i--;
296	}
297	while (child) {
298		if (!dir_emit(ctx,
299			    kbasename(child->full_name),
300			    strlen(kbasename(child->full_name)),
301			    child->unique_id, DT_DIR))
302			goto out;
303
304		ctx->pos++;
305		child = child->sibling;
306	}
307
308	/* Next, the properties as files.  */
309	prop = dp->properties;
310	while (i && prop) {
311		prop = prop->next;
312		i--;
313	}
314	while (prop) {
315		if (!dir_emit(ctx, prop->name, strlen(prop->name),
316			    prop->unique_id, DT_REG))
317			goto out;
318
319		ctx->pos++;
320		prop = prop->next;
321	}
322
323out:
324	mutex_unlock(&op_mutex);
325	return 0;
326}
327
328static struct kmem_cache *op_inode_cachep;
329
330static struct inode *openprom_alloc_inode(struct super_block *sb)
331{
332	struct op_inode_info *oi;
333
334	oi = kmem_cache_alloc(op_inode_cachep, GFP_KERNEL);
335	if (!oi)
336		return NULL;
337
338	return &oi->vfs_inode;
339}
340
341static void openprom_free_inode(struct inode *inode)
342{
343	kmem_cache_free(op_inode_cachep, OP_I(inode));
344}
345
346static struct inode *openprom_iget(struct super_block *sb, ino_t ino)
347{
348	struct inode *inode;
349
350	inode = iget_locked(sb, ino);
351	if (!inode)
352		return ERR_PTR(-ENOMEM);
353	if (inode->i_state & I_NEW) {
354		inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
355		if (inode->i_ino == OPENPROM_ROOT_INO) {
356			inode->i_op = &openprom_inode_operations;
357			inode->i_fop = &openprom_operations;
358			inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
359		}
360		unlock_new_inode(inode);
361	}
362	return inode;
363}
364
365static int openprom_remount(struct super_block *sb, int *flags, char *data)
366{
367	sync_filesystem(sb);
368	*flags |= SB_NOATIME;
369	return 0;
370}
371
372static const struct super_operations openprom_sops = {
373	.alloc_inode	= openprom_alloc_inode,
374	.free_inode	= openprom_free_inode,
375	.statfs		= simple_statfs,
376	.remount_fs	= openprom_remount,
377};
378
379static int openprom_fill_super(struct super_block *s, struct fs_context *fc)
380{
381	struct inode *root_inode;
382	struct op_inode_info *oi;
383	int ret;
384
385	s->s_flags |= SB_NOATIME;
386	s->s_blocksize = 1024;
387	s->s_blocksize_bits = 10;
388	s->s_magic = OPENPROM_SUPER_MAGIC;
389	s->s_op = &openprom_sops;
390	s->s_time_gran = 1;
391	root_inode = openprom_iget(s, OPENPROM_ROOT_INO);
392	if (IS_ERR(root_inode)) {
393		ret = PTR_ERR(root_inode);
394		goto out_no_root;
395	}
396
 
 
 
 
397	oi = OP_I(root_inode);
398	oi->type = op_inode_node;
399	oi->u.node = of_find_node_by_path("/");
 
400
401	s->s_root = d_make_root(root_inode);
402	if (!s->s_root)
403		goto out_no_root_dentry;
404	return 0;
405
406out_no_root_dentry:
407	ret = -ENOMEM;
408out_no_root:
409	printk("openprom_fill_super: get root inode failed\n");
410	return ret;
411}
412
413static int openpromfs_get_tree(struct fs_context *fc)
414{
415	return get_tree_single(fc, openprom_fill_super);
416}
417
418static const struct fs_context_operations openpromfs_context_ops = {
419	.get_tree	= openpromfs_get_tree,
 
420};
421
422static int openpromfs_init_fs_context(struct fs_context *fc)
423{
424	fc->ops = &openpromfs_context_ops;
425	return 0;
426}
427
428static struct file_system_type openprom_fs_type = {
429	.owner		= THIS_MODULE,
430	.name		= "openpromfs",
431	.init_fs_context = openpromfs_init_fs_context,
432	.kill_sb	= kill_anon_super,
433};
434MODULE_ALIAS_FS("openpromfs");
435
436static void op_inode_init_once(void *data)
437{
438	struct op_inode_info *oi = (struct op_inode_info *) data;
439
440	inode_init_once(&oi->vfs_inode);
441}
442
443static int __init init_openprom_fs(void)
444{
445	int err;
446
447	op_inode_cachep = kmem_cache_create("op_inode_cache",
448					    sizeof(struct op_inode_info),
449					    0,
450					    (SLAB_RECLAIM_ACCOUNT |
451					     SLAB_MEM_SPREAD | SLAB_ACCOUNT),
452					    op_inode_init_once);
453	if (!op_inode_cachep)
454		return -ENOMEM;
455
456	err = register_filesystem(&openprom_fs_type);
457	if (err)
458		kmem_cache_destroy(op_inode_cachep);
459
460	return err;
461}
462
463static void __exit exit_openprom_fs(void)
464{
465	unregister_filesystem(&openprom_fs_type);
466	/*
467	 * Make sure all delayed rcu free inodes are flushed before we
468	 * destroy cache.
469	 */
470	rcu_barrier();
471	kmem_cache_destroy(op_inode_cachep);
472}
473
474module_init(init_openprom_fs)
475module_exit(exit_openprom_fs)
 
476MODULE_LICENSE("GPL");