/*
* 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;
+ opr_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;
+ opr_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
*/
FdHandle_t *
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;
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;
- opr_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;
- opr_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) {
+ opr_Assert(fd == INVALID_FD);
IH_UNLOCK;
- OS_CLOSE(closeFd);
- IH_LOCK;
- fdInUseCount -= 1;
+ goto ih_open_retry;
}
IH_UNLOCK;
+
return fdP;
}