Whamcloud - gitweb
LU-5577 obd: change brw_page->count to unsigned
[fs/lustre-release.git] / lustre / osc / osc_cache.c
index de90f1a..c97ffa9 100644 (file)
@@ -76,6 +76,8 @@ static inline char *ext_flags(struct osc_extent *ext, char *flags)
        *buf++ = ext->oe_rw ? 'r' : 'w';
        if (ext->oe_intree)
                *buf++ = 'i';
+       if (ext->oe_sync)
+               *buf++ = 'S';
        if (ext->oe_srvlock)
                *buf++ = 's';
        if (ext->oe_hp)
@@ -102,28 +104,32 @@ static inline char list_empty_marker(struct list_head *list)
 static const char *oes_strings[] = {
        "inv", "active", "cache", "locking", "lockdone", "rpc", "trunc", NULL };
 
-#define OSC_EXTENT_DUMP(lvl, extent, fmt, ...) do {                    \
-       struct osc_extent *__ext = (extent);                            \
-       char __buf[16];                                                 \
-                                                                       \
-       CDEBUG(lvl,                                                     \
-               "extent %p@{" EXTSTR ", "                               \
-               "[%d|%d|%c|%s|%s|%p], [%d|%d|%c|%c|%p|%u|%p]} " fmt,    \
-               /* ----- extent part 0 ----- */                         \
-               __ext, EXTPARA(__ext),                                  \
-               /* ----- part 1 ----- */                                \
-               atomic_read(&__ext->oe_refc),                           \
-               atomic_read(&__ext->oe_users),                          \
-               list_empty_marker(&__ext->oe_link),                     \
-               oes_strings[__ext->oe_state], ext_flags(__ext, __buf),  \
-               __ext->oe_obj,                                          \
-               /* ----- part 2 ----- */                                \
-               __ext->oe_grants, __ext->oe_nr_pages,                   \
-               list_empty_marker(&__ext->oe_pages),                    \
-               waitqueue_active(&__ext->oe_waitq) ? '+' : '-',         \
-               __ext->oe_osclock, __ext->oe_mppr, __ext->oe_owner,     \
-               /* ----- part 4 ----- */                                \
-               ## __VA_ARGS__);                                        \
+#define OSC_EXTENT_DUMP(lvl, extent, fmt, ...) do {                          \
+       struct osc_extent *__ext = (extent);                                  \
+       char __buf[16];                                                       \
+                                                                             \
+       CDEBUG(lvl,                                                           \
+               "extent %p@{" EXTSTR ", "                                     \
+               "[%d|%d|%c|%s|%s|%p], [%d|%d|%c|%c|%p|%u|%p]} " fmt,          \
+               /* ----- extent part 0 ----- */                               \
+               __ext, EXTPARA(__ext),                                        \
+               /* ----- part 1 ----- */                                      \
+               atomic_read(&__ext->oe_refc),                         \
+               atomic_read(&__ext->oe_users),                        \
+               list_empty_marker(&__ext->oe_link),                           \
+               oes_strings[__ext->oe_state], ext_flags(__ext, __buf),        \
+               __ext->oe_obj,                                                \
+               /* ----- part 2 ----- */                                      \
+               __ext->oe_grants, __ext->oe_nr_pages,                         \
+               list_empty_marker(&__ext->oe_pages),                          \
+               waitqueue_active(&__ext->oe_waitq) ? '+' : '-',               \
+               __ext->oe_dlmlock, __ext->oe_mppr, __ext->oe_owner,           \
+               /* ----- part 4 ----- */                                      \
+               ## __VA_ARGS__);                                              \
+       if (lvl == D_ERROR && __ext->oe_dlmlock != NULL)                      \
+               LDLM_ERROR(__ext->oe_dlmlock, "extent: %p\n", __ext);         \
+       else                                                                  \
+               LDLM_DEBUG(__ext->oe_dlmlock, "extent: %p\n", __ext);         \
 } while (0)
 
 #undef EASSERTF
@@ -217,15 +223,19 @@ static int osc_extent_sanity_check0(struct osc_extent *ext,
        if (ext->oe_max_end < ext->oe_end || ext->oe_end < ext->oe_start)
                GOTO(out, rc = 80);
 
-       if (ext->oe_osclock == NULL && ext->oe_grants > 0)
+       if (ext->oe_sync && ext->oe_grants > 0)
                GOTO(out, rc = 90);
 
-       if (ext->oe_osclock) {
-               struct cl_lock_descr *descr;
-               descr = &ext->oe_osclock->cll_descr;
-               if (!(descr->cld_start <= ext->oe_start &&
-                     descr->cld_end >= ext->oe_max_end))
+       if (ext->oe_dlmlock != NULL) {
+               struct ldlm_extent *extent;
+
+               extent = &ext->oe_dlmlock->l_policy_data.l_extent;
+               if (!(extent->start <= cl_offset(osc2cl(obj), ext->oe_start) &&
+                     extent->end   >= cl_offset(osc2cl(obj), ext->oe_max_end)))
                        GOTO(out, rc = 100);
+
+               if (!(ext->oe_dlmlock->l_granted_mode & (LCK_PW | LCK_GROUP)))
+                       GOTO(out, rc = 102);
        }
 
        if (ext->oe_nr_pages > ext->oe_mppr)
@@ -321,7 +331,7 @@ static struct osc_extent *osc_extent_alloc(struct osc_object *obj)
        ext->oe_state = OES_INV;
        INIT_LIST_HEAD(&ext->oe_pages);
        init_waitqueue_head(&ext->oe_waitq);
-       ext->oe_osclock = NULL;
+       ext->oe_dlmlock = NULL;
 
        return ext;
 }
@@ -347,9 +357,11 @@ static void osc_extent_put(const struct lu_env *env, struct osc_extent *ext)
                LASSERT(ext->oe_state == OES_INV);
                LASSERT(!ext->oe_intree);
 
-               if (ext->oe_osclock) {
-                       cl_lock_put(env, ext->oe_osclock);
-                       ext->oe_osclock = NULL;
+               if (ext->oe_dlmlock != NULL) {
+                       lu_ref_add(&ext->oe_dlmlock->l_reference,
+                                  "osc_extent", ext);
+                       LDLM_LOCK_PUT(ext->oe_dlmlock);
+                       ext->oe_dlmlock = NULL;
                }
                osc_extent_free(ext);
        }
@@ -504,7 +516,7 @@ static int osc_extent_merge(const struct lu_env *env, struct osc_extent *cur,
        if (cur->oe_max_end != victim->oe_max_end)
                return -ERANGE;
 
-       LASSERT(cur->oe_osclock == victim->oe_osclock);
+       LASSERT(cur->oe_dlmlock == victim->oe_dlmlock);
        ppc_bits = osc_cli(obj)->cl_chunkbits - PAGE_CACHE_SHIFT;
        chunk_start = cur->oe_start >> ppc_bits;
        chunk_end   = cur->oe_end   >> ppc_bits;
@@ -584,13 +596,14 @@ static inline int overlapped(struct osc_extent *ex1, struct osc_extent *ex2)
  * Find or create an extent which includes @index, core function to manage
  * extent tree.
  */
-struct osc_extent *osc_extent_find(const struct lu_env *env,
-                                  struct osc_object *obj, pgoff_t index,
-                                  int *grants)
+static struct osc_extent *osc_extent_find(const struct lu_env *env,
+                                         struct osc_object *obj, pgoff_t index,
+                                         int *grants)
 
 {
        struct client_obd *cli = osc_cli(obj);
-       struct cl_lock    *lock;
+       struct osc_lock   *olck;
+       struct cl_lock_descr *descr;
        struct osc_extent *cur;
        struct osc_extent *ext;
        struct osc_extent *conflict = NULL;
@@ -608,9 +621,12 @@ struct osc_extent *osc_extent_find(const struct lu_env *env,
        if (cur == NULL)
                RETURN(ERR_PTR(-ENOMEM));
 
-       lock = cl_lock_at_pgoff(env, osc2cl(obj), index, NULL, 1, 0);
-       LASSERT(lock != NULL);
-       LASSERT(lock->cll_descr.cld_mode >= CLM_WRITE);
+       olck = osc_env_io(env)->oi_write_osclock;
+       LASSERTF(olck != NULL, "page %lu is not covered by lock\n", index);
+       LASSERT(olck->ols_state == OLS_GRANTED);
+
+       descr = &olck->ols_cl.cls_lock->cll_descr;
+       LASSERT(descr->cld_mode >= CLM_WRITE);
 
        LASSERT(cli->cl_chunkbits >= PAGE_CACHE_SHIFT);
        ppc_bits   = cli->cl_chunkbits - PAGE_CACHE_SHIFT;
@@ -622,19 +638,23 @@ struct osc_extent *osc_extent_find(const struct lu_env *env,
        max_pages = cli->cl_max_pages_per_rpc;
        LASSERT((max_pages & ~chunk_mask) == 0);
        max_end = index - (index % max_pages) + max_pages - 1;
-       max_end = min_t(pgoff_t, max_end, lock->cll_descr.cld_end);
+       max_end = min_t(pgoff_t, max_end, descr->cld_end);
 
        /* initialize new extent by parameters so far */
        cur->oe_max_end = max_end;
        cur->oe_start   = index & chunk_mask;
        cur->oe_end     = ((index + ~chunk_mask + 1) & chunk_mask) - 1;
-       if (cur->oe_start < lock->cll_descr.cld_start)
-               cur->oe_start = lock->cll_descr.cld_start;
+       if (cur->oe_start < descr->cld_start)
+               cur->oe_start = descr->cld_start;
        if (cur->oe_end > max_end)
                cur->oe_end = max_end;
-       cur->oe_osclock = lock;
        cur->oe_grants  = 0;
        cur->oe_mppr    = max_pages;
+       if (olck->ols_dlmlock != NULL) {
+               LASSERT(olck->ols_hold);
+               cur->oe_dlmlock = LDLM_LOCK_GET(olck->ols_dlmlock);
+               lu_ref_add(&olck->ols_dlmlock->l_reference, "osc_extent", cur);
+       }
 
        /* grants has been allocated by caller */
        LASSERTF(*grants >= chunksize + cli->cl_extent_tax,
@@ -656,7 +676,7 @@ restart:
                        break;
 
                /* if covering by different locks, no chance to match */
-               if (lock != ext->oe_osclock) {
+               if (olck->ols_dlmlock != ext->oe_dlmlock) {
                        EASSERTF(!overlapped(ext, cur), ext,
                                 EXTSTR"\n", EXTPARA(cur));
 
@@ -752,7 +772,7 @@ restart:
        if (found != NULL) {
                LASSERT(conflict == NULL);
                if (!IS_ERR(found)) {
-                       LASSERT(found->oe_osclock == cur->oe_osclock);
+                       LASSERT(found->oe_dlmlock == cur->oe_dlmlock);
                        OSC_EXTENT_DUMP(D_CACHE, found,
                                        "found caching ext for %lu.\n", index);
                }
@@ -767,7 +787,7 @@ restart:
                found = osc_extent_hold(cur);
                osc_extent_insert(obj, cur);
                OSC_EXTENT_DUMP(D_CACHE, cur, "add into tree %lu/%lu.\n",
-                               index, lock->cll_descr.cld_end);
+                               index, descr->cld_end);
        }
        osc_object_unlock(obj);
 
@@ -1037,7 +1057,7 @@ static int osc_extent_make_ready(const struct lu_env *env,
        struct osc_async_page *oap;
        struct osc_async_page *last = NULL;
        struct osc_object *obj = ext->oe_obj;
-       int page_count = 0;
+       unsigned int page_count = 0;
        int rc;
        ENTRY;
 
@@ -1078,9 +1098,10 @@ static int osc_extent_make_ready(const struct lu_env *env,
        /* the last page is the only one we need to refresh its count by
         * the size of file. */
        if (!(last->oap_async_flags & ASYNC_COUNT_STABLE)) {
-               last->oap_count = osc_refresh_count(env, last, OBD_BRW_WRITE);
-               LASSERT(last->oap_count > 0);
-               LASSERT(last->oap_page_off + last->oap_count <= PAGE_CACHE_SIZE);
+               int last_oap_count = osc_refresh_count(env, last, OBD_BRW_WRITE);
+               LASSERT(last_oap_count > 0);
+               LASSERT(last->oap_page_off + last_oap_count <= PAGE_CACHE_SIZE);
+               last->oap_count = last_oap_count;
                spin_lock(&last->oap_lock);
                last->oap_async_flags |= ASYNC_COUNT_STABLE;
                spin_unlock(&last->oap_lock);
@@ -1319,16 +1340,16 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap,
 
 #define OSC_DUMP_GRANT(lvl, cli, fmt, args...) do {                    \
        struct client_obd *__tmp = (cli);                               \
-       CDEBUG(lvl, "%s: grant { dirty: %ld/%ld dirty_pages: %d/%d "    \
+       CDEBUG(lvl, "%s: grant { dirty: %ld/%ld dirty_pages: %ld/%lu "  \
               "dropped: %ld avail: %ld, reserved: %ld, flight: %d }"   \
-              "lru {in list: %d, left: %d, waiters: %d }" fmt,         \
+              "lru {in list: %ld, left: %ld, waiters: %d }"fmt"\n",    \
               __tmp->cl_import->imp_obd->obd_name,                     \
               __tmp->cl_dirty_pages, __tmp->cl_dirty_max_pages,        \
-              atomic_read(&obd_dirty_pages), obd_max_dirty_pages,      \
+              atomic_long_read(&obd_dirty_pages), obd_max_dirty_pages, \
               __tmp->cl_lost_grant, __tmp->cl_avail_grant,             \
               __tmp->cl_reserved_grant, __tmp->cl_w_in_flight,         \
-              atomic_read(&__tmp->cl_lru_in_list),                     \
-              atomic_read(&__tmp->cl_lru_busy),                        \
+              atomic_long_read(&__tmp->cl_lru_in_list),                \
+              atomic_long_read(&__tmp->cl_lru_busy),                   \
               atomic_read(&__tmp->cl_lru_shrinkers), ##args);          \
 } while (0)
 
@@ -1336,9 +1357,9 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap,
 static void osc_consume_write_grant(struct client_obd *cli,
                                    struct brw_page *pga)
 {
-       assert_spin_locked(&cli->cl_loi_list_lock.lock);
+       assert_spin_locked(&cli->cl_loi_list_lock);
        LASSERT(!(pga->flag & OBD_BRW_FROM_GRANT));
-       atomic_inc(&obd_dirty_pages);
+       atomic_long_inc(&obd_dirty_pages);
        cli->cl_dirty_pages++;
        pga->flag |= OBD_BRW_FROM_GRANT;
        CDEBUG(D_CACHE, "using %lu grant credits for brw %p page %p\n",
@@ -1353,18 +1374,18 @@ static void osc_release_write_grant(struct client_obd *cli,
 {
        ENTRY;
 
-       assert_spin_locked(&cli->cl_loi_list_lock.lock);
+       assert_spin_locked(&cli->cl_loi_list_lock);
        if (!(pga->flag & OBD_BRW_FROM_GRANT)) {
                EXIT;
                return;
        }
 
        pga->flag &= ~OBD_BRW_FROM_GRANT;
-       atomic_dec(&obd_dirty_pages);
+       atomic_long_dec(&obd_dirty_pages);
        cli->cl_dirty_pages--;
        if (pga->flag & OBD_BRW_NOCACHE) {
                pga->flag &= ~OBD_BRW_NOCACHE;
-               atomic_dec(&obd_dirty_transit_pages);
+               atomic_long_dec(&obd_dirty_transit_pages);
                cli->cl_dirty_transit--;
        }
        EXIT;
@@ -1404,14 +1425,14 @@ static void __osc_unreserve_grant(struct client_obd *cli,
        }
 }
 
-void osc_unreserve_grant(struct client_obd *cli,
-                        unsigned int reserved, unsigned int unused)
+static void osc_unreserve_grant(struct client_obd *cli,
+                               unsigned int reserved, unsigned int unused)
 {
-       client_obd_list_lock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
        __osc_unreserve_grant(cli, reserved, unused);
        if (unused > 0)
                osc_wake_cache_waiters(cli);
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
 }
 
 /**
@@ -1432,8 +1453,8 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages,
 {
        int grant = (1 << cli->cl_chunkbits) + cli->cl_extent_tax;
 
-       client_obd_list_lock(&cli->cl_loi_list_lock);
-       atomic_sub(nr_pages, &obd_dirty_pages);
+       spin_lock(&cli->cl_loi_list_lock);
+       atomic_long_sub(nr_pages, &obd_dirty_pages);
        cli->cl_dirty_pages -= nr_pages;
        cli->cl_lost_grant += lost_grant;
        if (cli->cl_avail_grant < grant && cli->cl_lost_grant >= grant) {
@@ -1443,7 +1464,7 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages,
                cli->cl_avail_grant += grant;
        }
        osc_wake_cache_waiters(cli);
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
        CDEBUG(D_CACHE, "lost %u grant: %lu avail: %lu dirty: %lu\n",
               lost_grant, cli->cl_lost_grant,
               cli->cl_avail_grant, cli->cl_dirty_pages << PAGE_CACHE_SHIFT);
@@ -1455,9 +1476,9 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages,
  */
 static void osc_exit_cache(struct client_obd *cli, struct osc_async_page *oap)
 {
-       client_obd_list_lock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
        osc_release_write_grant(cli, &oap->oap_brw_page);
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
 }
 
 /**
@@ -1477,11 +1498,11 @@ static int osc_enter_cache_try(struct client_obd *cli,
                return 0;
 
        if (cli->cl_dirty_pages < cli->cl_dirty_max_pages &&
-           1 + atomic_read(&obd_dirty_pages) <= obd_max_dirty_pages) {
+           1 + atomic_long_read(&obd_dirty_pages) <= obd_max_dirty_pages) {
                osc_consume_write_grant(cli, &oap->oap_brw_page);
                if (transient) {
                        cli->cl_dirty_transit++;
-                       atomic_inc(&obd_dirty_transit_pages);
+                       atomic_long_inc(&obd_dirty_transit_pages);
                        oap->oap_brw_flags |= OBD_BRW_NOCACHE;
                }
                rc = 1;
@@ -1495,9 +1516,9 @@ static int osc_enter_cache_try(struct client_obd *cli,
 static int ocw_granted(struct client_obd *cli, struct osc_cache_waiter *ocw)
 {
        int rc;
-       client_obd_list_lock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
        rc = list_empty(&ocw->ocw_entry);
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
        return rc;
 }
 
@@ -1521,7 +1542,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli,
 
        OSC_DUMP_GRANT(D_CACHE, cli, "need:%d.\n", bytes);
 
-       client_obd_list_lock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
 
        /* force the caller to try sync io.  this can jump the list
         * of queued writes and create a discontiguous rpc stream */
@@ -1546,7 +1567,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli,
        while (cli->cl_dirty_pages > 0 || cli->cl_w_in_flight > 0) {
                list_add_tail(&ocw.ocw_entry, &cli->cl_cache_waiters);
                ocw.ocw_rc = 0;
-               client_obd_list_unlock(&cli->cl_loi_list_lock);
+               spin_unlock(&cli->cl_loi_list_lock);
 
                osc_io_unplug_async(env, cli, NULL);
 
@@ -1555,7 +1576,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli,
 
                rc = l_wait_event(ocw.ocw_waitq, ocw_granted(cli, &ocw), &lwi);
 
-               client_obd_list_lock(&cli->cl_loi_list_lock);
+               spin_lock(&cli->cl_loi_list_lock);
 
                /* l_wait_event is interrupted by signal, or timed out */
                if (rc < 0) {
@@ -1591,7 +1612,7 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli,
        }
        EXIT;
 out:
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
        OSC_DUMP_GRANT(D_CACHE, cli, "returned %d.\n", rc);
        RETURN(rc);
 }
@@ -1610,10 +1631,12 @@ void osc_wake_cache_waiters(struct client_obd *cli)
                ocw->ocw_rc = -EDQUOT;
                /* we can't dirty more */
                if ((cli->cl_dirty_pages  >= cli->cl_dirty_max_pages) ||
-                   (1 + atomic_read(&obd_dirty_pages) > obd_max_dirty_pages)) {
+                   (1 + atomic_long_read(&obd_dirty_pages) >
+                    obd_max_dirty_pages)) {
                        CDEBUG(D_CACHE, "no dirty room: dirty: %ld "
-                              "osc max %ld, sys max %d\n", cli->cl_dirty_pages,
-                              cli->cl_dirty_max_pages, obd_max_dirty_pages);
+                              "osc max %ld, sys max %ld\n",
+                              cli->cl_dirty_pages, cli->cl_dirty_max_pages,
+                              obd_max_dirty_pages);
                        goto wakeup;
                }
 
@@ -1750,9 +1773,9 @@ static int osc_list_maint(struct client_obd *cli, struct osc_object *osc)
 {
        int is_ready;
 
-       client_obd_list_lock(&cli->cl_loi_list_lock);
+       spin_lock(&cli->cl_loi_list_lock);
        is_ready = __osc_list_maint(cli, osc);
-       client_obd_list_unlock(&cli->cl_loi_list_lock);
+       spin_unlock(&cli->cl_loi_list_lock);
 
        return is_ready;
 }
@@ -1802,10 +1825,10 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli,
        oap->oap_interrupted = 0;
 
        if (oap->oap_cmd & OBD_BRW_WRITE && xid > 0) {
-               client_obd_list_lock(&cli->cl_loi_list_lock);
+               spin_lock(&cli->cl_loi_list_lock);
                osc_process_ar(&cli->cl_ar, xid, rc);
                osc_process_ar(&loi->loi_ar, xid, rc);
-               client_obd_list_unlock(&cli->cl_loi_list_lock);
+               spin_unlock(&cli->cl_loi_list_lock);
        }
 
        rc = osc_completion(env, oap, oap->oap_cmd, rc);
@@ -2120,7 +2143,7 @@ __must_hold(&cli->cl_loi_list_lock)
                }
 
                cl_object_get(obj);
-               client_obd_list_unlock(&cli->cl_loi_list_lock);
+               spin_unlock(&cli->cl_loi_list_lock);
                lu_object_ref_add_at(&obj->co_lu, &link, "check", current);
 
                /* attempt some read/write balancing by alternating between
@@ -2165,7 +2188,7 @@ __must_hold(&cli->cl_loi_list_lock)
                lu_object_ref_del_at(&obj->co_lu, &link, "check", current);
                cl_object_put(env, obj);
 
-               client_obd_list_lock(&cli->cl_loi_list_lock);
+               spin_lock(&cli->cl_loi_list_lock);
        }
 }
 
@@ -2181,9 +2204,9 @@ static int osc_io_unplug0(const struct lu_env *env, struct client_obd *cli,
                /* disable osc_lru_shrink() temporarily to avoid
                 * potential stack overrun problem. LU-2859 */
                atomic_inc(&cli->cl_lru_shrinkers);
-               client_obd_list_lock(&cli->cl_loi_list_lock);
+               spin_lock(&cli->cl_loi_list_lock);
                osc_check_rpcs(env, cli, pol);
-               client_obd_list_unlock(&cli->cl_loi_list_lock);
+               spin_unlock(&cli->cl_loi_list_lock);
                atomic_dec(&cli->cl_lru_shrinkers);
        } else {
                CDEBUG(D_CACHE, "Queue writeback work for client %p.\n", cli);
@@ -2319,9 +2342,9 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io,
                        grants = 0;
 
                /* it doesn't need any grant to dirty this page */
-               client_obd_list_lock(&cli->cl_loi_list_lock);
+               spin_lock(&cli->cl_loi_list_lock);
                rc = osc_enter_cache_try(cli, oap, grants, 0);
-               client_obd_list_unlock(&cli->cl_loi_list_lock);
+               spin_unlock(&cli->cl_loi_list_lock);
                if (rc == 0) { /* try failed */
                        grants = 0;
                        need_release = 1;
@@ -2614,6 +2637,7 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj,
        }
 
        ext->oe_rw = !!(cmd & OBD_BRW_READ);
+       ext->oe_sync = 1;
        ext->oe_urgent = 1;
        ext->oe_start = start;
        ext->oe_end = ext->oe_max_end = end;
@@ -3065,26 +3089,26 @@ static int check_and_discard_cb(const struct lu_env *env, struct cl_io *io,
                                struct osc_page *ops, void *cbdata)
 {
        struct osc_thread_info *info = osc_env_info(env);
-       struct cl_lock *lock = cbdata;
+       struct osc_object *osc = cbdata;
        pgoff_t index;
 
        index = osc_index(ops);
        if (index >= info->oti_fn_index) {
-               struct cl_lock *tmp;
+               struct ldlm_lock *tmp;
                struct cl_page *page = ops->ops_cl.cpl_page;
 
                /* refresh non-overlapped index */
-               tmp = cl_lock_at_pgoff(env, lock->cll_descr.cld_obj, index,
-                                      lock, 1, 0);
+               tmp = osc_dlmlock_at_pgoff(env, osc, index, 0, 0);
                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 = tmp->cll_descr.cld_end + 1;
-                       if (tmp->cll_descr.cld_end == CL_PAGE_EOF)
+                        * 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;
-                       cl_lock_put(env, tmp);
+                       LDLM_LOCK_PUT(tmp);
                } else if (cl_page_own(env, io, page) == 0) {
                        /* discard the page */
                        cl_page_discard(env, io, page);
@@ -3102,11 +3126,8 @@ static int discard_cb(const struct lu_env *env, struct cl_io *io,
                      struct osc_page *ops, void *cbdata)
 {
        struct osc_thread_info *info = osc_env_info(env);
-       struct cl_lock *lock = cbdata;
        struct cl_page *page = ops->ops_cl.cpl_page;
 
-       LASSERT(lock->cll_descr.cld_mode >= CLM_WRITE);
-
        /* page is top page. */
        info->oti_next_index = osc_index(ops) + 1;
        if (cl_page_own(env, io, page) == 0) {
@@ -3131,32 +3152,29 @@ static int discard_cb(const struct lu_env *env, struct cl_io *io,
  * If error happens on any step, the process continues anyway (the reasoning
  * behind this being that lock cancellation cannot be delayed indefinitely).
  */
-int osc_lock_discard_pages(const struct lu_env *env, struct osc_lock *ols)
+int osc_lock_discard_pages(const struct lu_env *env, struct osc_object *osc,
+                          pgoff_t start, pgoff_t end, enum cl_lock_mode mode)
 {
        struct osc_thread_info *info = osc_env_info(env);
        struct cl_io *io = &info->oti_io;
-       struct cl_object *osc = ols->ols_cl.cls_obj;
-       struct cl_lock *lock = ols->ols_cl.cls_lock;
-       struct cl_lock_descr *descr = &lock->cll_descr;
        osc_page_gang_cbt cb;
        int res;
        int result;
 
        ENTRY;
 
-       io->ci_obj = cl_object_top(osc);
+       io->ci_obj = cl_object_top(osc2cl(osc));
        io->ci_ignore_layout = 1;
        result = cl_io_init(env, io, CIT_MISC, io->ci_obj);
        if (result != 0)
                GOTO(out, result);
 
-       cb = descr->cld_mode == CLM_READ ? check_and_discard_cb : discard_cb;
-       info->oti_fn_index = info->oti_next_index = descr->cld_start;
+       cb = mode == CLM_READ ? check_and_discard_cb : discard_cb;
+       info->oti_fn_index = info->oti_next_index = start;
        do {
-               res = osc_page_gang_lookup(env, io, cl2osc(osc),
-                                          info->oti_next_index, descr->cld_end,
-                                          cb, (void *)lock);
-               if (info->oti_next_index > descr->cld_end)
+               res = osc_page_gang_lookup(env, io, osc,
+                                          info->oti_next_index, end, cb, osc);
+               if (info->oti_next_index > end)
                        break;
 
                if (res == CLP_GANG_RESCHED)