From d46a5ac7a7e2045e33c6ad6ffb8cf18a7e86a15a Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 19 May 2010 13:43:14 +1000 Subject: padata: Use a timer to handle remaining objects in the reorder queues padata_get_next needs to check whether the next object that need serialization must be parallel processed by the local cpu. This check was wrong implemented and returned always true, so the try_again loop in padata_reorder was never taken. This can lead to object leaks in some rare cases due to a race that appears with the trylock in padata_reorder. The try_again loop was not a good idea after all, because a cpu could take that loop frequently, so we handle this with a timer instead. This patch adds a timer to handle the race that appears with the trylock. If cpu1 queues an object to the reorder queue while cpu2 holds the pd->lock but left the while loop in padata_reorder already, cpu2 can't care for this object and cpu1 exits because it can't get the lock. Usually the next cpu that takes the lock cares for this object too. We need the timer just if this object was the last one that arrives to the reorder queues. The timer function sends it out in this case. Signed-off-by: Steffen Klassert Signed-off-by: Herbert Xu --- include/linux/padata.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/padata.h b/include/linux/padata.h index 51611da9c498..64836a63bd17 100644 --- a/include/linux/padata.h +++ b/include/linux/padata.h @@ -24,6 +24,7 @@ #include #include #include +#include struct padata_priv { struct list_head list; @@ -60,6 +61,7 @@ struct parallel_data { unsigned int max_seq_nr; cpumask_var_t cpumask; spinlock_t lock; + struct timer_list timer; }; struct padata_instance { -- cgit v1.2.3 From 0198ffd135f51d4fbb0c50036395716c06632ed9 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Wed, 19 May 2010 13:44:27 +1000 Subject: padata: Add some code comments Signed-off-by: Steffen Klassert Signed-off-by: Herbert Xu --- include/linux/padata.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'include/linux') diff --git a/include/linux/padata.h b/include/linux/padata.h index 64836a63bd17..8d8406246eef 100644 --- a/include/linux/padata.h +++ b/include/linux/padata.h @@ -26,6 +26,17 @@ #include #include +/** + * struct padata_priv - Embedded to the users data structure. + * + * @list: List entry, to attach to the padata lists. + * @pd: Pointer to the internal control structure. + * @cb_cpu: Callback cpu for serializatioon. + * @seq_nr: Sequence number of the parallelized data object. + * @info: Used to pass information from the parallel to the serial function. + * @parallel: Parallel execution function. + * @serial: Serial complete function. + */ struct padata_priv { struct list_head list; struct parallel_data *pd; @@ -36,11 +47,29 @@ struct padata_priv { void (*serial)(struct padata_priv *padata); }; +/** + * struct padata_list + * + * @list: List head. + * @lock: List lock. + */ struct padata_list { struct list_head list; spinlock_t lock; }; +/** + * struct padata_queue - The percpu padata queues. + * + * @parallel: List to wait for parallelization. + * @reorder: List to wait for reordering after parallel processing. + * @serial: List to wait for serialization after reordering. + * @pwork: work struct for parallelization. + * @swork: work struct for serialization. + * @pd: Backpointer to the internal control structure. + * @num_obj: Number of objects that are processed by this cpu. + * @cpu_index: Index of the cpu. + */ struct padata_queue { struct padata_list parallel; struct padata_list reorder; @@ -52,6 +81,20 @@ struct padata_queue { int cpu_index; }; +/** + * struct parallel_data - Internal control structure, covers everything + * that depends on the cpumask in use. + * + * @pinst: padata instance. + * @queue: percpu padata queues. + * @seq_nr: The sequence number that will be attached to the next object. + * @reorder_objects: Number of objects waiting in the reorder queues. + * @refcnt: Number of objects holding a reference on this parallel_data. + * @max_seq_nr: Maximal used sequence number. + * @cpumask: cpumask in use. + * @lock: Reorder lock. + * @timer: Reorder timer. + */ struct parallel_data { struct padata_instance *pinst; struct padata_queue *queue; @@ -64,6 +107,16 @@ struct parallel_data { struct timer_list timer; }; +/** + * struct padata_instance - The overall control structure. + * + * @cpu_notifier: cpu hotplug notifier. + * @wq: The workqueue in use. + * @pd: The internal control structure. + * @cpumask: User supplied cpumask. + * @lock: padata instance lock. + * @flags: padata flags. + */ struct padata_instance { struct notifier_block cpu_notifier; struct workqueue_struct *wq; -- cgit v1.2.3