Tony,

On Thu, Jun 15, 2006 at 02:56:42PM -0700, Luck, Tony wrote:
> > If not, what is your opinion of the two approaches above?
> 
> 1408 bytes of local storage out of a 4K stack on x86 sounds
> too big ... especially if you implement as suggested above:
> 
For x86, I am not suggesting 8, but something smaller like 4.
Current struct size for PMD is 176 and PNMC is 48, we can trim
a few bytes out of the reserved fields. Unfortunately we cannot
come down to 128 (nice cache line size) for the PMD.

>  someroutine(int count)
>  {
>       struct foo foo[8], *foop;
> 
>       if (count < 8)
>               foop = foo;
>       else
>               foop = kmalloc(8*sizeof *foop, GFP_...);
> 
>       ....
> }
> 
> The problem here is that you have already burned up a
> big patch of the stack with your local structure.  So
> kmalloc() is called without much left.  Most of the time
> this doesn't matter because kmalloc() will just give
> you a block from the slab without much further stack use.
> 
> But if memory is low, then the kmalloc() call will trigger
> a much deeper stack sequence to try to free up some, and
> since you already used a bunch of stack, this may push
> you over the edge ... but you won't know unless your test
> suites happen to trigger a memory shortage that happens
> just as you make this pfm call with >8 count.
> 
I understand your point. The alternative is as I described in
my previous E-mail to use an argument buffer per context.
But then you would have to use the following sequence:

 someroutine(intfd, struct foo *foo, int count)
 {
        struct foo *foop;

        ctx = get_ctx(fd);

        size = count * sizeof(*foop);

        spin_lock(&ctx->lock);

        if (ctx->arg_buffer_size < sz) {
                if (sz > sysctl.max_arg_size)
                        goto error;
                if (ctx->arg_buffer)
                        kfree(arg_buffer);
                ctx-> ctx_arg_buffer = kmalloc(sz);
                ctx->arg_buffer_sze = sz;
        }
        foop = ctx->arg_buffer;

        copy_from_user(foop, foo, sz);

        local_irq_save(flags);

        /* do the real work */

        local_irq_restore(flags);

        copy_to_user(foo, foop, sz);

        spin_unlock(&ctx->lock);
        
        ....
 }
But I am not sure you can really do copy_to/from with some locks held.
I know for sure you cannot do it with interrupts masked.

As I pointed out with this approacj, it is hard to protect against someone
creating NFILE contexts and allocating sysctl.max_arg_size for each.

Do you see a better alternative?

Thanks.

_______________________________________________
perfmon mailing list
[email protected]
http://www.hpl.hp.com/hosted/linux/mail-archives/perfmon/

Reply via email to