Esempio n. 1
0
/*
 * 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;

    IH_LOCK;

    /* Do we already have an open file handle for this Inode? */
    for (fdP = ihP->ih_fdtail; fdP != NULL; fdP = fdP->fd_ihprev) {
	if (fdP->fd_status == FD_HANDLE_CLOSING) {
	    /* The handle was open when an IH_REALLYCLOSE was issued, so we
	     * cannot reuse it; it will be closed soon. */
	    continue;
	}
#ifndef HAVE_PIO
	/*
	 * If we don't have positional i/o, don't try to share fds, since
	 * we can't do so in a threadsafe way.
	 */
	if (fdP->fd_status == FD_HANDLE_INUSE) {
	    continue;
	}
	osi_Assert(fdP->fd_status == FD_HANDLE_OPEN);
#else /* HAVE_PIO */
	osi_Assert(fdP->fd_status != FD_HANDLE_AVAIL);
#endif /* HAVE_PIO */

	fdP->fd_refcnt++;
	if (fdP->fd_status == FD_HANDLE_OPEN) {
	    fdP->fd_status = FD_HANDLE_INUSE;
	    DLL_DELETE(fdP, fdLruHead, fdLruTail, fd_next, fd_prev);
	}
	ihP->ih_refcnt++;
	IH_UNLOCK;
	return fdP;
    }

    /*
     * Try to open the Inode, return NULL on error.
     */
    fdInUseCount += 1;
    IH_UNLOCK;
ih_open_retry:
    fd = OS_IOPEN(ihP);
    IH_LOCK;
    if (fd == INVALID_FD && (errno != EMFILE || fdLruHead == NULL) ) {
	fdInUseCount -= 1;
	IH_UNLOCK;
	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);
	    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) {
	IH_UNLOCK;
	OS_CLOSE(closeFd);
	IH_LOCK;
	fdInUseCount -= 1;
    }

    IH_UNLOCK;
    return fdP;
}
Esempio n. 2
0
/*
 * 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;

    IH_LOCK;

    /* Do we already have an open file handle for this Inode? */
    for (fdP = ihP->ih_fdtail; fdP != NULL; fdP = fdP->fd_ihprev) {
	if (fdP->fd_status != FD_HANDLE_INUSE) {
	    assert(fdP->fd_status == FD_HANDLE_OPEN);
	    fdP->fd_status = FD_HANDLE_INUSE;
	    DLL_DELETE(fdP, fdLruHead, fdLruTail, fd_next, fd_prev);
	    ihP->ih_refcnt++;
	    IH_UNLOCK;
	    (void)FDH_SEEK(fdP, 0, SEEK_SET);
	    return fdP;
	}
    }

    /*
     * Try to open the Inode, return NULL on error.
     */
    fdInUseCount += 1;
    IH_UNLOCK;
ih_open_retry:
    fd = OS_IOPEN(ihP);
    IH_LOCK;
    if (fd == INVALID_FD && (errno != EMFILE || fdLruHead == NULL) ) {
	fdInUseCount -= 1;
	IH_UNLOCK;
	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;
	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);
	    goto ih_open_retry;
	}
    } else {
	if (fdAvailHead == NULL) {
	    fdHandleAllocateChunk();
	}
	fdP = fdAvailHead;
	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;

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

    IH_UNLOCK;
    return fdP;
}