Re: ram based block dev driver -- timer function -- async processing

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

 



On Friday 3. April 2009 12.52.51 nidhi mittal wrote:
> Hi all
> [...]
> i have tried all possible code modifications so many of times but each time
> i have to reboot after crash ...and that too doesnt leave any log message

First thing I'm thinking: do you try to dereference NULL somewhere?

> [...] 
> static void init_filtered_linked_list(void)
> {
> /*
>      just initializes frqp --- nothing more than  that  can be ignored
> */
>         frqp=(struct filtered_request_queue*)kzalloc(sizeof(struct
> filtered_request_queue),GFP_KERNEL);

	Normally, this will work out fine, but once in a while, you won't have enough 
memory. You should *really* check this for NULL
type:
if (!frqp) {
 /* do some error-handling, free already allocated memory, terminate 
gracefully etc */
}
>         INIT_LIST_HEAD(&(frqp->link));
>         spin_lock_init(&(frqp->lock));
> }
>
>
>
> static void blkdev_req_fn(struct request_queue *q)
> {
>         struct request *req;
>         struct filtered_request * my_req=NULL;
>         unsigned long  flags=0;
>         while((req = elv_next_request(q)) != NULL){
>                 if(!blk_fs_request(req)){
>                         end_request(req, 0);
>                         continue;
>                 }
>                 blkdev_dequeue_request(req);
>                my_req = (struct filtered_request*)kzalloc(sizeof(struct
> filtered_request),GFP_ATOMIC);
>                 my_req->req=req;

OK, now  you're heading into more dangerous territories. GFP_ATOMIC is a lot 
more sensitive to memory pressure. Thing is, when GFP_ATOMIC, if it cannot 
find free pages right there and then, it won't try to swap things out, it will 
just return NULL. 

The chances for getting nullpointer here is *much* greater than with 
GFP_KERNEL (which is, of course, blocking, as it can shift pages out).

>                 spin_lock_irqsave(&(frqp->lock),flags);
>                 list_add_tail(&(my_req->link),&(frqp->link));
>                 spin_unlock_irqrestore(&(frqp->lock),flags);
>                 printk(KERN_ALERT"i m going out of req function ");
>
>         }//while
> }
>
>
> static void set_timer_req_process(void)
> {
>         init_timer(&timer);
>         timer.function=handle_timer;
>         timer.expires=jiffies+(5*HZ);
>         add_timer(&timer);
> }
>
>
> static void handle_timer(unsigned long data)
> {
>         struct filtered_request *pos;
>         struct request *my_req;
>
>         struct bio_vec *bvec;
>         struct req_iterator iter;
>         struct bio *curr_bio;
>         int i;
>
>         sector_t sector ;
>         int nsect = 0;
>         unsigned long nr_bytes;
>
>         unsigned long  flags;
>         struct blkdev_device *dev;
>         char *buffer;
>         dev = dev_struct;
>
>         spin_lock_irqsave(&(frqp->lock),flags);
>         if(!list_empty(&(frqp->link)))
>         {
>                  list_for_each_entry(pos,&(frqp->link),link)
>                 {
>                         my_req = pos->req;
>                         sector=my_req->sector;
>                         rq_for_each_segment(bvec, my_req, iter)
>                         {
>                             curr_bio = iter.bio;
>                             i=iter.i;

Shouldn't you be careful about using the iterator directly. It was my 
impression that you should do your work on bvec. I may be wrong though.

You're sure that curr_bio is not null etc etc?

>                             buffer =
> __bio_kmap_atomic(curr_bio,i,KM_USER0);
>
> data_transfer(dev,sector,bio_cur_sectors(curr_bio),buffer,
> bio_data_dir(curr_bio) == WRITE);
>                            sector += bio_cur_sectors(curr_bio);
>                            nsect += bio_cur_sectors(curr_bio);
>                            __bio_kunmap_atomic(curr_bio, KM_USER0);
>                         }
>                       nr_bytes=nsect*512;
>                       blk_end_request(my_req,0,nr_bytes)
>                       pos->req=NULL;
>                 }//list_for_each_entry
>        }//!list_empty
>       if(!list_empty(&(frqp->link)))
>       {
>           list_for_each_entry(pos,&(frqp->link),link)
>                 {
>                        list_del(&(pos->link));
>                        kfree(pos);
>                 }
>         }
>         spin_unlock_irqrestore(&(frqp->lock),flags);
>         set_timer_req_process();
> }//function
>
>
> pl help i m stuck here totallygetting no clue at all ....same code works
> when used in normal request function ...but same code when processes
> request segment by segment in timer function ...crashes kernel ..pl pl help

Just skimming through the code, I see, as outlined above a few places where a 
nullpointer can get to you. I'd fix that first. Then feel free to send me the 
source, but I cannot give you any estimate as to *when* I have the time to go 
through it carefully though.. :)

> ...
>
> **if someone needs i can send full code too ...

As an first approach, start small, then add features gradually. Use printk's 
like there's no tomorrow, always test pointers, try to find similar drivers 
already in the kernel and see how they do it.

-- 
Henrik

Attachment: signature.asc
Description: This is a digitally signed message part.


[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