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