Drivers: hv: Notify the host of permanent hot-add failures
[linux-3.10.git] / drivers / hv / hv_balloon.c
index d1b4a46..4c605c7 100644 (file)
@@ -590,6 +590,16 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
 
                if (ret) {
                        pr_info("hot_add memory failed error is %d\n", ret);
+                       if (ret == -EEXIST) {
+                               /*
+                                * This error indicates that the error
+                                * is not a transient failure. This is the
+                                * case where the guest's physical address map
+                                * precludes hot adding memory. Stop all further
+                                * memory hot-add.
+                                */
+                               do_hot_add = false;
+                       }
                        has->ha_end_pfn -= HA_CHUNK;
                        has->covered_end_pfn -=  processed_pfn;
                        break;
@@ -849,11 +859,30 @@ static void hot_add_req(struct work_struct *dummy)
                rg_sz = region_size;
        }
 
-       resp.page_count = process_hot_add(pg_start, pfn_cnt,
-                                       rg_start, rg_sz);
+       if (do_hot_add)
+               resp.page_count = process_hot_add(pg_start, pfn_cnt,
+                                               rg_start, rg_sz);
 #endif
+       /*
+        * The result field of the response structure has the
+        * following semantics:
+        *
+        * 1. If all or some pages hot-added: Guest should return success.
+        *
+        * 2. If no pages could be hot-added:
+        *
+        * If the guest returns success, then the host
+        * will not attempt any further hot-add operations. This
+        * signifies a permanent failure.
+        *
+        * If the guest returns failure, then this failure will be
+        * treated as a transient failure and the host may retry the
+        * hot-add operation after some delay.
+        */
        if (resp.page_count > 0)
                resp.result = 1;
+       else if (!do_hot_add)
+               resp.result = 1;
        else
                resp.result = 0;