#include <roken.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <string.h>
-#ifdef AFS_NT40_ENV
-#include <fcntl.h>
-#else
-#include <sys/file.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#if defined(AFS_SUN5_ENV) || defined(AFS_NBSD_ENV)
-#include <sys/fcntl.h>
+#include <limits.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
-#endif
#include <rx/xdr.h>
#include <afs/afsint.h>
-#include <errno.h>
#include <afs/afssyscalls.h>
+#include <afs/afsutil.h>
+
#include "nfs.h"
#include "ihandle.h"
#include "viceinode.h"
#include "afs/afs_assert.h"
-#include <limits.h>
#ifdef AFS_PTHREAD_ENV
pthread_once_t ih_glock_once = PTHREAD_ONCE_INIT;
/* Hash table for inode handles */
IHashBucket_t ihashTable[I_HANDLE_HASH_SIZE];
+static int _ih_release_r(IHandle_t * ihP);
void *ih_sync_thread(void *);
/* start-time configurable I/O limits */
/* 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) {
- osi_Assert(fdP->fd_status == FD_HANDLE_OPEN);
+ if (fdP->fd_status == FD_HANDLE_INUSE) {
+ continue;
+ }
+ osi_Assert(fdP->fd_status == FD_HANDLE_OPEN);
#else /* HAVE_PIO */
- if (fdP->fd_status != FD_HANDLE_AVAIL) {
+ osi_Assert(fdP->fd_status != FD_HANDLE_AVAIL);
#endif /* HAVE_PIO */
- fdP->fd_refcnt++;
- if (fdP->fd_status == FD_HANDLE_OPEN) {
+
+ 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;
}
+ ihP->ih_refcnt++;
+ IH_UNLOCK;
+ return fdP;
}
/*
IH_LOCK;
osi_Assert(ih_Inited);
osi_Assert(fdInUseCount > 0);
- osi_Assert(fdP->fd_status == FD_HANDLE_INUSE);
+ osi_Assert(fdP->fd_status == FD_HANDLE_INUSE ||
+ fdP->fd_status == FD_HANDLE_CLOSING);
ihP = fdP->fd_ih;
* failed (this is determined by checking the ihandle for the flag
* IH_REALLY_CLOSED) or we have too many open files.
*/
- if (ihP->ih_flags & IH_REALLY_CLOSED || fdInUseCount > fdCacheSize) {
+ if (fdP->fd_status == FD_HANDLE_CLOSING ||
+ ihP->ih_flags & IH_REALLY_CLOSED || fdInUseCount > fdCacheSize) {
IH_UNLOCK;
return fd_reallyclose(fdP);
}
/* If this is not the only reference to the Inode then we can decrement
* the reference count, otherwise we need to call ih_release.
*/
- if (ihP->ih_refcnt > 1) {
+ if (ihP->ih_refcnt > 1)
ihP->ih_refcnt--;
- IH_UNLOCK;
- } else {
- IH_UNLOCK;
- ih_release(ihP);
- }
+ else
+ _ih_release_r(ihP);
+
+ IH_UNLOCK;
return 0;
}
IH_LOCK;
osi_Assert(ih_Inited);
osi_Assert(fdInUseCount > 0);
- osi_Assert(fdP->fd_status == FD_HANDLE_INUSE);
+ osi_Assert(fdP->fd_status == FD_HANDLE_INUSE ||
+ fdP->fd_status == FD_HANDLE_CLOSING);
ihP = fdP->fd_ih;
closeFd = fdP->fd_fd;
/* If this is not the only reference to the Inode then we can decrement
* the reference count, otherwise we need to call ih_release. */
- if (ihP->ih_refcnt > 1) {
+ if (ihP->ih_refcnt > 1)
ihP->ih_refcnt--;
- IH_UNLOCK;
- } else {
- IH_UNLOCK;
- ih_release(ihP);
- }
+ else
+ _ih_release_r(ihP);
+
+ IH_UNLOCK;
return 0;
}
next = fdP->fd_ihnext;
osi_Assert(fdP->fd_ih == ihP);
osi_Assert(fdP->fd_status == FD_HANDLE_OPEN
- || fdP->fd_status == FD_HANDLE_INUSE);
+ || fdP->fd_status == FD_HANDLE_INUSE
+ || fdP->fd_status == FD_HANDLE_CLOSING);
if (fdP->fd_status == FD_HANDLE_OPEN) {
DLL_DELETE(fdP, ihP->ih_fdhead, ihP->ih_fdtail, fd_ihnext,
fd_ihprev);
DLL_INSERT_TAIL(fdP, head, tail, fd_next, fd_prev);
} else {
closedAll = 0;
+ fdP->fd_status = FD_HANDLE_CLOSING;
ihP->ih_flags |= IH_REALLY_CLOSED;
}
}
ih_fdclose(ihP);
- if (ihP->ih_refcnt > 1) {
+ if (ihP->ih_refcnt > 1)
ihP->ih_refcnt--;
- IH_UNLOCK;
- } else {
- IH_UNLOCK;
- ih_release(ihP);
- }
+ else
+ _ih_release_r(ihP);
+
+ IH_UNLOCK;
return 0;
}
/* Release an Inode handle. All cached file descriptors for this
* inode are closed when the last reference to this handle is released
*/
-int
-ih_release(IHandle_t * ihP)
+static int
+_ih_release_r(IHandle_t * ihP)
{
int ihash;
if (!ihP)
return 0;
- IH_LOCK;
osi_Assert(ihP->ih_refcnt > 0);
if (ihP->ih_refcnt > 1) {
ihP->ih_refcnt--;
- IH_UNLOCK;
return 0;
}
DLL_INSERT_TAIL(ihP, ihAvailHead, ihAvailTail, ih_next, ih_prev);
- IH_UNLOCK;
return 0;
}
+/* Release an Inode handle. All cached file descriptors for this
+ * inode are closed when the last reference to this handle is released
+ */
+int
+ih_release(IHandle_t * ihP)
+{
+ int ret;
+
+ if (!ihP)
+ return 0;
+
+ IH_LOCK;
+ ret = _ih_release_r(ihP);
+ IH_UNLOCK;
+ return ret;
+}
+
/* Sync an inode to disk if its handle isn't NULL */
int
ih_condsync(IHandle_t * ihP)
ihPnext = ihP->ih_next;
if (ihPnext) ihPnext->ih_refcnt++;
- if (ihP->ih_refcnt > 1) {
+ if (ihP->ih_refcnt > 1)
ihP->ih_refcnt--;
- } else {
- IH_UNLOCK;
- ih_release(ihP);
- IH_LOCK;
- }
-
+ else
+ _ih_release_r(ihP);
}
}
IH_UNLOCK;
void *
ih_sync_thread(void *dummy) {
+ afs_pthread_setname_self("ih_syncer");
while(1) {
#ifdef AFS_PTHREAD_ENV