mirror of https://github.com/ipxe/ipxe.git
[downloader] Use generic data-transfer buffer mechanism
Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/38/head
parent
07b0d4fa30
commit
ae5e7f0cf4
|
@ -33,7 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#include <ipxe/uaccess.h>
|
||||
#include <ipxe/umalloc.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/profile.h>
|
||||
#include <ipxe/xferbuf.h>
|
||||
#include <ipxe/downloader.h>
|
||||
|
||||
/** @file
|
||||
|
@ -42,14 +42,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
*
|
||||
*/
|
||||
|
||||
/** Receive profiler */
|
||||
static struct profiler downloader_rx_profiler __profiler =
|
||||
{ .name = "downloader.rx" };
|
||||
|
||||
/** Data copy profiler */
|
||||
static struct profiler downloader_copy_profiler __profiler =
|
||||
{ .name = "downloader.copy" };
|
||||
|
||||
/** A downloader */
|
||||
struct downloader {
|
||||
/** Reference count for this object */
|
||||
|
@ -62,8 +54,8 @@ struct downloader {
|
|||
|
||||
/** Image to contain downloaded file */
|
||||
struct image *image;
|
||||
/** Current position within image buffer */
|
||||
size_t pos;
|
||||
/** Data transfer buffer */
|
||||
struct xfer_buffer buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -96,42 +88,14 @@ static void downloader_finished ( struct downloader *downloader, int rc ) {
|
|||
downloader->image->name, strerror ( rc ) );
|
||||
}
|
||||
|
||||
/* Update image length */
|
||||
downloader->image->len = downloader->buffer.len;
|
||||
|
||||
/* Shut down interfaces */
|
||||
intf_shutdown ( &downloader->xfer, rc );
|
||||
intf_shutdown ( &downloader->job, rc );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that download buffer is large enough for the specified size
|
||||
*
|
||||
* @v downloader Downloader
|
||||
* @v len Required minimum size
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int downloader_ensure_size ( struct downloader *downloader,
|
||||
size_t len ) {
|
||||
userptr_t new_buffer;
|
||||
|
||||
/* If buffer is already large enough, do nothing */
|
||||
if ( len <= downloader->image->len )
|
||||
return 0;
|
||||
|
||||
DBGC ( downloader, "Downloader %p extending to %zd bytes\n",
|
||||
downloader, len );
|
||||
|
||||
/* Extend buffer */
|
||||
new_buffer = urealloc ( downloader->image->data, len );
|
||||
if ( ! new_buffer ) {
|
||||
DBGC ( downloader, "Downloader %p could not extend buffer to "
|
||||
"%zd bytes\n", downloader, len );
|
||||
return -ENOSPC;
|
||||
}
|
||||
downloader->image->data = new_buffer;
|
||||
downloader->image->len = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Job control interface
|
||||
|
@ -152,8 +116,8 @@ static int downloader_progress ( struct downloader *downloader,
|
|||
* arrive out of order (e.g. with multicast protocols), but
|
||||
* it's a reasonable first approximation.
|
||||
*/
|
||||
progress->completed = downloader->pos;
|
||||
progress->total = downloader->image->len;
|
||||
progress->completed = downloader->buffer.pos;
|
||||
progress->total = downloader->buffer.len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -175,38 +139,17 @@ static int downloader_progress ( struct downloader *downloader,
|
|||
static int downloader_xfer_deliver ( struct downloader *downloader,
|
||||
struct io_buffer *iobuf,
|
||||
struct xfer_metadata *meta ) {
|
||||
size_t len;
|
||||
size_t max;
|
||||
int rc;
|
||||
|
||||
/* Start profiling */
|
||||
profile_start ( &downloader_rx_profiler );
|
||||
/* Add data to buffer */
|
||||
if ( ( rc = xferbuf_deliver ( &downloader->buffer, iob_disown ( iobuf ),
|
||||
meta ) ) != 0 )
|
||||
goto err_deliver;
|
||||
|
||||
/* Calculate new buffer position */
|
||||
if ( meta->flags & XFER_FL_ABS_OFFSET )
|
||||
downloader->pos = 0;
|
||||
downloader->pos += meta->offset;
|
||||
return 0;
|
||||
|
||||
/* Ensure that we have enough buffer space for this data */
|
||||
len = iob_len ( iobuf );
|
||||
max = ( downloader->pos + len );
|
||||
if ( ( rc = downloader_ensure_size ( downloader, max ) ) != 0 )
|
||||
goto done;
|
||||
|
||||
/* Copy data to buffer */
|
||||
profile_start ( &downloader_copy_profiler );
|
||||
copy_to_user ( downloader->image->data, downloader->pos,
|
||||
iobuf->data, len );
|
||||
profile_stop ( &downloader_copy_profiler );
|
||||
|
||||
/* Update current buffer position */
|
||||
downloader->pos += len;
|
||||
|
||||
done:
|
||||
free_iob ( iobuf );
|
||||
if ( rc != 0 )
|
||||
downloader_finished ( downloader, rc );
|
||||
profile_stop ( &downloader_rx_profiler );
|
||||
err_deliver:
|
||||
downloader_finished ( downloader, rc );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -266,6 +209,7 @@ int create_downloader ( struct interface *job, struct image *image ) {
|
|||
intf_init ( &downloader->xfer, &downloader_xfer_desc,
|
||||
&downloader->refcnt );
|
||||
downloader->image = image_get ( image );
|
||||
xferbuf_umalloc_init ( &downloader->buffer, &image->data );
|
||||
|
||||
/* Instantiate child objects and attach to our interfaces */
|
||||
if ( ( rc = xfer_open_uri ( &downloader->xfer, image->uri ) ) != 0 )
|
||||
|
|
Loading…
Reference in New Issue