📄 bc_dev22.c
字号:
} atomic_inc(&bc_buffers[i].count); } uptodate = 1;error_out: if (!end_that_request_first(req, uptodate, DEVICE_NAME)) end_that_request_last(req); goto repeat;}/*-- end of strategy routine --------------------------------*//*-- fops functions -----------------------------------------*/static int bc_open(struct inode *inode, struct file *file){ struct bc_device *bc; if (!inode) return -EINVAL; bc = get_bcdev(inode->i_rdev); if (NULL == bc) return save_fops.open(inode, file); MOD_INC_USE_COUNT; while (1) { down(&bc->bc_control); if (!bc->bc_flags.busy) break; up(&bc->bc_control); sleep_on(&wait_open); } bc->bc_refcnt++; up(&bc->bc_control); if (capable(CAP_SYS_ADMIN)) bc_add_pid(current->pid); return 0;}static int bc_release(struct inode *inode, struct file *file){ struct bc_device *bc; if (!inode) return 0; bc = get_bcdev(inode->i_rdev); if (NULL == bc) return save_fops.release(inode, file); down(&bc->bc_control); if (bc->bc_refcnt <= 0) printk(KERN_WARNING "bc_release: refcount (%d) <= 0\n", bc->bc_refcnt); else { bc->bc_refcnt--; MOD_DEC_USE_COUNT; } up(&bc->bc_control); return 0;}static ssize_t bc_read (struct file *file, char *buf, size_t count, loff_t *ppos){ struct bc_disk *bd; struct inode *inode; if (!file) return -EINVAL; inode = file->f_dentry->d_inode; bd = get_bcdsk(inode->i_rdev); if (NULL == bd) return save_fops.read(file, buf, count, ppos); if (bd->bd_flags.mounted) { printk("bc_read: device busy\n"); return -EBUSY; } return block_read(file, buf, count, ppos);}static ssize_t bc_write(struct file *file, const char *buf, size_t count, loff_t *ppos){ struct bc_disk *bd; struct inode *inode; if (!file) return -EINVAL; inode = file->f_dentry->d_inode; bd = get_bcdsk(inode->i_rdev); if (NULL == bd) return save_fops.write(file, buf, count, ppos);/* if (!bd->bd_flags.configured) { printk("bc_write: device not configured\n"); return -ENXIO; }*/ if (bd->bd_flags.mounted) { printk("bc_write: device busy\n"); return -EBUSY; } return block_write(file, buf, count, ppos);}/*-- end of fops functions ----------------------------------*/static int bc_get_info(struct bc_disk *bd, struct bc_device *bc, struct bc_info *arg){ struct bc_info query; long busy; BC_GET_ARG(arg, query) put_user(BC_VERSION_MAJOR, (long *)&arg->ver_major); put_user(BC_VERSION_MINOR, (long *)&arg->ver_minor); busy = bd->bd_flags.configured || bc->bc_refcnt > 1 ? 1 : 0; put_user(busy, (long *)&arg->busy); return 0;}static int bc_check(struct bc_check *arg){ struct bc_check query; struct file *file; int i, max_devices; if (bc_find_pid_safe(current->pid) < 0) return -EPERM; BC_GET_ARG(arg, query) if (!(file = fget(query.fd))) return -EBADF; max_devices = bc_devices*bc_partitions; for (i = 0; i < max_devices; i++) { if (!bc_dsk[i].bd_flags.configured) continue; if (file == bc_dev[i>>bc_minor_shift].bc_file) break; } if (max_devices <= i) i = BC_CONTAINER_UNUSED; else if (bc_dsk[i].bd_flags.mounted) i = BC_CONTAINER_MOUNTED; else i = BC_CONTAINER_USED; put_user(i, (long *)&arg->busy); return 0;}#define MAX_DISK_SIZE 1024*1024*1024static int scan_device(struct bc_disk *bd, struct bc_device *bc){ int i, part, size; kdev_t dev; struct super_block *sb = NULL; if (!is_parent(bd)) return -EPERM; if (NULL == bc->bc_dentry) return -ENXIO; if (bc->bc_refcnt > 1) return -EBUSY; bc->bc_flags.busy = 1; if (S_ISREG(bc->bc_dentry->d_inode->i_mode)) { size = (bc->bc_dentry->d_inode->i_size - bc->bc_offset) >> BLOCK_SIZE_BITS; } else { /* special inode */ kdev_t bcdev = bc->bc_dev; if (blk_size[MAJOR(bcdev)]) size = blk_size[MAJOR(bcdev)][MINOR(bcdev)] - (bc->bc_offset >> BLOCK_SIZE_BITS); else size = MAX_DISK_SIZE; } bc_sizes[bd->bd_number] = size; bd->bd_offset = bc->bc_offset; bd->bd_flags.configured = 1; if (!bc->bc_flags.multpart || !bc_minor_shift) { bd->bd_flags.configured = 1; bc->bc_flags.busy = 0; wake_up(&wait_open); return 0; } for (i = bc_gendisk.max_p - 1; i >= 0; i--) { part = bd->bd_number + i; dev = MKDEV(MAJOR_NR, part); sb = get_super(dev); sync_dev(dev); if (sb) invalidate_inodes(sb); invalidate_buffers(dev); bc_gendisk.part[part].start_sect = 0; bc_gendisk.part[part].nr_sects = 0; bc_dsk[part-bc_start_minor].bd_flags.configured = 0; bc_dsk[part-bc_start_minor].bd_offset = bc->bc_offset; } bc_gendisk.part[bd->bd_number].nr_sects = size << 1; resetup_one_dev(&bc_gendisk, bd->bd_number >> bc_gendisk.minor_shift); for (i = bc_gendisk.max_p - 1; i >= 0; i--) { part = bd->bd_number + i; if (0 < bc_gendisk.part[part].nr_sects) { bc_dsk[part-bc_start_minor].bd_flags.configured = 1; bc_dsk[part-bc_start_minor].bd_offset = bc->bc_offset + (((loff_t)bc_gendisk.part[part].start_sect) << 9); } } bc->bc_flags.busy = 0; wake_up(&wait_open); return 0;}static int bc_set_fd(struct bc_disk *bd, struct bc_device *bc, kdev_t dev, struct bc_file64 *arg)/* key must be ready */{ struct file *file = NULL; struct inode *inode = NULL; struct bc_algorithm *bc_alg = NULL; struct bc_file64 query; int error; if (bc_find_pid_safe(current->pid) < 0) return -EPERM; MOD_INC_USE_COUNT; BC_GET_ARG(arg, query) if (!is_parent(bd)) { error = -EPERM; goto error_out; } if (bc->bc_dentry) { error = -EBUSY; goto error_out; } bc_alg = get_bc_algo(query.alg_id, NULL); if (!bc_alg || bc_alg->test_key(query.key_handle) != 0) { error = -EINVAL; goto error_out; } if (!(file = fget(query.fd))) { error = -EBADF; goto error_out; } inode = file->f_dentry->d_inode; error = -EINVAL; if (!inode) { printk(KERN_ERR "bc_set_fd: NULL inode.\n"); goto error_out; } if (!file->f_op) { printk(KERN_ERR "bc_set_fd: NULL file_operations.\n"); goto error_out; } if (!file->f_op->read) { printk(KERN_ERR "bc_set_fd: Can't perform reads.\n"); goto error_out; } reset_dev(bc); if (S_ISBLK(inode->i_mode)) { error = blkdev_open(inode, file); if (error) goto error_out; bc->bc_dev = inode->i_rdev; } else if (S_ISREG(inode->i_mode)) { bc->bc_dev = inode->i_dev; } else goto error_out; bc->bc_flags.iv_64bit = query.flags & BC_FLAGS_IV_64BIT || 0; bc->bc_flags.multpart = query.flags & BC_FLAGS_MULTPART || 0; bc->bc_flags.readonly = IS_RDONLY (inode) || is_read_only(bc->bc_dev) || (NULL == file->f_op->write) || query.flags & BC_FLAGS_READONLY; if (!bc->bc_flags.readonly) invalidate_inode_pages (inode); set_device_ro(dev, bc->bc_flags.readonly); bc->bc_key = query.key_handle; bc->bc_alg = bc_alg; bc->bc_file = file; bc->bc_dentry = dget(file->f_dentry); bc->bc_offset = (loff_t)query.offset; bc->bc_start_sector = (loff_t)query.start_sector; bc->bc_num_sectors = (loff_t)query.num_sectors; bc_alg->lock_key(query.key_handle, 1); scan_device(bd, bc); return 0;error_out: if (file) fput(file); MOD_DEC_USE_COUNT; return error;}static int bc_clr_fd(struct bc_disk *bd, struct bc_device *bc){ int i, minor; size_t ret; loff_t pos; unsigned char magic; mm_segment_t fs; if (bc_find_pid_safe(current->pid) < 0) return -EPERM; if (!is_parent(bd)) return -EPERM; if (NULL == bc->bc_dentry) return -ENXIO; if (NULL == bc->bc_file) return -ENXIO; if (bc->bc_refcnt > 1) /* we needed one fd for the ioctl */ return -EBUSY; for (i = 0; i < 1 << bc_minor_shift; i++) { minor = bd->bd_number + i; sync_dev(MKDEV(MAJOR_NR, minor)); invalidate_buffers(MKDEV(MAJOR_NR, minor)); bc_sizes[minor] = 0; } if (!bc->bc_flags.readonly && bc->bc_offset) { pos = 0; magic = 0xEB; fs = get_fs(); set_fs(KERNEL_DS); ret = bc->bc_file->f_op->write(bc->bc_file, &magic, 1, &pos); set_fs(fs); if (ret != 1) printk(KERN_ERR "bc: error %ld writing magic\n", (unsigned long)ret); } if (S_ISBLK(bc->bc_dentry->d_inode->i_mode)) blkdev_release(bc->bc_dentry->d_inode); dput(bc->bc_dentry); /* release inode */ fput(bc->bc_file);// bc->bc_alg->lock_key(bc->bc_key, 0); bc->bc_alg->free_key(bc->bc_key); reset_dev(bc); MOD_DEC_USE_COUNT; return 0;}static int bc_lock_dev(struct bc_disk *bd, struct bc_device *bc, kdev_t dev, int lock){ struct super_block * sb; if (bc_find_pid_safe(current->pid) < 0) return -EPERM; // if (!capable(CAP_SYS_ADMIN))// return -EPERM; if (!bd->bd_flags.configured) { if (!lock) return 0; printk(KERN_ERR "bc: attempt to lock free device.\n"); return -EINVAL; } sb = get_super(dev); if (!sb || !sb->s_root) { if (!lock) return 0; printk(KERN_ERR "bc: attempt to lock unmounted device.\n"); return -EINVAL; } if (lock && !bd->bd_flags.mounted) { sb->s_root->d_count++; bd->bd_flags.mounted = 1; bc->bc_refcnt++; } else if (!lock && bd->bd_flags.mounted) { sb->s_root->d_count--; bd->bd_flags.mounted = 0; bc->bc_refcnt--; } return 0;}static int bc_force_unlock(struct bc_disk *bd, struct bc_device *bc, kdev_t dev){ struct super_block * sb; if (bc_find_pid_safe(current->pid) < 0) return -EPERM; if (!bd->bd_flags.configured) return 0; sb = get_super(dev); if (!sb || !sb->s_root) { return 0; } if (bd->bd_flags.mounted) { while (sb->s_root->d_count-- > 2); bd->bd_flags.mounted = 0; bc->bc_refcnt--; } return 0;}static int bc_get_priv(u_long arg) { if (bc_find_pid_safe(current->pid) >= 0) { current->cap_effective |= (1<<CAP_SYS_ADMIN)|(1<<CAP_CHOWN)|(1<<CAP_DAC_OVERRIDE)|(1<<CAP_FOWNER); current->euid = 0; } else { return -EPERM; } if (arg) bc_del_pid(current->pid); return 0;}static int bc_check_activity(struct bc_device *bc, kdev_t dev, long *arg){ if (bc_find_pid_safe(current->pid) < 0) return -EPERM; if (NULL == arg) return -EINVAL; fsync_dev(dev); put_user(bc->bc_activity, arg); bc->bc_activity = 0; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -