From 937bd5bebbf5c54318a4616a283eeca79822bde5 Mon Sep 17 00:00:00 2001 From: Akira Hayakawa Date: Fri, 17 May 2024 16:51:09 +0900 Subject: [PATCH] Don't abuse!! Rename to azbuse. (#52) * Rename to azbuse Don't abuse. --- .github/workflows/CI.yml | 35 +- .gitignore | 7 - Cargo.toml | 6 +- abuse-kmod/src/abuse.c | 542 ------------------- abuse-kmod/src/abuse.h | 102 ---- abusectl/src/main.rs | 30 - {abuse-kmod => azbuse-kmod}/Makefile | 4 +- {abuse-kmod => azbuse-kmod}/src/.gitignore | 8 +- {abuse-kmod => azbuse-kmod}/src/Makefile | 2 +- azbuse-kmod/src/azbuse.c | 542 +++++++++++++++++++ azbuse-kmod/src/azbuse.h | 98 ++++ {abuse-kmod => azbuse-kmod}/src/dkms.conf | 4 +- {abuse => azbuse}/Cargo.toml | 2 +- {abuse => azbuse}/src/lib.rs | 64 +-- {abusectl => azbusectl}/Cargo.toml | 2 +- azbusectl/src/main.rs | 30 + tests/abuse-ramdisk/README.md | 16 - tests/{abuse-ramdisk => ramdisk}/Cargo.toml | 4 +- tests/{abuse-ramdisk => ramdisk}/src/main.rs | 6 +- 19 files changed, 737 insertions(+), 767 deletions(-) delete mode 100644 abuse-kmod/src/abuse.c delete mode 100644 abuse-kmod/src/abuse.h delete mode 100644 abusectl/src/main.rs rename {abuse-kmod => azbuse-kmod}/Makefile (72%) rename {abuse-kmod => azbuse-kmod}/src/.gitignore (73%) rename {abuse-kmod => azbuse-kmod}/src/Makefile (91%) create mode 100644 azbuse-kmod/src/azbuse.c create mode 100644 azbuse-kmod/src/azbuse.h rename {abuse-kmod => azbuse-kmod}/src/dkms.conf (77%) rename {abuse => azbuse}/Cargo.toml (96%) rename {abuse => azbuse}/src/lib.rs (77%) rename {abusectl => azbusectl}/Cargo.toml (93%) create mode 100644 azbusectl/src/main.rs delete mode 100644 tests/abuse-ramdisk/README.md rename tests/{abuse-ramdisk => ramdisk}/Cargo.toml (89%) rename tests/{abuse-ramdisk => ramdisk}/src/main.rs (94%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d073610..860df9e 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -26,53 +26,50 @@ jobs: version: 1.0 - name: Build module - working-directory: abuse-kmod + working-directory: azbuse-kmod run: sudo make install - name: Load module run: | - sudo modprobe abuse + sudo modprobe azbuse ls /dev - - name: Install abusectl - run: sudo cargo install --path abusectl --root /usr/local + - name: Install azbusectl + run: sudo cargo install --path azbusectl --root /usr/local - - name: Add /dev/abuse1 + - name: Add /dev/azbuse1 run: | - sudo abusectl add 1 + sudo azbusectl add 1 lsblk - sudo abusectl remove 1 + sudo azbusectl remove 1 lsblk - sudo abusectl add 1 + sudo azbusectl add 1 lsblk - - name: Connect /dev/abuse1 and ramdisk + - name: Connect /dev/azbuse1 and ramdisk run: | - sudo cargo build -p abuse-ramdisk --release - sudo target/release/abuse-ramdisk 1 &> abuse.log & + sudo cargo build -p ramdisk --release + sudo target/release/ramdisk 1 &> azbuse.log & sleep 1 lsblk - name: Logical test (badblocks) - run: sudo badblocks -wsv /dev/abuse1 + run: sudo badblocks -wsv /dev/azbuse1 - name: Performance test - run: sudo ruby tests/perf.rb /dev/abuse1 + run: sudo ruby tests/perf.rb /dev/azbuse1 - name: Error log run: | - sudo cat /var/lib/dkms/abuse/1.0.0/build/make.log + sudo cat /var/lib/dkms/azbuse/1.0.0/build/make.log if: ${{ failure() }} - name: App Log run: | - sudo cat abuse.log + sudo cat azbuse.log if: ${{ always() }} - name: kernel Log run: | sudo dmesg - if: ${{ always() }} - - - \ No newline at end of file + if: ${{ always() }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 5c67d64..32e19f0 100644 --- a/.gitignore +++ b/.gitignore @@ -11,12 +11,5 @@ Cargo.lock tmp* -abuse-ramdisk.bin -nbd-ramdisk.bin - -dd-read.sh -dd-perf-read.sh -dd-perf-write.sh - log *.log \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 39082de..5fee527 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [workspace] members = [ - "abuse", - "abusectl", - "tests/abuse-ramdisk", + "azbuse", + "azbusectl", + "tests/ramdisk", ] [workspace.dependencies] diff --git a/abuse-kmod/src/abuse.c b/abuse-kmod/src/abuse.c deleted file mode 100644 index 53e4d63..0000000 --- a/abuse-kmod/src/abuse.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * This software is a fork of - * - * linux/drivers/block/abuse.c - * Written by Zachary Amsden, 7/23/2009 - * - * Copyright (c) 2009 Zachary Amsden - * Copyright (c) 2015 Naohiro Aota - * Copyright (c) 2021 Akira Hayakawa - * - * Redistribution of this file is permitted under the GNU General Public License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "abuse.h" - -#include - -static DEFINE_MUTEX(abuse_ctl_mutex); -static DEFINE_IDR(abuse_index_idr); - -static void abuse_flush_pending_requests(struct abuse_device *ab) -{ - struct ab_req *req, *tmp; - - spin_lock_irq(&ab->ab_lock); - list_for_each_entry_safe(req, tmp, &ab->ab_reqlist, list) { - req->rq->rq_flags |= RQF_FAILED; - blk_mq_complete_request(req->rq); - list_del(&req->list); - } - spin_unlock_irq(&ab->ab_lock); -} - -static int abuse_reset(struct abuse_device *ab) -{ - if (!ab->ab_disk->queue) - return -EINVAL; - - abuse_flush_pending_requests(ab); - ab->ab_blocksize = 0; - ab->ab_size = 0; - invalidate_disk(ab->ab_disk); - module_put(THIS_MODULE); - return 0; -} - -static int __abuse_get_status(struct abuse_device *ab, struct abuse_info *info) -{ - memset(info, 0, sizeof(*info)); - info->ab_number = ab->ab_number; - info->ab_size = ab->ab_size; - info->ab_blocksize = ab->ab_blocksize; - return 0; -} - -static int abuse_get_status(struct abuse_device *ab, struct abuse_info __user *arg) -{ - struct abuse_info info; - int err = 0; - - if (!arg) - err = -EINVAL; - if (!err) - err = __abuse_get_status(ab, &info); - if (!err && copy_to_user(arg, &info, sizeof(info))) - err = -EFAULT; - - return err; -} - -static int __abuse_set_status(struct abuse_device *ab, const struct abuse_info *info) -{ - sector_t size = (sector_t)(info->ab_size >> SECTOR_SHIFT); - loff_t blocks; - - if (unlikely((loff_t)size != size)) - return -EFBIG; - if (unlikely(info->ab_blocksize == 0)) - return -EINVAL; - - blocks = info->ab_size / info->ab_blocksize; - if (unlikely(info->ab_blocksize * blocks != info->ab_size)) - return -EINVAL; - - set_disk_ro(ab->ab_disk, 0); - - set_capacity(ab->ab_disk, size); - ab->ab_size = info->ab_size; - - blk_queue_logical_block_size(ab->ab_queue, info->ab_blocksize); - blk_queue_physical_block_size(ab->ab_queue, info->ab_blocksize); - ab->ab_blocksize = info->ab_blocksize; - - __module_get(THIS_MODULE); - - return 0; -} - -static int abuse_set_status(struct abuse_device *ab, const struct abuse_info __user *arg) -{ - struct abuse_info info; - if (copy_from_user(&info, arg, sizeof (struct abuse_info))) - return -EFAULT; - return __abuse_set_status(ab, &info); -} - -static unsigned xfr_command_from_cmd_flags(unsigned cmd_flags) { - unsigned int ret = 0; - switch (cmd_flags & REQ_OP_BITS) { - case REQ_OP_READ: - ret = CMD_OP_READ; - break; - case REQ_OP_WRITE: - ret = CMD_OP_WRITE; - break; - case REQ_OP_FLUSH: - ret = CMD_OP_FLUSH; - break; - case REQ_OP_DISCARD: - ret = CMD_OP_DISCARD; - break; - case REQ_OP_SECURE_ERASE: - ret = CMD_OP_SECURE_ERASE; - break; - case REQ_OP_WRITE_ZEROES: - ret = CMD_OP_WRITE_ZEROES; - break; - default: - ret = CMD_OP_UNKNOWN; - break; - } - if (cmd_flags & REQ_FUA) { - ret |= CMD_FUA; - } - if (cmd_flags & REQ_PREFLUSH) { - ret |= CMD_PREFLUSH; - } - if (cmd_flags & REQ_NOUNMAP) { - ret |= CMD_NOUNMAP; - } - if (cmd_flags & REQ_NOWAIT) { - ret |= CMD_NOWAIT; - } - if (cmd_flags & REQ_RAHEAD) { - ret |= CMD_RAHEAD; - } - return ret; -} - -static int abuse_get_req(struct abuse_device *ab, struct abuse_xfr_hdr __user *arg) -{ - struct abuse_xfr_hdr xfr; - struct ab_req *req = NULL; - - if (!arg) - return -EINVAL; - if (!ab) - return -ENODEV; - - if (copy_from_user(&xfr, arg, sizeof (struct abuse_xfr_hdr))) - return -EFAULT; - - spin_lock_irq(&ab->ab_lock); - req = list_first_entry_or_null(&ab->ab_reqlist, struct ab_req, list); - if (req) { - struct req_iterator iter; - struct bio_vec bvec; - int i = 0; - - list_del(&req->list); - spin_unlock_irq(&ab->ab_lock); - - // Use the pointer address as the unique id of the request - xfr.ab_id = (__u64)req; - xfr.ab_command = xfr_command_from_cmd_flags(req->rq->cmd_flags); - xfr.ab_offset = blk_rq_pos(req->rq) << SECTOR_SHIFT; - xfr.ab_len = blk_rq_bytes(req->rq); - rq_for_each_bvec(bvec, req->rq, iter) { - // physical address of the page - ab->ab_xfer[i].ab_address = (__u64)page_to_phys(bvec.bv_page); - ab->ab_xfer[i].n_pages = ((bvec.bv_offset + bvec.bv_len) + (4096-1)) / 4096; - ab->ab_xfer[i].ab_offset = bvec.bv_offset; - ab->ab_xfer[i].ab_len = bvec.bv_len; - i++; - } - xfr.ab_vec_count = i; - ab->ab_xfer_count = i; - } else { - spin_unlock_irq(&ab->ab_lock); - return -ENOMSG; - } - - if (copy_to_user(arg, &xfr, sizeof(xfr))) - return -EFAULT; - BUG_ON(xfr.ab_transfer_address == 0); - if (copy_to_user((__user void *) xfr.ab_transfer_address, ab->ab_xfer, xfr.ab_vec_count * sizeof(ab->ab_xfer[0]))) - return -EFAULT; - - return 0; -} - -static struct ab_req *abuse_find_req(struct abuse_device *ab, __u64 id) -{ - struct ab_req *req = id; - return req; -} - -// Complete a request -static int abuse_put_req(struct abuse_device *ab, struct abuse_completion __user *arg) -{ - struct abuse_completion xfr; - struct ab_req *req = NULL; - - if (!arg) - return -EINVAL; - if (!ab) - return -ENODEV; - - if (copy_from_user(&xfr, arg, sizeof (struct abuse_completion))) - return -EFAULT; - - req = abuse_find_req(ab, xfr.ab_id); - blk_mq_end_request(req->rq, errno_to_blk_status(xfr.ab_errno)); - return 0; -} - -static int abuse_connect(struct file *ctl, unsigned long arg) -{ - struct file *dev; - struct abuse_device *ab; - - if (ctl->private_data) - return -EBUSY; - - dev = fget(arg); - if (!dev) - return -EBADF; - - ab = idr_find(&abuse_index_idr, iminor(dev->f_inode)); - fput(dev); - - if (!ab) - return -ENODEV; - - ctl->private_data = ab; - - return 0; -} - -static int abctl_open(struct inode *nodp, struct file *filp) -{ - filp->private_data = NULL; - return 0; -} - -static int abctl_release(struct inode *inode, struct file *filp) -{ - struct abuse_device *ab = filp->private_data; - if (!ab) { - return -ENODEV; - } - - filp->private_data = NULL; - return 0; -} - -static unsigned int abctl_poll(struct file *filp, poll_table *wait) -{ - struct abuse_device *ab = filp->private_data; - unsigned int mask; - - if (ab == NULL) - return -ENODEV; - - poll_wait(filp, &ab->ab_event, wait); - mask = (list_empty(&ab->ab_reqlist)) ? 0 : POLLIN; - return mask; -} - -static int abctl_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct abuse_device *ab = filp->private_data; - int i; - int n = ab->ab_xfer_count; - int err = 0; - unsigned long cur = vma->vm_start; - for (i=0; iab_xfer[i].ab_address >> PAGE_SHIFT; - unsigned long len = ab->ab_xfer[i].n_pages << PAGE_SHIFT; - err |= remap_pfn_range(vma, cur, pfn, len, vma->vm_page_prot); - cur += len; - } - return err; -} - -static struct block_device_operations ab_fops = { - .owner = THIS_MODULE, -}; - -static int abuse_init_request(struct blk_mq_tag_set *set, struct request *rq, - unsigned int hctx_idx, unsigned int numa_node) -{ - struct ab_req *req = blk_mq_rq_to_pdu(rq); - - INIT_LIST_HEAD(&req->list); - req->rq = rq; - return 0; -} - -static blk_status_t abuse_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) -{ - struct ab_req *req = blk_mq_rq_to_pdu(bd->rq); - struct abuse_device *ab = req->rq->q->queuedata; - - blk_mq_start_request(bd->rq); - - spin_lock_irq(&ab->ab_lock); - list_add_tail(&req->list, &ab->ab_reqlist); - spin_unlock_irq(&ab->ab_lock); - - wake_up(&ab->ab_event); - return BLK_STS_OK; -} - -static struct blk_mq_ops abuse_mq_ops = { - .init_request = abuse_init_request, - .queue_rq = abuse_queue_rq, -}; - -// FIXME: error propagation -static struct abuse_device *abuse_add(int i) -{ - struct abuse_device *ab; - struct gendisk *disk; - int err; - - ab = kzalloc(sizeof(*ab), GFP_KERNEL); - if (!ab) - goto out; - - if (i >= 0) { - err = idr_alloc(&abuse_index_idr, ab, i, i + 1, GFP_KERNEL); - if (err == -ENOSPC) - err = -EEXIST; - } else { - err = idr_alloc(&abuse_index_idr, ab, 0, 0, GFP_KERNEL); - } - if (err < 0) - goto out_free_dev; - i = err; - - ab->tag_set.ops = &abuse_mq_ops; - ab->tag_set.nr_hw_queues = 1; - ab->tag_set.queue_depth = 128; - ab->tag_set.numa_node = NUMA_NO_NODE; - ab->tag_set.cmd_size = sizeof(struct ab_req); - ab->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; - ab->tag_set.driver_data = ab; - - err = blk_mq_alloc_tag_set(&ab->tag_set); - if (err) - goto out_free_idr; - - disk = blk_mq_alloc_disk(&ab->tag_set, ab); - if (!disk) - goto out_cleanup_tags; - ab->ab_queue = disk->queue; - ab->ab_queue->queuedata = ab; - blk_queue_flag_set(QUEUE_FLAG_NONROT, ab->ab_queue); - - disk->major = ABUSE_MAJOR; - disk->first_minor = i; - disk->minors = 1; - disk->fops = &ab_fops; - disk->private_data = ab; - sprintf(disk->disk_name, "abuse%d", i); - - err = add_disk(disk); - if (err) - goto out_cleanup_disk; - - ab->ab_disk = disk; - ab->ab_number = i; - init_waitqueue_head(&ab->ab_event); - spin_lock_init(&ab->ab_lock); - INIT_LIST_HEAD(&ab->ab_reqlist); - - return ab; - -out_cleanup_disk: - del_gendisk(ab->ab_disk); - put_disk(disk); -out_cleanup_tags: - blk_mq_free_tag_set(&ab->tag_set); -out_free_idr: - idr_remove(&abuse_index_idr, i); -out_free_dev: - kfree(ab); -out: - return NULL; -} - -static void abuse_remove(struct abuse_device *ab) -{ - del_gendisk(ab->ab_disk); - put_disk(ab->ab_disk); - blk_mq_free_tag_set(&ab->tag_set); - idr_remove(&abuse_index_idr, ab->ab_number); - kfree(ab); -} - -static long abctl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct abuse_device *ab = filp->private_data; - struct abuse_device *remove; - int err; - - switch (cmd) { - case ABUSE_GET_REQ: - err = abuse_get_req(ab, (struct abuse_xfr_hdr __user *) arg); - break; - case ABUSE_PUT_REQ: - err = abuse_put_req(ab, (struct abuse_completion __user *) arg); - break; - case ABUSE_GET_STATUS: - mutex_lock(&abuse_ctl_mutex); - err = abuse_get_status(ab, (struct abuse_info __user *) arg); - mutex_unlock(&abuse_ctl_mutex); - break; - case ABUSE_SET_STATUS: - mutex_lock(&abuse_ctl_mutex); - err = abuse_set_status(ab, (struct abuse_info __user *) arg); - mutex_unlock(&abuse_ctl_mutex); - break; - case ABUSE_RESET: - mutex_lock(&abuse_ctl_mutex); - err = abuse_reset(ab); - mutex_unlock(&abuse_ctl_mutex); - break; - case ABUSE_CTL_ADD: - mutex_lock(&abuse_ctl_mutex); - abuse_add(arg); - mutex_unlock(&abuse_ctl_mutex); - break; - case ABUSE_CTL_REMOVE: - mutex_lock(&abuse_ctl_mutex); - remove = idr_find(&abuse_index_idr, arg); - if (remove == NULL) { - err = -ENOENT; - } else { - err = remove->ab_number; - abuse_remove(remove); - } - mutex_unlock(&abuse_ctl_mutex); - break; - case ABUSE_CONNECT: - mutex_lock(&abuse_ctl_mutex); - err = abuse_connect(filp, arg); - mutex_unlock(&abuse_ctl_mutex); - break; - default: - err = -EINVAL; - } - - return err; -} - -static struct file_operations abctl_fops = { - .owner = THIS_MODULE, - .open = abctl_open, - .release = abctl_release, - .unlocked_ioctl = abctl_ioctl, - .poll = abctl_poll, - .mmap = abctl_mmap, -}; - -static struct miscdevice abuse_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = "abctl", - .fops = &abctl_fops, -}; - -static int __init abuse_init(void) -{ - int err; - - err = misc_register(&abuse_misc); - if (err < 0) - return err; - - err = -EIO; - if (register_blkdev(ABUSE_MAJOR, "abuse")) { - printk("abuse: register_blkdev failed!\n"); - goto unregister_misc; - } - - printk(KERN_INFO "abuse: module loaded\n"); - return 0; - -unregister_misc: - misc_deregister(&abuse_misc); - - return err; -} - -static int abuse_exit_cb(int id, void *ptr, void *data) -{ - struct abuse_device *ab = ptr; - abuse_remove(ab); - return 0; -} - -static void __exit abuse_exit(void) -{ - idr_for_each(&abuse_index_idr, abuse_exit_cb, NULL); - idr_destroy(&abuse_index_idr); - - unregister_blkdev(ABUSE_MAJOR, "abuse"); - misc_deregister(&abuse_misc); -} - -module_init(abuse_init); -module_exit(abuse_exit); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("devname:abctl"); -MODULE_ALIAS_BLOCKDEV_MAJOR(ABUSE_MAJOR); \ No newline at end of file diff --git a/abuse-kmod/src/abuse.h b/abuse-kmod/src/abuse.h deleted file mode 100644 index a628239..0000000 --- a/abuse-kmod/src/abuse.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * include/linux/abuse.h - * - * Copyright (c) 2009 Zachary Amsden - * Copyright (c) 2015 Naohiro Aota - * Copyright (c) 2021 Akira Hayakawa - * - * Redistribution of this file is permitted under the GNU General Public License. - */ - -#ifndef _LINUX_ABUSE_H -#define _LINUX_ABUSE_H - -#include -#include -#include -#include -#include -#include /* for __u64 */ - -enum { - ABUSE_FLAGS_READ_ONLY = 1, -}; - -struct abuse_info { - __u32 ab_number; /* r/o */ - __u64 ab_size; /* r/w */ - __u32 ab_blocksize; /* r/w */ -}; - -#define ABUSE_GET_STATUS 0x4120 -#define ABUSE_SET_STATUS 0x4121 -#define ABUSE_RESET 0x4122 -#define ABUSE_GET_REQ 0x4123 -#define ABUSE_PUT_REQ 0x4124 - -#define ABUSE_CTL_ADD 0x4186 -#define ABUSE_CTL_REMOVE 0x4187 -#define ABUSE_CONNECT 0x4188 - -struct abuse_vec { - __u64 ab_address; - __u32 n_pages; - __u32 ab_offset; - __u32 ab_len; -}; - -#define CMD_OP_UNKNOWN 0 -#define CMD_OP_READ 1 -#define CMD_OP_WRITE 2 -#define CMD_OP_FLUSH 3 -#define CMD_OP_DISCARD 4 -#define CMD_OP_SECURE_ERASE 5 -#define CMD_OP_WRITE_ZEROES 6 - -#define CMD_FUA 1<<8 -#define CMD_PREFLUSH 1<<9 -#define CMD_NOUNMAP 1<<10 -#define CMD_NOWAIT 1<<11 -#define CMD_RAHEAD 1<<12 - -struct abuse_xfr_hdr { - __u64 ab_id; - __u64 ab_offset; - __u64 ab_len; - __u32 ab_command; - __u32 ab_vec_count; - __u64 ab_transfer_address; -}; - -struct abuse_completion { - __u64 ab_id; - __u32 ab_errno; -}; - -#define ABUSE_MAJOR 60 -#define ABUSECTL_MAJOR 61 - -struct abuse_device { - int ab_number; - loff_t ab_size; - unsigned ab_blocksize; - - spinlock_t ab_lock; - struct list_head ab_reqlist; - wait_queue_head_t ab_event; - - struct request_queue *ab_queue; - struct blk_mq_tag_set tag_set; - struct gendisk *ab_disk; - - /* user xfer area */ - int ab_xfer_count; - struct abuse_vec ab_xfer[BIO_MAX_VECS]; -}; - -struct ab_req { - struct request *rq; - struct list_head list; -}; - -#endif \ No newline at end of file diff --git a/abusectl/src/main.rs b/abusectl/src/main.rs deleted file mode 100644 index a1ddddb..0000000 --- a/abusectl/src/main.rs +++ /dev/null @@ -1,30 +0,0 @@ -use clap::Parser; - -#[derive(Parser)] -enum Opts { - Add { idx: u16 }, - Remove { idx: u16 }, -} - -const ABUSE_CTL_ADD: u16 = 0x4186; -const ABUSE_CTL_REMOVE: u16 = 0x4187; - -nix::ioctl_write_int_bad!(abctl_add_device, ABUSE_CTL_ADD); -nix::ioctl_write_int_bad!(abctl_remove_device, ABUSE_CTL_REMOVE); - -fn main() { - use nix::fcntl::{open, OFlag}; - use nix::sys::stat::Mode; - - let opts = Opts::parse(); - - let fd = open("/dev/abctl", OFlag::empty(), Mode::empty()).expect("couldn't open /dev/abctl"); - match opts { - Opts::Add { idx } => unsafe { - abctl_add_device(fd, idx as i32).unwrap(); - }, - Opts::Remove { idx } => unsafe { - abctl_remove_device(fd, idx as i32).unwrap(); - }, - } -} diff --git a/abuse-kmod/Makefile b/azbuse-kmod/Makefile similarity index 72% rename from abuse-kmod/Makefile rename to azbuse-kmod/Makefile index 108dcb0..29afd13 100644 --- a/abuse-kmod/Makefile +++ b/azbuse-kmod/Makefile @@ -1,6 +1,6 @@ MODULE_VERSION ?= 1.0.0 -DKMS_DIR := /usr/src/abuse-$(MODULE_VERSION) -DKMS_KEY := -m abuse -v $(MODULE_VERSION) +DKMS_DIR := /usr/src/azbuse-$(MODULE_VERSION) +DKMS_KEY := -m azbuse -v $(MODULE_VERSION) install: cp -r src $(DKMS_DIR) diff --git a/abuse-kmod/src/.gitignore b/azbuse-kmod/src/.gitignore similarity index 73% rename from abuse-kmod/src/.gitignore rename to azbuse-kmod/src/.gitignore index 16b0a14..9bf4911 100644 --- a/abuse-kmod/src/.gitignore +++ b/azbuse-kmod/src/.gitignore @@ -1,6 +1,6 @@ -.abuse* -abuse.ko -abuse.mod* +.azbuse* +azbuse.ko +azbuse.mod* build.log check-compile.sh Module.symvers @@ -8,4 +8,4 @@ modules.order .tmp_versions .Module.symvers.cmd .modules.order.cmd -abuse.o \ No newline at end of file +azbuse.o \ No newline at end of file diff --git a/abuse-kmod/src/Makefile b/azbuse-kmod/src/Makefile similarity index 91% rename from abuse-kmod/src/Makefile rename to azbuse-kmod/src/Makefile index 69d0408..5c0a351 100644 --- a/abuse-kmod/src/Makefile +++ b/azbuse-kmod/src/Makefile @@ -1,7 +1,7 @@ KERNEL_SOURCE_VERSION ?= $(shell uname -r) KERNEL_TREE ?= /lib/modules/$(KERNEL_SOURCE_VERSION)/build -obj-m := abuse.o +obj-m := azbuse.o all: $(MAKE) -C $(KERNEL_TREE) M=$(PWD) modules diff --git a/azbuse-kmod/src/azbuse.c b/azbuse-kmod/src/azbuse.c new file mode 100644 index 0000000..0c6d7a8 --- /dev/null +++ b/azbuse-kmod/src/azbuse.c @@ -0,0 +1,542 @@ +/* + * This software is a fork of + * + * linux/drivers/block/abuse.c + * Written by Zachary Amsden, 7/23/2009 + * + * Copyright (c) 2009 Zachary Amsden + * Copyright (c) 2015 Naohiro Aota + * Copyright (c) 2021 Akira Hayakawa + * + * Redistribution of this file is permitted under the GNU General Public License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "azbuse.h" + +#include + +static DEFINE_MUTEX(azbuse_ctl_mutex); +static DEFINE_IDR(azbuse_index_idr); + +static void azbuse_flush_pending_requests(struct azbuse_device *azb) +{ + struct azb_req *req, *tmp; + + spin_lock_irq(&azb->azb_lock); + list_for_each_entry_safe(req, tmp, &azb->azb_reqlist, list) { + req->rq->rq_flags |= RQF_FAILED; + blk_mq_complete_request(req->rq); + list_del(&req->list); + } + spin_unlock_irq(&azb->azb_lock); +} + +static int azbuse_reset(struct azbuse_device *azb) +{ + if (!azb->azb_disk->queue) + return -EINVAL; + + azbuse_flush_pending_requests(azb); + azb->azb_blocksize = 0; + azb->azb_size = 0; + invalidate_disk(azb->azb_disk); + module_put(THIS_MODULE); + return 0; +} + +static int __azbuse_get_status(struct azbuse_device *azb, struct azbuse_info *info) +{ + memset(info, 0, sizeof(*info)); + info->azb_number = azb->azb_number; + info->azb_size = azb->azb_size; + info->azb_blocksize = azb->azb_blocksize; + return 0; +} + +static int azbuse_get_status(struct azbuse_device *azb, struct azbuse_info __user *arg) +{ + struct azbuse_info info; + int err = 0; + + if (!arg) + err = -EINVAL; + if (!err) + err = __azbuse_get_status(azb, &info); + if (!err && copy_to_user(arg, &info, sizeof(info))) + err = -EFAULT; + + return err; +} + +static int __azbuse_set_status(struct azbuse_device *azb, const struct azbuse_info *info) +{ + sector_t size = (sector_t)(info->azb_size >> SECTOR_SHIFT); + loff_t blocks; + + if (unlikely((loff_t)size != size)) + return -EFBIG; + if (unlikely(info->azb_blocksize == 0)) + return -EINVAL; + + blocks = info->azb_size / info->azb_blocksize; + if (unlikely(info->azb_blocksize * blocks != info->azb_size)) + return -EINVAL; + + set_disk_ro(azb->azb_disk, 0); + + set_capacity(azb->azb_disk, size); + azb->azb_size = info->azb_size; + + blk_queue_logical_block_size(azb->azb_queue, info->azb_blocksize); + blk_queue_physical_block_size(azb->azb_queue, info->azb_blocksize); + azb->azb_blocksize = info->azb_blocksize; + + __module_get(THIS_MODULE); + + return 0; +} + +static int azbuse_set_status(struct azbuse_device *azb, const struct azbuse_info __user *arg) +{ + struct azbuse_info info; + if (copy_from_user(&info, arg, sizeof (struct azbuse_info))) + return -EFAULT; + return __azbuse_set_status(azb, &info); +} + +static unsigned xfr_command_from_cmd_flags(unsigned cmd_flags) { + unsigned int ret = 0; + switch (cmd_flags & REQ_OP_BITS) { + case REQ_OP_READ: + ret = CMD_OP_READ; + break; + case REQ_OP_WRITE: + ret = CMD_OP_WRITE; + break; + case REQ_OP_FLUSH: + ret = CMD_OP_FLUSH; + break; + case REQ_OP_DISCARD: + ret = CMD_OP_DISCARD; + break; + case REQ_OP_SECURE_ERASE: + ret = CMD_OP_SECURE_ERASE; + break; + case REQ_OP_WRITE_ZEROES: + ret = CMD_OP_WRITE_ZEROES; + break; + default: + ret = CMD_OP_UNKNOWN; + break; + } + if (cmd_flags & REQ_FUA) { + ret |= CMD_FUA; + } + if (cmd_flags & REQ_PREFLUSH) { + ret |= CMD_PREFLUSH; + } + if (cmd_flags & REQ_NOUNMAP) { + ret |= CMD_NOUNMAP; + } + if (cmd_flags & REQ_NOWAIT) { + ret |= CMD_NOWAIT; + } + if (cmd_flags & REQ_RAHEAD) { + ret |= CMD_RAHEAD; + } + return ret; +} + +static int azbuse_get_req(struct azbuse_device *azb, struct azbuse_xfr_hdr __user *arg) +{ + struct azbuse_xfr_hdr xfr; + struct azb_req *req = NULL; + + if (!arg) + return -EINVAL; + if (!azb) + return -ENODEV; + + if (copy_from_user(&xfr, arg, sizeof (struct azbuse_xfr_hdr))) + return -EFAULT; + + spin_lock_irq(&azb->azb_lock); + req = list_first_entry_or_null(&azb->azb_reqlist, struct azb_req, list); + if (req) { + struct req_iterator iter; + struct bio_vec bvec; + int i = 0; + + list_del(&req->list); + spin_unlock_irq(&azb->azb_lock); + + // Use the pointer address as the unique id of the request + xfr.azb_id = (__u64)req; + xfr.azb_command = xfr_command_from_cmd_flags(req->rq->cmd_flags); + xfr.azb_offset = blk_rq_pos(req->rq) << SECTOR_SHIFT; + xfr.azb_len = blk_rq_bytes(req->rq); + rq_for_each_bvec(bvec, req->rq, iter) { + // physical address of the page + azb->azb_xfer[i].azb_address = (__u64)page_to_phys(bvec.bv_page); + azb->azb_xfer[i].n_pages = ((bvec.bv_offset + bvec.bv_len) + (4096-1)) / 4096; + azb->azb_xfer[i].azb_offset = bvec.bv_offset; + azb->azb_xfer[i].azb_len = bvec.bv_len; + i++; + } + xfr.azb_vec_count = i; + azb->azb_xfer_count = i; + } else { + spin_unlock_irq(&azb->azb_lock); + return -ENOMSG; + } + + if (copy_to_user(arg, &xfr, sizeof(xfr))) + return -EFAULT; + BUG_ON(xfr.azb_transfer_address == 0); + if (copy_to_user((__user void *) xfr.azb_transfer_address, azb->azb_xfer, xfr.azb_vec_count * sizeof(azb->azb_xfer[0]))) + return -EFAULT; + + return 0; +} + +static struct azb_req *azbuse_find_req(struct azbuse_device *azb, __u64 id) +{ + struct azb_req *req = id; + return req; +} + +// Complete a request +static int azbuse_put_req(struct azbuse_device *azb, struct azbuse_completion __user *arg) +{ + struct azbuse_completion xfr; + struct azb_req *req = NULL; + + if (!arg) + return -EINVAL; + if (!azb) + return -ENODEV; + + if (copy_from_user(&xfr, arg, sizeof (struct azbuse_completion))) + return -EFAULT; + + req = azbuse_find_req(azb, xfr.azb_id); + blk_mq_end_request(req->rq, errno_to_blk_status(xfr.azb_errno)); + return 0; +} + +static int azbuse_connect(struct file *ctl, unsigned long arg) +{ + struct file *dev; + struct azbuse_device *azb; + + if (ctl->private_data) + return -EBUSY; + + dev = fget(arg); + if (!dev) + return -EBADF; + + azb = idr_find(&azbuse_index_idr, iminor(dev->f_inode)); + fput(dev); + + if (!azb) + return -ENODEV; + + ctl->private_data = azb; + + return 0; +} + +static int azbusectl_open(struct inode *nodp, struct file *filp) +{ + filp->private_data = NULL; + return 0; +} + +static int azbusectl_release(struct inode *inode, struct file *filp) +{ + struct azbuse_device *azb = filp->private_data; + if (!azb) { + return -ENODEV; + } + + filp->private_data = NULL; + return 0; +} + +static unsigned int azbusectl_poll(struct file *filp, poll_table *wait) +{ + struct azbuse_device *azb = filp->private_data; + unsigned int mask; + + if (azb == NULL) + return -ENODEV; + + poll_wait(filp, &azb->azb_event, wait); + mask = (list_empty(&azb->azb_reqlist)) ? 0 : POLLIN; + return mask; +} + +static int azbusectl_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct azbuse_device *azb = filp->private_data; + int i; + int n = azb->azb_xfer_count; + int err = 0; + unsigned long cur = vma->vm_start; + for (i=0; iazb_xfer[i].azb_address >> PAGE_SHIFT; + unsigned long len = azb->azb_xfer[i].n_pages << PAGE_SHIFT; + err |= remap_pfn_range(vma, cur, pfn, len, vma->vm_page_prot); + cur += len; + } + return err; +} + +static struct block_device_operations azb_fops = { + .owner = THIS_MODULE, +}; + +static int azbuse_init_request(struct blk_mq_tag_set *set, struct request *rq, + unsigned int hctx_idx, unsigned int numa_node) +{ + struct azb_req *req = blk_mq_rq_to_pdu(rq); + + INIT_LIST_HEAD(&req->list); + req->rq = rq; + return 0; +} + +static blk_status_t azbuse_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) +{ + struct azb_req *req = blk_mq_rq_to_pdu(bd->rq); + struct azbuse_device *azb = req->rq->q->queuedata; + + blk_mq_start_request(bd->rq); + + spin_lock_irq(&azb->azb_lock); + list_add_tail(&req->list, &azb->azb_reqlist); + spin_unlock_irq(&azb->azb_lock); + + wake_up(&azb->azb_event); + return BLK_STS_OK; +} + +static struct blk_mq_ops azbuse_mq_ops = { + .init_request = azbuse_init_request, + .queue_rq = azbuse_queue_rq, +}; + +// FIXME: error propagation +static struct azbuse_device *azbuse_add(int i) +{ + struct azbuse_device *azb; + struct gendisk *disk; + int err; + + azb = kzalloc(sizeof(*azb), GFP_KERNEL); + if (!azb) + goto out; + + if (i >= 0) { + err = idr_alloc(&azbuse_index_idr, azb, i, i + 1, GFP_KERNEL); + if (err == -ENOSPC) + err = -EEXIST; + } else { + err = idr_alloc(&azbuse_index_idr, azb, 0, 0, GFP_KERNEL); + } + if (err < 0) + goto out_free_dev; + i = err; + + azb->tag_set.ops = &azbuse_mq_ops; + azb->tag_set.nr_hw_queues = 1; + azb->tag_set.queue_depth = 128; + azb->tag_set.numa_node = NUMA_NO_NODE; + azb->tag_set.cmd_size = sizeof(struct azb_req); + azb->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; + azb->tag_set.driver_data = azb; + + err = blk_mq_alloc_tag_set(&azb->tag_set); + if (err) + goto out_free_idr; + + disk = blk_mq_alloc_disk(&azb->tag_set, azb); + if (!disk) + goto out_cleanup_tags; + azb->azb_queue = disk->queue; + azb->azb_queue->queuedata = azb; + blk_queue_flag_set(QUEUE_FLAG_NONROT, azb->azb_queue); + + disk->major = AZBUSE_MAJOR; + disk->first_minor = i; + disk->minors = 1; + disk->fops = &azb_fops; + disk->private_data = azb; + sprintf(disk->disk_name, "azbuse%d", i); + + err = add_disk(disk); + if (err) + goto out_cleanup_disk; + + azb->azb_disk = disk; + azb->azb_number = i; + init_waitqueue_head(&azb->azb_event); + spin_lock_init(&azb->azb_lock); + INIT_LIST_HEAD(&azb->azb_reqlist); + + return azb; + +out_cleanup_disk: + del_gendisk(azb->azb_disk); + put_disk(disk); +out_cleanup_tags: + blk_mq_free_tag_set(&azb->tag_set); +out_free_idr: + idr_remove(&azbuse_index_idr, i); +out_free_dev: + kfree(azb); +out: + return NULL; +} + +static void azbuse_remove(struct azbuse_device *azb) +{ + del_gendisk(azb->azb_disk); + put_disk(azb->azb_disk); + blk_mq_free_tag_set(&azb->tag_set); + idr_remove(&azbuse_index_idr, azb->azb_number); + kfree(azb); +} + +static long azbusectl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct azbuse_device *azb = filp->private_data; + struct azbuse_device *remove; + int err; + + switch (cmd) { + case AZBUSE_GET_REQ: + err = azbuse_get_req(azb, (struct azbuse_xfr_hdr __user *) arg); + break; + case AZBUSE_PUT_REQ: + err = azbuse_put_req(azb, (struct azbuse_completion __user *) arg); + break; + case AZBUSE_GET_STATUS: + mutex_lock(&azbuse_ctl_mutex); + err = azbuse_get_status(azb, (struct azbuse_info __user *) arg); + mutex_unlock(&azbuse_ctl_mutex); + break; + case AZBUSE_SET_STATUS: + mutex_lock(&azbuse_ctl_mutex); + err = azbuse_set_status(azb, (struct azbuse_info __user *) arg); + mutex_unlock(&azbuse_ctl_mutex); + break; + case AZBUSE_RESET: + mutex_lock(&azbuse_ctl_mutex); + err = azbuse_reset(azb); + mutex_unlock(&azbuse_ctl_mutex); + break; + case AZBUSE_CTL_ADD: + mutex_lock(&azbuse_ctl_mutex); + azbuse_add(arg); + mutex_unlock(&azbuse_ctl_mutex); + break; + case AZBUSE_CTL_REMOVE: + mutex_lock(&azbuse_ctl_mutex); + remove = idr_find(&azbuse_index_idr, arg); + if (remove == NULL) { + err = -ENOENT; + } else { + err = remove->azb_number; + azbuse_remove(remove); + } + mutex_unlock(&azbuse_ctl_mutex); + break; + case AZBUSE_CONNECT: + mutex_lock(&azbuse_ctl_mutex); + err = azbuse_connect(filp, arg); + mutex_unlock(&azbuse_ctl_mutex); + break; + default: + err = -EINVAL; + } + + return err; +} + +static struct file_operations azbusectl_fops = { + .owner = THIS_MODULE, + .open = azbusectl_open, + .release = azbusectl_release, + .unlocked_ioctl = azbusectl_ioctl, + .poll = azbusectl_poll, + .mmap = azbusectl_mmap, +}; + +static struct miscdevice azbuse_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = "azbusectl", + .fops = &azbusectl_fops, +}; + +static int __init azbuse_init(void) +{ + int err; + + err = misc_register(&azbuse_misc); + if (err < 0) + return err; + + err = -EIO; + if (register_blkdev(AZBUSE_MAJOR, "azbuse")) { + printk("azbuse: register_blkdev failed!\n"); + goto unregister_misc; + } + + printk(KERN_INFO "azbuse: module loaded\n"); + return 0; + +unregister_misc: + misc_deregister(&azbuse_misc); + + return err; +} + +static int azbuse_exit_cb(int id, void *ptr, void *data) +{ + struct azbuse_device *azb = ptr; + azbuse_remove(azb); + return 0; +} + +static void __exit azbuse_exit(void) +{ + idr_for_each(&azbuse_index_idr, azbuse_exit_cb, NULL); + idr_destroy(&azbuse_index_idr); + + unregister_blkdev(AZBUSE_MAJOR, "azbuse"); + misc_deregister(&azbuse_misc); +} + +module_init(azbuse_init); +module_exit(azbuse_exit); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("devname:azbusectl"); +MODULE_ALIAS_BLOCKDEV_MAJOR(AZBUSE_MAJOR); \ No newline at end of file diff --git a/azbuse-kmod/src/azbuse.h b/azbuse-kmod/src/azbuse.h new file mode 100644 index 0000000..3492bd3 --- /dev/null +++ b/azbuse-kmod/src/azbuse.h @@ -0,0 +1,98 @@ +/* + * include/linux/abuse.h + * + * Copyright (c) 2009 Zachary Amsden + * Copyright (c) 2015 Naohiro Aota + * Copyright (c) 2021 Akira Hayakawa + * + * Redistribution of this file is permitted under the GNU General Public License. + */ + +#ifndef _LINUX_AZBUSE_H +#define _LINUX_AZBUSE_H + +#include +#include +#include +#include +#include +#include /* for __u64 */ + +struct azbuse_info { + __u32 azb_number; /* r/o */ + __u64 azb_size; /* r/w */ + __u32 azb_blocksize; /* r/w */ +}; + +#define AZBUSE_GET_STATUS 0x4120 +#define AZBUSE_SET_STATUS 0x4121 +#define AZBUSE_RESET 0x4122 +#define AZBUSE_GET_REQ 0x4123 +#define AZBUSE_PUT_REQ 0x4124 + +#define AZBUSE_CTL_ADD 0x4186 +#define AZBUSE_CTL_REMOVE 0x4187 +#define AZBUSE_CONNECT 0x4188 + +struct azbuse_vec { + __u64 azb_address; + __u32 n_pages; + __u32 azb_offset; + __u32 azb_len; +}; + +#define CMD_OP_UNKNOWN 0 +#define CMD_OP_READ 1 +#define CMD_OP_WRITE 2 +#define CMD_OP_FLUSH 3 +#define CMD_OP_DISCARD 4 +#define CMD_OP_SECURE_ERASE 5 +#define CMD_OP_WRITE_ZEROES 6 + +#define CMD_FUA 1<<8 +#define CMD_PREFLUSH 1<<9 +#define CMD_NOUNMAP 1<<10 +#define CMD_NOWAIT 1<<11 +#define CMD_RAHEAD 1<<12 + +struct azbuse_xfr_hdr { + __u64 azb_id; + __u64 azb_offset; + __u64 azb_len; + __u32 azb_command; + __u32 azb_vec_count; + __u64 azb_transfer_address; +}; + +struct azbuse_completion { + __u64 azb_id; + __u32 azb_errno; +}; + +#define AZBUSE_MAJOR 60 +#define AZBUSECTL_MAJOR 61 + +struct azbuse_device { + int azb_number; + loff_t azb_size; + unsigned azb_blocksize; + + spinlock_t azb_lock; + struct list_head azb_reqlist; + wait_queue_head_t azb_event; + + struct request_queue *azb_queue; + struct blk_mq_tag_set tag_set; + struct gendisk *azb_disk; + + /* user xfer area */ + int azb_xfer_count; + struct azbuse_vec azb_xfer[BIO_MAX_VECS]; +}; + +struct azb_req { + struct request *rq; + struct list_head list; +}; + +#endif \ No newline at end of file diff --git a/abuse-kmod/src/dkms.conf b/azbuse-kmod/src/dkms.conf similarity index 77% rename from abuse-kmod/src/dkms.conf rename to azbuse-kmod/src/dkms.conf index 2e005f9..1cd5f91 100644 --- a/abuse-kmod/src/dkms.conf +++ b/azbuse-kmod/src/dkms.conf @@ -1,6 +1,6 @@ -PACKAGE_NAME="abuse" +PACKAGE_NAME="azbuse" PACKAGE_VERSION="1.0.0" -BUILT_MODULE_NAME="abuse" +BUILT_MODULE_NAME="azbuse" DEST_MODULE_LOCATION="/kernel/drivers/block" MAKE="make all KERNEL_TREE=$kernel_source_dir" CLEAN="make clean" diff --git a/abuse/Cargo.toml b/azbuse/Cargo.toml similarity index 96% rename from abuse/Cargo.toml rename to azbuse/Cargo.toml index 30d9484..b81690b 100644 --- a/abuse/Cargo.toml +++ b/azbuse/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "abuse" +name = "azbuse" version = "0.1.0" authors = ["Akira Hayakawa "] edition = "2018" diff --git a/abuse/src/lib.rs b/azbuse/src/lib.rs similarity index 77% rename from abuse/src/lib.rs rename to azbuse/src/lib.rs index c4f07e7..d39fb13 100644 --- a/abuse/src/lib.rs +++ b/azbuse/src/lib.rs @@ -30,7 +30,7 @@ bitflags! { #[repr(C)] #[derive(Default, Debug)] -pub struct AbuseInfo { +pub struct AzbuseInfo { number: u32, size: u64, blocksize: u32, @@ -38,7 +38,7 @@ pub struct AbuseInfo { #[repr(C)] #[derive(Default)] -pub struct AbuseXfr { +pub struct AzbuseXfr { id: u64, offset: u64, len: u64, @@ -49,7 +49,7 @@ pub struct AbuseXfr { #[repr(C)] #[derive(Default, Clone, Copy)] -struct AbuseXfrIoVec { +struct AzbuseXfrIoVec { address: u64, n_pages: u32, offset: u32, @@ -58,24 +58,24 @@ struct AbuseXfrIoVec { #[repr(C)] #[derive(Default)] -pub struct AbuseCompletion { +pub struct AzbuseCompletion { id: u64, result: i32, } -const ABUSE_GET_STATUS: u16 = 0x4120; -const ABUSE_SET_STATUS: u16 = 0x4121; -const ABUSE_RESET: u16 = 0x4122; -const ABUSE_GET_REQ: u16 = 0x4123; -const ABUSE_PUT_REQ: u16 = 0x4124; -const ABUSE_CONNECT: u16 = 0x4188; +const AZBUSE_GET_STATUS: u16 = 0x4120; +const AZBUSE_SET_STATUS: u16 = 0x4121; +const AZBUSE_RESET: u16 = 0x4122; +const AZBUSE_GET_REQ: u16 = 0x4123; +const AZBUSE_PUT_REQ: u16 = 0x4124; +const AZBUSE_CONNECT: u16 = 0x4188; -nix::ioctl_read_bad!(abuse_get_status, ABUSE_GET_STATUS, AbuseInfo); -nix::ioctl_write_ptr_bad!(abuse_set_status, ABUSE_SET_STATUS, AbuseInfo); -nix::ioctl_none_bad!(abuse_reset, ABUSE_RESET); -nix::ioctl_read_bad!(abuse_get_req, ABUSE_GET_REQ, AbuseXfr); -nix::ioctl_write_ptr_bad!(abuse_put_req, ABUSE_PUT_REQ, AbuseCompletion); -nix::ioctl_write_int_bad!(abuse_connect, ABUSE_CONNECT); +nix::ioctl_read_bad!(azbuse_get_status, AZBUSE_GET_STATUS, AzbuseInfo); +nix::ioctl_write_ptr_bad!(azbuse_set_status, AZBUSE_SET_STATUS, AzbuseInfo); +nix::ioctl_none_bad!(azbuse_reset, AZBUSE_RESET); +nix::ioctl_read_bad!(azbuse_get_req, AZBUSE_GET_REQ, AzbuseXfr); +nix::ioctl_write_ptr_bad!(azbuse_put_req, AZBUSE_PUT_REQ, AzbuseCompletion); +nix::ioctl_write_int_bad!(azbuse_connect, AZBUSE_CONNECT); pub struct IOVec { page_address: usize, @@ -125,11 +125,11 @@ impl RequestHandler { async fn run_once(&mut self, req: Request) { let req_id = req.request_id; let res = self.engine.call(req).await; - let cmplt = AbuseCompletion { + let cmplt = AzbuseCompletion { id: req_id, result: res.errorno, }; - unsafe { abuse_put_req(self.fd, &cmplt) }.expect("failed to put req"); + unsafe { azbuse_put_req(self.fd, &cmplt) }.expect("failed to put req"); } async fn run(mut self) { while let Some(req) = self.rx.recv().await { @@ -149,22 +149,22 @@ pub async fn run_on(config: Config, engine: impl StorageEngine) { use nix::fcntl::{open, OFlag}; use nix::sys::stat::Mode; - let fd = open("/dev/abctl", OFlag::O_RDWR, Mode::empty()).expect("couldn't open /dev/abctl"); + let fd = open("/dev/azbusectl", OFlag::O_RDWR, Mode::empty()).expect("couldn't open /dev/azbusectl"); let devfd = { - let devpath = format!("/dev/abuse{}", config.dev_number); + let devpath = format!("/dev/azbuse{}", config.dev_number); open(devpath.as_str(), OFlag::empty(), Mode::empty()).expect("couldn't open device") }; - // This attaches struct ab_device to ctlfd->private_data - unsafe { abuse_connect(fd, devfd) }.expect("couldn't acquire abuse device"); - let mut info = AbuseInfo::default(); - unsafe { abuse_get_status(fd, &mut info) }.expect("couldn't get info"); + // This attaches struct azb_device to ctlfd->private_data + unsafe { azbuse_connect(fd, devfd) }.expect("couldn't acquire azbuse device"); + let mut info = AzbuseInfo::default(); + unsafe { azbuse_get_status(fd, &mut info) }.expect("couldn't get info"); dbg!(&info); - unsafe { abuse_reset(fd) }.expect("couldn't reset device"); + unsafe { azbuse_reset(fd) }.expect("couldn't reset device"); // size must be some multiple of blocksize info.size = config.dev_size; info.blocksize = 4096; - unsafe { abuse_set_status(fd, &info) }.expect("couldn't set info"); + unsafe { azbuse_set_status(fd, &info) }.expect("couldn't set info"); let mut poll = Poll::new().unwrap(); let mut source = SourceFd(&fd); @@ -173,12 +173,12 @@ pub async fn run_on(config: Config, engine: impl StorageEngine) { .expect("failed to set up poll"); let mut events = Events::with_capacity(1); - let iovec = [AbuseXfrIoVec::default(); BIO_MAX_VECS]; + let iovec = [AzbuseXfrIoVec::default(); BIO_MAX_VECS]; let io_vec_address: u64 = - unsafe { std::mem::transmute::<*const AbuseXfrIoVec, u64>(iovec.as_ptr()) }; - let mut xfr = AbuseXfr { + unsafe { std::mem::transmute::<*const AzbuseXfrIoVec, u64>(iovec.as_ptr()) }; + let mut xfr = AzbuseXfr { io_vec_address, - ..AbuseXfr::default() + ..AzbuseXfr::default() }; let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); @@ -195,14 +195,14 @@ pub async fn run_on(config: Config, engine: impl StorageEngine) { poll.poll(&mut events, None).expect("failed to poll"); 'poll: for ev in &events { loop { - if let Err(e) = unsafe { abuse_get_req(fd, &mut xfr) } { + if let Err(e) = unsafe { azbuse_get_req(fd, &mut xfr) } { break 'poll; } let n = xfr.io_vec_count as usize; let xfr_io_vec = { let out = unsafe { - std::mem::transmute::(xfr.io_vec_address) + std::mem::transmute::(xfr.io_vec_address) }; let out = unsafe { std::slice::from_raw_parts(out, n) }; out diff --git a/abusectl/Cargo.toml b/azbusectl/Cargo.toml similarity index 93% rename from abusectl/Cargo.toml rename to azbusectl/Cargo.toml index bea0e5a..d278c99 100644 --- a/abusectl/Cargo.toml +++ b/azbusectl/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "abusectl" +name = "azbusectl" version = "0.1.0" authors = ["Akira Hayakawa "] edition = "2018" diff --git a/azbusectl/src/main.rs b/azbusectl/src/main.rs new file mode 100644 index 0000000..36a0c29 --- /dev/null +++ b/azbusectl/src/main.rs @@ -0,0 +1,30 @@ +use clap::Parser; + +#[derive(Parser)] +enum Opts { + Add { idx: u16 }, + Remove { idx: u16 }, +} + +const AZBUSE_CTL_ADD: u16 = 0x4186; +const AZBUSE_CTL_REMOVE: u16 = 0x4187; + +nix::ioctl_write_int_bad!(azbuse_add_device, AZBUSE_CTL_ADD); +nix::ioctl_write_int_bad!(azbuse_remove_device, AZBUSE_CTL_REMOVE); + +fn main() { + use nix::fcntl::{open, OFlag}; + use nix::sys::stat::Mode; + + let opts = Opts::parse(); + + let fd = open("/dev/azbusectl", OFlag::empty(), Mode::empty()).expect("couldn't open /dev/azbusectl"); + match opts { + Opts::Add { idx } => unsafe { + azbuse_add_device(fd, idx as i32).unwrap(); + }, + Opts::Remove { idx } => unsafe { + azbuse_remove_device(fd, idx as i32).unwrap(); + }, + } +} diff --git a/tests/abuse-ramdisk/README.md b/tests/abuse-ramdisk/README.md deleted file mode 100644 index ae326ec..0000000 --- a/tests/abuse-ramdisk/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Usage - -## Module -``` -# cd abuse-kmod -# make install -# modprobe abuse -``` - -## Attach - -This will attach ramdisk to /dev/abuse0 - -``` -# ./abuse-ramdisk.bin 0 -``` \ No newline at end of file diff --git a/tests/abuse-ramdisk/Cargo.toml b/tests/ramdisk/Cargo.toml similarity index 89% rename from tests/abuse-ramdisk/Cargo.toml rename to tests/ramdisk/Cargo.toml index 76dfa11..7c21ebe 100644 --- a/tests/abuse-ramdisk/Cargo.toml +++ b/tests/ramdisk/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "abuse-ramdisk" +name = "ramdisk" version = "0.1.0" authors = ["Akira Hayakawa "] edition = "2018" @@ -16,4 +16,4 @@ bitflags = { workspace = true } tokio = { version = "1", features = ["rt-multi-thread", "macros"]} libc = "0.2" -abuse = { path = "../../abuse" } \ No newline at end of file +azbuse = { path = "../../azbuse" } \ No newline at end of file diff --git a/tests/abuse-ramdisk/src/main.rs b/tests/ramdisk/src/main.rs similarity index 94% rename from tests/abuse-ramdisk/src/main.rs rename to tests/ramdisk/src/main.rs index 38591e0..9b39313 100644 --- a/tests/abuse-ramdisk/src/main.rs +++ b/tests/ramdisk/src/main.rs @@ -1,4 +1,4 @@ -use abuse::{CmdFlags, IOVec, Request, Response, StorageEngine}; +use azbuse::{CmdFlags, IOVec, Request, Response, StorageEngine}; use async_trait::async_trait; use clap::Parser; use core::ffi::c_void; @@ -12,14 +12,14 @@ async fn main() { let opts = Opts::parse(); let dev_number = opts.dev_number; let sz = 1500 << 20; // 1500MB - let config = abuse::Config { + let config = azbuse::Config { dev_number, dev_size: sz as u64, }; let engine = Engine { mem: MemBuffer::new(sz), }; - abuse::run_on(config, engine).await; + azbuse::run_on(config, engine).await; } struct Engine {