Hello Pranay! Thanks for your reply. I apologize for my very late reply, I was very preoccupied earlier at work. On Tue, Jun 24, 2014 at 1:07 PM, Pranay Srivastava <pranjas@gmail.com> wrote:
Hello Alvin,
On Mon, Jun 23, 2014 at 10:39 PM, Alvin Abitria <abitria.alvin@gmail.com> wrote:
Hello,
I'm developing a block driver using the make_request method, effectively bypassing existing scsi or request stack in block layer. So that means im directly working with bios. As prescribed in linux documentation and from referring to similar drivers in kernel, you close a session with a bio with the bio_endio function.
So it means you are just passing on the bios without the request structure if I'm correct? I don't know how you are handling blk_finish_plug without having request or request queue, I maybe wrong in understanding how you are handling it.
Yes, I'm working on bio's level. No struct requests, and I haven't used blk_finish_plug yet. The block driver method I'm implementing is somewhat along the same line with nvme and mtip2xxx drivers in drivers/block directory (but differing in hardware specific level of course).
I usually invoke bio_endio during successful I/O completion, meaning
with an
error code of zero. But there are cases that this is not fulfilled or there are error cases. My question is, what are the valid error codes that can be used with it? My initial impression is that other than zero as error code, -EIO is the one that you should use I think, bio_endio will fail. I've read somewhere that -EBUSY is not recognized, and I tried -EIO but my driver crashed. I got a panic in some dio_xxx function leading from bio_endio(bio,-EIO). I would like to block subsequent bios sent
If it's okay for you to post the error then can you do that? I was seeing the code for dio_end_io but it would be good if you can post the exact crash backtrace if you've got that.
Here you go: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [<ffffffff811b9a80>] bio_check_pages_dirty+0x50/0xe0 PGD 42e5e4067 PUD 42e6e7067 PMD 0 Oops: 0000 [#1] SMP last sysfs file: /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size CPU 7 Modules linked in: block_module(U) fuse ip6table_filter ip6_tables ebtable_nat ebtables ipt_MASQUERADE iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack ipt_REJECT xt_CHECKSUM iptable_mangle iptable_filter ip_tables bridge autofs4 sunrpc 8021q garp stp llc cpufreq_ondemand freq_table pcc_cpufreq ipv6 vhost_net macvtap macvlan tun kvm_intel kvm uinput power_meter hpilo hpwdt sg tg3 microcode serio_raw iTCO_wdt iTCO_vendor_support ioatdma dca shpchp ext4 mbcache jbd2 sd_mod crc_t10dif hpsa pata_acpi ata_generic ata_piix dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_wait_scan] Pid: 3740, comm: fio Not tainted 2.6.32-358.el6.x86_64 #1 HP ProLiant DL380p Gen8 RIP: 0010:[<ffffffff811b9a80>] [<ffffffff811b9a80>] bio_check_pages_dirty+0x50/0xe0 RSP: 0018:ffff8804191618c8 EFLAGS: 00010046 RAX: 2000000000000000 RBX: ffff88041909f0c0 RCX: 00000000000011ae RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffff8804191618f8 R08: ffffffff81c07728 R09: 0000000000000040 R10: 0000000000000002 R11: 0000000000000002 R12: 0000000000000000 R13: ffff8804191b9b80 R14: ffff8804191b9b80 R15: 0000000000000000 FS: 00007fcd43e2d720(0000) GS:ffff8800366e0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000041e69f000 CR4: 00000000000407e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process fio (pid: 3740, threadinfo ffff880419160000, task ffff88043341f500) Stack: 0000000000000000 ffff88043433f400 ffff88043433f520 ffff88041909f0c0 <d> ffff88041909f0c0 ffff8804191b9b80 ffff880419161948 ffffffff811bdc38 <d> ffff880419161968 0000000034236400 00000000fffffffb ffff88043433f400 Call Trace: [<ffffffff811bdc38>] dio_bio_complete+0xc8/0xd0 [<ffffffff811bef4f>] dio_bio_end_aio+0x2f/0xd0 [<ffffffff811b920d>] bio_endio+0x1d/0x40 [<ffffffffa02c15a1>] block_make_request+0xe1/0x150 [block_module] [<ffffffff8125ccce>] generic_make_request+0x25e/0x530 [<ffffffff811bae72>] ? bvec_alloc_bs+0x62/0x110 [<ffffffff8125d02d>] submit_bio+0x8d/0x120 [<ffffffff811bdf6c>] dio_bio_submit+0xbc/0xc0 [<ffffffff811be951>] __blockdev_direct_IO_newtrunc+0x631/0xb30 [<ffffffff8111afe3>] ? filemap_fault+0xd3/0x500 [<ffffffff811beeae>] __blockdev_direct_IO+0x5e/0xd0 [<ffffffff811bb280>] ? blkdev_get_blocks+0x0/0xc0 [<ffffffff811bc347>] blkdev_direct_IO+0x57/0x60 [<ffffffff811bb280>] ? blkdev_get_blocks+0x0/0xc0 [<ffffffff8111bb8b>] generic_file_aio_read+0x6bb/0x700 [<ffffffff81166a2a>] ? kmem_getpages+0xba/0x170 [<ffffffff81166f87>] ? cache_grow+0x217/0x320 [<ffffffff811bb893>] blkdev_aio_read+0x53/0xc0 [<ffffffff8111c633>] ? mempool_alloc+0x63/0x140 [<ffffffff811bb840>] ? blkdev_aio_read+0x0/0xc0 [<ffffffff811cadc4>] aio_rw_vect_retry+0x84/0x200 [<ffffffff811cc784>] aio_run_iocb+0x64/0x170 [<ffffffff811cdbb1>] do_io_submit+0x291/0x920 [<ffffffff811ce250>] sys_io_submit+0x10/0x20 [<ffffffff8100b072>] system_call_fastpath+0x16/0x1b Code: 31 e4 45 31 ff eb 15 0f 1f 40 00 0f b7 43 28 41 83 c4 01 41 83 c7 01 44 39 e0 7e 36 4d 63 ec 49 c1 e5 04 4f 8d 2c 2e 49 8b 7d 00 <48> 8b 07 a8 10 75 06 66 a9 00 c0 74 d3 e8 5e 59 f7 ff 49 c7 45 RIP [<ffffffff811b9a80>] bio_check_pages_dirty+0x50/0xe0 RSP <ffff8804191618c8> CR2: 0000000000000000 Basically, after receiving the bio from generic_make_request, I checked and found that I already have the maximum outstanding pending I/O (bios) and couldn't accomodate this bio for now. Rather than just exiting the make_request() routine, I decided to close this bio or return it to kernel via bio_endio(bio, -EIO). No processing or modification was done to the bio, I just used the callback fn above.
to me after reaching my queue depth and with no tags left, and so I want to use bio_endio with an error code.
If you have a request queue then you could call blk_stop_queue and blk_start_queue but I don't know if this is relevant to your case.
I do have a request queue allocated using blk_alloc_queue, but this is more of a dummy queue in my case - I don't use it as much as the struct requests would use it. Its function that I used is for me to register my make_request function, register the maximum I/O size and max number of buffer segments that can be sent to my driver. Thanks for the suggestion, I haven't tried blk_stop_queue and blk_start_queue but I hope it will work. I also like the possibility that you can prevent the upper layers from sending me further bio when my queue depth is full, then letting them know once my driver can accomodate new bios - more of telling them I'm busy right now, don't send me further bios, etc. Is that the general idea behind the two functions you mentioned? I also notice that the two kernel APIs you gave either set/clear a certain request queue flag. I'd like to think that upper layers (generic_make_request etc) check that flag first to decide if it can dispatch bios to my driver, is that right?
What are those error codes, and will they work for my intended function? Thanks!
-EIO should work, but first let's find out why you got the crash.
Thanks. I hope we get to the bottom why it failed and crashed. Let me
know if you have questions.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
-- ---P.K.S
Alvin