mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	bcachefs: Check for casefolded dirents in non casefolded dirs
Check for mismatches between casefold dirents and casefold directories. A mismatch will cause lookups to fail, as we'll be doing the lookup with the casefolded name, which won't match the non-casefolded dirent, and vice versa. Reported-by: Christopher Snowhill <chris@kode54.net> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
		
							parent
							
								
									ecd76c5f10
								
							
						
					
					
						commit
						010c894681
					
				
					 2 changed files with 42 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -2190,6 +2190,41 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
 | 
			
		|||
 | 
			
		||||
	struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
 | 
			
		||||
 | 
			
		||||
	/* check casefold */
 | 
			
		||||
	if (fsck_err_on(d.v->d_casefold != !!hash_info->cf_encoding,
 | 
			
		||||
			trans, dirent_casefold_mismatch,
 | 
			
		||||
			"dirent casefold does not match dir casefold\n%s",
 | 
			
		||||
			(printbuf_reset(&buf),
 | 
			
		||||
			 bch2_bkey_val_to_text(&buf, c, k),
 | 
			
		||||
			 buf.buf))) {
 | 
			
		||||
		struct qstr name = bch2_dirent_get_name(d);
 | 
			
		||||
		u32 subvol = d.v->d_type == DT_SUBVOL
 | 
			
		||||
			? d.v->d_parent_subvol
 | 
			
		||||
			: 0;
 | 
			
		||||
		u64 target = d.v->d_type == DT_SUBVOL
 | 
			
		||||
			? d.v->d_child_subvol
 | 
			
		||||
			: d.v->d_inum;
 | 
			
		||||
		u64 dir_offset;
 | 
			
		||||
 | 
			
		||||
		ret =   bch2_hash_delete_at(trans,
 | 
			
		||||
					    bch2_dirent_hash_desc, hash_info, iter,
 | 
			
		||||
					    BTREE_UPDATE_internal_snapshot_node) ?:
 | 
			
		||||
			bch2_dirent_create_snapshot(trans, subvol,
 | 
			
		||||
						    d.k->p.inode, d.k->p.snapshot,
 | 
			
		||||
						    hash_info,
 | 
			
		||||
						    d.v->d_type,
 | 
			
		||||
						    &name,
 | 
			
		||||
						    target,
 | 
			
		||||
						    &dir_offset,
 | 
			
		||||
						    BTREE_ITER_with_updates|
 | 
			
		||||
						    BTREE_UPDATE_internal_snapshot_node|
 | 
			
		||||
						    STR_HASH_must_create) ?:
 | 
			
		||||
			bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
 | 
			
		||||
 | 
			
		||||
		/* might need another check_dirents pass */
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (d.v->d_type == DT_SUBVOL) {
 | 
			
		||||
		ret = check_dirent_to_subvol(trans, iter, d);
 | 
			
		||||
		if (ret)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -209,6 +209,7 @@ enum bch_fsck_flags {
 | 
			
		|||
	x(subvol_to_missing_root,				188,	0)		\
 | 
			
		||||
	x(subvol_root_wrong_bi_subvol,				189,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(bkey_in_missing_snapshot,				190,	0)		\
 | 
			
		||||
	x(bkey_in_deleted_snapshot,				315,	0)		\
 | 
			
		||||
	x(inode_pos_inode_nonzero,				191,	0)		\
 | 
			
		||||
	x(inode_pos_blockdev_range,				192,	0)		\
 | 
			
		||||
	x(inode_alloc_cursor_inode_bad,				301,	0)		\
 | 
			
		||||
| 
						 | 
				
			
			@ -216,6 +217,7 @@ enum bch_fsck_flags {
 | 
			
		|||
	x(inode_str_hash_invalid,				194,	0)		\
 | 
			
		||||
	x(inode_v3_fields_start_bad,				195,	0)		\
 | 
			
		||||
	x(inode_snapshot_mismatch,				196,	0)		\
 | 
			
		||||
	x(snapshot_key_missing_inode_snapshot,			314,	0)		\
 | 
			
		||||
	x(inode_unlinked_but_clean,				197,	0)		\
 | 
			
		||||
	x(inode_unlinked_but_nlink_nonzero,			198,	0)		\
 | 
			
		||||
	x(inode_unlinked_and_not_open,				281,	0)		\
 | 
			
		||||
| 
						 | 
				
			
			@ -237,6 +239,8 @@ enum bch_fsck_flags {
 | 
			
		|||
	x(inode_unreachable,					210,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(inode_journal_seq_in_future,				299,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(inode_i_sectors_underflow,				312,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(inode_has_case_insensitive_not_set,			316,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(inode_parent_has_case_insensitive_not_set,		317,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(vfs_inode_i_blocks_underflow,				311,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(vfs_inode_i_blocks_not_zero_at_truncate,		313,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(deleted_inode_but_clean,				211,	FSCK_AUTOFIX)	\
 | 
			
		||||
| 
						 | 
				
			
			@ -262,6 +266,7 @@ enum bch_fsck_flags {
 | 
			
		|||
	x(dirent_to_overwritten_inode,				302,	0)		\
 | 
			
		||||
	x(dirent_to_missing_subvol,				230,	0)		\
 | 
			
		||||
	x(dirent_to_itself,					231,	0)		\
 | 
			
		||||
	x(dirent_casefold_mismatch,				318,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(quota_type_invalid,					232,	0)		\
 | 
			
		||||
	x(xattr_val_size_too_small,				233,	0)		\
 | 
			
		||||
	x(xattr_val_size_too_big,				234,	0)		\
 | 
			
		||||
| 
						 | 
				
			
			@ -301,6 +306,7 @@ enum bch_fsck_flags {
 | 
			
		|||
	x(btree_ptr_v2_written_0,				268,	0)		\
 | 
			
		||||
	x(subvol_snapshot_bad,					269,	0)		\
 | 
			
		||||
	x(subvol_inode_bad,					270,	0)		\
 | 
			
		||||
	x(subvol_missing,					308,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(alloc_key_stripe_sectors_wrong,			271,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(accounting_mismatch,					272,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(accounting_replicas_not_marked,			273,	0)		\
 | 
			
		||||
| 
						 | 
				
			
			@ -322,7 +328,7 @@ enum bch_fsck_flags {
 | 
			
		|||
	x(dirent_stray_data_after_cf_name,			305,	0)		\
 | 
			
		||||
	x(rebalance_work_incorrectly_set,			309,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(rebalance_work_incorrectly_unset,			310,	FSCK_AUTOFIX)	\
 | 
			
		||||
	x(MAX,							314,	0)
 | 
			
		||||
	x(MAX,							319,	0)
 | 
			
		||||
 | 
			
		||||
enum bch_sb_error_id {
 | 
			
		||||
#define x(t, n, ...) BCH_FSCK_ERR_##t = n,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue