mirror of https://github.com/torvalds/linux.git
for-6.17-fix-tag
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmiTNoEACgkQxWXV+ddt
WDuo3Q/+PPl1TH5+8A9zp+Aq0teDiF4I4pfpFRcoy+18lvNiPj8zFMOelOoOXczb
rpYegaAjTrtZFlk9lVChTI4fSlAUkhPjgzELMWmpQsTSiYqGJxLO7B3BJEBqvuEt
HDR0l1yBOW30EFszc8LKDXFj6IPI78xtQ2QyzFOcs0Xk9RVO2e8NpTFeroSr/bou
uORWjZKOpQwPMLHjhZmhg/iAO+BM4hdV0MP9mQL4p4fAEfm0IKkRvQC/IQitSmHD
e2WB9GsnFn6DxkEy3AkqZyyKwEfWNTIo+af4xSkbfOIn1KRtvABCXRtvb7Iuc31z
TjPTubCsVIa48MeYkK+Qj7roMbjpcIIPciSgQWnEF/OTaiEZtPgbJJUYtQbtg/6o
IglLquGn96k10sWIBEaiqBbmTwDOEaPLrrq75PeN5F6BENGAGdNr19B+5UXPvGpp
f5XBoSKrgvFmtEzhSzkOk9obJvUaY5060JMVoymUopOXQdi243gAzGJaPLKugzDY
qwRHe594DR438FFfDtqCs9s8+F23SL+mRWoD5H26H0fTgOe8hMc1sSELD99yZrRm
4SGum5/7VjF422Q3lacHrdCaOWCFr3tbbK+6CYB975v0XwGIZj0Lh1Y7joDx0faW
YHee1AcPw3zAqXXUcKv5aU3KcdsCE9xXlLAUDxVGxQzebh46heU=
=tSdx
-----END PGP SIGNATURE-----
Merge tag 'for-6.17-fix-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fix from David Sterba:
"A single btrfs commit. It fixes a problem that people started to hit
since 6.15.3 during log replay (e.g. after a crash).
The bug is old but got more likely to happen since commit
5e85262e54 ("btrfs: fix fsync of files with no hard links not
persisting deletion") got backported to stable (6.15 only)"
* tag 'for-6.17-fix-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: fix log tree replay failure due to file with 0 links and extents
This commit is contained in:
commit
cca7a0aae8
|
|
@ -321,8 +321,7 @@ struct walk_control {
|
|||
|
||||
/*
|
||||
* Ignore any items from the inode currently being processed. Needs
|
||||
* to be set every time we find a BTRFS_INODE_ITEM_KEY and we are in
|
||||
* the LOG_WALK_REPLAY_INODES stage.
|
||||
* to be set every time we find a BTRFS_INODE_ITEM_KEY.
|
||||
*/
|
||||
bool ignore_cur_inode;
|
||||
|
||||
|
|
@ -2465,23 +2464,30 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
|
|||
|
||||
nritems = btrfs_header_nritems(eb);
|
||||
for (i = 0; i < nritems; i++) {
|
||||
struct btrfs_inode_item *inode_item;
|
||||
|
||||
btrfs_item_key_to_cpu(eb, &key, i);
|
||||
|
||||
/* inode keys are done during the first stage */
|
||||
if (key.type == BTRFS_INODE_ITEM_KEY &&
|
||||
wc->stage == LOG_WALK_REPLAY_INODES) {
|
||||
struct btrfs_inode_item *inode_item;
|
||||
u32 mode;
|
||||
|
||||
inode_item = btrfs_item_ptr(eb, i,
|
||||
struct btrfs_inode_item);
|
||||
if (key.type == BTRFS_INODE_ITEM_KEY) {
|
||||
inode_item = btrfs_item_ptr(eb, i, struct btrfs_inode_item);
|
||||
/*
|
||||
* If we have a tmpfile (O_TMPFILE) that got fsync'ed
|
||||
* and never got linked before the fsync, skip it, as
|
||||
* replaying it is pointless since it would be deleted
|
||||
* later. We skip logging tmpfiles, but it's always
|
||||
* possible we are replaying a log created with a kernel
|
||||
* that used to log tmpfiles.
|
||||
* An inode with no links is either:
|
||||
*
|
||||
* 1) A tmpfile (O_TMPFILE) that got fsync'ed and never
|
||||
* got linked before the fsync, skip it, as replaying
|
||||
* it is pointless since it would be deleted later.
|
||||
* We skip logging tmpfiles, but it's always possible
|
||||
* we are replaying a log created with a kernel that
|
||||
* used to log tmpfiles;
|
||||
*
|
||||
* 2) A non-tmpfile which got its last link deleted
|
||||
* while holding an open fd on it and later got
|
||||
* fsynced through that fd. We always log the
|
||||
* parent inodes when inode->last_unlink_trans is
|
||||
* set to the current transaction, so ignore all the
|
||||
* inode items for this inode. We will delete the
|
||||
* inode when processing the parent directory with
|
||||
* replay_dir_deletes().
|
||||
*/
|
||||
if (btrfs_inode_nlink(eb, inode_item) == 0) {
|
||||
wc->ignore_cur_inode = true;
|
||||
|
|
@ -2489,8 +2495,14 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
|
|||
} else {
|
||||
wc->ignore_cur_inode = false;
|
||||
}
|
||||
ret = replay_xattr_deletes(wc->trans, root, log,
|
||||
path, key.objectid);
|
||||
}
|
||||
|
||||
/* Inode keys are done during the first stage. */
|
||||
if (key.type == BTRFS_INODE_ITEM_KEY &&
|
||||
wc->stage == LOG_WALK_REPLAY_INODES) {
|
||||
u32 mode;
|
||||
|
||||
ret = replay_xattr_deletes(wc->trans, root, log, path, key.objectid);
|
||||
if (ret)
|
||||
break;
|
||||
mode = btrfs_inode_mode(eb, inode_item);
|
||||
|
|
|
|||
Loading…
Reference in New Issue