[Lguest] [PATCH 1/1][V2] Least Recently Used pgdirs
Jason Yeh
jasonyeh0908 at gmail.com
Tue Aug 21 11:18:35 EST 2007
Rusty Russell wrote:
>
> +51 lines (+1% lines) for 3% improvement? Sold!
>
> Except you seem to have increased the number of pgdirs to 5, so
> benchmark results don't really count:
The number is probably too good to be true. I will see how changing it
back will impact the new number.
>
> + if (lg->num_pgdirs > PGDIR_MAX) {
>
> This should be ==.
>
> Also, I think you mis-understood my recommendation. I was saying that
> find_pgdir_from_list should probably move the pgdir to the front, not
> alloc_newpgdir().
It was pointed out by Glauber that calling find_pgdir_from_list() does
not always mean that the pgdir will be used. It was the reason why I no
longer move the the pgidr in find_pgdir_from_list().
>
> Also build doesn't need to be -j4, that's overkill for a UP box.
>
> Your patch was still line-wrapped. Perhaps you need to use an
> attachment?
Thunderbird ate my external editor formatting for lunch. I will dump
Thunderbird and use another email client when corresponding to lists.
>
> Other minor things:
> 1) I prefer "MAX_PGDIRS" to PGDIR_MAX (the latter suggests pgdir is a
> counter or something).
>
>> + /* pgdir LRU
>> + * Newest pgdir is added to the head of the list.
>> + * pgdir_list is the tail of the list */
>> + struct list_head pgdir_list;
>> + struct pgdir *pgdir_cur;
>> + unsigned int num_pgdirs;
>
> Comment needs more meat, I think. How about:
>
> /* We keep up to MAX_PGDIRS page tables for each guest: latest-used is
> * moved to the head and we discard from the tail (ie. LRU). */
>
>> -static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable)
>> +static struct pgdir * find_pgdir_from_list(struct lguest *lg, unsigned
>> long pgtable)
>
> No space between the "struct pgdir *" and the "find_pgdir". Not sure it
> needs to be renamed, either?
>
>> +/* Helper to allocate new pgdir */
>> +struct pgdir * alloc_newpgdir(void)
>
> static? Also, alloc_newpgdir is redundant: alloc_pgdir?
>
>> -static unsigned int new_pgdir(struct lguest *lg,
>> +static struct pgdir * new_pgdir(struct lguest *lg,
>
> "static struct pgdir *new_pgdir()".
>
>> * top-level pgdir). This happens on almost every context switch. */
>> void guest_new_pagetable(struct lguest *lg, unsigned long pgtable)
>> {
>> - int newpgdir, repin = 0;
>> + int repin = 0;
>> + struct pgdir * newpgdir;
>
> No space after the '*'.
>
>> * its first page table is. We set some things up here: */
>> int init_guest_pagetable(struct lguest *lg, unsigned long pgtable)
>> {
>> + struct pgdir * newpgdir;
>> +
>> /* In flush_user_mappings() we loop from 0 to
>> * "vaddr_to_pgd_index(lg->page_offset)". This assumes it won't hit
>> * the Switcher mappings, so check that now. */
>> if (vaddr_to_pgd_index(lg->page_offset) >= SWITCHER_PGD_INDEX)
>> return -EINVAL;
>> - /* We start on the first shadow page table, and give it a blank PGD
>> - * page. */
>> - lg->pgdidx = 0;
>> - lg->pgdirs[lg->pgdidx].cr3 = pgtable;
>> - lg->pgdirs[lg->pgdidx].pgdir = (spgd_t*)get_zeroed_page(GFP_KERNEL);
>> - if (!lg->pgdirs[lg->pgdidx].pgdir)
>> +
>> + INIT_LIST_HEAD(&lg->pgdir_list);
>> +
>> + newpgdir = alloc_newpgdir();
>> + if (!newpgdir)
>> return -ENOMEM;
>> +
>> + lg->pgdir_cur = newpgdir;
>> + newpgdir->cr3 = pgtable;
>> + list_add(&newpgdir->list, &lg->pgdir_list);
>> + lg->num_pgdirs = 1;
>> +
>
> Hmm, perhaps rename alloc_newpgdir() to "add_pgdir()" and have it do the
> "list_add(&newpgdir->list, &lg->pgdir_list);", "lg->num_pgdirs++" and
> cr3 assignments? Then this code becomes:
>
> lg->pgdir_cur = add_pgdir(lg, pgtable);
> if (!lg->pgdir_cur)
> return -ENOMEM;
>
> And new_pgdir becomes:
>
> /* Have we reached the maximum number of pgdirs we can hold? */
> if (lg->num_pgdirs == PGDIR_MAX) {
> /* Grab the tail for recycling and move it to the front. */
> newpgdir = list_entry(lg->pgdir_list.prev, struct pgdir, list);
> list_move(&newpgdir->list, &lg->pgdir_list);
> /* Release all the non-kernel mappings. */
> flush_user_mappings(lg, newpgdir);
> /* Record which Guest toplevel this shadows. */
> lg->cr3 = cr3;
> } else {
> /* Now we try to allocate a fresh one. */
> newpgdir = alloc_newpgdir(lg, cr3);
> if (!newpgdir)
> kill_guest(lg, "failed to get fresh pgdir");
> /* This is a blank page, so there are no kernel
> * mappings: caller must map the stack! */
> *blank_pgdir = 1;
> }
> return newpgdir;
> }
I will incorporate the suggestion in my next patch. Thanks for the comments.
Jason
More information about the Lguest
mailing list