Block device driver
Привет всем!
Есть задача изготовления драйвера блочного устройства. В нём нужно делать I/O к другим дископодобным девайсам ... Гуглил, читал LDD, LDD3 ... но видимо что-то всё равно упускаю ...
Есть тут кто имеет предметный опыт написания ? В качестве первого вопроса: после инсталляции модуля в dmesg появляется «cut -here» секция, что это означает ? Что-то пошло не так, или это информационный блок ?
root@sysman:/home/sysman/Works/vCloud/block# insmod dudriver.ko
root@sysman:/home/sysman/Works/vCloud/block#
[ 4174.458121] DUDRIVER: Initialize the driver ...
[ 4174.458123] [DUDRIVER:458] : Assigned major = 252
[ 4174.458125] [DUDRIVER:367] : [ffff97cb191ebf60] Begin setup device, mode = 0 ...
[ 4174.458238] blk_queue_max_segment_size: set to minimum 4096
[ 4174.458240] [DUDRIVER:388] : [ffff97cb191ebf60] Opening ...
[ 4174.458253] [DUDRIVER:402] : [ffff97cb191ebf60] Opened, iodevfp = ffff97cab93aef00.
[ 4174.458257] [DUDRIVER:425] : [ffff97cb191ebf60] disk_name = dua, iobuf = ffff97cace83cc00
[ 4174.458259] ------------[ cut here ]------------
[ 4174.458265] WARNING: CPU: 2 PID: 5049 at /build/linux-hwe-0vY49E/linux-hwe-4.10.0/block/genhd.c:596 device_add_disk+0x2cf/0x480
[ 4174.458266] Modules linked in: dudriver(OE+) vboxsf(OE) vboxvideo(OE) crct10dif_pclmul crc32_pclmul joydev ghash_clmulni_intel ttm drm_kms_helper drm fb_sys_fops syscopyarea sysfillrect vboxguest(OE) sysimgblt pcbc input_leds mac_hid serio_raw aesni_intel aes_x86_64 crypto_simd glue_helper i2c_piix4 cryptd intel_rapl_perf parport_pc ppdev lp parport autofs4 hid_generic usbhid hid fjes psmouse ahci e1000 libahci video
[ 4174.458283] CPU: 2 PID: 5049 Comm: insmod Tainted: G OE 4.10.0-42-generic #46~16.04.1-Ubuntu
[ 4174.458284] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 4174.458285] Call Trace:
[ 4174.458290] dump_stack+0x63/0x90
[ 4174.458293] __warn+0xcb/0xf0
[ 4174.458294] warn_slowpath_null+0x1d/0x20
[ 4174.458295] device_add_disk+0x2cf/0x480
[ 4174.458298] dua_init+0x2dd/0x1000 [dudriver]
[ 4174.458299] ? 0xffffffffc033d000
[ 4174.458302] do_one_initcall+0x53/0x1c0
[ 4174.458306] ? kmem_cache_alloc_trace+0x152/0x1c0
[ 4174.458308] do_init_module+0x5f/0x1ff
[ 4174.458311] load_module+0x1825/0x1bf0
[ 4174.458312] ? __symbol_put+0x60/0x60
[ 4174.458315] ? ima_post_read_file+0x7d/0xa0
[ 4174.458319] ? security_kernel_post_read_file+0x6b/0x80
[ 4174.458320] SYSC_finit_module+0xdf/0x110
[ 4174.458321] SyS_finit_module+0xe/0x10
[ 4174.458327] entry_SYSCALL_64_fastpath+0x1e/0xad
[ 4174.458328] RIP: 0033:0x7fda77b60499
[ 4174.458329] RSP: 002b:00007ffe49df7778 EFLAGS: 00000206 ORIG_RAX: 0000000000000139
[ 4174.458330] RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fda77b60499
[ 4174.458331] RDX: 0000000000000000 RSI: 0000563ba88dc26b RDI: 0000000000000003
[ 4174.458331] RBP: 00007ffe49df6730 R08: 0000000000000000 R09: 00007fda77e25ea0
[ 4174.458332] R10: 0000000000000003 R11: 0000000000000206 R12: 000000000000006a
[ 4174.458332] R13: 0000563ba92261d0 R14: 0000563ba9226130 R15: 00007ffe49df65fc
[ 4174.458333] ---[ end trace 9676674954dab3b5 ]---
[ 4174.459946] [DUDRIVER:434] : [ffff97cb191ebf60] setup device end (dua)
[ 4174.459947] DUDRIVER: End the driver initialization.
root@sysman:/home/sysman/Works/vCloud/block#
Следующая проблема связана с I/O из модуля, похоже что нет возврата из vfs_read/vfs_write , сужу по dmesg, не выходим на «Checking read/write status».
/**
* @brief xfer - Handle an I/O request.
*
* @param dcb - device context block
*
* @param lbn - Logical Block Number
* @param bcnt - a length of the data in the I/O buffer
* @param buff - I/O buffer
* @param iodir - I/O direction: 0 - READ, 1 - WRITE
*
* @return - 0 > : bytes count has beed read/wrote
* - 0 <= errno
*/
static int xfer (
DRIVER_CTX * dctx,
sector_t lbn,
size_t bcnt,
char * iobuf,
int iodir
)
{
loff_t pos = lbn * DUDRV$K_BLKSZ;
size_t status64 = bcnt;
mm_segment_t old_fs;
$TRACE( ": [%p] Start I/O : iodevfp=%p lbn=%lu bcnt=%lu iobuf=%p iodir=%d", dctx, dctx->iodevfp, lbn, bcnt, iobuf, iodir);
if ( !dctx || !dctx->iodevfp )
{
printk(KERN_ERR __MODULE__ ": [%p] %s(%p) -> EIO\n", dctx,
iodir == WRITE ? "write" : "read", dctx->iodevfp);
return -EIO;
}
if ( iodir == WRITE )
copy_to_user (dctx->iobuf, iobuf, DUDRV$K_BLKSZ);
old_fs = get_fs();
set_fs(get_ds());
if ( iodir == WRITE )
status64 = vfs_write(dctx->iodevfp, dctx->iobuf, bcnt, &pos);
else status64 = vfs_read(dctx->iodevfp, dctx->iobuf, bcnt, &pos);
set_fs( old_fs );
$TRACE("Checking read/write status = %ld ...", status64);
if ( bcnt != status64 )
printk(KERN_ERR __MODULE__ ": [%p] %s(%p, %lu octets, pos = %llu) -> %lu\n", dctx,
iodir == WRITE ? "write" : "read", dctx->iodevfp, bcnt, pos, status64);
if ( iodir == READ )
copy_from_user (iobuf, dctx->iobuf, DUDRV$K_BLKSZ);
$TRACE( ": [%p] End I/O : pos=%llu bcnt=%lu iobuf=%p iodir=%d, status = %ld", dctx, pos, bcnt, iobuf, iodir, status64);
return status64;
}
Буду благодарен за любую помощь.