From c3822433d020325223dc098393e03131fd91330b Mon Sep 17 00:00:00 2001 From: Ralph Ronnquist Date: Wed, 10 Aug 2022 20:58:29 +1000 Subject: [PATCH] bug fixing overlay option --- fusefile.c | 151 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 113 insertions(+), 38 deletions(-) diff --git a/fusefile.c b/fusefile.c index 99424c5..f74632a 100644 --- a/fusefile.c +++ b/fusefile.c @@ -45,6 +45,7 @@ struct Source { ssize_t to; ssize_t start; // starting position in concatenated file int fd; + int dirty; }; static struct { @@ -69,6 +70,8 @@ static struct { size_t limit; } overlay; +static void usage(); + #define FRAG(m) (overlay.table+m) #define BEG(m) (FRAG(m)->pos) #define END(m) (FRAG(m)->pos + FRAG(m)->size) @@ -102,6 +105,10 @@ static void overlay_save_count() { size -= n; p += n; } + if ( overlay.source.dirty++ > 1000 ) { + fsync( overlay.source.fd ); + overlay.source.dirty = 0; + } } static void overlay_save_table(size_t lo,size_t hi) { @@ -122,6 +129,10 @@ static void overlay_save_table(size_t lo,size_t hi) { size -= n; p += n; } + if ( overlay.source.dirty++ > 1000 ) { + fsync( overlay.source.fd ); + overlay.source.dirty = 0; + } } static void overlay_insert(size_t p,off_t pos,size_t size) { @@ -150,28 +161,77 @@ static void overlay_delete(size_t p) { } static void overlay_mark(off_t pos,size_t size) { +#if DEBUG + fprintf( stderr, "overlay_mark( %ld, %ld )\n", pos, size ); +#endif + int deleted = 0; + ssize_t q; ssize_t p = overlay_prior_fragment( pos ); + // p is the nearest region below pos (or -1) if ( p >= 0 && pos <= END(p) ) { - // Merge new marks with fragment p + // p overlaps mark region + if ( END(p) >= pos + size ) { +#if DEBUG + fprintf( stderr, "overlay size 1( %ld )\n", FRAG(p)->size ); +#endif + return; // new mark within existing. + } + // new mark region extends existing FRAG(p)->size = pos + size - BEG(p); - if ( p+1 < overlay.count && BEG(p+1) <= END(p) ) { - FRAG(p)->size = END(p+1) - BEG(p); - overlay_delete( p+1 ); - overlay_save_table( p, overlay.count ); - } else { - overlay_save_table( p, p+1 ); + q = p+1; + while ( q < overlay.count && BEG(q) <= END(p) ) { + if ( END(q) > END(p) ) { + FRAG(p)->size = END(q) - BEG(p); + } + overlay_delete( q ); + deleted++; } + overlay_save_table( p, deleted? overlay.count : q ); +#if DEBUG + fprintf( stderr, "overlay size 2( %ld ) deleted %d\n", + FRAG(p)->size, deleted ); +#endif return; } - p++; // index of subsequent fragment - if ( p < overlay.count && BEG(p) < pos + size ) { - // Merge new marks with pragment p+1 - FRAG(p)->size = END(p) - pos; - FRAG(p)->pos = pos; - overlay_save_table( p, p+1 ); - } else { + // The region p does not expand into new mark region + p++; // subsequent region + if ( p >= overlay.count || BEG(p) > pos + size ) { + // New mark is separate region at p overlay_insert( p, pos, size); +#if DEBUG + fprintf( stderr, "overlay size 4( %ld )\n", FRAG(p)->size ); +#endif overlay_save_table( p, overlay.count ); + return; + } + // New marks start before and overlap with the region + if ( BEG(p) + FRAG(p)->size < pos + size ) { + FRAG(p)->size = size; // new mark covers old region + } else { + FRAG(p)->size += BEG(p) - pos; + } + BEG(p) = pos; + q = p+1; + while ( q < overlay.count && BEG(q) <= END(p) ) { + if ( END(q) > END(p) ) { + FRAG(p)->size = END(q) - BEG(p); + } + overlay_delete( q ); + deleted++; + } + overlay_save_table( p, deleted? overlay.count : q ); +#if DEBUG + fprintf( stderr, "overlay size 4( %ld ) deleted %d\n", + FRAG(p)->size, deleted ); +#endif +} + +static void setup_overlay(char *filename) { + overlay.source.filename = filename; + overlay.source.fd = open( filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ); + if ( overlay.source.fd < 0 ) { + perror( filename ); + usage(); } } @@ -188,17 +248,6 @@ static int RANGE(int s,int n ) { return ( s == n ) && *(range+c) == 0; } -static void usage(); - -static void setup_overlay(char *filename) { - overlay.source.filename = filename; - overlay.source.fd = open( filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ); - if ( overlay.source.fd < 0 ) { - perror( filename ); - usage(); - } -} - static int setup_sources(char **argv,int i,int n) { sources.array = calloc( n, sizeof( struct Source ) ); if ( sources.array == 0 ) { @@ -428,6 +477,10 @@ static int fusefile_read(const char *path, char *buf, size_t size, if ( n > size ) { n = size; } + if ( sources.array[i].dirty ) { + fsync( sources.array[i].fd ); + sources.array[i].dirty = 0; + } #if DEBUG fprintf( stderr, " seek fd=%d to %ld\n", sources.array[i].fd, b ); #endif @@ -440,12 +493,6 @@ static int fusefile_read(const char *path, char *buf, size_t size, n, sources.array[i].fd ); #endif ssize_t r = read( sources.array[i].fd, buf + rr, n ); - if ( overlay.source.filename ) { - int x = overlay_merge( buf + rr, off + rr, r ); - if ( x ) { - return x; - } - } #if DEBUG fprintf( stderr, " got %ld bytes\n", r ); #endif @@ -456,6 +503,16 @@ static int fusefile_read(const char *path, char *buf, size_t size, if ( r == 0 ) { break; } + if ( overlay.source.filename ) { + if ( overlay.source.dirty ) { + fsync( overlay.source.fd ); + overlay.source.dirty = 0; + } + int x = overlay_merge( buf + rr, off + rr, r ); + if ( x ) { + return x; + } + } rr += r; off += r; size -= r; @@ -516,18 +573,16 @@ static int write_block(off_t off,const char *buf,size_t size) { #if DEBUG fprintf( stderr, "write_block( %ld, ?, %ld )\n", off, size ); #endif + if ( overlay.source.filename ) { + overlay_mark( off, size ); // Mark region as written + } while ( size > 0 ) { int index = find_source( off ); // index of source file if ( index < 0 ) { return -EIO; // past EOF } - struct Source *source; - if ( overlay.source.filename ) { - source = &overlay.source; - overlay_mark( off, size ); // Mark region as written - } else { - source = &sources.array[ index ]; - } + struct Source *source = overlay.source.filename? + &overlay.source : &sources.array[ index ]; off_t from = off - source->start + source->from; off_t max = source->to - from; if ( lseek( source->fd, from, SEEK_SET ) < 0 ) { @@ -545,6 +600,10 @@ static int write_block(off_t off,const char *buf,size_t size) { size -= n; off += n; } + if ( source->dirty++ >= 1000 ) { + fsync( source->fd ); + source->dirty = 0; + } } return 0; } @@ -608,6 +667,20 @@ static void fusefile_destroy(void *data) { } } +static void fsync_all_dirty() { + int i = 0; + for ( ; i < sources.count; i++ ) { + if ( sources.array[i].dirty ) { + fsync( sources.array[i].fd ); + sources.array[i].dirty = 0; + } + } + if ( overlay.source.filename && overlay.source.dirty ) { + fsync( overlay.source.fd ); + overlay.source.dirty = 0; + } +} + static int fusefile_flush(const char *path, struct fuse_file_info *info) { #if DEBUG fprintf( stderr, "fusefile_flush( %s )\n", path ); @@ -615,6 +688,7 @@ static int fusefile_flush(const char *path, struct fuse_file_info *info) { if ( strcmp( path, "/" ) != 0 ) { return -ENOENT; } + fsync_all_dirty(); return 0; } @@ -635,6 +709,7 @@ static int fusefile_fsync(const char *path, int x, struct fuse_file_info *fi) { if ( strcmp( path, "/" ) != 0 ) { return -ENOENT; } + fsync_all_dirty(); return 0; } -- 2.39.2