@@ -95,6 +95,7 @@
#include <linux/radix-tree.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
+#include <linux/pagevec.h>
struct inode;
@@ -896,7 +897,8 @@ struct cl_page_operations {
const struct cl_page_slice *slice);
/** Destructor. Frees resources and slice itself. */
void (*cpo_fini)(const struct lu_env *env,
- struct cl_page_slice *slice);
+ struct cl_page_slice *slice,
+ struct pagevec *pvec);
/**
* Optional debugging helper. Prints given page slice.
*
@@ -2147,6 +2149,9 @@ struct cl_page *cl_page_alloc(const struct lu_env *env,
enum cl_page_type type);
void cl_page_get(struct cl_page *page);
void cl_page_put(const struct lu_env *env, struct cl_page *page);
+void cl_pagevec_put(const struct lu_env *env,
+ struct cl_page *page,
+ struct pagevec *pvec);
void cl_page_print(const struct lu_env *env, void *cookie, lu_printer_t printer,
const struct cl_page *pg);
void cl_page_header_print(const struct lu_env *env, void *cookie,
@@ -179,6 +179,7 @@ struct osc_thread_info {
struct lustre_handle oti_handle;
struct cl_page_list oti_plist;
struct cl_io oti_io;
+ struct pagevec oti_pagevec;
void *oti_pvec[OTI_PVEC_SIZE];
/*
* Fields used by cl_lock_discard_pages().
@@ -54,16 +54,22 @@
*
*/
-static void vvp_page_fini_common(struct vvp_page *vpg)
+static void vvp_page_fini_common(struct vvp_page *vpg, struct pagevec *pvec)
{
struct page *vmpage = vpg->vpg_page;
LASSERT(vmpage);
- put_page(vmpage);
+ if (pvec) {
+ if (!pagevec_add(pvec, vmpage))
+ pagevec_release(pvec);
+ } else {
+ put_page(vmpage);
+ }
}
static void vvp_page_fini(const struct lu_env *env,
- struct cl_page_slice *slice)
+ struct cl_page_slice *slice,
+ struct pagevec *pvec)
{
struct vvp_page *vpg = cl2vvp_page(slice);
struct page *vmpage = vpg->vpg_page;
@@ -73,7 +79,7 @@ static void vvp_page_fini(const struct lu_env *env,
* VPG_FREEING state.
*/
LASSERT((struct cl_page *)vmpage->private != slice->cpl_page);
- vvp_page_fini_common(vpg);
+ vvp_page_fini_common(vpg, pvec);
}
static int vvp_page_own(const struct lu_env *env,
@@ -471,13 +477,14 @@ static int vvp_transient_page_is_vmlocked(const struct lu_env *env,
}
static void vvp_transient_page_fini(const struct lu_env *env,
- struct cl_page_slice *slice)
+ struct cl_page_slice *slice,
+ struct pagevec *pvec)
{
struct vvp_page *vpg = cl2vvp_page(slice);
struct cl_page *clp = slice->cpl_page;
struct vvp_object *clobj = cl2vvp(clp->cp_obj);
- vvp_page_fini_common(vpg);
+ vvp_page_fini_common(vpg, pvec);
atomic_dec(&clobj->vob_transient_pages);
}
@@ -4,5 +4,5 @@ ccflags-y += -I$(srctree)/$(src)/../include
obj-$(CONFIG_LUSTRE_FS) += lov.o
lov-y := lov_obd.o lov_pack.o lov_offset.o lov_merge.o \
lov_request.o lov_ea.o lov_dev.o lov_object.o lov_page.o \
- lov_lock.o lov_io.o lovsub_dev.o lovsub_object.o lovsub_page.o \
+ lov_lock.o lov_io.o lovsub_dev.o lovsub_object.o \
lov_pool.o lproc_lov.o
@@ -466,10 +466,6 @@ struct lov_sublock_env {
struct cl_io *lse_io;
};
-struct lovsub_page {
- struct cl_page_slice lsb_cl;
-};
-
struct lov_thread_info {
struct cl_object_conf lti_stripe_conf;
struct lu_fid lti_fid;
@@ -626,8 +622,6 @@ struct lov_io_sub *lov_sub_get(const struct lu_env *env, struct lov_io *lio,
int lov_page_init(const struct lu_env *env, struct cl_object *ob,
struct cl_page *page, pgoff_t index);
-int lovsub_page_init(const struct lu_env *env, struct cl_object *ob,
- struct cl_page *page, pgoff_t index);
int lov_page_init_empty(const struct lu_env *env, struct cl_object *obj,
struct cl_page *page, pgoff_t index);
int lov_page_init_composite(const struct lu_env *env, struct cl_object *obj,
@@ -782,13 +776,6 @@ static inline struct lov_page *cl2lov_page(const struct cl_page_slice *slice)
return container_of(slice, struct lov_page, lps_cl);
}
-static inline struct lovsub_page *
-cl2lovsub_page(const struct cl_page_slice *slice)
-{
- LINVRNT(lovsub_is_object(&slice->cpl_obj->co_lu));
- return container_of(slice, struct lovsub_page, lsb_cl);
-}
-
static inline struct lov_io *cl2lov_io(const struct lu_env *env,
const struct cl_io_slice *ios)
{
deleted file mode 100644
@@ -1,68 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * Implementation of cl_page for LOVSUB layer.
- *
- * Author: Nikita Danilov <nikita.danilov@sun.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LOV
-
-#include "lov_cl_internal.h"
-
-/** \addtogroup lov
- * @{
- */
-
-/*****************************************************************************
- *
- * Lovsub page operations.
- *
- */
-
-static void lovsub_page_fini(const struct lu_env *env,
- struct cl_page_slice *slice)
-{
-}
-
-static const struct cl_page_operations lovsub_page_ops = {
- .cpo_fini = lovsub_page_fini
-};
-
-int lovsub_page_init(const struct lu_env *env, struct cl_object *obj,
- struct cl_page *page, pgoff_t index)
-{
- struct lovsub_page *lsb = cl_object_page_slice(obj, page);
-
- cl_page_slice_add(page, &lsb->lsb_cl, obj, index, &lovsub_page_ops);
- return 0;
-}
-
-/** @} lov */
@@ -90,7 +90,8 @@ static void cl_page_get_trust(struct cl_page *page)
return NULL;
}
-static void cl_page_free(const struct lu_env *env, struct cl_page *page)
+static void cl_page_free(const struct lu_env *env, struct cl_page *page,
+ struct pagevec *pvec)
{
struct cl_object *obj = page->cp_obj;
struct cl_page_slice *slice;
@@ -104,7 +105,7 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *page)
cpl_linkage)) != NULL) {
list_del_init(page->cp_layers.next);
if (unlikely(slice->cpl_ops->cpo_fini))
- slice->cpl_ops->cpo_fini(env, slice);
+ slice->cpl_ops->cpo_fini(env, slice, pvec);
}
lu_object_ref_del_at(&obj->co_lu, &page->cp_obj_ref, "cl_page", page);
cl_object_put(env, obj);
@@ -152,7 +153,7 @@ struct cl_page *cl_page_alloc(const struct lu_env *env,
page, ind);
if (result != 0) {
__cl_page_delete(env, page);
- cl_page_free(env, page);
+ cl_page_free(env, page, NULL);
page = ERR_PTR(result);
break;
}
@@ -299,15 +300,13 @@ void cl_page_get(struct cl_page *page)
EXPORT_SYMBOL(cl_page_get);
/**
- * Releases a reference to a page.
+ * Releases a reference to a page, use the pagevec to release the pages
+ * in batch if provided.
*
- * When last reference is released, page is returned to the cache, unless it
- * is in cl_page_state::CPS_FREEING state, in which case it is immediately
- * destroyed.
- *
- * \see cl_object_put(), cl_lock_put().
+ * Users need to do a final pagevec_release() to release any trailing pages.
*/
-void cl_page_put(const struct lu_env *env, struct cl_page *page)
+void cl_pagevec_put(const struct lu_env *env, struct cl_page *page,
+ struct pagevec *pvec)
{
CL_PAGE_HEADER(D_TRACE, env, page, "%d\n",
refcount_read(&page->cp_ref));
@@ -322,9 +321,24 @@ void cl_page_put(const struct lu_env *env, struct cl_page *page)
* Page is no longer reachable by other threads. Tear
* it down.
*/
- cl_page_free(env, page);
+ cl_page_free(env, page, pvec);
}
}
+EXPORT_SYMBOL(cl_pagevec_put);
+
+/**
+ * Releases a reference to a page, wrapper to cl_pagevec_put
+ *
+ * When last reference is released, page is returned to the cache, unless it
+ * is in cl_page_state::CPS_FREEING state, in which case it is immediately
+ * destroyed.
+ *
+ * \see cl_object_put(), cl_lock_put().
+ */
+void cl_page_put(const struct lu_env *env, struct cl_page *page)
+{
+ cl_pagevec_put(env, page, NULL);
+}
EXPORT_SYMBOL(cl_page_put);
/**
@@ -259,7 +259,8 @@ static void echo_page_completion(const struct lu_env *env,
}
static void echo_page_fini(const struct lu_env *env,
- struct cl_page_slice *slice)
+ struct cl_page_slice *slice,
+ struct pagevec *pvec)
{
struct echo_object *eco = cl2echo_obj(slice->cpl_obj);
@@ -985,6 +985,7 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index,
struct client_obd *cli = osc_cli(obj);
struct osc_async_page *oap;
struct osc_async_page *tmp;
+ struct pagevec *pvec;
int pages_in_chunk = 0;
int ppc_bits = cli->cl_chunkbits - PAGE_SHIFT;
u64 trunc_chunk = trunc_index >> ppc_bits;
@@ -1008,6 +1009,8 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index,
io = osc_env_thread_io(env);
io->ci_obj = cl_object_top(osc2cl(obj));
io->ci_ignore_layout = 1;
+ pvec = &osc_env_info(env)->oti_pagevec;
+ pagevec_init(pvec);
rc = cl_io_init(env, io, CIT_MISC, io->ci_obj);
if (rc < 0)
goto out;
@@ -1046,11 +1049,13 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index,
}
lu_ref_del(&page->cp_reference, "truncate", current);
- cl_page_put(env, page);
+ cl_pagevec_put(env, page, pvec);
--ext->oe_nr_pages;
++nr_pages;
}
+ pagevec_release(pvec);
+
EASSERTF(ergo(ext->oe_start >= trunc_index + !!partial,
ext->oe_nr_pages == 0),
ext, "trunc_index %lu, partial %d\n", trunc_index, partial);
@@ -3030,6 +3035,7 @@ bool osc_page_gang_lookup(const struct lu_env *env, struct cl_io *io,
osc_page_gang_cbt cb, void *cbdata)
{
struct osc_page *ops;
+ struct pagevec *pagevec;
void **pvec;
pgoff_t idx;
unsigned int nr;
@@ -3040,6 +3046,8 @@ bool osc_page_gang_lookup(const struct lu_env *env, struct cl_io *io,
idx = start;
pvec = osc_env_info(env)->oti_pvec;
+ pagevec = &osc_env_info(env)->oti_pagevec;
+ pagevec_init(pagevec);
spin_lock(&osc->oo_tree_lock);
while ((nr = radix_tree_gang_lookup(&osc->oo_tree, pvec,
idx, OTI_PVEC_SIZE)) > 0) {
@@ -3086,8 +3094,10 @@ bool osc_page_gang_lookup(const struct lu_env *env, struct cl_io *io,
page = ops->ops_cl.cpl_page;
lu_ref_del(&page->cp_reference, "gang_lookup", current);
- cl_page_put(env, page);
+ cl_pagevec_put(env, page, pagevec);
}
+ pagevec_release(pagevec);
+
if (nr < OTI_PVEC_SIZE || end_of_region)
break;
@@ -506,8 +506,10 @@ static void osc_lru_use(struct client_obd *cli, struct osc_page *opg)
static void discard_pagevec(const struct lu_env *env, struct cl_io *io,
struct cl_page **pvec, int max_index)
{
+ struct pagevec *pagevec = &osc_env_info(env)->oti_pagevec;
int i;
+ pagevec_init(pagevec);
for (i = 0; i < max_index; i++) {
struct cl_page *page = pvec[i];
@@ -515,10 +517,11 @@ static void discard_pagevec(const struct lu_env *env, struct cl_io *io,
cl_page_delete(env, page);
cl_page_discard(env, io, page);
cl_page_disown(env, io, page);
- cl_page_put(env, page);
+ cl_pagevec_put(env, page, pagevec);
pvec[i] = NULL;
}
+ pagevec_release(pagevec);
}
/**