Whamcloud - gitweb
LU-13799 llite: Adjust dio refcounting
[fs/lustre-release.git] / lustre / include / cl_object.h
index 3e31227..e180f68 100644 (file)
@@ -27,7 +27,6 @@
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
  */
 #ifndef _LUSTRE_CL_OBJECT_H
 #define _LUSTRE_CL_OBJECT_H
@@ -179,15 +178,15 @@ struct cl_attr {
  * Fields in cl_attr that are being set.
  */
 enum cl_attr_valid {
-       CAT_SIZE   = 1 << 0,
-       CAT_KMS    = 1 << 1,
-       CAT_MTIME  = 1 << 3,
-       CAT_ATIME  = 1 << 4,
-       CAT_CTIME  = 1 << 5,
-       CAT_BLOCKS = 1 << 6,
-       CAT_UID    = 1 << 7,
-       CAT_GID    = 1 << 8,
-       CAT_PROJID = 1 << 9
+       CAT_SIZE        = BIT(0),
+       CAT_KMS         = BIT(1),
+       CAT_MTIME       = BIT(3),
+       CAT_ATIME       = BIT(4),
+       CAT_CTIME       = BIT(5),
+       CAT_BLOCKS      = BIT(6),
+       CAT_UID         = BIT(7),
+       CAT_GID         = BIT(8),
+       CAT_PROJID      = BIT(9),
 };
 
 /**
@@ -623,7 +622,7 @@ enum cl_page_state {
          *
          * \invariant cl_page::cp_owner == NULL && cl_page::cp_req == NULL
          */
-        CPS_CACHED,
+       CPS_CACHED = 1,
         /**
          * Page is exclusively owned by some cl_io. Page may end up in this
          * state as a result of
@@ -715,8 +714,13 @@ enum cl_page_type {
          *  to vmpage which is not belonging to the same object of cl_page.
          *  it is used in DirectIO and lockless IO. */
         CPT_TRANSIENT,
+       CPT_NR
 };
 
+#define        CP_STATE_BITS   4
+#define        CP_TYPE_BITS    2
+#define        CP_MAX_LAYER    3
+
 /**
  * Fields are protected by the lock on struct page, except for atomics and
  * immutables.
@@ -728,41 +732,53 @@ enum cl_page_type {
  */
 struct cl_page {
        /** Reference counter. */
-       atomic_t                 cp_ref;
+       atomic_t                cp_ref;
+       /** layout_entry + stripe index, composed using lov_comp_index() */
+       unsigned int            cp_lov_index;
+       pgoff_t                 cp_osc_index;
        /** An object this page is a part of. Immutable after creation. */
        struct cl_object        *cp_obj;
        /** vmpage */
        struct page             *cp_vmpage;
+       /**
+        * Assigned if doing direct IO, because in this case cp_vmpage is not
+        * a valid page cache page, hence the inode cannot be inferred from
+        * cp_vmpage->mapping->host.
+        */
+       struct inode            *cp_inode;
        /** Linkage of pages within group. Pages must be owned */
-       struct list_head         cp_batch;
-       /** List of slices. Immutable after creation. */
-       struct list_head         cp_layers;
+       struct list_head        cp_batch;
+       /** array of slices offset. Immutable after creation. */
+       unsigned char           cp_layer_offset[CP_MAX_LAYER]; /* 24 bits */
+       /** current slice index */
+       unsigned char           cp_layer_count:2; /* 26 bits */
        /**
         * Page state. This field is const to avoid accidental update, it is
         * modified only internally within cl_page.c. Protected by a VM lock.
         */
-       const enum cl_page_state cp_state;
+       enum cl_page_state       cp_state:CP_STATE_BITS; /* 30 bits */
         /**
          * Page type. Only CPT_TRANSIENT is used so far. Immutable after
          * creation.
          */
-        enum cl_page_type        cp_type;
+       enum cl_page_type       cp_type:CP_TYPE_BITS; /* 32 bits */
+       /* which slab kmem index this memory allocated from */
+       short int               cp_kmem_index; /* 48 bits */
+       unsigned int            cp_unused1:16;  /* 64 bits */
 
-        /**
-         * Owning IO in cl_page_state::CPS_OWNED state. Sub-page can be owned
-         * by sub-io. Protected by a VM lock.
-         */
+       /**
+        * Owning IO in cl_page_state::CPS_OWNED state. Sub-page can be owned
+        * by sub-io. Protected by a VM lock.
+        */
         struct cl_io            *cp_owner;
-        /** List of references to this page, for debugging. */
-        struct lu_ref            cp_reference;
+       /** List of references to this page, for debugging. */
+        struct lu_ref          cp_reference;
        /** Link to an object, for debugging. */
-       struct lu_ref_link       cp_obj_ref;
+       struct lu_ref_link      cp_obj_ref;
        /** Link to a queue, for debugging. */
-       struct lu_ref_link       cp_queue_ref;
+       struct lu_ref_link      cp_queue_ref;
        /** Assigned if doing a sync_io */
-       struct cl_sync_io       *cp_sync_io;
-       /** layout_entry + stripe index, composed using lov_comp_index() */
-       unsigned int            cp_lov_index;
+       struct cl_sync_io       *cp_sync_io;
 };
 
 /**
@@ -772,15 +788,12 @@ struct cl_page {
  */
 struct cl_page_slice {
         struct cl_page                  *cpl_page;
-       pgoff_t                          cpl_index;
         /**
          * Object slice corresponding to this page slice. Immutable after
          * creation.
          */
         struct cl_object                *cpl_obj;
         const struct cl_page_operations *cpl_ops;
-        /** Linkage into cl_page::cp_layers. Immutable after creation. */
-       struct list_head                 cpl_linkage;
 };
 
 /**
@@ -993,23 +1006,6 @@ struct cl_page_operations {
         void (*cpo_clip)(const struct lu_env *env,
                          const struct cl_page_slice *slice,
                          int from, int to);
-        /**
-         * \pre  the page was queued for transferring.
-         * \post page is removed from client's pending list, or -EBUSY
-         *       is returned if it has already been in transferring.
-         *
-         * This is one of seldom page operation which is:
-         * 0. called from top level;
-         * 1. don't have vmpage locked;
-         * 2. every layer should synchronize execution of its ->cpo_cancel()
-         *    with completion handlers. Osc uses client obd lock for this
-         *    purpose. Based on there is no vvp_page_cancel and
-         *    lov_page_cancel(), cpo_cancel is defacto protected by client lock.
-         *
-         * \see osc_page_cancel().
-         */
-        int (*cpo_cancel)(const struct lu_env *env,
-                          const struct cl_page_slice *slice);
        /**
         * Write out a page by kernel. This is only called by ll_writepage
         * right now.
@@ -1310,7 +1306,6 @@ do {                                                                    \
 struct cl_page_list {
        unsigned                 pl_nr;
        struct list_head         pl_pages;
-       struct task_struct      *pl_owner;
 };
 
 /**
@@ -1421,6 +1416,11 @@ enum cl_io_type {
         * To give advice about access of a file
         */
        CIT_LADVISE,
+       /**
+        * SEEK_HOLE/SEEK_DATA handling to search holes or data
+        * across all file objects
+        */
+       CIT_LSEEK,
         CIT_OP_NR
 };
 
@@ -1481,9 +1481,13 @@ struct cl_read_ahead {
        unsigned long   cra_rpc_pages;
        /* Release callback. If readahead holds resources underneath, this
         * function should be called to release it. */
-       void            (*cra_release)(const struct lu_env *env, void *cbdata);
+       void            (*cra_release)(const struct lu_env *env,
+                                      struct cl_read_ahead *ra);
+
        /* Callback data for cra_release routine */
-       void            *cra_cbdata;
+       void            *cra_dlmlock;
+       void            *cra_oio;
+
        /* whether lock is in contention */
        bool            cra_contention;
 };
@@ -1492,7 +1496,7 @@ static inline void cl_read_ahead_release(const struct lu_env *env,
                                         struct cl_read_ahead *ra)
 {
        if (ra->cra_release != NULL)
-               ra->cra_release(env, ra->cra_cbdata);
+               ra->cra_release(env, ra);
        memset(ra, 0, sizeof(*ra));
 }
 
@@ -1603,6 +1607,11 @@ struct cl_io_operations {
                        struct cl_page_list *queue, int from, int to,
                        cl_commit_cbt cb);
        /**
+        * Release active extent.
+        */
+       void  (*cio_extent_release)(const struct lu_env *env,
+                                   const struct cl_io_slice *slice);
+       /**
         * Decide maximum read ahead extent
         *
         * \pre io->ci_type == CIT_READ
@@ -1610,6 +1619,13 @@ struct cl_io_operations {
        int (*cio_read_ahead)(const struct lu_env *env,
                              const struct cl_io_slice *slice,
                              pgoff_t start, struct cl_read_ahead *ra);
+       /**
+        *
+        * Reserve LRU slots before IO.
+        */
+       int (*cio_lru_reserve) (const struct lu_env *env,
+                               const struct cl_io_slice *slice,
+                               loff_t pos, size_t bytes);
         /**
          * Optional debugging helper. Print given io slice.
          */
@@ -1622,11 +1638,11 @@ struct cl_io_operations {
  * \ingroup cl_lock
  */
 enum cl_enq_flags {
-        /**
-         * instruct server to not block, if conflicting lock is found. Instead
-         * -EWOULDBLOCK is returned immediately.
-         */
-        CEF_NONBLOCK     = 0x00000001,
+       /**
+        * instruct server to not block, if conflicting lock is found. Instead
+        * -EAGAIN is returned immediately.
+        */
+       CEF_NONBLOCK     = 0x00000001,
        /**
         * Tell lower layers this is a glimpse request, translated to
         * LDLM_FL_HAS_INTENT at LDLM layer.
@@ -1772,6 +1788,31 @@ struct cl_io_rw_common {
        size_t  crw_count;
        int     crw_nonblock;
 };
+enum cl_setattr_subtype {
+       /** regular setattr **/
+       CL_SETATTR_REG = 1,
+       /** truncate(2) **/
+       CL_SETATTR_TRUNC,
+       /** fallocate(2) - mode preallocate **/
+       CL_SETATTR_FALLOCATE
+};
+
+struct cl_io_range {
+       loff_t cir_pos;
+       size_t cir_count;
+};
+
+struct cl_io_pt {
+       struct cl_io_pt *cip_next;
+       struct kiocb cip_iocb;
+       struct iov_iter cip_iter;
+       struct file *cip_file;
+       enum cl_io_type cip_iot;
+       unsigned int cip_need_restart:1;
+       loff_t cip_pos;
+       size_t cip_count;
+       ssize_t cip_result;
+};
 
 /**
  * State for io.
@@ -1789,6 +1830,8 @@ struct cl_io {
         enum cl_io_state               ci_state;
         /** main object this io is against. Immutable after creation. */
         struct cl_object              *ci_obj;
+       /** one AIO request might be split in cl_io_loop */
+       struct cl_dio_aio             *ci_aio;
         /**
          * Upper layer io, of which this io is a part of. Immutable after
          * creation.
@@ -1820,6 +1863,13 @@ struct cl_io {
                        int                      sa_stripe_index;
                        struct ost_layout        sa_layout;
                        const struct lu_fid     *sa_parent_fid;
+                       /* SETATTR interface is used for regular setattr, */
+                       /* truncate(2) and fallocate(2) subtypes */
+                       enum cl_setattr_subtype  sa_subtype;
+                       /* The following are used for fallocate(2) */
+                       int                      sa_falloc_mode;
+                       loff_t                   sa_falloc_offset;
+                       loff_t                   sa_falloc_end;
                } ci_setattr;
                struct cl_data_version_io {
                        u64 dv_data_version;
@@ -1857,6 +1907,14 @@ struct cl_io {
                        enum lu_ladvise_type     li_advice;
                        __u64                    li_flags;
                } ci_ladvise;
+               struct cl_lseek_io {
+                       loff_t                   ls_start;
+                       loff_t                   ls_result;
+                       int                      ls_whence;
+               } ci_lseek;
+               struct cl_misc_io {
+                       time64_t                 lm_next_rpc_time;
+               } ci_misc;
         } u;
         struct cl_2queue     ci_queue;
         size_t               ci_nob;
@@ -1917,13 +1975,31 @@ struct cl_io {
        /**
         * Ignore lockless and do normal locking for this io.
         */
-                            ci_ignore_lockless:1,
+                            ci_dio_lock:1,
        /**
         * Set if we've tried all mirrors for this read IO, if it's not set,
         * the read IO will check to-be-read OSCs' status, and make fast-switch
         * another mirror if some of the OSTs are not healthy.
         */
-                            ci_tried_all_mirrors:1;
+                            ci_tried_all_mirrors:1,
+       /**
+        * Random read hints, readahead will be disabled.
+        */
+                            ci_rand_read:1,
+       /**
+        * Sequential read hints.
+        */
+                            ci_seq_read:1,
+       /**
+        * Do parallel (async) submission of DIO RPCs.  Note DIO is still sync
+        * to userspace, only the RPCs are submitted async, then waited for at
+        * the llite layer before returning.
+        */
+                            ci_parallel_dio:1;
+       /**
+        * Bypass quota check
+        */
+       unsigned             ci_noquota:1;
        /**
         * How many times the read has retried before this one.
         * Set by the top level and consumed by the LOV.
@@ -2030,8 +2106,8 @@ static inline struct cl_site *lu2cl_site(const struct lu_site *site)
 
 static inline struct cl_device *lu2cl_dev(const struct lu_device *d)
 {
-        LASSERT(d == NULL || IS_ERR(d) || lu_device_is_cl(d));
-        return container_of0(d, struct cl_device, cd_lu_dev);
+       LASSERT(d == NULL || IS_ERR(d) || lu_device_is_cl(d));
+       return container_of_safe(d, struct cl_device, cd_lu_dev);
 }
 
 static inline struct lu_device *cl2lu_dev(struct cl_device *d)
@@ -2041,49 +2117,49 @@ static inline struct lu_device *cl2lu_dev(struct cl_device *d)
 
 static inline struct cl_object *lu2cl(const struct lu_object *o)
 {
-        LASSERT(o == NULL || IS_ERR(o) || lu_device_is_cl(o->lo_dev));
-        return container_of0(o, struct cl_object, co_lu);
+       LASSERT(o == NULL || IS_ERR(o) || lu_device_is_cl(o->lo_dev));
+       return container_of_safe(o, struct cl_object, co_lu);
 }
 
 static inline const struct cl_object_conf *
 lu2cl_conf(const struct lu_object_conf *conf)
 {
-        return container_of0(conf, struct cl_object_conf, coc_lu);
+       return container_of_safe(conf, struct cl_object_conf, coc_lu);
 }
 
 static inline struct cl_object *cl_object_next(const struct cl_object *obj)
 {
-        return obj ? lu2cl(lu_object_next(&obj->co_lu)) : NULL;
+       return obj ? lu2cl(lu_object_next(&obj->co_lu)) : NULL;
 }
 
 static inline struct cl_object_header *luh2coh(const struct lu_object_header *h)
 {
-        return container_of0(h, struct cl_object_header, coh_lu);
+       return container_of_safe(h, struct cl_object_header, coh_lu);
 }
 
 static inline struct cl_site *cl_object_site(const struct cl_object *obj)
 {
-        return lu2cl_site(obj->co_lu.lo_dev->ld_site);
+       return lu2cl_site(obj->co_lu.lo_dev->ld_site);
 }
 
 static inline
 struct cl_object_header *cl_object_header(const struct cl_object *obj)
 {
-        return luh2coh(obj->co_lu.lo_header);
+       return luh2coh(obj->co_lu.lo_header);
 }
 
 static inline int cl_device_init(struct cl_device *d, struct lu_device_type *t)
 {
-        return lu_device_init(&d->cd_lu_dev, t);
+       return lu_device_init(&d->cd_lu_dev, t);
 }
 
 static inline void cl_device_fini(struct cl_device *d)
 {
-        lu_device_fini(&d->cd_lu_dev);
+       lu_device_fini(&d->cd_lu_dev);
 }
 
 void cl_page_slice_add(struct cl_page *page, struct cl_page_slice *slice,
-                      struct cl_object *obj, pgoff_t index,
+                      struct cl_object *obj,
                       const struct cl_page_operations *ops);
 void cl_lock_slice_add(struct cl_lock *lock, struct cl_lock_slice *slice,
                        struct cl_object *obj,
@@ -2161,14 +2237,6 @@ static inline int cl_object_refc(struct cl_object *clob)
 
 /** \defgroup cl_page cl_page
  * @{ */
-enum {
-        CLP_GANG_OKAY = 0,
-        CLP_GANG_RESCHED,
-        CLP_GANG_AGAIN,
-        CLP_GANG_ABORT
-};
-/* callback of cl_page_gang_lookup() */
-
 struct cl_page *cl_page_find        (const struct lu_env *env,
                                      struct cl_object *obj,
                                      pgoff_t idx, struct page *vmpage,
@@ -2233,7 +2301,6 @@ int  cl_page_cache_add  (const struct lu_env *env, struct cl_io *io,
                          struct cl_page *pg, enum cl_req_type crt);
 void cl_page_clip       (const struct lu_env *env, struct cl_page *pg,
                          int from, int to);
-int  cl_page_cancel     (const struct lu_env *env, struct cl_page *page);
 int  cl_page_flush      (const struct lu_env *env, struct cl_io *io,
                         struct cl_page *pg);
 
@@ -2310,6 +2377,10 @@ struct cl_client_cache {
         * Used at umounting time and signaled on BRW commit
         */
        wait_queue_head_t       ccc_unstable_waitq;
+       /**
+        * Serialize max_cache_mb write operation
+        */
+       struct mutex            ccc_max_cache_mb_lock;
 };
 /**
  * cl_cache functions
@@ -2367,12 +2438,13 @@ int   cl_io_submit_sync  (const struct lu_env *env, struct cl_io *io,
 int   cl_io_commit_async (const struct lu_env *env, struct cl_io *io,
                          struct cl_page_list *queue, int from, int to,
                          cl_commit_cbt cb);
+void  cl_io_extent_release (const struct lu_env *env, struct cl_io *io);
+int cl_io_lru_reserve(const struct lu_env *env, struct cl_io *io,
+                     loff_t pos, size_t bytes);
 int   cl_io_read_ahead   (const struct lu_env *env, struct cl_io *io,
                          pgoff_t start, struct cl_read_ahead *ra);
 void  cl_io_rw_advance   (const struct lu_env *env, struct cl_io *io,
                           size_t nob);
-int   cl_io_cancel       (const struct lu_env *env, struct cl_io *io,
-                          struct cl_page_list *queue);
 
 /**
  * True, iff \a io is an O_APPEND write(2).
@@ -2392,13 +2464,25 @@ static inline int cl_io_is_mkwrite(const struct cl_io *io)
        return io->ci_type == CIT_FAULT && io->u.ci_fault.ft_mkwrite;
 }
 
+static inline int cl_io_is_fault_writable(const struct cl_io *io)
+{
+       return io->ci_type == CIT_FAULT && io->u.ci_fault.ft_writable;
+}
+
 /**
  * True, iff \a io is a truncate(2).
  */
 static inline int cl_io_is_trunc(const struct cl_io *io)
 {
        return io->ci_type == CIT_SETATTR &&
-               (io->u.ci_setattr.sa_avalid & ATTR_SIZE);
+               (io->u.ci_setattr.sa_avalid & ATTR_SIZE) &&
+               (io->u.ci_setattr.sa_subtype != CL_SETATTR_FALLOCATE);
+}
+
+static inline int cl_io_is_fallocate(const struct cl_io *io)
+{
+       return (io->ci_type == CIT_SETATTR) &&
+              (io->u.ci_setattr.sa_subtype == CL_SETATTR_FALLOCATE);
 }
 
 struct cl_io *cl_io_top(struct cl_io *io);
@@ -2446,33 +2530,35 @@ static inline struct cl_page *cl_page_list_first(struct cl_page_list *plist)
 #define cl_page_list_for_each_safe(page, temp, list)                    \
        list_for_each_entry_safe((page), (temp), &(list)->pl_pages, cp_batch)
 
-void cl_page_list_init   (struct cl_page_list *plist);
-void cl_page_list_add    (struct cl_page_list *plist, struct cl_page *page);
-void cl_page_list_move   (struct cl_page_list *dst, struct cl_page_list *src,
-                          struct cl_page *page);
+void cl_page_list_init(struct cl_page_list *plist);
+void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page,
+                     bool get_ref);
+void cl_page_list_move(struct cl_page_list *dst, struct cl_page_list *src,
+                      struct cl_page *page);
 void cl_page_list_move_head(struct cl_page_list *dst, struct cl_page_list *src,
-                         struct cl_page *page);
-void cl_page_list_splice (struct cl_page_list *list,
-                          struct cl_page_list *head);
-void cl_page_list_del    (const struct lu_env *env,
-                          struct cl_page_list *plist, struct cl_page *page);
-void cl_page_list_disown (const struct lu_env *env,
-                          struct cl_io *io, struct cl_page_list *plist);
-void cl_page_list_assume (const struct lu_env *env,
-                          struct cl_io *io, struct cl_page_list *plist);
+                           struct cl_page *page);
+void cl_page_list_splice(struct cl_page_list *list,
+                        struct cl_page_list *head);
+void cl_page_list_del(const struct lu_env *env,
+                     struct cl_page_list *plist, struct cl_page *page);
+void cl_page_list_disown(const struct lu_env *env,
+                        struct cl_io *io, struct cl_page_list *plist);
+void cl_page_list_assume(const struct lu_env *env,
+                        struct cl_io *io, struct cl_page_list *plist);
 void cl_page_list_discard(const struct lu_env *env,
-                          struct cl_io *io, struct cl_page_list *plist);
-void cl_page_list_fini   (const struct lu_env *env, struct cl_page_list *plist);
-
-void cl_2queue_init     (struct cl_2queue *queue);
-void cl_2queue_add      (struct cl_2queue *queue, struct cl_page *page);
-void cl_2queue_disown   (const struct lu_env *env,
-                         struct cl_io *io, struct cl_2queue *queue);
-void cl_2queue_assume   (const struct lu_env *env,
-                         struct cl_io *io, struct cl_2queue *queue);
-void cl_2queue_discard  (const struct lu_env *env,
-                         struct cl_io *io, struct cl_2queue *queue);
-void cl_2queue_fini     (const struct lu_env *env, struct cl_2queue *queue);
+                         struct cl_io *io, struct cl_page_list *plist);
+void cl_page_list_fini(const struct lu_env *env, struct cl_page_list *plist);
+
+void cl_2queue_init(struct cl_2queue *queue);
+void cl_2queue_add(struct cl_2queue *queue, struct cl_page *page,
+                  bool get_ref);
+void cl_2queue_disown(const struct lu_env *env, struct cl_io *io,
+                     struct cl_2queue *queue);
+void cl_2queue_assume(const struct lu_env *env, struct cl_io *io,
+                     struct cl_2queue *queue);
+void cl_2queue_discard(const struct lu_env *env, struct cl_io *io,
+                      struct cl_2queue *queue);
+void cl_2queue_fini(const struct lu_env *env, struct cl_2queue *queue);
 void cl_2queue_init_page(struct cl_2queue *queue, struct cl_page *page);
 
 /** @} cl_page_list */
@@ -2491,11 +2577,14 @@ typedef void (cl_sync_io_end_t)(const struct lu_env *, struct cl_sync_io *);
 void cl_sync_io_init_notify(struct cl_sync_io *anchor, int nr,
                            struct cl_dio_aio *aio, cl_sync_io_end_t *end);
 
-int  cl_sync_io_wait(const struct lu_env *env, struct cl_sync_io *anchor,
-                    long timeout);
+int cl_sync_io_wait(const struct lu_env *env, struct cl_sync_io *anchor,
+                   long timeout);
 void cl_sync_io_note(const struct lu_env *env, struct cl_sync_io *anchor,
                     int ioret);
-struct cl_dio_aio *cl_aio_alloc(struct kiocb *iocb);
+int cl_sync_io_wait_recycle(const struct lu_env *env, struct cl_sync_io *anchor,
+                           long timeout, int ioret);
+struct cl_dio_aio *cl_aio_alloc(struct kiocb *iocb, struct cl_object *obj);
+void cl_aio_free(const struct lu_env *env, struct cl_dio_aio *aio);
 static inline void cl_sync_io_init(struct cl_sync_io *anchor, int nr)
 {
        cl_sync_io_init_notify(anchor, nr, NULL, NULL);
@@ -2524,8 +2613,10 @@ struct cl_sync_io {
 struct cl_dio_aio {
        struct cl_sync_io       cda_sync;
        struct cl_page_list     cda_pages;
+       struct cl_object        *cda_obj;
        struct kiocb            *cda_iocb;
        ssize_t                 cda_bytes;
+       unsigned                cda_no_aio_complete:1;
 };
 
 /** @} cl_sync_io */