46
46
#include <linux/scatterlist.h>
47
47
#include <linux/bitmap.h>
48
48
#include <linux/list.h>
49
+ #include <linux/workqueue.h>
49
50
50
51
#include <xen/xen.h>
51
52
#include <xen/xenbus.h>
@@ -121,6 +122,8 @@ static inline struct blkif_req *blkif_req(struct request *rq)
121
122
122
123
static DEFINE_MUTEX (blkfront_mutex );
123
124
static const struct block_device_operations xlvbd_block_fops ;
125
+ static struct delayed_work blkfront_work ;
126
+ static LIST_HEAD (info_list );
124
127
125
128
/*
126
129
* Maximum number of segments in indirect requests, the actual value used by
@@ -216,6 +219,7 @@ struct blkfront_info
216
219
/* Save uncomplete reqs and bios for migration. */
217
220
struct list_head requests ;
218
221
struct bio_list bio_list ;
222
+ struct list_head info_list ;
219
223
};
220
224
221
225
static unsigned int nr_minors ;
@@ -1759,6 +1763,12 @@ static int write_per_ring_nodes(struct xenbus_transaction xbt,
1759
1763
return err ;
1760
1764
}
1761
1765
1766
+ static void free_info (struct blkfront_info * info )
1767
+ {
1768
+ list_del (& info -> info_list );
1769
+ kfree (info );
1770
+ }
1771
+
1762
1772
/* Common code used when first setting up, and when resuming. */
1763
1773
static int talk_to_blkback (struct xenbus_device * dev ,
1764
1774
struct blkfront_info * info )
@@ -1880,7 +1890,10 @@ static int talk_to_blkback(struct xenbus_device *dev,
1880
1890
destroy_blkring :
1881
1891
blkif_free (info , 0 );
1882
1892
1883
- kfree (info );
1893
+ mutex_lock (& blkfront_mutex );
1894
+ free_info (info );
1895
+ mutex_unlock (& blkfront_mutex );
1896
+
1884
1897
dev_set_drvdata (& dev -> dev , NULL );
1885
1898
1886
1899
return err ;
@@ -1991,6 +2004,10 @@ static int blkfront_probe(struct xenbus_device *dev,
1991
2004
info -> handle = simple_strtoul (strrchr (dev -> nodename , '/' )+ 1 , NULL , 0 );
1992
2005
dev_set_drvdata (& dev -> dev , info );
1993
2006
2007
+ mutex_lock (& blkfront_mutex );
2008
+ list_add (& info -> info_list , & info_list );
2009
+ mutex_unlock (& blkfront_mutex );
2010
+
1994
2011
return 0 ;
1995
2012
}
1996
2013
@@ -2301,6 +2318,12 @@ static void blkfront_gather_backend_features(struct blkfront_info *info)
2301
2318
if (indirect_segments <= BLKIF_MAX_SEGMENTS_PER_REQUEST )
2302
2319
indirect_segments = 0 ;
2303
2320
info -> max_indirect_segments = indirect_segments ;
2321
+
2322
+ if (info -> feature_persistent ) {
2323
+ mutex_lock (& blkfront_mutex );
2324
+ schedule_delayed_work (& blkfront_work , HZ * 10 );
2325
+ mutex_unlock (& blkfront_mutex );
2326
+ }
2304
2327
}
2305
2328
2306
2329
/*
@@ -2482,7 +2505,9 @@ static int blkfront_remove(struct xenbus_device *xbdev)
2482
2505
mutex_unlock (& info -> mutex );
2483
2506
2484
2507
if (!bdev ) {
2485
- kfree (info );
2508
+ mutex_lock (& blkfront_mutex );
2509
+ free_info (info );
2510
+ mutex_unlock (& blkfront_mutex );
2486
2511
return 0 ;
2487
2512
}
2488
2513
@@ -2502,7 +2527,9 @@ static int blkfront_remove(struct xenbus_device *xbdev)
2502
2527
if (info && !bdev -> bd_openers ) {
2503
2528
xlvbd_release_gendisk (info );
2504
2529
disk -> private_data = NULL ;
2505
- kfree (info );
2530
+ mutex_lock (& blkfront_mutex );
2531
+ free_info (info );
2532
+ mutex_unlock (& blkfront_mutex );
2506
2533
}
2507
2534
2508
2535
mutex_unlock (& bdev -> bd_mutex );
@@ -2585,7 +2612,7 @@ static void blkif_release(struct gendisk *disk, fmode_t mode)
2585
2612
dev_info (disk_to_dev (bdev -> bd_disk ), "releasing disk\n" );
2586
2613
xlvbd_release_gendisk (info );
2587
2614
disk -> private_data = NULL ;
2588
- kfree (info );
2615
+ free_info (info );
2589
2616
}
2590
2617
2591
2618
out :
@@ -2618,6 +2645,61 @@ static struct xenbus_driver blkfront_driver = {
2618
2645
.is_ready = blkfront_is_ready ,
2619
2646
};
2620
2647
2648
+ static void purge_persistent_grants (struct blkfront_info * info )
2649
+ {
2650
+ unsigned int i ;
2651
+ unsigned long flags ;
2652
+
2653
+ for (i = 0 ; i < info -> nr_rings ; i ++ ) {
2654
+ struct blkfront_ring_info * rinfo = & info -> rinfo [i ];
2655
+ struct grant * gnt_list_entry , * tmp ;
2656
+
2657
+ spin_lock_irqsave (& rinfo -> ring_lock , flags );
2658
+
2659
+ if (rinfo -> persistent_gnts_c == 0 ) {
2660
+ spin_unlock_irqrestore (& rinfo -> ring_lock , flags );
2661
+ continue ;
2662
+ }
2663
+
2664
+ list_for_each_entry_safe (gnt_list_entry , tmp , & rinfo -> grants ,
2665
+ node ) {
2666
+ if (gnt_list_entry -> gref == GRANT_INVALID_REF ||
2667
+ gnttab_query_foreign_access (gnt_list_entry -> gref ))
2668
+ continue ;
2669
+
2670
+ list_del (& gnt_list_entry -> node );
2671
+ gnttab_end_foreign_access (gnt_list_entry -> gref , 0 , 0UL );
2672
+ rinfo -> persistent_gnts_c -- ;
2673
+ __free_page (gnt_list_entry -> page );
2674
+ kfree (gnt_list_entry );
2675
+ }
2676
+
2677
+ spin_unlock_irqrestore (& rinfo -> ring_lock , flags );
2678
+ }
2679
+ }
2680
+
2681
+ static void blkfront_delay_work (struct work_struct * work )
2682
+ {
2683
+ struct blkfront_info * info ;
2684
+ bool need_schedule_work = false;
2685
+
2686
+ mutex_lock (& blkfront_mutex );
2687
+
2688
+ list_for_each_entry (info , & info_list , info_list ) {
2689
+ if (info -> feature_persistent ) {
2690
+ need_schedule_work = true;
2691
+ mutex_lock (& info -> mutex );
2692
+ purge_persistent_grants (info );
2693
+ mutex_unlock (& info -> mutex );
2694
+ }
2695
+ }
2696
+
2697
+ if (need_schedule_work )
2698
+ schedule_delayed_work (& blkfront_work , HZ * 10 );
2699
+
2700
+ mutex_unlock (& blkfront_mutex );
2701
+ }
2702
+
2621
2703
static int __init xlblk_init (void )
2622
2704
{
2623
2705
int ret ;
@@ -2650,6 +2732,8 @@ static int __init xlblk_init(void)
2650
2732
return - ENODEV ;
2651
2733
}
2652
2734
2735
+ INIT_DELAYED_WORK (& blkfront_work , blkfront_delay_work );
2736
+
2653
2737
ret = xenbus_register_frontend (& blkfront_driver );
2654
2738
if (ret ) {
2655
2739
unregister_blkdev (XENVBD_MAJOR , DEV_NAME );
@@ -2663,6 +2747,8 @@ module_init(xlblk_init);
2663
2747
2664
2748
static void __exit xlblk_exit (void )
2665
2749
{
2750
+ cancel_delayed_work_sync (& blkfront_work );
2751
+
2666
2752
xenbus_unregister_driver (& blkfront_driver );
2667
2753
unregister_blkdev (XENVBD_MAJOR , DEV_NAME );
2668
2754
kfree (minors );
0 commit comments