Files
xen/tools/xentrace/mread.c
T
Roger Pau Monne 8c21339be4 xen{trace/analyze}: don't use 64bit versions of libc functions
This is not needed, neither encouraged. Configure already checks
_FILE_OFFSET_BITS and appends it when needed, so that the right functions
are used. Also remove the usage of loff_t and O_LARGEFILE for the same
reason.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Cc: George Dunlap <george.dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: Olaf Hering <olaf@aepfle.de>
Acked-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
2015-06-25 12:12:21 +01:00

161 lines
4.3 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
#include "mread.h"
mread_handle_t mread_init(int fd)
{
struct stat s;
mread_handle_t h;
h=malloc(sizeof(struct mread_ctrl));
if (!h)
{
perror("malloc");
exit(1);
}
bzero(h, sizeof(struct mread_ctrl));
h->fd = fd;
fstat(fd, &s);
h->file_size = s.st_size;
return h;
}
ssize_t mread64(mread_handle_t h, void *rec, ssize_t len, off_t offset)
{
/* Idea: have a "cache" of N mmaped regions. If the offset is
* in one of the regions, just copy it. If not, evict one of the
* regions and map the appropriate range.
*
* Basic algorithm:
* - See if the offset is in one of the regions
* - If not, map it
* - evict an old region
* - map the new region
* - Copy
*/
char * b=NULL;
int bind=-1;
off_t boffset=0;
ssize_t bsize;
#define dprintf(x...)
//#define dprintf fprintf
dprintf(warn, "%s: offset %llx len %d\n", __func__,
offset, len);
if ( offset > h->file_size )
{
dprintf(warn, " offset > file size %llx, returning 0\n",
h->file_size);
return 0;
}
if ( offset + len > h->file_size )
{
dprintf(warn, " offset+len > file size %llx, truncating\n",
h->file_size);
len = h->file_size - offset;
}
/* Try to find the offset in our range */
dprintf(warn, " Trying last, %d\n", last);
if ( h->map[h->last].buffer
&& (offset & MREAD_BUF_MASK) == h->map[h->last].start_offset )
{
bind=h->last;
goto copy;
}
/* Scan to see if it's anywhere else */
dprintf(warn, " Scanning\n");
for(bind=0; bind<MREAD_MAPS; bind++)
if ( h->map[bind].buffer
&& (offset & MREAD_BUF_MASK) == h->map[bind].start_offset )
{
dprintf(warn, " Found, index %d\n", bind);
break;
}
/* If we didn't find it, evict someone and map it */
if ( bind == MREAD_MAPS )
{
dprintf(warn, " Clock\n");
while(1)
{
h->clock++;
if(h->clock >= MREAD_MAPS)
h->clock=0;
dprintf(warn, " %d\n", h->clock);
if(h->map[h->clock].buffer == NULL)
{
dprintf(warn, " Buffer null, using\n");
break;
}
if(!h->map[h->clock].accessed)
{
dprintf(warn, " Not accessed, using\n");
break;
}
h->map[h->clock].accessed=0;
}
if(h->map[h->clock].buffer)
{
dprintf(warn, " Unmapping\n");
munmap(h->map[h->clock].buffer, MREAD_BUF_SIZE);
}
/* FIXME: Try MAP_HUGETLB? */
/* FIXME: Make sure this works on large files... */
h->map[h->clock].start_offset = offset & MREAD_BUF_MASK;
dprintf(warn, " Mapping %llx from offset %llx\n",
MREAD_BUF_SIZE, h->map[h->clock].start_offset);
h->map[h->clock].buffer = mmap(NULL, MREAD_BUF_SIZE, PROT_READ,
MAP_SHARED,
h->fd,
h->map[h->clock].start_offset);
dprintf(warn, " mmap returned %p\n", h->map[h->clock].buffer);
if ( h->map[h->clock].buffer == MAP_FAILED )
{
h->map[h->clock].buffer = NULL;
perror("mmap");
exit(1);
}
bind = h->clock;
}
h->last=bind;
copy:
h->map[bind].accessed=1;
b=h->map[bind].buffer;
boffset=offset - h->map[bind].start_offset;
if ( boffset + len > MREAD_BUF_SIZE )
bsize = MREAD_BUF_SIZE - boffset;
else
bsize = len;
dprintf(warn, " Using index %d, buffer at %p, buffer offset %llx len %d\n",
bind, b, boffset, bsize);
bcopy(b+boffset, rec, bsize);
/* Handle the boundary case; make sure this is after doing anything
* with the static variables*/
if ( len > bsize )
{
dprintf(warn, " Finishing up by reading l %d o %llx\n",
len-bsize, offset+bsize);
mread64(h, rec+bsize, len-bsize, offset+bsize);
}
/* FIXME: ?? */
return len;
#undef dprintf
}