darshan-posix.c 55.5 KB
Newer Older
1 2 3 4 5
/*
 *  (C) 2009 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

6
#include "darshan-runtime-config.h"
7 8 9 10 11 12 13 14 15 16 17 18 19 20
#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>
21
#include <libgen.h>
22
#include <limits.h>
Philip Carns's avatar
Philip Carns committed
23
#include <aio.h>
24 25
#define __USE_GNU
#include <pthread.h>
26 27 28

#include "darshan.h"

29
#ifndef HAVE_OFF64_T
30 31 32
typedef int64_t off64_t;
#endif

33 34
extern char* __progname_full;

35
#ifdef DARSHAN_PRELOAD
36 37 38
#define __USE_GNU
#include <dlfcn.h>
#include <stdlib.h>
39

40 41 42 43 44
#define DARSHAN_FORWARD_DECL(name,ret,args) \
  ret (*__real_ ## name)args = NULL;

#define DARSHAN_DECL(__name) __name

45 46 47 48 49 50 51 52 53 54 55 56 57
#define DARSHAN_MPI_CALL(func) __real_ ## func

#define MAP_OR_FAIL(func) \
    if (!(__real_ ## func)) \
    { \
        __real_ ## func = dlsym(RTLD_NEXT, #func); \
        if(!(__real_ ## func)) { \
           fprintf(stderr, "Darshan failed to map symbol: %s\n", #func); \
           exit(1); \
       } \
    }


58
extern double (*__real_PMPI_Wtime)(void);
59

60 61 62 63 64 65 66
#else

#define DARSHAN_FORWARD_DECL(name,ret,args) \
  extern ret __real_ ## name args;

#define DARSHAN_DECL(__name) __wrap_ ## __name

67 68 69 70
#define MAP_OR_FAIL(func)

#define DARSHAN_MPI_CALL(func) func

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
#endif

DARSHAN_FORWARD_DECL(creat, int, (const char* path, mode_t mode));
DARSHAN_FORWARD_DECL(creat64, int, (const char* path, mode_t mode));
DARSHAN_FORWARD_DECL(open, int, (const char *path, int flags, ...));
DARSHAN_FORWARD_DECL(open64, int, (const char *path, int flags, ...));
DARSHAN_FORWARD_DECL(close, int, (int fd));
DARSHAN_FORWARD_DECL(write, ssize_t, (int fd, const void *buf, size_t count));
DARSHAN_FORWARD_DECL(read, ssize_t, (int fd, void *buf, size_t count));
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));
DARSHAN_FORWARD_DECL(pread, ssize_t, (int fd, 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(pwrite, ssize_t, (int fd, const void *buf, size_t count, off_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));
DARSHAN_FORWARD_DECL(__fxstat, int, (int vers, int fd, struct stat *buf));
DARSHAN_FORWARD_DECL(__fxstat64, int, (int vers, int fd, 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(__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(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));
DARSHAN_FORWARD_DECL(fopen, FILE*, (const char *path, const char *mode));
DARSHAN_FORWARD_DECL(fopen64, FILE*, (const char *path, const char *mode));
DARSHAN_FORWARD_DECL(fclose, int, (FILE *fp));
DARSHAN_FORWARD_DECL(fread, size_t, (void *ptr, size_t size, size_t nmemb, FILE *stream));
DARSHAN_FORWARD_DECL(fwrite, size_t, (const void *ptr, size_t size, size_t nmemb, FILE *stream));
DARSHAN_FORWARD_DECL(fseek, int, (FILE *stream, long offset, int whence));
DARSHAN_FORWARD_DECL(fsync, int, (int fd));
DARSHAN_FORWARD_DECL(fdatasync, int, (int fd));
Philip Carns's avatar
Philip Carns committed
105 106 107 108 109 110 111 112
DARSHAN_FORWARD_DECL(aio_read, int, (struct aiocb *aiocbp));
DARSHAN_FORWARD_DECL(aio_read64, int, (struct aiocb *aiocbp));
DARSHAN_FORWARD_DECL(aio_write, int, (struct aiocb *aiocbp));
DARSHAN_FORWARD_DECL(aio_write64, int, (struct aiocb *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 aiocb *const aiocb_list[], int nitems, struct sigevent *sevp));
DARSHAN_FORWARD_DECL(aio_return, ssize_t, (struct aiocb *aiocbp));
DARSHAN_FORWARD_DECL(aio_return64, ssize_t, (struct aiocb *aiocbp));
113

114
pthread_mutex_t cp_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
115 116
struct darshan_job_runtime* darshan_global_job = NULL;
static int my_rank = -1;
117
static struct stat64 cp_stat_buf;
118
static int darshan_mem_alignment = 1;
119

120 121 122 123
/* struct to track information about aio operations in flight */
struct darshan_aio_tracker
{
    double tm1;
124
    struct aiocb *aiocbp;
125 126 127
    struct darshan_aio_tracker* next;
};

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
/* these are paths that we will not trace */
static char* exclusions[] = {
"/etc/",
"/dev/",
"/usr/",
"/bin/",
"/boot/",
"/lib/",
"/opt/",
"/sbin/",
"/sys/",
"/proc/",
NULL
};

143 144
static double posix_wtime(void);

145 146
static void cp_access_counter(struct darshan_file_runtime* file, ssize_t size,     enum cp_counter_type type);

147 148 149 150 151 152 153 154
static struct darshan_file_ref* ref_by_handle(
    const void* handle,
    int handle_sz,
    enum darshan_handle_type handle_type);

static struct darshan_file_runtime* darshan_file_by_fd(int fd);
static void darshan_file_close_fd(int fd);
static struct darshan_file_runtime* darshan_file_by_name_setfd(const char* name, int fd);
155
static char* clean_path(const char* path);
156

Philip Carns's avatar
Philip Carns committed
157
#define CP_RECORD_WRITE(__ret, __fd, __count, __pwrite_flag, __pwrite_offset, __aligned, __stream_flag, __tm1, __tm2) do{ \
158
    size_t stride; \
Philip Carns's avatar
Philip Carns committed
159
    int64_t this_offset; \
160 161
    int64_t file_alignment; \
    struct darshan_file_runtime* file; \
162
    double __elapsed = __tm2-__tm1; \
163 164 165
    if(__ret < 0) break; \
    file = darshan_file_by_fd(__fd); \
    if(!file) break; \
Philip Carns's avatar
Philip Carns committed
166 167 168 169
    if(__pwrite_flag) \
        this_offset = __pwrite_offset; \
    else \
        this_offset = file->offset; \
170
    file_alignment = CP_VALUE(file, CP_FILE_ALIGNMENT); \
Philip Carns's avatar
Philip Carns committed
171
    if(this_offset > file->last_byte_written) \
172
        CP_INC(file, CP_SEQ_WRITES, 1); \
Philip Carns's avatar
Philip Carns committed
173
    if(this_offset == (file->last_byte_written + 1)) \
174
        CP_INC(file, CP_CONSEC_WRITES, 1); \
Philip Carns's avatar
Philip Carns committed
175
    if(this_offset > 0 && this_offset > file->last_byte_written \
176
        && file->last_byte_written != 0) \
Philip Carns's avatar
Philip Carns committed
177
        stride = this_offset - file->last_byte_written - 1; \
178 179
    else \
        stride = 0; \
Philip Carns's avatar
Philip Carns committed
180 181 182
    file->last_byte_written = this_offset + __ret - 1; \
    file->offset = this_offset + __ret; \
    CP_MAX(file, CP_MAX_BYTE_WRITTEN, (this_offset + __ret -1)); \
183 184 185 186 187 188 189 190 191
    CP_INC(file, CP_BYTES_WRITTEN, __ret); \
    if(__stream_flag) \
        CP_INC(file, CP_POSIX_FWRITES, 1); \
    else \
        CP_INC(file, CP_POSIX_WRITES, 1); \
    CP_BUCKET_INC(file, CP_SIZE_WRITE_0_100, __ret); \
    cp_access_counter(file, stride, CP_COUNTER_STRIDE); \
    if(!__aligned) \
        CP_INC(file, CP_MEM_NOT_ALIGNED, 1); \
Philip Carns's avatar
Philip Carns committed
192
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
193 194 195 196 197
        CP_INC(file, CP_FILE_NOT_ALIGNED, 1); \
    cp_access_counter(file, __ret, CP_COUNTER_ACCESS); \
    if(file->last_io_type == CP_READ) \
        CP_INC(file, CP_RW_SWITCHES, 1); \
    file->last_io_type = CP_WRITE; \
198
    CP_F_INC_NO_OVERLAP(file, __tm1, __tm2, file->last_posix_write_end, CP_F_POSIX_WRITE_TIME); \
199 200 201
    if(CP_F_VALUE(file, CP_F_WRITE_START_TIMESTAMP) == 0) \
        CP_F_SET(file, CP_F_WRITE_START_TIMESTAMP, __tm1); \
    CP_F_SET(file, CP_F_WRITE_END_TIMESTAMP, __tm2); \
202 203 204
    if(CP_F_VALUE(file, CP_F_MAX_WRITE_TIME) < __elapsed){ \
        CP_F_SET(file, CP_F_MAX_WRITE_TIME, __elapsed); \
        CP_SET(file, CP_MAX_WRITE_TIME_SIZE, __ret); } \
205 206
} while(0)

207
#define CP_RECORD_READ(__ret, __fd, __count, __pread_flag, __pread_offset, __aligned, __stream_flag, __tm1, __tm2) do{ \
208
    size_t stride; \
209
    int64_t this_offset; \
210 211
    struct darshan_file_runtime* file; \
    int64_t file_alignment; \
212
    double __elapsed = __tm2-__tm1; \
213 214 215
    if(__ret < 0) break; \
    file = darshan_file_by_fd(__fd); \
    if(!file) break; \
216 217 218 219
    if(__pread_flag)\
        this_offset = __pread_offset; \
    else \
        this_offset = file->offset; \
220
    file_alignment = CP_VALUE(file, CP_FILE_ALIGNMENT); \
221
    if(this_offset > file->last_byte_read) \
222
        CP_INC(file, CP_SEQ_READS, 1); \
223
    if(this_offset == (file->last_byte_read + 1)) \
224
        CP_INC(file, CP_CONSEC_READS, 1); \
225
    if(this_offset > 0 && this_offset > file->last_byte_read \
226
        && file->last_byte_read != 0) \
227
        stride = this_offset - file->last_byte_read - 1; \
228 229
    else \
        stride = 0; \
230 231 232
    file->last_byte_read = this_offset + __ret - 1; \
    CP_MAX(file, CP_MAX_BYTE_READ, (this_offset + __ret -1)); \
    file->offset = this_offset + __ret; \
233 234 235 236 237 238 239 240 241
    CP_INC(file, CP_BYTES_READ, __ret); \
    if(__stream_flag)\
        CP_INC(file, CP_POSIX_FREADS, 1); \
    else\
        CP_INC(file, CP_POSIX_READS, 1); \
    CP_BUCKET_INC(file, CP_SIZE_READ_0_100, __ret); \
    cp_access_counter(file, stride, CP_COUNTER_STRIDE); \
    if(!__aligned) \
        CP_INC(file, CP_MEM_NOT_ALIGNED, 1); \
Philip Carns's avatar
Philip Carns committed
242
    if(file_alignment > 0 && (this_offset % file_alignment) != 0) \
243 244 245 246 247
        CP_INC(file, CP_FILE_NOT_ALIGNED, 1); \
    cp_access_counter(file, __ret, CP_COUNTER_ACCESS); \
    if(file->last_io_type == CP_WRITE) \
        CP_INC(file, CP_RW_SWITCHES, 1); \
    file->last_io_type = CP_READ; \
248
    CP_F_INC_NO_OVERLAP(file, __tm1, __tm2, file->last_posix_read_end, CP_F_POSIX_READ_TIME); \
249 250 251
    if(CP_F_VALUE(file, CP_F_READ_START_TIMESTAMP) == 0) \
        CP_F_SET(file, CP_F_READ_START_TIMESTAMP, __tm1); \
    CP_F_SET(file, CP_F_READ_END_TIMESTAMP, __tm2); \
252 253 254
    if(CP_F_VALUE(file, CP_F_MAX_READ_TIME) < __elapsed){ \
        CP_F_SET(file, CP_F_MAX_READ_TIME, __elapsed); \
        CP_SET(file, CP_MAX_READ_TIME_SIZE, __ret); } \
255 256
} while(0)

257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
#define CP_LOOKUP_RECORD_STAT(__path, __statbuf, __tm1, __tm2) do { \
    char* exclude; \
    int tmp_index = 0; \
    struct darshan_file_runtime* file; \
    while((exclude = exclusions[tmp_index])) { \
        if(!(strncmp(exclude, __path, strlen(exclude)))) \
            break; \
        tmp_index++; \
    } \
    if(exclude) break; \
    file = darshan_file_by_name(__path); \
    if (file) \
    { \
        CP_RECORD_STAT(file, __statbuf, __tm1, __tm2); \
    } \
} while(0)

    
275
#define CP_RECORD_STAT(__file, __statbuf, __tm1, __tm2) do { \
276
    if(!CP_VALUE((__file), CP_POSIX_STATS) && !CP_VALUE((__file), CP_POSIX_OPENS)){ \
277 278 279 280
        CP_SET((__file), CP_FILE_ALIGNMENT, (__statbuf)->st_blksize); \
        CP_SET((__file), CP_SIZE_AT_OPEN, (__statbuf)->st_size); \
    }\
    (__file)->log_file->rank = my_rank; \
281
    CP_F_INC_NO_OVERLAP(file, __tm1, __tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME); \
282 283 284
    CP_INC(__file, CP_POSIX_STATS, 1); \
} while(0)

Philip Carns's avatar
Philip Carns committed
285
#ifdef __CP_STAT_AT_OPEN
286
#define CP_STAT_FILE(_f, _p, _r) do { \
287
    if(!CP_VALUE((_f), CP_POSIX_STATS) && !CP_VALUE((_f), CP_POSIX_OPENS)){ \
288
        if(fstat64(_r, &cp_stat_buf) == 0) { \
Philip Carns's avatar
Philip Carns committed
289 290 291 292 293 294
            CP_SET(_f, CP_FILE_ALIGNMENT, cp_stat_buf.st_blksize); \
            CP_SET(_f, CP_SIZE_AT_OPEN, cp_stat_buf.st_size); \
        }\
    }\
}while(0)
#else
295
#define CP_STAT_FILE(_f, _p, _r) do { }while(0)
Philip Carns's avatar
Philip Carns committed
296 297
#endif

298 299 300 301 302 303 304 305 306 307 308
#define CP_RECORD_OPEN(__ret, __path, __mode, __stream_flag, __tm1, __tm2) do { \
    struct darshan_file_runtime* file; \
    char* exclude; \
    int tmp_index = 0; \
    if(__ret < 0) break; \
    while((exclude = exclusions[tmp_index])) { \
        if(!(strncmp(exclude, __path, strlen(exclude)))) \
            break; \
        tmp_index++; \
    } \
    if(exclude) break; \
309
    file = darshan_file_by_name_setfd(__path, __ret); \
310
    if(!file) break; \
311
    CP_STAT_FILE(file, __path, __ret); \
312 313 314 315 316 317 318 319 320 321 322
    file->log_file->rank = my_rank; \
    if(__mode) \
        CP_SET(file, CP_MODE, __mode); \
    file->offset = 0; \
    file->last_byte_written = 0; \
    file->last_byte_read = 0; \
    if(__stream_flag)\
        CP_INC(file, CP_POSIX_FOPENS, 1); \
    else \
        CP_INC(file, CP_POSIX_OPENS, 1); \
    if(CP_F_VALUE(file, CP_F_OPEN_TIMESTAMP) == 0) \
323
        CP_F_SET(file, CP_F_OPEN_TIMESTAMP, posix_wtime()); \
324
    CP_F_INC_NO_OVERLAP(file, __tm1, __tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME); \
325 326
} while (0)

327
int DARSHAN_DECL(close)(int fd)
328 329 330 331 332 333
{
    struct darshan_file_runtime* file;
    int tmp_fd = fd;
    double tm1, tm2;
    int ret;

334 335
    MAP_OR_FAIL(close);

336 337 338 339 340 341 342 343 344 345
    tm1 = darshan_wtime();
    ret = __real_close(fd);
    tm2 = darshan_wtime();

    CP_LOCK();
    file = darshan_file_by_fd(tmp_fd);
    if(file)
    {
        file->last_byte_written = 0;
        file->last_byte_read = 0;
346
        CP_F_SET(file, CP_F_CLOSE_TIMESTAMP, posix_wtime());
347
        CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME);
348
        darshan_file_close_fd(tmp_fd);
349 350 351 352 353 354
    }
    CP_UNLOCK();

    return(ret);
}

355
int DARSHAN_DECL(fclose)(FILE *fp)
356 357 358 359 360 361
{
    struct darshan_file_runtime* file;
    int tmp_fd = fileno(fp);
    double tm1, tm2;
    int ret;

362 363
    MAP_OR_FAIL(fclose);

364 365 366 367 368 369 370 371 372 373
    tm1 = darshan_wtime();
    ret = __real_fclose(fp);
    tm2 = darshan_wtime();
    
    CP_LOCK();
    file = darshan_file_by_fd(tmp_fd);
    if(file)
    {
        file->last_byte_written = 0;
        file->last_byte_read = 0;
374
        CP_F_SET(file, CP_F_CLOSE_TIMESTAMP, posix_wtime());
375
        CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME);
376
        darshan_file_close_fd(tmp_fd);
377 378 379 380 381 382 383
    }
    CP_UNLOCK();

    return(ret);
}


384
int DARSHAN_DECL(fsync)(int fd)
385 386 387 388 389
{
    int ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

390 391
    MAP_OR_FAIL(fsync);

392 393 394 395 396 397 398 399 400 401 402
    tm1 = darshan_wtime();
    ret = __real_fsync(fd);
    tm2 = darshan_wtime();

    if(ret < 0)
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
403
        CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_write_end, CP_F_POSIX_WRITE_TIME); \
404 405 406 407 408 409 410
        CP_INC(file, CP_POSIX_FSYNCS, 1);
    }
    CP_UNLOCK();

    return(ret);
}

411
int DARSHAN_DECL(fdatasync)(int fd)
412 413 414 415 416
{
    int ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

417 418
    MAP_OR_FAIL(fdatasync);

419 420 421 422 423 424 425 426 427 428
    tm1 = darshan_wtime();
    ret = __real_fdatasync(fd);
    tm2 = darshan_wtime();
    if(ret < 0)
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
429
        CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_write_end, CP_F_POSIX_WRITE_TIME); \
430 431 432 433 434 435 436 437
        CP_INC(file, CP_POSIX_FDSYNCS, 1);
    }
    CP_UNLOCK();

    return(ret);
}


438
void* DARSHAN_DECL(mmap64)(void *addr, size_t length, int prot, int flags,
439 440 441 442 443
    int fd, off64_t offset)
{
    void* ret;
    struct darshan_file_runtime* file;

444 445
    MAP_OR_FAIL(mmap64);

446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
    ret = __real_mmap64(addr, length, prot, flags, fd, offset);
    if(ret == MAP_FAILED)
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
        CP_INC(file, CP_POSIX_MMAPS, 1);
    }
    CP_UNLOCK();

    return(ret);
}


462
void* DARSHAN_DECL(mmap)(void *addr, size_t length, int prot, int flags,
463 464 465 466 467
    int fd, off_t offset)
{
    void* ret;
    struct darshan_file_runtime* file;

468 469
    MAP_OR_FAIL(mmap);

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
    ret = __real_mmap(addr, length, prot, flags, fd, offset);
    if(ret == MAP_FAILED)
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
        CP_INC(file, CP_POSIX_MMAPS, 1);
    }
    CP_UNLOCK();

    return(ret);
}

485
int DARSHAN_DECL(creat)(const char* path, mode_t mode)
486 487 488 489
{
    int ret;
    double tm1, tm2;

490 491
    MAP_OR_FAIL(creat);

492 493 494 495 496 497 498 499 500 501 502
    tm1 = darshan_wtime();
    ret = __real_creat(path, mode);
    tm2 = darshan_wtime();

    CP_LOCK();
    CP_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}

503
int DARSHAN_DECL(creat64)(const char* path, mode_t mode)
504 505 506 507
{
    int ret;
    double tm1, tm2;

508 509
    MAP_OR_FAIL(creat64);

510 511 512 513 514 515 516 517 518 519 520
    tm1 = darshan_wtime();
    ret = __real_creat64(path, mode);
    tm2 = darshan_wtime();

    CP_LOCK();
    CP_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}

521
int DARSHAN_DECL(open64)(const char* path, int flags, ...)
522 523 524 525 526
{
    int mode = 0;
    int ret;
    double tm1, tm2;

527 528
    MAP_OR_FAIL(open64);

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
    if (flags & O_CREAT) 
    {
        va_list arg;
        va_start(arg, flags);
        mode = va_arg(arg, int);
        va_end(arg);

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

    CP_LOCK();
    CP_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}

554
int DARSHAN_DECL(open)(const char *path, int flags, ...)
555 556 557 558 559
{
    int mode = 0;
    int ret;
    double tm1, tm2;

560 561
    MAP_OR_FAIL(open);

562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
    if (flags & O_CREAT) 
    {
        va_list arg;
        va_start(arg, flags);
        mode = va_arg(arg, int);
        va_end(arg);

        tm1 = darshan_wtime();
        ret = __real_open(path, flags, mode);
        tm2 = darshan_wtime();
    }
    else
    {
        tm1 = darshan_wtime();
        ret = __real_open(path, flags);
        tm2 = darshan_wtime();
    }

    CP_LOCK();
    CP_RECORD_OPEN(ret, path, mode, 0, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}

587
FILE* DARSHAN_DECL(fopen64)(const char *path, const char *mode)
588 589 590 591 592
{
    FILE* ret;
    int fd;
    double tm1, tm2;

593 594
    MAP_OR_FAIL(fopen64);

595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
    tm1 = darshan_wtime();
    ret = __real_fopen64(path, mode);
    tm2 = darshan_wtime();
    if(ret == 0)
        fd = -1;
    else
        fd = fileno(ret);

    CP_LOCK();
    CP_RECORD_OPEN(fd, path, 0, 1, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}

610
FILE* DARSHAN_DECL(fopen)(const char *path, const char *mode)
611 612 613 614 615
{
    FILE* ret;
    int fd;
    double tm1, tm2;

616 617
    MAP_OR_FAIL(fopen);

618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
    tm1 = darshan_wtime();
    ret = __real_fopen(path, mode);
    tm2 = darshan_wtime();
    if(ret == 0)
        fd = -1;
    else
        fd = fileno(ret);

    CP_LOCK();
    CP_RECORD_OPEN(fd, path, 0, 1, tm1, tm2);
    CP_UNLOCK();

    return(ret);
}

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

638 639
    MAP_OR_FAIL(__xstat64);

640 641 642 643 644 645 646
    tm1 = darshan_wtime();
    ret = __real___xstat64(vers, path, buf);
    tm2 = darshan_wtime();
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    CP_LOCK();
647
    CP_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
648 649 650 651 652
    CP_UNLOCK();

    return(ret);
}

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

658 659
    MAP_OR_FAIL(__lxstat64);

660 661 662 663 664 665 666
    tm1 = darshan_wtime();
    ret = __real___lxstat64(vers, path, buf);
    tm2 = darshan_wtime();
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    CP_LOCK();
667
    CP_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
668 669 670 671 672
    CP_UNLOCK();

    return(ret);
}

673
int DARSHAN_DECL(__fxstat64)(int vers, int fd, struct stat64 *buf)
674 675 676 677 678
{
    int ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

679 680
    MAP_OR_FAIL(__fxstat64);

681 682 683 684 685 686 687 688 689 690 691 692 693 694
    tm1 = darshan_wtime();
    ret = __real___fxstat64(vers, fd, buf);
    tm2 = darshan_wtime();
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    /* skip logging if this was triggered internally */
    if(buf == &cp_stat_buf)
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
695
        CP_RECORD_STAT(file, buf, tm1, tm2);
696 697 698 699 700 701 702
    }
    CP_UNLOCK();

    return(ret);
}


703
int DARSHAN_DECL(__xstat)(int vers, const char *path, struct stat *buf)
704 705 706 707
{
    int ret;
    double tm1, tm2;

708 709
    MAP_OR_FAIL(__xstat);

710 711 712 713 714 715 716
    tm1 = darshan_wtime();
    ret = __real___xstat(vers, path, buf);
    tm2 = darshan_wtime();
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    CP_LOCK();
717
    CP_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
718 719 720 721 722
    CP_UNLOCK();

    return(ret);
}

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

728 729
    MAP_OR_FAIL(__lxstat);

730 731 732 733 734 735 736
    tm1 = darshan_wtime();
    ret = __real___lxstat(vers, path, buf);
    tm2 = darshan_wtime();
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    CP_LOCK();
737
    CP_LOOKUP_RECORD_STAT(path, buf, tm1, tm2);
738 739 740 741 742
    CP_UNLOCK();

    return(ret);
}

743
int DARSHAN_DECL(__fxstat)(int vers, int fd, struct stat *buf)
744 745 746 747 748
{
    int ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

749 750
    MAP_OR_FAIL(__fxstat);

751 752 753 754 755 756 757
    tm1 = darshan_wtime();
    ret = __real___fxstat(vers, fd, buf);
    tm2 = darshan_wtime();
    if(ret < 0 || !S_ISREG(buf->st_mode))
        return(ret);

    /* skip logging if this was triggered internally */
758
    if((void*)buf == (void*)&cp_stat_buf)
759 760 761 762 763 764
        return(ret);

    CP_LOCK();
    file = darshan_file_by_fd(fd);
    if(file)
    {
765
        CP_RECORD_STAT(file, buf, tm1, tm2);
766 767 768 769 770 771
    }
    CP_UNLOCK();

    return(ret);
}

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

778 779
    MAP_OR_FAIL(pread64);

780
    if((unsigned long)buf % darshan_mem_alignment == 0)
781 782 783 784 785 786
        aligned_flag = 1;

    tm1 = darshan_wtime();
    ret = __real_pread64(fd, buf, count, offset);
    tm2 = darshan_wtime();
    CP_LOCK();
787
    CP_RECORD_READ(ret, fd, count, 1, offset, aligned_flag, 0, tm1, tm2);
788 789 790 791
    CP_UNLOCK();
    return(ret);
}

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

798 799
    MAP_OR_FAIL(pread);

800
    if((unsigned long)buf % darshan_mem_alignment == 0)
801 802 803 804 805 806
        aligned_flag = 1;

    tm1 = darshan_wtime();
    ret = __real_pread(fd, buf, count, offset);
    tm2 = darshan_wtime();
    CP_LOCK();
807
    CP_RECORD_READ(ret, fd, count, 1, offset, aligned_flag, 0, tm1, tm2);
808 809 810 811 812
    CP_UNLOCK();
    return(ret);
}


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

819 820
    MAP_OR_FAIL(pwrite);

821
    if((unsigned long)buf % darshan_mem_alignment == 0)
822 823 824 825 826 827
        aligned_flag = 1;

    tm1 = darshan_wtime();
    ret = __real_pwrite(fd, buf, count, offset);
    tm2 = darshan_wtime();
    CP_LOCK();
Philip Carns's avatar
Philip Carns committed
828
    CP_RECORD_WRITE(ret, fd, count, 1, offset, aligned_flag, 0, tm1, tm2);
829 830 831 832
    CP_UNLOCK();
    return(ret);
}

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

839 840
    MAP_OR_FAIL(pwrite64);

841
    if((unsigned long)buf % darshan_mem_alignment == 0)
842 843 844 845 846 847
        aligned_flag = 1;

    tm1 = darshan_wtime();
    ret = __real_pwrite64(fd, buf, count, offset);
    tm2 = darshan_wtime();
    CP_LOCK();
Philip Carns's avatar
Philip Carns committed
848
    CP_RECORD_WRITE(ret, fd, count, 1, offset, aligned_flag, 0, tm1, tm2);
849 850 851 852
    CP_UNLOCK();
    return(ret);
}

853
ssize_t DARSHAN_DECL(readv)(int fd, const struct iovec *iov, int iovcnt)
854 855 856 857 858 859
{
    ssize_t ret;
    int aligned_flag = 1;
    int i;
    double tm1, tm2;

860 861
    MAP_OR_FAIL(readv);

862 863
    for(i=0; i<iovcnt; i++)
    {
864
        if(((unsigned long)iov[i].iov_base % darshan_mem_alignment) != 0)
865 866 867 868 869 870 871
            aligned_flag = 0;
    }

    tm1 = darshan_wtime();
    ret = __real_readv(fd, iov, iovcnt);
    tm2 = darshan_wtime();
    CP_LOCK();
872
    CP_RECORD_READ(ret, fd, count, 0, 0, aligned_flag, 0, tm1, tm2);
873 874 875 876
    CP_UNLOCK();
    return(ret);
}

877
ssize_t DARSHAN_DECL(writev)(int fd, const struct iovec *iov, int iovcnt)
878 879 880 881 882 883
{
    ssize_t ret;
    int aligned_flag = 1;
    int i;
    double tm1, tm2;

884 885
    MAP_OR_FAIL(writev);

886 887
    for(i=0; i<iovcnt; i++)
    {
888
        if(!((unsigned long)iov[i].iov_base % darshan_mem_alignment == 0))
889 890 891 892 893 894 895
            aligned_flag = 0;
    }

    tm1 = darshan_wtime();
    ret = __real_writev(fd, iov, iovcnt);
    tm2 = darshan_wtime();
    CP_LOCK();
Philip Carns's avatar
Philip Carns committed
896
    CP_RECORD_WRITE(ret, fd, count, 0, 0, aligned_flag, 0, tm1, tm2);
897 898 899 900
    CP_UNLOCK();
    return(ret);
}

901
size_t DARSHAN_DECL(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
902 903 904 905 906
{
    size_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

907 908
    MAP_OR_FAIL(fread);

909
    if((unsigned long)ptr % darshan_mem_alignment == 0)
910 911 912 913 914 915 916
        aligned_flag = 1;

    tm1 = darshan_wtime();
    ret = __real_fread(ptr, size, nmemb, stream);
    tm2 = darshan_wtime();
    CP_LOCK();
    if(ret > 0)
917
        CP_RECORD_READ(size*ret, fileno(stream), (size*nmemb), 0, 0, aligned_flag, 1, tm1, tm2);
918
    else
919
        CP_RECORD_READ(ret, fileno(stream), (size*nmemb), 0, 0, aligned_flag, 1, tm1, tm2);
920 921 922 923
    CP_UNLOCK();
    return(ret);
}

924
ssize_t DARSHAN_DECL(read)(int fd, void *buf, size_t count)
925 926 927 928 929
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

930 931
    MAP_OR_FAIL(read);

932
    if((unsigned long)buf % darshan_mem_alignment == 0)
933 934 935 936 937 938
        aligned_flag = 1;

    tm1 = darshan_wtime();
    ret = __real_read(fd, buf, count);
    tm2 = darshan_wtime();
    CP_LOCK();
939
    CP_RECORD_READ(ret, fd, count, 0, 0, aligned_flag, 0, tm1, tm2);
940 941 942 943
    CP_UNLOCK();
    return(ret);
}

944
ssize_t DARSHAN_DECL(write)(int fd, const void *buf, size_t count)
945 946 947 948 949
{
    ssize_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

950 951
    MAP_OR_FAIL(write);

952
    if((unsigned long)buf % darshan_mem_alignment == 0)
953 954 955 956 957 958
        aligned_flag = 1;

    tm1 = darshan_wtime();
    ret = __real_write(fd, buf, count);
    tm2 = darshan_wtime();
    CP_LOCK();
Philip Carns's avatar
Philip Carns committed
959
    CP_RECORD_WRITE(ret, fd, count, 0, 0, aligned_flag, 0, tm1, tm2);
960 961 962 963
    CP_UNLOCK();
    return(ret);
}

964
size_t DARSHAN_DECL(fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *stream)
965 966 967 968 969
{
    size_t ret;
    int aligned_flag = 0;
    double tm1, tm2;

970 971
    MAP_OR_FAIL(fwrite);

972
    if((unsigned long)ptr % darshan_mem_alignment == 0)
973 974 975 976 977 978 979
        aligned_flag = 1;

    tm1 = darshan_wtime();
    ret = __real_fwrite(ptr, size, nmemb, stream);
    tm2 = darshan_wtime();
    CP_LOCK();
    if(ret > 0)
Philip Carns's avatar
Philip Carns committed
980
        CP_RECORD_WRITE(size*ret, fileno(stream), (size*nmemb), 0, 0, aligned_flag, 1, tm1, tm2);
981
    else
Philip Carns's avatar
Philip Carns committed
982
        CP_RECORD_WRITE(ret, fileno(stream), 0, 0, 0, aligned_flag, 1, tm1, tm2);
983 984 985 986
    CP_UNLOCK();
    return(ret);
}

987
off64_t DARSHAN_DECL(lseek64)(int fd, off64_t offset, int whence)
988
{
Philip Carns's avatar
Philip Carns committed
989
    off64_t ret;
990 991 992
    struct darshan_file_runtime* file;
    double tm1, tm2;

993 994
    MAP_OR_FAIL(lseek64);

995 996 997 998 999 1000 1001 1002 1003 1004
    tm1 = darshan_wtime();
    ret = __real_lseek64(fd, offset, whence);
    tm2 = darshan_wtime();
    if(ret >= 0)
    {
        CP_LOCK();
        file = darshan_file_by_fd(fd);
        if(file)
        {
            file->offset = ret;
1005
            CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME);
1006 1007 1008 1009 1010 1011 1012
            CP_INC(file, CP_POSIX_SEEKS, 1);
        }
        CP_UNLOCK();
    }
    return(ret);
}

1013
off_t DARSHAN_DECL(lseek)(int fd, off_t offset, int whence)
1014 1015 1016 1017 1018
{
    off_t ret;
    struct darshan_file_runtime* file;
    double tm1, tm2;

1019 1020
    MAP_OR_FAIL(lseek);

1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
    tm1 = darshan_wtime();
    ret = __real_lseek(fd, offset, whence);
    tm2 = darshan_wtime();
    if(ret >= 0)
    {
        CP_LOCK();
        file = darshan_file_by_fd(fd);
        if(file)
        {
            file->offset = ret;
1031
            CP_F_INC_NO_OVERLAP(file, tm1, tm2, file->last_posix_meta_end, CP_F_POSIX_META_TIME);
1032 1033 1034 1035 1036 1037 1038
            CP_INC(file, CP_POSIX_SEEKS, 1);
        }
        CP_UNLOCK();
    }
    return(ret);
}

1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
/* finds the tracker structure for a given aio operation, removes it from
 * the linked list for the darshan_file structure, and returns a pointer.  
 *
 * returns NULL if aio operation not found
 */
static struct darshan_aio_tracker* darshan_aio_tracker_del(struct aiocb *aiocbp)
{
    struct darshan_aio_tracker *tmp, *prev;
    struct darshan_file_runtime* file;

    CP_LOCK();
    file = darshan_file_by_fd(aiocbp->aio_fildes);
    if(file)
    {
        /* is there a tracker struct for this operation? */
        tmp = file->aio_list_head; 
        prev = NULL;
        while(tmp)
        {
            if(tmp->aiocbp == aiocbp)
            {
                if(prev)
                    prev->next = tmp->next;
                else
                    file->aio_list_head = tmp->next;

                if(tmp == file->aio_list_tail)
                    file->aio_list_tail = prev;

                break;
            }
            else
            {
                prev = tmp;
                tmp = tmp->next;
            }
        }
    }

    CP_UNLOCK();

    return(tmp);
}

Philip Carns's avatar
Philip Carns committed
1083 1084 1085
ssize_t DARSHAN_DECL(aio_return64)(struct aiocb *aiocbp)
{
    int ret;
1086 1087 1088
    double tm2;
    struct darshan_aio_tracker *tmp;
    int aligned_flag = 0;
Philip Carns's avatar
Philip Carns committed
1089 1090 1091 1092

    MAP_OR_FAIL(aio_return64);

    ret = __real_aio_return64(aiocbp);
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
    tm2 = darshan_wtime();
    tmp = darshan_aio_tracker_del(aiocbp);

    if(tmp)
    {
        if((unsigned long)aiocbp->aio_buf % darshan_mem_alignment == 0)
            aligned_flag = 1;
        CP_LOCK();
        CP_RECORD_WRITE(ret, aiocbp->aio_fildes, aiocbp->aio_nbytes,
            1, aiocbp->aio_offset, aligned_flag, 0, tmp->tm1, tm2);
        CP_UNLOCK();
        free(tmp);
    }
Philip Carns's avatar
Philip Carns committed
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153

    return(ret);
}

ssize_t DARSHAN_DECL(aio_return)(struct aiocb *aiocbp)
{
    int ret;

    MAP_OR_FAIL(aio_return);

    printf("TESTING: wrapped aio_return()\n");

    ret = __real_aio_return(aiocbp);

    return(ret);
}

int DARSHAN_DECL(lio_listio)(int mode, struct aiocb *const aiocb_list[],
    int nitems, struct sigevent *sevp)
{
    int ret;

    MAP_OR_FAIL(lio_listio);

    printf("TESTING: wrapped lio_listio()\n");

    ret = __real_lio_listio(mode, aiocb_list, nitems, sevp);

    return(ret);
}

int DARSHAN_DECL(lio_listio64)(int mode, struct aiocb *const aiocb_list[],
    int nitems, struct sigevent *sevp)
{
    int ret;

    MAP_OR_FAIL(lio_listio64);

    printf("TESTING: wrapped lio_listio64()\n");

    ret = __real_lio_listio64(mode, aiocb_list, nitems, sevp);

    return(ret);
}

int DARSHAN_DECL(aio_write64)(struct aiocb *aiocbp)
{
    int ret;
1154 1155
    struct darshan_aio_tracker* tracker;
    struct darshan_file_runtime* file;
Philip Carns's avatar
Philip Carns committed
1156 1157 1158 1159 1160 1161

    MAP_OR_FAIL(aio_write64);

    printf("TESTING: wrapped aio_write64()\n");

    ret = __real_aio_write64(aiocbp);
1162 1163
    if(ret == 0)
    {
1164
        CP_LOCK();
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
        file = darshan_file_by_fd(aiocbp->aio_fildes);
        if(file)
        {
            tracker = malloc(sizeof(*tracker));
            if(tracker)
            {
                tracker->tm1 = darshan_wtime();
                tracker->aiocbp = aiocbp;
                tracker->next = NULL;
                if(file->aio_list_tail)
                {
                    file