// SPDX-License-Identifier: GPL-2.0 /* * Interface between ext4 and JBD
*/
#include"ext4_jbd2.h"
#include <trace/events/ext4.h>
int ext4_inode_journal_mode(struct inode *inode)
{ if (EXT4_JOURNAL(inode) == NULL) return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */ /* We do not support data journalling with delayed allocation */ if (!S_ISREG(inode->i_mode) ||
ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||
test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
(ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
!test_opt(inode->i_sb, DELALLOC) &&
!mapping_large_folio_support(inode->i_mapping))) { /* We do not support data journalling for encrypted data */ if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */ return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */
} if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
BUG();
}
/* Just increment the non-pointer handle value */ static handle_t *ext4_get_nojournal(void)
{
handle_t *handle = current->journal_info; unsignedlong ref_cnt = (unsignedlong)handle;
BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
ref_cnt++;
handle = (handle_t *)ref_cnt;
current->journal_info = handle; return handle;
}
/* Decrement the non-pointer handle value */ staticvoid ext4_put_nojournal(handle_t *handle)
{ unsignedlong ref_cnt = (unsignedlong)handle;
BUG_ON(ref_cnt == 0);
ref_cnt--;
handle = (handle_t *)ref_cnt;
current->journal_info = handle;
}
/* * Wrappers for jbd2_journal_start/end.
*/ staticint ext4_journal_check_start(struct super_block *sb)
{ int ret;
journal_t *journal;
might_sleep();
ret = ext4_emergency_state(sb); if (unlikely(ret)) return ret;
if (WARN_ON_ONCE(sb_rdonly(sb))) return -EROFS;
WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
journal = EXT4_SB(sb)->s_journal; /* * Special case here: if the journal has aborted behind our * backs (eg. EIO in the commit thread), then we still need to * take the FS itself readonly cleanly.
*/ if (journal && is_journal_aborted(journal)) {
ext4_abort(sb, -journal->j_errno, "Detected aborted journal"); return -EROFS;
} return 0;
}
handle_t *__ext4_journal_start_sb(struct inode *inode, struct super_block *sb, unsignedint line, int type, int blocks, int rsv_blocks, int revoke_creds)
{
journal_t *journal; int err; if (inode)
trace_ext4_journal_start_inode(inode, blocks, rsv_blocks,
revoke_creds, type,
_RET_IP_); else
trace_ext4_journal_start_sb(sb, blocks, rsv_blocks,
revoke_creds, type,
_RET_IP_);
err = ext4_journal_check_start(sb); if (err < 0) return ERR_PTR(err);
/* * If the block device has write error flag, it may have failed to * async write out metadata buffers in the background. In this case, * we could read old data from disk and write it out again, which * may lead to on-disk filesystem inconsistency.
*/ if (errseq_check(&mapping->wb_err, READ_ONCE(sbi->s_bdev_wb_err))) {
spin_lock(&sbi->s_bdev_wb_lock);
err = errseq_check_and_advance(&mapping->wb_err, &sbi->s_bdev_wb_err);
spin_unlock(&sbi->s_bdev_wb_lock); if (err)
ext4_error_err(sb, -err, "Error while async write back metadata");
}
}
int __ext4_journal_get_write_access(constchar *where, unsignedint line,
handle_t *handle, struct super_block *sb, struct buffer_head *bh, enum ext4_journal_trigger_type trigger_type)
{ int err;
/* * The ext4 forget function must perform a revoke if we are freeing data * which has been journaled. Metadata (eg. indirect blocks) must be * revoked in all cases. * * "bh" may be NULL: a metadata block may have been freed from memory * but there may still be a record of it in the journal, and that record * still needs to be revoked.
*/ int __ext4_forget(constchar *where, unsignedint line, handle_t *handle, int is_metadata, struct inode *inode, struct buffer_head *bh, ext4_fsblk_t blocknr)
{ int err;
/* * In the no journal case, we should wait for the ongoing buffer * to complete and do a forget.
*/ if (!ext4_handle_valid(handle)) { if (bh) {
clear_buffer_dirty(bh);
wait_on_buffer(bh);
__bforget(bh);
} return 0;
}
/* Never use the revoke function if we are doing full data * journaling: there is no need to, and a V1 superblock won't * support it. Otherwise, only skip the revoke on un-journaled
* data blocks. */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.