Re: need help in understanding basics of block device driver

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

 



Hi Nidhi,

I might have confused u a bit more, so i would
like to help you out.

A page consists of one or more segments.
Segments consists of various sectors.
A block buffer contains sectors.

Each disk I/O consists of segments.

bio are descriptors for I/O operations consisting of one or more
segments. Each segment in a bio is represented by bio_vec.
Now if you see the fields of bio_vec structure you have page,
len and offset.

Now, if you considering the transfer of data from device or to the
device, you need to calculate how much amount of data you need to read
or write from the device from the specified sector.

unsigned long offset = sector*KERNEL_SECTOR_SIZE;
and no of bytes to transfer, that is,
unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;

And the buffer is the request buffer where you receive data from
device or from where you write data to device.


I hope that helps.



Thanks.


On Fri, Mar 6, 2009 at 10:02 PM, Rohit Sharma <imreckless@xxxxxxxxx> wrote:
> Hi Nidhi
>
> Please use, plain text for writing mails to newbies, it does not
> look good.
>
>> hi all
>> i was practising writing block device driver from linux device driver 3rd
>> edition
>> but was confused
>> as
>> it gives two implementation to transfer data from device
>> 1.without using bios
>> 2.using bios
>> in ist implementation ---- cut short version of book code is -----
>> while ((req = elv_next_request(q)) != NULL) {
>>     struct sbull_dev *dev = req->rq_disk->private_data;
>>     sbull_transfer(dev, req->sector, req->current_nr_sectors,req->buffer,
>> rq_data_dir(req));
>>     end_request(req, 1);
>> }
>> static void sbull_transfer(struct sbull_dev *dev, unsigned long sector,
>>          unsigned long nsect, char *buffer, int write)
>> {
>>     unsigned long offset = sector*KERNEL_SECTOR_SIZE;
>>     unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;
>>     if ((offset + nbytes) > dev->size) {
>>          printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset,
>> nbytes);
>>          return;
>>     }
>>     if (write)
>>          memcpy(dev->data + offset, buffer, nbytes);
>>     else
>>          memcpy(buffer, dev->data + offset, nbytes);
>> }
>> ****************************************************************************************************************************
> dont put stars like this it does not look good.
>
>> Now my question is '
>> when current_nr_sectors ====  is the number of sectors left to be
>> transferres in the current segment
>>
>> similarly req->buffer --- is also the data of current bio as it was written
>> in LDD : text is as below
>> "this field is simply the result of calling bio_data on the current
>> bio.where bio_data(bio) Returns a kernel logical address pointing to the
>> data to be transferre"
>> therefore it seems it is only pointing to the data buffer of current bio
>> only.....
>>
>> at one place number os sectors left in currnt segment at other place address
>> to which transfer is made of current bio ....i am confused
>>
> Looks like you are a lot confused, see the implementation of
> sbd_transfer() carefully, dont get confused, a segment is a part of
> bio and a buffer may contain several segments.
>
> Now lets see in detail,
>
> A buffer points to a page,
> a page consists of contagious memory location from where data has to
> be transferred. These are called segments within a page.
>
> So, to transfer a segment you need to specify the buffer that contains
> the segment.
>
> I hope this is clear.
>
> If you see the implementation of sbd_transfer, offset of the segment
> is calculated.
>
> unsigned long offset = sector*KERNEL_SECTOR_SIZE;
>
> and
> no. of bytes to transfer
>
> unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;
>
> I hope now your confusion is clear.
>
>
>
>
> I hope that helps.
> Read about pages, segments and buffers from UTLK.
>
>
>
> ****************************************************************************************************************************************************************************************************************
>> ********************************************************************
>>
>>
>>
>> On Fri, Mar 6, 2009 at 12:50 AM, Rohit Sharma <imreckless@xxxxxxxxx> wrote:
>>>
>>> Hi Nidhi,
>>>
>>> Seems like you are stuck up with this issue.
>>>
>>> Refer the following links if you haven't
>>> Check out this link to understand block device driver
>>> http://lwn.net/Articles/driver-porting/
>>>
>>> for bio structures check this link
>>> http://lwn.net/Articles/26404/
>>> >
>>> > in gyst :
>>> > when you actually transfer data in request processing function
>>> > using req->current_nr_sectors
>>> > from req->buffer
>>> > in while elv_next_request loop
>>>
>>> Please try to provide with the code snippet, will help us understand the
>>> problem better.
>>>
>>> > and if its transferred successfully book does end_request(req,1)
>>> >
>>> > then my ques is
>>> > Q1.  end_request doesnt end the request but ends the part of request
>>> > what is that part --- a bio OR a segment or what ?
>>> >
>>> A request consists of a list of bios and bios consists of several
>>> segments,
>>> and the end request is called to finish the processing of current request.
>>>
>>> > by seeing current_nr_sectors it seems it transfer segment by segment ---
>>> > but seeing req->buffer (equivalent to bio_data(current bio)) seems
>>> > transferring bio by bio ??
>>> >
>>> i think you are referring to sbd_transfer() function,
>>>
>>> sbd_transfer(&Device, req->sector, req->current_nr_sectors,
>>>                            req->buffer, rq_data_dir(req));
>>>
>>> what i understand is that it says transfer these many sectors
>>> 'req->current_nr_sectors'
>>> starting from sector no. 'req->sector' from buffer 'req->buffer' and
>>> direction of data
>>> 'rq_data_dir(req)' --> says READ or WRITE request.
>>>
>>>
>>>
>>> I hope that helps.
>>>
>>>
>>>
>>> Thanks.
>>> >
>>> > Nidhi
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> > --
>>> > Thanks & Regards
>>> > Nidhi
>>
>>
>>
>> --
>> Thanks & Regards
>> Nidhi
>>
>

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ



[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