@@ -83,6 +83,18 @@ module_param_named(max_persistent_grants, xen_blkif_max_pgrants, int, 0644);
83
83
MODULE_PARM_DESC (max_persistent_grants ,
84
84
"Maximum number of grants to map persistently" );
85
85
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
+
86
98
/*
87
99
* Maximum number of rings/queues blkback supports, allow as many queues as there
88
100
* are CPUs if user has not specified a value.
@@ -123,6 +135,13 @@ module_param(log_stats, int, 0644);
123
135
/* Number of free pages to remove on each call to gnttab_free_pages */
124
136
#define NUM_BATCH_FREE_PAGES 10
125
137
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
+
126
145
static inline int get_free_page (struct xen_blkif_ring * ring , struct page * * page )
127
146
{
128
147
unsigned long flags ;
@@ -278,7 +297,7 @@ static void put_persistent_gnt(struct xen_blkif_ring *ring,
278
297
{
279
298
if (!test_bit (PERSISTENT_GNT_ACTIVE , persistent_gnt -> flags ))
280
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
301
clear_bit (PERSISTENT_GNT_ACTIVE , persistent_gnt -> flags );
283
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
390
struct persistent_gnt * persistent_gnt ;
372
391
struct rb_node * n ;
373
392
unsigned int num_clean , total ;
374
- bool scan_used = false, clean_used = false ;
393
+ bool scan_used = false;
375
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
396
if (work_busy (& ring -> persistent_purge_work )) {
384
397
pr_alert_ratelimited ("Scheduled work from previous purge is still busy, cannot purge list\n" );
385
398
goto out ;
386
399
}
387
400
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 ;
401
+ if (ring -> persistent_gnt_c < xen_blkif_max_pgrants ||
402
+ (ring -> persistent_gnt_c == xen_blkif_max_pgrants &&
403
+ !ring -> blkif -> vbd .overflow_max_grants )) {
404
+ num_clean = 0 ;
405
+ } else {
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
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
420
* number of grants.
402
421
*/
403
422
404
- total = num_clean ;
405
-
406
- pr_debug ("Going to purge %u persistent grants\n" , num_clean );
423
+ total = 0 ;
407
424
408
425
BUG_ON (!list_empty (& ring -> persistent_purge_list ));
409
426
root = & ring -> persistent_gnts ;
@@ -412,46 +429,37 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring)
412
429
BUG_ON (persistent_gnt -> handle ==
413
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
432
if (test_bit (PERSISTENT_GNT_ACTIVE , persistent_gnt -> flags ))
421
433
continue ;
422
- if (!scan_used &&
423
- (test_bit (PERSISTENT_GNT_WAS_ACTIVE , persistent_gnt -> flags )))
434
+ if (!scan_used && !persistent_gnt_timeout (persistent_gnt ))
435
+ continue ;
436
+ if (scan_used && total >= num_clean )
424
437
continue ;
425
438
426
439
rb_erase (& persistent_gnt -> node , root );
427
440
list_add (& persistent_gnt -> remove_node ,
428
441
& ring -> persistent_purge_list );
429
- if (-- num_clean == 0 )
430
- goto finished ;
442
+ total ++ ;
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
446
* grants that were used since last purge in order to cope
435
447
* with the requested num
436
448
*/
437
- if (!scan_used && ! clean_used ) {
438
- pr_debug ("Still missing %u purged frames\n" , num_clean );
449
+ if (!scan_used && total < num_clean ) {
450
+ pr_debug ("Still missing %u purged frames\n" , num_clean - total );
439
451
scan_used = true;
440
452
goto purge_list ;
441
453
}
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
- }
448
454
449
- ring -> persistent_gnt_c -= (total - num_clean );
450
- ring -> blkif -> vbd .overflow_max_grants = 0 ;
455
+ if (total ) {
456
+ ring -> persistent_gnt_c -= total ;
457
+ ring -> blkif -> vbd .overflow_max_grants = 0 ;
451
458
452
- /* We can defer this work */
453
- schedule_work (& ring -> persistent_purge_work );
454
- pr_debug ("Purged %u/%u\n" , (total - num_clean ), total );
459
+ /* We can defer this work */
460
+ schedule_work (& ring -> persistent_purge_work );
461
+ pr_debug ("Purged %u/%u\n" , num_clean , total );
462
+ }
455
463
456
464
out :
457
465
return ;
0 commit comments