/src/hdf5/src/H5Fsuper_cache.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 | | * |
15 | | * Created: H5Fsuper_cache.c |
16 | | * |
17 | | * Purpose: Implement file superblock & driver info metadata cache methods |
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 | | #define H5G_FRIEND /*suppress error about including H5Gpkg */ |
28 | | |
29 | | /***********/ |
30 | | /* Headers */ |
31 | | /***********/ |
32 | | #include "H5private.h" /* Generic Functions */ |
33 | | #include "H5Eprivate.h" /* Error handling */ |
34 | | #include "H5Fpkg.h" /* File access */ |
35 | | #include "H5FDprivate.h" /* File drivers */ |
36 | | #include "H5FLprivate.h" /* Free Lists */ |
37 | | #include "H5Gpkg.h" /* Groups */ |
38 | | #include "H5MMprivate.h" /* Memory management */ |
39 | | |
40 | | /****************/ |
41 | | /* Local Macros */ |
42 | | /****************/ |
43 | | |
44 | | /******************/ |
45 | | /* Local Typedefs */ |
46 | | /******************/ |
47 | | |
48 | | /********************/ |
49 | | /* Package Typedefs */ |
50 | | /********************/ |
51 | | |
52 | | /********************/ |
53 | | /* Local Prototypes */ |
54 | | /********************/ |
55 | | |
56 | | /* Metadata cache (H5AC) callbacks */ |
57 | | static herr_t H5F__cache_superblock_get_initial_load_size(void *udata, size_t *image_len); |
58 | | static herr_t H5F__cache_superblock_get_final_load_size(const void *image_ptr, size_t image_len, void *udata, |
59 | | size_t *actual_len); |
60 | | static htri_t H5F__cache_superblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr); |
61 | | static void *H5F__cache_superblock_deserialize(const void *image, size_t len, void *udata, bool *dirty); |
62 | | static herr_t H5F__cache_superblock_image_len(const void *thing, size_t *image_len); |
63 | | static herr_t H5F__cache_superblock_serialize(const H5F_t *f, void *image, size_t len, void *thing); |
64 | | static herr_t H5F__cache_superblock_free_icr(void *thing); |
65 | | |
66 | | static herr_t H5F__cache_drvrinfo_get_initial_load_size(void *udata, size_t *image_len); |
67 | | static herr_t H5F__cache_drvrinfo_get_final_load_size(const void *image_ptr, size_t image_len, void *udata, |
68 | | size_t *actual_len); |
69 | | static void *H5F__cache_drvrinfo_deserialize(const void *image, size_t len, void *udata, bool *dirty); |
70 | | static herr_t H5F__cache_drvrinfo_image_len(const void *thing, size_t *image_len); |
71 | | static herr_t H5F__cache_drvrinfo_serialize(const H5F_t *f, void *image, size_t len, void *thing); |
72 | | static herr_t H5F__cache_drvrinfo_free_icr(void *thing); |
73 | | |
74 | | /* Local encode/decode routines */ |
75 | | static herr_t H5F__superblock_prefix_decode(H5F_super_t *sblock, const uint8_t **image_ref, size_t len, |
76 | | const H5F_superblock_cache_ud_t *udata, bool extend_eoa); |
77 | | static herr_t H5F__drvrinfo_prefix_decode(H5O_drvinfo_t *drvinfo, char *drv_name, const uint8_t **image_ref, |
78 | | size_t len, H5F_drvrinfo_cache_ud_t *udata, bool extend_eoa); |
79 | | |
80 | | /*********************/ |
81 | | /* Package Variables */ |
82 | | /*********************/ |
83 | | |
84 | | /* H5F superblock inherits cache-like properties from H5AC */ |
85 | | const H5AC_class_t H5AC_SUPERBLOCK[1] = {{ |
86 | | H5AC_SUPERBLOCK_ID, /* Metadata client ID */ |
87 | | "Superblock", /* Metadata client name (for debugging) */ |
88 | | H5FD_MEM_SUPER, /* File space memory type for client */ |
89 | | H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */ |
90 | | H5F__cache_superblock_get_initial_load_size, /* 'get_initial_load_size' callback */ |
91 | | H5F__cache_superblock_get_final_load_size, /* 'get_final_load_size' callback */ |
92 | | H5F__cache_superblock_verify_chksum, /* 'verify_chksum' callback */ |
93 | | H5F__cache_superblock_deserialize, /* 'deserialize' callback */ |
94 | | H5F__cache_superblock_image_len, /* 'image_len' callback */ |
95 | | NULL, /* 'pre_serialize' callback */ |
96 | | H5F__cache_superblock_serialize, /* 'serialize' callback */ |
97 | | NULL, /* 'notify' callback */ |
98 | | H5F__cache_superblock_free_icr, /* 'free_icr' callback */ |
99 | | NULL, /* 'fsf_size' callback */ |
100 | | }}; |
101 | | |
102 | | /* H5F driver info block inherits cache-like properties from H5AC */ |
103 | | const H5AC_class_t H5AC_DRVRINFO[1] = {{ |
104 | | H5AC_DRVRINFO_ID, /* Metadata client ID */ |
105 | | "Driver info block", /* Metadata client name (for debugging) */ |
106 | | H5FD_MEM_SUPER, /* File space memory type for client */ |
107 | | H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */ |
108 | | H5F__cache_drvrinfo_get_initial_load_size, /* 'get_initial_load_size' callback */ |
109 | | H5F__cache_drvrinfo_get_final_load_size, /* 'get_final_load_size' callback */ |
110 | | NULL, /* 'verify_chksum' callback */ |
111 | | H5F__cache_drvrinfo_deserialize, /* 'deserialize' callback */ |
112 | | H5F__cache_drvrinfo_image_len, /* 'image_len' callback */ |
113 | | NULL, /* 'pre_serialize' callback */ |
114 | | H5F__cache_drvrinfo_serialize, /* 'serialize' callback */ |
115 | | NULL, /* 'notify' callback */ |
116 | | H5F__cache_drvrinfo_free_icr, /* 'free_icr' callback */ |
117 | | NULL, /* 'fsf_size' callback */ |
118 | | }}; |
119 | | |
120 | | /*****************************/ |
121 | | /* Library Private Variables */ |
122 | | /*****************************/ |
123 | | |
124 | | /* Declare extern the free list to manage the H5F_super_t struct */ |
125 | | H5FL_EXTERN(H5F_super_t); |
126 | | |
127 | | /*******************/ |
128 | | /* Local Variables */ |
129 | | /*******************/ |
130 | | |
131 | | /*------------------------------------------------------------------------- |
132 | | * Function: H5F__superblock_prefix_decode |
133 | | * |
134 | | * Purpose: Decode a superblock prefix |
135 | | * |
136 | | * Return: SUCCEED/FAIL |
137 | | *------------------------------------------------------------------------- |
138 | | */ |
139 | | static herr_t |
140 | | H5F__superblock_prefix_decode(H5F_super_t *sblock, const uint8_t **image_ref, size_t len, |
141 | | const H5F_superblock_cache_ud_t *udata, bool extend_eoa) |
142 | 16 | { |
143 | 16 | const uint8_t *image = (const uint8_t *)*image_ref; /* Pointer into raw data buffer */ |
144 | 16 | const uint8_t *end = image + len - 1; /* Pointer to end of buffer */ |
145 | 16 | htri_t ret_value = SUCCEED; |
146 | | |
147 | 16 | FUNC_ENTER_PACKAGE |
148 | | |
149 | 16 | assert(sblock); |
150 | 16 | assert(image_ref); |
151 | 16 | assert(image); |
152 | 16 | assert(udata); |
153 | 16 | assert(udata->f); |
154 | | |
155 | | /* Skip over signature (already checked when locating the superblock) */ |
156 | 16 | if (H5_IS_BUFFER_OVERFLOW(image, H5F_SIGNATURE_LEN, end)) |
157 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); |
158 | 16 | image += H5F_SIGNATURE_LEN; |
159 | | |
160 | | /* Superblock version */ |
161 | 16 | if (H5_IS_BUFFER_OVERFLOW(image, 1, end)) |
162 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); |
163 | 16 | sblock->super_vers = *image++; |
164 | 16 | if (sblock->super_vers > HDF5_SUPERBLOCK_VERSION_LATEST) |
165 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad superblock version number"); |
166 | | |
167 | | /* Size check */ |
168 | 16 | if (((size_t)(image - (const uint8_t *)*image_ref)) != H5F_SUPERBLOCK_FIXED_SIZE) |
169 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad superblock (fixed) size"); |
170 | | |
171 | | /* Determine the size of addresses & size of offsets, for computing the |
172 | | * variable-sized portion of the superblock. |
173 | | */ |
174 | 16 | if (sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) { |
175 | 16 | if (H5_IS_BUFFER_OVERFLOW(image, 6, end)) |
176 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); |
177 | 16 | sblock->sizeof_addr = image[4]; |
178 | 16 | sblock->sizeof_size = image[5]; |
179 | 16 | } |
180 | 0 | else { |
181 | 0 | if (H5_IS_BUFFER_OVERFLOW(image, 2, end)) |
182 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); |
183 | 0 | sblock->sizeof_addr = image[0]; |
184 | 0 | sblock->sizeof_size = image[1]; |
185 | 0 | } |
186 | | |
187 | 16 | if (sblock->sizeof_addr != 2 && sblock->sizeof_addr != 4 && sblock->sizeof_addr != 8 && |
188 | 0 | sblock->sizeof_addr != 16 && sblock->sizeof_addr != 32) |
189 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number in an address"); |
190 | 16 | if (sblock->sizeof_size != 2 && sblock->sizeof_size != 4 && sblock->sizeof_size != 8 && |
191 | 0 | sblock->sizeof_size != 16 && sblock->sizeof_size != 32) |
192 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number for object size"); |
193 | | |
194 | | /* Check for extending the EOA for the file */ |
195 | 16 | if (extend_eoa) { |
196 | 8 | size_t variable_size; /* Variable size of superblock */ |
197 | | |
198 | | /* Determine the size of the variable-length part of the superblock */ |
199 | 8 | variable_size = |
200 | 8 | (size_t)H5F_SUPERBLOCK_VARLEN_SIZE(sblock->super_vers, sblock->sizeof_addr, sblock->sizeof_size); |
201 | 8 | if (variable_size == 0) |
202 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "variable size can't be zero"); |
203 | | |
204 | | /* Make certain we can read the variable-sized portion of the superblock */ |
205 | 8 | if (H5F__set_eoa(udata->f, H5FD_MEM_SUPER, (haddr_t)(H5F_SUPERBLOCK_FIXED_SIZE + variable_size)) < 0) |
206 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed"); |
207 | 8 | } |
208 | | |
209 | | /* Update the image buffer pointer */ |
210 | 16 | *image_ref = image; |
211 | | |
212 | 16 | done: |
213 | 16 | FUNC_LEAVE_NOAPI(ret_value) |
214 | 16 | } /* end H5F__superblock_prefix_decode() */ |
215 | | |
216 | | /*------------------------------------------------------------------------- |
217 | | * Function: H5F__drvrinfo_prefix_decode |
218 | | * |
219 | | * Purpose: Decode a driver info prefix |
220 | | * |
221 | | * Return: SUCCEED/FAIL |
222 | | *------------------------------------------------------------------------- |
223 | | */ |
224 | | static herr_t |
225 | | H5F__drvrinfo_prefix_decode(H5O_drvinfo_t *drvrinfo, char *drv_name, const uint8_t **image_ref, size_t len, |
226 | | H5F_drvrinfo_cache_ud_t *udata, bool extend_eoa) |
227 | 16 | { |
228 | 16 | const uint8_t *image = (const uint8_t *)*image_ref; /* Pointer into raw data buffer */ |
229 | 16 | const uint8_t *end = image + len - 1; /* Pointer to end of buffer */ |
230 | 16 | unsigned drv_vers; /* Version of driver info block */ |
231 | 16 | herr_t ret_value = SUCCEED; |
232 | | |
233 | 16 | FUNC_ENTER_PACKAGE |
234 | | |
235 | 16 | assert(drvrinfo); |
236 | 16 | assert(image_ref); |
237 | 16 | assert(image); |
238 | 16 | assert(udata); |
239 | 16 | assert(udata->f); |
240 | | |
241 | | /* Version number */ |
242 | 16 | if (H5_IS_BUFFER_OVERFLOW(image, 1, end)) |
243 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); |
244 | 16 | drv_vers = *image++; |
245 | 16 | if (drv_vers != HDF5_DRIVERINFO_VERSION_0) |
246 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad driver information block version number"); |
247 | | |
248 | | /* Reserved bytes */ |
249 | 16 | if (H5_IS_BUFFER_OVERFLOW(image, 3, end)) |
250 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); |
251 | 16 | image += 3; |
252 | | |
253 | | /* Driver info size */ |
254 | 16 | if (H5_IS_BUFFER_OVERFLOW(image, 4, end)) |
255 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); |
256 | 16 | UINT32DECODE(image, drvrinfo->len); |
257 | | |
258 | | /* Driver name and/or version */ |
259 | 16 | if (drv_name) { |
260 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 8, end)) |
261 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); |
262 | 8 | H5MM_memcpy(drv_name, (const char *)image, (size_t)8); |
263 | 8 | drv_name[8] = '\0'; |
264 | 8 | image += 8; /* advance past name/version */ |
265 | 8 | } |
266 | | |
267 | | /* Extend the EOA if required so that we can read the complete driver info block */ |
268 | 16 | if (extend_eoa) { |
269 | 8 | haddr_t eoa; /* Current EOA for the file */ |
270 | 8 | haddr_t min_eoa; /* Minimum EOA needed for reading the driver info */ |
271 | | |
272 | | /* Get current EOA... */ |
273 | 8 | eoa = H5FD_get_eoa(udata->f->shared->lf, H5FD_MEM_SUPER); |
274 | 8 | if (!H5_addr_defined(eoa)) |
275 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "driver get_eoa request failed"); |
276 | | |
277 | | /* ... if it is too small, extend it. */ |
278 | 8 | min_eoa = udata->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drvrinfo->len; |
279 | | |
280 | | /* If it grew, set it */ |
281 | 8 | if (H5_addr_gt(min_eoa, eoa)) |
282 | 8 | if (H5FD_set_eoa(udata->f->shared->lf, H5FD_MEM_SUPER, min_eoa) < 0) |
283 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed"); |
284 | 8 | } |
285 | | |
286 | | /* Update the image buffer pointer */ |
287 | 16 | *image_ref = image; |
288 | | |
289 | 16 | done: |
290 | 16 | FUNC_LEAVE_NOAPI(ret_value) |
291 | 16 | } /* end H5F__drvrinfo_prefix_decode() */ |
292 | | |
293 | | /*------------------------------------------------------------------------- |
294 | | * Function: H5F__cache_superblock_get_initial_load_size |
295 | | * |
296 | | * Purpose: Compute the size of the data structure on disk |
297 | | * |
298 | | * Return: SUCCEED/FAIL |
299 | | *------------------------------------------------------------------------- |
300 | | */ |
301 | | static herr_t |
302 | | H5F__cache_superblock_get_initial_load_size(void H5_ATTR_UNUSED *_udata, size_t *image_len) |
303 | 8 | { |
304 | 8 | FUNC_ENTER_PACKAGE_NOERR |
305 | | |
306 | 8 | assert(image_len); |
307 | | |
308 | | /* Set the initial image length size */ |
309 | 8 | *image_len = H5F_SUPERBLOCK_SPEC_READ_SIZE; |
310 | | |
311 | 8 | FUNC_LEAVE_NOAPI(SUCCEED) |
312 | 8 | } /* end H5F__cache_superblock_get_initial_load_size() */ |
313 | | |
314 | | /*------------------------------------------------------------------------- |
315 | | * Function: H5F__cache_superblock_get_final_load_size |
316 | | * |
317 | | * Purpose: Compute the final size of the data structure on disk |
318 | | * |
319 | | * Return: SUCCEED/FAIL |
320 | | *------------------------------------------------------------------------- |
321 | | */ |
322 | | static herr_t |
323 | | H5F__cache_superblock_get_final_load_size(const void *_image, size_t image_len, void *_udata, |
324 | | size_t *actual_len) |
325 | 8 | { |
326 | 8 | const uint8_t *image = _image; /* Pointer into raw data buffer */ |
327 | 8 | H5F_superblock_cache_ud_t *udata = (H5F_superblock_cache_ud_t *)_udata; /* User data */ |
328 | 8 | H5F_super_t sblock; /* Temporary file superblock */ |
329 | 8 | htri_t ret_value = SUCCEED; |
330 | | |
331 | 8 | FUNC_ENTER_PACKAGE |
332 | | |
333 | 8 | assert(image); |
334 | 8 | assert(udata); |
335 | 8 | assert(actual_len); |
336 | 8 | assert(*actual_len == image_len); |
337 | 8 | assert(image_len >= H5F_SUPERBLOCK_FIXED_SIZE + 6); |
338 | | |
339 | | /* Deserialize the file superblock's prefix */ |
340 | 8 | if (H5F__superblock_prefix_decode(&sblock, &image, image_len, udata, true) < 0) |
341 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, FAIL, "can't decode file superblock prefix"); |
342 | | |
343 | | /* Save the version to be used in verify_chksum callback */ |
344 | 8 | udata->super_vers = sblock.super_vers; |
345 | | |
346 | | /* Set the final size for the cache image */ |
347 | 8 | *actual_len = H5F_SUPERBLOCK_FIXED_SIZE + (size_t)H5F_SUPERBLOCK_VARLEN_SIZE( |
348 | 8 | sblock.super_vers, sblock.sizeof_addr, sblock.sizeof_size); |
349 | | |
350 | 8 | done: |
351 | 8 | FUNC_LEAVE_NOAPI(ret_value) |
352 | 8 | } /* end H5F__cache_superblock_get_final_load_size() */ |
353 | | |
354 | | /*------------------------------------------------------------------------- |
355 | | * Function: H5F__cache_superblock_verify_chksum |
356 | | * |
357 | | * Purpose: Verify the computed checksum of the data structure is the |
358 | | * same as the stored chksum. |
359 | | * |
360 | | * Return: Success: true/false |
361 | | * Failure: Negative |
362 | | *------------------------------------------------------------------------- |
363 | | */ |
364 | | static htri_t |
365 | | H5F__cache_superblock_verify_chksum(const void *_image, size_t len, void *_udata) |
366 | 8 | { |
367 | 8 | const uint8_t *image = _image; /* Pointer into raw data buffer */ |
368 | 8 | H5F_superblock_cache_ud_t *udata = (H5F_superblock_cache_ud_t *)_udata; /* User data */ |
369 | 8 | uint32_t stored_chksum; /* Stored metadata checksum value */ |
370 | 8 | uint32_t computed_chksum; /* Computed metadata checksum value */ |
371 | 8 | htri_t ret_value = true; |
372 | | |
373 | 8 | FUNC_ENTER_PACKAGE |
374 | | |
375 | 8 | assert(image); |
376 | 8 | assert(udata); |
377 | | |
378 | | /* No checksum for version 0 & 1 */ |
379 | 8 | if (udata->super_vers >= HDF5_SUPERBLOCK_VERSION_2) { |
380 | | |
381 | | /* Get stored and computed checksums */ |
382 | 0 | if (H5F_get_checksums(image, len, &stored_chksum, &computed_chksum) < 0) |
383 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get checksums"); |
384 | | |
385 | 0 | if (stored_chksum != computed_chksum) |
386 | 0 | ret_value = false; |
387 | 0 | } |
388 | | |
389 | 8 | done: |
390 | 8 | FUNC_LEAVE_NOAPI(ret_value) |
391 | 8 | } /* end H5F__cache_superblock_verify_chksum() */ |
392 | | |
393 | | /*------------------------------------------------------------------------- |
394 | | * Function: H5F__cache_superblock_deserialize |
395 | | * |
396 | | * Purpose: Load an object from the disk |
397 | | * |
398 | | * Return: Success: Pointer to new object |
399 | | * Failure: NULL |
400 | | *------------------------------------------------------------------------- |
401 | | */ |
402 | | static void * |
403 | | H5F__cache_superblock_deserialize(const void *_image, size_t len, void *_udata, bool H5_ATTR_UNUSED *dirty) |
404 | 8 | { |
405 | 8 | H5F_super_t *sblock = NULL; /* File's superblock */ |
406 | 8 | H5F_superblock_cache_ud_t *udata = (H5F_superblock_cache_ud_t *)_udata; /* User data */ |
407 | 8 | const uint8_t *image = _image; /* Pointer into raw data buffer */ |
408 | 8 | const uint8_t *end = image + len - 1; /* Pointer to end of buffer */ |
409 | 8 | H5F_super_t *ret_value = NULL; |
410 | | |
411 | 8 | FUNC_ENTER_PACKAGE |
412 | | |
413 | 8 | assert(image); |
414 | 8 | assert(udata); |
415 | 8 | assert(udata->f); |
416 | 8 | assert(len >= H5F_SUPERBLOCK_FIXED_SIZE + 6); |
417 | | |
418 | | /* Allocate space for the superblock */ |
419 | 8 | if (NULL == (sblock = H5FL_CALLOC(H5F_super_t))) |
420 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
421 | | |
422 | | /* Deserialize the file superblock's prefix */ |
423 | 8 | if (H5F__superblock_prefix_decode(sblock, &image, len, udata, false) < 0) |
424 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode file superblock prefix"); |
425 | | |
426 | | /* Check for older version of superblock format */ |
427 | 8 | if (sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) { |
428 | 8 | uint32_t status_flags; /* File status flags */ |
429 | 8 | unsigned sym_leaf_k; /* Symbol table leaf node's 'K' value */ |
430 | 8 | unsigned snode_btree_k; /* B-tree symbol table internal node 'K' value */ |
431 | 8 | unsigned chunk_btree_k; /* B-tree chunk internal node 'K' value */ |
432 | | |
433 | | /* Freespace version (hard-wired) */ |
434 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 1, end)) |
435 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
436 | 8 | if (HDF5_FREESPACE_VERSION != *image++) |
437 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad free space version number"); |
438 | | |
439 | | /* Root group version number (hard-wired) */ |
440 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 1, end)) |
441 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
442 | 8 | if (HDF5_OBJECTDIR_VERSION != *image++) |
443 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad object directory version number"); |
444 | | |
445 | | /* Skip over reserved byte */ |
446 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 1, end)) |
447 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
448 | 8 | image++; |
449 | | |
450 | | /* Shared header version number (hard-wired) */ |
451 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 1, end)) |
452 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
453 | 8 | if (HDF5_SHAREDHEADER_VERSION != *image++) |
454 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad shared-header format version number"); |
455 | | |
456 | | /* Skip over size of file addresses (already decoded) */ |
457 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 1, end)) |
458 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
459 | 8 | image++; |
460 | 8 | udata->f->shared->sizeof_addr = sblock->sizeof_addr; /* Keep a local copy also */ |
461 | | |
462 | | /* Skip over size of file sizes (already decoded) */ |
463 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 1, end)) |
464 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
465 | 8 | image++; |
466 | 8 | udata->f->shared->sizeof_size = sblock->sizeof_size; /* Keep a local copy also */ |
467 | | |
468 | | /* Skip over reserved byte */ |
469 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 1, end)) |
470 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
471 | 8 | image++; |
472 | | |
473 | | /* Various B-tree sizes */ |
474 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 2, end)) |
475 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
476 | 8 | UINT16DECODE(image, sym_leaf_k); |
477 | 8 | if (sym_leaf_k == 0) |
478 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad symbol table leaf node 1/2 rank"); |
479 | 8 | udata->sym_leaf_k = sym_leaf_k; /* Keep a local copy also */ |
480 | | |
481 | | /* Need 'get' call to set other array values */ |
482 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 2, end)) |
483 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
484 | 8 | UINT16DECODE(image, snode_btree_k); |
485 | 8 | if (snode_btree_k == 0) |
486 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad 1/2 rank for btree internal nodes"); |
487 | 8 | udata->btree_k[H5B_SNODE_ID] = snode_btree_k; |
488 | | |
489 | | /* Delay setting the value in the property list until we've checked |
490 | | * for the indexed storage B-tree internal 'K' value later. |
491 | | */ |
492 | | |
493 | | /* File status flags (not really used yet) */ |
494 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, 4, end)) |
495 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
496 | 8 | UINT32DECODE(image, status_flags); |
497 | 8 | if (status_flags > 255) |
498 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad superblock status flags"); |
499 | 8 | sblock->status_flags = (uint8_t)status_flags; |
500 | 8 | if (sblock->status_flags & ~H5F_SUPER_ALL_FLAGS) |
501 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock"); |
502 | | |
503 | | /* If the superblock version # is greater than 0, read in the indexed |
504 | | * storage B-tree internal 'K' value |
505 | | */ |
506 | 8 | if (sblock->super_vers > HDF5_SUPERBLOCK_VERSION_DEF) { |
507 | 0 | if (H5_IS_BUFFER_OVERFLOW(image, 2, end)) |
508 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
509 | 0 | UINT16DECODE(image, chunk_btree_k); |
510 | | |
511 | | /* Reserved bytes are present only in version 1 */ |
512 | 0 | if (sblock->super_vers == HDF5_SUPERBLOCK_VERSION_1) { |
513 | | /* Reserved */ |
514 | 0 | if (H5_IS_BUFFER_OVERFLOW(image, 2, end)) |
515 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
516 | 0 | image += 2; |
517 | 0 | } |
518 | 0 | } |
519 | 8 | else |
520 | 8 | chunk_btree_k = HDF5_BTREE_CHUNK_IK_DEF; |
521 | 8 | udata->btree_k[H5B_CHUNK_ID] = chunk_btree_k; |
522 | | |
523 | | /* Remainder of "variable-sized" portion of superblock */ |
524 | 8 | if (H5_IS_BUFFER_OVERFLOW(image, H5F_sizeof_addr(udata->f) * 4, end)) |
525 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
526 | 8 | H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->base_addr /*out*/); |
527 | 8 | H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->ext_addr /*out*/); |
528 | 8 | H5F_addr_decode(udata->f, (const uint8_t **)&image, &udata->stored_eof /*out*/); |
529 | 8 | H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->driver_addr /*out*/); |
530 | | |
531 | | /* Allocate space for the root group symbol table entry */ |
532 | 8 | if (sblock->root_ent) |
533 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "root entry should not exist yet"); |
534 | 8 | if (NULL == (sblock->root_ent = (H5G_entry_t *)H5MM_calloc(sizeof(H5G_entry_t)))) |
535 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, |
536 | 8 | "can't allocate space for root group symbol table entry"); |
537 | | |
538 | | /* Decode the root group symbol table entry */ |
539 | 8 | if (H5G_ent_decode(udata->f, (const uint8_t **)&image, sblock->root_ent, end) < 0) |
540 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode root group symbol table entry"); |
541 | | |
542 | | /* Set the root group address to the correct value */ |
543 | 8 | sblock->root_addr = sblock->root_ent->header; |
544 | | |
545 | | /* This step is for h5repart tool only. If user wants to change file driver |
546 | | * from family to sec2 while using h5repart, set the driver address to |
547 | | * undefined to let the library ignore the family driver information saved |
548 | | * in the superblock. |
549 | | */ |
550 | 8 | if (udata->ignore_drvrinfo && H5_addr_defined(sblock->driver_addr)) { |
551 | | /* Eliminate the driver info */ |
552 | 0 | sblock->driver_addr = HADDR_UNDEF; |
553 | 0 | udata->drvrinfo_removed = true; |
554 | 0 | } |
555 | | |
556 | | /* NOTE: Driver info block is decoded separately, later */ |
557 | 8 | } |
558 | 0 | else { |
559 | 0 | uint32_t read_chksum; /* Checksum read from file */ |
560 | | |
561 | | /* Skip over size of file addresses (already decoded) */ |
562 | 0 | image++; |
563 | 0 | udata->f->shared->sizeof_addr = sblock->sizeof_addr; /* Keep a local copy also */ |
564 | | /* Skip over size of file sizes (already decoded) */ |
565 | 0 | image++; |
566 | 0 | udata->f->shared->sizeof_size = sblock->sizeof_size; /* Keep a local copy also */ |
567 | | |
568 | | /* Check whether the image pointer is out of bounds */ |
569 | 0 | if (H5_IS_BUFFER_OVERFLOW(image, 1, end)) |
570 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
571 | | |
572 | | /* File status flags (not really used yet) */ |
573 | 0 | sblock->status_flags = *image++; |
574 | 0 | if (sblock->status_flags & ~H5F_SUPER_ALL_FLAGS) |
575 | 0 | HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock"); |
576 | | |
577 | | /* Check whether the image pointer will be out of bounds */ |
578 | 0 | if (H5_IS_BUFFER_OVERFLOW(image, H5F_SIZEOF_ADDR(udata->f) * 4, end)) |
579 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
580 | | |
581 | | /* Base, superblock extension, end of file & root group object header addresses */ |
582 | 0 | H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->base_addr /*out*/); |
583 | 0 | H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->ext_addr /*out*/); |
584 | 0 | H5F_addr_decode(udata->f, (const uint8_t **)&image, &udata->stored_eof /*out*/); |
585 | 0 | H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->root_addr /*out*/); |
586 | | |
587 | | /* checksum verification already done in verify_chksum cb */ |
588 | | |
589 | | /* Check whether the image pointer will be out of bounds */ |
590 | 0 | if (H5_IS_BUFFER_OVERFLOW(image, sizeof(uint32_t), end)) |
591 | 0 | HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds"); |
592 | | |
593 | | /* Decode checksum */ |
594 | 0 | UINT32DECODE(image, read_chksum); |
595 | | |
596 | | /* The Driver Information Block may not appear with the version |
597 | | * 2 super block. Thus we set the driver_addr field of the in |
598 | | * core representation of the super block HADDR_UNDEF to prevent |
599 | | * any attempt to load the Driver Information Block. |
600 | | */ |
601 | 0 | sblock->driver_addr = HADDR_UNDEF; |
602 | 0 | } |
603 | | |
604 | | /* Size check */ |
605 | 8 | if ((size_t)(image - (const uint8_t *)_image) > len) |
606 | 0 | HDONE_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad decoded superblock size"); |
607 | | |
608 | 8 | ret_value = sblock; |
609 | | |
610 | 8 | done: |
611 | | /* Release the [possibly partially initialized] superblock on error */ |
612 | 8 | if (!ret_value && sblock) |
613 | 0 | if (H5F__super_free(sblock) < 0) |
614 | 0 | HDONE_ERROR(H5E_FILE, H5E_CANTFREE, NULL, "unable to destroy superblock data"); |
615 | | |
616 | 8 | FUNC_LEAVE_NOAPI(ret_value) |
617 | 8 | } /* end H5F__cache_superblock_deserialize() */ |
618 | | |
619 | | /*------------------------------------------------------------------------- |
620 | | * Function: H5F__cache_superblock_image_len |
621 | | * |
622 | | * Purpose: Compute the size of the data structure on disk |
623 | | * |
624 | | * Return: SUCCEED/FAIL |
625 | | *------------------------------------------------------------------------- |
626 | | */ |
627 | | static herr_t |
628 | | H5F__cache_superblock_image_len(const void *_thing, size_t *image_len) |
629 | 8 | { |
630 | 8 | const H5F_super_t *sblock = (const H5F_super_t *)_thing; /* Pointer to the object */ |
631 | | |
632 | 8 | FUNC_ENTER_PACKAGE_NOERR |
633 | | |
634 | 8 | assert(sblock); |
635 | 8 | assert(sblock->cache_info.type == H5AC_SUPERBLOCK); |
636 | 8 | assert(image_len); |
637 | | |
638 | | /* Set the image length size */ |
639 | 8 | *image_len = (size_t)H5F_SUPERBLOCK_SIZE(sblock); |
640 | | |
641 | 8 | FUNC_LEAVE_NOAPI(SUCCEED) |
642 | 8 | } /* end H5F__cache_superblock_image_len() */ |
643 | | |
644 | | /*------------------------------------------------------------------------- |
645 | | * Function: H5F__cache_superblock_serialize |
646 | | * |
647 | | * Purpose: Flush a dirty object to disk |
648 | | * |
649 | | * Return: SUCCEED/FAIL |
650 | | *------------------------------------------------------------------------- |
651 | | */ |
652 | | static herr_t |
653 | | H5F__cache_superblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len, void *_thing) |
654 | 8 | { |
655 | 8 | H5F_super_t *sblock = (H5F_super_t *)_thing; /* Pointer to the object */ |
656 | 8 | uint8_t *image = _image; /* Pointer into raw data buffer */ |
657 | 8 | haddr_t rel_eof; /* Relative EOF for file */ |
658 | 8 | herr_t ret_value = SUCCEED; |
659 | | |
660 | 8 | FUNC_ENTER_PACKAGE |
661 | | |
662 | 8 | assert(f); |
663 | 8 | assert(image); |
664 | 8 | assert(sblock); |
665 | | |
666 | | /* Assert that the superblock is marked as being flushed last (and |
667 | | collectively in parallel) */ |
668 | | /* (We'll rely on the cache to make sure it actually *is* flushed |
669 | | last (and collectively in parallel), but this check doesn't hurt) */ |
670 | 8 | assert(sblock->cache_info.flush_me_last); |
671 | | |
672 | | /* Encode the common portion of the file superblock for all versions */ |
673 | 8 | H5MM_memcpy(image, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN); |
674 | 8 | image += H5F_SIGNATURE_LEN; |
675 | 8 | *image++ = (uint8_t)sblock->super_vers; |
676 | | |
677 | | /* Check for older version of superblock format */ |
678 | 8 | if (sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) { |
679 | 8 | *image++ = (uint8_t)HDF5_FREESPACE_VERSION; /* (hard-wired) */ |
680 | 8 | *image++ = (uint8_t)HDF5_OBJECTDIR_VERSION; /* (hard-wired) */ |
681 | 8 | *image++ = 0; /* reserved*/ |
682 | | |
683 | 8 | *image++ = (uint8_t)HDF5_SHAREDHEADER_VERSION; /* (hard-wired) */ |
684 | 8 | *image++ = sblock->sizeof_addr; |
685 | 8 | *image++ = sblock->sizeof_size; |
686 | 8 | *image++ = 0; /* reserved */ |
687 | | |
688 | 8 | UINT16ENCODE(image, sblock->sym_leaf_k); |
689 | 8 | UINT16ENCODE(image, sblock->btree_k[H5B_SNODE_ID]); |
690 | 8 | UINT32ENCODE(image, (uint32_t)sblock->status_flags); |
691 | | |
692 | | /* |
693 | | * Versions of the superblock >0 have the indexed storage B-tree |
694 | | * internal 'K' value stored |
695 | | */ |
696 | 8 | if (sblock->super_vers > HDF5_SUPERBLOCK_VERSION_DEF) { |
697 | 0 | UINT16ENCODE(image, sblock->btree_k[H5B_CHUNK_ID]); |
698 | 0 | *image++ = 0; /*reserved */ |
699 | 0 | *image++ = 0; /*reserved */ |
700 | 0 | } /* end if */ |
701 | | |
702 | | /* Encode the base address */ |
703 | 8 | H5F_addr_encode(f, &image, sblock->base_addr); |
704 | | |
705 | | /* Encode the address of global free-space index */ |
706 | 8 | H5F_addr_encode(f, &image, sblock->ext_addr); |
707 | | |
708 | | /* Encode the end-of-file address. Note that at this point in time, |
709 | | * the EOF value itself may not be reflective of the file's size, as |
710 | | * we will eventually truncate the file to match the EOA value. As |
711 | | * such, use the EOA value in its place, knowing that the current EOF |
712 | | * value will ultimately match it. */ |
713 | 8 | if ((rel_eof = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER)) == HADDR_UNDEF) |
714 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed"); |
715 | 8 | H5F_addr_encode(f, &image, (rel_eof + sblock->base_addr)); |
716 | | |
717 | | /* Encode the driver information block address */ |
718 | 8 | H5F_addr_encode(f, &image, sblock->driver_addr); |
719 | | |
720 | | /* Encode the root group object entry, including the cached stab info */ |
721 | 8 | if (H5G_ent_encode(f, &image, sblock->root_ent) < 0) |
722 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTENCODE, FAIL, "can't encode root group symbol table entry"); |
723 | | |
724 | | /* NOTE: Driver info block is handled separately */ |
725 | | |
726 | 8 | } /* end if */ |
727 | 0 | else { /* sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2 */ |
728 | 0 | uint32_t chksum; /* Checksum temporary variable */ |
729 | 0 | H5O_loc_t *root_oloc; /* Pointer to root group's object location */ |
730 | | |
731 | | /* Size of file addresses & offsets, and status flags */ |
732 | 0 | *image++ = sblock->sizeof_addr; |
733 | 0 | *image++ = sblock->sizeof_size; |
734 | 0 | *image++ = sblock->status_flags; |
735 | | |
736 | | /* Encode the base address */ |
737 | 0 | H5F_addr_encode(f, &image, sblock->base_addr); |
738 | | |
739 | | /* Encode the address of the superblock extension */ |
740 | 0 | H5F_addr_encode(f, &image, sblock->ext_addr); |
741 | | |
742 | | /* At this point in time, the EOF value itself may |
743 | | * not be reflective of the file's size, since we'll eventually |
744 | | * truncate it to match the EOA value. As such, use the EOA value |
745 | | * in its place, knowing that the current EOF value will |
746 | | * ultimately match it. */ |
747 | 0 | if ((rel_eof = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER)) == HADDR_UNDEF) |
748 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed"); |
749 | 0 | H5F_addr_encode(f, &image, (rel_eof + sblock->base_addr)); |
750 | | |
751 | | /* Retrieve information for root group */ |
752 | 0 | if (NULL == (root_oloc = H5G_oloc(f->shared->root_grp))) |
753 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to retrieve root group information"); |
754 | | |
755 | | /* Encode address of root group's object header */ |
756 | 0 | H5F_addr_encode(f, &image, root_oloc->addr); |
757 | | |
758 | | /* Compute superblock checksum */ |
759 | 0 | chksum = H5_checksum_metadata(_image, ((size_t)H5F_SUPERBLOCK_SIZE(sblock) - H5F_SIZEOF_CHKSUM), 0); |
760 | | |
761 | | /* Superblock checksum */ |
762 | 0 | UINT32ENCODE(image, chksum); |
763 | | |
764 | | /* Sanity check */ |
765 | 0 | assert((size_t)(image - (uint8_t *)_image) == (size_t)H5F_SUPERBLOCK_SIZE(sblock)); |
766 | 0 | } |
767 | | |
768 | | /* Sanity check */ |
769 | 8 | assert((size_t)(image - (uint8_t *)_image) == len); |
770 | | |
771 | 8 | done: |
772 | 8 | FUNC_LEAVE_NOAPI(ret_value) |
773 | 8 | } /* H5F__cache_superblock_serialize() */ |
774 | | |
775 | | /*------------------------------------------------------------------------- |
776 | | * Function: H5F__cache_superblock_free_icr |
777 | | * |
778 | | * Purpose: Destroy/release an "in core representation" of a data |
779 | | * structure |
780 | | * |
781 | | * Return: SUCCEED/FAIL |
782 | | *------------------------------------------------------------------------- |
783 | | */ |
784 | | static herr_t |
785 | | H5F__cache_superblock_free_icr(void *_thing) |
786 | 6 | { |
787 | 6 | H5F_super_t *sblock = (H5F_super_t *)_thing; /* Pointer to the object */ |
788 | 6 | herr_t ret_value = SUCCEED; |
789 | | |
790 | 6 | FUNC_ENTER_PACKAGE |
791 | | |
792 | 6 | assert(sblock); |
793 | 6 | assert(sblock->cache_info.type == H5AC_SUPERBLOCK); |
794 | | |
795 | | /* Destroy superblock */ |
796 | 6 | if (H5F__super_free(sblock) < 0) |
797 | 0 | HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free superblock"); |
798 | | |
799 | 6 | done: |
800 | 6 | FUNC_LEAVE_NOAPI(ret_value) |
801 | 6 | } /* H5F__cache_superblock_free_icr() */ |
802 | | |
803 | | /*------------------------------------------------------------------------- |
804 | | * Function: H5F__cache_drvrinfo_get_initial_load_size |
805 | | * |
806 | | * Purpose: Compute the initial size of the data structure on disk. |
807 | | * |
808 | | * Return: SUCCEED/FAIL |
809 | | *------------------------------------------------------------------------- |
810 | | */ |
811 | | static herr_t |
812 | | H5F__cache_drvrinfo_get_initial_load_size(void H5_ATTR_UNUSED *_udata, size_t *image_len) |
813 | 8 | { |
814 | 8 | FUNC_ENTER_PACKAGE_NOERR |
815 | | |
816 | 8 | assert(image_len); |
817 | | |
818 | | /* Set the initial image length size */ |
819 | 8 | *image_len = H5F_DRVINFOBLOCK_HDR_SIZE; /* Fixed size portion of driver info block */ |
820 | | |
821 | 8 | FUNC_LEAVE_NOAPI(SUCCEED) |
822 | 8 | } /* end H5F__cache_drvrinfo_get_initial_load_size() */ |
823 | | |
824 | | /*------------------------------------------------------------------------- |
825 | | * Function: H5F__cache_drvrinfo_get_final_load_size |
826 | | * |
827 | | * Purpose: Compute the final size of the data structure on disk. |
828 | | * |
829 | | * Return: SUCCEED/FAIL |
830 | | *------------------------------------------------------------------------- |
831 | | */ |
832 | | static herr_t |
833 | | H5F__cache_drvrinfo_get_final_load_size(const void *_image, size_t image_len, void *_udata, |
834 | | size_t *actual_len) |
835 | 8 | { |
836 | 8 | const uint8_t *image = _image; /* Pointer into raw data buffer */ |
837 | 8 | H5F_drvrinfo_cache_ud_t *udata = (H5F_drvrinfo_cache_ud_t *)_udata; /* User data */ |
838 | 8 | H5O_drvinfo_t drvrinfo; /* Driver info */ |
839 | 8 | herr_t ret_value = SUCCEED; |
840 | | |
841 | 8 | FUNC_ENTER_PACKAGE |
842 | | |
843 | 8 | assert(image); |
844 | 8 | assert(udata); |
845 | 8 | assert(actual_len); |
846 | 8 | assert(*actual_len == image_len); |
847 | 8 | assert(image_len == H5F_DRVINFOBLOCK_HDR_SIZE); |
848 | | |
849 | | /* Deserialize the file driver info's prefix */ |
850 | 8 | if (H5F__drvrinfo_prefix_decode(&drvrinfo, NULL, &image, image_len, udata, true) < 0) |
851 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, FAIL, "can't decode file driver info prefix"); |
852 | | |
853 | | /* Set the final size for the cache image */ |
854 | 8 | *actual_len = H5F_DRVINFOBLOCK_HDR_SIZE + drvrinfo.len; |
855 | | |
856 | 8 | done: |
857 | 8 | FUNC_LEAVE_NOAPI(ret_value) |
858 | 8 | } /* end H5F__cache_drvrinfo_get_final_load_size() */ |
859 | | |
860 | | /*------------------------------------------------------------------------- |
861 | | * Function: H5F__cache_drvrinfo_deserialize |
862 | | * |
863 | | * Purpose: Loads an object from the disk |
864 | | * |
865 | | * Return: Success: Pointer to a new driver info struct |
866 | | * Failure: NULL |
867 | | *------------------------------------------------------------------------- |
868 | | */ |
869 | | static void * |
870 | | H5F__cache_drvrinfo_deserialize(const void *_image, size_t len, void *_udata, bool H5_ATTR_UNUSED *dirty) |
871 | 8 | { |
872 | 8 | H5O_drvinfo_t *drvinfo = NULL; /* Driver info */ |
873 | 8 | H5F_drvrinfo_cache_ud_t *udata = (H5F_drvrinfo_cache_ud_t *)_udata; /* User data */ |
874 | 8 | const uint8_t *image = _image; /* Pointer into raw data buffer */ |
875 | 8 | char drv_name[9]; /* Name of driver */ |
876 | 8 | H5O_drvinfo_t *ret_value = NULL; |
877 | | |
878 | 8 | FUNC_ENTER_PACKAGE |
879 | | |
880 | 8 | assert(image); |
881 | 8 | assert(len >= H5F_DRVINFOBLOCK_HDR_SIZE); |
882 | 8 | assert(udata); |
883 | 8 | assert(udata->f); |
884 | | |
885 | | /* Allocate space for the driver info */ |
886 | 8 | if (NULL == (drvinfo = (H5O_drvinfo_t *)H5MM_calloc(sizeof(H5O_drvinfo_t)))) |
887 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "memory allocation failed for driver info message"); |
888 | | |
889 | | /* Deserialize the file driver info's prefix */ |
890 | 8 | if (H5F__drvrinfo_prefix_decode(drvinfo, drv_name, &image, len, udata, false) < 0) |
891 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode file driver info prefix"); |
892 | | |
893 | | /* Sanity check */ |
894 | 8 | assert(len == (H5F_DRVINFOBLOCK_HDR_SIZE + drvinfo->len)); |
895 | | |
896 | | /* Validate and decode driver information */ |
897 | 8 | if (H5FD_sb_load(udata->f->shared->lf, drv_name, image) < 0) |
898 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "unable to decode driver information"); |
899 | | |
900 | | /* Sanity check */ |
901 | 8 | assert((size_t)(image - (const uint8_t *)_image) <= len); |
902 | | |
903 | 8 | ret_value = drvinfo; |
904 | | |
905 | 8 | done: |
906 | | /* Release the [possibly partially initialized] driver info message on error */ |
907 | 8 | if (!ret_value && drvinfo) |
908 | 0 | H5MM_xfree(drvinfo); |
909 | | |
910 | 8 | FUNC_LEAVE_NOAPI(ret_value) |
911 | 8 | } /* end H5F__cache_drvrinfo_deserialize() */ |
912 | | |
913 | | /*------------------------------------------------------------------------- |
914 | | * Function: H5F__cache_drvrinfo_image_len |
915 | | * |
916 | | * Purpose: Compute the size of the data structure on disk |
917 | | * |
918 | | * Return: SUCCEED/FAIL |
919 | | *------------------------------------------------------------------------- |
920 | | */ |
921 | | static herr_t |
922 | | H5F__cache_drvrinfo_image_len(const void *_thing, size_t *image_len) |
923 | 0 | { |
924 | 0 | const H5O_drvinfo_t *drvinfo = (const H5O_drvinfo_t *)_thing; /* Pointer to the object */ |
925 | |
|
926 | 0 | FUNC_ENTER_PACKAGE_NOERR |
927 | |
|
928 | 0 | assert(drvinfo); |
929 | 0 | assert(drvinfo->cache_info.type == H5AC_DRVRINFO); |
930 | 0 | assert(image_len); |
931 | | |
932 | | /* Set the image length size */ |
933 | 0 | *image_len = (size_t)(H5F_DRVINFOBLOCK_HDR_SIZE + /* Fixed-size portion of driver info block */ |
934 | 0 | drvinfo->len); /* Variable-size portion of driver info block */ |
935 | |
|
936 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
937 | 0 | } /* end H5F__cache_drvrinfo_image_len() */ |
938 | | |
939 | | /*------------------------------------------------------------------------- |
940 | | * Function: H5F__cache_drvrinfo_serialize |
941 | | * |
942 | | * Purpose: Flush a dirty object to disk |
943 | | * |
944 | | * Return: SUCCEED/FAIL |
945 | | *------------------------------------------------------------------------- |
946 | | */ |
947 | | static herr_t |
948 | | H5F__cache_drvrinfo_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_NDEBUG_UNUSED len, void *_thing) |
949 | 2 | { |
950 | 2 | H5O_drvinfo_t *drvinfo = (H5O_drvinfo_t *)_thing; /* Pointer to the object */ |
951 | 2 | uint8_t *image = _image; /* Pointer into raw data buffer */ |
952 | 2 | uint8_t *dbuf; /* Pointer to beginning of driver info */ |
953 | 2 | herr_t ret_value = SUCCEED; |
954 | | |
955 | 2 | FUNC_ENTER_PACKAGE |
956 | | |
957 | 2 | assert(f); |
958 | 2 | assert(image); |
959 | 2 | assert(drvinfo); |
960 | 2 | assert(drvinfo->cache_info.type == H5AC_DRVRINFO); |
961 | 2 | assert(len == (size_t)(H5F_DRVINFOBLOCK_HDR_SIZE + drvinfo->len)); |
962 | | |
963 | | /* Save pointer to beginning of driver info */ |
964 | 2 | dbuf = image; |
965 | | |
966 | | /* Encode the driver information block */ |
967 | 2 | *image++ = HDF5_DRIVERINFO_VERSION_0; /* Version */ |
968 | 2 | *image++ = 0; /* reserved */ |
969 | 2 | *image++ = 0; /* reserved */ |
970 | 2 | *image++ = 0; /* reserved */ |
971 | | |
972 | | /* Driver info size, excluding header */ |
973 | 2 | UINT32ENCODE(image, drvinfo->len); |
974 | | |
975 | | /* Encode driver-specific data */ |
976 | 2 | if (H5FD_sb_encode(f->shared->lf, (char *)image, dbuf + H5F_DRVINFOBLOCK_HDR_SIZE) < 0) |
977 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information"); |
978 | | |
979 | | /* Advance buffer pointer past name & variable-sized portion of driver info */ |
980 | 2 | image += 8 + drvinfo->len; |
981 | | |
982 | | /* Sanity check */ |
983 | 2 | assert((size_t)(image - (uint8_t *)_image) == len); |
984 | | |
985 | 2 | done: |
986 | 2 | FUNC_LEAVE_NOAPI(ret_value) |
987 | 2 | } /* H5F__cache_drvrinfo_serialize() */ |
988 | | |
989 | | /*------------------------------------------------------------------------- |
990 | | * Function: H5F__cache_drvrinfo_free_icr |
991 | | * |
992 | | * Purpose: Destroy/release an "in core representation" of a data |
993 | | * structure |
994 | | * |
995 | | * Return: SUCCEED/FAIL |
996 | | *------------------------------------------------------------------------- |
997 | | */ |
998 | | static herr_t |
999 | | H5F__cache_drvrinfo_free_icr(void *_thing) |
1000 | 6 | { |
1001 | 6 | H5O_drvinfo_t *drvinfo = (H5O_drvinfo_t *)_thing; /* Pointer to the object */ |
1002 | | |
1003 | 6 | FUNC_ENTER_PACKAGE_NOERR |
1004 | | |
1005 | 6 | assert(drvinfo); |
1006 | 6 | assert(drvinfo->cache_info.type == H5AC_DRVRINFO); |
1007 | | |
1008 | | /* Destroy driver info message */ |
1009 | 6 | H5MM_xfree(drvinfo); |
1010 | | |
1011 | 6 | FUNC_LEAVE_NOAPI(SUCCEED) |
1012 | 6 | } /* H5F__cache_drvrinfo_free_icr() */ |