|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH V5] xen/privcmd.c: improve performance of MMAPBATCH_V2.
On Jan 2, 2013, at 11:45 AM, Mats Petersson <mats.petersson@xxxxxxxxxx> wrote:
> On 02/01/13 15:47, Andres Lagar-Cavilla wrote:
>> Hi,
>> On Dec 20, 2012, at 6:32 AM, Ian Campbell <ian.campbell@xxxxxxxxxx> wrote:
>>
>>> On Thu, 2012-12-20 at 11:00 +0000, Mats Petersson wrote:
>>>
>>>>>> - err = 0;
>>>>>> + err = last_err;
>>>>> This means that if you have 100 failures followed by one success you
>>>>> return success overall. Is that intentional? That doesn't seem right.
>>>> As far as I see, it doesn't mean that. last_err is only set at the
>>>> beginning of the call (to zero) and if there is an error.
>>> Ah, yes I missed that (but it still isn't right, see below).
>>>
>>>>>> diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
>>>>>> index 0bbbccb..8f86a44 100644
>>>>>> --- a/drivers/xen/privcmd.c
>>>>>> +++ b/drivers/xen/privcmd.c
>>>>> [...]
>>>>>> @@ -283,12 +317,10 @@ static int mmap_batch_fn(void *data, void *state)
>>>>>> if (xen_feature(XENFEAT_auto_translated_physmap))
>>>>>> cur_page = pages[st->index++];
>>>>>>
>>>>>> - ret = xen_remap_domain_mfn_range(st->vma, st->va & PAGE_MASK,
>>>>>> *mfnp, 1,
>>>>>> - st->vma->vm_page_prot,
>>>>>> st->domain,
>>>>>> - &cur_page);
>>>>>> -
>>>>>> - /* Store error code for second pass. */
>>>>>> - *(st->err++) = ret;
>>>>>> + BUG_ON(nr < 0);
>>>>>> + ret = xen_remap_domain_mfn_array(st->vma, st->va & PAGE_MASK,
>>>>>> mfnp, nr,
>>>>>> + st->err, st->vma->vm_page_prot,
>>>>>> + st->domain, &cur_page);
>>>>>>
>>>>>> /* And see if it affects the global_error. */
>>>>> The code which follows needs adjustment to cope with the fact that we
>>>>> now batch. I think it needs to walk st->err and set global_error as
>>>>> appropriate. This is related to my comment about the return value of
>>>>> xen_remap_domain_mfn_range too.
>>>> The return value, as commented above, is "either 0 or the last error we
>>>> saw". There should be no need to walk the st->err, as we know if there
>>>> was some error or not.
>>> The code which follows tries to latch having seen ENOENT in preference
>>> to other errors, so you don't need 0 or the last error, you need either
>>> 0, ENOENT if one occurred somewhere in the batch or an error!=ENOENT.
>>> (or maybe its vice versa, either way the last error isn't necessarily
>>> what you need).
>> Yeah the error reporting interface sucks. All I can say in my defense is
>> that it was that way when I got here.
>>
>> FWIW EFAULT *takes* precedence over ENOENT.
>> /* If we have not had any EFAULT-like global errors then set the global
>> * error to -ENOENT if necessary. */
>> if ((ret == 0) && (state.global_error == -ENOENT))
>> ret = -ENOENT;
>>
>> Otherwise, any individual mapping that fails differently from ENOENT does
>> not affect the global error. That is, in absence of global errors like
>> EFAULT, and in absence of per-mapping ENOENT return codes, per mapping
>> errors like EINVAL do not affect the ioctl return code which remains zero.
>>
>> IIUC Ian has been pointing that your code breaks this last statement.
> Sorry, are you saying the correct behaviour is to return 0 if we have EINVAL
> or some other error [aside from EFAULT and ENOENT]?
Yes. Note that before we get to actual mapping work we may fail with ENOMEM,
EINVAL, etc (but your patch does not affect that).
> Or are you saying that my code is broken such that it does this?
I didn't grok the patch as far as being sure whether it does it or not. I'll
look at your next version.
Thanks
Andres
>
> I did some fixes, that I believe "does the right thing", before Christmas,
> but since I knew most people wouldn't be available, I didn't post it. I will
> try to get round to it before the end of the week.
>
> --
> Mats
>>
>> Thanks
>> Andres
>>>>> I think rather than trying to fabricate some sort of meaningful error
>>>>> code for an entire batch xen_remap_domain_mfn_range should just return
>>>>> an indication about whether there were any errors or not and leave it to
>>>>> the caller to figure out the overall result by looking at the err array.
>>>>>
>>>>> Perhaps return either the number of errors or the number of successes
>>>>> (which turns the following if into either (ret) or (ret < nr)
>>>>> respectively).
>>>> I'm trying to not change how the code above expects things to work.
>>>> Whilst it would be lovely to rewrite the entire code dealing with
>>>> mapping memory, I don't think that's within the scope of my current
>>>> project. And if I don't wish to rewrite all of libxc's memory management
>>> I'm not talking about changing the libxc or ioctl interface, only about
>>> the internal-to-Linux interface between privcmd and mmu.c. In fact I'm
>>> only actually asking you to change the return value of the new function
>>> you are adding to the API.
>>>
>>>> code, I don't want to alter what values are returned or when. The
>>>> current code follows what WAS happening before my changes - which isn't
>>>> exactly the most fantastic thing, and I think there may actually be bugs
>>>> in there, such as:
>>>> if (ret < 0) {
>>>> if (ret == -ENOENT)
>>>> st->global_error = -ENOENT;
>>>> else {
>>>> /* Record that at least one error has happened. */
>>>> if (st->global_error == 0)
>>>> st->global_error = 1;
>>>> }
>>>> }
>>>> if we enter this once with -EFAULT, and then after that with -ENOENT,
>>>> global_error will say -ENOENT. I think knowing that we got an EFAULT is
>>>> "higher importance" than ENOENT, but that's how the old code was
>>>> working, and I'm not sure I should change it at this point.
>>> But I think you are changing it, by this behaviour or returning the last
>>> error in the batch which causes this code to behave differently. That's
>>> what I'm asking you to avoid!
>>>
>>>>>> if (ret < 0) {
>>>>>> @@ -300,7 +332,7 @@ static int mmap_batch_fn(void *data, void *state)
>>>>>> st->global_error = 1;
>>>>>> }
>>>>>> }
>>>>>> - st->va += PAGE_SIZE;
>>>>>> + st->va += PAGE_SIZE * nr;
>>>>>>
>>>>>> return 0;
>>>>>> }
>>>>>> @@ -430,8 +462,8 @@ static long privcmd_ioctl_mmap_batch(void __user
>>>>>> *udata, int version)
>>>>>> state.err = err_array;
>>>>>>
>>>>>> /* mmap_batch_fn guarantees ret == 0 */
>>>>>> - BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t),
>>>>>> - &pagelist, mmap_batch_fn, &state));
>>>>>> + BUG_ON(traverse_pages_block(m.num, sizeof(xen_pfn_t),
>>>>>> + &pagelist, mmap_batch_fn, &state));
>>>>> Can we make traverse_pages and _block common by passing a block size
>>>>> parameter?
>>>> Yes of course. Is there much benefit from that? I understand that it's
>>>> less code, but it also makes the original traverse_pages more complex.
>>>> Not convinced it helps much - it's quite a small function, so not much
>>>> extra code. Additionally, all of the callback functions will have to
>>>> deal with an extra parameter (that is probably ignored in all but one
>>>> place).
>>> It depends on what the combined version ends up looking like but in
>>> general I'm in favour of one more generic function over several cloned
>>> and hacked versions of the same thing.
>>>
>>> Ian.
>>>
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |