Skip to content

Commit 057d3cc

Browse files
committed
Merge branch 'stable/for-jens-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen into for-linus
Pull Xen block driver fixes from Konrad: "Fix for flushing out persistent pages at a deterministic rate" * 'stable/for-jens-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: xen/blkback: remove unused pers_gnts_lock from struct xen_blkif_ring xen/blkback: move persistent grants flags to bool xen/blkfront: reorder tests in xlblk_init() xen/blkfront: cleanup stale persistent grants xen/blkback: don't keep persistent grants too long
2 parents 38cfb5a + 6f2f39a commit 057d3cc

File tree

4 files changed

+163
-70
lines changed

4 files changed

+163
-70
lines changed

Documentation/ABI/testing/sysfs-driver-xen-blkback

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,13 @@ Description:
1515
blkback. If the frontend tries to use more than
1616
max_persistent_grants, the LRU kicks in and starts
1717
removing 5% of max_persistent_grants every 100ms.
18+
19+
What: /sys/module/xen_blkback/parameters/persistent_grant_unused_seconds
20+
Date: August 2018
21+
KernelVersion: 4.19
22+
Contact: Roger Pau Monné <roger.pau@citrix.com>
23+
Description:
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.

drivers/block/xen-blkback/blkback.c

Lines changed: 53 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ module_param_named(max_persistent_grants, xen_blkif_max_pgrants, int, 0644);
8383
MODULE_PARM_DESC(max_persistent_grants,
8484
"Maximum number of grants to map persistently");
8585

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+
91+
static unsigned int xen_blkif_pgrant_timeout = 60;
92+
module_param_named(persistent_grant_unused_seconds, xen_blkif_pgrant_timeout,
93+
uint, 0644);
94+
MODULE_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+
8698
/*
8799
* Maximum number of rings/queues blkback supports, allow as many queues as there
88100
* are CPUs if user has not specified a value.
@@ -123,6 +135,13 @@ module_param(log_stats, int, 0644);
123135
/* Number of free pages to remove on each call to gnttab_free_pages */
124136
#define NUM_BATCH_FREE_PAGES 10
125137

138+
static 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+
126145
static inline int get_free_page(struct xen_blkif_ring *ring, struct page **page)
127146
{
128147
unsigned long flags;
@@ -236,8 +255,7 @@ static int add_persistent_gnt(struct xen_blkif_ring *ring,
236255
}
237256
}
238257

239-
bitmap_zero(persistent_gnt->flags, PERSISTENT_GNT_FLAGS_SIZE);
240-
set_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags);
258+
persistent_gnt->active = true;
241259
/* Add new node and rebalance tree. */
242260
rb_link_node(&(persistent_gnt->node), parent, new);
243261
rb_insert_color(&(persistent_gnt->node), &ring->persistent_gnts);
@@ -261,11 +279,11 @@ static struct persistent_gnt *get_persistent_gnt(struct xen_blkif_ring *ring,
261279
else if (gref > data->gnt)
262280
node = node->rb_right;
263281
else {
264-
if(test_bit(PERSISTENT_GNT_ACTIVE, data->flags)) {
282+
if (data->active) {
265283
pr_alert_ratelimited("requesting a grant already in use\n");
266284
return NULL;
267285
}
268-
set_bit(PERSISTENT_GNT_ACTIVE, data->flags);
286+
data->active = true;
269287
atomic_inc(&ring->persistent_gnt_in_use);
270288
return data;
271289
}
@@ -276,10 +294,10 @@ static struct persistent_gnt *get_persistent_gnt(struct xen_blkif_ring *ring,
276294
static void put_persistent_gnt(struct xen_blkif_ring *ring,
277295
struct persistent_gnt *persistent_gnt)
278296
{
279-
if(!test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags))
297+
if (!persistent_gnt->active)
280298
pr_alert_ratelimited("freeing a grant already unused\n");
281-
set_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags);
282-
clear_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags);
299+
persistent_gnt->last_used = jiffies;
300+
persistent_gnt->active = false;
283301
atomic_dec(&ring->persistent_gnt_in_use);
284302
}
285303

@@ -371,26 +389,26 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring)
371389
struct persistent_gnt *persistent_gnt;
372390
struct rb_node *n;
373391
unsigned int num_clean, total;
374-
bool scan_used = false, clean_used = false;
392+
bool scan_used = false;
375393
struct rb_root *root;
376394

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-
383395
if (work_busy(&ring->persistent_purge_work)) {
384396
pr_alert_ratelimited("Scheduled work from previous purge is still busy, cannot purge list\n");
385397
goto out;
386398
}
387399

388-
num_clean = (xen_blkif_max_pgrants / 100) * LRU_PERCENT_CLEAN;
389-
num_clean = ring->persistent_gnt_c - xen_blkif_max_pgrants + num_clean;
390-
num_clean = min(ring->persistent_gnt_c, num_clean);
391-
if ((num_clean == 0) ||
392-
(num_clean > (ring->persistent_gnt_c - atomic_read(&ring->persistent_gnt_in_use))))
393-
goto out;
400+
if (ring->persistent_gnt_c < xen_blkif_max_pgrants ||
401+
(ring->persistent_gnt_c == xen_blkif_max_pgrants &&
402+
!ring->blkif->vbd.overflow_max_grants)) {
403+
num_clean = 0;
404+
} else {
405+
num_clean = (xen_blkif_max_pgrants / 100) * LRU_PERCENT_CLEAN;
406+
num_clean = ring->persistent_gnt_c - xen_blkif_max_pgrants +
407+
num_clean;
408+
num_clean = min(ring->persistent_gnt_c, num_clean);
409+
pr_debug("Going to purge at least %u persistent grants\n",
410+
num_clean);
411+
}
394412

395413
/*
396414
* At this point, we can assure that there will be no calls
@@ -401,9 +419,7 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring)
401419
* number of grants.
402420
*/
403421

404-
total = num_clean;
405-
406-
pr_debug("Going to purge %u persistent grants\n", num_clean);
422+
total = 0;
407423

408424
BUG_ON(!list_empty(&ring->persistent_purge_list));
409425
root = &ring->persistent_gnts;
@@ -412,46 +428,37 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring)
412428
BUG_ON(persistent_gnt->handle ==
413429
BLKBACK_INVALID_HANDLE);
414430

415-
if (clean_used) {
416-
clear_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags);
431+
if (persistent_gnt->active)
417432
continue;
418-
}
419-
420-
if (test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags))
433+
if (!scan_used && !persistent_gnt_timeout(persistent_gnt))
421434
continue;
422-
if (!scan_used &&
423-
(test_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags)))
435+
if (scan_used && total >= num_clean)
424436
continue;
425437

426438
rb_erase(&persistent_gnt->node, root);
427439
list_add(&persistent_gnt->remove_node,
428440
&ring->persistent_purge_list);
429-
if (--num_clean == 0)
430-
goto finished;
441+
total++;
431442
}
432443
/*
433-
* If we get here it means we also need to start cleaning
444+
* Check whether we also need to start cleaning
434445
* grants that were used since last purge in order to cope
435446
* with the requested num
436447
*/
437-
if (!scan_used && !clean_used) {
438-
pr_debug("Still missing %u purged frames\n", num_clean);
448+
if (!scan_used && total < num_clean) {
449+
pr_debug("Still missing %u purged frames\n", num_clean - total);
439450
scan_used = true;
440451
goto purge_list;
441452
}
442-
finished:
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-
}
448453

449-
ring->persistent_gnt_c -= (total - num_clean);
450-
ring->blkif->vbd.overflow_max_grants = 0;
454+
if (total) {
455+
ring->persistent_gnt_c -= total;
456+
ring->blkif->vbd.overflow_max_grants = 0;
451457

452-
/* We can defer this work */
453-
schedule_work(&ring->persistent_purge_work);
454-
pr_debug("Purged %u/%u\n", (total - num_clean), total);
458+
/* We can defer this work */
459+
schedule_work(&ring->persistent_purge_work);
460+
pr_debug("Purged %u/%u\n", num_clean, total);
461+
}
455462

456463
out:
457464
return;

drivers/block/xen-blkback/common.h

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -233,24 +233,15 @@ struct xen_vbd {
233233

234234
struct backend_info;
235235

236-
/* Number of available flags */
237-
#define PERSISTENT_GNT_FLAGS_SIZE 2
238-
/* This persistent grant is currently in use */
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-
246236
/* Number of requests that we can fit in a ring */
247237
#define XEN_BLKIF_REQS_PER_PAGE 32
248238

249239
struct persistent_gnt {
250240
struct page *page;
251241
grant_ref_t gnt;
252242
grant_handle_t handle;
253-
DECLARE_BITMAP(flags, PERSISTENT_GNT_FLAGS_SIZE);
243+
unsigned long last_used;
244+
bool active;
254245
struct rb_node node;
255246
struct list_head remove_node;
256247
};
@@ -278,7 +269,6 @@ struct xen_blkif_ring {
278269
wait_queue_head_t pending_free_wq;
279270

280271
/* Tree to store persistent grants. */
281-
spinlock_t pers_gnts_lock;
282272
struct rb_root persistent_gnts;
283273
unsigned int persistent_gnt_c;
284274
atomic_t persistent_gnt_in_use;

0 commit comments

Comments
 (0)