qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 3/3] Add helper functions to enable virtio-9p ma


From: Venkateswararao Jujjuri (JV)
Subject: Re: [Qemu-devel] [PATCH 3/3] Add helper functions to enable virtio-9p make use of the threadlets
Date: Tue, 09 Nov 2010 17:41:44 -0800
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101027 Thunderbird/3.1.6

On 11/9/2010 1:06 AM, Stefan Hajnoczi wrote:
> On Mon, Nov 8, 2010 at 10:47 AM, Arun R Bharadwaj
> <address@hidden> wrote:
>> diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
>> index 7c59988..61b65fd 100644
>> --- a/hw/virtio-9p.c
>> +++ b/hw/virtio-9p.c
>> @@ -18,6 +18,7 @@
>>  #include "fsdev/qemu-fsdev.h"
>>  #include "virtio-9p-debug.h"
>>  #include "virtio-9p-xattr.h"
>> +#include "qemu-threadlets.h"
>>
>>  int debug_9p_pdu;
>>
>> @@ -33,6 +34,146 @@ enum {
>>     Oappend = 0x80,
>>  };
>>
>> +struct v9fs_post_op {
>> +    QTAILQ_ENTRY(v9fs_post_op) node;
>> +    void (*func)(void *arg);
>> +    void *arg;
>> +};
> 
> Structs are usually typedefed:
> typedef struct V9fsPostOp {
>     ...
> } V9fsPostOp;
> 
> QEMU usually doesn't use struct explicitly unless a library interface
> requires it.
> 
>> +
>> +static struct {
>> +    int rfd;
>> +    int wfd;
>> +    QemuMutex lock;
>> +    QTAILQ_HEAD(, v9fs_post_op) post_op_list;
>> +} v9fs_async_struct;
>> +
>> +static void die2(int err, const char *what)
>> +{
>> +    fprintf(stderr, "%s failed: %s\n", what, strerror(err));
>> +    abort();
>> +}
>> +
>> +static void die(const char *what)
>> +{
>> +    die2(errno, what);
>> +}
>> +
>> +#define ASYNC_MAX_PROCESS   5
>> +
>> +/**
>> + * v9fs_process_post_ops: Process any pending v9fs_post_posix_operation
>> + * @arg: Not used.
>> + *
>> + * This function serves as a callback to the iothread to be called into 
>> whenever
>> + * the v9fs_async_struct.wfd is written into. This thread goes through the 
>> list
>> + * of v9fs_post_posix_operations() and executes them. In the process, it 
>> might
>> + * queue more job on the asynchronous thread pool.
>> + */
>> +static void v9fs_process_post_ops(void *arg)
>> +{
>> +    int count = 0;
>> +    struct v9fs_post_op *post_op;
>> +    int ret;
>> +    char byte;
>> +
>> +    qemu_mutex_lock(&v9fs_async_struct.lock);
>> +    do {
>> +        ret = read(v9fs_async_struct.rfd, &byte, sizeof(byte));
>> +    } while (ret >= 0 && errno != EAGAIN);
> 
> } while (ret > 1 || (ret == -1 && errno == EINTR)); ?

Not sure why we need to retry if ret > 1; all we need is

} while (ret == -1 && errno == EINTR);

> 
>> +
>> +    for (count = 0; count < ASYNC_MAX_PROCESS; count++) {
>> +        if (QTAILQ_EMPTY(&(v9fs_async_struct.post_op_list))) {
>> +           break;
>> +        }
>> +        post_op = QTAILQ_FIRST(&(v9fs_async_struct.post_op_list));
>> +        QTAILQ_REMOVE(&(v9fs_async_struct.post_op_list), post_op, node);
>> +
>> +        qemu_mutex_unlock(&v9fs_async_struct.lock);
>> +        post_op->func(post_op->arg);
>> +        qemu_free(post_op);
>> +        qemu_mutex_lock(&v9fs_async_struct.lock);
>> +    }
>> +    qemu_mutex_unlock(&v9fs_async_struct.lock);
>> +}
>> +
>> +/**
>> + * v9fs_async_signal: Inform the io-thread of completion of async job.
>> + *
>> + * This function is used to inform the iothread that a particular
>> + * async-operation pertaining to v9fs has been completed and that the io 
>> thread
>> + * can handle the v9fs_post_posix_operation.
>> + *
>> + * This is based on the aio_signal_handler
>> + */
>> +static inline void v9fs_async_signal(void)
>> +{
>> +    char byte = 0;
>> +    ssize_t ret;
>> +    int tries = 0;
>> +
>> +    qemu_mutex_lock(&v9fs_async_struct.lock);
>> +    do {
>> +        assert(tries != 100);
>> +       ret = write(v9fs_async_struct.wfd, &byte, sizeof(byte));
>> +        tries++;
>> +    } while (ret < 0 && errno == EAGAIN);
>> +    qemu_mutex_unlock(&v9fs_async_struct.lock);
>> +
>> +    if (ret < 0 && errno != EAGAIN)
>> +        die("write() in v9fs");
> 
> { } coding style
> 
>> +
>> +    if (kill(getpid(), SIGUSR2)) die("kill failed");
> 
> { } coding style
> 
>> +}
>> +
>> +/**
>> + * v9fs_async_helper_done: Marks the completion of the v9fs_async job
>> + * @func: v9fs_post_posix_func() for post-processing invoked in the context 
>> of
>> + *        the io-thread
>> + * @arg: Argument to func.
>> + *
>> + * This function is called from the context of one of the asynchronous 
>> threads
>> + * in the thread pool. This is called when the asynchronous thread has 
>> finished
>> + * executing a v9fs_posix_operation. It's purpose is to initiate the 
>> process of
>> + * informing the io-thread that the v9fs_posix_operation has completed.
>> + */
>> +static void v9fs_async_helper_done(void (*func)(void *arg), void *arg)
>> +{
>> +    struct v9fs_post_op *post_op;
>> +
>> +    post_op = qemu_mallocz(sizeof(*post_op));
>> +    post_op->func = func;
>> +    post_op->arg = arg;
>> +
>> +    qemu_mutex_lock(&v9fs_async_struct.lock);
>> +    QTAILQ_INSERT_TAIL(&(v9fs_async_struct.post_op_list), post_op, node);
>> +    qemu_mutex_unlock(&v9fs_async_struct.lock);
>> +
>> +    v9fs_async_signal();
>> +}
>> +
>> +/**
>> + * v9fs_do_async_posix: Offload v9fs_posix_operation onto async thread.
>> + * @vs: V9fsOPState variable for the OP operation.
>> + * @posix_fn: The posix function which has to be offloaded onto async 
>> thread.
>> + * @post_fn_ptr: Address of the location to hold the post_fn corresponding 
>> to
>> + * the posix_fn
>> + * @post_fn: The post processing function corresponding to the posix_fn.
>> + *
>> + * This function is a helper to offload posix_operation on to the 
>> asynchronous
>> + * thread pool. It sets up the associations with the post_function that 
>> needs to
>> + * be invoked by from the context of the iothread once the posix_fn has been
>> + * executed.
>> + */
>> +static void v9fs_do_async_posix(ThreadletWork *work ,
>> +                                void (*posix_fn)(ThreadletWork *work),
>> +                                void (**post_fn_ptr)(void *arg),
>> +                                void (*post_fn)(void *arg))
>> +{
>> +    *post_fn_ptr = post_fn;
>> +    work->func = posix_fn;
>> +    submit_work(work);
>> +}
>> +
>>  static int omode_to_uflags(int8_t mode)
>>  {
>>     int ret = 0;
>> @@ -3657,7 +3798,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, 
>> V9fsConf *conf)
>>     int i, len;
>>     struct stat stat;
>>     FsTypeEntry *fse;
>> -
>> +    int fds[2];
>>
>>     s = (V9fsState *)virtio_common_init("virtio-9p",
>>                                     VIRTIO_ID_9P,
>> @@ -3740,5 +3881,27 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, 
>> V9fsConf *conf)
>>                         s->tag_len;
>>     s->vdev.get_config = virtio_9p_get_config;
>>
>> +    if (qemu_pipe(fds) == -1) {
>> +        fprintf(stderr, "failed to create fd's for virtio-9p\n");
>> +        exit(1);
>> +    }
>> +
>> +    v9fs_async_struct.rfd = fds[0];
>> +    v9fs_async_struct.wfd = fds[1];
>> +
>> +    printf("v9fs: rfd: %d\n", v9fs_async_struct.rfd);
>> +    printf("v9fs: wfd: %d\n", v9fs_async_struct.wfd);
>> +
>> +    fcntl(fds[0], F_SETFL, O_NONBLOCK);
>> +    fcntl(fds[1], F_SETFL, O_NONBLOCK);
>> +
>> +    qemu_set_fd_handler(fds[0], v9fs_process_post_ops, NULL, NULL);
>> +    QTAILQ_INIT(&v9fs_async_struct.post_op_list);
>> +    qemu_mutex_init(&(v9fs_async_struct.lock));
>> +    /* Create async queue. */
> 
> Please delete this comment, it seems outdated.
> 
>> +
>> +    (void)v9fs_do_async_posix;
>> +    (void)v9fs_async_helper_done;
>> +
>>     return &s->vdev;
>>  }
>> diff --git a/posix-aio-compat.c b/posix-aio-compat.c
>> index 9e02d18..8019be7 100644
>> --- a/posix-aio-compat.c
>> +++ b/posix-aio-compat.c
>> @@ -260,6 +260,8 @@ static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb)
>>     return nbytes;
>>  }
>>
>> +static PosixAioState */;
>> +
>>  static void aio_thread(ThreadletWork *work)
>>  {
>>     pid_t pid;
>> @@ -290,6 +292,15 @@ static void aio_thread(ThreadletWork *work)
>>     aiocb->ret = ret;
>>     qemu_mutex_unlock(&aiocb_mutex);
>>
>> +    if (posix_aio_state) {
> 
> This test is not needed because posix_aio_state must be non-NULL here.

I see similar check in the old code also..

- JV

> 
>> +        char byte = 0;
>> +        ssize_t ret;
>> +
>> +        ret = write(posix_aio_state->wfd, &byte, sizeof(byte));
>> +        if (ret < 0 && errno != EAGAIN)
> 
> Please always use if () { ... } curly braces.  QEMU coding style.
> 
> Stefan
> 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]