Whamcloud - gitweb
LU-1346 libcfs: cleanup libcfs primitive (linux-prim.h)
[fs/lustre-release.git] / lustre / obdclass / cl_page.c
index acdb2e9..5db41e8 100644 (file)
@@ -179,8 +179,8 @@ EXPORT_SYMBOL(cl_page_lookup);
  * Return at least one page in @queue unless there is no covered page.
  */
 int cl_page_gang_lookup(const struct lu_env *env, struct cl_object *obj,
-                        struct cl_io *io, pgoff_t start, pgoff_t end,
-                        cl_page_gang_cb_t cb, void *cbdata)
+                       struct cl_io *io, pgoff_t start, pgoff_t end,
+                       cl_page_gang_cb_t cb, void *cbdata)
 {
         struct cl_object_header *hdr;
         struct cl_page          *page;
@@ -223,46 +223,46 @@ int cl_page_gang_lookup(const struct lu_env *env, struct cl_object *obj,
                          */
                         PASSERT(env, page, slice != NULL);
 
-                        page = slice->cpl_page;
-                        /*
-                         * Can safely call cl_page_get_trust() under
-                         * radix-tree spin-lock.
-                         *
-                         * XXX not true, because @page is from object another
-                         * than @hdr and protected by different tree lock.
-                         */
-                        cl_page_get_trust(page);
-                        lu_ref_add_atomic(&page->cp_reference,
-                                          "gang_lookup", cfs_current());
-                        pvec[j++] = page;
-                }
+                       page = slice->cpl_page;
+                       /*
+                        * Can safely call cl_page_get_trust() under
+                        * radix-tree spin-lock.
+                        *
+                        * XXX not true, because @page is from object another
+                        * than @hdr and protected by different tree lock.
+                        */
+                       cl_page_get_trust(page);
+                       lu_ref_add_atomic(&page->cp_reference,
+                                         "gang_lookup", current);
+                       pvec[j++] = page;
+               }
 
-                /*
-                 * Here a delicate locking dance is performed. Current thread
-                 * holds a reference to a page, but has to own it before it
-                 * can be placed into queue. Owning implies waiting, so
-                 * radix-tree lock is to be released. After a wait one has to
-                 * check that pages weren't truncated (cl_page_own() returns
-                 * error in the latter case).
-                 */
+               /*
+                * Here a delicate locking dance is performed. Current thread
+                * holds a reference to a page, but has to own it before it
+                * can be placed into queue. Owning implies waiting, so
+                * radix-tree lock is to be released. After a wait one has to
+                * check that pages weren't truncated (cl_page_own() returns
+                * error in the latter case).
+                */
                spin_unlock(&hdr->coh_page_guard);
-                tree_lock = 0;
-
-                for (i = 0; i < j; ++i) {
-                        page = pvec[i];
-                        if (res == CLP_GANG_OKAY)
-                                res = (*cb)(env, io, page, cbdata);
-                        lu_ref_del(&page->cp_reference,
-                                   "gang_lookup", cfs_current());
-                        cl_page_put(env, page);
-                }
-                if (nr < CLT_PVEC_SIZE || end_of_region)
-                        break;
+               tree_lock = 0;
+
+               for (i = 0; i < j; ++i) {
+                       page = pvec[i];
+                       if (res == CLP_GANG_OKAY)
+                               res = (*cb)(env, io, page, cbdata);
+                       lu_ref_del(&page->cp_reference,
+                                  "gang_lookup", current);
+                       cl_page_put(env, page);
+               }
+               if (nr < CLT_PVEC_SIZE || end_of_region)
+                       break;
 
-                if (res == CLP_GANG_OKAY && cfs_need_resched())
-                        res = CLP_GANG_RESCHED;
-                if (res != CLP_GANG_OKAY)
-                        break;
+               if (res == CLP_GANG_OKAY && need_resched())
+                       res = CLP_GANG_RESCHED;
+               if (res != CLP_GANG_OKAY)
+                       break;
 
                spin_lock(&hdr->coh_page_guard);
                tree_lock = 1;
@@ -514,7 +514,7 @@ static inline int cl_page_invariant(const struct cl_page *pg)
         child  = pg->cp_child;
         owner  = pg->cp_owner;
 
-        return cl_page_in_use(pg) &&
+        return cl_page_in_use_noref(pg) &&
                 ergo(parent != NULL, parent->cp_child == pg) &&
                 ergo(child != NULL, child->cp_parent == pg) &&
                 ergo(child != NULL, pg->cp_obj != child->cp_obj) &&
@@ -863,7 +863,7 @@ void cl_page_disown0(const struct lu_env *env,
         ENTRY;
         state = pg->cp_state;
         PINVRNT(env, pg, state == CPS_OWNED || state == CPS_FREEING);
-        PINVRNT(env, pg, cl_page_invariant(pg));
+        PINVRNT(env, pg, cl_page_invariant(pg) || state == CPS_FREEING);
         cl_page_owner_clear(pg);
 
         if (state == CPS_OWNED)
@@ -1045,7 +1045,8 @@ EXPORT_SYMBOL(cl_page_unassume);
 void cl_page_disown(const struct lu_env *env,
                     struct cl_io *io, struct cl_page *pg)
 {
-        PINVRNT(env, pg, cl_page_is_owned(pg, io));
+        PINVRNT(env, pg, cl_page_is_owned(pg, io) ||
+                        pg->cp_state == CPS_FREEING);
 
         ENTRY;
         pg = cl_page_top(pg);
@@ -1474,36 +1475,36 @@ static int page_prune_cb(const struct lu_env *env, struct cl_io *io,
  */
 int cl_pages_prune(const struct lu_env *env, struct cl_object *clobj)
 {
-        struct cl_thread_info   *info;
-        struct cl_object        *obj = cl_object_top(clobj);
-        struct cl_io            *io;
-        int                      result;
+       struct cl_thread_info   *info;
+       struct cl_object        *obj = cl_object_top(clobj);
+       struct cl_io            *io;
+       int                      result;
 
-        ENTRY;
-        info  = cl_env_info(env);
-        io    = &info->clt_io;
+       ENTRY;
+       info  = cl_env_info(env);
+       io    = &info->clt_io;
 
-        /*
-         * initialize the io. This is ugly since we never do IO in this
-         * function, we just make cl_page_list functions happy. -jay
-         */
-        io->ci_obj = obj;
+       /*
+        * initialize the io. This is ugly since we never do IO in this
+        * function, we just make cl_page_list functions happy. -jay
+        */
+       io->ci_obj = obj;
        io->ci_ignore_layout = 1;
-        result = cl_io_init(env, io, CIT_MISC, obj);
-        if (result != 0) {
-                cl_io_fini(env, io);
-                RETURN(io->ci_result);
-        }
+       result = cl_io_init(env, io, CIT_MISC, obj);
+       if (result != 0) {
+               cl_io_fini(env, io);
+               RETURN(io->ci_result);
+       }
 
-        do {
-                result = cl_page_gang_lookup(env, obj, io, 0, CL_PAGE_EOF,
-                                             page_prune_cb, NULL);
-                if (result == CLP_GANG_RESCHED)
-                        cfs_cond_resched();
-        } while (result != CLP_GANG_OKAY);
+       do {
+               result = cl_page_gang_lookup(env, obj, io, 0, CL_PAGE_EOF,
+                                            page_prune_cb, NULL);
+               if (result == CLP_GANG_RESCHED)
+                       cond_resched();
+       } while (result != CLP_GANG_OKAY);
 
-        cl_io_fini(env, io);
-        RETURN(result);
+       cl_io_fini(env, io);
+       RETURN(result);
 }
 EXPORT_SYMBOL(cl_pages_prune);