|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
/*
|
|
|
|
|
data source for libisoburn.
|
|
|
|
|
|
|
|
|
|
Copyright 2007 - 2010 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
|
|
|
|
|
Copyright 2007 - 2012 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
|
|
|
|
|
and Thomas Schmitt <scdbackup@gmx.net>
|
|
|
|
|
Provided under GPL version 2 or later.
|
|
|
|
|
*/
|
|
|
|
@ -33,17 +33,7 @@
|
|
|
|
|
#include "isoburn.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Cached reading of image tree data */
|
|
|
|
|
/* Multi tile: 32 * 64 kB */
|
|
|
|
|
|
|
|
|
|
/* The size of a single tile.
|
|
|
|
|
Powers of 2 only ! Less than 16 makes not much sense.
|
|
|
|
|
*/
|
|
|
|
|
#define Libisoburn_tile_blockS 32
|
|
|
|
|
|
|
|
|
|
/* The number of tiles in the cache
|
|
|
|
|
*/
|
|
|
|
|
#define Libisoburn_cache_tileS 32
|
|
|
|
|
/* Cached reading of image tree data by multiple tiles */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Debugging only: This reports cache loads on stderr.
|
|
|
|
@ -52,7 +42,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct isoburn_cache_tile {
|
|
|
|
|
char cache_data[Libisoburn_tile_blockS * 2048];
|
|
|
|
|
char *cache_data;
|
|
|
|
|
uint32_t cache_lba;
|
|
|
|
|
uint32_t last_error_lba;
|
|
|
|
|
uint32_t last_aligned_error_lba;
|
|
|
|
@ -62,7 +52,9 @@ struct isoburn_cache_tile {
|
|
|
|
|
|
|
|
|
|
struct isoburn_cached_drive {
|
|
|
|
|
struct burn_drive *drive;
|
|
|
|
|
struct isoburn_cache_tile tiles[Libisoburn_cache_tileS];
|
|
|
|
|
struct isoburn_cache_tile **tiles;
|
|
|
|
|
int num_tiles;
|
|
|
|
|
int tile_blocks;
|
|
|
|
|
int current_age;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -92,7 +84,7 @@ int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
|
|
|
|
|
off_t count;
|
|
|
|
|
uint32_t aligned_lba;
|
|
|
|
|
char msg[80];
|
|
|
|
|
struct isoburn_cache_tile *tiles;
|
|
|
|
|
struct isoburn_cache_tile **tiles;
|
|
|
|
|
struct isoburn_cached_drive *icd;
|
|
|
|
|
|
|
|
|
|
if(src == NULL || buffer == NULL)
|
|
|
|
@ -117,7 +109,7 @@ int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
|
|
|
|
|
return ISO_ASSERT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tiles = (struct isoburn_cache_tile *) icd->tiles;
|
|
|
|
|
tiles = icd->tiles;
|
|
|
|
|
|
|
|
|
|
if(icd->displacement_sign == 1) {
|
|
|
|
|
if(lba + icd->displacement < lba) {
|
|
|
|
@ -132,12 +124,13 @@ address_rollover:;
|
|
|
|
|
lba -= icd->displacement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aligned_lba= lba & ~(Libisoburn_tile_blockS - 1);
|
|
|
|
|
aligned_lba= lba & ~(icd->tile_blocks - 1);
|
|
|
|
|
|
|
|
|
|
for(i=0; i<Libisoburn_cache_tileS; i++) {
|
|
|
|
|
if(aligned_lba == tiles[i].cache_lba && tiles[i].cache_lba != 0xffffffff) {
|
|
|
|
|
(tiles[i].cache_hits)++;
|
|
|
|
|
memcpy(buffer, tiles[i].cache_data + (lba - aligned_lba) * 2048, 2048);
|
|
|
|
|
for (i = 0; i < icd->num_tiles; i++) {
|
|
|
|
|
if(aligned_lba == tiles[i]->cache_lba &&
|
|
|
|
|
tiles[i]->cache_lba != 0xffffffff) {
|
|
|
|
|
(tiles[i]->cache_hits)++;
|
|
|
|
|
memcpy(buffer, tiles[i]->cache_data + (lba - aligned_lba) * 2048, 2048);
|
|
|
|
|
count= 2048;
|
|
|
|
|
ds_inc_age(icd, i, 0);
|
|
|
|
|
return 1;
|
|
|
|
@ -147,37 +140,37 @@ address_rollover:;
|
|
|
|
|
/* find oldest tile */
|
|
|
|
|
oldest_age= Libisoburn_max_agE;
|
|
|
|
|
oldest= 0;
|
|
|
|
|
for(i= 0; i<Libisoburn_cache_tileS; i++) {
|
|
|
|
|
if(tiles[i].cache_lba == 0xffffffff) {
|
|
|
|
|
for(i = 0; i < icd->num_tiles; i++) {
|
|
|
|
|
if(tiles[i]->cache_lba == 0xffffffff) {
|
|
|
|
|
oldest= i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(tiles[i].age<oldest_age) {
|
|
|
|
|
oldest_age= tiles[i].age;
|
|
|
|
|
if(tiles[i]->age < oldest_age) {
|
|
|
|
|
oldest_age= tiles[i]->age;
|
|
|
|
|
oldest= i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tiles[oldest].cache_lba= 0xffffffff; /* invalidate cache */
|
|
|
|
|
if(tiles[oldest].last_aligned_error_lba == aligned_lba) {
|
|
|
|
|
tiles[oldest]->cache_lba= 0xffffffff; /* invalidate cache */
|
|
|
|
|
if(tiles[oldest]->last_aligned_error_lba == aligned_lba) {
|
|
|
|
|
ret = 0;
|
|
|
|
|
} else {
|
|
|
|
|
ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048,
|
|
|
|
|
(char *) tiles[oldest].cache_data,
|
|
|
|
|
Libisoburn_tile_blockS * 2048, &count, 2);
|
|
|
|
|
(char *) tiles[oldest]->cache_data,
|
|
|
|
|
icd->tile_blocks * 2048, &count, 2);
|
|
|
|
|
}
|
|
|
|
|
if (ret <= 0 ) {
|
|
|
|
|
tiles[oldest].last_aligned_error_lba = aligned_lba;
|
|
|
|
|
tiles[oldest]->last_aligned_error_lba = aligned_lba;
|
|
|
|
|
|
|
|
|
|
/* Read-ahead failure ? Try to read 2048 directly. */
|
|
|
|
|
if(tiles[oldest].last_error_lba == lba)
|
|
|
|
|
if(tiles[oldest]->last_error_lba == lba)
|
|
|
|
|
ret = 0;
|
|
|
|
|
else
|
|
|
|
|
ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer,
|
|
|
|
|
2048, &count, 0);
|
|
|
|
|
if (ret > 0)
|
|
|
|
|
return 1;
|
|
|
|
|
tiles[oldest].last_error_lba = lba;
|
|
|
|
|
tiles[oldest]->last_error_lba = lba;
|
|
|
|
|
sprintf(msg, "ds_read_block(%lu) returns %lX",
|
|
|
|
|
(unsigned long) lba, (unsigned long) ret);
|
|
|
|
|
isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "DEBUG", 0);
|
|
|
|
@ -186,14 +179,14 @@ address_rollover:;
|
|
|
|
|
|
|
|
|
|
#ifdef Libisoburn_read_cache_reporT
|
|
|
|
|
fprintf(stderr, "Tile %2.2d : After %3d hits, new load from %8x , count= %d\n",
|
|
|
|
|
oldest, tiles[oldest].cache_hits, aligned_lba, (int) count);
|
|
|
|
|
oldest, tiles[oldest]->cache_hits, aligned_lba, (int) count);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
tiles[oldest].cache_lba= aligned_lba;
|
|
|
|
|
tiles[oldest].cache_hits= 1;
|
|
|
|
|
tiles[oldest]->cache_lba= aligned_lba;
|
|
|
|
|
tiles[oldest]->cache_hits= 1;
|
|
|
|
|
ds_inc_age(icd, oldest, 0);
|
|
|
|
|
|
|
|
|
|
memcpy(buffer, tiles[oldest].cache_data + (lba - aligned_lba) * 2048, 2048);
|
|
|
|
|
memcpy(buffer, tiles[oldest]->cache_data + (lba - aligned_lba) * 2048, 2048);
|
|
|
|
|
count= 2048;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
@ -212,11 +205,107 @@ static int ds_close(IsoDataSource *src)
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int isoburn_cache_tile_destroy(struct isoburn_cache_tile **o,
|
|
|
|
|
int flag)
|
|
|
|
|
{
|
|
|
|
|
if (*o == NULL)
|
|
|
|
|
return(0);
|
|
|
|
|
if ((*o)->cache_data != NULL)
|
|
|
|
|
free((*o)->cache_data);
|
|
|
|
|
free(*o);
|
|
|
|
|
*o = NULL;
|
|
|
|
|
return(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int isoburn_cache_tile_new(struct isoburn_cache_tile **o,
|
|
|
|
|
int tile_blocks, int flag)
|
|
|
|
|
{
|
|
|
|
|
struct isoburn_cache_tile *t;
|
|
|
|
|
|
|
|
|
|
*o = t = calloc(1, sizeof(struct isoburn_cache_tile));
|
|
|
|
|
if (t == NULL)
|
|
|
|
|
goto fail;
|
|
|
|
|
t->cache_data = NULL;
|
|
|
|
|
t->cache_lba = 0xffffffff;
|
|
|
|
|
t->cache_hits = 0;
|
|
|
|
|
t->last_error_lba = 0xffffffff;
|
|
|
|
|
t->last_aligned_error_lba = 0xffffffff;
|
|
|
|
|
t->age= 0;
|
|
|
|
|
|
|
|
|
|
t->cache_data = calloc(1, tile_blocks * 2048);
|
|
|
|
|
if (t->cache_data == NULL)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
return(1);
|
|
|
|
|
fail:;
|
|
|
|
|
isoburn_cache_tile_destroy(o, 0);
|
|
|
|
|
return(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int isoburn_cached_drive_destroy(struct isoburn_cached_drive **o,
|
|
|
|
|
int flag)
|
|
|
|
|
{
|
|
|
|
|
struct isoburn_cached_drive *c;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (*o == NULL)
|
|
|
|
|
return(0);
|
|
|
|
|
c= *o;
|
|
|
|
|
if (c->tiles != NULL) {
|
|
|
|
|
for (i = 0; i < c->num_tiles; i++)
|
|
|
|
|
isoburn_cache_tile_destroy(&(c->tiles[i]), 0);
|
|
|
|
|
free(c->tiles);
|
|
|
|
|
}
|
|
|
|
|
free(c);
|
|
|
|
|
*o= NULL;
|
|
|
|
|
return(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int isoburn_cached_drive_new(struct isoburn_cached_drive **o,
|
|
|
|
|
struct burn_drive *d, int cache_tiles,
|
|
|
|
|
int tile_blocks, int flag)
|
|
|
|
|
{
|
|
|
|
|
struct isoburn_cached_drive *icd;
|
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
|
|
*o = icd = calloc(1,sizeof(struct isoburn_cached_drive));
|
|
|
|
|
if (o == NULL)
|
|
|
|
|
return(-1);
|
|
|
|
|
icd->drive = d;
|
|
|
|
|
icd->tiles = NULL;
|
|
|
|
|
icd->num_tiles = cache_tiles;
|
|
|
|
|
icd->tile_blocks = tile_blocks;
|
|
|
|
|
icd->current_age = 0;
|
|
|
|
|
icd->displacement = 0;
|
|
|
|
|
icd->displacement_sign = 0;
|
|
|
|
|
|
|
|
|
|
icd->tiles = calloc(1, sizeof(struct isoburn_cache_tile *) * icd->num_tiles);
|
|
|
|
|
if (icd->tiles == NULL)
|
|
|
|
|
goto fail;
|
|
|
|
|
for (i = 0; i < icd->num_tiles; i++) {
|
|
|
|
|
ret = isoburn_cache_tile_new(&(icd->tiles[i]), icd->tile_blocks, 0);
|
|
|
|
|
if (ret <= 0)
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
return(1);
|
|
|
|
|
fail:;
|
|
|
|
|
isoburn_cached_drive_destroy(o, 0);
|
|
|
|
|
return(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void ds_free_data(IsoDataSource *src)
|
|
|
|
|
{
|
|
|
|
|
/* nothing to do */;
|
|
|
|
|
if(src->data != NULL)
|
|
|
|
|
free(src->data);
|
|
|
|
|
struct isoburn_cached_drive *icd;
|
|
|
|
|
|
|
|
|
|
if(src->data != NULL) {
|
|
|
|
|
icd= (struct isoburn_cached_drive *) src->data;
|
|
|
|
|
isoburn_cached_drive_destroy(&icd, 0);
|
|
|
|
|
}
|
|
|
|
|
src->data= NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -234,37 +323,33 @@ int isoburn_data_source_shutdown(IsoDataSource *src, int flag)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IsoDataSource *isoburn_data_source_new(struct burn_drive *d,
|
|
|
|
|
uint32_t displacement, int displacement_sign)
|
|
|
|
|
uint32_t displacement, int displacement_sign,
|
|
|
|
|
int cache_tiles, int tile_blocks)
|
|
|
|
|
{
|
|
|
|
|
IsoDataSource *ret;
|
|
|
|
|
IsoDataSource *src;
|
|
|
|
|
struct isoburn_cached_drive *icd= NULL;
|
|
|
|
|
int i;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (d==NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
ret = malloc(sizeof(IsoDataSource));
|
|
|
|
|
icd = calloc(1,sizeof(struct isoburn_cached_drive));
|
|
|
|
|
if (ret == NULL || icd == NULL)
|
|
|
|
|
src = malloc(sizeof(IsoDataSource));
|
|
|
|
|
if (src == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
ret = isoburn_cached_drive_new(&icd, d, cache_tiles, tile_blocks, 0);
|
|
|
|
|
if (ret <= 0) {
|
|
|
|
|
free(src);
|
|
|
|
|
return NULL;
|
|
|
|
|
ret->version = 0;
|
|
|
|
|
ret->refcount = 1;
|
|
|
|
|
ret->read_block = ds_read_block;
|
|
|
|
|
ret->open = ds_open;
|
|
|
|
|
ret->close = ds_close;
|
|
|
|
|
ret->free_data = ds_free_data;
|
|
|
|
|
ret->data = icd;
|
|
|
|
|
icd->drive = d;
|
|
|
|
|
icd->current_age= 0;
|
|
|
|
|
for(i= 0; i<Libisoburn_cache_tileS; i++) {
|
|
|
|
|
icd->tiles[i].cache_lba = 0xffffffff;
|
|
|
|
|
icd->tiles[i].cache_hits = 0;
|
|
|
|
|
icd->tiles[i].last_error_lba = 0xffffffff;
|
|
|
|
|
icd->tiles[i].last_aligned_error_lba = 0xffffffff;
|
|
|
|
|
icd->tiles[i].age= 0;
|
|
|
|
|
}
|
|
|
|
|
src->version = 0;
|
|
|
|
|
src->refcount = 1;
|
|
|
|
|
src->read_block = ds_read_block;
|
|
|
|
|
src->open = ds_open;
|
|
|
|
|
src->close = ds_close;
|
|
|
|
|
src->free_data = ds_free_data;
|
|
|
|
|
src->data = icd;
|
|
|
|
|
icd->displacement = displacement;
|
|
|
|
|
icd->displacement_sign = displacement_sign;
|
|
|
|
|
return ret;
|
|
|
|
|
return src;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -274,11 +359,11 @@ static int ds_inc_age(struct isoburn_cached_drive *icd, int idx, int flag)
|
|
|
|
|
|
|
|
|
|
(icd->current_age)++;
|
|
|
|
|
if(icd->current_age>=Libisoburn_max_agE) { /* reset all ages (allow waste) */
|
|
|
|
|
for(i= 0; i<Libisoburn_cache_tileS; i++)
|
|
|
|
|
(icd->tiles)[i].age= 0;
|
|
|
|
|
for(i = 0; i < icd->num_tiles; i++)
|
|
|
|
|
(icd->tiles)[i]->age= 0;
|
|
|
|
|
icd->current_age= 1;
|
|
|
|
|
}
|
|
|
|
|
(icd->tiles)[idx].age= icd->current_age;
|
|
|
|
|
(icd->tiles)[idx]->age= icd->current_age;
|
|
|
|
|
return(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|