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