diff --git a/drivers/block/zram/zram_group/group_writeback.c b/drivers/block/zram/zram_group/group_writeback.c index ceeb5cf4321db059f0b52ed441f80b44448d5152..34f7ca6165870ff52b03a58ab533868398ca8a71 100644 --- a/drivers/block/zram/zram_group/group_writeback.c +++ b/drivers/block/zram/zram_group/group_writeback.c @@ -280,12 +280,18 @@ static u64 write_one_extent(struct zram *zram, u16 gid) if (!hpio) goto free_extent; + zgrp_get_ext(zram->zgrp, eid); size = collect_objs(zram, gid, hpio, hyperhold_extent_size(eid)); if (size == 0) { pr_err("group %u has no data in zram.\n", gid); + zgrp_put_ext(zram->zgrp, eid); goto put_hpio; } zgrp_ext_insert(zram->zgrp, eid, gid); + if (zgrp_put_ext(zram->zgrp, eid)) { + zgrp_ext_delete(zram->zgrp, eid, gid); + hyperhold_should_free_extent(eid); + } ret = hyperhold_write_async(hpio, write_endio, priv); if (ret) diff --git a/drivers/block/zram/zram_group/zlist.c b/drivers/block/zram/zram_group/zlist.c index d1fe608759492ea64bd6fb0843a05697834f5dcf..fd8295ecadaacb27312f7bde75cc48dd9940f54e 100644 --- a/drivers/block/zram/zram_group/zlist.c +++ b/drivers/block/zram/zram_group/zlist.c @@ -205,14 +205,22 @@ bool zlist_set_priv(u32 idx, struct zlist_table *tab) return ret; } -bool zlist_clr_priv(u32 idx, struct zlist_table *tab) +bool zlist_clr_priv_nolock(u32 idx, struct zlist_table *tab) { struct zlist_node *node = idx2node(idx, tab); bool ret = false; - zlist_node_lock(node); ret = !test_and_clear_bit(ZLIST_PRIV_BIT, (unsigned long *)node); - zlist_node_unlock(node); + + return ret; +} + +bool zlist_test_priv_nolock(u32 idx, struct zlist_table *tab) +{ + struct zlist_node *node = idx2node(idx, tab); + bool ret = false; + + ret = test_bit(ZLIST_PRIV_BIT, (unsigned long *)node); return ret; } diff --git a/drivers/block/zram/zram_group/zlist.h b/drivers/block/zram/zram_group/zlist.h index 9509e3b674ca8303caa6a2279948d29a30a199b7..a7cbf37509e9291a1feee9dbc9ac78f79a924f42 100644 --- a/drivers/block/zram/zram_group/zlist.h +++ b/drivers/block/zram/zram_group/zlist.h @@ -15,10 +15,10 @@ #define ZLIST_IDX_MAX (1 << ZLIST_IDX_SHIFT) struct zlist_node { - u32 prev : ZLIST_IDX_SHIFT; - u32 lock : 1; - u32 next : ZLIST_IDX_SHIFT; - u32 priv : 1; + u64 prev : ZLIST_IDX_SHIFT; + u64 lock : 1; + u64 next : ZLIST_IDX_SHIFT; + u64 priv : 1; }; struct zlist_table { @@ -83,7 +83,8 @@ static inline bool zlist_del(u32 hid, u32 idx, struct zlist_table *tab) } bool zlist_set_priv(u32 idx, struct zlist_table *tab); -bool zlist_clr_priv(u32 idx, struct zlist_table *tab); +bool zlist_clr_priv_nolock(u32 idx, struct zlist_table *tab); +bool zlist_test_priv_nolock(u32 idx, struct zlist_table *tab); void zlist_node_init(u32 idx, struct zlist_table *tab); diff --git a/drivers/block/zram/zram_group/zram_group.c b/drivers/block/zram/zram_group/zram_group.c index 85c7f00b4b7e40d7d5a78d65092d9aba5c316f01..9a023e77d5cdb9c90f2b5c2682d1373135e7d86f 100644 --- a/drivers/block/zram/zram_group/zram_group.c +++ b/drivers/block/zram/zram_group/zram_group.c @@ -489,6 +489,45 @@ u32 zgrp_isolate_exts(struct zram_group *zgrp, u16 gid, u32 *eids, u32 nr, bool return cnt; } +void zgrp_get_ext(struct zram_group *zgrp, u32 eid) +{ + u32 hid; + + if (!CHECK(zgrp, "zram group is not enable!\n")) + return; + if (!CHECK(zgrp->wbgrp.enable, "zram group writeback is not enable!\n")) + return; + if (!CHECK_BOUND(eid, 0, zgrp->wbgrp.nr_ext - 1)) + return; + + hid = eid + zgrp->nr_obj + zgrp->nr_grp; + zlist_set_priv(hid, zgrp->obj_tab); + pr_info("get extent %u\n", eid); +} + +bool zgrp_put_ext(struct zram_group *zgrp, u32 eid) +{ + u32 hid; + bool ret = false; + + if (!CHECK(zgrp, "zram group is not enable!\n")) + return false; + if (!CHECK(zgrp->wbgrp.enable, "zram group writeback is not enable!\n")) + return false; + if (!CHECK_BOUND(eid, 0, zgrp->wbgrp.nr_ext - 1)) + return false; + + hid = eid + zgrp->nr_obj + zgrp->nr_grp; + zlist_lock(hid, zgrp->obj_tab); + zlist_clr_priv_nolock(hid, zgrp->obj_tab); + ret = zlist_is_isolated_nolock(hid, zgrp->obj_tab); + zlist_unlock(hid, zgrp->obj_tab); + + pr_info("put extent %u, ret = %d\n", eid, ret); + + return ret; +} + /* * insert obj at @index into extent @eid */ @@ -517,6 +556,7 @@ void wbgrp_obj_insert(struct zram_group *zgrp, u32 index, u32 eid) bool wbgrp_obj_delete(struct zram_group *zgrp, u32 index, u32 eid) { u32 hid; + bool ret = false; if (!zgrp) { pr_debug("zram group is not enable!"); @@ -531,7 +571,12 @@ bool wbgrp_obj_delete(struct zram_group *zgrp, u32 index, u32 eid) pr_debug("delete obj %u from extent %u\n", index, eid); hid = eid + zgrp->nr_obj + zgrp->nr_grp; - return zlist_del(hid, index, zgrp->obj_tab); + zlist_lock(hid, zgrp->obj_tab); + ret = zlist_del_nolock(hid, index, zgrp->obj_tab) + && !zlist_test_priv_nolock(hid, zgrp->obj_tab); + zlist_unlock(hid, zgrp->obj_tab); + + return ret; } /* @@ -567,7 +612,8 @@ u32 wbgrp_isolate_objs(struct zram_group *zgrp, u32 eid, u32 *idxs, u32 nr, bool for (i = 0; i < cnt; i++) zlist_del_nolock(hid, idxs[i], zgrp->obj_tab); if (last) - *last = cnt && zlist_is_isolated_nolock(hid, zgrp->obj_tab); + *last = cnt && zlist_is_isolated_nolock(hid, zgrp->obj_tab) + && !zlist_test_priv_nolock(hid, zgrp->obj_tab); zlist_unlock(hid, zgrp->obj_tab); pr_debug("isolated %u objs from extent %u.\n", cnt, eid); diff --git a/drivers/block/zram/zram_group/zram_group.h b/drivers/block/zram/zram_group/zram_group.h index 7ac16ba87703a02e8ab2572602ec901c8199c2e0..9b184b7bda77b55ddb78b37a0d0af06c2e04caa3 100644 --- a/drivers/block/zram/zram_group/zram_group.h +++ b/drivers/block/zram/zram_group/zram_group.h @@ -86,6 +86,8 @@ int zram_group_apply_writeback(struct zram_group *zgrp, u32 nr_ext); void zgrp_ext_insert(struct zram_group *zgrp, u32 eid, u16 gid); bool zgrp_ext_delete(struct zram_group *zgrp, u32 eid, u16 gid); u32 zgrp_isolate_exts(struct zram_group *zgrp, u16 gid, u32 *eids, u32 nr, bool *last); +void zgrp_get_ext(struct zram_group *zgrp, u32 eid); +bool zgrp_put_ext(struct zram_group *zgrp, u32 eid); void wbgrp_obj_insert(struct zram_group *zgrp, u32 index, u32 eid); bool wbgrp_obj_delete(struct zram_group *zgrp, u32 index, u32 eid); u32 wbgrp_isolate_objs(struct zram_group *zgrp, u32 eid, u32 *idxs, u32 nr, bool *last);