Whamcloud - gitweb
LU-14286 osd-ldiskfs: fallocate() should zero new blocks
[fs/lustre-release.git] / lustre / osc / osc_cache.c
index e0c9901..364a71f 100644 (file)
@@ -1851,6 +1851,9 @@ can_merge(const struct osc_extent *ext, const struct osc_extent *in_rpc)
        if (in_rpc->oe_dio && overlapped(ext, in_rpc))
                return false;
 
+       if (ext->oe_is_rdma_only != in_rpc->oe_is_rdma_only)
+               return false;
+
        return true;
 }
 
@@ -2320,7 +2323,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
 
        oap->oap_cmd = cmd;
        oap->oap_page_off = ops->ops_from;
-       oap->oap_count = ops->ops_to - ops->ops_from;
+       oap->oap_count = ops->ops_to - ops->ops_from + 1;
        /* No need to hold a lock here,
         * since this page is not in any list yet. */
        oap->oap_async_flags = 0;
@@ -2581,7 +2584,8 @@ int osc_queue_sync_pages(const struct lu_env *env, const struct cl_io *io,
                ++page_count;
                mppr <<= (page_count > mppr);
 
-               if (unlikely(opg->ops_from > 0 || opg->ops_to < PAGE_SIZE))
+               if (unlikely(opg->ops_from > 0 ||
+                            opg->ops_to < PAGE_SIZE - 1))
                        can_merge = false;
        }
 
@@ -2606,6 +2610,29 @@ int osc_queue_sync_pages(const struct lu_env *env, const struct cl_io *io,
        ext->oe_srvlock = !!(brw_flags & OBD_BRW_SRVLOCK);
        ext->oe_ndelay = !!(brw_flags & OBD_BRW_NDELAY);
        ext->oe_dio = !!(brw_flags & OBD_BRW_NOCACHE);
+       if (ext->oe_dio && !ext->oe_rw) { /* direct io write */
+               int grants;
+               int ppc;
+
+               ppc = 1 << (cli->cl_chunkbits - PAGE_SHIFT);
+               grants = cli->cl_grant_extent_tax;
+               grants += (1 << cli->cl_chunkbits) *
+                       ((page_count + ppc - 1) / ppc);
+
+               spin_lock(&cli->cl_loi_list_lock);
+               if (osc_reserve_grant(cli, grants) == 0) {
+                       list_for_each_entry(oap, list, oap_pending_item) {
+                               osc_consume_write_grant(cli,
+                                                       &oap->oap_brw_page);
+                               atomic_long_inc(&obd_dirty_pages);
+                       }
+                       osc_unreserve_grant_nolock(cli, grants, 0);
+                       ext->oe_grants = grants;
+               }
+               spin_unlock(&cli->cl_loi_list_lock);
+       }
+
+       ext->oe_is_rdma_only = !!(brw_flags & OBD_BRW_RDMA_ONLY);
        ext->oe_nr_pages = page_count;
        ext->oe_mppr = mppr;
        list_splice_init(list, &ext->oe_pages);
@@ -3090,28 +3117,51 @@ static bool check_and_discard_cb(const struct lu_env *env, struct cl_io *io,
 {
        struct osc_thread_info *info = osc_env_info(env);
        struct osc_object *osc = cbdata;
+       struct cl_page *page = ops->ops_cl.cpl_page;
        pgoff_t index;
+       bool discard = false;
 
        index = osc_index(ops);
-       if (index >= info->oti_fn_index) {
-               struct ldlm_lock *tmp;
-               struct cl_page *page = ops->ops_cl.cpl_page;
 
+       /* negative lock caching */
+       if (index < info->oti_ng_index) {
+               discard = true;
+       } else if (index >= info->oti_fn_index) {
+               struct ldlm_lock *tmp;
                /* refresh non-overlapped index */
                tmp = osc_dlmlock_at_pgoff(env, osc, index,
-                                          OSC_DAP_FL_TEST_LOCK);
+                                          OSC_DAP_FL_TEST_LOCK |
+                                          OSC_DAP_FL_AST | OSC_DAP_FL_RIGHT);
                if (tmp != NULL) {
                        __u64 end = tmp->l_policy_data.l_extent.end;
-                       /* Cache the first-non-overlapped index so as to skip
-                        * all pages within [index, oti_fn_index). This is safe
-                        * because if tmp lock is canceled, it will discard
-                        * these pages. */
-                       info->oti_fn_index = cl_index(osc2cl(osc), end + 1);
-                       if (end == OBD_OBJECT_EOF)
-                               info->oti_fn_index = CL_PAGE_EOF;
+                       __u64 start = tmp->l_policy_data.l_extent.start;
+
+                       /* no lock covering this page */
+                       if (index < cl_index(osc2cl(osc), start)) {
+                               /* no lock at @index, first lock at @start */
+                               info->oti_ng_index = cl_index(osc2cl(osc),
+                                                    start);
+                               discard = true;
+                       } else {
+                               /* Cache the first-non-overlapped index so as to
+                                * skip all pages within [index, oti_fn_index).
+                                * This is safe because if tmp lock is canceled,
+                                * it will discard these pages.
+                                */
+                               info->oti_fn_index = cl_index(osc2cl(osc),
+                                                    end + 1);
+                               if (end == OBD_OBJECT_EOF)
+                                       info->oti_fn_index = CL_PAGE_EOF;
+                       }
                        LDLM_LOCK_PUT(tmp);
-               } else if (cl_page_own(env, io, page) == 0) {
-                       /* discard the page */
+               } else {
+                       info->oti_ng_index = CL_PAGE_EOF;
+                       discard = true;
+               }
+       }
+
+       if (discard) {
+               if (cl_page_own(env, io, page) == 0) {
                        cl_page_discard(env, io, page);
                        cl_page_disown(env, io, page);
                } else {
@@ -3174,6 +3224,7 @@ int osc_lock_discard_pages(const struct lu_env *env, struct osc_object *osc,
 
        cb = discard ? osc_discard_cb : check_and_discard_cb;
        info->oti_fn_index = info->oti_next_index = start;
+       info->oti_ng_index = 0;
 
        osc_page_gang_lookup(env, io, osc,
                             info->oti_next_index, end, cb, osc);