summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuergen Gross <jgross@suse.com>2018-08-13 10:01:10 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2018-08-27 12:12:03 -0400
commit973e5405f2f67ddbb2bf07b3ffc71908a37fea8e (patch)
tree291850d68c314417cb2b074fddf9aa5171126a7a
parentb86d865cb1cae1e61527ea0b8977078bbf694328 (diff)
xen/blkback: don't keep persistent grants too long
Persistent grants are allocated until a threshold per ring is being reached. Those grants won't be freed until the ring is being destroyed meaning there will be resources kept busy which might no longer be used. Instead of freeing only persistent grants until the threshold is reached add a timestamp and remove all persistent grants not having been in use for a minute. Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r--Documentation/ABI/testing/sysfs-driver-xen-blkback10
-rw-r--r--drivers/block/xen-blkback/blkback.c88
-rw-r--r--drivers/block/xen-blkback/common.h8
3 files changed, 60 insertions, 46 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-xen-blkback b/Documentation/ABI/testing/sysfs-driver-xen-blkback
index 8bb43b66eb55..4e7babb3ba1f 100644
--- a/Documentation/ABI/testing/sysfs-driver-xen-blkback
+++ b/Documentation/ABI/testing/sysfs-driver-xen-blkback
@@ -15,3 +15,13 @@ Description:
15 blkback. If the frontend tries to use more than 15 blkback. If the frontend tries to use more than
16 max_persistent_grants, the LRU kicks in and starts 16 max_persistent_grants, the LRU kicks in and starts
17 removing 5% of max_persistent_grants every 100ms. 17 removing 5% of max_persistent_grants every 100ms.
18
19What: /sys/module/xen_blkback/parameters/persistent_grant_unused_seconds
20Date: August 2018
21KernelVersion: 4.19
22Contact: Roger Pau Monné <roger.pau@citrix.com>
23Description:
24 How long a persistent grant is allowed to remain
25 allocated without being in use. The time is in
26 seconds, 0 means indefinitely long.
27 The default is 60 seconds.
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index b55b245e8052..9eae7b243f68 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -84,6 +84,18 @@ MODULE_PARM_DESC(max_persistent_grants,
84 "Maximum number of grants to map persistently"); 84 "Maximum number of grants to map persistently");
85 85
86/* 86/*
87 * How long a persistent grant is allowed to remain allocated without being in
88 * use. The time is in seconds, 0 means indefinitely long.
89 */
90
91static unsigned int xen_blkif_pgrant_timeout = 60;
92module_param_named(persistent_grant_unused_seconds, xen_blkif_pgrant_timeout,
93 uint, 0644);
94MODULE_PARM_DESC(persistent_grant_unused_seconds,
95 "Time in seconds an unused persistent grant is allowed to "
96 "remain allocated. Default is 60, 0 means unlimited.");
97
98/*
87 * Maximum number of rings/queues blkback supports, allow as many queues as there 99 * Maximum number of rings/queues blkback supports, allow as many queues as there
88 * are CPUs if user has not specified a value. 100 * are CPUs if user has not specified a value.
89 */ 101 */
@@ -123,6 +135,13 @@ module_param(log_stats, int, 0644);
123/* Number of free pages to remove on each call to gnttab_free_pages */ 135/* Number of free pages to remove on each call to gnttab_free_pages */
124#define NUM_BATCH_FREE_PAGES 10 136#define NUM_BATCH_FREE_PAGES 10
125 137
138static inline bool persistent_gnt_timeout(struct persistent_gnt *persistent_gnt)
139{
140 return xen_blkif_pgrant_timeout &&
141 (jiffies - persistent_gnt->last_used >=
142 HZ * xen_blkif_pgrant_timeout);
143}
144
126static inline int get_free_page(struct xen_blkif_ring *ring, struct page **page) 145static inline int get_free_page(struct xen_blkif_ring *ring, struct page **page)
127{ 146{
128 unsigned long flags; 147 unsigned long flags;
@@ -278,7 +297,7 @@ static void put_persistent_gnt(struct xen_blkif_ring *ring,
278{ 297{
279 if(!test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags)) 298 if(!test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags))
280 pr_alert_ratelimited("freeing a grant already unused\n"); 299 pr_alert_ratelimited("freeing a grant already unused\n");
281 set_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags); 300 persistent_gnt->last_used = jiffies;
282 clear_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags); 301 clear_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags);
283 atomic_dec(&ring->persistent_gnt_in_use); 302 atomic_dec(&ring->persistent_gnt_in_use);
284} 303}
@@ -371,26 +390,26 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring)
371 struct persistent_gnt *persistent_gnt; 390 struct persistent_gnt *persistent_gnt;
372 struct rb_node *n; 391 struct rb_node *n;
373 unsigned int num_clean, total; 392 unsigned int num_clean, total;
374 bool scan_used = false, clean_used = false; 393 bool scan_used = false;
375 struct rb_root *root; 394 struct rb_root *root;
376 395
377 if (ring->persistent_gnt_c < xen_blkif_max_pgrants ||
378 (ring->persistent_gnt_c == xen_blkif_max_pgrants &&
379 !ring->blkif->vbd.overflow_max_grants)) {
380 goto out;
381 }
382
383 if (work_busy(&ring->persistent_purge_work)) { 396 if (work_busy(&ring->persistent_purge_work)) {
384 pr_alert_ratelimited("Scheduled work from previous purge is still busy, cannot purge list\n"); 397 pr_alert_ratelimited("Scheduled work from previous purge is still busy, cannot purge list\n");
385 goto out; 398 goto out;
386 } 399 }
387 400
388 num_clean = (xen_blkif_max_pgrants / 100) * LRU_PERCENT_CLEAN; 401 if (ring->persistent_gnt_c < xen_blkif_max_pgrants ||
389 num_clean = ring->persistent_gnt_c - xen_blkif_max_pgrants + num_clean; 402 (ring->persistent_gnt_c == xen_blkif_max_pgrants &&
390 num_clean = min(ring->persistent_gnt_c, num_clean); 403 !ring->blkif->vbd.overflow_max_grants)) {
391 if ((num_clean == 0) || 404 num_clean = 0;
392 (num_clean > (ring->persistent_gnt_c - atomic_read(&ring->persistent_gnt_in_use)))) 405 } else {
393 goto out; 406 num_clean = (xen_blkif_max_pgrants / 100) * LRU_PERCENT_CLEAN;
407 num_clean = ring->persistent_gnt_c - xen_blkif_max_pgrants +
408 num_clean;
409 num_clean = min(ring->persistent_gnt_c, num_clean);
410 pr_debug("Going to purge at least %u persistent grants\n",
411 num_clean);
412 }
394 413
395 /* 414 /*
396 * At this point, we can assure that there will be no calls 415 * At this point, we can assure that there will be no calls
@@ -401,9 +420,7 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring)
401 * number of grants. 420 * number of grants.
402 */ 421 */
403 422
404 total = num_clean; 423 total = 0;
405
406 pr_debug("Going to purge %u persistent grants\n", num_clean);
407 424
408 BUG_ON(!list_empty(&ring->persistent_purge_list)); 425 BUG_ON(!list_empty(&ring->persistent_purge_list));
409 root = &ring->persistent_gnts; 426 root = &ring->persistent_gnts;
@@ -412,46 +429,37 @@ purge_list:
412 BUG_ON(persistent_gnt->handle == 429 BUG_ON(persistent_gnt->handle ==
413 BLKBACK_INVALID_HANDLE); 430 BLKBACK_INVALID_HANDLE);
414 431
415 if (clean_used) {
416 clear_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags);
417 continue;
418 }
419
420 if (test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags)) 432 if (test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags))
421 continue; 433 continue;
422 if (!scan_used && 434 if (!scan_used && !persistent_gnt_timeout(persistent_gnt))
423 (test_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags))) 435 continue;
436 if (scan_used && total >= num_clean)
424 continue; 437 continue;
425 438
426 rb_erase(&persistent_gnt->node, root); 439 rb_erase(&persistent_gnt->node, root);
427 list_add(&persistent_gnt->remove_node, 440 list_add(&persistent_gnt->remove_node,
428 &ring->persistent_purge_list); 441 &ring->persistent_purge_list);
429 if (--num_clean == 0) 442 total++;
430 goto finished;
431 } 443 }
432 /* 444 /*
433 * If we get here it means we also need to start cleaning 445 * Check whether we also need to start cleaning
434 * grants that were used since last purge in order to cope 446 * grants that were used since last purge in order to cope
435 * with the requested num 447 * with the requested num
436 */ 448 */
437 if (!scan_used && !clean_used) { 449 if (!scan_used && total < num_clean) {
438 pr_debug("Still missing %u purged frames\n", num_clean); 450 pr_debug("Still missing %u purged frames\n", num_clean - total);
439 scan_used = true; 451 scan_used = true;
440 goto purge_list; 452 goto purge_list;
441 } 453 }
442finished:
443 if (!clean_used) {
444 pr_debug("Finished scanning for grants to clean, removing used flag\n");
445 clean_used = true;
446 goto purge_list;
447 }
448 454
449 ring->persistent_gnt_c -= (total - num_clean); 455 if (total) {
450 ring->blkif->vbd.overflow_max_grants = 0; 456 ring->persistent_gnt_c -= total;
457 ring->blkif->vbd.overflow_max_grants = 0;
451 458
452 /* We can defer this work */ 459 /* We can defer this work */
453 schedule_work(&ring->persistent_purge_work); 460 schedule_work(&ring->persistent_purge_work);
454 pr_debug("Purged %u/%u\n", (total - num_clean), total); 461 pr_debug("Purged %u/%u\n", num_clean, total);
462 }
455 463
456out: 464out:
457 return; 465 return;
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index ecb35fe8ca8d..7bff72db3b7e 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -234,14 +234,9 @@ struct xen_vbd {
234struct backend_info; 234struct backend_info;
235 235
236/* Number of available flags */ 236/* Number of available flags */
237#define PERSISTENT_GNT_FLAGS_SIZE 2 237#define PERSISTENT_GNT_FLAGS_SIZE 1
238/* This persistent grant is currently in use */ 238/* This persistent grant is currently in use */
239#define PERSISTENT_GNT_ACTIVE 0 239#define PERSISTENT_GNT_ACTIVE 0
240/*
241 * This persistent grant has been used, this flag is set when we remove the
242 * PERSISTENT_GNT_ACTIVE, to know that this grant has been used recently.
243 */
244#define PERSISTENT_GNT_WAS_ACTIVE 1
245 240
246/* Number of requests that we can fit in a ring */ 241/* Number of requests that we can fit in a ring */
247#define XEN_BLKIF_REQS_PER_PAGE 32 242#define XEN_BLKIF_REQS_PER_PAGE 32
@@ -250,6 +245,7 @@ struct persistent_gnt {
250 struct page *page; 245 struct page *page;
251 grant_ref_t gnt; 246 grant_ref_t gnt;
252 grant_handle_t handle; 247 grant_handle_t handle;
248 unsigned long last_used;
253 DECLARE_BITMAP(flags, PERSISTENT_GNT_FLAGS_SIZE); 249 DECLARE_BITMAP(flags, PERSISTENT_GNT_FLAGS_SIZE);
254 struct rb_node node; 250 struct rb_node node;
255 struct list_head remove_node; 251 struct list_head remove_node;