Skip to content

Instantly share code, notes, and snippets.

@TheNeikos

TheNeikos/rblk.c Secret

Created November 16, 2015 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TheNeikos/8798788defa1a9f316e6 to your computer and use it in GitHub Desktop.
Save TheNeikos/8798788defa1a9f316e6 to your computer and use it in GitHub Desktop.
#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/bio.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/ioctl.h>
#include <linux/mutex.h>
#include <linux/compiler.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <net/sock.h>
#include <linux/net.h>
#include <linux/kthread.h>
#include <linux/types.h>
#include <linux/debugfs.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marcel Müller <neikos@neikos.email>");
static int rblk_cnt = 1;
module_param(rblk_cnt, int, 0444);
MODULE_PARM_DESC(rblk_cnt, "number of block devices to initialize (default: 1)");
static DEFINE_SPINLOCK(rblk_lock);
struct rblk_dev {
spinlock_t queue_lock;
struct gendisk* disk;
};
static int rblk_major;
static struct rblk_dev* rblk_d;
static int rblk_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
long size;
printk(KERN_INFO "rblk: Got IOCTL %#x\n", cmd);
return -ENOTTY;
}
static struct block_device_operations rblk_fops = {
.owner = THIS_MODULE,
.ioctl = rblk_ioctl,
};
static void rblk_request_handler(struct request_queue *q)
__releases(q->queue_lock) __acquires(q->queue_lock)
{
struct request* req;
unsigned long flags = 0;
printk(KERN_INFO "rblk: Got request(s) \n");
while ((req = blk_fetch_request(q)) != NULL) {
printk(KERN_INFO "rblk: Handling request \n");
spin_lock_irqsave(q->queue_lock, flags);
blk_end_request_all(req, -ENOTTY);
spin_unlock_irqrestore(q->queue_lock, flags);
printk(KERN_INFO "rblk: Handled request \n");
}
}
static int __init rblk_init(void)
{
int i;
rblk_major = register_blkdev(0, "rblk");
if (!rblk_major) {
printk(KERN_ERR "rblk: Could not registed block device\n");
return -EINVAL;
}
rblk_d = kcalloc(rblk_cnt, sizeof(*rblk_d), GFP_KERNEL);
if (!rblk_d) {
printk(KERN_ERR "rblk: Could not allocate memory\n");
return -ENOMEM;
}
for (i = 0; i < rblk_cnt; i++) {
struct gendisk* disk = alloc_disk(1 << fls(rblk_cnt));
if (!disk) {
printk(KERN_ERR "rblk: alloc_disk failure\n");
goto out_free;
}
rblk_d[i].disk = disk;
disk->queue = blk_init_queue(rblk_request_handler, &rblk_lock);
if (!disk->queue) {
printk(KERN_ERR "rblk: Could not init req queue\n");
put_disk(disk);
goto out_free;
}
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue);
queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, disk->queue);
disk->queue->limits.discard_granularity = 512;
blk_queue_max_discard_sectors(disk->queue, UINT_MAX);
disk->queue->limits.discard_zeroes_data = 0;
blk_queue_max_hw_sectors(disk->queue, 65536);
disk->queue->limits.max_sectors = 256;
spin_lock_init(&rblk_d[i].queue_lock);
disk->major = rblk_major;
disk->first_minor = i << fls(rblk_cnt);
disk->fops = &rblk_fops;
disk->private_data = &rblk_d[i];
sprintf(disk->disk_name, "rblk%d", i);
// set_capacity(disk, 0); // TODO: Add param
add_disk(disk);
set_capacity(disk, 512 * 1024 * 1024);
}
return 0;
out_free:
while(i--) {
struct gendisk *disk = rblk_d[i].disk;
if (disk) {
del_gendisk(disk);
blk_cleanup_queue(disk->queue);
put_disk(disk);
}
}
unregister_blkdev(rblk_major, "rblk");
kfree(rblk_d);
return -EINVAL;
}
static void __exit rblk_cleanup(void)
{
int i;
for (i = 0; i < rblk_cnt; i++) {
struct gendisk *disk = rblk_d[i].disk;
if (disk) {
del_gendisk(disk);
blk_cleanup_queue(disk->queue);
put_disk(disk);
}
}
unregister_blkdev(rblk_major, "rblk");
kfree(rblk_d);
}
module_init(rblk_init);
module_exit(rblk_cleanup);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment