Commit 6f9972bb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ext4 updates from Ted Ts'o:
 "Miscellaneous ext4 cleanups and bug fixes. Pretty boring this cycle..."

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: add .kunitconfig fragment to enable ext4-specific tests
  ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
  ext4: reset retry counter when ext4_alloc_file_blocks() makes progress
  ext4: fix potential htree index checksum corruption
  ext4: factor out htree rep invariant check
  ext4: Change list_for_each* to list_for_each_entry*
  ext4: don't try to processed freed blocks until mballoc is initialized
  ext4: use DEFINE_MUTEX() for mutex lock
parents 5b47b10e 0a76945f
Loading
Loading
Loading
Loading

fs/ext4/.kunitconfig

0 → 100644
+3 −0
Original line number Diff line number Diff line
CONFIG_KUNIT=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_KUNIT_TESTS=y
+1 −2
Original line number Diff line number Diff line
@@ -103,8 +103,7 @@ config EXT4_DEBUG

config EXT4_KUNIT_TESTS
	tristate "KUnit tests for ext4" if !KUNIT_ALL_TESTS
	select EXT4_FS
	depends on KUNIT
	depends on EXT4_FS && KUNIT
	default KUNIT_ALL_TESTS
	help
	  This builds the ext4 KUnit tests.
+8 −8
Original line number Diff line number Diff line
@@ -4382,8 +4382,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
{
	struct inode *inode = file_inode(file);
	handle_t *handle;
	int ret = 0;
	int ret2 = 0, ret3 = 0;
	int ret, ret2 = 0, ret3 = 0;
	int retries = 0;
	int depth = 0;
	struct ext4_map_blocks map;
@@ -4408,7 +4407,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
	depth = ext_depth(inode);

retry:
	while (ret >= 0 && len) {
	while (len) {
		/*
		 * Recalculate credits when extent tree depth changes.
		 */
@@ -4430,9 +4429,13 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
				   inode->i_ino, map.m_lblk,
				   map.m_len, ret);
			ext4_mark_inode_dirty(handle, inode);
			ret2 = ext4_journal_stop(handle);
			ext4_journal_stop(handle);
			break;
		}
		/*
		 * allow a full retry cycle for any remaining allocations
		 */
		retries = 0;
		map.m_lblk += ret;
		map.m_len = len = len - ret;
		epos = (loff_t)map.m_lblk << inode->i_blkbits;
@@ -4450,11 +4453,8 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
		if (unlikely(ret2))
			break;
	}
	if (ret == -ENOSPC &&
			ext4_should_retry_alloc(inode->i_sb, &retries)) {
		ret = 0;
	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
		goto retry;
	}

	return ret > 0 ? ret2 : ret;
}
+11 −18
Original line number Diff line number Diff line
@@ -915,13 +915,11 @@ static int ext4_fc_submit_inode_data_all(journal_t *journal)
	struct super_block *sb = (struct super_block *)(journal->j_private);
	struct ext4_sb_info *sbi = EXT4_SB(sb);
	struct ext4_inode_info *ei;
	struct list_head *pos;
	int ret = 0;

	spin_lock(&sbi->s_fc_lock);
	ext4_set_mount_flag(sb, EXT4_MF_FC_COMMITTING);
	list_for_each(pos, &sbi->s_fc_q[FC_Q_MAIN]) {
		ei = list_entry(pos, struct ext4_inode_info, i_fc_list);
	list_for_each_entry(ei, &sbi->s_fc_q[FC_Q_MAIN], i_fc_list) {
		ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING);
		while (atomic_read(&ei->i_fc_updates)) {
			DEFINE_WAIT(wait);
@@ -978,17 +976,15 @@ __releases(&sbi->s_fc_lock)
{
	struct super_block *sb = (struct super_block *)(journal->j_private);
	struct ext4_sb_info *sbi = EXT4_SB(sb);
	struct ext4_fc_dentry_update *fc_dentry;
	struct ext4_fc_dentry_update *fc_dentry, *fc_dentry_n;
	struct inode *inode;
	struct list_head *pos, *n, *fcd_pos, *fcd_n;
	struct ext4_inode_info *ei;
	struct ext4_inode_info *ei, *ei_n;
	int ret;

	if (list_empty(&sbi->s_fc_dentry_q[FC_Q_MAIN]))
		return 0;
	list_for_each_safe(fcd_pos, fcd_n, &sbi->s_fc_dentry_q[FC_Q_MAIN]) {
		fc_dentry = list_entry(fcd_pos, struct ext4_fc_dentry_update,
					fcd_list);
	list_for_each_entry_safe(fc_dentry, fc_dentry_n,
				 &sbi->s_fc_dentry_q[FC_Q_MAIN], fcd_list) {
		if (fc_dentry->fcd_op != EXT4_FC_TAG_CREAT) {
			spin_unlock(&sbi->s_fc_lock);
			if (!ext4_fc_add_dentry_tlv(
@@ -1004,8 +1000,8 @@ __releases(&sbi->s_fc_lock)
		}

		inode = NULL;
		list_for_each_safe(pos, n, &sbi->s_fc_q[FC_Q_MAIN]) {
			ei = list_entry(pos, struct ext4_inode_info, i_fc_list);
		list_for_each_entry_safe(ei, ei_n, &sbi->s_fc_q[FC_Q_MAIN],
					 i_fc_list) {
			if (ei->vfs_inode.i_ino == fc_dentry->fcd_ino) {
				inode = &ei->vfs_inode;
				break;
@@ -1057,7 +1053,6 @@ static int ext4_fc_perform_commit(journal_t *journal)
	struct ext4_sb_info *sbi = EXT4_SB(sb);
	struct ext4_inode_info *iter;
	struct ext4_fc_head head;
	struct list_head *pos;
	struct inode *inode;
	struct blk_plug plug;
	int ret = 0;
@@ -1099,8 +1094,7 @@ static int ext4_fc_perform_commit(journal_t *journal)
		goto out;
	}

	list_for_each(pos, &sbi->s_fc_q[FC_Q_MAIN]) {
		iter = list_entry(pos, struct ext4_inode_info, i_fc_list);
	list_for_each_entry(iter, &sbi->s_fc_q[FC_Q_MAIN], i_fc_list) {
		inode = &iter->vfs_inode;
		if (!ext4_test_inode_state(inode, EXT4_STATE_FC_COMMITTING))
			continue;
@@ -1226,9 +1220,8 @@ static void ext4_fc_cleanup(journal_t *journal, int full)
{
	struct super_block *sb = journal->j_private;
	struct ext4_sb_info *sbi = EXT4_SB(sb);
	struct ext4_inode_info *iter;
	struct ext4_inode_info *iter, *iter_n;
	struct ext4_fc_dentry_update *fc_dentry;
	struct list_head *pos, *n;

	if (full && sbi->s_fc_bh)
		sbi->s_fc_bh = NULL;
@@ -1236,8 +1229,8 @@ static void ext4_fc_cleanup(journal_t *journal, int full)
	jbd2_fc_release_bufs(journal);

	spin_lock(&sbi->s_fc_lock);
	list_for_each_safe(pos, n, &sbi->s_fc_q[FC_Q_MAIN]) {
		iter = list_entry(pos, struct ext4_inode_info, i_fc_list);
	list_for_each_entry_safe(iter, iter_n, &sbi->s_fc_q[FC_Q_MAIN],
				 i_fc_list) {
		list_del_init(&iter->i_fc_list);
		ext4_clear_inode_state(&iter->vfs_inode,
				       EXT4_STATE_FC_COMMITTING);
+27 −18
Original line number Diff line number Diff line
@@ -731,6 +731,29 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
		       (space/bcount)*100/blocksize);
	return (struct stats) { names, space, bcount};
}

/*
 * Linear search cross check
 */
static inline void htree_rep_invariant_check(struct dx_entry *at,
					     struct dx_entry *target,
					     u32 hash, unsigned int n)
{
	while (n--) {
		dxtrace(printk(KERN_CONT ","));
		if (dx_get_hash(++at) > hash) {
			at--;
			break;
		}
	}
	ASSERT(at == target - 1);
}
#else /* DX_DEBUG */
static inline void htree_rep_invariant_check(struct dx_entry *at,
					     struct dx_entry *target,
					     u32 hash, unsigned int n)
{
}
#endif /* DX_DEBUG */

/*
@@ -827,20 +850,7 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
				p = m + 1;
		}

		if (0) { // linear search cross check
			unsigned n = count - 1;
			at = entries;
			while (n--)
			{
				dxtrace(printk(KERN_CONT ","));
				if (dx_get_hash(++at) > hash)
				{
					at--;
					break;
				}
			}
			ASSERT(at == p - 1);
		}
		htree_rep_invariant_check(entries, p, hash, count - 1);

		at = p - 1;
		dxtrace(printk(KERN_CONT " %x->%u\n",
@@ -2401,11 +2411,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
						   (frame - 1)->bh);
			if (err)
				goto journal_error;
			if (restart) {
			err = ext4_handle_dirty_dx_node(handle, dir,
							frame->bh);
			if (err)
				goto journal_error;
			}
		} else {
			struct dx_root *dxroot;
			memcpy((char *) entries2, (char *) entries,
Loading