The namei fileserver can run into "too many open files" since ih_open
assumes that it can always open a new file before deciding another file should be closed when exceeding a threshold. The EMFILE error is simply returned to the caller.

The "ad hoc" reserve of 64 free file descriptors can get depleted when more than 64 threads try to open a file simultaneously (the lock is dropped), just making the reserve bigger does not solve the problem as the number of threads grow.

The attached patch now recovers from EMFILE and adjusts the threshold as to not make recovery the norm. It does not alter the "reserve", although setting it to 0 now works fine as well.

Bcc'ed to openafs-bugs.

--
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Rainer Toebbicke
European Laboratory for Particle Physics(CERN) - Geneva, Switzerland
Phone: +41 22 767 8985       Fax: +41 22 767 7155
--- openafs/src/vol/ihandle.c.o144      2007-03-20 14:36:37.000000000 +0100
+++ openafs/src/vol/ihandle.c   2007-10-16 14:51:25.000000000 +0200
@@ -325,9 +325,10 @@
      */
     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;
@@ -337,13 +338,23 @@
      * 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);
        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();

Reply via email to