From ffd0fddad2117675ffb80a4bb0da4c0e5d0a3112 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Tue, 24 Mar 2009 17:06:07 -0500 Subject: [svn-r16609] Bug fix (#1161): When a family file created with v1.6 library is opened and closed with v1.8 library, v1.8 library writes the driver info block in the superblock. But v1.6 doesn't write it. This caused the data after the superblock to be overwritten. The solution is to use a flag to indicate when the original file doesn't have the driver info, v1.8 library doesn't write it either. Tested on jam. I have some trouble to access smirom and linew using h5committest. --- src/H5F.c | 1 + src/H5FDfamily.c | 17 ++++++++++++----- src/H5Fpkg.h | 1 + src/H5Fsuper.c | 12 +++++++++++- test/family_v16_00000.h5 | Bin 5120 -> 5120 bytes test/mount.c | 1 + test/vfd.c | 25 ++++++++++++++++++++++++- 7 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/H5F.c b/src/H5F.c index e7b4cd3..6ca852a 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -891,6 +891,7 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) for(u = 0; u < NELMTS(f->shared->fs_addr); u++) f->shared->fs_addr[u] = HADDR_UNDEF; f->shared->driver_addr = HADDR_UNDEF; + f->shared->write_driver = TRUE; f->shared->accum.loc = HADDR_UNDEF; f->shared->lf = lf; diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index cfad5e3..1d508dc 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -626,8 +626,15 @@ H5FD_family_sb_encode(H5FD_t *_file, char *name/*out*/, unsigned char *buf/*out* HDstrncpy(name, "NCSAfami", (size_t)8); name[8] = '\0'; - /* Store member file size */ - UINT64ENCODE(buf, (uint64_t)file->memb_size); + /* Store member file size. Use the member file size from the property here. + * This is to guarantee backward compatibility. If a file is created with + * v1.6 library and the driver info isn't saved in the superblock. We open + * it with v1.8, the FILE->MEMB_SIZE will be the actual size of the first + * member file (see H5FD_family_open). So it isn't safe to use FILE->MEMB_SIZE. + * If the file is created with v1.8, the correctness of FILE->PMEM_SIZE is + * checked in H5FD_family_sb_decode. SLU - 2009/3/21 + */ + UINT64ENCODE(buf, (uint64_t)file->pmem_size); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5FD_family_sb_encode() */ @@ -668,9 +675,9 @@ H5FD_family_sb_decode(H5FD_t *_file, const char UNUSED *name, const unsigned cha /* For h5repart only. Private property of new member size is used to signal * h5repart is being used to change member file size. h5repart will open * files for read and write. When the files are closed, metadata will be - * flushed to the files and updated this new size */ + * flushed to the files and updated to this new size */ if(file->mem_newsize) { - file->memb_size = file->mem_newsize; + file->memb_size = file->pmem_size = file->mem_newsize; HGOTO_DONE(ret_value) } /* end if */ @@ -682,7 +689,7 @@ H5FD_family_sb_decode(H5FD_t *_file, const char UNUSED *name, const unsigned cha if(msize != file->pmem_size) { char err_msg[128]; - sprintf(err_msg, "family member size should be %lu, is %lu", (unsigned long)msize, (unsigned long)file->pmem_size); + sprintf(err_msg, "Family member size should be %lu. But the size from file access property is %lu", (unsigned long)msize, (unsigned long)file->pmem_size); HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, err_msg) } /* end if */ diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 4080705..6434017 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -134,6 +134,7 @@ typedef struct H5F_file_t { unsigned sohm_vers; /* Version of shared message table on disk */ unsigned sohm_nindexes; /* Number of shared messages indexes in the table */ haddr_t driver_addr; /* File driver information block address*/ + hbool_t write_driver; /* Whether to write file driver block in the superblock */ unsigned long feature_flags; /* VFL Driver feature Flags */ haddr_t maxaddr; /* Maximum address for file */ diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index 70e0954..69c7a8d 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -466,6 +466,16 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) if(H5FD_sb_decode(lf, drv_name, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to decode driver information") } /* end if */ + else + /* This flag is false only if a file was created with v1.6 library or + * before and no driver info was saved in the superblock. When the file is + * closed and superblock is written to the file, v1.8 library or after + * doesn't write the driver info in the superblock. Otherwise, the newly + * added driver block will overwrite the (meta)data right after the + * superblock. SLU - 2009/3/24 + */ + shared->write_driver = FALSE; + } /* end if */ else { haddr_t root_addr; /* Address of root group */ @@ -934,7 +944,7 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id) /* Encode the driver information block. */ H5_ASSIGN_OVERFLOW(driver_size, H5FD_sb_size(f->shared->lf), hsize_t, size_t); - if(driver_size > 0) { + if(driver_size > 0 && f->shared->write_driver) { char driver_name[9]; /* Name of driver, for driver info block */ uint8_t *dbuf = p; /* Pointer to beginning of driver info */ diff --git a/test/family_v16_00000.h5 b/test/family_v16_00000.h5 index 5b69c93..bf1a711 100644 Binary files a/test/family_v16_00000.h5 and b/test/family_v16_00000.h5 differ diff --git a/test/mount.c b/test/mount.c index 14ab346..f358634 100644 --- a/test/mount.c +++ b/test/mount.c @@ -502,6 +502,7 @@ test_assoc(hid_t fapl) * of file2. */ if(H5Oget_info_by_name(file1, "/mnt1", &oi2, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + if(oi1.fileno != oi2.fileno || H5F_addr_ne(oi1.addr, oi2.addr)) { H5_FAILED(); puts(" Association failed."); diff --git a/test/vfd.c b/test/vfd.c index 310b931..3e792cc 100644 --- a/test/vfd.c +++ b/test/vfd.c @@ -802,6 +802,8 @@ static herr_t test_family_compat(void) { hid_t file = (-1), fapl; + hid_t dset; + char dname[]="dataset"; char filename[1024]; char pathname[1024]; char *srcdir = getenv("srcdir"); /*where the src code is located*/ @@ -824,7 +826,28 @@ test_family_compat(void) } HDstrcat(pathname, filename); - if((file = H5Fopen(pathname, H5F_ACC_RDONLY, fapl)) < 0) + /* Make sure we can open the file. Use the read and write mode to flush the + * superblock. */ + if((file = H5Fopen(pathname, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR; + + if((dset = H5Dopen(file, dname, H5P_DEFAULT)) < 0) + TEST_ERROR; + + if(H5Dclose(dset) < 0) + TEST_ERROR; + + if(H5Fclose(file) < 0) + TEST_ERROR; + + /* Open the file again to make sure it isn't corrupted. */ + if((file = H5Fopen(pathname, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR; + + if((dset = H5Dopen(file, dname, H5P_DEFAULT)) < 0) + TEST_ERROR; + + if(H5Dclose(dset) < 0) TEST_ERROR; if(H5Fclose(file) < 0) -- cgit v0.12