diff --git a/lustre/include/lustre_net.h b/lustre/include/lustre_net.h
index 2391e80c577d3e85b65424c0d045ed218b78fefa..8543659c4e4012d8ba016cd79c0de73a661d4865 100644
--- a/lustre/include/lustre_net.h
+++ b/lustre/include/lustre_net.h
@@ -181,21 +181,16 @@ struct ptlrpc_request_set {
         cfs_waitq_t       set_waitq;
         cfs_waitq_t      *set_wakeup_ptr;
         struct list_head  set_requests;
-        struct list_head  set_cblist; /* list of completion callbacks */
         set_interpreter_func    set_interpret; /* completion callback */
         void              *set_arg; /* completion context */
+        void              *set_countp; /* pointer to NOB counter in case 
+                                        * of directIO (bug11737) */
         /* locked so that any old caller can communicate requests to
          * the set holder who can then fold them into the lock-free set */
         spinlock_t        set_new_req_lock;
         struct list_head  set_new_requests;
 };
 
-struct ptlrpc_set_cbdata {
-        struct list_head        psc_item;
-        set_interpreter_func    psc_interpret;
-        void                   *psc_data;
-};
-
 struct ptlrpc_bulk_desc;
 
 /*
@@ -694,8 +689,6 @@ void ptlrpc_restart_req(struct ptlrpc_request *req);
 void ptlrpc_abort_inflight(struct obd_import *imp);
 
 struct ptlrpc_request_set *ptlrpc_prep_set(void);
-int ptlrpc_set_add_cb(struct ptlrpc_request_set *set,
-                      set_interpreter_func fn, void *data);
 int ptlrpc_set_next_timeout(struct ptlrpc_request_set *);
 int ptlrpc_check_set(struct ptlrpc_request_set *set);
 int ptlrpc_set_wait(struct ptlrpc_request_set *);
diff --git a/lustre/include/obd_class.h b/lustre/include/obd_class.h
index 19bf151fd070dae3ecab45407408db1a24225c8e..cfb217eab271236c5413867dbd2f70471ca21e4b 100644
--- a/lustre/include/obd_class.h
+++ b/lustre/include/obd_class.h
@@ -923,12 +923,15 @@ static inline int obd_brw_rqset(int cmd, struct obd_export *exp,
 {
         struct ptlrpc_request_set *set = NULL;
         struct obd_info oinfo = { { { 0 } } };
+        atomic_t nob;
         int rc = 0;
         ENTRY;
 
         set =  ptlrpc_prep_set();
         if (set == NULL)
                 RETURN(-ENOMEM);
+        atomic_set(&nob, 0);
+        set->set_countp = &nob;
 
         oinfo.oi_oa = oa;
         oinfo.oi_md = lsm;
@@ -937,6 +940,8 @@ static inline int obd_brw_rqset(int cmd, struct obd_export *exp,
                 rc = ptlrpc_set_wait(set);
                 if (rc)
                         CERROR("error from callback: rc = %d\n", rc);
+                else
+                        rc = atomic_read(&nob);
         } else {
                 CDEBUG(rc == -ENOSPC ? D_INODE : D_ERROR,
                        "error from obd_brw_async: rc = %d\n", rc);
diff --git a/lustre/llite/rw26.c b/lustre/llite/rw26.c
index 5ea3a6c0e87307d2ca66faddc89132f55384722b..d32a4472bb3807c53906b4f1b827a076c1362fef 100644
--- a/lustre/llite/rw26.c
+++ b/lustre/llite/rw26.c
@@ -133,14 +133,15 @@ static void ll_free_user_pages(struct page **pages, int npages, int do_dirty)
 
 static ssize_t ll_direct_IO_26_seg(int rw, struct inode *inode,
                                    struct address_space *mapping,
-                                   struct obd_info *oinfo,
-                                   struct ptlrpc_request_set *set,
+                                   struct lov_stripe_md *lsm,
                                    size_t size, loff_t file_offset,
                                    struct page **pages, int page_count)
 {
         struct brw_page *pga;
+        struct obdo oa;
         int i, rc = 0;
         size_t length;
+        loff_t file_offset_orig = file_offset;
         ENTRY;
 
         OBD_ALLOC(pga, sizeof(*pga) * page_count);
@@ -162,11 +163,15 @@ static ssize_t ll_direct_IO_26_seg(int rw, struct inode *inode,
                         POISON_PAGE(pages[i], 0x0d);
         }
 
-        rc = obd_brw_async(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ,
-                           ll_i2obdexp(inode), oinfo, page_count,
-                           pga, NULL, set);
-        if (rc == 0)
-                rc = size;
+        ll_inode_fill_obdo(inode, rw, &oa);
+
+        rc = obd_brw_rqset(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ,
+                           ll_i2obdexp(inode), &oa, lsm, page_count, pga, NULL);
+        if ((rc > 0) && (rw == WRITE)) {
+                lov_stripe_lock(lsm);
+                obd_adjust_kms(ll_i2obdexp(inode), lsm, file_offset_orig + rc, 0);
+                lov_stripe_unlock(lsm);
+        }
 
         OBD_FREE(pga, sizeof(*pga) * page_count);
         RETURN(rc);
@@ -186,10 +191,6 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
         struct inode *inode = file->f_mapping->host;
         ssize_t count = iov_length(iov, nr_segs), tot_bytes = 0;
         struct ll_inode_info *lli = ll_i2info(inode);
-        struct lov_stripe_md *lsm = lli->lli_smd;
-        struct ptlrpc_request_set *set;
-        struct obd_info oinfo;
-        struct obdo oa;
         unsigned long seg;
         size_t size = MAX_DIO_SIZE;
         ENTRY;
@@ -219,30 +220,10 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
                         RETURN(-EINVAL);
         }
 
-        set = ptlrpc_prep_set();
-        if (set == NULL)
-                RETURN(-ENOMEM);
-
-        ll_inode_fill_obdo(inode, rw, &oa);
-        oinfo.oi_oa = &oa;
-        oinfo.oi_md = lsm;
-
-        /* need locking between buffered and direct access. and race with 
-         *size changing by concurrent truncates and writes. */
-        if (rw == READ)
-                LOCK_INODE_MUTEX(inode);
-
         for (seg = 0; seg < nr_segs; seg++) {
                 size_t iov_left = iov[seg].iov_len;
                 unsigned long user_addr = (unsigned long)iov[seg].iov_base;
 
-                if (rw == READ) {
-                        if (file_offset >= inode->i_size)
-                                break;
-                        if (file_offset + iov_left > inode->i_size)
-                                iov_left = inode->i_size - file_offset;
-                }
-
                 while (iov_left > 0) {
                         struct page **pages;
                         int page_count;
@@ -255,7 +236,7 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
                         if (page_count > 0) {
                                 result = ll_direct_IO_26_seg(rw, inode,
                                                              file->f_mapping,
-                                                             &oinfo, set,
+                                                             lli->lli_smd,
                                                              min(size,iov_left),
                                                              file_offset, pages,
                                                              page_count);
@@ -280,8 +261,8 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
                                         continue;
                                 }
                                 if (tot_bytes > 0)
-                                        GOTO(wait_io, tot_bytes);
-                                GOTO(out, tot_bytes = page_count < 0 ? page_count : result);
+                                        RETURN(tot_bytes);
+                                RETURN(page_count < 0 ? page_count : result);
                         }
 
                         tot_bytes += result;
@@ -290,24 +271,6 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
                         user_addr += result;
                 }
         }
-
-        if (tot_bytes > 0) {
-                int rc;
-        wait_io:
-                rc = ptlrpc_set_wait(set);
-                if (rc)
-                        GOTO(out, tot_bytes = rc);
-                if (rw == WRITE) {
-                        lov_stripe_lock(lsm);
-                        obd_adjust_kms(ll_i2obdexp(inode), lsm, file_offset, 0);
-                        lov_stripe_unlock(lsm);
-                }
-        }
-out:
-        if (rw == READ)
-                UNLOCK_INODE_MUTEX(inode);
-
-        ptlrpc_set_destroy(set);
         RETURN(tot_bytes);
 }
 
diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c
index 66c2ece7859acf8e68cb4bedf710c89aa51c2fbc..31569ca2168c4dd5a7048e16a0f4cb10922f91ae 100644
--- a/lustre/lov/lov_obd.c
+++ b/lustre/lov/lov_obd.c
@@ -1583,10 +1583,8 @@ static int lov_brw_async(int cmd, struct obd_export *exp,
         }
         LASSERT(rc == 0);
         LASSERT(set->set_interpret == NULL);
-        LASSERT(set->set_arg == NULL);
-        rc = ptlrpc_set_add_cb(set, lov_brw_interpret, lovset);
-        if (rc)
-                GOTO(out, rc);
+        set->set_interpret = (set_interpreter_func)lov_brw_interpret;
+        set->set_arg = (void *)lovset;
 
         RETURN(rc);
 out:
diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c
index 955caa1b6a36f869e188a7fa5b01c9a7e4df44b5..381631cadffbb34876b79d97c3da31b9694073a9 100644
--- a/lustre/osc/osc_request.c
+++ b/lustre/osc/osc_request.c
@@ -1354,6 +1354,7 @@ static int brw_interpret(struct ptlrpc_request *request, void *data, int rc)
 {
         struct osc_brw_async_args *aa = data;
         int                        i;
+        int                        nob = rc;
         ENTRY;
 
         rc = osc_brw_fini_request(request, rc);
@@ -1363,6 +1364,8 @@ static int brw_interpret(struct ptlrpc_request *request, void *data, int rc)
                 if (rc == 0)
                         RETURN(0);
         }
+        if ((rc >= 0) && request->rq_set && request->rq_set->set_countp)
+                atomic_add(nob, (atomic_t *)request->rq_set->set_countp);
         client_obd_list_lock(&aa->aa_cli->cl_loi_list_lock);
         if (lustre_msg_get_opc(request->rq_reqmsg) == OST_WRITE)
                 aa->aa_cli->cl_w_in_flight--;
diff --git a/lustre/ptlrpc/client.c b/lustre/ptlrpc/client.c
index 00a7f1949b33a1a644aa33a6b66ce5cb2752bceb..c182672cf12ab97791c53c8308e485f666351abe 100644
--- a/lustre/ptlrpc/client.c
+++ b/lustre/ptlrpc/client.c
@@ -573,8 +573,7 @@ struct ptlrpc_request_set *ptlrpc_prep_set(void)
         set->set_remaining = 0;
         spin_lock_init(&set->set_new_req_lock);
         CFS_INIT_LIST_HEAD(&set->set_new_requests);
-        CFS_INIT_LIST_HEAD(&set->set_cblist);
-        
+
         RETURN(set);
 }
 
@@ -633,23 +632,6 @@ void ptlrpc_set_destroy(struct ptlrpc_request_set *set)
         EXIT;
 }
 
-int ptlrpc_set_add_cb(struct ptlrpc_request_set *set,
-                      set_interpreter_func fn, void *data)
-{
-        struct ptlrpc_set_cbdata *cbdata;
-
-        OBD_SLAB_ALLOC(cbdata, ptlrpc_cbdata_slab,
-                        CFS_ALLOC_STD, sizeof(*cbdata));
-        if (cbdata == NULL)
-                RETURN(-ENOMEM);
-
-        cbdata->psc_interpret = fn;
-        cbdata->psc_data = data;
-        list_add_tail(&cbdata->psc_item, &set->set_cblist);
-
-        RETURN(0);
-}
-
 void ptlrpc_set_add_req(struct ptlrpc_request_set *set,
                         struct ptlrpc_request *req)
 {
@@ -1393,19 +1375,6 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
                 int (*interpreter)(struct ptlrpc_request_set *set,void *,int) =
                         set->set_interpret;
                 rc = interpreter (set, set->set_arg, rc);
-        } else {
-                struct ptlrpc_set_cbdata *cbdata, *n;
-                int err;
-
-                list_for_each_entry_safe(cbdata, n,
-                                         &set->set_cblist, psc_item) {
-                        list_del_init(&cbdata->psc_item);
-                        err = cbdata->psc_interpret(set, cbdata->psc_data, rc);
-                        if (err && !rc)
-                                rc = err;
-                        OBD_SLAB_FREE(cbdata, ptlrpc_cbdata_slab,
-                                        sizeof(*cbdata));
-                }
         }
 
         RETURN(rc);
diff --git a/lustre/ptlrpc/ptlrpc_internal.h b/lustre/ptlrpc/ptlrpc_internal.h
index a769aa50605a2aea63898e2f4ae8a16c378a4f22..f427fbe0293f42fa93980e29be9e49f8e32d9118 100644
--- a/lustre/ptlrpc/ptlrpc_internal.h
+++ b/lustre/ptlrpc/ptlrpc_internal.h
@@ -35,7 +35,6 @@ struct obd_import;
 struct ldlm_res_id;
 struct ptlrpc_request_set;
 extern int test_req_buffer_pressure;
-extern cfs_mem_cache_t *ptlrpc_cbdata_slab;
 
 void ptlrpc_request_handle_notconn(struct ptlrpc_request *);
 void lustre_assert_wire_constants(void);
diff --git a/lustre/ptlrpc/ptlrpc_module.c b/lustre/ptlrpc/ptlrpc_module.c
index 889aa2d3959a1c1b89fecfa742c4a8e1335fe6b3..66d51b9f8671dd84af0397fb359d6d5e133d48e0 100644
--- a/lustre/ptlrpc/ptlrpc_module.c
+++ b/lustre/ptlrpc/ptlrpc_module.c
@@ -38,7 +38,6 @@
 
 #include "ptlrpc_internal.h"
 
-cfs_mem_cache_t *ptlrpc_cbdata_slab;
 extern spinlock_t ptlrpc_last_xid_lock;
 extern spinlock_t ptlrpc_rs_debug_lock;
 extern spinlock_t ptlrpc_all_services_lock;
@@ -79,19 +78,10 @@ __init int ptlrpc_init(void)
         rc = ldlm_init();
         if (rc)
                 GOTO(cleanup, rc);
-        cleanup_phase = 4;
-
-        ptlrpc_cbdata_slab = cfs_mem_cache_create("ptlrpc_cbdatas",
-                                sizeof (struct ptlrpc_set_cbdata), 0,
-                                SLAB_HWCACHE_ALIGN);
-        if (ptlrpc_cbdata_slab == NULL)
-                GOTO(cleanup, rc);
         RETURN(0);
 
 cleanup:
         switch(cleanup_phase) {
-        case 4:
-                ldlm_exit();
         case 3:
                 ptlrpc_stop_pinger();
         case 2:
@@ -111,7 +101,6 @@ static void __exit ptlrpc_exit(void)
         ptlrpc_stop_pinger();
         ptlrpc_exit_portals();
         ptlrpc_cleanup_connection();
-        cfs_mem_cache_destroy(ptlrpc_cbdata_slab);
 }
 
 /* connection.c */
@@ -160,7 +149,6 @@ EXPORT_SYMBOL(ptlrpc_retain_replayable_request);
 EXPORT_SYMBOL(ptlrpc_next_xid);
 
 EXPORT_SYMBOL(ptlrpc_prep_set);
-EXPORT_SYMBOL(ptlrpc_set_add_cb);
 EXPORT_SYMBOL(ptlrpc_set_add_req);
 EXPORT_SYMBOL(ptlrpc_set_add_new_req);
 EXPORT_SYMBOL(ptlrpc_set_destroy);
diff --git a/lustre/tests/directio.c b/lustre/tests/directio.c
index 1108cba9bdcf897aa3eb07d3329bb6e1146de7e4..ebcedb2c781063e69a3716234228b480efd27622 100644
--- a/lustre/tests/directio.c
+++ b/lustre/tests/directio.c
@@ -23,12 +23,11 @@ int main(int argc, char **argv)
         long len;
         off64_t seek;
         struct stat64 st;
-        char pad = 0xba;
         int action;
         int rc;
 
         if (argc < 5 || argc > 6) {
-                printf("Usage: %s <read/write/rdwr/readhole> file seek nr_blocks [blocksize]\n", argv[0]);
+                printf("Usage: %s <read/write/rdwr> file seek nr_blocks [blocksize]\n", argv[0]);
                 return 1;
         }
 
@@ -38,10 +37,7 @@ int main(int argc, char **argv)
                 action = O_WRONLY;
         else if (!strcmp(argv[1], "rdwr"))
                 action = O_RDWR;
-        else if (!strcmp(argv[1], "readhole")) {
-                action = O_RDONLY;
-                pad = 0;
-        } else {
+        else {
                 printf("Usage: %s <read/write/rdwr> file seek nr_blocks [blocksize]\n", argv[0]);
                 return 1;
         }
@@ -78,7 +74,7 @@ int main(int argc, char **argv)
                 printf("No memory %s\n", strerror(errno));
                 return 1;
         }
-        memset(wbuf, pad, len);
+        memset(wbuf, 0xba, len);
 
         if (action == O_WRONLY || action == O_RDWR) {
                 if (lseek64(fd, seek, SEEK_SET) < 0) {
diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh
index f397bd727d244669262acf1e9365ce7da2ea4811..ab063888d5b4bd76c23897981215b493c802c7de 100644
--- a/lustre/tests/sanity.sh
+++ b/lustre/tests/sanity.sh
@@ -4299,19 +4299,9 @@ test_119b() # bug 11737
         sync
         multiop $DIR/$tfile oO_RDONLY:O_DIRECT:r$((2048 * 1024)) || \
                 error "direct read failed"
-        rm -f $DIR/$tfile
 }
 run_test 119b "Sparse directIO read must return actual read amount"
 
-test_119c() # bug 13099
-{
-        BSIZE=1048576
-        directio write $DIR/$tfile 3 1 $BSIZE || error "direct write failed"
-        directio readhole $DIR/$tfile 0 2 $BSIZE || error "reading hole failed"
-        rm -f $DIR/$tfile
-}
-run_test 119c "Testing for direct read hitting hole"
-
 LDLM_POOL_CTL_RECALC=1
 LDLM_POOL_CTL_SHRINK=2