Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 Jan 2019 13:53:00 +0100
From:      Willem Jan Withagen <wjw@digiware.nl>
To:        Alan Somers <asomers@freebsd.org>
Cc:        FreeBSD Hackers <freebsd-hackers@freebsd.org>
Subject:   Re: Using kqueue with aio_read/write
Message-ID:  <016fda76-8f02-ca62-af7d-062262bd4a09@digiware.nl>
In-Reply-To: <CAOtMX2ics595SQTDR=ORF8YCTOgm9JSk-Nv1T89O6iCOp5O4fg@mail.gmail.com>
References:  <8753521a-4555-ec2a-5efc-dee2660b4d9b@digiware.nl> <CAOtMX2iOy4Uf%2B9%2BuYhbX-wXJ68E57CjTW0aLPsa3dH__n4oP_w@mail.gmail.com> <969d9a38-d3dd-78d0-c974-ba14ec4747db@digiware.nl> <CAOtMX2ics595SQTDR=ORF8YCTOgm9JSk-Nv1T89O6iCOp5O4fg@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On 02/01/2019 03:23, Alan Somers wrote:
> On Tue, Jan 1, 2019 at 6:56 PM Willem Jan Withagen <wjw@digiware.nl> wrote:
>> On 28/12/2018 02:47, Alan Somers wrote:
>>> On Thu, Dec 27, 2018 at 6:15 PM Willem Jan Withagen <wjw@digiware.nl> wrote:
>>>> Hi,
>>>>
>>>> Im trying to understand why I cannot get so code to work.
>>>> This is the smallest extract I can make to show my problem.
>>>>
>>>> I would expect the kevent() call to return every timeo tick.
>>>> Even if I tell it NOT to time-out I get these spurts of errors
>>>>
>>>> Since there is nothing to trigger the AIO-event, I would expect kqueue
>>>> to hold indefinitly.
>>>>
>>>> But it does not generate anything other than errors
>>>> And instead it repeatedly complains that there is a permission error:
>>>>      get_events_kevent: EV_Error(1) kevent(): Operation not permitted
>>>>
>>>> But I'm not getting where that would the case...
>>>>
>>>> Surely a pilot error, but I do overlook it al the time.
>>>> So suggestions are welcome.
>>>>
>>>> Thanx,
>>>> --WjW
>>>>
>>>> #include <aio.h>
>>>> #include <errno.h>
>>>> #include <fcntl.h>
>>>> #include <stdio.h>
>>>> #include <stdlib.h>
>>>> #include <string.h>
>>>> #include <sys/stat.h>
>>>> #include <sys/event.h>
>>>> #include <unistd.h>
>>>>
>>>> #define BUFFER_SIZE     512
>>>> #define MAX_EVENTS 32
>>>>
>>>> #define FILENAME "/tmp/aio_test"
>>>> char filename[256];
>>>> int fd;
>>>> int done = 0;
>>>>
>>>> void get_events_kevent(int fd, int kq)
>>>> {
>>>>        printf("get_events function fd = %d, kq = %d\n", fd, kq);
>>>>        int i = 0, errcnt = 0, err, ret, reterr, rev;
>>>>        int search = 1;
>>>>
>>>>        int timeout_ms = 10;
>>>>        struct timespec timeo = {
>>>>            timeout_ms / 1000,
>>>>            (timeout_ms % 1000) * 1000 * 1000
>>>>        };
>>>>        struct kevent filter[16];
>>>>        struct kevent changed[16];
>>>>
>>>>        EV_SET(&filter[0], fd, EVFILT_AIO,
>>>>                EV_ADD,
>>>>                0, 0, 0 );
>>> This is the first problem.  There's no need to explicitly set
>>> EVFILT_AIO on the kqueue.  It gets set by the aio_read(2) or similar
>>> syscall.  And this invocation wouldn't be correct anyway, because for
>>> AIO the ident field refers to the address of the struct aiocb, not the
>>> file descriptor.  If the only events you care about are AIO, then you
>>> can pass NULL as the filter argument to kevent.  I suspect this is the
>>> cause of your problem.  The kernel probably thinks you're trying to
>>> register for an aiocb that's outside of your address space or
>>> something like that.
>>>
>>>
>>>>        while (!done) {
>>>>            printf("+");
>>>>            rev = kevent(kq, filter, 1, changed, 16, 0); //&timeo);
>>>>            if (rev < 0) {
>>>>                perror("kevent error");
>>>>            } else if (rev == 0) {
>>>>                printf("T");
>>>>            } else {
>>>>                printf("rev(%d)\n", rev);
>>>>                if (changed[0].flags == EV_ERROR) {
>>>>                    errno = changed[0].data;
>>>>                    printf( "%s: EV_Error(%d) kevent(): %s\n", __func__, errno,
>>>>                        strerror(errno));
>>>>                    memset(&changed[0], 0, sizeof(struct kevent));
>>>>                } else {
>>>>                    err = aio_error((struct aiocb*)changed[0].udata);
>>> No need to call aio_error(2) after kevent(2) returns.  You can go
>>> straight to aio_return.  aio_error shouldn't hurt, but it isn't
>>> necessary.
>> According to kevent(2) calling kevent can return errors on the called
>> aio_calls.
>> It then returns with EV_ERROR in flags, and errno is stored in the
>> event.data.
>>
>> But what would be going on when the event's flag contains EV_ERROR but
>> event's data is still 0???
>>
>> the udata field still seems to point to the aio data that was passed
>> into the aio block when calling aio_read().
>>
>> Should I ignore this as a non-error?
>>
>> --WjW
> Are you sure you bzero()ed your aiocb before initializing it?  Any
> stack garbage that was present in its
> aio_sigevent.sigev_notify_kevent_flags field will be dutifully copied
> into the returned kevent.  And in any case, the definitive way to get
> the final status of a completed aio operation is with aio_return.
That seems to help in getting things clear...

    -13> 2019-01-02 13:32:31.834 dc15a80  1 bdev:327 paio 
get_next_completed processing event i = 0 aio_return(22) (22) Invalid 
argument

Disadvantage is that it is not clear yet which of the many arguments 
that is?

--WjW




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?016fda76-8f02-ca62-af7d-062262bd4a09>