Whamcloud - gitweb
LU-1305 osd: object operations for osd-zfs
[fs/lustre-release.git] / libsysio / src / ioctx.c
index 70c1b3e..6c06654 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <sched.h>
 #include <assert.h>
-#include <sys/types.h>
 #include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/queue.h>
 
 #include "sysio.h"
-#include "inode.h"
 #include "xtio.h"
+#include "inode.h"
+
+#if defined(REDSTORM)
+#include <catamount/do_iostats.h>
+#endif
 
-/*
- * Asynchronous IO context support.
- */
 
 /*
- * Arguments to IO vector enumerator callback when used by _sysio_doio().
+ * Asynchronous IO context support.
  */
-struct doio_helper_args {
-       ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, void *);     /* base func */
-       void    *arg;                                           /* caller arg */
-};
 
 /*
  * List of all outstanding (in-flight) asynch IO requests tracked
@@ -119,7 +118,6 @@ _sysio_ioctx_new(struct inode *ino,
 
        IOCTX_INIT(ioctx,
                   0,
-                  (ioid_t )ioctx,
                   wr,
                   ino,
                   iov, iovlen,
@@ -166,18 +164,33 @@ _sysio_ioctx_cb(struct ioctx *ioctx,
  * this implementation.
  */
 struct ioctx *
-_sysio_ioctx_find(ioid_t id)
+_sysio_ioctx_find(void *id)
 {
        struct ioctx *ioctx;
 
        for (ioctx = aioq.lh_first; ioctx; ioctx = ioctx->ioctx_link.le_next)
-               if (ioctx->ioctx_id == id)
+               if (ioctx == id)
                        return ioctx;
 
        return NULL;
 }
 
 /*
+ * Check if asynchronous IO operation is complete.
+ */
+int
+_sysio_ioctx_done(struct ioctx *ioctx)
+{
+
+       if (ioctx->ioctx_done)
+               return 1;
+       if (!(*ioctx->ioctx_ino->i_ops.inop_iodone)(ioctx))
+               return 0;
+       ioctx->ioctx_done = 1;
+       return 1;
+}
+
+/*
  * Wait for asynchronous IO operation to complete, return status
  * and dispose of the context.
  *
@@ -192,9 +205,11 @@ _sysio_ioctx_wait(struct ioctx *ioctx)
        /*
         * Wait for async operation to complete.
         */
-       while (!(ioctx->ioctx_done ||
-                (*ioctx->ioctx_ino->i_ops.inop_iodone)(ioctx)))
-               ;
+       while (!_sysio_ioctx_done(ioctx)) {
+#ifdef POSIX_PRIORITY_SCHEDULING
+               (void )sched_yield();
+#endif
+       }
 
        /*
         * Get status.
@@ -229,6 +244,10 @@ _sysio_ioctx_complete(struct ioctx *ioctx)
 {
        struct ioctx_callback *entry;
 
+
+       /* update IO stats */
+       _SYSIO_UPDACCT(ioctx->ioctx_write, ioctx->ioctx_cc);
+
        /*
         * Run the call-back queue.
         */
@@ -250,300 +269,3 @@ _sysio_ioctx_complete(struct ioctx *ioctx)
 
        free(ioctx);
 }
-
-/*
- * General help validating strided-IO vectors.
- *
- * A driver may call this to make sure underflow/overflow of an off_t can't
- * occur and overflow of a ssize_t can't occur when writing. The sum
- * of the reconciled transfer length is returned or some appropriate
- * error depending on underflow/overflow.
- *
- * The following algorithm assumes:
- *
- * a) sizeof(size_t) >= sizeof(ssize_t)
- * b) 2's complement arithmetic
- * c) The compiler won't optimize away code because it's developers
- *     believed that something with an undefined result in `C' can't happen.
- */
-ssize_t
-_sysio_validx(const struct intnl_xtvec *xtv, size_t xtvlen,
-             const struct iovec *iov, size_t iovlen,
-             _SYSIO_OFF_T limit)
-{
-       ssize_t acc, cc;
-       struct iovec iovec;
-       struct intnl_xtvec xtvec;
-       _SYSIO_OFF_T off;
-
-       if (!(xtvlen && iovlen))
-               return -EINVAL;
-
-       acc = 0;
-       xtvec.xtv_len = iovec.iov_len = 0;
-       do {
-               while (!xtvec.xtv_len) {
-                       if (!xtvlen--)
-                               break;
-                       if (!xtv->xtv_len) {
-                               xtv++;
-                               continue;
-                       }
-                       xtvec = *xtv++;
-                       if (xtvec.xtv_off < 0)
-                               return -EINVAL;
-               }
-               if (!xtvec.xtv_len)
-                       break;
-               do {
-                       while (!iovec.iov_len) {
-                               if (!iovlen--)
-                                       break;
-                               if (!iov->iov_len) {
-                                       iov++;
-                                       continue;
-                               }
-                               iovec = *iov++;
-                       }
-                       if (!iovec.iov_len)
-                               break;
-                       cc = iovec.iov_len;
-                       if (cc < 0)
-                               return -EINVAL;
-                       if ((size_t )cc > xtvec.xtv_len)
-                               cc = xtvec.xtv_len;
-                       xtvec.xtv_len -= cc;
-                       iovec.iov_len -= cc;
-                       off = xtvec.xtv_off + cc;
-                       if (xtvec.xtv_off && off <= xtvec.xtv_off)
-                               return off < 0 ? -EINVAL : -EOVERFLOW;
-                       if (off > limit)
-                               return -EFBIG;
-                       xtvec.xtv_off = off;
-                       cc += acc;
-                       if (acc && (cc <= acc))
-                               return -EINVAL;
-                       acc = cc;
-               } while (xtvec.xtv_len && iovlen);
-       } while ((xtvlen || xtvec.xtv_len) && iovlen);
-       return acc;
-}
-
-/*
- */
-ssize_t
-_sysio_enumerate_extents(const struct intnl_xtvec *xtv, size_t xtvlen,
-                        const struct iovec *iov, size_t iovlen,
-                        ssize_t (*f)(const struct iovec *, int,
-                                     _SYSIO_OFF_T,
-                                     ssize_t,
-                                     void *),
-                        void *arg)
-{
-       ssize_t acc, tmp, cc;
-       struct iovec iovec;
-       struct intnl_xtvec xtvec;
-       const struct iovec *start;
-       _SYSIO_OFF_T off;
-       size_t  n;
-       size_t  remain;
-       
-       acc = 0;
-       iovec.iov_len = 0;
-       while (xtvlen) {
-               /*
-                * Coalesce contiguous extent vector entries.
-                */
-               off = xtvec.xtv_off = xtv->xtv_off;
-               off += xtvec.xtv_len = xtv->xtv_len;
-               while (++xtv, --xtvlen) {
-                       if (off != xtv->xtv_off) {
-                               /*
-                                * Not contiguous.
-                                */
-                               break;
-                       }
-                       if (!xtv->xtv_len) {
-                               /*
-                                * Zero length.
-                                */
-                               continue;
-                       }
-                       off += xtv->xtv_len;
-                       xtvec.xtv_len += xtv->xtv_len;
-               }
-               while (xtvec.xtv_len) {
-                       if (iovec.iov_len) {
-                               tmp = iovec.iov_len; 
-                               if (iovec.iov_len > xtvec.xtv_len) {
-                                       iovec.iov_len = xtvec.xtv_len;
-                               } 
-                               cc =
-                                   (*f)(&iovec, 1,
-                                        xtvec.xtv_off,
-                                        xtvec.xtv_len,
-                                        arg);
-                               if (cc <= 0) {
-                                       if (acc)
-                                               return acc;
-                                       return cc;
-                               }
-                               iovec.iov_base = (char *)iovec.iov_base + cc;
-                               iovec.iov_len = tmp - cc; 
-                               tmp = cc + acc;
-                               if (acc && tmp <= acc)
-                                       abort();                /* paranoia */
-                               acc = tmp;
-                       } else {
-                               start = iov;
-                               n = xtvec.xtv_len;
-                               do {
-                                       if (iov->iov_len > n) {
-                                               /*
-                                                * That'll do.
-                                                */
-                                               break;
-                                       }
-                                       n -= iov->iov_len;
-                                       iov++;
-                               } while (--iovlen);
-                               if (iov == start) {
-                                       iovec = *iov++;
-#if 0
-                                       if (iovec.iov_len > n) {
-                                               iovec.iov_len = n;
-                                       } 
-#endif
-                                       continue;
-                               }
-                               remain = xtvec.xtv_len - n;
-                               cc =
-                                   (*f)(start, iov - start,
-                                                                xtvec.xtv_off,
-                                                                xtvec.xtv_len - n,
-                                        arg);
-                               if (cc <= 0) {
-                                       if (acc)
-                                               return acc;
-                                       return cc;
-                               }
-                                                               
-                               tmp = cc + acc;
-                               if (acc && tmp <= acc)
-                                       abort();                /* paranoia */
-                               acc = tmp;
-                               
-                               if (remain && !iovlen) 
-                                       return acc;
-                               
-                               remain -= cc;
-                               if (remain)
-                                       return acc;             /* short */
-                       }
-                       xtvec.xtv_off += cc;
-                       xtvec.xtv_len -= cc;
-               }
-       }
-       return acc;
-}
-
-ssize_t
-_sysio_enumerate_iovec(const struct iovec *iov, size_t count,
-                      _SYSIO_OFF_T off,
-                      ssize_t limit,
-                      ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, void *),
-                      void *arg)
-{
-       ssize_t acc, cc;
-       size_t  n;
-       unsigned indx;
-       size_t  remain;
-
-       if (!count)
-               return -EINVAL;
-       assert(limit >= 0);
-       acc = 0;
-       n = limit;
-       for (indx = 0; n && indx < count; indx++) {
-               if (iov[indx].iov_len < n) {
-                       cc = (ssize_t )iov[indx].iov_len;
-                       if (cc < 0)
-                               return -EINVAL;
-               } else
-                       cc = (ssize_t )n;
-               if (!cc)
-                       continue;
-               n -= cc;
-               cc += acc;
-               if (acc && cc <= acc)
-                       return -EINVAL;
-               acc = cc;
-       }
-       if (!acc)
-               return 0;
-       acc = 0;
-       do {
-               if (!iov->iov_len) {
-                       iov++;
-                       continue;
-               }
-               n =
-                   iov->iov_len < (size_t )limit
-                     ? iov->iov_len
-                     : (size_t )limit;
-               cc = (*f)(iov->iov_base, n, off, arg);
-               if (cc <= 0) {
-                       if (acc)
-                               return acc;
-                       return cc;
-               }
-               off += cc;
-               limit -= cc;
-               remain = iov->iov_len - cc;
-               cc += acc;
-               if (acc && cc <= acc)
-                       abort();                        /* bad driver! */
-               acc = cc;
-               if (remain || !limit)
-                       break;                          /* short/limited read */
-               iov++;
-       } while (--count);
-       return acc;
-}
-
-static ssize_t
-_sysio_doio_helper(const struct iovec *iov, int count,
-                  _SYSIO_OFF_T off,
-                  ssize_t limit,
-                  struct doio_helper_args *args)
-{
-
-       return _sysio_enumerate_iovec(iov, count,
-                                     off, limit,
-                                     args->f,
-                                     args->arg);
-}
-
-/*
- * A meta-driver for the whole strided-io process. Appropriate when
- * the driver can't handle anything but simple p{read,write}-like
- * interface.
- */
-ssize_t
-_sysio_doio(const struct intnl_xtvec *xtv, size_t xtvlen,
-           const struct iovec *iov, size_t iovlen,
-           ssize_t (*f)(void *, size_t, _SYSIO_OFF_T, void *),
-           void *arg)
-{
-       struct doio_helper_args arguments;
-
-       arguments.f = f;
-       arguments.arg = arg;
-       return _sysio_enumerate_extents(xtv, xtvlen,
-                                       iov, iovlen,
-                                       (ssize_t (*)(const struct iovec *, int,
-                                                    _SYSIO_OFF_T,
-                                                    ssize_t,
-                                                    void *))_sysio_doio_helper,
-                                       &arguments);
-}