darshan-posix.c 57.4 KB
Newer Older
1
/*
Shane Snyder's avatar
Shane Snyder committed
2 3 4
 * Copyright (C) 2015 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
5 6
 */

7 8 9
#define _XOPEN_SOURCE 500
#define _GNU_SOURCE

10
#include "darshan-runtime-config.h"
11 12 13 14 15 16 17 18 19 20 21 22 23 24
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <search.h>
#include <assert.h>
25
#include <libgen.h>
Philip Carns's avatar
Philip Carns committed
26
#include <aio.h>
27
#include <pthread.h>
28

29
#include "utlist.h"
30
#include "darshan.h"
31
#include "darshan-dynamic.h"
32

33
#ifndef HAVE_OFF64_T
34 35
typedef int64_t off64_t;
#endif
36 37 38
#ifndef HAVE_AIOCB64
#define aiocb64 aiocb
#endif
39

40

41 42
DARSHAN_FORWARD_DECL(open, int, (const char *path, int flags, ...));
DARSHAN_FORWARD_DECL(open64, int, (const char *path, int flags, ...));
43 44
DARSHAN_FORWARD_DECL(creat, int, (const char* path, mode_t mode));
DARSHAN_FORWARD_DECL(creat64, int, (const char* path, mode_t mode));
45 46 47 48
DARSHAN_FORWARD_DECL(mkstemp, int, (char *template));
DARSHAN_FORWARD_DECL(mkostemp, int, (char *template, int flags));
DARSHAN_FORWARD_DECL(mkstemps, int, (char *template, int suffixlen));
DARSHAN_FORWARD_DECL(mkostemps, int, (char *template, int suffixlen, int flags));
49 50 51 52 53 54 55 56
DARSHAN_FORWARD_DECL(read, ssize_t, (int fd, void *buf, size_t count));
DARSHAN_FORWARD_DECL(write, ssize_t, (int fd, const void *buf, size_t count));
DARSHAN_FORWARD_DECL(pread, ssize_t, (int fd, void *buf, size_t count, off_t offset));
DARSHAN_FORWARD_DECL(pwrite, ssize_t, (int fd, const void *buf, size_t count, off_t offset));
DARSHAN_FORWARD_DECL(pread64, ssize_t, (int fd, void *buf, size_t count, off64_t offset));
DARSHAN_FORWARD_DECL(pwrite64, ssize_t, (int fd, const void *buf, size_t count, off64_t offset));
DARSHAN_FORWARD_DECL(readv, ssize_t, (int fd, const struct iovec *iov, int iovcnt));
DARSHAN_FORWARD_DECL(writev, ssize_t, (int fd, const struct iovec *iov, int iovcnt));
57 58
DARSHAN_FORWARD_DECL(lseek, off_t, (int fd, off_t offset, int whence));
DARSHAN_FORWARD_DECL(lseek64, off64_t, (int fd, off64_t offset, int whence));
59 60 61 62 63 64
DARSHAN_FORWARD_DECL(__xstat, int, (int vers, const char* path, struct stat *buf));
DARSHAN_FORWARD_DECL(__xstat64, int, (int vers, const char* path, struct stat64 *buf));
DARSHAN_FORWARD_DECL(__lxstat, int, (int vers, const char* path, struct stat *buf));
DARSHAN_FORWARD_DECL(__lxstat64, int, (int vers, const char* path, struct stat64 *buf));
DARSHAN_FORWARD_DECL(__fxstat, int, (int vers, int fd, struct stat *buf));
DARSHAN_FORWARD_DECL(__fxstat64, int, (int vers, int fd, struct stat64 *buf));
Shane Snyder's avatar
Shane Snyder committed
65 66
DARSHAN_FORWARD_DECL(mmap, void*, (void *addr, size_t length, int prot, int flags, int fd, off_t offset));
DARSHAN_FORWARD_DECL(mmap64, void*, (void *addr, size_t length, int prot, int flags, int fd, off64_t offset));
67 68
DARSHAN_FORWARD_DECL(fsync, int, (int fd));
DARSHAN_FORWARD_DECL(fdatasync, int, (int fd));
69
DARSHAN_FORWARD_DECL(close, int, (int fd));
70 71 72 73 74 75 76 77
DARSHAN_FORWARD_DECL(aio_read, int, (struct aiocb *aiocbp));
DARSHAN_FORWARD_DECL(aio_write, int, (struct aiocb *aiocbp));
DARSHAN_FORWARD_DECL(aio_read64, int, (struct aiocb64 *aiocbp));
DARSHAN_FORWARD_DECL(aio_write64, int, (struct aiocb64 *aiocbp));
DARSHAN_FORWARD_DECL(aio_return, ssize_t, (struct aiocb *aiocbp));
DARSHAN_FORWARD_DECL(aio_return64, ssize_t, (struct aiocb64 *aiocbp));
DARSHAN_FORWARD_DECL(lio_listio, int, (int mode, struct aiocb *const aiocb_list[], int nitems, struct sigevent *sevp));
DARSHAN_FORWARD_DECL(lio_listio64, int, (int mode, struct aiocb64 *const aiocb_list[], int nitems, struct sigevent *sevp));
78

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
/* The posix_file_record_ref structure maintains necessary runtime metadata
 * for the POSIX file record (darshan_posix_file structure, defined in
 * darshan-posix-log-format.h) pointed to by 'file_rec'. This metadata
 * assists with the instrumenting of specific statistics in the file record.
 *
 * RATIONALE: the POSIX module needs to track some stateful, volatile 
 * information about each open file (like the current file offset, most recent 
 * access time, etc.) to aid in instrumentation, but this information can't be
 * stored in the darshan_posix_file struct because we don't want it to appear in
 * the final darshan log file.  We therefore associate a posix_file_record_ref
 * struct with each darshan_posix_file struct in order to track this information
 * (i.e., the mapping between posix_file_record_ref structs to darshan_posix_file
 * structs is one-to-one).
 *
 * NOTE: we use the 'darshan_record_ref' interface (in darshan-common) to
 * associate different types of handles with this posix_file_record_ref struct.
 * This allows us to index this struct (and the underlying file record) by using
 * either the corresponding Darshan record identifier (derived from the filename)
97 98
 * or by a generated file descriptor, for instance. Note that, while there should
 * only be a single Darshan record identifier that indexes a posix_file_record_ref,
99 100
 * there could be multiple open file descriptors that index it.
 */
101
struct posix_file_record_ref
102
{
103
    struct darshan_posix_file *file_rec;
104 105 106
    int64_t offset;
    int64_t last_byte_read;
    int64_t last_byte_written;
Shane Snyder's avatar
Shane Snyder committed
107
    enum darshan_io_type last_io_type;
108 109 110
    double last_meta_end;
    double last_read_end;
    double last_write_end;
111
    void *access_root;
112
    int access_count;
113
    void *stride_root;
114
    int stride_count;
115
    struct posix_aio_tracker* aio_list;
116
    int fs_type; /* same as darshan_fs_info->fs_type */
117 118
};

119 120 121 122
/* The posix_runtime structure maintains necessary state for storing
 * POSIX file records and for coordinating with darshan-core at 
 * shutdown time.
 */
123 124
struct posix_runtime
{
125 126 127
    void *rec_id_hash;
    void *fd_hash;
    int file_rec_count;
128 129
};

130 131 132 133 134
/* struct to track information about aio operations in flight */
struct posix_aio_tracker
{
    double tm1;
    void *aiocbp;
135
    struct posix_aio_tracker *next;
136
};
137

138 139 140
static void posix_runtime_initialize(
    void);
static struct posix_file_record_ref *posix_track_new_file_record(
141
    darshan_record_id rec_id, const char *path);
142 143 144 145
static void posix_aio_tracker_add(
    int fd, void *aiocbp);
static struct posix_aio_tracker* posix_aio_tracker_del(
    int fd, void *aiocbp);
146 147
static void posix_finalize_file_records(
    void *rec_ref_p);
148 149 150 151 152
static void posix_record_reduction_op(
    void* infile_v, void* inoutfile_v, int *len, MPI_Datatype *datatype);
static void posix_shared_record_variance(
    MPI_Comm mod_comm, struct darshan_posix_file *inrec_array,
    struct darshan_posix_file *outrec_array, int shared_rec_count);
153
static void posix_cleanup_runtime(
154
    void);
155 156

static void posix_shutdown(
157
    MPI_Comm mod_comm, darshan_record_id *shared_recs,
158
    int shared_rec_count, void **posix_buf, int *posix_buf_sz);
159 160 161 162 163 164 165

static struct posix_runtime *posix_runtime = NULL;
static pthread_mutex_t posix_runtime_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static int instrumentation_disabled = 0;
static int my_rank = -1;
static int darshan_mem_alignment = 1;

166 167 168
#define POSIX_LOCK() pthread_mutex_lock(&posix_runtime_mutex)
#define POSIX_UNLOCK() pthread_mutex_unlock(&posix_runtime_mutex)

169 170
#define POSIX_PRE_RECORD() do { \
    POSIX_LOCK(); \
171 172 173
    if(!instrumentation_disabled) { \
        if(!posix_runtime) posix_runtime_initialize(); \
        if(posix_runtime) break; \
174
    } \
175 176
    POSIX_UNLOCK(); \
    return(ret); \
177 178 179 180 181
} while(0)

#define POSIX_POST_RECORD() do { \
    POSIX_UNLOCK(); \
} while(0)
182

Philip Carns's avatar
Philip Carns committed
183
#define POSIX_RECORD_OPEN(__ret, __path, __mode, __tm1, __tm2) do { \
184
    darshan_record_id rec_id; \
185 186
    struct posix_file_record_ref *rec_ref; \
    char *newpath; \
187
    if(__ret < 0) break; \
188 189 190 191 192 193 194
    newpath = darshan_clean_file_path(__path); \
    if(!newpath) newpath = (char *)__path; \
    if(darshan_core_excluded_path(newpath)) { \
        if(newpath != __path) free(newpath); \
        break; \
    } \
    rec_id = darshan_core_gen_record_id(newpath); \
195
    rec_ref = darshan_lookup_record_ref(posix_runtime->rec_id_hash, &rec_id, sizeof(darshan_record_id)); \
196
    if(!rec_ref) rec_ref = posix_track_new_file_record(rec_id, newpath); \
197
    if(!rec_ref) { \
198 199
        if(newpath != __path) free(newpath); \
        break; \
200
    } \
201
    if(__mode) \
202 203 204 205
        rec_ref->file_rec->counters[POSIX_MODE] = __mode; \
    rec_ref->offset = 0; \
    rec_ref->last_byte_written = 0; \
    rec_ref->last_byte_read = 0; \
206
    rec_ref->file_rec->counters[POSIX_OPENS] += 1; \
207 208 209 210
    if(rec_ref->file_rec->fcounters[POSIX_F_OPEN_START_TIMESTAMP] == 0 || \
     rec_ref->file_rec->fcounters[POSIX_F_OPEN_START_TIMESTAMP] > __tm1) \
        rec_ref->file_rec->fcounters[POSIX_F_OPEN_START_TIMESTAMP] = __tm1; \
    rec_ref->file_rec->fcounters[POSIX_F_OPEN_END_TIMESTAMP] = __tm2; \
211 212
    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[POSIX_F_META_TIME], \
        __tm1, __tm2, rec_ref->last_meta_end); \
213
    darshan_add_record_ref(&(posix_runtime->fd_hash), &__ret, sizeof(int), rec_ref); \
214
    darshan_instrument_fs_data(rec_ref->fs_type, newpath, __ret); \
215
    if(newpath != __path) free(newpath); \
216 217
} while(0)

218
#define POSIX_RECORD_READ(__ret, __fd, __pread_flag, __pread_offset, __aligned, __tm1, __tm2) do { \
219
    struct posix_file_record_ref* rec_ref; \
220
    size_t stride; \
221
    int64_t this_offset; \
222
    int64_t file_alignment; \
223 224
    double __elapsed = __tm2-__tm1; \
    if(__ret < 0) break; \
225 226
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &(__fd), sizeof(int)); \
    if(!rec_ref) break; \
227
    if(__pread_flag) \
228 229
        this_offset = __pread_offset; \
    else \
230 231 232 233 234 235 236 237
        this_offset = rec_ref->offset; \
    if(this_offset > rec_ref->last_byte_read) \
        rec_ref->file_rec->counters[POSIX_SEQ_READS] += 1;  \
    if(this_offset == (rec_ref->last_byte_read + 1)) \
        rec_ref->file_rec->counters[POSIX_CONSEC_READS] += 1;  \
    if(this_offset > 0 && this_offset > rec_ref->last_byte_read \
        && rec_ref->last_byte_read != 0) \
        stride = this_offset - rec_ref->last_byte_read - 1; \
238
    else \
239
        stride = 0; \
240 241 242 243 244
    rec_ref->last_byte_read = this_offset + __ret - 1; \
    rec_ref->offset = this_offset + __ret; \
    if(rec_ref->file_rec->counters[POSIX_MAX_BYTE_READ] < (this_offset + __ret - 1)) \
        rec_ref->file_rec->counters[POSIX_MAX_BYTE_READ] = (this_offset + __ret - 1); \
    rec_ref->file_rec->counters[POSIX_BYTES_READ] += __ret; \
245
    rec_ref->file_rec->counters[POSIX_READS] += 1; \
246 247 248 249 250 251 252
    DARSHAN_BUCKET_INC(&(rec_ref->file_rec->counters[POSIX_SIZE_READ_0_100]), __ret); \
    darshan_common_val_counter(&rec_ref->access_root, &rec_ref->access_count, __ret, \
        &(rec_ref->file_rec->counters[POSIX_ACCESS1_ACCESS]), \
        &(rec_ref->file_rec->counters[POSIX_ACCESS1_COUNT])); \
    darshan_common_val_counter(&rec_ref->stride_root, &rec_ref->stride_count, stride, \
        &(rec_ref->file_rec->counters[POSIX_STRIDE1_STRIDE]), \
        &(rec_ref->file_rec->counters[POSIX_STRIDE1_COUNT])); \
253
    if(!__aligned) \
254 255
        rec_ref->file_rec->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
    file_alignment = rec_ref->file_rec->counters[POSIX_FILE_ALIGNMENT]; \
256
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
257 258 259 260
        rec_ref->file_rec->counters[POSIX_FILE_NOT_ALIGNED] += 1; \
    if(rec_ref->last_io_type == DARSHAN_IO_WRITE) \
        rec_ref->file_rec->counters[POSIX_RW_SWITCHES] += 1; \
    rec_ref->last_io_type = DARSHAN_IO_READ; \
261 262
    if(rec_ref->file_rec->fcounters[POSIX_F_READ_START_TIMESTAMP] == 0 || \
     rec_ref->file_rec->fcounters[POSIX_F_READ_START_TIMESTAMP] > __tm1) \
263 264 265 266 267 268 269
        rec_ref->file_rec->fcounters[POSIX_F_READ_START_TIMESTAMP] = __tm1; \
    rec_ref->file_rec->fcounters[POSIX_F_READ_END_TIMESTAMP] = __tm2; \
    if(rec_ref->file_rec->fcounters[POSIX_F_MAX_READ_TIME] < __elapsed) { \
        rec_ref->file_rec->fcounters[POSIX_F_MAX_READ_TIME] = __elapsed; \
        rec_ref->file_rec->counters[POSIX_MAX_READ_TIME_SIZE] = __ret; } \
    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[POSIX_F_READ_TIME], \
        __tm1, __tm2, rec_ref->last_read_end); \
270 271
} while(0)

272
#define POSIX_RECORD_WRITE(__ret, __fd, __pwrite_flag, __pwrite_offset, __aligned, __tm1, __tm2) do { \
273
    struct posix_file_record_ref* rec_ref; \
274
    size_t stride; \
275
    int64_t this_offset; \
276
    int64_t file_alignment; \
277 278
    double __elapsed = __tm2-__tm1; \
    if(__ret < 0) break; \
279 280
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &__fd, sizeof(int)); \
    if(!rec_ref) break; \
281
    if(__pwrite_flag) \
282 283
        this_offset = __pwrite_offset; \
    else \
284 285 286 287 288 289 290 291
        this_offset = rec_ref->offset; \
    if(this_offset > rec_ref->last_byte_written) \
        rec_ref->file_rec->counters[POSIX_SEQ_WRITES] += 1; \
    if(this_offset == (rec_ref->last_byte_written + 1)) \
        rec_ref->file_rec->counters[POSIX_CONSEC_WRITES] += 1; \
    if(this_offset > 0 && this_offset > rec_ref->last_byte_written \
        && rec_ref->last_byte_written != 0) \
        stride = this_offset - rec_ref->last_byte_written - 1; \
292
    else \
293
        stride = 0; \
294 295 296 297 298
    rec_ref->last_byte_written = this_offset + __ret - 1; \
    rec_ref->offset = this_offset + __ret; \
    if(rec_ref->file_rec->counters[POSIX_MAX_BYTE_WRITTEN] < (this_offset + __ret - 1)) \
        rec_ref->file_rec->counters[POSIX_MAX_BYTE_WRITTEN] = (this_offset + __ret - 1); \
    rec_ref->file_rec->counters[POSIX_BYTES_WRITTEN] += __ret; \
299
    rec_ref->file_rec->counters[POSIX_WRITES] += 1; \
300 301 302 303 304 305 306
    DARSHAN_BUCKET_INC(&(rec_ref->file_rec->counters[POSIX_SIZE_WRITE_0_100]), __ret); \
    darshan_common_val_counter(&rec_ref->access_root, &rec_ref->access_count, __ret, \
        &(rec_ref->file_rec->counters[POSIX_ACCESS1_ACCESS]), \
        &(rec_ref->file_rec->counters[POSIX_ACCESS1_COUNT])); \
    darshan_common_val_counter(&rec_ref->stride_root, &rec_ref->stride_count, stride, \
        &(rec_ref->file_rec->counters[POSIX_STRIDE1_STRIDE]), \
        &(rec_ref->file_rec->counters[POSIX_STRIDE1_COUNT])); \
307
    if(!__aligned) \
308 309
        rec_ref->file_rec->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
    file_alignment = rec_ref->file_rec->counters[POSIX_FILE_ALIGNMENT]; \
310
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
311 312 313 314
        rec_ref->file_rec->counters[POSIX_FILE_NOT_ALIGNED] += 1; \
    if(rec_ref->last_io_type == DARSHAN_IO_READ) \
        rec_ref->file_rec->counters[POSIX_RW_SWITCHES] += 1; \
    rec_ref->last_io_type = DARSHAN_IO_WRITE; \
315 316
    if(rec_ref->file_rec->fcounters[POSIX_F_WRITE_START_TIMESTAMP] == 0 || \
     rec_ref->file_rec->fcounters[POSIX_F_WRITE_START_TIMESTAMP] > __tm1) \
317 318 319 320 321 322 323
        rec_ref->file_rec->fcounters[POSIX_F_WRITE_START_TIMESTAMP] = __tm1; \
    rec_ref->file_rec->fcounters[POSIX_F_WRITE_END_TIMESTAMP] = __tm2; \
    if(rec_ref->file_rec->fcounters[POSIX_F_MAX_WRITE_TIME] < __elapsed) { \
        rec_ref->file_rec->fcounters[POSIX_F_MAX_WRITE_TIME] = __elapsed; \
        rec_ref->file_rec->counters[POSIX_MAX_WRITE_TIME_SIZE] = __ret; } \
    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[POSIX_F_WRITE_TIME], \
        __tm1, __tm2, rec_ref->last_write_end); \
324
} while(0)
325

326
#define POSIX_LOOKUP_RECORD_STAT(__path, __statbuf, __tm1, __tm2) do { \
327
    darshan_record_id rec_id; \
328 329 330 331 332 333
    struct posix_file_record_ref* rec_ref; \
    char *newpath = darshan_clean_file_path(__path); \
    if(!newpath) newpath = (char *)__path; \
    if(darshan_core_excluded_path(newpath)) { \
        if(newpath != __path) free(newpath); \
        break; \
334
    } \
335 336
    rec_id = darshan_core_gen_record_id(newpath); \
    rec_ref = darshan_lookup_record_ref(posix_runtime->rec_id_hash, &rec_id, sizeof(darshan_record_id)); \
337
    if(!rec_ref) rec_ref = posix_track_new_file_record(rec_id, newpath); \
338
    if(newpath != __path) free(newpath); \
339 340
    if(rec_ref) { \
        POSIX_RECORD_STAT(rec_ref, __statbuf, __tm1, __tm2); \
341 342 343
    } \
} while(0)

344 345 346 347
#define POSIX_RECORD_STAT(__rec_ref, __statbuf, __tm1, __tm2) do { \
    (__rec_ref)->file_rec->counters[POSIX_STATS] += 1; \
    DARSHAN_TIMER_INC_NO_OVERLAP((__rec_ref)->file_rec->fcounters[POSIX_F_META_TIME], \
        __tm1, __tm2, (__rec_ref)->last_meta_end); \
348 349
} while(0)

350

351 352 353 354
/**********************************************************
 *      Wrappers for POSIX I/O functions of interest      * 
 **********************************************************/

355
int DARSHAN_DECL(open)(const char *path, int flags, ...)
356 357 358 359 360
{
    int mode = 0;
    int ret;
    double tm1, tm2;

361 362
    MAP_OR_FAIL(open);

363
    if(flags & O_CREAT) 
364 365 366 367 368 369
    {
        va_list arg;
        va_start(arg, flags);
        mode = va_arg(arg, int);
        va_end(arg);

370
        tm1 = darshan_core_wtime();
371
        ret = __real_open(path, flags, mode);
372
        tm2 = darshan_core_wtime();
373 374 375
    }
    else
    {
376
        tm1 = darshan_core_wtime();
377
        ret = __real_open(path, flags);
378
        tm2 = darshan_core_wtime();
379 380
    }

381
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
382
    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
383
    POSIX_POST_RECORD();
384 385 386 387

    return(ret);
}

Shane Snyder's avatar
Shane Snyder committed
388 389 390 391 392 393
int DARSHAN_DECL(open64)(const char *path, int flags, ...)
{
    int mode = 0;
    int ret;
    double tm1, tm2;

394
    MAP_OR_FAIL(open64);
Shane Snyder's avatar
Shane Snyder committed
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413

    if(flags & O_CREAT)
    {
        va_list arg;
        va_start(arg, flags);
        mode = va_arg(arg, int);
        va_end(arg);

        tm1 = darshan_core_wtime();
        ret = __real_open64(path, flags, mode);
        tm2 = darshan_core_wtime();
    }
    else
    {
        tm1 = darshan_core_wtime();
        ret = __real_open64(path, flags);
        tm2 = darshan_core_wtime();
    }

414
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
415
    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
416
    POSIX_POST_RECORD();
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431

    return(ret);
}

int DARSHAN_DECL(creat)(const char* path, mode_t mode)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(creat);

    tm1 = darshan_core_wtime();
    ret = __real_creat(path, mode);
    tm2 = darshan_core_wtime();

432
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
433
    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
434
    POSIX_POST_RECORD();
435 436 437 438 439 440 441 442 443 444

    return(ret);
}

int DARSHAN_DECL(creat64)(const char* path, mode_t mode)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(creat64);
Shane Snyder's avatar
Shane Snyder committed
445

446 447 448 449
    tm1 = darshan_core_wtime();
    ret = __real_creat64(path, mode);
    tm2 = darshan_core_wtime();

450
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
451
    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
452
    POSIX_POST_RECORD();
453 454 455 456

    return(ret);
}

457 458 459 460 461 462 463 464 465 466 467
int DARSHAN_DECL(mkstemp)(char* template)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(mkstemp);

    tm1 = darshan_core_wtime();
    ret = __real_mkstemp(template);
    tm2 = darshan_core_wtime();

468
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
469
    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
470
    POSIX_POST_RECORD();
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485

    return(ret);
}

int DARSHAN_DECL(mkostemp)(char* template, int flags)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(mkostemp);

    tm1 = darshan_core_wtime();
    ret = __real_mkostemp(template, flags);
    tm2 = darshan_core_wtime();

486
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
487
    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
488
    POSIX_POST_RECORD();
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503

    return(ret);
}

int DARSHAN_DECL(mkstemps)(char* template, int suffixlen)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(mkstemps);

    tm1 = darshan_core_wtime();
    ret = __real_mkstemps(template, suffixlen);
    tm2 = darshan_core_wtime();

504
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
505
    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
506
    POSIX_POST_RECORD();
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521

    return(ret);
}

int DARSHAN_DECL(mkostemps)(char* template, int suffixlen, int flags)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(mkostemps);

    tm1 = darshan_core_wtime();
    ret = __real_mkostemps(template, suffixlen, flags);
    tm2 = darshan_core_wtime();

522
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
523
    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
524
    POSIX_POST_RECORD();
525 526 527 528

    return(ret);
}

529 530 531 532 533 534
ssize_t DARSHAN_DECL(read)(int fd, void *buf, size_t count)
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

Shane Snyder's avatar
Shane Snyder committed
535
    MAP_OR_FAIL(read);
536

537
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
538 539 540 541 542

    tm1 = darshan_core_wtime();
    ret = __real_read(fd, buf, count);
    tm2 = darshan_core_wtime();

543
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
544
    POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, tm1, tm2);
545
    POSIX_POST_RECORD();
546 547 548 549 550 551 552 553 554 555 556 557

    return(ret);
}

ssize_t DARSHAN_DECL(write)(int fd, const void *buf, size_t count)
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

    MAP_OR_FAIL(write);

558
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
559 560 561 562 563

    tm1 = darshan_core_wtime();
    ret = __real_write(fd, buf, count);
    tm2 = darshan_core_wtime();

564
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
565
    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, tm1, tm2);
566
    POSIX_POST_RECORD();
567 568 569 570 571 572 573 574 575 576 577 578

    return(ret);
}

ssize_t DARSHAN_DECL(pread)(int fd, void *buf, size_t count, off_t offset)
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

    MAP_OR_FAIL(pread);

579
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
580 581 582 583 584

    tm1 = darshan_core_wtime();
    ret = __real_pread(fd, buf, count, offset);
    tm2 = darshan_core_wtime();

585
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
586
    POSIX_RECORD_READ(ret, fd, 1, offset, aligned_flag, tm1, tm2);
587
    POSIX_POST_RECORD();
588 589 590 591 592 593 594 595 596 597 598 599

    return(ret);
}

ssize_t DARSHAN_DECL(pwrite)(int fd, const void *buf, size_t count, off_t offset)
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

    MAP_OR_FAIL(pwrite);

600
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
601 602 603 604 605

    tm1 = darshan_core_wtime();
    ret = __real_pwrite(fd, buf, count, offset);
    tm2 = darshan_core_wtime();

606
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
607
    POSIX_RECORD_WRITE(ret, fd, 1, offset, aligned_flag, tm1, tm2);
608
    POSIX_POST_RECORD();
609 610 611 612 613 614 615 616 617 618 619 620

    return(ret);
}

ssize_t DARSHAN_DECL(pread64)(int fd, void *buf, size_t count, off64_t offset)
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

    MAP_OR_FAIL(pread64);

621
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
622 623 624 625 626

    tm1 = darshan_core_wtime();
    ret = __real_pread64(fd, buf, count, offset);
    tm2 = darshan_core_wtime();

627
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
628
    POSIX_RECORD_READ(ret, fd, 1, offset, aligned_flag, tm1, tm2);
629
    POSIX_POST_RECORD();
630 631 632 633 634 635 636 637 638 639 640 641

    return(ret);
}

ssize_t DARSHAN_DECL(pwrite64)(int fd, const void *buf, size_t count, off64_t offset)
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

    MAP_OR_FAIL(pwrite64);

642
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
643 644 645 646 647

    tm1 = darshan_core_wtime();
    ret = __real_pwrite64(fd, buf, count, offset);
    tm2 = darshan_core_wtime();

648
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
649
    POSIX_RECORD_WRITE(ret, fd, 1, offset, aligned_flag, tm1, tm2);
650
    POSIX_POST_RECORD();
651 652 653 654 655 656 657

    return(ret);
}

ssize_t DARSHAN_DECL(readv)(int fd, const struct iovec *iov, int iovcnt)
{
    ssize_t ret;
658
    int aligned_flag = 1;
659 660 661 662
    int i;
    double tm1, tm2;

    MAP_OR_FAIL(readv);
663

664 665 666 667
    for(i=0; i<iovcnt; i++)
    {
        if(((unsigned long)iov[i].iov_base % darshan_mem_alignment) != 0)
            aligned_flag = 0;
668
    }
669 670 671 672 673

    tm1 = darshan_core_wtime();
    ret = __real_readv(fd, iov, iovcnt);
    tm2 = darshan_core_wtime();

674
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
675
    POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, tm1, tm2);
676
    POSIX_POST_RECORD();
677 678 679 680 681 682 683

    return(ret);
}

ssize_t DARSHAN_DECL(writev)(int fd, const struct iovec *iov, int iovcnt)
{
    ssize_t ret;
684
    int aligned_flag = 1;
685 686 687 688
    int i;
    double tm1, tm2;

    MAP_OR_FAIL(writev);
689

690 691 692 693
    for(i=0; i<iovcnt; i++)
    {
        if(((unsigned long)iov[i].iov_base % darshan_mem_alignment) != 0)
            aligned_flag = 0;
694
    }
695 696 697 698 699

    tm1 = darshan_core_wtime();
    ret = __real_writev(fd, iov, iovcnt);
    tm2 = darshan_core_wtime();

700
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
701
    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, tm1, tm2);
702
    POSIX_POST_RECORD();
703 704 705 706 707 708 709

    return(ret);
}

off_t DARSHAN_DECL(lseek)(int fd, off_t offset, int whence)
{
    off_t ret;
710
    struct posix_file_record_ref *rec_ref;
711 712 713 714 715 716 717 718 719 720
    double tm1, tm2;

    MAP_OR_FAIL(lseek);

    tm1 = darshan_core_wtime();
    ret = __real_lseek(fd, offset, whence);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
721
        POSIX_PRE_RECORD();
722 723
        rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
        if(rec_ref)
724
        {
725
            rec_ref->offset = ret;
726
            DARSHAN_TIMER_INC_NO_OVERLAP(
727 728 729
                rec_ref->file_rec->fcounters[POSIX_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[POSIX_SEEKS] += 1;
730
        }
731
        POSIX_POST_RECORD();
732 733 734 735 736 737 738 739
    }

    return(ret);
}

off_t DARSHAN_DECL(lseek64)(int fd, off_t offset, int whence)
{
    off_t ret;
740
    struct posix_file_record_ref *rec_ref;
741 742 743 744 745 746 747 748 749 750
    double tm1, tm2;

    MAP_OR_FAIL(lseek64);

    tm1 = darshan_core_wtime();
    ret = __real_lseek64(fd, offset, whence);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
751
        POSIX_PRE_RECORD();
752 753
        rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
        if(rec_ref)
754
        {
755
            rec_ref->offset = ret;
756
            DARSHAN_TIMER_INC_NO_OVERLAP(
757 758 759
                rec_ref->file_rec->fcounters[POSIX_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[POSIX_SEEKS] += 1;
760
        }
761
        POSIX_POST_RECORD();
762 763 764 765 766
    }

    return(ret);
}

767 768 769 770 771 772 773 774 775 776 777 778 779 780
int DARSHAN_DECL(__xstat)(int vers, const char *path, struct stat *buf)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(__xstat);

    tm1 = darshan_core_wtime();
    ret = __real___xstat(vers, path, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

781
    POSIX_PRE_RECORD();
782
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
783
    POSIX_POST_RECORD();
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801

    return(ret);
}

int DARSHAN_DECL(__xstat64)(int vers, const char *path, struct stat64 *buf)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(__xstat64);

    tm1 = darshan_core_wtime();
    ret = __real___xstat64(vers, path, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

802
    POSIX_PRE_RECORD();
803
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
804
    POSIX_POST_RECORD();
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822

    return(ret);
}

int DARSHAN_DECL(__lxstat)(int vers, const char *path, struct stat *buf)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(__lxstat);

    tm1 = darshan_core_wtime();
    ret = __real___lxstat(vers, path, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

823
    POSIX_PRE_RECORD();
824
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
825
    POSIX_POST_RECORD();
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843

    return(ret);
}

int DARSHAN_DECL(__lxstat64)(int vers, const char *path, struct stat64 *buf)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(__lxstat64);

    tm1 = darshan_core_wtime();
    ret = __real___lxstat64(vers, path, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

844
    POSIX_PRE_RECORD();
845
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
846
    POSIX_POST_RECORD();
847 848 849 850 851 852 853

    return(ret);
}

int DARSHAN_DECL(__fxstat)(int vers, int fd, struct stat *buf)
{
    int ret;
854
    struct posix_file_record_ref *rec_ref;
855 856 857 858 859 860 861 862 863 864 865
    double tm1, tm2;

    MAP_OR_FAIL(__fxstat);

    tm1 = darshan_core_wtime();
    ret = __real___fxstat(vers, fd, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

866
    POSIX_PRE_RECORD();
867 868
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
    if(rec_ref)
869
    {
870
        POSIX_RECORD_STAT(rec_ref, buf, tm1, tm2);
871
    }
872
    POSIX_POST_RECORD();
873 874 875 876 877 878 879

    return(ret);
}

int DARSHAN_DECL(__fxstat64)(int vers, int fd, struct stat64 *buf)
{
    int ret;
880
    struct posix_file_record_ref *rec_ref;
881 882 883 884 885 886 887 888 889 890 891
    double tm1, tm2;

    MAP_OR_FAIL(__fxstat64);

    tm1 = darshan_core_wtime();
    ret = __real___fxstat64(vers, fd, buf);
    tm2 = darshan_core_wtime();

    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

892
    POSIX_PRE_RECORD();
893 894
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
    if(rec_ref)
895
    {
896
        POSIX_RECORD_STAT(rec_ref, buf, tm1, tm2);
897
    }
898
    POSIX_POST_RECORD();
899 900 901 902

    return(ret);
}

Shane Snyder's avatar
Shane Snyder committed
903 904 905 906
void* DARSHAN_DECL(mmap)(void *addr, size_t length, int prot, int flags,
    int fd, off_t offset)
{
    void* ret;
907
    struct posix_file_record_ref *rec_ref;
Shane Snyder's avatar
Shane Snyder committed
908 909 910 911 912 913 914

    MAP_OR_FAIL(mmap);

    ret = __real_mmap(addr, length, prot, flags, fd, offset);
    if(ret == MAP_FAILED)
        return(ret);

915
    POSIX_PRE_RECORD();
916 917
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
    if(rec_ref)
Shane Snyder's avatar
Shane Snyder committed
918
    {
919
        rec_ref->file_rec->counters[POSIX_MMAPS] += 1;
Shane Snyder's avatar
Shane Snyder committed
920
    }
921
    POSIX_POST_RECORD();
Shane Snyder's avatar
Shane Snyder committed
922 923 924 925 926 927 928 929

    return(ret);
}

void* DARSHAN_DECL(mmap64)(void *addr, size_t length, int prot, int flags,
    int fd, off64_t offset)
{
    void* ret;
930
    struct posix_file_record_ref *rec_ref;
Shane Snyder's avatar
Shane Snyder committed
931 932 933 934 935 936 937

    MAP_OR_FAIL(mmap64);

    ret = __real_mmap64(addr, length, prot, flags, fd, offset);
    if(ret == MAP_FAILED)
        return(ret);

938
    POSIX_PRE_RECORD();
939 940
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
    if(rec_ref)
Shane Snyder's avatar
Shane Snyder committed
941
    {
942
        rec_ref->file_rec->counters[POSIX_MMAPS] += 1;
Shane Snyder's avatar
Shane Snyder committed
943
    }
944
    POSIX_POST_RECORD();
Shane Snyder's avatar
Shane Snyder committed
945 946 947 948

    return(ret);
}

949 950 951
int DARSHAN_DECL(fsync)(int fd)
{
    int ret;
952
    struct posix_file_record_ref *rec_ref;
953 954 955 956 957 958 959 960 961 962 963
    double tm1, tm2;

    MAP_OR_FAIL(fsync);

    tm1 = darshan_core_wtime();
    ret = __real_fsync(fd);
    tm2 = darshan_core_wtime();

    if(ret < 0)
        return(ret);

964
    POSIX_PRE_RECORD();
965 966
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
    if(rec_ref)
967
    {
968
        DARSHAN_TIMER_INC_NO_OVERLAP(
969 970 971
            rec_ref->file_rec->fcounters[POSIX_F_WRITE_TIME],
            tm1, tm2, rec_ref->last_write_end);
        rec_ref->file_rec->counters[POSIX_FSYNCS] += 1;
972
    }
973
    POSIX_POST_RECORD();
974 975 976 977 978 979 980

    return(ret);
}

int DARSHAN_DECL(fdatasync)(int fd)
{
    int ret;
981
    struct posix_file_record_ref *rec_ref;
982 983 984 985 986 987 988 989 990 991 992
    double tm1, tm2;

    MAP_OR_FAIL(fdatasync);

    tm1 = darshan_core_wtime();
    ret = __real_fdatasync(fd);
    tm2 = darshan_core_wtime();

    if(ret < 0)
        return(ret);

993
    POSIX_PRE_RECORD();
994 995
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
    if(rec_ref)
996
    {
997
        DARSHAN_TIMER_INC_NO_OVERLAP(
998 999 1000
            rec_ref->file_rec->fcounters[POSIX_F_WRITE_TIME],
            tm1, tm2, rec_ref->last_write_end);
        rec_ref->file_rec->counters[POSIX_FDSYNCS] += 1;
1001
    }
1002
    POSIX_POST_RECORD();
1003 1004 1005 1006

    return(ret);
}

1007 1008 1009
int DARSHAN_DECL(close)(int fd)
{
    int ret;
1010 1011
    struct posix_file_record_ref *rec_ref;
    double tm1, tm2;
1012 1013 1014 1015 1016 1017 1018

    MAP_OR_FAIL(close);

    tm1 = darshan_core_wtime();
    ret = __real_close(fd);
    tm2 = darshan_core_wtime();