/src/hdf5/src/H5MFsection.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the 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 | | * Purpose: Free space section callbacks for file. |
15 | | * |
16 | | */ |
17 | | |
18 | | /****************/ |
19 | | /* Module Setup */ |
20 | | /****************/ |
21 | | |
22 | | #define H5F_FRIEND /*suppress error about including H5Fpkg */ |
23 | | #include "H5MFmodule.h" /* This source code file is part of the H5MF module */ |
24 | | |
25 | | /***********/ |
26 | | /* Headers */ |
27 | | /***********/ |
28 | | #include "H5private.h" /* Generic Functions */ |
29 | | #include "H5Eprivate.h" /* Error handling */ |
30 | | #include "H5Fpkg.h" /* File access */ |
31 | | #include "H5FLprivate.h" /* Free Lists */ |
32 | | #include "H5MFpkg.h" /* File memory management */ |
33 | | |
34 | | /****************/ |
35 | | /* Local Macros */ |
36 | | /****************/ |
37 | | |
38 | | /******************/ |
39 | | /* Local Typedefs */ |
40 | | /******************/ |
41 | | |
42 | | /********************/ |
43 | | /* Package Typedefs */ |
44 | | /********************/ |
45 | | |
46 | | /********************/ |
47 | | /* Local Prototypes */ |
48 | | /********************/ |
49 | | |
50 | | /* 'simple/small/large' section callbacks */ |
51 | | static H5FS_section_info_t *H5MF__sect_deserialize(const H5FS_section_class_t *cls, const uint8_t *buf, |
52 | | haddr_t sect_addr, hsize_t sect_size, unsigned *des_flags); |
53 | | static herr_t H5MF__sect_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *sect); |
54 | | static H5FS_section_info_t *H5MF__sect_split(H5FS_section_info_t *sect, hsize_t frag_size); |
55 | | |
56 | | /* 'simple' section callbacks */ |
57 | | static htri_t H5MF__sect_simple_can_merge(const H5FS_section_info_t *sect1, const H5FS_section_info_t *sect2, |
58 | | void *udata); |
59 | | static herr_t H5MF__sect_simple_merge(H5FS_section_info_t **sect1, H5FS_section_info_t *sect2, void *udata); |
60 | | static htri_t H5MF__sect_simple_can_shrink(const H5FS_section_info_t *_sect, void *udata); |
61 | | static herr_t H5MF__sect_simple_shrink(H5FS_section_info_t **_sect, void *udata); |
62 | | |
63 | | /* 'small' section callbacks */ |
64 | | static herr_t H5MF__sect_small_add(H5FS_section_info_t **_sect, unsigned *flags, void *_udata); |
65 | | static htri_t H5MF__sect_small_can_merge(const H5FS_section_info_t *sect1, const H5FS_section_info_t *sect2, |
66 | | void *udata); |
67 | | static herr_t H5MF__sect_small_merge(H5FS_section_info_t **sect1, H5FS_section_info_t *sect2, void *udata); |
68 | | |
69 | | /* 'large' section callbacks */ |
70 | | static htri_t H5MF__sect_large_can_merge(const H5FS_section_info_t *sect1, const H5FS_section_info_t *sect2, |
71 | | void *udata); |
72 | | static herr_t H5MF__sect_large_merge(H5FS_section_info_t **sect1, H5FS_section_info_t *sect2, void *udata); |
73 | | static htri_t H5MF__sect_large_can_shrink(const H5FS_section_info_t *_sect, void *udata); |
74 | | static herr_t H5MF__sect_large_shrink(H5FS_section_info_t **_sect, void *udata); |
75 | | |
76 | | /*********************/ |
77 | | /* Package Variables */ |
78 | | /*********************/ |
79 | | |
80 | | /* Class info for "simple" free space sections */ |
81 | | const H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SIMPLE[1] = {{ |
82 | | /* Class variables */ |
83 | | H5MF_FSPACE_SECT_SIMPLE, /* Section type */ |
84 | | 0, /* Extra serialized size */ |
85 | | H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ |
86 | | NULL, /* Class private info */ |
87 | | |
88 | | /* Class methods */ |
89 | | NULL, /* Initialize section class */ |
90 | | NULL, /* Terminate section class */ |
91 | | |
92 | | /* Object methods */ |
93 | | NULL, /* Add section */ |
94 | | NULL, /* Serialize section */ |
95 | | H5MF__sect_deserialize, /* Deserialize section */ |
96 | | H5MF__sect_simple_can_merge, /* Can sections merge? */ |
97 | | H5MF__sect_simple_merge, /* Merge sections */ |
98 | | H5MF__sect_simple_can_shrink, /* Can section shrink container?*/ |
99 | | H5MF__sect_simple_shrink, /* Shrink container w/section */ |
100 | | H5MF__sect_free, /* Free section */ |
101 | | H5MF__sect_valid, /* Check validity of section */ |
102 | | H5MF__sect_split, /* Split section node for alignment */ |
103 | | NULL, /* Dump debugging for section */ |
104 | | }}; |
105 | | |
106 | | /* Class info for "small" free space sections */ |
107 | | const H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SMALL[1] = {{ |
108 | | /* Class variables */ |
109 | | H5MF_FSPACE_SECT_SMALL, /* Section type */ |
110 | | 0, /* Extra serialized size */ |
111 | | H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ |
112 | | NULL, /* Class private info */ |
113 | | |
114 | | /* Class methods */ |
115 | | NULL, /* Initialize section class */ |
116 | | NULL, /* Terminate section class */ |
117 | | |
118 | | /* Object methods */ |
119 | | H5MF__sect_small_add, /* Add section */ |
120 | | NULL, /* Serialize section */ |
121 | | H5MF__sect_deserialize, /* Deserialize section */ |
122 | | H5MF__sect_small_can_merge, /* Can sections merge? */ |
123 | | H5MF__sect_small_merge, /* Merge sections */ |
124 | | NULL, /* Can section shrink container?*/ |
125 | | NULL, /* Shrink container w/section */ |
126 | | H5MF__sect_free, /* Free section */ |
127 | | H5MF__sect_valid, /* Check validity of section */ |
128 | | H5MF__sect_split, /* Split section node for alignment */ |
129 | | NULL, /* Dump debugging for section */ |
130 | | }}; |
131 | | |
132 | | /* Class info for "large" free space sections */ |
133 | | const H5FS_section_class_t H5MF_FSPACE_SECT_CLS_LARGE[1] = {{ |
134 | | /* Class variables */ |
135 | | H5MF_FSPACE_SECT_LARGE, /* Section type */ |
136 | | 0, /* Extra serialized size */ |
137 | | H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ |
138 | | NULL, /* Class private info */ |
139 | | |
140 | | /* Class methods */ |
141 | | NULL, /* Initialize section class */ |
142 | | NULL, /* Terminate section class */ |
143 | | |
144 | | /* Object methods */ |
145 | | NULL, /* Add section */ |
146 | | NULL, /* Serialize section */ |
147 | | H5MF__sect_deserialize, /* Deserialize section */ |
148 | | H5MF__sect_large_can_merge, /* Can sections merge? */ |
149 | | H5MF__sect_large_merge, /* Merge sections */ |
150 | | H5MF__sect_large_can_shrink, /* Can section shrink container?*/ |
151 | | H5MF__sect_large_shrink, /* Shrink container w/section */ |
152 | | H5MF__sect_free, /* Free section */ |
153 | | H5MF__sect_valid, /* Check validity of section */ |
154 | | H5MF__sect_split, /* Split section node for alignment */ |
155 | | NULL, /* Dump debugging for section */ |
156 | | }}; |
157 | | |
158 | | /*****************************/ |
159 | | /* Library Private Variables */ |
160 | | /*****************************/ |
161 | | |
162 | | /*******************/ |
163 | | /* Local Variables */ |
164 | | /*******************/ |
165 | | |
166 | | /* Declare a free list to manage the H5MF_free_section_t struct */ |
167 | | H5FL_DEFINE_STATIC(H5MF_free_section_t); |
168 | | |
169 | | /* |
170 | | * "simple/small/large" section callbacks |
171 | | */ |
172 | | |
173 | | /*------------------------------------------------------------------------- |
174 | | * Function: H5MF__sect_new |
175 | | * |
176 | | * Purpose: Create a new section of "ctype" and return it to the caller |
177 | | * |
178 | | * Return: Pointer to new section on success/NULL on failure |
179 | | * |
180 | | *------------------------------------------------------------------------- |
181 | | */ |
182 | | H5MF_free_section_t * |
183 | | H5MF__sect_new(unsigned ctype, haddr_t sect_off, hsize_t sect_size) |
184 | 346 | { |
185 | 346 | H5MF_free_section_t *sect; /* 'Simple' free space section to add */ |
186 | 346 | H5MF_free_section_t *ret_value = NULL; /* Return value */ |
187 | | |
188 | 346 | FUNC_ENTER_PACKAGE |
189 | | |
190 | | /* Check arguments. */ |
191 | 346 | assert(sect_size); |
192 | | |
193 | | /* Create free space section node */ |
194 | 346 | if (NULL == (sect = H5FL_MALLOC(H5MF_free_section_t))) |
195 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, |
196 | 346 | "memory allocation failed for direct block free list section"); |
197 | | |
198 | | /* Set the information passed in */ |
199 | 346 | sect->sect_info.addr = sect_off; |
200 | 346 | sect->sect_info.size = sect_size; |
201 | | |
202 | | /* Set the section's class & state */ |
203 | 346 | sect->sect_info.type = ctype; |
204 | 346 | sect->sect_info.state = H5FS_SECT_LIVE; |
205 | | |
206 | | /* Set return value */ |
207 | 346 | ret_value = sect; |
208 | | |
209 | 346 | done: |
210 | 346 | FUNC_LEAVE_NOAPI(ret_value) |
211 | 346 | } /* end H5MF__sect_new() */ |
212 | | |
213 | | /*------------------------------------------------------------------------- |
214 | | * Function: H5MF__sect_free |
215 | | * |
216 | | * Purpose: Free a 'simple/small/large' section node |
217 | | * |
218 | | * Return: Success: non-negative |
219 | | * Failure: negative |
220 | | * |
221 | | *------------------------------------------------------------------------- |
222 | | */ |
223 | | herr_t |
224 | | H5MF__sect_free(H5FS_section_info_t *_sect) |
225 | 316 | { |
226 | 316 | H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect; /* File free section */ |
227 | | |
228 | 316 | FUNC_ENTER_PACKAGE_NOERR |
229 | | |
230 | | /* Check arguments. */ |
231 | 316 | assert(sect); |
232 | | |
233 | | /* Release the section */ |
234 | 316 | sect = H5FL_FREE(H5MF_free_section_t, sect); |
235 | | |
236 | 316 | FUNC_LEAVE_NOAPI(SUCCEED) |
237 | 316 | } /* H5MF__sect_free() */ |
238 | | |
239 | | /*------------------------------------------------------------------------- |
240 | | * Function: H5MF__sect_deserialize |
241 | | * |
242 | | * Purpose: Deserialize a buffer into a "live" section |
243 | | * |
244 | | * Return: Success: non-negative |
245 | | * Failure: negative |
246 | | * |
247 | | *------------------------------------------------------------------------- |
248 | | */ |
249 | | static H5FS_section_info_t * |
250 | | H5MF__sect_deserialize(const H5FS_section_class_t *cls, const uint8_t H5_ATTR_UNUSED *buf, haddr_t sect_addr, |
251 | | hsize_t sect_size, unsigned H5_ATTR_UNUSED *des_flags) |
252 | 12 | { |
253 | 12 | H5MF_free_section_t *sect; /* New section */ |
254 | 12 | H5FS_section_info_t *ret_value = NULL; /* Return value */ |
255 | | |
256 | 12 | FUNC_ENTER_PACKAGE |
257 | | |
258 | | /* Check arguments. */ |
259 | 12 | assert(cls); |
260 | 12 | assert(H5_addr_defined(sect_addr)); |
261 | 12 | assert(sect_size); |
262 | | |
263 | | /* Create free space section for block */ |
264 | 12 | if (NULL == (sect = H5MF__sect_new(cls->type, sect_addr, sect_size))) |
265 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section"); |
266 | | |
267 | | /* Set return value */ |
268 | 12 | ret_value = (H5FS_section_info_t *)sect; |
269 | | |
270 | 12 | done: |
271 | 12 | FUNC_LEAVE_NOAPI(ret_value) |
272 | 12 | } /* H5MF__sect_deserialize() */ |
273 | | |
274 | | /*------------------------------------------------------------------------- |
275 | | * Function: H5MF__sect_valid |
276 | | * |
277 | | * Purpose: Check the validity of a section |
278 | | * |
279 | | * Return: Success: non-negative |
280 | | * Failure: negative |
281 | | * |
282 | | *------------------------------------------------------------------------- |
283 | | */ |
284 | | static herr_t |
285 | | H5MF__sect_valid(const H5FS_section_class_t H5_ATTR_UNUSED *cls, const H5FS_section_info_t |
286 | | #ifdef NDEBUG |
287 | | H5_ATTR_UNUSED |
288 | | #endif /* NDEBUG */ |
289 | | *_sect) |
290 | 0 | { |
291 | | #ifndef NDEBUG |
292 | | const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */ |
293 | | #endif /* NDEBUG */ |
294 | |
|
295 | 0 | FUNC_ENTER_PACKAGE_NOERR |
296 | | |
297 | | /* Check arguments. */ |
298 | 0 | assert(sect); |
299 | |
|
300 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
301 | 0 | } /* H5MF__sect_valid() */ |
302 | | |
303 | | /*------------------------------------------------------------------------- |
304 | | * Function: H5MF__sect_split |
305 | | * |
306 | | * Purpose: Split SECT into 2 sections: fragment for alignment & the aligned section |
307 | | * SECT's addr and size are updated to point to the aligned section |
308 | | * |
309 | | * Return: Success: the fragment for aligning sect |
310 | | * Failure: null |
311 | | * |
312 | | *------------------------------------------------------------------------- |
313 | | */ |
314 | | static H5FS_section_info_t * |
315 | | H5MF__sect_split(H5FS_section_info_t *sect, hsize_t frag_size) |
316 | 6 | { |
317 | 6 | H5MF_free_section_t *ret_value = NULL; /* Return value */ |
318 | | |
319 | 6 | FUNC_ENTER_PACKAGE |
320 | | |
321 | | /* Allocate space for new section */ |
322 | 6 | if (NULL == (ret_value = H5MF__sect_new(sect->type, sect->addr, frag_size))) |
323 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section"); |
324 | | |
325 | | /* Set new section's info */ |
326 | 6 | sect->addr += frag_size; |
327 | 6 | sect->size -= frag_size; |
328 | | |
329 | 6 | done: |
330 | 6 | FUNC_LEAVE_NOAPI((H5FS_section_info_t *)ret_value) |
331 | 6 | } /* end H5MF__sect_split() */ |
332 | | |
333 | | /* |
334 | | * "simple" section callbacks |
335 | | */ |
336 | | |
337 | | /*------------------------------------------------------------------------- |
338 | | * Function: H5MF__sect_simple_can_merge |
339 | | * |
340 | | * Purpose: Can two sections of this type merge? |
341 | | * |
342 | | * Note: Second section must be "after" first section |
343 | | * |
344 | | * Return: Success: non-negative (true/false) |
345 | | * Failure: negative |
346 | | * |
347 | | *------------------------------------------------------------------------- |
348 | | */ |
349 | | static htri_t |
350 | | H5MF__sect_simple_can_merge(const H5FS_section_info_t *_sect1, const H5FS_section_info_t *_sect2, |
351 | | void H5_ATTR_UNUSED *_udata) |
352 | 100 | { |
353 | 100 | const H5MF_free_section_t *sect1 = (const H5MF_free_section_t *)_sect1; /* File free section */ |
354 | 100 | const H5MF_free_section_t *sect2 = (const H5MF_free_section_t *)_sect2; /* File free section */ |
355 | 100 | htri_t ret_value = FAIL; /* Return value */ |
356 | | |
357 | 100 | FUNC_ENTER_PACKAGE_NOERR |
358 | | |
359 | | /* Check arguments. */ |
360 | 100 | assert(sect1); |
361 | 100 | assert(sect2); |
362 | 100 | assert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ |
363 | 100 | assert(H5_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); |
364 | | |
365 | | /* Check if second section adjoins first section */ |
366 | 100 | ret_value = H5_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr); |
367 | | |
368 | 100 | FUNC_LEAVE_NOAPI(ret_value) |
369 | 100 | } /* H5MF__sect_simple_can_merge() */ |
370 | | |
371 | | /*------------------------------------------------------------------------- |
372 | | * Function: H5MF__sect_simple_merge |
373 | | * |
374 | | * Purpose: Merge two sections of this type |
375 | | * |
376 | | * Note: Second section always merges into first node |
377 | | * |
378 | | * Return: Success: non-negative |
379 | | * Failure: negative |
380 | | * |
381 | | *------------------------------------------------------------------------- |
382 | | */ |
383 | | static herr_t |
384 | | H5MF__sect_simple_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2, |
385 | | void H5_ATTR_UNUSED *_udata) |
386 | 24 | { |
387 | 24 | H5MF_free_section_t **sect1 = (H5MF_free_section_t **)_sect1; /* File free section */ |
388 | 24 | H5MF_free_section_t *sect2 = (H5MF_free_section_t *)_sect2; /* File free section */ |
389 | 24 | herr_t ret_value = SUCCEED; /* Return value */ |
390 | | |
391 | 24 | FUNC_ENTER_PACKAGE |
392 | | |
393 | | /* Check arguments. */ |
394 | 24 | assert(sect1); |
395 | 24 | assert((*sect1)->sect_info.type == H5MF_FSPACE_SECT_SIMPLE); |
396 | 24 | assert(sect2); |
397 | 24 | assert(sect2->sect_info.type == H5MF_FSPACE_SECT_SIMPLE); |
398 | 24 | assert(H5_addr_eq((*sect1)->sect_info.addr + (*sect1)->sect_info.size, sect2->sect_info.addr)); |
399 | | |
400 | | /* Add second section's size to first section */ |
401 | 24 | (*sect1)->sect_info.size += sect2->sect_info.size; |
402 | | |
403 | | /* Get rid of second section */ |
404 | 24 | if (H5MF__sect_free((H5FS_section_info_t *)sect2) < 0) |
405 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node"); |
406 | | |
407 | 24 | done: |
408 | 24 | FUNC_LEAVE_NOAPI(ret_value) |
409 | 24 | } /* H5MF__sect_simple_merge() */ |
410 | | |
411 | | /*------------------------------------------------------------------------- |
412 | | * Function: H5MF__sect_simple_can_shrink |
413 | | * |
414 | | * Purpose: Can this section shrink the container? |
415 | | * |
416 | | * Return: Success: non-negative (true/false) |
417 | | * Failure: negative |
418 | | * |
419 | | *------------------------------------------------------------------------- |
420 | | */ |
421 | | static htri_t |
422 | | H5MF__sect_simple_can_shrink(const H5FS_section_info_t *_sect, void *_udata) |
423 | 184 | { |
424 | 184 | const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */ |
425 | 184 | H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ |
426 | 184 | haddr_t eoa; /* End of address space in the file */ |
427 | 184 | haddr_t end; /* End of section to extend */ |
428 | 184 | htri_t ret_value = FAIL; /* Return value */ |
429 | | |
430 | 184 | FUNC_ENTER_PACKAGE |
431 | | |
432 | | /* Check arguments. */ |
433 | 184 | assert(sect); |
434 | 184 | assert(udata); |
435 | 184 | assert(udata->f); |
436 | | |
437 | | /* Retrieve the end of the file's address space */ |
438 | 184 | if (HADDR_UNDEF == (eoa = H5F_get_eoa(udata->f, udata->alloc_type))) |
439 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed"); |
440 | | |
441 | | /* Compute address of end of section to check */ |
442 | 184 | end = sect->sect_info.addr + sect->sect_info.size; |
443 | | |
444 | | /* Check if the section is exactly at the end of the allocated space in the file */ |
445 | 184 | if (H5_addr_eq(end, eoa)) { |
446 | | /* Set the shrinking type */ |
447 | 19 | udata->shrink = H5MF_SHRINK_EOA; |
448 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
449 | | fprintf(stderr, "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "}, shrinks file, eoa = %" PRIuHADDR "\n", |
450 | | __func__, sect->sect_info.addr, sect->sect_info.size, eoa); |
451 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
452 | | |
453 | | /* Indicate shrinking can occur */ |
454 | 19 | HGOTO_DONE(true); |
455 | 19 | } /* end if */ |
456 | 165 | else { |
457 | | /* Shrinking can't occur if the 'eoa_shrink_only' flag is set and we're not shrinking the EOA */ |
458 | 165 | if (udata->allow_eoa_shrink_only) |
459 | 24 | HGOTO_DONE(false); |
460 | | |
461 | | /* Check if this section is allowed to merge with metadata aggregation block */ |
462 | 141 | if (udata->f->shared->fs_aggr_merge[udata->alloc_type] & H5F_FS_MERGE_METADATA) { |
463 | 141 | htri_t status; /* Status from aggregator adjoin */ |
464 | | |
465 | | /* See if section can absorb the aggregator & vice versa */ |
466 | 141 | if ((status = H5MF__aggr_can_absorb(udata->f, &(udata->f->shared->meta_aggr), sect, |
467 | 141 | &(udata->shrink))) < 0) |
468 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, |
469 | 141 | "error merging section with aggregation block"); |
470 | 141 | else if (status > 0) { |
471 | | /* Set the aggregator to operate on */ |
472 | 35 | udata->aggr = &(udata->f->shared->meta_aggr); |
473 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
474 | | fprintf(stderr, "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "}, adjoins metadata aggregator\n", |
475 | | __func__, sect->sect_info.addr, sect->sect_info.size); |
476 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
477 | | |
478 | | /* Indicate shrinking can occur */ |
479 | 35 | HGOTO_DONE(true); |
480 | 35 | } /* end if */ |
481 | 141 | } /* end if */ |
482 | | |
483 | | /* Check if this section is allowed to merge with small 'raw' aggregation block */ |
484 | 106 | if (udata->f->shared->fs_aggr_merge[udata->alloc_type] & H5F_FS_MERGE_RAWDATA) { |
485 | 0 | htri_t status; /* Status from aggregator adjoin */ |
486 | | |
487 | | /* See if section can absorb the aggregator & vice versa */ |
488 | 0 | if ((status = H5MF__aggr_can_absorb(udata->f, &(udata->f->shared->sdata_aggr), sect, |
489 | 0 | &(udata->shrink))) < 0) |
490 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, |
491 | 0 | "error merging section with aggregation block"); |
492 | 0 | else if (status > 0) { |
493 | | /* Set the aggregator to operate on */ |
494 | 0 | udata->aggr = &(udata->f->shared->sdata_aggr); |
495 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
496 | | fprintf(stderr, |
497 | | "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "}, adjoins small data aggregator\n", |
498 | | __func__, sect->sect_info.addr, sect->sect_info.size); |
499 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
500 | | |
501 | | /* Indicate shrinking can occur */ |
502 | 0 | HGOTO_DONE(true); |
503 | 0 | } /* end if */ |
504 | 0 | } /* end if */ |
505 | 106 | } /* end else */ |
506 | | |
507 | | /* Set return value */ |
508 | 106 | ret_value = false; |
509 | | |
510 | 184 | done: |
511 | 184 | FUNC_LEAVE_NOAPI(ret_value) |
512 | 184 | } /* H5MF__sect_simple_can_shrink() */ |
513 | | |
514 | | /*------------------------------------------------------------------------- |
515 | | * Function: H5MF__sect_simple_shrink |
516 | | * |
517 | | * Purpose: Shrink container with section |
518 | | * |
519 | | * Return: Success: non-negative |
520 | | * Failure: negative |
521 | | * |
522 | | *------------------------------------------------------------------------- |
523 | | */ |
524 | | static herr_t |
525 | | H5MF__sect_simple_shrink(H5FS_section_info_t **_sect, void *_udata) |
526 | 54 | { |
527 | 54 | H5MF_free_section_t **sect = (H5MF_free_section_t **)_sect; /* File free section */ |
528 | 54 | H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ |
529 | 54 | herr_t ret_value = SUCCEED; /* Return value */ |
530 | | |
531 | 54 | FUNC_ENTER_PACKAGE |
532 | | |
533 | | /* Check arguments. */ |
534 | 54 | assert(sect); |
535 | 54 | assert(udata); |
536 | 54 | assert(udata->f); |
537 | | |
538 | | /* Check for shrinking file */ |
539 | 54 | if (H5MF_SHRINK_EOA == udata->shrink) { |
540 | | /* Sanity check */ |
541 | 19 | assert(H5F_INTENT(udata->f) & H5F_ACC_RDWR); |
542 | | |
543 | | /* Release section's space at EOA */ |
544 | 19 | if (H5F__free(udata->f, udata->alloc_type, (*sect)->sect_info.addr, (*sect)->sect_info.size) < 0) |
545 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "driver free request failed"); |
546 | 19 | } /* end if */ |
547 | 35 | else { |
548 | | /* Sanity check */ |
549 | 35 | assert(udata->aggr); |
550 | | |
551 | | /* Absorb the section into the aggregator or vice versa */ |
552 | 35 | if (H5MF__aggr_absorb(udata->f, udata->aggr, *sect, udata->allow_sect_absorb) < 0) |
553 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, |
554 | 35 | "can't absorb section into aggregator or vice versa"); |
555 | 35 | } /* end else */ |
556 | | |
557 | | /* Check for freeing section */ |
558 | 54 | if (udata->shrink != H5MF_SHRINK_SECT_ABSORB_AGGR) { |
559 | | /* Free section */ |
560 | 19 | if (H5MF__sect_free((H5FS_section_info_t *)*sect) < 0) |
561 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node"); |
562 | | |
563 | | /* Mark section as freed, for free space manager */ |
564 | 19 | *sect = NULL; |
565 | 19 | } /* end if */ |
566 | | |
567 | 54 | done: |
568 | 54 | FUNC_LEAVE_NOAPI(ret_value) |
569 | 54 | } /* H5MF__sect_simple_shrink() */ |
570 | | |
571 | | /* |
572 | | * "small" section callbacks |
573 | | */ |
574 | | |
575 | | /*------------------------------------------------------------------------- |
576 | | * Function: H5MF__sect_small_add |
577 | | * |
578 | | * Purpose: Perform actions on a small "meta" action before adding it to the free space manager: |
579 | | * 1) Drop the section if it is at page end and its size <= page end threshold |
580 | | * 2) Adjust section size to include page end threshold if |
581 | | * (section size + threshold) is at page end |
582 | | * |
583 | | * Return: Success: non-negative |
584 | | * Failure: negative |
585 | | * |
586 | | *------------------------------------------------------------------------- |
587 | | */ |
588 | | static herr_t |
589 | | H5MF__sect_small_add(H5FS_section_info_t **_sect, unsigned *flags, void *_udata) |
590 | 227 | { |
591 | 227 | H5MF_free_section_t **sect = (H5MF_free_section_t **)_sect; /* Fractal heap free section */ |
592 | 227 | H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ |
593 | 227 | haddr_t sect_end; |
594 | 227 | hsize_t rem, prem; |
595 | 227 | herr_t ret_value = SUCCEED; /* Return value */ |
596 | | |
597 | 227 | FUNC_ENTER_PACKAGE |
598 | | |
599 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
600 | | fprintf(stderr, "%s: Entering, section {%" PRIuHADDR ", %" PRIuHSIZE "}\n", __func__, |
601 | | (*sect)->sect_info.addr, (*sect)->sect_info.size); |
602 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
603 | | |
604 | | /* Do not adjust the section raw data or global heap data */ |
605 | 227 | if (udata->alloc_type == H5FD_MEM_DRAW || udata->alloc_type == H5FD_MEM_GHEAP) |
606 | 0 | HGOTO_DONE(ret_value); |
607 | | |
608 | 227 | sect_end = (*sect)->sect_info.addr + (*sect)->sect_info.size; |
609 | 227 | if (0 == udata->f->shared->fs_page_size) |
610 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_BADVALUE, FAIL, "page size of zero would result in division by zero"); |
611 | 227 | rem = sect_end % udata->f->shared->fs_page_size; |
612 | 227 | prem = udata->f->shared->fs_page_size - rem; |
613 | | |
614 | | /* Drop the section if it is at page end and its size is <= pgend threshold */ |
615 | 227 | if (!rem && (*sect)->sect_info.size <= H5F_PGEND_META_THRES(udata->f) && |
616 | 227 | (*flags & H5FS_ADD_RETURNED_SPACE)) { |
617 | 8 | if (H5MF__sect_free((H5FS_section_info_t *)(*sect)) < 0) |
618 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node"); |
619 | 8 | *sect = NULL; |
620 | 8 | *flags &= (unsigned)~H5FS_ADD_RETURNED_SPACE; |
621 | 8 | *flags |= H5FS_PAGE_END_NO_ADD; |
622 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
623 | | fprintf(stderr, "%s: section is dropped\n", __func__); |
624 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
625 | 8 | } /* end if */ |
626 | | /* Adjust the section if it is not at page end but its size + prem is at page end */ |
627 | 219 | else if (prem <= H5F_PGEND_META_THRES(udata->f)) { |
628 | 3 | (*sect)->sect_info.size += prem; |
629 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
630 | | fprintf(stderr, "%s: section is adjusted {%" PRIuHADDR ", %" PRIuHSIZE "}\n", __func__, |
631 | | (*sect)->sect_info.addr, (*sect)->sect_info.size); |
632 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
633 | 3 | } /* end if */ |
634 | | |
635 | 227 | done: |
636 | 227 | FUNC_LEAVE_NOAPI(ret_value) |
637 | 227 | } /* H5MF__sect_small_add() */ |
638 | | |
639 | | /*------------------------------------------------------------------------- |
640 | | * Function: H5MF__sect_small_can_merge |
641 | | * |
642 | | * Purpose: Can two sections of this type merge? |
643 | | * |
644 | | * Note: Second section must be "after" first section |
645 | | * The "merged" section cannot cross page boundary. |
646 | | * |
647 | | * Return: Success: non-negative (true/false) |
648 | | * Failure: negative |
649 | | * |
650 | | *------------------------------------------------------------------------- |
651 | | */ |
652 | | static htri_t |
653 | | H5MF__sect_small_can_merge(const H5FS_section_info_t *_sect1, const H5FS_section_info_t *_sect2, void *_udata) |
654 | 85 | { |
655 | 85 | const H5MF_free_section_t *sect1 = (const H5MF_free_section_t *)_sect1; /* File free section */ |
656 | 85 | const H5MF_free_section_t *sect2 = (const H5MF_free_section_t *)_sect2; /* File free section */ |
657 | 85 | H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ |
658 | 85 | htri_t ret_value = false; /* Return value */ |
659 | | |
660 | 85 | FUNC_ENTER_PACKAGE_NOERR |
661 | | |
662 | | /* Check arguments. */ |
663 | 85 | assert(sect1); |
664 | 85 | assert(sect2); |
665 | 85 | assert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ |
666 | 85 | assert(H5_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); |
667 | | |
668 | | /* Check if second section adjoins first section */ |
669 | 85 | ret_value = H5_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr); |
670 | 85 | if (ret_value > 0) |
671 | | /* If they are on different pages, couldn't merge */ |
672 | 11 | if ((sect1->sect_info.addr / udata->f->shared->fs_page_size) != |
673 | 11 | (((sect2->sect_info.addr + sect2->sect_info.size - 1) / udata->f->shared->fs_page_size))) |
674 | 4 | ret_value = false; |
675 | | |
676 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
677 | | fprintf(stderr, "%s: Leaving: ret_value = %d\n", __func__, ret_value); |
678 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
679 | | |
680 | 85 | FUNC_LEAVE_NOAPI(ret_value) |
681 | 85 | } /* H5MF__sect_small_can_merge() */ |
682 | | |
683 | | /*------------------------------------------------------------------------- |
684 | | * Function: H5MF__sect_small_merge |
685 | | * |
686 | | * Purpose: Merge two sections of this type |
687 | | * |
688 | | * Note: Second section always merges into first node. |
689 | | * If the size of the "merged" section is equal to file space page size, |
690 | | * free the section. |
691 | | * |
692 | | * Return: Success: non-negative |
693 | | * Failure: negative |
694 | | * |
695 | | *------------------------------------------------------------------------- |
696 | | */ |
697 | | static herr_t |
698 | | H5MF__sect_small_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2, void *_udata) |
699 | 7 | { |
700 | 7 | H5MF_free_section_t **sect1 = (H5MF_free_section_t **)_sect1; /* File free section */ |
701 | 7 | H5MF_free_section_t *sect2 = (H5MF_free_section_t *)_sect2; /* File free section */ |
702 | 7 | H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ |
703 | 7 | herr_t ret_value = SUCCEED; /* Return value */ |
704 | | |
705 | 7 | FUNC_ENTER_PACKAGE |
706 | | |
707 | | /* Check arguments. */ |
708 | 7 | assert(sect1); |
709 | 7 | assert((*sect1)->sect_info.type == H5MF_FSPACE_SECT_SMALL); |
710 | 7 | assert(sect2); |
711 | 7 | assert(sect2->sect_info.type == H5MF_FSPACE_SECT_SMALL); |
712 | 7 | assert(H5_addr_eq((*sect1)->sect_info.addr + (*sect1)->sect_info.size, sect2->sect_info.addr)); |
713 | | |
714 | | /* Add second section's size to first section */ |
715 | 7 | (*sect1)->sect_info.size += sect2->sect_info.size; |
716 | | |
717 | 7 | if ((*sect1)->sect_info.size == udata->f->shared->fs_page_size) { |
718 | 2 | if (H5MF_xfree(udata->f, udata->alloc_type, (*sect1)->sect_info.addr, (*sect1)->sect_info.size) < 0) |
719 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free merged section"); |
720 | | |
721 | | /* Need to free possible metadata page in the PB cache */ |
722 | | /* This is in response to the data corruption bug from fheap.c with page buffering + page strategy */ |
723 | | /* Note: Large metadata page bypasses the PB cache */ |
724 | | /* Note: Update of raw data page (large or small sized) is handled by the PB cache */ |
725 | 2 | if (udata->f->shared->page_buf != NULL && udata->alloc_type != H5FD_MEM_DRAW) |
726 | 0 | if (H5PB_remove_entry(udata->f->shared, (*sect1)->sect_info.addr) < 0) |
727 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free merged section"); |
728 | | |
729 | 2 | if (H5MF__sect_free((H5FS_section_info_t *)(*sect1)) < 0) |
730 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node"); |
731 | 2 | *sect1 = NULL; |
732 | 2 | } /* end if */ |
733 | | |
734 | | /* Get rid of second section */ |
735 | 7 | if (H5MF__sect_free((H5FS_section_info_t *)sect2) < 0) |
736 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node"); |
737 | | |
738 | 7 | done: |
739 | 7 | FUNC_LEAVE_NOAPI(ret_value) |
740 | 7 | } /* H5MF__sect_small_merge() */ |
741 | | |
742 | | /* |
743 | | * "Large" section callbacks |
744 | | */ |
745 | | |
746 | | /*------------------------------------------------------------------------- |
747 | | * Function: H5MF__sect_large_can_merge (same as H5MF__sect_simple_can_merge) |
748 | | * |
749 | | * Purpose: Can two sections of this type merge? |
750 | | * |
751 | | * Note: Second section must be "after" first section |
752 | | * |
753 | | * Return: Success: non-negative (true/false) |
754 | | * Failure: negative |
755 | | * |
756 | | *------------------------------------------------------------------------- |
757 | | */ |
758 | | static htri_t |
759 | | H5MF__sect_large_can_merge(const H5FS_section_info_t *_sect1, const H5FS_section_info_t *_sect2, |
760 | | void H5_ATTR_UNUSED *_udata) |
761 | 13 | { |
762 | 13 | const H5MF_free_section_t *sect1 = (const H5MF_free_section_t *)_sect1; /* File free section */ |
763 | 13 | const H5MF_free_section_t *sect2 = (const H5MF_free_section_t *)_sect2; /* File free section */ |
764 | 13 | htri_t ret_value = false; /* Return value */ |
765 | | |
766 | 13 | FUNC_ENTER_PACKAGE_NOERR |
767 | | |
768 | | /* Check arguments. */ |
769 | 13 | assert(sect1); |
770 | 13 | assert(sect2); |
771 | 13 | assert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ |
772 | 13 | assert(H5_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); |
773 | | |
774 | 13 | ret_value = H5_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr); |
775 | | |
776 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
777 | | fprintf(stderr, "%s: Leaving: ret_value = %d\n", __func__, ret_value); |
778 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
779 | | |
780 | 13 | FUNC_LEAVE_NOAPI(ret_value) |
781 | 13 | } /* H5MF__sect_large_can_merge() */ |
782 | | |
783 | | /*------------------------------------------------------------------------- |
784 | | * Function: H5MF__sect_large_merge (same as H5MF__sect_simple_merge) |
785 | | * |
786 | | * Purpose: Merge two sections of this type |
787 | | * |
788 | | * Note: Second section always merges into first node |
789 | | * |
790 | | * Return: Success: non-negative |
791 | | * Failure: negative |
792 | | * |
793 | | *------------------------------------------------------------------------- |
794 | | */ |
795 | | static herr_t |
796 | | H5MF__sect_large_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2, void H5_ATTR_UNUSED *_udata) |
797 | 0 | { |
798 | 0 | H5MF_free_section_t **sect1 = (H5MF_free_section_t **)_sect1; /* File free section */ |
799 | 0 | H5MF_free_section_t *sect2 = (H5MF_free_section_t *)_sect2; /* File free section */ |
800 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
801 | |
|
802 | 0 | FUNC_ENTER_PACKAGE |
803 | | |
804 | | /* Check arguments. */ |
805 | 0 | assert(sect1); |
806 | 0 | assert((*sect1)->sect_info.type == H5MF_FSPACE_SECT_LARGE); |
807 | 0 | assert(sect2); |
808 | 0 | assert(sect2->sect_info.type == H5MF_FSPACE_SECT_LARGE); |
809 | 0 | assert(H5_addr_eq((*sect1)->sect_info.addr + (*sect1)->sect_info.size, sect2->sect_info.addr)); |
810 | | |
811 | | /* Add second section's size to first section */ |
812 | 0 | (*sect1)->sect_info.size += sect2->sect_info.size; |
813 | | |
814 | | /* Get rid of second section */ |
815 | 0 | if (H5MF__sect_free((H5FS_section_info_t *)sect2) < 0) |
816 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node"); |
817 | | |
818 | 0 | done: |
819 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
820 | 0 | } /* H5MF__sect_large_merge() */ |
821 | | |
822 | | /*------------------------------------------------------------------------- |
823 | | * Function: H5MF__sect_large_can_shrink |
824 | | * |
825 | | * Purpose: Can this section shrink the container? |
826 | | * |
827 | | * Return: Success: non-negative (true/false) |
828 | | * Failure: negative |
829 | | * |
830 | | *------------------------------------------------------------------------- |
831 | | */ |
832 | | static htri_t |
833 | | H5MF__sect_large_can_shrink(const H5FS_section_info_t *_sect, void *_udata) |
834 | 137 | { |
835 | 137 | const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */ |
836 | 137 | H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ |
837 | 137 | haddr_t eoa; /* End of address space in the file */ |
838 | 137 | haddr_t end; /* End of section to extend */ |
839 | 137 | htri_t ret_value = false; /* Return value */ |
840 | | |
841 | 137 | FUNC_ENTER_PACKAGE |
842 | | |
843 | | /* Check arguments. */ |
844 | 137 | assert(sect); |
845 | 137 | assert(sect->sect_info.type == H5MF_FSPACE_SECT_LARGE); |
846 | 137 | assert(udata); |
847 | 137 | assert(udata->f); |
848 | | |
849 | | /* Retrieve the end of the file's address space */ |
850 | 137 | if (HADDR_UNDEF == (eoa = H5FD_get_eoa(udata->f->shared->lf, udata->alloc_type))) |
851 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed"); |
852 | | |
853 | | /* Compute address of end of section to check */ |
854 | 137 | end = sect->sect_info.addr + sect->sect_info.size; |
855 | | |
856 | | /* Check if the section is exactly at the end of the allocated space in the file */ |
857 | 137 | if (H5_addr_eq(end, eoa) && sect->sect_info.size >= udata->f->shared->fs_page_size) { |
858 | | /* Set the shrinking type */ |
859 | 2 | udata->shrink = H5MF_SHRINK_EOA; |
860 | | #ifdef H5MF_ALLOC_DEBUG_MORE |
861 | | fprintf(stderr, "%s: section {%" PRIuHADDR ", %" PRIuHSIZE "}, shrinks file, eoa = %" PRIuHADDR "\n", |
862 | | __func__, sect->sect_info.addr, sect->sect_info.size, eoa); |
863 | | #endif /* H5MF_ALLOC_DEBUG_MORE */ |
864 | | |
865 | | /* Indicate shrinking can occur */ |
866 | 2 | HGOTO_DONE(true); |
867 | 2 | } /* end if */ |
868 | | |
869 | 137 | done: |
870 | 137 | FUNC_LEAVE_NOAPI(ret_value) |
871 | 137 | } /* H5MF__sect_large_can_shrink() */ |
872 | | |
873 | | /*------------------------------------------------------------------------- |
874 | | * Function: H5MF__sect_large_shrink |
875 | | * |
876 | | * Purpose: Shrink a large-sized section |
877 | | * |
878 | | * Return: Success: non-negative |
879 | | * Failure: negative |
880 | | * |
881 | | *------------------------------------------------------------------------- |
882 | | */ |
883 | | static herr_t |
884 | | H5MF__sect_large_shrink(H5FS_section_info_t **_sect, void *_udata) |
885 | 2 | { |
886 | 2 | H5MF_free_section_t **sect = (H5MF_free_section_t **)_sect; /* File free section */ |
887 | 2 | H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ |
888 | 2 | hsize_t frag_size = 0; /* Fragment size */ |
889 | 2 | herr_t ret_value = SUCCEED; /* Return value */ |
890 | | |
891 | 2 | FUNC_ENTER_PACKAGE |
892 | | |
893 | | /* Check arguments. */ |
894 | 2 | assert(sect); |
895 | 2 | assert((*sect)->sect_info.type == H5MF_FSPACE_SECT_LARGE); |
896 | 2 | assert(udata); |
897 | 2 | assert(udata->f); |
898 | 2 | assert(udata->shrink == H5MF_SHRINK_EOA); |
899 | 2 | assert(H5F_INTENT(udata->f) & H5F_ACC_RDWR); |
900 | 2 | assert(H5F_PAGED_AGGR(udata->f)); |
901 | | |
902 | | /* Calculate possible mis-aligned fragment */ |
903 | 2 | H5MF_EOA_MISALIGN(udata->f, (*sect)->sect_info.addr, udata->f->shared->fs_page_size, frag_size); |
904 | | |
905 | | /* Free full pages from EOA */ |
906 | | /* Retain partial page in the free-space manager so as to keep EOA at page boundary */ |
907 | 2 | if (H5F__free(udata->f, udata->alloc_type, (*sect)->sect_info.addr + frag_size, |
908 | 2 | (*sect)->sect_info.size - frag_size) < 0) |
909 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "driver free request failed"); |
910 | | |
911 | 2 | if (frag_size) /* Adjust section size for the partial page */ |
912 | 0 | (*sect)->sect_info.size = frag_size; |
913 | 2 | else { |
914 | | /* Free section */ |
915 | 2 | if (H5MF__sect_free((H5FS_section_info_t *)*sect) < 0) |
916 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node"); |
917 | | |
918 | | /* Mark section as freed, for free space manager */ |
919 | 2 | *sect = NULL; |
920 | 2 | } /* end else */ |
921 | | |
922 | 2 | done: |
923 | 2 | FUNC_LEAVE_NOAPI(ret_value) |
924 | 2 | } /* H5MF__sect_large_shrink() */ |