* FAILED: patch "[PATCH] udf: Fix data loss when converting inline inodes to out of" failed to apply to 7.2-stable tree
@ 2026-09-04 4:53 gregkh
2026-09-10 1:17 ` [PATCH 7.2.y 1/2] udf: Move udf_map_block() up Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: gregkh @ 2026-09-04 4:53 UTC (permalink / raw)
To: jack; +Cc: stable
The patch below does not apply to the 7.2-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-7.2.y
git checkout FETCH_HEAD
git cherry-pick -x 62333e480d12ab186f89fe2725b372d12f72d5eb
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026090407-drool-bonehead-8d81@gregkh' --subject-prefix 'PATCH 7.2.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 62333e480d12ab186f89fe2725b372d12f72d5eb Mon Sep 17 00:00:00 2001
From: Jan Kara <jack@suse.cz>
Date: Thu, 30 Jul 2026 12:42:29 +0200
Subject: [PATCH] udf: Fix data loss when converting inline inodes to out of
line
When udf_expand_file_adinicb() converts file from inline format to out
of line, we use filemap_fdatawrite() to writeout the data to the new
blocks. However since 36580ed08776 ("udf: Do not allocate blocks on page
writeback") the writeback actually doesn't allocate the new block and
the folio dirty bit is just silently cleared. Thus unless the file is
written to after the conversion (as it can easily happen in case of
truncate up), the data is just lost. Fix the problem by explicitely
allocating the block underlying the data before starting writeback.
Fixes: 36580ed08776 ("udf: Do not allocate blocks on page writeback")
CC: stable@vger.kernel.org
Link: https://patch.msgid.link/20260730104232.4086759-4-jack@suse.cz
Signed-off-by: Jan Kara <jack@suse.cz>
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index d3303f58cf07..1f131876c345 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -405,6 +405,10 @@ int udf_expand_file_adinicb(struct inode *inode)
{
struct folio *folio;
struct udf_inode_info *iinfo = UDF_I(inode);
+ struct udf_map_rq map = {
+ .lblk = 0,
+ .iflags = UDF_MAP_CREATE,
+ };
int err;
WARN_ON_ONCE(!inode_is_locked(inode));
@@ -434,20 +438,27 @@ int udf_expand_file_adinicb(struct inode *inode)
iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
else
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
+ up_write(&iinfo->i_data_sem);
+
+ /* Allocate the block underlying the data */
+ err = udf_map_block(inode, &map);
+ if (err < 0)
+ goto restore;
+
folio_mark_dirty(folio);
folio_unlock(folio);
- up_write(&iinfo->i_data_sem);
err = filemap_fdatawrite(inode->i_mapping);
if (err) {
/* Restore everything back so that we don't lose data... */
folio_lock(folio);
+restore:
down_write(&iinfo->i_data_sem);
memcpy_from_folio(iinfo->i_data + iinfo->i_lenEAttr,
folio, 0, inode->i_size);
- folio_unlock(folio);
iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
iinfo->i_lenAlloc = inode->i_size;
up_write(&iinfo->i_data_sem);
+ folio_unlock(folio);
}
folio_put(folio);
mark_inode_dirty(inode);
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 7.2.y 1/2] udf: Move udf_map_block() up
2026-09-04 4:53 FAILED: patch "[PATCH] udf: Fix data loss when converting inline inodes to out of" failed to apply to 7.2-stable tree gregkh
@ 2026-09-10 1:17 ` Sasha Levin
2026-09-10 1:17 ` [PATCH 7.2.y 2/2] udf: Fix data loss when converting inline inodes to out of line Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: Sasha Levin @ 2026-09-10 1:17 UTC (permalink / raw)
To: stable; +Cc: Jan Kara, Sasha Levin
From: Jan Kara <jack@suse.cz>
[ Upstream commit 97e9d759a4193eabe4d8b6ecac093aac664c16e3 ]
Move udf_map_block() in the file to avoid forward declarations.
Link: https://patch.msgid.link/20260730104232.4086759-3-jack@suse.cz
Signed-off-by: Jan Kara <jack@suse.cz>
Stable-dep-of: 62333e480d12 ("udf: Fix data loss when converting inline inodes to out of line")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/udf/inode.c | 118 ++++++++++++++++++++++++-------------------------
1 file changed, 59 insertions(+), 59 deletions(-)
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index c519644acfd7d..074ee35ef3c29 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -336,65 +336,6 @@ const struct address_space_operations udf_aops = {
.migrate_folio = buffer_migrate_folio,
};
-/*
- * Expand file stored in ICB to a normal one-block-file
- *
- * This function requires i_mutex held
- */
-int udf_expand_file_adinicb(struct inode *inode)
-{
- struct folio *folio;
- struct udf_inode_info *iinfo = UDF_I(inode);
- int err;
-
- WARN_ON_ONCE(!inode_is_locked(inode));
- if (!iinfo->i_lenAlloc) {
- down_write(&iinfo->i_data_sem);
- if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
- iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
- else
- iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
- up_write(&iinfo->i_data_sem);
- mark_inode_dirty(inode);
- return 0;
- }
-
- folio = __filemap_get_folio(inode->i_mapping, 0,
- FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_KERNEL);
- if (IS_ERR(folio))
- return PTR_ERR(folio);
-
- if (!folio_test_uptodate(folio))
- udf_adinicb_read_folio(folio);
- down_write(&iinfo->i_data_sem);
- memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00,
- iinfo->i_lenAlloc);
- iinfo->i_lenAlloc = 0;
- if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
- iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
- else
- iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
- folio_mark_dirty(folio);
- folio_unlock(folio);
- up_write(&iinfo->i_data_sem);
- err = filemap_fdatawrite(inode->i_mapping);
- if (err) {
- /* Restore everything back so that we don't lose data... */
- folio_lock(folio);
- down_write(&iinfo->i_data_sem);
- memcpy_from_folio(iinfo->i_data + iinfo->i_lenEAttr,
- folio, 0, inode->i_size);
- folio_unlock(folio);
- iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
- iinfo->i_lenAlloc = inode->i_size;
- up_write(&iinfo->i_data_sem);
- }
- folio_put(folio);
- mark_inode_dirty(inode);
-
- return err;
-}
-
#define UDF_MAP_CREATE 0x01 /* Mapping can allocate new blocks */
#define UDF_MAP_NOPREALLOC 0x02 /* Do not preallocate blocks */
@@ -455,6 +396,65 @@ static int udf_map_block(struct inode *inode, struct udf_map_rq *map)
return ret;
}
+/*
+ * Expand file stored in ICB to a normal one-block-file
+ *
+ * This function requires i_mutex held
+ */
+int udf_expand_file_adinicb(struct inode *inode)
+{
+ struct folio *folio;
+ struct udf_inode_info *iinfo = UDF_I(inode);
+ int err;
+
+ WARN_ON_ONCE(!inode_is_locked(inode));
+ if (!iinfo->i_lenAlloc) {
+ down_write(&iinfo->i_data_sem);
+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+ iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
+ else
+ iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
+ up_write(&iinfo->i_data_sem);
+ mark_inode_dirty(inode);
+ return 0;
+ }
+
+ folio = __filemap_get_folio(inode->i_mapping, 0,
+ FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_KERNEL);
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
+
+ if (!folio_test_uptodate(folio))
+ udf_adinicb_read_folio(folio);
+ down_write(&iinfo->i_data_sem);
+ memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00,
+ iinfo->i_lenAlloc);
+ iinfo->i_lenAlloc = 0;
+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+ iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
+ else
+ iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
+ folio_mark_dirty(folio);
+ folio_unlock(folio);
+ up_write(&iinfo->i_data_sem);
+ err = filemap_fdatawrite(inode->i_mapping);
+ if (err) {
+ /* Restore everything back so that we don't lose data... */
+ folio_lock(folio);
+ down_write(&iinfo->i_data_sem);
+ memcpy_from_folio(iinfo->i_data + iinfo->i_lenEAttr,
+ folio, 0, inode->i_size);
+ folio_unlock(folio);
+ iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
+ iinfo->i_lenAlloc = inode->i_size;
+ up_write(&iinfo->i_data_sem);
+ }
+ folio_put(folio);
+ mark_inode_dirty(inode);
+
+ return err;
+}
+
static int __udf_get_block(struct inode *inode, sector_t block,
struct buffer_head *bh_result, int flags)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 7.2.y 2/2] udf: Fix data loss when converting inline inodes to out of line
2026-09-10 1:17 ` [PATCH 7.2.y 1/2] udf: Move udf_map_block() up Sasha Levin
@ 2026-09-10 1:17 ` Sasha Levin
0 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-09-10 1:17 UTC (permalink / raw)
To: stable; +Cc: Jan Kara, Sasha Levin
From: Jan Kara <jack@suse.cz>
[ Upstream commit 62333e480d12ab186f89fe2725b372d12f72d5eb ]
When udf_expand_file_adinicb() converts file from inline format to out
of line, we use filemap_fdatawrite() to writeout the data to the new
blocks. However since 36580ed08776 ("udf: Do not allocate blocks on page
writeback") the writeback actually doesn't allocate the new block and
the folio dirty bit is just silently cleared. Thus unless the file is
written to after the conversion (as it can easily happen in case of
truncate up), the data is just lost. Fix the problem by explicitely
allocating the block underlying the data before starting writeback.
Fixes: 36580ed08776 ("udf: Do not allocate blocks on page writeback")
CC: stable@vger.kernel.org
Link: https://patch.msgid.link/20260730104232.4086759-4-jack@suse.cz
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/udf/inode.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 074ee35ef3c29..e1fdf9f9c9f50 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -405,6 +405,10 @@ int udf_expand_file_adinicb(struct inode *inode)
{
struct folio *folio;
struct udf_inode_info *iinfo = UDF_I(inode);
+ struct udf_map_rq map = {
+ .lblk = 0,
+ .iflags = UDF_MAP_CREATE,
+ };
int err;
WARN_ON_ONCE(!inode_is_locked(inode));
@@ -434,20 +438,27 @@ int udf_expand_file_adinicb(struct inode *inode)
iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
else
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
+ up_write(&iinfo->i_data_sem);
+
+ /* Allocate the block underlying the data */
+ err = udf_map_block(inode, &map);
+ if (err < 0)
+ goto restore;
+
folio_mark_dirty(folio);
folio_unlock(folio);
- up_write(&iinfo->i_data_sem);
err = filemap_fdatawrite(inode->i_mapping);
if (err) {
/* Restore everything back so that we don't lose data... */
folio_lock(folio);
+restore:
down_write(&iinfo->i_data_sem);
memcpy_from_folio(iinfo->i_data + iinfo->i_lenEAttr,
folio, 0, inode->i_size);
- folio_unlock(folio);
iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
iinfo->i_lenAlloc = inode->i_size;
up_write(&iinfo->i_data_sem);
+ folio_unlock(folio);
}
folio_put(folio);
mark_inode_dirty(inode);
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-10 1:17 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-04 4:53 FAILED: patch "[PATCH] udf: Fix data loss when converting inline inodes to out of" failed to apply to 7.2-stable tree gregkh
2026-09-10 1:17 ` [PATCH 7.2.y 1/2] udf: Move udf_map_block() up Sasha Levin
2026-09-10 1:17 ` [PATCH 7.2.y 2/2] udf: Fix data loss when converting inline inodes to out of line Sasha Levin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.