Skip to content

Commit 92d59ad

Browse files
Alexander Aringteigland
authored andcommitted
dlm: do message processing in softirq context
Move dlm message processing from an ordered workqueue context to an ordered softirq context. Handling dlm messages in softirq will allow requests to be cleared more quickly and efficiently, and should avoid longer queues of incomplete requests. Later patches are expected to run completion/blocking callbacks directly from this message processing context, further reducing context switches required to complete a request. In the longer term, concurrent message processing could be implemented. Signed-off-by: Alexander Aring <[email protected]> Signed-off-by: David Teigland <[email protected]>
1 parent 578acf9 commit 92d59ad

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

fs/dlm/lowcomms.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ static void process_dlm_messages(struct work_struct *work);
204204
static DECLARE_WORK(process_work, process_dlm_messages);
205205
static DEFINE_SPINLOCK(processqueue_lock);
206206
static bool process_dlm_messages_pending;
207+
static DECLARE_WAIT_QUEUE_HEAD(processqueue_wq);
207208
static atomic_t processqueue_count;
208209
static LIST_HEAD(processqueue);
209210

@@ -877,7 +878,8 @@ static void process_dlm_messages(struct work_struct *work)
877878
}
878879

879880
list_del(&pentry->list);
880-
atomic_dec(&processqueue_count);
881+
if (atomic_dec_and_test(&processqueue_count))
882+
wake_up(&processqueue_wq);
881883
spin_unlock_bh(&processqueue_lock);
882884

883885
for (;;) {
@@ -895,7 +897,8 @@ static void process_dlm_messages(struct work_struct *work)
895897
}
896898

897899
list_del(&pentry->list);
898-
atomic_dec(&processqueue_count);
900+
if (atomic_dec_and_test(&processqueue_count))
901+
wake_up(&processqueue_wq);
899902
spin_unlock_bh(&processqueue_lock);
900903
}
901904
}
@@ -1511,7 +1514,20 @@ static void process_recv_sockets(struct work_struct *work)
15111514
/* CF_RECV_PENDING cleared */
15121515
break;
15131516
case DLM_IO_FLUSH:
1514-
flush_workqueue(process_workqueue);
1517+
/* we can't flush the process_workqueue here because a
1518+
* WQ_MEM_RECLAIM workequeue can occurr a deadlock for a non
1519+
* WQ_MEM_RECLAIM workqueue such as process_workqueue. Instead
1520+
* we have a waitqueue to wait until all messages are
1521+
* processed.
1522+
*
1523+
* This handling is only necessary to backoff the sender and
1524+
* not queue all messages from the socket layer into DLM
1525+
* processqueue. When DLM is capable to parse multiple messages
1526+
* on an e.g. per socket basis this handling can might be
1527+
* removed. Especially in a message burst we are too slow to
1528+
* process messages and the queue will fill up memory.
1529+
*/
1530+
wait_event(processqueue_wq, !atomic_read(&processqueue_count));
15151531
fallthrough;
15161532
case DLM_IO_RESCHED:
15171533
cond_resched();
@@ -1701,11 +1717,7 @@ static int work_start(void)
17011717
return -ENOMEM;
17021718
}
17031719

1704-
/* ordered dlm message process queue,
1705-
* should be converted to a tasklet
1706-
*/
1707-
process_workqueue = alloc_ordered_workqueue("dlm_process",
1708-
WQ_HIGHPRI | WQ_MEM_RECLAIM);
1720+
process_workqueue = alloc_workqueue("dlm_process", WQ_HIGHPRI | WQ_BH, 0);
17091721
if (!process_workqueue) {
17101722
log_print("can't start dlm_process");
17111723
destroy_workqueue(io_workqueue);

0 commit comments

Comments
 (0)