diff options
Diffstat (limited to 'drivers/md/dm-log-userspace-base.c')
-rw-r--r-- | drivers/md/dm-log-userspace-base.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c index 1c25ad3d02a2..767adf300fa5 100644 --- a/drivers/md/dm-log-userspace-base.c +++ b/drivers/md/dm-log-userspace-base.c | |||
@@ -37,8 +37,15 @@ struct log_c { | |||
37 | */ | 37 | */ |
38 | uint64_t in_sync_hint; | 38 | uint64_t in_sync_hint; |
39 | 39 | ||
40 | /* | ||
41 | * Mark and clear requests are held until a flush is issued | ||
42 | * so that we can group, and thereby limit, the amount of | ||
43 | * network traffic between kernel and userspace. The 'flush_lock' | ||
44 | * is used to protect these lists. | ||
45 | */ | ||
40 | spinlock_t flush_lock; | 46 | spinlock_t flush_lock; |
41 | struct list_head flush_list; /* only for clear and mark requests */ | 47 | struct list_head mark_list; |
48 | struct list_head clear_list; | ||
42 | }; | 49 | }; |
43 | 50 | ||
44 | static mempool_t *flush_entry_pool; | 51 | static mempool_t *flush_entry_pool; |
@@ -169,7 +176,8 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti, | |||
169 | 176 | ||
170 | strncpy(lc->uuid, argv[0], DM_UUID_LEN); | 177 | strncpy(lc->uuid, argv[0], DM_UUID_LEN); |
171 | spin_lock_init(&lc->flush_lock); | 178 | spin_lock_init(&lc->flush_lock); |
172 | INIT_LIST_HEAD(&lc->flush_list); | 179 | INIT_LIST_HEAD(&lc->mark_list); |
180 | INIT_LIST_HEAD(&lc->clear_list); | ||
173 | 181 | ||
174 | str_size = build_constructor_string(ti, argc - 1, argv + 1, &ctr_str); | 182 | str_size = build_constructor_string(ti, argc - 1, argv + 1, &ctr_str); |
175 | if (str_size < 0) { | 183 | if (str_size < 0) { |
@@ -362,14 +370,16 @@ static int userspace_flush(struct dm_dirty_log *log) | |||
362 | int r = 0; | 370 | int r = 0; |
363 | unsigned long flags; | 371 | unsigned long flags; |
364 | struct log_c *lc = log->context; | 372 | struct log_c *lc = log->context; |
365 | LIST_HEAD(flush_list); | 373 | LIST_HEAD(mark_list); |
374 | LIST_HEAD(clear_list); | ||
366 | struct flush_entry *fe, *tmp_fe; | 375 | struct flush_entry *fe, *tmp_fe; |
367 | 376 | ||
368 | spin_lock_irqsave(&lc->flush_lock, flags); | 377 | spin_lock_irqsave(&lc->flush_lock, flags); |
369 | list_splice_init(&lc->flush_list, &flush_list); | 378 | list_splice_init(&lc->mark_list, &mark_list); |
379 | list_splice_init(&lc->clear_list, &clear_list); | ||
370 | spin_unlock_irqrestore(&lc->flush_lock, flags); | 380 | spin_unlock_irqrestore(&lc->flush_lock, flags); |
371 | 381 | ||
372 | if (list_empty(&flush_list)) | 382 | if (list_empty(&mark_list) && list_empty(&clear_list)) |
373 | return 0; | 383 | return 0; |
374 | 384 | ||
375 | /* | 385 | /* |
@@ -379,7 +389,16 @@ static int userspace_flush(struct dm_dirty_log *log) | |||
379 | * do it one by one. | 389 | * do it one by one. |
380 | */ | 390 | */ |
381 | 391 | ||
382 | list_for_each_entry(fe, &flush_list, list) { | 392 | list_for_each_entry(fe, &mark_list, list) { |
393 | r = userspace_do_request(lc, lc->uuid, fe->type, | ||
394 | (char *)&fe->region, | ||
395 | sizeof(fe->region), | ||
396 | NULL, NULL); | ||
397 | if (r) | ||
398 | goto fail; | ||
399 | } | ||
400 | |||
401 | list_for_each_entry(fe, &clear_list, list) { | ||
383 | r = userspace_do_request(lc, lc->uuid, fe->type, | 402 | r = userspace_do_request(lc, lc->uuid, fe->type, |
384 | (char *)&fe->region, | 403 | (char *)&fe->region, |
385 | sizeof(fe->region), | 404 | sizeof(fe->region), |
@@ -397,7 +416,11 @@ fail: | |||
397 | * Calling code will receive an error and will know that | 416 | * Calling code will receive an error and will know that |
398 | * the log facility has failed. | 417 | * the log facility has failed. |
399 | */ | 418 | */ |
400 | list_for_each_entry_safe(fe, tmp_fe, &flush_list, list) { | 419 | list_for_each_entry_safe(fe, tmp_fe, &mark_list, list) { |
420 | list_del(&fe->list); | ||
421 | mempool_free(fe, flush_entry_pool); | ||
422 | } | ||
423 | list_for_each_entry_safe(fe, tmp_fe, &clear_list, list) { | ||
401 | list_del(&fe->list); | 424 | list_del(&fe->list); |
402 | mempool_free(fe, flush_entry_pool); | 425 | mempool_free(fe, flush_entry_pool); |
403 | } | 426 | } |
@@ -427,7 +450,7 @@ static void userspace_mark_region(struct dm_dirty_log *log, region_t region) | |||
427 | spin_lock_irqsave(&lc->flush_lock, flags); | 450 | spin_lock_irqsave(&lc->flush_lock, flags); |
428 | fe->type = DM_ULOG_MARK_REGION; | 451 | fe->type = DM_ULOG_MARK_REGION; |
429 | fe->region = region; | 452 | fe->region = region; |
430 | list_add(&fe->list, &lc->flush_list); | 453 | list_add(&fe->list, &lc->mark_list); |
431 | spin_unlock_irqrestore(&lc->flush_lock, flags); | 454 | spin_unlock_irqrestore(&lc->flush_lock, flags); |
432 | 455 | ||
433 | return; | 456 | return; |
@@ -464,7 +487,7 @@ static void userspace_clear_region(struct dm_dirty_log *log, region_t region) | |||
464 | spin_lock_irqsave(&lc->flush_lock, flags); | 487 | spin_lock_irqsave(&lc->flush_lock, flags); |
465 | fe->type = DM_ULOG_CLEAR_REGION; | 488 | fe->type = DM_ULOG_CLEAR_REGION; |
466 | fe->region = region; | 489 | fe->region = region; |
467 | list_add(&fe->list, &lc->flush_list); | 490 | list_add(&fe->list, &lc->clear_list); |
468 | spin_unlock_irqrestore(&lc->flush_lock, flags); | 491 | spin_unlock_irqrestore(&lc->flush_lock, flags); |
469 | 492 | ||
470 | return; | 493 | return; |