Whamcloud - gitweb
LU-1187 osp: add osp_md_object for remote directory.
[fs/lustre-release.git] / libsysio / src / file.c
index 8d2c3a8..9ed054e 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.
@@ -75,7 +75,8 @@ _sysio_fnew(struct inode *ino, int flags)
                return NULL;
 
        _SYSIO_FINIT(fil, ino, flags);
-       I_REF(ino);
+       F_REF(fil);
+       I_REF(fil->f_ino);
 
        return fil;
 }
@@ -92,6 +93,7 @@ _sysio_fgone(struct file *fil)
        assert(fil->f_ino);
        err = (*fil->f_ino->i_ops.inop_close)(fil->f_ino);
        assert(!err);
+       I_RELE(fil->f_ino);
        free(fil);
 }
 
@@ -119,29 +121,27 @@ _sysio_fcompletio(struct ioctx *ioctx, struct file *fil)
 static int
 fd_grow(size_t n)
 {
-       int     fd;
        size_t  count;
        struct file **noftab, **filp;
 
        /*
         * Sanity check the new size.
         */
-       fd = (int )n;
-       if ((size_t )fd != n)
+       if ((int )n < 0)
                return -EMFILE;
 
-       if (n < 8)
-               n = 8;
-       if (n >= _sysio_oftab_size && n - _sysio_oftab_size < _sysio_oftab_size)
-               n = (n + 1) * 2;
+       /*
+        * We never shrink the table.
+        */
+       if (n <= _sysio_oftab_size)
+               return 0;
+
        noftab = realloc(_sysio_oftab, n * sizeof(struct file *));
        if (!noftab)
                return -ENOMEM;
        _sysio_oftab = noftab;
        count = _sysio_oftab_size;
        _sysio_oftab_size = n;
-       if (n < count)
-               return 0;
        filp = _sysio_oftab + count;
        n -= count;
        while (n--)
@@ -149,7 +149,7 @@ fd_grow(size_t n)
        return 0;
 }
 
-#if ZERO_SUM_MEMORY
+#ifdef ZERO_SUM_MEMORY
 void
 _sysio_fd_shutdown()
 {
@@ -160,21 +160,24 @@ _sysio_fd_shutdown()
 #endif
 
 /*
- * Find a free slot in the open files table.
+ * Find a free slot in the open files table greater than or equal to the
+ * argument.
  */
 static int
-find_free_fildes()
+find_free_fildes(int low)
 {
-       size_t  n;
+       int     n;
        int     err;
        struct file **filp;
 
-       for (n = 0, filp = _sysio_oftab;
-            n < _sysio_oftab_size && *filp;
+       for (n = low, filp = _sysio_oftab + low;
+            n >= 0 && (unsigned )n < _sysio_oftab_size && *filp;
             n++, filp++)
                ;
-       if (n >= _sysio_oftab_size) {
-               err = fd_grow(n);
+       if (n < 0)
+               return -ENFILE;
+       if ((unsigned )n >= _sysio_oftab_size) {
+               err = fd_grow((unsigned )n + 1);
                if (err)
                        return err;
                filp = &_sysio_oftab[n];
@@ -216,26 +219,29 @@ _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;
 
        /*
-        * New fd < 0 => any available descriptor.
+        * Search for a free descriptor if needed.
         */
-       if (fd < 0) {
-               fd = find_free_fildes();
+       if (fd < 0 || !force) {
+               if (fd < 0)
+                       fd = 0;
+               fd = find_free_fildes(fd);
                if (fd < 0)
                        return fd;
        }
 
        if ((unsigned )fd >= _sysio_oftab_size) {
-               err = fd_grow(fd);
+               err = fd_grow((unsigned )fd + 1);
                if (err)
                        return err;
        }
@@ -258,22 +264,24 @@ _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;
 
-       if (oldfd == newfd)
-               return 0;
+       if (oldfd == newfd && oldfd >= 0)
+               return newfd;
 
        fil = _sysio_fd_find(oldfd);
        if (!fil)
                return -EBADF;
 
-       fd = _sysio_fd_set(fil, newfd);
+       fd = _sysio_fd_set(fil, newfd, force);
        if (fd >= 0)
                F_REF(fil);
        return fd;