📄 inode.c
字号:
filp->f_pos++; i++; /* fall through */ case 1: if (filldir(dirent, "..", 2, i, IROOT, DT_DIR) < 0) return 0; filp->f_pos++; i++; /* fall through */ default: while (i >= 2 && i < 2+NRSPECIAL) { spec = &special[filp->f_pos-2]; if (filldir(dirent, spec->name, strlen(spec->name), i, ISPECIAL | (filp->f_pos-2+IROOT), DT_UNKNOWN) < 0) return 0; filp->f_pos++; i++; } if (i < 2+NRSPECIAL) return 0; i -= 2+NRSPECIAL; down (&usb_bus_list_lock); for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) { if (i > 0) { i--; continue; } bus = list_entry(list, struct usb_bus, bus_list); sprintf(numbuf, "%03d", bus->busnum); if (filldir(dirent, numbuf, 3, filp->f_pos, IBUS | ((bus->busnum & 0xff) << 8), DT_UNKNOWN) < 0) break; filp->f_pos++; } up (&usb_bus_list_lock); return 0; }}static int bus_readdir(struct usb_device *dev, unsigned long ino, int pos, struct file *filp, void *dirent, filldir_t filldir){ char numbuf[8]; unsigned int i; if (!dev) return pos; sprintf(numbuf, "%03d", dev->devnum); if (pos > 0) pos--; else { if (filldir(dirent, numbuf, 3, filp->f_pos, ino | (dev->devnum & 0xff), DT_UNKNOWN) < 0) return -1; filp->f_pos++; } for (i = 0; i < dev->maxchild; i++) { if (!dev->children[i]) continue; pos = bus_readdir(dev->children[i], ino, pos, filp, dirent, filldir); if (pos < 0) return -1; } return pos;}static int usbdevfs_bus_readdir(struct file *filp, void *dirent, filldir_t filldir){ struct inode *inode = filp->f_dentry->d_inode; unsigned long ino = inode->i_ino; struct usb_bus *bus; /* sanity check */ if (ITYPE(ino) != IBUS) return -EINVAL; switch ((unsigned int)filp->f_pos) { case 0: if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0) return 0; filp->f_pos++; /* fall through */ case 1: if (filldir(dirent, "..", 2, filp->f_pos, IROOT, DT_DIR) < 0) return 0; filp->f_pos++; /* fall through */ default: lock_kernel(); bus = usbdevfs_findbus(IBUSNR(ino)); bus_readdir(bus->root_hub, IDEVICE | ((bus->busnum & 0xff) << 8), filp->f_pos-2, filp, dirent, filldir); unlock_kernel(); return 0; }}static struct file_operations usbdevfs_root_file_operations = { readdir: usbdevfs_root_readdir,};static struct inode_operations usbdevfs_root_inode_operations = { lookup: usbdevfs_root_lookup,};static struct file_operations usbdevfs_bus_file_operations = { readdir: usbdevfs_bus_readdir,};static struct inode_operations usbdevfs_bus_inode_operations = { lookup: usbdevfs_bus_lookup,};static void usbdevfs_read_inode(struct inode *inode){ struct special *spec; inode->i_ctime = inode->i_mtime = inode->i_atime = CURRENT_TIME; inode->i_mode = S_IFREG; inode->i_gid = inode->i_uid = 0; INIT_LIST_HEAD(&inode->u.usbdev_i.dlist); INIT_LIST_HEAD(&inode->u.usbdev_i.slist); inode->u.usbdev_i.p.dev = NULL; inode->u.usbdev_i.p.bus = NULL; switch (ITYPE(inode->i_ino)) { case ISPECIAL: if (inode->i_ino == IROOT) { inode->i_op = &usbdevfs_root_inode_operations; inode->i_fop = &usbdevfs_root_file_operations; inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; return; } if (inode->i_ino <= IROOT || inode->i_ino > IROOT+NRSPECIAL) return; spec = &special[inode->i_ino-(IROOT+1)]; inode->i_fop = spec->fops; return; case IDEVICE: return; case IBUS: return; default: return; }}static void usbdevfs_put_super(struct super_block *sb){ list_del(&sb->u.usbdevfs_sb.slist); INIT_LIST_HEAD(&sb->u.usbdevfs_sb.slist); while (!list_empty(&sb->u.usbdevfs_sb.ilist)) free_inode(list_entry(sb->u.usbdevfs_sb.ilist.next, struct inode, u.usbdev_i.slist));}static int usbdevfs_statfs(struct super_block *sb, struct statfs *buf){ buf->f_type = USBDEVICE_SUPER_MAGIC; buf->f_bsize = PAGE_SIZE/sizeof(long); /* ??? */ buf->f_bfree = 0; buf->f_bavail = 0; buf->f_ffree = 0; buf->f_namelen = NAME_MAX; return 0;}static int usbdevfs_remount(struct super_block *s, int *flags, char *data){ struct list_head *ilist = s->u.usbdevfs_sb.ilist.next; struct inode *inode; int ret; if ((ret = parse_options(s, data))) { printk(KERN_WARNING "usbdevfs: remount parameter error\n"); return ret; } for (; ilist != &s->u.usbdevfs_sb.ilist; ilist = ilist->next) { inode = list_entry(ilist, struct inode, u.usbdev_i.slist); switch (ITYPE(inode->i_ino)) { case ISPECIAL : inode->i_uid = s->u.usbdevfs_sb.listuid; inode->i_gid = s->u.usbdevfs_sb.listgid; inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG; break; case IBUS : inode->i_uid = s->u.usbdevfs_sb.busuid; inode->i_gid = s->u.usbdevfs_sb.busgid; inode->i_mode = s->u.usbdevfs_sb.busmode | S_IFDIR; break; case IDEVICE : inode->i_uid = s->u.usbdevfs_sb.devuid; inode->i_gid = s->u.usbdevfs_sb.devgid; inode->i_mode = s->u.usbdevfs_sb.devmode | S_IFREG; break; } } return 0;}static struct super_operations usbdevfs_sops = { read_inode: usbdevfs_read_inode, put_super: usbdevfs_put_super, statfs: usbdevfs_statfs, remount_fs: usbdevfs_remount,};struct super_block *usbdevfs_read_super(struct super_block *s, void *data, int silent){ struct inode *root_inode, *inode; struct list_head *blist; struct usb_bus *bus; unsigned int i; if (parse_options(s, data)) { printk(KERN_WARNING "usbdevfs: mount parameter error\n"); return NULL; } /* fill superblock */ s->s_blocksize = 1024; s->s_blocksize_bits = 10; s->s_magic = USBDEVICE_SUPER_MAGIC; s->s_op = &usbdevfs_sops; INIT_LIST_HEAD(&s->u.usbdevfs_sb.slist); INIT_LIST_HEAD(&s->u.usbdevfs_sb.ilist); root_inode = iget(s, IROOT); if (!root_inode) goto out_no_root; s->s_root = d_alloc_root(root_inode); if (!s->s_root) goto out_no_root; lock_kernel(); list_add_tail(&s->u.usbdevfs_sb.slist, &superlist); for (i = 0; i < NRSPECIAL; i++) { if (!(inode = iget(s, IROOT+1+i))) continue; inode->i_uid = s->u.usbdevfs_sb.listuid; inode->i_gid = s->u.usbdevfs_sb.listgid; inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG; special[i].inode = inode; list_add_tail(&inode->u.usbdev_i.slist, &s->u.usbdevfs_sb.ilist); list_add_tail(&inode->u.usbdev_i.dlist, &special[i].inodes); } down (&usb_bus_list_lock); for (blist = usb_bus_list.next; blist != &usb_bus_list; blist = blist->next) { bus = list_entry(blist, struct usb_bus, bus_list); new_bus_inode(bus, s); recurse_new_dev_inode(bus->root_hub, s); } up (&usb_bus_list_lock); unlock_kernel(); return s; out_no_root: printk("usbdevfs_read_super: get root inode failed\n"); iput(root_inode); return NULL;}/* * The usbdevfs name is now deprecated (as of 2.4.19). * It will be removed when the 2.7.x development cycle is started. * You have been warned :) */static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, FS_SINGLE);static DECLARE_FSTYPE(usbfs_type, "usbfs", usbdevfs_read_super, FS_SINGLE);/* --------------------------------------------------------------------- */static void update_special_inodes (void){ int i; for (i = 0; i < NRSPECIAL; i++) { struct inode *inode = special[i].inode; if (inode) inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; }}void usbdevfs_add_bus(struct usb_bus *bus){ struct list_head *slist; lock_kernel(); for (slist = superlist.next; slist != &superlist; slist = slist->next) new_bus_inode(bus, list_entry(slist, struct super_block, u.usbdevfs_sb.slist)); update_special_inodes(); unlock_kernel(); usbdevfs_conn_disc_event();}void usbdevfs_remove_bus(struct usb_bus *bus){ lock_kernel(); while (!list_empty(&bus->inodes)) free_inode(list_entry(bus->inodes.next, struct inode, u.usbdev_i.dlist)); update_special_inodes(); unlock_kernel(); usbdevfs_conn_disc_event();}void usbdevfs_add_device(struct usb_device *dev){ struct list_head *slist; lock_kernel(); for (slist = superlist.next; slist != &superlist; slist = slist->next) new_dev_inode(dev, list_entry(slist, struct super_block, u.usbdevfs_sb.slist)); update_special_inodes(); unlock_kernel(); usbdevfs_conn_disc_event();}void usbdevfs_remove_device(struct usb_device *dev){ struct dev_state *ds; struct siginfo sinfo; lock_kernel(); while (!list_empty(&dev->inodes)) free_inode(list_entry(dev->inodes.next, struct inode, u.usbdev_i.dlist)); while (!list_empty(&dev->filelist)) { ds = list_entry(dev->filelist.next, struct dev_state, list); list_del(&ds->list); INIT_LIST_HEAD(&ds->list); down_write(&ds->devsem); ds->dev = NULL; up_write(&ds->devsem); if (ds->discsignr) { sinfo.si_signo = SIGPIPE; sinfo.si_errno = EPIPE; sinfo.si_code = SI_ASYNCIO; sinfo.si_addr = ds->disccontext; send_sig_info(ds->discsignr, &sinfo, ds->disctask); } } update_special_inodes(); unlock_kernel(); usbdevfs_conn_disc_event();}/* --------------------------------------------------------------------- */#ifdef CONFIG_PROC_FS static struct proc_dir_entry *usbdir = NULL;#endif int __init usbdevfs_init(void){ int ret; for (ret = 0; ret < NRSPECIAL; ret++) { INIT_LIST_HEAD(&special[ret].inodes); } if ((ret = usb_register(&usbdevfs_driver))) return ret; if ((ret = register_filesystem(&usbdevice_fs_type))) { usb_deregister(&usbdevfs_driver); return ret; } if ((ret = register_filesystem(&usbfs_type))) { usb_deregister(&usbdevfs_driver); unregister_filesystem(&usbdevice_fs_type); return ret; }#ifdef CONFIG_PROC_FS /* create mount point for usbdevfs */ usbdir = proc_mkdir("usb", proc_bus);#endif return ret;}void __exit usbdevfs_cleanup(void){ usb_deregister(&usbdevfs_driver); unregister_filesystem(&usbdevice_fs_type); unregister_filesystem(&usbfs_type);#ifdef CONFIG_PROC_FS if (usbdir) remove_proc_entry("usb", proc_bus);#endif}#if 0module_init(usbdevfs_init);module_exit(usbdevfs_cleanup);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -