/* fd cache size that will be used if/when ih_UseLargeCache()
* is called */
vol_io_params.fd_max_cachesize = FD_MAX_CACHESIZE;
+
+ vol_io_params.sync_behavior = IH_SYNC_ONCLOSE;
+}
+
+int
+ih_SetSyncBehavior(const char *behavior)
+{
+ int val;
+
+ if (strcmp(behavior, "always") == 0) {
+ val = IH_SYNC_ALWAYS;
+
+ } else if (strcmp(behavior, "onclose") == 0) {
+ val = IH_SYNC_ONCLOSE;
+
+ } else if (strcmp(behavior, "never") == 0) {
+ val = IH_SYNC_NEVER;
+
+ } else {
+ /* invalid behavior name */
+ return -1;
+ }
+
+ vol_io_params.sync_behavior = val;
+ return 0;
}
#ifdef AFS_PTHREAD_ENV
/*
* 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);
- 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;
}
ihP->ih_refcnt++; /* must not disappear over unlock */
if (ihP->ih_synced) {
FdHandle_t *fdP;
+ opr_Assert(vol_io_params.sync_behavior != IH_SYNC_ALWAYS);
+ opr_Assert(vol_io_params.sync_behavior != IH_SYNC_NEVER);
ihP->ih_synced = 0;
IH_UNLOCK;
return 0;
}
#endif /* !AFS_NT40_ENV */
+
+int
+ih_fdsync(FdHandle_t *fdP)
+{
+ switch (vol_io_params.sync_behavior) {
+ case IH_SYNC_ALWAYS:
+ return OS_SYNC(fdP->fd_fd);
+ case IH_SYNC_ONCLOSE:
+ if (fdP->fd_ih) {
+ fdP->fd_ih->ih_synced = 1;
+ return 0;
+ }
+ return 1;
+ case IH_SYNC_NEVER:
+ return 0;
+ default:
+ opr_Assert(0);
+ }
+}