Coverage Report

Created: 2024-06-18 06:29

/src/hdf5/src/H5Fio.c
Line
Count
Source (jump to first uncovered line)
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 COPYING 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
 *
15
 * Created:             H5Fio.c
16
 *
17
 * Purpose:             File I/O routines.
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5Fmodule.h" /* This source code file is part of the H5F module */
27
28
/***********/
29
/* Headers */
30
/***********/
31
#include "H5private.h"   /* Generic Functions     */
32
#include "H5Eprivate.h"  /* Error handling        */
33
#include "H5Fpkg.h"      /* File access       */
34
#include "H5FDprivate.h" /* File drivers        */
35
#include "H5PBprivate.h" /* Page Buffer       */
36
37
/****************/
38
/* Local Macros */
39
/****************/
40
41
/******************/
42
/* Local Typedefs */
43
/******************/
44
45
/********************/
46
/* Package Typedefs */
47
/********************/
48
49
/********************/
50
/* Local Prototypes */
51
/********************/
52
53
/*********************/
54
/* Package Variables */
55
/*********************/
56
57
/*****************************/
58
/* Library Private Variables */
59
/*****************************/
60
61
/*******************/
62
/* Local Variables */
63
/*******************/
64
65
/*-------------------------------------------------------------------------
66
 * Function:  H5F_shared_block_read
67
 *
68
 * Purpose: Reads some data from a file/server/etc into a buffer.
69
 *    The data is contiguous.  The address is relative to the base
70
 *    address for the file.
71
 *
72
 * Return:  Non-negative on success/Negative on failure
73
 *
74
 *-------------------------------------------------------------------------
75
 */
76
herr_t
77
H5F_shared_block_read(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, void *buf /*out*/)
78
0
{
79
0
    H5FD_mem_t map_type;            /* Mapped memory type */
80
0
    herr_t     ret_value = SUCCEED; /* Return value */
81
82
0
    FUNC_ENTER_NOAPI(FAIL)
83
84
    /* Sanity checks */
85
0
    assert(f_sh);
86
0
    assert(buf);
87
0
    assert(H5_addr_defined(addr));
88
89
    /* Check for attempting I/O on 'temporary' file address */
90
0
    if (H5_addr_le(f_sh->tmp_addr, (addr + size)))
91
0
        HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space");
92
93
    /* Treat global heap as raw data */
94
0
    map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type;
95
96
    /* Pass through page buffer layer */
97
0
    if (H5PB_read(f_sh, map_type, addr, size, buf) < 0)
98
0
        HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read through page buffer failed");
99
100
0
done:
101
0
    FUNC_LEAVE_NOAPI(ret_value)
102
0
} /* end H5F_shared_block_read() */
103
104
/*-------------------------------------------------------------------------
105
 * Function:  H5F_block_read
106
 *
107
 * Purpose: Reads some data from a file/server/etc into a buffer.
108
 *    The data is contiguous.  The address is relative to the base
109
 *    address for the file.
110
 *
111
 * Return:  Non-negative on success/Negative on failure
112
 *
113
 *-------------------------------------------------------------------------
114
 */
115
herr_t
116
H5F_block_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, void *buf /*out*/)
117
170
{
118
170
    H5FD_mem_t map_type;            /* Mapped memory type */
119
170
    herr_t     ret_value = SUCCEED; /* Return value */
120
121
170
    FUNC_ENTER_NOAPI(FAIL)
122
123
    /* Sanity checks */
124
170
    assert(f);
125
170
    assert(f->shared);
126
170
    assert(buf);
127
170
    assert(H5_addr_defined(addr));
128
129
    /* Check for attempting I/O on 'temporary' file address */
130
170
    if (H5_addr_le(f->shared->tmp_addr, (addr + size)))
131
0
        HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space");
132
133
    /* Treat global heap as raw data */
134
170
    map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type;
135
136
    /* Pass through page buffer layer */
137
170
    if (H5PB_read(f->shared, map_type, addr, size, buf) < 0)
138
0
        HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read through page buffer failed");
139
140
170
done:
141
170
    FUNC_LEAVE_NOAPI(ret_value)
142
170
} /* end H5F_block_read() */
143
144
/*-------------------------------------------------------------------------
145
 * Function:  H5F_shared_block_write
146
 *
147
 * Purpose: Writes some data from memory to a file/server/etc.  The
148
 *    data is contiguous.  The address is relative to the base
149
 *    address.
150
 *
151
 * Return:  Non-negative on success/Negative on failure
152
 *
153
 *-------------------------------------------------------------------------
154
 */
155
herr_t
156
H5F_shared_block_write(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf)
157
0
{
158
0
    H5FD_mem_t map_type;            /* Mapped memory type */
159
0
    herr_t     ret_value = SUCCEED; /* Return value */
160
161
0
    FUNC_ENTER_NOAPI(FAIL)
162
163
    /* Sanity checks */
164
0
    assert(f_sh);
165
0
    assert(H5F_SHARED_INTENT(f_sh) & H5F_ACC_RDWR);
166
0
    assert(buf);
167
0
    assert(H5_addr_defined(addr));
168
169
    /* Check for attempting I/O on 'temporary' file address */
170
0
    if (H5_addr_le(f_sh->tmp_addr, (addr + size)))
171
0
        HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space");
172
173
    /* Treat global heap as raw data */
174
0
    map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type;
175
176
    /* Pass through page buffer layer */
177
0
    if (H5PB_write(f_sh, map_type, addr, size, buf) < 0)
178
0
        HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write through page buffer failed");
179
180
0
done:
181
0
    FUNC_LEAVE_NOAPI(ret_value)
182
0
} /* end H5F_shared_block_write() */
183
184
/*-------------------------------------------------------------------------
185
 * Function:  H5F_block_write
186
 *
187
 * Purpose: Writes some data from memory to a file/server/etc.  The
188
 *    data is contiguous.  The address is relative to the base
189
 *    address.
190
 *
191
 * Return:  Non-negative on success/Negative on failure
192
 *
193
 *-------------------------------------------------------------------------
194
 */
195
herr_t
196
H5F_block_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf)
197
0
{
198
0
    H5FD_mem_t map_type;            /* Mapped memory type */
199
0
    herr_t     ret_value = SUCCEED; /* Return value */
200
201
0
    FUNC_ENTER_NOAPI(FAIL)
202
203
    /* Sanity checks */
204
0
    assert(f);
205
0
    assert(f->shared);
206
0
    assert(H5F_INTENT(f) & H5F_ACC_RDWR);
207
0
    assert(buf);
208
0
    assert(H5_addr_defined(addr));
209
210
    /* Check for attempting I/O on 'temporary' file address */
211
0
    if (H5_addr_le(f->shared->tmp_addr, (addr + size)))
212
0
        HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space");
213
214
    /* Treat global heap as raw data */
215
0
    map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type;
216
217
    /* Pass through page buffer layer */
218
0
    if (H5PB_write(f->shared, map_type, addr, size, buf) < 0)
219
0
        HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write through page buffer failed");
220
0
done:
221
0
    FUNC_LEAVE_NOAPI(ret_value)
222
0
} /* end H5F_block_write() */
223
224
/*-------------------------------------------------------------------------
225
 * Function:    H5F_shared_select_read
226
 *
227
 * Purpose:     Reads some data from a file/server/etc into a buffer.
228
 *              The location of the data is defined by the mem_spaces and
229
 *              file_spaces dataspace arrays, along with the offsets
230
 *              array.  The addresses is relative to the base address for
231
 *              the file.
232
 *
233
 * Return:      Non-negative on success/Negative on failure
234
 *
235
 *-------------------------------------------------------------------------
236
 */
237
herr_t
238
H5F_shared_select_read(H5F_shared_t *f_sh, H5FD_mem_t type, uint32_t count, H5S_t **mem_spaces,
239
                       H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], void *bufs[] /* out */)
240
0
{
241
0
    H5FD_mem_t map_type;            /* Mapped memory type */
242
0
    herr_t     ret_value = SUCCEED; /* Return value */
243
244
0
    FUNC_ENTER_NOAPI(FAIL)
245
246
    /* Sanity checks */
247
0
    assert(f_sh);
248
0
    assert((mem_spaces) || (count == 0));
249
0
    assert((file_spaces) || (count == 0));
250
0
    assert((offsets) || (count == 0));
251
0
    assert((element_sizes) || (count == 0));
252
0
    assert((bufs) || (count == 0));
253
254
    /* Treat global heap as raw data */
255
0
    map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type;
256
257
    /* Pass down to file driver layer (bypass page buffer for now) */
258
0
    if (H5FD_read_selection(f_sh->lf, map_type, count, mem_spaces, file_spaces, offsets, element_sizes,
259
0
                            bufs) < 0)
260
0
        HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "selection read through file driver failed");
261
262
0
done:
263
0
    FUNC_LEAVE_NOAPI(ret_value)
264
0
} /* end H5F_shared_select_read() */
265
266
/*-------------------------------------------------------------------------
267
 * Function:    H5F_shared_select_write
268
 *
269
 * Purpose:     Writes some data from a buffer to a file/server/etc.
270
 *              The location of the data is defined by the mem_spaces and
271
 *              file_spaces dataspace arrays, along with the offsets
272
 *              array.  The addresses is relative to the base address for
273
 *              the file.
274
 *
275
 * Return:      Non-negative on success/Negative on failure
276
 *
277
 *-------------------------------------------------------------------------
278
 */
279
herr_t
280
H5F_shared_select_write(H5F_shared_t *f_sh, H5FD_mem_t type, uint32_t count, H5S_t **mem_spaces,
281
                        H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], const void *bufs[])
282
0
{
283
0
    H5FD_mem_t map_type;            /* Mapped memory type */
284
0
    herr_t     ret_value = SUCCEED; /* Return value */
285
286
0
    FUNC_ENTER_NOAPI(FAIL)
287
288
    /* Sanity checks */
289
0
    assert(f_sh);
290
0
    assert((mem_spaces) || (count == 0));
291
0
    assert((file_spaces) || (count == 0));
292
0
    assert((offsets) || (count == 0));
293
0
    assert((element_sizes) || (count == 0));
294
0
    assert((bufs) || (count == 0));
295
296
    /* Treat global heap as raw data */
297
0
    map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type;
298
299
    /* Pass down to file driver layer (bypass page buffer for now) */
300
0
    if (H5FD_write_selection(f_sh->lf, map_type, count, mem_spaces, file_spaces, offsets, element_sizes,
301
0
                             bufs) < 0)
302
0
        HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "selection write through file driver failed");
303
304
0
done:
305
0
    FUNC_LEAVE_NOAPI(ret_value)
306
0
} /* end H5F_shared_select_write() */
307
308
herr_t
309
H5F_shared_vector_read(H5F_shared_t *f_sh, uint32_t count, H5FD_mem_t types[], haddr_t addrs[],
310
                       size_t sizes[], void *bufs[])
311
0
{
312
0
    herr_t ret_value = SUCCEED;
313
314
0
    FUNC_ENTER_NOAPI(FAIL)
315
316
    /* Sanity checks */
317
0
    assert(f_sh);
318
0
    assert((types) || (count == 0));
319
0
    assert((addrs) || (count == 0));
320
0
    assert((sizes) || (count == 0));
321
0
    assert((bufs) || (count == 0));
322
323
    /*
324
     * Note that we don't try to map global heap data to raw
325
     * data here, as it may become expensive to check for when
326
     * I/O vectors are large. This may change in the future, but,
327
     * for now, assume the caller has done this already.
328
     */
329
#ifndef NDEBUG
330
    for (uint32_t i = 0; i < count; i++) {
331
        /* Break early if H5FD_MEM_NOLIST was specified
332
         * since a full 'count'-sized array may not
333
         * have been passed for 'types'
334
         */
335
        if (i > 0 && types[i] == H5FD_MEM_NOLIST)
336
            break;
337
338
        assert(types[i] != H5FD_MEM_GHEAP);
339
    }
340
#endif
341
342
    /* Pass down to file driver layer (bypass page buffer for now) */
343
0
    if (H5FD_read_vector(f_sh->lf, count, types, addrs, sizes, bufs) < 0)
344
0
        HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read through file driver failed");
345
346
0
done:
347
0
    FUNC_LEAVE_NOAPI(ret_value)
348
0
}
349
350
/*-------------------------------------------------------------------------
351
 * Function:    H5F_shared_vector_write
352
 *
353
 * Purpose:     Writes data from `count` buffers (from the `bufs` array) to
354
 *              a file/server/etc. at the offsets provided in the `addrs`
355
 *              array, with the data sizes specified in the `sizes` array
356
 *              and data memory types specified in the `types` array. The
357
 *              addresses are relative to the base address for the file.
358
 *
359
 *-------------------------------------------------------------------------
360
 */
361
herr_t
362
H5F_shared_vector_write(H5F_shared_t *f_sh, uint32_t count, H5FD_mem_t types[], haddr_t addrs[],
363
                        size_t sizes[], const void *bufs[])
364
0
{
365
0
    herr_t ret_value = SUCCEED;
366
367
0
    FUNC_ENTER_NOAPI(FAIL)
368
369
    /* Sanity checks */
370
0
    assert(f_sh);
371
0
    assert((types) || (count == 0));
372
0
    assert((addrs) || (count == 0));
373
0
    assert((sizes) || (count == 0));
374
0
    assert((bufs) || (count == 0));
375
376
    /*
377
     * Note that we don't try to map global heap data to raw
378
     * data here, as it may become expensive to check for when
379
     * I/O vectors are large. This may change in the future, but,
380
     * for now, assume the caller has done this already.
381
     */
382
#ifndef NDEBUG
383
    for (uint32_t i = 0; i < count; i++) {
384
        /* Break early if H5FD_MEM_NOLIST was specified
385
         * since a full 'count'-sized array may not
386
         * have been passed for 'types'
387
         */
388
        if (i > 0 && types[i] == H5FD_MEM_NOLIST)
389
            break;
390
391
        assert(types[i] != H5FD_MEM_GHEAP);
392
    }
393
#endif
394
395
    /* Pass down to file driver layer (bypass page buffer for now) */
396
0
    if (H5FD_write_vector(f_sh->lf, count, types, addrs, sizes, bufs) < 0)
397
0
        HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write through file driver failed");
398
399
0
done:
400
0
    FUNC_LEAVE_NOAPI(ret_value)
401
0
}
402
403
/*-------------------------------------------------------------------------
404
 * Function:    H5F_flush_tagged_metadata
405
 *
406
 * Purpose:     Flushes metadata with specified tag in the metadata cache
407
 *              to disk.
408
 *
409
 * Return:      Non-negative on success/Negative on failure
410
 *
411
 *-------------------------------------------------------------------------
412
 */
413
herr_t
414
H5F_flush_tagged_metadata(H5F_t *f, haddr_t tag)
415
0
{
416
0
    herr_t ret_value = SUCCEED;
417
418
0
    FUNC_ENTER_NOAPI(FAIL)
419
420
    /* Use tag to search for and flush associated metadata */
421
0
    if (H5AC_flush_tagged_metadata(f, tag) < 0)
422
0
        HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush tagged metadata");
423
424
    /* Flush and reset the accumulator */
425
0
    if (H5F__accum_reset(f->shared, true) < 0)
426
0
        HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator");
427
428
    /* Flush file buffers to disk. */
429
0
    if (H5FD_flush(f->shared->lf, false) < 0)
430
0
        HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed");
431
432
0
done:
433
0
    FUNC_LEAVE_NOAPI(ret_value)
434
0
} /* end H5F_flush_tagged_metadata */
435
436
/*-------------------------------------------------------------------------
437
 * Function:    H5F__evict_cache_entries
438
 *
439
 * Purpose:     To evict all cache entries except the pinned superblock entry
440
 *
441
 * Return:      Non-negative on success/Negative on failure
442
 *
443
 *-------------------------------------------------------------------------
444
 */
445
herr_t
446
H5F__evict_cache_entries(H5F_t *f)
447
0
{
448
0
    herr_t ret_value = SUCCEED;
449
450
0
    FUNC_ENTER_PACKAGE
451
452
0
    assert(f);
453
0
    assert(f->shared);
454
455
    /* Evict all except pinned entries in the cache */
456
0
    if (H5AC_evict(f) < 0)
457
0
        HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "unable to evict all except pinned entries");
458
459
#ifndef NDEBUG
460
    {
461
        unsigned status = 0;
462
        uint32_t cur_num_entries;
463
464
        /* Retrieve status of the superblock */
465
        if (H5AC_get_entry_status(f, (haddr_t)0, &status) < 0)
466
            HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to get entry status");
467
468
        /* Verify status of the superblock entry in the cache */
469
        if (!(status & H5AC_ES__IN_CACHE) || !(status & H5AC_ES__IS_PINNED))
470
            HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to get entry status");
471
472
        /* Get the number of cache entries */
473
        if (H5AC_get_cache_size(f->shared->cache, NULL, NULL, NULL, &cur_num_entries) < 0)
474
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_get_cache_size() failed.");
475
476
        /* Should be the only one left in the cache (the superblock) */
477
        if (cur_num_entries != 1)
478
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "number of cache entries is not correct");
479
    }
480
#endif /* NDEBUG */
481
482
0
done:
483
0
    FUNC_LEAVE_NOAPI(ret_value)
484
0
} /* end H5F__evict_cache_entries() */
485
486
/*-------------------------------------------------------------------------
487
 * Function:    H5F_get_checksums
488
 *
489
 * Purpose:     Decode checksum stored in the buffer
490
 *    Calculate checksum for the data in the buffer
491
 *
492
 * Note:  Assumes that the checksum is the last data in the buffer
493
 *
494
 * Return:      Non-negative on success/Negative on failure
495
 *
496
 *-------------------------------------------------------------------------
497
 */
498
herr_t
499
H5F_get_checksums(const uint8_t *buf, size_t buf_size, uint32_t *s_chksum /*out*/, uint32_t *c_chksum /*out*/)
500
0
{
501
0
    herr_t ret_value = SUCCEED;
502
503
0
    FUNC_ENTER_NOAPI_NOINIT
504
505
    /* Check arguments */
506
0
    assert(buf);
507
0
    assert(buf_size);
508
509
    /* Check for buffer size smaller than H5_SIZEOF_CHKSUM */
510
0
    if (buf_size < H5_SIZEOF_CHKSUM)
511
0
        HGOTO_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "checksum buffer is smaller than expected");
512
513
    /* Return the stored checksum */
514
0
    if (s_chksum) {
515
0
        const uint8_t *chk_p; /* Pointer into raw data buffer */
516
517
        /* Offset to the checksum in the buffer */
518
0
        chk_p = buf + buf_size - H5_SIZEOF_CHKSUM;
519
520
        /* Decode the checksum stored in the buffer */
521
0
        UINT32DECODE(chk_p, *s_chksum);
522
0
    } /* end if */
523
524
    /* Return the computed checksum for the buffer */
525
0
    if (c_chksum)
526
0
        *c_chksum = H5_checksum_metadata(buf, buf_size - H5_SIZEOF_CHKSUM, 0);
527
528
0
done:
529
0
    FUNC_LEAVE_NOAPI(ret_value)
530
0
} /* end H5F_get_chksums() */