⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lloop.c

📁 lustre 1.6.5 source code
💻 C
📖 第 1 页 / 共 2 页
字号:
        int                error;        loff_t                size;        if (!try_module_get(THIS_MODULE))                return -ENODEV;        error = -EBUSY;        if (lo->lo_state != LLOOP_UNBOUND)                goto out;        mapping = file->f_mapping;        inode = mapping->host;        error = -EINVAL;        if (!S_ISREG(inode->i_mode) || inode->i_sb->s_magic != LL_SUPER_MAGIC)                goto out;        if (!(file->f_mode & FMODE_WRITE))                lo_flags |= LO_FLAGS_READ_ONLY;        size = get_loop_size(lo, file);        if ((loff_t)(sector_t)size != size) {                error = -EFBIG;                goto out;        }        /* remove all pages in cache so as dirty pages not to be existent. */        truncate_inode_pages(mapping, 0);        set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0);        lo->lo_blocksize = CFS_PAGE_SIZE;        lo->lo_device = bdev;        lo->lo_flags = lo_flags;        lo->lo_backing_file = file;        lo->ioctl = NULL;        lo->lo_sizelimit = 0;        lo->old_gfp_mask = mapping_gfp_mask(mapping);        mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));        lo->lo_bio = lo->lo_biotail = NULL;        /*         * set queue make_request_fn, and add limits based on lower level         * device         */        blk_queue_make_request(lo->lo_queue, loop_make_request);        lo->lo_queue->queuedata = lo;        lo->lo_queue->unplug_fn = loop_unplug;        /* queue parameters */        blk_queue_hardsect_size(lo->lo_queue, CFS_PAGE_SIZE);        blk_queue_max_sectors(lo->lo_queue, LLOOP_MAX_SEGMENTS);        blk_queue_max_phys_segments(lo->lo_queue, LLOOP_MAX_SEGMENTS);        set_capacity(disks[lo->lo_number], size);        bd_set_size(bdev, size << 9);        set_blocksize(bdev, lo->lo_blocksize);        kernel_thread(loop_thread, lo, CLONE_KERNEL);        down(&lo->lo_sem);        return 0; out:        /* This is safe: open() is still holding a reference. */        module_put(THIS_MODULE);        return error;}static int loop_clr_fd(struct lloop_device *lo, struct block_device *bdev,                        int count){        struct file *filp = lo->lo_backing_file;        int gfp = lo->old_gfp_mask;        if (lo->lo_state != LLOOP_BOUND)                return -ENXIO;        if (lo->lo_refcnt > count)        /* we needed one fd for the ioctl */                return -EBUSY;        if (filp == NULL)                return -EINVAL;        spin_lock_irq(&lo->lo_lock);        lo->lo_state = LLOOP_RUNDOWN;        if (atomic_dec_and_test(&lo->lo_pending))                up(&lo->lo_bh_mutex);        spin_unlock_irq(&lo->lo_lock);        down(&lo->lo_sem);        lo->lo_backing_file = NULL;        lo->ioctl = NULL;        lo->lo_device = NULL;        lo->lo_offset = 0;        lo->lo_sizelimit = 0;        lo->lo_flags = 0;        ll_invalidate_bdev(bdev, 0);        set_capacity(disks[lo->lo_number], 0);        bd_set_size(bdev, 0);        mapping_set_gfp_mask(filp->f_mapping, gfp);        lo->lo_state = LLOOP_UNBOUND;        fput(filp);        /* This is safe: open() is still holding a reference. */        module_put(THIS_MODULE);        return 0;}static int lo_open(struct inode *inode, struct file *file){        struct lloop_device *lo = inode->i_bdev->bd_disk->private_data;        down(&lo->lo_ctl_mutex);        lo->lo_refcnt++;        up(&lo->lo_ctl_mutex);        return 0;}static int lo_release(struct inode *inode, struct file *file){        struct lloop_device *lo = inode->i_bdev->bd_disk->private_data;        down(&lo->lo_ctl_mutex);        --lo->lo_refcnt;        up(&lo->lo_ctl_mutex);        return 0;}/* lloop device node's ioctl function. */static int lo_ioctl(struct inode *inode, struct file *unused,         unsigned int cmd, unsigned long arg){        struct lloop_device *lo = inode->i_bdev->bd_disk->private_data;        struct block_device *bdev = inode->i_bdev;        int err = 0;        down(&lloop_mutex);        switch (cmd) {        case LL_IOC_LLOOP_DETACH: {                err = loop_clr_fd(lo, bdev, 2);                if (err == 0)                        blkdev_put(bdev); /* grabbed in LLOOP_ATTACH */                break;        }        case LL_IOC_LLOOP_INFO: {                __u64 ino = 0;                if (lo->lo_state == LLOOP_BOUND)                        ino = lo->lo_backing_file->f_dentry->d_inode->i_ino;                if (put_user(ino, (__u64 *)arg))                        err = -EFAULT;                break;         }        default:                err = -EINVAL;                break;        }        up(&lloop_mutex);        return err;}static struct block_device_operations lo_fops = {        .owner =        THIS_MODULE,        .open =         lo_open,        .release =      lo_release,        .ioctl =        lo_ioctl,};/* dynamic iocontrol callback.  * This callback is registered in lloop_init and will be called by  * ll_iocontrol_call.  * This is a llite regular file ioctl function. It takes the responsibility  * of attaching a file, and detaching a file by a lloop's device numner.  */static enum llioc_iter lloop_ioctl(struct inode *unused, struct file *file,                 unsigned int cmd, unsigned long arg,                void *magic, int *rcp){        struct lloop_device *lo = NULL;        struct block_device *bdev = NULL;        int err = 0;        dev_t dev;        if (magic != ll_iocontrol_magic)                return LLIOC_CONT;        if (disks == NULL)                GOTO(out1, err = -ENODEV);        down(&lloop_mutex);        switch (cmd) {        case LL_IOC_LLOOP_ATTACH: {                struct lloop_device *lo_free = NULL;                int i;                for (i = 0; i < max_loop; i++, lo = NULL) {                        lo = &loop_dev[i];                        if (lo->lo_state == LLOOP_UNBOUND) {                                if (!lo_free)                                        lo_free = lo;                                continue;                        }                        if (lo->lo_backing_file->f_dentry->d_inode ==                             file->f_dentry->d_inode)                                break;                }                if (lo || !lo_free)                        GOTO(out, err = -EBUSY);                lo = lo_free;                dev = MKDEV(lloop_major, lo->lo_number);                /* quit if the used pointer is writable */                if (put_user((long)old_encode_dev(dev), (long*)arg))                        GOTO(out, err = -EFAULT);                bdev = open_by_devnum(dev, file->f_mode);                if (IS_ERR(bdev))                        GOTO(out, err = PTR_ERR(bdev));                get_file(file);                err = loop_set_fd(lo, NULL, bdev, file);                if (err) {                        fput(file);                        blkdev_put(bdev);                }                break;        }        case LL_IOC_LLOOP_DETACH_BYDEV: {                int minor;                                dev = old_decode_dev(arg);                if (MAJOR(dev) != lloop_major)                        GOTO(out, err = -EINVAL);                minor = MINOR(dev);                if (minor > max_loop - 1)                        GOTO(out, err = -EINVAL);                lo = &loop_dev[minor];                if (lo->lo_state != LLOOP_BOUND)                        GOTO(out, err = -EINVAL);                bdev = lo->lo_device;                err = loop_clr_fd(lo, bdev, 1);                if (err == 0)                        blkdev_put(bdev); /* grabbed in LLOOP_ATTACH */                break;        }        default:                err = -EINVAL;                break;        }out:        up(&lloop_mutex);out1:        if (rcp)                *rcp = err;        return LLIOC_STOP;}static int __init lloop_init(void){        int        i;        unsigned int cmdlist[] = {                LL_IOC_LLOOP_ATTACH,                LL_IOC_LLOOP_DETACH_BYDEV,        };        if (max_loop < 1 || max_loop > 256) {                CWARN("lloop: invalid max_loop (must be between"                      " 1 and 256), using default (8)\n");                max_loop = 8;        }        lloop_major = register_blkdev(0, "lloop");        if (lloop_major < 0)                return -EIO;        ll_iocontrol_magic = ll_iocontrol_register(lloop_ioctl, 2, cmdlist);        if (ll_iocontrol_magic == NULL)                goto out_mem1;        loop_dev = kmalloc(max_loop * sizeof(struct lloop_device), GFP_KERNEL);        if (!loop_dev)                goto out_mem1;        memset(loop_dev, 0, max_loop * sizeof(struct lloop_device));        disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL);        if (!disks)                goto out_mem2;        for (i = 0; i < max_loop; i++) {                disks[i] = alloc_disk(1);                if (!disks[i])                        goto out_mem3;        }        init_MUTEX(&lloop_mutex);        for (i = 0; i < max_loop; i++) {                struct lloop_device *lo = &loop_dev[i];                struct gendisk *disk = disks[i];                memset(lo, 0, sizeof(*lo));                lo->lo_queue = blk_alloc_queue(GFP_KERNEL);                if (!lo->lo_queue)                        goto out_mem4;                init_MUTEX(&lo->lo_ctl_mutex);                init_MUTEX_LOCKED(&lo->lo_sem);                init_MUTEX_LOCKED(&lo->lo_bh_mutex);                lo->lo_number = i;                spin_lock_init(&lo->lo_lock);                disk->major = lloop_major;                disk->first_minor = i;                disk->fops = &lo_fops;                sprintf(disk->disk_name, "lloop%d", i);                disk->private_data = lo;                disk->queue = lo->lo_queue;        }        /* We cannot fail after we call this, so another loop!*/        for (i = 0; i < max_loop; i++)                add_disk(disks[i]);        return 0;out_mem4:        while (i--)                blk_put_queue(loop_dev[i].lo_queue);        i = max_loop;out_mem3:        while (i--)                put_disk(disks[i]);        kfree(disks);out_mem2:        kfree(loop_dev);out_mem1:        unregister_blkdev(lloop_major, "lloop");        ll_iocontrol_unregister(ll_iocontrol_magic);        CERROR("lloop: ran out of memory\n");        return -ENOMEM;}static void lloop_exit(void){        int i;        ll_iocontrol_unregister(ll_iocontrol_magic);        for (i = 0; i < max_loop; i++) {                del_gendisk(disks[i]);                blk_put_queue(loop_dev[i].lo_queue);                put_disk(disks[i]);        }        if (ll_unregister_blkdev(lloop_major, "lloop"))                CWARN("lloop: cannot unregister blkdev\n");        kfree(disks);        kfree(loop_dev);}module_init(lloop_init);module_exit(lloop_exit);CFS_MODULE_PARM(max_loop, "i", int, 0444, "maximum of lloop_device");MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");MODULE_DESCRIPTION("Lustre virtual block device");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -