From 60ee9e08b0635692929808d26f2f40a719a18192 Mon Sep 17 00:00:00 2001 From: Mara Date: Fri, 15 Apr 2022 09:14:23 +0300 Subject: [PATCH 1/4] lab07: Add solution for ex01 Signed-off-by: Mara-Ioana Nicolae --- .../1-2-3-6-ram-disk/kernel/Kbuild | 3 + .../1-2-3-6-ram-disk/kernel/ram-disk.c | 219 ++++++++++++++++++ .../1-2-3-6-ram-disk/user/.gitignore | 1 + .../1-2-3-6-ram-disk/user/Makefile | 8 + .../1-2-3-6-ram-disk/user/ram-disk-test.c | 89 +++++++ .../4-5-relay-disk/Kbuild | 3 + .../4-5-relay-disk/relay-disk.c | 85 +++++++ .../4-5-relay-disk/test-relay-disk | 20 ++ 8 files changed, 428 insertions(+) create mode 100644 tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/Kbuild create mode 100644 tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c create mode 100644 tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/.gitignore create mode 100644 tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/Makefile create mode 100644 tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/ram-disk-test.c create mode 100644 tools/labs/skels/block_device_drivers/4-5-relay-disk/Kbuild create mode 100644 tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c create mode 100644 tools/labs/skels/block_device_drivers/4-5-relay-disk/test-relay-disk diff --git a/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/Kbuild b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/Kbuild new file mode 100644 index 00000000000000..4f1b616bf92028 --- /dev/null +++ b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/Kbuild @@ -0,0 +1,3 @@ +EXTRA_CFLAGS = -Wall -g -Wno-unused + +obj-m = ram-disk.o diff --git a/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c new file mode 100644 index 00000000000000..56ca2f922c411a --- /dev/null +++ b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c @@ -0,0 +1,219 @@ +/* + * SO2 - Block device drivers lab (#7) + * Linux - Exercise #1, #2, #3, #6 (RAM Disk) + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("Simple RAM Disk"); +MODULE_AUTHOR("SO2"); +MODULE_LICENSE("GPL"); + + +#define KERN_LOG_LEVEL KERN_ALERT + +#define MY_BLOCK_MAJOR 7 +#define MY_BLKDEV_NAME "mybdev" +#define MY_BLOCK_MINORS 1 +#define NR_SECTORS 128 + +#define KERNEL_SECTOR_SIZE 512 + +/* TODO 6: use bios for read/write requests */ +#define USE_BIO_TRANSFER 0 + + +static struct my_block_dev { + struct blk_mq_tag_set tag_set; + struct request_queue *queue; + struct gendisk *gd; + u8 *data; + size_t size; +} g_dev; + +static int my_block_open(struct block_device *bdev, fmode_t mode) +{ + return 0; +} + +static void my_block_release(struct gendisk *gd, fmode_t mode) +{ +} + +static const struct block_device_operations my_block_ops = { + .owner = THIS_MODULE, + .open = my_block_open, + .release = my_block_release +}; + +static void my_block_transfer(struct my_block_dev *dev, sector_t sector, + unsigned long len, char *buffer, int dir) +{ + unsigned long offset = sector * KERNEL_SECTOR_SIZE; + + /* check for read/write beyond end of block device */ + if ((offset + len) > dev->size) + return; + + /* TODO 3: read/write to dev buffer depending on dir */ +} + +/* to transfer data using bio structures enable USE_BIO_TRANFER */ +#if USE_BIO_TRANSFER == 1 +static void my_xfer_request(struct my_block_dev *dev, struct request *req) +{ + /* TODO 6: iterate segments */ + + /* TODO 6: copy bio data to device buffer */ +} +#endif + +static blk_status_t my_block_request(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) +{ + struct request *rq; + struct my_block_dev *dev = hctx->queue->queuedata; + + /* TODO 2: get pointer to request */ + + /* TODO 2: start request processing. */ + + /* TODO 2: check fs request. Return if passthrough. */ + + /* TODO 2: print request information */ + +#if USE_BIO_TRANSFER == 1 + /* TODO 6: process the request by calling my_xfer_request */ +#else + /* TODO 3: process the request by calling my_block_transfer */ +#endif + + /* TODO 2: end request successfully */ + +out: + return BLK_STS_OK; +} + +static struct blk_mq_ops my_queue_ops = { + .queue_rq = my_block_request, +}; + +static int create_block_device(struct my_block_dev *dev) +{ + int err; + + dev->size = NR_SECTORS * KERNEL_SECTOR_SIZE; + dev->data = vmalloc(dev->size); + if (dev->data == NULL) { + printk(KERN_ERR "vmalloc: out of memory\n"); + err = -ENOMEM; + goto out_vmalloc; + } + + /* Initialize tag set. */ + dev->tag_set.ops = &my_queue_ops; + dev->tag_set.nr_hw_queues = 1; + dev->tag_set.queue_depth = 128; + dev->tag_set.numa_node = NUMA_NO_NODE; + dev->tag_set.cmd_size = 0; + dev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; + err = blk_mq_alloc_tag_set(&dev->tag_set); + if (err) { + printk(KERN_ERR "blk_mq_alloc_tag_set: can't allocate tag set\n"); + goto out_alloc_tag_set; + } + + /* Allocate queue. */ + dev->queue = blk_mq_init_queue(&dev->tag_set); + if (IS_ERR(dev->queue)) { + printk(KERN_ERR "blk_mq_init_queue: out of memory\n"); + err = -ENOMEM; + goto out_blk_init; + } + blk_queue_logical_block_size(dev->queue, KERNEL_SECTOR_SIZE); + dev->queue->queuedata = dev; + + /* initialize the gendisk structure */ + dev->gd = alloc_disk(MY_BLOCK_MINORS); + if (!dev->gd) { + printk(KERN_ERR "alloc_disk: failure\n"); + err = -ENOMEM; + goto out_alloc_disk; + } + + dev->gd->major = MY_BLOCK_MAJOR; + dev->gd->first_minor = 0; + dev->gd->fops = &my_block_ops; + dev->gd->queue = dev->queue; + dev->gd->private_data = dev; + snprintf(dev->gd->disk_name, DISK_NAME_LEN, "myblock"); + set_capacity(dev->gd, NR_SECTORS); + + add_disk(dev->gd); + + return 0; + +out_alloc_disk: + blk_cleanup_queue(dev->queue); +out_blk_init: + blk_mq_free_tag_set(&dev->tag_set); +out_alloc_tag_set: + vfree(dev->data); +out_vmalloc: + return err; +} + +static int __init my_block_init(void) +{ + int err = 0; + + /* TODO 1: register block device */ + err = register_blkdev(MY_BLOCK_MAJOR, MY_BLKDEV_NAME); + if (err < 0) { + pr_err("unable to register mybdev block device\n"); + return -EBUSY; + } + /* TODO 2: create block device using create_block_device */ + + return 0; + +out: + /* TODO 2: unregister block device in case of an error */ + return err; +} + +static void delete_block_device(struct my_block_dev *dev) +{ + if (dev->gd) { + del_gendisk(dev->gd); + put_disk(dev->gd); + } + + if (dev->queue) + blk_cleanup_queue(dev->queue); + if (dev->tag_set.tags) + blk_mq_free_tag_set(&dev->tag_set); + if (dev->data) + vfree(dev->data); +} + +static void __exit my_block_exit(void) +{ + /* TODO 2: cleanup block device using delete_block_device */ + unregister_blkdev(MY_BLOCK_MAJOR, MY_BLKDEV_NAME); + /* TODO 1: unregister block device */ +} + +module_init(my_block_init); +module_exit(my_block_exit); diff --git a/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/.gitignore b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/.gitignore new file mode 100644 index 00000000000000..1330ce0fdf63c7 --- /dev/null +++ b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/.gitignore @@ -0,0 +1 @@ +/ram-disk-test diff --git a/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/Makefile b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/Makefile new file mode 100644 index 00000000000000..a653ce1e2faf79 --- /dev/null +++ b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/Makefile @@ -0,0 +1,8 @@ +CFLAGS = -Wall -g -m32 -static + +all: ram-disk-test + +.PHONY: clean + +clean: + -rm -f *~ *.o ram-disk-test diff --git a/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/ram-disk-test.c b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/ram-disk-test.c new file mode 100644 index 00000000000000..a6d2b3a3214b8f --- /dev/null +++ b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/user/ram-disk-test.c @@ -0,0 +1,89 @@ +/* + * SO2 - Block device driver (#8) + * Test suite for exercise #3 (RAM Disk) + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NR_SECTORS 128 +#define SECTOR_SIZE 512 + +#define DEVICE_NAME "/dev/myblock" +#define MODULE_NAME "ram-disk" +#define MY_BLOCK_MAJOR "240" +#define MY_BLOCK_MINOR "0" + + +#define max_elem_value(elem) \ + (1 << 8*sizeof(elem)) + +static unsigned char buffer[SECTOR_SIZE]; +static unsigned char buffer_copy[SECTOR_SIZE]; + +static void test_sector(int fd, size_t sector) +{ + int i; + + for (i = 0; i < sizeof(buffer) / sizeof(buffer[0]); i++) + buffer[i] = rand() % max_elem_value(buffer[0]); + + lseek(fd, sector * SECTOR_SIZE, SEEK_SET); + write(fd, buffer, sizeof(buffer)); + + fsync(fd); + + lseek(fd, sector * SECTOR_SIZE, SEEK_SET); + read(fd, buffer_copy, sizeof(buffer_copy)); + + printf("test sector %3d ... ", sector); + if (memcmp(buffer, buffer_copy, sizeof(buffer_copy)) == 0) + printf("passed\n"); + else + printf("failed\n"); +} + +int main(void) +{ + int fd; + size_t i; + int back_errno; + + printf("insmod ../kernel/" MODULE_NAME ".ko\n"); + if (system("insmod ../kernel/" MODULE_NAME ".ko\n")) { + fprintf(stderr, "insmod failed\n"); + exit(EXIT_FAILURE); + } + + sleep(1); + + printf("mknod " DEVICE_NAME " b " MY_BLOCK_MAJOR " " MY_BLOCK_MINOR "\n"); + system("mknod " DEVICE_NAME " b " MY_BLOCK_MAJOR " " MY_BLOCK_MINOR "\n"); + sleep(1); + + fd = open(DEVICE_NAME, O_RDWR); + if (fd < 0) { + back_errno = errno; + perror("open"); + fprintf(stderr, "errno is %d\n", back_errno); + exit(EXIT_FAILURE); + } + + srand(time(NULL)); + for (i = 0; i < NR_SECTORS; i++) + test_sector(fd, i); + + close(fd); + + sleep(1); + printf("rmmod " MODULE_NAME "\n"); + system("rmmod " MODULE_NAME "\n"); + + return 0; +} diff --git a/tools/labs/skels/block_device_drivers/4-5-relay-disk/Kbuild b/tools/labs/skels/block_device_drivers/4-5-relay-disk/Kbuild new file mode 100644 index 00000000000000..222ee815adcb9e --- /dev/null +++ b/tools/labs/skels/block_device_drivers/4-5-relay-disk/Kbuild @@ -0,0 +1,3 @@ +EXTRA_CFLAGS = -Wall -g -Wno-unused + +obj-m = relay-disk.o diff --git a/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c b/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c new file mode 100644 index 00000000000000..44178bfdcdc530 --- /dev/null +++ b/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c @@ -0,0 +1,85 @@ +/* + * SO2 Lab - Block device drivers (#7) + * Linux - Exercise #4, #5 (Relay disk - bio) + */ + +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("SO2"); +MODULE_DESCRIPTION("Relay disk"); +MODULE_LICENSE("GPL"); + +#define KERN_LOG_LEVEL KERN_ALERT + +#define PHYSICAL_DISK_NAME "/dev/vdb" +#define KERNEL_SECTOR_SIZE 512 + +#define BIO_WRITE_MESSAGE "def" + + +/* pointer to physical device structure */ +static struct block_device *phys_bdev; + +static void send_test_bio(struct block_device *bdev, int dir) +{ + struct bio *bio = bio_alloc(GFP_NOIO, 1); + struct page *page; + char *buf; + + /* TODO 4: fill bio (bdev, sector, direction) */ + + page = alloc_page(GFP_NOIO); + bio_add_page(bio, page, KERNEL_SECTOR_SIZE, 0); + + /* TODO 5: write message to bio buffer if direction is write */ + + /* TODO 4: submit bio and wait for completion */ + + /* TODO 4: read data (first 3 bytes) from bio buffer and print it */ + + bio_put(bio); + __free_page(page); +} + +static struct block_device *open_disk(char *name) +{ + struct block_device *bdev; + + /* TODO 4: get block device in exclusive mode */ + + return bdev; +} + +static int __init relay_init(void) +{ + phys_bdev = open_disk(PHYSICAL_DISK_NAME); + if (phys_bdev == NULL) { + printk(KERN_ERR "[relay_init] No such device\n"); + return -EINVAL; + } + + send_test_bio(phys_bdev, REQ_OP_READ); + + return 0; +} + +static void close_disk(struct block_device *bdev) +{ + /* TODO 4: put block device */ +} + +static void __exit relay_exit(void) +{ + /* TODO 5: send test write bio */ + + close_disk(phys_bdev); +} + +module_init(relay_init); +module_exit(relay_exit); diff --git a/tools/labs/skels/block_device_drivers/4-5-relay-disk/test-relay-disk b/tools/labs/skels/block_device_drivers/4-5-relay-disk/test-relay-disk new file mode 100644 index 00000000000000..f73aad004ea50c --- /dev/null +++ b/tools/labs/skels/block_device_drivers/4-5-relay-disk/test-relay-disk @@ -0,0 +1,20 @@ +#!/bin/sh + +PHYSICAL_DISK_NAME="/dev/vdb" +TMP_FILE="/tmp/disk_data" +echo "abc" > "$PHYSICAL_DISK_NAME" +if ! insmod relay-disk.ko +then + echo "insmod failed" + exit 1 +fi +if ! rmmod relay-disk +then + echo "rmmod failed" + exit 1 +fi +sleep 1 + +echo -n "read from $PHYSICAL_DISK_NAME: " +dd if=$PHYSICAL_DISK_NAME of=$TMP_FILE count=3 bs=1 &> /dev/null +cat $TMP_FILE | hexdump -v -e '/1 "%02X "'; echo From 9898be76ce7dfcfdcdebf0c5772b6cf9a1ed849c Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 17 Apr 2022 16:40:39 +0300 Subject: [PATCH 2/4] lab07: Add solution for ex 2, 3, 4 Signed-off-by: Mara --- .../1-2-3-6-ram-disk/kernel/ram-disk.c | 67 +++++++++++++------ .../4-5-relay-disk/relay-disk.c | 11 ++- .../4-5-relay-disk/test-relay-disk | 0 3 files changed, 56 insertions(+), 22 deletions(-) mode change 100644 => 100755 tools/labs/skels/block_device_drivers/4-5-relay-disk/test-relay-disk diff --git a/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c index 56ca2f922c411a..a3c3d6d2e01c5a 100644 --- a/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c +++ b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c @@ -23,7 +23,7 @@ MODULE_LICENSE("GPL"); #define KERN_LOG_LEVEL KERN_ALERT -#define MY_BLOCK_MAJOR 7 +#define MY_BLOCK_MAJOR 240 #define MY_BLKDEV_NAME "mybdev" #define MY_BLOCK_MINORS 1 #define NR_SECTORS 128 @@ -67,6 +67,17 @@ static void my_block_transfer(struct my_block_dev *dev, sector_t sector, return; /* TODO 3: read/write to dev buffer depending on dir */ + if (dir == 0) { + pr_err("read\n"); + memcpy(buffer, dev->data + offset, len); + } else { + if (dir == 1) { + pr_err("write\n"); + memcpy(dev->data + offset, buffer, len); + } else { + return; + } + } } /* to transfer data using bio structures enable USE_BIO_TRANFER */ @@ -86,21 +97,31 @@ static blk_status_t my_block_request(struct blk_mq_hw_ctx *hctx, struct my_block_dev *dev = hctx->queue->queuedata; /* TODO 2: get pointer to request */ - + rq = bd->rq; /* TODO 2: start request processing. */ - + blk_mq_start_request(rq); /* TODO 2: check fs request. Return if passthrough. */ + if (blk_rq_is_passthrough(rq)) { + /* TODO 2: print request information */ + printk(KERN_NOTICE "Skip non-fs request\n"); + blk_mq_end_request(rq, BLK_STS_IOERR); + goto out; + } - /* TODO 2: print request information */ + pr_info("Request received:\n"); + pr_info("Start of sector: %llu\n", blk_rq_pos(rq)); + pr_info("Total size: %u\n", blk_rq_bytes(rq)); + pr_info("Direction: %hu\n", rq_data_dir(rq)); #if USE_BIO_TRANSFER == 1 /* TODO 6: process the request by calling my_xfer_request */ #else /* TODO 3: process the request by calling my_block_transfer */ + my_block_transfer(dev, blk_rq_pos(rq), blk_rq_bytes(rq), bio_data(rq->bio), rq_data_dir(rq)); #endif /* TODO 2: end request successfully */ - + blk_mq_end_request(rq, BLK_STS_OK); out: return BLK_STS_OK; } @@ -174,6 +195,21 @@ static int create_block_device(struct my_block_dev *dev) return err; } +static void delete_block_device(struct my_block_dev *dev) +{ + if (dev->gd) { + del_gendisk(dev->gd); + put_disk(dev->gd); + } + + if (dev->queue) + blk_cleanup_queue(dev->queue); + if (dev->tag_set.tags) + blk_mq_free_tag_set(&dev->tag_set); + if (dev->data) + vfree(dev->data); +} + static int __init my_block_init(void) { int err = 0; @@ -185,34 +221,23 @@ static int __init my_block_init(void) return -EBUSY; } /* TODO 2: create block device using create_block_device */ + create_block_device(&g_dev); return 0; out: /* TODO 2: unregister block device in case of an error */ + delete_block_device(&g_dev); return err; } -static void delete_block_device(struct my_block_dev *dev) -{ - if (dev->gd) { - del_gendisk(dev->gd); - put_disk(dev->gd); - } - - if (dev->queue) - blk_cleanup_queue(dev->queue); - if (dev->tag_set.tags) - blk_mq_free_tag_set(&dev->tag_set); - if (dev->data) - vfree(dev->data); -} - static void __exit my_block_exit(void) { /* TODO 2: cleanup block device using delete_block_device */ - unregister_blkdev(MY_BLOCK_MAJOR, MY_BLKDEV_NAME); + delete_block_device(&g_dev); /* TODO 1: unregister block device */ + unregister_blkdev(MY_BLOCK_MAJOR, MY_BLKDEV_NAME); + } module_init(my_block_init); diff --git a/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c b/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c index 44178bfdcdc530..5c637690c5c260 100644 --- a/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c +++ b/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c @@ -33,6 +33,9 @@ static void send_test_bio(struct block_device *bdev, int dir) char *buf; /* TODO 4: fill bio (bdev, sector, direction) */ + bio->bi_disk = bdev->bd_disk; + bio->bi_iter.bi_sector = 0; + bio->bi_opf = REQ_OP_READ; page = alloc_page(GFP_NOIO); bio_add_page(bio, page, KERNEL_SECTOR_SIZE, 0); @@ -40,8 +43,12 @@ static void send_test_bio(struct block_device *bdev, int dir) /* TODO 5: write message to bio buffer if direction is write */ /* TODO 4: submit bio and wait for completion */ + submit_bio_wait(bio); /* TODO 4: read data (first 3 bytes) from bio buffer and print it */ + buf = kmap_atomic(page); + pr_info("%02x\t%02x\t%02x\n", buf[0], buf[1], buf[2]); + kunmap_atomic(buf); bio_put(bio); __free_page(page); @@ -52,7 +59,8 @@ static struct block_device *open_disk(char *name) struct block_device *bdev; /* TODO 4: get block device in exclusive mode */ - + pr_info("Name: %s\n", name); + bdev = blkdev_get_by_path(name, FMODE_READ | FMODE_WRITE | FMODE_EXCL, THIS_MODULE); return bdev; } @@ -72,6 +80,7 @@ static int __init relay_init(void) static void close_disk(struct block_device *bdev) { /* TODO 4: put block device */ + blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); } static void __exit relay_exit(void) diff --git a/tools/labs/skels/block_device_drivers/4-5-relay-disk/test-relay-disk b/tools/labs/skels/block_device_drivers/4-5-relay-disk/test-relay-disk old mode 100644 new mode 100755 From 929ec8559fec8b92bebf9e1469bb6bded22a90a8 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 17 Apr 2022 20:58:33 +0300 Subject: [PATCH 3/4] lab06: Add solution for ex5 Signed-off-by: Mara --- .../4-5-relay-disk/relay-disk.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c b/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c index 5c637690c5c260..98d7ff32f91bc6 100644 --- a/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c +++ b/tools/labs/skels/block_device_drivers/4-5-relay-disk/relay-disk.c @@ -20,8 +20,8 @@ MODULE_LICENSE("GPL"); #define PHYSICAL_DISK_NAME "/dev/vdb" #define KERNEL_SECTOR_SIZE 512 -#define BIO_WRITE_MESSAGE "def" - +#define BIO_WRITE_MESSAGE "HELLOOOO" +#define BUFSIZ 512 /* pointer to physical device structure */ static struct block_device *phys_bdev; @@ -42,6 +42,13 @@ static void send_test_bio(struct block_device *bdev, int dir) /* TODO 5: write message to bio buffer if direction is write */ + if (dir == REQ_OP_WRITE) { + bio->bi_opf = REQ_OP_WRITE; + buf = kmap_atomic(page); + memcpy(buf, BIO_WRITE_MESSAGE, strlen(BIO_WRITE_MESSAGE)); + kunmap_atomic(buf); + } + /* TODO 4: submit bio and wait for completion */ submit_bio_wait(bio); @@ -86,7 +93,7 @@ static void close_disk(struct block_device *bdev) static void __exit relay_exit(void) { /* TODO 5: send test write bio */ - + send_test_bio(phys_bdev, REQ_OP_WRITE); close_disk(phys_bdev); } From d814c573912182f4c758565f1d1ed31073639b19 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 17 Apr 2022 21:26:44 +0300 Subject: [PATCH 4/4] lab06: Add solution for ex6 Signed-off-by: Mara --- .../1-2-3-6-ram-disk/kernel/ram-disk.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c index a3c3d6d2e01c5a..f927054814a61b 100644 --- a/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c +++ b/tools/labs/skels/block_device_drivers/1-2-3-6-ram-disk/kernel/ram-disk.c @@ -26,12 +26,12 @@ MODULE_LICENSE("GPL"); #define MY_BLOCK_MAJOR 240 #define MY_BLKDEV_NAME "mybdev" #define MY_BLOCK_MINORS 1 -#define NR_SECTORS 128 +#define NR_SECTORS 128 #define KERNEL_SECTOR_SIZE 512 /* TODO 6: use bios for read/write requests */ -#define USE_BIO_TRANSFER 0 +#define USE_BIO_TRANSFER 1 static struct my_block_dev { @@ -85,8 +85,21 @@ static void my_block_transfer(struct my_block_dev *dev, sector_t sector, static void my_xfer_request(struct my_block_dev *dev, struct request *req) { /* TODO 6: iterate segments */ + struct bio_vec bvec; + struct req_iterator iter; + rq_for_each_segment(bvec, req, iter) { /* TODO 6: copy bio data to device buffer */ + sector_t sector = iter.iter.bi_sector; + char *buffer = kmap_atomic(bvec.bv_page); + unsigned long offset = bvec.bv_offset; + size_t len = bvec.bv_len; + int dir = bio_data_dir(iter.bio); + + my_block_transfer(dev, sector, len, buffer + offset, dir); + + kunmap_atomic(buffer); + } } #endif @@ -115,6 +128,7 @@ static blk_status_t my_block_request(struct blk_mq_hw_ctx *hctx, #if USE_BIO_TRANSFER == 1 /* TODO 6: process the request by calling my_xfer_request */ + #else /* TODO 3: process the request by calling my_block_transfer */ my_block_transfer(dev, blk_rq_pos(rq), blk_rq_bytes(rq), bio_data(rq->bio), rq_data_dir(rq));