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