您的位置:程序门 -> linux/unix社区 -> 内核及驱动程序研究区



读generic_make_request函数时的一点疑问


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


读generic_make_request函数时的一点疑问[已结贴,结贴人:old123]
发表于:2007-07-16 09:56:02 楼主
generic_make_request函数最后提交请求给驱动时是用下面的代码实现的:
do   {
                                  q   =   blk_get_queue(bh-> b_rdev);
                                  if   (!q)   {
                                                  printk(kern_err
                                                                "generic_make_request:   trying   to   access   "
                                                                "nonexistent   block-device   %s   (%ld)\n ",
                                                                kdevname(bh-> b_rdev),   bh-> b_rsector);
                                                  buffer_io_error(bh);
                                                  break;
                                  }
                  }   while   (q-> make_request_fn(q,   rw,   bh));
  }
发表于:2007-07-16 09:57:041楼 得分:0
我就是不明白为什么要用do-while循环。直接提交给驱动的请求队列不就可以了吗,为什么要这么做呢?
发表于:2007-07-16 11:06:142楼 得分:10
用了do   while说明请求不是提交一次就可以了,算法上有这个需要,要联系上下文。
发表于:2007-07-16 14:50:203楼 得分:0
{
825                   int   major   =   major(bh-> b_rdev);
826                   int   minorsize   =   0;
827                   request_queue_t   *q;
828  
829                   if   (!bh-> b_end_io)
830                                   bug();
831  
832                   /*   test   device   size,   when   known.   */
833                   if   (blk_size[major])
834                                   minorsize   =   blk_size[major][minor(bh-> b_rdev)];
835                   if   (minorsize)   {
836                                   unsigned   long   maxsector   =   (minorsize   < <   1)   +   1;
837                                   unsigned   long   sector   =   bh-> b_rsector;
838                                   unsigned   int   count   =   bh-> b_size   > >   9;
839  
840                                   if   (maxsector   <   count   ¦ ¦   maxsector   -   count   <   sector)   {
841                                                   /*   yecch   */
842                                                   bh-> b_state   &=   (1   < <   bh_lock)   ¦   (1   < <   bh_mapped);
843  
844                                                   /*   this   may   well   happen   -   the   kernel   calls   bread()
845                                                         without   checking   the   size   of   the   device,   e.g.,
846                                                         when   mounting   a   device.   */
847                                                   printk(kern_info
848                                                                 "attempt   to   access   beyond   end   of   device\n ");
849                                                   printk(kern_info   "%s:   rw=%d,   want=%ld,   limit=%d\n ",
850                                                                 kdevname(bh-> b_rdev),   rw,
851                                                                 (sector   +   count)> > 1,   minorsize);
852  
853                                                   /*   yecch   again   */
854                                                   bh-> b_end_io(bh,   0);
855                                                   return;
856                                   }
857                   }
858  
859                   /*
860                     *   resolve   the   mapping   until   finished.   (drivers   are
861                     *   still   free   to   implement/resolve   their   own   stacking
862                     *   by   explicitly   returning   0)
863                     */
864                   /*   note:   we   don 't   repeat   the   blk_size   check   for   each   new   device.
865                     *   stacking   drivers   are   expected   to   know   what   they   are   doing.
866                     */
867                   do   {
868                                   q   =   blk_get_queue(bh-> b_rdev);
869                                   if   (!q)   {
870                                                   printk(kern_err
871                                                                 "generic_make_request:   trying   to   access   "
872                                                                 "nonexistent   block-device   %s   (%ld)\n ",
873                                                                 kdevname(bh-> b_rdev),   bh-> b_rsector);
874                                                   buffer_io_error(bh);
875                                                   break;
876                                   }
877                   }   while   (q-> make_request_fn(q,   rw,   bh));
878   }
        上面是generic_make_request的全部代码,能不能详细说明下?多谢了
发表于:2007-07-16 15:18:174楼 得分:10
859                   /*
860                     *   resolve   the   mapping   until   finished.   (drivers   are
861                     *   still   free   to   implement/resolve   their   own   stacking
862                     *   by   explicitly   returning   0)
863                     */

这段注释说明了do   while的必要性,这个块设备可能正在处理别的什么,导致一次的make_request_fn可能并没有成功,于是进行下一次的请求,直到成功,在这个过程中,如果blk_get_queue返回0,将会中止这个request的过程去处理它自己的堆栈。
发表于:2007-07-17 11:24:385楼 得分:0
static   int   __make_request(request_queue_t   *   q,   int   rw,
628                                                                       struct   buffer_head   *   bh)
629   {
630                   unsigned   int   sector,   count;
631                   int   max_segments   =   max_segments;
632                   struct   request   *   req,   *freereq   =   null;
633                   int   rw_ahead,   max_sectors,   el_ret;
634                   struct   list_head   *head,   *insert_here;
635                   int   latency;
636                   elevator_t   *elevator   =   &q-> elevator;
637  
638                   count   =   bh-> b_size   > >   9;
639                   sector   =   bh-> b_rsector;
640  
641                   rw_ahead   =   0;       /*   normal   case;   gets   changed   below   for   reada   */
642                   switch   (rw)   {
643                                   case   reada:
644                                                   rw_ahead   =   1;
645                                                   rw   =   read;             /*   drop   into   read   */
646                                   case   read:
647                                   case   write:
648                                                   latency   =   elevator_request_latency(elevator,   rw);
649                                                   break;
650                                   default:
651                                                   bug();
652                                                   goto   end_io;
653                   }
654  
655                   /*   we 'd   better   have   a   real   physical   mapping!
656                         check   this   bit   only   if   the   buffer   was   dirty   and   just   locked
657                         down   by   us   so   at   this   point   flushpage   will   block   and
658                         won 't   clear   the   mapped   bit   under   us.   */
659                   if   (!buffer_mapped(bh))
660                                   bug();
661  
662                   /*
663                     *   temporary   solution   -   in   2.5   this   will   be   done   by   the   lowlevel
664                     *   driver.   create   a   bounce   buffer   if   the   buffer   data   points   into
665                     *   high   memory   -   keep   the   original   buffer   otherwise.
666                     */
667   #if   config_highmem
668                   bh   =   create_bounce(rw,   bh);
669   #endif
670  
671   /*   look   for   a   free   request.   */
672                   /*
673                     *   try   to   coalesce   the   new   request   with   old   requests
674                     */
675                   max_sectors   =   get_max_sectors(bh-> b_rdev);
676  
677   again:
678                   req   =   null;
679                   head   =   &q-> queue_head;
680                   /*
681                     *   now   we   acquire   the   request   spinlock,   we   have   to   be   mega   careful
682                     *   not   to   schedule   or   do   something   nonatomic
683                     */
684                   spin_lock_irq(&io_request_lock);
685  
686                   insert_here   =   head-> prev;
687                   if   (list_empty(head))   {
688                                   q-> plug_device_fn(q,   bh-> b_rdev);   /*   is   atomic   */
689                                   goto   get_rq;
690                   }   else   if   (q-> head_active   &&   !q-> plugged)
691                                   head   =   head-> next;
692  
693                   el_ret   =   elevator-> elevator_merge_fn(q,   &req,   head,   bh,   rw,max_sectors);
694                   switch   (el_ret)   {
695  
696                                   case   elevator_back_merge:
697                                                   if   (!q-> back_merge_fn(q,   req,   bh,   max_segments))   {
698                                                                   insert_here   =   &req-> queue;
699                                                                   break;
700                                                   }
701                                                   elevator-> elevator_merge_cleanup_fn(q,   req,   count);
702                                                   req-> bhtail-> b_reqnext   =   bh;
703                                                   req-> bhtail   =   bh;
704                                                   req-> nr_sectors   =   req-> hard_nr_sectors   +=   count;
705                                                   blk_started_io(count);
706                                                   drive_stat_acct(req-> rq_dev,   req-> cmd,   count,   0);
707                                                   attempt_back_merge(q,   req,   max_sectors,   max_segments);
708                                                   goto   out;
709  
710                                   case   elevator_front_merge:
711                                                   if   (!q-> front_merge_fn(q,   req,   bh,   max_segments))   {
712                                                                   insert_here   =   req-> queue.prev;
713                                                                   break;
714                                                   }
715                                                   elevator-> elevator_merge_cleanup_fn(q,   req,   count);
716                                                   bh-> b_reqnext   =   req-> bh;
717                                                   req-> bh   =   bh;
718                                                   req-> buffer   =   bh-> b_data;
719                                                   req-> current_nr_sectors   =   count;
720                                                   req-> sector   =   req-> hard_sector   =   sector;
721                                                   req-> nr_sectors   =   req-> hard_nr_sectors   +=   count;
722                                                   blk_started_io(count);
723                                                   drive_stat_acct(req-> rq_dev,   req-> cmd,   count,   0);
724                                                   attempt_front_merge(q,   head,   req,   max_sectors,   max_segments);
725                                                   goto   out;
726  
727                                   /*
728                                     *   elevator   says   don 't/can 't   merge.   get   new   request
729                                     */
730                                   case   elevator_no_merge:
731                                                   /*
732                                                     *   use   elevator   hints   as   to   where   to   insert   the
733                                                     *   request.   if   no   hints,   just   add   it   to   the   back
734                                                     *   of   the   queue
735                                                     */
736                                                   if   (req)
737                                                                   insert_here   =   &req-> queue;
738                                                   break;
739  
740                                   default:
741                                                   printk( "elevator   returned   crap   (%d)\n ",   el_ret);
742                                                   bug();
743                   }
744                                  
745                   /*
746                     *   grab   a   free   request   from   the   freelist   -   if   that   is   empty,   check
747                     *   if   we   are   doing   read   ahead   and   abort   instead   of   blocking   for
748                     *   a   free   slot.
749                     */
750   get_rq:
751                   if   (freereq)   {
752                                   req   =   freereq;
753                                   freereq   =   null;
754                   }   else   if   ((req   =   get_request(q,   rw))   ==   null)   {
755                                   spin_unlock_irq(&io_request_lock);
756                                   if   (rw_ahead)
757                                                   goto   end_io;
758  
759                                   freereq   =   __get_request_wait(q,   rw);
760                                   goto   again;
761                   }
762  
763   /*   fill   up   the   request-info,   and   add   it   to   the   queue   */
764                   req-> elevator_sequence   =   latency;
765                   req-> cmd   =   rw;
766                   req-> errors   =   0;
767                   req-> hard_sector   =   req-> sector   =   sector;
768                   req-> hard_nr_sectors   =   req-> nr_sectors   =   count;
769                   req-> current_nr_sectors   =   count;
770                   req-> nr_segments   =   1;   /*   always   1   for   a   new   request.   */
771                   req-> nr_hw_segments   =   1;   /*   always   1   for   a   new   request.   */
772                   req-> buffer   =   bh-> b_data;
773                   req-> waiting   =   null;
774                   req-> bh   =   bh;
775                   req-> bhtail   =   bh;
776                   req-> rq_dev   =   bh-> b_rdev;
777                   blk_started_io(count);
778                   add_request(q,   req,   insert_here);
779   out:
780                   if   (freereq)
781                                   blkdev_release_request(freereq);
782                   spin_unlock_irq(&io_request_lock);
783                   return   0;
784   end_io:
785                   bh-> b_end_io(bh,   test_bit(bh_uptodate,   &bh-> b_state));
786                   return   0;
787   }
make_request_fn这个函数实际上是指向__make_request的指针,上面是__make_request的代码,我没有看到里面返回非0的地方,不知道有没有人能解答我的困惑啊。
发表于:2007-07-17 13:30:196楼 得分:0
740                                   default:
741                                                   printk( "elevator   returned   crap   (%d)\n ",   el_ret);
742                                                   bug();

如果真如你所说,make_request_fn这个函数确实是指向__make_request,那么从上面代码,最有理由怀疑的就是bug()。
发表于:2007-07-18 15:13:427楼 得分:0
#define   bug()                       __bug(__file__,   __line__,   null)
void   __bug(const   char   *file,   int   line,   void   *data)
494   {
495                   printk(kern_crit "kernel   bug   at   %s:%d! ",   file,   line);
496                   if   (data)
497                                   printk(kern_crit "   -   extra   data   =   %p ",   data);
498                   printk( "\n ");
499                   *(int   *)0   =   0;
500   }
bug()这个宏似乎还跟体系结构相关,我用的2410,上面两段是从include/asm-arm/page.h里面剪切出来的,希望能有人能看懂


快速检索

最新资讯
热门点击