Message ID | 1434450415-11339-6-git-send-email-dgilbert@redhat.com |
---|---|
State | New |
Headers | show |
"Dr. David Alan Gilbert (git)" <dgilbert@redhat.com> wrote: > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com> > > qemu_get_buffer always copies the data it reads to a users buffer, > however in many cases the file buffer inside qemu_file could be given > back to the caller, avoiding the copy. This isn't always possible > depending on the size and alignment of the data. > > Thus 'qemu_get_buffer_less_copy' either copies the data to a supplied > buffer or updates a pointer to the internal buffer if convenient. > > Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> I don't know still where this function is used, but function is correct. Can I suggest to change th ename to: qemu_get_buffer_in_place()? less_copy sounds ambigous to me :p
* Juan Quintela (quintela@redhat.com) wrote: > "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com> wrote: > > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com> > > > > qemu_get_buffer always copies the data it reads to a users buffer, > > however in many cases the file buffer inside qemu_file could be given > > back to the caller, avoiding the copy. This isn't always possible > > depending on the size and alignment of the data. > > > > Thus 'qemu_get_buffer_less_copy' either copies the data to a supplied > > buffer or updates a pointer to the internal buffer if convenient. > > > > Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> > > Reviewed-by: Juan Quintela <quintela@redhat.com> > > I don't know still where this function is used, but function is correct. > > Can I suggest to change th ename to: > > qemu_get_buffer_in_place()? > > less_copy sounds ambigous to me :p Changed. Dave -- Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
On (Tue) 16 Jun 2015 [11:26:18], Dr. David Alan Gilbert (git) wrote: > From: "Dr. David Alan Gilbert" <dgilbert@redhat.com> > > qemu_get_buffer always copies the data it reads to a users buffer, > however in many cases the file buffer inside qemu_file could be given > back to the caller, avoiding the copy. This isn't always possible > depending on the size and alignment of the data. > > Thus 'qemu_get_buffer_less_copy' either copies the data to a supplied > buffer or updates a pointer to the internal buffer if convenient. > > Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Amit Shah <amit.shah@redhat.com> Amit
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h index 4f67d79..29a9d69 100644 --- a/include/migration/qemu-file.h +++ b/include/migration/qemu-file.h @@ -162,6 +162,8 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size); ssize_t qemu_put_compression_data(QEMUFile *f, const uint8_t *p, size_t size, int level); int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src); +int qemu_get_buffer_less_copy(QEMUFile *f, uint8_t **buf, int size); + /* * Note that you can only peek continuous bytes from where the current pointer * is; you aren't guaranteed to be able to peak to +n bytes unless you've diff --git a/migration/qemu-file.c b/migration/qemu-file.c index 965a757..c111a6b 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -427,6 +427,53 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size) } /* + * Read 'size' bytes of data from the file. + * 'size' can be larger than the internal buffer. + * + * The data: + * may be held on an internal buffer (in which case *buf is updated + * to point to it) that is valid until the next qemu_file operation. + * OR + * will be copied to the *buf that was passed in. + * + * The code tries to avoid the copy if possible. + * + * It will return size bytes unless there was an error, in which case it will + * return as many as it managed to read (assuming blocking fd's which + * all current QEMUFile are) + * + * Note: Since **buf may get changed, the caller should take care to + * keep a pointer to the original buffer if it needs to deallocate it. + */ +int qemu_get_buffer_less_copy(QEMUFile *f, uint8_t **buf, int size) +{ + int pending = size; + int done = 0; + bool first = true; + + while (pending > 0) { + int res; + uint8_t *src; + + res = qemu_peek_buffer(f, &src, MIN(pending, IO_BUF_SIZE), 0); + if (res == 0) { + return done; + } + qemu_file_skip(f, res); + done += res; + pending -= res; + if (first && res == size) { + *buf = src; + break; + } + first = false; + memcpy(buf, src, res); + buf += res; + } + return done; +} + +/* * Peeks a single byte from the buffer; this isn't guaranteed to work if * offset leaves a gap after the previous read/peeked data. */