Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1/*
  2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  3 * Licensed under the GPL
  4 */
  5
  6#include <linux/ctype.h>
  7#include <linux/dcache.h>
  8#include <linux/file.h>
  9#include <linux/fs.h>
 10#include <linux/init.h>
 11#include <linux/kernel.h>
 12#include <linux/list.h>
 13#include <linux/module.h>
 14#include <linux/mount.h>
 15#include <linux/slab.h>
 16#include <linux/statfs.h>
 17#include <linux/types.h>
 18#include <linux/pid_namespace.h>
 19#include <linux/namei.h>
 20#include <asm/uaccess.h>
 21#include "os.h"
 22
 23static struct inode *get_inode(struct super_block *, struct dentry *);
 24
 25struct hppfs_data {
 26	struct list_head list;
 27	char contents[PAGE_SIZE - sizeof(struct list_head)];
 28};
 29
 30struct hppfs_private {
 31	struct file *proc_file;
 32	int host_fd;
 33	loff_t len;
 34	struct hppfs_data *contents;
 35};
 36
 37struct hppfs_inode_info {
 38	struct dentry *proc_dentry;
 39	struct inode vfs_inode;
 40};
 41
 42static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode)
 43{
 44	return container_of(inode, struct hppfs_inode_info, vfs_inode);
 45}
 46
 47#define HPPFS_SUPER_MAGIC 0xb00000ee
 48
 49static const struct super_operations hppfs_sbops;
 50
 51static int is_pid(struct dentry *dentry)
 52{
 53	struct super_block *sb;
 54	int i;
 55
 56	sb = dentry->d_sb;
 57	if (dentry->d_parent != sb->s_root)
 58		return 0;
 59
 60	for (i = 0; i < dentry->d_name.len; i++) {
 61		if (!isdigit(dentry->d_name.name[i]))
 62			return 0;
 63	}
 64	return 1;
 65}
 66
 67static char *dentry_name(struct dentry *dentry, int extra)
 68{
 69	struct dentry *parent;
 70	char *root, *name;
 71	const char *seg_name;
 72	int len, seg_len;
 73
 74	len = 0;
 75	parent = dentry;
 76	while (parent->d_parent != parent) {
 77		if (is_pid(parent))
 78			len += strlen("pid") + 1;
 79		else len += parent->d_name.len + 1;
 80		parent = parent->d_parent;
 81	}
 82
 83	root = "proc";
 84	len += strlen(root);
 85	name = kmalloc(len + extra + 1, GFP_KERNEL);
 86	if (name == NULL)
 87		return NULL;
 88
 89	name[len] = '\0';
 90	parent = dentry;
 91	while (parent->d_parent != parent) {
 92		if (is_pid(parent)) {
 93			seg_name = "pid";
 94			seg_len = strlen("pid");
 95		}
 96		else {
 97			seg_name = parent->d_name.name;
 98			seg_len = parent->d_name.len;
 99		}
100
101		len -= seg_len + 1;
102		name[len] = '/';
103		strncpy(&name[len + 1], seg_name, seg_len);
104		parent = parent->d_parent;
105	}
106	strncpy(name, root, strlen(root));
107	return name;
108}
109
110static int file_removed(struct dentry *dentry, const char *file)
111{
112	char *host_file;
113	int extra, fd;
114
115	extra = 0;
116	if (file != NULL)
117		extra += strlen(file) + 1;
118
119	host_file = dentry_name(dentry, extra + strlen("/remove"));
120	if (host_file == NULL) {
121		printk(KERN_ERR "file_removed : allocation failed\n");
122		return -ENOMEM;
123	}
124
125	if (file != NULL) {
126		strcat(host_file, "/");
127		strcat(host_file, file);
128	}
129	strcat(host_file, "/remove");
130
131	fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
132	kfree(host_file);
133	if (fd > 0) {
134		os_close_file(fd);
135		return 1;
136	}
137	return 0;
138}
139
140static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
141				   struct nameidata *nd)
142{
143	struct dentry *proc_dentry, *parent;
144	struct qstr *name = &dentry->d_name;
145	struct inode *inode;
146	int err, deleted;
147
148	deleted = file_removed(dentry, NULL);
149	if (deleted < 0)
150		return ERR_PTR(deleted);
151	else if (deleted)
152		return ERR_PTR(-ENOENT);
153
154	parent = HPPFS_I(ino)->proc_dentry;
155	mutex_lock(&parent->d_inode->i_mutex);
156	proc_dentry = lookup_one_len(name->name, parent, name->len);
157	mutex_unlock(&parent->d_inode->i_mutex);
158
159	if (IS_ERR(proc_dentry))
160		return proc_dentry;
161
162	err = -ENOMEM;
163	inode = get_inode(ino->i_sb, proc_dentry);
164	if (!inode)
165		goto out;
166
167 	d_add(dentry, inode);
168	return NULL;
169
170 out:
171	return ERR_PTR(err);
172}
173
174static const struct inode_operations hppfs_file_iops = {
175};
176
177static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count,
178			 loff_t *ppos, int is_user)
179{
180	ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
181	ssize_t n;
182
183	read = file->f_path.dentry->d_inode->i_fop->read;
184
185	if (!is_user)
186		set_fs(KERNEL_DS);
187
188	n = (*read)(file, buf, count, &file->f_pos);
189
190	if (!is_user)
191		set_fs(USER_DS);
192
193	if (ppos)
194		*ppos = file->f_pos;
195	return n;
196}
197
198static ssize_t hppfs_read_file(int fd, char __user *buf, ssize_t count)
199{
200	ssize_t n;
201	int cur, err;
202	char *new_buf;
203
204	n = -ENOMEM;
205	new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
206	if (new_buf == NULL) {
207		printk(KERN_ERR "hppfs_read_file : kmalloc failed\n");
208		goto out;
209	}
210	n = 0;
211	while (count > 0) {
212		cur = min_t(ssize_t, count, PAGE_SIZE);
213		err = os_read_file(fd, new_buf, cur);
214		if (err < 0) {
215			printk(KERN_ERR "hppfs_read : read failed, "
216			       "errno = %d\n", err);
217			n = err;
218			goto out_free;
219		} else if (err == 0)
220			break;
221
222		if (copy_to_user(buf, new_buf, err)) {
223			n = -EFAULT;
224			goto out_free;
225		}
226		n += err;
227		count -= err;
228	}
229 out_free:
230	kfree(new_buf);
231 out:
232	return n;
233}
234
235static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count,
236			  loff_t *ppos)
237{
238	struct hppfs_private *hppfs = file->private_data;
239	struct hppfs_data *data;
240	loff_t off;
241	int err;
242
243	if (hppfs->contents != NULL) {
244		int rem;
245
246		if (*ppos >= hppfs->len)
247			return 0;
248
249		data = hppfs->contents;
250		off = *ppos;
251		while (off >= sizeof(data->contents)) {
252			data = list_entry(data->list.next, struct hppfs_data,
253					  list);
254			off -= sizeof(data->contents);
255		}
256
257		if (off + count > hppfs->len)
258			count = hppfs->len - off;
259		rem = copy_to_user(buf, &data->contents[off], count);
260		*ppos += count - rem;
261		if (rem > 0)
262			return -EFAULT;
263	} else if (hppfs->host_fd != -1) {
264		err = os_seek_file(hppfs->host_fd, *ppos);
265		if (err) {
266			printk(KERN_ERR "hppfs_read : seek failed, "
267			       "errno = %d\n", err);
268			return err;
269		}
270		err = hppfs_read_file(hppfs->host_fd, buf, count);
271		if (err < 0) {
272			printk(KERN_ERR "hppfs_read: read failed: %d\n", err);
273			return err;
274		}
275		count = err;
276		if (count > 0)
277			*ppos += count;
278	}
279	else count = read_proc(hppfs->proc_file, buf, count, ppos, 1);
280
281	return count;
282}
283
284static ssize_t hppfs_write(struct file *file, const char __user *buf,
285			   size_t len, loff_t *ppos)
286{
287	struct hppfs_private *data = file->private_data;
288	struct file *proc_file = data->proc_file;
289	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
290
291	write = proc_file->f_path.dentry->d_inode->i_fop->write;
292	return (*write)(proc_file, buf, len, ppos);
293}
294
295static int open_host_sock(char *host_file, int *filter_out)
296{
297	char *end;
298	int fd;
299
300	end = &host_file[strlen(host_file)];
301	strcpy(end, "/rw");
302	*filter_out = 1;
303	fd = os_connect_socket(host_file);
304	if (fd > 0)
305		return fd;
306
307	strcpy(end, "/r");
308	*filter_out = 0;
309	fd = os_connect_socket(host_file);
310	return fd;
311}
312
313static void free_contents(struct hppfs_data *head)
314{
315	struct hppfs_data *data;
316	struct list_head *ele, *next;
317
318	if (head == NULL)
319		return;
320
321	list_for_each_safe(ele, next, &head->list) {
322		data = list_entry(ele, struct hppfs_data, list);
323		kfree(data);
324	}
325	kfree(head);
326}
327
328static struct hppfs_data *hppfs_get_data(int fd, int filter,
329					 struct file *proc_file,
330					 struct file *hppfs_file,
331					 loff_t *size_out)
332{
333	struct hppfs_data *data, *new, *head;
334	int n, err;
335
336	err = -ENOMEM;
337	data = kmalloc(sizeof(*data), GFP_KERNEL);
338	if (data == NULL) {
339		printk(KERN_ERR "hppfs_get_data : head allocation failed\n");
340		goto failed;
341	}
342
343	INIT_LIST_HEAD(&data->list);
344
345	head = data;
346	*size_out = 0;
347
348	if (filter) {
349		while ((n = read_proc(proc_file, data->contents,
350				      sizeof(data->contents), NULL, 0)) > 0)
351			os_write_file(fd, data->contents, n);
352		err = os_shutdown_socket(fd, 0, 1);
353		if (err) {
354			printk(KERN_ERR "hppfs_get_data : failed to shut down "
355			       "socket\n");
356			goto failed_free;
357		}
358	}
359	while (1) {
360		n = os_read_file(fd, data->contents, sizeof(data->contents));
361		if (n < 0) {
362			err = n;
363			printk(KERN_ERR "hppfs_get_data : read failed, "
364			       "errno = %d\n", err);
365			goto failed_free;
366		} else if (n == 0)
367			break;
368
369		*size_out += n;
370
371		if (n < sizeof(data->contents))
372			break;
373
374		new = kmalloc(sizeof(*data), GFP_KERNEL);
375		if (new == 0) {
376			printk(KERN_ERR "hppfs_get_data : data allocation "
377			       "failed\n");
378			err = -ENOMEM;
379			goto failed_free;
380		}
381
382		INIT_LIST_HEAD(&new->list);
383		list_add(&new->list, &data->list);
384		data = new;
385	}
386	return head;
387
388 failed_free:
389	free_contents(head);
390 failed:
391	return ERR_PTR(err);
392}
393
394static struct hppfs_private *hppfs_data(void)
395{
396	struct hppfs_private *data;
397
398	data = kmalloc(sizeof(*data), GFP_KERNEL);
399	if (data == NULL)
400		return data;
401
402	*data = ((struct hppfs_private ) { .host_fd  		= -1,
403					   .len  		= -1,
404					   .contents 		= NULL } );
405	return data;
406}
407
408static int file_mode(int fmode)
409{
410	if (fmode == (FMODE_READ | FMODE_WRITE))
411		return O_RDWR;
412	if (fmode == FMODE_READ)
413		return O_RDONLY;
414	if (fmode == FMODE_WRITE)
415		return O_WRONLY;
416	return 0;
417}
418
419static int hppfs_open(struct inode *inode, struct file *file)
420{
421	const struct cred *cred = file->f_cred;
422	struct hppfs_private *data;
423	struct vfsmount *proc_mnt;
424	struct dentry *proc_dentry;
425	char *host_file;
426	int err, fd, type, filter;
427
428	err = -ENOMEM;
429	data = hppfs_data();
430	if (data == NULL)
431		goto out;
432
433	host_file = dentry_name(file->f_path.dentry, strlen("/rw"));
434	if (host_file == NULL)
435		goto out_free2;
436
437	proc_dentry = HPPFS_I(inode)->proc_dentry;
438	proc_mnt = inode->i_sb->s_fs_info;
439
440	/* XXX This isn't closed anywhere */
441	data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
442				      file_mode(file->f_mode), cred);
443	err = PTR_ERR(data->proc_file);
444	if (IS_ERR(data->proc_file))
445		goto out_free1;
446
447	type = os_file_type(host_file);
448	if (type == OS_TYPE_FILE) {
449		fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
450		if (fd >= 0)
451			data->host_fd = fd;
452		else
453			printk(KERN_ERR "hppfs_open : failed to open '%s', "
454			       "errno = %d\n", host_file, -fd);
455
456		data->contents = NULL;
457	} else if (type == OS_TYPE_DIR) {
458		fd = open_host_sock(host_file, &filter);
459		if (fd > 0) {
460			data->contents = hppfs_get_data(fd, filter,
461							data->proc_file,
462							file, &data->len);
463			if (!IS_ERR(data->contents))
464				data->host_fd = fd;
465		} else
466			printk(KERN_ERR "hppfs_open : failed to open a socket "
467			       "in '%s', errno = %d\n", host_file, -fd);
468	}
469	kfree(host_file);
470
471	file->private_data = data;
472	return 0;
473
474 out_free1:
475	kfree(host_file);
476 out_free2:
477	free_contents(data->contents);
478	kfree(data);
479 out:
480	return err;
481}
482
483static int hppfs_dir_open(struct inode *inode, struct file *file)
484{
485	const struct cred *cred = file->f_cred;
486	struct hppfs_private *data;
487	struct vfsmount *proc_mnt;
488	struct dentry *proc_dentry;
489	int err;
490
491	err = -ENOMEM;
492	data = hppfs_data();
493	if (data == NULL)
494		goto out;
495
496	proc_dentry = HPPFS_I(inode)->proc_dentry;
497	proc_mnt = inode->i_sb->s_fs_info;
498	data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
499				      file_mode(file->f_mode), cred);
500	err = PTR_ERR(data->proc_file);
501	if (IS_ERR(data->proc_file))
502		goto out_free;
503
504	file->private_data = data;
505	return 0;
506
507 out_free:
508	kfree(data);
509 out:
510	return err;
511}
512
513static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
514{
515	struct hppfs_private *data = file->private_data;
516	struct file *proc_file = data->proc_file;
517	loff_t (*llseek)(struct file *, loff_t, int);
518	loff_t ret;
519
520	llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek;
521	if (llseek != NULL) {
522		ret = (*llseek)(proc_file, off, where);
523		if (ret < 0)
524			return ret;
525	}
526
527	return default_llseek(file, off, where);
528}
529
530static const struct file_operations hppfs_file_fops = {
531	.owner		= NULL,
532	.llseek		= hppfs_llseek,
533	.read		= hppfs_read,
534	.write		= hppfs_write,
535	.open		= hppfs_open,
536};
537
538struct hppfs_dirent {
539	void *vfs_dirent;
540	filldir_t filldir;
541	struct dentry *dentry;
542};
543
544static int hppfs_filldir(void *d, const char *name, int size,
545			 loff_t offset, u64 inode, unsigned int type)
546{
547	struct hppfs_dirent *dirent = d;
548
549	if (file_removed(dirent->dentry, name))
550		return 0;
551
552	return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset,
553				  inode, type);
554}
555
556static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
557{
558	struct hppfs_private *data = file->private_data;
559	struct file *proc_file = data->proc_file;
560	int (*readdir)(struct file *, void *, filldir_t);
561	struct hppfs_dirent dirent = ((struct hppfs_dirent)
562		                      { .vfs_dirent  	= ent,
563					.filldir 	= filldir,
564					.dentry  	= file->f_path.dentry
565				      });
566	int err;
567
568	readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir;
569
570	proc_file->f_pos = file->f_pos;
571	err = (*readdir)(proc_file, &dirent, hppfs_filldir);
572	file->f_pos = proc_file->f_pos;
573
574	return err;
575}
576
577static int hppfs_fsync(struct file *file, loff_t start, loff_t end,
578		       int datasync)
579{
580	return filemap_write_and_wait_range(file->f_mapping, start, end);
581}
582
583static const struct file_operations hppfs_dir_fops = {
584	.owner		= NULL,
585	.readdir	= hppfs_readdir,
586	.open		= hppfs_dir_open,
587	.fsync		= hppfs_fsync,
588	.llseek		= default_llseek,
589};
590
591static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf)
592{
593	sf->f_blocks = 0;
594	sf->f_bfree = 0;
595	sf->f_bavail = 0;
596	sf->f_files = 0;
597	sf->f_ffree = 0;
598	sf->f_type = HPPFS_SUPER_MAGIC;
599	return 0;
600}
601
602static struct inode *hppfs_alloc_inode(struct super_block *sb)
603{
604	struct hppfs_inode_info *hi;
605
606	hi = kmalloc(sizeof(*hi), GFP_KERNEL);
607	if (!hi)
608		return NULL;
609
610	hi->proc_dentry = NULL;
611	inode_init_once(&hi->vfs_inode);
612	return &hi->vfs_inode;
613}
614
615void hppfs_evict_inode(struct inode *ino)
616{
617	clear_inode(ino);
618	dput(HPPFS_I(ino)->proc_dentry);
619	mntput(ino->i_sb->s_fs_info);
620}
621
622static void hppfs_i_callback(struct rcu_head *head)
623{
624	struct inode *inode = container_of(head, struct inode, i_rcu);
625	kfree(HPPFS_I(inode));
626}
627
628static void hppfs_destroy_inode(struct inode *inode)
629{
630	call_rcu(&inode->i_rcu, hppfs_i_callback);
631}
632
633static const struct super_operations hppfs_sbops = {
634	.alloc_inode	= hppfs_alloc_inode,
635	.destroy_inode	= hppfs_destroy_inode,
636	.evict_inode	= hppfs_evict_inode,
637	.statfs		= hppfs_statfs,
638};
639
640static int hppfs_readlink(struct dentry *dentry, char __user *buffer,
641			  int buflen)
642{
643	struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
644	return proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer,
645						    buflen);
646}
647
648static void *hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
649{
650	struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
651
652	return proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd);
653}
654
655static void hppfs_put_link(struct dentry *dentry, struct nameidata *nd,
656			   void *cookie)
657{
658	struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
659
660	if (proc_dentry->d_inode->i_op->put_link)
661		proc_dentry->d_inode->i_op->put_link(proc_dentry, nd, cookie);
662}
663
664static const struct inode_operations hppfs_dir_iops = {
665	.lookup		= hppfs_lookup,
666};
667
668static const struct inode_operations hppfs_link_iops = {
669	.readlink	= hppfs_readlink,
670	.follow_link	= hppfs_follow_link,
671	.put_link	= hppfs_put_link,
672};
673
674static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
675{
676	struct inode *proc_ino = dentry->d_inode;
677	struct inode *inode = new_inode(sb);
678
679	if (!inode) {
680		dput(dentry);
681		return ERR_PTR(-ENOMEM);
682	}
683
684	if (S_ISDIR(dentry->d_inode->i_mode)) {
685		inode->i_op = &hppfs_dir_iops;
686		inode->i_fop = &hppfs_dir_fops;
687	} else if (S_ISLNK(dentry->d_inode->i_mode)) {
688		inode->i_op = &hppfs_link_iops;
689		inode->i_fop = &hppfs_file_fops;
690	} else {
691		inode->i_op = &hppfs_file_iops;
692		inode->i_fop = &hppfs_file_fops;
693	}
694
695	HPPFS_I(inode)->proc_dentry = dentry;
696
697	inode->i_uid = proc_ino->i_uid;
698	inode->i_gid = proc_ino->i_gid;
699	inode->i_atime = proc_ino->i_atime;
700	inode->i_mtime = proc_ino->i_mtime;
701	inode->i_ctime = proc_ino->i_ctime;
702	inode->i_ino = proc_ino->i_ino;
703	inode->i_mode = proc_ino->i_mode;
704	set_nlink(inode, proc_ino->i_nlink);
705	inode->i_size = proc_ino->i_size;
706	inode->i_blocks = proc_ino->i_blocks;
707
708	return inode;
709}
710
711static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
712{
713	struct inode *root_inode;
714	struct vfsmount *proc_mnt;
715	int err = -ENOENT;
716
717	proc_mnt = mntget(current->nsproxy->pid_ns->proc_mnt);
718	if (IS_ERR(proc_mnt))
719		goto out;
720
721	sb->s_blocksize = 1024;
722	sb->s_blocksize_bits = 10;
723	sb->s_magic = HPPFS_SUPER_MAGIC;
724	sb->s_op = &hppfs_sbops;
725	sb->s_fs_info = proc_mnt;
726
727	err = -ENOMEM;
728	root_inode = get_inode(sb, dget(proc_mnt->mnt_root));
729	sb->s_root = d_make_root(root_inode);
730	if (!sb->s_root)
731		goto out_mntput;
732
733	return 0;
734
735 out_mntput:
736	mntput(proc_mnt);
737 out:
738	return(err);
739}
740
741static struct dentry *hppfs_read_super(struct file_system_type *type,
742			    int flags, const char *dev_name,
743			    void *data)
744{
745	return mount_nodev(type, flags, data, hppfs_fill_super);
746}
747
748static struct file_system_type hppfs_type = {
749	.owner 		= THIS_MODULE,
750	.name 		= "hppfs",
751	.mount 		= hppfs_read_super,
752	.kill_sb	= kill_anon_super,
753	.fs_flags 	= 0,
754};
755
756static int __init init_hppfs(void)
757{
758	return register_filesystem(&hppfs_type);
759}
760
761static void __exit exit_hppfs(void)
762{
763	unregister_filesystem(&hppfs_type);
764}
765
766module_init(init_hppfs)
767module_exit(exit_hppfs)
768MODULE_LICENSE("GPL");