Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 17: Data Synchronization


The implementation ofset_bdi_congestedis very simple. Only a single bit need be set in the request
queue — albeit a different bit depending on the direction of congestion:

block/backing-dev.c
void set_bdi_congested(struct backing_dev_info *bdi, int rw)
{
enum bdi_state bit;

bit = (rw == WRITE)? BDI_write_congested : BDI_read_congested;
set_bit(bit, &bdi->state);
}

However, the kernel is also responsible for adding processes waiting on a congested queue to the
congestion_wqhwait queue. I describe how this is done shortly.

The function used to clear congestion on a queue isclear_queue_congestedand is not much more
complicated. Again, it is invoked at just one point in the kernel^6 by_freed_request, which is in the code
path originating fromblk_put_requestthat returnsrequestinstances no longer needed to the kernel
cache. At this point, it is easy to check whether the number of freerequests has exceeded the above
threshold for clearing congestion.

Once the congested bit for the desired direction has been deleted, a process waiting on the
congestion_wqhqueue to perform I/O operations is woken by thewake_upfunction described in
Chapter 14. Recall thatclear_queue_congestedis just a front end forclear_bdi_congested:

block/ll_rw_blk.c
void clear_bdi_congested(struct backing_dev_info *bdi, int rw)
{
enum bdi_state bit;
wait_queue_head_t *wqh = &congestion_wqh[rw];

bit = (rw == WRITE)? BDI_write_congested : BDI_read_congested;
clear_bit(bit, &bdi->state);

if (waitqueue_active(wqh))
wake_up(wqh);
}

17.11.4 Waiting on Congested Queues


Of course, it’s no use marking queues as congestedand clearing them when the situation improves — the
kernel must also be able to wait until a queue is free again. You have already seen that a wait queue is
employed for this purpose, so it remains to discuss how processes are added to the wait queue.

The kernel uses thecongestion_waitfunction for this purpose. It adds a process to thecongestion_wqh
wait queue when congestion occurs. The function requires two parameters — the direction of data flow
(read or write operation) and a time out after which the process is always woken, even if the queue is still
congested. The time out is used to prevent excessively long periods of inactivity — after all, a queue may
be congested for quite some time.

(^6) This again ignores the possibility that the system administrator fiddles withnr_requestsof the queue.

Free download pdf