Re: About bio_endio

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx> wrote:
Hello Alvin,

On Mon, Jun 23, 2014 at 10:39 PM, Alvin Abitria <abitria.alvin@xxxxxxxxx> 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@xxxxxxxxxxxxxxxxx
> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>



--
        ---P.K.S
Alvin
_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux