mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
jbd2,ext4: add a shrinker to release checkpointed buffers
Current metadata buffer release logic in bdev_try_to_free_page() have a lot of use-after-free issues when umount filesystem concurrently, and it is difficult to fix directly because ext4 is the only user of s_op->bdev_try_to_free_page callback and we may have to add more special refcount or lock that is only used by ext4 into the common vfs layer, which is unacceptable. One better solution is remove the bdev_try_to_free_page callback, but the real problem is we cannot easily release journal_head on the checkpointed buffer, so try_to_free_buffers() cannot release buffers and page under memory pressure, which is more likely to trigger out-of-memory. So we cannot remove the callback directly before we find another way to release journal_head. This patch introduce a shrinker to free journal_head on the checkpointed transaction. After the journal_head got freed, try_to_free_buffers() could free buffer properly. Signed-off-by: Zhang Yi <yi.zhang@huawei.com> Suggested-by: Jan Kara <jack@suse.cz> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20210610112440.3438139-6-yi.zhang@huawei.com Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
214eb5a4d8
commit
4ba3fcdde7
5 changed files with 369 additions and 0 deletions
|
@ -909,6 +909,29 @@ struct journal_s
|
|||
*/
|
||||
struct buffer_head *j_chkpt_bhs[JBD2_NR_BATCH];
|
||||
|
||||
/**
|
||||
* @j_shrinker:
|
||||
*
|
||||
* Journal head shrinker, reclaim buffer's journal head which
|
||||
* has been written back.
|
||||
*/
|
||||
struct shrinker j_shrinker;
|
||||
|
||||
/**
|
||||
* @j_jh_shrink_count:
|
||||
*
|
||||
* Number of journal buffers on the checkpoint list. [j_list_lock]
|
||||
*/
|
||||
struct percpu_counter j_jh_shrink_count;
|
||||
|
||||
/**
|
||||
* @j_shrink_transaction:
|
||||
*
|
||||
* Record next transaction will shrink on the checkpoint list.
|
||||
* [j_list_lock]
|
||||
*/
|
||||
transaction_t *j_shrink_transaction;
|
||||
|
||||
/**
|
||||
* @j_head:
|
||||
*
|
||||
|
@ -1422,6 +1445,7 @@ extern void jbd2_journal_commit_transaction(journal_t *);
|
|||
|
||||
/* Checkpoint list management */
|
||||
void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy);
|
||||
unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, unsigned long *nr_to_scan);
|
||||
int __jbd2_journal_remove_checkpoint(struct journal_head *);
|
||||
void jbd2_journal_destroy_checkpoint(journal_t *journal);
|
||||
void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *);
|
||||
|
@ -1532,6 +1556,8 @@ extern int jbd2_journal_set_features
|
|||
(journal_t *, unsigned long, unsigned long, unsigned long);
|
||||
extern void jbd2_journal_clear_features
|
||||
(journal_t *, unsigned long, unsigned long, unsigned long);
|
||||
extern int jbd2_journal_register_shrinker(journal_t *journal);
|
||||
extern void jbd2_journal_unregister_shrinker(journal_t *journal);
|
||||
extern int jbd2_journal_load (journal_t *journal);
|
||||
extern int jbd2_journal_destroy (journal_t *);
|
||||
extern int jbd2_journal_recover (journal_t *journal);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue