Whamcloud - gitweb
LU-2531 osc: evict extents in trunc whatever happens
[fs/lustre-release.git] / lustre / osc / osc_cache.c
index 48ca84c..ebdb17b 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011 Whamcloud, Inc.
+ * Copyright (c) 2012, Intel Corporation.
  *
  */
 /*
@@ -799,10 +799,11 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext,
        struct client_obd *cli = osc_cli(ext->oe_obj);
        struct osc_async_page *oap;
        struct osc_async_page *tmp;
-       struct osc_async_page *last = NULL;
        int nr_pages = ext->oe_nr_pages;
        int lost_grant = 0;
        int blocksize = cli->cl_import->imp_obd->obd_osfs.os_bsize ? : 4096;
+       __u64 last_off = 0;
+       int last_count = -1;
        ENTRY;
 
        OSC_EXTENT_DUMP(D_CACHE, ext, "extent finished.\n");
@@ -813,8 +814,10 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext,
                                     oap_pending_item) {
                cfs_list_del_init(&oap->oap_rpc_item);
                cfs_list_del_init(&oap->oap_pending_item);
-               if (last == NULL || last->oap_obj_off < oap->oap_obj_off)
-                       last = oap;
+               if (last_off <= oap->oap_obj_off) {
+                       last_off = oap->oap_obj_off;
+                       last_count = oap->oap_count;
+               }
 
                --ext->oe_nr_pages;
                osc_ap_completion(env, cli, oap, sent, rc);
@@ -824,7 +827,7 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext,
        if (!sent) {
                lost_grant = ext->oe_grants;
        } else if (blocksize < CFS_PAGE_SIZE &&
-                  last->oap_count != CFS_PAGE_SIZE) {
+                  last_count != CFS_PAGE_SIZE) {
                /* For short writes we shouldn't count parts of pages that
                 * span a whole chunk on the OST side, or our accounting goes
                 * wrong.  Should match the code in filter_grant_check. */
@@ -1390,8 +1393,6 @@ static void __osc_unreserve_grant(struct client_obd *cli,
        } else {
                cli->cl_avail_grant += unused;
        }
-       if (unused > 0)
-               osc_wake_cache_waiters(cli);
 }
 
 void osc_unreserve_grant(struct client_obd *cli,
@@ -1399,6 +1400,8 @@ void osc_unreserve_grant(struct client_obd *cli,
 {
        client_obd_list_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);
 }
 
@@ -1437,12 +1440,15 @@ static void osc_free_grant(struct client_obd *cli, unsigned int nr_pages,
               cli->cl_avail_grant, cli->cl_dirty);
 }
 
-/* The companion to osc_enter_cache(), called when @oap is no longer part of
- * the dirty accounting.  Writeback completes or truncate happens before
- * writing starts.  Must be called with the loi lock held. */
+/**
+ * The companion to osc_enter_cache(), called when @oap is no longer part of
+ * the dirty accounting due to error.
+ */
 static void osc_exit_cache(struct client_obd *cli, struct osc_async_page *oap)
 {
+       client_obd_list_lock(&cli->cl_loi_list_lock);
        osc_release_write_grant(cli, &oap->oap_brw_page);
+       client_obd_list_unlock(&cli->cl_loi_list_lock);
 }
 
 /**
@@ -1477,8 +1483,13 @@ static int osc_enter_cache_try(struct client_obd *cli,
        return rc;
 }
 
-/* Caller must hold loi_list_lock - we drop/regain it if we need to wait for
- * grant or cache space. */
+/**
+ * The main entry to reserve dirty page accounting. Usually the grant reserved
+ * in this function will be freed in bulk in osc_free_grant() unless it fails
+ * to add osc cache, in that case, it will be freed in osc_exit_cache().
+ *
+ * The process will be put into sleep if it's already run out of grant.
+ */
 static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli,
                           struct osc_async_page *oap, int bytes)
 {
@@ -2433,10 +2444,11 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io,
                ext->oe_memalloc = 1;
 
        ext->oe_urgent = 1;
-       if (ext->oe_state == OES_CACHE && cfs_list_empty(&ext->oe_link)) {
+       if (ext->oe_state == OES_CACHE) {
                OSC_EXTENT_DUMP(D_CACHE, ext,
                                "flush page %p make it urgent.\n", oap);
-               cfs_list_add_tail(&ext->oe_link, &obj->oo_urgent_exts);
+               if (cfs_list_empty(&ext->oe_link))
+                       cfs_list_add_tail(&ext->oe_link, &obj->oo_urgent_exts);
                unplug = true;
        }
        rc = 0;
@@ -2613,6 +2625,8 @@ again:
                        break;
                }
 
+               OSC_EXTENT_DUMP(D_CACHE, ext, "try to trunc:"LPU64".\n", size);
+
                osc_extent_get(ext);
                if (ext->oe_state == OES_ACTIVE) {
                        /* though we grab inode mutex for write path, but we
@@ -2677,13 +2691,17 @@ again:
                osc_extent_put(env, ext);
        }
        if (waiting != NULL) {
-               if (result == 0)
-                       result = osc_extent_wait(env, waiting, OES_INV);
+               int rc;
+
+               /* ignore the result of osc_extent_wait the write initiator
+                * should take care of it. */
+               rc = osc_extent_wait(env, waiting, OES_INV);
+               if (rc < 0)
+                       OSC_EXTENT_DUMP(D_CACHE, ext, "wait error: %d.\n", rc);
 
                osc_extent_put(env, waiting);
                waiting = NULL;
-               if (result == 0)
-                       goto again;
+               goto again;
        }
        RETURN(result);
 }
@@ -2819,10 +2837,9 @@ int osc_cache_writeback_range(const struct lu_env *env, struct osc_object *obj,
                                        ext->oe_urgent = 1;
                                        list = &obj->oo_urgent_exts;
                                }
-                               if (list != NULL) {
+                               if (list != NULL)
                                        cfs_list_move_tail(&ext->oe_link, list);
-                                       unplug = true;
-                               }
+                               unplug = true;
                        } else {
                                /* the only discarder is lock cancelling, so
                                 * [start, end] must contain this extent */