ext4: expand commit callback
PATCH v2 1/1 ext4: expand commit callback
The per-commit callback was used by mballoc code to manage free space bitmaps after deleted blocks have been released. This patch expand it to contain multiple different callbacks.
* add a ext4_journal_cb_entry to store journal callback function.
* add an ext4_journal_cb_entry member in ext4_free_data.
* transaction->t_private_list is used to link all journal callback entries.
* add ext4_journal_callback_add/del functions to add/deletel callback entry into/from jounal->j_private.
Signed-off-by Bobi Jam <[email protected]>
Signed-off-by Andreas Dilger <[email protected]>
--- fs/ext4/ext4_jbd2.h | 72 ++++++++++++++++++++++++ fs/ext4/mballoc.c | 151 ++++++++++++++++++++++++--------------------------- fs/ext4/mballoc.h | 18 ++++--- fs/ext4/super.c | 18 ++++++ 4 files changed, 171 insertions(+), 88 deletions(-)
fs/ext4/ext4_jbd2.h +72 -0
@@ -104,6 +104,78 @@#define EXT4_MAXQUOTAS_INIT_BLOCKS (sb) (MAXQUOTAS*EXT4_QUOTA_INIT_BLOCKS(sb))#define EXT4_MAXQUOTAS_DEL_BLOCKS (sb) (MAXQUOTAS*EXT4_QUOTA_DEL_BLOCKS(sb)) +/** +* struct ext4_journal_cb_entry - Base structure for callback information. +* +* This struct is a 'seed' structure for a using with your own callback +* structs. If you are using callbacks you must allocate one of these +* or another struct of your own definition which has this struct +* as it's first element and pass it to ext4_journal_callback_add(). +*/ +struct ext4_journal_cb_entry { +/* list information for other callbacks attached to the same handle */ +struct list_head jce_list; + +/* Function to call with this callback structure */ +void (*jce_func)(struct super_block *sb, +struct ext4_journal_cb_entry *jce,int error); + +/* user data goes here */ +}; + +/** +* ext4_journal_callback_add: add a function to call after transaction commit +* @handle: active journal transaction handle to register callback on +* @func: callback function to call after the transaction has committed: +* @sb: superblock of current filesystem for transaction +* @jce: returned journal callback data +* @rc: journal state at commit (0 = transaction committed properly) +* @jce: journal callback data (internal and function private data struct) +* +* The registered function will be called in the context of the journal thread +* after the transaction for which the handle was created has completed. +* +* No locks are held when the callback function is called, so it is safe to +* call blocking functions from within the callback, but the callback should +* not block or run for too long, or the filesystem will be blocked waiting for +* the next transaction to commit. No journaling functions can be used, or +* there is a risk of deadlock. +* +* There is no guaranteed calling order of multiple registered callbacks on +* the same transaction. +*/ +static inline void ext4_journal_callback_add (handle_t *handle, +void (*func)(struct super_block *sb, +struct ext4_journal_cb_entry *jce, +int rc), +struct ext4_journal_cb_entry *jce) +{ +struct ext4_sb_info *sbi = +EXT4_SB (handle->h_transaction->t_journal->j_private); + +/* Add the jce to transaction's private list */ + jce->jce_func = func; +spin_lock (&sbi->s_md_lock); +list_add_tail (&jce->jce_list, &handle->h_transaction->t_private_list); +spin_unlock (&sbi->s_md_lock); +} + +/** +* ext4_journal_callback_del: delete a registered callback +* @handle: active journal transaction handle on which callback was registered +* @jce: registered journal callback entry to unregister +*/ +static inline void ext4_journal_callback_del (handle_t *handle, +struct ext4_journal_cb_entry *jce) +{ +struct ext4_sb_info *sbi = +EXT4_SB (handle->h_transaction->t_journal->j_private); + +spin_lock (&sbi->s_md_lock); +list_del_init (&jce->jce_list); +spin_unlock (&sbi->s_md_lock); +} + int ext4_mark_iloc_dirty(handle_t *handle, struct inode *inode,
fs/ext4/mballoc.c +71 -80
258 lines not on this page · raw message
fs/ext4/mballoc.h +10 -8
@@ -96,21 +96,23 @@ extern u8 mb_enable_debug;struct ext4_free_data { -/* this links the free block information from group_info */ -struct rb_node node; +/* MUST be the first member */ +struct ext4_journal_cb_entry efd_jce; + +/* ext4_free_data private data starts from here */ -/* this links the free block information from ext4_sb_info */ -struct list_head list; +/* this links the free block information from group_info */ +struct rb_node efd_node;/* group which free block extent belongs */ -ext4_group_t group; +ext4_group_t efd_group;/* free block extent */ -ext4_grpblk_t start_cluster; -ext4_grpblk_t count; +ext4_grpblk_t efd_start_cluster; +ext4_grpblk_t efd_count;/* transaction which freed this extent */ -tid_t t_tid; +tid_t efd_tid; };struct ext4_prealloc_space {
fs/ext4/super.c +18 -0
@@ -431,6 +431,22 @@ static int block_device_ejected(struct super_block *sb)return bdi->dev ==NULL ; } +static void ext4_journal_commit_callback (journal_t *journal,transaction_t *txn) +{ +struct super_block *sb = journal->j_private; +struct ext4_sb_info *sbi =EXT4_SB (sb); +int error =is_journal_aborted (journal); +struct ext4_journal_cb_entry *jce, *tmp; + +spin_lock (&sbi->s_md_lock); +list_for_each_entry_safe (jce, tmp, &txn->t_private_list, jce_list) { +list_del_init (&jce->jce_list); +spin_unlock (&sbi->s_md_lock); + jce->jce_func (sb, jce, error); +spin_lock (&sbi->s_md_lock); + } +spin_unlock (&sbi->s_md_lock); +}/* Deal with the reporting of failure conditions on a filesystem such as * inconsistencies detected or read IO failures.
@@ -3698,6 +3714,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) }set_task_ioprio (sbi->s_journal->j_task, journal_ioprio); + sbi->s_journal->j_commit_callback = ext4_journal_commit_callback; +/* * The journal may have updated the bg summary counts, so we * need to update the global counters.
Signature · 1 line
1.7.7