1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
/*
* Copyright (C) by Argonne National Laboratory
* See COPYRIGHT in top-level directory
*/
#include "adio.h"
#include "adio_extern.h"
/* this used to be implemented in every file system as an fcntl, but the code
* is identical for all file systems without a real "preallocate" system call.
* This naive approach will get the job done, but not in a terribly efficient
* manner.
*/
void ADIOI_GEN_Prealloc(ADIO_File fd, ADIO_Offset diskspace, int *error_code)
{
ADIO_Offset curr_fsize, alloc_size, size, len, done, ntimes;
ADIO_Status status;
int i;
char *buf;
ADIO_Fcntl_t *fcntl_struct;
static char myname[] = "ADIOI_GEN_PREALLOC";
/* will be called by one process only */
/* On file systems with no preallocation function, we have to
* explicitly write
* to allocate space. Since there could be holes in the file,
* we need to read up to the current file size, write it back,
* and then write beyond that depending on how much
* preallocation is needed.
* read/write in sizes of no more than ADIOI_PREALLOC_BUFSZ */
/*curr_fsize = fd->fp_ind; */
fcntl_struct = (ADIO_Fcntl_t *) ADIOI_Malloc(sizeof(ADIO_Fcntl_t));
ADIO_Fcntl(fd, ADIO_FCNTL_GET_FSIZE, fcntl_struct, error_code);
curr_fsize = fcntl_struct->fsize; /* don't rely on fd->fp_ind: might be
* working on a pre-existing file */
alloc_size = diskspace;
size = MPL_MIN(curr_fsize, alloc_size);
ntimes = (size + ADIOI_PREALLOC_BUFSZ - 1) / ADIOI_PREALLOC_BUFSZ;
buf = (char *) ADIOI_Malloc(ADIOI_PREALLOC_BUFSZ);
done = 0;
for (i = 0; i < ntimes; i++) {
len = MPL_MIN(size - done, ADIOI_PREALLOC_BUFSZ);
ADIO_ReadContig(fd, buf, (int) len, /* len is ADIO_Offset but is <= ADIOI_PREALLOC_BUFSZ (16M),
* so it fits in an int parameter */
MPI_BYTE, ADIO_EXPLICIT_OFFSET, done, &status, error_code);
if (*error_code != MPI_SUCCESS) {
*error_code = MPIO_Err_create_code(MPI_SUCCESS,
MPIR_ERR_RECOVERABLE,
myname, __LINE__, MPI_ERR_IO, "**iopreallocrdwr", 0);
return;
}
ADIO_WriteContig(fd, buf, (int) len, /* len is ADIO_Offset but is <= ADIOI_PREALLOC_BUFSZ (16M),
* so it fits in an int parameter */
MPI_BYTE, ADIO_EXPLICIT_OFFSET, done, &status, error_code);
if (*error_code != MPI_SUCCESS)
return;
done += len;
}
if (alloc_size > curr_fsize) {
memset(buf, 0, ADIOI_PREALLOC_BUFSZ);
size = alloc_size - curr_fsize;
ntimes = (size + ADIOI_PREALLOC_BUFSZ - 1) / ADIOI_PREALLOC_BUFSZ;
for (i = 0; i < ntimes; i++) {
len = MPL_MIN(alloc_size - done, ADIOI_PREALLOC_BUFSZ);
ADIO_WriteContig(fd, buf, (int) len, /* len is ADIO_Offset but is <= ADIOI_PREALLOC_BUFSZ (16M),
* so it fits in an int parameter */
MPI_BYTE, ADIO_EXPLICIT_OFFSET, done, &status, error_code);
if (*error_code != MPI_SUCCESS)
return;
done += len;
}
}
ADIOI_Free(fcntl_struct);
ADIOI_Free(buf);
*error_code = MPI_SUCCESS;
}
|