-
-#ifndef lint
-#endif
-
/*
- * COPYRIGHT (C) Transarc Corporation 1998
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
*/
-/************************************************************************/
-/* */
+
/* ihandle.c - file descriptor cacheing for Inode handles. */
/* */
/************************************************************************/
+#include <afsconfig.h>
#include <afs/param.h>
+
+RCSID
+ ("$Header$");
+
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/file.h>
#include <unistd.h>
#include <sys/stat.h>
-#ifdef AFS_SUN5_ENV
+#if defined(AFS_SUN5_ENV) || defined(AFS_NBSD_ENV)
#include <sys/fcntl.h>
#include <sys/resource.h>
#endif
#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
#include <rx/xdr.h>
#include <afs/afsint.h>
#include <errno.h>
#include <afs/afssyscalls.h>
-#include "ihandle.h"
#include "nfs.h"
+#include "ihandle.h"
#include "viceinode.h"
#ifdef AFS_PTHREAD_ENV
#include <assert.h>
#endif /* AFS_PTHREAD_ENV */
#include <limits.h>
-extern afs_int32 DErrno;
+#ifndef AFS_NT40_ENV
+#ifdef O_LARGEFILE
+#define afs_stat stat64
+#define afs_fstat fstat64
+#else /* !O_LARGEFILE */
+#define afs_stat stat
+#define afs_fstat fstat
+#endif /* !O_LARGEFILE */
+#endif /* AFS_NT40_ENV */
#ifdef AFS_PTHREAD_ENV
pthread_once_t ih_glock_once = PTHREAD_ONCE_INIT;
#ifdef AFS_PTHREAD_ENV
/* Initialize the global ihandle mutex */
-void ih_glock_init()
+void
+ih_glock_init()
{
assert(pthread_mutex_init(&ih_glock_mutex, NULL) == 0);
}
#endif /* AFS_PTHREAD_ENV */
/* Initialize the file descriptor cache */
-void ih_Initialize() {
+void
+ih_Initialize(void)
+{
int i;
-#ifdef AFS_SUN5_ENV
- struct rlimit rlim;
-#endif /* AFS_SUN5_ENV */
assert(!ih_Inited);
ih_Inited = 1;
DLL_INIT_LIST(ihAvailHead, ihAvailTail);
DLL_INIT_LIST(fdAvailHead, fdAvailTail);
DLL_INIT_LIST(fdLruHead, fdLruTail);
- for (i = 0 ; i < I_HANDLE_HASH_SIZE ; i++) {
+ for (i = 0; i < I_HANDLE_HASH_SIZE; i++) {
DLL_INIT_LIST(ihashTable[i].ihash_head, ihashTable[i].ihash_tail);
}
#if defined(AFS_NT40_ENV)
fdMaxCacheSize = FD_MAX_CACHESIZE;
-#elif defined(AFS_SUN5_ENV)
- assert(getrlimit(RLIMIT_NOFILE, &rlim) == 0);
- rlim.rlim_cur = rlim.rlim_max;
- assert(setrlimit(RLIMIT_NOFILE, &rlim) == 0);
- fdMaxCacheSize = rlim.rlim_cur-FD_HANDLE_SETASIDE;
- fdMaxCacheSize = MIN(fdMaxCacheSize, FD_MAX_CACHESIZE);
- assert(fdMaxCacheSize > 0);
+#elif defined(AFS_SUN5_ENV) || defined(AFS_NBSD_ENV)
+ {
+ struct rlimit rlim;
+ assert(getrlimit(RLIMIT_NOFILE, &rlim) == 0);
+ rlim.rlim_cur = rlim.rlim_max;
+ assert(setrlimit(RLIMIT_NOFILE, &rlim) == 0);
+ fdMaxCacheSize = rlim.rlim_cur - FD_HANDLE_SETASIDE;
+#ifdef AFS_NBSD_ENV
+ /* XXX this is to avoid using up all system fd netbsd is
+ * somewhat broken and have set maximum fd for a root process
+ * to the same as system fd that is avaible, so if the
+ * fileserver uses all up process fds, all system fd will be
+ * used up too !
+ *
+ * Check for this better
+ */
+ fdMaxCacheSize /= 4;
+#endif
+ fdMaxCacheSize = MIN(fdMaxCacheSize, FD_MAX_CACHESIZE);
+ assert(fdMaxCacheSize > 0);
+ }
#elif defined(AFS_HPUX_ENV)
/* Avoid problems with "UFSOpen: igetinode failed" panics on HPUX 11.0 */
fdMaxCacheSize = 0;
#else
- fdMaxCacheSize = MAX(sysconf(_SC_OPEN_MAX)-FD_HANDLE_SETASIDE, 0);
- fdMaxCacheSize = MIN(fdMaxCacheSize, FD_MAX_CACHESIZE);
+ {
+ long fdMax = MAX(sysconf(_SC_OPEN_MAX) - FD_HANDLE_SETASIDE, 0);
+ fdMaxCacheSize = (int)MIN(fdMax, FD_MAX_CACHESIZE);
+ }
#endif
fdCacheSize = MIN(fdMaxCacheSize, FD_DEFAULT_CACHESIZE);
}
/* Make the file descriptor cache as big as possible. Don't this call
* if the program uses fopen or fdopen. */
-void ih_UseLargeCache() {
- IH_LOCK
-
+void
+ih_UseLargeCache(void)
+{
+ IH_LOCK;
if (!ih_Inited) {
ih_Initialize();
}
fdCacheSize = fdMaxCacheSize;
- IH_UNLOCK
+ IH_UNLOCK;
}
/* Allocate a chunk of inode handles */
-void iHandleAllocateChunk()
+void
+iHandleAllocateChunk(void)
{
int i;
IHandle_t *ihP;
assert(ihAvailHead == NULL);
- ihP = (IHandle_t *)malloc(I_HANDLE_MALLOCSIZE * sizeof(IHandle_t));
+ ihP = (IHandle_t *) malloc(I_HANDLE_MALLOCSIZE * sizeof(IHandle_t));
assert(ihP != NULL);
- for (i = 0 ; i < I_HANDLE_MALLOCSIZE ; i++) {
+ for (i = 0; i < I_HANDLE_MALLOCSIZE; i++) {
ihP[i].ih_refcnt = 0;
DLL_INSERT_TAIL(&ihP[i], ihAvailHead, ihAvailTail, ih_next, ih_prev);
}
}
/* Initialize an inode handle */
-IHandle_t *ih_init(int dev, int vid, Inode ino)
+IHandle_t *
+ih_init(int dev, int vid, Inode ino)
{
int ihash = IH_HASH(dev, vid, ino);
IHandle_t *ihP;
- IH_LOCK
-
+ IH_LOCK;
if (!ih_Inited) {
ih_Initialize();
}
/* Do we already have a handle for this Inode? */
- for (ihP = ihashTable[ihash].ihash_head ; ihP ; ihP = ihP->ih_next) {
+ for (ihP = ihashTable[ihash].ihash_head; ihP; ihP = ihP->ih_next) {
if (ihP->ih_ino == ino && ihP->ih_vid == vid && ihP->ih_dev == dev) {
ihP->ih_refcnt++;
- IH_UNLOCK
+ IH_UNLOCK;
return ihP;
}
}
DLL_INIT_LIST(ihP->ih_fdhead, ihP->ih_fdtail);
DLL_INSERT_TAIL(ihP, ihashTable[ihash].ihash_head,
ihashTable[ihash].ihash_tail, ih_next, ih_prev);
- IH_UNLOCK
+ IH_UNLOCK;
return ihP;
}
/* Copy an inode handle */
-IHandle_t *ih_copy(IHandle_t *ihP)
+IHandle_t *
+ih_copy(IHandle_t * ihP)
{
- IH_LOCK
+ IH_LOCK;
assert(ih_Inited);
assert(ihP->ih_refcnt > 0);
ihP->ih_refcnt++;
- IH_UNLOCK
+ IH_UNLOCK;
return ihP;
}
/* Allocate a chunk of file descriptor handles */
-void fdHandleAllocateChunk()
+void
+fdHandleAllocateChunk(void)
{
int i;
FdHandle_t *fdP;
assert(fdAvailHead == NULL);
- fdP = (FdHandle_t *)malloc(FD_HANDLE_MALLOCSIZE * sizeof(FdHandle_t));
+ fdP = (FdHandle_t *) malloc(FD_HANDLE_MALLOCSIZE * sizeof(FdHandle_t));
assert(fdP != NULL);
- for (i = 0 ; i < FD_HANDLE_MALLOCSIZE ; i++) {
+ for (i = 0; i < FD_HANDLE_MALLOCSIZE; i++) {
fdP[i].fd_status = FD_HANDLE_AVAIL;
fdP[i].fd_ih = NULL;
fdP[i].fd_fd = INVALID_FD;
}
/* Allocate a chunk of stream handles */
-void streamHandleAllocateChunk()
+void
+streamHandleAllocateChunk(void)
{
int i;
StreamHandle_t *streamP;
assert(streamAvailHead == NULL);
streamP = (StreamHandle_t *)
- malloc(STREAM_HANDLE_MALLOCSIZE * sizeof(StreamHandle_t));
+ malloc(STREAM_HANDLE_MALLOCSIZE * sizeof(StreamHandle_t));
assert(streamP != NULL);
- for (i = 0 ; i < STREAM_HANDLE_MALLOCSIZE ; i++) {
+ for (i = 0; i < STREAM_HANDLE_MALLOCSIZE; i++) {
streamP[i].str_fd = INVALID_FD;
DLL_INSERT_TAIL(&streamP[i], streamAvailHead, streamAvailTail,
str_next, str_prev);
/*
* Get a file descriptor handle given an Inode handle
*/
-FdHandle_t *ih_open(IHandle_t *ihP)
+FdHandle_t *
+ih_open(IHandle_t * ihP)
{
FdHandle_t *fdP;
FD_t fd;
FD_t closeFd;
- IH_LOCK
+ if (!ihP) /* XXX should log here in the fileserver */
+ return NULL;
- if (!ih_Inited) {
- ih_Initialize();
- }
+ IH_LOCK;
/* Do we already have an open file handle for this Inode? */
- for (fdP = ihP->ih_fdtail ; fdP != NULL ; fdP = fdP->fd_ihprev) {
+ 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
- FDH_SEEK(fdP, 0, SEEK_SET);
+ 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_UNLOCK;
fd = OS_IOPEN(ihP);
- IH_LOCK
+ IH_LOCK;
if (fd == INVALID_FD) {
fdInUseCount -= 1;
- IH_UNLOCK
+ IH_UNLOCK;
return NULL;
}
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);
+ DLL_INSERT_TAIL(fdP, ihP->ih_fdhead, ihP->ih_fdtail, fd_ihnext,
+ fd_ihprev);
if (closeFd != INVALID_FD) {
- IH_UNLOCK
+ IH_UNLOCK;
OS_CLOSE(closeFd);
- IH_LOCK
+ IH_LOCK;
fdInUseCount -= 1;
}
- ihP->ih_refcnt++;
- IH_UNLOCK
+ IH_UNLOCK;
return fdP;
}
/*
* Return a file descriptor handle to the cache
*/
-int fd_close(FdHandle_t *fdP)
+int
+fd_close(FdHandle_t * fdP)
{
- FD_t closeFd;
IHandle_t *ihP;
if (!fdP)
return 0;
- IH_LOCK
+ IH_LOCK;
assert(ih_Inited);
assert(fdInUseCount > 0);
assert(fdP->fd_status == FD_HANDLE_INUSE);
ihP = fdP->fd_ih;
- /* If a previous attempt to close ( ih_reallyclose() )
- * all fd handles failed, then the IH_REALLY_CLOSED flag is set in
- * the Inode handle so we call fd_reallyclose
+ /* Call fd_reallyclose to really close the unused file handles if
+ * the previous attempt to close (ih_reallyclose()) all file handles
+ * 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 ) {
- IH_UNLOCK
- return (fd_reallyclose(fdP));
- }
-
- /* If we have too many open files then close the descriptor. If we
- * hold the last reference to the Inode handle then wait and let
- * ih_release do the work. */
- if (fdInUseCount > fdCacheSize && ihP->ih_refcnt > 1) {
- assert(fdInUseCount > 0);
- closeFd = fdP->fd_fd;
- DLL_DELETE(fdP, fdP->fd_ih->ih_fdhead, fdP->fd_ih->ih_fdtail,
- fd_ihnext, fd_ihprev);
- 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;
- ihP->ih_refcnt--;
- IH_UNLOCK
- OS_CLOSE(closeFd);
- IH_LOCK
- fdInUseCount -= 1;
- IH_UNLOCK
- return 0;
+ if (ihP->ih_flags & IH_REALLY_CLOSED || fdInUseCount > fdCacheSize) {
+ IH_UNLOCK;
+ return fd_reallyclose(fdP);
}
/* Put this descriptor back into the cache */
DLL_INSERT_TAIL(fdP, fdLruHead, fdLruTail, fd_next, fd_prev);
/* If this is not the only reference to the Inode then we can decrement
- * the reference count, otherwise we need to call ih_release. */
+ * the reference count, otherwise we need to call ih_release.
+ */
if (ihP->ih_refcnt > 1) {
ihP->ih_refcnt--;
- IH_UNLOCK
+ IH_UNLOCK;
} else {
- IH_UNLOCK
+ IH_UNLOCK;
ih_release(ihP);
}
}
/*
- * Return a file descriptor handle to the cache
+ * Actually close the file descriptor handle and return it to
+ * the free list.
*/
-int fd_reallyclose(FdHandle_t *fdP)
+int
+fd_reallyclose(FdHandle_t * fdP)
{
FD_t closeFd;
IHandle_t *ihP;
if (!fdP)
return 0;
- IH_LOCK
+ IH_LOCK;
assert(ih_Inited);
assert(fdInUseCount > 0);
assert(fdP->fd_status == FD_HANDLE_INUSE);
ihP = fdP->fd_ih;
closeFd = fdP->fd_fd;
- DLL_DELETE(fdP, fdP->fd_ih->ih_fdhead, fdP->fd_ih->ih_fdtail,
- fd_ihnext, fd_ihprev);
+ DLL_DELETE(fdP, ihP->ih_fdhead, ihP->ih_fdtail, fd_ihnext, fd_ihprev);
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
+
+ /* All the file descriptor handles have been closed; reset
+ * the IH_REALLY_CLOSED flag indicating that ih_reallyclose
+ * has completed its job.
+ */
+ if (!ihP->ih_fdhead) {
+ ihP->ih_flags &= ~IH_REALLY_CLOSED;
+ }
+
+ IH_UNLOCK;
OS_CLOSE(closeFd);
- IH_LOCK
+ IH_LOCK;
fdInUseCount -= 1;
/* 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) {
ihP->ih_refcnt--;
- IH_UNLOCK
+ IH_UNLOCK;
} else {
- IH_UNLOCK
+ IH_UNLOCK;
ih_release(ihP);
}
+
return 0;
}
/* Enable buffered I/O on a file descriptor */
-StreamHandle_t *stream_fdopen(FD_t fd)
+StreamHandle_t *
+stream_fdopen(FD_t fd)
{
StreamHandle_t *streamP;
- IH_LOCK
+ IH_LOCK;
if (streamAvailHead == NULL) {
streamHandleAllocateChunk();
}
streamP = streamAvailHead;
DLL_DELETE(streamP, streamAvailHead, streamAvailTail, str_next, str_prev);
- IH_UNLOCK
-
+ IH_UNLOCK;
streamP->str_fd = fd;
streamP->str_buflen = 0;
streamP->str_bufoff = 0;
}
/* Open a file for buffered I/O */
-StreamHandle_t *stream_open(char *filename, char *mode)
+StreamHandle_t *
+stream_open(const char *filename, const char *mode)
{
FD_t fd;
} else if (strcmp(mode, "r+") == 0) {
fd = OS_OPEN(filename, O_RDWR, 0);
} else if (strcmp(mode, "w") == 0) {
- fd = OS_OPEN(filename, O_WRONLY|O_TRUNC|O_CREAT, 0);
+ fd = OS_OPEN(filename, O_WRONLY | O_TRUNC | O_CREAT, 0);
} else if (strcmp(mode, "w+") == 0) {
- fd = OS_OPEN(filename, O_RDWR|O_TRUNC|O_CREAT, 0);
+ fd = OS_OPEN(filename, O_RDWR | O_TRUNC | O_CREAT, 0);
} else if (strcmp(mode, "a") == 0) {
- fd = OS_OPEN(filename, O_WRONLY|O_APPEND|O_CREAT, 0);
+ fd = OS_OPEN(filename, O_WRONLY | O_APPEND | O_CREAT, 0);
} else if (strcmp(mode, "a+") == 0) {
- fd = OS_OPEN(filename, O_RDWR|O_APPEND|O_CREAT, 0);
+ fd = OS_OPEN(filename, O_RDWR | O_APPEND | O_CREAT, 0);
} else {
- assert(FALSE); /* not implemented */
+ assert(FALSE); /* not implemented */
}
if (fd == INVALID_FD) {
}
/* fread for buffered I/O handles */
-int stream_read(void *ptr, int size, int nitems, StreamHandle_t *streamP)
+afs_sfsize_t
+stream_read(void *ptr, afs_fsize_t size, afs_fsize_t nitems,
+ StreamHandle_t * streamP)
{
- int nbytes, bytesRead, bytesToRead;
+ afs_fsize_t nbytes, bytesRead, bytesToRead;
char *p;
/* Need to seek before changing direction */
while (nbytes > 0 && !streamP->str_eof) {
if (streamP->str_buflen == 0) {
streamP->str_bufoff = 0;
- streamP->str_buflen = OS_READ(streamP->str_fd, streamP->str_buffer,
- STREAM_HANDLE_BUFSIZE);
+ streamP->str_buflen =
+ OS_READ(streamP->str_fd, streamP->str_buffer,
+ STREAM_HANDLE_BUFSIZE);
if (streamP->str_buflen < 0) {
streamP->str_error = errno;
streamP->str_buflen = 0;
if (bytesToRead > streamP->str_buflen) {
bytesToRead = streamP->str_buflen;
}
- memcpy(p, streamP->str_buffer+streamP->str_bufoff, bytesToRead);
+ memcpy(p, streamP->str_buffer + streamP->str_bufoff, bytesToRead);
p += bytesToRead;
streamP->str_bufoff += bytesToRead;
streamP->str_buflen -= bytesToRead;
nbytes -= bytesToRead;
}
- return (bytesRead/size);
+ return (bytesRead / size);
}
/* fwrite for buffered I/O handles */
-int stream_write(void *ptr, int size, int nitems, StreamHandle_t *streamP)
+afs_sfsize_t
+stream_write(void *ptr, afs_fsize_t size, afs_fsize_t nitems,
+ StreamHandle_t * streamP)
{
char *p;
- int rc, nbytes, bytesWritten, bytesToWrite;
+ afs_sfsize_t rc;
+ afs_fsize_t nbytes, bytesWritten, bytesToWrite;
/* Need to seek before changing direction */
if (streamP->str_direction == STREAM_DIRECTION_NONE) {
if (bytesToWrite > streamP->str_buflen) {
bytesToWrite = streamP->str_buflen;
}
- memcpy(streamP->str_buffer+streamP->str_bufoff, p, bytesToWrite);
+ memcpy(streamP->str_buffer + streamP->str_bufoff, p, bytesToWrite);
p += bytesToWrite;
streamP->str_bufoff += bytesToWrite;
streamP->str_buflen -= bytesToWrite;
nbytes -= bytesToWrite;
}
- return (bytesWritten/size);
+ return (bytesWritten / size);
}
/* fseek for buffered I/O handles */
-int stream_seek(StreamHandle_t *streamP, int offset, int whence)
+int
+stream_seek(StreamHandle_t * streamP, afs_foff_t offset, int whence)
{
int rc;
int retval = 0;
- if (streamP->str_direction == STREAM_DIRECTION_WRITE &&
- streamP->str_bufoff > 0) {
+ if (streamP->str_direction == STREAM_DIRECTION_WRITE
+ && streamP->str_bufoff > 0) {
rc = OS_WRITE(streamP->str_fd, streamP->str_buffer,
streamP->str_bufoff);
if (rc < 0) {
}
/* fflush for buffered I/O handles */
-int stream_flush(StreamHandle_t *streamP)
+int
+stream_flush(StreamHandle_t * streamP)
{
int rc;
int retval = 0;
- if (streamP->str_direction == STREAM_DIRECTION_WRITE &&
- streamP->str_bufoff > 0) {
+ if (streamP->str_direction == STREAM_DIRECTION_WRITE
+ && streamP->str_bufoff > 0) {
rc = OS_WRITE(streamP->str_fd, streamP->str_buffer,
streamP->str_bufoff);
if (rc < 0) {
}
/* Free a buffered I/O handle */
-int stream_close(StreamHandle_t *streamP, int reallyClose)
+int
+stream_close(StreamHandle_t * streamP, int reallyClose)
{
int rc;
int retval = 0;
assert(streamP != NULL);
- if (streamP->str_direction == STREAM_DIRECTION_WRITE &&
- streamP->str_bufoff > 0) {
+ if (streamP->str_direction == STREAM_DIRECTION_WRITE
+ && streamP->str_bufoff > 0) {
rc = OS_WRITE(streamP->str_fd, streamP->str_buffer,
streamP->str_bufoff);
if (rc < 0) {
}
streamP->str_fd = INVALID_FD;
- IH_LOCK
+ IH_LOCK;
DLL_INSERT_TAIL(streamP, streamAvailHead, streamAvailTail,
str_next, str_prev);
- IH_UNLOCK
-
+ IH_UNLOCK;
return retval;
}
-/* Close all cached file descriptors for this inode. */
-int ih_reallyclose(IHandle_t *ihP)
+/* Close all unused file descriptors associated with the inode
+ * handle. Called with IH_LOCK held. May drop and reacquire
+ * IH_LOCK. Sets the IH_REALLY_CLOSED flag in the inode handle
+ * if it fails to close all file handles.
+ */
+static int
+ih_fdclose(IHandle_t * ihP)
{
- int closeCount;
- FdHandle_t *fdP;
- FdHandle_t *head, *tail;
-
- if (!ihP)
- return 0;
-
- IH_LOCK
+ int closeCount, closedAll;
+ FdHandle_t *fdP, *head, *tail, *next;
assert(ihP->ih_refcnt > 0);
+ closedAll = 1;
+ DLL_INIT_LIST(head, tail);
+ ihP->ih_flags &= ~IH_REALLY_CLOSED;
+
/*
* Remove the file descriptors for this Inode from the LRU queue
- * and put them on a temporary queue so we drop the lock before
- * we close the files.
+ * and the IHandle queue and put them on a temporary queue so we
+ * can drop the lock before we close the files.
*/
- DLL_INIT_LIST(head, tail);
- for (fdP = ihP->ih_fdhead ; fdP != NULL ; fdP = fdP->fd_ihnext) {
+ for (fdP = ihP->ih_fdhead; fdP != NULL; fdP = next) {
+ next = fdP->fd_ihnext;
+ assert(fdP->fd_ih == ihP);
+ assert(fdP->fd_status == FD_HANDLE_OPEN
+ || fdP->fd_status == FD_HANDLE_INUSE);
if (fdP->fd_status == FD_HANDLE_OPEN) {
- assert(fdP->fd_ih == ihP);
+ DLL_DELETE(fdP, ihP->ih_fdhead, ihP->ih_fdtail, fd_ihnext,
+ fd_ihprev);
DLL_DELETE(fdP, fdLruHead, fdLruTail, fd_next, fd_prev);
DLL_INSERT_TAIL(fdP, head, tail, fd_next, fd_prev);
} else {
+ closedAll = 0;
ihP->ih_flags |= IH_REALLY_CLOSED;
}
}
-
- /*
- * If we found any file descriptors in use, then we dont zero out
- * fdhead and fdtail, since ih_reallyclose() will be called again on this
- * Inode handle
- */
- if ( ! (ihP->ih_flags & IH_REALLY_CLOSED) )
- DLL_INIT_LIST(ihP->ih_fdhead, ihP->ih_fdtail);
+ /* If the ihandle reference count is 1, we should have
+ * closed all file descriptors.
+ */
+ if (ihP->ih_refcnt == 1 || closedAll) {
+ assert(closedAll);
+ assert(!ihP->ih_fdhead);
+ assert(!ihP->ih_fdtail);
+ }
if (head == NULL) {
- IH_UNLOCK
- return 0;
+ return 0; /* No file descriptors closed */
}
+ IH_UNLOCK;
/*
* Close the file descriptors
*/
closeCount = 0;
- for (fdP = head ; fdP != NULL ; fdP = fdP->fd_ihnext) {
- IH_UNLOCK
+ for (fdP = head; fdP != NULL; fdP = fdP->fd_next) {
OS_CLOSE(fdP->fd_fd);
- IH_LOCK
- assert(fdInUseCount > 0);
- fdInUseCount -= 1;
fdP->fd_status = FD_HANDLE_AVAIL;
fdP->fd_fd = INVALID_FD;
fdP->fd_ih = NULL;
closeCount++;
}
+ IH_LOCK;
+ assert(fdInUseCount >= closeCount);
+ fdInUseCount -= closeCount;
+
/*
* Append the temporary queue to the list of available descriptors
*/
head->fd_prev = fdAvailTail;
fdAvailTail = tail;
}
- IH_UNLOCK
return 0;
}
+/* Close all cached file descriptors for this inode. */
+int
+ih_reallyclose(IHandle_t * ihP)
+{
+ if (!ihP)
+ return 0;
+
+ IH_LOCK;
+ assert(ihP->ih_refcnt > 0);
+ ih_fdclose(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)
+ * inode are closed when the last reference to this handle is released
+ */
+int
+ih_release(IHandle_t * ihP)
{
- int closeCount;
- FdHandle_t *fdP;
- FdHandle_t *head, *tail;
int ihash;
if (!ihP)
return 0;
- IH_LOCK
-
- /**
- * If the IH_REALLY_CLOSED flag is set then clear it here before adding
- * the Inode handle to the available queue
- */
- if ( ihP->ih_flags & IH_REALLY_CLOSED )
- ihP->ih_flags &= ~IH_REALLY_CLOSED;
+ IH_LOCK;
+ assert(ihP->ih_refcnt > 0);
- ihP->ih_refcnt--;
- if (ihP->ih_refcnt > 0) {
- IH_UNLOCK
+ if (ihP->ih_refcnt > 1) {
+ ihP->ih_refcnt--;
+ IH_UNLOCK;
return 0;
}
- assert(ihP->ih_refcnt == 0);
-
ihash = IH_HASH(ihP->ih_dev, ihP->ih_vid, ihP->ih_ino);
DLL_DELETE(ihP, ihashTable[ihash].ihash_head,
ihashTable[ihash].ihash_tail, ih_next, ih_prev);
- /*
- * Remove the file descriptors for this Inode from the LRU queue
- * and put them on a temporary queue so we drop the lock before
- * we close the files.
- */
- DLL_INIT_LIST(head, tail);
- for (fdP = ihP->ih_fdhead ; fdP != NULL ; fdP = fdP->fd_ihnext) {
- assert(fdP->fd_status == FD_HANDLE_OPEN);
- assert(fdP->fd_ih == ihP);
- DLL_DELETE(fdP, fdLruHead, fdLruTail, fd_next, fd_prev);
- DLL_INSERT_TAIL(fdP, head, tail, fd_next, fd_prev);
- }
- DLL_INIT_LIST(ihP->ih_fdhead, ihP->ih_fdtail);
-
- if (head == NULL) {
- DLL_INSERT_TAIL(ihP, ihAvailHead, ihAvailTail, ih_next, ih_prev);
- IH_UNLOCK
- return 0;
- }
+ ih_fdclose(ihP);
- /*
- * Close the file descriptors
- */
- closeCount = 0;
- for (fdP = head ; fdP != NULL ; fdP = fdP->fd_ihnext) {
- IH_UNLOCK
- OS_CLOSE(fdP->fd_fd);
- IH_LOCK
- assert(fdInUseCount > 0);
- fdInUseCount -= 1;
- fdP->fd_status = FD_HANDLE_AVAIL;
- fdP->fd_fd = INVALID_FD;
- fdP->fd_ih = NULL;
- closeCount++;
- }
+ ihP->ih_refcnt--;
- /*
- * Append the temporary queue to the list of available descriptors
- */
- if (fdAvailHead == NULL) {
- fdAvailHead = head;
- fdAvailTail = tail;
- } else {
- fdAvailTail->fd_next = head;
- head->fd_prev = fdAvailTail;
- fdAvailTail = tail;
- }
DLL_INSERT_TAIL(ihP, ihAvailHead, ihAvailTail, ih_next, ih_prev);
- IH_UNLOCK
+ IH_UNLOCK;
return 0;
}
/* Sync an inode to disk if its handle isn't NULL */
-int ih_condsync(IHandle_t *ihP)
+int
+ih_condsync(IHandle_t * ihP)
{
int code;
FdHandle_t *fdP;
* OS specific support routines.
*************************************************************************/
#ifndef AFS_NAMEI_ENV
-Inode ih_icreate(IHandle_t *ih, int dev, char *part, Inode nI, int p1, int p2,
- int p3, int p4)
+Inode
+ih_icreate(IHandle_t * ih, int dev, char *part, Inode nI, int p1, int p2,
+ int p3, int p4)
{
Inode ino;
#ifdef AFS_3DISPARES
#ifndef AFS_NT40_ENV
-int ih_size(int fd)
+afs_sfsize_t
+ih_size(int fd)
{
- struct stat status;
- if (fstat(fd, &status)<0)
+ struct afs_stat status;
+ if (afs_fstat(fd, &status) < 0)
return -1;
return status.st_size;
}