author | Alberto Bertogli
<albertito@gmail.com> 2005-03-10 07:34:35 UTC |
committer | Alberto Bertogli
<albertito@gmail.com> 2007-07-15 13:49:04 UTC |
parent | f7982307ba785c713f9a2613ca35a20ff325545c |
bindings/preload/libjio_preload.c | +126 | -8 |
diff --git a/bindings/preload/libjio_preload.c b/bindings/preload/libjio_preload.c index fb9c7dd..1924d4f 100644 --- a/bindings/preload/libjio_preload.c +++ b/bindings/preload/libjio_preload.c @@ -58,11 +58,14 @@ static int (*c_ftruncate64)(int fd, off64_t length); static off_t (*c_lseek)(int fd, off_t offset, int whence); static off64_t (*c_lseek64)(int fd, off64_t offset, int whence); static int (*c_fsync)(int fd); +static int (*c_dup)(int oldfd); +static int (*c_dup2)(int oldfd, int newfd); /* file descriptor table, to translate fds to jfs */ struct fd_entry { int fd; + unsigned int *refcount; struct jfs *fs; pthread_mutex_t lock; }; @@ -96,6 +99,7 @@ static struct fd_entry fd_table[MAXFD]; if (called) \ fprintf(stderr, "\t"); \ called++; \ + fprintf(stderr, "%5.5d ", getpid()); \ fprintf(stderr, "%s(): ", __FUNCTION__ ); \ fprintf(stderr, __VA_ARGS__); \ fflush(stderr); \ @@ -182,6 +186,8 @@ static int __attribute__((constructor)) init(void) libc_load(lseek); libc_load(lseek64); libc_load(fsync); + libc_load(dup); + libc_load(dup2); printd("done\n"); return 1; @@ -255,6 +261,8 @@ int open(const char *pathname, int flags, ...) fd_lock(fd); fd_table[fd].fd = fd; + fd_table[fd].refcount = malloc(sizeof(unsigned int)); + *fd_table[fd].refcount = 1; fd_table[fd].fs = fs; fd_unlock(fd); @@ -327,6 +335,8 @@ int open64(const char *pathname, int flags, ...) fd_lock(fd); fd_table[fd].fd = fd; + fd_table[fd].refcount = malloc(sizeof(unsigned int)); + *fd_table[fd].refcount = 1; fd_table[fd].fs = fs; fd_unlock(fd); @@ -334,6 +344,38 @@ int open64(const char *pathname, int flags, ...) return fd; } +/* close() is split in two functions: unlocked_close() that performs the real + * actual close and cleanup, and close() which takes care of the locking and + * calls unlocked_close(); this is because in dup*() we need to close with + * locks already held to avoid races. */ +int unlocked_close(int fd) +{ + int r; + + if (*fd_table[fd].refcount > 1) { + /* we still have references, don't really close */ + printd("not closing, refcount: %d\n", *fd_table[fd].refcount); + (*fd_table[fd].refcount)--; + fd_table[fd].fd = -1; + fd_table[fd].refcount = NULL; + fd_table[fd].fs = NULL; + return 0; + } + + rec_inc(); + r = jclose(fd_table[fd].fs); + rec_dec(); + + if (fd_table[fd].fs != NULL) { + fd_table[fd].fd = -1; + free(fd_table[fd].refcount); + fd_table[fd].refcount = NULL; + free(fd_table[fd].fs); + fd_table[fd].fs = NULL; + } + + return r; +} int close(int fd) { @@ -357,14 +399,7 @@ int close(int fd) } printd("libjio\n"); - rec_inc(); - r = jclose(fs); - if (fd_table[fd].fs != NULL) { - free(fd_table[fd].fs); - fd_table[fd].fd = -1; - fd_table[fd].fs = NULL; - } - rec_dec(); + r = unlocked_close(fd); fd_unlock(fd); printd("return %d\n", r); @@ -393,6 +428,89 @@ int unlink(const char *pathname) return r; } +int dup(int oldfd) +{ + int r; + + if (called) { + printd("orig\n"); + return (*c_dup)(oldfd); + } + + if (fd_table[oldfd].fs == NULL) { + printd("NULL fs, fd %d\n", oldfd); + fd_unlock(oldfd); + return (*c_dup)(oldfd); + } + + if (!fd_lock(oldfd)) { + printd("out of bounds fd: %d\n", oldfd); + return -1; + } + + printd("libjio\n"); + + rec_inc(); + r = (*c_dup)(oldfd); + rec_dec(); + + if (r >= 0) { + fd_lock(r); + fd_table[r].fd = r; + fd_table[r].refcount = fd_table[oldfd].refcount; + (*fd_table[r].refcount)++; + fd_table[r].fs = fd_table[oldfd].fs; + fd_unlock(r); + } + + fd_unlock(oldfd); + printd("return %d\n", r); + return r; +} + +int dup2(int oldfd, int newfd) +{ + int r; + + if (called) { + printd("orig\n"); + return (*c_dup2)(oldfd, newfd); + } + + if (!fd_lock(oldfd)) { + printd("out of bounds fd: %d\n", oldfd); + return -1; + } + + if (fd_table[oldfd].fs == NULL) { + printd("NULL fs, fd %d\n", oldfd); + fd_unlock(oldfd); + return (*c_dup2)(oldfd, newfd); + } + + printd("libjio\n"); + + rec_inc(); + r = (*c_dup2)(oldfd, newfd); + rec_dec(); + + if (r >= 0) { + fd_lock(newfd); + if (fd_table[newfd].fs != NULL) { + unlocked_close(newfd); + } + fd_table[newfd].fd = newfd; + fd_table[newfd].refcount = fd_table[oldfd].refcount; + (*fd_table[newfd].refcount)++; + fd_table[newfd].fs = fd_table[oldfd].fs; + fd_unlock(newfd); + } + + fd_unlock(oldfd); + printd("return %d\n", r); + return r; +} + /* the rest of the functions are automagically generated from the following * macro. The ugliest. I'm so proud. */