Esempio n. 1
0
/**
 * test_alloc_help - Print help message to proc buffer
 * @procentry: Which proc buffer to write to
 */
void test_alloc_help(int procentry) {
	vmrproc_openbuffer(&testinfo[procentry]);

	printp("%s%s\n\n", MODULENAME, testinfo[procentry].name);
	printp("To run test, run \n");
	printp("echo order number > /proc/vmregress/%s\n\n", MODULENAME);
	printp("gfp_highuser = %d\n", gfp_highuser);
	printp("ms_delay = %d\n", ms_delay);
	printp("expected_count = %d\n", expected_count);
	printp("procbuf starting pages = %lu\n", PROCBUF_INIT_PAGES);
	
	vmrproc_closebuffer(&testinfo[procentry]);
}
Esempio n. 2
0
/**
 * test_fault_help - Print help message to proc buffer
 * @procentry: Which proc buffer to write to
 */
void test_fault_help(int procentry) {
	/* Efficively clear the proc buffer */
	vmrproc_openbuffer(&testinfo[procentry]);

	printp("%s%s\n\n", MODULENAME, testinfo[procentry].name);
	printp("To run test, run \n");
	printp("echo numpasses [numpages] > /proc/vmregress/%s%s\n\n", MODULENAME, testinfo[procentry].name);
	printp("Where numpasses is how many times to reference all the pages within\n");
	printp("a mapped area in memory numpages is an optional parameter of how many\n");
	printp("pages to allocate. When the test completes, cat this proc entry again\n");
	printp("to see the results.\n");
	printp("For more information, read the comment at the top of src/test/fault.c\n\n");

	vmrproc_closebuffer(&testinfo[procentry]);

	/* Set flags */
	testinfo[procentry].flags |= VMR_PRINTMAP;
}
Esempio n. 3
0
/**
 *
 * test_alloc_runtest - Allocate and free a number of pages from a ZONE_NORMAL
 * @params: Parameters read from the proc entry
 * @argc:   Number of parameters actually entered
 * @procentry: Proc buffer to write to
 *
 * If pages is set to 0, pages will be allocated until the pages_high watermark
 * is hit
 * Returns
 * 0  on success
 * -1 on failure
 *
 */
int test_alloc_runtest(int *params, int argc, int procentry) {
	unsigned long order;		/* Order of pages */
	unsigned long numpages;		/* Number of pages to allocate */
	struct page **pages;		/* Pages that were allocated */
	unsigned long attempts=0;
	unsigned long alloced=0;
	unsigned long nextjiffies = jiffies;
	unsigned long lastjiffies = jiffies;
	unsigned long success=0;
	unsigned long fail=0;
	unsigned long resched_count=0;
	unsigned long aborted=0;
	unsigned long long start_cycles, cycles;
	unsigned long page_dma=0, page_dma32=0, page_normal=0, page_highmem=0, page_easyrclm=0;
	struct zone *zone;
	char finishString[60];
	int timing_pages, pages_required;

	/* Set gfp_flags based on the module parameter */
	if (gfp_highuser) {
#ifdef GFP_RCLMUSER
		vmr_printk("Using highmem with GFP_RCLMUSER\n");
		gfp_flags = GFP_RCLMUSER;
#elif defined(GFP_HIGH_MOVABLE)
		vmr_printk("Using highmem with GFP_HIGH_MOVABLE\n");
		gfp_flags = GFP_HIGH_MOVABLE;
#elif defined(GFP_HIGHUSER_MOVABLE)
		vmr_printk("Using highmem with GFP_HIGHUSER_MOVABLE\n");
		gfp_flags = GFP_HIGHUSER_MOVABLE;
#else
		vmr_printk("Using highmem with GFP_HIGHUSER | __GFP_EASYRCLM\n");
		gfp_flags = GFP_HIGHUSER | __GFP_EASYRCLM;
#endif
	} else {
		vmr_printk("Using lowmem\n");
		gfp_flags |= __GFP_EASYRCLM|__GFP_MOVABLE;
	}
	vmr_printk("__GFP_EASYRCLM is 0x%8X\n", __GFP_EASYRCLM);
	vmr_printk("__GFP_MOVABLE  is 0x%8X\n", __GFP_MOVABLE);
	vmr_printk("gfp_flags       = 0x%8X\n", gfp_flags);
	
	/* Get the parameters */
	order = params[0];
	numpages = params[1];

	/* Make sure a buffer is available */
	if (vmrproc_checkbuffer(testinfo[HIGHALLOC_REPORT])) BUG();
	if (vmrproc_checkbuffer(testinfo[HIGHALLOC_TIMING])) BUG();
	if (vmrproc_checkbuffer(testinfo[HIGHALLOC_BUDDYINFO])) BUG();
	vmrproc_openbuffer(&testinfo[HIGHALLOC_REPORT]);
	vmrproc_openbuffer(&testinfo[HIGHALLOC_TIMING]);
	vmrproc_openbuffer(&testinfo[HIGHALLOC_BUDDYINFO]);

	/* Check parameters */
	if (order < 0 || order >= MAX_ORDER) {
		vmr_printk("Order request of %lu makes no sense\n", order);
		return -1;
	}

	if (numpages < 0) {
		vmr_printk("Number of pages %lu makes no sense\n", numpages);
		return -1;
	}

	/* 
	 * Allocate memory to store pointers to pages.
	 */
	pages = __vmalloc((numpages+1) * sizeof(struct page **),
			GFP_KERNEL|__GFP_HIGHMEM|__GFP_KERNRCLM|__GFP_RECLAIMABLE,
			PAGE_KERNEL);
	if (pages == NULL) {
		printp("Failed to allocate space to store page pointers\n");
		vmrproc_closebuffer(&testinfo[HIGHALLOC_REPORT]);
		vmrproc_closebuffer(&testinfo[HIGHALLOC_TIMING]);
		vmrproc_closebuffer(&testinfo[HIGHALLOC_BUDDYINFO]);
		return 0;
	}

	/* Setup proc buffer for timings */
	timing_pages = testinfo[HIGHALLOC_TIMING].procbuf_size / PAGE_SIZE;
	pages_required = (numpages * 20) / PAGE_SIZE;
	if (pages_required > timing_pages) {
		vmrproc_growbuffer(pages_required - timing_pages, 
					&testinfo[HIGHALLOC_TIMING]);
	}

	/* Setup proc buffer for highorder alloc */
	timing_pages = testinfo[HIGHALLOC_BUDDYINFO].procbuf_size / PAGE_SIZE;
	pages_required = (numpages * ((256 + 30 + 15 * MAX_ORDER) * num_online_nodes())) / PAGE_SIZE;
	if (pages_required > timing_pages) {
		vmrproc_growbuffer(pages_required - timing_pages, 
					&testinfo[HIGHALLOC_BUDDYINFO]);
	}

#if defined(OOM_DISABLE) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
	/* Disable OOM Killer */
	vmr_printk("Disabling OOM killer for running process\n");
	oomkilladj = current->oomkilladj;
	current->oomkilladj = OOM_DISABLE;
#endif /* OOM_DISABLE */

	/*
	 * Attempt to allocate the requested number of pages
	 */
	while (attempts++ != numpages) {
		struct page *page;
		if (lastjiffies > jiffies) nextjiffies = jiffies;
		while (jiffies < nextjiffies) check_resched(resched_count);
		nextjiffies = jiffies + ( (HZ * ms_delay)/1000);

		/* Print message if this is taking a long time */
		if (jiffies - lastjiffies > HZ) {
			printk("High order alloc test attempts: %lu (%lu)\n",
					attempts-1, alloced);
		}

		/* Print out a message every so often anyway */
		if (attempts > 1 && (attempts-1) % 10 == 0) {
			printp_entry(HIGHALLOC_TIMING, "\n");
			printk("High order alloc test attempts: %lu (%lu)\n",
					attempts-1, alloced);
		}

		lastjiffies = jiffies;

		start_cycles = read_clockcycles();
		page = alloc_pages(gfp_flags | __GFP_NOWARN, order);
		cycles = read_clockcycles() - start_cycles;

		if (page) {
			printp_entry(HIGHALLOC_TIMING, "%-11llu ", cycles);
			printp_buddyinfo(testinfo, HIGHALLOC_BUDDYINFO, attempts, 1);
			success++;
			pages[alloced++] = page;

			/* Count what zone this is */
			zone = page_zone(page);
			if (zone->name != NULL && !strcmp(zone->name, "EasyRclm")) page_easyrclm++;
			if (zone->name != NULL && !strcmp(zone->name, "Movable")) page_easyrclm++;
			if (zone->name != NULL && !strcmp(zone->name, "HighMem")) page_highmem++;
			if (zone->name != NULL && !strcmp(zone->name, "Normal")) page_normal++;
			if (zone->name != NULL && !strcmp(zone->name, "DMA32")) page_dma32++;
			if (zone->name != NULL && !strcmp(zone->name, "DMA")) page_dma++;


			/* Give up if it takes more than 60 seconds to allocate */
			if (jiffies - lastjiffies > HZ * 600) {
				printk("Took more than 600 seconds to allocate a block, giving up");
				aborted = attempts;
				attempts = numpages;
				break;
			}

		} else {
			printp_entry(HIGHALLOC_TIMING, "-%-10llu ", cycles);
			printp_buddyinfo(testinfo, HIGHALLOC_BUDDYINFO, attempts, 0);
			fail++;

			/* Give up if it takes more than 30 seconds to fail */
			if (jiffies - lastjiffies > HZ * 1200) {
				printk("Took more than 1200 seconds and still failed to allocate, giving up");
				aborted = attempts;
				attempts = numpages;
				break;
			}
		}
	}

	/* Re-enable OOM Killer state */
#ifdef OOM_DISABLED
	vmr_printk("Re-enabling OOM Killer status\n");
	current->oomkilladj = oomkilladj;
#endif

	vmr_printk("Test completed with %lu allocs, printing results\n", alloced);

	/* Print header */
	printp("Order:                 %lu\n", order);
	printp("Allocation type:       %s\n", gfp_highuser ? "HighMem" : "Normal");
	printp("Attempted allocations: %lu\n", numpages);
	printp("Success allocs:        %lu\n", success);
	printp("Failed allocs:         %lu\n", fail);
	printp("DMA32 zone allocs:       %lu\n", page_dma32);
	printp("DMA zone allocs:       %lu\n", page_dma);
	printp("Normal zone allocs:    %lu\n", page_normal);
	printp("HighMem zone allocs:   %lu\n", page_highmem);
	printp("EasyRclm zone allocs:  %lu\n", page_easyrclm);
	printp("%% Success:            %lu\n", (success * 100) / (unsigned long)numpages);

	/*
	 * Free up the pages
	 */
	vmr_printk("Test complete, freeing %lu pages\n", alloced);
	if (alloced > 0) {
		do {
			alloced--;
			if (pages[alloced] != NULL)
				__free_pages(pages[alloced], order);
		} while (alloced != 0);
		vfree(pages);
	}
	
	if (aborted == 0)
		strcpy(finishString, "Test completed successfully\n");
	else
		sprintf(finishString, "Test aborted after %lu allocations due to delays\n", aborted);
	
	printp(finishString);
	vmr_printk("Test completed, closing buffer\n");

	vmrproc_closebuffer(&testinfo[HIGHALLOC_REPORT]);
	vmrproc_closebuffer(&testinfo[HIGHALLOC_TIMING]);
	vmrproc_closebuffer(&testinfo[HIGHALLOC_BUDDYINFO]);
	vmr_printk("%s", finishString);
	return 0;
}
Esempio n. 4
0
/**
 *
 * test_fault_runtest - Allocate and free a number of pages from a zone
 * @params: Parameters read from the proc entry
 * @argc:   Number of parameters actually entered
 * @procentry: Proc buffer to write to
 *
 * If pages is set to 0, pages will be allocated until the pages_high watermark
 * is hit
 * Returns
 * 0  on success
 * -1 on failure
 *
 */
int test_fault_runtest(int *params, int argc, int procentry) {
	unsigned long nopages;		/* Number of pages to allocate */
	int nopasses;			/* Number of times to run test */
	C_ZONE *zone;			/* Zone been tested on */
	unsigned long freelimit;	/* The min no. free pages in zone */
	unsigned long alloccount;	/* Number of pages alloced */
	unsigned long present;		/* Number of pages present */
	unsigned long addr=0;		/* Address mapped area starts */
	unsigned long len;		/* Length of mapped area */
	unsigned long sched_count;	/* How many times schedule is called */
	unsigned long start;		/* Start of a test in jiffies */
	int totalpasses;		/* Total number of passes */
	int failed=0;			/* Failed mappings */

	/* Get the parameters */
	nopasses = params[0];
	nopages  = params[1];

	/* Make sure a buffer is available */
	if (vmrproc_checkbuffer(testinfo[procentry])) BUG();
	vmrproc_openbuffer(&testinfo[procentry]);

	/* Make sure passes is valid */
	if (nopasses <= 0)
	{
		vmr_printk("Cannot make 0 or negative number of passes\n");
		return -1;
	}

	/* Print header */
	printp("%s Test Results (" UTS_RELEASE ").\n\n", testinfo[procentry].name);

	/* Get the parameters for the test */
	if (test_fault_calculate_parameters(procentry, &zone, &nopages, &freelimit) == -1) {
		printp("Test failed\n");
		return -1;
	}
	len = nopages * PAGE_SIZE;

	/*
	 * map a region of memory where our pages are going to be stored 
	 * This is the same as the system call to mmap
	 *
	 */
	addr =  do_mmap(NULL,		/* No struct file */
			0,		/* No starting address */
			len,		/* Length of address space */
			PROT_WRITE | PROT_READ, /* Protection */
			MAP_PRIVATE | MAP_ANONYMOUS,	/* Private mapping */
			0);
			
	/* get_unmapped area has a horrible way of returning errors */
	if (addr == -1) {
		printp("Failed to mmap");
		return -1;
	}

	/* Print area information */
	printp("Mapped Area Information\n");
	printp("o address:  0x%lX\n", addr);
	printp("o length:   %lu (%lu pages)\n", len, nopages);
	printp("\n");

	/* Begin test */
	printp("Test Parameters\n");
	printp("o Passes:	       %d\n",  nopasses);
	printp("o Starting Free pages: %lu\n", zone->free_pages);
	printp("o Free page limit:     %lu\n", freelimit);
	printp("o References:	       %lu\n", nopages);
	printp("\n");

	printp("Test Results\n");
	printp("Pass       Refd     Present   Time\n");
	totalpasses = nopasses;

	/* Copy the string into every page once to alloc all ptes */
	alloccount=0;
	start = jiffies;
	while (nopages-- > 0) {
		check_resched(sched_count);

		copy_to_user((unsigned long *)(addr + (nopages * PAGE_SIZE)),
			test_string,
			strlen(test_string));

		alloccount++;
	}

	/*
	 * Step through the page tables pass number of times swapping in
	 * pages as necessary
	 */
	for (;;) {

		/* Count the number of pages present */
		present = countpages_mm(current->mm, addr, len, &sched_count);

		/* Print test info */
		printp("%-8d %8lu %8lu %8lums\n", totalpasses-nopasses,
							alloccount,
							present,
							jiffies_to_ms(start));

		if (nopasses-- == 0) break;

		/* Touch all the pages in the mapped area */
		start = jiffies;
		alloccount = forall_pte_mm(current->mm, addr, len, 
				&sched_count, NULL, touch_pte);

	}
	
	printp("\nPost Test Information\n");
	printp("o Finishing Free pages: %lu\n", zone->free_pages);
	printp("o Schedule() calls:     %lu\n", sched_count);
	printp("o Failed mappings:      %u\n",  failed);
	printp("\n");

	printp("Test completed successfully\n");

	/* Print out a process map */
	vmr_printmap(current->mm, addr, len, &sched_count, &testinfo[procentry]);
	/* Unmap the area */
	if (do_munmap(current->mm, addr, len) == -1) {
		printp("WARNING: Failed to unmap memory area"); }

	vmrproc_closebuffer(&testinfo[procentry]);
	return 0;
}