/*
* 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
#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
+#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/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 "nfs.h"
#include "ihandle.h"
#include "viceinode.h"
-#ifdef AFS_PTHREAD_ENV
-#include <assert.h>
-#else /* AFS_PTHREAD_ENV */
-#include "afs/assert.h"
-#endif /* AFS_PTHREAD_ENV */
+#include "afs/afs_assert.h"
#include <limits.h>
-#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;
pthread_mutex_t ih_glock_mutex;
FdHandle_t *fdLruTail;
int ih_Inited = 0;
+int ih_PkgDefaultsSet = 0;
/* Most of the servers use fopen/fdopen. Since the FILE structure
* only has eight bits for the file descriptor, the cache size
* has to be less than 256. The cache can be made larger as long
* as you are sure you don't need fopen/fdopen. */
+
+/* As noted in ihandle.h, the fileno member of FILE on most platforms
+ * in 2008 is a 16- or 32-bit signed int. -Matt
+ */
int fdMaxCacheSize = 0;
int fdCacheSize = 0;
/* Hash table for inode handles */
IHashBucket_t ihashTable[I_HANDLE_HASH_SIZE];
+void *ih_sync_thread(void *);
+
+/* start-time configurable I/O limits */
+ih_init_params vol_io_params;
+
+void ih_PkgDefaults(void)
+{
+ /* once */
+ ih_PkgDefaultsSet = 1;
+
+ /* default to well-known values */
+ vol_io_params.fd_handle_setaside = FD_HANDLE_SETASIDE;
+
+ /* initial fd cachesize. the only one that will be used if
+ * the application does not call ih_UseLargeCache(). set this
+ * to a value representable in fileno member of the system's
+ * FILE structure (or equivalent). */
+ vol_io_params.fd_initial_cachesize = FD_DEFAULT_CACHESIZE;
+
+ /* fd cache size that will be used if/when ih_UseLargeCache()
+ * is called */
+ vol_io_params.fd_max_cachesize = FD_MAX_CACHESIZE;
+}
#ifdef AFS_PTHREAD_ENV
/* Initialize the global ihandle mutex */
void
-ih_glock_init()
+ih_glock_init(void)
{
- assert(pthread_mutex_init(&ih_glock_mutex, NULL) == 0);
+ MUTEX_INIT(&ih_glock_mutex, "ih glock", MUTEX_DEFAULT, 0);
}
#endif /* AFS_PTHREAD_ENV */
ih_Initialize(void)
{
int i;
- assert(!ih_Inited);
+ osi_Assert(!ih_Inited);
ih_Inited = 1;
DLL_INIT_LIST(ihAvailHead, ihAvailTail);
DLL_INIT_LIST(fdAvailHead, fdAvailTail);
DLL_INIT_LIST(ihashTable[i].ihash_head, ihashTable[i].ihash_tail);
}
#if defined(AFS_NT40_ENV)
- fdMaxCacheSize = FD_MAX_CACHESIZE;
+ fdMaxCacheSize = vol_io_params.fd_max_cachesize;
#elif defined(AFS_SUN5_ENV) || defined(AFS_NBSD_ENV)
{
struct rlimit rlim;
- assert(getrlimit(RLIMIT_NOFILE, &rlim) == 0);
+ osi_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;
+ osi_Assert(setrlimit(RLIMIT_NOFILE, &rlim) == 0);
+ fdMaxCacheSize = rlim.rlim_cur - vol_io_params.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
*/
fdMaxCacheSize /= 4;
#endif
- fdMaxCacheSize = MIN(fdMaxCacheSize, FD_MAX_CACHESIZE);
- assert(fdMaxCacheSize > 0);
+ fdMaxCacheSize = MIN(fdMaxCacheSize, vol_io_params.fd_max_cachesize);
+ osi_Assert(fdMaxCacheSize > 0);
}
#elif defined(AFS_HPUX_ENV)
/* Avoid problems with "UFSOpen: igetinode failed" panics on HPUX 11.0 */
fdMaxCacheSize = 0;
#else
{
- long fdMax = MAX(sysconf(_SC_OPEN_MAX) - FD_HANDLE_SETASIDE, 0);
- fdMaxCacheSize = (int)MIN(fdMax, FD_MAX_CACHESIZE);
+ long fdMax = MAX(sysconf(_SC_OPEN_MAX) - vol_io_params.fd_handle_setaside,
+ 0);
+ fdMaxCacheSize = (int)MIN(fdMax, vol_io_params.fd_max_cachesize);
}
#endif
- fdCacheSize = MIN(fdMaxCacheSize, FD_DEFAULT_CACHESIZE);
+ fdCacheSize = MIN(fdMaxCacheSize, vol_io_params.fd_initial_cachesize);
+
+ {
+#ifdef AFS_PTHREAD_ENV
+ pthread_t syncer;
+ pthread_attr_t tattr;
+
+ pthread_attr_init(&tattr);
+ pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
+
+ pthread_create(&syncer, &tattr, ih_sync_thread, NULL);
+#else /* AFS_PTHREAD_ENV */
+ PROCESS syncer;
+ LWP_CreateProcess(ih_sync_thread, 16*1024, LWP_MAX_PRIORITY - 2,
+ NULL, "ih_syncer", &syncer);
+#endif /* AFS_PTHREAD_ENV */
+ }
+
}
/* Make the file descriptor cache as big as possible. Don't this call
- * if the program uses fopen or fdopen. */
+ * if the program uses fopen or fdopen, if fd_max_cachesize cannot be
+ * represented in the fileno member of the system FILE structure (or
+ * equivalent).
+ */
void
ih_UseLargeCache(void)
{
IH_LOCK;
+
+ if (!ih_PkgDefaultsSet) {
+ ih_PkgDefaults();
+ }
+
if (!ih_Inited) {
- ih_Initialize();
+ ih_Initialize();
}
+
fdCacheSize = fdMaxCacheSize;
IH_UNLOCK;
int i;
IHandle_t *ihP;
- assert(ihAvailHead == NULL);
+ osi_Assert(ihAvailHead == NULL);
ihP = (IHandle_t *) malloc(I_HANDLE_MALLOCSIZE * sizeof(IHandle_t));
- assert(ihP != NULL);
+ osi_Assert(ihP != NULL);
for (i = 0; i < I_HANDLE_MALLOCSIZE; i++) {
ihP[i].ih_refcnt = 0;
DLL_INSERT_TAIL(&ihP[i], ihAvailHead, ihAvailTail, ih_next, ih_prev);
int ihash = IH_HASH(dev, vid, ino);
IHandle_t *ihP;
+ if (!ih_PkgDefaultsSet) {
+ ih_PkgDefaults();
+ }
+
IH_LOCK;
if (!ih_Inited) {
- ih_Initialize();
+ ih_Initialize();
}
/* Do we already have a handle for this Inode? */
iHandleAllocateChunk();
}
ihP = ihAvailHead;
- assert(ihP->ih_refcnt == 0);
+ osi_Assert(ihP->ih_refcnt == 0);
DLL_DELETE(ihP, ihAvailHead, ihAvailTail, ih_next, ih_prev);
ihP->ih_dev = dev;
ihP->ih_vid = vid;
ihP->ih_ino = ino;
ihP->ih_flags = 0;
+ ihP->ih_synced = 0;
ihP->ih_refcnt = 1;
DLL_INIT_LIST(ihP->ih_fdhead, ihP->ih_fdtail);
DLL_INSERT_TAIL(ihP, ihashTable[ihash].ihash_head,
ih_copy(IHandle_t * ihP)
{
IH_LOCK;
- assert(ih_Inited);
- assert(ihP->ih_refcnt > 0);
+ osi_Assert(ih_Inited);
+ osi_Assert(ihP->ih_refcnt > 0);
ihP->ih_refcnt++;
IH_UNLOCK;
return ihP;
int i;
FdHandle_t *fdP;
- assert(fdAvailHead == NULL);
+ osi_Assert(fdAvailHead == NULL);
fdP = (FdHandle_t *) malloc(FD_HANDLE_MALLOCSIZE * sizeof(FdHandle_t));
- assert(fdP != NULL);
+ osi_Assert(fdP != NULL);
for (i = 0; i < FD_HANDLE_MALLOCSIZE; i++) {
fdP[i].fd_status = FD_HANDLE_AVAIL;
+ fdP[i].fd_refcnt = 0;
fdP[i].fd_ih = NULL;
fdP[i].fd_fd = INVALID_FD;
+ fdP[i].fd_ihnext = NULL;
+ fdP[i].fd_ihprev = NULL;
DLL_INSERT_TAIL(&fdP[i], fdAvailHead, fdAvailTail, fd_next, fd_prev);
}
}
int i;
StreamHandle_t *streamP;
- assert(streamAvailHead == NULL);
+ osi_Assert(streamAvailHead == NULL);
streamP = (StreamHandle_t *)
malloc(STREAM_HANDLE_MALLOCSIZE * sizeof(StreamHandle_t));
- assert(streamP != NULL);
+ osi_Assert(streamP != NULL);
for (i = 0; i < STREAM_HANDLE_MALLOCSIZE; i++) {
streamP[i].str_fd = INVALID_FD;
DLL_INSERT_TAIL(&streamP[i], streamAvailHead, streamAvailTail,
/* Do we already have an open file handle for this Inode? */
for (fdP = ihP->ih_fdtail; fdP != NULL; fdP = fdP->fd_ihprev) {
+#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) {
- assert(fdP->fd_status == FD_HANDLE_OPEN);
+ osi_Assert(fdP->fd_status == FD_HANDLE_OPEN);
+#else /* HAVE_PIO */
+ if (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;
- (void) FDH_SEEK(fdP, 0, SEEK_SET);
return fdP;
}
}
*/
fdInUseCount += 1;
IH_UNLOCK;
+ih_open_retry:
fd = OS_IOPEN(ihP);
IH_LOCK;
- if (fd == INVALID_FD) {
+ if (fd == INVALID_FD && (errno != EMFILE || fdLruHead == NULL) ) {
fdInUseCount -= 1;
IH_UNLOCK;
return NULL;
* 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 && fdLruHead != NULL) {
+ if ((fdInUseCount > fdCacheSize || fd == INVALID_FD) && fdLruHead != NULL) {
fdP = fdLruHead;
- assert(fdP->fd_status == FD_HANDLE_OPEN);
+ 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;
- assert(fdP->fd_status == FD_HANDLE_AVAIL);
+ 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++;
return 0;
IH_LOCK;
- assert(ih_Inited);
- assert(fdInUseCount > 0);
- assert(fdP->fd_status == FD_HANDLE_INUSE);
+ osi_Assert(ih_Inited);
+ osi_Assert(fdInUseCount > 0);
+ osi_Assert(fdP->fd_status == FD_HANDLE_INUSE);
ihP = fdP->fd_ih;
return fd_reallyclose(fdP);
}
- /* Put this descriptor back into the cache */
- fdP->fd_status = FD_HANDLE_OPEN;
- DLL_INSERT_TAIL(fdP, fdLruHead, fdLruTail, fd_next, fd_prev);
+ fdP->fd_refcnt--;
+ if (fdP->fd_refcnt == 0) {
+ /* Put this descriptor back into the cache */
+ fdP->fd_status = FD_HANDLE_OPEN;
+ 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.
return 0;
IH_LOCK;
- assert(ih_Inited);
- assert(fdInUseCount > 0);
- assert(fdP->fd_status == FD_HANDLE_INUSE);
+ osi_Assert(ih_Inited);
+ osi_Assert(fdInUseCount > 0);
+ osi_Assert(fdP->fd_status == FD_HANDLE_INUSE);
ihP = fdP->fd_ih;
closeFd = fdP->fd_fd;
+ fdP->fd_refcnt--;
- DLL_DELETE(fdP, ihP->ih_fdhead, ihP->ih_fdtail, fd_ihnext, fd_ihprev);
- DLL_INSERT_TAIL(fdP, fdAvailHead, fdAvailTail, fd_next, fd_prev);
+ if (fdP->fd_refcnt == 0) {
+ 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;
+ fdP->fd_status = FD_HANDLE_AVAIL;
+ fdP->fd_refcnt = 0;
+ fdP->fd_ih = NULL;
+ fdP->fd_fd = INVALID_FD;
+ }
/* All the file descriptor handles have been closed; reset
* the IH_REALLY_CLOSED flag indicating that ih_reallyclose
ihP->ih_flags &= ~IH_REALLY_CLOSED;
}
- IH_UNLOCK;
- OS_CLOSE(closeFd);
- IH_LOCK;
- fdInUseCount -= 1;
+ if (fdP->fd_refcnt == 0) {
+ IH_UNLOCK;
+ OS_CLOSE(closeFd);
+ 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. */
streamP->str_fd = fd;
streamP->str_buflen = 0;
streamP->str_bufoff = 0;
+ streamP->str_fdoff = 0;
streamP->str_error = 0;
streamP->str_eof = 0;
streamP->str_direction = STREAM_DIRECTION_NONE;
StreamHandle_t *
stream_open(const char *filename, const char *mode)
{
- FD_t fd;
+ FD_t fd = INVALID_FD;
if (strcmp(mode, "r") == 0) {
fd = OS_OPEN(filename, O_RDONLY, 0);
} else if (strcmp(mode, "a+") == 0) {
fd = OS_OPEN(filename, O_RDWR | O_APPEND | O_CREAT, 0);
} else {
- assert(FALSE); /* not implemented */
+ osi_Assert(FALSE); /* not implemented */
}
if (fd == INVALID_FD) {
streamP->str_bufoff = 0;
streamP->str_buflen = 0;
} else {
- assert(streamP->str_direction == STREAM_DIRECTION_READ);
+ osi_Assert(streamP->str_direction == STREAM_DIRECTION_READ);
}
bytesRead = 0;
if (streamP->str_buflen == 0) {
streamP->str_bufoff = 0;
streamP->str_buflen =
- OS_READ(streamP->str_fd, streamP->str_buffer,
- STREAM_HANDLE_BUFSIZE);
+ OS_PREAD(streamP->str_fd, streamP->str_buffer,
+ STREAM_HANDLE_BUFSIZE, streamP->str_fdoff);
if (streamP->str_buflen < 0) {
streamP->str_error = errno;
streamP->str_buflen = 0;
streamP->str_eof = 1;
break;
}
+ streamP->str_fdoff += streamP->str_buflen;
}
bytesToRead = nbytes;
streamP->str_bufoff = 0;
streamP->str_buflen = STREAM_HANDLE_BUFSIZE;
} else {
- assert(streamP->str_direction == STREAM_DIRECTION_WRITE);
+ osi_Assert(streamP->str_direction == STREAM_DIRECTION_WRITE);
}
nbytes = size * nitems;
p = (char *)ptr;
while (nbytes > 0) {
if (streamP->str_buflen == 0) {
- rc = OS_WRITE(streamP->str_fd, streamP->str_buffer,
- STREAM_HANDLE_BUFSIZE);
+ rc = OS_PWRITE(streamP->str_fd, streamP->str_buffer,
+ STREAM_HANDLE_BUFSIZE, streamP->str_fdoff);
if (rc < 0) {
streamP->str_error = errno;
bytesWritten = 0;
break;
}
+ streamP->str_fdoff += rc;
streamP->str_bufoff = 0;
streamP->str_buflen = STREAM_HANDLE_BUFSIZE;
}
/* fseek for buffered I/O handles */
int
-stream_seek(StreamHandle_t * streamP, afs_foff_t offset, int whence)
+stream_aseek(StreamHandle_t * streamP, afs_foff_t offset)
{
- int rc;
+ ssize_t rc;
int retval = 0;
if (streamP->str_direction == STREAM_DIRECTION_WRITE
&& streamP->str_bufoff > 0) {
- rc = OS_WRITE(streamP->str_fd, streamP->str_buffer,
- streamP->str_bufoff);
+ rc = OS_PWRITE(streamP->str_fd, streamP->str_buffer,
+ streamP->str_bufoff, streamP->str_fdoff);
if (rc < 0) {
streamP->str_error = errno;
retval = -1;
}
}
+ streamP->str_fdoff = offset;
streamP->str_bufoff = 0;
streamP->str_buflen = 0;
streamP->str_eof = 0;
streamP->str_direction = STREAM_DIRECTION_NONE;
- if (OS_SEEK(streamP->str_fd, offset, whence) < 0) {
- streamP->str_error = errno;
- retval = -1;
- }
return retval;
}
int
stream_flush(StreamHandle_t * streamP)
{
- int rc;
+ ssize_t rc;
int retval = 0;
if (streamP->str_direction == STREAM_DIRECTION_WRITE
&& streamP->str_bufoff > 0) {
- rc = OS_WRITE(streamP->str_fd, streamP->str_buffer,
- streamP->str_bufoff);
+ rc = OS_PWRITE(streamP->str_fd, streamP->str_buffer,
+ streamP->str_bufoff, streamP->str_fdoff);
if (rc < 0) {
streamP->str_error = errno;
retval = -1;
+ } else {
+ streamP->str_fdoff += rc;
}
streamP->str_bufoff = 0;
streamP->str_buflen = STREAM_HANDLE_BUFSIZE;
int
stream_close(StreamHandle_t * streamP, int reallyClose)
{
- int rc;
+ ssize_t rc;
int retval = 0;
- assert(streamP != NULL);
+ osi_Assert(streamP != NULL);
if (streamP->str_direction == STREAM_DIRECTION_WRITE
&& streamP->str_bufoff > 0) {
- rc = OS_WRITE(streamP->str_fd, streamP->str_buffer,
- streamP->str_bufoff);
+ rc = OS_PWRITE(streamP->str_fd, streamP->str_buffer,
+ streamP->str_bufoff, streamP->str_fdoff);
if (rc < 0) {
retval = -1;
+ } else {
+ streamP->str_fdoff += rc;
}
}
if (reallyClose) {
int closeCount, closedAll;
FdHandle_t *fdP, *head, *tail, *next;
- assert(ihP->ih_refcnt > 0);
+ osi_Assert(ihP->ih_refcnt > 0);
closedAll = 1;
DLL_INIT_LIST(head, tail);
*/
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
+ osi_Assert(fdP->fd_ih == ihP);
+ osi_Assert(fdP->fd_status == FD_HANDLE_OPEN
|| fdP->fd_status == FD_HANDLE_INUSE);
if (fdP->fd_status == FD_HANDLE_OPEN) {
DLL_DELETE(fdP, ihP->ih_fdhead, ihP->ih_fdtail, fd_ihnext,
* closed all file descriptors.
*/
if (ihP->ih_refcnt == 1 || closedAll) {
- assert(closedAll);
- assert(!ihP->ih_fdhead);
- assert(!ihP->ih_fdtail);
+ osi_Assert(closedAll);
+ osi_Assert(!ihP->ih_fdhead);
+ osi_Assert(!ihP->ih_fdtail);
}
if (head == NULL) {
for (fdP = head; fdP != NULL; fdP = fdP->fd_next) {
OS_CLOSE(fdP->fd_fd);
fdP->fd_status = FD_HANDLE_AVAIL;
+ fdP->fd_refcnt = 0;
fdP->fd_fd = INVALID_FD;
fdP->fd_ih = NULL;
closeCount++;
}
IH_LOCK;
- assert(fdInUseCount >= closeCount);
+ osi_Assert(fdInUseCount >= closeCount);
fdInUseCount -= closeCount;
/*
return 0;
IH_LOCK;
- assert(ihP->ih_refcnt > 0);
+ ihP->ih_refcnt++; /* must not disappear over unlock */
+ if (ihP->ih_synced) {
+ FdHandle_t *fdP;
+ ihP->ih_synced = 0;
+ IH_UNLOCK;
+
+ fdP = IH_OPEN(ihP);
+ if (fdP) {
+ OS_SYNC(fdP->fd_fd);
+ FDH_CLOSE(fdP);
+ }
+
+ IH_LOCK;
+ }
+
+ osi_Assert(ihP->ih_refcnt > 0);
+
ih_fdclose(ihP);
- IH_UNLOCK;
+ if (ihP->ih_refcnt > 1) {
+ ihP->ih_refcnt--;
+ IH_UNLOCK;
+ } else {
+ IH_UNLOCK;
+ ih_release(ihP);
+ }
return 0;
}
return 0;
IH_LOCK;
- assert(ihP->ih_refcnt > 0);
+ osi_Assert(ihP->ih_refcnt > 0);
if (ihP->ih_refcnt > 1) {
ihP->ih_refcnt--;
return code;
}
+void
+ih_sync_all(void) {
+
+ int ihash;
+
+ IH_LOCK;
+ for (ihash = 0; ihash < I_HANDLE_HASH_SIZE; ihash++) {
+ IHandle_t *ihP, *ihPnext;
+
+ ihP = ihashTable[ihash].ihash_head;
+ if (ihP)
+ ihP->ih_refcnt++; /* must not disappear over unlock */
+ for (; ihP; ihP = ihPnext) {
+
+ if (ihP->ih_synced) {
+ FdHandle_t *fdP;
+
+ ihP->ih_synced = 0;
+ IH_UNLOCK;
+
+ fdP = IH_OPEN(ihP);
+ if (fdP) {
+ OS_SYNC(fdP->fd_fd);
+ FDH_CLOSE(fdP);
+ }
+
+ IH_LOCK;
+ }
+
+ /* when decrementing the refcount, the ihandle might disappear
+ and we might not even be able to proceed to the next one.
+ Hence the gymnastics putting a hold on the next one already */
+ ihPnext = ihP->ih_next;
+ if (ihPnext) ihPnext->ih_refcnt++;
+
+ if (ihP->ih_refcnt > 1) {
+ ihP->ih_refcnt--;
+ } else {
+ IH_UNLOCK;
+ ih_release(ihP);
+ IH_LOCK;
+ }
+
+ }
+ }
+ IH_UNLOCK;
+}
+
+void *
+ih_sync_thread(void *dummy) {
+ while(1) {
+
+#ifdef AFS_PTHREAD_ENV
+ sleep(10);
+#else /* AFS_PTHREAD_ENV */
+ IOMGR_Sleep(60);
+#endif /* AFS_PTHREAD_ENV */
+
+ ih_sync_all();
+ }
+ return NULL;
+}
/*************************************************************************
}
#endif /* AFS_NAMEI_ENV */
-
-#ifndef AFS_NT40_ENV
afs_sfsize_t
-ih_size(int fd)
+ih_size(FD_t fd)
{
- struct afs_stat status;
+#ifdef AFS_NT40_ENV
+ LARGE_INTEGER size;
+ if (!GetFileSizeEx(fd, &size))
+ return -1;
+ return size.QuadPart;
+#else
+ struct afs_stat_st status;
if (afs_fstat(fd, &status) < 0)
return -1;
return status.st_size;
-}
#endif
+}
+
+#ifndef HAVE_PIO
+ssize_t
+ih_pread(int fd, void * buf, size_t count, afs_foff_t offset)
+{
+ afs_foff_t code;
+ code = OS_SEEK(fd, offset, 0);
+ if (code < 0)
+ return code;
+ return OS_READ(fd, buf, count);
+}
+
+ssize_t
+ih_pwrite(int fd, const void * buf, size_t count, afs_foff_t offset)
+{
+ afs_foff_t code;
+ code = OS_SEEK(fd, offset, 0);
+ if (code < 0)
+ return code;
+ return OS_WRITE(fd, buf, count);
+}
+#endif /* !HAVE_PIO */