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