New API calls iso_stream_zisofs_discard_bpt() and iso_image_zisofs_discard_bpt()

This commit is contained in:
Thomas Schmitt 2020-10-25 16:59:32 +01:00
parent cc2e0e32a3
commit 80449f0dc9
4 changed files with 184 additions and 44 deletions

View File

@ -85,9 +85,9 @@ static uint64_t ziso_block_pointer_mgt(uint64_t num, int mode);
/* A ratio describing the part of the maximum number of block pointers which /* A ratio describing the part of the maximum number of block pointers which
* shall be kept free by intermediate discarding of block pointers. See above * shall be kept free by intermediate discarding of block pointers. See above
* ISO_ZISOFS_MANY_BLOCKS. * ISO_ZISOFS_MANY_BLOCKS. -1.0 disables this feature.
*/ */
#define ISO_ZISOFS_KBF_RATIO 0.5 #define ISO_ZISOFS_KBF_RATIO -1.0
/* --------------------------- Runtime parameters ------------------------- */ /* --------------------------- Runtime parameters ------------------------- */
@ -106,6 +106,12 @@ static int64_t ziso_max_file_blocks = ISO_ZISOFS_MAX_BLOCKS_F;
static int64_t ziso_many_block_limit = ISO_ZISOFS_MANY_BLOCKS; static int64_t ziso_many_block_limit = ISO_ZISOFS_MANY_BLOCKS;
static double ziso_keep_blocks_free_ratio = ISO_ZISOFS_KBF_RATIO; static double ziso_keep_blocks_free_ratio = ISO_ZISOFS_KBF_RATIO;
/* Discard block pointers on last stream close even if the size constraints
* are not met. To be set to 1 at block pointer overflow. To be set to 0
* when all compression filters are deleted.
*/
static int ziso_early_bpt_discard = 0;
static static
int ziso_decide_v2_usage(off_t orig_size) int ziso_decide_v2_usage(off_t orig_size)
@ -375,6 +381,50 @@ static
int ziso_stream_compress(IsoStream *stream, void *buf, size_t desired); int ziso_stream_compress(IsoStream *stream, void *buf, size_t desired);
/*
* @param flag bit0= discard even if the size conditions are not met
bit1= check for open_counter == 1 rather than == 0
*/
static
int ziso_discard_bpt(IsoStream *stream, int flag)
{
ZisofsFilterStreamData *data;
ZisofsComprStreamData *cstd = NULL;
int block_size;
double max_blocks, free_blocks;
data = stream->data;
if (stream->class->read == &ziso_stream_compress)
cstd = (ZisofsComprStreamData *) data;
if (cstd == NULL)
return 0;
block_size = (1 << ziso_decide_bs_log2(cstd->orig_size));
max_blocks = ziso_max_file_blocks;
if (max_blocks < 1.0)
max_blocks = 1.0;
free_blocks = ziso_max_total_blocks -
ziso_block_pointer_mgt((uint64_t) 0, 3);
if (cstd->block_pointers == NULL) {
return 0;
} else if (cstd->open_counter != !!(flag & 2)) {
return 0;
} else if (!((flag & 1) || ziso_early_bpt_discard)) {
if (ziso_many_block_limit <= 0 ||
cstd->orig_size / block_size + !!(cstd->orig_size % block_size)
+ 1 < (uint64_t) ziso_many_block_limit)
if (ziso_keep_blocks_free_ratio < 0.0 ||
free_blocks / max_blocks >= ziso_keep_blocks_free_ratio)
return 0;
}
ziso_block_pointer_mgt(cstd->block_pointer_counter, 2);
free((char *) cstd->block_pointers);
cstd->block_pointers_dropped = 1;
cstd->block_pointers = NULL;
cstd->block_pointer_counter = 0;
return 1;
}
/* /*
* @param flag bit0= original stream is not open * @param flag bit0= original stream is not open
* bit1= do not destroy large * bit1= do not destroy large
@ -385,8 +435,6 @@ int ziso_stream_close_flag(IsoStream *stream, int flag)
{ {
ZisofsFilterStreamData *data; ZisofsFilterStreamData *data;
ZisofsComprStreamData *cstd = NULL; ZisofsComprStreamData *cstd = NULL;
int block_size, discard;
double max_blocks, free_blocks;
if (stream == NULL) { if (stream == NULL) {
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
@ -395,35 +443,8 @@ int ziso_stream_close_flag(IsoStream *stream, int flag)
if (stream->class->read == &ziso_stream_compress) if (stream->class->read == &ziso_stream_compress)
cstd = (ZisofsComprStreamData *) data; cstd = (ZisofsComprStreamData *) data;
if (cstd != NULL) { if (cstd != NULL && !(flag & 2))
block_size = (1 << ziso_decide_bs_log2(cstd->orig_size)); ziso_discard_bpt(stream, 2);
max_blocks = ziso_max_file_blocks;
if (max_blocks < 1.0)
max_blocks = 1.0;
free_blocks = ziso_max_total_blocks -
ziso_block_pointer_mgt((uint64_t) 0, 3);
discard = 1;
if (flag & 2) {
discard = 0;
} else if (cstd->block_pointers == NULL) {
discard = 0;
} else if (cstd->open_counter != 1) {
discard = 0;
} else if (ziso_many_block_limit <= 0 ||
cstd->orig_size / block_size + !!(cstd->orig_size % block_size)
+ 1 < (uint64_t) ziso_many_block_limit) {
if (ziso_keep_blocks_free_ratio < 0.0 ||
free_blocks / max_blocks >= ziso_keep_blocks_free_ratio)
discard = 0;
}
if (discard) {
ziso_block_pointer_mgt(cstd->block_pointer_counter, 2);
free((char *) cstd->block_pointers);
cstd->block_pointers_dropped = 1;
cstd->block_pointers = NULL;
cstd->block_pointer_counter = 0;
}
}
if (data->running == NULL) { if (data->running == NULL) {
return 1; return 1;
@ -601,8 +622,10 @@ int ziso_stream_compress(IsoStream *stream, void *buf, size_t desired)
1 + !!(orig_size % rng->block_size); 1 + !!(orig_size % rng->block_size);
if (num_blocks > (uint64_t) ziso_max_file_blocks) if (num_blocks > (uint64_t) ziso_max_file_blocks)
return (rng->error_ret = ISO_ZISOFS_TOO_LARGE); return (rng->error_ret = ISO_ZISOFS_TOO_LARGE);
if (ziso_block_pointer_mgt((uint64_t) num_blocks, 0) == 0) if (ziso_block_pointer_mgt((uint64_t) num_blocks, 0) == 0) {
return (rng->error_ret = ISO_ZISOFS_TOO_MANY_PTR); ziso_early_bpt_discard = 1;
return (rng->error_ret = ISO_ZISOFS_TOO_MANY_PTR);
}
if (orig_size != (off_t) data->orig_size) if (orig_size != (off_t) data->orig_size)
return (rng->error_ret = ISO_FILTER_WRONG_INPUT); return (rng->error_ret = ISO_FILTER_WRONG_INPUT);
if (ziso_decide_v2_usage(orig_size)) { if (ziso_decide_v2_usage(orig_size)) {
@ -651,6 +674,7 @@ int ziso_stream_compress(IsoStream *stream, void *buf, size_t desired)
/* On the first pass, create pointer array with all 0s */ /* On the first pass, create pointer array with all 0s */
if (ziso_block_pointer_mgt(num_blocks, 1) == 0) { if (ziso_block_pointer_mgt(num_blocks, 1) == 0) {
rng->block_pointer_fill = 0; rng->block_pointer_fill = 0;
ziso_early_bpt_discard = 1;
return (rng->error_ret = ISO_ZISOFS_TOO_MANY_PTR); return (rng->error_ret = ISO_ZISOFS_TOO_MANY_PTR);
} }
data->block_pointers = calloc(rng->block_pointer_fill, 8); data->block_pointers = calloc(rng->block_pointer_fill, 8);
@ -1152,6 +1176,8 @@ void ziso_stream_free(IsoStream *stream)
} }
if (--ziso_ref_count < 0) if (--ziso_ref_count < 0)
ziso_ref_count = 0; ziso_ref_count = 0;
if (ziso_ref_count == 0)
ziso_early_bpt_discard = 0;
} }
iso_stream_unref(data->orig); iso_stream_unref(data->orig);
free(data); free(data);
@ -1673,8 +1699,6 @@ int iso_zisofs_set_params(struct iso_zisofs_ctrl *params, int flag)
if (params->bpt_discard_free_ratio != 0.0) if (params->bpt_discard_free_ratio != 0.0)
ziso_keep_blocks_free_ratio = params->bpt_discard_free_ratio; ziso_keep_blocks_free_ratio = params->bpt_discard_free_ratio;
/* >>> zisofs2: more parameters */
return 1; return 1;
#else #else
@ -1723,9 +1747,14 @@ int iso_stream_get_zisofs_par(IsoStream *stream, int *stream_type,
uint8_t zisofs_algo[2], uint8_t* algo_num, uint8_t zisofs_algo[2], uint8_t* algo_num,
int *block_size_log2, int flag) int *block_size_log2, int flag)
{ {
#ifdef Libisofs_with_zliB
uint64_t uncompressed_size; uint64_t uncompressed_size;
int header_size_div4, ret; int header_size_div4, ret;
if (stream == NULL)
return ISO_NULL_POINTER;
ret = ziso_is_zisofs_stream(stream, stream_type, zisofs_algo, ret = ziso_is_zisofs_stream(stream, stream_type, zisofs_algo,
&header_size_div4, block_size_log2, &header_size_div4, block_size_log2,
&uncompressed_size, 0); &uncompressed_size, 0);
@ -1733,5 +1762,33 @@ int iso_stream_get_zisofs_par(IsoStream *stream, int *stream_type,
return 0; return 0;
*algo_num = ziso_algo_to_num(zisofs_algo); *algo_num = ziso_algo_to_num(zisofs_algo);
return 1; return 1;
#else
return ISO_ZLIB_NOT_ENABLED;
#endif /* ! Libisofs_with_zliB */
} }
/* API */
int iso_stream_zisofs_discard_bpt(IsoStream *stream, int flag)
{
#ifdef Libisofs_with_zliB
int ret;
if (stream == NULL)
return ISO_NULL_POINTER;
ret = ziso_discard_bpt(stream, 1);
return ret;
#else
return ISO_ZLIB_NOT_ENABLED;
#endif /* ! Libisofs_with_zliB */
}

View File

@ -1144,9 +1144,69 @@ int iso_image_was_blind_attrs(IsoImage *image, int flag)
{ {
int ret; int ret;
if (image == NULL)
return ISO_NULL_POINTER;
ret = image->blind_on_local_get_attrs; ret = image->blind_on_local_get_attrs;
if (flag & 1) if (flag & 1)
image->blind_on_local_get_attrs = 0; image->blind_on_local_get_attrs = 0;
return ret; return ret;
} }
/*
* @param flag bit0= recursion is active
*/
static
int iso_dir_zisofs_discard_bpt(IsoDir *dir, int flag)
{
int ret;
IsoDirIter *iter = NULL;
IsoNode *node;
IsoDir *subdir;
IsoFile *file;
IsoStream *stream;
ret = iso_dir_get_children(dir, &iter);
if (ret < 0)
return ret;
while (iso_dir_iter_next(iter, &node) == 1) {
if (iso_node_get_type(node) == LIBISO_DIR) {
subdir = (IsoDir *) node;
ret = iso_dir_zisofs_discard_bpt(subdir, flag | 1);
if (ret < 0)
goto ex;
continue;
}
if (iso_node_get_type(node) != LIBISO_FILE)
continue;
file = (IsoFile *) node;
stream = iso_file_get_stream(file);
if (stream == NULL)
continue;
ret = iso_stream_zisofs_discard_bpt(stream, 0);
if (ret < 0)
goto ex;
}
ret = ISO_SUCCESS;
ex:;
if (iter != NULL)
iso_dir_iter_free(iter);
return ret;
}
/* API */
int iso_image_zisofs_discard_bpt(IsoImage *image, int flag)
{
int ret;
IsoDir *dir;
if (image == NULL)
return ISO_NULL_POINTER;
dir = image->root;
if (dir == NULL)
return ISO_SUCCESS;
ret = iso_dir_zisofs_discard_bpt(dir, 0);
return ret;
}

View File

@ -7988,6 +7988,7 @@ int iso_file_add_zisofs_filter(IsoFile *file, int flag);
* Bitfield for control purposes, unused yet, submit 0 * Bitfield for control purposes, unused yet, submit 0
* @return * @return
* 1 on success, 0 if the stream has not class->type "ziso" or "osiz" * 1 on success, 0 if the stream has not class->type "ziso" or "osiz"
* <0 on error
* @since 1.5.4 * @since 1.5.4
*/ */
int iso_stream_get_zisofs_par(IsoStream *stream, int *stream_type, int iso_stream_get_zisofs_par(IsoStream *stream, int *stream_type,
@ -7995,6 +7996,33 @@ int iso_stream_get_zisofs_par(IsoStream *stream, int *stream_type,
int *block_size_log2, int flag); int *block_size_log2, int flag);
/**
* Discard the buffered zisofs compression block pointers of a stream, if the
* stream is a zisofs compression stream and not currently opened.
* @param stream
* The stream to be manipulated.
* @param flag
* Bitfield for control purposes, unused yet, submit 0
* @return
* 1 on success, 0 if no block pointers were reoved, <0 on error
* @since 1.5.4
*/
int iso_stream_zisofs_discard_bpt(IsoStream *stream, int flag);
/**
* Discard all buffered zisofs compression block pointers of streams in the
* given image, which are zisofs compression streams and not currently opened.
* @param image
* The image to be manipulated.
* @param flag
* Bitfield for control purposes, unused yet, submit 0
* @return
* ISO_SUCCESS on success, <0 on error
* @since 1.5.4
*/
int iso_image_zisofs_discard_bpt(IsoImage *image, int flag);
/** /**
* Inquire the number of zisofs compression and uncompression filters which * Inquire the number of zisofs compression and uncompression filters which
* are in use. * are in use.
@ -8117,13 +8145,6 @@ struct iso_zisofs_ctrl {
*/ */
double bpt_discard_free_ratio; double bpt_discard_free_ratio;
/* >>> ??? zisofs2: a limit for number of zisofs2 files in order to keep
the number of these old kernel warnings bearable:
"isofs: Unknown ZF compression algorithm: PZ"
0 = default >>> ??? value ? no limit ?
*/
}; };
/** /**

View File

@ -154,6 +154,7 @@ iso_image_tree_clone;
iso_image_unref; iso_image_unref;
iso_image_update_sizes; iso_image_update_sizes;
iso_image_was_blind_attrs; iso_image_was_blind_attrs;
iso_image_zisofs_discard_bpt;
iso_init; iso_init;
iso_init_with_flag; iso_init_with_flag;
iso_interval_reader_destroy; iso_interval_reader_destroy;
@ -273,6 +274,7 @@ iso_stream_read;
iso_stream_ref; iso_stream_ref;
iso_stream_unref; iso_stream_unref;
iso_stream_update_size; iso_stream_update_size;
iso_stream_zisofs_discard_bpt;
iso_symlink_get_dest; iso_symlink_get_dest;
iso_symlink_set_dest; iso_symlink_set_dest;
iso_text_to_sev; iso_text_to_sev;