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");
v6.2
  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		inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(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 openprom_remount(struct super_block *sb, int *flags, char *data)
359{
360	sync_filesystem(sb);
361	*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	.remount_fs	= openprom_remount,
370};
371
372static int openprom_fill_super(struct super_block *s, struct fs_context *fc)
373{
374	struct inode *root_inode;
375	struct op_inode_info *oi;
376	int ret;
377
378	s->s_flags |= SB_NOATIME;
379	s->s_blocksize = 1024;
380	s->s_blocksize_bits = 10;
381	s->s_magic = OPENPROM_SUPER_MAGIC;
382	s->s_op = &openprom_sops;
383	s->s_time_gran = 1;
384	root_inode = openprom_iget(s, OPENPROM_ROOT_INO);
385	if (IS_ERR(root_inode)) {
386		ret = PTR_ERR(root_inode);
387		goto out_no_root;
388	}
389
390	root_inode->i_mtime = root_inode->i_atime =
391		root_inode->i_ctime = current_time(root_inode);
392	root_inode->i_op = &openprom_inode_operations;
393	root_inode->i_fop = &openprom_operations;
394	root_inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
395	oi = OP_I(root_inode);
396	oi->type = op_inode_node;
397	oi->u.node = of_find_node_by_path("/");
398	unlock_new_inode(root_inode);
399
400	s->s_root = d_make_root(root_inode);
401	if (!s->s_root)
402		goto out_no_root_dentry;
403	return 0;
404
405out_no_root_dentry:
406	ret = -ENOMEM;
407out_no_root:
408	printk("openprom_fill_super: get root inode failed\n");
409	return ret;
410}
411
412static int openpromfs_get_tree(struct fs_context *fc)
413{
414	return get_tree_single(fc, openprom_fill_super);
415}
416
417static const struct fs_context_operations openpromfs_context_ops = {
418	.get_tree	= openpromfs_get_tree,
 
419};
420
421static int openpromfs_init_fs_context(struct fs_context *fc)
422{
423	fc->ops = &openpromfs_context_ops;
424	return 0;
425}
426
427static struct file_system_type openprom_fs_type = {
428	.owner		= THIS_MODULE,
429	.name		= "openpromfs",
430	.init_fs_context = openpromfs_init_fs_context,
431	.kill_sb	= kill_anon_super,
432};
433MODULE_ALIAS_FS("openpromfs");
434
435static void op_inode_init_once(void *data)
436{
437	struct op_inode_info *oi = (struct op_inode_info *) data;
438
439	inode_init_once(&oi->vfs_inode);
440}
441
442static int __init init_openprom_fs(void)
443{
444	int err;
445
446	op_inode_cachep = kmem_cache_create("op_inode_cache",
447					    sizeof(struct op_inode_info),
448					    0,
449					    (SLAB_RECLAIM_ACCOUNT |
450					     SLAB_MEM_SPREAD | SLAB_ACCOUNT),
451					    op_inode_init_once);
452	if (!op_inode_cachep)
453		return -ENOMEM;
454
455	err = register_filesystem(&openprom_fs_type);
456	if (err)
457		kmem_cache_destroy(op_inode_cachep);
458
459	return err;
460}
461
462static void __exit exit_openprom_fs(void)
463{
464	unregister_filesystem(&openprom_fs_type);
465	/*
466	 * Make sure all delayed rcu free inodes are flushed before we
467	 * destroy cache.
468	 */
469	rcu_barrier();
470	kmem_cache_destroy(op_inode_cachep);
471}
472
473module_init(init_openprom_fs)
474module_exit(exit_openprom_fs)
 
475MODULE_LICENSE("GPL");