@@ -189,10 +189,9 @@ int64_t vcpu_calculate_dirtyrate(int64_t calc_time_ms,
189
189
return duration ;
190
190
}
191
191
192
- static bool is_sample_period_valid (int64_t sec )
192
+ static bool is_calc_time_valid (int64_t msec )
193
193
{
194
- if (sec < MIN_FETCH_DIRTYRATE_TIME_SEC ||
195
- sec > MAX_FETCH_DIRTYRATE_TIME_SEC ) {
194
+ if ((msec < MIN_CALC_TIME_MS ) || (msec > MAX_CALC_TIME_MS )) {
196
195
return false;
197
196
}
198
197
@@ -216,7 +215,39 @@ static int dirtyrate_set_state(int *state, int old_state, int new_state)
216
215
}
217
216
}
218
217
219
- static struct DirtyRateInfo * query_dirty_rate_info (void )
218
+ /* Decimal power of given time unit relative to one second */
219
+ static int time_unit_to_power (TimeUnit time_unit )
220
+ {
221
+ switch (time_unit ) {
222
+ case TIME_UNIT_SECOND :
223
+ return 0 ;
224
+ case TIME_UNIT_MILLISECOND :
225
+ return -3 ;
226
+ default :
227
+ assert (false); /* unreachable */
228
+ return 0 ;
229
+ }
230
+ }
231
+
232
+ static int64_t convert_time_unit (int64_t value , TimeUnit unit_from ,
233
+ TimeUnit unit_to )
234
+ {
235
+ int power = time_unit_to_power (unit_from ) -
236
+ time_unit_to_power (unit_to );
237
+ while (power < 0 ) {
238
+ value /= 10 ;
239
+ power += 1 ;
240
+ }
241
+ while (power > 0 ) {
242
+ value *= 10 ;
243
+ power -= 1 ;
244
+ }
245
+ return value ;
246
+ }
247
+
248
+
249
+ static struct DirtyRateInfo *
250
+ query_dirty_rate_info (TimeUnit calc_time_unit )
220
251
{
221
252
int i ;
222
253
int64_t dirty_rate = DirtyStat .dirty_rate ;
@@ -225,7 +256,10 @@ static struct DirtyRateInfo *query_dirty_rate_info(void)
225
256
226
257
info -> status = CalculatingState ;
227
258
info -> start_time = DirtyStat .start_time ;
228
- info -> calc_time = DirtyStat .calc_time ;
259
+ info -> calc_time = convert_time_unit (DirtyStat .calc_time_ms ,
260
+ TIME_UNIT_MILLISECOND ,
261
+ calc_time_unit );
262
+ info -> calc_time_unit = calc_time_unit ;
229
263
info -> sample_pages = DirtyStat .sample_pages ;
230
264
info -> mode = dirtyrate_mode ;
231
265
@@ -264,7 +298,7 @@ static void init_dirtyrate_stat(int64_t start_time,
264
298
{
265
299
DirtyStat .dirty_rate = -1 ;
266
300
DirtyStat .start_time = start_time ;
267
- DirtyStat .calc_time = config .sample_period_seconds ;
301
+ DirtyStat .calc_time_ms = config .calc_time_ms ;
268
302
DirtyStat .sample_pages = config .sample_pages_per_gigabytes ;
269
303
270
304
switch (config .mode ) {
@@ -574,7 +608,6 @@ static inline void dirtyrate_manual_reset_protect(void)
574
608
575
609
static void calculate_dirtyrate_dirty_bitmap (struct DirtyRateConfig config )
576
610
{
577
- int64_t msec = 0 ;
578
611
int64_t start_time ;
579
612
DirtyPageRecord dirty_pages ;
580
613
@@ -602,9 +635,7 @@ static void calculate_dirtyrate_dirty_bitmap(struct DirtyRateConfig config)
602
635
start_time = qemu_clock_get_ms (QEMU_CLOCK_REALTIME );
603
636
DirtyStat .start_time = start_time / 1000 ;
604
637
605
- msec = config .sample_period_seconds * 1000 ;
606
- msec = dirty_stat_wait (msec , start_time );
607
- DirtyStat .calc_time = msec / 1000 ;
638
+ DirtyStat .calc_time_ms = dirty_stat_wait (config .calc_time_ms , start_time );
608
639
609
640
/*
610
641
* do two things.
@@ -615,12 +646,12 @@ static void calculate_dirtyrate_dirty_bitmap(struct DirtyRateConfig config)
615
646
616
647
record_dirtypages_bitmap (& dirty_pages , false);
617
648
618
- DirtyStat .dirty_rate = do_calculate_dirtyrate (dirty_pages , msec );
649
+ DirtyStat .dirty_rate = do_calculate_dirtyrate (dirty_pages ,
650
+ DirtyStat .calc_time_ms );
619
651
}
620
652
621
653
static void calculate_dirtyrate_dirty_ring (struct DirtyRateConfig config )
622
654
{
623
- int64_t duration ;
624
655
uint64_t dirtyrate = 0 ;
625
656
uint64_t dirtyrate_sum = 0 ;
626
657
int i = 0 ;
@@ -631,12 +662,10 @@ static void calculate_dirtyrate_dirty_ring(struct DirtyRateConfig config)
631
662
DirtyStat .start_time = qemu_clock_get_ms (QEMU_CLOCK_REALTIME ) / 1000 ;
632
663
633
664
/* calculate vcpu dirtyrate */
634
- duration = vcpu_calculate_dirtyrate (config .sample_period_seconds * 1000 ,
635
- & DirtyStat .dirty_ring ,
636
- GLOBAL_DIRTY_DIRTY_RATE ,
637
- true);
638
-
639
- DirtyStat .calc_time = duration / 1000 ;
665
+ DirtyStat .calc_time_ms = vcpu_calculate_dirtyrate (config .calc_time_ms ,
666
+ & DirtyStat .dirty_ring ,
667
+ GLOBAL_DIRTY_DIRTY_RATE ,
668
+ true);
640
669
641
670
/* calculate vm dirtyrate */
642
671
for (i = 0 ; i < DirtyStat .dirty_ring .nvcpu ; i ++ ) {
@@ -652,7 +681,6 @@ static void calculate_dirtyrate_sample_vm(struct DirtyRateConfig config)
652
681
{
653
682
struct RamblockDirtyInfo * block_dinfo = NULL ;
654
683
int block_count = 0 ;
655
- int64_t msec = 0 ;
656
684
int64_t initial_time ;
657
685
658
686
rcu_read_lock ();
@@ -662,17 +690,16 @@ static void calculate_dirtyrate_sample_vm(struct DirtyRateConfig config)
662
690
}
663
691
rcu_read_unlock ();
664
692
665
- msec = config .sample_period_seconds * 1000 ;
666
- msec = dirty_stat_wait ( msec , initial_time );
693
+ DirtyStat . calc_time_ms = dirty_stat_wait ( config .calc_time_ms ,
694
+ initial_time );
667
695
DirtyStat .start_time = initial_time / 1000 ;
668
- DirtyStat .calc_time = msec / 1000 ;
669
696
670
697
rcu_read_lock ();
671
698
if (!compare_page_hash_info (block_dinfo , block_count )) {
672
699
goto out ;
673
700
}
674
701
675
- update_dirtyrate (msec );
702
+ update_dirtyrate (DirtyStat . calc_time_ms );
676
703
677
704
out :
678
705
rcu_read_unlock ();
@@ -718,6 +745,8 @@ void *get_dirtyrate_thread(void *arg)
718
745
}
719
746
720
747
void qmp_calc_dirty_rate (int64_t calc_time ,
748
+ bool has_calc_time_unit ,
749
+ TimeUnit calc_time_unit ,
721
750
bool has_sample_pages ,
722
751
int64_t sample_pages ,
723
752
bool has_mode ,
@@ -737,10 +766,15 @@ void qmp_calc_dirty_rate(int64_t calc_time,
737
766
return ;
738
767
}
739
768
740
- if (!is_sample_period_valid (calc_time )) {
741
- error_setg (errp , "calc-time is out of range[%d, %d]." ,
742
- MIN_FETCH_DIRTYRATE_TIME_SEC ,
743
- MAX_FETCH_DIRTYRATE_TIME_SEC );
769
+ int64_t calc_time_ms = convert_time_unit (
770
+ calc_time ,
771
+ has_calc_time_unit ? calc_time_unit : TIME_UNIT_SECOND ,
772
+ TIME_UNIT_MILLISECOND
773
+ );
774
+
775
+ if (!is_calc_time_valid (calc_time_ms )) {
776
+ error_setg (errp , "Calculation time is out of range [%dms, %dms]." ,
777
+ MIN_CALC_TIME_MS , MAX_CALC_TIME_MS );
744
778
return ;
745
779
}
746
780
@@ -787,7 +821,7 @@ void qmp_calc_dirty_rate(int64_t calc_time,
787
821
return ;
788
822
}
789
823
790
- config .sample_period_seconds = calc_time ;
824
+ config .calc_time_ms = calc_time_ms ;
791
825
config .sample_pages_per_gigabytes = sample_pages ;
792
826
config .mode = mode ;
793
827
@@ -806,14 +840,18 @@ void qmp_calc_dirty_rate(int64_t calc_time,
806
840
(void * )& config , QEMU_THREAD_DETACHED );
807
841
}
808
842
809
- struct DirtyRateInfo * qmp_query_dirty_rate (Error * * errp )
843
+
844
+ struct DirtyRateInfo * qmp_query_dirty_rate (bool has_calc_time_unit ,
845
+ TimeUnit calc_time_unit ,
846
+ Error * * errp )
810
847
{
811
- return query_dirty_rate_info ();
848
+ return query_dirty_rate_info (
849
+ has_calc_time_unit ? calc_time_unit : TIME_UNIT_SECOND );
812
850
}
813
851
814
852
void hmp_info_dirty_rate (Monitor * mon , const QDict * qdict )
815
853
{
816
- DirtyRateInfo * info = query_dirty_rate_info ();
854
+ DirtyRateInfo * info = query_dirty_rate_info (TIME_UNIT_SECOND );
817
855
818
856
monitor_printf (mon , "Status: %s\n" ,
819
857
DirtyRateStatus_str (info -> status ));
@@ -873,8 +911,11 @@ void hmp_calc_dirty_rate(Monitor *mon, const QDict *qdict)
873
911
mode = DIRTY_RATE_MEASURE_MODE_DIRTY_RING ;
874
912
}
875
913
876
- qmp_calc_dirty_rate (sec , has_sample_pages , sample_pages , true,
877
- mode , & err );
914
+ qmp_calc_dirty_rate (sec , /* calc-time */
915
+ false, TIME_UNIT_SECOND , /* calc-time-unit */
916
+ has_sample_pages , sample_pages ,
917
+ true, mode ,
918
+ & err );
878
919
if (err ) {
879
920
hmp_handle_error (mon , err );
880
921
return ;
0 commit comments