Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>

authored by

Alexander Aring and committed by
David Teigland
92d59adf 578acf9a

+20 -8
+20 -8
fs/dlm/lowcomms.c
··· 204 204 static DECLARE_WORK(process_work, process_dlm_messages); 205 205 static DEFINE_SPINLOCK(processqueue_lock); 206 206 static bool process_dlm_messages_pending; 207 + static DECLARE_WAIT_QUEUE_HEAD(processqueue_wq); 207 208 static atomic_t processqueue_count; 208 209 static LIST_HEAD(processqueue); 209 210 ··· 878 877 } 879 878 880 879 list_del(&pentry->list); 881 - atomic_dec(&processqueue_count); 880 + if (atomic_dec_and_test(&processqueue_count)) 881 + wake_up(&processqueue_wq); 882 882 spin_unlock_bh(&processqueue_lock); 883 883 884 884 for (;;) { ··· 897 895 } 898 896 899 897 list_del(&pentry->list); 900 - atomic_dec(&processqueue_count); 898 + if (atomic_dec_and_test(&processqueue_count)) 899 + wake_up(&processqueue_wq); 901 900 spin_unlock_bh(&processqueue_lock); 902 901 } 903 902 } ··· 1514 1511 /* CF_RECV_PENDING cleared */ 1515 1512 break; 1516 1513 case DLM_IO_FLUSH: 1517 - flush_workqueue(process_workqueue); 1514 + /* we can't flush the process_workqueue here because a 1515 + * WQ_MEM_RECLAIM workequeue can occurr a deadlock for a non 1516 + * WQ_MEM_RECLAIM workqueue such as process_workqueue. Instead 1517 + * we have a waitqueue to wait until all messages are 1518 + * processed. 1519 + * 1520 + * This handling is only necessary to backoff the sender and 1521 + * not queue all messages from the socket layer into DLM 1522 + * processqueue. When DLM is capable to parse multiple messages 1523 + * on an e.g. per socket basis this handling can might be 1524 + * removed. Especially in a message burst we are too slow to 1525 + * process messages and the queue will fill up memory. 1526 + */ 1527 + wait_event(processqueue_wq, !atomic_read(&processqueue_count)); 1518 1528 fallthrough; 1519 1529 case DLM_IO_RESCHED: 1520 1530 cond_resched(); ··· 1717 1701 return -ENOMEM; 1718 1702 } 1719 1703 1720 - /* ordered dlm message process queue, 1721 - * should be converted to a tasklet 1722 - */ 1723 - process_workqueue = alloc_ordered_workqueue("dlm_process", 1724 - WQ_HIGHPRI | WQ_MEM_RECLAIM); 1704 + process_workqueue = alloc_workqueue("dlm_process", WQ_HIGHPRI | WQ_BH, 0); 1725 1705 if (!process_workqueue) { 1726 1706 log_print("can't start dlm_process"); 1727 1707 destroy_workqueue(io_workqueue);