@@ -633,6 +633,37 @@ static void vmballoon_add_page(struct vmballoon *b, int idx, struct page *p)
633633 b -> page = p ;
634634}
635635
636+ /**
637+ * vmballoon_change - retrieve the required balloon change
638+ *
639+ * @b: pointer for the balloon.
640+ *
641+ * Return: the required change for the balloon size. A positive number
642+ * indicates inflation, a negative number indicates a deflation.
643+ */
644+ static int64_t vmballoon_change (struct vmballoon * b )
645+ {
646+ int64_t size , target ;
647+
648+ size = b -> size ;
649+ target = b -> target ;
650+
651+ /*
652+ * We must cast first because of int sizes
653+ * Otherwise we might get huge positives instead of negatives
654+ */
655+
656+ if (b -> reset_required )
657+ return 0 ;
658+
659+ /* consider a 2MB slack on deflate, unless the balloon is emptied */
660+ if (target < size && size - target < vmballoon_page_size (true) &&
661+ target != 0 )
662+ return 0 ;
663+
664+ return target - size ;
665+ }
666+
636667/*
637668 * Inflate the balloon towards its target size. Note that we try to limit
638669 * the rate of allocation to make sure we are not choking the rest of the
@@ -644,8 +675,6 @@ static void vmballoon_inflate(struct vmballoon *b)
644675 int error = 0 ;
645676 bool is_2m_pages ;
646677
647- pr_debug ("%s - size: %d, target %d\n" , __func__ , b -> size , b -> target );
648-
649678 /*
650679 * First try NOSLEEP page allocations to inflate balloon.
651680 *
@@ -667,11 +696,8 @@ static void vmballoon_inflate(struct vmballoon *b)
667696 */
668697 is_2m_pages = b -> supported_page_sizes == VMW_BALLOON_NUM_PAGE_SIZES ;
669698
670- pr_debug ("%s - goal: %d" , __func__ , b -> target - b -> size );
671-
672- while (!b -> reset_required &&
673- b -> size + num_pages * vmballoon_page_size (is_2m_pages )
674- < b -> target ) {
699+ while ((int64_t )(num_pages * vmballoon_page_size (is_2m_pages )) <
700+ vmballoon_change (b )) {
675701 struct page * page ;
676702
677703 STATS_INC (b -> stats .alloc [is_2m_pages ]);
@@ -742,8 +768,6 @@ static void vmballoon_deflate(struct vmballoon *b)
742768{
743769 unsigned is_2m_pages ;
744770
745- pr_debug ("%s - size: %d, target %d\n" , __func__ , b -> size , b -> target );
746-
747771 /* free pages to reach target */
748772 for (is_2m_pages = 0 ; is_2m_pages < b -> supported_page_sizes ;
749773 is_2m_pages ++ ) {
@@ -753,11 +777,9 @@ static void vmballoon_deflate(struct vmballoon *b)
753777 & b -> page_sizes [is_2m_pages ];
754778
755779 list_for_each_entry_safe (page , next , & page_size -> pages , lru ) {
756- if (b -> reset_required ||
757- (b -> target > 0 &&
758- b -> size - num_pages
759- * vmballoon_page_size (is_2m_pages )
760- < b -> target + vmballoon_page_size (true)))
780+ if ((int64_t )(num_pages *
781+ vmballoon_page_size (is_2m_pages )) >=
782+ - vmballoon_change (b ))
761783 break ;
762784
763785 list_del (& page -> lru );
@@ -921,28 +943,35 @@ static void vmballoon_reset(struct vmballoon *b)
921943 pr_err ("failed to send guest ID to the host\n" );
922944}
923945
924- /*
925- * Balloon work function: reset protocol, if needed, get the new size and
926- * adjust balloon as needed. Repeat in 1 sec.
946+ /**
947+ * vmballoon_work - periodic balloon worker for reset, inflation and deflation.
948+ *
949+ * @work: pointer to the &work_struct which is provided by the workqueue.
950+ *
951+ * Resets the protocol if needed, gets the new size and adjusts balloon as
952+ * needed. Repeat in 1 sec.
927953 */
928954static void vmballoon_work (struct work_struct * work )
929955{
930956 struct delayed_work * dwork = to_delayed_work (work );
931957 struct vmballoon * b = container_of (dwork , struct vmballoon , dwork );
958+ int64_t change = 0 ;
932959
933960 STATS_INC (b -> stats .timer );
934961
935962 if (b -> reset_required )
936963 vmballoon_reset (b );
937964
938- if (!b -> reset_required && vmballoon_send_get_target (b )) {
939- unsigned long target = b -> target ;
965+ if (vmballoon_send_get_target (b ))
966+ change = vmballoon_change (b );
967+
968+ if (change != 0 ) {
969+ pr_debug ("%s - size: %u, target %u" , __func__ ,
970+ b -> size , b -> target );
940971
941- /* update target, adjust size */
942- if (b -> size < target )
972+ if (change > 0 )
943973 vmballoon_inflate (b );
944- else if (target == 0 ||
945- b -> size > target + vmballoon_page_size (true))
974+ else /* (change < 0) */
946975 vmballoon_deflate (b );
947976 }
948977
0 commit comments