loader: tftp: Add preload method
The preload method will transfer the whole file in a buffer and cache it so read/lseek operations are faster. Reviewed by: imp, tsoome MFC after: 2 weeks Sponsored by: Beckhoff Automation GmbH & Co. KG Differential Revision: https://reviews.freebsd.org/D33410
This commit is contained in:
parent
c25d9aff46
commit
3eb019000c
@ -73,6 +73,7 @@ static int tftp_read(struct open_file *, void *, size_t, size_t *);
|
||||
static off_t tftp_seek(struct open_file *, off_t, int);
|
||||
static int tftp_set_blksize(struct tftp_handle *, const char *);
|
||||
static int tftp_stat(struct open_file *, struct stat *);
|
||||
static int tftp_preload(struct open_file *);
|
||||
|
||||
struct fs_ops tftp_fsops = {
|
||||
.fs_name = "tftp",
|
||||
@ -82,6 +83,7 @@ struct fs_ops tftp_fsops = {
|
||||
.fo_write = null_write,
|
||||
.fo_seek = tftp_seek,
|
||||
.fo_stat = tftp_stat,
|
||||
.fo_preload = tftp_preload,
|
||||
.fo_readdir = null_readdir
|
||||
};
|
||||
|
||||
@ -521,6 +523,16 @@ tftp_read(struct open_file *f, void *addr, size_t size,
|
||||
size = tftpfile->tftp_tsize - tftpfile->off;
|
||||
}
|
||||
|
||||
if (tftpfile->tftp_cache != NULL) {
|
||||
bcopy(tftpfile->tftp_cache + tftpfile->off,
|
||||
addr, size);
|
||||
|
||||
addr = (char *)addr + size;
|
||||
tftpfile->off += size;
|
||||
res -= size;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (size > 0) {
|
||||
int needblock, count;
|
||||
|
||||
@ -586,6 +598,7 @@ tftp_read(struct open_file *f, void *addr, size_t size,
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
if (resid != NULL)
|
||||
*resid = res;
|
||||
return (rc);
|
||||
@ -603,6 +616,7 @@ tftp_close(struct open_file *f)
|
||||
if (tftpfile) {
|
||||
free(tftpfile->path);
|
||||
free(tftpfile->pkt);
|
||||
free(tftpfile->tftp_cache);
|
||||
free(tftpfile);
|
||||
}
|
||||
is_open = 0;
|
||||
@ -643,6 +657,52 @@ tftp_seek(struct open_file *f, off_t offset, int where)
|
||||
return (tftpfile->off);
|
||||
}
|
||||
|
||||
static int
|
||||
tftp_preload(struct open_file *f)
|
||||
{
|
||||
struct tftp_handle *tftpfile;
|
||||
char *cache;
|
||||
int rc;
|
||||
#ifdef TFTP_DEBUG
|
||||
time_t start, end;
|
||||
#endif
|
||||
|
||||
tftpfile = f->f_fsdata;
|
||||
cache = malloc(sizeof(char) * tftpfile->tftp_tsize);
|
||||
if (cache == NULL) {
|
||||
printf("Couldn't allocate %ju bytes for preload caching"
|
||||
", disabling caching\n",
|
||||
(uintmax_t)sizeof(char) * tftpfile->tftp_tsize);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifdef TFTP_DEBUG
|
||||
start = getsecs();
|
||||
printf("Preloading %s ", tftpfile->path);
|
||||
#endif
|
||||
while (tftpfile->islastblock == 0) {
|
||||
twiddle(32);
|
||||
rc = tftp_getnextblock(tftpfile);
|
||||
if (rc) {
|
||||
free(cache);
|
||||
printf("Got TFTP error %d, disabling caching\n", rc);
|
||||
return (rc);
|
||||
}
|
||||
bcopy(tftpfile->tftp_hdr->th_data,
|
||||
cache + (tftpfile->tftp_blksize * (tftpfile->currblock - 1)),
|
||||
tftpfile->validsize);
|
||||
}
|
||||
#ifdef TFTP_DEBUG
|
||||
end = getsecs();
|
||||
printf("\nPreloaded %s (%ju bytes) during %jd seconds\n",
|
||||
tftpfile->path, (intmax_t)tftpfile->tftp_tsize,
|
||||
(intmax_t)end - start);
|
||||
#endif
|
||||
|
||||
tftpfile->tftp_cache = cache;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
tftp_set_blksize(struct tftp_handle *h, const char *str)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user