📄 inode.c
字号:
down(&file->f_dentry->d_inode->i_sem); switch(orig) { case 0: if (offset > 0) { file->f_pos = offset; retval = file->f_pos; } break; case 1: if ((offset + file->f_pos) > 0) { file->f_pos += offset; retval = file->f_pos; } break; default: break; } up(&file->f_dentry->d_inode->i_sem); return retval;}static int default_open (struct inode *inode, struct file *file){ if (inode->u.generic_ip) file->private_data = inode->u.generic_ip; return 0;}static struct file_operations default_file_operations = { .read = default_read_file, .write = default_write_file, .open = default_open, .llseek = default_file_lseek,};static struct super_operations usbfs_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, .remount_fs = remount,};static int usbfs_fill_super(struct super_block *sb, void *data, int silent){ struct inode *inode; struct dentry *root; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = USBDEVICE_SUPER_MAGIC; sb->s_op = &usbfs_ops; sb->s_time_gran = 1; inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0); if (!inode) { dbg("%s: could not get inode!",__FUNCTION__); return -ENOMEM; } root = d_alloc_root(inode); if (!root) { dbg("%s: could not get root dentry!",__FUNCTION__); iput(inode); return -ENOMEM; } sb->s_root = root; return 0;}/* * fs_create_by_name - create a file, given a name * @name: name of file * @mode: type of file * @parent: dentry of directory to create it in * @dentry: resulting dentry of file * * This function handles both regular files and directories. */static int fs_create_by_name (const char *name, mode_t mode, struct dentry *parent, struct dentry **dentry){ int error = 0; /* If the parent is not specified, we create it in the root. * We need the root dentry to do this, which is in the super * block. A pointer to that is in the struct vfsmount that we * have around. */ if (!parent ) { if (usbfs_mount && usbfs_mount->mnt_sb) { parent = usbfs_mount->mnt_sb->s_root; } } if (!parent) { dbg("Ah! can not find a parent!"); return -EFAULT; } *dentry = NULL; down(&parent->d_inode->i_sem); *dentry = lookup_one_len(name, parent, strlen(name)); if (!IS_ERR(dentry)) { if ((mode & S_IFMT) == S_IFDIR) error = usbfs_mkdir (parent->d_inode, *dentry, mode); else error = usbfs_create (parent->d_inode, *dentry, mode); } else error = PTR_ERR(dentry); up(&parent->d_inode->i_sem); return error;}static struct dentry *fs_create_file (const char *name, mode_t mode, struct dentry *parent, void *data, struct file_operations *fops, uid_t uid, gid_t gid){ struct dentry *dentry; int error; dbg("creating file '%s'",name); error = fs_create_by_name (name, mode, parent, &dentry); if (error) { dentry = NULL; } else { if (dentry->d_inode) { if (data) dentry->d_inode->u.generic_ip = data; if (fops) dentry->d_inode->i_fop = fops; dentry->d_inode->i_uid = uid; dentry->d_inode->i_gid = gid; } } return dentry;}static void fs_remove_file (struct dentry *dentry){ struct dentry *parent = dentry->d_parent; if (!parent || !parent->d_inode) return; down(&parent->d_inode->i_sem); if (usbfs_positive(dentry)) { if (dentry->d_inode) { if (S_ISDIR(dentry->d_inode->i_mode)) usbfs_rmdir(parent->d_inode, dentry); else usbfs_unlink(parent->d_inode, dentry); dput(dentry); } } up(&parent->d_inode->i_sem);}/* --------------------------------------------------------------------- */static struct super_block *usb_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data){ return get_sb_single(fs_type, flags, data, usbfs_fill_super);}static struct file_system_type usb_fs_type = { .owner = THIS_MODULE, .name = "usbfs", .get_sb = usb_get_sb, .kill_sb = kill_litter_super,};/* --------------------------------------------------------------------- */static int create_special_files (void){ struct dentry *parent; int retval; /* the simple_pin_fs calls will call remount with no options * without this flag that would overwrite the real mount options (if any) */ ignore_mount = 1; /* create the devices special file */ retval = simple_pin_fs("usbfs", &usbfs_mount, &usbfs_mount_count); if (retval) { err ("Unable to get usbfs mount"); goto exit; } ignore_mount = 0; parent = usbfs_mount->mnt_sb->s_root; devices_usbfs_dentry = fs_create_file ("devices", listmode | S_IFREG, parent, NULL, &usbfs_devices_fops, listuid, listgid); if (devices_usbfs_dentry == NULL) { err ("Unable to create devices usbfs file"); retval = -ENODEV; goto error_clean_mounts; } goto exit; error_clean_mounts: simple_release_fs(&usbfs_mount, &usbfs_mount_count);exit: return retval;}static void remove_special_files (void){ if (devices_usbfs_dentry) fs_remove_file (devices_usbfs_dentry); devices_usbfs_dentry = NULL; simple_release_fs(&usbfs_mount, &usbfs_mount_count);}void usbfs_update_special (void){ struct inode *inode; if (devices_usbfs_dentry) { inode = devices_usbfs_dentry->d_inode; if (inode) inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; }}static void usbfs_add_bus(struct usb_bus *bus){ struct dentry *parent; char name[8]; int retval; /* create the special files if this is the first bus added */ if (num_buses == 0) { retval = create_special_files(); if (retval) return; } ++num_buses; sprintf (name, "%03d", bus->busnum); parent = usbfs_mount->mnt_sb->s_root; bus->usbfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent, bus, NULL, busuid, busgid); if (bus->usbfs_dentry == NULL) { err ("error creating usbfs bus entry"); return; }}static void usbfs_remove_bus(struct usb_bus *bus){ if (bus->usbfs_dentry) { fs_remove_file (bus->usbfs_dentry); bus->usbfs_dentry = NULL; } --num_buses; if (num_buses <= 0) { remove_special_files(); num_buses = 0; }}static void usbfs_add_device(struct usb_device *dev){ char name[8]; int i; int i_size; sprintf (name, "%03d", dev->devnum); dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG, dev->bus->usbfs_dentry, dev, &usbfs_device_file_operations, devuid, devgid); if (dev->usbfs_dentry == NULL) { err ("error creating usbfs device entry"); return; } /* Set the size of the device's file to be * equal to the size of the device descriptors. */ i_size = sizeof (struct usb_device_descriptor); for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) { struct usb_config_descriptor *config = (struct usb_config_descriptor *)dev->rawdescriptors[i]; i_size += le16_to_cpu(config->wTotalLength); } if (dev->usbfs_dentry->d_inode) dev->usbfs_dentry->d_inode->i_size = i_size;}static void usbfs_remove_device(struct usb_device *dev){ struct dev_state *ds; struct siginfo sinfo; if (dev->usbfs_dentry) { fs_remove_file (dev->usbfs_dentry); dev->usbfs_dentry = NULL; } while (!list_empty(&dev->filelist)) { ds = list_entry(dev->filelist.next, struct dev_state, list); wake_up_all(&ds->wait); list_del_init(&ds->list); if (ds->discsignr) { sinfo.si_signo = SIGPIPE; sinfo.si_errno = EPIPE; sinfo.si_code = SI_ASYNCIO; sinfo.si_addr = ds->disccontext; kill_proc_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid); } }}static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev){ switch (action) { case USB_DEVICE_ADD: usbfs_add_device(dev); break; case USB_DEVICE_REMOVE: usbfs_remove_device(dev); break; case USB_BUS_ADD: usbfs_add_bus(dev); break; case USB_BUS_REMOVE: usbfs_remove_bus(dev); } usbfs_update_special(); usbfs_conn_disc_event(); return NOTIFY_OK;}static struct notifier_block usbfs_nb = { .notifier_call = usbfs_notify,};/* --------------------------------------------------------------------- */static struct proc_dir_entry *usbdir = NULL;int __init usbfs_init(void){ int retval; retval = register_filesystem(&usb_fs_type); if (retval) return retval; usb_register_notify(&usbfs_nb); /* create mount point for usbfs */ usbdir = proc_mkdir("usb", proc_bus); return 0;}void usbfs_cleanup(void){ usb_unregister_notify(&usbfs_nb); unregister_filesystem(&usb_fs_type); if (usbdir) remove_proc_entry("usb", proc_bus);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -