diff options
Diffstat (limited to 'mm/pdflush.c')
| -rw-r--r-- | mm/pdflush.c | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/mm/pdflush.c b/mm/pdflush.c index 118905e3d788..f2caf96993f8 100644 --- a/mm/pdflush.c +++ b/mm/pdflush.c | |||
| @@ -58,6 +58,14 @@ static DEFINE_SPINLOCK(pdflush_lock); | |||
| 58 | int nr_pdflush_threads = 0; | 58 | int nr_pdflush_threads = 0; |
| 59 | 59 | ||
| 60 | /* | 60 | /* |
| 61 | * The max/min number of pdflush threads. R/W by sysctl at | ||
| 62 | * /proc/sys/vm/nr_pdflush_threads_max/min | ||
| 63 | */ | ||
| 64 | int nr_pdflush_threads_max __read_mostly = MAX_PDFLUSH_THREADS; | ||
| 65 | int nr_pdflush_threads_min __read_mostly = MIN_PDFLUSH_THREADS; | ||
| 66 | |||
| 67 | |||
| 68 | /* | ||
| 61 | * The time at which the pdflush thread pool last went empty | 69 | * The time at which the pdflush thread pool last went empty |
| 62 | */ | 70 | */ |
| 63 | static unsigned long last_empty_jifs; | 71 | static unsigned long last_empty_jifs; |
| @@ -68,7 +76,7 @@ static unsigned long last_empty_jifs; | |||
| 68 | * Thread pool management algorithm: | 76 | * Thread pool management algorithm: |
| 69 | * | 77 | * |
| 70 | * - The minimum and maximum number of pdflush instances are bound | 78 | * - The minimum and maximum number of pdflush instances are bound |
| 71 | * by MIN_PDFLUSH_THREADS and MAX_PDFLUSH_THREADS. | 79 | * by nr_pdflush_threads_min and nr_pdflush_threads_max. |
| 72 | * | 80 | * |
| 73 | * - If there have been no idle pdflush instances for 1 second, create | 81 | * - If there have been no idle pdflush instances for 1 second, create |
| 74 | * a new one. | 82 | * a new one. |
| @@ -98,7 +106,6 @@ static int __pdflush(struct pdflush_work *my_work) | |||
| 98 | INIT_LIST_HEAD(&my_work->list); | 106 | INIT_LIST_HEAD(&my_work->list); |
| 99 | 107 | ||
| 100 | spin_lock_irq(&pdflush_lock); | 108 | spin_lock_irq(&pdflush_lock); |
| 101 | nr_pdflush_threads++; | ||
| 102 | for ( ; ; ) { | 109 | for ( ; ; ) { |
| 103 | struct pdflush_work *pdf; | 110 | struct pdflush_work *pdf; |
| 104 | 111 | ||
| @@ -126,20 +133,25 @@ static int __pdflush(struct pdflush_work *my_work) | |||
| 126 | 133 | ||
| 127 | (*my_work->fn)(my_work->arg0); | 134 | (*my_work->fn)(my_work->arg0); |
| 128 | 135 | ||
| 136 | spin_lock_irq(&pdflush_lock); | ||
| 137 | |||
| 129 | /* | 138 | /* |
| 130 | * Thread creation: For how long have there been zero | 139 | * Thread creation: For how long have there been zero |
| 131 | * available threads? | 140 | * available threads? |
| 141 | * | ||
| 142 | * To throttle creation, we reset last_empty_jifs. | ||
| 132 | */ | 143 | */ |
| 133 | if (time_after(jiffies, last_empty_jifs + 1 * HZ)) { | 144 | if (time_after(jiffies, last_empty_jifs + 1 * HZ)) { |
| 134 | /* unlocked list_empty() test is OK here */ | 145 | if (list_empty(&pdflush_list) && |
| 135 | if (list_empty(&pdflush_list)) { | 146 | nr_pdflush_threads < nr_pdflush_threads_max) { |
| 136 | /* unlocked test is OK here */ | 147 | last_empty_jifs = jiffies; |
| 137 | if (nr_pdflush_threads < MAX_PDFLUSH_THREADS) | 148 | nr_pdflush_threads++; |
| 138 | start_one_pdflush_thread(); | 149 | spin_unlock_irq(&pdflush_lock); |
| 150 | start_one_pdflush_thread(); | ||
| 151 | spin_lock_irq(&pdflush_lock); | ||
| 139 | } | 152 | } |
| 140 | } | 153 | } |
| 141 | 154 | ||
| 142 | spin_lock_irq(&pdflush_lock); | ||
| 143 | my_work->fn = NULL; | 155 | my_work->fn = NULL; |
| 144 | 156 | ||
| 145 | /* | 157 | /* |
| @@ -148,7 +160,7 @@ static int __pdflush(struct pdflush_work *my_work) | |||
| 148 | */ | 160 | */ |
| 149 | if (list_empty(&pdflush_list)) | 161 | if (list_empty(&pdflush_list)) |
| 150 | continue; | 162 | continue; |
| 151 | if (nr_pdflush_threads <= MIN_PDFLUSH_THREADS) | 163 | if (nr_pdflush_threads <= nr_pdflush_threads_min) |
| 152 | continue; | 164 | continue; |
| 153 | pdf = list_entry(pdflush_list.prev, struct pdflush_work, list); | 165 | pdf = list_entry(pdflush_list.prev, struct pdflush_work, list); |
| 154 | if (time_after(jiffies, pdf->when_i_went_to_sleep + 1 * HZ)) { | 166 | if (time_after(jiffies, pdf->when_i_went_to_sleep + 1 * HZ)) { |
| @@ -236,14 +248,27 @@ int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0) | |||
| 236 | 248 | ||
| 237 | static void start_one_pdflush_thread(void) | 249 | static void start_one_pdflush_thread(void) |
| 238 | { | 250 | { |
| 239 | kthread_run(pdflush, NULL, "pdflush"); | 251 | struct task_struct *k; |
| 252 | |||
| 253 | k = kthread_run(pdflush, NULL, "pdflush"); | ||
| 254 | if (unlikely(IS_ERR(k))) { | ||
| 255 | spin_lock_irq(&pdflush_lock); | ||
| 256 | nr_pdflush_threads--; | ||
| 257 | spin_unlock_irq(&pdflush_lock); | ||
| 258 | } | ||
| 240 | } | 259 | } |
| 241 | 260 | ||
| 242 | static int __init pdflush_init(void) | 261 | static int __init pdflush_init(void) |
| 243 | { | 262 | { |
| 244 | int i; | 263 | int i; |
| 245 | 264 | ||
| 246 | for (i = 0; i < MIN_PDFLUSH_THREADS; i++) | 265 | /* |
| 266 | * Pre-set nr_pdflush_threads... If we fail to create, | ||
| 267 | * the count will be decremented. | ||
| 268 | */ | ||
| 269 | nr_pdflush_threads = nr_pdflush_threads_min; | ||
| 270 | |||
| 271 | for (i = 0; i < nr_pdflush_threads_min; i++) | ||
| 247 | start_one_pdflush_thread(); | 272 | start_one_pdflush_thread(); |
| 248 | return 0; | 273 | return 0; |
| 249 | } | 274 | } |
