Line | Count | Source |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /****************/ |
14 | | /* Module Setup */ |
15 | | /****************/ |
16 | | |
17 | | #include "H5Fmodule.h" /* This source code file is part of the H5F module */ |
18 | | |
19 | | /***********/ |
20 | | /* Headers */ |
21 | | /***********/ |
22 | | #include "H5private.h" /* Generic Functions */ |
23 | | #include "H5ACprivate.h" /* Metadata cache */ |
24 | | #include "H5Eprivate.h" /* Error handling */ |
25 | | #include "H5Fpkg.h" /* File access */ |
26 | | #include "H5FDprivate.h" /* File drivers */ |
27 | | #include "H5FLprivate.h" /* Free Lists */ |
28 | | #include "H5Iprivate.h" /* IDs */ |
29 | | #include "H5MFprivate.h" /* File memory management */ |
30 | | #include "H5MMprivate.h" /* Memory management */ |
31 | | #include "H5Pprivate.h" /* Property lists */ |
32 | | #include "H5SMprivate.h" /* Shared Object Header Messages */ |
33 | | |
34 | | /****************/ |
35 | | /* Local Macros */ |
36 | | /****************/ |
37 | | |
38 | | /******************/ |
39 | | /* Local Typedefs */ |
40 | | /******************/ |
41 | | |
42 | | /********************/ |
43 | | /* Package Typedefs */ |
44 | | /********************/ |
45 | | |
46 | | /********************/ |
47 | | /* Local Prototypes */ |
48 | | /********************/ |
49 | | static herr_t H5F__super_ext_create(H5F_t *f, H5O_loc_t *ext_ptr); |
50 | | static herr_t H5F__update_super_ext_driver_msg(H5F_t *f); |
51 | | |
52 | | /*********************/ |
53 | | /* Package Variables */ |
54 | | /*********************/ |
55 | | |
56 | | /*****************************/ |
57 | | /* Library Private Variables */ |
58 | | /*****************************/ |
59 | | |
60 | | /* Declare a free list to manage the H5F_super_t struct */ |
61 | | H5FL_DEFINE(H5F_super_t); |
62 | | |
63 | | /*******************/ |
64 | | /* Local Variables */ |
65 | | /*******************/ |
66 | | |
67 | | /* Format version bounds for superblock */ |
68 | | static const unsigned HDF5_superblock_ver_bounds[] = { |
69 | | HDF5_SUPERBLOCK_VERSION_DEF, /* H5F_LIBVER_EARLIEST */ |
70 | | HDF5_SUPERBLOCK_VERSION_2, /* H5F_LIBVER_V18 */ |
71 | | HDF5_SUPERBLOCK_VERSION_3, /* H5F_LIBVER_V110 */ |
72 | | HDF5_SUPERBLOCK_VERSION_3, /* H5F_LIBVER_V112 */ |
73 | | HDF5_SUPERBLOCK_VERSION_3, /* H5F_LIBVER_V114 */ |
74 | | HDF5_SUPERBLOCK_VERSION_3, /* H5F_LIBVER_V200 */ |
75 | | HDF5_SUPERBLOCK_VERSION_LATEST /* H5F_LIBVER_LATEST */ |
76 | | }; |
77 | | |
78 | | /*------------------------------------------------------------------------- |
79 | | * Function: H5F__super_ext_create |
80 | | * |
81 | | * Purpose: Create the superblock extension |
82 | | * |
83 | | * Return: Success: non-negative on success |
84 | | * Failure: Negative |
85 | | * |
86 | | *------------------------------------------------------------------------- |
87 | | */ |
88 | | static herr_t |
89 | | H5F__super_ext_create(H5F_t *f, H5O_loc_t *ext_ptr) |
90 | 53 | { |
91 | 53 | herr_t ret_value = SUCCEED; /* Return value */ |
92 | | |
93 | 53 | FUNC_ENTER_PACKAGE |
94 | | |
95 | | /* Sanity check */ |
96 | 53 | assert(f); |
97 | 53 | assert(f->shared); |
98 | 53 | assert(f->shared->sblock); |
99 | 53 | assert(!H5_addr_defined(f->shared->sblock->ext_addr)); |
100 | 53 | assert(ext_ptr); |
101 | | |
102 | | /* Check for older version of superblock format that can't support superblock extensions */ |
103 | 53 | if (f->shared->sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) |
104 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, |
105 | 53 | "superblock extension not permitted with version %u of superblock", |
106 | 53 | f->shared->sblock->super_vers); |
107 | 53 | else if (H5_addr_defined(f->shared->sblock->ext_addr)) |
108 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "superblock extension already exists?!?!"); |
109 | 53 | else { |
110 | | /* The superblock extension isn't actually a group, but the |
111 | | * default group creation list should work fine. |
112 | | * If we don't supply a size for the object header, HDF5 will |
113 | | * allocate H5O_MIN_SIZE by default. This is currently |
114 | | * big enough to hold the biggest possible extension, but should |
115 | | * be tuned if more information is added to the superblock |
116 | | * extension. |
117 | | */ |
118 | 53 | H5O_loc_reset(ext_ptr); |
119 | 53 | if (H5O_create(f, (size_t)0, (size_t)1, H5P_GROUP_CREATE_DEFAULT, ext_ptr) < 0) |
120 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "unable to create superblock extension"); |
121 | | |
122 | | /* Record the address of the superblock extension */ |
123 | 53 | f->shared->sblock->ext_addr = ext_ptr->addr; |
124 | 53 | } /* end else */ |
125 | | |
126 | 53 | done: |
127 | 53 | FUNC_LEAVE_NOAPI(ret_value) |
128 | 53 | } /* H5F__super_ext_create() */ |
129 | | |
130 | | /*------------------------------------------------------------------------- |
131 | | * Function: H5F__super_ext_open |
132 | | * |
133 | | * Purpose: Open an existing superblock extension |
134 | | * |
135 | | * Return: Success: non-negative on success |
136 | | * Failure: Negative |
137 | | * |
138 | | *------------------------------------------------------------------------- |
139 | | */ |
140 | | herr_t |
141 | | H5F__super_ext_open(H5F_t *f, haddr_t ext_addr, H5O_loc_t *ext_ptr) |
142 | 1.48k | { |
143 | 1.48k | herr_t ret_value = SUCCEED; /* Return value */ |
144 | | |
145 | 1.48k | FUNC_ENTER_PACKAGE |
146 | | |
147 | | /* Sanity check */ |
148 | 1.48k | assert(f); |
149 | 1.48k | assert(H5_addr_defined(ext_addr)); |
150 | 1.48k | assert(ext_ptr); |
151 | | |
152 | | /* Set up "fake" object location for superblock extension */ |
153 | 1.48k | H5O_loc_reset(ext_ptr); |
154 | 1.48k | ext_ptr->file = f; |
155 | 1.48k | ext_ptr->addr = ext_addr; |
156 | | |
157 | | /* Open the superblock extension object header */ |
158 | 1.48k | if (H5O_open(ext_ptr) < 0) |
159 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open superblock extension"); |
160 | | |
161 | 1.48k | done: |
162 | 1.48k | FUNC_LEAVE_NOAPI(ret_value) |
163 | 1.48k | } /* H5F__super_ext_open() */ |
164 | | |
165 | | /*------------------------------------------------------------------------- |
166 | | * Function: H5F__super_ext_close |
167 | | * |
168 | | * Purpose: Close superblock extension |
169 | | * |
170 | | * Return: Success: non-negative on success |
171 | | * Failure: Negative |
172 | | * |
173 | | *------------------------------------------------------------------------- |
174 | | */ |
175 | | herr_t |
176 | | H5F__super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr, bool was_created) |
177 | 584 | { |
178 | 584 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
179 | 584 | herr_t ret_value = SUCCEED; /* Return value */ |
180 | | |
181 | 584 | FUNC_ENTER_PACKAGE |
182 | | |
183 | | /* Sanity check */ |
184 | 584 | assert(f); |
185 | 584 | assert(ext_ptr); |
186 | | |
187 | | /* Check if extension was created */ |
188 | 584 | if (was_created) { |
189 | | /* Set the ring type in the API context */ |
190 | 53 | H5AC_set_ring(H5AC_RING_SBE, &orig_ring); |
191 | | |
192 | | /* Increment link count on superblock extension's object header */ |
193 | 53 | if (H5O_link(ext_ptr, 1) < 0) |
194 | 0 | HGOTO_ERROR(H5E_FILE, H5E_LINKCOUNT, FAIL, "unable to increment hard link count"); |
195 | | |
196 | | /* Decrement refcount on superblock extension's object header in memory */ |
197 | 53 | if (H5O_dec_rc_by_loc(ext_ptr) < 0) |
198 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "unable to decrement refcount on superblock extension"); |
199 | 53 | } /* end if */ |
200 | | |
201 | | /* Twiddle the number of open objects to avoid closing the file. */ |
202 | 584 | f->nopen_objs++; |
203 | 584 | if (H5O_close(ext_ptr, NULL) < 0) |
204 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close superblock extension"); |
205 | 584 | f->nopen_objs--; |
206 | | |
207 | 584 | done: |
208 | | /* Reset the ring in the API context */ |
209 | 584 | if (orig_ring != H5AC_RING_INV) |
210 | 53 | H5AC_set_ring(orig_ring, NULL); |
211 | | |
212 | 584 | FUNC_LEAVE_NOAPI(ret_value) |
213 | 584 | } /* H5F__super_ext_close() */ |
214 | | |
215 | | /*------------------------------------------------------------------------- |
216 | | * Function: H5F__update_super_ext_driver_msg |
217 | | * |
218 | | * Purpose: Update the superblock extension file driver info message if |
219 | | * we are using a V 2 superblock. Observe that the function |
220 | | * is a NO-OP if the file driver info message does not exist. |
221 | | * This is necessary, as the function is called whenever the |
222 | | * EOA is updated, and were it to create the file driver info |
223 | | * message, it would find itself in an infinite recursion. |
224 | | * |
225 | | * Return: Success: SUCCEED |
226 | | * Failure: FAIL |
227 | | * |
228 | | *------------------------------------------------------------------------- |
229 | | */ |
230 | | static herr_t |
231 | | H5F__update_super_ext_driver_msg(H5F_t *f) |
232 | 0 | { |
233 | 0 | H5F_super_t *sblock; /* Pointer to the super block */ |
234 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
235 | |
|
236 | 0 | FUNC_ENTER_PACKAGE |
237 | | |
238 | | /* Sanity check */ |
239 | 0 | assert(f); |
240 | 0 | assert(f->shared); |
241 | 0 | sblock = f->shared->sblock; |
242 | 0 | assert(sblock); |
243 | 0 | assert(sblock->cache_info.type == H5AC_SUPERBLOCK); |
244 | | |
245 | | /* Update the driver information message in the superblock extension |
246 | | * if appropriate. |
247 | | */ |
248 | 0 | if (sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2) { |
249 | 0 | if (H5_addr_defined(sblock->ext_addr)) { |
250 | | /* Check for ignoring the driver info for this file */ |
251 | 0 | if (!H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO)) { |
252 | 0 | size_t driver_size; /* Size of driver info block (bytes)*/ |
253 | | |
254 | | /* Check for driver info */ |
255 | 0 | H5_CHECKED_ASSIGN(driver_size, size_t, H5FD_sb_size(f->shared->lf), hsize_t); |
256 | | |
257 | | /* Nothing to do unless there is both driver info and |
258 | | * the driver info superblock extension message has |
259 | | * already been created. |
260 | | */ |
261 | 0 | if (driver_size > 0) { |
262 | 0 | H5O_drvinfo_t drvinfo; /* Driver info */ |
263 | 0 | uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Driver info block encoding buffer */ |
264 | | |
265 | | /* Sanity check */ |
266 | 0 | assert(driver_size <= H5F_MAX_DRVINFOBLOCK_SIZE); |
267 | | |
268 | | /* Encode driver-specific data */ |
269 | 0 | if (H5FD_sb_encode(f->shared->lf, drvinfo.name, dbuf) < 0) |
270 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information"); |
271 | | |
272 | | /* Write the message to the superblock extension. |
273 | | * |
274 | | * Note that the superblock extension and the |
275 | | * file driver info message must already exist. |
276 | | */ |
277 | 0 | drvinfo.len = driver_size; |
278 | 0 | drvinfo.buf = dbuf; |
279 | 0 | if (H5F__super_ext_write_msg(f, H5O_DRVINFO_ID, &drvinfo, false, H5O_MSG_NO_FLAGS_SET) < |
280 | 0 | 0) |
281 | 0 | HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, |
282 | 0 | "unable to update driver info header message"); |
283 | 0 | } /* end if driver_size > 0 */ |
284 | 0 | } /* end if !H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO) */ |
285 | 0 | } /* end if superblock extension exists */ |
286 | 0 | } /* end if sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2 */ |
287 | | |
288 | 0 | done: |
289 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
290 | 0 | } /* end H5F__update_super_ext_driver_msg() */ |
291 | | |
292 | | /*------------------------------------------------------------------------- |
293 | | * Function: H5F__super_read |
294 | | * |
295 | | * Purpose: Reads the superblock from the file or from the BUF. If |
296 | | * ADDR is a valid address, then it reads it from the file. |
297 | | * If not, then BUF must be non-NULL for it to read from the |
298 | | * BUF. |
299 | | * |
300 | | * Return: Success: SUCCEED |
301 | | * Failure: FAIL |
302 | | * |
303 | | *------------------------------------------------------------------------- |
304 | | */ |
305 | | herr_t |
306 | | H5F__super_read(H5F_t *f, H5P_genplist_t *fa_plist, bool initial_read) |
307 | 1.93k | { |
308 | 1.93k | H5AC_ring_t orig_ring = H5AC_RING_INV; |
309 | 1.93k | H5F_super_t *sblock = NULL; /* Superblock structure */ |
310 | 1.93k | H5F_superblock_cache_ud_t udata; /* User data for cache callbacks */ |
311 | 1.93k | H5P_genplist_t *c_plist; /* File creation property list */ |
312 | 1.93k | H5FD_t *file; /* File driver pointer */ |
313 | 1.93k | unsigned sblock_flags = H5AC__NO_FLAGS_SET; /* flags used in superblock unprotect call */ |
314 | 1.93k | haddr_t super_addr = HADDR_UNDEF; /* Absolute address of superblock */ |
315 | 1.93k | haddr_t eof; /* End of file address */ |
316 | 1.93k | unsigned rw_flags; /* Read/write permissions for file */ |
317 | 1.93k | bool skip_eof_check = false; /* Whether to skip checking the EOF value */ |
318 | | #ifdef H5_HAVE_PARALLEL |
319 | | int mpi_size = 1; |
320 | | #endif /* H5_HAVE_PARALLEL */ |
321 | 1.93k | herr_t ret_value = SUCCEED; /* Return value */ |
322 | | |
323 | 1.93k | FUNC_ENTER_PACKAGE_TAG(H5AC__SUPERBLOCK_TAG) |
324 | | |
325 | | /* initialize the drvinfo to NULL -- we will overwrite this if there |
326 | | * is a driver information block |
327 | | */ |
328 | 1.93k | f->shared->drvinfo = NULL; |
329 | | |
330 | | /* Set up file driver I/O info */ |
331 | 1.93k | file = f->shared->lf; |
332 | | |
333 | | /* Find the superblock */ |
334 | | #ifdef H5_HAVE_PARALLEL |
335 | | if (H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) |
336 | | if ((mpi_size = H5F_mpi_get_size(f)) < 0) |
337 | | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve MPI communicator size"); |
338 | | |
339 | | /* If we are an MPI application with at least two processes, the |
340 | | * following superblock signature location optimization is applicable. |
341 | | * |
342 | | * Note: For parallel applications which don't setup for using the |
343 | | * HDF5 MPIO driver, we will arrive here with mpi_size == 1. |
344 | | * This occurs because of the variable initialization (above) and the |
345 | | * fact that we have skipped actually calling MPI functions to determine |
346 | | * our MPI rank and size. |
347 | | */ |
348 | | if (mpi_size > 1) { |
349 | | MPI_Comm this_comm; |
350 | | int mpi_rank; |
351 | | int mpi_result; |
352 | | |
353 | | /* Sanity check */ |
354 | | assert(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)); |
355 | | |
356 | | /* Set up MPI info */ |
357 | | if ((mpi_rank = H5F_mpi_get_rank(f)) < 0) |
358 | | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "Can't get MPI rank"); |
359 | | if (MPI_COMM_NULL == (this_comm = H5F_mpi_get_comm(f))) |
360 | | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get MPI communicator"); |
361 | | |
362 | | /* Search for the file's signature only with rank 0 process */ |
363 | | if (0 == mpi_rank) { |
364 | | /* Try detecting file's signature */ |
365 | | /* (Don't leave before Bcast, to avoid hang on error) */ |
366 | | H5E_PAUSE_ERRORS |
367 | | { |
368 | | H5FD_locate_signature(file, &super_addr); |
369 | | } |
370 | | H5E_RESUME_ERRORS |
371 | | } /* end if */ |
372 | | |
373 | | /* Broadcast superblock address to other processes */ |
374 | | if (MPI_SUCCESS != (mpi_result = MPI_Bcast(&super_addr, sizeof(super_addr), MPI_BYTE, 0, this_comm))) |
375 | | HMPI_GOTO_ERROR(FAIL, "MPI_Bcast failed", mpi_result) |
376 | | } /* end if */ |
377 | | else { |
378 | | /* Locate the signature as per per the serial library */ |
379 | | #endif /* H5_HAVE_PARALLEL */ |
380 | | |
381 | 1.93k | if (H5FD_locate_signature(file, &super_addr) < 0) |
382 | 0 | HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to locate file signature"); |
383 | | |
384 | | #ifdef H5_HAVE_PARALLEL |
385 | | } /* end else */ |
386 | | #endif /* H5_HAVE_PARALLEL */ |
387 | 1.93k | if (!H5_addr_defined(super_addr)) |
388 | 30 | HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "file signature not found"); |
389 | | |
390 | | /* Check for userblock present */ |
391 | 1.90k | if (H5_addr_gt(super_addr, 0)) { |
392 | | /* Set the base address for the file in the VFD now */ |
393 | 4 | if (H5F__set_base_addr(f, super_addr) < 0) |
394 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "failed to set base address for file driver"); |
395 | 4 | } /* end if */ |
396 | | |
397 | | /* Determine file intent for superblock protect */ |
398 | | |
399 | | /* Must tell cache at protect time that the super block is to be |
400 | | * flushed last (and collectively in the parallel case). |
401 | | */ |
402 | 1.90k | rw_flags = H5AC__FLUSH_LAST_FLAG; |
403 | | #ifdef H5_HAVE_PARALLEL |
404 | | rw_flags |= H5C__FLUSH_COLLECTIVELY_FLAG; |
405 | | #endif /* H5_HAVE_PARALLEL */ |
406 | 1.90k | if (!(H5F_INTENT(f) & H5F_ACC_RDWR)) |
407 | 0 | rw_flags |= H5AC__READ_ONLY_FLAG; |
408 | | |
409 | | /* Get the shared file creation property list */ |
410 | 1.90k | if (NULL == (c_plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id))) |
411 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "can't get property list"); |
412 | | |
413 | | /* Make certain we can read the fixed-size portion of the superblock */ |
414 | 1.90k | if (H5F__set_eoa(f, H5FD_MEM_SUPER, (haddr_t)H5F_SUPERBLOCK_SPEC_READ_SIZE) < 0) |
415 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "set end of space allocation request failed"); |
416 | | |
417 | | /* Set up the user data for cache callbacks */ |
418 | 1.90k | udata.f = f; |
419 | 1.90k | udata.ignore_drvrinfo = H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO); |
420 | 1.90k | udata.sym_leaf_k = 0; |
421 | 1.90k | if (H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, udata.btree_k) < 0) |
422 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes"); |
423 | 1.90k | udata.stored_eof = HADDR_UNDEF; |
424 | 1.90k | udata.drvrinfo_removed = false; |
425 | | |
426 | | /* Set the ring type in the API context */ |
427 | 1.90k | H5AC_set_ring(H5AC_RING_SB, &orig_ring); |
428 | | |
429 | | /* Look up the superblock */ |
430 | 1.90k | if (NULL == (sblock = (H5F_super_t *)H5AC_protect(f, H5AC_SUPERBLOCK, (haddr_t)0, &udata, rw_flags))) |
431 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTPROTECT, FAIL, "unable to load superblock"); |
432 | | |
433 | | /* |
434 | | * When opening a file with SWMR-write access, the library will check to |
435 | | * ensure that: |
436 | | * --superblock version 3 is used |
437 | | * --superblock version does not exceed the version allowed by high bound |
438 | | * --upgrade low_bound to at least V110 |
439 | | * Otherwise fail file open for SMWR-write access |
440 | | * |
441 | | * Upgrading low_bound will give the best format versions available for |
442 | | * that superblock version. Due to the possible upgrade, the fapl returned |
443 | | * from H5Fget_access_plist() might indicate a low_bound higher than what |
444 | | * the user originally set. |
445 | | * |
446 | | * For details, please see RFC:Setting Bounds for Object Creation in HDF5 1.10.0. |
447 | | */ |
448 | 1.90k | if (H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) { |
449 | 0 | if (sblock->super_vers < HDF5_SUPERBLOCK_VERSION_3) |
450 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "superblock version for SWMR is less than 3"); |
451 | 0 | if (sblock->super_vers > HDF5_superblock_ver_bounds[f->shared->high_bound]) |
452 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "superblock version exceeds high bound"); |
453 | 0 | f->shared->low_bound = MAX(H5F_LIBVER_V110, f->shared->low_bound); |
454 | 0 | } |
455 | | |
456 | | /* Pin the superblock in the cache */ |
457 | 1.90k | if (H5AC_pin_protected_entry(sblock) < 0) |
458 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTPIN, FAIL, "unable to pin superblock"); |
459 | | |
460 | | /* Mark the superblock dirty if it was modified during loading */ |
461 | 1.90k | if (((rw_flags & H5AC__READ_ONLY_FLAG) == 0) && udata.ignore_drvrinfo && udata.drvrinfo_removed) { |
462 | 0 | assert(sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2); |
463 | 0 | sblock_flags |= H5AC__DIRTIED_FLAG; |
464 | 0 | } /* end if */ |
465 | | |
466 | | /* The superblock must be flushed last (and collectively in parallel) */ |
467 | 1.90k | sblock_flags |= H5AC__FLUSH_LAST_FLAG; |
468 | | #ifdef H5_HAVE_PARALLEL |
469 | | sblock_flags |= H5AC__FLUSH_COLLECTIVELY_FLAG; |
470 | | #endif /* H5_HAVE_PARALLEL */ |
471 | | |
472 | | /* Check if superblock address is different from base address and adjust |
473 | | * base address and "end of file" address if so. |
474 | | */ |
475 | 1.90k | if (!H5_addr_eq(super_addr, sblock->base_addr)) { |
476 | | /* If the superblock moved in the file, adjust the EOF */ |
477 | | /* (Handles moving earlier & later) */ |
478 | 495 | udata.stored_eof -= (sblock->base_addr - super_addr); |
479 | | |
480 | | /* Adjust base address for offsets of the HDF5 data in the file */ |
481 | 495 | sblock->base_addr = super_addr; |
482 | | |
483 | | /* Set the base address for the file in the VFD now */ |
484 | 495 | if (H5F__set_base_addr(f, sblock->base_addr) < 0) |
485 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "failed to set base address for file driver"); |
486 | | |
487 | | /* Indicate that the superblock should be marked dirty */ |
488 | 495 | if ((rw_flags & H5AC__READ_ONLY_FLAG) == 0) |
489 | 495 | sblock_flags |= H5AC__DIRTIED_FLAG; |
490 | 495 | } /* end if */ |
491 | | |
492 | | /* Set information in the file's creation property list */ |
493 | 1.90k | if (H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &sblock->super_vers) < 0) |
494 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set superblock version"); |
495 | 1.90k | if (H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &sblock->sizeof_addr) < 0) |
496 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set byte number in an address"); |
497 | 1.90k | if (H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sblock->sizeof_size) < 0) |
498 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set byte number for object size"); |
499 | | |
500 | | /* Handle the B-tree 'K' values */ |
501 | 1.90k | if (sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) { |
502 | | /* Sanity check */ |
503 | 758 | assert(udata.sym_leaf_k != 0); |
504 | | |
505 | | /* Set the symbol table internal node 'K' value */ |
506 | 758 | if (H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &udata.sym_leaf_k) < 0) |
507 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set rank for symbol table leaf nodes"); |
508 | 758 | sblock->sym_leaf_k = udata.sym_leaf_k; |
509 | | |
510 | | /* Set the B-tree internal node values, etc */ |
511 | 758 | if (H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, udata.btree_k) < 0) |
512 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set rank for btree internal nodes"); |
513 | 758 | H5MM_memcpy(sblock->btree_k, udata.btree_k, sizeof(unsigned) * (size_t)H5B_NUM_BTREE_ID); |
514 | 758 | } /* end if */ |
515 | 1.14k | else { |
516 | | /* Get the (default) B-tree internal node values, etc */ |
517 | | /* (Note: these may be reset in a superblock extension) */ |
518 | 1.14k | if (H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, sblock->btree_k) < 0) |
519 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes"); |
520 | 1.14k | if (H5P_get(c_plist, H5F_CRT_SYM_LEAF_NAME, &sblock->sym_leaf_k) < 0) |
521 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes"); |
522 | 1.14k | } /* end else */ |
523 | | |
524 | | /* |
525 | | * The user-defined data is the area of the file before the base |
526 | | * address. |
527 | | */ |
528 | 1.90k | if (H5P_set(c_plist, H5F_CRT_USER_BLOCK_NAME, &sblock->base_addr) < 0) |
529 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set userblock size"); |
530 | | |
531 | | /* |
532 | | * Make sure that the data is not truncated. One case where this is |
533 | | * possible is if the first file of a family of files was opened |
534 | | * individually. |
535 | | * |
536 | | * Can skip this test when it is not the initial file open. |
537 | | * |
538 | | * When flushing file buffers and fractal heap is involved, |
539 | | * the library will allocate actual space for tmp addresses |
540 | | * via the file layer. The aggregator allocates a block, |
541 | | * thus the eoa might be greater than eof. |
542 | | * Note: the aggregator is changed again after being reset |
543 | | * earlier before H5AC_flush due to allocation of tmp addresses. |
544 | | * |
545 | | * The EOF check must be skipped when the file is opened for SWMR read, |
546 | | * as the file can appear truncated if only part of it has been |
547 | | * been flushed to disk by the SWMR writer process. |
548 | | * |
549 | | * The EOF check is also skipped when the private property |
550 | | * H5F_ACS_SKIP_EOF_CHECK_NAME exists in the fapl. |
551 | | * This property is enabled by the tool h5clear with these |
552 | | * two options: (1) --filesize (2) --increment |
553 | | */ |
554 | | |
555 | | /* Check if this private property exists in fapl */ |
556 | 1.90k | if (H5P_exist_plist(fa_plist, H5F_ACS_SKIP_EOF_CHECK_NAME) > 0) |
557 | 1.90k | if (H5P_get(fa_plist, H5F_ACS_SKIP_EOF_CHECK_NAME, &skip_eof_check) < 0) |
558 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get skip EOF check value"); |
559 | | |
560 | 1.90k | if (H5F_INTENT(f) & H5F_ACC_SWMR_READ) { |
561 | | /* |
562 | | * When the file is opened for SWMR read access, skip the check if |
563 | | * the file has a version 3 superblock capable of SWMR support |
564 | | */ |
565 | 0 | if (sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_3) |
566 | 0 | skip_eof_check = true; |
567 | 0 | } |
568 | 1.90k | if (!skip_eof_check && initial_read) { |
569 | 1.90k | if (HADDR_UNDEF == (eof = H5FD_get_eof(f->shared->lf, H5FD_MEM_DEFAULT))) |
570 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to determine file size"); |
571 | | |
572 | | /* (Account for the stored EOA being absolute offset -QAK) */ |
573 | 1.90k | if ((eof + sblock->base_addr) < udata.stored_eof) |
574 | 3 | HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, FAIL, |
575 | 1.90k | "truncated file: eof = %llu, sblock->base_addr = %llu, stored_eof = %llu", |
576 | 1.90k | (unsigned long long)eof, (unsigned long long)sblock->base_addr, |
577 | 1.90k | (unsigned long long)udata.stored_eof); |
578 | 1.90k | } |
579 | | |
580 | | /* |
581 | | * Tell the file driver how much address space has already been |
582 | | * allocated so that it knows how to allocate additional memory. |
583 | | */ |
584 | | |
585 | | /* Set the ring type in the API context */ |
586 | 1.90k | H5AC_set_ring(H5AC_RING_SBE, NULL); |
587 | | |
588 | | /* Decode the optional driver information block */ |
589 | 1.90k | if (H5_addr_defined(sblock->driver_addr)) { |
590 | 465 | H5O_drvinfo_t *drvinfo; /* Driver info */ |
591 | 465 | H5F_drvrinfo_cache_ud_t drvrinfo_udata; /* User data for metadata callbacks */ |
592 | 465 | unsigned drvinfo_flags = H5AC__NO_FLAGS_SET; /* Flags used in driver info block unprotect call */ |
593 | | |
594 | | /* Sanity check - driver info block should only be defined for |
595 | | * superblock version < 2. |
596 | | */ |
597 | 465 | assert(sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2); |
598 | | |
599 | | /* Set up user data */ |
600 | 465 | drvrinfo_udata.f = f; |
601 | 465 | drvrinfo_udata.driver_addr = sblock->driver_addr; |
602 | | |
603 | | /* extend EOA so we can read at least the fixed sized |
604 | | * portion of the driver info block |
605 | | */ |
606 | 465 | if (H5FD_set_eoa(f->shared->lf, H5FD_MEM_SUPER, sblock->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < |
607 | 465 | 0) /* will extend eoa later if required */ |
608 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed"); |
609 | | |
610 | | /* Look up the driver info block */ |
611 | 465 | if (NULL == (drvinfo = (H5O_drvinfo_t *)H5AC_protect(f, H5AC_DRVRINFO, sblock->driver_addr, |
612 | 465 | &drvrinfo_udata, rw_flags))) |
613 | 5 | HGOTO_ERROR(H5E_FILE, H5E_CANTPROTECT, FAIL, "unable to load driver info block"); |
614 | | |
615 | | /* Loading the driver info block is enough to set up the right info */ |
616 | | |
617 | | /* Check if we need to rewrite the driver info block info */ |
618 | 460 | if (((rw_flags & H5AC__READ_ONLY_FLAG) == 0) && H5F_HAS_FEATURE(f, H5FD_FEAT_DIRTY_DRVRINFO_LOAD)) |
619 | 0 | drvinfo_flags |= H5AC__DIRTIED_FLAG; |
620 | | |
621 | | /* set the pin entry flag so that the driver information block |
622 | | * cache entry will be pinned in the cache. |
623 | | */ |
624 | 460 | drvinfo_flags |= H5AC__PIN_ENTRY_FLAG; |
625 | | |
626 | | /* Release the driver info block */ |
627 | 460 | if (H5AC_unprotect(f, H5AC_DRVRINFO, sblock->driver_addr, drvinfo, drvinfo_flags) < 0) |
628 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTUNPROTECT, FAIL, "unable to release driver info block"); |
629 | | |
630 | | /* save a pointer to the driver information cache entry */ |
631 | 460 | f->shared->drvinfo = drvinfo; |
632 | 460 | } /* end if */ |
633 | | |
634 | | /* (Account for the stored EOA being absolute offset -NAF) */ |
635 | 1.89k | if (H5F__set_eoa(f, H5FD_MEM_DEFAULT, udata.stored_eof - sblock->base_addr) < 0) |
636 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set end-of-address marker for file"); |
637 | | |
638 | | /* Decode the optional superblock extension info */ |
639 | 1.89k | if (H5_addr_defined(sblock->ext_addr)) { |
640 | 1.14k | H5O_loc_t ext_loc; /* "Object location" for superblock extension */ |
641 | 1.14k | H5O_btreek_t btreek; /* v1 B-tree 'K' value message from superblock extension */ |
642 | 1.14k | H5O_drvinfo_t drvinfo; /* Driver info message from superblock extension */ |
643 | 1.14k | size_t u; /* Local index variable */ |
644 | 1.14k | htri_t status; /* Status for message existing */ |
645 | | |
646 | | /* Sanity check - superblock extension should only be defined for |
647 | | * superblock version >= 2. |
648 | | */ |
649 | 1.14k | if (sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) |
650 | 2 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, |
651 | 1.14k | "invalid superblock - extension message should not be defined for version < 2"); |
652 | | |
653 | | /* Check for superblock extension being located "outside" the stored |
654 | | * 'eoa' value, which can occur with the split/multi VFD. |
655 | | */ |
656 | 1.14k | if (H5_addr_gt(sblock->ext_addr, udata.stored_eof)) { |
657 | | /* Set the 'eoa' for the object header memory type large enough |
658 | | * to give some room for a reasonably sized superblock extension. |
659 | | * (This is _rather_ a kludge -QAK) |
660 | | */ |
661 | 0 | if (H5F__set_eoa(f, H5FD_MEM_OHDR, (haddr_t)(sblock->ext_addr + 1024)) < 0) |
662 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set end-of-address marker for file"); |
663 | 0 | } /* end if */ |
664 | | |
665 | | /* Open the superblock extension */ |
666 | 1.14k | if (H5F__super_ext_open(f, sblock->ext_addr, &ext_loc) < 0) |
667 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open file's superblock extension"); |
668 | | |
669 | | /* Check for the extension having a 'driver info' message */ |
670 | 1.14k | if ((status = H5O_msg_exists(&ext_loc, H5O_DRVINFO_ID)) < 0) |
671 | 880 | HGOTO_ERROR(H5E_FILE, H5E_EXISTS, FAIL, "unable to read object header"); |
672 | 261 | if (status) { |
673 | | /* Check for ignoring the driver info for this file */ |
674 | 1 | if (!udata.ignore_drvrinfo) { |
675 | | |
676 | | /* Retrieve the 'driver info' structure */ |
677 | 1 | if (NULL == H5O_msg_read(&ext_loc, H5O_DRVINFO_ID, &drvinfo)) |
678 | 1 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "driver info message not present"); |
679 | | |
680 | | /* Validate and decode driver information */ |
681 | 0 | if (H5FD_sb_load(f->shared->lf, drvinfo.name, drvinfo.buf) < 0) { |
682 | 0 | H5O_msg_reset(H5O_DRVINFO_ID, &drvinfo); |
683 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, FAIL, "unable to decode driver information"); |
684 | 0 | } /* end if */ |
685 | | |
686 | | /* Reset driver info message */ |
687 | 0 | H5O_msg_reset(H5O_DRVINFO_ID, &drvinfo); |
688 | |
|
689 | 0 | assert(false == f->shared->drvinfo_sb_msg_exists); |
690 | 0 | f->shared->drvinfo_sb_msg_exists = true; |
691 | 0 | } /* end else */ |
692 | 1 | } /* end if */ |
693 | | |
694 | | /* Read in the shared OH message information if there is any */ |
695 | 260 | if (H5SM_get_info(&ext_loc, c_plist) < 0) |
696 | 1 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to read SOHM table information"); |
697 | | |
698 | | /* Check for the extension having a 'v1 B-tree "K"' message */ |
699 | 259 | if ((status = H5O_msg_exists(&ext_loc, H5O_BTREEK_ID)) < 0) |
700 | 0 | HGOTO_ERROR(H5E_FILE, H5E_EXISTS, FAIL, "unable to read object header"); |
701 | 259 | if (status) { |
702 | | /* Retrieve the 'v1 B-tree "K"' structure */ |
703 | 7 | if (NULL == H5O_msg_read(&ext_loc, H5O_BTREEK_ID, &btreek)) |
704 | 1 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "v1 B-tree 'K' info message not present"); |
705 | | |
706 | | /* Set non-default v1 B-tree 'K' value info from file */ |
707 | 6 | sblock->btree_k[H5B_CHUNK_ID] = btreek.btree_k[H5B_CHUNK_ID]; |
708 | 6 | sblock->btree_k[H5B_SNODE_ID] = btreek.btree_k[H5B_SNODE_ID]; |
709 | 6 | sblock->sym_leaf_k = btreek.sym_leaf_k; |
710 | | |
711 | | /* Set non-default v1 B-tree 'K' values in the property list */ |
712 | 6 | if (H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btreek.btree_k) < 0) |
713 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set rank for btree internal nodes"); |
714 | 6 | if (H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &btreek.sym_leaf_k) < 0) |
715 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set rank for symbol table leaf nodes"); |
716 | 6 | } /* end if */ |
717 | | |
718 | | /* Check for the extension having a 'free-space manager info' message */ |
719 | 258 | if ((status = H5O_msg_exists(&ext_loc, H5O_FSINFO_ID)) < 0) |
720 | 0 | HGOTO_ERROR(H5E_FILE, H5E_EXISTS, FAIL, "unable to read object header"); |
721 | 258 | if (status) { |
722 | 249 | uint8_t flags; /* Message flags */ |
723 | | |
724 | | /* Get message flags */ |
725 | 249 | if (H5O_msg_get_flags(&ext_loc, H5O_FSINFO_ID, &flags) < 0) |
726 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, |
727 | 249 | "unable to message flags for free-space manager info message"); |
728 | | |
729 | | /* If message is NOT marked "unknown"--set up file space info */ |
730 | 249 | if (!(flags & H5O_MSG_FLAG_WAS_UNKNOWN)) { |
731 | 245 | H5O_fsinfo_t fsinfo; /* File space info message from superblock extension */ |
732 | | |
733 | 245 | memset(&fsinfo, 0, sizeof(H5O_fsinfo_t)); |
734 | | |
735 | | /* f->shared->null_fsm_addr: Whether to drop free-space to the floor */ |
736 | | /* The h5clear tool uses this property to tell the library |
737 | | * to drop free-space to the floor |
738 | | */ |
739 | 245 | if (H5P_exist_plist(fa_plist, H5F_ACS_NULL_FSM_ADDR_NAME) > 0) |
740 | 245 | if (H5P_get(fa_plist, H5F_ACS_NULL_FSM_ADDR_NAME, &f->shared->null_fsm_addr) < 0) |
741 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, |
742 | 245 | "can't get clearance for persisting fsm addr"); |
743 | | |
744 | | /* Retrieve the 'file space info' structure */ |
745 | 245 | if (NULL == H5O_msg_read(&ext_loc, H5O_FSINFO_ID, &fsinfo)) |
746 | 52 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get free-space manager info message"); |
747 | | |
748 | | /* Version bounds check */ |
749 | 193 | if (H5O_fsinfo_check_version(H5F_HIGH_BOUND(f), &fsinfo) < 0) |
750 | 3 | HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, |
751 | 193 | "File space info message's version out of bounds"); |
752 | | |
753 | | /* Update changed values */ |
754 | 190 | if (f->shared->fs_version != fsinfo.version) |
755 | 190 | f->shared->fs_version = fsinfo.version; |
756 | 190 | if (f->shared->fs_strategy != fsinfo.strategy) { |
757 | 175 | f->shared->fs_strategy = fsinfo.strategy; |
758 | | |
759 | | /* Set non-default strategy in the property list */ |
760 | 175 | if (H5P_set(c_plist, H5F_CRT_FILE_SPACE_STRATEGY_NAME, &fsinfo.strategy) < 0) |
761 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set file space strategy"); |
762 | 175 | } /* end if */ |
763 | 190 | if (f->shared->fs_persist != fsinfo.persist) { |
764 | 151 | f->shared->fs_persist = fsinfo.persist; |
765 | | |
766 | | /* Set non-default strategy in the property list */ |
767 | 151 | if (H5P_set(c_plist, H5F_CRT_FREE_SPACE_PERSIST_NAME, &fsinfo.persist) < 0) |
768 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set file space strategy"); |
769 | 151 | } /* end if */ |
770 | 190 | if (f->shared->fs_threshold != fsinfo.threshold) { |
771 | 146 | f->shared->fs_threshold = fsinfo.threshold; |
772 | | |
773 | | /* Set non-default threshold in the property list */ |
774 | 146 | if (H5P_set(c_plist, H5F_CRT_FREE_SPACE_THRESHOLD_NAME, &fsinfo.threshold) < 0) |
775 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set file space strategy"); |
776 | 146 | } /* end if */ |
777 | | |
778 | 190 | if (f->shared->fs_page_size < H5F_FILE_SPACE_PAGE_SIZE_MIN) |
779 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file space page size too small"); |
780 | 190 | if (fsinfo.page_size < H5F_FILE_SPACE_PAGE_SIZE_MIN) |
781 | 3 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file space page size too small"); |
782 | | |
783 | 187 | if (f->shared->fs_page_size != fsinfo.page_size) { |
784 | 136 | f->shared->fs_page_size = fsinfo.page_size; |
785 | | |
786 | | /* Set file space page size in the property list */ |
787 | 136 | if (H5P_set(c_plist, H5F_CRT_FILE_SPACE_PAGE_SIZE_NAME, &fsinfo.page_size) < 0) |
788 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set file space page size"); |
789 | 136 | } /* end if */ |
790 | 187 | if (f->shared->pgend_meta_thres != fsinfo.pgend_meta_thres) |
791 | | /* Initialize page end meta threshold */ |
792 | 110 | f->shared->pgend_meta_thres = fsinfo.pgend_meta_thres; |
793 | | |
794 | 187 | if (f->shared->eoa_fsm_fsalloc != fsinfo.eoa_pre_fsm_fsalloc) |
795 | 148 | f->shared->eoa_fsm_fsalloc = fsinfo.eoa_pre_fsm_fsalloc; |
796 | | |
797 | | /* |
798 | | * If the following two conditions are true: |
799 | | * (1) skipping EOF check (skip_eof_check) |
800 | | * (2) dropping free-space to the floor (f->shared->null_fsm_addr) |
801 | | * skip the asserts as "eoa_fsm_fsalloc" may be undefined |
802 | | * for a crashed file with persistent free space managers. |
803 | | * The above two conditions are enabled when the tool h5clear --increment |
804 | | * option is used. |
805 | | */ |
806 | 187 | if (!skip_eof_check && !f->shared->null_fsm_addr) |
807 | 187 | assert((!f->shared->fs_persist) || (f->shared->eoa_fsm_fsalloc != HADDR_UNDEF)); |
808 | | |
809 | | /* |
810 | | * A crashed file with persistent free-space managers may have |
811 | | * undefined f->shared->eoa_fsm_fsalloc. |
812 | | * eoa_fsm_fsalloc is the final eoa which is saved in the free-space |
813 | | * info message's eoa_pre_fsm_fsalloc field for backward compatibility. |
814 | | * If the tool h5clear sets to dropping free-space to the floor |
815 | | * as indicated by f->shared->null_fsm_addr, we are not going to |
816 | | * perform actions to settle things on file close in the routines |
817 | | * H5MF_settle_meta_data_fsm() and H5MF_settle_raw_data_fsm(). |
818 | | * |
819 | | * We remove the following check: |
820 | | * if((f->shared->eoa_pre_fsm_fsalloc != HADDR_UNDEF || null_fsm_addr) && |
821 | | * (H5F_INTENT(f) & H5F_ACC_RDWR)) |
822 | | * f->shared->first_alloc_dealloc = true; |
823 | | * |
824 | | * Because: |
825 | | * --there is no more f->shared->eoa_pre_fsm_fsalloc and |
826 | | * f->shared->first_alloc_dealloc |
827 | | * --the check for null_fsm_addr is directly done in H5MF_settle_meta_data_fsm() |
828 | | * and H5MF_settle_raw_data_fsm() |
829 | | */ |
830 | | |
831 | 187 | f->shared->fs_addr[0] = HADDR_UNDEF; |
832 | 2.43k | for (u = 1; u < NELMTS(f->shared->fs_addr); u++) |
833 | 2.24k | f->shared->fs_addr[u] = fsinfo.fs_addr[u - 1]; |
834 | | |
835 | | /* If the following two conditions are true: |
836 | | * (1) file is persisting free-space |
837 | | * (2) dropping free-space to the floor (f->shared->null_fsm_addr) |
838 | | * nullify the addresses of the FSMs |
839 | | */ |
840 | 187 | if (f->shared->fs_persist && f->shared->null_fsm_addr) |
841 | 0 | for (u = 0; u < NELMTS(fsinfo.fs_addr); u++) |
842 | 0 | f->shared->fs_addr[u] = fsinfo.fs_addr[u] = HADDR_UNDEF; |
843 | | |
844 | | /* For fsinfo.mapped: remove the FSINFO message from the superblock extension |
845 | | and write a new message to the extension */ |
846 | | /* For f->shared->null_fsm_addr: just update FSINFO message in the superblock extension */ |
847 | 187 | if (((fsinfo.mapped || f->shared->null_fsm_addr) && (rw_flags & H5AC__READ_ONLY_FLAG) == 0)) { |
848 | | |
849 | | /* Do the same kluge until we know for sure. VC */ |
850 | 51 | #if 1 /* bug fix test code -- tidy this up if all goes well */ /* JRM */ |
851 | | /* KLUGE ALERT!! |
852 | | * |
853 | | * H5F__super_ext_write_msg() expects f->shared->sblock to |
854 | | * be set -- verify that it is NULL, and then set it. |
855 | | * Set it back to NULL when we are done. |
856 | | */ |
857 | 51 | assert(f->shared->sblock == NULL); |
858 | 51 | f->shared->sblock = sblock; |
859 | 51 | #endif /* JRM */ |
860 | | |
861 | 51 | if (f->shared->null_fsm_addr) { |
862 | 0 | if (H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, false, |
863 | 0 | H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0) |
864 | 0 | HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, |
865 | 0 | "error in writing fsinfo message to superblock extension"); |
866 | 0 | } |
867 | 51 | else { |
868 | 51 | if (H5F__super_ext_remove_msg(f, H5O_FSINFO_ID) < 0) { |
869 | 5 | #if 1 /* bug fix test code -- tidy this up if all goes well */ /* JRM */ |
870 | 5 | f->shared->sblock = NULL; |
871 | 5 | #endif /* JRM */ |
872 | | |
873 | 5 | HGOTO_ERROR(H5E_FILE, H5E_CANTDELETE, FAIL, |
874 | 5 | "error in removing message from superblock extension"); |
875 | 5 | } |
876 | | |
877 | 46 | if (H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, true, |
878 | 46 | H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0) |
879 | 0 | HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, |
880 | 46 | "error in writing fsinfo message to superblock extension"); |
881 | 46 | } |
882 | 46 | #if 1 /* bug fix test code -- tidy this up if all goes well */ /* JRM */ |
883 | 46 | f->shared->sblock = NULL; |
884 | 46 | #endif /* JRM */ |
885 | | |
886 | 46 | } /* end if */ |
887 | 187 | } /* end if not marked "unknown" */ |
888 | 249 | } /* end if */ |
889 | | |
890 | | /* Check for the extension having a 'metadata cache image' message */ |
891 | 195 | if ((status = H5O_msg_exists(&ext_loc, H5O_MDCI_MSG_ID)) < 0) |
892 | 0 | HGOTO_ERROR(H5E_FILE, H5E_EXISTS, FAIL, "unable to read object header"); |
893 | 195 | if (status) { |
894 | 13 | bool rw = ((rw_flags & H5AC__READ_ONLY_FLAG) == 0); |
895 | 13 | H5O_mdci_t mdci_msg; |
896 | | |
897 | | /* if the metadata cache image superblock extension message exists, |
898 | | * read its contents and pass the data on to the metadata cache. |
899 | | * Given this data, the cache will load and decode the metadata |
900 | | * cache image block, decoded it and load its contents into the |
901 | | * the cache on the test protect call. |
902 | | * |
903 | | * Further, if the file is opened R/W, the metadata cache will |
904 | | * delete the metadata cache image superblock extension and free |
905 | | * the cache image block. Don't do this now as f->shared |
906 | | * is not fully setup, which complicates matters. |
907 | | */ |
908 | | |
909 | | /* Retrieve the 'metadata cache image message' structure */ |
910 | 13 | if (NULL == H5O_msg_read(&ext_loc, H5O_MDCI_MSG_ID, &mdci_msg)) |
911 | 3 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get metadata cache image message"); |
912 | | |
913 | | /* Indicate to the cache that there's an image to load on first protect call */ |
914 | 10 | if (H5AC_load_cache_image_on_next_protect(f, mdci_msg.addr, mdci_msg.size, rw) < 0) |
915 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTLOAD, FAIL, |
916 | 10 | "call to H5AC_load_cache_image_on_next_protect failed"); |
917 | 10 | } /* end if */ |
918 | | |
919 | | /* Close superblock extension */ |
920 | 192 | if (H5F__super_ext_close(f, &ext_loc, false) < 0) |
921 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close file's superblock extension"); |
922 | 192 | } /* end if */ |
923 | | |
924 | | /* Update the driver info if VFD indicated to do so */ |
925 | | /* (NOTE: only for later versions of superblock, earlier versions are handled |
926 | | * earlier in this routine. |
927 | | */ |
928 | 945 | if (((rw_flags & H5AC__READ_ONLY_FLAG) == 0) && sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2 && |
929 | 195 | H5_addr_defined(sblock->ext_addr)) { |
930 | | /* Check for modifying the driver info when opening the file */ |
931 | 192 | if (H5F_HAS_FEATURE(f, H5FD_FEAT_DIRTY_DRVRINFO_LOAD)) { |
932 | 0 | size_t driver_size; /* Size of driver info block (bytes) */ |
933 | | |
934 | | /* Check for driver info message */ |
935 | 0 | H5_CHECKED_ASSIGN(driver_size, size_t, H5FD_sb_size(f->shared->lf), hsize_t); |
936 | 0 | if (driver_size > 0) { |
937 | 0 | H5O_drvinfo_t drvinfo; /* Driver info */ |
938 | 0 | uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Driver info block encoding buffer */ |
939 | | |
940 | | /* Sanity check */ |
941 | 0 | assert(driver_size <= H5F_MAX_DRVINFOBLOCK_SIZE); |
942 | | |
943 | | /* Encode driver-specific data */ |
944 | 0 | if (H5FD_sb_encode(f->shared->lf, drvinfo.name, dbuf) < 0) |
945 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information"); |
946 | | |
947 | | /* Set the driver info information for the superblock extension */ |
948 | 0 | drvinfo.len = driver_size; |
949 | 0 | drvinfo.buf = dbuf; |
950 | | |
951 | | /* Write driver info information to the superblock extension */ |
952 | |
|
953 | 0 | #if 1 /* bug fix test code -- tidy this up if all goes well */ /* JRM */ |
954 | | /* KLUGE ALERT!! |
955 | | * |
956 | | * H5F__super_ext_write_msg() expects f->shared->sblock to |
957 | | * be set -- verify that it is NULL, and then set it. |
958 | | * Set it back to NULL when we are done. |
959 | | */ |
960 | 0 | assert(f->shared->sblock == NULL); |
961 | 0 | f->shared->sblock = sblock; |
962 | 0 | #endif /* JRM */ |
963 | 0 | if (H5F__super_ext_write_msg(f, H5O_DRVINFO_ID, &drvinfo, false, H5O_MSG_NO_FLAGS_SET) < 0) |
964 | 0 | HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, |
965 | 0 | "error in writing message to superblock extension"); |
966 | | |
967 | 0 | #if 1 /* bug fix test code -- tidy this up if all goes well */ /* JRM */ |
968 | 0 | f->shared->sblock = NULL; |
969 | 0 | #endif /* JRM */ |
970 | |
|
971 | 0 | } /* end if */ |
972 | 0 | } /* end if */ |
973 | | /* Check for eliminating the driver info block */ |
974 | 192 | else if (H5F_HAS_FEATURE(f, H5FD_FEAT_IGNORE_DRVRINFO)) { |
975 | | /* Remove the driver info message from the superblock extension */ |
976 | 0 | if (H5F__super_ext_remove_msg(f, H5O_DRVINFO_ID) < 0) |
977 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, |
978 | 0 | "error in removing message from superblock extension"); |
979 | | |
980 | | /* Check if the superblock extension was removed */ |
981 | 0 | if (!H5_addr_defined(sblock->ext_addr)) |
982 | 0 | sblock_flags |= H5AC__DIRTIED_FLAG; |
983 | 0 | } /* end if */ |
984 | 192 | } /* end if */ |
985 | | |
986 | | /* Set the pointer to the pinned superblock */ |
987 | 945 | f->shared->sblock = sblock; |
988 | | |
989 | | /* Set the page aggregation mode */ |
990 | 945 | if (H5F__set_paged_aggr(f, (bool)H5F_PAGED_AGGR(f)) < 0) |
991 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "failed to set paged_aggr status for file driver"); |
992 | | |
993 | 1.93k | done: |
994 | | /* Reset the ring in the API context */ |
995 | 1.93k | if (orig_ring != H5AC_RING_INV) |
996 | 1.90k | H5AC_set_ring(orig_ring, NULL); |
997 | | |
998 | | /* Release the superblock */ |
999 | 1.93k | if (sblock && H5AC_unprotect(f, H5AC_SUPERBLOCK, (haddr_t)0, sblock, sblock_flags) < 0) |
1000 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTUNPROTECT, FAIL, "unable to close superblock"); |
1001 | | |
1002 | | /* If we have failed, make sure no entries are left in the |
1003 | | * metadata cache, so that it can be shut down and discarded. |
1004 | | */ |
1005 | 1.93k | if (ret_value < 0) { |
1006 | | /* Unpin and discard drvinfo cache entry */ |
1007 | 989 | if (f->shared->drvinfo) { |
1008 | 1 | if (H5AC_unpin_entry(f->shared->drvinfo) < 0) |
1009 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTUNPIN, FAIL, "unable to unpin driver info"); |
1010 | | |
1011 | | /* Evict the driver info block from the cache */ |
1012 | 1 | if (sblock) { |
1013 | 1 | if (H5AC_expunge_entry(f, H5AC_DRVRINFO, sblock->driver_addr, H5AC__NO_FLAGS_SET) < 0) |
1014 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, FAIL, "unable to expunge driver info block"); |
1015 | 1 | f->shared->drvinfo = NULL; |
1016 | 1 | } |
1017 | 1 | } /* end if */ |
1018 | | |
1019 | | /* Unpin & discard superblock */ |
1020 | 989 | if (sblock) { |
1021 | | /* Unpin superblock in cache */ |
1022 | 959 | if (H5AC_unpin_entry(sblock) < 0) |
1023 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock"); |
1024 | | |
1025 | | /* Evict the superblock from the cache */ |
1026 | 959 | if (H5AC_expunge_entry(f, H5AC_SUPERBLOCK, (haddr_t)0, H5AC__NO_FLAGS_SET) < 0) |
1027 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, FAIL, "unable to expunge superblock"); |
1028 | 959 | f->shared->sblock = NULL; |
1029 | 959 | } /* end if */ |
1030 | 989 | } /* end if */ |
1031 | | |
1032 | 1.93k | FUNC_LEAVE_NOAPI_TAG(ret_value) |
1033 | 1.93k | } /* end H5F__super_read() */ |
1034 | | |
1035 | | /*------------------------------------------------------------------------- |
1036 | | * Function: H5F__super_init |
1037 | | * |
1038 | | * Purpose: Allocates the superblock for the file and initializes |
1039 | | * information about the superblock in memory. Writes extension |
1040 | | * messages if any are needed. |
1041 | | * |
1042 | | * Return: Success: SUCCEED |
1043 | | * Failure: FAIL |
1044 | | * |
1045 | | *------------------------------------------------------------------------- |
1046 | | */ |
1047 | | herr_t |
1048 | | H5F__super_init(H5F_t *f) |
1049 | 0 | { |
1050 | 0 | H5F_super_t *sblock = NULL; /* Superblock cache structure */ |
1051 | 0 | bool sblock_in_cache = false; /* Whether the superblock has been inserted into the metadata cache */ |
1052 | 0 | H5O_drvinfo_t *drvinfo = NULL; /* Driver info */ |
1053 | 0 | bool drvinfo_in_cache = |
1054 | 0 | false; /* Whether the driver info block has been inserted into the metadata cache */ |
1055 | 0 | H5P_genplist_t *plist; /* File creation property list */ |
1056 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; |
1057 | 0 | hsize_t userblock_size; /* Size of userblock, in bytes */ |
1058 | 0 | hsize_t superblock_size = 0; /* Size of superblock, in bytes */ |
1059 | 0 | haddr_t superblock_addr = HADDR_UNDEF; |
1060 | 0 | size_t driver_size; /* Size of driver info block (bytes) */ |
1061 | 0 | unsigned super_vers = HDF5_SUPERBLOCK_VERSION_DEF; /* Superblock version for file */ |
1062 | 0 | H5O_loc_t ext_loc; /* Superblock extension object location */ |
1063 | 0 | bool need_ext; /* Whether the superblock extension is needed */ |
1064 | 0 | bool ext_created = false; /* Whether the extension has been created */ |
1065 | 0 | bool non_default_fs_settings = false; /* Whether the file has non-default free-space settings */ |
1066 | 0 | herr_t ret_value = SUCCEED; /* Return Value */ |
1067 | |
|
1068 | 0 | FUNC_ENTER_PACKAGE_TAG(H5AC__SUPERBLOCK_TAG) |
1069 | | |
1070 | | /* Allocate space for the superblock */ |
1071 | 0 | if (NULL == (sblock = H5FL_CALLOC(H5F_super_t))) |
1072 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "memory allocation failed"); |
1073 | | |
1074 | | /* Initialize various address information */ |
1075 | 0 | sblock->base_addr = HADDR_UNDEF; |
1076 | 0 | sblock->ext_addr = HADDR_UNDEF; |
1077 | 0 | sblock->driver_addr = HADDR_UNDEF; |
1078 | 0 | sblock->root_addr = HADDR_UNDEF; |
1079 | | |
1080 | | /* Get the shared file creation property list */ |
1081 | 0 | if (NULL == (plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id))) |
1082 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a property list"); |
1083 | | |
1084 | | /* Initialize sym_leaf_k */ |
1085 | 0 | if (H5P_get(plist, H5F_CRT_SYM_LEAF_NAME, &sblock->sym_leaf_k) < 0) |
1086 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get byte number for object size"); |
1087 | | |
1088 | | /* Initialize btree_k */ |
1089 | 0 | if (H5P_get(plist, H5F_CRT_BTREE_RANK_NAME, &sblock->btree_k[0]) < 0) |
1090 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes"); |
1091 | | |
1092 | | /* Check for non-default free-space settings */ |
1093 | 0 | if (!(f->shared->fs_strategy == H5F_FILE_SPACE_STRATEGY_DEF && |
1094 | 0 | f->shared->fs_persist == H5F_FREE_SPACE_PERSIST_DEF && |
1095 | 0 | f->shared->fs_threshold == H5F_FREE_SPACE_THRESHOLD_DEF && |
1096 | 0 | f->shared->fs_page_size == H5F_FILE_SPACE_PAGE_SIZE_DEF)) |
1097 | 0 | non_default_fs_settings = true; |
1098 | | |
1099 | | /* |
1100 | | * When creating a file with write access, the library will: |
1101 | | * -- set superblock version to 0, 1 or 2 based on feature enabled |
1102 | | * -- no change to low_bound |
1103 | | * When creating a file with SWMR-write access, the library will: |
1104 | | * (See explanation (#) below.) |
1105 | | * -- set superblock version to 3 |
1106 | | * -- upgrade low_bound to at least V110 |
1107 | | * |
1108 | | * Then the library will finalize superblock version to that allowed by |
1109 | | * low_bound if that is higher. |
1110 | | * Lastly, the library will check to ensure the superblock version does not |
1111 | | * exceed the version allowed by high_bound. Otherwise fail file open. |
1112 | | * |
1113 | | * For details, please see RFC:Setting Bounds for Object Creation in HDF5 1.10.0. |
1114 | | * |
1115 | | * (#) |
1116 | | * Version 3 superblock is introduced in 1.10 for SWMR due to the problem of |
1117 | | * the status_flags field in the superblock. The problem is discussed in |
1118 | | * jira issue SWMR-79 and also in the RFC: File Format Changes in HDF5 1.10.0. |
1119 | | * The file's low_bound is upgraded for SWMR so that the library will |
1120 | | * use the best format versions available in 1.10. |
1121 | | * Due to the possible upgrade, the fapl returned from H5Fget_access_plist() |
1122 | | * might indicate a low_bound higher than what the user originally set. |
1123 | | */ |
1124 | | |
1125 | | /* |
1126 | | * Creating a file with SWMR-write access will |
1127 | | * upgrade superblock version and low_bound |
1128 | | */ |
1129 | 0 | if (H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) { |
1130 | 0 | super_vers = HDF5_SUPERBLOCK_VERSION_3; |
1131 | 0 | f->shared->low_bound = MAX(H5F_LIBVER_V110, f->shared->low_bound); |
1132 | | |
1133 | | /* Bump superblock version to create superblock extension for SOHM info */ |
1134 | 0 | } |
1135 | 0 | else if (f->shared->sohm_nindexes > 0) |
1136 | 0 | super_vers = HDF5_SUPERBLOCK_VERSION_2; |
1137 | | /* |
1138 | | * Bump superblock version to create superblock extension for: |
1139 | | * -- non-default file space strategy or |
1140 | | * -- non-default persisting free-space or |
1141 | | * -- non-default free-space threshold or |
1142 | | * -- non-default page_size |
1143 | | */ |
1144 | 0 | else if (non_default_fs_settings) |
1145 | 0 | super_vers = HDF5_SUPERBLOCK_VERSION_2; |
1146 | | /* Check for non-default indexed storage B-tree internal 'K' value |
1147 | | * and set the version # of the superblock to 1 if it is a non-default |
1148 | | * value. |
1149 | | */ |
1150 | 0 | else if (sblock->btree_k[H5B_CHUNK_ID] != HDF5_BTREE_CHUNK_IK_DEF) |
1151 | 0 | super_vers = HDF5_SUPERBLOCK_VERSION_1; |
1152 | | |
1153 | | /* Finalize superblock version to that allowed by the file's low bound if higher */ |
1154 | 0 | super_vers = MAX(super_vers, HDF5_superblock_ver_bounds[f->shared->low_bound]); |
1155 | | |
1156 | | /* Version bounds check */ |
1157 | 0 | if (super_vers > HDF5_superblock_ver_bounds[f->shared->high_bound]) |
1158 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "superblock version out of bounds"); |
1159 | | |
1160 | | /* If a newer superblock version is required, set it here */ |
1161 | 0 | if (super_vers != HDF5_SUPERBLOCK_VERSION_DEF) { |
1162 | 0 | H5P_genplist_t *c_plist; /* Property list */ |
1163 | |
|
1164 | 0 | if (NULL == (c_plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id))) |
1165 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not property list"); |
1166 | 0 | if (H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0) |
1167 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to set superblock version"); |
1168 | 0 | } /* end if */ |
1169 | | |
1170 | 0 | if (H5FD_set_paged_aggr(f->shared->lf, (bool)H5F_PAGED_AGGR(f)) < 0) |
1171 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set paged_aggr status for file driver"); |
1172 | | |
1173 | | /* |
1174 | | * The superblock starts immediately after the user-defined |
1175 | | * header, which we have already insured is a proper size. The |
1176 | | * base address is set to the same thing as the superblock for |
1177 | | * now. |
1178 | | */ |
1179 | 0 | if (H5P_get(plist, H5F_CRT_USER_BLOCK_NAME, &userblock_size) < 0) |
1180 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get userblock size"); |
1181 | | |
1182 | | /* Sanity check the userblock size vs. the file's allocation alignment */ |
1183 | 0 | if (userblock_size > 0) { |
1184 | | /* Set up the alignment to use for page or aggr fs */ |
1185 | 0 | hsize_t alignment = H5F_PAGED_AGGR(f) ? f->shared->fs_page_size : f->shared->alignment; |
1186 | |
|
1187 | 0 | if (userblock_size < alignment) |
1188 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "userblock size must be > file object alignment"); |
1189 | 0 | if (0 != (userblock_size % alignment)) |
1190 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, |
1191 | 0 | "userblock size must be an integral multiple of file object alignment"); |
1192 | 0 | } /* end if */ |
1193 | | |
1194 | 0 | sblock->base_addr = userblock_size; |
1195 | 0 | sblock->status_flags = 0; |
1196 | | |
1197 | | /* Reserve space for the userblock */ |
1198 | 0 | if (H5F__set_eoa(f, H5FD_MEM_SUPER, userblock_size) < 0) |
1199 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set EOA value for userblock"); |
1200 | | |
1201 | | /* Set the base address for the file in the VFD now, after allocating |
1202 | | * space for userblock. |
1203 | | */ |
1204 | 0 | if (H5F__set_base_addr(f, sblock->base_addr) < 0) |
1205 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver"); |
1206 | | |
1207 | | /* Save a local copy of the superblock version number, size of addresses & offsets */ |
1208 | 0 | sblock->super_vers = super_vers; |
1209 | 0 | sblock->sizeof_addr = f->shared->sizeof_addr; |
1210 | 0 | sblock->sizeof_size = f->shared->sizeof_size; |
1211 | | |
1212 | | /* Compute the size of the superblock */ |
1213 | 0 | superblock_size = (hsize_t)H5F_SUPERBLOCK_SIZE(sblock); |
1214 | | |
1215 | | /* Compute the size of the driver information block */ |
1216 | 0 | H5_CHECKED_ASSIGN(driver_size, size_t, H5FD_sb_size(f->shared->lf), hsize_t); |
1217 | | |
1218 | | /* The following code sets driver_size to the valued needed |
1219 | | * for the driver info block, and sets the driver info block |
1220 | | * address regardless of the version of the superblock. |
1221 | | */ |
1222 | 0 | if (driver_size > 0) { |
1223 | | /* Add in the driver info header, for older superblocks */ |
1224 | | /* Superblock versions >= 2 will put the driver info in a message |
1225 | | * and don't need the header -QAK, 1/4/2017 |
1226 | | */ |
1227 | 0 | if (super_vers < HDF5_SUPERBLOCK_VERSION_2) |
1228 | 0 | driver_size += H5F_DRVINFOBLOCK_HDR_SIZE; |
1229 | | |
1230 | | /* |
1231 | | * The file driver information block begins immediately after the |
1232 | | * superblock. (relative to base address in file) |
1233 | | */ |
1234 | 0 | sblock->driver_addr = superblock_size; |
1235 | 0 | } /* end if */ |
1236 | | |
1237 | | /* |
1238 | | * Allocate space for the superblock & driver info block. |
1239 | | * We do it with one allocation request because the superblock needs to be |
1240 | | * at the beginning of the file and only the first allocation request is |
1241 | | * required to return memory at format address zero. |
1242 | | */ |
1243 | 0 | if (super_vers < HDF5_SUPERBLOCK_VERSION_2) |
1244 | 0 | superblock_size += driver_size; |
1245 | | |
1246 | | /* Set the ring type in the API context */ |
1247 | 0 | H5AC_set_ring(H5AC_RING_SB, &orig_ring); |
1248 | | |
1249 | | /* Insert superblock into cache, pinned */ |
1250 | 0 | if (H5AC_insert_entry(f, H5AC_SUPERBLOCK, (haddr_t)0, sblock, |
1251 | 0 | H5AC__PIN_ENTRY_FLAG | H5AC__FLUSH_LAST_FLAG | H5AC__FLUSH_COLLECTIVELY_FLAG) < 0) |
1252 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINS, FAIL, "can't add superblock to cache"); |
1253 | 0 | sblock_in_cache = true; |
1254 | | |
1255 | | /* Keep a copy of the superblock info */ |
1256 | 0 | f->shared->sblock = sblock; |
1257 | | |
1258 | | /* Allocate space for the superblock */ |
1259 | 0 | if (HADDR_UNDEF == (superblock_addr = H5MF_alloc(f, H5FD_MEM_SUPER, superblock_size))) |
1260 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "file allocation failed for superblock"); |
1261 | | |
1262 | | /* set the drvinfo filed to NULL -- will overwrite this later if needed */ |
1263 | 0 | f->shared->drvinfo = NULL; |
1264 | | |
1265 | | /* |
1266 | | * Determine if we will need a superblock extension |
1267 | | */ |
1268 | | |
1269 | | /* Files with SOHM indices always need the superblock extension */ |
1270 | 0 | if (f->shared->sohm_nindexes > 0) { |
1271 | 0 | assert(super_vers >= HDF5_SUPERBLOCK_VERSION_2); |
1272 | 0 | need_ext = true; |
1273 | 0 | } /* end if */ |
1274 | | /* Files with non-default free space settings always need the superblock extension */ |
1275 | 0 | else if (non_default_fs_settings) { |
1276 | 0 | assert(super_vers >= HDF5_SUPERBLOCK_VERSION_2); |
1277 | 0 | need_ext = true; |
1278 | 0 | } /* end if */ |
1279 | | /* If we're going to use a version of the superblock format which allows |
1280 | | * for the superblock extension, check for non-default values to store |
1281 | | * in it. |
1282 | | */ |
1283 | 0 | else if (super_vers >= HDF5_SUPERBLOCK_VERSION_2) { |
1284 | | /* Check for non-default v1 B-tree 'K' values to store */ |
1285 | 0 | if (sblock->btree_k[H5B_SNODE_ID] != HDF5_BTREE_SNODE_IK_DEF || |
1286 | 0 | sblock->btree_k[H5B_CHUNK_ID] != HDF5_BTREE_CHUNK_IK_DEF || |
1287 | 0 | sblock->sym_leaf_k != H5F_CRT_SYM_LEAF_DEF) |
1288 | 0 | need_ext = true; |
1289 | | /* Check for driver info to store */ |
1290 | 0 | else if (driver_size > 0) |
1291 | 0 | need_ext = true; |
1292 | 0 | else |
1293 | 0 | need_ext = false; |
1294 | 0 | } /* end if */ |
1295 | 0 | else |
1296 | 0 | need_ext = false; |
1297 | | |
1298 | | /* Set the ring type in the API context */ |
1299 | 0 | H5AC_set_ring(H5AC_RING_SBE, NULL); |
1300 | | |
1301 | | /* Create the superblock extension for "extra" superblock data, if necessary. */ |
1302 | 0 | if (need_ext) { |
1303 | | /* The superblock extension isn't actually a group, but the |
1304 | | * default group creation list should work fine. |
1305 | | * If we don't supply a size for the object header, HDF5 will |
1306 | | * allocate H5O_MIN_SIZE by default. This is currently |
1307 | | * big enough to hold the biggest possible extension, but should |
1308 | | * be tuned if more information is added to the superblock |
1309 | | * extension. |
1310 | | */ |
1311 | 0 | if (H5F__super_ext_create(f, &ext_loc) < 0) |
1312 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "unable to create superblock extension"); |
1313 | 0 | ext_created = true; |
1314 | | |
1315 | | /* Create the Shared Object Header Message table and register it with |
1316 | | * the metadata cache, if this file supports shared messages. |
1317 | | */ |
1318 | 0 | if (f->shared->sohm_nindexes > 0) { |
1319 | | /* Initialize the shared message code & write the SOHM message to the extension */ |
1320 | 0 | if (H5SM_init(f, plist, &ext_loc) < 0) |
1321 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create SOHM table"); |
1322 | 0 | } |
1323 | | |
1324 | | /* Check for non-default v1 B-tree 'K' values to store */ |
1325 | 0 | if (sblock->btree_k[H5B_SNODE_ID] != HDF5_BTREE_SNODE_IK_DEF || |
1326 | 0 | sblock->btree_k[H5B_CHUNK_ID] != HDF5_BTREE_CHUNK_IK_DEF || |
1327 | 0 | sblock->sym_leaf_k != H5F_CRT_SYM_LEAF_DEF) { |
1328 | 0 | H5O_btreek_t btreek; /* v1 B-tree 'K' value message for superblock extension */ |
1329 | | |
1330 | | /* Write v1 B-tree 'K' value information to the superblock extension */ |
1331 | 0 | btreek.btree_k[H5B_CHUNK_ID] = sblock->btree_k[H5B_CHUNK_ID]; |
1332 | 0 | btreek.btree_k[H5B_SNODE_ID] = sblock->btree_k[H5B_SNODE_ID]; |
1333 | 0 | btreek.sym_leaf_k = sblock->sym_leaf_k; |
1334 | 0 | if (H5O_msg_create(&ext_loc, H5O_BTREEK_ID, H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_DONTSHARE, |
1335 | 0 | H5O_UPDATE_TIME, &btreek) < 0) |
1336 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, |
1337 | 0 | "unable to update v1 B-tree 'K' value header message"); |
1338 | 0 | } /* end if */ |
1339 | | |
1340 | | /* Check for driver info to store */ |
1341 | 0 | if (driver_size > 0) { |
1342 | 0 | H5O_drvinfo_t info; /* Driver info */ |
1343 | 0 | uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Driver info block encoding buffer */ |
1344 | | |
1345 | | /* Sanity check */ |
1346 | 0 | assert(driver_size <= H5F_MAX_DRVINFOBLOCK_SIZE); |
1347 | | |
1348 | | /* Encode driver-specific data */ |
1349 | 0 | memset(dbuf, 0, sizeof(dbuf)); |
1350 | 0 | if (H5FD_sb_encode(f->shared->lf, info.name, dbuf) < 0) |
1351 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information"); |
1352 | | |
1353 | | /* Write driver info information to the superblock extension */ |
1354 | 0 | info.len = driver_size; |
1355 | 0 | info.buf = dbuf; |
1356 | 0 | if (H5O_msg_create(&ext_loc, H5O_DRVINFO_ID, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &info) < 0) |
1357 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update driver info header message"); |
1358 | | |
1359 | 0 | assert(false == f->shared->drvinfo_sb_msg_exists); |
1360 | 0 | f->shared->drvinfo_sb_msg_exists = true; |
1361 | 0 | } /* end if */ |
1362 | | |
1363 | | /* Check for non-default free-space info settings */ |
1364 | 0 | if (non_default_fs_settings) { |
1365 | 0 | H5F_mem_page_t ptype; |
1366 | 0 | H5O_fsinfo_t fsinfo; /* Free space manager info message */ |
1367 | | |
1368 | | /* Write free-space manager info message to superblock extension object header if needed */ |
1369 | 0 | fsinfo.strategy = f->shared->fs_strategy; |
1370 | 0 | fsinfo.persist = f->shared->fs_persist; |
1371 | 0 | fsinfo.threshold = f->shared->fs_threshold; |
1372 | 0 | fsinfo.page_size = f->shared->fs_page_size; |
1373 | 0 | fsinfo.pgend_meta_thres = f->shared->pgend_meta_thres; |
1374 | 0 | fsinfo.eoa_pre_fsm_fsalloc = HADDR_UNDEF; |
1375 | 0 | fsinfo.mapped = false; |
1376 | | |
1377 | | /* Set the version for the fsinfo message */ |
1378 | 0 | if (H5O_fsinfo_set_version(H5F_LOW_BOUND(f), H5F_HIGH_BOUND(f), &fsinfo) < 0) |
1379 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set version of fsinfo"); |
1380 | 0 | f->shared->fs_version = fsinfo.version; |
1381 | |
|
1382 | 0 | for (ptype = H5F_MEM_PAGE_SUPER; ptype < H5F_MEM_PAGE_NTYPES; ptype++) |
1383 | 0 | fsinfo.fs_addr[ptype - 1] = HADDR_UNDEF; |
1384 | |
|
1385 | 0 | if (H5O_msg_create(&ext_loc, H5O_FSINFO_ID, H5O_MSG_FLAG_DONTSHARE | H5O_MSG_FLAG_MARK_IF_UNKNOWN, |
1386 | 0 | H5O_UPDATE_TIME, &fsinfo) < 0) |
1387 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update free-space info header message"); |
1388 | 0 | } /* end if */ |
1389 | 0 | } /* end if */ |
1390 | 0 | else { |
1391 | | /* Check for creating an "old-style" driver info block */ |
1392 | 0 | if (driver_size > 0) { |
1393 | | /* Sanity check */ |
1394 | 0 | assert(H5_addr_defined(sblock->driver_addr)); |
1395 | | |
1396 | | /* Allocate space for the driver info */ |
1397 | 0 | if (NULL == (drvinfo = (H5O_drvinfo_t *)H5MM_calloc(sizeof(H5O_drvinfo_t)))) |
1398 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, |
1399 | 0 | "memory allocation failed for driver info message"); |
1400 | | |
1401 | | /* Set up driver info message */ |
1402 | | /* (NOTE: All the actual information (name & driver information) is |
1403 | | * actually based on the VFD info in the file handle and |
1404 | | * will be encoded by the VFD's 'encode' callback, so it |
1405 | | * doesn't need to be set here. -QAK, 7/20/2013 |
1406 | | */ |
1407 | 0 | H5_CHECKED_ASSIGN(drvinfo->len, size_t, H5FD_sb_size(f->shared->lf), hsize_t); |
1408 | | |
1409 | | /* Insert driver info block into cache */ |
1410 | 0 | if (H5AC_insert_entry(f, H5AC_DRVRINFO, sblock->driver_addr, drvinfo, |
1411 | 0 | H5AC__PIN_ENTRY_FLAG | H5AC__FLUSH_LAST_FLAG | |
1412 | 0 | H5AC__FLUSH_COLLECTIVELY_FLAG) < 0) |
1413 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINS, FAIL, "can't add driver info block to cache"); |
1414 | 0 | drvinfo_in_cache = true; |
1415 | 0 | f->shared->drvinfo = drvinfo; |
1416 | 0 | } /* end if */ |
1417 | 0 | else |
1418 | 0 | assert(!H5_addr_defined(sblock->driver_addr)); |
1419 | 0 | } /* end if */ |
1420 | | |
1421 | 0 | done: |
1422 | | /* Reset the ring in the API context */ |
1423 | 0 | if (orig_ring != H5AC_RING_INV) |
1424 | 0 | H5AC_set_ring(orig_ring, NULL); |
1425 | | |
1426 | | /* Close superblock extension, if it was created */ |
1427 | 0 | if (ext_created && H5F__super_ext_close(f, &ext_loc, ext_created) < 0) |
1428 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension"); |
1429 | | |
1430 | | /* Cleanup on failure */ |
1431 | 0 | if (ret_value < 0) { |
1432 | | /* Check if the driver info block has been allocated yet */ |
1433 | 0 | if (drvinfo) { |
1434 | | /* Check if we've cached it already */ |
1435 | 0 | if (drvinfo_in_cache) { |
1436 | | /* Unpin drvinfo in cache */ |
1437 | 0 | if (H5AC_unpin_entry(drvinfo) < 0) |
1438 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTUNPIN, FAIL, "unable to unpin driver info"); |
1439 | | |
1440 | | /* Evict the driver info block from the cache */ |
1441 | 0 | if (H5AC_expunge_entry(f, H5AC_DRVRINFO, sblock->driver_addr, H5AC__NO_FLAGS_SET) < 0) |
1442 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, FAIL, "unable to expunge driver info block"); |
1443 | 0 | } /* end if */ |
1444 | 0 | else |
1445 | | /* Free driver info block */ |
1446 | 0 | H5MM_xfree(drvinfo); |
1447 | 0 | } /* end if */ |
1448 | | |
1449 | | /* Check if the superblock has been allocated yet */ |
1450 | 0 | if (sblock) { |
1451 | 0 | if (non_default_fs_settings && H5_addr_defined(superblock_addr)) { |
1452 | | /* |
1453 | | * For non-default free-space settings, the allocation of |
1454 | | * space in the file for the superblock may have have allocated |
1455 | | * memory for the free-space manager and inserted it into the |
1456 | | * metadata cache. Clean that up before returning or we may fail |
1457 | | * to close the file later due to the metadata cache's metadata |
1458 | | * free space manager ring (H5AC_RING_MDFSM) not being clean. |
1459 | | */ |
1460 | 0 | if (H5MF_try_close(f) < 0) |
1461 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't close file free space manager"); |
1462 | 0 | } |
1463 | | |
1464 | | /* Check if we've cached it already */ |
1465 | 0 | if (sblock_in_cache) { |
1466 | | /* Unpin superblock in cache */ |
1467 | 0 | if (H5AC_unpin_entry(sblock) < 0) |
1468 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock"); |
1469 | | |
1470 | | /* Evict the superblock from the cache */ |
1471 | 0 | if (H5AC_expunge_entry(f, H5AC_SUPERBLOCK, (haddr_t)0, H5AC__NO_FLAGS_SET) < 0) |
1472 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, FAIL, "unable to expunge superblock"); |
1473 | 0 | } /* end if */ |
1474 | 0 | else |
1475 | | /* Free superblock */ |
1476 | 0 | if (H5F__super_free(sblock) < 0) |
1477 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "unable to destroy superblock"); |
1478 | | |
1479 | | /* Reset variables in file structure */ |
1480 | 0 | f->shared->sblock = NULL; |
1481 | 0 | } /* end if */ |
1482 | 0 | } /* end if */ |
1483 | |
|
1484 | 0 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
1485 | 0 | } /* end H5F__super_init() */ |
1486 | | |
1487 | | /*------------------------------------------------------------------------- |
1488 | | * Function: H5F_eoa_dirty |
1489 | | * |
1490 | | * Purpose: Mark the file's EOA info dirty |
1491 | | * |
1492 | | * Return: Success: non-negative on success |
1493 | | * Failure: Negative |
1494 | | * |
1495 | | *------------------------------------------------------------------------- |
1496 | | */ |
1497 | | herr_t |
1498 | | H5F_eoa_dirty(H5F_t *f) |
1499 | 1.04k | { |
1500 | 1.04k | herr_t ret_value = SUCCEED; /* Return value */ |
1501 | | |
1502 | 1.04k | FUNC_ENTER_NOAPI(FAIL) |
1503 | | |
1504 | | /* Sanity check */ |
1505 | 1.04k | assert(f); |
1506 | 1.04k | assert(f->shared); |
1507 | 1.04k | assert(f->shared->sblock); |
1508 | | |
1509 | | /* Mark superblock dirty in cache, so change to EOA will get encoded */ |
1510 | 1.04k | if (H5F_super_dirty(f) < 0) |
1511 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty"); |
1512 | | |
1513 | | /* If the driver information block exists, mark it dirty as well |
1514 | | * so that the change in eoa will be reflected there as well if |
1515 | | * appropriate. |
1516 | | */ |
1517 | 1.04k | if (f->shared->drvinfo) { |
1518 | 305 | if (H5AC_mark_entry_dirty(f->shared->drvinfo) < 0) |
1519 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark drvinfo as dirty"); |
1520 | 305 | } /* end if */ |
1521 | | /* If the driver info is stored as a message, update that instead */ |
1522 | 742 | else if (f->shared->drvinfo_sb_msg_exists) { |
1523 | 0 | if (H5F__update_super_ext_driver_msg(f) < 0) |
1524 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark drvinfo message as dirty"); |
1525 | 0 | } |
1526 | | |
1527 | 1.04k | done: |
1528 | 1.04k | FUNC_LEAVE_NOAPI(ret_value) |
1529 | 1.04k | } /* H5F_eoa_dirty() */ |
1530 | | |
1531 | | /*------------------------------------------------------------------------- |
1532 | | * Function: H5F_super_dirty |
1533 | | * |
1534 | | * Purpose: Mark the file's superblock dirty |
1535 | | * |
1536 | | * Return: Success: non-negative on success |
1537 | | * Failure: Negative |
1538 | | * |
1539 | | *------------------------------------------------------------------------- |
1540 | | */ |
1541 | | herr_t |
1542 | | H5F_super_dirty(H5F_t *f) |
1543 | 1.81k | { |
1544 | 1.81k | herr_t ret_value = SUCCEED; /* Return value */ |
1545 | | |
1546 | 1.81k | FUNC_ENTER_NOAPI(FAIL) |
1547 | | |
1548 | | /* Sanity check */ |
1549 | 1.81k | assert(f); |
1550 | 1.81k | assert(f->shared); |
1551 | 1.81k | assert(f->shared->sblock); |
1552 | | |
1553 | | /* Mark superblock dirty in cache, so change to EOA will get encoded */ |
1554 | 1.81k | if (H5AC_mark_entry_dirty(f->shared->sblock) < 0) |
1555 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty"); |
1556 | | |
1557 | 1.81k | done: |
1558 | 1.81k | FUNC_LEAVE_NOAPI(ret_value) |
1559 | 1.81k | } /* H5F_super_dirty() */ |
1560 | | |
1561 | | /*------------------------------------------------------------------------- |
1562 | | * Function: H5F__super_free |
1563 | | * |
1564 | | * Purpose: Destroyer the file's superblock |
1565 | | * |
1566 | | * Return: Success: non-negative on success |
1567 | | * Failure: Negative |
1568 | | * |
1569 | | *------------------------------------------------------------------------- |
1570 | | */ |
1571 | | herr_t |
1572 | | H5F__super_free(H5F_super_t *sblock) |
1573 | 1.59k | { |
1574 | 1.59k | FUNC_ENTER_PACKAGE_NOERR |
1575 | | |
1576 | | /* Sanity check */ |
1577 | 1.59k | assert(sblock); |
1578 | | |
1579 | | /* Free root group symbol table entry, if any */ |
1580 | 1.59k | sblock->root_ent = (H5G_entry_t *)H5MM_xfree(sblock->root_ent); |
1581 | | |
1582 | | /* Free superblock */ |
1583 | 1.59k | sblock = (H5F_super_t *)H5FL_FREE(H5F_super_t, sblock); |
1584 | | |
1585 | 1.59k | FUNC_LEAVE_NOAPI(SUCCEED) |
1586 | 1.59k | } /* H5F__super_free() */ |
1587 | | |
1588 | | /*------------------------------------------------------------------------- |
1589 | | * Function: H5F__super_size |
1590 | | * |
1591 | | * Purpose: Get storage size of the superblock and superblock extension |
1592 | | * |
1593 | | * Return: Success: non-negative on success |
1594 | | * Failure: Negative |
1595 | | * |
1596 | | *------------------------------------------------------------------------- |
1597 | | */ |
1598 | | herr_t |
1599 | | H5F__super_size(H5F_t *f, hsize_t *super_size, hsize_t *super_ext_size) |
1600 | 0 | { |
1601 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
1602 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1603 | |
|
1604 | 0 | FUNC_ENTER_PACKAGE |
1605 | | |
1606 | | /* Sanity check */ |
1607 | 0 | assert(f); |
1608 | 0 | assert(f->shared); |
1609 | 0 | assert(f->shared->sblock); |
1610 | | |
1611 | | /* Set the superblock size */ |
1612 | 0 | if (super_size) |
1613 | 0 | *super_size = (hsize_t)H5F_SUPERBLOCK_SIZE(f->shared->sblock); |
1614 | | |
1615 | | /* Set the superblock extension size */ |
1616 | 0 | if (super_ext_size) { |
1617 | 0 | if (H5_addr_defined(f->shared->sblock->ext_addr)) { |
1618 | 0 | H5O_loc_t ext_loc; /* "Object location" for superblock extension */ |
1619 | 0 | H5O_hdr_info_t hdr_info; /* Object info for superblock extension */ |
1620 | | |
1621 | | /* Set up "fake" object location for superblock extension */ |
1622 | 0 | H5O_loc_reset(&ext_loc); |
1623 | 0 | ext_loc.file = f; |
1624 | 0 | ext_loc.addr = f->shared->sblock->ext_addr; |
1625 | | |
1626 | | /* Set the ring type in the API context */ |
1627 | 0 | H5AC_set_ring(H5AC_RING_SBE, &orig_ring); |
1628 | | |
1629 | | /* Get object header info for superblock extension */ |
1630 | 0 | if (H5O_get_hdr_info(&ext_loc, &hdr_info) < 0) |
1631 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve superblock extension info"); |
1632 | | |
1633 | | /* Set the superblock extension size */ |
1634 | 0 | *super_ext_size = hdr_info.space.total; |
1635 | 0 | } /* end if */ |
1636 | 0 | else |
1637 | | /* Set the superblock extension size to zero */ |
1638 | 0 | *super_ext_size = (hsize_t)0; |
1639 | 0 | } /* end if */ |
1640 | | |
1641 | 0 | done: |
1642 | | /* Reset the ring in the API context */ |
1643 | 0 | if (orig_ring != H5AC_RING_INV) |
1644 | 0 | H5AC_set_ring(orig_ring, NULL); |
1645 | |
|
1646 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1647 | 0 | } /* H5F__super_size() */ |
1648 | | |
1649 | | /*------------------------------------------------------------------------- |
1650 | | * Function: H5F__super_ext_write_msg() |
1651 | | * |
1652 | | * Purpose: Write the message with ID to the superblock extension |
1653 | | * |
1654 | | * Return: Non-negative on success/Negative on failure |
1655 | | * |
1656 | | *------------------------------------------------------------------------- |
1657 | | */ |
1658 | | herr_t |
1659 | | H5F__super_ext_write_msg(H5F_t *f, unsigned id, void *mesg, bool may_create, unsigned mesg_flags) |
1660 | 260 | { |
1661 | 260 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
1662 | 260 | bool ext_created = false; /* Whether superblock extension was created */ |
1663 | 260 | bool ext_opened = false; /* Whether superblock extension was opened */ |
1664 | 260 | H5O_loc_t ext_loc; /* "Object location" for superblock extension */ |
1665 | 260 | htri_t status; /* Indicate whether the message exists or not */ |
1666 | 260 | herr_t ret_value = SUCCEED; /* Return value */ |
1667 | | |
1668 | 260 | FUNC_ENTER_PACKAGE |
1669 | | |
1670 | | /* Sanity checks */ |
1671 | 260 | assert(f); |
1672 | 260 | assert(f->shared); |
1673 | 260 | assert(f->shared->sblock); |
1674 | | |
1675 | | /* Set the ring type in the API context */ |
1676 | 260 | H5AC_set_ring(H5AC_RING_SBE, &orig_ring); |
1677 | | |
1678 | | /* Open/create the superblock extension object header */ |
1679 | 260 | if (H5_addr_defined(f->shared->sblock->ext_addr)) { |
1680 | 207 | if (H5F__super_ext_open(f, f->shared->sblock->ext_addr, &ext_loc) < 0) |
1681 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open file's superblock extension"); |
1682 | 207 | } /* end if */ |
1683 | 53 | else { |
1684 | 53 | assert(may_create); |
1685 | 53 | if (H5F__super_ext_create(f, &ext_loc) < 0) |
1686 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "unable to create file's superblock extension"); |
1687 | 53 | ext_created = true; |
1688 | 53 | } /* end else */ |
1689 | 260 | assert(H5_addr_defined(ext_loc.addr)); |
1690 | 260 | ext_opened = true; |
1691 | | |
1692 | | /* Check if message with ID does not exist in the object header */ |
1693 | 260 | if ((status = H5O_msg_exists(&ext_loc, id)) < 0) |
1694 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, |
1695 | 260 | "unable to check object header for message or message exists"); |
1696 | | |
1697 | | /* Check for creating vs. writing */ |
1698 | 260 | if (may_create) { |
1699 | 119 | if (status) |
1700 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "Message should not exist"); |
1701 | | |
1702 | | /* Create the message with ID in the superblock extension */ |
1703 | 119 | if (H5O_msg_create(&ext_loc, id, (mesg_flags | H5O_MSG_FLAG_DONTSHARE), H5O_UPDATE_TIME, mesg) < 0) |
1704 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to create the message in object header"); |
1705 | 119 | } /* end if */ |
1706 | 141 | else { |
1707 | 141 | if (!status) |
1708 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "Message should exist"); |
1709 | | |
1710 | | /* Update the message with ID in the superblock extension */ |
1711 | 141 | if (H5O_msg_write(&ext_loc, id, (mesg_flags | H5O_MSG_FLAG_DONTSHARE), H5O_UPDATE_TIME, mesg) < 0) |
1712 | 64 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to write the message in object header"); |
1713 | 141 | } /* end else */ |
1714 | | |
1715 | 260 | done: |
1716 | | /* Reset the ring in the API context */ |
1717 | 260 | if (orig_ring != H5AC_RING_INV) |
1718 | 260 | H5AC_set_ring(orig_ring, NULL); |
1719 | | |
1720 | | /* Close the superblock extension, if it was opened */ |
1721 | 260 | if (ext_opened && H5F__super_ext_close(f, &ext_loc, ext_created) < 0) |
1722 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension"); |
1723 | | |
1724 | | /* Mark superblock dirty in cache, if superblock extension was created */ |
1725 | 260 | if (ext_created && H5AC_mark_entry_dirty(f->shared->sblock) < 0) |
1726 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty"); |
1727 | | |
1728 | 260 | FUNC_LEAVE_NOAPI(ret_value) |
1729 | 260 | } /* H5F__super_ext_write_msg() */ |
1730 | | |
1731 | | /*------------------------------------------------------------------------- |
1732 | | * Function: H5F__super_ext_remove_msg |
1733 | | * |
1734 | | * Purpose: Remove the message with ID from the superblock extension |
1735 | | * |
1736 | | * Return: Non-negative on success/Negative on failure |
1737 | | * |
1738 | | *------------------------------------------------------------------------- |
1739 | | */ |
1740 | | herr_t |
1741 | | H5F__super_ext_remove_msg(H5F_t *f, unsigned id) |
1742 | 132 | { |
1743 | 132 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
1744 | 132 | H5O_loc_t ext_loc; /* "Object location" for superblock extension */ |
1745 | 132 | bool ext_opened = false; /* Whether the superblock extension was opened */ |
1746 | 132 | int null_count = 0; /* # of null messages */ |
1747 | 132 | htri_t status; /* Indicate whether the message exists or not */ |
1748 | 132 | herr_t ret_value = SUCCEED; /* Return value */ |
1749 | | |
1750 | 132 | FUNC_ENTER_PACKAGE |
1751 | | |
1752 | | /* Make sure that the superblock extension object header exists */ |
1753 | 132 | assert(H5_addr_defined(f->shared->sblock->ext_addr)); |
1754 | | |
1755 | | /* Set the ring type in the API context */ |
1756 | 132 | H5AC_set_ring(H5AC_RING_SBE, &orig_ring); |
1757 | | |
1758 | | /* Open superblock extension object header */ |
1759 | 132 | if (H5F__super_ext_open(f, f->shared->sblock->ext_addr, &ext_loc) < 0) |
1760 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "error in starting file's superblock extension"); |
1761 | 132 | ext_opened = true; |
1762 | | |
1763 | | /* Check if message with ID exists in the object header */ |
1764 | 132 | if ((status = H5O_msg_exists(&ext_loc, id)) < 0) |
1765 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check object header for message"); |
1766 | 132 | else if (status) { |
1767 | | /* message exists */ |
1768 | 132 | H5O_hdr_info_t hdr_info; /* Object header info for superblock extension */ |
1769 | | |
1770 | | /* Remove the message */ |
1771 | 132 | if (H5O_msg_remove(&ext_loc, id, H5O_ALL, true) < 0) |
1772 | 5 | HGOTO_ERROR(H5E_FILE, H5E_CANTDELETE, FAIL, "unable to delete free-space manager info message"); |
1773 | | |
1774 | | /* Get info for the superblock extension's object header */ |
1775 | 127 | if (H5O_get_hdr_info(&ext_loc, &hdr_info) < 0) |
1776 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve superblock extension info"); |
1777 | | |
1778 | | /* If the object header is an empty base chunk, remove superblock extension */ |
1779 | 127 | if (hdr_info.nchunks == 1) { |
1780 | 124 | if ((null_count = H5O_msg_count(&ext_loc, H5O_NULL_ID)) < 0) |
1781 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTCOUNT, FAIL, "unable to count messages"); |
1782 | 124 | else if ((unsigned)null_count == hdr_info.nmesgs) { |
1783 | 57 | assert(H5_addr_defined(ext_loc.addr)); |
1784 | 57 | if (H5O_delete(f, ext_loc.addr) < 0) |
1785 | 4 | HGOTO_ERROR(H5E_FILE, H5E_CANTCOUNT, FAIL, "unable to count messages"); |
1786 | 53 | f->shared->sblock->ext_addr = HADDR_UNDEF; |
1787 | 53 | } /* end else-if */ |
1788 | 124 | } /* end if */ |
1789 | 127 | } /* end if */ |
1790 | | |
1791 | 132 | done: |
1792 | | /* Reset the ring in the API context */ |
1793 | 132 | if (orig_ring != H5AC_RING_INV) |
1794 | 132 | H5AC_set_ring(orig_ring, NULL); |
1795 | | |
1796 | | /* Close superblock extension object header, if opened */ |
1797 | 132 | if (ext_opened && H5F__super_ext_close(f, &ext_loc, false) < 0) |
1798 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension"); |
1799 | | |
1800 | 132 | FUNC_LEAVE_NOAPI(ret_value) |
1801 | 132 | } /* H5F__super_ext_remove_msg() */ |