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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
*
* Copyright (C) 1997 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*/
#include "ad_xfs.h"
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
/* style: allow:free:2 sig:0 */
static void ADIOI_XFS_Aligned_Mem_File_Read(ADIO_File fd, void *buf, int len,
ADIO_Offset offset, int *err);
void ADIOI_XFS_ReadContig(ADIO_File fd, void *buf, int count,
MPI_Datatype datatype, int file_ptr_type,
ADIO_Offset offset, ADIO_Status *status, int *error_code)
{
int diff, size, nbytes;
MPI_Count err=-1, datatype_size, len;
void *newbuf;
static char myname[] = "ADIOI_XFS_READCONTIG";
MPI_Type_size_x(datatype, &datatype_size);
len = datatype_size * count;
fd->fp_sys_posn = -1; /* set it to null, since we are using pread */
if (file_ptr_type == ADIO_INDIVIDUAL) offset = fd->fp_ind;
if (!(fd->direct_read)) /* direct I/O not enabled */
err = pread(fd->fd_sys, buf, len, offset);
else { /* direct I/O enabled */
/* (1) if mem_aligned && file_aligned
use direct I/O to read up to correct io_size
use buffered I/O for remaining */
if (!(((long) buf) % fd->d_mem) && !(offset % fd->d_miniosz))
ADIOI_XFS_Aligned_Mem_File_Read(fd, buf, len, offset, &err);
/* (2) if !file_aligned
use buffered I/O to read up to file_aligned
At that point, if still mem_aligned, use (1)
else copy into aligned buf and then use (1) */
else if (offset % fd->d_miniosz) {
diff = fd->d_miniosz - (offset % fd->d_miniosz);
diff = ADIOI_MIN(diff, len);
nbytes = pread(fd->fd_sys, buf, diff, offset);
buf = ((char *) buf) + diff;
offset += diff;
size = len - diff;
if (!(((long) buf) % fd->d_mem)) {
ADIOI_XFS_Aligned_Mem_File_Read(fd, buf, size, offset, &err);
nbytes += err;
}
else {
newbuf = (void *) memalign(XFS_MEMALIGN, size);
if (newbuf) {
ADIOI_XFS_Aligned_Mem_File_Read(fd, newbuf, size, offset, &err);
if (err > 0) memcpy(buf, newbuf, err);
nbytes += err;
ADIOI_Free(newbuf);
}
else nbytes += pread(fd->fd_sys, buf, size, offset);
}
err = nbytes;
}
/* (3) if !mem_aligned && file_aligned
copy into aligned buf, then use (1) */
else {
newbuf = (void *) memalign(XFS_MEMALIGN, len);
if (newbuf) {
ADIOI_XFS_Aligned_Mem_File_Read(fd, newbuf, len, offset, &err);
if (err > 0) memcpy(buf, newbuf, err);
ADIOI_Free(newbuf);
}
else err = pread(fd->fd_sys, buf, len, offset);
}
}
if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += err;
#ifdef HAVE_STATUS_SET_BYTES
if (err != -1) MPIR_Status_set_bytes(status, datatype, err);
#endif
if (err == -1) {
*error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
myname, __LINE__, MPI_ERR_IO, "**io",
"**io %s", strerror(errno));
}
else *error_code = MPI_SUCCESS;
}
void ADIOI_XFS_Aligned_Mem_File_Read(ADIO_File fd, void *buf, int len,
ADIO_Offset offset, int *err)
{
int ntimes, rem, newrem, i, size, nbytes;
unsigned read_chunk_sz = fd->hints->fs_hints.xfs.read_chunk_sz;
/* memory buffer is aligned, offset in file is aligned,
io_size may or may not be of the right size.
use direct I/O to read up to correct io_size,
use buffered I/O for remaining. */
if (!(len % fd->d_miniosz) &&
(len >= fd->d_miniosz) && (len <= read_chunk_sz))
*err = pread(fd->fd_direct, buf, len, offset);
else if (len < fd->d_miniosz)
*err = pread(fd->fd_sys, buf, len, offset);
else if (len > read_chunk_sz) {
ntimes = len/(read_chunk_sz);
rem = len - ntimes * read_chunk_sz;
nbytes = 0;
for (i=0; i<ntimes; i++) {
nbytes += pread(fd->fd_direct, ((char *)buf) + i * read_chunk_sz,
read_chunk_sz, offset);
offset += read_chunk_sz;
}
if (rem) {
if (!(rem % fd->d_miniosz))
nbytes += pread(fd->fd_direct,
((char *)buf) + ntimes * read_chunk_sz, rem, offset);
else {
newrem = rem % fd->d_miniosz;
size = rem - newrem;
if (size) {
nbytes += pread(fd->fd_direct,
((char *)buf) + ntimes * read_chunk_sz, size, offset);
offset += size;
}
nbytes += pread(fd->fd_sys,
((char *)buf) + ntimes * read_chunk_sz + size, newrem, offset);
}
}
*err = nbytes;
}
else {
rem = len % fd->d_miniosz;
size = len - rem;
nbytes = pread(fd->fd_direct, buf, size, offset);
nbytes += pread(fd->fd_sys, (char *)buf + size, rem, offset+size);
*err = nbytes;
}
}
|