Improve interaction of vectx and tftp

On slow platforms, it helps to spread the hashing load
over time so that tftp does not timeout.

Also, some .4th files are too big to fit in cache of pkgfs,
so increase cache size and ensure fully populated.

Reviewed by:	stevek
MFC after:	1 week
Differential Revision: https://reviews.freebsd.org/D24287
This commit is contained in:
Simon J. Gerraty 2020-04-07 16:56:34 +00:00
parent b30c6ac9f9
commit 723f904176
3 changed files with 57 additions and 29 deletions

View File

@ -211,6 +211,7 @@ ssize_t
vectx_read(struct vectx *ctx, void *buf, size_t nbytes) vectx_read(struct vectx *ctx, void *buf, size_t nbytes)
{ {
unsigned char *bp = buf; unsigned char *bp = buf;
int d;
int n; int n;
int delta; int delta;
int x; int x;
@ -221,23 +222,30 @@ vectx_read(struct vectx *ctx, void *buf, size_t nbytes)
off = 0; off = 0;
do { do {
n = read(ctx->vec_fd, &bp[off], nbytes - off); /*
if (n < 0) * Do this in reasonable chunks so
* we don't timeout if doing tftp
*/
x = nbytes - off;
x = MIN(PAGE_SIZE, x);
d = n = read(ctx->vec_fd, &bp[off], x);
if (n < 0) {
return (n); return (n);
if (n > 0) { }
if (d > 0) {
/* we may have seeked backwards! */ /* we may have seeked backwards! */
delta = ctx->vec_hashed - ctx->vec_off; delta = ctx->vec_hashed - ctx->vec_off;
if (delta > 0) { if (delta > 0) {
x = MIN(delta, n); x = MIN(delta, d);
off += x; off += x;
n -= x; d -= x;
ctx->vec_off += x; ctx->vec_off += x;
} }
if (n > 0) { if (d > 0) {
ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], n); ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], d);
off += n; off += d;
ctx->vec_off += n; ctx->vec_off += d;
ctx->vec_hashed += n; ctx->vec_hashed += d;
} }
} }
} while (n > 0 && off < nbytes); } while (n > 0 && off < nbytes);

View File

@ -60,7 +60,7 @@ struct fs_ops pkgfs_fsops = {
}; };
#define PKG_BUFSIZE 512 #define PKG_BUFSIZE 512
#define PKG_MAXCACHESZ 16384 #define PKG_MAXCACHESZ (16384 * 3)
#define PKG_FILEEXT ".tgz" #define PKG_FILEEXT ".tgz"
@ -132,6 +132,7 @@ struct package
static struct package *package = NULL; static struct package *package = NULL;
static int new_package(int, struct package **); static int new_package(int, struct package **);
static int cache_data(struct tarfile *tf, int);
void void
pkgfs_cleanup(void) pkgfs_cleanup(void)
@ -282,6 +283,9 @@ pkg_read(struct open_file *f, void *buf, size_t size, size_t *res)
return (EBADF); return (EBADF);
} }
if (tf->tf_cachesz == 0)
cache_data(tf, 1);
fp = tf->tf_fp; fp = tf->tf_fp;
p = buf; p = buf;
sz = 0; sz = 0;
@ -311,16 +315,6 @@ pkg_read(struct open_file *f, void *buf, size_t size, size_t *res)
fp += sz; fp += sz;
p += sz; p += sz;
size -= sz; size -= sz;
if (tf->tf_cachesz != 0)
continue;
tf->tf_cachesz = (sz <= PKG_MAXCACHESZ) ? sz : PKG_MAXCACHESZ;
tf->tf_cache = malloc(tf->tf_cachesz);
if (tf->tf_cache != NULL)
memcpy(tf->tf_cache, buf, tf->tf_cachesz);
else
tf->tf_cachesz = 0;
} }
tf->tf_fp = fp; tf->tf_fp = fp;
@ -484,8 +478,20 @@ get_zipped(struct package *pkg, void *buf, size_t bufsz)
return (0); return (0);
} }
/**
* @brief
* cache data of a tarfile
*
* @param[in] tf
* tarfile pointer
*
* @param[in] force
* If file size > PKG_MAXCACHESZ, cache that much
*
* @return 0, -1 (errno set to error value)
*/
static int static int
cache_data(struct tarfile *tf) cache_data(struct tarfile *tf, int force)
{ {
struct package *pkg; struct package *pkg;
size_t sz; size_t sz;
@ -503,21 +509,28 @@ cache_data(struct tarfile *tf)
return (-1); return (-1);
} }
if (tf->tf_cachesz > 0) {
DBG(("%s: data already cached\n", __func__));
errno = EINVAL;
return (-1);
}
if (tf->tf_ofs != pkg->pkg_ofs) { if (tf->tf_ofs != pkg->pkg_ofs) {
DBG(("%s: caching after partial read of file %s?\n", DBG(("%s: caching after force read of file %s?\n",
__func__, tf->tf_hdr.ut_name)); __func__, tf->tf_hdr.ut_name));
errno = EINVAL; errno = EINVAL;
return (-1); return (-1);
} }
/* We don't cache everything... */ /* We don't cache everything... */
if (tf->tf_size > PKG_MAXCACHESZ) { if (tf->tf_size > PKG_MAXCACHESZ && !force) {
errno = ENOMEM; errno = ENOBUFS;
return (-1); return (-1);
} }
sz = tf->tf_size < PKG_MAXCACHESZ ? tf->tf_size : PKG_MAXCACHESZ;
/* All files are padded to a multiple of 512 bytes. */ /* All files are padded to a multiple of 512 bytes. */
sz = (tf->tf_size + 0x1ff) & ~0x1ff; sz = (sz + 0x1ff) & ~0x1ff;
tf->tf_cache = malloc(sz); tf->tf_cache = malloc(sz);
if (tf->tf_cache == NULL) { if (tf->tf_cache == NULL) {
@ -741,7 +754,7 @@ scan_tarfile(struct package *pkg, struct tarfile *last)
if (ofs != pkg->pkg_ofs) { if (ofs != pkg->pkg_ofs) {
if (last != NULL && pkg->pkg_ofs == last->tf_ofs) { if (last != NULL && pkg->pkg_ofs == last->tf_ofs) {
if (cache_data(last) == -1) if (cache_data(last, 0) == -1)
return (NULL); return (NULL);
} else { } else {
sz = ofs - pkg->pkg_ofs; sz = ofs - pkg->pkg_ofs;

View File

@ -100,11 +100,13 @@ static int is_open = 0;
* Jumbo frames in the future. * Jumbo frames in the future.
*/ */
#define TFTP_MAX_BLKSIZE 9008 #define TFTP_MAX_BLKSIZE 9008
#define TFTP_TRIES 2
struct tftp_handle { struct tftp_handle {
struct iodesc *iodesc; struct iodesc *iodesc;
int currblock; /* contents of lastdata */ int currblock; /* contents of lastdata */
int islastblock; /* flag */ int islastblock:1; /* flag */
int tries:4; /* number of read attempts */
int validsize; int validsize;
int off; int off;
char *path; /* saved for re-requests */ char *path; /* saved for re-requests */
@ -530,7 +532,12 @@ tftp_read(struct open_file *f, void *addr, size_t size,
#ifdef TFTP_DEBUG #ifdef TFTP_DEBUG
printf("tftp: read error\n"); printf("tftp: read error\n");
#endif #endif
return (rc); if (tftpfile->tries > TFTP_TRIES) {
return (rc);
} else {
tftpfile->tries++;
tftp_makereq(tftpfile);
}
} }
if (tftpfile->islastblock) if (tftpfile->islastblock)
break; break;