static int pfn_covered()

in hv_balloon.c [785:843]


static int pfn_covered(unsigned long start_pfn, unsigned long pfn_cnt)
{
	struct hv_hotadd_state *has;
	struct hv_hotadd_gap *gap;
	unsigned long residual, new_inc;
	int ret = 0;
	unsigned long flags;

	spin_lock_irqsave(&dm_device.ha_lock, flags);
	list_for_each_entry(has, &dm_device.ha_region_list, list) {
		/*
		 * If the pfn range we are dealing with is not in the current
		 * "hot add block", move on.
		 */
		if (start_pfn < has->start_pfn || start_pfn >= has->end_pfn)
			continue;

		/*
		 * If the current start pfn is not where the covered_end
		 * is, create a gap and update covered_end_pfn.
		 */
		if (has->covered_end_pfn != start_pfn) {
			gap = kzalloc(sizeof(struct hv_hotadd_gap), GFP_ATOMIC);
			if (!gap) {
				ret = -ENOMEM;
				break;
			}

			INIT_LIST_HEAD(&gap->list);
			gap->start_pfn = has->covered_end_pfn;
			gap->end_pfn = start_pfn;
			list_add_tail(&gap->list, &has->gap_list);

			has->covered_end_pfn = start_pfn;
		}

		/*
		 * If the current hot add-request extends beyond
		 * our current limit; extend it.
		 */
		if ((start_pfn + pfn_cnt) > has->end_pfn) {
			residual = (start_pfn + pfn_cnt - has->end_pfn);
			/*
			 * Extend the region by multiples of HA_CHUNK.
			 */
			new_inc = (residual / HA_CHUNK) * HA_CHUNK;
			if (residual % HA_CHUNK)
				new_inc += HA_CHUNK;

			has->end_pfn += new_inc;
		}

		ret = 1;
		break;
	}
	spin_unlock_irqrestore(&dm_device.ha_lock, flags);

	return ret;
}