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: H5MF.c |
16 | | * |
17 | | * Purpose: File memory management functions. |
18 | | * |
19 | | *------------------------------------------------------------------------- |
20 | | */ |
21 | | |
22 | | /****************/ |
23 | | /* Module Setup */ |
24 | | /****************/ |
25 | | |
26 | | #define H5F_FRIEND /*suppress error about including H5Fpkg */ |
27 | | #define H5FS_FRIEND /*suppress error about including H5Fpkg */ |
28 | | #include "H5MFmodule.h" /* This source code file is part of the H5MF module */ |
29 | | |
30 | | /***********/ |
31 | | /* Headers */ |
32 | | /***********/ |
33 | | #include "H5private.h" /* Generic Functions */ |
34 | | #include "H5Eprivate.h" /* Error handling */ |
35 | | #include "H5Fpkg.h" /* File access */ |
36 | | #include "H5FSpkg.h" /* File free space */ |
37 | | #include "H5MFpkg.h" /* File memory management */ |
38 | | #include "H5VMprivate.h" /* Vectors and arrays */ |
39 | | |
40 | | /****************/ |
41 | | /* Local Macros */ |
42 | | /****************/ |
43 | | |
44 | 0 | #define H5MF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */ |
45 | 0 | #define H5MF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */ |
46 | | |
47 | | #define H5MF_CHECK_FSM(FSM, CF) \ |
48 | 0 | do { \ |
49 | 0 | assert(*CF == false); \ |
50 | 0 | if (!H5_addr_defined(FSM->addr) || !H5_addr_defined(FSM->sect_addr)) \ |
51 | 0 | *CF = true; \ |
52 | 0 | } while (0) |
53 | | |
54 | | /* For non-paged aggregation: map allocation request type to tracked free-space type */ |
55 | | /* F_SH -- pointer to H5F_shared_t; T -- H5FD_mem_t */ |
56 | | #define H5MF_ALLOC_TO_FS_AGGR_TYPE(F_SH, T) \ |
57 | 0 | ((H5FD_MEM_DEFAULT == (F_SH)->fs_type_map[T]) ? (T) : (F_SH)->fs_type_map[T]) |
58 | | |
59 | | /******************/ |
60 | | /* Local Typedefs */ |
61 | | /******************/ |
62 | | |
63 | | /* Enum for kind of free space section+aggregator merging allowed for a file */ |
64 | | typedef enum { |
65 | | H5MF_AGGR_MERGE_SEPARATE, /* Everything in separate free list */ |
66 | | H5MF_AGGR_MERGE_DICHOTOMY, /* Metadata in one free list and raw data in another */ |
67 | | H5MF_AGGR_MERGE_TOGETHER /* Metadata & raw data in one free list */ |
68 | | } H5MF_aggr_merge_t; |
69 | | |
70 | | /* User data for section info iterator callback for iterating over free space sections */ |
71 | | typedef struct { |
72 | | H5F_sect_info_t *sects; /* section info to be retrieved */ |
73 | | size_t sect_count; /* # of sections requested */ |
74 | | size_t sect_idx; /* the current count of sections */ |
75 | | } H5MF_sect_iter_ud_t; |
76 | | |
77 | | /********************/ |
78 | | /* Package Typedefs */ |
79 | | /********************/ |
80 | | |
81 | | /********************/ |
82 | | /* Local Prototypes */ |
83 | | /********************/ |
84 | | |
85 | | /* Allocator routines */ |
86 | | static haddr_t H5MF__alloc_pagefs(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size); |
87 | | |
88 | | /* "File closing" routines */ |
89 | | static herr_t H5MF__close_aggrfs(H5F_t *f); |
90 | | static herr_t H5MF__close_pagefs(H5F_t *f); |
91 | | static herr_t H5MF__close_shrink_eoa(H5F_t *f); |
92 | | |
93 | | /* General routines */ |
94 | | static herr_t H5MF__get_free_sects(H5F_t *f, H5FS_t *fspace, H5MF_sect_iter_ud_t *sect_udata, size_t *nums); |
95 | | static bool H5MF__fsm_type_is_self_referential(H5F_shared_t *f_sh, H5F_mem_page_t fsm_type); |
96 | | static bool H5MF__fsm_is_self_referential(H5F_shared_t *f_sh, H5FS_t *fspace); |
97 | | static herr_t H5MF__continue_alloc_fsm(H5F_shared_t *f_sh, H5FS_t *sm_hdr_fspace, H5FS_t *sm_sinfo_fspace, |
98 | | H5FS_t *lg_hdr_fspace, H5FS_t *lg_sinfo_fspace, |
99 | | bool *continue_alloc_fsm); |
100 | | |
101 | | /* Free-space type manager routines */ |
102 | | static herr_t H5MF__create_fstype(H5F_t *f, H5F_mem_page_t type); |
103 | | static herr_t H5MF__close_fstype(H5F_t *f, H5F_mem_page_t type); |
104 | | static herr_t H5MF__delete_fstype(H5F_t *f, H5F_mem_page_t type); |
105 | | static herr_t H5MF__close_delete_fstype(H5F_t *f, H5F_mem_page_t type); |
106 | | |
107 | | /* Callbacks */ |
108 | | static herr_t H5MF__sects_cb(H5FS_section_info_t *_sect, void *_udata); |
109 | | |
110 | | /*********************/ |
111 | | /* Package Variables */ |
112 | | /*********************/ |
113 | | |
114 | | /* Package initialization variable */ |
115 | | bool H5_PKG_INIT_VAR = false; |
116 | | |
117 | | /*****************************/ |
118 | | /* Library Private Variables */ |
119 | | /*****************************/ |
120 | | |
121 | | /*******************/ |
122 | | /* Local Variables */ |
123 | | /*******************/ |
124 | | |
125 | | /*------------------------------------------------------------------------- |
126 | | * Function: H5MF_init_merge_flags |
127 | | * |
128 | | * Purpose: Initialize the free space section+aggregator merge flags |
129 | | * for the file. |
130 | | * |
131 | | * Return: SUCCEED/FAIL |
132 | | * |
133 | | *------------------------------------------------------------------------- |
134 | | */ |
135 | | herr_t |
136 | | H5MF_init_merge_flags(H5F_shared_t *f_sh) |
137 | 332 | { |
138 | 332 | H5MF_aggr_merge_t mapping_type; /* Type of free list mapping */ |
139 | 332 | H5FD_mem_t type; /* Memory type for iteration */ |
140 | 332 | bool all_same; /* Whether all the types map to the same value */ |
141 | 332 | herr_t ret_value = SUCCEED; /* Return value */ |
142 | | |
143 | 332 | FUNC_ENTER_NOAPI(FAIL) |
144 | | |
145 | | /* check args */ |
146 | 332 | assert(f_sh); |
147 | 332 | assert(f_sh->lf); |
148 | | |
149 | | /* Iterate over all the free space types to determine if sections of that type |
150 | | * can merge with the metadata or small 'raw' data aggregator |
151 | | */ |
152 | 332 | all_same = true; |
153 | 1.32k | for (type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; type++) |
154 | | /* Check for any different type mappings */ |
155 | 1.32k | if (f_sh->fs_type_map[type] != f_sh->fs_type_map[H5FD_MEM_DEFAULT]) { |
156 | 332 | all_same = false; |
157 | 332 | break; |
158 | 332 | } /* end if */ |
159 | | |
160 | | /* Check for all allocation types mapping to the same free list type */ |
161 | 332 | if (all_same) { |
162 | 0 | if (f_sh->fs_type_map[H5FD_MEM_DEFAULT] == H5FD_MEM_DEFAULT) |
163 | 0 | mapping_type = H5MF_AGGR_MERGE_SEPARATE; |
164 | 0 | else |
165 | 0 | mapping_type = H5MF_AGGR_MERGE_TOGETHER; |
166 | 0 | } /* end if */ |
167 | 332 | else { |
168 | | /* Check for raw data mapping into same list as metadata */ |
169 | 332 | if (f_sh->fs_type_map[H5FD_MEM_DRAW] == f_sh->fs_type_map[H5FD_MEM_SUPER]) |
170 | 0 | mapping_type = H5MF_AGGR_MERGE_SEPARATE; |
171 | 332 | else { |
172 | 332 | bool all_metadata_same; /* Whether all metadata go in same free list */ |
173 | | |
174 | | /* One or more allocation type don't map to the same free list type */ |
175 | | /* Check if all the metadata allocation types map to the same type */ |
176 | 332 | all_metadata_same = true; |
177 | 2.32k | for (type = H5FD_MEM_SUPER; type < H5FD_MEM_NTYPES; type++) |
178 | | /* Skip checking raw data free list mapping */ |
179 | | /* (global heap is treated as raw data) */ |
180 | 1.99k | if (type != H5FD_MEM_DRAW && type != H5FD_MEM_GHEAP) { |
181 | | /* Check for any different type mappings */ |
182 | 1.32k | if (f_sh->fs_type_map[type] != f_sh->fs_type_map[H5FD_MEM_SUPER]) { |
183 | 0 | all_metadata_same = false; |
184 | 0 | break; |
185 | 0 | } /* end if */ |
186 | 1.32k | } /* end if */ |
187 | | |
188 | | /* Check for all metadata on same free list */ |
189 | 332 | if (all_metadata_same) |
190 | 332 | mapping_type = H5MF_AGGR_MERGE_DICHOTOMY; |
191 | 0 | else |
192 | 0 | mapping_type = H5MF_AGGR_MERGE_SEPARATE; |
193 | 332 | } /* end else */ |
194 | 332 | } /* end else */ |
195 | | |
196 | | /* Based on mapping type, initialize merging flags for each free list type */ |
197 | 332 | switch (mapping_type) { |
198 | 0 | case H5MF_AGGR_MERGE_SEPARATE: |
199 | | /* Don't merge any metadata together */ |
200 | 0 | memset(f_sh->fs_aggr_merge, 0, sizeof(f_sh->fs_aggr_merge)); |
201 | | |
202 | | /* Check if merging raw data should be allowed */ |
203 | | /* (treat global heaps as raw data) */ |
204 | 0 | if (H5FD_MEM_DRAW == f_sh->fs_type_map[H5FD_MEM_DRAW] || |
205 | 0 | H5FD_MEM_DEFAULT == f_sh->fs_type_map[H5FD_MEM_DRAW]) { |
206 | 0 | f_sh->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA; |
207 | 0 | f_sh->fs_aggr_merge[H5FD_MEM_GHEAP] = H5F_FS_MERGE_RAWDATA; |
208 | 0 | } /* end if */ |
209 | 0 | break; |
210 | | |
211 | 332 | case H5MF_AGGR_MERGE_DICHOTOMY: |
212 | | /* Merge all metadata together (but not raw data) */ |
213 | 332 | memset(f_sh->fs_aggr_merge, H5F_FS_MERGE_METADATA, sizeof(f_sh->fs_aggr_merge)); |
214 | | |
215 | | /* Allow merging raw data allocations together */ |
216 | | /* (treat global heaps as raw data) */ |
217 | 332 | f_sh->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA; |
218 | 332 | f_sh->fs_aggr_merge[H5FD_MEM_GHEAP] = H5F_FS_MERGE_RAWDATA; |
219 | 332 | break; |
220 | | |
221 | 0 | case H5MF_AGGR_MERGE_TOGETHER: |
222 | | /* Merge all allocation types together */ |
223 | 0 | memset(f_sh->fs_aggr_merge, (H5F_FS_MERGE_METADATA | H5F_FS_MERGE_RAWDATA), |
224 | 0 | sizeof(f_sh->fs_aggr_merge)); |
225 | 0 | break; |
226 | | |
227 | 0 | default: |
228 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_BADVALUE, FAIL, "invalid mapping type"); |
229 | 332 | } /* end switch */ |
230 | | |
231 | 332 | done: |
232 | 332 | FUNC_LEAVE_NOAPI(ret_value) |
233 | 332 | } /* end H5MF_init_merge_flags() */ |
234 | | |
235 | | /*------------------------------------------------------------------------- |
236 | | * Function: H5MF__alloc_to_fs_type |
237 | | * |
238 | | * Purpose: Map "alloc_type" to the free-space manager type |
239 | | * |
240 | | * Return: Success: non-negative |
241 | | * Failure: negative |
242 | | * |
243 | | *------------------------------------------------------------------------- |
244 | | */ |
245 | | void |
246 | | H5MF__alloc_to_fs_type(H5F_shared_t *f_sh, H5FD_mem_t alloc_type, hsize_t size, H5F_mem_page_t *fs_type) |
247 | 0 | { |
248 | 0 | FUNC_ENTER_PACKAGE_NOERR |
249 | | |
250 | | /* Check arguments */ |
251 | 0 | assert(f_sh); |
252 | 0 | assert(fs_type); |
253 | |
|
254 | 0 | if (H5F_SHARED_PAGED_AGGR(f_sh)) { /* paged aggregation */ |
255 | 0 | if (size >= f_sh->fs_page_size) { |
256 | 0 | if (H5F_SHARED_HAS_FEATURE(f_sh, H5FD_FEAT_PAGED_AGGR)) { /* multi or split driver */ |
257 | | /* For non-contiguous address space, map to large size free-space manager for each alloc_type |
258 | | */ |
259 | 0 | if (H5FD_MEM_DEFAULT == f_sh->fs_type_map[alloc_type]) |
260 | 0 | *fs_type = (H5F_mem_page_t)(alloc_type + (H5FD_MEM_NTYPES - 1)); |
261 | 0 | else |
262 | 0 | *fs_type = (H5F_mem_page_t)(f_sh->fs_type_map[alloc_type] + (H5FD_MEM_NTYPES - 1)); |
263 | 0 | } /* end if */ |
264 | 0 | else |
265 | | /* For contiguous address space, map to generic large size free-space manager */ |
266 | 0 | *fs_type = H5F_MEM_PAGE_GENERIC; /* H5F_MEM_PAGE_SUPER */ |
267 | 0 | } /* end if */ |
268 | 0 | else |
269 | 0 | *fs_type = (H5F_mem_page_t)H5MF_ALLOC_TO_FS_AGGR_TYPE(f_sh, alloc_type); |
270 | 0 | } /* end if */ |
271 | 0 | else /* non-paged aggregation */ |
272 | 0 | *fs_type = (H5F_mem_page_t)H5MF_ALLOC_TO_FS_AGGR_TYPE(f_sh, alloc_type); |
273 | |
|
274 | 0 | FUNC_LEAVE_NOAPI_VOID |
275 | 0 | } /* end H5MF__alloc_to_fs_type() */ |
276 | | |
277 | | /*------------------------------------------------------------------------- |
278 | | * Function: H5MF__open_fstype |
279 | | * |
280 | | * Purpose: Open an existing free space manager of TYPE for file by |
281 | | * creating a free-space structure. |
282 | | * Note that TYPE can be H5F_mem_page_t or H5FD_mem_t enum types. |
283 | | * |
284 | | * Return: Success: non-negative |
285 | | * Failure: negative |
286 | | * |
287 | | *------------------------------------------------------------------------- |
288 | | */ |
289 | | herr_t |
290 | | H5MF__open_fstype(H5F_t *f, H5F_mem_page_t type) |
291 | 0 | { |
292 | 0 | const H5FS_section_class_t *classes[] = {/* Free space section classes implemented for file */ |
293 | 0 | H5MF_FSPACE_SECT_CLS_SIMPLE, H5MF_FSPACE_SECT_CLS_SMALL, |
294 | 0 | H5MF_FSPACE_SECT_CLS_LARGE}; |
295 | 0 | hsize_t alignment; /* Alignment to use */ |
296 | 0 | hsize_t threshold; /* Threshold to use */ |
297 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
298 | 0 | H5AC_ring_t fsm_ring; /* Ring of FSM */ |
299 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
300 | |
|
301 | 0 | FUNC_ENTER_PACKAGE_TAG(H5AC__FREESPACE_TAG) |
302 | | |
303 | | /* |
304 | | * Check arguments. |
305 | | */ |
306 | 0 | assert(f); |
307 | 0 | if (H5F_PAGED_AGGR(f)) |
308 | 0 | assert(type < H5F_MEM_PAGE_NTYPES); |
309 | 0 | else { |
310 | 0 | assert((H5FD_mem_t)type < H5FD_MEM_NTYPES); |
311 | 0 | assert((H5FD_mem_t)type != H5FD_MEM_NOLIST); |
312 | 0 | } /* end else */ |
313 | 0 | assert(f->shared); |
314 | 0 | assert(H5_addr_defined(f->shared->fs_addr[type])); |
315 | 0 | assert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED); |
316 | | |
317 | | /* Set up the alignment and threshold to use depending on the manager type */ |
318 | 0 | if (H5F_PAGED_AGGR(f)) { |
319 | 0 | alignment = (type == H5F_MEM_PAGE_GENERIC) ? f->shared->fs_page_size : (hsize_t)H5F_ALIGN_DEF; |
320 | 0 | threshold = H5F_ALIGN_THRHD_DEF; |
321 | 0 | } /* end if */ |
322 | 0 | else { |
323 | 0 | alignment = f->shared->alignment; |
324 | 0 | threshold = f->shared->threshold; |
325 | 0 | } /* end else */ |
326 | | |
327 | | /* Set the ring type in the API context */ |
328 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, type)) |
329 | 0 | fsm_ring = H5AC_RING_MDFSM; |
330 | 0 | else |
331 | 0 | fsm_ring = H5AC_RING_RDFSM; |
332 | 0 | H5AC_set_ring(fsm_ring, &orig_ring); |
333 | | |
334 | | /* Open an existing free space structure for the file */ |
335 | 0 | if (NULL == (f->shared->fs_man[type] = H5FS_open(f, f->shared->fs_addr[type], NELMTS(classes), classes, f, |
336 | 0 | alignment, threshold))) |
337 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info"); |
338 | | |
339 | | /* Set the state for the free space manager to "open", if it is now */ |
340 | 0 | if (f->shared->fs_man[type]) |
341 | 0 | f->shared->fs_state[type] = H5F_FS_STATE_OPEN; |
342 | |
|
343 | 0 | done: |
344 | | /* Reset the ring in the API context */ |
345 | 0 | if (orig_ring != H5AC_RING_INV) |
346 | 0 | H5AC_set_ring(orig_ring, NULL); |
347 | |
|
348 | 0 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
349 | 0 | } /* end H5MF__open_fstype() */ |
350 | | |
351 | | /*------------------------------------------------------------------------- |
352 | | * Function: H5MF__create_fstype |
353 | | * |
354 | | * Purpose: Create free space manager of TYPE for the file by creating |
355 | | * a free-space structure |
356 | | * Note that TYPE can be H5F_mem_page_t or H5FD_mem_t enum types. |
357 | | * |
358 | | * Return: Success: non-negative |
359 | | * Failure: negative |
360 | | * |
361 | | *------------------------------------------------------------------------- |
362 | | */ |
363 | | static herr_t |
364 | | H5MF__create_fstype(H5F_t *f, H5F_mem_page_t type) |
365 | 0 | { |
366 | 0 | const H5FS_section_class_t *classes[] = {/* Free space section classes implemented for file */ |
367 | 0 | H5MF_FSPACE_SECT_CLS_SIMPLE, H5MF_FSPACE_SECT_CLS_SMALL, |
368 | 0 | H5MF_FSPACE_SECT_CLS_LARGE}; |
369 | 0 | H5FS_create_t fs_create; /* Free space creation parameters */ |
370 | 0 | hsize_t alignment; /* Alignment to use */ |
371 | 0 | hsize_t threshold; /* Threshold to use */ |
372 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
373 | 0 | H5AC_ring_t fsm_ring; /* Ring of FSM */ |
374 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
375 | |
|
376 | 0 | FUNC_ENTER_PACKAGE |
377 | | |
378 | | /* |
379 | | * Check arguments. |
380 | | */ |
381 | 0 | assert(f); |
382 | 0 | if (H5F_PAGED_AGGR(f)) |
383 | 0 | assert(type < H5F_MEM_PAGE_NTYPES); |
384 | 0 | else { |
385 | 0 | assert((H5FD_mem_t)type < H5FD_MEM_NTYPES); |
386 | 0 | assert((H5FD_mem_t)type != H5FD_MEM_NOLIST); |
387 | 0 | } /* end else */ |
388 | 0 | assert(f->shared); |
389 | 0 | assert(!H5_addr_defined(f->shared->fs_addr[type])); |
390 | 0 | assert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED); |
391 | | |
392 | | /* Set the free space creation parameters */ |
393 | 0 | fs_create.client = H5FS_CLIENT_FILE_ID; |
394 | 0 | fs_create.shrink_percent = H5MF_FSPACE_SHRINK; |
395 | 0 | fs_create.expand_percent = H5MF_FSPACE_EXPAND; |
396 | 0 | fs_create.max_sect_addr = 1 + H5VM_log2_gen((uint64_t)f->shared->maxaddr); |
397 | 0 | fs_create.max_sect_size = f->shared->maxaddr; |
398 | | |
399 | | /* Set up alignment and threshold to use depending on TYPE */ |
400 | 0 | if (H5F_PAGED_AGGR(f)) { |
401 | 0 | alignment = (type == H5F_MEM_PAGE_GENERIC) ? f->shared->fs_page_size : (hsize_t)H5F_ALIGN_DEF; |
402 | 0 | threshold = H5F_ALIGN_THRHD_DEF; |
403 | 0 | } /* end if */ |
404 | 0 | else { |
405 | 0 | alignment = f->shared->alignment; |
406 | 0 | threshold = f->shared->threshold; |
407 | 0 | } /* end else */ |
408 | | |
409 | | /* Set the ring type in the API context */ |
410 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, type)) |
411 | 0 | fsm_ring = H5AC_RING_MDFSM; |
412 | 0 | else |
413 | 0 | fsm_ring = H5AC_RING_RDFSM; |
414 | 0 | H5AC_set_ring(fsm_ring, &orig_ring); |
415 | |
|
416 | 0 | if (NULL == (f->shared->fs_man[type] = |
417 | 0 | H5FS_create(f, NULL, &fs_create, NELMTS(classes), classes, f, alignment, threshold))) |
418 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info"); |
419 | | |
420 | | /* Set the state for the free space manager to "open", if it is now */ |
421 | 0 | if (f->shared->fs_man[type]) |
422 | 0 | f->shared->fs_state[type] = H5F_FS_STATE_OPEN; |
423 | |
|
424 | 0 | done: |
425 | | /* Reset the ring in the API context */ |
426 | 0 | if (orig_ring != H5AC_RING_INV) |
427 | 0 | H5AC_set_ring(orig_ring, NULL); |
428 | |
|
429 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
430 | 0 | } /* end H5MF__create_fstype() */ |
431 | | |
432 | | /*------------------------------------------------------------------------- |
433 | | * Function: H5MF__start_fstype |
434 | | * |
435 | | * Purpose: Open or create a free space manager of a given TYPE. |
436 | | * Note that TYPE can be H5F_mem_page_t or H5FD_mem_t enum types. |
437 | | * |
438 | | * Return: Success: non-negative |
439 | | * Failure: negative |
440 | | * |
441 | | *------------------------------------------------------------------------- |
442 | | */ |
443 | | herr_t |
444 | | H5MF__start_fstype(H5F_t *f, H5F_mem_page_t type) |
445 | 0 | { |
446 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
447 | |
|
448 | 0 | FUNC_ENTER_PACKAGE |
449 | | |
450 | | /* |
451 | | * Check arguments. |
452 | | */ |
453 | 0 | assert(f); |
454 | 0 | assert(f->shared); |
455 | 0 | if (H5F_PAGED_AGGR(f)) |
456 | 0 | assert(type < H5F_MEM_PAGE_NTYPES); |
457 | 0 | else { |
458 | 0 | assert((H5FD_mem_t)type < H5FD_MEM_NTYPES); |
459 | 0 | assert((H5FD_mem_t)type != H5FD_MEM_NOLIST); |
460 | 0 | } /* end else */ |
461 | | |
462 | | /* Check if the free space manager exists already */ |
463 | 0 | if (H5_addr_defined(f->shared->fs_addr[type])) { |
464 | | /* Open existing free space manager */ |
465 | 0 | if (H5MF__open_fstype(f, type) < 0) |
466 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTOPENOBJ, FAIL, "can't initialize file free space"); |
467 | 0 | } /* end if */ |
468 | 0 | else { |
469 | | /* Create new free space manager */ |
470 | 0 | if (H5MF__create_fstype(f, type) < 0) |
471 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCREATE, FAIL, "can't initialize file free space"); |
472 | 0 | } /* end else */ |
473 | | |
474 | 0 | done: |
475 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
476 | 0 | } /* end H5MF__start_fstype() */ |
477 | | |
478 | | /*------------------------------------------------------------------------- |
479 | | * Function: H5MF__delete_fstype |
480 | | * |
481 | | * Purpose: Delete the free-space manager as specified by TYPE. |
482 | | * Note that TYPE can be H5F_mem_page_t or H5FD_mem_t enum types. |
483 | | * |
484 | | * Return: Success: non-negative |
485 | | * Failure: negative |
486 | | * |
487 | | *------------------------------------------------------------------------- |
488 | | */ |
489 | | static herr_t |
490 | | H5MF__delete_fstype(H5F_t *f, H5F_mem_page_t type) |
491 | 0 | { |
492 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
493 | 0 | H5AC_ring_t fsm_ring = H5AC_RING_INV; /* Ring of FSM */ |
494 | 0 | haddr_t tmp_fs_addr; /* Temporary holder for free space manager address */ |
495 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
496 | |
|
497 | 0 | FUNC_ENTER_PACKAGE |
498 | | |
499 | | /* check args */ |
500 | 0 | assert(f); |
501 | 0 | if (H5F_PAGED_AGGR(f)) |
502 | 0 | assert(type < H5F_MEM_PAGE_NTYPES); |
503 | 0 | else |
504 | 0 | assert((H5FD_mem_t)type < H5FD_MEM_NTYPES); |
505 | 0 | assert(H5_addr_defined(f->shared->fs_addr[type])); |
506 | | |
507 | | /* Put address into temporary variable and reset it */ |
508 | | /* (Avoids loopback in file space freeing routine) */ |
509 | 0 | tmp_fs_addr = f->shared->fs_addr[type]; |
510 | 0 | f->shared->fs_addr[type] = HADDR_UNDEF; |
511 | | |
512 | | /* Shift to "deleting" state, to make certain we don't track any |
513 | | * file space freed as a result of deleting the free space manager. |
514 | | */ |
515 | 0 | f->shared->fs_state[type] = H5F_FS_STATE_DELETING; |
516 | | |
517 | | /* Set the ring type in the API context */ |
518 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, type)) |
519 | 0 | fsm_ring = H5AC_RING_MDFSM; |
520 | 0 | else |
521 | 0 | fsm_ring = H5AC_RING_RDFSM; |
522 | 0 | H5AC_set_ring(fsm_ring, &orig_ring); |
523 | |
|
524 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
525 | | fprintf(stderr, "%s: Before deleting free space manager\n", __func__); |
526 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
527 | | |
528 | | /* Delete free space manager for this type */ |
529 | 0 | if (H5FS_delete(f, tmp_fs_addr) < 0) |
530 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't delete free space manager"); |
531 | | |
532 | | /* Shift [back] to closed state */ |
533 | 0 | assert(f->shared->fs_state[type] == H5F_FS_STATE_DELETING); |
534 | 0 | f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; |
535 | | |
536 | | /* Sanity check that the free space manager for this type wasn't started up again */ |
537 | 0 | assert(!H5_addr_defined(f->shared->fs_addr[type])); |
538 | |
|
539 | 0 | done: |
540 | | /* Reset the ring in the API context */ |
541 | 0 | if (orig_ring != H5AC_RING_INV) |
542 | 0 | H5AC_set_ring(orig_ring, NULL); |
543 | |
|
544 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
545 | 0 | } /* end H5MF__delete_fstype() */ |
546 | | |
547 | | /*------------------------------------------------------------------------- |
548 | | * Function: H5MF__close_fstype |
549 | | * |
550 | | * Purpose: Close the free space manager of TYPE for file |
551 | | * Note that TYPE can be H5F_mem_page_t or H5FD_mem_t enum types. |
552 | | * |
553 | | * Return: Success: non-negative |
554 | | * Failure: negative |
555 | | * |
556 | | *------------------------------------------------------------------------- |
557 | | */ |
558 | | static herr_t |
559 | | H5MF__close_fstype(H5F_t *f, H5F_mem_page_t type) |
560 | 0 | { |
561 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
562 | |
|
563 | 0 | FUNC_ENTER_PACKAGE |
564 | | |
565 | | /* |
566 | | * Check arguments. |
567 | | */ |
568 | 0 | assert(f); |
569 | 0 | if (H5F_PAGED_AGGR(f)) |
570 | 0 | assert(type < H5F_MEM_PAGE_NTYPES); |
571 | 0 | else |
572 | 0 | assert((H5FD_mem_t)type < H5FD_MEM_NTYPES); |
573 | 0 | assert(f->shared); |
574 | 0 | assert(f->shared->fs_man[type]); |
575 | 0 | assert(f->shared->fs_state[type] != H5F_FS_STATE_CLOSED); |
576 | |
|
577 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
578 | | fprintf(stderr, "%s: Before closing free space manager\n", __func__); |
579 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
580 | | |
581 | | /* Close an existing free space structure for the file */ |
582 | 0 | if (H5FS_close(f, f->shared->fs_man[type]) < 0) |
583 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't release free space info"); |
584 | 0 | f->shared->fs_man[type] = NULL; |
585 | 0 | f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; |
586 | |
|
587 | 0 | done: |
588 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
589 | 0 | } /* end H5MF__close_fstype() */ |
590 | | |
591 | | /*------------------------------------------------------------------------- |
592 | | * Function: H5MF__add_sect |
593 | | * |
594 | | * Purpose: To add a section to the specified free-space manager. |
595 | | * |
596 | | * Return: Success: non-negative |
597 | | * Failure: negative |
598 | | * |
599 | | *------------------------------------------------------------------------- |
600 | | */ |
601 | | herr_t |
602 | | H5MF__add_sect(H5F_t *f, H5FD_mem_t alloc_type, H5FS_t *fspace, H5MF_free_section_t *node, |
603 | | bool *merged_or_shrunk) |
604 | 0 | { |
605 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
606 | 0 | H5AC_ring_t fsm_ring = H5AC_RING_INV; /* Ring of FSM */ |
607 | 0 | H5MF_sect_ud_t udata; /* User data for callback */ |
608 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
609 | |
|
610 | 0 | FUNC_ENTER_PACKAGE |
611 | |
|
612 | 0 | assert(f); |
613 | 0 | assert(fspace); |
614 | 0 | assert(node); |
615 | | |
616 | | /* Construct user data for callbacks */ |
617 | 0 | udata.f = f; |
618 | 0 | udata.alloc_type = alloc_type; |
619 | 0 | udata.allow_sect_absorb = true; |
620 | 0 | udata.allow_eoa_shrink_only = false; |
621 | | |
622 | | /* Set the ring type in the API context */ |
623 | 0 | if (H5MF__fsm_is_self_referential(f->shared, fspace)) |
624 | 0 | fsm_ring = H5AC_RING_MDFSM; |
625 | 0 | else |
626 | 0 | fsm_ring = H5AC_RING_RDFSM; |
627 | 0 | H5AC_set_ring(fsm_ring, &orig_ring); |
628 | |
|
629 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
630 | | fprintf(stderr, |
631 | | "%s: adding node, node->sect_info.addr = %" PRIuHADDR ", node->sect_info.size = %" PRIuHSIZE "\n", |
632 | | __func__, node->sect_info.addr, node->sect_info.size); |
633 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
634 | | /* Add the section */ |
635 | 0 | if (H5FS_sect_add(f, fspace, (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata, |
636 | 0 | merged_or_shrunk) < 0) |
637 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't re-add section to file free space"); |
638 | | |
639 | 0 | done: |
640 | | /* Reset the ring in the API context */ |
641 | 0 | if (orig_ring != H5AC_RING_INV) |
642 | 0 | H5AC_set_ring(orig_ring, NULL); |
643 | |
|
644 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
645 | 0 | } /* end H5MF__add_sect() */ |
646 | | |
647 | | /*------------------------------------------------------------------------- |
648 | | * Function: H5MF__find_sect |
649 | | * |
650 | | * Purpose: To find a section from the specified free-space manager to fulfill the request. |
651 | | * If found, re-add the left-over space back to the manager. |
652 | | * |
653 | | * Return: true if a section is found to fulfill the request |
654 | | * false if not |
655 | | * |
656 | | *------------------------------------------------------------------------- |
657 | | */ |
658 | | htri_t |
659 | | H5MF__find_sect(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size, H5FS_t *fspace, haddr_t *addr) |
660 | 0 | { |
661 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
662 | 0 | H5AC_ring_t fsm_ring = H5AC_RING_INV; /* Ring of FSM */ |
663 | 0 | H5MF_free_section_t *node; /* Free space section pointer */ |
664 | 0 | htri_t ret_value = FAIL; /* Whether an existing free list node was found */ |
665 | |
|
666 | 0 | FUNC_ENTER_PACKAGE |
667 | |
|
668 | 0 | assert(f); |
669 | 0 | assert(fspace); |
670 | | |
671 | | /* Set the ring type in the API context */ |
672 | 0 | if (H5MF__fsm_is_self_referential(f->shared, fspace)) |
673 | 0 | fsm_ring = H5AC_RING_MDFSM; |
674 | 0 | else |
675 | 0 | fsm_ring = H5AC_RING_RDFSM; |
676 | 0 | H5AC_set_ring(fsm_ring, &orig_ring); |
677 | | |
678 | | /* Try to get a section from the free space manager */ |
679 | 0 | if ((ret_value = H5FS_sect_find(f, fspace, size, (H5FS_section_info_t **)&node)) < 0) |
680 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "error locating free space in file"); |
681 | | |
682 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
683 | | fprintf(stderr, "%s: section found = %d\n", __func__, ret_value); |
684 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
685 | | |
686 | | /* Check for actually finding section */ |
687 | 0 | if (ret_value) { |
688 | | /* Sanity check */ |
689 | 0 | assert(node); |
690 | | |
691 | | /* Retrieve return value */ |
692 | 0 | if (addr) |
693 | 0 | *addr = node->sect_info.addr; |
694 | | |
695 | | /* Check for eliminating the section */ |
696 | 0 | if (node->sect_info.size == size) { |
697 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
698 | | fprintf(stderr, "%s: freeing node\n", __func__); |
699 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
700 | | |
701 | | /* Free section node */ |
702 | 0 | if (H5MF__sect_free((H5FS_section_info_t *)node) < 0) |
703 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node"); |
704 | 0 | } /* end if */ |
705 | 0 | else { |
706 | | /* Adjust information for section */ |
707 | 0 | node->sect_info.addr += size; |
708 | 0 | node->sect_info.size -= size; |
709 | |
|
710 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
711 | | fprintf(stderr, "%s: re-adding node, node->sect_info.size = %" PRIuHSIZE "\n", __func__, |
712 | | node->sect_info.size); |
713 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
714 | | |
715 | | /* Re-add the section to the free-space manager */ |
716 | 0 | if (H5MF__add_sect(f, alloc_type, fspace, node, NULL) < 0) { |
717 | 0 | node->sect_info.addr -= size; |
718 | 0 | node->sect_info.size += size; |
719 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't re-add section to file free space"); |
720 | 0 | } |
721 | 0 | } /* end else */ |
722 | 0 | } /* end if */ |
723 | | |
724 | 0 | done: |
725 | | /* Reset the ring in the API context */ |
726 | 0 | if (orig_ring != H5AC_RING_INV) |
727 | 0 | H5AC_set_ring(orig_ring, NULL); |
728 | |
|
729 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
730 | 0 | } /* end H5MF__find_sect() */ |
731 | | |
732 | | /*------------------------------------------------------------------------- |
733 | | * Function: H5MF_alloc |
734 | | * |
735 | | * Purpose: Allocate SIZE bytes of file memory and return the relative |
736 | | * address where that contiguous chunk of file memory exists. |
737 | | * The TYPE argument describes the purpose for which the storage |
738 | | * is being requested. |
739 | | * |
740 | | * Return: Success: The file address of new chunk. |
741 | | * Failure: HADDR_UNDEF |
742 | | * |
743 | | *------------------------------------------------------------------------- |
744 | | */ |
745 | | haddr_t |
746 | | H5MF_alloc(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size) |
747 | 0 | { |
748 | 0 | H5AC_ring_t fsm_ring = H5AC_RING_INV; /* free space manager ring */ |
749 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
750 | 0 | H5F_mem_page_t fs_type; /* Free space type (mapped from allocation type) */ |
751 | 0 | haddr_t ret_value = HADDR_UNDEF; /* Return value */ |
752 | |
|
753 | 0 | FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, HADDR_UNDEF) |
754 | | #ifdef H5MF_ALLOC_DEBUG |
755 | | fprintf(stderr, "%s: alloc_type = %u, size = %" PRIuHSIZE "\n", __func__, (unsigned)alloc_type, size); |
756 | | #endif /* H5MF_ALLOC_DEBUG */ |
757 | | |
758 | | /* check arguments */ |
759 | 0 | assert(f); |
760 | 0 | assert(f->shared); |
761 | 0 | assert(f->shared->lf); |
762 | 0 | assert(size > 0); |
763 | |
|
764 | 0 | H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &fs_type); |
765 | |
|
766 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
767 | | fprintf(stderr, "%s: Check 1.0\n", __func__); |
768 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
769 | | |
770 | | /* Set the ring type in the API context */ |
771 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, fs_type)) |
772 | 0 | fsm_ring = H5AC_RING_MDFSM; |
773 | 0 | else |
774 | 0 | fsm_ring = H5AC_RING_RDFSM; |
775 | 0 | H5AC_set_ring(fsm_ring, &orig_ring); |
776 | | |
777 | | /* Check if we are using the free space manager for this file */ |
778 | 0 | if (H5F_HAVE_FREE_SPACE_MANAGER(f)) { |
779 | | /* We are about to change the contents of the free space manager -- |
780 | | * notify metadata cache that the associated fsm ring is |
781 | | * unsettled |
782 | | */ |
783 | 0 | if (H5AC_unsettle_ring(f, fsm_ring) < 0) |
784 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, HADDR_UNDEF, |
785 | 0 | "attempt to notify cache that ring is unsettled failed"); |
786 | | |
787 | | /* Check if the free space manager for the file has been initialized */ |
788 | 0 | if (!f->shared->fs_man[fs_type] && H5_addr_defined(f->shared->fs_addr[fs_type])) { |
789 | | /* Open the free-space manager */ |
790 | 0 | if (H5MF__open_fstype(f, fs_type) < 0) |
791 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTOPENOBJ, HADDR_UNDEF, "can't initialize file free space"); |
792 | 0 | assert(f->shared->fs_man[fs_type]); |
793 | 0 | } /* end if */ |
794 | | |
795 | | /* Search for large enough space in the free space manager */ |
796 | 0 | if (f->shared->fs_man[fs_type]) |
797 | 0 | if (H5MF__find_sect(f, alloc_type, size, f->shared->fs_man[fs_type], &ret_value) < 0) |
798 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "error locating a node"); |
799 | 0 | } /* end if */ |
800 | | |
801 | | /* If no space is found from the free-space manager, continue further action */ |
802 | 0 | if (!H5_addr_defined(ret_value)) { |
803 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
804 | | fprintf(stderr, "%s: Check 2.0\n", __func__); |
805 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
806 | 0 | if (f->shared->fs_strategy == H5F_FSPACE_STRATEGY_PAGE) { |
807 | 0 | assert(f->shared->fs_page_size >= H5F_FILE_SPACE_PAGE_SIZE_MIN); |
808 | 0 | if (HADDR_UNDEF == (ret_value = H5MF__alloc_pagefs(f, alloc_type, size))) |
809 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, |
810 | 0 | "allocation failed from paged aggregation"); |
811 | 0 | } /* end if */ |
812 | 0 | else { /* For non-paged aggregation, continue further action */ |
813 | 0 | if (HADDR_UNDEF == (ret_value = H5MF_aggr_vfd_alloc(f, alloc_type, size))) |
814 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "allocation failed from aggr/vfd"); |
815 | 0 | } /* end else */ |
816 | 0 | } /* end if */ |
817 | 0 | assert(H5_addr_defined(ret_value)); |
818 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
819 | | fprintf(stderr, "%s: Check 3.0\n", __func__); |
820 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
821 | |
|
822 | 0 | done: |
823 | | /* Reset the ring in the API context */ |
824 | 0 | if (orig_ring != H5AC_RING_INV) |
825 | 0 | H5AC_set_ring(orig_ring, NULL); |
826 | |
|
827 | | #ifdef H5MF_ALLOC_DEBUG |
828 | | fprintf(stderr, "%s: Leaving: ret_value = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", __func__, ret_value, |
829 | | size); |
830 | | #endif /* H5MF_ALLOC_DEBUG */ |
831 | | #ifdef H5MF_ALLOC_DEBUG_DUMP |
832 | | H5MF__sects_dump(f, stderr); |
833 | | #endif /* H5MF_ALLOC_DEBUG_DUMP */ |
834 | |
|
835 | 0 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
836 | 0 | } /* end H5MF_alloc() */ |
837 | | |
838 | | /*------------------------------------------------------------------------- |
839 | | * Function: H5MF__alloc_pagefs |
840 | | * |
841 | | * Purpose: Allocate space from either the large or small free-space manager. |
842 | | * For "large" request: |
843 | | * Allocate request from VFD |
844 | | * Determine mis-aligned fragment and return the fragment to the |
845 | | * appropriate manager |
846 | | * For "small" request: |
847 | | * Allocate a page from the large manager |
848 | | * Determine whether space is available from a mis-aligned fragment |
849 | | * being returned to the manager |
850 | | * Return left-over space to the manager after fulfilling request |
851 | | * |
852 | | * Return: Success: The file address of new chunk. |
853 | | * Failure: HADDR_UNDEF |
854 | | * |
855 | | *------------------------------------------------------------------------- |
856 | | */ |
857 | | static haddr_t |
858 | | H5MF__alloc_pagefs(H5F_t *f, H5FD_mem_t alloc_type, hsize_t size) |
859 | 0 | { |
860 | 0 | H5F_mem_page_t ptype; /* Free-space manager type */ |
861 | 0 | H5MF_free_section_t *node = NULL; /* Free space section pointer */ |
862 | 0 | bool section_merged_or_shrunk = false; /* Whether free space section was merged or shrunk away */ |
863 | 0 | haddr_t ret_value = HADDR_UNDEF; /* Return value */ |
864 | |
|
865 | 0 | FUNC_ENTER_PACKAGE |
866 | |
|
867 | | #ifdef H5MF_ALLOC_DEBUG |
868 | | fprintf(stderr, "%s: alloc_type = %u, size = %" PRIuHSIZE "\n", __func__, (unsigned)alloc_type, size); |
869 | | #endif /* H5MF_ALLOC_DEBUG */ |
870 | |
|
871 | 0 | H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &ptype); |
872 | |
|
873 | 0 | switch (ptype) { |
874 | 0 | case H5F_MEM_PAGE_GENERIC: |
875 | 0 | case H5F_MEM_PAGE_LARGE_BTREE: |
876 | 0 | case H5F_MEM_PAGE_LARGE_DRAW: |
877 | 0 | case H5F_MEM_PAGE_LARGE_GHEAP: |
878 | 0 | case H5F_MEM_PAGE_LARGE_LHEAP: |
879 | 0 | case H5F_MEM_PAGE_LARGE_OHDR: { |
880 | 0 | haddr_t eoa; /* EOA for the file */ |
881 | 0 | hsize_t frag_size = 0; /* Fragment size */ |
882 | | |
883 | | /* Get the EOA for the file */ |
884 | 0 | if (HADDR_UNDEF == (eoa = H5F_get_eoa(f, alloc_type))) |
885 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, HADDR_UNDEF, "Unable to get eoa"); |
886 | 0 | assert(!(eoa % f->shared->fs_page_size)); |
887 | |
|
888 | 0 | H5MF_EOA_MISALIGN(f, (eoa + size), f->shared->fs_page_size, frag_size); |
889 | | |
890 | | /* Allocate from VFD */ |
891 | 0 | if (HADDR_UNDEF == (ret_value = H5F__alloc(f, alloc_type, size + frag_size, NULL, NULL))) |
892 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate file space"); |
893 | | |
894 | | /* If there is a mis-aligned fragment at EOA */ |
895 | 0 | if (frag_size) { |
896 | | |
897 | | /* Start up the free-space manager */ |
898 | 0 | if (!(f->shared->fs_man[ptype])) |
899 | 0 | if (H5MF__start_fstype(f, ptype) < 0) |
900 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, |
901 | 0 | "can't initialize file free space"); |
902 | | |
903 | | /* Create free space section for the fragment */ |
904 | 0 | if (NULL == (node = H5MF__sect_new(H5MF_FSPACE_SECT_LARGE, ret_value + size, frag_size))) |
905 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, |
906 | 0 | "can't initialize free space section"); |
907 | | |
908 | | /* Add the fragment to the large free-space manager */ |
909 | 0 | if (H5MF__add_sect(f, alloc_type, f->shared->fs_man[ptype], node, §ion_merged_or_shrunk) < |
910 | 0 | 0) { |
911 | 0 | if (section_merged_or_shrunk) |
912 | 0 | node = NULL; |
913 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, |
914 | 0 | "can't re-add section to file free space"); |
915 | 0 | } |
916 | | |
917 | 0 | node = NULL; |
918 | 0 | } /* end if */ |
919 | 0 | } break; |
920 | | |
921 | 0 | case H5F_MEM_PAGE_META: |
922 | 0 | case H5F_MEM_PAGE_DRAW: |
923 | 0 | case H5F_MEM_PAGE_BTREE: |
924 | 0 | case H5F_MEM_PAGE_GHEAP: |
925 | 0 | case H5F_MEM_PAGE_LHEAP: |
926 | 0 | case H5F_MEM_PAGE_OHDR: { |
927 | 0 | haddr_t new_page; /* The address for the new file size page */ |
928 | | |
929 | | /* Allocate one file space page */ |
930 | 0 | if (HADDR_UNDEF == (new_page = H5MF_alloc(f, alloc_type, f->shared->fs_page_size))) |
931 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate file space"); |
932 | | |
933 | | /* Start up the free-space manager */ |
934 | 0 | if (!(f->shared->fs_man[ptype])) |
935 | 0 | if (H5MF__start_fstype(f, ptype) < 0) |
936 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "can't initialize file free space"); |
937 | 0 | assert(f->shared->fs_man[ptype]); |
938 | |
|
939 | 0 | if (NULL == (node = H5MF__sect_new(H5MF_FSPACE_SECT_SMALL, (new_page + size), |
940 | 0 | (f->shared->fs_page_size - size)))) |
941 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "can't initialize free space section"); |
942 | | |
943 | | /* Add the remaining space in the page to the manager */ |
944 | 0 | if (H5MF__add_sect(f, alloc_type, f->shared->fs_man[ptype], node, §ion_merged_or_shrunk) < |
945 | 0 | 0) { |
946 | 0 | if (section_merged_or_shrunk) |
947 | 0 | node = NULL; |
948 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, |
949 | 0 | "can't re-add section to file free space"); |
950 | 0 | } |
951 | | |
952 | 0 | node = NULL; |
953 | | |
954 | | /* Insert the new page into the Page Buffer list of new pages so |
955 | | we don't read an empty page from disk */ |
956 | 0 | if (f->shared->page_buf != NULL && H5PB_add_new_page(f->shared, alloc_type, new_page) < 0) |
957 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, |
958 | 0 | "can't add new page to Page Buffer new page list"); |
959 | | |
960 | 0 | ret_value = new_page; |
961 | 0 | } break; |
962 | | |
963 | 0 | case H5F_MEM_PAGE_NTYPES: |
964 | 0 | case H5F_MEM_PAGE_DEFAULT: |
965 | 0 | default: |
966 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, |
967 | 0 | "can't allocate file space: unrecognized type"); |
968 | 0 | break; |
969 | 0 | } /* end switch */ |
970 | | |
971 | 0 | done: |
972 | | #ifdef H5MF_ALLOC_DEBUG |
973 | | fprintf(stderr, "%s: Leaving: ret_value = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", __func__, ret_value, |
974 | | size); |
975 | | #endif /* H5MF_ALLOC_DEBUG */ |
976 | | #ifdef H5MF_ALLOC_DEBUG_DUMP |
977 | | H5MF__sects_dump(f, stderr); |
978 | | #endif /* H5MF_ALLOC_DEBUG_DUMP */ |
979 | | |
980 | | /* Release section node, if allocated and not added to section list or merged */ |
981 | 0 | if (node) |
982 | 0 | if (H5MF__sect_free((H5FS_section_info_t *)node) < 0) |
983 | 0 | HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, HADDR_UNDEF, "can't free section node"); |
984 | |
|
985 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
986 | 0 | } /* end H5MF__alloc_pagefs() */ |
987 | | |
988 | | /*------------------------------------------------------------------------- |
989 | | * Function: H5MF_alloc_tmp |
990 | | * |
991 | | * Purpose: Allocate temporary space in the file |
992 | | * |
993 | | * Note: The address returned is non-overlapping with any other address |
994 | | * in the file and suitable for insertion into the metadata |
995 | | * cache. |
996 | | * |
997 | | * The address is _not_ suitable for actual file I/O and will |
998 | | * cause an error if it is so used. |
999 | | * |
1000 | | * The space allocated with this routine should _not_ be freed, |
1001 | | * it should just be abandoned. Calling H5MF_xfree() with space |
1002 | | * from this routine will cause an error. |
1003 | | * |
1004 | | * Return: Success: Temporary file address |
1005 | | * Failure: HADDR_UNDEF |
1006 | | * |
1007 | | *------------------------------------------------------------------------- |
1008 | | */ |
1009 | | haddr_t |
1010 | | H5MF_alloc_tmp(H5F_t *f, hsize_t size) |
1011 | 0 | { |
1012 | 0 | haddr_t eoa; /* End of allocated space in the file */ |
1013 | 0 | haddr_t ret_value = HADDR_UNDEF; /* Return value */ |
1014 | |
|
1015 | 0 | FUNC_ENTER_NOAPI(HADDR_UNDEF) |
1016 | | #ifdef H5MF_ALLOC_DEBUG |
1017 | | fprintf(stderr, "%s: size = %" PRIuHSIZE "\n", __func__, size); |
1018 | | #endif /* H5MF_ALLOC_DEBUG */ |
1019 | | |
1020 | | /* check args */ |
1021 | 0 | assert(f); |
1022 | 0 | assert(f->shared); |
1023 | 0 | assert(f->shared->lf); |
1024 | 0 | assert(size > 0); |
1025 | | |
1026 | | /* Retrieve the 'eoa' for the file */ |
1027 | 0 | if (HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_DEFAULT))) |
1028 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, HADDR_UNDEF, "driver get_eoa request failed"); |
1029 | | |
1030 | | /* Compute value to return */ |
1031 | 0 | ret_value = f->shared->tmp_addr - size; |
1032 | | |
1033 | | /* Check for overlap into the actual allocated space in the file */ |
1034 | 0 | if (H5_addr_le(ret_value, eoa)) |
1035 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, HADDR_UNDEF, "driver get_eoa request failed"); |
1036 | | |
1037 | | /* Adjust temporary address allocator in the file */ |
1038 | 0 | f->shared->tmp_addr = ret_value; |
1039 | |
|
1040 | 0 | done: |
1041 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1042 | 0 | } /* end H5MF_alloc_tmp() */ |
1043 | | |
1044 | | /*------------------------------------------------------------------------- |
1045 | | * Function: H5MF_xfree |
1046 | | * |
1047 | | * Purpose: Frees part of a file, making that part of the file |
1048 | | * available for reuse. |
1049 | | * |
1050 | | * Return: Non-negative on success/Negative on failure |
1051 | | * |
1052 | | *------------------------------------------------------------------------- |
1053 | | */ |
1054 | | herr_t |
1055 | | H5MF_xfree(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size) |
1056 | 0 | { |
1057 | 0 | H5F_mem_page_t fs_type; /* Free space type (mapped from allocation type) */ |
1058 | 0 | H5MF_free_section_t *node = NULL; /* Free space section pointer */ |
1059 | 0 | unsigned ctype; /* section class type */ |
1060 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
1061 | 0 | H5AC_ring_t fsm_ring; /* Ring of FSM */ |
1062 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1063 | |
|
1064 | 0 | FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) |
1065 | | #ifdef H5MF_ALLOC_DEBUG |
1066 | | fprintf(stderr, "%s: Entering - alloc_type = %u, addr = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", |
1067 | | __func__, (unsigned)alloc_type, addr, size); |
1068 | | #endif /* H5MF_ALLOC_DEBUG */ |
1069 | | |
1070 | | /* check arguments */ |
1071 | 0 | assert(f); |
1072 | 0 | if (!H5_addr_defined(addr) || 0 == size) |
1073 | 0 | HGOTO_DONE(SUCCEED); |
1074 | 0 | assert(addr != 0); /* Can't deallocate the superblock :-) */ |
1075 | |
|
1076 | 0 | H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &fs_type); |
1077 | | |
1078 | | /* Set the ring type in the API context */ |
1079 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, fs_type)) |
1080 | 0 | fsm_ring = H5AC_RING_MDFSM; |
1081 | 0 | else |
1082 | 0 | fsm_ring = H5AC_RING_RDFSM; |
1083 | 0 | H5AC_set_ring(fsm_ring, &orig_ring); |
1084 | | |
1085 | | /* we are about to change the contents of the free space manager -- |
1086 | | * notify metadata cache that the associated fsm ring is |
1087 | | * unsettled |
1088 | | */ |
1089 | | /* Only do so for strategies that use free-space managers */ |
1090 | 0 | if (H5F_HAVE_FREE_SPACE_MANAGER(f)) |
1091 | 0 | if (H5AC_unsettle_ring(f, fsm_ring) < 0) |
1092 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, |
1093 | 0 | "attempt to notify cache that ring is unsettled failed"); |
1094 | | |
1095 | | /* Check for attempting to free space that's a 'temporary' file address */ |
1096 | 0 | if (H5_addr_le(f->shared->tmp_addr, addr)) |
1097 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_BADRANGE, FAIL, "attempting to free temporary file space"); |
1098 | | |
1099 | | /* If it's metadata, check if the space to free intersects with the file's |
1100 | | * metadata accumulator |
1101 | | */ |
1102 | 0 | if (H5FD_MEM_DRAW != alloc_type) { |
1103 | | /* Check if the space to free intersects with the file's metadata accumulator */ |
1104 | 0 | if (H5F__accum_free(f->shared, alloc_type, addr, size) < 0) |
1105 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, |
1106 | 0 | "can't check free space intersection w/metadata accumulator"); |
1107 | 0 | } /* end if */ |
1108 | | |
1109 | | /* Check if the free space manager for the file has been initialized */ |
1110 | 0 | if (!f->shared->fs_man[fs_type]) { |
1111 | | /* If there's no free space manager for objects of this type, |
1112 | | * see if we can avoid creating one by checking if the freed |
1113 | | * space is at the end of the file |
1114 | | */ |
1115 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1116 | | fprintf(stderr, "%s: fs_addr = %" PRIuHADDR "\n", __func__, f->shared->fs_addr[fs_type]); |
1117 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1118 | 0 | if (!H5_addr_defined(f->shared->fs_addr[fs_type])) { |
1119 | 0 | htri_t status; /* "can absorb" status for section into */ |
1120 | |
|
1121 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1122 | | fprintf(stderr, "%s: Trying to avoid starting up free space manager\n", __func__); |
1123 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1124 | | /* Try to shrink the file or absorb the block into a block aggregator */ |
1125 | 0 | if ((status = H5MF_try_shrink(f, alloc_type, addr, size)) < 0) |
1126 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't check for absorbing block"); |
1127 | 0 | else if (status > 0) |
1128 | | /* Indicate success */ |
1129 | 0 | HGOTO_DONE(SUCCEED); |
1130 | 0 | else if (size < f->shared->fs_threshold) { |
1131 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1132 | | fprintf(stderr, "%s: dropping addr = %" PRIuHADDR ", size = %" PRIuHSIZE ", on the floor!\n", |
1133 | | __func__, addr, size); |
1134 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1135 | 0 | HGOTO_DONE(SUCCEED); |
1136 | 0 | } /* end else-if */ |
1137 | 0 | } /* end if */ |
1138 | | |
1139 | | /* If we are deleting the free space manager, leave now, to avoid |
1140 | | * [re-]starting it. |
1141 | | * or if file space strategy type is not using a free space manager |
1142 | | * (H5F_FSPACE_STRATEGY_AGGR or H5F_FSPACE_STRATEGY_NONE), drop free space |
1143 | | * section on the floor. |
1144 | | * |
1145 | | * Note: this drops the space to free on the floor... |
1146 | | * |
1147 | | */ |
1148 | 0 | if (f->shared->fs_state[fs_type] == H5F_FS_STATE_DELETING || !H5F_HAVE_FREE_SPACE_MANAGER(f)) { |
1149 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1150 | | fprintf(stderr, "%s: dropping addr = %" PRIuHADDR ", size = %" PRIuHSIZE ", on the floor!\n", |
1151 | | __func__, addr, size); |
1152 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1153 | 0 | HGOTO_DONE(SUCCEED); |
1154 | 0 | } /* end if */ |
1155 | | |
1156 | | /* There's either already a free space manager, or the freed |
1157 | | * space isn't at the end of the file, so start up (or create) |
1158 | | * the file space manager |
1159 | | */ |
1160 | 0 | if (H5MF__start_fstype(f, fs_type) < 0) |
1161 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space"); |
1162 | 0 | } /* end if */ |
1163 | | |
1164 | | /* Create the free-space section for the freed section */ |
1165 | 0 | ctype = H5MF_SECT_CLASS_TYPE(f, size); |
1166 | 0 | if (NULL == (node = H5MF__sect_new(ctype, addr, size))) |
1167 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section"); |
1168 | | |
1169 | | /* If size of the freed section is larger than threshold, add it to the free space manager */ |
1170 | 0 | if (size >= f->shared->fs_threshold) { |
1171 | 0 | bool section_merged_or_shrunk = false; /* Whether free space section was merged or shrunk away */ |
1172 | |
|
1173 | 0 | assert(f->shared->fs_man[fs_type]); |
1174 | |
|
1175 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1176 | | fprintf(stderr, "%s: Before H5FS_sect_add()\n", __func__); |
1177 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1178 | | |
1179 | | /* Add to the free space for the file */ |
1180 | 0 | if (H5MF__add_sect(f, alloc_type, f->shared->fs_man[fs_type], node, §ion_merged_or_shrunk) < 0) { |
1181 | 0 | if (section_merged_or_shrunk) |
1182 | 0 | node = NULL; |
1183 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't add section to file free space"); |
1184 | 0 | } |
1185 | | |
1186 | 0 | node = NULL; |
1187 | |
|
1188 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1189 | | fprintf(stderr, "%s: After H5FS_sect_add()\n", __func__); |
1190 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1191 | 0 | } /* end if */ |
1192 | 0 | else { |
1193 | 0 | htri_t merged; /* Whether node was merged */ |
1194 | 0 | H5MF_sect_ud_t udata; /* User data for callback */ |
1195 | | |
1196 | | /* Construct user data for callbacks */ |
1197 | 0 | udata.f = f; |
1198 | 0 | udata.alloc_type = alloc_type; |
1199 | 0 | udata.allow_sect_absorb = true; |
1200 | 0 | udata.allow_eoa_shrink_only = false; |
1201 | | |
1202 | | /* Try to merge the section that is smaller than threshold */ |
1203 | 0 | if ((merged = H5FS_sect_try_merge(f, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, |
1204 | 0 | H5FS_ADD_RETURNED_SPACE, &udata)) < 0) |
1205 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't merge section to file free space"); |
1206 | 0 | else if (merged == true) /* successfully merged */ |
1207 | | /* Indicate that the node was used */ |
1208 | 0 | node = NULL; |
1209 | 0 | } /* end else */ |
1210 | | |
1211 | 0 | done: |
1212 | | /* Reset the ring in the API context */ |
1213 | 0 | if (orig_ring != H5AC_RING_INV) |
1214 | 0 | H5AC_set_ring(orig_ring, NULL); |
1215 | | |
1216 | | /* Release section node, if allocated and not added to section list or merged */ |
1217 | 0 | if (node) |
1218 | 0 | if (H5MF__sect_free((H5FS_section_info_t *)node) < 0) |
1219 | 0 | HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node"); |
1220 | |
|
1221 | | #ifdef H5MF_ALLOC_DEBUG |
1222 | | fprintf(stderr, "%s: Leaving, ret_value = %d\n", __func__, ret_value); |
1223 | | #endif /* H5MF_ALLOC_DEBUG */ |
1224 | | #ifdef H5MF_ALLOC_DEBUG_DUMP |
1225 | | H5MF__sects_dump(f, stderr); |
1226 | | #endif /* H5MF_ALLOC_DEBUG_DUMP */ |
1227 | 0 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
1228 | 0 | } /* end H5MF_xfree() */ |
1229 | | |
1230 | | /*------------------------------------------------------------------------- |
1231 | | * Function: H5MF_try_extend |
1232 | | * |
1233 | | * Purpose: Extend a block in the file if possible. |
1234 | | * For non-paged aggregation: |
1235 | | * --try to extend at EOA |
1236 | | * --try to extend into the aggregators |
1237 | | * --try to extend into a free-space section if adjoined |
1238 | | * For paged aggregation: |
1239 | | * --try to extend at EOA |
1240 | | * --try to extend into a free-space section if adjoined |
1241 | | * --try to extend into the page end threshold if a metadata block |
1242 | | * |
1243 | | * Return: Success: true(1) - Block was extended |
1244 | | * false(0) - Block could not be extended |
1245 | | * Failure: FAIL |
1246 | | * |
1247 | | *------------------------------------------------------------------------- |
1248 | | */ |
1249 | | htri_t |
1250 | | H5MF_try_extend(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size, hsize_t extra_requested) |
1251 | 0 | { |
1252 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
1253 | 0 | H5AC_ring_t fsm_ring; /* Ring of FSM */ |
1254 | 0 | haddr_t end; /* End of block to extend */ |
1255 | 0 | H5FD_mem_t map_type; /* Mapped type */ |
1256 | 0 | H5F_mem_page_t fs_type = H5F_MEM_PAGE_NTYPES; /* free space type */ |
1257 | 0 | htri_t allow_extend = true; /* Possible to extend the block */ |
1258 | 0 | hsize_t frag_size = 0; /* Size of mis-aligned fragment */ |
1259 | 0 | htri_t ret_value = false; /* Return value */ |
1260 | |
|
1261 | 0 | FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) |
1262 | | #ifdef H5MF_ALLOC_DEBUG |
1263 | | fprintf(stderr, |
1264 | | "%s: Entering: alloc_type = %u, addr = %" PRIuHADDR ", size = %" PRIuHSIZE |
1265 | | ", extra_requested = %" PRIuHSIZE "\n", |
1266 | | __func__, (unsigned)alloc_type, addr, size, extra_requested); |
1267 | | #endif /* H5MF_ALLOC_DEBUG */ |
1268 | | |
1269 | | /* Sanity check */ |
1270 | 0 | assert(f); |
1271 | 0 | assert(H5F_INTENT(f) & H5F_ACC_RDWR); |
1272 | | |
1273 | | /* Set mapped type, treating global heap as raw data */ |
1274 | 0 | map_type = (alloc_type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : alloc_type; |
1275 | | |
1276 | | /* Compute end of block to extend */ |
1277 | 0 | end = addr + size; |
1278 | | |
1279 | | /* For paged aggregation: |
1280 | | * To extend a small block: can only extend if not crossing page boundary |
1281 | | * To extend a large block at EOA: calculate in advance mis-aligned fragment so EOA will still end at |
1282 | | * page boundary |
1283 | | */ |
1284 | 0 | if (H5F_PAGED_AGGR(f)) { |
1285 | 0 | if (size < f->shared->fs_page_size) { |
1286 | | /* To extend a small block: cannot cross page boundary */ |
1287 | 0 | if ((addr / f->shared->fs_page_size) != (((end + extra_requested) - 1) / f->shared->fs_page_size)) |
1288 | 0 | allow_extend = false; |
1289 | 0 | } /* end if */ |
1290 | 0 | else { |
1291 | 0 | haddr_t eoa; /* EOA for the file */ |
1292 | | |
1293 | | /* To extend a large block: calculate in advance the mis-aligned fragment so EOA will end at |
1294 | | * page boundary if extended */ |
1295 | 0 | if (HADDR_UNDEF == (eoa = H5F_get_eoa(f, alloc_type))) |
1296 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "Unable to get eoa"); |
1297 | 0 | assert(!(eoa % f->shared->fs_page_size)); |
1298 | |
|
1299 | 0 | H5MF_EOA_MISALIGN(f, (eoa + extra_requested), f->shared->fs_page_size, frag_size); |
1300 | 0 | } /* end else */ |
1301 | 0 | } /* end if */ |
1302 | | |
1303 | | /* Get free space type from allocation type */ |
1304 | 0 | H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &fs_type); |
1305 | | |
1306 | | /* Set the ring type in the API context */ |
1307 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, fs_type)) |
1308 | 0 | fsm_ring = H5AC_RING_MDFSM; |
1309 | 0 | else |
1310 | 0 | fsm_ring = H5AC_RING_RDFSM; |
1311 | 0 | H5AC_set_ring(fsm_ring, &orig_ring); |
1312 | |
|
1313 | 0 | if (allow_extend) { |
1314 | | /* Try extending the block at EOA */ |
1315 | 0 | if ((ret_value = H5F__try_extend(f, map_type, end, extra_requested + frag_size)) < 0) |
1316 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending file"); |
1317 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1318 | | fprintf(stderr, "%s: extended = %d\n", __func__, ret_value); |
1319 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1320 | | |
1321 | | /* If extending at EOA succeeds: */ |
1322 | | /* for paged aggregation, put the fragment into the large-sized free-space manager */ |
1323 | 0 | if (ret_value == true && H5F_PAGED_AGGR(f) && frag_size) { |
1324 | 0 | H5MF_free_section_t *node = NULL; /* Free space section pointer */ |
1325 | | |
1326 | | /* Should be large-sized block */ |
1327 | 0 | assert(size >= f->shared->fs_page_size); |
1328 | | |
1329 | | /* Start up the free-space manager */ |
1330 | 0 | if (!(f->shared->fs_man[fs_type])) |
1331 | 0 | if (H5MF__start_fstype(f, fs_type) < 0) |
1332 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space"); |
1333 | | |
1334 | | /* Create free space section for the fragment */ |
1335 | 0 | if (NULL == (node = H5MF__sect_new(H5MF_FSPACE_SECT_LARGE, end + extra_requested, frag_size))) |
1336 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section"); |
1337 | | |
1338 | | /* Add the fragment to the large-sized free-space manager */ |
1339 | 0 | if (H5MF__add_sect(f, alloc_type, f->shared->fs_man[fs_type], node, NULL) < 0) |
1340 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't re-add section to file free space"); |
1341 | | |
1342 | 0 | node = NULL; |
1343 | 0 | } /* end if */ |
1344 | | |
1345 | | /* For non-paged aggregation: try to extend into the aggregators */ |
1346 | 0 | if (ret_value == false && (f->shared->fs_strategy == H5F_FSPACE_STRATEGY_FSM_AGGR || |
1347 | 0 | f->shared->fs_strategy == H5F_FSPACE_STRATEGY_AGGR)) { |
1348 | 0 | H5F_blk_aggr_t *aggr; /* Aggregator to use */ |
1349 | | |
1350 | | /* Check if the block is able to extend into aggregation block */ |
1351 | 0 | aggr = (map_type == H5FD_MEM_DRAW) ? &(f->shared->sdata_aggr) : &(f->shared->meta_aggr); |
1352 | 0 | if ((ret_value = H5MF__aggr_try_extend(f, aggr, map_type, end, extra_requested)) < 0) |
1353 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending aggregation block"); |
1354 | |
|
1355 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1356 | | fprintf(stderr, "%s: H5MF__aggr_try_extend = %d\n", __func__, ret_value); |
1357 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1358 | 0 | } /* end if */ |
1359 | | |
1360 | | /* If no extension so far, try to extend into a free-space section */ |
1361 | 0 | if (ret_value == false && |
1362 | 0 | ((f->shared->fs_strategy == H5F_FSPACE_STRATEGY_FSM_AGGR) || (H5F_PAGED_AGGR(f)))) { |
1363 | 0 | H5MF_sect_ud_t udata; /* User data */ |
1364 | | |
1365 | | /* Construct user data for callbacks */ |
1366 | 0 | udata.f = f; |
1367 | 0 | udata.alloc_type = alloc_type; |
1368 | | |
1369 | | /* Check if the free space for the file has been initialized */ |
1370 | 0 | if (!f->shared->fs_man[fs_type] && H5_addr_defined(f->shared->fs_addr[fs_type])) |
1371 | | /* Open the free-space manager */ |
1372 | 0 | if (H5MF__open_fstype(f, fs_type) < 0) |
1373 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space"); |
1374 | | |
1375 | | /* Try to extend the block into a free-space section */ |
1376 | 0 | if (f->shared->fs_man[fs_type]) { |
1377 | 0 | if ((ret_value = H5FS_sect_try_extend(f, f->shared->fs_man[fs_type], addr, size, |
1378 | 0 | extra_requested, H5FS_ADD_RETURNED_SPACE, &udata)) < 0) |
1379 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, |
1380 | 0 | "error extending block in free space manager"); |
1381 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1382 | | fprintf(stderr, "%s: Try to H5FS_sect_try_extend = %d\n", __func__, ret_value); |
1383 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1384 | 0 | } /* end if */ |
1385 | | |
1386 | | /* For paged aggregation and a metadata block: try to extend into page end threshold */ |
1387 | 0 | if (ret_value == false && H5F_PAGED_AGGR(f) && map_type != H5FD_MEM_DRAW) { |
1388 | 0 | H5MF_EOA_MISALIGN(f, end, f->shared->fs_page_size, frag_size); |
1389 | |
|
1390 | 0 | if (frag_size <= H5F_PGEND_META_THRES(f) && extra_requested <= frag_size) |
1391 | 0 | ret_value = true; |
1392 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1393 | | fprintf(stderr, "%s: Try to extend into the page end threshold = %d\n", __func__, ret_value); |
1394 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1395 | 0 | } /* end if */ |
1396 | 0 | } /* end if */ |
1397 | 0 | } /* allow_extend */ |
1398 | | |
1399 | 0 | done: |
1400 | | /* Reset the ring in the API context */ |
1401 | 0 | if (orig_ring != H5AC_RING_INV) |
1402 | 0 | H5AC_set_ring(orig_ring, NULL); |
1403 | |
|
1404 | | #ifdef H5MF_ALLOC_DEBUG |
1405 | | fprintf(stderr, "%s: Leaving: ret_value = %d\n", __func__, ret_value); |
1406 | | #endif /* H5MF_ALLOC_DEBUG */ |
1407 | | #ifdef H5MF_ALLOC_DEBUG_DUMP |
1408 | | H5MF__sects_dump(f, stderr); |
1409 | | #endif /* H5MF_ALLOC_DEBUG_DUMP */ |
1410 | |
|
1411 | 0 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
1412 | 0 | } /* end H5MF_try_extend() */ |
1413 | | |
1414 | | /*------------------------------------------------------------------------- |
1415 | | * Function: H5MF_try_shrink |
1416 | | * |
1417 | | * Purpose: Try to shrink the size of a file with a block or absorb it |
1418 | | * into a block aggregator. |
1419 | | * |
1420 | | * Return: Non-negative on success/Negative on failure |
1421 | | * |
1422 | | *------------------------------------------------------------------------- |
1423 | | */ |
1424 | | htri_t |
1425 | | H5MF_try_shrink(H5F_t *f, H5FD_mem_t alloc_type, haddr_t addr, hsize_t size) |
1426 | 0 | { |
1427 | 0 | H5MF_free_section_t *node = NULL; /* Free space section pointer */ |
1428 | 0 | H5MF_sect_ud_t udata; /* User data for callback */ |
1429 | 0 | const H5FS_section_class_t *sect_cls; /* Section class */ |
1430 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
1431 | 0 | H5AC_ring_t fsm_ring = H5AC_RING_INV; /* Ring of FSM */ |
1432 | 0 | H5F_mem_page_t fs_type; /* Free space type */ |
1433 | 0 | htri_t ret_value = false; /* Return value */ |
1434 | |
|
1435 | 0 | FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) |
1436 | | #ifdef H5MF_ALLOC_DEBUG |
1437 | | fprintf(stderr, "%s: Entering - alloc_type = %u, addr = %" PRIuHADDR ", size = %" PRIuHSIZE "\n", |
1438 | | __func__, (unsigned)alloc_type, addr, size); |
1439 | | #endif /* H5MF_ALLOC_DEBUG */ |
1440 | | |
1441 | | /* check arguments */ |
1442 | 0 | assert(f); |
1443 | 0 | assert(f->shared); |
1444 | 0 | assert(f->shared->lf); |
1445 | 0 | assert(H5_addr_defined(addr)); |
1446 | 0 | assert(size > 0); |
1447 | | |
1448 | | /* Set up free-space section class information */ |
1449 | 0 | sect_cls = H5MF_SECT_CLS_TYPE(f, size); |
1450 | 0 | assert(sect_cls); |
1451 | | |
1452 | | /* Get free space type from allocation type */ |
1453 | 0 | H5MF__alloc_to_fs_type(f->shared, alloc_type, size, &fs_type); |
1454 | | |
1455 | | /* Set the ring type in the API context */ |
1456 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, fs_type)) |
1457 | 0 | fsm_ring = H5AC_RING_MDFSM; |
1458 | 0 | else |
1459 | 0 | fsm_ring = H5AC_RING_RDFSM; |
1460 | 0 | H5AC_set_ring(fsm_ring, &orig_ring); |
1461 | | |
1462 | | /* Create free-space section for block */ |
1463 | 0 | if (NULL == (node = H5MF__sect_new(sect_cls->type, addr, size))) |
1464 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section"); |
1465 | | |
1466 | | /* Construct user data for callbacks */ |
1467 | 0 | udata.f = f; |
1468 | 0 | udata.alloc_type = alloc_type; |
1469 | 0 | udata.allow_sect_absorb = false; /* Force section to be absorbed into aggregator */ |
1470 | 0 | udata.allow_eoa_shrink_only = false; |
1471 | | |
1472 | | /* Check if the block can shrink the container */ |
1473 | 0 | if (sect_cls->can_shrink) { |
1474 | 0 | if ((ret_value = (*sect_cls->can_shrink)((const H5FS_section_info_t *)node, &udata)) < 0) |
1475 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't check if section can shrink container"); |
1476 | 0 | if (ret_value > 0) { |
1477 | 0 | assert(sect_cls->shrink); |
1478 | |
|
1479 | 0 | if ((*sect_cls->shrink)((H5FS_section_info_t **)&node, &udata) < 0) |
1480 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink container"); |
1481 | 0 | } /* end if */ |
1482 | 0 | } /* end if */ |
1483 | | |
1484 | 0 | done: |
1485 | | /* Reset the ring in the API context */ |
1486 | 0 | if (orig_ring != H5AC_RING_INV) |
1487 | 0 | H5AC_set_ring(orig_ring, NULL); |
1488 | | |
1489 | | /* Free section node allocated */ |
1490 | 0 | if (node && H5MF__sect_free((H5FS_section_info_t *)node) < 0) |
1491 | 0 | HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node"); |
1492 | |
|
1493 | | #ifdef H5MF_ALLOC_DEBUG |
1494 | | fprintf(stderr, "%s: Leaving, ret_value = %d\n", __func__, ret_value); |
1495 | | #endif /* H5MF_ALLOC_DEBUG */ |
1496 | 0 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
1497 | 0 | } /* end H5MF_try_shrink() */ |
1498 | | |
1499 | | /*------------------------------------------------------------------------- |
1500 | | * Function: H5MF_close |
1501 | | * |
1502 | | * Purpose: Close the free space tracker(s) for a file: |
1503 | | * paged or non-paged aggregation |
1504 | | * |
1505 | | * Return: SUCCEED/FAIL |
1506 | | * |
1507 | | *------------------------------------------------------------------------- |
1508 | | */ |
1509 | | herr_t |
1510 | | H5MF_close(H5F_t *f) |
1511 | 287 | { |
1512 | 287 | herr_t ret_value = SUCCEED; /* Return value */ |
1513 | | |
1514 | 287 | FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) |
1515 | | #ifdef H5MF_ALLOC_DEBUG |
1516 | | fprintf(stderr, "%s: Entering\n", __func__); |
1517 | | #endif /* H5MF_ALLOC_DEBUG */ |
1518 | | |
1519 | | /* check args */ |
1520 | 287 | assert(f); |
1521 | 287 | assert(f->shared); |
1522 | | |
1523 | 287 | if (H5F_PAGED_AGGR(f)) { |
1524 | 0 | if ((ret_value = H5MF__close_pagefs(f)) < 0) |
1525 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, |
1526 | 0 | "can't close free-space managers for 'page' file space"); |
1527 | 0 | } |
1528 | 287 | else { |
1529 | 287 | if ((ret_value = H5MF__close_aggrfs(f)) < 0) |
1530 | 1 | HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, |
1531 | 287 | "can't close free-space managers for 'aggr' file space"); |
1532 | 287 | } |
1533 | | |
1534 | 287 | done: |
1535 | | #ifdef H5MF_ALLOC_DEBUG |
1536 | | fprintf(stderr, "%s: Leaving\n", __func__); |
1537 | | #endif /* H5MF_ALLOC_DEBUG */ |
1538 | 287 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
1539 | 287 | } /* end H5MF_close() */ |
1540 | | |
1541 | | /*------------------------------------------------------------------------- |
1542 | | * Function: H5MF__close_delete_fstype |
1543 | | * |
1544 | | * Purpose: Common code for closing and deleting the freespace manager |
1545 | | * of TYPE for file. |
1546 | | * Note that TYPE can be H5F_mem_page_t or H5FD_mem_t enum types. |
1547 | | * |
1548 | | * Return: SUCCEED/FAIL |
1549 | | * |
1550 | | *------------------------------------------------------------------------- |
1551 | | */ |
1552 | | static herr_t |
1553 | | H5MF__close_delete_fstype(H5F_t *f, H5F_mem_page_t type) |
1554 | 2.00k | { |
1555 | 2.00k | herr_t ret_value = SUCCEED; /* Return value */ |
1556 | | |
1557 | 2.00k | FUNC_ENTER_PACKAGE |
1558 | | #ifdef H5MF_ALLOC_DEBUG |
1559 | | fprintf(stderr, "%s: Entering\n", __func__); |
1560 | | #endif /* H5MF_ALLOC_DEBUG */ |
1561 | | |
1562 | | /* check args */ |
1563 | 2.00k | assert(f); |
1564 | 2.00k | assert(f->shared); |
1565 | 2.00k | if (H5F_PAGED_AGGR(f)) |
1566 | 2.00k | assert(type < H5F_MEM_PAGE_NTYPES); |
1567 | 2.00k | else |
1568 | 2.00k | assert((H5FD_mem_t)type < H5FD_MEM_NTYPES); |
1569 | | |
1570 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1571 | | fprintf(stderr, "%s: Check 1.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %" PRIuHADDR "\n", |
1572 | | __func__, (unsigned)type, (void *)f->shared->fs_man[type], (unsigned)type, |
1573 | | f->shared->fs_addr[type]); |
1574 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1575 | | |
1576 | | /* If the free space manager for this type is open, close it */ |
1577 | 2.00k | if (f->shared->fs_man[type]) |
1578 | 0 | if (H5MF__close_fstype(f, type) < 0) |
1579 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't close the free space manager"); |
1580 | | |
1581 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
1582 | | fprintf(stderr, "%s: Check 2.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %" PRIuHADDR "\n", |
1583 | | __func__, (unsigned)type, (void *)f->shared->fs_man[type], (unsigned)type, |
1584 | | f->shared->fs_addr[type]); |
1585 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
1586 | | |
1587 | | /* If there is free space manager info for this type, delete it */ |
1588 | 2.00k | if (H5_addr_defined(f->shared->fs_addr[type])) |
1589 | 0 | if (H5MF__delete_fstype(f, type) < 0) |
1590 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't delete the free space manager"); |
1591 | | |
1592 | 2.00k | done: |
1593 | | #ifdef H5MF_ALLOC_DEBUG |
1594 | | fprintf(stderr, "%s: Leaving\n", __func__); |
1595 | | #endif /* H5MF_ALLOC_DEBUG */ |
1596 | 2.00k | FUNC_LEAVE_NOAPI(ret_value) |
1597 | 2.00k | } /* H5MF__close_delete() */ |
1598 | | |
1599 | | /*------------------------------------------------------------------------- |
1600 | | * Function: H5MF_try_close |
1601 | | * |
1602 | | * Purpose: This is called by H5Fformat_convert() to close and delete |
1603 | | * free-space managers when downgrading persistent free-space |
1604 | | * to non-persistent. |
1605 | | * |
1606 | | * Return: SUCCEED/FAIL |
1607 | | * |
1608 | | *------------------------------------------------------------------------- |
1609 | | */ |
1610 | | herr_t |
1611 | | H5MF_try_close(H5F_t *f) |
1612 | 0 | { |
1613 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
1614 | 0 | H5AC_ring_t curr_ring = H5AC_RING_INV; /* Current ring value */ |
1615 | 0 | H5AC_ring_t needed_ring = H5AC_RING_INV; /* Ring value needed for this iteration */ |
1616 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1617 | |
|
1618 | 0 | FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) |
1619 | | #ifdef H5MF_ALLOC_DEBUG |
1620 | | fprintf(stderr, "%s: Entering\n", __func__); |
1621 | | #endif /* H5MF_ALLOC_DEBUG */ |
1622 | | |
1623 | | /* check args */ |
1624 | 0 | assert(f); |
1625 | | |
1626 | | /* If there have been no file space allocations / deallocation so |
1627 | | * far, must call H5MF_tidy_self_referential_fsm_hack() to float |
1628 | | * all self referential FSMs and release file space allocated to |
1629 | | * them. Otherwise, the function will be called after the format |
1630 | | * conversion, and will become very confused. |
1631 | | * |
1632 | | * The situation is further complicated if a cache image exists |
1633 | | * and had not yet been loaded into the metadata cache. In this |
1634 | | * case, call H5AC_force_cache_image_load() instead of |
1635 | | * H5MF_tidy_self_referential_fsm_hack(). H5AC_force_cache_image_load() |
1636 | | * will load the cache image, and then call |
1637 | | * H5MF_tidy_self_referential_fsm_hack() to discard the cache image |
1638 | | * block. |
1639 | | */ |
1640 | | |
1641 | | /* Set the ring type in the API context. In most cases, we will |
1642 | | * need H5AC_RING_RDFSM, so initially set the ring in |
1643 | | * the context to that value. We will alter this later if needed. |
1644 | | */ |
1645 | 0 | H5AC_set_ring(H5AC_RING_RDFSM, &orig_ring); |
1646 | 0 | curr_ring = H5AC_RING_RDFSM; |
1647 | |
|
1648 | 0 | if (H5F_PAGED_AGGR(f)) { |
1649 | 0 | H5F_mem_page_t ptype; /* Memory type for iteration */ |
1650 | | |
1651 | | /* Iterate over all the free space types that have managers and |
1652 | | * get each free list's space |
1653 | | */ |
1654 | 0 | for (ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; ptype++) { |
1655 | | /* Test to see if we need to switch rings -- do so if required */ |
1656 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, ptype)) |
1657 | 0 | needed_ring = H5AC_RING_MDFSM; |
1658 | 0 | else |
1659 | 0 | needed_ring = H5AC_RING_RDFSM; |
1660 | |
|
1661 | 0 | if (needed_ring != curr_ring) { |
1662 | 0 | H5AC_set_ring(needed_ring, NULL); |
1663 | 0 | curr_ring = needed_ring; |
1664 | 0 | } /* end if */ |
1665 | |
|
1666 | 0 | if (H5MF__close_delete_fstype(f, ptype) < 0) |
1667 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't close the free space manager"); |
1668 | 0 | } /* end for */ |
1669 | 0 | } /* end if */ |
1670 | 0 | else { |
1671 | 0 | H5FD_mem_t type; /* Memory type for iteration */ |
1672 | | |
1673 | | /* Iterate over all the free space types that have managers and |
1674 | | * get each free list's space |
1675 | | */ |
1676 | 0 | for (type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; type++) { |
1677 | | /* Test to see if we need to switch rings -- do so if required */ |
1678 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, (H5F_mem_page_t)type)) |
1679 | 0 | needed_ring = H5AC_RING_MDFSM; |
1680 | 0 | else |
1681 | 0 | needed_ring = H5AC_RING_RDFSM; |
1682 | |
|
1683 | 0 | if (needed_ring != curr_ring) { |
1684 | 0 | H5AC_set_ring(needed_ring, NULL); |
1685 | 0 | curr_ring = needed_ring; |
1686 | 0 | } /* end if */ |
1687 | |
|
1688 | 0 | if (H5MF__close_delete_fstype(f, (H5F_mem_page_t)type) < 0) |
1689 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't close the free space manager"); |
1690 | 0 | } /* end for */ |
1691 | 0 | } /* end else */ |
1692 | | |
1693 | 0 | done: |
1694 | | /* Reset the ring in the API context */ |
1695 | 0 | if (orig_ring != H5AC_RING_INV) |
1696 | 0 | H5AC_set_ring(orig_ring, NULL); |
1697 | |
|
1698 | | #ifdef H5MF_ALLOC_DEBUG |
1699 | | fprintf(stderr, "%s: Leaving\n", __func__); |
1700 | | #endif /* H5MF_ALLOC_DEBUG */ |
1701 | 0 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
1702 | 0 | } /* H5MF_try_close() */ |
1703 | | |
1704 | | /*------------------------------------------------------------------------- |
1705 | | * Function: H5MF__close_aggrfs |
1706 | | * |
1707 | | * Purpose: Close the free space tracker(s) for a file: non-paged aggregation |
1708 | | * |
1709 | | * Return: SUCCEED/FAIL |
1710 | | * |
1711 | | *------------------------------------------------------------------------- |
1712 | | */ |
1713 | | static herr_t |
1714 | | H5MF__close_aggrfs(H5F_t *f) |
1715 | 287 | { |
1716 | 287 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
1717 | 287 | H5AC_ring_t curr_ring = H5AC_RING_INV; /* Current ring value */ |
1718 | 287 | H5AC_ring_t needed_ring = H5AC_RING_INV; /* Ring value needed for this iteration. */ |
1719 | 287 | H5FD_mem_t type; /* Memory type for iteration */ |
1720 | 287 | herr_t ret_value = SUCCEED; /* Return value */ |
1721 | | |
1722 | 287 | FUNC_ENTER_PACKAGE |
1723 | | #ifdef H5MF_ALLOC_DEBUG |
1724 | | fprintf(stderr, "%s: Entering\n", __func__); |
1725 | | #endif /* H5MF_ALLOC_DEBUG */ |
1726 | | |
1727 | | /* check args */ |
1728 | 287 | assert(f); |
1729 | 287 | assert(f->shared); |
1730 | 287 | assert(f->shared->lf); |
1731 | 287 | assert(f->shared->sblock); |
1732 | | |
1733 | | /* Set the ring type in the API context. In most cases, we will |
1734 | | * need H5AC_RING_RDFSM, so initially set the ring in |
1735 | | * the context to that value. We will alter this later if needed. |
1736 | | */ |
1737 | 287 | H5AC_set_ring(H5AC_RING_RDFSM, &orig_ring); |
1738 | 287 | curr_ring = H5AC_RING_RDFSM; |
1739 | | |
1740 | | /* Free the space in aggregators */ |
1741 | | /* (for space not at EOA, it may be put into free space managers) */ |
1742 | 287 | if (H5MF_free_aggrs(f) < 0) |
1743 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't free aggregators"); |
1744 | | |
1745 | | /* Trying shrinking the EOA for the file */ |
1746 | 287 | if (H5MF__close_shrink_eoa(f) < 0) |
1747 | 1 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa"); |
1748 | | |
1749 | | /* Making free-space managers persistent for superblock version >= 2 */ |
1750 | 286 | if (f->shared->sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2 && f->shared->fs_persist) { |
1751 | 0 | H5O_fsinfo_t fsinfo; /* File space info message */ |
1752 | 0 | haddr_t final_eoa; /* Final eoa -- for sanity check */ |
1753 | 0 | H5F_mem_page_t ptype; /* Memory type for iteration */ |
1754 | | |
1755 | | /* superblock extension and free space manager message should |
1756 | | * exist at this point -- verify at least the former. |
1757 | | */ |
1758 | 0 | assert(H5_addr_defined(f->shared->sblock->ext_addr)); |
1759 | | |
1760 | | /* file space for all non-empty free space managers should be |
1761 | | * allocated at this point, and these free space managers should |
1762 | | * be written to file and thus their headers and section info |
1763 | | * entries in the metadata cache should be clean. |
1764 | | */ |
1765 | | |
1766 | | /* gather data for the free space manager superblock extension message. |
1767 | | * |
1768 | | * In passing, verify that all the free space managers are closed. |
1769 | | */ |
1770 | 0 | for (ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; ptype++) |
1771 | 0 | fsinfo.fs_addr[ptype - 1] = HADDR_UNDEF; |
1772 | 0 | for (type = H5FD_MEM_SUPER; type < H5FD_MEM_NTYPES; type++) |
1773 | 0 | fsinfo.fs_addr[type - 1] = f->shared->fs_addr[type]; |
1774 | 0 | fsinfo.strategy = f->shared->fs_strategy; |
1775 | 0 | fsinfo.persist = f->shared->fs_persist; |
1776 | 0 | fsinfo.threshold = f->shared->fs_threshold; |
1777 | 0 | fsinfo.page_size = f->shared->fs_page_size; |
1778 | 0 | fsinfo.pgend_meta_thres = f->shared->pgend_meta_thres; |
1779 | 0 | fsinfo.eoa_pre_fsm_fsalloc = f->shared->eoa_fsm_fsalloc; |
1780 | 0 | fsinfo.version = f->shared->fs_version; |
1781 | | |
1782 | | /* Write the free space manager message -- message must already exist */ |
1783 | 0 | if (H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, false, H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0) |
1784 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_WRITEERROR, FAIL, |
1785 | 0 | "error in writing message to superblock extension"); |
1786 | | |
1787 | | /* Close the free space managers */ |
1788 | 0 | for (type = H5FD_MEM_SUPER; type < H5FD_MEM_NTYPES; type++) { |
1789 | 0 | if (f->shared->fs_man[type]) { |
1790 | | /* Test to see if we need to switch rings -- do so if required */ |
1791 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, (H5F_mem_page_t)type)) |
1792 | 0 | needed_ring = H5AC_RING_MDFSM; |
1793 | 0 | else |
1794 | 0 | needed_ring = H5AC_RING_RDFSM; |
1795 | |
|
1796 | 0 | if (needed_ring != curr_ring) { |
1797 | 0 | H5AC_set_ring(needed_ring, NULL); |
1798 | 0 | curr_ring = needed_ring; |
1799 | 0 | } /* end if */ |
1800 | |
|
1801 | 0 | assert(f->shared->fs_state[type] == H5F_FS_STATE_OPEN); |
1802 | |
|
1803 | 0 | if (H5FS_close(f, f->shared->fs_man[type]) < 0) |
1804 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't close free space manager"); |
1805 | 0 | f->shared->fs_man[type] = NULL; |
1806 | 0 | f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; |
1807 | 0 | } /* end if */ |
1808 | 0 | f->shared->fs_addr[type] = HADDR_UNDEF; |
1809 | 0 | } /* end for */ |
1810 | | |
1811 | | /* verify that we haven't dirtied any metadata cache entries |
1812 | | * from the metadata free space manager ring out. |
1813 | | */ |
1814 | 0 | assert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM)); |
1815 | | |
1816 | | /* verify that the aggregators are still shutdown. */ |
1817 | 0 | assert(f->shared->sdata_aggr.tot_size == 0); |
1818 | 0 | assert(f->shared->sdata_aggr.addr == 0); |
1819 | 0 | assert(f->shared->sdata_aggr.size == 0); |
1820 | |
|
1821 | 0 | assert(f->shared->meta_aggr.tot_size == 0); |
1822 | 0 | assert(f->shared->meta_aggr.addr == 0); |
1823 | 0 | assert(f->shared->meta_aggr.size == 0); |
1824 | | |
1825 | | /* Trying shrinking the EOA for the file */ |
1826 | | /* (in case any free space is now at the EOA) */ |
1827 | 0 | if (H5MF__close_shrink_eoa(f) < 0) |
1828 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa"); |
1829 | | |
1830 | | /* get the eoa, and verify that it has the expected value */ |
1831 | 0 | if (HADDR_UNDEF == (final_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT))) |
1832 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size"); |
1833 | | |
1834 | | /* f->shared->eoa_post_fsm_fsalloc is undefined if there has |
1835 | | * been no file space allocation or deallocation since file |
1836 | | * open. |
1837 | | */ |
1838 | 0 | assert(H5F_NULL_FSM_ADDR(f) || final_eoa == f->shared->eoa_fsm_fsalloc); |
1839 | 0 | } /* end if */ |
1840 | 286 | else { /* super_vers can be 0, 1, 2 */ |
1841 | 2.28k | for (type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; type++) |
1842 | 2.00k | if (H5MF__close_delete_fstype(f, (H5F_mem_page_t)type) < 0) |
1843 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space"); |
1844 | 286 | } /* end else */ |
1845 | | |
1846 | | /* Free the space in aggregators (again) */ |
1847 | | /* (in case any free space information re-started them) */ |
1848 | 286 | if (H5MF_free_aggrs(f) < 0) |
1849 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't free aggregators"); |
1850 | | |
1851 | | /* Trying shrinking the EOA for the file */ |
1852 | | /* (in case any free space is now at the EOA) */ |
1853 | 286 | if (H5MF__close_shrink_eoa(f) < 0) |
1854 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa"); |
1855 | | |
1856 | 287 | done: |
1857 | | /* Reset the ring in the API context */ |
1858 | 287 | if (orig_ring != H5AC_RING_INV) |
1859 | 287 | H5AC_set_ring(orig_ring, NULL); |
1860 | | |
1861 | | #ifdef H5MF_ALLOC_DEBUG |
1862 | | fprintf(stderr, "%s: Leaving\n", __func__); |
1863 | | #endif /* H5MF_ALLOC_DEBUG */ |
1864 | 287 | FUNC_LEAVE_NOAPI(ret_value) |
1865 | 287 | } /* end H5MF__close_aggrfs() */ |
1866 | | |
1867 | | /*------------------------------------------------------------------------- |
1868 | | * Function: H5MF__close_pagefs |
1869 | | * |
1870 | | * Purpose: Close the free space tracker(s) for a file: paged aggregation |
1871 | | * |
1872 | | * Return: SUCCEED/FAIL |
1873 | | * |
1874 | | *------------------------------------------------------------------------- |
1875 | | */ |
1876 | | static herr_t |
1877 | | H5MF__close_pagefs(H5F_t *f) |
1878 | 0 | { |
1879 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
1880 | 0 | H5AC_ring_t curr_ring = H5AC_RING_INV; /* Current ring value */ |
1881 | 0 | H5AC_ring_t needed_ring = H5AC_RING_INV; /* Ring value needed for this iteration. */ |
1882 | 0 | H5F_mem_page_t ptype; /* Memory type for iteration */ |
1883 | 0 | H5O_fsinfo_t fsinfo; /* File space info message */ |
1884 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1885 | |
|
1886 | 0 | FUNC_ENTER_PACKAGE |
1887 | | #ifdef H5MF_ALLOC_DEBUG |
1888 | | fprintf(stderr, "%s: Entering\n", __func__); |
1889 | | #endif /* H5MF_ALLOC_DEBUG */ |
1890 | | |
1891 | | /* check args */ |
1892 | 0 | assert(f); |
1893 | 0 | assert(f->shared); |
1894 | 0 | assert(f->shared->lf); |
1895 | 0 | assert(f->shared->sblock); |
1896 | 0 | assert(f->shared->fs_page_size); |
1897 | 0 | assert(f->shared->sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2); |
1898 | | |
1899 | | /* Set the ring type in the API context. In most cases, we will |
1900 | | * need H5AC_RING_RDFSM, so initially set the ring in |
1901 | | * the context to that value. We will alter this later if needed. |
1902 | | */ |
1903 | 0 | H5AC_set_ring(H5AC_RING_RDFSM, &orig_ring); |
1904 | 0 | curr_ring = H5AC_RING_RDFSM; |
1905 | | |
1906 | | /* Trying shrinking the EOA for the file */ |
1907 | 0 | if (H5MF__close_shrink_eoa(f) < 0) |
1908 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa"); |
1909 | | |
1910 | | /* Set up file space info message */ |
1911 | 0 | fsinfo.strategy = f->shared->fs_strategy; |
1912 | 0 | fsinfo.persist = f->shared->fs_persist; |
1913 | 0 | fsinfo.threshold = f->shared->fs_threshold; |
1914 | 0 | fsinfo.page_size = f->shared->fs_page_size; |
1915 | 0 | fsinfo.pgend_meta_thres = f->shared->pgend_meta_thres; |
1916 | 0 | fsinfo.eoa_pre_fsm_fsalloc = HADDR_UNDEF; |
1917 | 0 | fsinfo.version = f->shared->fs_version; |
1918 | |
|
1919 | 0 | for (ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; ptype++) |
1920 | 0 | fsinfo.fs_addr[ptype - 1] = HADDR_UNDEF; |
1921 | |
|
1922 | 0 | if (f->shared->fs_persist) { |
1923 | 0 | haddr_t final_eoa; /* final eoa -- for sanity check */ |
1924 | | |
1925 | | /* superblock extension and free space manager message should |
1926 | | * exist at this point -- verify at least the former. |
1927 | | */ |
1928 | 0 | assert(H5_addr_defined(f->shared->sblock->ext_addr)); |
1929 | | |
1930 | | /* file space for all non-empty free space managers should be |
1931 | | * allocated at this point, and these free space managers should |
1932 | | * be written to file and thus their headers and section info |
1933 | | * entries in the metadata cache should be clean. |
1934 | | */ |
1935 | | |
1936 | | /* gather data for the free space manager superblock extension message. |
1937 | | * Only need addresses of FSMs and eoa prior to allocation of |
1938 | | * file space for the self referential free space managers. Other |
1939 | | * data was gathered above. |
1940 | | */ |
1941 | 0 | for (ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; ptype++) |
1942 | 0 | fsinfo.fs_addr[ptype - 1] = f->shared->fs_addr[ptype]; |
1943 | 0 | fsinfo.eoa_pre_fsm_fsalloc = f->shared->eoa_fsm_fsalloc; |
1944 | | |
1945 | | /* Write the free space manager message -- message must already exist */ |
1946 | 0 | if (H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, false, H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0) |
1947 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_WRITEERROR, FAIL, |
1948 | 0 | "error in writing message to superblock extension"); |
1949 | | |
1950 | | /* Close the free space managers */ |
1951 | | /* use H5MF__close_fstype() for this? */ |
1952 | 0 | for (ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; ptype++) { |
1953 | 0 | if (f->shared->fs_man[ptype]) { |
1954 | | /* Test to see if we need to switch rings -- do so if required */ |
1955 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, ptype)) |
1956 | 0 | needed_ring = H5AC_RING_MDFSM; |
1957 | 0 | else |
1958 | 0 | needed_ring = H5AC_RING_RDFSM; |
1959 | |
|
1960 | 0 | if (needed_ring != curr_ring) { |
1961 | 0 | H5AC_set_ring(needed_ring, NULL); |
1962 | 0 | curr_ring = needed_ring; |
1963 | 0 | } /* end if */ |
1964 | |
|
1965 | 0 | assert(f->shared->fs_state[ptype] == H5F_FS_STATE_OPEN); |
1966 | |
|
1967 | 0 | if (H5FS_close(f, f->shared->fs_man[ptype]) < 0) |
1968 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't close free space manager"); |
1969 | 0 | f->shared->fs_man[ptype] = NULL; |
1970 | 0 | f->shared->fs_state[ptype] = H5F_FS_STATE_CLOSED; |
1971 | 0 | } /* end if */ |
1972 | 0 | f->shared->fs_addr[ptype] = HADDR_UNDEF; |
1973 | 0 | } /* end for */ |
1974 | | |
1975 | | /* verify that we haven't dirtied any metadata cache entries |
1976 | | * from the metadata free space manager ring out. |
1977 | | */ |
1978 | 0 | assert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM)); |
1979 | | |
1980 | | /* Trying shrinking the EOA for the file */ |
1981 | | /* (in case any free space is now at the EOA) */ |
1982 | 0 | if (H5MF__close_shrink_eoa(f) < 0) |
1983 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa"); |
1984 | | |
1985 | | /* get the eoa, and verify that it has the expected value */ |
1986 | 0 | if (HADDR_UNDEF == (final_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT))) |
1987 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size"); |
1988 | | |
1989 | | /* f->shared->eoa_post_fsm_fsalloc is undefined if there has |
1990 | | * been no file space allocation or deallocation since file |
1991 | | * open. |
1992 | | * |
1993 | | * If there is a cache image in the file at file open, |
1994 | | * f->shared->first_alloc_dealloc will always be false unless |
1995 | | * the file is opened R/O, as otherwise, the image will have been |
1996 | | * read and discarded by this point. |
1997 | | * |
1998 | | * If a cache image was created on file close, the actual EOA |
1999 | | * should be in f->shared->eoa_post_mdci_fsalloc. Note that in |
2000 | | * this case, it is conceivable that f->shared->first_alloc_dealloc |
2001 | | * will still be true, as the cache image is allocated directly from |
2002 | | * the file driver layer. However, as this possibility seems remote, |
2003 | | * it is ignored in the following assert. |
2004 | | */ |
2005 | 0 | assert((H5F_NULL_FSM_ADDR(f)) || (final_eoa == f->shared->eoa_fsm_fsalloc) || |
2006 | 0 | ((H5_addr_defined(f->shared->eoa_post_mdci_fsalloc)) && |
2007 | 0 | (final_eoa == f->shared->eoa_post_mdci_fsalloc))); |
2008 | 0 | } /* end if */ |
2009 | 0 | else { |
2010 | | /* Iterate over all the free space types that have managers |
2011 | | * and get each free list's space |
2012 | | */ |
2013 | 0 | for (ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; ptype++) |
2014 | 0 | if (H5MF__close_delete_fstype(f, ptype) < 0) |
2015 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't close the free space manager"); |
2016 | | |
2017 | | /* Write file space info message to superblock extension object header */ |
2018 | | /* Create the superblock extension object header in advance if needed */ |
2019 | 0 | if (H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, false, H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0) |
2020 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_WRITEERROR, FAIL, |
2021 | 0 | "error in writing message to superblock extension"); |
2022 | 0 | } /* end else */ |
2023 | | |
2024 | | /* Trying shrinking the EOA for the file */ |
2025 | | /* (in case any free space is now at the EOA) */ |
2026 | 0 | if (H5MF__close_shrink_eoa(f) < 0) |
2027 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa"); |
2028 | | |
2029 | 0 | done: |
2030 | | /* Reset the ring in the API context */ |
2031 | 0 | if (orig_ring != H5AC_RING_INV) |
2032 | 0 | H5AC_set_ring(orig_ring, NULL); |
2033 | |
|
2034 | | #ifdef H5MF_ALLOC_DEBUG |
2035 | | fprintf(stderr, "%s: Leaving\n", __func__); |
2036 | | #endif /* H5MF_ALLOC_DEBUG */ |
2037 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
2038 | 0 | } /* end H5MF__close_pagefs() */ |
2039 | | |
2040 | | /*------------------------------------------------------------------------- |
2041 | | * Function: H5MF__close_shrink_eoa |
2042 | | * |
2043 | | * Purpose: Shrink the EOA while closing |
2044 | | * |
2045 | | * Return: SUCCEED/FAIL |
2046 | | * |
2047 | | *------------------------------------------------------------------------- |
2048 | | */ |
2049 | | static herr_t |
2050 | | H5MF__close_shrink_eoa(H5F_t *f) |
2051 | 573 | { |
2052 | 573 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
2053 | 573 | H5AC_ring_t curr_ring = H5AC_RING_INV; /* Current ring value */ |
2054 | 573 | H5AC_ring_t needed_ring = H5AC_RING_INV; /* Ring value needed for this iteration. */ |
2055 | 573 | H5F_mem_t type; |
2056 | 573 | H5F_mem_page_t ptype; /* Memory type for iteration */ |
2057 | 573 | bool eoa_shrank; /* Whether an EOA shrink occurs */ |
2058 | 573 | htri_t status; /* Status value */ |
2059 | 573 | H5MF_sect_ud_t udata; /* User data for callback */ |
2060 | 573 | herr_t ret_value = SUCCEED; /* Return value */ |
2061 | | |
2062 | 573 | FUNC_ENTER_PACKAGE |
2063 | | |
2064 | | /* check args */ |
2065 | 573 | assert(f); |
2066 | 573 | assert(f->shared); |
2067 | | |
2068 | | /* Construct user data for callbacks */ |
2069 | 573 | udata.f = f; |
2070 | 573 | udata.allow_sect_absorb = false; |
2071 | 573 | udata.allow_eoa_shrink_only = true; |
2072 | | |
2073 | | /* Set the ring type in the API context */ |
2074 | 573 | H5AC_set_ring(H5AC_RING_RDFSM, &orig_ring); |
2075 | 573 | curr_ring = H5AC_RING_RDFSM; |
2076 | | |
2077 | | /* Iterate until no more EOA shrinking occurs */ |
2078 | 573 | do { |
2079 | 573 | eoa_shrank = false; |
2080 | | |
2081 | 573 | if (H5F_PAGED_AGGR(f)) { |
2082 | | /* Check the last section of each free-space manager */ |
2083 | 0 | for (ptype = H5F_MEM_PAGE_META; ptype < H5F_MEM_PAGE_NTYPES; ptype++) { |
2084 | 0 | if (f->shared->fs_man[ptype]) { |
2085 | | /* Test to see if we need to switch rings -- do so if required */ |
2086 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, ptype)) |
2087 | 0 | needed_ring = H5AC_RING_MDFSM; |
2088 | 0 | else |
2089 | 0 | needed_ring = H5AC_RING_RDFSM; |
2090 | |
|
2091 | 0 | if (needed_ring != curr_ring) { |
2092 | 0 | H5AC_set_ring(needed_ring, NULL); |
2093 | 0 | curr_ring = needed_ring; |
2094 | 0 | } /* end if */ |
2095 | |
|
2096 | 0 | udata.alloc_type = (H5FD_mem_t)((H5FD_mem_t)ptype < H5FD_MEM_NTYPES |
2097 | 0 | ? ptype |
2098 | 0 | : ((ptype % (H5F_mem_page_t)H5FD_MEM_NTYPES) + 1)); |
2099 | |
|
2100 | 0 | if ((status = H5FS_sect_try_shrink_eoa(f, f->shared->fs_man[ptype], &udata)) < 0) |
2101 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't check for shrinking eoa"); |
2102 | 0 | else if (status > 0) |
2103 | 0 | eoa_shrank = true; |
2104 | 0 | } /* end if */ |
2105 | 0 | } /* end for */ |
2106 | 0 | } /* end if */ |
2107 | 573 | else { |
2108 | | /* Check the last section of each free-space manager */ |
2109 | 4.58k | for (type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; type++) { |
2110 | 4.01k | if (f->shared->fs_man[type]) { |
2111 | | /* Test to see if we need to switch rings -- do so if required */ |
2112 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, (H5F_mem_page_t)type)) |
2113 | 0 | needed_ring = H5AC_RING_MDFSM; |
2114 | 0 | else |
2115 | 0 | needed_ring = H5AC_RING_RDFSM; |
2116 | |
|
2117 | 0 | if (needed_ring != curr_ring) { |
2118 | 0 | H5AC_set_ring(needed_ring, NULL); |
2119 | 0 | curr_ring = needed_ring; |
2120 | 0 | } /* end if */ |
2121 | |
|
2122 | 0 | udata.alloc_type = type; |
2123 | |
|
2124 | 0 | if ((status = H5FS_sect_try_shrink_eoa(f, f->shared->fs_man[type], &udata)) < 0) |
2125 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't check for shrinking eoa"); |
2126 | 0 | else if (status > 0) |
2127 | 0 | eoa_shrank = true; |
2128 | 0 | } /* end if */ |
2129 | 4.01k | } /* end for */ |
2130 | | |
2131 | | /* check the two aggregators */ |
2132 | 573 | if ((status = H5MF__aggrs_try_shrink_eoa(f)) < 0) |
2133 | 1 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't check for shrinking eoa"); |
2134 | 572 | else if (status > 0) |
2135 | 0 | eoa_shrank = true; |
2136 | 573 | } /* end else */ |
2137 | 573 | } while (eoa_shrank); |
2138 | | |
2139 | 573 | done: |
2140 | | /* Reset the ring in the API context */ |
2141 | 573 | if (orig_ring != H5AC_RING_INV) |
2142 | 573 | H5AC_set_ring(orig_ring, NULL); |
2143 | | |
2144 | 573 | FUNC_LEAVE_NOAPI(ret_value) |
2145 | 573 | } /* end H5MF__close_shrink_eoa() */ |
2146 | | |
2147 | | /*------------------------------------------------------------------------- |
2148 | | * Function: H5MF_get_freespace |
2149 | | * |
2150 | | * Purpose: Retrieve the amount of free space in the file |
2151 | | * |
2152 | | * Return: Success: Amount of free space in file |
2153 | | * Failure: Negative |
2154 | | * |
2155 | | *------------------------------------------------------------------------- |
2156 | | */ |
2157 | | herr_t |
2158 | | H5MF_get_freespace(H5F_t *f, hsize_t *tot_space, hsize_t *meta_size) |
2159 | 0 | { |
2160 | 0 | haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */ |
2161 | 0 | hsize_t ma_size = 0; /* Size of "metadata aggregator" */ |
2162 | 0 | haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */ |
2163 | 0 | hsize_t sda_size = 0; /* Size of "small data aggregator" */ |
2164 | 0 | hsize_t tot_fs_size = 0; /* Amount of all free space managed */ |
2165 | 0 | hsize_t tot_meta_size = 0; /* Amount of metadata for free space managers */ |
2166 | 0 | H5FD_mem_t tt; /* Memory type for iteration */ |
2167 | 0 | H5F_mem_page_t type; /* Memory type for iteration */ |
2168 | 0 | H5F_mem_page_t start_type; /* Memory type for iteration */ |
2169 | 0 | H5F_mem_page_t end_type; /* Memory type for iteration */ |
2170 | 0 | htri_t fs_started[H5F_MEM_PAGE_NTYPES]; /* Indicate whether the free-space manager has been started */ |
2171 | 0 | haddr_t fs_eoa[H5FD_MEM_NTYPES]; /* EAO for each free-space manager */ |
2172 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
2173 | 0 | H5AC_ring_t curr_ring = H5AC_RING_INV; /* Current ring value */ |
2174 | 0 | H5AC_ring_t needed_ring = H5AC_RING_INV; /* Ring value needed for this iteration. */ |
2175 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
2176 | |
|
2177 | 0 | FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) |
2178 | | |
2179 | | /* check args */ |
2180 | 0 | assert(f); |
2181 | 0 | assert(f->shared); |
2182 | 0 | assert(f->shared->lf); |
2183 | | |
2184 | | /* Set the ring type in the API context. In most cases, we will |
2185 | | * need H5AC_RING_RDFSM, so initially set the ring in |
2186 | | * the context to that value. We will alter this later if needed. |
2187 | | */ |
2188 | 0 | H5AC_set_ring(H5AC_RING_RDFSM, &orig_ring); |
2189 | 0 | curr_ring = H5AC_RING_RDFSM; |
2190 | | |
2191 | | /* Determine start/end points for loop */ |
2192 | 0 | if (H5F_PAGED_AGGR(f)) { |
2193 | 0 | start_type = H5F_MEM_PAGE_META; |
2194 | 0 | end_type = H5F_MEM_PAGE_NTYPES; |
2195 | 0 | } /* end if */ |
2196 | 0 | else { |
2197 | 0 | start_type = (H5F_mem_page_t)H5FD_MEM_SUPER; |
2198 | 0 | end_type = (H5F_mem_page_t)H5FD_MEM_NTYPES; |
2199 | 0 | } /* end else */ |
2200 | |
|
2201 | 0 | for (tt = H5FD_MEM_SUPER; tt < H5FD_MEM_NTYPES; tt++) |
2202 | 0 | if (HADDR_UNDEF == (fs_eoa[tt] = H5F_get_eoa(f, tt))) |
2203 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed"); |
2204 | | |
2205 | 0 | if (!H5F_PAGED_AGGR(f)) { |
2206 | | /* Retrieve metadata aggregator info, if available */ |
2207 | 0 | if (H5MF__aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size) < 0) |
2208 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query metadata aggregator stats"); |
2209 | | |
2210 | | /* Retrieve 'small data' aggregator info, if available */ |
2211 | 0 | if (H5MF__aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size) < 0) |
2212 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query small data aggregator stats"); |
2213 | 0 | } /* end if */ |
2214 | | |
2215 | | /* Iterate over all the free space types that have managers and get each free list's space */ |
2216 | 0 | for (type = start_type; type < end_type; type++) { |
2217 | 0 | fs_started[type] = false; |
2218 | | |
2219 | | /* Check if the free space for the file has been initialized */ |
2220 | 0 | if (!f->shared->fs_man[type] && H5_addr_defined(f->shared->fs_addr[type])) { |
2221 | 0 | if (H5MF__open_fstype(f, type) < 0) |
2222 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space"); |
2223 | 0 | assert(f->shared->fs_man[type]); |
2224 | 0 | fs_started[type] = true; |
2225 | 0 | } /* end if */ |
2226 | | |
2227 | | /* Test to see if we need to switch rings -- do so if required */ |
2228 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, (H5F_mem_page_t)type)) |
2229 | 0 | needed_ring = H5AC_RING_MDFSM; |
2230 | 0 | else |
2231 | 0 | needed_ring = H5AC_RING_RDFSM; |
2232 | |
|
2233 | 0 | if (needed_ring != curr_ring) { |
2234 | 0 | H5AC_set_ring(needed_ring, NULL); |
2235 | 0 | curr_ring = needed_ring; |
2236 | 0 | } /* end if */ |
2237 | | |
2238 | | /* Check if there's free space of this type */ |
2239 | 0 | if (f->shared->fs_man[type]) { |
2240 | 0 | hsize_t type_fs_size = 0; /* Amount of free space managed for each type */ |
2241 | 0 | hsize_t type_meta_size = 0; /* Amount of free space metadata for each type */ |
2242 | | |
2243 | | /* Retrieve free space size from free space manager */ |
2244 | 0 | if (H5FS_sect_stats(f->shared->fs_man[type], &type_fs_size, NULL) < 0) |
2245 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space stats"); |
2246 | 0 | if (H5FS_size(f->shared->fs_man[type], &type_meta_size) < 0) |
2247 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space metadata stats"); |
2248 | | |
2249 | | /* Increment total free space for types */ |
2250 | 0 | tot_fs_size += type_fs_size; |
2251 | 0 | tot_meta_size += type_meta_size; |
2252 | 0 | } /* end if */ |
2253 | 0 | } /* end for */ |
2254 | | |
2255 | | /* Close the free-space managers if they were opened earlier in this routine */ |
2256 | 0 | for (type = start_type; type < end_type; type++) { |
2257 | | /* Test to see if we need to switch rings -- do so if required */ |
2258 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, (H5F_mem_page_t)type)) |
2259 | 0 | needed_ring = H5AC_RING_MDFSM; |
2260 | 0 | else |
2261 | 0 | needed_ring = H5AC_RING_RDFSM; |
2262 | |
|
2263 | 0 | if (needed_ring != curr_ring) { |
2264 | 0 | H5AC_set_ring(needed_ring, &curr_ring); |
2265 | 0 | curr_ring = needed_ring; |
2266 | 0 | } /* end if */ |
2267 | |
|
2268 | 0 | if (fs_started[type]) |
2269 | 0 | if (H5MF__close_fstype(f, type) < 0) |
2270 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't close file free space"); |
2271 | 0 | } /* end for */ |
2272 | | |
2273 | | /* Set the value(s) to return */ |
2274 | | /* (The metadata & small data aggregators count as free space now, since they aren't at EOA) */ |
2275 | 0 | if (tot_space) |
2276 | 0 | *tot_space = tot_fs_size + ma_size + sda_size; |
2277 | 0 | if (meta_size) |
2278 | 0 | *meta_size = tot_meta_size; |
2279 | |
|
2280 | 0 | done: |
2281 | | /* Reset the ring in the API context */ |
2282 | 0 | if (orig_ring != H5AC_RING_INV) |
2283 | 0 | H5AC_set_ring(orig_ring, NULL); |
2284 | |
|
2285 | 0 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
2286 | 0 | } /* end H5MF_get_freespace() */ |
2287 | | |
2288 | | /*------------------------------------------------------------------------- |
2289 | | * Function: H5MF_get_free_sections() |
2290 | | * |
2291 | | * Purpose: To retrieve free-space section information for |
2292 | | * paged or non-paged aggregation |
2293 | | * |
2294 | | * Return: SUCCEED/FAIL |
2295 | | * |
2296 | | *------------------------------------------------------------------------- |
2297 | | */ |
2298 | | herr_t |
2299 | | H5MF_get_free_sections(H5F_t *f, H5FD_mem_t type, size_t nsects, H5F_sect_info_t *sect_info, |
2300 | | size_t *sect_count) |
2301 | 0 | { |
2302 | 0 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
2303 | 0 | H5AC_ring_t curr_ring = H5AC_RING_INV; /* Current ring value */ |
2304 | 0 | H5AC_ring_t needed_ring = H5AC_RING_INV; /* Ring value needed for this iteration. */ |
2305 | 0 | size_t total_sects = 0; /* Total number of sections */ |
2306 | 0 | H5MF_sect_iter_ud_t sect_udata; /* User data for callback */ |
2307 | 0 | H5F_mem_page_t start_type, end_type; /* Memory types to iterate over */ |
2308 | 0 | H5F_mem_page_t ty; /* Memory type for iteration */ |
2309 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
2310 | |
|
2311 | 0 | FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) |
2312 | | |
2313 | | /* check args */ |
2314 | 0 | assert(f); |
2315 | 0 | assert(f->shared); |
2316 | 0 | assert(f->shared->lf); |
2317 | | |
2318 | | /* H5MF_tidy_self_referential_fsm_hack() will fail if any self |
2319 | | * referential FSM is opened prior to the call to it. Thus call |
2320 | | * it here if necessary and if it hasn't been called already. |
2321 | | * |
2322 | | * The situation is further complicated if a cache image exists |
2323 | | * and had not yet been loaded into the metadata cache. In this |
2324 | | * case, call H5AC_force_cache_image_load() instead of |
2325 | | * H5MF_tidy_self_referential_fsm_hack(). H5AC_force_cache_image_load() |
2326 | | * will load the cache image, and then call |
2327 | | * H5MF_tidy_self_referential_fsm_hack() to discard the cache image |
2328 | | * block. |
2329 | | */ |
2330 | |
|
2331 | 0 | if (type == H5FD_MEM_DEFAULT) { |
2332 | 0 | start_type = H5F_MEM_PAGE_SUPER; |
2333 | 0 | end_type = H5F_MEM_PAGE_NTYPES; |
2334 | 0 | } /* end if */ |
2335 | 0 | else { |
2336 | 0 | start_type = end_type = (H5F_mem_page_t)type; |
2337 | 0 | if (H5F_PAGED_AGGR(f)) /* set to the corresponding LARGE free-space manager */ |
2338 | 0 | end_type = end_type + (H5F_mem_page_t)H5FD_MEM_NTYPES; |
2339 | 0 | else |
2340 | 0 | end_type++; |
2341 | 0 | } /* end else */ |
2342 | | |
2343 | | /* Set up user data for section iteration */ |
2344 | 0 | sect_udata.sects = sect_info; |
2345 | 0 | sect_udata.sect_count = nsects; |
2346 | 0 | sect_udata.sect_idx = 0; |
2347 | | |
2348 | | /* Set the ring type in the API context. In most cases, we will |
2349 | | * need H5AC_RING_RDFSM, so initially set the ring in |
2350 | | * the context to that value. We will alter this later if needed. |
2351 | | */ |
2352 | 0 | H5AC_set_ring(H5AC_RING_RDFSM, &orig_ring); |
2353 | 0 | curr_ring = H5AC_RING_RDFSM; |
2354 | | |
2355 | | /* Iterate over memory types, retrieving the number of sections of each type */ |
2356 | 0 | for (ty = start_type; ty < end_type; ty++) { |
2357 | 0 | bool fs_started = false; /* The free-space manager is opened or not */ |
2358 | 0 | size_t nums = 0; /* The number of free-space sections */ |
2359 | | |
2360 | | /* Test to see if we need to switch rings -- do so if required */ |
2361 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, ty)) |
2362 | 0 | needed_ring = H5AC_RING_MDFSM; |
2363 | 0 | else |
2364 | 0 | needed_ring = H5AC_RING_RDFSM; |
2365 | |
|
2366 | 0 | if (needed_ring != curr_ring) { |
2367 | 0 | H5AC_set_ring(needed_ring, &curr_ring); |
2368 | 0 | curr_ring = needed_ring; |
2369 | 0 | } /* end if */ |
2370 | |
|
2371 | 0 | if (!f->shared->fs_man[ty] && H5_addr_defined(f->shared->fs_addr[ty])) { |
2372 | 0 | if (H5MF__open_fstype(f, ty) < 0) |
2373 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't open the free space manager"); |
2374 | 0 | assert(f->shared->fs_man[ty]); |
2375 | 0 | fs_started = true; |
2376 | 0 | } /* end if */ |
2377 | | |
2378 | | /* Check if there's free space sections of this type */ |
2379 | 0 | if (f->shared->fs_man[ty]) |
2380 | 0 | if (H5MF__get_free_sects(f, f->shared->fs_man[ty], §_udata, &nums) < 0) |
2381 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, |
2382 | 0 | "can't get section info for the free space manager"); |
2383 | | |
2384 | | /* Increment total # of sections */ |
2385 | 0 | total_sects += nums; |
2386 | | |
2387 | | /* Close the free space manager of this type, if we started it here */ |
2388 | 0 | if (fs_started) |
2389 | 0 | if (H5MF__close_fstype(f, ty) < 0) |
2390 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCLOSEOBJ, FAIL, "can't close file free space"); |
2391 | 0 | if ((H5F_PAGED_AGGR(f)) && (type != H5FD_MEM_DEFAULT)) |
2392 | 0 | ty = ty + (H5F_mem_page_t)H5FD_MEM_NTYPES - 2; |
2393 | 0 | } /* end for */ |
2394 | | |
2395 | | /* Set value to return */ |
2396 | 0 | *sect_count = total_sects; |
2397 | |
|
2398 | 0 | done: |
2399 | | /* Reset the ring in the API context */ |
2400 | 0 | if (orig_ring != H5AC_RING_INV) |
2401 | 0 | H5AC_set_ring(orig_ring, NULL); |
2402 | |
|
2403 | 0 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
2404 | 0 | } /* H5MF_get_free_sections() */ |
2405 | | |
2406 | | /*------------------------------------------------------------------------- |
2407 | | * Function: H5MF__sects_cb() |
2408 | | * |
2409 | | * Purpose: Iterator callback for each free-space section |
2410 | | * Retrieve address and size into user data |
2411 | | * |
2412 | | * Return: Always succeed |
2413 | | * |
2414 | | *------------------------------------------------------------------------- |
2415 | | */ |
2416 | | static herr_t |
2417 | | H5MF__sects_cb(H5FS_section_info_t *_sect, void *_udata) |
2418 | 0 | { |
2419 | 0 | H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect; |
2420 | 0 | H5MF_sect_iter_ud_t *udata = (H5MF_sect_iter_ud_t *)_udata; |
2421 | |
|
2422 | 0 | FUNC_ENTER_PACKAGE_NOERR |
2423 | |
|
2424 | 0 | if (udata->sect_idx < udata->sect_count) { |
2425 | 0 | udata->sects[udata->sect_idx].addr = sect->sect_info.addr; |
2426 | 0 | udata->sects[udata->sect_idx].size = sect->sect_info.size; |
2427 | 0 | udata->sect_idx++; |
2428 | 0 | } /* end if */ |
2429 | |
|
2430 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
2431 | 0 | } /* H5MF__sects_cb() */ |
2432 | | |
2433 | | /*------------------------------------------------------------------------- |
2434 | | * Function: H5MF__get_free_sects |
2435 | | * |
2436 | | * Purpose: Retrieve section information for the specified free-space manager. |
2437 | | * |
2438 | | * Return: Success: non-negative |
2439 | | * Failure: negative |
2440 | | * |
2441 | | *------------------------------------------------------------------------- |
2442 | | */ |
2443 | | static herr_t |
2444 | | H5MF__get_free_sects(H5F_t *f, H5FS_t *fspace, H5MF_sect_iter_ud_t *sect_udata, size_t *nums) |
2445 | 0 | { |
2446 | 0 | hsize_t hnums = 0; /* # of sections */ |
2447 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
2448 | |
|
2449 | 0 | FUNC_ENTER_PACKAGE |
2450 | | |
2451 | | /* check args */ |
2452 | 0 | assert(f); |
2453 | 0 | assert(sect_udata); |
2454 | 0 | assert(nums); |
2455 | 0 | assert(fspace); |
2456 | | |
2457 | | /* Query how many sections of this type */ |
2458 | 0 | if (H5FS_sect_stats(fspace, NULL, &hnums) < 0) |
2459 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space stats"); |
2460 | 0 | H5_CHECKED_ASSIGN(*nums, size_t, hnums, hsize_t); |
2461 | | |
2462 | | /* Check if we should retrieve the section info */ |
2463 | 0 | if (sect_udata->sects && *nums > 0) |
2464 | | /* Iterate over all the free space sections of this type, adding them to the user's section info */ |
2465 | 0 | if (H5FS_sect_iterate(f, fspace, H5MF__sects_cb, sect_udata) < 0) |
2466 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_BADITER, FAIL, "can't iterate over sections"); |
2467 | | |
2468 | 0 | done: |
2469 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
2470 | 0 | } /* H5MF__get_free_sects() */ |
2471 | | |
2472 | | /*------------------------------------------------------------------------- |
2473 | | * Function: H5MF_settle_raw_data_fsm() |
2474 | | * |
2475 | | * Purpose: Handle any tasks required before the metadata cache |
2476 | | * can serialize or flush the raw data free space manager |
2477 | | * and any metadata free space managers that reside in the |
2478 | | * raw data free space manager ring. |
2479 | | * |
2480 | | * Specifically, this means any metadata managers that DON'T |
2481 | | * handle space allocation for free space manager header or |
2482 | | * section info will reside in the raw data free space manager |
2483 | | * ring. |
2484 | | * |
2485 | | * In the absence of page allocation, there is at most one |
2486 | | * free space manager per memory type defined in H5F_mem_t. |
2487 | | * Of these, the one that allocates H5FD_MEM_DRAW will |
2488 | | * always reside in the raw data free space manager ring. |
2489 | | * If there is more than one metadata free space manager, |
2490 | | * all that don't handle H5FD_MEM_FSPACE_HDR or |
2491 | | * H5FD_MEM_FSPACE_SINFO (which map to H5FD_MEM_OHDR and |
2492 | | * H5FD_MEM_LHEAP respectively) will reside in the raw |
2493 | | * data free space manager ring as well |
2494 | | * |
2495 | | * With page allocation, the situation is conceptually |
2496 | | * identical, but more complex in practice. |
2497 | | * |
2498 | | * In the worst case (multi file driver) page allocation |
2499 | | * can result in two free space managers for each memory |
2500 | | * type -- one for small (less than on equal to one page) |
2501 | | * allocations, and one for large (greater than one page) |
2502 | | * allocations. |
2503 | | * |
2504 | | * In the more common one file case, page allocation will |
2505 | | * result in a total of three free space managers -- one for |
2506 | | * small (<= one page) raw data allocations, one for small |
2507 | | * metadata allocations (i.e, all memory types other than |
2508 | | * H5FD_MEM_DRAW), and one for all large (> one page) |
2509 | | * allocations. |
2510 | | * |
2511 | | * Despite these complications, the solution is the same in |
2512 | | * the page allocation case -- free space managers (be they |
2513 | | * small data or large) are assigned to the raw data free |
2514 | | * space manager ring if they don't allocate file space for |
2515 | | * free space managers. Note that in the one file case, the |
2516 | | * large free space manager must be assigned to the metadata |
2517 | | * free space manager ring, as it both allocates pages for |
2518 | | * the metadata free space manager, and allocates space for |
2519 | | * large (> 1 page) metadata cache entries. |
2520 | | * |
2521 | | * At present, the task list for this routine is: |
2522 | | * |
2523 | | * 1) Reduce the EOA to the extent possible. To do this: |
2524 | | * |
2525 | | * a) Free both aggregators. Space not at EOA will be |
2526 | | * added to the appropriate free space manager. |
2527 | | * |
2528 | | * The raw data aggregator should not be restarted |
2529 | | * after this point. It is possible that the metadata |
2530 | | * aggregator will be. |
2531 | | * |
2532 | | * b) Free all file space currently allocated to free |
2533 | | * space managers. |
2534 | | * |
2535 | | * c) Delete the free space manager superblock |
2536 | | * extension message if allocated. |
2537 | | * |
2538 | | * This done, reduce the EOA by moving it to just before |
2539 | | * the last piece of free memory in the file. |
2540 | | * |
2541 | | * 2) Ensure that space is allocated for the free space |
2542 | | * manager superblock extension message. Must do this |
2543 | | * now, before reallocating file space for free space |
2544 | | * managers, as it is possible that this allocation may |
2545 | | * grab the last section in a FSM -- making it unnecessary |
2546 | | * to re-allocate file space for it. |
2547 | | * |
2548 | | * 3) Scan all free space managers not involved in allocating |
2549 | | * space for free space managers. For each such free space |
2550 | | * manager, test to see if it contains free space. If |
2551 | | * it does, allocate file space for its header and section |
2552 | | * data. If it contains no free space, leave it without |
2553 | | * allocated file space as there is no need to save it to |
2554 | | * file. |
2555 | | * |
2556 | | * Note that all free space managers in this class should |
2557 | | * see no further space allocations / deallocations as |
2558 | | * at this point, all raw data allocations should be |
2559 | | * finalized, as should all metadata allocations not |
2560 | | * involving free space managers. |
2561 | | * |
2562 | | * We will allocate space for free space managers involved |
2563 | | * in the allocation of file space for free space managers |
2564 | | * in H5MF_settle_meta_data_fsm() |
2565 | | * |
2566 | | * Return: SUCCEED/FAIL |
2567 | | * |
2568 | | *------------------------------------------------------------------------- |
2569 | | */ |
2570 | | herr_t |
2571 | | H5MF_settle_raw_data_fsm(H5F_t *f, bool *fsm_settled) |
2572 | 172 | { |
2573 | 172 | int pass_count; |
2574 | 172 | hsize_t alloc_size; |
2575 | 172 | H5F_mem_t mem_type; /* Memory type for iteration */ |
2576 | 172 | H5F_mem_page_t fsm_type = H5F_MEM_PAGE_NTYPES; /* FSM type for iteration */ |
2577 | 172 | H5O_fsinfo_t fsinfo; /* Free space manager info message */ |
2578 | 172 | H5FS_stat_t fs_stat; /* Information for free-space manager */ |
2579 | 172 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
2580 | 172 | H5AC_ring_t curr_ring = H5AC_RING_INV; /* Current ring value */ |
2581 | 172 | H5AC_ring_t needed_ring = H5AC_RING_INV; /* Ring value needed for this iteration */ |
2582 | 172 | herr_t ret_value = SUCCEED; /* Return value */ |
2583 | | |
2584 | 172 | FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) |
2585 | | |
2586 | | /* Check args */ |
2587 | 172 | assert(f); |
2588 | 172 | assert(f->shared); |
2589 | 172 | assert(fsm_settled); |
2590 | | |
2591 | | /* Initialize structs */ |
2592 | 172 | memset(&fsinfo, 0, sizeof(fsinfo)); |
2593 | 172 | memset(&fs_stat, 0, sizeof(fs_stat)); |
2594 | | |
2595 | | /* |
2596 | | * Only need to settle things if we are persisting free space and |
2597 | | * the private property in f->shared->null_fsm_addr is not enabled. |
2598 | | */ |
2599 | 172 | if (f->shared->fs_persist && !H5F_NULL_FSM_ADDR(f)) { |
2600 | 0 | bool fsm_opened[H5F_MEM_PAGE_NTYPES]; /* State of FSM */ |
2601 | 0 | bool fsm_visited[H5F_MEM_PAGE_NTYPES]; /* State of FSM */ |
2602 | | |
2603 | | /* should only be called if file is opened R/W */ |
2604 | 0 | assert(H5F_INTENT(f) & H5F_ACC_RDWR); |
2605 | | |
2606 | | /* shouldn't be called unless we have a superblock supporting the |
2607 | | * superblock extension. |
2608 | | */ |
2609 | 0 | if (f->shared->sblock) |
2610 | 0 | assert(f->shared->sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2); |
2611 | | |
2612 | | /* Initialize fsm_opened and fsm_visited */ |
2613 | 0 | memset(fsm_opened, 0, sizeof(fsm_opened)); |
2614 | 0 | memset(fsm_visited, 0, sizeof(fsm_visited)); |
2615 | | |
2616 | | /* 1) Reduce the EOA to the extent possible. */ |
2617 | | |
2618 | | /* a) Free the space in aggregators: |
2619 | | * |
2620 | | * (for space not at EOF, it may be put into free space managers) |
2621 | | * |
2622 | | * Do this now so that the raw data FSM (and any other FSM that isn't |
2623 | | * involved in space allocation for FSMs) will have no further activity. |
2624 | | * |
2625 | | * Note that while the raw data aggregator should not be restarted during |
2626 | | * the close process, this need not be the case for the metadata aggregator. |
2627 | | * |
2628 | | * Note also that the aggregators will not exist if page aggregation |
2629 | | * is enabled -- skip this if so. |
2630 | | */ |
2631 | | /* Vailin -- is this correct? */ |
2632 | 0 | if (!H5F_PAGED_AGGR(f) && (H5MF_free_aggrs(f) < 0)) |
2633 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free aggregators"); |
2634 | | |
2635 | | /* Set the ring type in the DXPL. In most cases, we will |
2636 | | * need H5AC_RING_MDFSM first, so initially set the ring in |
2637 | | * the DXPL to that value. We will alter this later if |
2638 | | * needed. |
2639 | | */ |
2640 | 0 | H5AC_set_ring(H5AC_RING_MDFSM, &orig_ring); |
2641 | 0 | curr_ring = H5AC_RING_MDFSM; |
2642 | | |
2643 | | /* b) Free the file space (if any) allocated to each free space manager. |
2644 | | * |
2645 | | * Do this to facilitate reduction of the size of the file to the |
2646 | | * extent possible. We will re-allocate space to free space managers |
2647 | | * that have free space to save after this reduction. |
2648 | | * |
2649 | | * In the case of the raw data free space manager, and any other free |
2650 | | * space manager that does not allocate space for free space managers, |
2651 | | * allocations should be complete at this point, as all raw data should |
2652 | | * have space allocated and be flushed to file by now. Thus we |
2653 | | * can examine such free space managers and only re-allocate space for |
2654 | | * them if they contain free space. Do this later in this function after |
2655 | | * the EOA has been reduced to the extent possible. |
2656 | | * |
2657 | | * For free space managers that allocate file space for free space |
2658 | | * managers (usually just a single metadata free space manager, but for |
2659 | | * now at least, free space managers for different types of metadata |
2660 | | * are possible), the matter is more ticklish due to the self- |
2661 | | * referential nature of the problem. These FSMs are dealt with in |
2662 | | * H5MF_settle_meta_data_fsm(). |
2663 | | * |
2664 | | * Since paged allocation may be enabled, there may be up to two |
2665 | | * free space managers per memory type -- one for small and one for |
2666 | | * large allocation. Hence we must loop over the memory types twice |
2667 | | * setting the allocation size accordingly if paged allocation is |
2668 | | * enabled. |
2669 | | */ |
2670 | 0 | for (pass_count = 0; pass_count <= 1; pass_count++) { |
2671 | 0 | if (pass_count == 0) |
2672 | 0 | alloc_size = 1; |
2673 | 0 | else if (H5F_PAGED_AGGR(f)) |
2674 | 0 | alloc_size = f->shared->fs_page_size + 1; |
2675 | 0 | else /* no need for a second pass */ |
2676 | 0 | break; |
2677 | | |
2678 | 0 | for (mem_type = H5FD_MEM_SUPER; mem_type < H5FD_MEM_NTYPES; mem_type++) { |
2679 | 0 | H5MF__alloc_to_fs_type(f->shared, mem_type, alloc_size, &fsm_type); |
2680 | |
|
2681 | 0 | if (pass_count == 0) { /* this is the first pass */ |
2682 | 0 | assert(fsm_type > H5F_MEM_PAGE_DEFAULT); |
2683 | 0 | assert(fsm_type < H5F_MEM_PAGE_LARGE_SUPER); |
2684 | 0 | } /* end if */ |
2685 | 0 | else if (H5F_PAGED_AGGR(f)) { /* page alloc active */ |
2686 | 0 | assert(fsm_type >= H5F_MEM_PAGE_LARGE_SUPER); |
2687 | 0 | assert(fsm_type < H5F_MEM_PAGE_NTYPES); |
2688 | 0 | } /* end else-if */ |
2689 | 0 | else /* paged allocation disabled -- should be unreachable */ |
2690 | 0 | assert(false); |
2691 | |
|
2692 | 0 | if (!fsm_visited[fsm_type]) { |
2693 | 0 | fsm_visited[fsm_type] = true; |
2694 | | |
2695 | | /* If there is no active FSM for this type, but such a FSM has |
2696 | | * space allocated in file, open it so that we can free its file |
2697 | | * space. |
2698 | | */ |
2699 | 0 | if (NULL == f->shared->fs_man[fsm_type]) { |
2700 | 0 | if (H5_addr_defined(f->shared->fs_addr[fsm_type])) { |
2701 | | /* Sanity check */ |
2702 | 0 | assert(fsm_opened[fsm_type] == false); |
2703 | |
|
2704 | 0 | if (H5MF__open_fstype(f, fsm_type) < 0) |
2705 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, |
2706 | 0 | "can't initialize file free space manager"); |
2707 | 0 | fsm_opened[fsm_type] = true; |
2708 | 0 | } /* end if */ |
2709 | 0 | } /* end if */ |
2710 | | |
2711 | 0 | if (f->shared->fs_man[fsm_type]) { |
2712 | | /* Test to see if we need to switch rings -- do so if required */ |
2713 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, fsm_type)) |
2714 | 0 | needed_ring = H5AC_RING_MDFSM; |
2715 | 0 | else |
2716 | 0 | needed_ring = H5AC_RING_RDFSM; |
2717 | |
|
2718 | 0 | if (needed_ring != curr_ring) { |
2719 | 0 | H5AC_set_ring(needed_ring, NULL); |
2720 | 0 | curr_ring = needed_ring; |
2721 | 0 | } /* end if */ |
2722 | | |
2723 | | /* Query free space manager info for this type */ |
2724 | 0 | if (H5FS_stat_info(f, f->shared->fs_man[fsm_type], &fs_stat) < 0) |
2725 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't get free-space info"); |
2726 | | |
2727 | | /* Check if the free space manager has space in the file */ |
2728 | 0 | if (H5_addr_defined(fs_stat.addr) || H5_addr_defined(fs_stat.sect_addr)) { |
2729 | | /* Delete the free space manager in the file. Will |
2730 | | * reallocate later if the free space manager contains |
2731 | | * any free space. |
2732 | | */ |
2733 | 0 | if (H5FS_free(f, f->shared->fs_man[fsm_type], true) < 0) |
2734 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, |
2735 | 0 | "can't release free-space headers"); |
2736 | 0 | f->shared->fs_addr[fsm_type] = HADDR_UNDEF; |
2737 | 0 | } /* end if */ |
2738 | 0 | } /* end if */ |
2739 | | |
2740 | | /* note that we are tracking opened FSM -- we will close them |
2741 | | * at the end of the function. |
2742 | | */ |
2743 | 0 | } /* end if */ |
2744 | 0 | } /* end for */ |
2745 | 0 | } /* end for */ |
2746 | | |
2747 | | /* c) Delete the free space manager superblock extension message |
2748 | | * if allocated. |
2749 | | * |
2750 | | * Must do this since the routine that writes / creates superblock |
2751 | | * extension messages will choke if the target message is |
2752 | | * unexpectedly either absent or present. |
2753 | | * |
2754 | | * Update: This is probably unnecessary, as I gather that the |
2755 | | * file space manager info message is guaranteed to exist. |
2756 | | * Leave it in for now, but consider removing it. |
2757 | | */ |
2758 | 0 | if (f->shared->sblock) { |
2759 | 0 | if (H5_addr_defined(f->shared->sblock->ext_addr)) |
2760 | 0 | if (H5F__super_ext_remove_msg(f, H5O_FSINFO_ID) < 0) |
2761 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, |
2762 | 0 | "error in removing message from superblock extension"); |
2763 | 0 | } |
2764 | | |
2765 | | /* As the final element in 1), shrink the EOA for the file */ |
2766 | 0 | if (H5MF__close_shrink_eoa(f) < 0) |
2767 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa"); |
2768 | | |
2769 | 0 | if (f->shared->sblock) { |
2770 | | /* 2) Ensure that space is allocated for the free space manager superblock |
2771 | | * extension message. Must do this now, before reallocating file space |
2772 | | * for free space managers, as it is possible that this allocation may |
2773 | | * grab the last section in a FSM -- making it unnecessary to |
2774 | | * re-allocate file space for it. |
2775 | | * |
2776 | | * Do this by writing a free space manager superblock extension message. |
2777 | | * |
2778 | | * Since no free space manager has file space allocated for it, this |
2779 | | * message must be invalid since we can't save addresses of FSMs when |
2780 | | * those addresses are unknown. This is OK -- we will write the correct |
2781 | | * values to the message at free space manager shutdown. |
2782 | | */ |
2783 | 0 | for (fsm_type = H5F_MEM_PAGE_SUPER; fsm_type < H5F_MEM_PAGE_NTYPES; fsm_type++) |
2784 | 0 | fsinfo.fs_addr[fsm_type - 1] = HADDR_UNDEF; |
2785 | 0 | fsinfo.strategy = f->shared->fs_strategy; |
2786 | 0 | fsinfo.persist = f->shared->fs_persist; |
2787 | 0 | fsinfo.threshold = f->shared->fs_threshold; |
2788 | 0 | fsinfo.page_size = f->shared->fs_page_size; |
2789 | 0 | fsinfo.pgend_meta_thres = f->shared->pgend_meta_thres; |
2790 | 0 | fsinfo.eoa_pre_fsm_fsalloc = HADDR_UNDEF; |
2791 | |
|
2792 | 0 | if (H5F__super_ext_write_msg(f, H5O_FSINFO_ID, &fsinfo, true, H5O_MSG_FLAG_MARK_IF_UNKNOWN) < 0) |
2793 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_WRITEERROR, FAIL, |
2794 | 0 | "error in writing fsinfo message to superblock extension"); |
2795 | 0 | } |
2796 | | |
2797 | | /* 3) Scan all free space managers not involved in allocating |
2798 | | * space for free space managers. For each such free space |
2799 | | * manager, test to see if it contains free space. If |
2800 | | * it does, allocate file space for its header and section |
2801 | | * data. If it contains no free space, leave it without |
2802 | | * allocated file space as there is no need to save it to |
2803 | | * file. |
2804 | | * |
2805 | | * Note that all free space managers in this class should |
2806 | | * see no further space allocations / deallocations as |
2807 | | * at this point, all raw data allocations should be |
2808 | | * finalized, as should all metadata allocations not involving |
2809 | | * free space managers. |
2810 | | * |
2811 | | * We will allocate space for free space managers involved |
2812 | | * in the allocation of file space for free space managers |
2813 | | * in H5MF_settle_meta_data_fsm() |
2814 | | */ |
2815 | | |
2816 | | /* Reinitialize fsm_visited */ |
2817 | 0 | for (fsm_type = H5F_MEM_PAGE_SUPER; fsm_type < H5F_MEM_PAGE_NTYPES; fsm_type++) |
2818 | 0 | fsm_visited[fsm_type] = false; |
2819 | |
|
2820 | 0 | for (pass_count = 0; pass_count <= 1; pass_count++) { |
2821 | 0 | if (pass_count == 0) |
2822 | 0 | alloc_size = 1; |
2823 | 0 | else if (H5F_PAGED_AGGR(f)) |
2824 | 0 | alloc_size = f->shared->fs_page_size + 1; |
2825 | 0 | else /* no need for a second pass */ |
2826 | 0 | break; |
2827 | | |
2828 | 0 | for (mem_type = H5FD_MEM_SUPER; mem_type < H5FD_MEM_NTYPES; mem_type++) { |
2829 | 0 | H5MF__alloc_to_fs_type(f->shared, mem_type, alloc_size, &fsm_type); |
2830 | |
|
2831 | 0 | if (pass_count == 0) { /* this is the first pass */ |
2832 | 0 | assert(fsm_type > H5F_MEM_PAGE_DEFAULT); |
2833 | 0 | assert(fsm_type < H5F_MEM_PAGE_LARGE_SUPER); |
2834 | 0 | } /* end if */ |
2835 | 0 | else if (H5F_PAGED_AGGR(f)) { /* page alloc active */ |
2836 | 0 | assert(fsm_type >= H5F_MEM_PAGE_LARGE_SUPER); |
2837 | 0 | assert(fsm_type < H5F_MEM_PAGE_NTYPES); |
2838 | 0 | } /* end else-if */ |
2839 | 0 | else /* paged allocation disabled -- should be unreachable */ |
2840 | 0 | assert(false); |
2841 | | |
2842 | | /* Test to see if we need to switch rings -- do so if required */ |
2843 | 0 | if (H5MF__fsm_type_is_self_referential(f->shared, fsm_type)) |
2844 | 0 | needed_ring = H5AC_RING_MDFSM; |
2845 | 0 | else |
2846 | 0 | needed_ring = H5AC_RING_RDFSM; |
2847 | |
|
2848 | 0 | if (needed_ring != curr_ring) { |
2849 | 0 | H5AC_set_ring(needed_ring, NULL); |
2850 | 0 | curr_ring = needed_ring; |
2851 | 0 | } /* end if */ |
2852 | | |
2853 | | /* Since there can be a many-to-one mapping from memory types |
2854 | | * to free space managers, ensure that we don't visit any FSM |
2855 | | * more than once. |
2856 | | */ |
2857 | 0 | if (!fsm_visited[fsm_type]) { |
2858 | 0 | fsm_visited[fsm_type] = true; |
2859 | |
|
2860 | 0 | if (f->shared->fs_man[fsm_type]) { |
2861 | | /* Only allocate file space if the target free space manager |
2862 | | * doesn't allocate file space for free space managers. Note |
2863 | | * that this is also the deciding factor as to whether a FSM |
2864 | | * in in the raw data FSM ring. |
2865 | | */ |
2866 | 0 | if (!H5MF__fsm_type_is_self_referential(f->shared, fsm_type)) { |
2867 | | /* The current ring should be H5AC_RING_RDFSM */ |
2868 | 0 | assert(curr_ring == H5AC_RING_RDFSM); |
2869 | | |
2870 | | /* Query free space manager info for this type */ |
2871 | 0 | if (H5FS_stat_info(f, f->shared->fs_man[fsm_type], &fs_stat) < 0) |
2872 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get free-space info"); |
2873 | | |
2874 | | /* If the free space manager contains section info, |
2875 | | * allocate space for the header and sinfo (note that |
2876 | | * space must not be allocated at present -- verify |
2877 | | * verify this with assertions). |
2878 | | */ |
2879 | 0 | if (fs_stat.serial_sect_count > 0) { |
2880 | | /* Sanity check */ |
2881 | 0 | assert(!H5_addr_defined(fs_stat.addr)); |
2882 | | |
2883 | | /* Allocate FSM header */ |
2884 | 0 | if (H5FS_alloc_hdr(f, f->shared->fs_man[fsm_type], |
2885 | 0 | &f->shared->fs_addr[fsm_type]) < 0) |
2886 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, |
2887 | 0 | "can't allocated free-space header"); |
2888 | | |
2889 | | /* Allocate FSM section info */ |
2890 | 0 | assert(!H5_addr_defined(fs_stat.sect_addr)); |
2891 | 0 | assert(fs_stat.alloc_sect_size == 0); |
2892 | 0 | if (H5FS_alloc_sect(f, f->shared->fs_man[fsm_type]) < 0) |
2893 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, |
2894 | 0 | "can't allocate free-space section info"); |
2895 | |
|
2896 | | #ifndef NDEBUG |
2897 | | /* Re-Query free space manager info for this type */ |
2898 | | if (H5FS_stat_info(f, f->shared->fs_man[fsm_type], &fs_stat) < 0) |
2899 | | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, |
2900 | | "can't get free-space info"); |
2901 | | |
2902 | | assert(H5_addr_defined(fs_stat.addr)); |
2903 | | assert(H5_addr_defined(fs_stat.sect_addr)); |
2904 | | assert(fs_stat.serial_sect_count > 0); |
2905 | | assert(fs_stat.alloc_sect_size > 0); |
2906 | | assert(fs_stat.alloc_sect_size == fs_stat.sect_size); |
2907 | | #endif /* NDEBUG */ |
2908 | 0 | } /* end if */ |
2909 | 0 | else { |
2910 | 0 | assert(!H5_addr_defined(fs_stat.addr)); |
2911 | 0 | assert(!H5_addr_defined(fs_stat.sect_addr)); |
2912 | 0 | assert(fs_stat.serial_sect_count == 0); |
2913 | 0 | assert(fs_stat.alloc_sect_size == 0); |
2914 | 0 | } /* end else */ |
2915 | 0 | } /* end if */ |
2916 | 0 | } /* end if */ |
2917 | | |
2918 | | /* Close any opened FSMs */ |
2919 | 0 | if (fsm_opened[fsm_type]) { |
2920 | 0 | if (H5MF__close_fstype(f, fsm_type) < 0) |
2921 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, |
2922 | 0 | "can't close file free space manager"); |
2923 | 0 | fsm_opened[fsm_type] = false; |
2924 | 0 | } /* end if */ |
2925 | 0 | } /* end if */ |
2926 | 0 | } /* end for */ |
2927 | 0 | } /* end for */ |
2928 | | |
2929 | | /* verify that all opened FSMs were closed */ |
2930 | 0 | for (fsm_type = H5F_MEM_PAGE_SUPER; fsm_type < H5F_MEM_PAGE_NTYPES; fsm_type++) |
2931 | 0 | assert(!fsm_opened[fsm_type]); |
2932 | | |
2933 | | /* Indicate that the FSM was settled successfully */ |
2934 | 0 | *fsm_settled = true; |
2935 | 0 | } /* end if */ |
2936 | | |
2937 | 172 | done: |
2938 | | /* Reset the ring in the API context */ |
2939 | 172 | if (orig_ring != H5AC_RING_INV) |
2940 | 0 | H5AC_set_ring(orig_ring, NULL); |
2941 | | |
2942 | 172 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
2943 | 172 | } /* H5MF_settle_raw_data_fsm() */ |
2944 | | |
2945 | | /*------------------------------------------------------------------------- |
2946 | | * Function: H5MF_settle_meta_data_fsm() |
2947 | | * |
2948 | | * Purpose: If the free space manager is persistent, handle any tasks |
2949 | | * required before the metadata cache can serialize or flush |
2950 | | * the metadata free space manager(s) that handle file space |
2951 | | * allocation for free space managers. |
2952 | | * |
2953 | | * In most cases, there will be only one manager assigned |
2954 | | * to this role. However, since for reasons unknown, |
2955 | | * free space manager headers and section info blocks are |
2956 | | * different classes of memory, it is possible that two free |
2957 | | * space managers will be involved. |
2958 | | * |
2959 | | * On entry to this function, the raw data settle routine |
2960 | | * (H5MF_settle_raw_data_fsm()) should have: |
2961 | | * |
2962 | | * 1) Freed the aggregators. |
2963 | | * |
2964 | | * 2) Freed all file space allocated to the free space managers. |
2965 | | * |
2966 | | * 3) Deleted the free space manager superblock extension message |
2967 | | * |
2968 | | * 4) Reduced the EOA to the extent possible. |
2969 | | * |
2970 | | * 5) Re-created the free space manager superblock extension |
2971 | | * message. |
2972 | | * |
2973 | | * 6) Reallocated file space for all non-empty free space |
2974 | | * managers NOT involved in allocation of space for free |
2975 | | * space managers. |
2976 | | * |
2977 | | * Note that these free space managers (if not empty) should |
2978 | | * have been written to file by this point, and that no |
2979 | | * further space allocations involving them should take |
2980 | | * place during file close. |
2981 | | * |
2982 | | * On entry to this routine, the free space manager(s) involved |
2983 | | * in allocation of file space for free space managers should |
2984 | | * still be floating. (i.e. should not have any file space |
2985 | | * allocated to them.) |
2986 | | * |
2987 | | * Similarly, the raw data aggregator should not have been |
2988 | | * restarted. Note that it is probable that reallocation of |
2989 | | * space in 5) and 6) above will have re-started the metadata |
2990 | | * aggregator. |
2991 | | * |
2992 | | * |
2993 | | * In this routine, we proceed as follows: |
2994 | | * |
2995 | | * 1) Verify that the free space manager(s) involved in file |
2996 | | * space allocation for free space managers are still floating. |
2997 | | * |
2998 | | * 2) Free the aggregators. |
2999 | | * |
3000 | | * 3) Reduce the EOA to the extent possible, and make note |
3001 | | * of the resulting value. This value will be stored |
3002 | | * in the fsinfo superblock extension message and be used |
3003 | | * in the subsequent file open. |
3004 | | * |
3005 | | * 4) Re-allocate space for any free space manager(s) that: |
3006 | | * |
3007 | | * a) are involved in allocation of space for free space |
3008 | | * managers, and |
3009 | | * |
3010 | | * b) contain free space. |
3011 | | * |
3012 | | * It is possible that we could allocate space for one |
3013 | | * of these free space manager(s) only to have the allocation |
3014 | | * result in the free space manager being empty and thus |
3015 | | * obliging us to free the space again. Thus there is the |
3016 | | * potential for an infinite loop if we want to avoid saving |
3017 | | * empty free space managers. |
3018 | | * |
3019 | | * Similarly, it is possible that we could allocate space |
3020 | | * for a section info block, only to discover that this |
3021 | | * allocation has changed the size of the section info -- |
3022 | | * forcing us to deallocate and start the loop over again. |
3023 | | * |
3024 | | * The solution is to modify the FSM code to |
3025 | | * save empty FSMs to file, and to allow section info blocks |
3026 | | * to be oversized. That is, only allow section info to increase |
3027 | | * in size, not shrink. The solution is now implemented. |
3028 | | * |
3029 | | * 5) Make note of the EOA -- used for sanity checking on |
3030 | | * FSM shutdown. This is saved as eoa_pre_fsm_fsalloc in |
3031 | | * the free-space info message for backward compatibility |
3032 | | * with the 1.10 library that has the hack. |
3033 | | * |
3034 | | * Return: SUCCEED/FAIL |
3035 | | * |
3036 | | *------------------------------------------------------------------------- |
3037 | | */ |
3038 | | herr_t |
3039 | | H5MF_settle_meta_data_fsm(H5F_t *f, bool *fsm_settled) |
3040 | 172 | { |
3041 | 172 | H5F_mem_page_t sm_fshdr_fs_type = H5F_MEM_PAGE_NTYPES; /* small fs hdr fsm */ |
3042 | 172 | H5F_mem_page_t sm_fssinfo_fs_type = H5F_MEM_PAGE_NTYPES; /* small fs sinfo fsm */ |
3043 | 172 | H5F_mem_page_t lg_fshdr_fs_type = H5F_MEM_PAGE_DEFAULT; /* large fs hdr fsm */ |
3044 | 172 | H5F_mem_page_t lg_fssinfo_fs_type = H5F_MEM_PAGE_DEFAULT; /* large fs sinfo fsm */ |
3045 | 172 | H5FS_t *sm_hdr_fspace = NULL; /* ptr to sm FSM hdr alloc FSM */ |
3046 | 172 | H5FS_t *sm_sinfo_fspace = NULL; /* ptr to sm FSM sinfo alloc FSM */ |
3047 | 172 | H5FS_t *lg_hdr_fspace = NULL; /* ptr to lg FSM hdr alloc FSM */ |
3048 | 172 | H5FS_t *lg_sinfo_fspace = NULL; /* ptr to lg FSM sinfo alloc FSM */ |
3049 | 172 | haddr_t eoa_fsm_fsalloc; /* eoa after file space allocation */ |
3050 | | /* for self referential FSMs */ |
3051 | 172 | bool continue_alloc_fsm = false; /* Continue allocating addr and sect_addr for FSMs */ |
3052 | 172 | H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ |
3053 | 172 | herr_t ret_value = SUCCEED; /* Return value */ |
3054 | | |
3055 | 172 | FUNC_ENTER_NOAPI_TAG(H5AC__FREESPACE_TAG, FAIL) |
3056 | | |
3057 | | /* Check args */ |
3058 | 172 | assert(f); |
3059 | 172 | assert(f->shared); |
3060 | 172 | assert(fsm_settled); |
3061 | | |
3062 | | /* |
3063 | | * Only need to settle things if we are persisting free space and |
3064 | | * the private property in f->shared->null_fsm_addr is not enabled. |
3065 | | */ |
3066 | 172 | if (f->shared->fs_persist && !H5F_NULL_FSM_ADDR(f)) { |
3067 | | /* Sanity check */ |
3068 | 0 | assert(f->shared->lf); |
3069 | | |
3070 | | /* should only be called if file is opened R/W */ |
3071 | 0 | assert(H5F_INTENT(f) & H5F_ACC_RDWR); |
3072 | |
|
3073 | 0 | H5MF__alloc_to_fs_type(f->shared, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fs_type); |
3074 | 0 | H5MF__alloc_to_fs_type(f->shared, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fs_type); |
3075 | |
|
3076 | 0 | assert(sm_fshdr_fs_type > H5F_MEM_PAGE_DEFAULT); |
3077 | 0 | assert(sm_fshdr_fs_type < H5F_MEM_PAGE_LARGE_SUPER); |
3078 | |
|
3079 | 0 | assert(sm_fssinfo_fs_type > H5F_MEM_PAGE_DEFAULT); |
3080 | 0 | assert(sm_fssinfo_fs_type < H5F_MEM_PAGE_LARGE_SUPER); |
3081 | |
|
3082 | 0 | if (H5_addr_defined(f->shared->fs_addr[sm_fshdr_fs_type])) |
3083 | 0 | HGOTO_ERROR(H5E_FSPACE, H5E_BADVALUE, FAIL, |
3084 | 0 | "small free space header block manager should not have had file space allocated"); |
3085 | 0 | if (H5_addr_defined(f->shared->fs_addr[sm_fssinfo_fs_type])) |
3086 | 0 | HGOTO_ERROR( |
3087 | 0 | H5E_FSPACE, H5E_BADVALUE, FAIL, |
3088 | 0 | "small free space serialized section manager should not have had file space allocated"); |
3089 | | |
3090 | | /* Note that in most cases, sm_hdr_fspace will equal sm_sinfo_fspace. */ |
3091 | 0 | sm_hdr_fspace = f->shared->fs_man[sm_fshdr_fs_type]; |
3092 | 0 | sm_sinfo_fspace = f->shared->fs_man[sm_fssinfo_fs_type]; |
3093 | |
|
3094 | 0 | if (H5F_PAGED_AGGR(f)) { |
3095 | 0 | H5MF__alloc_to_fs_type(f->shared, H5FD_MEM_FSPACE_HDR, f->shared->fs_page_size + 1, |
3096 | 0 | &lg_fshdr_fs_type); |
3097 | 0 | H5MF__alloc_to_fs_type(f->shared, H5FD_MEM_FSPACE_SINFO, f->shared->fs_page_size + 1, |
3098 | 0 | &lg_fssinfo_fs_type); |
3099 | |
|
3100 | 0 | assert(lg_fshdr_fs_type >= H5F_MEM_PAGE_LARGE_SUPER); |
3101 | 0 | assert(lg_fshdr_fs_type < H5F_MEM_PAGE_NTYPES); |
3102 | |
|
3103 | 0 | assert(lg_fssinfo_fs_type >= H5F_MEM_PAGE_LARGE_SUPER); |
3104 | 0 | assert(lg_fssinfo_fs_type < H5F_MEM_PAGE_NTYPES); |
3105 | |
|
3106 | 0 | if (H5_addr_defined(f->shared->fs_addr[lg_fshdr_fs_type])) |
3107 | 0 | HGOTO_ERROR(H5E_FSPACE, H5E_BADVALUE, FAIL, |
3108 | 0 | "large free space header block manager should not have had file space allocated"); |
3109 | 0 | if (H5_addr_defined(f->shared->fs_addr[lg_fssinfo_fs_type])) |
3110 | 0 | HGOTO_ERROR( |
3111 | 0 | H5E_FSPACE, H5E_BADVALUE, FAIL, |
3112 | 0 | "large free space serialized section manager should not have had file space allocated"); |
3113 | | |
3114 | | /* Note that in most cases, lg_hdr_fspace will equal lg_sinfo_fspace. */ |
3115 | 0 | lg_hdr_fspace = f->shared->fs_man[lg_fshdr_fs_type]; |
3116 | 0 | lg_sinfo_fspace = f->shared->fs_man[lg_fssinfo_fs_type]; |
3117 | 0 | } /* end if */ |
3118 | | |
3119 | | /* Set the ring in the API context appropriately for subsequent calls */ |
3120 | 0 | H5AC_set_ring(H5AC_RING_MDFSM, &orig_ring); |
3121 | |
|
3122 | | #ifndef NDEBUG |
3123 | | { |
3124 | | H5FS_stat_t fs_stat; /* Information for hdr FSM */ |
3125 | | |
3126 | | if (sm_hdr_fspace) { |
3127 | | /* Query free space manager info for this type */ |
3128 | | if (H5FS_stat_info(f, sm_hdr_fspace, &fs_stat) < 0) |
3129 | | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get free-space info"); |
3130 | | |
3131 | | assert(!H5_addr_defined(fs_stat.addr)); |
3132 | | assert(!H5_addr_defined(fs_stat.sect_addr)); |
3133 | | assert(fs_stat.alloc_sect_size == 0); |
3134 | | } /* end if */ |
3135 | | |
3136 | | /* Verify that sm_sinfo_fspace is floating if it exists and is distinct */ |
3137 | | if ((sm_sinfo_fspace) && (sm_hdr_fspace != sm_sinfo_fspace)) { |
3138 | | /* Query free space manager info for this type */ |
3139 | | if (H5FS_stat_info(f, sm_sinfo_fspace, &fs_stat) < 0) |
3140 | | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get free-space info"); |
3141 | | |
3142 | | assert(!H5_addr_defined(fs_stat.addr)); |
3143 | | assert(!H5_addr_defined(fs_stat.sect_addr)); |
3144 | | assert(fs_stat.alloc_sect_size == 0); |
3145 | | } /* end if */ |
3146 | | |
3147 | | if (H5F_PAGED_AGGR(f)) { |
3148 | | /* Verify that lg_hdr_fspace is floating if it exists */ |
3149 | | if (lg_hdr_fspace) { |
3150 | | /* Query free space manager info for this type */ |
3151 | | if (H5FS_stat_info(f, lg_hdr_fspace, &fs_stat) < 0) |
3152 | | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get free-space info (3)"); |
3153 | | |
3154 | | assert(!H5_addr_defined(fs_stat.addr)); |
3155 | | assert(!H5_addr_defined(fs_stat.sect_addr)); |
3156 | | assert(fs_stat.alloc_sect_size == 0); |
3157 | | } /* end if */ |
3158 | | |
3159 | | /* Verify that lg_sinfo_fspace is floating if it |
3160 | | * exists and is distinct |
3161 | | */ |
3162 | | if ((lg_sinfo_fspace) && (lg_hdr_fspace != lg_sinfo_fspace)) { |
3163 | | /* Query free space manager info for this type */ |
3164 | | if (H5FS_stat_info(f, lg_sinfo_fspace, &fs_stat) < 0) |
3165 | | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get free-space info (4)"); |
3166 | | |
3167 | | assert(!H5_addr_defined(fs_stat.addr)); |
3168 | | assert(!H5_addr_defined(fs_stat.sect_addr)); |
3169 | | assert(fs_stat.alloc_sect_size == 0); |
3170 | | } /* end if */ |
3171 | | } /* end if */ |
3172 | | } |
3173 | | #endif /* NDEBUG */ |
3174 | | |
3175 | | /* Free the space in the metadata aggregator. Do this via the |
3176 | | * H5MF_free_aggrs() call. Note that the raw data aggregator must |
3177 | | * have already been freed. Sanity checks for this? |
3178 | | * |
3179 | | * Note that the aggregators will not exist if paged aggregation |
3180 | | * is enabled -- don't attempt to free if this is the case. |
3181 | | */ |
3182 | | /* (for space not at EOF, it may be put into free space managers) */ |
3183 | 0 | if ((!H5F_PAGED_AGGR(f)) && (H5MF_free_aggrs(f) < 0)) |
3184 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free aggregators"); |
3185 | | |
3186 | | /* Trying shrinking the EOA for the file */ |
3187 | 0 | if (H5MF__close_shrink_eoa(f) < 0) |
3188 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa"); |
3189 | | |
3190 | | /* WARNING: This approach settling the self referential free space |
3191 | | * managers and allocating space for them in the file will |
3192 | | * not work as currently implemented with the split and |
3193 | | * multi file drivers, as the self referential free space |
3194 | | * manager header and section info can be stored in up to |
3195 | | * two different files -- requiring that up to two EOA's |
3196 | | * be stored in the free space manager's superblock |
3197 | | * extension message. |
3198 | | * |
3199 | | * As of this writing, we are solving this problem by |
3200 | | * simply not supporting persistent FSMs with the split |
3201 | | * and multi file drivers. |
3202 | | * |
3203 | | * Current plans are to do away with the multi file |
3204 | | * driver, so this should be a non-issue in this case. |
3205 | | * |
3206 | | * We should be able to support the split file driver |
3207 | | * without a file format change. However, the code to |
3208 | | * do so does not exist at present. |
3209 | | * NOTE: not sure whether to remove or keep the above comments |
3210 | | */ |
3211 | | |
3212 | | /* |
3213 | | * Continue allocating file space for the header and section info until |
3214 | | * they are all settled, |
3215 | | */ |
3216 | 0 | do { |
3217 | 0 | continue_alloc_fsm = false; |
3218 | 0 | if (sm_hdr_fspace) |
3219 | 0 | if (H5FS_vfd_alloc_hdr_and_section_info_if_needed( |
3220 | 0 | f, sm_hdr_fspace, &(f->shared->fs_addr[sm_fshdr_fs_type])) < 0) |
3221 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, |
3222 | 0 | "can't vfd allocate sm hdr FSM file space"); |
3223 | | |
3224 | 0 | if (sm_sinfo_fspace && (sm_sinfo_fspace != sm_hdr_fspace)) |
3225 | 0 | if (H5FS_vfd_alloc_hdr_and_section_info_if_needed( |
3226 | 0 | f, sm_sinfo_fspace, &(f->shared->fs_addr[sm_fssinfo_fs_type])) < 0) |
3227 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, |
3228 | 0 | "can't vfd allocate sm sinfo FSM file space"); |
3229 | | |
3230 | 0 | if (H5F_PAGED_AGGR(f)) { |
3231 | 0 | if (lg_hdr_fspace) |
3232 | 0 | if (H5FS_vfd_alloc_hdr_and_section_info_if_needed( |
3233 | 0 | f, lg_hdr_fspace, &(f->shared->fs_addr[lg_fshdr_fs_type])) < 0) |
3234 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, |
3235 | 0 | "can't vfd allocate lg hdr FSM file space"); |
3236 | | |
3237 | 0 | if (lg_sinfo_fspace && (lg_sinfo_fspace != lg_hdr_fspace)) |
3238 | 0 | if (H5FS_vfd_alloc_hdr_and_section_info_if_needed( |
3239 | 0 | f, lg_sinfo_fspace, &(f->shared->fs_addr[lg_fssinfo_fs_type])) < 0) |
3240 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, |
3241 | 0 | "can't vfd allocate lg sinfo FSM file space"); |
3242 | 0 | } /* end if */ |
3243 | | |
3244 | 0 | sm_hdr_fspace = f->shared->fs_man[sm_fshdr_fs_type]; |
3245 | 0 | sm_sinfo_fspace = f->shared->fs_man[sm_fssinfo_fs_type]; |
3246 | 0 | if (H5F_PAGED_AGGR(f)) { |
3247 | 0 | lg_hdr_fspace = f->shared->fs_man[lg_fshdr_fs_type]; |
3248 | 0 | lg_sinfo_fspace = f->shared->fs_man[lg_fssinfo_fs_type]; |
3249 | 0 | } |
3250 | |
|
3251 | 0 | if (H5MF__continue_alloc_fsm(f->shared, sm_hdr_fspace, sm_sinfo_fspace, lg_hdr_fspace, |
3252 | 0 | lg_sinfo_fspace, &continue_alloc_fsm) < 0) |
3253 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't vfd allocate lg sinfo FSM file space"); |
3254 | 0 | } while (continue_alloc_fsm); |
3255 | | |
3256 | | /* All free space managers should have file space allocated for them |
3257 | | * now, and should see no further allocations / deallocations. |
3258 | | * For backward compatibility, store the eoa in f->shared->eoa_fsm_fsalloc |
3259 | | * which will be set to fsinfo.eoa_pre_fsm_fsalloc when we actually write |
3260 | | * the free-space info message to the superblock extension. |
3261 | | * This will allow the 1.10 library with the hack to open the file with |
3262 | | * the new solution. |
3263 | | */ |
3264 | | /* Get the eoa after allocation of file space for the self referential |
3265 | | * free space managers. Assuming no cache image, this should be the |
3266 | | * final EOA of the file. |
3267 | | */ |
3268 | 0 | if (HADDR_UNDEF == (eoa_fsm_fsalloc = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT))) |
3269 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size"); |
3270 | 0 | f->shared->eoa_fsm_fsalloc = eoa_fsm_fsalloc; |
3271 | | |
3272 | | /* Indicate that the FSM was settled successfully */ |
3273 | 0 | *fsm_settled = true; |
3274 | 0 | } /* end if */ |
3275 | | |
3276 | 172 | done: |
3277 | | /* Reset the ring in the API context */ |
3278 | 172 | if (orig_ring != H5AC_RING_INV) |
3279 | 0 | H5AC_set_ring(orig_ring, NULL); |
3280 | | |
3281 | 172 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
3282 | 172 | } /* H5MF_settle_meta_data_fsm() */ |
3283 | | |
3284 | | /*------------------------------------------------------------------------- |
3285 | | * Function: H5MF__continue_alloc_fsm |
3286 | | * |
3287 | | * Purpose: To determine whether any of the input FSMs has allocated |
3288 | | * its "addr" and "sect_addr". |
3289 | | * Return true or false in *continue_alloc_fsm. |
3290 | | * |
3291 | | * Return: SUCCEED/FAIL |
3292 | | * |
3293 | | *------------------------------------------------------------------------- |
3294 | | */ |
3295 | | static herr_t |
3296 | | H5MF__continue_alloc_fsm(H5F_shared_t *f_sh, H5FS_t *sm_hdr_fspace, H5FS_t *sm_sinfo_fspace, |
3297 | | H5FS_t *lg_hdr_fspace, H5FS_t *lg_sinfo_fspace, bool *continue_alloc_fsm) |
3298 | 0 | { |
3299 | 0 | FUNC_ENTER_PACKAGE_NOERR |
3300 | | |
3301 | | /* Sanity checks */ |
3302 | 0 | assert(f_sh); |
3303 | 0 | assert(continue_alloc_fsm); |
3304 | | |
3305 | | /* Check sm_hdr_fspace */ |
3306 | 0 | if (sm_hdr_fspace && sm_hdr_fspace->serial_sect_count > 0 && sm_hdr_fspace->sinfo) |
3307 | 0 | H5MF_CHECK_FSM(sm_hdr_fspace, continue_alloc_fsm); |
3308 | |
|
3309 | 0 | if (!(*continue_alloc_fsm)) |
3310 | 0 | if (sm_sinfo_fspace && sm_sinfo_fspace != sm_hdr_fspace && sm_sinfo_fspace->serial_sect_count > 0 && |
3311 | 0 | sm_sinfo_fspace->sinfo) |
3312 | 0 | H5MF_CHECK_FSM(sm_hdr_fspace, continue_alloc_fsm); |
3313 | |
|
3314 | 0 | if (H5F_SHARED_PAGED_AGGR(f_sh) && !(*continue_alloc_fsm)) { |
3315 | | /* Check lg_hdr_fspace */ |
3316 | 0 | if (lg_hdr_fspace && lg_hdr_fspace->serial_sect_count > 0 && lg_hdr_fspace->sinfo) |
3317 | 0 | H5MF_CHECK_FSM(lg_hdr_fspace, continue_alloc_fsm); |
3318 | | |
3319 | | /* Check lg_sinfo_fspace */ |
3320 | 0 | if (!(*continue_alloc_fsm)) |
3321 | 0 | if (lg_sinfo_fspace && lg_sinfo_fspace != lg_hdr_fspace && |
3322 | 0 | lg_sinfo_fspace->serial_sect_count > 0 && lg_sinfo_fspace->sinfo) |
3323 | 0 | H5MF_CHECK_FSM(lg_sinfo_fspace, continue_alloc_fsm); |
3324 | 0 | } /* end if */ |
3325 | |
|
3326 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
3327 | 0 | } /* H5MF__continue_alloc_fsm() */ |
3328 | | |
3329 | | /*------------------------------------------------------------------------- |
3330 | | * Function: H5MF__fsm_type_is_self_referential() |
3331 | | * |
3332 | | * Purpose: Return true if the indicated free space manager allocates |
3333 | | * file space for free space managers. Return false otherwise. |
3334 | | * |
3335 | | * Return: true/false |
3336 | | * |
3337 | | *------------------------------------------------------------------------- |
3338 | | */ |
3339 | | static bool |
3340 | | H5MF__fsm_type_is_self_referential(H5F_shared_t *f_sh, H5F_mem_page_t fsm_type) |
3341 | 0 | { |
3342 | 0 | H5F_mem_page_t sm_fshdr_fsm = H5F_MEM_PAGE_NTYPES; |
3343 | 0 | H5F_mem_page_t sm_fssinfo_fsm = H5F_MEM_PAGE_NTYPES; |
3344 | 0 | H5F_mem_page_t lg_fshdr_fsm = H5F_MEM_PAGE_NTYPES; |
3345 | 0 | H5F_mem_page_t lg_fssinfo_fsm = H5F_MEM_PAGE_NTYPES; |
3346 | 0 | bool result = false; |
3347 | |
|
3348 | 0 | FUNC_ENTER_PACKAGE_NOERR |
3349 | | |
3350 | | /* Sanity check */ |
3351 | 0 | assert(f_sh); |
3352 | 0 | assert(fsm_type >= H5F_MEM_PAGE_DEFAULT); |
3353 | 0 | assert(fsm_type < H5F_MEM_PAGE_NTYPES); |
3354 | |
|
3355 | 0 | H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fsm); |
3356 | 0 | H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fsm); |
3357 | |
|
3358 | 0 | if (H5F_SHARED_PAGED_AGGR(f_sh)) { |
3359 | 0 | H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_HDR, f_sh->fs_page_size + 1, &lg_fshdr_fsm); |
3360 | 0 | H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_SINFO, f_sh->fs_page_size + 1, &lg_fssinfo_fsm); |
3361 | |
|
3362 | 0 | result = (fsm_type == sm_fshdr_fsm) || (fsm_type == sm_fssinfo_fsm) || (fsm_type == lg_fshdr_fsm) || |
3363 | 0 | (fsm_type == lg_fssinfo_fsm); |
3364 | 0 | } /* end if */ |
3365 | 0 | else { |
3366 | | /* In principle, fsm_type should always be less than |
3367 | | * H5F_MEM_PAGE_LARGE_SUPER whenever paged aggregation |
3368 | | * is not enabled. However, since there is code that does |
3369 | | * not observe this principle, force the result to false if |
3370 | | * fsm_type is greater than or equal to H5F_MEM_PAGE_LARGE_SUPER. |
3371 | | */ |
3372 | 0 | if (fsm_type >= H5F_MEM_PAGE_LARGE_SUPER) |
3373 | 0 | result = false; |
3374 | 0 | else |
3375 | 0 | result = (fsm_type == sm_fshdr_fsm) || (fsm_type == sm_fssinfo_fsm); |
3376 | 0 | } /* end else */ |
3377 | |
|
3378 | 0 | FUNC_LEAVE_NOAPI(result) |
3379 | 0 | } /* H5MF__fsm_type_is_self_referential() */ |
3380 | | |
3381 | | /*------------------------------------------------------------------------- |
3382 | | * Function: H5MF__fsm_is_self_referential() |
3383 | | * |
3384 | | * Purpose: Return true if the indicated free space manager allocates |
3385 | | * file space for free space managers. Return false otherwise. |
3386 | | * |
3387 | | * Return: true/false |
3388 | | * |
3389 | | *------------------------------------------------------------------------- |
3390 | | */ |
3391 | | static bool |
3392 | | H5MF__fsm_is_self_referential(H5F_shared_t *f_sh, H5FS_t *fspace) |
3393 | 0 | { |
3394 | 0 | H5F_mem_page_t sm_fshdr_fsm = H5F_MEM_PAGE_NTYPES; |
3395 | 0 | H5F_mem_page_t sm_fssinfo_fsm = H5F_MEM_PAGE_NTYPES; |
3396 | 0 | bool result = false; |
3397 | |
|
3398 | 0 | FUNC_ENTER_PACKAGE_NOERR |
3399 | | |
3400 | | /* Sanity check */ |
3401 | 0 | assert(f_sh); |
3402 | 0 | assert(fspace); |
3403 | |
|
3404 | 0 | H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_HDR, (size_t)1, &sm_fshdr_fsm); |
3405 | 0 | H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_SINFO, (size_t)1, &sm_fssinfo_fsm); |
3406 | |
|
3407 | 0 | if (H5F_SHARED_PAGED_AGGR(f_sh)) { |
3408 | 0 | H5F_mem_page_t lg_fshdr_fsm = H5F_MEM_PAGE_NTYPES; |
3409 | 0 | H5F_mem_page_t lg_fssinfo_fsm = H5F_MEM_PAGE_NTYPES; |
3410 | |
|
3411 | 0 | H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_HDR, f_sh->fs_page_size + 1, &lg_fshdr_fsm); |
3412 | 0 | H5MF__alloc_to_fs_type(f_sh, H5FD_MEM_FSPACE_SINFO, f_sh->fs_page_size + 1, &lg_fssinfo_fsm); |
3413 | |
|
3414 | 0 | result = (fspace == f_sh->fs_man[sm_fshdr_fsm]) || (fspace == f_sh->fs_man[sm_fssinfo_fsm]) || |
3415 | 0 | (fspace == f_sh->fs_man[lg_fshdr_fsm]) || (fspace == f_sh->fs_man[lg_fssinfo_fsm]); |
3416 | 0 | } /* end if */ |
3417 | 0 | else |
3418 | 0 | result = (fspace == f_sh->fs_man[sm_fshdr_fsm]) || (fspace == f_sh->fs_man[sm_fssinfo_fsm]); |
3419 | |
|
3420 | 0 | FUNC_LEAVE_NOAPI(result) |
3421 | 0 | } /* H5MF__fsm_is_self_referential() */ |