darshan-posix.c 65.5 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"
Shane Snyder's avatar
Shane Snyder committed
32
#include "darshan-dxt.h"
33

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

41

42 43
DARSHAN_FORWARD_DECL(open, int, (const char *path, int flags, ...));
DARSHAN_FORWARD_DECL(open64, int, (const char *path, int flags, ...));
44
DARSHAN_FORWARD_DECL(__open_2, int, (const char *path, int oflag));
45 46
DARSHAN_FORWARD_DECL(creat, int, (const char* path, mode_t mode));
DARSHAN_FORWARD_DECL(creat64, int, (const char* path, mode_t mode));
47 48 49
DARSHAN_FORWARD_DECL(dup, int, (int oldfd));
DARSHAN_FORWARD_DECL(dup2, int, (int oldfd, int newfd));
DARSHAN_FORWARD_DECL(dup3, int, (int oldfd, int newfd, int flags));
50
DARSHAN_FORWARD_DECL(fileno, int, (FILE *stream));
51 52 53 54
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));
55 56 57 58 59 60 61 62
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));
63 64
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));
65 66 67 68 69 70
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));
71
#ifdef DARSHAN_WRAP_MMAP
Shane Snyder's avatar
Shane Snyder committed
72 73
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));
74
#endif /* DARSHAN_WRAP_MMAP */
75 76
DARSHAN_FORWARD_DECL(fsync, int, (int fd));
DARSHAN_FORWARD_DECL(fdatasync, int, (int fd));
77
DARSHAN_FORWARD_DECL(close, int, (int fd));
78 79 80 81 82 83 84 85
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));
86
DARSHAN_FORWARD_DECL(rename, int, (const char *oldpath, const char *newpath));
87

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/* 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)
106 107
 * 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,
108 109
 * there could be multiple open file descriptors that index it.
 */
110
struct posix_file_record_ref
111
{
112
    struct darshan_posix_file *file_rec;
113 114 115
    int64_t offset;
    int64_t last_byte_read;
    int64_t last_byte_written;
Shane Snyder's avatar
Shane Snyder committed
116
    enum darshan_io_type last_io_type;
117 118 119
    double last_meta_end;
    double last_read_end;
    double last_write_end;
120
    void *access_root;
121
    int access_count;
122
    void *stride_root;
123
    int stride_count;
124
    struct posix_aio_tracker* aio_list;
125
    int fs_type; /* same as darshan_fs_info->fs_type */
126 127
};

128 129 130 131
/* The posix_runtime structure maintains necessary state for storing
 * POSIX file records and for coordinating with darshan-core at 
 * shutdown time.
 */
132 133
struct posix_runtime
{
134 135 136
    void *rec_id_hash;
    void *fd_hash;
    int file_rec_count;
137 138
};

139 140 141 142 143
/* struct to track information about aio operations in flight */
struct posix_aio_tracker
{
    double tm1;
    void *aiocbp;
144
    struct posix_aio_tracker *next;
145
};
146

147 148 149
static void posix_runtime_initialize(
    void);
static struct posix_file_record_ref *posix_track_new_file_record(
150
    darshan_record_id rec_id, const char *path);
151 152 153 154
static void posix_aio_tracker_add(
    int fd, void *aiocbp);
static struct posix_aio_tracker* posix_aio_tracker_del(
    int fd, void *aiocbp);
155
static void posix_finalize_file_records(
156
    void *rec_ref_p, void *user_ptr);
157 158
static void posix_cleanup_runtime(
    void);
159
#ifdef HAVE_MPI
160 161 162 163 164
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);
165 166 167 168
static void posix_mpi_redux(
    void *posix_buf, MPI_Comm mod_comm,
    darshan_record_id *shared_recs, int shared_rec_count);
#endif
169
static void posix_shutdown(
170
    void **posix_buf, int *posix_buf_sz);
171

172 173
/* extern function def for querying record name from a STDIO stream */
extern char *darshan_stdio_lookup_record_name(FILE *stream);
174

175 176 177 178 179
static struct posix_runtime *posix_runtime = NULL;
static pthread_mutex_t posix_runtime_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static int my_rank = -1;
static int darshan_mem_alignment = 1;

180 181 182
#define POSIX_LOCK() pthread_mutex_lock(&posix_runtime_mutex)
#define POSIX_UNLOCK() pthread_mutex_unlock(&posix_runtime_mutex)

183 184
#define POSIX_PRE_RECORD() do { \
    POSIX_LOCK(); \
185
    if(!darshan_core_disabled_instrumentation()) { \
186 187 188
        if(!posix_runtime) { \
            posix_runtime_initialize(); \
        } \
189
        if(posix_runtime) break; \
190
    } \
191 192
    POSIX_UNLOCK(); \
    return(ret); \
193 194 195 196 197
} while(0)

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

199 200 201 202
#define POSIX_RECORD_OPEN(__ret, __path, __mode, __tm1, __tm2) do { \
    darshan_record_id __rec_id; \
    struct posix_file_record_ref *__rec_ref; \
    char *__newpath; \
203
    if(__ret < 0) break; \
204 205 206 207
    __newpath = darshan_clean_file_path(__path); \
    if(!__newpath) __newpath = (char *)__path; \
    if(darshan_core_excluded_path(__newpath)) { \
        if(__newpath != __path) free(__newpath); \
208 209
        break; \
    } \
210 211 212 213 214
    __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)); \
    if(!__rec_ref) __rec_ref = posix_track_new_file_record(__rec_id, __newpath); \
    if(!__rec_ref) { \
        if(__newpath != __path) free(__newpath); \
215
        break; \
216
    } \
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    _POSIX_RECORD_OPEN(__ret, __rec_ref, __mode, __tm1, __tm2, 1, -1); \
    darshan_instrument_fs_data(__rec_ref->fs_type, __newpath, __ret); \
    if(__newpath != __path) free(__newpath); \
} while(0)

#define POSIX_RECORD_REFOPEN(__ret, __rec_ref, __tm1, __tm2, __ref_counter) do { \
    if(__ret < 0 || !__rec_ref) break; \
    _POSIX_RECORD_OPEN(__ret, __rec_ref, 0, __tm1, __tm2, 0, __ref_counter); \
} while(0)

#define _POSIX_RECORD_OPEN(__ret, __rec_ref, __mode, __tm1, __tm2, __reset_flag, __ref_counter) do { \
    if(__mode) __rec_ref->file_rec->counters[POSIX_MODE] = __mode; \
    if(__reset_flag) { \
        __rec_ref->offset = 0; \
        __rec_ref->last_byte_written = 0; \
        __rec_ref->last_byte_read = 0; \
    } \
    __rec_ref->file_rec->counters[POSIX_OPENS] += 1; \
    if(__ref_counter >= 0) __rec_ref->file_rec->counters[__ref_counter] += 1; \
    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; \
    DARSHAN_TIMER_INC_NO_OVERLAP(__rec_ref->file_rec->fcounters[POSIX_F_META_TIME], \
        __tm1, __tm2, __rec_ref->last_meta_end); \
    darshan_add_record_ref(&(posix_runtime->fd_hash), &__ret, sizeof(int), __rec_ref); \
243 244
} while(0)

245
#define POSIX_RECORD_READ(__ret, __fd, __pread_flag, __pread_offset, __aligned, __tm1, __tm2) do { \
246
    struct posix_file_record_ref* rec_ref; \
247
    size_t stride; \
248
    int64_t this_offset; \
249
    int64_t file_alignment; \
250 251
    double __elapsed = __tm2-__tm1; \
    if(__ret < 0) break; \
252 253
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &(__fd), sizeof(int)); \
    if(!rec_ref) break; \
254
    if(__pread_flag) \
255 256
        this_offset = __pread_offset; \
    else \
257
        this_offset = rec_ref->offset; \
258
    /* DXT to record detailed read tracing information */ \
Shane Snyder's avatar
Shane Snyder committed
259
    dxt_posix_read(rec_ref->file_rec->base_rec.id, this_offset, __ret, __tm1, __tm2); \
260 261 262 263 264 265 266
    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; \
267
    else \
268
        stride = 0; \
269 270 271 272 273
    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; \
274
    rec_ref->file_rec->counters[POSIX_READS] += 1; \
275 276 277 278 279 280 281
    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])); \
282
    if(!__aligned) \
283 284
        rec_ref->file_rec->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
    file_alignment = rec_ref->file_rec->counters[POSIX_FILE_ALIGNMENT]; \
285
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
286 287 288 289
        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; \
290 291
    if(rec_ref->file_rec->fcounters[POSIX_F_READ_START_TIMESTAMP] == 0 || \
     rec_ref->file_rec->fcounters[POSIX_F_READ_START_TIMESTAMP] > __tm1) \
292 293 294 295 296 297 298
        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); \
299 300
} while(0)

301
#define POSIX_RECORD_WRITE(__ret, __fd, __pwrite_flag, __pwrite_offset, __aligned, __tm1, __tm2) do { \
302
    struct posix_file_record_ref* rec_ref; \
303
    size_t stride; \
304
    int64_t this_offset; \
305
    int64_t file_alignment; \
306 307
    double __elapsed = __tm2-__tm1; \
    if(__ret < 0) break; \
308 309
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &__fd, sizeof(int)); \
    if(!rec_ref) break; \
310
    if(__pwrite_flag) \
311 312
        this_offset = __pwrite_offset; \
    else \
313
        this_offset = rec_ref->offset; \
314
    /* DXT to record detailed write tracing information */ \
Shane Snyder's avatar
Shane Snyder committed
315
    dxt_posix_write(rec_ref->file_rec->base_rec.id, this_offset, __ret, __tm1, __tm2); \
316 317 318 319 320 321 322
    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; \
323
    else \
324
        stride = 0; \
325 326 327 328 329
    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; \
330
    rec_ref->file_rec->counters[POSIX_WRITES] += 1; \
331 332 333 334 335 336 337
    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])); \
338
    if(!__aligned) \
339 340
        rec_ref->file_rec->counters[POSIX_MEM_NOT_ALIGNED] += 1; \
    file_alignment = rec_ref->file_rec->counters[POSIX_FILE_ALIGNMENT]; \
341
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
342 343 344 345
        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; \
346 347
    if(rec_ref->file_rec->fcounters[POSIX_F_WRITE_START_TIMESTAMP] == 0 || \
     rec_ref->file_rec->fcounters[POSIX_F_WRITE_START_TIMESTAMP] > __tm1) \
348 349 350 351 352 353 354
        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); \
355
} while(0)
356

357
#define POSIX_LOOKUP_RECORD_STAT(__path, __statbuf, __tm1, __tm2) do { \
358
    darshan_record_id rec_id; \
359 360 361 362 363 364
    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; \
365
    } \
366 367
    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)); \
368
    if(!rec_ref) rec_ref = posix_track_new_file_record(rec_id, newpath); \
369
    if(newpath != __path) free(newpath); \
370 371
    if(rec_ref) { \
        POSIX_RECORD_STAT(rec_ref, __statbuf, __tm1, __tm2); \
372 373 374
    } \
} while(0)

375 376 377 378
#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); \
379 380
} while(0)

381

382 383 384 385
/**********************************************************
 *      Wrappers for POSIX I/O functions of interest      * 
 **********************************************************/

386
int DARSHAN_DECL(open)(const char *path, int flags, ...)
387 388 389 390 391
{
    int mode = 0;
    int ret;
    double tm1, tm2;

392 393
    MAP_OR_FAIL(open);

394
    if(flags & O_CREAT) 
395 396 397 398 399 400
    {
        va_list arg;
        va_start(arg, flags);
        mode = va_arg(arg, int);
        va_end(arg);

401
        tm1 = darshan_core_wtime();
402
        ret = __real_open(path, flags, mode);
403
        tm2 = darshan_core_wtime();
404 405 406
    }
    else
    {
407
        tm1 = darshan_core_wtime();
408
        ret = __real_open(path, flags);
409
        tm2 = darshan_core_wtime();
410 411
    }

412
    POSIX_PRE_RECORD();
413
    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
414
    POSIX_POST_RECORD();
415 416 417 418

    return(ret);
}

419 420 421 422 423 424 425 426 427 428 429 430
int DARSHAN_DECL(__open_2)(const char *path, int oflag)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(__open_2);

    tm1 = darshan_core_wtime();
    ret = __real___open_2(path, oflag);
    tm2 = darshan_core_wtime();

    POSIX_PRE_RECORD();
431
    POSIX_RECORD_OPEN(ret, path, 0, tm1, tm2);
432 433 434 435 436
    POSIX_POST_RECORD();

    return(ret);
}

Shane Snyder's avatar
Shane Snyder committed
437 438 439 440 441 442
int DARSHAN_DECL(open64)(const char *path, int flags, ...)
{
    int mode = 0;
    int ret;
    double tm1, tm2;

443
    MAP_OR_FAIL(open64);
Shane Snyder's avatar
Shane Snyder committed
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462

    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();
    }

463
    POSIX_PRE_RECORD();
464
    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
465
    POSIX_POST_RECORD();
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480

    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();

481
    POSIX_PRE_RECORD();
482
    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
483
    POSIX_POST_RECORD();
484 485 486 487 488 489 490 491 492 493

    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
494

495 496 497 498
    tm1 = darshan_core_wtime();
    ret = __real_creat64(path, mode);
    tm2 = darshan_core_wtime();

499
    POSIX_PRE_RECORD();
500
    POSIX_RECORD_OPEN(ret, path, mode, tm1, tm2);
501
    POSIX_POST_RECORD();
502 503 504 505

    return(ret);
}

506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
int DARSHAN_DECL(dup)(int oldfd)
{
    int ret;
    struct posix_file_record_ref *rec_ref;
    double tm1, tm2;

    MAP_OR_FAIL(dup);

    tm1 = darshan_core_wtime();
    ret = __real_dup(oldfd);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
        POSIX_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash,
            &oldfd, sizeof(oldfd));
        POSIX_RECORD_REFOPEN(ret, rec_ref, tm1, tm2, POSIX_DUPS);
        POSIX_POST_RECORD();
    }

    return(ret);
}

int DARSHAN_DECL(dup2)(int oldfd, int newfd)
{
    int ret;
    struct posix_file_record_ref *rec_ref;
    double tm1, tm2;

    MAP_OR_FAIL(dup2);

    tm1 = darshan_core_wtime();
    ret = __real_dup2(oldfd, newfd);
    tm2 = darshan_core_wtime();

    if(ret >=0)
    {
        POSIX_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash,
            &oldfd, sizeof(oldfd));
        POSIX_RECORD_REFOPEN(ret, rec_ref, tm1, tm2, POSIX_DUPS);
        POSIX_POST_RECORD();
    }

    return(ret);
}

int DARSHAN_DECL(dup3)(int oldfd, int newfd, int flags)
{
    int ret;
    struct posix_file_record_ref *rec_ref;
    double tm1, tm2;

    MAP_OR_FAIL(dup3);

    tm1 = darshan_core_wtime();
    ret = __real_dup3(oldfd, newfd, flags);
    tm2 = darshan_core_wtime();

    if(ret >=0)
    {
        POSIX_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash,
            &oldfd, sizeof(oldfd));
        POSIX_RECORD_REFOPEN(ret, rec_ref, tm1, tm2, POSIX_DUPS);
        POSIX_POST_RECORD();
    }

    return(ret);
}

578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
int DARSHAN_DECL(fileno)(FILE *stream)
{
    int ret;
    double tm1, tm2;
    darshan_record_id rec_id;
    struct posix_file_record_ref *rec_ref;

    MAP_OR_FAIL(fileno);

    tm1 = darshan_core_wtime();
    ret = __real_fileno(stream);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
        char *rec_name = darshan_stdio_lookup_record_name(stream);
        if(rec_name)
        {
            rec_id = darshan_core_gen_record_id(rec_name);
597 598

            POSIX_PRE_RECORD();
599 600 601 602 603 604 605 606 607 608 609 610
            rec_ref = darshan_lookup_record_ref(posix_runtime->rec_id_hash,
                &rec_id, sizeof(darshan_record_id));
            if(!rec_ref)
                rec_ref = posix_track_new_file_record(rec_id, rec_name);
            POSIX_RECORD_REFOPEN(ret, rec_ref, tm1, tm2, POSIX_FILENOS);
            POSIX_POST_RECORD();
        }
    }

    return(ret);
}

611 612 613 614 615 616 617 618 619 620 621
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();

622
    POSIX_PRE_RECORD();
623
    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
624
    POSIX_POST_RECORD();
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639

    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();

640
    POSIX_PRE_RECORD();
641
    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
642
    POSIX_POST_RECORD();
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657

    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();

658
    POSIX_PRE_RECORD();
659
    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
660
    POSIX_POST_RECORD();
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675

    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();

676
    POSIX_PRE_RECORD();
677
    POSIX_RECORD_OPEN(ret, template, 0, tm1, tm2);
678
    POSIX_POST_RECORD();
679 680 681 682

    return(ret);
}

683 684 685 686 687 688
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
689
    MAP_OR_FAIL(read);
690

691
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
692 693 694 695 696

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

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

    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);

712
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
713 714 715 716 717

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

718
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
719
    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, tm1, tm2);
720
    POSIX_POST_RECORD();
721 722 723 724 725 726 727 728 729 730 731 732

    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);

733
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
734 735 736 737 738

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

739
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
740
    POSIX_RECORD_READ(ret, fd, 1, offset, aligned_flag, tm1, tm2);
741
    POSIX_POST_RECORD();
742 743 744 745 746 747 748 749 750 751 752 753

    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);

754
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
755 756 757 758 759

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

760
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
761
    POSIX_RECORD_WRITE(ret, fd, 1, offset, aligned_flag, tm1, tm2);
762
    POSIX_POST_RECORD();
763 764 765 766 767 768 769 770 771 772 773 774

    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);

775
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
776 777 778 779 780

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

781
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
782
    POSIX_RECORD_READ(ret, fd, 1, offset, aligned_flag, tm1, tm2);
783
    POSIX_POST_RECORD();
784 785 786 787 788 789 790 791 792 793 794 795

    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);

796
    if((unsigned long)buf % darshan_mem_alignment == 0) aligned_flag = 1;
797 798 799 800 801

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

802
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
803
    POSIX_RECORD_WRITE(ret, fd, 1, offset, aligned_flag, tm1, tm2);
804
    POSIX_POST_RECORD();
805 806 807 808 809 810 811

    return(ret);
}

ssize_t DARSHAN_DECL(readv)(int fd, const struct iovec *iov, int iovcnt)
{
    ssize_t ret;
812
    int aligned_flag = 1;
813 814 815 816
    int i;
    double tm1, tm2;

    MAP_OR_FAIL(readv);
817

818 819 820 821
    for(i=0; i<iovcnt; i++)
    {
        if(((unsigned long)iov[i].iov_base % darshan_mem_alignment) != 0)
            aligned_flag = 0;
822
    }
823 824 825 826 827

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

828
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
829
    POSIX_RECORD_READ(ret, fd, 0, 0, aligned_flag, tm1, tm2);
830
    POSIX_POST_RECORD();
831 832 833 834 835 836 837

    return(ret);
}

ssize_t DARSHAN_DECL(writev)(int fd, const struct iovec *iov, int iovcnt)
{
    ssize_t ret;
838
    int aligned_flag = 1;
839 840 841 842
    int i;
    double tm1, tm2;

    MAP_OR_FAIL(writev);
843

844 845 846 847
    for(i=0; i<iovcnt; i++)
    {
        if(((unsigned long)iov[i].iov_base % darshan_mem_alignment) != 0)
            aligned_flag = 0;
848
    }
849 850 851 852 853

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

854
    POSIX_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
855
    POSIX_RECORD_WRITE(ret, fd, 0, 0, aligned_flag, tm1, tm2);
856
    POSIX_POST_RECORD();
857 858 859 860 861 862 863

    return(ret);
}

off_t DARSHAN_DECL(lseek)(int fd, off_t offset, int whence)
{
    off_t ret;
864
    struct posix_file_record_ref *rec_ref;
865 866 867 868 869 870 871 872 873 874
    double tm1, tm2;

    MAP_OR_FAIL(lseek);

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

    if(ret >= 0)
    {
875
        POSIX_PRE_RECORD();
876 877
        rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
        if(rec_ref)
878
        {
879
            rec_ref->offset = ret;
880
            DARSHAN_TIMER_INC_NO_OVERLAP(
881 882 883
                rec_ref->file_rec->fcounters[POSIX_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[POSIX_SEEKS] += 1;
884
        }
885
        POSIX_POST_RECORD();
886 887 888 889 890
    }

    return(ret);
}

891
off64_t DARSHAN_DECL(lseek64)(int fd, off64_t offset, int whence)
892 893
{
    off_t ret;
894
    struct posix_file_record_ref *rec_ref;
895 896 897 898 899 900 901 902 903 904
    double tm1, tm2;

    MAP_OR_FAIL(lseek64);

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

    if(ret >= 0)
    {
905
        POSIX_PRE_RECORD();
906 907
        rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
        if(rec_ref)
908
        {
909
            rec_ref->offset = ret;
910
            DARSHAN_TIMER_INC_NO_OVERLAP(
911 912 913
                rec_ref->file_rec->fcounters[POSIX_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[POSIX_SEEKS] += 1;
914
        }
915
        POSIX_POST_RECORD();
916 917 918 919 920
    }

    return(ret);
}

921 922 923 924 925 926 927 928 929 930 931 932 933 934
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);

935
    POSIX_PRE_RECORD();
936
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
937
    POSIX_POST_RECORD();
938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955

    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);

956
    POSIX_PRE_RECORD();
957
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
958
    POSIX_POST_RECORD();
959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976

    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);

977
    POSIX_PRE_RECORD();
978
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
979
    POSIX_POST_RECORD();
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997

    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);

998
    POSIX_PRE_RECORD();
999
    POSIX_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
1000
    POSIX_POST_RECORD();
1001 1002 1003 1004 1005 1006 1007

    return(ret);
}

int DARSHAN_DECL(__fxstat)(int vers, int fd, struct stat *buf)
{
    int ret;
1008
    struct posix_file_record_ref *rec_ref;
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
    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);

1020
    POSIX_PRE_RECORD();
1021 1022
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
    if(rec_ref)
1023
    {
1024
        POSIX_RECORD_STAT(rec_ref, buf, tm1, tm2);
1025
    }
1026
    POSIX_POST_RECORD();
1027 1028 1029 1030 1031 1032 1033

    return(ret);
}

int DARSHAN_DECL(__fxstat64)(int vers, int fd, struct stat64 *buf)
{
    int ret;
1034
    struct posix_file_record_ref *rec_ref;
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
    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);

1046
    POSIX_PRE_RECORD();
1047 1048
    rec_ref = darshan_lookup_record_ref(posix_runtime->fd_hash, &fd, sizeof(int));
    if(rec_ref)
1049
    {
1050
        POSIX_RECORD_STAT(rec_ref, buf, tm1, tm2);
1051
    }
1052
    POSIX_POST_RECORD();
1053 1054 1055 1056

    return(ret);
}

1057
#ifdef DARSHAN_WRAP_MMAP
Shane Snyder's avatar
Shane Snyder committed
1058 1059 1060 1061
void* DARSHAN_DECL(mmap)(void *addr, size_t length, int prot, int flags,
    int fd, off_t offset)
{
    void* ret;
1062
    struct posix_file_record_ref *rec_ref;
Shane Snyder's avatar
Shane Snyder committed
1063 1064 1065

    MAP_OR_FAIL(mmap);

1066 1067 1068 1069 1070 1071 1072 1073
    if(fd < 0 || (flags & MAP_ANONYMOUS))
    {
        /* mmap is not associated with a backing file; skip all Darshan
         * characterization attempts.
         */
        return(__real_mmap(addr, length, prot, flags, fd, offset));
    }

Shane Snyder's avatar
Shane Snyder committed
1074 1075 1076 1077
    ret = __real_mmap(addr, length, prot, flags, fd, offset);
    if(ret == MAP_FAILED)
        return(ret);

1078
    POSIX_PRE_RECORD();