From 2c619d2105ed3d0846640a48c0c4a8d687691c8d Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Thu, 30 May 2013 17:52:32 -0500 Subject: [PATCH] ihandle: Refactor ih_open to split out ih_attachfd Refactor the function ih_open, so part of its logic gets split out into the new ih_attachfd_r (and ih_attachfd) function. This allows other code to splice in an existing fd, without going through the normal "open" path. This patch should incur no functional change; it is just code reorganization. Reviewed-on: http://gerrit.openafs.org/9968 Tested-by: BuildBot Reviewed-by: Derrick Brashear (cherry picked from commit f40e20d5671310500fb4f6acf38980e158a74c66) Change-Id: I40bb515b5c822c3be3d3819c0183091753c41dea Reviewed-on: http://gerrit.openafs.org/10176 Reviewed-by: Derrick Brashear Tested-by: BuildBot Reviewed-by: Mark Vitale Reviewed-by: Andrew Deason Reviewed-by: Stephan Wiesand --- src/vol/ihandle.c | 142 ++++++++++++++++++++++++++++++---------------- src/vol/ihandle.h | 1 + 2 files changed, 93 insertions(+), 50 deletions(-) diff --git a/src/vol/ihandle.c b/src/vol/ihandle.c index 80c9c229f..ab7bbd67f 100644 --- a/src/vol/ihandle.c +++ b/src/vol/ihandle.c @@ -354,6 +354,93 @@ streamHandleAllocateChunk(void) } } +/* + * Get a file descriptor handle given an Inode handle + * Takes the given file descriptor, and creates a new FdHandle_t for it, + * attached to the given IHandle_t. fd can be INVALID_FD, indicating that the + * caller failed to open the relevant file because we had too many FDs open; + * ih_attachfd_r will then just evict/close an existing fd in the cache, and + * return NULL. + */ +static FdHandle_t * +ih_attachfd_r(IHandle_t *ihP, FD_t fd) +{ + FD_t closeFd; + FdHandle_t *fdP; + + /* fdCacheSize limits the size of the descriptor cache, but + * we permit the number of open files to exceed fdCacheSize. + * We only recycle open file descriptors when the number + * of open files reaches the size of the cache */ + if ((fdInUseCount > fdCacheSize || fd == INVALID_FD) && fdLruHead != NULL) { + fdP = fdLruHead; + osi_Assert(fdP->fd_status == FD_HANDLE_OPEN); + DLL_DELETE(fdP, fdLruHead, fdLruTail, fd_next, fd_prev); + DLL_DELETE(fdP, fdP->fd_ih->ih_fdhead, fdP->fd_ih->ih_fdtail, + fd_ihnext, fd_ihprev); + closeFd = fdP->fd_fd; + if (fd == INVALID_FD) { + fdCacheSize--; /* reduce in order to not run into here too often */ + DLL_INSERT_TAIL(fdP, fdAvailHead, fdAvailTail, fd_next, fd_prev); + fdP->fd_status = FD_HANDLE_AVAIL; + fdP->fd_ih = NULL; + fdP->fd_fd = INVALID_FD; + IH_UNLOCK; + OS_CLOSE(closeFd); + IH_LOCK; + fdInUseCount -= 1; + return NULL; + } + } else { + if (fdAvailHead == NULL) { + fdHandleAllocateChunk(); + } + fdP = fdAvailHead; + osi_Assert(fdP->fd_status == FD_HANDLE_AVAIL); + DLL_DELETE(fdP, fdAvailHead, fdAvailTail, fd_next, fd_prev); + closeFd = INVALID_FD; + } + + fdP->fd_status = FD_HANDLE_INUSE; + fdP->fd_fd = fd; + fdP->fd_ih = ihP; + fdP->fd_refcnt++; + + ihP->ih_refcnt++; + + /* Add this handle to the Inode's list of open descriptors */ + DLL_INSERT_TAIL(fdP, ihP->ih_fdhead, ihP->ih_fdtail, fd_ihnext, + fd_ihprev); + + if (closeFd != INVALID_FD) { + IH_UNLOCK; + OS_CLOSE(closeFd); + IH_LOCK; + fdInUseCount -= 1; + } + + return fdP; +} + +FdHandle_t * +ih_attachfd(IHandle_t *ihP, FD_t fd) +{ + FdHandle_t *fdP; + + IH_LOCK; + + fdInUseCount += 1; + + fdP = ih_attachfd_r(ihP, fd); + if (!fdP) { + fdInUseCount -= 1; + } + + IH_UNLOCK; + + return fdP; +} + /* * Get a file descriptor handle given an Inode handle */ @@ -362,7 +449,6 @@ ih_open(IHandle_t * ihP) { FdHandle_t *fdP; FD_t fd; - FD_t closeFd; if (!ihP) /* XXX should log here in the fileserver */ return NULL; @@ -413,59 +499,15 @@ ih_open_retry: return NULL; } - /* fdCacheSize limits the size of the descriptor cache, but - * we permit the number of open files to exceed fdCacheSize. - * We only recycle open file descriptors when the number - * of open files reaches the size of the cache */ - if ((fdInUseCount > fdCacheSize || fd == INVALID_FD) && fdLruHead != NULL) { - fdP = fdLruHead; - osi_Assert(fdP->fd_status == FD_HANDLE_OPEN); - DLL_DELETE(fdP, fdLruHead, fdLruTail, fd_next, fd_prev); - DLL_DELETE(fdP, fdP->fd_ih->ih_fdhead, fdP->fd_ih->ih_fdtail, - fd_ihnext, fd_ihprev); - closeFd = fdP->fd_fd; - if (fd == INVALID_FD) { - fdCacheSize--; /* reduce in order to not run into here too often */ - DLL_INSERT_TAIL(fdP, fdAvailHead, fdAvailTail, fd_next, fd_prev); - fdP->fd_status = FD_HANDLE_AVAIL; - fdP->fd_ih = NULL; - fdP->fd_fd = INVALID_FD; - IH_UNLOCK; - OS_CLOSE(closeFd); - IH_LOCK; - fdInUseCount -= 1; - IH_UNLOCK; - goto ih_open_retry; - } - } else { - if (fdAvailHead == NULL) { - fdHandleAllocateChunk(); - } - fdP = fdAvailHead; - osi_Assert(fdP->fd_status == FD_HANDLE_AVAIL); - DLL_DELETE(fdP, fdAvailHead, fdAvailTail, fd_next, fd_prev); - closeFd = INVALID_FD; - } - - fdP->fd_status = FD_HANDLE_INUSE; - fdP->fd_fd = fd; - fdP->fd_ih = ihP; - fdP->fd_refcnt++; - - ihP->ih_refcnt++; - - /* Add this handle to the Inode's list of open descriptors */ - DLL_INSERT_TAIL(fdP, ihP->ih_fdhead, ihP->ih_fdtail, fd_ihnext, - fd_ihprev); - - if (closeFd != INVALID_FD) { + fdP = ih_attachfd_r(ihP, fd); + if (!fdP) { + osi_Assert(fd == INVALID_FD); IH_UNLOCK; - OS_CLOSE(closeFd); - IH_LOCK; - fdInUseCount -= 1; + goto ih_open_retry; } IH_UNLOCK; + return fdP; } diff --git a/src/vol/ihandle.h b/src/vol/ihandle.h index 718d9ae42..e7b9b7e7b 100644 --- a/src/vol/ihandle.h +++ b/src/vol/ihandle.h @@ -342,6 +342,7 @@ extern int stream_close(StreamHandle_t * streamP, int reallyClose); extern int ih_reallyclose(IHandle_t * ihP); extern int ih_release(IHandle_t * ihP); extern int ih_condsync(IHandle_t * ihP); +extern FdHandle_t *ih_attachfd(IHandle_t * ihP, FD_t fd); /* Macros common to user space and inode API's. */ #define IH_INIT(H, D, V, I) ((H) = ih_init((D), (V), (I))) -- 2.39.5