All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stefan Berger <stefanb@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [RFC PATCH v3 1/6] QEMUSizedBuffer/QEMUFile
Date: Mon, 11 Aug 2014 15:16:49 -0400	[thread overview]
Message-ID: <53E916A1.6070301@linux.vnet.ibm.com> (raw)
In-Reply-To: <20140811184714.GJ2368@work-vm>

On 08/11/2014 02:47 PM, Dr. David Alan Gilbert wrote:
> * Gonglei (Arei) (arei.gonglei@huawei.com) wrote:
>
> <snip>
>
>>> +/**
>>> + * Grow the QEMUSizedBuffer to the given size and allocated
>>> + * memory for it.
>>> + *
>>> + * @qsb: A QEMUSizedBuffer
>>> + * @new_size: The new size of the buffer
>>> + *
>>> + * Returns an error code in case of memory allocation failure
>>> + * or the new size of the buffer otherwise. The returned size
>>> + * may be greater or equal to @new_size.
>>> + */
>>> +static ssize_t qsb_grow(QEMUSizedBuffer *qsb, size_t new_size)
>>> +{
>>> +    size_t needed_chunks, i;
>>> +    size_t chunk_size = QSB_CHUNK_SIZE;
>>> +
>>> +    if (qsb->size < new_size) {
>>> +        needed_chunks = DIV_ROUND_UP(new_size - qsb->size,
>>> +                                     chunk_size);
>>> +
>>> +        qsb->iov = g_realloc_n(qsb->iov, qsb->n_iov + needed_chunks,
>>> +                               sizeof(struct iovec));
>>> +        if (qsb->iov == NULL) {
>>> +            return -ENOMEM;
>>> +        }
>> OK...
> Is it?  https://developer.gnome.org/glib/stable/glib-Memory-Allocation.html
> says that g_realloc_n is 'similar to g_realloc()' except for overflow protection,
> g_realloc() doesn't say what it's behaviour on OOM is, but g_try_realloc says
> that 'Contrast with g_realloc(), which aborts the program on failure'
> So the only case iov will return NULL there is if the size is 0 which it can't
> be.  So should that be a g_try_realloc_n ?
>
>>> +
>>> +        for (i = qsb->n_iov; i < qsb->n_iov + needed_chunks; i++) {
>>> +            qsb->iov[i].iov_base = g_malloc0(chunk_size);
>>> +            qsb->iov[i].iov_len = chunk_size;
>>> +        }
>>> +
>>> +        qsb->n_iov += needed_chunks;
>>> +        qsb->size += (needed_chunks * chunk_size);
>>> +    }
>>> +
>>> +    return qsb->size;
>>> +}
>>> +
>>> +/**
>>> + * Write into the QEMUSizedBuffer at a given position and a given
>>> + * number of bytes. This function will automatically grow the
>>> + * QEMUSizedBuffer.
>>> + *
>>> + * @qsb: A QEMUSizedBuffer
>>> + * @source: A byte array to copy data from
>>> + * @pos: The position withing the @qsb to write data to
>>> + * @size: The number of bytes to copy into the @qsb
>>> + *
>>> + * Returns an error code in case of memory allocation failure,
>>> + * @size otherwise.
>>> + */
>>> +ssize_t qsb_write_at(QEMUSizedBuffer *qsb, const uint8_t *source,
>>> +                     off_t pos, size_t count)
>>> +{
>>> +    ssize_t rc = qsb_grow(qsb, pos + count);
>>> +    size_t to_copy;
>>> +    size_t all_copy = count;
>>> +    const struct iovec *iov;
>>> +    ssize_t index;
>>> +    char *dest;
>>> +    off_t d_off, s_off = 0;
>>> +
>>> +    if (rc < 0) {
>>> +        return rc;
>>> +    }
>>> +
>> OK...
>>
>>> +    if (pos + count > qsb->used) {
>>> +        qsb->used = pos + count;
>>> +    }
>>> +
>>> +    index = qsb_get_iovec(qsb, pos, &d_off);
>>> +    if (index < 0) {
>>> +        return 0;
>>> +    }
>>> +
>>> +    while (all_copy > 0) {
>>> +        iov = &qsb->iov[index];
>>> +
>>> +        dest = iov->iov_base;
>>> +
>>> +        to_copy = iov->iov_len - d_off;
>>> +        if (to_copy > all_copy) {
>>> +            to_copy = all_copy;
>>> +        }
>>> +
>>> +        memcpy(&dest[d_off], &source[s_off], to_copy);
>>> +
>>> +        s_off += to_copy;
>>> +        all_copy -= to_copy;
>>> +
>>> +        d_off = 0;
>>> +        index++;
>>> +    }
>>> +
>>> +    return count;
>>> +}
>>> +
>>> +/**
>>> + * Create an exact copy of the given QEMUSizedBuffer.
>>> + *
>>> + * @qsb : A QEMUSizedBuffer
>>> + *
>>> + * Returns a clone of @qsb
>>> + */
>>> +QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *qsb)
>>> +{
>>> +    QEMUSizedBuffer *out = qsb_create(NULL, qsb_get_length(qsb));
>>> +    size_t i;
>>> +    off_t pos = 0;
>>> +
>>> +    for (i = 0; i < qsb->n_iov; i++) {
>>> +        pos += qsb_write_at(out, qsb->iov[i].iov_base,
>>> +                            pos, qsb->iov[i].iov_len);
>> If qsb_write_at() return -ENOMEM, just simply add it to pos ?
> qsb_create uses g_new0 so it will abort on out of memory;
> what should qsb_clone do if qsb_write_at returns -ENOMEM?
> (Admittedly anything is better than getting the position wrong).
> I guess the choice is to allow it to return NULL, tidying up
> and offering the chance sometime in the future of tidying up
> the other allocators.

I remember looking at all the allocation API as well. It seems QEMU 
would terminate upon OOM since g_new0 is used all over the place.

     Stefan

  reply	other threads:[~2014-08-11 19:17 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-09  6:26 [Qemu-devel] [RFC PATCH v3 0/6] VMState testing Sanidhya Kashyap
2014-08-09  6:26 ` [Qemu-devel] [RFC PATCH v3 1/6] QEMUSizedBuffer/QEMUFile Sanidhya Kashyap
2014-08-11  2:49   ` Gonglei (Arei)
2014-08-11 18:47     ` Dr. David Alan Gilbert
2014-08-11 19:16       ` Stefan Berger [this message]
2014-08-11 16:38   ` Eric Blake
2014-08-09  6:26 ` [Qemu-devel] [RFC PATCH v3 2/6] VMState test: get information about the registered devices Sanidhya Kashyap
2014-08-11 16:24   ` Eric Blake
2014-08-09  6:26 ` [Qemu-devel] [RFC PATCH v3 3/6] VMstate test: basic VMState testing mechanism Sanidhya Kashyap
2014-08-11 16:32   ` Eric Blake
2014-08-09  6:26 ` [Qemu-devel] [RFC PATCH v3 4/6] VMState test: querying the vmstate testing process Sanidhya Kashyap
2014-08-11 16:35   ` Eric Blake
2014-08-09  6:26 ` [Qemu-devel] [RFC PATCH v3 5/6] VMState test: update period of " Sanidhya Kashyap
2014-08-09  6:26 ` [Qemu-devel] [RFC PATCH v3 6/6] VMState test: cancel mechanism for an already running " Sanidhya Kashyap

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53E916A1.6070301@linux.vnet.ibm.com \
    --to=stefanb@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.