From: Cyril H. <su...@li...> - 2013-10-23 16:51:09
|
The branch, master, has been updated via 69d3b326811ba347e75335756ae7c5334deb9f11 (commit) via 82a13465123b31108d914fe148646c58e23532be (commit) from 6c5ad9bbf066eaf00fbe4aaecc5a2c727a28f14d (commit) - Log ----------------------------------------------------------------- commit 69d3b326811ba347e75335756ae7c5334deb9f11 Author: Alexey Kodanev <ale...@or...> Date: Tue Oct 22 16:16:42 2013 +0400 device-drivers: tbio: fixes Obsolete code updated to the actual kernel BIO API. User-space program rewritten to use LTP lib. Signed-off-by: Alexey Kodanev <ale...@or...> commit 82a13465123b31108d914fe148646c58e23532be Author: Alexey Kodanev <ale...@or...> Date: Fri Oct 18 13:39:43 2013 +0400 device-drivers: tbio: rearrange test files Signed-off-by: Alexey Kodanev <ale...@or...> ----------------------------------------------------------------------- Summary of changes: .../kernel/device-drivers/{block => tbio}/Makefile | 0 .../device-drivers/tbio/kernel_space/Makefile | 22 - .../device-drivers/tbio/kernel_space/load_tbio.sh | 5 - .../kernel/device-drivers/tbio/kernel_space/tbio.c | 589 -------------------- .../kernel/device-drivers/tbio/kernel_space/tbio.h | 96 ---- .../device-drivers/tbio/tbio_kernel/.gitignore | 7 + .../device-drivers/tbio/tbio_kernel/Makefile | 33 ++ .../device-drivers/tbio/tbio_kernel/ltp_tbio.c | 569 +++++++++++++++++++ .../tbio/{kernel_space => tbio_kernel}/str_tbio.h | 0 .../kernel/device-drivers/tbio/tbio_kernel/tbio.h | 71 +++ .../device-drivers/tbio/tbio_user/.gitignore | 1 + .../block_dev_user => tbio/tbio_user}/Makefile | 0 .../kernel/device-drivers/tbio/tbio_user/tbio.c | 334 +++++++++++ .../kernel/device-drivers/tbio/user_space/Makefile | 9 - .../device-drivers/tbio/user_space/tbio_ki.c | 86 --- .../device-drivers/tbio/user_space/user_tbio.c | 348 ------------ .../device-drivers/tbio/user_space/user_tbio.h | 22 - 17 files changed, 1015 insertions(+), 1177 deletions(-) copy testcases/kernel/device-drivers/{block => tbio}/Makefile (100%) delete mode 100644 testcases/kernel/device-drivers/tbio/kernel_space/Makefile delete mode 100755 testcases/kernel/device-drivers/tbio/kernel_space/load_tbio.sh delete mode 100644 testcases/kernel/device-drivers/tbio/kernel_space/tbio.c delete mode 100644 testcases/kernel/device-drivers/tbio/kernel_space/tbio.h create mode 100644 testcases/kernel/device-drivers/tbio/tbio_kernel/.gitignore create mode 100644 testcases/kernel/device-drivers/tbio/tbio_kernel/Makefile create mode 100644 testcases/kernel/device-drivers/tbio/tbio_kernel/ltp_tbio.c rename testcases/kernel/device-drivers/tbio/{kernel_space => tbio_kernel}/str_tbio.h (100%) create mode 100644 testcases/kernel/device-drivers/tbio/tbio_kernel/tbio.h create mode 100644 testcases/kernel/device-drivers/tbio/tbio_user/.gitignore copy testcases/kernel/device-drivers/{block/block_dev_user => tbio/tbio_user}/Makefile (100%) create mode 100644 testcases/kernel/device-drivers/tbio/tbio_user/tbio.c delete mode 100644 testcases/kernel/device-drivers/tbio/user_space/Makefile delete mode 100644 testcases/kernel/device-drivers/tbio/user_space/tbio_ki.c delete mode 100644 testcases/kernel/device-drivers/tbio/user_space/user_tbio.c delete mode 100644 testcases/kernel/device-drivers/tbio/user_space/user_tbio.h diff --git a/testcases/kernel/device-drivers/block/Makefile b/testcases/kernel/device-drivers/tbio/Makefile similarity index 100% copy from testcases/kernel/device-drivers/block/Makefile copy to testcases/kernel/device-drivers/tbio/Makefile diff --git a/testcases/kernel/device-drivers/tbio/kernel_space/Makefile b/testcases/kernel/device-drivers/tbio/kernel_space/Makefile deleted file mode 100644 index 2bbd1f5..0000000 --- a/testcases/kernel/device-drivers/tbio/kernel_space/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# -# Makefile for GCOV profiling kernel module -# - -#KERNELDIR := /usr/src/linux-2.5.64-gcov -EXTRA_CFLAGS := -Wall - -ifneq ($(KERNELRELEASE),) - -obj-m := tbio.o -else -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) - -default: - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules -# $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules -endif - -clean: - rm -f *.o rm -f .*.cmd rm -f *.bb* rm -f *.ko rm -f *.mod.* 2>/dev/null || true - diff --git a/testcases/kernel/device-drivers/tbio/kernel_space/load_tbio.sh b/testcases/kernel/device-drivers/tbio/kernel_space/load_tbio.sh deleted file mode 100755 index 724bd65..0000000 --- a/testcases/kernel/device-drivers/tbio/kernel_space/load_tbio.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -insmod -f ./tbio.ko || insmod -f ./tbio.o || exit 1 -rm -f /dev/tbio0 -major=`awk '/tbio/{print \$1}' /proc/devices` -mknod /dev/tbio0 b $major 0 diff --git a/testcases/kernel/device-drivers/tbio/kernel_space/tbio.c b/testcases/kernel/device-drivers/tbio/kernel_space/tbio.c deleted file mode 100644 index 447d223..0000000 --- a/testcases/kernel/device-drivers/tbio/kernel_space/tbio.c +++ /dev/null @@ -1,589 +0,0 @@ -/* - * - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - - * This module will test block io layer. - * - * module: tbio - * Copyright (c) International Business Machines Corp., 2003 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; - * - * FILE : tbio.c - * USAGE : kernel_space:./load_tbio.sh - * user_space :./test_bio - * - * DESCRIPTION : The module will test block i/o layer for kernel 2.5 - * REQUIREMENTS: - * 1) glibc 2.1.91 or above. - * - * HISTORY : - * 11/19/2003 Kai Zhao (lt...@cn...) - * - * CODE COVERAGE: 74.9% - fs/bio.c (Total Coverage) - * - */ - -#ifndef __KERNEL__ -#define __KERNEL__ -#endif - -#include <linux/module.h> -//#include <linux/moduleparam.h> -#include <linux/init.h> - -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/errno.h> -#include <linux/types.h> -#include <linux/vmalloc.h> -#include <linux/genhd.h> -#include <linux/blkdev.h> -#include <linux/buffer_head.h> -#include "tbio.h" - -#define BLK_DEFAULT_TIMEOUT (60 * HZ) -MODULE_AUTHOR("Kai Zhao <lt...@cn...>"); -MODULE_DESCRIPTION(TMOD_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -//module_param(major_num , int , 0); -static int hardsect_size = 1024; -//module_param(hardsect_size , int , 0); -static int nsectors = 1024; -//module_param(nsectors , int , 0); - -static struct bio *tbiop = NULL, *tbiop_dup = NULL; -//static struct bio_pair *bio_pairp = NULL; -static struct request_queue Queue; - -static struct tbio_device { - unsigned long size; - spinlock_t lock; - u8 *data; - struct gendisk *gd; - struct block_device *bdev; -} Device; - -static int send_request(request_queue_t * q, struct bio *bio, - struct block_device *bdev, struct tbio_interface *inter, - int writing) -{ - struct request *rq; - void *buffer = NULL; - unsigned long start_time; - int err; - - rq = blk_get_request(q, writing ? WRITE : READ, __GFP_WAIT); - rq->cmd_len = inter->cmd_len; - //printk("inter.cmd %s\n" , inter->cmd); - if (copy_from_user(rq->cmd, inter->cmd, inter->cmd_len)) - goto out_request; - //printk("tbio: rq->cmd : %s\n",rq->cmd); - if (sizeof(rq->cmd) != inter->cmd_len) - memset(rq->cmd + inter->cmd_len, 0, - sizeof(rq->cmd) - inter->cmd_len); - - rq->bio = rq->biotail = NULL; - - blk_rq_bio_prep(q, rq, bio); - - rq->data = buffer; - rq->data_len = inter->data_len; - - rq->timeout = 0; - if (!rq->timeout) - rq->timeout = q->sg_timeout; - if (!rq->timeout) - rq->timeout = BLK_DEFAULT_TIMEOUT; - - start_time = jiffies; - - DECLARE_COMPLETION(wait); - - rq->rq_disk = bdev->bd_disk; - - rq->waiting = &wait; - elv_add_request(q, rq, 1, 1); - generic_unplug_device(q); - wait_for_completion(&wait); - //printk("tbio: completion\n"); - if (rq->errors) { - err = -EIO; - printk("tbio: rq->errors\n"); - return err; - } - - blk_put_request(rq); - - return 0; -out_request: - blk_put_request(rq); - return -EFAULT; - -} - -static int tbio_io(struct block_device *bdev, struct tbio_interface *uptr) -{ - tbio_interface_t inter; - struct bio *bio = NULL; - int reading = 0, writing = 0; - void *buffer = NULL; - //struct request *rq; - request_queue_t *q; - q = bdev_get_queue(Device.bdev); - - if (copy_from_user(&inter, uptr, sizeof(tbio_interface_t))) { - printk("tbio: copy_from_user\n"); - return -EFAULT; - } - - if (inter.data_len > (q->max_sectors << 9)) { - printk("tbio: inter.in_len > q->max_sectors << 9\n"); - return -EIO; - } - - if (inter.data_len) { - - switch (inter.direction) { - default: - return -EINVAL; - case TBIO_TO_DEV: - writing = 1; - break; - case TBIO_FROM_DEV: - reading = 1; - break; - } - - bio = bio_map_user(bdev, (unsigned long)inter.data, - inter.data_len, reading); - - if (!bio) { - printk("tbio : bio_map_user failed\n"); - buffer = - kmalloc(inter.data_len, q->bounce_gfp | GFP_USER); - if (!buffer) { - printk("tbio: buffer no memory\n"); - return -1; - } - copy_from_user(buffer, inter.data, inter.data_len); - printk("tbio: buffer %s\n", (char *)buffer); - } - - } - - send_request(q, bio, bdev, &inter, writing); - - if (bio) - bio_unmap_user(bio, reading); - return 0; -} - -static int test_bio_put(struct bio *biop) -{ - - if (biop) - bio_put(biop); - - return 0; -} - -static int test_bio_clone(void) -{ - tbiop_dup = bio_clone(tbiop, GFP_NOIO); - if (tbiop_dup == NULL) { - printk("tbio: bio_clone failed\n"); - return -1; - } - - test_bio_put(tbiop_dup); - - return 0; -} - -static int test_bio_add_page(void) -{ - int res = 0, i = 0, offset = 0; - unsigned long addr = 0; - struct page *ppage = NULL; - - for (i = 0; i < 128; i++) { - - addr = get_zeroed_page(GFP_KERNEL); - - if (addr == 0) { - printk("tbio: get free page failed %ld\n", addr); - return -1; - } - - ppage = virt_to_page(addr); - if (ppage == NULL) { - printk - ("tbio: covert virture page to page struct failed\n"); - return -1; - } - - res = bio_add_page(tbiop, ppage, PAGE_SIZE, offset); - if (res < 0) { - printk("bio_add_page :res %d\n", res); - return -1; - } - offset += res; - // printk ("tbio: bio_add_page : %d\n", res); - } - return 0; -} - -static int test_do_bio_alloc(int num) -{ - tbiop = bio_alloc(GFP_KERNEL, num); - if (tbiop == NULL) { - printk("tbio: bio_alloc failed\n"); - return -1; - } - bio_put(tbiop); - - return 0; -} - -static int test_bio_alloc(void) -{ - int res = 0; - res = test_do_bio_alloc(2); - if (res < 0) { - printk("can not alloc bio for %d\n", 2); - return -1; - } - - res = test_do_bio_alloc(8); - if (res < 0) { - printk("can not alloc bio for %d\n", 8); - return -1; - } - res = test_do_bio_alloc(32); - if (res < 0) { - printk("can not alloc bio for %d\n", 32); - return -1; - } - res = test_do_bio_alloc(96); - if (res < 0) { - printk("can not alloc bio for %d\n", 96); - return -1; - } - res = test_do_bio_alloc(BIO_MAX_PAGES); - if (res < 0) { - printk("can not alloc bio for %d\n", BIO_MAX_PAGES); - return -1; - } - - tbiop = bio_alloc(GFP_KERNEL, BIO_MAX_PAGES); - if (tbiop == NULL) { - printk("tbio: bio_alloc failed\n"); - return -1; - } - - return 0; -} - -static int test_bio_split(struct block_device *bdev, - struct tbio_interface *uptr) -{ - tbio_interface_t inter; - struct bio *bio = NULL; - struct bio_pair *bio_pairp = NULL; - int reading = 0, writing = 0; - void *buffer = NULL; - request_queue_t *q; - q = bdev_get_queue(Device.bdev); - - if (copy_from_user(&inter, uptr, sizeof(tbio_interface_t))) { - printk("tbio: copy_from_user\n"); - return -EFAULT; - } - - if (inter.data_len > (q->max_sectors << 9)) { - printk("tbio: inter.in_len > q->max_sectors << 9\n"); - return -EIO; - } - - if (inter.data_len) { - - switch (inter.direction) { - default: - return -EINVAL; - case TBIO_TO_DEV: - writing = 1; - break; - case TBIO_FROM_DEV: - reading = 1; - break; - } - - bio = bio_map_user(bdev, (unsigned long)inter.data, - inter.data_len, reading); - - if (!bio) { - printk("tbio : bio_map_user failed\n"); - buffer = - kmalloc(inter.data_len, q->bounce_gfp | GFP_USER); - if (!buffer) { - printk("tbio: buffer no memory\n"); - return -1; - } - copy_from_user(buffer, inter.data, inter.data_len); - printk("tbio: buffer %s\n", (char *)buffer); - } else { - // printk("tbio: bio sectors %d\n", bio_sectors(bio)); - // printk("tbio: split now\n"); - bio_pairp = bio_split(bio, bio_split_pool, 2); - - if (bio_pairp == NULL) { - printk("tbio: bio_split failed\n"); - bio_unmap_user(bio, reading); - return -1; - } - } - - } - - send_request(q, &(bio_pairp->bio1), bdev, &inter, writing); - q = bdev_get_queue(Device.bdev); - send_request(q, &(bio_pairp->bio2), bdev, &inter, writing); - - if (bio_pairp) { - bio_pair_release(bio_pairp); - return 0; - } - - if (bio) - bio_unmap_user(bio, reading); - - return 0; - -} - -static int test_bio_get_nr_vecs(void) -{ - int number = 0; - - if (!tbiop) { - printk("tbio: tbiop is NULL\n"); - return -1; - } - - number = bio_get_nr_vecs(tbiop->bi_bdev); - - if (number < 0) { - printk("tbio: bio_get_nr_vec failed\n"); - return -1; - } - //printk("bio_get_nr_vecs: %d\n",number); - return 0; -} - -static int tbio_ioctl(struct inode *ino, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; -// request_queue_t *q; - - //q = bdev_get_queue(Device.bdev); - - printk("ttbio: ioctl 0x%x 0x%lx\n", cmd, arg); - - switch (cmd) { - case LTP_TBIO_DO_IO: - { - err = bd_claim(Device.bdev, current); - if (err) { - printk("tbio:bd_claim\n"); - break; - } - - err = - tbio_io(Device.bdev, (struct tbio_interface *)arg); - bd_release(Device.bdev); - } - break; - - case LTP_TBIO_CLONE: - err = test_bio_clone(); - break; - case LTP_TBIO_ADD_PAGE: - err = test_bio_add_page(); - break; - case LTP_TBIO_ALLOC: - err = test_bio_alloc(); - break; - case LTP_TBIO_GET_NR_VECS: - err = test_bio_get_nr_vecs(); - break; - case LTP_TBIO_PUT: - err = test_bio_put(tbiop); - break; - case LTP_TBIO_SPLIT: - { - err = bd_claim(Device.bdev, current); - if (err) { - printk("tbio:bd_claim\n"); - break; - } - - err = - test_bio_split(Device.bdev, - (struct tbio_interface *)arg); - bd_release(Device.bdev); - - } - break; - //case LTP_TBIO_PAIR_RELEASE: err = test_bio_pair_release();break; - - } - return 0; -} - -static void tbio_transfer(struct request *req, struct tbio_device *dev) -{ - - struct bio *bio = req->bio; - - //printk("tbio: bio_data(bio) %s\n" , (char *)bio_data(bio)); - if (bio_data_dir(bio)) { - printk("tbio: write \"%s\" to dev\n", (char *)bio_data(bio)); - memcpy(dev->data, bio_data(bio), bio->bi_size); - } else { - memcpy(bio_data(bio), dev->data, bio->bi_size); - printk("tbio: read \"%s\" from dev\n", (char *)bio_data(bio)); - } - -} - -static void tbio_request(request_queue_t * q) -{ - struct request *req; - - while ((req = elv_next_request(q)) != NULL) { - - tbio_transfer(req, &Device); - end_request(req, 1); - } -} - -static int tbio_open(struct inode *inode, struct file *filep) -{ - if (!Device.bdev) { - Device.bdev = inode->i_bdev; - //atomic_inc((atomic_t)&Device.bdev->bd_part_count); - } - - return 0; -} - -static int tbio_release(struct inode *inode, struct file *filep) -{ - return 0; -} - -int tbio_media_changed(struct gendisk *gd) -{ - return 0; -} - -int tbio_revalidate(struct gendisk *gd) -{ - return 0; -} - -static struct block_device_operations tbio_ops = { - .owner = THIS_MODULE, - .open = tbio_open, - .ioctl = tbio_ioctl, - .release = tbio_release, - .media_changed = tbio_media_changed, - .revalidate_disk = tbio_revalidate -}; - -static int __init tbio_init(void) -{ - Device.size = nsectors * hardsect_size; - int result; - spin_lock_init(&Device.lock); - Device.data = vmalloc(Device.size); - if (Device.data == NULL) - return -ENOMEM; - Device.bdev = NULL; - - result = register_blkdev(TBIO_MAJOR, DEVICE_NAME); //, &tbio_ops); - - printk(KERN_ALERT "LTP BIO: register_blkdev result=%d major %d\n", - result, TBIO_MAJOR); - - if (result <= 0) { - printk(KERN_WARNING "tbio:unable to get major number\n"); - goto out; - } - - Device.gd = alloc_disk(1); - if (!Device.gd) - goto out_unregister; - Device.gd->major = TBIO_MAJOR; - Device.gd->first_minor = 0; - Device.gd->fops = &tbio_ops; - Device.gd->private_data = &Device; - strcpy(Device.gd->disk_name, "tbio0"); - set_capacity(Device.gd, nsectors); - blk_init_queue(tbio_request, &Device.lock); - Device.gd->queue = &Queue; - add_disk(Device.gd); - - return 0; - -out_unregister: - unregister_chrdev(TBIO_MAJOR, "tbio"); -out: - vfree(Device.data); - return -ENOMEM; -} - -static void tbio_exit(void) -{ - if (Device.bdev) { - invalidate_bdev(Device.bdev, 1); - bdput(Device.bdev); - } - - del_gendisk(Device.gd); - put_disk(Device.gd); - unregister_blkdev(TBIO_MAJOR, "tbio"); - vfree(Device.data); -} - -module_init(tbio_init); -module_exit(tbio_exit); diff --git a/testcases/kernel/device-drivers/tbio/kernel_space/tbio.h b/testcases/kernel/device-drivers/tbio/kernel_space/tbio.h deleted file mode 100644 index e650399..0000000 --- a/testcases/kernel/device-drivers/tbio/kernel_space/tbio.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - - * In this header file keep all flags and other - * structures that will be needed in both kernel - * and user space. Specifically the ioctl flags - * will go in here so that in user space a program - * can specify flags for the ioctl call. - * - * module: tbio - * Copyright (c) International Business Machines Corp., 2003 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; - * - * FILE : tbio.h - * USAGE : kernel_space:./load_tbio.sh - * user_space :./test_bio - * - * DESCRIPTION : The module will test block i/o layer for kernel 2.5 - * REQUIREMENTS: - * 1) glibc 2.1.91 or above. - * - * HISTORY : - * 11/19/2003 Kai Zhao (lt...@cn...) - * - * CODE COVERAGE: 74.9% - fs/bio.c (Total Coverage) - * - */ - -#define TMOD_DRIVER_NAME "ltp test block I/O layer module" -#define DEVICE_NAME "/dev/tbio" -#define MAG_NUM 'k' -#define TBIO_MAJOR 258 - -#define TBIO_TO_DEV 1 -#define TBIO_FROM_DEV 2 - -/* put ioctl flags here, use the _IO macro which is - found in linux/ioctl.h, takes a letter, and an - integer */ - -#define LTP_TBIO_CLONE _IO(MAG_NUM,1) -#define LTP_TBIO_ALLOC _IO(MAG_NUM,2) -#define LTP_TBIO_GET_NR_VECS _IO(MAG_NUM,3) -#define LTP_TBIO_PUT _IO(MAG_NUM,4) -#define LTP_TBIO_SPLIT _IO(MAG_NUM,5) -#define LTP_TBIO_DO_IO _IO(MAG_NUM,6) -#define LTP_TBIO_ADD_PAGE _IO(MAG_NUM,7) - -/* memory between the kernel and user space is - seperated, so that if a structure is needed - to be passed between kernel and user space - a call must be made to copy_to_user or copy - from user. Use this structure to streamline - that process. For example: A function that - writes to a disc takes in a ki_write_t - pointer from userspace. In the user space - program specify the length of the pointer as - in_len, and in_data as the actual structure. */ - -struct tbio_interface { - void *data; // input data - int data_len; // input data length - int direction; // read or write form DEV - unsigned char *cmd; // read or write - int cmd_len; // length of cmd -}; -typedef struct tbio_interface tbio_interface_t; - diff --git a/testcases/kernel/device-drivers/tbio/tbio_kernel/.gitignore b/testcases/kernel/device-drivers/tbio/tbio_kernel/.gitignore new file mode 100644 index 0000000..7ce5765 --- /dev/null +++ b/testcases/kernel/device-drivers/tbio/tbio_kernel/.gitignore @@ -0,0 +1,7 @@ +/ltp_tbio.ko +/*.mod.c +/modules.order +/.tmp_versions +/.*.ko +/.*.cmd +/Module.symvers diff --git a/testcases/kernel/device-drivers/tbio/tbio_kernel/Makefile b/testcases/kernel/device-drivers/tbio/tbio_kernel/Makefile new file mode 100644 index 0000000..6c6ba92 --- /dev/null +++ b/testcases/kernel/device-drivers/tbio/tbio_kernel/Makefile @@ -0,0 +1,33 @@ +# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +ifneq ($(KERNELRELEASE),) + +obj-m := ltp_tbio.o + +else + +top_srcdir ?= ../../../../.. +include $(top_srcdir)/include/mk/env_pre.mk + +REQ_VERSION_MAJOR := 2 +REQ_VERSION_PATCH := 6 +MAKE_TARGETS := ltp_tbio.ko + +include $(top_srcdir)/include/mk/module.mk +include $(top_srcdir)/include/mk/generic_leaf_target.mk + +endif diff --git a/testcases/kernel/device-drivers/tbio/tbio_kernel/ltp_tbio.c b/testcases/kernel/device-drivers/tbio/tbio_kernel/ltp_tbio.c new file mode 100644 index 0000000..5198b82 --- /dev/null +++ b/testcases/kernel/device-drivers/tbio/tbio_kernel/ltp_tbio.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) International Business Machines Corp., 2001 + * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * This module will test block io layer. + * + * module: tbio + * + * FILE : tbio.c + * USAGE : kernel_space:./load_tbio.sh + * user_space :./test_bio + * + * DESCRIPTION : The module will test block i/o layer for kernel 2.5 + * REQUIREMENTS: + * 1) glibc 2.1.91 or above. + * + * HISTORY : + * 11/19/2003 Kai Zhao (lt...@cn...) + * + * CODE COVERAGE: 74.9% - fs/bio.c (Total Coverage) + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/version.h> +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/vmalloc.h> +#include <linux/genhd.h> +#include <linux/blkdev.h> +#include <linux/buffer_head.h> + +#include "tbio.h" + +MODULE_AUTHOR("Kai Zhao <lt...@cn...>"); +MODULE_AUTHOR("Alexey Kodanev <ale...@or...>"); +MODULE_DESCRIPTION(TMOD_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +#define prk_err(fmt, ...) \ + pr_err(TBIO_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__) +#define prk_info(fmt, ...) \ + pr_info(TBIO_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__) + +static int nsectors = 4096; +module_param(nsectors, int, 0444); +MODULE_PARM_DESC(nsectors, "The number of sectors"); + +static struct bio *tbiop, *tbiop_dup; + +static struct tbio_device { + unsigned long size; + spinlock_t lock; + u8 *data; + struct gendisk *gd; + struct block_device *bdev; + struct request_queue *q; +} tbio_dev; + +static int send_request(struct request_queue *q, struct bio *bio, + struct block_device *bdev, struct tbio_interface *inter, + int writing) +{ + struct request *rq; + rq = blk_make_request(q, bio, GFP_KERNEL); + if (!rq) { + prk_err("failed to make request"); + return -EFAULT; + } + + rq->cmd_len = inter->cmd_len; + + if (copy_from_user(rq->cmd, inter->cmd, inter->cmd_len)) + goto out_request; + + if (sizeof(rq->cmd) != inter->cmd_len) { + memset(rq->cmd + inter->cmd_len, 0, + sizeof(rq->cmd) - inter->cmd_len); + } + + rq->__sector = bio->bi_sector; + + if (blk_execute_rq(q, bdev->bd_disk, rq, 0)) + goto out_request; + + blk_put_request(rq); + + return 0; + +out_request: + + blk_put_request(rq); + return -EFAULT; +} + +static int tbio_io(struct block_device *bdev, struct tbio_interface *uptr) +{ + int ret; + tbio_interface_t inter; + struct bio *bio = NULL; + int reading = 0, writing = 0; + void *buf = NULL; + struct request_queue *q = bdev_get_queue(bdev); + + if (copy_from_user(&inter, uptr, sizeof(tbio_interface_t))) { + prk_err("copy_from_user"); + return -EFAULT; + } + + if (inter.data_len > (q->limits.max_sectors << 9)) { + prk_err("inter.in_len > q->max_sectors << 9"); + return -EIO; + } + + if (inter.data_len) { + + switch (inter.direction) { + default: + return -EINVAL; + case TBIO_TO_DEV: + writing = 1; + break; + case TBIO_FROM_DEV: + reading = 1; + break; + } + + bio = bio_map_user(q, bdev, (unsigned long)inter.data, + inter.data_len, reading, GFP_KERNEL); + + if (!bio) { + prk_err("bio_map_user failed"); + buf = kmalloc(inter.data_len, q->bounce_gfp | GFP_USER); + if (!buf) { + prk_err("buffer no memory"); + return -1; + } + ret = copy_from_user(buf, inter.data, inter.data_len); + if (ret) + prk_err("copy_from_user() failed"); + + prk_info("buffer %s\n, copy_from_user returns '%d'", + (char *)buf, ret); + } + + } + + send_request(q, bio, bdev, &inter, writing); + + if (bio) + bio_unmap_user(bio); + return 0; +} + +static int test_bio_put(struct bio *biop) +{ + if (biop) + bio_put(biop); + + return 0; +} + +static int test_bio_clone(void) +{ + tbiop_dup = bio_clone(tbiop, GFP_NOIO); + if (tbiop_dup == NULL) { + prk_err("bio_clone failed"); + return -1; + } + + test_bio_put(tbiop_dup); + + return 0; +} + +static int test_bio_add_page(void) +{ + int ret = 0, i = 0, offset = 0; + unsigned long addr = 0; + struct page *ppage = NULL; + + for (i = 0; i < 128; i++) { + + addr = get_zeroed_page(GFP_KERNEL); + + if (addr == 0) { + prk_err("get free page failed %ld", addr); + ret = -1; + break; + } + + ppage = virt_to_page(addr); + if (ppage == NULL) { + prk_err("covert virture page to page struct failed"); + ret = -1; + break; + } + + ret = bio_add_page(tbiop, ppage, PAGE_SIZE, offset); + if (ret < 0) { + prk_err("bio_add_page failed"); + break; + } + offset += ret; + } + + return ret; +} + +static int test_do_bio_alloc(int num) +{ + tbiop = bio_alloc(GFP_KERNEL, num); + if (tbiop == NULL) { + prk_err("bio_alloc failed"); + return -1; + } + bio_put(tbiop); + + return 0; +} + +static int test_bio_alloc(void) +{ + if (test_do_bio_alloc(2) < 0) { + prk_err("can not alloc bio for %d", 2); + return -1; + } + + if (test_do_bio_alloc(8) < 0) { + prk_err("can not alloc bio for %d", 8); + return -1; + } + + if (test_do_bio_alloc(32) < 0) { + prk_err("can not alloc bio for %d", 32); + return -1; + } + + if (test_do_bio_alloc(96) < 0) { + prk_err("can not alloc bio for %d", 96); + return -1; + } + + if (test_do_bio_alloc(BIO_MAX_PAGES) < 0) { + prk_err("can not alloc bio for %d", BIO_MAX_PAGES); + return -1; + } + + tbiop = bio_alloc(GFP_KERNEL, BIO_MAX_PAGES); + if (tbiop == NULL) { + prk_err("bio_alloc failed"); + return -1; + } + + tbiop->bi_bdev = tbio_dev.bdev; + tbiop->bi_sector = 0; + + return 0; +} + +static int test_bio_split(struct block_device *bdev, + struct tbio_interface *uptr) +{ + int ret; + tbio_interface_t inter; + struct bio *bio = NULL; + struct bio_pair *bio_pairp = NULL; + int reading = 0, writing = 0; + void *buf = NULL; + struct request_queue *q = bdev_get_queue(bdev); + if (!q) { + prk_err("bdev_get_queue() failed"); + return -EFAULT; + } + + prk_info("test_bio_split"); + + if (copy_from_user(&inter, uptr, sizeof(tbio_interface_t))) { + prk_err("copy_from_user"); + return -EFAULT; + } + + if (inter.data_len > (q->limits.max_sectors << 9)) { + prk_err("inter.in_len > q->limits.max_sectors << 9"); + return -EIO; + } + + prk_info("inter.data_len is %d", inter.data_len); + if (inter.data_len) { + + switch (inter.direction) { + default: + return -EINVAL; + case TBIO_TO_DEV: + writing = 1; + break; + case TBIO_FROM_DEV: + reading = 1; + break; + } + + bio = bio_map_user(q, bdev, (unsigned long)inter.data, + inter.data_len, reading, GFP_KERNEL); + + if (!bio) { + prk_err("bio_map_user failed"); + buf = kmalloc(inter.data_len, q->bounce_gfp | GFP_USER); + if (!buf) { + prk_err("buffer no memory"); + return -1; + } + ret = copy_from_user(buf, inter.data, inter.data_len); + if (ret) + prk_err("copy_from_user() failed"); + + prk_info("buffer %s", (char *)buf); + } else { + bio_pairp = bio_split(bio, 2); + + if (bio_pairp == NULL) { + prk_err("bio_split failed"); + bio_unmap_user(bio); + return -1; + } + } + + } + + send_request(q, &(bio_pairp->bio1), bdev, &inter, writing); + q = bdev_get_queue(bdev); + send_request(q, &(bio_pairp->bio2), bdev, &inter, writing); + + if (bio_pairp) + bio_pair_release(bio_pairp); + + if (bio) + bio_unmap_user(bio); + + return 0; +} + +static int test_bio_get_nr_vecs(void) +{ + int number = 0; + + number = bio_get_nr_vecs(tbio_dev.bdev); + + if (number < 0) { + prk_err("bio_get_nr_vec failed"); + return -1; + } + + prk_info("bio_get_nr_vecs: %d", number); + return 0; +} + +static int tbio_ioctl(struct block_device *blk, fmode_t mode, + unsigned cmd, unsigned long arg) +{ + int err = 0; + + tbio_dev.bdev = blkdev_get_by_path( + DEVICE_NAME, FMODE_READ | FMODE_WRITE, NULL); + + switch (cmd) { + case LTP_TBIO_DO_IO: + prk_info("TEST-CASE: LTP_TBIO_DO_IO:"); + err = tbio_io(tbio_dev.bdev, (struct tbio_interface *)arg); + break; + case LTP_TBIO_CLONE: + prk_info("TEST-CASE: LTP_TBIO_CLONE:"); + err = test_bio_clone(); + break; + case LTP_TBIO_ADD_PAGE: + prk_info("TEST-CASE: LTP_TBIO_ADD_PAGE:"); + err = test_bio_add_page(); + break; + case LTP_TBIO_ALLOC: + prk_info("TEST-CASE: LTP_TBIO_ALLOC:"); + err = test_bio_alloc(); + break; + case LTP_TBIO_GET_NR_VECS: + prk_info("TEST-CASE: LTP_TBIO_GET_NR_VECS:"); + err = test_bio_get_nr_vecs(); + break; + case LTP_TBIO_PUT: + prk_info("TEST-CASE: LTP_TBIO_PUT:"); + err = test_bio_put(tbiop); + break; + case LTP_TBIO_SPLIT: + prk_info("TEST-CASE: LTP_TBIO_SPLIT:"); + err = test_bio_split(tbio_dev.bdev, + (struct tbio_interface *)arg); + break; + } + + prk_info("TEST-CASE DONE"); + blkdev_put(tbio_dev.bdev, FMODE_READ | FMODE_WRITE); + return err; +} + +static int tbio_transfer(struct request *req, struct tbio_device *dev) +{ + unsigned int i = 0, offset = 0; + char *buf; + unsigned long flags; + size_t size; + + struct bio_vec *bv; + struct req_iterator iter; + + size = blk_rq_cur_bytes(req); + prk_info("bio req of size %zu:", size); + offset = blk_rq_pos(req) * 512; + + rq_for_each_segment(bv, req, iter) { + size = bv->bv_len; + prk_info("%s bio(%u), segs(%u) sect(%u) pos(%lu) off(%u)", + (bio_data_dir(iter.bio) == READ) ? "READ" : "WRITE", + i, bio_segments(iter.bio), bio_sectors(iter.bio), + iter.bio->bi_sector, offset); + + if (get_capacity(req->rq_disk) * 512 < offset) { + prk_info("Error, small capacity %zu, offset %u", + get_capacity(req->rq_disk) * 512, + offset); + continue; + } + + buf = bvec_kmap_irq(bv, &flags); + if (bio_data_dir(iter.bio) == WRITE) + memcpy(dev->data + offset, buf, size); + else + memcpy(buf, dev->data + offset, size); + offset += size; + flush_kernel_dcache_page(bv->bv_page); + bvec_kunmap_irq(buf, &flags); + ++i; + } + + return 0; +} + +static void tbio_request(struct request_queue *q) +{ + int ret = 0; + struct request *req; + + while ((req = blk_fetch_request(q)) != NULL) { + + ret = tbio_transfer(req, &tbio_dev); + + spin_unlock_irq(q->queue_lock); + blk_end_request_all(req, ret); + spin_lock_irq(q->queue_lock); + } +} + +static int tbio_open(struct block_device *blk, fmode_t mode) +{ + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) +static int tbio_release(struct gendisk *gd, fmode_t mode) +#else +static void tbio_release(struct gendisk *gd, fmode_t mode) +#endif +{ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) + return 0; +#endif +} + +int tbio_media_changed(struct gendisk *gd) +{ + return 0; +} + +int tbio_revalidate(struct gendisk *gd) +{ + return 0; +} + +static const struct block_device_operations tbio_ops = { + .owner = THIS_MODULE, + .open = tbio_open, + .ioctl = tbio_ioctl, + .release = tbio_release, + .media_changed = tbio_media_changed, + .revalidate_disk = tbio_revalidate +}; + +static int __init tbio_init(void) +{ + tbio_dev.size = nsectors * 512; + + tbio_dev.data = vmalloc(tbio_dev.size); + if (tbio_dev.data == NULL) + return -ENOMEM; + strcpy(tbio_dev.data, "tbio data"); + tbio_dev.bdev = NULL; + + TBIO_MAJOR = register_blkdev(0, DEVICE_NAME); + if (TBIO_MAJOR <= 0) { + prk_err("unable to get major number"); + goto out; + } + prk_info("register_blkdev major %d", TBIO_MAJOR); + + spin_lock_init(&tbio_dev.lock); + tbio_dev.q = blk_init_queue(tbio_request, &tbio_dev.lock); + if (!tbio_dev.q) { + prk_err("failed to init queue"); + goto out_unregister; + } + + tbio_dev.gd = alloc_disk(1); + if (!tbio_dev.gd) + goto out_unregister; + tbio_dev.gd->major = TBIO_MAJOR; + tbio_dev.gd->first_minor = 0; + tbio_dev.gd->fops = &tbio_ops; + tbio_dev.gd->private_data = &tbio_dev; + tbio_dev.gd->queue = tbio_dev.q; + strcpy(tbio_dev.gd->disk_name, "tbio"); + set_capacity(tbio_dev.gd, nsectors); + tbio_dev.gd->queue->queuedata = tbio_dev.gd; + + add_disk(tbio_dev.gd); + + return 0; + +out_unregister: + unregister_blkdev(TBIO_MAJOR, DEVICE_NAME); +out: + vfree(tbio_dev.data); + return -ENOMEM; +} +module_init(tbio_init); + +static void tbio_exit(void) +{ + blk_cleanup_queue(tbio_dev.q); + del_gendisk(tbio_dev.gd); + put_disk(tbio_dev.gd); + unregister_blkdev(TBIO_MAJOR, DEVICE_NAME); + vfree(tbio_dev.data); + prk_info("exit"); +} +module_exit(tbio_exit); diff --git a/testcases/kernel/device-drivers/tbio/kernel_space/str_tbio.h b/testcases/kernel/device-drivers/tbio/tbio_kernel/str_tbio.h similarity index 100% rename from testcases/kernel/device-drivers/tbio/kernel_space/str_tbio.h rename to testcases/kernel/device-drivers/tbio/tbio_kernel/str_tbio.h diff --git a/testcases/kernel/device-drivers/tbio/tbio_kernel/tbio.h b/testcases/kernel/device-drivers/tbio/tbio_kernel/tbio.h new file mode 100644 index 0000000..cf6df73 --- /dev/null +++ b/testcases/kernel/device-drivers/tbio/tbio_kernel/tbio.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) International Business Machines Corp., 2001 + * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * In this header file keep all flags and other + * structures that will be needed in both kernel + * and user space. Specifically the ioctl flags + * will go in here so that in user space a program + * can specify flags for the ioctl call. + * + * HISTORY : + * 11/19/2003 Kai Zhao (lt...@cn...) + * + * CODE COVERAGE: 74.9% - fs/bio.c (Total Coverage) + * + */ + +#define TMOD_DRIVER_NAME "ltp test block I/O layer module" +#define TBIO_DEVICE_NAME "ltp_tbio" +#define DEVICE_NAME "/dev/tbio" +#define MAG_NUM 'k' +int TBIO_MAJOR; + +#define TBIO_TO_DEV 1 +#define TBIO_FROM_DEV 2 + +/* put ioctl flags here, use the _IO macro which is + found in linux/ioctl.h, takes a letter, and an + integer */ + +#define LTP_TBIO_CLONE _IO(MAG_NUM,1) +#define LTP_TBIO_ALLOC _IO(MAG_NUM,2) +#define LTP_TBIO_GET_NR_VECS _IO(MAG_NUM,3) +#define LTP_TBIO_PUT _IO(MAG_NUM,4) +#define LTP_TBIO_SPLIT _IO(MAG_NUM,5) +#define LTP_TBIO_DO_IO _IO(MAG_NUM,6) +#define LTP_TBIO_ADD_PAGE _IO(MAG_NUM,7) + +/* memory between the kernel and user space is + seperated, so that if a structure is needed + to be passed between kernel and user space + a call must be made to copy_to_user or copy + from user. Use this structure to streamline + that process. For example: A function that + writes to a disc takes in a ki_write_t + pointer from userspace. In the user space + program specify the length of the pointer as + in_len, and in_data as the actual structure. */ + +struct tbio_interface { + void *data; /* input data */ + int data_len; /* input data length */ + int direction; /* read or write form DEV */ + char *cmd; /* read or write */ + int cmd_len; /* length of cmd */ +}; +typedef struct tbio_interface tbio_interface_t; diff --git a/testcases/kernel/device-drivers/tbio/tbio_user/.gitignore b/testcases/kernel/device-drivers/tbio/tbio_user/.gitignore new file mode 100644 index 0000000..79076dc --- /dev/null +++ b/testcases/kernel/device-drivers/tbio/tbio_user/.gitignore @@ -0,0 +1 @@ +/tbio diff --git a/testcases/kernel/device-drivers/block/block_dev_user/Makefile b/testcases/kernel/device-drivers/tbio/tbio_user/Makefile similarity index 100% copy from testcases/kernel/device-drivers/block/block_dev_user/Makefile copy to testcases/kernel/device-drivers/tbio/tbio_user/Makefile diff --git a/testcases/kernel/device-drivers/tbio/tbio_user/tbio.c b/testcases/kernel/device-drivers/tbio/tbio_user/tbio.c new file mode 100644 index 0000000..81085a3 --- /dev/null +++ b/testcases/kernel/device-drivers/tbio/tbio_user/tbio.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) International Business Machines Corp., 2001 + * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * This is the main of your user space test program, + * which will open the correct kernel bioule, find the + * file descriptor value and use that value to make + * ioctl calls to the system + * + * Use the ki_generic and other ki_testname functions + * to abstract the calls from the main + * + * FILE : user_tbio.c + * USAGE : kernel_space:./load_tbio.sh + * user_space :./test_bio + * + * DESCRIPTION : The bioule will test block i/o layer for kernel 2.5 + * REQUIREMENTS: + * 1) glibc 2.1.91 or above. + * + * HISTORY : + * 11/19/2003 Kai Zhao (lt...@cn...) + * + * CODE COVERAGE: 74.9% - fs/bio.c (Total Coverage) + * + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <linux/kernel.h> +#include <unistd.h> +#include <string.h> + +#include "test.h" +#include "usctest.h" +#include "safe_macros.h" +#include "tst_module.h" + +#include "../tbio_kernel/tbio.h" + +char *TCID = TBIO_DEVICE_NAME; + +static const char module_name[] = "ltp_tbio.ko"; +static int module_loaded; +static int tbio_fd = -1; + +void cleanup(void) +{ + + if (tbio_fd != -1) { + close(tbio_fd); + tbio_fd = -1; + } + + if (module_loaded) + tst_module_unload(NULL, module_name); + + TEST_CLEANUP; +} + + +void setup(void) +{ + tst_require_root(NULL); + + if (tst_kvercmp(2, 6, 0) < 0) { + tst_brkm(TCONF, NULL, + "Test must be run with kernel 2.6 or newer"); + } + + tst_module_load(cleanup, module_name, NULL); + module_loaded = 1; + + dev_t devt; + struct stat st; + + SAFE_FILE_SCANF(cleanup, "/sys/class/block/tbio/dev", + "%d:0", &TBIO_MAJOR); + + devt = makedev(TBIO_MAJOR, 0); + /* + * Check for the /dev/tbase node, and create if it does not + * exist. + */ + errno = 0; + if (stat(DEVICE_NAME, &st)) { + if (errno == ENOENT) { + /* dev node does not exist */ + if (mknod(DEVICE_NAME, S_IFCHR | S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP, devt)) { + tst_brkm(TBROK | TERRNO, cleanup, + "mknod failed at %s:%d", + __FILE__, __LINE__); + } + } else { + tst_brkm(TBROK | TERRNO, cleanup, + "problem with tbase device node directory"); + } + } else { + /* + * /dev/tbio CHR device exists. Check to make sure it is for a + * block device and that it has the right major and minor. + */ + if ((!(st.st_mode & S_IFCHR)) || (st.st_rdev != devt)) { + /* Recreate the dev node */ + if (!unlink(DEVICE_NAME)) { + if (mknod(DEVICE_NAME, S_IFCHR | S_IRUSR | + S_IWUSR | S_IRGRP | S_IWGRP, devt)) { + tst_brkm(TBROK | TERRNO, cleanup, + "mknod failed at %s:%d", + __FILE__, __LINE__); + } + } else { + tst_brkm(TBROK | TERRNO, cleanup, + "unlink failed"); + } + } + } + + tbio_fd = open(DEVICE_NAME, O_RDWR); + if (tbio_fd < 0) { + tst_brkm(TBROK | TERRNO, cleanup, "open of %s failed", + DEVICE_NAME); + } + + tst_resm(TINFO, "Device opened successfully "); +} + + +int tbio_to_dev(int fd, int flag) +{ + int rc; + tbio_interface_t bif; + + memset(&bif, 0, sizeof(tbio_interface_t)); + rc = posix_memalign(&bif.data, 512, 1024); + if (rc) { + tst_resm(TINFO, "posix_memalign failed"); + return -1; + } + + strcpy(bif.data, "User space data"); + bif.data_len = 1024; + bif.direction = TBIO_TO_DEV; + bif.cmd = SAFE_MALLOC(cleanup, 6); + if (bif.cmd == NULL) { + tst_resm(TINFO, "malloc cmd space failed"); + free(bif.data); + return -1; + } + strcpy(bif.cmd, "WRITE"); + bif.cmd_len = 6; + + rc = ioctl(fd, flag, &bif); + if (rc) { + free(bif.data); + free(bif.cmd); + tst_resm(TINFO, "Ioctl error for TBIO_TO_DEV"); + return rc; + } + + free(bif.data); + free(bif.cmd); + + return 0; + +} + +int tbio_from_dev(int fd, int flag) +{ + int rc; + tbio_interface_t bif; + + memset(&bif, 0, sizeof(tbio_interface_t)); + rc = posix_memalign(&bif.data, 512, 1024); + if (rc) { + tst_resm(TINFO, "posix_memalign failed"); + return -1; + } + + memset(bif.data, 0, 1024); + + bif.data_len = 1024; + bif.direction = TBIO_FROM_DEV; + bif.cmd = SAFE_MALLOC(cleanup, 6); + if (bif.cmd == NULL) { + tst_resm(TINFO, "malloc cmd space failed"); + free(bif.data); + return -1; + } + strcpy(bif.cmd, "READ"); + bif.cmd_len = 6; + + rc = ioctl(fd, flag, &bif); + if (rc) { + free(bif.data); + free(bif.cmd); + tst_resm(TINFO, "Ioctl error for TBIO_TO_DEV"); + return rc; + } + + if (strcmp(bif.data, "User space data")) { + tst_resm(TINFO, "TBIO_FROM_DEV failed"); + free(bif.data); + free(bif.cmd); + return -1; + } + + free(bif.data); + free(bif.cmd); + + return 0; + +} + +int tbio_split_to_dev(int fd, int flag) +{ + int rc; + tbio_interface_t bif; + + memset(&bif, 0, sizeof(tbio_interface_t)); + rc = posix_memalign(&bif.data, 512, 2048); + if (rc) { + tst_resm(TINFO, "posix_memalign failed"); + return -1; + } + + strcpy(bif.data, "User space data"); + bif.data_len = 2048; + bif.direction = TBIO_TO_DEV; + bif.cmd = SAFE_MALLOC(cleanup, 6); + if (bif.cmd == NULL) { + tst_resm(TINFO, "malloc cmd space failed"); + free(bif.data); + return -1; + } + strcpy(bif.cmd, "WRITE"); + bif.cmd_len = 6; + + rc = ioctl(fd, flag, &bif); + if (rc) { + free(bif.data); + free(bif.cmd); + tst_resm(TINFO, "Ioctl error for TBIO_TO_DEV"); + return rc; + } + + free(bif.data); + free(bif.cmd); + + return 0; + +} + +int ki_generic(int fd, int flag) +{ + tbio_interface_t bif; + + int rc = ioctl(fd, flag, &bif); + if (rc) + tst_resm(TINFO | TERRNO, "ioctl error"); + + return rc; +} + + +int main(void) +{ + setup(); + + if (ki_generic(tbio_fd, LTP_TBIO_ALLOC)) + tst_resm(TFAIL, "failed on LTP_TBIO_ALLOC test"); + else + tst_resm(TPASS, "success on LTP_TBIO_ALLOC test"); + + if (ki_generic(tbio_fd, LTP_TBIO_CLONE)) + tst_resm(TFAIL, "failed on LTP_TBIO_CLONE test"); + else + tst_resm(TPASS, "success on LTP_TBIO_CLONE test"); + + if (ki_generic(tbio_fd, LTP_TBIO_GET_NR_VECS)) + tst_resm(TFAIL, "failed on LTP_TBIO_GET_NR_VECS test"); + else + tst_resm(TPASS, "success on LTP_TBIO_GET_NR_VECS test"); + + if (ki_generic(tbio_fd, LTP_TBIO_ADD_PAGE)) + tst_resm(TFAIL, "failed on LTP_TBIO_ADD_PAGE test"); + else + tst_resm(TPASS, "success on LTP_TBIO_ADD_PAGE test"); + + if (tbio_split_to_dev(tbio_fd, LTP_TBIO_SPLIT)) + tst_resm(TFAIL, "failed on LTP_TBIO_SPLIT:write to dev"); + else + tst_resm(TPASS, "success on LTP_TBIO_SPLIT:write to dev"); + + if (tbio_to_dev(tbio_fd, LTP_TBIO_DO_IO)) + tst_resm(TFAIL, "failed on LTP_TBIO_DO_IO:write to dev"); + else + tst_resm(TPASS, "success on LTP_TBIO_DO_IO:write to dev"); + + if (tbio_from_dev(tbio_fd, LTP_TBIO_DO_IO)) + tst_resm(TFAIL, "failed on LTP_TBIO_DO_IO:read from dev"); + else + tst_resm(TPASS, "success on LTP_TBIO_DO_IO:read from dev"); + + if (ki_generic(tbio_fd, LTP_TBIO_PUT)) + tst_resm(TFAIL, "failed on LTP_TBIO_PUT test"); + else + tst_resm(TPASS, "success on LTP_TBIO_PUT test"); + + cleanup(); + + tst_exit(); +} diff --git a/testcases/kernel/device-drivers/tbio/user_space/Makefile b/testcases/kernel/device-drivers/tbio/user_space/Makefile deleted file mode 100644 index 9fe124e..0000000 --- a/testcases/kernel/device-drivers/tbio/user_space/Makefile +++ /dev/null @@ -1,9 +0,0 @@ - -CFLAGS += -O2 -Wall -W -g -OBJS = tbio_ki.o user_tbio.o - -test_bio: $(OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ - -clean: - rm -f $(OBJS) test_bio diff --git a/testcases/kernel/device-drivers/tbio/user_space/tbio_ki.c b/testcases/kernel/device-drivers/tbio/user_space/tbio_ki.c deleted file mode 100644 index b5d6d46..0000000 --- a/testcases/kernel/device-drivers/tbio/user_space/tbio_ki.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - * This file will include user space functions that will drive - * the kernel module to test various functions and kernel - * calls. Each function will need to setup the tif structure - * so that the in parameters and out parameters are correctly - * initialized - * - * use bif structure for passing params between user - * space and kernel space, in some tests it is really not - * needed, and if nothing is needed to pass in utilize - * the ki_generic function below. the tif structure makes - * it easy to maintain all the tests if they have the same - * process in kernel space to read in params in the kernel - * module no matter what the test is - * - * module: tbio - * Copyright (c) International Business Machines Corp., 2003 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; - * - * FILE : tbio_ki.c - * USAGE : kernel_space:./load_tbio.sh - * user_space :./test_bio - * - * DESCRIPTION : The module will test block i/o layer for kernel 2.5 - * REQUIREMENTS: - * 1) glibc 2.1.91 or above. - * - * HISTORY : - * 11/19/2003 Kai Zhao (lt...@cn...) - * - * CODE COVERAGE: 74.9% - fs/bio.c (Total Coverage) - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <sys/ioctl.h> -#include "../kernel_space/tbio.h" - -int ki_generic(int fd, int flag) -{ - int rc; - tbio_interface_t bif; - - rc = ioctl(fd, flag, &bif); - if (rc) { - printf("Ioctl error\n"); - return rc; - } - - return rc; -} - -#if 0 - -#endif diff --git a/testcases/kernel/device-drivers/tbio/user_space/user_tbio.c b/testcases/kernel/device-drivers/tbio/user_space/user_tbio.c deleted file mode 100644 index d3e88d1..0000000 --- a/testcases/kernel/device-drivers/tbio/user_space/user_tbio.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * - * Copyright (c) International Business Machines Corp., 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - * This is the main of your user space test program, - * which will open the correct kernel bioule, find the - * file descriptor value and use that value to make - * ioctl calls to the system - * - * Use the ki_generic and other ki_testname functions - * to abstract the calls from the main - * - * bioule: tbio - * Copyright (c) International Business Machines Corp., 2003 - * - * This program is free software; you can redistribute it and/or bioify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; - * - * FILE : user_tbio.c - * USAGE : kernel_space:./load_tbio.sh - * user_space :./test_bio - * - * DESCRIPTION : The bioule will test block i/o layer for kernel 2.5 - * REQUIREMENTS: - * 1) glibc 2.1.91 or above. - * - * HISTORY : - * 11/19/2003 Kai Zhao (lt...@cn...) - * - * CODE COVERAGE: 74.9% - fs/bio.c (Total Coverage) - * - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <linux/kernel.h> - -#include "user_tbio.h" -#include "../kernel_space/tbio.h" - -static int tbio_fd = -1; /* file descriptor */ - -int tbioopen() -{ - - dev_t devt; - struct stat st; - int rc = 0; - - devt = makedev(TBIO_MAJOR, 0); - - if (rc) { - if (errno == ENOENT) { - /* dev node does not exist. */ - rc = mkdir(DEVICE_NAME, (S_IFDIR | S_IRWXU | - S_IRGRP | S_IXGRP | - S_IROTH | S_IXOTH)); - } else { - printf - ("ERROR: Problem with Base dev directory. Error code from stat() is %d\n\n", - errno); - } - - } else { - if (!(st.st_mode & S_IFDIR)) { - rc = unlink(DEVICE_NAME); - if (!rc) { - rc = mkdir(DEVICE_NAME, (S_IFDIR | S_IRWXU | - S_IRGRP | S_IXGRP | - S_IROTH | S_IXOTH)); - } - } - } - - /* - * Check for the /dev/tbase node, and create if it does not - * exist. - */ - rc = stat(DEVICE_NAME, &st); - if (rc) { - if (errno == ENOENT) { - /* dev node does not exist */ - rc = mknod(DEVICE_NAME, - (S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | - S_IWGRP), devt); - } else { - printf - ("ERROR:Problem with tbase device node directory. Error code form stat() is %d\n\n", - errno); - } - - } else { - /* - * /dev/tbio CHR device exists. Check to make sure it is for a - * block device and that it has the right major and minor. - */ - if ((!(st.st_mode & S_IFCHR)) || (st.st_rdev != devt)) { - - /* Recreate the dev node. */ - rc = unlink(DEVICE_NAME); - if (!rc) { - rc = mknod(DEVICE_NAME, - (S_IFCHR | S_IRUSR | S_IWUSR | - S_IRGRP | S_IWGRP), devt); - } - } - } - - tbio_fd = open(DEVICE_NAME, O_RDWR); - - if (tbio_fd < 0) { - printf("ERROR: Open of device %s failed %d errno = %d\n", - DEVICE_NAME, tbio_fd, errno); - return errno; - } else { - printf("Device opened successfully \n"); - return 0; - } - -} - -int tbioclose() -{ - - if (tbio_fd != -1) { - close(tbio_fd); - tbio_fd = -1; - } - - return 0; -} - -int tbio_to_dev(int fd, int flag) -{ - int rc; - tbio_interface_t bif; - - memset(&bif, 0, sizeof(tbio_interface_t)); - rc = posix_memalign(&bif.data, 512, 1024); - if (rc) { - printf("posix_memalign failed\n"); - return -1; - } - - strcpy(bif.data, "User space data"); - bif.data_len = 1024; - bif.direction = TBIO_TO_DEV; - bif.cmd = (char *)malloc(6); - if (bif.cmd == NULL) { - printf("malloc cmd space failed\n"); - free(bif.data); - return -1; - } - strcpy(bif.cmd, "WRITE"); - bif.cmd_len = 6; - - rc = ioctl(fd, flag, &bif); - if (rc) { - free(bif.data); - free(bif.cmd); - printf("Ioctl error for TBIO_TO_DEV\n"); - return rc; - } - - free(bif.data); - free(bif.cmd); - - return 0; - -} - -int tbio_from_dev(int fd, int flag) -{ - int rc; - tbio_interface_t bif; - - memset(&bif, 0, sizeof(tbio_interface_t)); - rc = posix_memalign(&bif.data, 512, 1024); - if (rc) { - printf("posix_memalign failed\n"); - return -1; - } - - memset(bif.data, 0, 1024); - - bif.data_len = 1024; - bif.direction = TBIO_FROM_DEV; - bif.cmd = (char *)malloc(6); - if (bif.cmd == NULL) { - printf("malloc cmd space failed\n"); - free(bif.data); - return -1; - } - strcpy(bif.cmd, "READ"); - bif.cmd_len = 6; - - rc = ioctl(fd, flag, &bif); - if (rc) { - free(bif.data); - free(bif.cmd); - printf("Ioctl error for TBIO_TO_DEV\n"); - return rc; - } - //printf("read from dev %s\n",bif.data); - if (strcmp(bif.data, "User space data")) { - printf("TBIO_FROM_DEV failed\n"); - free(bif.data); - free(bif.cmd); - return -1; - } - - free(bif.data); - free(bif.cmd); - - return 0; - -} - -int tbio_split_to_dev(int fd, int flag) -{ - int rc; - tbio_interface_t bif; - - memset(&bif, 0, sizeof(tbio_interface_t)); - rc = posix_memalign(&bif.data, 512, 2048); - if (rc) { - printf("posix_memalign failed\n"); - return -1; - } - - strcpy(bif.data, "User space data"); - bif.data_len = 2048; - bif.direction = TBIO_TO_DEV; - bif.cmd = (char *)malloc(6); - if (bif.cmd == NULL) { - printf("malloc cmd space failed\n"); - free(bif.data); - return -1; - } - strcpy(bif.cmd, "WRITE"); - bif.cmd_len = 6; - - rc = ioctl(fd, flag, &bif); - if (rc) { - free(bif.data); - free(bif.cmd); - printf("Ioctl error for TBIO_TO_DEV\n"); - return rc; - } - - free(bif.data); - free(bif.cmd); - - return 0; - -} - -int main() -{ - int rc; - - /* open the bioule */ - rc = tbioopen(); - if (rc) { - printf("Test bio Driver may not be loaded\n"); - exit(1); - } - - if (ki_generic(tbio_fd, LTP_TBIO_ALLOC)) - printf("Failed on LTP_TBIO_ALLOC test\n"); - else - printf("Success on LTP_TBIO_ALLOC test\n"); - - if (ki_generic(tbio_fd, LTP_TBIO_CLONE)) - printf("Failed on LTP_TBIO_CLONE test\n"); - else - printf("Success on LTP_TBIO_CLONE test\n"); - - if (ki_generic(tbio_fd, LTP_TBIO_GET_NR_VECS)) - printf("Failed on LTP_TBIO_GET_NR_VECS test\n"); - else - printf("Success on LTP_TBIO_GET_NR_VECS test\n"); - - if (ki_generic(tbio_fd, LTP_TBIO_ADD_PAGE)) - printf("Failed on LTP_TBIO_ADD_PAGE test\n"); - else - printf("Success on LTP_TBIO_ADD_PAGE test\n"); - - if (tbio_split_to_dev(tbio_fd, LTP_TBIO_SPLIT)) - printf("Failed on LTP_TBIO_SPLIT:write to dev\n"); - else - printf("Success on LTP_TBIO_SPLIT:write to dev\n"); - - if (tbio_to_dev(tbio_fd, LTP_TBIO_DO_I... [truncated message content] |