From: zhanghailiang <zhang.zhanghailiang@huawei.com>
To: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: joel.schopp@amd.com, quintela@redhat.com,
stefanb@linux.vnet.ibm.com, qemu-devel@nongnu.org,
armbru@redhat.com, arei.gonglei@huawei.com,
sanidhya.iiith@gmail.com
Subject: Re: [Qemu-devel] [PATCH v5 1/2] QEMUSizedBuffer based QEMUFile
Date: Wed, 8 Oct 2014 17:29:05 +0800 [thread overview]
Message-ID: <543503E1.6080707@huawei.com> (raw)
In-Reply-To: <20141008090831.GD2521@work-vm>
On 2014/10/8 17:08, Dr. David Alan Gilbert wrote:
> * zhanghailiang (zhang.zhanghailiang@huawei.com) wrote:
>
>>> +static ssize_t qsb_grow(QEMUSizedBuffer *qsb, size_t new_size)
>>> +{
>>> + size_t needed_chunks, i;
>>> +
>>> + if (qsb->size < new_size) {
>>> + struct iovec *new_iov;
>>> + size_t size_diff = new_size - qsb->size;
>>> + size_t chunk_size = (size_diff > QSB_MAX_CHUNK_SIZE)
>>> + ? QSB_MAX_CHUNK_SIZE : QSB_CHUNK_SIZE;
>>> +
>>> + needed_chunks = DIV_ROUND_UP(size_diff, chunk_size);
>>> +
>>> + new_iov = g_try_malloc_n(qsb->n_iov + needed_chunks,
>>> + sizeof(struct iovec));
>>
>> It seems that *g_try_malloc_n* was supported since glib2-2.24 version,
>> But it don't check this when do *configure* before compile...;)
>
> new_iov = g_try_new(struct iovec, qsb->n_iov + needed_chunks);
>
> seems to work for me; let me know if you hit any others.
>
;), This also works for me. Thanks.
> Dave
>
>
>
>>
>>> + if (new_iov == NULL) {
>>> + return -ENOMEM;
>>> + }
>>> +
>>> + /* Allocate new chunks as needed into new_iov */
>>> + for (i = qsb->n_iov; i < qsb->n_iov + needed_chunks; i++) {
>>> + new_iov[i].iov_base = g_try_malloc0(chunk_size);
>>> + new_iov[i].iov_len = chunk_size;
>>> + if (!new_iov[i].iov_base) {
>>> + size_t j;
>>> +
>>> + /* Free previously allocated new chunks */
>>> + for (j = qsb->n_iov; j < i; j++) {
>>> + g_free(new_iov[j].iov_base);
>>> + }
>>> + g_free(new_iov);
>>> +
>>> + return -ENOMEM;
>>> + }
>>> + }
>>> +
>>> + /*
>>> + * Now we can't get any allocation errors, copy over to new iov
>>> + * and switch.
>>> + */
>>> + for (i = 0; i < qsb->n_iov; i++) {
>>> + new_iov[i] = qsb->iov[i];
>>> + }
>>> +
>>> + qsb->n_iov += needed_chunks;
>>> + g_free(qsb->iov);
>>> + qsb->iov = new_iov;
>>> + 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 within the @qsb to write data to
>>> + * @size: The number of bytes to copy into the @qsb
>>> + *
>>> + * Returns @size or a negative error code in case of memory allocation failure,
>>> + * or with an invalid 'pos'
>>> + */
>>> +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;
>>> + }
>>> +
>>> + if (pos + count > qsb->used) {
>>> + qsb->used = pos + count;
>>> + }
>>> +
>>> + index = qsb_get_iovec(qsb, pos, &d_off);
>>> + if (index < 0) {
>>> + return -EINVAL;
>>> + }
>>> +
>>> + 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 a deep copy of the given QEMUSizedBuffer.
>>> + *
>>> + * @qsb: A QEMUSizedBuffer
>>> + *
>>> + * Returns a clone of @qsb or NULL on allocation failure
>>> + */
>>> +QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *qsb)
>>> +{
>>> + QEMUSizedBuffer *out = qsb_create(NULL, qsb_get_length(qsb));
>>> + size_t i;
>>> + ssize_t res;
>>> + off_t pos = 0;
>>> +
>>> + if (!out) {
>>> + return NULL;
>>> + }
>>> +
>>> + for (i = 0; i < qsb->n_iov; i++) {
>>> + res = qsb_write_at(out, qsb->iov[i].iov_base,
>>> + pos, qsb->iov[i].iov_len);
>>> + if (res < 0) {
>>> + qsb_free(out);
>>> + return NULL;
>>> + }
>>> + pos += res;
>>> + }
>>> +
>>> + return out;
>>> +}
>>> +
>>> +typedef struct QEMUBuffer {
>>> + QEMUSizedBuffer *qsb;
>>> + QEMUFile *file;
>>> +} QEMUBuffer;
>>> +
>>> +static int buf_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
>>> +{
>>> + QEMUBuffer *s = opaque;
>>> + ssize_t len = qsb_get_length(s->qsb) - pos;
>>> +
>>> + if (len <= 0) {
>>> + return 0;
>>> + }
>>> +
>>> + if (len > size) {
>>> + len = size;
>>> + }
>>> + return qsb_get_buffer(s->qsb, pos, len, buf);
>>> +}
>>> +
>>> +static int buf_put_buffer(void *opaque, const uint8_t *buf,
>>> + int64_t pos, int size)
>>> +{
>>> + QEMUBuffer *s = opaque;
>>> +
>>> + return qsb_write_at(s->qsb, buf, pos, size);
>>> +}
>>> +
>>> +static int buf_close(void *opaque)
>>> +{
>>> + QEMUBuffer *s = opaque;
>>> +
>>> + qsb_free(s->qsb);
>>> +
>>> + g_free(s);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +const QEMUSizedBuffer *qemu_buf_get(QEMUFile *f)
>>> +{
>>> + QEMUBuffer *p;
>>> +
>>> + qemu_fflush(f);
>>> +
>>> + p = f->opaque;
>>> +
>>> + return p->qsb;
>>> +}
>>> +
>>> +static const QEMUFileOps buf_read_ops = {
>>> + .get_buffer = buf_get_buffer,
>>> + .close = buf_close,
>>> +};
>>> +
>>> +static const QEMUFileOps buf_write_ops = {
>>> + .put_buffer = buf_put_buffer,
>>> + .close = buf_close,
>>> +};
>>> +
>>> +QEMUFile *qemu_bufopen(const char *mode, QEMUSizedBuffer *input)
>>> +{
>>> + QEMUBuffer *s;
>>> +
>>> + if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') ||
>>> + mode[1] != '\0') {
>>> + error_report("qemu_bufopen: Argument validity check failed");
>>> + return NULL;
>>> + }
>>> +
>>> + s = g_malloc0(sizeof(QEMUBuffer));
>>> + if (mode[0] == 'r') {
>>> + s->qsb = input;
>>> + }
>>> +
>>> + if (s->qsb == NULL) {
>>> + s->qsb = qsb_create(NULL, 0);
>>> + }
>>> + if (!s->qsb) {
>>> + g_free(s);
>>> + error_report("qemu_bufopen: qsb_create failed");
>>> + return NULL;
>>> + }
>>> +
>>> +
>>> + if (mode[0] == 'r') {
>>> + s->file = qemu_fopen_ops(s, &buf_read_ops);
>>> + } else {
>>> + s->file = qemu_fopen_ops(s, &buf_write_ops);
>>> + }
>>> + return s->file;
>>> +}
>>>
>>
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
>
> .
>
next prev parent reply other threads:[~2014-10-08 9:29 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-29 9:41 [Qemu-devel] [PATCH v5 0/2] In memory QEMUFile Dr. David Alan Gilbert (git)
2014-09-29 9:41 ` [Qemu-devel] [PATCH v5 1/2] QEMUSizedBuffer based QEMUFile Dr. David Alan Gilbert (git)
2014-10-08 2:52 ` zhanghailiang
2014-10-08 8:23 ` Dr. David Alan Gilbert
2014-10-08 8:34 ` Markus Armbruster
2014-10-08 9:08 ` Dr. David Alan Gilbert
2014-10-08 9:29 ` zhanghailiang [this message]
2014-09-29 9:41 ` [Qemu-devel] [PATCH v5 2/2] Tests: QEMUSizedBuffer/QEMUBuffer Dr. David Alan Gilbert (git)
2014-09-29 14:42 ` [Qemu-devel] [PATCH v5 0/2] In memory QEMUFile Eric Blake
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=543503E1.6080707@huawei.com \
--to=zhang.zhanghailiang@huawei.com \
--cc=arei.gonglei@huawei.com \
--cc=armbru@redhat.com \
--cc=dgilbert@redhat.com \
--cc=joel.schopp@amd.com \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
--cc=sanidhya.iiith@gmail.com \
--cc=stefanb@linux.vnet.ibm.com \
/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.