From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33234) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XbnYn-00016A-O0 for qemu-devel@nongnu.org; Wed, 08 Oct 2014 05:29:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XbnYi-00045e-SG for qemu-devel@nongnu.org; Wed, 08 Oct 2014 05:29:29 -0400 Received: from szxga01-in.huawei.com ([119.145.14.64]:13656) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XbnYh-00045H-U7 for qemu-devel@nongnu.org; Wed, 08 Oct 2014 05:29:24 -0400 Message-ID: <543503E1.6080707@huawei.com> Date: Wed, 8 Oct 2014 17:29:05 +0800 From: zhanghailiang MIME-Version: 1.0 References: <1411983695-7910-1-git-send-email-dgilbert@redhat.com> <1411983695-7910-2-git-send-email-dgilbert@redhat.com> <5434A6D7.50209@huawei.com> <20141008090831.GD2521@work-vm> In-Reply-To: <20141008090831.GD2521@work-vm> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v5 1/2] QEMUSizedBuffer based QEMUFile List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "Dr. David Alan Gilbert" 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 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 > > . >