30
30
#define AUTOCOMMIT_MSEC 1000
31
31
#define MAX_AGE_DIV 16
32
32
#define MAX_AGE_UNSPECIFIED -1UL
33
+ #define PAUSE_WRITEBACK (HZ * 3)
33
34
34
35
#define BITMAP_GRANULARITY 65536
35
36
#if BITMAP_GRANULARITY < PAGE_SIZE
@@ -125,6 +126,7 @@ struct dm_writecache {
125
126
size_t freelist_high_watermark ;
126
127
size_t freelist_low_watermark ;
127
128
unsigned long max_age ;
129
+ unsigned long pause ;
128
130
129
131
unsigned uncommitted_blocks ;
130
132
unsigned autocommit_blocks ;
@@ -174,11 +176,13 @@ struct dm_writecache {
174
176
bool cleaner :1 ;
175
177
bool cleaner_set :1 ;
176
178
bool metadata_only :1 ;
179
+ bool pause_set :1 ;
177
180
178
181
unsigned high_wm_percent_value ;
179
182
unsigned low_wm_percent_value ;
180
183
unsigned autocommit_time_value ;
181
184
unsigned max_age_value ;
185
+ unsigned pause_value ;
182
186
183
187
unsigned writeback_all ;
184
188
struct workqueue_struct * writeback_wq ;
@@ -1470,9 +1474,11 @@ static int writecache_map(struct dm_target *ti, struct bio *bio)
1470
1474
}
1471
1475
1472
1476
unlock_remap_origin :
1473
- if (bio_data_dir (bio ) != READ ) {
1474
- dm_iot_io_begin (& wc -> iot , 1 );
1475
- bio -> bi_private = (void * )2 ;
1477
+ if (likely (wc -> pause != 0 )) {
1478
+ if (bio_op (bio ) == REQ_OP_WRITE ) {
1479
+ dm_iot_io_begin (& wc -> iot , 1 );
1480
+ bio -> bi_private = (void * )2 ;
1481
+ }
1476
1482
}
1477
1483
bio_set_dev (bio , wc -> dev -> bdev );
1478
1484
wc_unlock (wc );
@@ -1837,10 +1843,19 @@ static void writecache_writeback(struct work_struct *work)
1837
1843
dm_kcopyd_client_flush (wc -> dm_kcopyd );
1838
1844
}
1839
1845
1840
- if (!wc -> writeback_all && !dm_suspended (wc -> ti )) {
1841
- while (!dm_iot_idle_for (& wc -> iot , HZ )) {
1842
- cond_resched ();
1843
- msleep (1000 );
1846
+ if (likely (wc -> pause != 0 )) {
1847
+ while (1 ) {
1848
+ unsigned long idle ;
1849
+ if (unlikely (wc -> cleaner ) || unlikely (wc -> writeback_all ) ||
1850
+ unlikely (dm_suspended (wc -> ti )))
1851
+ break ;
1852
+ idle = dm_iot_idle_time (& wc -> iot );
1853
+ if (idle >= wc -> pause )
1854
+ break ;
1855
+ idle = wc -> pause - idle ;
1856
+ if (idle > HZ )
1857
+ idle = HZ ;
1858
+ schedule_timeout_idle (idle );
1844
1859
}
1845
1860
}
1846
1861
@@ -2113,7 +2128,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
2113
2128
struct wc_memory_superblock s ;
2114
2129
2115
2130
static struct dm_arg _args [] = {
2116
- {0 , 17 , "Invalid number of feature args" },
2131
+ {0 , 18 , "Invalid number of feature args" },
2117
2132
};
2118
2133
2119
2134
as .argc = argc ;
@@ -2206,6 +2221,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
2206
2221
goto bad ;
2207
2222
}
2208
2223
} else {
2224
+ wc -> pause = PAUSE_WRITEBACK ;
2209
2225
r = mempool_init_kmalloc_pool (& wc -> copy_pool , 1 , sizeof (struct copy_struct ));
2210
2226
if (r ) {
2211
2227
ti -> error = "Could not allocate mempool" ;
@@ -2344,6 +2360,18 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
2344
2360
} else goto invalid_optional ;
2345
2361
} else if (!strcasecmp (string , "metadata_only" )) {
2346
2362
wc -> metadata_only = true;
2363
+ } else if (!strcasecmp (string , "pause_writeback" ) && opt_params >= 1 ) {
2364
+ unsigned pause_msecs ;
2365
+ if (WC_MODE_PMEM (wc ))
2366
+ goto invalid_optional ;
2367
+ string = dm_shift_arg (& as ), opt_params -- ;
2368
+ if (sscanf (string , "%u%c" , & pause_msecs , & dummy ) != 1 )
2369
+ goto invalid_optional ;
2370
+ if (pause_msecs > 60000 )
2371
+ goto invalid_optional ;
2372
+ wc -> pause = msecs_to_jiffies (pause_msecs );
2373
+ wc -> pause_set = true;
2374
+ wc -> pause_value = pause_msecs ;
2347
2375
} else {
2348
2376
invalid_optional :
2349
2377
r = - EINVAL ;
@@ -2569,6 +2597,8 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
2569
2597
extra_args ++ ;
2570
2598
if (wc -> metadata_only )
2571
2599
extra_args ++ ;
2600
+ if (wc -> pause_set )
2601
+ extra_args += 2 ;
2572
2602
2573
2603
DMEMIT ("%u" , extra_args );
2574
2604
if (wc -> start_sector_set )
@@ -2591,6 +2621,8 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
2591
2621
DMEMIT (" %sfua" , wc -> writeback_fua ? "" : "no" );
2592
2622
if (wc -> metadata_only )
2593
2623
DMEMIT (" metadata_only" );
2624
+ if (wc -> pause_set )
2625
+ DMEMIT (" pause_writeback %u" , wc -> pause_value );
2594
2626
break ;
2595
2627
}
2596
2628
}
0 commit comments