Coverage Report

Created: 2025-10-10 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Fsuper.c
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() */