From 6668ab7d32fdc6de47a0faa63756dcf20f8df2ee Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 1 May 2012 07:49:46 +0000 Subject: [PATCH] New -check_media option async_chunks= --- xorriso/check_media.c | 16 +- xorriso/check_media.h | 5 +- xorriso/drive_mgt.c | 588 +++++++++++++++++++++++++++--------- xorriso/xorriso.1 | 9 +- xorriso/xorriso.info | 69 +++-- xorriso/xorriso.texi | 9 +- xorriso/xorriso_timestamp.h | 2 +- 7 files changed, 510 insertions(+), 188 deletions(-) diff --git a/xorriso/check_media.c b/xorriso/check_media.c index 05fb0b3e..c5247443 100644 --- a/xorriso/check_media.c +++ b/xorriso/check_media.c @@ -571,6 +571,7 @@ int Checkmediajob_new(struct CheckmediajoB **o, int flag) m->min_lba= -1; m->max_lba= -1; m->min_block_size= 0; + m->async_chunks= 0; m->mode= 0; m->start_time= time(NULL); m->time_limit= 28800; @@ -655,6 +656,12 @@ int Xorriso_check_media_setup_job(struct XorrisO *xorriso, ret= Sfile_str(job->abort_file_path, argv[i] + 11, 0); if(ret <= 0) goto ex; + } else if(strncmp(argv[i], "async_chunks=", 13) == 0) { + num= Scanf_io_size(argv[i] + 13, 1); + if(num >= 0 && num <= 1024) + job->async_chunks= num; + else + goto bad_value; } else if(strncmp(argv[i], "bad_limit=", 10) == 0) { if(strcmp(argv[i] + 10, "good") == 0) xorriso->check_media_bad_limit= Xorriso_read_quality_gooD; @@ -689,7 +696,7 @@ int Xorriso_check_media_setup_job(struct XorrisO *xorriso, if(num >= 2048 || num == 0) job->min_block_size= num / 2048; else - goto unknown_value; + goto bad_value; } else if(strncmp(argv[i], "event=", 6) == 0) { strncpy(sev_text, argv[i] + 6, 19); sev_text[19]= 0; @@ -731,7 +738,7 @@ int Xorriso_check_media_setup_job(struct XorrisO *xorriso, num= -1; sscanf(argv[i] + 11, "%lf", &num); if(num > 0x7fffffff || num < 0) - goto unknown_value; + goto bad_value; job->patch_lba0_msc1= num; job->patch_lba0= (num >= 32) + (strstr(argv[i] + 11, ":force") != NULL); } else @@ -815,6 +822,11 @@ unknown_value:; "-check_media: Unknown value with option %s", argv[i]); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; +bad_value:; + sprintf(xorriso->info_text, + "-check_media: Unsuitable value with option %s", argv[i]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; } } else { sprintf(xorriso->info_text, "-check_media: Unknown option '%s'", argv[i]); diff --git a/xorriso/check_media.h b/xorriso/check_media.h index 030ebbad..6bc6c963 100644 --- a/xorriso/check_media.h +++ b/xorriso/check_media.h @@ -99,7 +99,10 @@ struct CheckmediajoB { int max_lba; /* if >=0 : read up to this address, else use mode */ int min_block_size; /* granularity desired by user - */ + */ + int async_chunks; /* >= 2 : run MD5 thread, use given number of chunks + else : synchronous + */ int mode; /* 0= track by track 1= single sweep over libisoburn medium capacity 2= single sweep over libburn medium capacity diff --git a/xorriso/drive_mgt.c b/xorriso/drive_mgt.c index f97a512f..55a60f70 100644 --- a/xorriso/drive_mgt.c +++ b/xorriso/drive_mgt.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "xorriso.h" @@ -2106,6 +2107,312 @@ int Xorriso_check_for_abort(struct XorrisO *xorriso, } +struct xorriso_md5_state { + + /* Resources */ + struct XorrisO *xorriso; + void *ctx; + struct SpotlisT *spotlist; + pthread_mutex_t spot_mutex; + + /* Checksum tag cursor */ + uint32_t md5_start; + uint32_t next_tag; + int chain_broken; + int in_track_gap; + int was_sb_tag; + int md5_spot_value; + uint32_t md5_spot_lba; + + /* Asynchronous operation */ + + int slave_state; /* Operated by slave + 0= not yet started + 1= slave is started + 2= slave has reached its end + 3= slave failed to start + */ + int chunk_size; + int num_chunks; + char **chunk; + int *chunk_state; /* 0= content invalid (set by boss at creation time), + 1= content readable (set by boss), + 2= content was read (set by MD5 slave), + 3= end-of-processing (set by boss when done) + */ + int *chunk_fill; /* Actual number of valid bytes in chunk */ + uint32_t *chunk_lba; + int chunk_w_idx; /* Write index. Operated by boss */ + int chunk_r_idx; /* Read index. Operated by MD5 slave */ + + off_t w_sleeps; + off_t r_sleeps; + +}; + + +int Xorriso__add_spot(struct xorriso_md5_state *state, + int start_lba, int blocks, int quality, int flag) +{ + int ret; + + if(state->chunk != NULL) { + ret= pthread_mutex_lock(&(state->spot_mutex)); + if(ret != 0) + return(0); + } + ret= Spotlist_add_item(state->spotlist, start_lba, blocks, quality, 0); + if(state->chunk != NULL) + pthread_mutex_unlock(&(state->spot_mutex)); + return(ret); +} + + +int Xorriso_chunk_md5(struct XorrisO *xorriso, char *data, int to_read, + uint32_t from_lba, struct xorriso_md5_state *state, int flag) +{ + int j, ret= 0, valid, tag_type; + uint32_t lba, pos, range_start, range_size; + char md5[16], tag_md5[16], *tag_type_name= "", *comparison, *sev_text; + void *cloned_ctx= NULL; + + for(j= 0; j < to_read; j++) { + lba= j + from_lba; + if(lba < state->md5_start) + continue; + ret= 0; + if(lba > state->md5_start + 16 && + (state->next_tag == 0 || state->chain_broken || lba == state->next_tag)){ + ret= iso_util_decode_md5_tag(data + j * 2048, &tag_type, + &pos, &range_start, &range_size, + &(state->next_tag), tag_md5, + !!state->chain_broken); + } + valid= (ret == 1 || ret == (int) ISO_MD5_AREA_CORRUPTED) && pos == lba; + if(valid && tag_type == 2 && (lba < state->md5_start + 32 || + state->in_track_gap)){ + tag_type_name= "superblock"; + state->was_sb_tag= 1; + if(state->in_track_gap && range_start != state->md5_start && + range_start < lba && lba - range_start <= (uint32_t) j) { + /* Looking for next session : start computing in hindsight. + Session start and superblock tag are supposed to be in the + same 64 kB chunk. + */ + iso_md5_end(&(state->ctx), md5); + ret= iso_md5_start(&(state->ctx)); + if(ret < 0) { + Xorriso_no_malloc_memory(xorriso, NULL, 0); + ret= -1; goto ex; + } + iso_md5_compute(&(state->ctx), data + (j - (lba - range_start)) * 2048, + (lba - range_start) * 2048); + state->md5_start= range_start; + state->in_track_gap= 0; + } + } else if(valid && tag_type == 4 && lba < 32) { + tag_type_name= "relocated 64kB superblock"; + }else if(valid && tag_type == 3 && state->was_sb_tag) { + tag_type_name= "tree"; + }else if(valid && tag_type == 1) { + + /* >>> ??? allow this without superblock and tree tag ? */ + + tag_type_name= "session"; + } else { + tag_type_name= ""; + } + if (tag_type_name[0]) { + if(range_start != state->md5_start) { + sprintf(xorriso->info_text, + "Found MD5 %s tag which covers different data range", tag_type_name); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0); + sprintf(xorriso->info_text, " Expected: %u Found: %u", + (unsigned int) state->md5_start, range_start); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0); + state->chain_broken= 1; + valid= 0; + } else { + ret= iso_md5_clone(state->ctx, &cloned_ctx); + if(ret <= 0) { + Xorriso_no_malloc_memory(xorriso, NULL, 0); + ret= -1; goto ex; + } + iso_md5_end(&cloned_ctx, md5); + + if(ret == (int) ISO_MD5_AREA_CORRUPTED) { + comparison= "CORRUPTED"; + sev_text= "WARNING"; + state->md5_spot_value= Xorriso_read_quality_md5_mismatcH; + state->chain_broken= 1; + } else if(! iso_md5_match(tag_md5, md5)) { + comparison= "NON-MATCHING"; + sev_text= "WARNING"; + state->md5_spot_value= Xorriso_read_quality_md5_mismatcH; + state->chain_broken= 1; + } else { + comparison= "matching"; + sev_text= "UPDATE"; + state->md5_spot_value= Xorriso_read_quality_md5_matcH; + } + state->md5_spot_lba= lba; + sprintf(xorriso->info_text, + "Found %s MD5 %s tag: start=%d size=%d", + comparison, tag_type_name, state->md5_start, + lba - state->md5_start); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, sev_text, 0); + } + if(valid && (tag_type == 1 || (tag_type == 4 && pos == lba && lba < 32))){ + if(state->md5_spot_value != Xorriso_read_quality_untesteD) { + ret= Xorriso__add_spot(state, state->md5_start, + state->md5_spot_lba - state->md5_start, state->md5_spot_value, 0); + if(ret <= 0) + goto ex; + } + state->md5_spot_value= Xorriso_read_quality_untesteD; + state->md5_start = lba + 1; + if(state->md5_start % 32) + state->md5_start= state->md5_start + (32 - (state->md5_start % 32)); + state->next_tag= 0; + + iso_md5_end(&(state->ctx), md5); + ret= iso_md5_start(&(state->ctx)); + if(ret < 0) { + Xorriso_no_malloc_memory(xorriso, NULL, 0); + ret= -1; goto ex; + } + if(tag_type == 1) + state->in_track_gap= 1; + continue; + } + } + iso_md5_compute(state->ctx, data + j * 2048, 2048); + } + ret= 1; +ex:; + return(ret); +} + + +static void *Xorriso__md5_slave(void *state_pt) +{ + struct xorriso_md5_state *state; + int ret, c_state, c_idx; + static int u_wait= 1; + + state= state_pt; + state->slave_state= 1; + + while(1) { + c_idx= state->chunk_r_idx; + c_state= state->chunk_state[c_idx]; + if(c_state == 1) { + ret= Xorriso_chunk_md5(state->xorriso, state->chunk[c_idx], + state->chunk_fill[c_idx], state->chunk_lba[c_idx], + state, 0); + if(ret <= 0) + goto ex; + state->chunk_state[c_idx]= 2; + state->chunk_r_idx= (c_idx + 1) % state->num_chunks; + } else if(c_state == 3) { + goto ex; + } else { + + /* >>> have a timeout ? */; + + if(u_wait > 0) + usleep(u_wait); + state->r_sleeps++; + } + } + +ex:; + state->slave_state= 2; + return NULL; +} + + +int Xorriso_start_chunk_md5(struct XorrisO *xorriso, + struct xorriso_md5_state *state, int flag) +{ + int ret, u_wait= 1000; + pthread_attr_t attr; + pthread_attr_t *attr_pt = NULL; + pthread_t thread; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + attr_pt= &attr; + + ret= pthread_create(&thread, attr_pt, Xorriso__md5_slave, state); + if(ret != 0) { + sprintf(xorriso->info_text, + "-check_media: Cannot create thread for MD5 computation"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= 0; goto ex; + } + + while(state->slave_state != 1) { + + /* >>> have a timeout ? */; + /* >>> if this fails set state->slave_state= 3 */ + + usleep(u_wait); + } + ret= 1; +ex:; + return(ret); +} + + +int Xorriso__wait_chunk_md5(struct xorriso_md5_state *state, + int u_wait, int flag) +{ + while(state->chunk_state[state->chunk_w_idx] == 1) { + + /* >>> have a timeout ? */; + + usleep(u_wait); + state->w_sleeps++; + } + return(1); +} + + +int Xorriso__wait_slave_md5_end(struct xorriso_md5_state *state, + int u_wait, int flag) +{ + while(state->slave_state == 1) { + + /* >>> have a timeout ? */; + + usleep(u_wait); + } + return(1); +} + + +int Xorriso__end_slave_md5(struct xorriso_md5_state *state, + int u_wait, int flag) +{ + int i, ret; + + /* Tell slave thread to end */ + for(i= 0; i < state->num_chunks; i++) { + ret= Xorriso__wait_chunk_md5(state, 10000, 0); + if(ret <= 0) + return(ret); + state->chunk_state[state->chunk_w_idx]= 3; + state->chunk_w_idx= (state->chunk_w_idx + 1) % state->num_chunks; + } + /* Wait for slave to end */ + ret= Xorriso__wait_slave_md5_end(state, 10000, 0); + if(ret <= 0) + return(ret); + return(1); +} + + /* @param flag bit0= this is a follow-up session (i.e. on CD: TAO) bit1= no pacifier messages bit2= compute stream MD5 and look out for checksum tag @@ -2123,23 +2430,40 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist, int start_lba= 0; struct burn_drive *drive; struct burn_drive_info *dinfo; - char *data= NULL; + char *data= NULL, *data_pt; off_t data_count, to_read, read_count= 0, write_amount; double pre_read_time, post_read_time, time_diff, total_time_diff= 0; double last_abort_file_time= 0; - void *ctx= NULL, *cloned_ctx= NULL; - char md5[16], tag_md5[16]; - uint32_t pos, range_start, range_size, next_tag= 0, lba, md5_spot_lba= 0; - int md5_spot_value= Xorriso_read_quality_untesteD, chain_broken= 0; - int tag_type= 0, valid, was_sb_tag= 0, in_track_gap= 0; - char *comparison= "", *sev_text= "DEBUG", *tag_type_name= ""; + void *ctx= NULL; + char md5[16]; + size_t data_size; + struct xorriso_md5_state state; + int num_chunks, async_md5; + static off_t chunks_limit= 256 * 1024 * 1024; + + memset(&state, 0, sizeof(state)); + state.chunk= NULL; + state.chunk_state= NULL; + state.chunk_fill= NULL; + state.chunk_lba= NULL; + state.spotlist= spotlist; if(read_chunk > 1024) read_chunk= 1024; else if(read_chunk < 1) read_chunk= 1; - Xorriso_alloc_meM(data, char, 2 * read_chunk * 1024); + num_chunks= job->async_chunks; + if(((off_t) num_chunks) * ((off_t) read_chunk) > chunks_limit) + num_chunks= chunks_limit / read_chunk; + async_md5= (num_chunks >= 2); + + if(async_md5) + data_size= num_chunks * read_chunk * 2048; + else + data_size= read_chunk * 2048; + Xorriso_alloc_meM(data, char, data_size); + data_pt= data; ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, "on attempt to check media readability", @@ -2171,6 +2495,50 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist, } } + state.xorriso= xorriso; + state.ctx= ctx; + state.spotlist= spotlist; + state.md5_start= md5_start; + state.next_tag= 0; + state.chain_broken= 0; + state.in_track_gap= 0; + state.was_sb_tag= 0; + state.md5_spot_value= Xorriso_read_quality_untesteD; + state.md5_spot_lba= 0; + state.slave_state= 0; + state.chunk_size= read_chunk; + if(async_md5) { + state.num_chunks= num_chunks; + Xorriso_alloc_meM(state.chunk, char *, num_chunks); + Xorriso_alloc_meM(state.chunk_state, int, num_chunks); + Xorriso_alloc_meM(state.chunk_fill, int, num_chunks); + Xorriso_alloc_meM(state.chunk_lba, uint32_t, num_chunks); + for(i= 0; i < state.num_chunks; i++) { + state.chunk[i]= data + read_chunk * i * 2048; + state.chunk_state[i]= 0; + state.chunk_fill[i]= 0; + state.chunk_lba[i]= 0; + } + ret= pthread_mutex_init(&(state.spot_mutex), NULL); + if(ret != 0) { + sprintf(xorriso->info_text, + "-check_media: Cannot initialize thread mutex"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + goto ex; + } + } else + state.num_chunks= 0; + state.chunk_w_idx= 0; + state.chunk_r_idx= 0; + state.w_sleeps= 0; + state.r_sleeps= 0; + + if(async_md5) { + ret= Xorriso_start_chunk_md5(xorriso, &state, 0); + if(ret <= 0) + goto ex; + } + start_lba= from_lba; to_read= read_chunk; post_read_time= Sfile_microtime(0); @@ -2195,12 +2563,12 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist, Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); abort_check:; if(prev_quality >= 0) { - ret= Spotlist_add_item(spotlist, start_lba, i + from_lba - start_lba, + ret= Xorriso__add_spot(&state, start_lba, i + from_lba - start_lba, prev_quality, 0); if(ret <= 0) goto ex; } - ret= Spotlist_add_item(spotlist, i + from_lba, block_count - i, + ret= Xorriso__add_spot(&state, i + from_lba, block_count - i, Xorriso_read_quality_untesteD, 0); if(ret > 0) ret= 2; @@ -2249,8 +2617,16 @@ abort_check:; } else { data_count= 0; pre_read_time= Sfile_microtime(0); - ret= burn_read_data(drive, ((off_t) (i + from_lba)) * (off_t) 2048, data, - to_read * (off_t) 2048, &data_count, 4 * !retry); + + if(async_md5) { + ret= Xorriso__wait_chunk_md5(&state, 1, 0); + if(ret <= 0) + goto ex; + data_pt= state.chunk[state.chunk_w_idx]; + } + + ret= burn_read_data(drive, ((off_t) (i + from_lba)) * (off_t) 2048, + data_pt, to_read * (off_t) 2048, &data_count, 4 * !retry); post_read_time= Sfile_microtime(0); time_diff= post_read_time - pre_read_time; total_time_diff+= time_diff; @@ -2260,12 +2636,12 @@ abort_check:; if(data_count / 2048 < to_read) { if(data_count > 0 && retry) { if(prev_quality >= 0) { - ret= Spotlist_add_item(spotlist, start_lba, + ret= Xorriso__add_spot(&state, start_lba, i + from_lba - start_lba, prev_quality, 0); if(ret <= 0) goto ex; } - ret= Spotlist_add_item(spotlist, i + from_lba, data_count / 2048, + ret= Xorriso__add_spot(&state, i + from_lba, data_count / 2048, Xorriso_read_quality_partiaL, 0); if(ret <= 0) goto ex; @@ -2289,120 +2665,18 @@ abort_check:; /* MD5 checksumming */ if(ctx != NULL) { - for(j= 0; j < to_read; j++) { - lba= i + j + from_lba; - if(lba < (uint32_t) md5_start) - continue; - ret= 0; - if(lba > (uint32_t) (md5_start) + 16 && - (next_tag == 0 || chain_broken || lba == next_tag)) { - ret= iso_util_decode_md5_tag(data + j * 2048, &tag_type, - &pos, &range_start, &range_size, - &next_tag, tag_md5, !!chain_broken); - } - valid= (ret == 1 || ret == (int) ISO_MD5_AREA_CORRUPTED) && - pos == lba; - if(valid && tag_type == 2 && (lba < ((uint32_t) md5_start) + 32 || - in_track_gap)) { - tag_type_name= "superblock"; - was_sb_tag= 1; - if(in_track_gap && range_start != ((uint32_t) md5_start) && - range_start < lba && lba - range_start <= (uint32_t) j) { - /* Looking for next session : start computing in hindsight. - Session start and superblock tag are supposed to be in the - same 64 kB chunk. - */ - iso_md5_end(&ctx, md5); - ret= iso_md5_start(&ctx); - if(ret < 0) { - Xorriso_no_malloc_memory(xorriso, NULL, 0); - ret= -1; goto ex; - } - iso_md5_compute(&ctx, data + (j - (lba - range_start)) * 2048, - (lba - range_start) * 2048); - md5_start= range_start; - in_track_gap= 0; - } - } else if(valid && tag_type == 4 && lba < 32) { - tag_type_name= "relocated 64kB superblock"; - }else if(valid && tag_type == 3 && was_sb_tag) { - tag_type_name= "tree"; - }else if(valid && tag_type == 1) { + if(async_md5) { + state.chunk_fill[state.chunk_w_idx]= to_read; + state.chunk_lba[state.chunk_w_idx]= i + from_lba; + state.chunk_state[state.chunk_w_idx]= 1; + /* The MD5 thread will call Xorriso_chunk_md5() */ - /* >>> ??? allow this without superblock and tree tag ? */ - - tag_type_name= "session"; - } else { - tag_type_name= ""; - } - if (tag_type_name[0]) { - if(range_start != (uint32_t) md5_start) { - sprintf(xorriso->info_text, - "Found MD5 %s tag which covers different data range", - tag_type_name); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0); - sprintf(xorriso->info_text, - " Expected: %u Found: %u", - (unsigned int) md5_start, range_start); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0); - chain_broken= 1; - valid= 0; - } else { - ret= iso_md5_clone(ctx, &cloned_ctx); - if(ret <= 0) { - Xorriso_no_malloc_memory(xorriso, NULL, 0); - ret= -1; goto ex; - } - iso_md5_end(&cloned_ctx, md5); - - if(ret == (int) ISO_MD5_AREA_CORRUPTED) { - comparison= "CORRUPTED"; - sev_text= "WARNING"; - md5_spot_value= Xorriso_read_quality_md5_mismatcH; - chain_broken= 1; - } else if(! iso_md5_match(tag_md5, md5)) { - comparison= "NON-MATCHING"; - sev_text= "WARNING"; - md5_spot_value= Xorriso_read_quality_md5_mismatcH; - chain_broken= 1; - } else { - comparison= "matching"; - sev_text= "UPDATE"; - md5_spot_value= Xorriso_read_quality_md5_matcH; - } - md5_spot_lba= lba; - sprintf(xorriso->info_text, - "Found %s MD5 %s tag: start=%d size=%d", - comparison, tag_type_name, md5_start, lba - md5_start); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, - sev_text, 0); - } - if(valid && (tag_type == 1 || - (tag_type == 4 && pos == lba && lba < 32))) { - if(md5_spot_value != Xorriso_read_quality_untesteD) { - ret= Spotlist_add_item(spotlist, md5_start, - md5_spot_lba - md5_start, md5_spot_value, 0); - if(ret <= 0) - goto ex; - } - md5_spot_value= Xorriso_read_quality_untesteD; - md5_start = lba + 1; - if (md5_start % 32) - md5_start= md5_start + (32 - (md5_start % 32)); - next_tag= 0; - - iso_md5_end(&ctx, md5); - ret= iso_md5_start(&ctx); - if(ret < 0) { - Xorriso_no_malloc_memory(xorriso, NULL, 0); - ret= -1; goto ex; - } - if(tag_type == 1) - in_track_gap= 1; - continue; - } - } - iso_md5_compute(ctx, data + j * 2048, 2048); + state.chunk_w_idx= (state.chunk_w_idx + 1) % state.num_chunks; + } else { + ret= Xorriso_chunk_md5(xorriso, data_pt, to_read, + (uint32_t) (i + from_lba), &state, 0); + if(ret <= 0) + goto ex; } } @@ -2426,7 +2700,7 @@ failed_to_write:; "FAILURE", 0); {ret= 0; goto ex;} } - ret= write(job->data_to_fd, data, write_amount); + ret= write(job->data_to_fd, data_pt, write_amount); if(ret == -1) goto failed_to_write; } @@ -2434,8 +2708,8 @@ failed_to_write:; } if(quality != prev_quality) { if(prev_quality >= 0) { - ret= Spotlist_add_item(spotlist, start_lba, i + from_lba - start_lba, - prev_quality, 0); + ret= Xorriso__add_spot(&state, start_lba, + i + from_lba - start_lba, prev_quality, 0); if(ret <= 0) goto ex; } @@ -2452,7 +2726,7 @@ failed_to_write:; } } if(prev_quality >= 0) { - ret= Spotlist_add_item(spotlist, start_lba, + ret= Xorriso__add_spot(&state, start_lba, block_count + from_lba - start_lba, prev_quality, 0); if(ret <= 0) goto ex; @@ -2467,28 +2741,48 @@ failed_to_write:; /* MD5 checksumming : register result */ + if(async_md5) { + ret= Xorriso__end_slave_md5(&state, 10000, 0); + if(ret <= 0) + goto ex; + } /* >>> ??? allow chain_broken to be a match ? */ - if(next_tag > 0) { + if(state.next_tag > 0) { sprintf(xorriso->info_text, "Missing announced MD5 tag: start=%d pos=%d", - md5_start, next_tag); + state.md5_start, state.next_tag); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); - md5_spot_value= Xorriso_read_quality_md5_mismatcH; - md5_spot_lba= next_tag; + state.md5_spot_value= Xorriso_read_quality_md5_mismatcH; + state.md5_spot_lba= state.next_tag; } - if(md5_spot_value != Xorriso_read_quality_untesteD) { - ret= Spotlist_add_item(spotlist, md5_start, md5_spot_lba - md5_start, - md5_spot_value, 0); + if(state.md5_spot_value != Xorriso_read_quality_untesteD) { + ret= Xorriso__add_spot(&state, state.md5_start, + state.md5_spot_lba - state.md5_start, state.md5_spot_value, 0); if(ret <= 0) goto ex; } ret= 1; -ex: - if(ctx != NULL) - iso_md5_end(&ctx, md5); +ex:; + if(async_md5) { + Xorriso__end_slave_md5(&state, 10000, 0); + sprintf(xorriso->info_text, + "async_chunks=%d , chunk_size=%d , w_sleeps: %.f , r_sleeps: %.f", + state.num_chunks, read_chunk, (double) state.w_sleeps, + (double) state.r_sleeps); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + if(state.chunk != NULL) + pthread_mutex_destroy(&(state.spot_mutex)); + Xorriso_free_meM(state.chunk); + Xorriso_free_meM(state.chunk_state); + Xorriso_free_meM(state.chunk_fill); + Xorriso_free_meM(state.chunk_lba); + } Xorriso_free_meM(data); + if(state.ctx != NULL) + iso_md5_end(&(state.ctx), md5); + return(ret); } @@ -2519,10 +2813,11 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, if(ret<=0) goto ex; - /* >>> determine medium type dependent blocking factor: - 32 kB for CD (with 2kB retry) and DVD, 64 kB for BD - eventually adjust read_chunk - */; + ret = burn_disc_get_profile(drive, &profile_no, profile_name); + if(ret <= 0) + profile_no= 0; + if(profile_no >= 0x40 && profile_no <= 0x43) /* BD-ROM, BD-R, BD-RE */ + read_chunk= 32; if(job->min_block_size != 0) read_chunk= job->min_block_size; @@ -2568,9 +2863,6 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, ret= burn_get_read_capacity(drive, &read_capacity, 0); if(ret <= 0) read_capacity= -1; - ret = burn_disc_get_profile(drive, &profile_no, profile_name); - if(ret <= 0) - profile_no= 0; if(job->max_lba >= 0) { blocks= job->max_lba + 1 - start_lba; diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index 7857c219..cc10e607 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -9,7 +9,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH XORRISO 1 "Version 1.2.3, Apr 02, 2012" +.TH XORRISO 1 "Version 1.2.3, Mai 01, 2012" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -3549,7 +3549,7 @@ abort_file=/var/opt/xorriso/do_abort_check_media .br sector_map='' map_with_volid=off patch_lba0=off report=blocks .br -bad_limit=valid slow_limit=1.0 chunk_size=0s +bad_limit=valid slow_limit=1.0 chunk_size=0s async_chunks=0 .br Option "reset=now" restores these startup defaults. .br @@ -3657,6 +3657,11 @@ slow. This may be a fractional number like 0.1 or 1.5. \fBchunk_size=size\fR sets the number of bytes to be read in one read operation. This gets rounded down to full blocks of 2048 bytes. 0 means automatic size. +.br +\fBasync_chunks=number\fR +enables asynchronous MD5 processing if number is 2 or larger. +In this case the given number of read chunks is allocated as fifo buffer. +On very fast MMC drives try: chunk_size=32s async_chunks=16. .TP \fB\-check_md5\fR severity iso_rr_path [***] Compare the data content of the given files in the loaded image with their diff --git a/xorriso/xorriso.info b/xorriso/xorriso.info index 2d654131..862f3b69 100644 --- a/xorriso/xorriso.info +++ b/xorriso/xorriso.info @@ -3128,7 +3128,7 @@ transmission errors. time_limit=28800 item_limit=100000 data_to=" event=ALL abort_file=/var/opt/xorriso/do_abort_check_media sector_map=" map_with_volid=off patch_lba0=off report=blocks - bad_limit=valid slow_limit=1.0 chunk_size=0s + bad_limit=valid slow_limit=1.0 chunk_size=0s async_chunks=0 Option "reset=now" restores these startup defaults. Non-default options are: @@ -3224,6 +3224,11 @@ transmission errors. sets the number of bytes to be read in one read operation. This gets rounded down to full blocks of 2048 bytes. 0 means automatic size. + async_chunks=number + enables asynchronous MD5 processing if number is 2 or larger. + In this case the given number of read chunks is allocated as + fifo buffer. On very fast MMC drives try: chunk_size=32s + async_chunks=16. -check_md5 severity iso_rr_path [***] Compare the data content of the given files in the loaded image @@ -4381,8 +4386,8 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top * -cdx sets working directory on disk: Navigate. (line 16) * -changes_pending overrides change status: Writing. (line 13) * -charset sets input/output character set: Charset. (line 43) -* -check_md5 verifies file checksum: Verify. (line 148) -* -check_md5_r verifies file tree checksums: Verify. (line 164) +* -check_md5 verifies file checksum: Verify. (line 153) +* -check_md5_r verifies file tree checksums: Verify. (line 169) * -check_media reads media block by block: Verify. (line 21) * -check_media_defaults sets -check_media options: Verify. (line 41) * -chgrp sets group in ISO image: Manip. (line 50) @@ -4813,8 +4818,8 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top * Verify, compare ISO and disk file, -compare: Navigate. (line 146) * Verify, compare ISO and disk tree, -compare_r: Navigate. (line 159) * Verify, compare ISO and disk, -compare_l: Navigate. (line 164) -* Verify, file checksum, -check_md5: Verify. (line 148) -* Verify, file tree checksums, -check_md5_r: Verify. (line 164) +* Verify, file checksum, -check_md5: Verify. (line 153) +* Verify, file tree checksums, -check_md5_r: Verify. (line 169) * Verify, preset -check_media, -check_media_defaults: Verify. (line 41) * Write, block size, -dvd_obs: SetWrite. (line 265) * Write, bootability, -boot_image: Bootable. (line 26) @@ -4871,32 +4876,32 @@ Node: DialogCtl139832 Node: Inquiry142429 Node: Navigate147295 Node: Verify155556 -Node: Restore164245 -Node: Emulation171154 -Node: Scripting180965 -Node: Frontend188125 -Node: Examples189425 -Node: ExDevices190602 -Node: ExCreate191261 -Node: ExDialog192546 -Node: ExGrowing193811 -Node: ExModifying194616 -Node: ExBootable195120 -Node: ExCharset195672 -Node: ExPseudo196493 -Node: ExCdrecord197391 -Node: ExMkisofs197708 -Node: ExGrowisofs199048 -Node: ExException200183 -Node: ExTime200637 -Node: ExIncBackup201096 -Node: ExRestore205087 -Node: ExRecovery206047 -Node: Files206617 -Node: Seealso207916 -Node: Bugreport208639 -Node: Legal209220 -Node: CommandIdx210150 -Node: ConceptIdx225738 +Node: Restore164522 +Node: Emulation171431 +Node: Scripting181242 +Node: Frontend188402 +Node: Examples189702 +Node: ExDevices190879 +Node: ExCreate191538 +Node: ExDialog192823 +Node: ExGrowing194088 +Node: ExModifying194893 +Node: ExBootable195397 +Node: ExCharset195949 +Node: ExPseudo196770 +Node: ExCdrecord197668 +Node: ExMkisofs197985 +Node: ExGrowisofs199325 +Node: ExException200460 +Node: ExTime200914 +Node: ExIncBackup201373 +Node: ExRestore205364 +Node: ExRecovery206324 +Node: Files206894 +Node: Seealso208193 +Node: Bugreport208916 +Node: Legal209497 +Node: CommandIdx210427 +Node: ConceptIdx226015  End Tag Table diff --git a/xorriso/xorriso.texi b/xorriso/xorriso.texi index a9ba29f4..861c0aba 100644 --- a/xorriso/xorriso.texi +++ b/xorriso/xorriso.texi @@ -50,7 +50,7 @@ @c man .\" First parameter, NAME, should be all caps @c man .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection @c man .\" other parameters are allowed: see man(7), man(1) -@c man .TH XORRISO 1 "Version 1.2.3, Apr 02, 2012" +@c man .TH XORRISO 1 "Version 1.2.3, Mai 01, 2012" @c man .\" Please adjust this date whenever revising the manpage. @c man .\" @c man .\" Some roff macros, for reference: @@ -4199,7 +4199,7 @@ abort_file=/var/opt/xorriso/do_abort_check_media @* sector_map='' map_with_volid=off patch_lba0=off report=blocks @* -bad_limit=valid slow_limit=1.0 chunk_size=0s +bad_limit=valid slow_limit=1.0 chunk_size=0s async_chunks=0 @* Option "reset=now" restores these startup defaults. @* @@ -4309,6 +4309,11 @@ slow. This may be a fractional number like 0.1 or 1.5. @item chunk_size=size sets the number of bytes to be read in one read operation. This gets rounded down to full blocks of 2048 bytes. 0 means automatic size. +@* +@item async_chunks=number +enables asynchronous MD5 processing if number is 2 or larger. +In this case the given number of read chunks is allocated as fifo buffer. +On very fast MMC drives try: chunk_size=32s async_chunks=16. @end table @c man .TP @kindex -check_md5 verifies file checksum diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 2637e0b3..810f5396 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2012.04.28.161532" +#define Xorriso_timestamP "2012.05.01.075022"