On Wednesday 05 December 2007 17:24, Andrew Morton wrote:The problem is that you (a) may or may not know just how bad a worst case can be, and (b) may block unnecessarily by being pessimistic.On Wed, 5 Dec 2007 16:03:01 -0800 Daniel Phillips <phillips@xxxxxxxxx> wrote:...a block device these days may not be just a single device, but may be a stack of devices connected together by a generic mechanism such as device mapper, or a hardcoded stack such as multi-disk or network block device. It is necessary to consider the resource requirements of the stack as a whole _before_ letting a transfer proceed into any layer of the stack, otherwise deadlock on many partially completed transfers becomes a possibility. For this reason, the bio throttling is only implemented at the initial, highest level submission of the bio to the block layer and not for any recursive submission of the same bio to a lower level block device in a stack.Rather than asking the stack "how much memory will this request consume"
This in turn has rather far reaching implications: the top level device in a stack must take care of inspecting the entire stack in order to determine how to calculate its resource requirements, thus becoming
the boss device for the entire stack. Though this intriguing idea could easily become the cause of endless design work and many thousands of lines of fancy code, today I sidestep the question entirely using the "just provide lots of reserve" strategy. Horrifying as it may seem to some, this is precisely the strategy that Linux has used in the context of resource management in general, from the very beginning and likely continuing for quite some time into the future My strongly held opinion in this matter is that we need to solve the real, underlying problems definitively with nice code before declaring the opening of fancy patch season. So I am leaving further discussion of automatic resource discovery algorithms and the like out of this post.
you could instead ask "how much memory are you currently using".
ie: on entry to the stack, do
current->account_block_allocations = 1;
make_request(...);
rq->used_memory += current->pages_used_for_block_allocations;
and in the page allocator do
if (!in_interrupt() && current->account_block_allocations)
current->pages_used_for_block_allocations++;
and then somehow handle deallocation too ;)
Ah, and how do you ensure that you do not deadlock while making this
inquiry? Perhaps send a dummy transaction down the pipe? Even so,
deadlock is possible, quite evidently so in the real life example I have
at hand.
Yours is essentially one of the strategies I had in mind, the other major
one being simply to examine the whole stack, which presupposes some
as-yet-nonexistant kernel wide method of representing block device
stacks in all there glorious possible topology variations.
The basic idea being to know in real time how much memory a particular
block stack is presently using. Then, on entry to that stack, if the
stack's current usage is too high, wait for it to subside.
We do not wait for high block device resource usage to subside before
submitting more requests. The improvement you suggest is aimed at
automatically determining resource requirements by sampling a
running system, rather than requiring a programmer to determine them
arduously by hand. Something like automatically determining a
workable locking strategy by analyzing running code, wouldn't that be
a treat? I will hope for one of those under my tree at Christmas.