Help understanding block layer sample in LDD3
Hi there, I've been reading LDD3's chapter 16 on block devices a few times, and have made toys block layers module. Now I've been looking at the up-to-date examples provided by martinez javier[1], but still there's a fundamental concept I fail to understand. Considering only the RM_FULL and RM_SIMPLE cases, a request queue is created, bound with a lock, and associated with a request function. In the simple case, that function "sbull_request" processes each request from the request queue, and delegates the work to "sbull_transfer", which basically performs some arithmetic and does the actual data copy. This function is given a sector, a number of sectors, a pointer to a buffer, and a read or write parameter extracted from the request using blk_rq_pos(), blk_rq_cur_sectors(), req->buffer and rq_data_dir() respectively. On the other hand, the same mechanism is used, but a different function is associated: "sbull_full_request". That function also extracts requests and delegates the actual work to "sbull_xfer_request" which iterates on the request's bio, calls "sbull_xfer_bio" which itself iterates on the bio's segments and finally, calls the same "sbull_transfer" function. What I fail to understand is: how (with the same initialization) the behaviour of the module using those two somehow different mechanism is equivalent. One has to understand the full complexity of the underlying data structure (requests having bio, having segments) while the other only reads the containing structure (the struct request) and do the same job, without iterations. Bonus point, to give some context: I'm writing an asynchronous block-layer which has to split requests into custom subrequest. I'm wondering which approach (between those two) I should pickup. Thanks for reading so far, and for any hints :) [1] https://github.com/martinezjavier/ldd3/blob/master/sbull/sbull.c -- François
On Fri, Jul 29, 2016 at 3:14 PM, François <fser@code-libre.org> wrote:
Hi there,
I've been reading LDD3's chapter 16 on block devices a few times, and have made toys block layers module. Now I've been looking at the up-to-date examples provided by martinez javier[1], but still there's a fundamental concept I fail to understand.
Considering only the RM_FULL and RM_SIMPLE cases, a request queue is created, bound with a lock, and associated with a request function.
In the simple case, that function "sbull_request" processes each request from the request queue, and delegates the work to "sbull_transfer", which basically performs some arithmetic and does the actual data copy. This function is given a sector, a number of sectors, a pointer to a buffer, and a read or write parameter extracted from the request using blk_rq_pos(), blk_rq_cur_sectors(), req->buffer and rq_data_dir() respectively.
On the other hand, the same mechanism is used, but a different function is associated: "sbull_full_request". That function also extracts requests and delegates the actual work to "sbull_xfer_request" which iterates on the request's bio, calls "sbull_xfer_bio" which itself iterates on the bio's segments and finally, calls the same "sbull_transfer" function.
What I fail to understand is: how (with the same initialization) the behaviour of the module using those two somehow different mechanism is equivalent.
I don't see req->buffer. Which version you are using?
One has to understand the full complexity of the underlying data structure (requests having bio, having segments) while the other only reads the containing structure (the struct request) and do the same job, without iterations.
Bonus point, to give some context: I'm writing an asynchronous block-layer which has to split requests into custom subrequest. I'm wondering which approach (between those two) I should pickup.
If this is a memory backed block driver, then perhaps you can handle multiple requests[?]. I don't think you need to actually break up the same request into multiple requests.
Thanks for reading so far, and for any hints :)
[1] https://github.com/martinezjavier/ldd3/blob/master/sbull/sbull.c -- François
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
-- ---P.K.S
On Fri, Jul 29, 2016 at 03:58:28PM +0530, Pranay Srivastava wrote:
I don't see req->buffer. Which version you are using?
You're absolutely right. Both [1] and [2] seems to be outdated. I'm currently compiling and testing most of my code on a 3.19 on a 14.04 LTS ubuntu in a VM, rather than the actual kernel. It's simpler for me to work that way. [1] https://github.com/martinezjavier/ldd3/blob/master/sbull/sbull.c#L119 [2] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documen... [...]
If this is a memory backed block driver, then perhaps you can handle multiple requests[?]. I don't think you need to actually break up the same request into multiple requests.
Actually, it is a shared memory based. Hence, a request might larger than the available room in the shared memory. This case has to be handled. Thanks for your input! -- François
On Fri, Jul 29, 2016 at 4:15 PM, François <fser@code-libre.org> wrote:
On Fri, Jul 29, 2016 at 03:58:28PM +0530, Pranay Srivastava wrote:
I don't see req->buffer. Which version you are using?
You're absolutely right. Both [1] and [2] seems to be outdated. I'm currently compiling and testing most of my code on a 3.19 on a 14.04 LTS ubuntu in a VM, rather than the actual kernel. It's simpler for me to work that way.
[1] https://github.com/martinezjavier/ldd3/blob/master/sbull/sbull.c#L119 [2] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documen...
[...]
If this is a memory backed block driver, then perhaps you can handle multiple requests[?]. I don't think you need to actually break up the same request into multiple requests.
Actually, it is a shared memory based. Hence, a request might larger than the available room in the shared memory. This case has to be handled.
So basically you hold on to some pages[?] and use that as your disk right? I guess setcapacity should take care of this [no?] I think if you just take care of the proper mapping of sector(s) to your driver then it should be alright. Too large request shouldn't reach your driver even when you have the device opened as raw and not mounted it.
Thanks for your input!
-- François
-- ---P.K.S
On Fri, Jul 29, 2016 at 04:26:41PM +0530, Pranay Srivastava wrote:
On Fri, Jul 29, 2016 at 4:15 PM, François <fser@code-libre.org> wrote:
On Fri, Jul 29, 2016 at 03:58:28PM +0530, Pranay Srivastava wrote:
I don't see req->buffer. Which version you are using?
You're absolutely right. Both [1] and [2] seems to be outdated. I'm currently compiling and testing most of my code on a 3.19 on a 14.04 LTS ubuntu in a VM, rather than the actual kernel. It's simpler for me to work that way.
[1] https://github.com/martinezjavier/ldd3/blob/master/sbull/sbull.c#L119 [2] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documen...
[...]
If this is a memory backed block driver, then perhaps you can handle multiple requests[?]. I don't think you need to actually break up the same request into multiple requests.
Actually, it is a shared memory based. Hence, a request might larger than the available room in the shared memory. This case has to be handled.
So basically you hold on to some pages[?] and use that as your disk right?
Well those shared pages are used to exchange chunks of data with another party, which will itself get those data, produce bio, submit bio, and put response on the shared region.
I guess setcapacity should take care of this [no?]
The set_capacity() value is the one reported by the other party which queries an actual block device. Eventhough request size could be resized, if the other party takes time to respond, very few memory might be available, but large request can be enqueued. So limiting the capacity does not seem to be an option here.
I think if you just take care of the proper mapping of sector(s) to your driver then it should be alright.
Too large request shouldn't reach your driver even when you have the device opened as raw and not mounted it.
Thanks for your input!
-- François
-- ---P.K.S
-- François
participants (2)
-
François -
Pranay Srivastava