diff --git a/linux-5.14-rc5/include/linux/hermit_types.h b/linux-5.14-rc5/include/linux/hermit_types.h index 832f8012d..63d864011 100644 --- a/linux-5.14-rc5/include/linux/hermit_types.h +++ b/linux-5.14-rc5/include/linux/hermit_types.h @@ -21,6 +21,8 @@ struct hmt_work_struct { * swap stats to control async swap out */ struct hmt_swap_ctrl { + // `lock` must be the first field in the struct to avoid breaking + // `hmt_clear_locked_swap_ctrl()`. spinlock_t lock; atomic_t sthd_cnt; atomic_t active_sthd_cnt; diff --git a/linux-5.14-rc5/mm/hermit_utils.c b/linux-5.14-rc5/mm/hermit_utils.c index aaf5a0b1f..02e82f008 100644 --- a/linux-5.14-rc5/mm/hermit_utils.c +++ b/linux-5.14-rc5/mm/hermit_utils.c @@ -179,13 +179,20 @@ static inline void hmt_update_low_watermark(struct mem_cgroup *memcg, } } +// Resets a locked `hmt_swap_ctrl` without dropping the lock. +// We assume `offsetof(hmt_swap_ctrl, lock) = 0`. +static void hmt_clear_locked_swap_ctrl(struct hmt_swap_ctrl *sc) +{ + memset(sc + sizeof(sc->lock), 0, sizeof(*sc) - sizeof(sc->lock)); +} + // must hold sc->lock inline void hmt_update_swap_ctrl(struct mem_cgroup *memcg, struct hmt_swap_ctrl *sc) { const int UPD_PERIOD = 1000; // update swap-in tput per UPD_PERIOD us if (sc->swin_ts[0] == 0) { - memset(sc, 0, sizeof(struct hmt_swap_ctrl)); + hmt_clear_locked_swap_ctrl(sc); sc->swin_ts[0] = get_cycles_light(); sc->nr_pg_charged[0] = atomic64_read(&memcg->total_pg_charge); return; @@ -311,7 +318,7 @@ void hermit_init_memcg(struct mem_cgroup *memcg) return; memset(&memcg->hmt_sc, 0, sizeof(struct hmt_swap_ctrl)); - memcg->hmt_sc.lock = __SPIN_LOCK_UNLOCKED(memcg->hmt_sc.lock); + spin_lock_init(&memcg->hmt_sc.lock); for (i = 0; i < HMT_MAX_NR_STHDS; i++) { INIT_WORK(&memcg->sthds[i].work, hermit_high_work_func); memcg->sthds[i].id = i;