static void hv_mem_hot_add()

in hv_balloon.c [700:764]


static void hv_mem_hot_add(unsigned long start, unsigned long size,
				unsigned long pfn_count,
				struct hv_hotadd_state *has)
{
	int ret = 0;
	int i, nid;
	unsigned long start_pfn;
	unsigned long processed_pfn;
	unsigned long total_pfn = pfn_count;
	unsigned long flags;

	for (i = 0; i < (size/HA_CHUNK); i++) {
		start_pfn = start + (i * HA_CHUNK);

		spin_lock_irqsave(&dm_device.ha_lock, flags);
		has->ha_end_pfn +=  HA_CHUNK;

		if (total_pfn > HA_CHUNK) {
			processed_pfn = HA_CHUNK;
			total_pfn -= HA_CHUNK;
		} else {
			processed_pfn = total_pfn;
			total_pfn = 0;
		}

		has->covered_end_pfn +=  processed_pfn;
		spin_unlock_irqrestore(&dm_device.ha_lock, flags);

		reinit_completion(&dm_device.ol_waitevent);

		nid = memory_add_physaddr_to_nid(PFN_PHYS(start_pfn));
		ret = add_memory(nid, PFN_PHYS((start_pfn)),
				(HA_CHUNK << PAGE_SHIFT), MHP_MERGE_RESOURCE);

		if (ret) {
			pr_err("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;
			}
			spin_lock_irqsave(&dm_device.ha_lock, flags);
			has->ha_end_pfn -= HA_CHUNK;
			has->covered_end_pfn -=  processed_pfn;
			spin_unlock_irqrestore(&dm_device.ha_lock, flags);
			break;
		}

		/*
		 * Wait for memory to get onlined. If the kernel onlined the
		 * memory when adding it, this will return directly. Otherwise,
		 * it will wait for user space to online the memory. This helps
		 * to avoid adding memory faster than it is getting onlined. As
		 * adding succeeded, it is ok to proceed even if the memory was
		 * not onlined in time.
		 */
		wait_for_completion_timeout(&dm_device.ol_waitevent, 5 * HZ);
		post_status(&dm_device);
	}
}