Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.1 774 lines 17 kB view raw
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 end_writeback(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 INIT_LIST_HEAD(&inode->i_dentry); 626 kfree(HPPFS_I(inode)); 627} 628 629static void hppfs_destroy_inode(struct inode *inode) 630{ 631 call_rcu(&inode->i_rcu, hppfs_i_callback); 632} 633 634static const struct super_operations hppfs_sbops = { 635 .alloc_inode = hppfs_alloc_inode, 636 .destroy_inode = hppfs_destroy_inode, 637 .evict_inode = hppfs_evict_inode, 638 .statfs = hppfs_statfs, 639}; 640 641static int hppfs_readlink(struct dentry *dentry, char __user *buffer, 642 int buflen) 643{ 644 struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; 645 return proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer, 646 buflen); 647} 648 649static void *hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) 650{ 651 struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; 652 653 return proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd); 654} 655 656static void hppfs_put_link(struct dentry *dentry, struct nameidata *nd, 657 void *cookie) 658{ 659 struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; 660 661 if (proc_dentry->d_inode->i_op->put_link) 662 proc_dentry->d_inode->i_op->put_link(proc_dentry, nd, cookie); 663} 664 665static const struct inode_operations hppfs_dir_iops = { 666 .lookup = hppfs_lookup, 667}; 668 669static const struct inode_operations hppfs_link_iops = { 670 .readlink = hppfs_readlink, 671 .follow_link = hppfs_follow_link, 672 .put_link = hppfs_put_link, 673}; 674 675static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) 676{ 677 struct inode *proc_ino = dentry->d_inode; 678 struct inode *inode = new_inode(sb); 679 680 if (!inode) { 681 dput(dentry); 682 return ERR_PTR(-ENOMEM); 683 } 684 685 if (S_ISDIR(dentry->d_inode->i_mode)) { 686 inode->i_op = &hppfs_dir_iops; 687 inode->i_fop = &hppfs_dir_fops; 688 } else if (S_ISLNK(dentry->d_inode->i_mode)) { 689 inode->i_op = &hppfs_link_iops; 690 inode->i_fop = &hppfs_file_fops; 691 } else { 692 inode->i_op = &hppfs_file_iops; 693 inode->i_fop = &hppfs_file_fops; 694 } 695 696 HPPFS_I(inode)->proc_dentry = dentry; 697 698 inode->i_uid = proc_ino->i_uid; 699 inode->i_gid = proc_ino->i_gid; 700 inode->i_atime = proc_ino->i_atime; 701 inode->i_mtime = proc_ino->i_mtime; 702 inode->i_ctime = proc_ino->i_ctime; 703 inode->i_ino = proc_ino->i_ino; 704 inode->i_mode = proc_ino->i_mode; 705 inode->i_nlink = proc_ino->i_nlink; 706 inode->i_size = proc_ino->i_size; 707 inode->i_blocks = proc_ino->i_blocks; 708 709 return inode; 710} 711 712static int hppfs_fill_super(struct super_block *sb, void *d, int silent) 713{ 714 struct inode *root_inode; 715 struct vfsmount *proc_mnt; 716 int err = -ENOENT; 717 718 proc_mnt = mntget(current->nsproxy->pid_ns->proc_mnt); 719 if (IS_ERR(proc_mnt)) 720 goto out; 721 722 sb->s_blocksize = 1024; 723 sb->s_blocksize_bits = 10; 724 sb->s_magic = HPPFS_SUPER_MAGIC; 725 sb->s_op = &hppfs_sbops; 726 sb->s_fs_info = proc_mnt; 727 728 err = -ENOMEM; 729 root_inode = get_inode(sb, dget(proc_mnt->mnt_sb->s_root)); 730 if (!root_inode) 731 goto out_mntput; 732 733 sb->s_root = d_alloc_root(root_inode); 734 if (!sb->s_root) 735 goto out_iput; 736 737 return 0; 738 739 out_iput: 740 iput(root_inode); 741 out_mntput: 742 mntput(proc_mnt); 743 out: 744 return(err); 745} 746 747static struct dentry *hppfs_read_super(struct file_system_type *type, 748 int flags, const char *dev_name, 749 void *data) 750{ 751 return mount_nodev(type, flags, data, hppfs_fill_super); 752} 753 754static struct file_system_type hppfs_type = { 755 .owner = THIS_MODULE, 756 .name = "hppfs", 757 .mount = hppfs_read_super, 758 .kill_sb = kill_anon_super, 759 .fs_flags = 0, 760}; 761 762static int __init init_hppfs(void) 763{ 764 return register_filesystem(&hppfs_type); 765} 766 767static void __exit exit_hppfs(void) 768{ 769 unregister_filesystem(&hppfs_type); 770} 771 772module_init(init_hppfs) 773module_exit(exit_hppfs) 774MODULE_LICENSE("GPL");