[go: up one dir, main page]

0% found this document useful (0 votes)
169 views34 pages

Block Device Drivers: - Naga Manjunath Senior S/W Engg in Bosch

This document discusses block device drivers in Linux and provides code for a simple block device driver called sbull. It includes functions for initializing and registering the driver, allocating a RAM disk, handling read/write requests, and removing the driver. The code simulates a 10MB ramdisk with one partition. Later sections discuss extending sbull to support multiple partitions through additional functions and data structures. Lab exercises walk through compiling, loading and testing the basic and extended drivers.

Uploaded by

Naga Manjunath
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
169 views34 pages

Block Device Drivers: - Naga Manjunath Senior S/W Engg in Bosch

This document discusses block device drivers in Linux and provides code for a simple block device driver called sbull. It includes functions for initializing and registering the driver, allocating a RAM disk, handling read/write requests, and removing the driver. The code simulates a 10MB ramdisk with one partition. Later sections discuss extending sbull to support multiple partitions through additional functions and data structures. Lab exercises walk through compiling, loading and testing the basic and extended drivers.

Uploaded by

Naga Manjunath
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 34

Block Device Drivers

-Naga Manjunath Senior s\w Engg in Bosch

Linux Device Driver Architecture

Quick Functions Reference


#include <Linux/fs.h>
int register_blkdev(unsigned int major, const char *name); int unregister_blkdev(unsigned int major, const char *name); struct block_device_operations

#include <linux/genhd.h>
struct gendisk *alloc_disk(int minors); void add_disk(struct gendisk *gd); void set_capacity(struct gendisk *gd, setor_t sectors);

Quick Functions Reference


(cont)

#include <linux/fs.h>
struct block_device_operations

#include<linuix/genhd.h>
struct gendisk

#include <linux/blkdev.h>
struct request

struct gendisk

struct block_device_operations

Needed files:
sbull.c Makefile

Simple block device driver: sbull

Driver description:
it allocates 10 MB memory space to simulate a ramdisk which is like you insert a disk into the system the ramdisk has only one partition many file operations can be performed on it
mkfs, mount, umount, cp, ls, <

Simple block device driver: sbull (cont)


Needed functions:
sbull_init() sbull_exit() sbull_open() sbull_release() sbull_request() sbull_transfer()

Source code of sbull.c


#include #include #include #include #include #include #include #include <linux/init.h> <linux/module.h> <linux/kernel.h> <linux/fs.h> <linux/genhd.h> <linux/blkdev.h> <linux/vmalloc.h> <linux/hdreg.h>

include and define

#define KERNEL_SECTOR_SIZE 512

// define sector size is 512 in kernel

// HARDWARE define (ramdisksize = 20000*512 = 10M bytes) int nsectors = 20000; // number of sectors int hardsector_size = 512; // sector size = 512 bytes int dev_major_nr = 0; // system automatically allocate major number int SBULL_MINORS = 1; // MAX minor number is 1 ,ie.only one partition char dev_name[8] = "sbull"; MODULE_AUTHOR(MANJU"); MODULE_LICENSE("DualBSD/GPL");

Source code of sbull.c (cont)


struct sbull_dev { unsigned long size; unsigned char *data; spinlock_t lock; struct gendisk *gd; struct block_device *bdev; }Device;

struct and function prototype

static struct sbull_dev *dev = &Device; // function prototype static int sbull_open(struct inode *inode, struct file *filp); static int sbull_release(struct inode *inode, struct file *filp); static void sbull_transfer(struct sbull_dev *dev, unsigned long sector,unsigned long nsect, char *buffer, int write); static void sbull_request(request_queue_t *q);

Source code of sbull.c (cont)


static struct block_device_operations sbull_ops = { .owner = THIS_MODULE, .open = sbull_open, .release = sbull_release };

struct Device and open, release methods

static int sbull_open(struct inode *inode, struct file *filp) { printk("sbull_open(): do nothing...\n"); return 0; } static int sbull_release(struct inode *inode, struct file *filp) { printk("sbull_release(): do nothing...\n"); return 0; }

Source code of sbull.c (cont)


static int sbull_init(void) { printk("sbull_init(): initial sbull...\n"); // initial struct sbull_dev dev_major_nr = register_blkdev(dev_major_nr, dev_name); if (dev_major_nr <= 0) { printk("sbull_init(): unable to get major number\n"); return 0; } memset(dev, 0, sizeof(struct sbull_dev)); dev->size = nsectors * hardsector_size; dev->data = vmalloc(dev->size); if (dev->data == NULL) { printk("sbull_init(): vmalloc failure.\n"); return 0; } // initial spinlock spin_lock_init(&dev->lock);

sbull_init method

Source code of sbull.c (cont)


// initial gendisk struct *gd dev->gd = alloc_disk(SBULL_MINORS); if (!dev->gd) { printk("sbull_init(): allocate disk failure.\n"); return 0; } dev->gd->major = dev_major_nr; dev->gd->first_minor = 0; dev->gd->fops = &sbull_ops; // file operations pointer dev->gd->private_data= dev; // for private use strcpy(dev->gd->disk_name, "sbulla"); // device name is sbulla set_capacity(dev->gd, nsectors); // initial queue dev->gd->queue = blk_init_queue(sbull_request, &dev->lock); add_disk(dev->gd); return 0; }

sbull_init method: (cont)

Source code of sbull.c (cont)

sbull_request method

static void sbull_request(request_queue_t *q) { struct request *req; while((req = elv_next_request(q)) != NULL) { struct sbull_dev *dev = req->rq_disk->private_data; if( !blk_fs_request(req)) { If non-fs request here, end_request(req,0); do nothing } else { next sector to submit no. of sectors to submit sbull_transfer(dev, req->sector, req->current_nr_sectors, req->buffer, rq_data_dir(req)); end_request(req,1); } } decide the transfer dir. }

Source code of sbull.c (cont)


sbull_transfer method
static void sbull_transfer(struct sbull_dev *dev, unsigned long sector, unsigned long nsect, char *buffer, int write) { unsigned long offset = sector * KERNEL_SECTOR_SIZE; unsigned long nbytes = nsect * KERNEL_SECTOR_SIZE; if( (offset + nbytes) > dev->size ) { printk(KERN_NOTICE "beyond-end write (%ld %ld)\n", offset, nbytes); return; } if(write) memcpy(dev->data + offset, buffer, nbytes); else memcpy(buffer, dev->data + offset, nbytes); }

Source code of sbull.c (cont)


sbull_exit method and module-related macros

static void sbull_exit(void) { printk("sbull_exit(): exit sbull...\n"); del_gendisk(dev->gd); put_disk(dev->gd); unregister_blkdev(dev_major_nr, dev_name); vfree(dev->data); } module_init(sbull_init); module_exit(sbull_exit);

The Makefile of sbull


# Makefilefor sbull.c(kernel 2.6.x) # If KERNELRELEASE is defined, we've been invoked from the # kernel build system and can use its language. ifneq ($(KERNELRELEASE),) obj-m := sbull.o # Otherwise we were called directly from the command # line; invoke the kernel build system. else KDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: rm rf *.o *.ko *.mod.c endif

LAB 1
Create the simple block device driver and insert into the kernel:
make sudo insmod sbull.ko cat /proc/devices | grep sbull

LAB 1 (cont)
Create the device node and mount it:
sudo mknod /dev/sbulla b XXX 0
replaces XXX to the major number you get above Ubuntu may create the /dev/sbulla for us

sudo mkfs.ext2 /dev/sbulla mkdir temp sudo mount /dev/sbulla temp df

LAB 1 (cont)

LAB 1 (cont)
Test the read and write abilities:
cd temp sudo mkdir HANEL cd .. sudo umount temp mkdir temp2 sudo mount /dev/sbulla temp2 ls temp2

LAB 1 (cont)

LAB 1 (cont)
Remove the sbull module from the kernel:
sudo umount temp2 sudo rmmod sbull
Ubuntu will also clear the /dev/sbulla for us

LAB 2
In this exercise, a extended version sbull will be introduced
it allocates 10 MB memory space to simulate a ramdisk which is like you insert a disk into the system the ramdisk has 2 partitions (partitionable) many file operations can be performed on it
mkfs, mount, umount, cp, ls, <

LAB 2 (cont)
In order to let the sbull able to be partitioned, there are something needed be done:
sets SBULL_MINORS to 2 adds new structure member short users in sbull_dev adds one new function in sbull_ops structure alters the sbull_open and sbull_release functions

LAB 2 (cont)

The structure method sbull_ioctl

int sbull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { long size; struct hd_geometry geo; struct sbull_dev *dev = filp->private_data; switch(cmd) { case HDIO_GETGEO: size = dev->size; geo.cylinders= (size & ~0x3f) >> 6; geo.heads= 4; geo.sectors= 16; geo.start= 4; if (copy_to_user((void __user *) arg, &geo, sizeof(geo))) return -EFAULT; return 0; } return -ENOTTY; /* unknown command */

Provides the geometry information

LAB 2 (cont)
The functions sbull_open and sbull_release
static int sbull_open(struct inode *inode, struct file *filp) { struct sbull_dev *dev = inode->i_bdev->bd_disk->private_data; filp->private_data= dev; spin_lock(&dev->lock); dev->users++; spin_unlock(&dev->lock); return 0; } static int sbull_release(struct inode *inode, struct file *filp) { struct sbull_dev *dev = inode->i_bdev->bd_disk->private_data; spin_lock(&dev->lock); dev->users--; spin_unlock(&dev->lock); return 0; }

LAB 2 (cont)
Test the extended sbull modules:
make clean make sudo insmod sbull.ko sudo fdisk H 16 /dev/sbulla

LAB 2 (cont)

LAB 2 (cont)
Now we have two partitions in the sbull ramdisk Formats they by the following instructions: sudo mkfs.ext2 /dev/sbulla1 sudo mkfs.ext2 /dev/sbulla2 sudo mount /dev/sbulla1 temp sudo mount /dev/sbulla2 temp2 df

LAB 3
Please format the sbull in LAB1 by instruction: sudo mkfs.vfat F16 /dev/sbulla and observe what happened Try the same instruction executed on the sbulla in LAB2 Based on the LAB2, give me one block device with: 20MB and can be partitioned automatically: you can consult the sbull of LDD here

LAB 3 (cont)

LAB 3
There are two errors in the sbull of OReilly:
comment out the #include <linux/config.h> change the line 181
from end_that_request_last(req); to end_that_request_last(req, 1);

if you want to try that one, just type:


make sudo insmod sbull.ko ls al /dev/sbull*

Reference
Driver porting: a simple block driver Linux Device Drivers 3rd Edition Cross-Referencing Linux Linux Block Device Architecture

You might also like