sys-kernel/hardened-kernel: update bcachefs patches
Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
This commit is contained in:
@@ -0,0 +1,392 @@
|
||||
From 73c097f81f25b59e97de37f326918bd2119ae26e Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Miroshnichenko <alex@millerson.name>
|
||||
Date: Sun, 3 Aug 2025 19:50:52 +0300
|
||||
Subject: [PATCH] bcachefs: revert 6.15 backport patches to prepare for aplying
|
||||
master patches
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
|
||||
---
|
||||
fs/bcachefs/dirent.c | 12 +++++-
|
||||
fs/bcachefs/dirent.h | 4 +-
|
||||
fs/bcachefs/errcode.h | 2 -
|
||||
fs/bcachefs/fs.c | 8 +---
|
||||
fs/bcachefs/fsck.c | 8 ----
|
||||
fs/bcachefs/inode.c | 77 ++++++++++++----------------------
|
||||
fs/bcachefs/namei.c | 4 +-
|
||||
fs/bcachefs/sb-errors_format.h | 4 +-
|
||||
fs/bcachefs/subvolume.c | 19 ++-------
|
||||
9 files changed, 46 insertions(+), 92 deletions(-)
|
||||
|
||||
diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c
|
||||
index 901230ca4a75..a51195088227 100644
|
||||
--- a/fs/bcachefs/dirent.c
|
||||
+++ b/fs/bcachefs/dirent.c
|
||||
@@ -395,8 +395,8 @@ int bch2_dirent_read_target(struct btree_trans *trans, subvol_inum dir,
|
||||
}
|
||||
|
||||
int bch2_dirent_rename(struct btree_trans *trans,
|
||||
- subvol_inum src_dir, struct bch_hash_info *src_hash,
|
||||
- subvol_inum dst_dir, struct bch_hash_info *dst_hash,
|
||||
+ subvol_inum src_dir, struct bch_hash_info *src_hash, u64 *src_dir_i_size,
|
||||
+ subvol_inum dst_dir, struct bch_hash_info *dst_hash, u64 *dst_dir_i_size,
|
||||
const struct qstr *src_name, subvol_inum *src_inum, u64 *src_offset,
|
||||
const struct qstr *dst_name, subvol_inum *dst_inum, u64 *dst_offset,
|
||||
enum bch_rename_mode mode)
|
||||
@@ -535,6 +535,14 @@ int bch2_dirent_rename(struct btree_trans *trans,
|
||||
new_src->v.d_type == DT_SUBVOL)
|
||||
new_src->v.d_parent_subvol = cpu_to_le32(src_dir.subvol);
|
||||
|
||||
+ if (old_dst.k)
|
||||
+ *dst_dir_i_size -= bkey_bytes(old_dst.k);
|
||||
+ *src_dir_i_size -= bkey_bytes(old_src.k);
|
||||
+
|
||||
+ if (mode == BCH_RENAME_EXCHANGE)
|
||||
+ *src_dir_i_size += bkey_bytes(&new_src->k);
|
||||
+ *dst_dir_i_size += bkey_bytes(&new_dst->k);
|
||||
+
|
||||
ret = bch2_trans_update(trans, &dst_iter, &new_dst->k_i, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
diff --git a/fs/bcachefs/dirent.h b/fs/bcachefs/dirent.h
|
||||
index 999b895fa28a..d3e7ae669575 100644
|
||||
--- a/fs/bcachefs/dirent.h
|
||||
+++ b/fs/bcachefs/dirent.h
|
||||
@@ -80,8 +80,8 @@ enum bch_rename_mode {
|
||||
};
|
||||
|
||||
int bch2_dirent_rename(struct btree_trans *,
|
||||
- subvol_inum, struct bch_hash_info *,
|
||||
- subvol_inum, struct bch_hash_info *,
|
||||
+ subvol_inum, struct bch_hash_info *, u64 *,
|
||||
+ subvol_inum, struct bch_hash_info *, u64 *,
|
||||
const struct qstr *, subvol_inum *, u64 *,
|
||||
const struct qstr *, subvol_inum *, u64 *,
|
||||
enum bch_rename_mode);
|
||||
diff --git a/fs/bcachefs/errcode.h b/fs/bcachefs/errcode.h
|
||||
index 346766299cb3..d9ebffa5b3a2 100644
|
||||
--- a/fs/bcachefs/errcode.h
|
||||
+++ b/fs/bcachefs/errcode.h
|
||||
@@ -209,8 +209,6 @@
|
||||
x(EINVAL, remove_would_lose_data) \
|
||||
x(EINVAL, no_resize_with_buckets_nouse) \
|
||||
x(EINVAL, inode_unpack_error) \
|
||||
- x(EINVAL, inode_not_unlinked) \
|
||||
- x(EINVAL, inode_has_child_snapshot) \
|
||||
x(EINVAL, varint_decode_error) \
|
||||
x(EINVAL, erasure_coding_found_btree_node) \
|
||||
x(EOPNOTSUPP, may_not_use_incompat_feature) \
|
||||
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
|
||||
index 8a47ce3467e8..47f1a64c5c8d 100644
|
||||
--- a/fs/bcachefs/fs.c
|
||||
+++ b/fs/bcachefs/fs.c
|
||||
@@ -2181,13 +2181,7 @@ static void bch2_evict_inode(struct inode *vinode)
|
||||
KEY_TYPE_QUOTA_WARN);
|
||||
bch2_quota_acct(c, inode->ei_qid, Q_INO, -1,
|
||||
KEY_TYPE_QUOTA_WARN);
|
||||
- int ret = bch2_inode_rm(c, inode_inum(inode));
|
||||
- if (ret && !bch2_err_matches(ret, EROFS)) {
|
||||
- bch_err_msg(c, ret, "VFS incorrectly tried to delete inode %llu:%llu",
|
||||
- inode->ei_inum.subvol,
|
||||
- inode->ei_inum.inum);
|
||||
- bch2_sb_error_count(c, BCH_FSCK_ERR_vfs_bad_inode_rm);
|
||||
- }
|
||||
+ bch2_inode_rm(c, inode_inum(inode));
|
||||
|
||||
/*
|
||||
* If we are deleting, we need it present in the vfs hash table
|
||||
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
|
||||
index bf117f2225d8..aaf187085276 100644
|
||||
--- a/fs/bcachefs/fsck.c
|
||||
+++ b/fs/bcachefs/fsck.c
|
||||
@@ -1183,14 +1183,6 @@ static int check_inode(struct btree_trans *trans,
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
- if (fsck_err_on(S_ISDIR(u.bi_mode) && u.bi_size,
|
||||
- trans, inode_dir_has_nonzero_i_size,
|
||||
- "directory %llu:%u with nonzero i_size %lli",
|
||||
- u.bi_inum, u.bi_snapshot, u.bi_size)) {
|
||||
- u.bi_size = 0;
|
||||
- do_update = true;
|
||||
- }
|
||||
-
|
||||
ret = bch2_inode_has_child_snapshots(trans, k.k->p);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c
|
||||
index 845efd429d13..490b85841de9 100644
|
||||
--- a/fs/bcachefs/inode.c
|
||||
+++ b/fs/bcachefs/inode.c
|
||||
@@ -38,7 +38,6 @@ static const char * const bch2_inode_flag_strs[] = {
|
||||
#undef x
|
||||
|
||||
static int delete_ancestor_snapshot_inodes(struct btree_trans *, struct bpos);
|
||||
-static int may_delete_deleted_inum(struct btree_trans *, subvol_inum);
|
||||
|
||||
static const u8 byte_table[8] = { 1, 2, 3, 4, 6, 8, 10, 13 };
|
||||
|
||||
@@ -1049,23 +1048,19 @@ int bch2_inode_rm(struct bch_fs *c, subvol_inum inum)
|
||||
u32 snapshot;
|
||||
int ret;
|
||||
|
||||
- ret = lockrestart_do(trans, may_delete_deleted_inum(trans, inum));
|
||||
- if (ret)
|
||||
- goto err2;
|
||||
-
|
||||
/*
|
||||
* If this was a directory, there shouldn't be any real dirents left -
|
||||
* but there could be whiteouts (from hash collisions) that we should
|
||||
* delete:
|
||||
*
|
||||
- * XXX: the dirent code ideally would delete whiteouts when they're no
|
||||
+ * XXX: the dirent could ideally would delete whiteouts when they're no
|
||||
* longer needed
|
||||
*/
|
||||
ret = bch2_inode_delete_keys(trans, inum, BTREE_ID_extents) ?:
|
||||
bch2_inode_delete_keys(trans, inum, BTREE_ID_xattrs) ?:
|
||||
bch2_inode_delete_keys(trans, inum, BTREE_ID_dirents);
|
||||
if (ret)
|
||||
- goto err2;
|
||||
+ goto err;
|
||||
retry:
|
||||
bch2_trans_begin(trans);
|
||||
|
||||
@@ -1347,8 +1342,10 @@ int bch2_inode_rm_snapshot(struct btree_trans *trans, u64 inum, u32 snapshot)
|
||||
delete_ancestor_snapshot_inodes(trans, SPOS(0, inum, snapshot));
|
||||
}
|
||||
|
||||
-static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
|
||||
- bool from_deleted_inodes)
|
||||
+static int may_delete_deleted_inode(struct btree_trans *trans,
|
||||
+ struct btree_iter *iter,
|
||||
+ struct bpos pos,
|
||||
+ bool *need_another_pass)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct btree_iter inode_iter;
|
||||
@@ -1363,13 +1360,11 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
|
||||
return ret;
|
||||
|
||||
ret = bkey_is_inode(k.k) ? 0 : -BCH_ERR_ENOENT_inode;
|
||||
- if (fsck_err_on(from_deleted_inodes && ret,
|
||||
+ if (fsck_err_on(!bkey_is_inode(k.k),
|
||||
trans, deleted_inode_missing,
|
||||
"nonexistent inode %llu:%u in deleted_inodes btree",
|
||||
pos.offset, pos.snapshot))
|
||||
goto delete;
|
||||
- if (ret)
|
||||
- goto out;
|
||||
|
||||
ret = bch2_inode_unpack(k, &inode);
|
||||
if (ret)
|
||||
@@ -1377,8 +1372,7 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
|
||||
|
||||
if (S_ISDIR(inode.bi_mode)) {
|
||||
ret = bch2_empty_dir_snapshot(trans, pos.offset, 0, pos.snapshot);
|
||||
- if (fsck_err_on(from_deleted_inodes &&
|
||||
- bch2_err_matches(ret, ENOTEMPTY),
|
||||
+ if (fsck_err_on(bch2_err_matches(ret, ENOTEMPTY),
|
||||
trans, deleted_inode_is_dir,
|
||||
"non empty directory %llu:%u in deleted_inodes btree",
|
||||
pos.offset, pos.snapshot))
|
||||
@@ -1387,25 +1381,17 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- ret = inode.bi_flags & BCH_INODE_unlinked ? 0 : -BCH_ERR_inode_not_unlinked;
|
||||
- if (fsck_err_on(from_deleted_inodes && ret,
|
||||
+ if (fsck_err_on(!(inode.bi_flags & BCH_INODE_unlinked),
|
||||
trans, deleted_inode_not_unlinked,
|
||||
"non-deleted inode %llu:%u in deleted_inodes btree",
|
||||
pos.offset, pos.snapshot))
|
||||
goto delete;
|
||||
- if (ret)
|
||||
- goto out;
|
||||
-
|
||||
- ret = !(inode.bi_flags & BCH_INODE_has_child_snapshot)
|
||||
- ? 0 : -BCH_ERR_inode_has_child_snapshot;
|
||||
|
||||
- if (fsck_err_on(from_deleted_inodes && ret,
|
||||
+ if (fsck_err_on(inode.bi_flags & BCH_INODE_has_child_snapshot,
|
||||
trans, deleted_inode_has_child_snapshots,
|
||||
"inode with child snapshots %llu:%u in deleted_inodes btree",
|
||||
pos.offset, pos.snapshot))
|
||||
goto delete;
|
||||
- if (ret)
|
||||
- goto out;
|
||||
|
||||
ret = bch2_inode_has_child_snapshots(trans, k.k->p);
|
||||
if (ret < 0)
|
||||
@@ -1422,28 +1408,19 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
-
|
||||
- if (!from_deleted_inodes) {
|
||||
- ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
|
||||
- -BCH_ERR_inode_has_child_snapshot;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
goto delete;
|
||||
|
||||
}
|
||||
|
||||
- if (from_deleted_inodes) {
|
||||
- if (test_bit(BCH_FS_clean_recovery, &c->flags) &&
|
||||
- !fsck_err(trans, deleted_inode_but_clean,
|
||||
- "filesystem marked as clean but have deleted inode %llu:%u",
|
||||
- pos.offset, pos.snapshot)) {
|
||||
- ret = 0;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- ret = 1;
|
||||
+ if (test_bit(BCH_FS_clean_recovery, &c->flags) &&
|
||||
+ !fsck_err(trans, deleted_inode_but_clean,
|
||||
+ "filesystem marked as clean but have deleted inode %llu:%u",
|
||||
+ pos.offset, pos.snapshot)) {
|
||||
+ ret = 0;
|
||||
+ goto out;
|
||||
}
|
||||
+
|
||||
+ ret = 1;
|
||||
out:
|
||||
fsck_err:
|
||||
bch2_trans_iter_exit(trans, &inode_iter);
|
||||
@@ -1454,19 +1431,12 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
|
||||
goto out;
|
||||
}
|
||||
|
||||
-static int may_delete_deleted_inum(struct btree_trans *trans, subvol_inum inum)
|
||||
-{
|
||||
- u32 snapshot;
|
||||
-
|
||||
- return bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot) ?:
|
||||
- may_delete_deleted_inode(trans, SPOS(0, inum.inum, snapshot), false);
|
||||
-}
|
||||
-
|
||||
int bch2_delete_dead_inodes(struct bch_fs *c)
|
||||
{
|
||||
struct btree_trans *trans = bch2_trans_get(c);
|
||||
+ bool need_another_pass;
|
||||
int ret;
|
||||
-
|
||||
+again:
|
||||
/*
|
||||
* if we ran check_inodes() unlinked inodes will have already been
|
||||
* cleaned up but the write buffer will be out of sync; therefore we
|
||||
@@ -1476,6 +1446,8 @@ int bch2_delete_dead_inodes(struct bch_fs *c)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
+ need_another_pass = false;
|
||||
+
|
||||
/*
|
||||
* Weird transaction restart handling here because on successful delete,
|
||||
* bch2_inode_rm_snapshot() will return a nested transaction restart,
|
||||
@@ -1485,7 +1457,7 @@ int bch2_delete_dead_inodes(struct bch_fs *c)
|
||||
ret = for_each_btree_key_commit(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
|
||||
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
|
||||
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
|
||||
- ret = may_delete_deleted_inode(trans, k.k->p, true);
|
||||
+ ret = may_delete_deleted_inode(trans, &iter, k.k->p, &need_another_pass);
|
||||
if (ret > 0) {
|
||||
bch_verbose_ratelimited(c, "deleting unlinked inode %llu:%u",
|
||||
k.k->p.offset, k.k->p.snapshot);
|
||||
@@ -1506,6 +1478,9 @@ int bch2_delete_dead_inodes(struct bch_fs *c)
|
||||
|
||||
ret;
|
||||
}));
|
||||
+
|
||||
+ if (!ret && need_another_pass)
|
||||
+ goto again;
|
||||
err:
|
||||
bch2_trans_put(trans);
|
||||
return ret;
|
||||
diff --git a/fs/bcachefs/namei.c b/fs/bcachefs/namei.c
|
||||
index 413fb60cff43..9136a9097789 100644
|
||||
--- a/fs/bcachefs/namei.c
|
||||
+++ b/fs/bcachefs/namei.c
|
||||
@@ -418,8 +418,8 @@ int bch2_rename_trans(struct btree_trans *trans,
|
||||
}
|
||||
|
||||
ret = bch2_dirent_rename(trans,
|
||||
- src_dir, &src_hash,
|
||||
- dst_dir, &dst_hash,
|
||||
+ src_dir, &src_hash, &src_dir_u->bi_size,
|
||||
+ dst_dir, &dst_hash, &dst_dir_u->bi_size,
|
||||
src_name, &src_inum, &src_offset,
|
||||
dst_name, &dst_inum, &dst_offset,
|
||||
mode);
|
||||
diff --git a/fs/bcachefs/sb-errors_format.h b/fs/bcachefs/sb-errors_format.h
|
||||
index 9387f6092fe9..4036a20c6adc 100644
|
||||
--- a/fs/bcachefs/sb-errors_format.h
|
||||
+++ b/fs/bcachefs/sb-errors_format.h
|
||||
@@ -232,7 +232,6 @@ enum bch_fsck_flags {
|
||||
x(inode_dir_multiple_links, 206, FSCK_AUTOFIX) \
|
||||
x(inode_dir_missing_backpointer, 284, FSCK_AUTOFIX) \
|
||||
x(inode_dir_unlinked_but_not_empty, 286, FSCK_AUTOFIX) \
|
||||
- x(inode_dir_has_nonzero_i_size, 319, FSCK_AUTOFIX) \
|
||||
x(inode_multiple_links_but_nlink_0, 207, FSCK_AUTOFIX) \
|
||||
x(inode_wrong_backpointer, 208, FSCK_AUTOFIX) \
|
||||
x(inode_wrong_nlink, 209, FSCK_AUTOFIX) \
|
||||
@@ -244,7 +243,6 @@ enum bch_fsck_flags {
|
||||
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(vfs_bad_inode_rm, 320, 0) \
|
||||
x(deleted_inode_but_clean, 211, FSCK_AUTOFIX) \
|
||||
x(deleted_inode_missing, 212, FSCK_AUTOFIX) \
|
||||
x(deleted_inode_is_dir, 213, FSCK_AUTOFIX) \
|
||||
@@ -330,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, 321, 0)
|
||||
+ x(MAX, 319, 0)
|
||||
|
||||
enum bch_sb_error_id {
|
||||
#define x(t, n, ...) BCH_FSCK_ERR_##t = n,
|
||||
diff --git a/fs/bcachefs/subvolume.c b/fs/bcachefs/subvolume.c
|
||||
index bc6009a71284..d0209f7658bb 100644
|
||||
--- a/fs/bcachefs/subvolume.c
|
||||
+++ b/fs/bcachefs/subvolume.c
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "errcode.h"
|
||||
#include "error.h"
|
||||
#include "fs.h"
|
||||
-#include "inode.h"
|
||||
#include "recovery_passes.h"
|
||||
#include "snapshot.h"
|
||||
#include "subvolume.h"
|
||||
@@ -114,20 +113,10 @@ static int check_subvol(struct btree_trans *trans,
|
||||
"subvolume %llu points to missing subvolume root %llu:%u",
|
||||
k.k->p.offset, le64_to_cpu(subvol.v->inode),
|
||||
le32_to_cpu(subvol.v->snapshot))) {
|
||||
- /*
|
||||
- * Recreate - any contents that are still disconnected
|
||||
- * will then get reattached under lost+found
|
||||
- */
|
||||
- bch2_inode_init_early(c, &inode);
|
||||
- bch2_inode_init_late(&inode, bch2_current_time(c),
|
||||
- 0, 0, S_IFDIR|0700, 0, NULL);
|
||||
- inode.bi_inum = le64_to_cpu(subvol.v->inode);
|
||||
- inode.bi_snapshot = le32_to_cpu(subvol.v->snapshot);
|
||||
- inode.bi_subvol = k.k->p.offset;
|
||||
- inode.bi_parent_subvol = le32_to_cpu(subvol.v->fs_path_parent);
|
||||
- ret = __bch2_fsck_write_inode(trans, &inode);
|
||||
- if (ret)
|
||||
- goto err;
|
||||
+ ret = bch2_subvolume_delete(trans, iter->pos.offset);
|
||||
+ bch_err_msg(c, ret, "deleting subvolume %llu", iter->pos.offset);
|
||||
+ ret = ret ?: -BCH_ERR_transaction_restart_nested;
|
||||
+ goto err;
|
||||
}
|
||||
} else {
|
||||
goto err;
|
||||
--
|
||||
2.49.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,177 @@
|
||||
From 81f83264e1127666cfc72cc998b69103ae44b881 Mon Sep 17 00:00:00 2001
|
||||
From: Amir Goldstein <amir73il@gmail.com>
|
||||
Date: Mon, 2 Jun 2025 19:17:02 +0200
|
||||
Subject: [PATCH] ovl: support layers on case-folding capable filesystems
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Case folding is often applied to subtrees and not on an entire
|
||||
filesystem.
|
||||
|
||||
Disallowing layers from filesystems that support case folding is over
|
||||
limiting.
|
||||
|
||||
Replace the rule that case-folding capable are not allowed as layers
|
||||
with a rule that case folded directories are not allowed in a merged
|
||||
directory stack.
|
||||
|
||||
Should case folding be enabled on an underlying directory while
|
||||
overlayfs is mounted the outcome is generally undefined.
|
||||
|
||||
Specifically in ovl_lookup(), we check the base underlying directory
|
||||
and fail with -ESTALE and write a warning to kmsg if an underlying
|
||||
directory case folding is enabled.
|
||||
|
||||
Suggested-by: Kent Overstreet <kent.overstreet@linux.dev>
|
||||
Link: https://lore.kernel.org/linux-fsdevel/20250520051600.1903319-1-kent.overstreet@linux.dev/
|
||||
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
|
||||
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
|
||||
Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
|
||||
---
|
||||
fs/overlayfs/namei.c | 31 ++++++++++++++++++++++++++++---
|
||||
fs/overlayfs/overlayfs.h | 6 ++++++
|
||||
fs/overlayfs/params.c | 10 ++++------
|
||||
fs/overlayfs/util.c | 15 +++++++++++----
|
||||
4 files changed, 49 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
|
||||
index 2043f0369059..76d6248b625e 100644
|
||||
--- a/fs/overlayfs/namei.c
|
||||
+++ b/fs/overlayfs/namei.c
|
||||
@@ -230,13 +230,26 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
|
||||
struct dentry **ret, bool drop_negative)
|
||||
{
|
||||
struct ovl_fs *ofs = OVL_FS(d->sb);
|
||||
- struct dentry *this;
|
||||
+ struct dentry *this = NULL;
|
||||
+ const char *warn;
|
||||
struct path path;
|
||||
int err;
|
||||
bool last_element = !post[0];
|
||||
bool is_upper = d->layer->idx == 0;
|
||||
char val;
|
||||
|
||||
+ /*
|
||||
+ * We allow filesystems that are case-folding capable but deny composing
|
||||
+ * ovl stack from case-folded directories. If someone has enabled case
|
||||
+ * folding on a directory on underlying layer, the warranty of the ovl
|
||||
+ * stack is voided.
|
||||
+ */
|
||||
+ if (ovl_dentry_casefolded(base)) {
|
||||
+ warn = "case folded parent";
|
||||
+ err = -ESTALE;
|
||||
+ goto out_warn;
|
||||
+ }
|
||||
+
|
||||
this = ovl_lookup_positive_unlocked(d, name, base, namelen, drop_negative);
|
||||
if (IS_ERR(this)) {
|
||||
err = PTR_ERR(this);
|
||||
@@ -246,10 +259,17 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
+ if (ovl_dentry_casefolded(this)) {
|
||||
+ warn = "case folded child";
|
||||
+ err = -EREMOTE;
|
||||
+ goto out_warn;
|
||||
+ }
|
||||
+
|
||||
if (ovl_dentry_weird(this)) {
|
||||
/* Don't support traversing automounts and other weirdness */
|
||||
+ warn = "unsupported object type";
|
||||
err = -EREMOTE;
|
||||
- goto out_err;
|
||||
+ goto out_warn;
|
||||
}
|
||||
|
||||
path.dentry = this;
|
||||
@@ -283,8 +303,9 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
|
||||
} else {
|
||||
if (ovl_lookup_trap_inode(d->sb, this)) {
|
||||
/* Caught in a trap of overlapping layers */
|
||||
+ warn = "overlapping layers";
|
||||
err = -ELOOP;
|
||||
- goto out_err;
|
||||
+ goto out_warn;
|
||||
}
|
||||
|
||||
if (last_element)
|
||||
@@ -316,6 +337,10 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
|
||||
this = NULL;
|
||||
goto out;
|
||||
|
||||
+out_warn:
|
||||
+ pr_warn_ratelimited("failed lookup in %s (%pd2, name='%.*s', err=%i): %s\n",
|
||||
+ is_upper ? "upper" : "lower", base,
|
||||
+ namelen, name, err, warn);
|
||||
out_err:
|
||||
dput(this);
|
||||
return err;
|
||||
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
|
||||
index 497323128e5f..55806bd36faa 100644
|
||||
--- a/fs/overlayfs/overlayfs.h
|
||||
+++ b/fs/overlayfs/overlayfs.h
|
||||
@@ -448,6 +448,12 @@ void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry,
|
||||
void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry,
|
||||
struct ovl_entry *oe, unsigned int mask);
|
||||
bool ovl_dentry_weird(struct dentry *dentry);
|
||||
+
|
||||
+static inline bool ovl_dentry_casefolded(struct dentry *dentry)
|
||||
+{
|
||||
+ return sb_has_encoding(dentry->d_sb) && IS_CASEFOLDED(d_inode(dentry));
|
||||
+}
|
||||
+
|
||||
enum ovl_path_type ovl_path_type(struct dentry *dentry);
|
||||
void ovl_path_upper(struct dentry *dentry, struct path *path);
|
||||
void ovl_path_lower(struct dentry *dentry, struct path *path);
|
||||
diff --git a/fs/overlayfs/params.c b/fs/overlayfs/params.c
|
||||
index f42488c01957..2b9b31524c38 100644
|
||||
--- a/fs/overlayfs/params.c
|
||||
+++ b/fs/overlayfs/params.c
|
||||
@@ -282,13 +282,11 @@ static int ovl_mount_dir_check(struct fs_context *fc, const struct path *path,
|
||||
return invalfc(fc, "%s is not a directory", name);
|
||||
|
||||
/*
|
||||
- * Root dentries of case-insensitive capable filesystems might
|
||||
- * not have the dentry operations set, but still be incompatible
|
||||
- * with overlayfs. Check explicitly to prevent post-mount
|
||||
- * failures.
|
||||
+ * Allow filesystems that are case-folding capable but deny composing
|
||||
+ * ovl stack from case-folded directories.
|
||||
*/
|
||||
- if (sb_has_encoding(path->mnt->mnt_sb))
|
||||
- return invalfc(fc, "case-insensitive capable filesystem on %s not supported", name);
|
||||
+ if (ovl_dentry_casefolded(path->dentry))
|
||||
+ return invalfc(fc, "case-insensitive directory on %s not supported", name);
|
||||
|
||||
if (ovl_dentry_weird(path->dentry))
|
||||
return invalfc(fc, "filesystem on %s not supported", name);
|
||||
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
|
||||
index dcccb4b4a66c..593c4da107d6 100644
|
||||
--- a/fs/overlayfs/util.c
|
||||
+++ b/fs/overlayfs/util.c
|
||||
@@ -206,10 +206,17 @@ bool ovl_dentry_weird(struct dentry *dentry)
|
||||
if (!d_can_lookup(dentry) && !d_is_file(dentry) && !d_is_symlink(dentry))
|
||||
return true;
|
||||
|
||||
- return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT |
|
||||
- DCACHE_MANAGE_TRANSIT |
|
||||
- DCACHE_OP_HASH |
|
||||
- DCACHE_OP_COMPARE);
|
||||
+ if (dentry->d_flags & (DCACHE_NEED_AUTOMOUNT | DCACHE_MANAGE_TRANSIT))
|
||||
+ return true;
|
||||
+
|
||||
+ /*
|
||||
+ * Allow filesystems that are case-folding capable but deny composing
|
||||
+ * ovl stack from case-folded directories.
|
||||
+ */
|
||||
+ if (sb_has_encoding(dentry->d_sb))
|
||||
+ return IS_CASEFOLDED(d_inode(dentry));
|
||||
+
|
||||
+ return dentry->d_flags & (DCACHE_OP_HASH | DCACHE_OP_COMPARE);
|
||||
}
|
||||
|
||||
enum ovl_path_type ovl_path_type(struct dentry *dentry)
|
||||
--
|
||||
2.49.1
|
||||
|
||||
Reference in New Issue
Block a user