Whamcloud - gitweb
LU-2800 autoconf: clean up sysctl table handling
[fs/lustre-release.git] / libsysio / src / file_hack.c
index bad70be..e2eb79d 100644 (file)
 #include <assert.h>
 #include <errno.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/queue.h>
 
 #include "sysio.h"
 #include "file.h"
 #include "inode.h"
-#include "xtio.h"
 
 /*
  * Support for file IO.
@@ -106,6 +106,7 @@ _sysio_fnew(struct inode *ino, int flags)
                return NULL;
 
        _SYSIO_FINIT(fil, ino, flags);
+       F_REF(fil);
        I_REF(ino);
 
        return fil;
@@ -122,6 +123,7 @@ _sysio_fgone(struct file *fil)
        assert(!fil->f_ref);
        assert(fil->f_ino);
        err = (*fil->f_ino->i_ops.inop_close)(fil->f_ino);
+       I_RELE(fil->f_ino);
        assert(!err);
        free(fil);
 }
@@ -186,7 +188,7 @@ fd_grow(oftab_t *oftab, size_t n)
        return 0;
 }
 
-#if ZERO_SUM_MEMORY
+#ifdef ZERO_SUM_MEMORY
 static void free_oftab(oftab_t *ot)
 {
        if (ot->table) {
@@ -204,24 +206,27 @@ _sysio_fd_shutdown()
 #endif
 
 /*
- * Find a free slot in the open files table.
- * target < 0: any free slot
- * target >= 0: get slot [target]
+ * Find a free slot in the open files table which >= @low
+ * low < 0 means any
  */
 static int
-find_free_fildes(oftab_t *oftab, int target)
+find_free_fildes(oftab_t *oftab, int low)
  {
        int     n;
        int     err;
        struct file **filp;
  
-       if (target < 0) {
-               for (n = 0, filp = oftab->table;
-                    n < oftab->size && *filp;
-                    n++, filp++)
-                       ;
-       } else
-               n = target - oftab->offset;
+       if (low < 0)
+               low = oftab->offset;
+
+       n = low - oftab->offset;
+       if (n < 0)
+               return -ENFILE;
+
+       for (filp = oftab->table + n;
+            n < oftab->size && *filp;
+            n++, filp++)
+               ;
 
        if (n >= oftab->size) {
                err = fd_grow(oftab, n);
@@ -231,18 +236,6 @@ find_free_fildes(oftab_t *oftab, int target)
                assert(!*filp);
        }
  
-#ifdef HAVE_LUSTRE_HACK
-       /* FIXME sometimes we could intercept open/socket to create
-        * a fd, but missing close()? currently we have this problem
-         * with resolv lib. as a workaround simply destroy the file
-        * struct here.
-        */
-       if (oftab->table[n]) {
-               free(oftab->table[n]);
-               oftab->table[n] = NULL;
-       }
-#endif
-
        return oftab->offset + n;
 }
 
@@ -289,7 +282,7 @@ _sysio_fd_close(int fd)
 {
        struct file *fil;
 
-       fil = fil = __sysio_fd_get(fd, 1);
+       fil = __sysio_fd_get(fd, 1);
        if (!fil)
                return -EBADF;
 
@@ -299,35 +292,55 @@ _sysio_fd_close(int fd)
 }
 
 /*
- * Associate open file record with given file descriptor or any available
- * file descriptor if less than zero.
+ * Associate open file record with given file descriptor (if forced), or any
+ * available file descriptor if less than zero, or any available descriptor
+ * greater than or equal to the given one if not forced.
  */
 int
-_sysio_fd_set(struct file *fil, int fd)
+_sysio_fd_set(struct file *fil, int fd, int force)
 {
        int     err;
        struct file *ofil;
        oftab_t *oftab;
 
+       if (force && fd < 0)
+               abort();
+
        init_oftab();
 
        oftab = select_oftab(fd);
 
        /*
-        * New fd < 0 => any available descriptor.
+        * Search for a free descriptor if needed.
         */
-       fd = find_free_fildes(oftab, fd);
-       if (fd < 0)
-               return fd;
+       if (!force) {
+               fd = find_free_fildes(oftab, fd);
+               if (fd < 0)
+                       return fd;
+       }
 
-       assert(fd < oftab->offset + oftab->size);
+       if (fd - oftab->offset >= oftab->size) {
+               err = fd_grow(oftab, fd - oftab->offset);
+               if (err)
+                       return err;
+       }
 
        /*
         * Remember old.
         */
        ofil = __sysio_fd_get(fd, 1);
-       if (ofil)
-               F_RELE(ofil);
+       if (ofil) {
+               /* FIXME sometimes we could intercept open/socket to create
+                * a fd, but missing close()? currently we have this problem
+                * with resolv lib. as a workaround simply destroy the file
+                * struct here. And this hack will break the behavior of
+                * DUPFD.
+                */
+               if (fd >= 0 && oftab == &_sysio_oftab[0])
+                       free(ofil);
+               else
+                       F_RELE(ofil);
+       }
 
        oftab->table[fd - oftab->offset] = fil;
 
@@ -338,18 +351,20 @@ _sysio_fd_set(struct file *fil, int fd)
  * Duplicate old file descriptor.
  *
  * If the new file descriptor is less than zero, the new file descriptor
- * is chosen freely.
+ * is chosen freely. Otherwise, choose an available descriptor greater
+ * than or equal to the new, if not forced. Otherwise, if forced, (re)use
+ * the new.
  */
 int
-_sysio_fd_dup2(int oldfd, int newfd)
+_sysio_fd_dup(int oldfd, int newfd, int force)
 {
        struct file *fil;
        int     fd;
 
        init_oftab();
 
-       if (oldfd == newfd)
-               return 0;
+       if (oldfd == newfd && oldfd >= 0)
+               return newfd;
 
        fil = _sysio_fd_find(oldfd);
        if (!fil)
@@ -359,7 +374,7 @@ _sysio_fd_dup2(int oldfd, int newfd)
        if (select_oftab(oldfd) != select_oftab(newfd))
                return -EINVAL;
 
-       fd = _sysio_fd_set(fil, newfd);
+       fd = _sysio_fd_set(fil, newfd, force);
        if (fd >= 0)
                F_REF(fil);
        return fd;
@@ -384,23 +399,19 @@ _sysio_oftable_close_all(oftab_t *oftab)
 int
 _sysio_fd_close_all()
 {
-       int     fd;
-       struct file **filp;
-       oftab_t *oftab;
-       int i;
-
-       /*
-        * Close all open descriptors.
-        */
+       /* Close all open descriptors */
        _sysio_oftable_close_all(&_sysio_oftab[OFTAB_VIRTUAL]);
-       /* XXX see liblustre/llite_lib.c for explaination */
+       /* FIXME: libsysio does not currently perform enough cleanup of
+        * open files to allow __liblustre_cleanup_() to safely call
+        * unmount(). See the related FIXME comment in that function
+        * for details. The following disabled code is left in place to
+        * document the solution that was originally under consideration
+        * but never fully implemented. */
 #if 0
        _sysio_oftable_close_all(&_sysio_oftab[OFTAB_NATIVE]);
 #endif
 
-       /*
-        * Release current working directory.
-        */
+       /* Release current working directory */
        if (_sysio_cwd) {
                P_RELE(_sysio_cwd);
                _sysio_cwd = NULL;