--- /dev/null
+From 2c26fb3783f69a5a373c823d4c2bc4028c855bd7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 10:50:17 +0800
+Subject: net: Drop the lock in skb_may_tx_timestamp()
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+commit 983512f3a87fd8dc4c94dfa6b596b6e57df5aad7 upstream.
+
+skb_may_tx_timestamp() may acquire sock::sk_callback_lock. The lock must
+not be taken in IRQ context, only softirq is okay. A few drivers receive
+the timestamp via a dedicated interrupt and complete the TX timestamp
+from that handler. This will lead to a deadlock if the lock is already
+write-locked on the same CPU.
+
+Taking the lock can be avoided. The socket (pointed by the skb) will
+remain valid until the skb is released. The ->sk_socket and ->file
+member will be set to NULL once the user closes the socket which may
+happen before the timestamp arrives.
+If we happen to observe the pointer while the socket is closing but
+before the pointer is set to NULL then we may use it because both
+pointer (and the file's cred member) are RCU freed.
+
+Drop the lock. Use READ_ONCE() to obtain the individual pointer. Add a
+matching WRITE_ONCE() where the pointer are cleared.
+
+Link: https://lore.kernel.org/all/20260205145104.iWinkXHv@linutronix.de
+Fixes: b245be1f4db1a ("net-timestamp: no-payload only sysctl")
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260220183858.N4ERjFW6@linutronix.de
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[ adapted sk_set_socket() in include/net/sock.h to fix the conflict from
+ not having commit 5d6b58c932ec ("net: lockless sock_i_ino()") and the
+ additional previous changes required by it.
+ It comes down to just now having the lines of
+ if (sock) {
+ WRITE_ONCE(sk->sk_uid, SOCK_INODE(sock)->i_uid);
+ WRITE_ONCE(sk->sk_ino, SOCK_INODE(sock)->i_ino);
+ }
+ below the changed line. ]
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/sock.h | 2 +-
+ net/core/skbuff.c | 23 ++++++++++++++++++-----
+ net/socket.c | 2 +-
+ 3 files changed, 20 insertions(+), 7 deletions(-)
+
+diff --git a/include/net/sock.h b/include/net/sock.h
+index f0e391afb511d2..b9c44e47cb7a78 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -1981,7 +1981,7 @@ static inline int sk_rx_queue_get(const struct sock *sk)
+
+ static inline void sk_set_socket(struct sock *sk, struct socket *sock)
+ {
+- sk->sk_socket = sock;
++ WRITE_ONCE(sk->sk_socket, sock);
+ }
+
+ static inline wait_queue_head_t *sk_sleep(struct sock *sk)
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index e4a39e0f55f242..90a63c356affb2 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -4772,15 +4772,28 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
+
+ static bool skb_may_tx_timestamp(struct sock *sk, bool tsonly)
+ {
+- bool ret;
++ struct socket *sock;
++ struct file *file;
++ bool ret = false;
+
+ if (likely(READ_ONCE(sysctl_tstamp_allow_data) || tsonly))
+ return true;
+
+- read_lock_bh(&sk->sk_callback_lock);
+- ret = sk->sk_socket && sk->sk_socket->file &&
+- file_ns_capable(sk->sk_socket->file, &init_user_ns, CAP_NET_RAW);
+- read_unlock_bh(&sk->sk_callback_lock);
++ /* The sk pointer remains valid as long as the skb is. The sk_socket and
++ * file pointer may become NULL if the socket is closed. Both structures
++ * (including file->cred) are RCU freed which means they can be accessed
++ * within a RCU read section.
++ */
++ rcu_read_lock();
++ sock = READ_ONCE(sk->sk_socket);
++ if (!sock)
++ goto out;
++ file = READ_ONCE(sock->file);
++ if (!file)
++ goto out;
++ ret = file_ns_capable(file, &init_user_ns, CAP_NET_RAW);
++out:
++ rcu_read_unlock();
+ return ret;
+ }
+
+diff --git a/net/socket.c b/net/socket.c
+index de838c3b004861..eb157ea2a3efbb 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -608,7 +608,7 @@ static void __sock_release(struct socket *sock, struct inode *inode)
+ iput(SOCK_INODE(sock));
+ return;
+ }
+- sock->file = NULL;
++ WRITE_ONCE(sock->file, NULL);
+ }
+
+ /**
+--
+2.53.0
+
bluetooth-bnep-pin-l2cap-connection-during-netdev-registration.patch
bluetooth-fix-uaf-in-bt_accept_dequeue.patch
bluetooth-l2cap-validate-option-length-before-reading-conf-opt-value.patch
+net-drop-the-lock-in-skb_may_tx_timestamp.patch
--- /dev/null
+From eb2697900d0ebd2573f3179231aec11df803ca2f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 10:49:43 +0800
+Subject: net: Drop the lock in skb_may_tx_timestamp()
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+commit 983512f3a87fd8dc4c94dfa6b596b6e57df5aad7 upstream.
+
+skb_may_tx_timestamp() may acquire sock::sk_callback_lock. The lock must
+not be taken in IRQ context, only softirq is okay. A few drivers receive
+the timestamp via a dedicated interrupt and complete the TX timestamp
+from that handler. This will lead to a deadlock if the lock is already
+write-locked on the same CPU.
+
+Taking the lock can be avoided. The socket (pointed by the skb) will
+remain valid until the skb is released. The ->sk_socket and ->file
+member will be set to NULL once the user closes the socket which may
+happen before the timestamp arrives.
+If we happen to observe the pointer while the socket is closing but
+before the pointer is set to NULL then we may use it because both
+pointer (and the file's cred member) are RCU freed.
+
+Drop the lock. Use READ_ONCE() to obtain the individual pointer. Add a
+matching WRITE_ONCE() where the pointer are cleared.
+
+Link: https://lore.kernel.org/all/20260205145104.iWinkXHv@linutronix.de
+Fixes: b245be1f4db1a ("net-timestamp: no-payload only sysctl")
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260220183858.N4ERjFW6@linutronix.de
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[ adapted sk_set_socket() in include/net/sock.h to fix the conflict from
+ not having commit 5d6b58c932ec ("net: lockless sock_i_ino()") and the
+ additional previous changes required by it.
+ It comes down to just now having the lines of
+ if (sock) {
+ WRITE_ONCE(sk->sk_uid, SOCK_INODE(sock)->i_uid);
+ WRITE_ONCE(sk->sk_ino, SOCK_INODE(sock)->i_ino);
+ }
+ below the changed line. ]
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/sock.h | 2 +-
+ net/core/skbuff.c | 23 ++++++++++++++++++-----
+ net/socket.c | 2 +-
+ 3 files changed, 20 insertions(+), 7 deletions(-)
+
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 962acf4a644da9..2b13a41cd99a99 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -2070,7 +2070,7 @@ static inline int sk_rx_queue_get(const struct sock *sk)
+
+ static inline void sk_set_socket(struct sock *sk, struct socket *sock)
+ {
+- sk->sk_socket = sock;
++ WRITE_ONCE(sk->sk_socket, sock);
+ }
+
+ static inline wait_queue_head_t *sk_sleep(struct sock *sk)
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 82add06ca935f1..6281cfed03bb29 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -4953,15 +4953,28 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
+
+ static bool skb_may_tx_timestamp(struct sock *sk, bool tsonly)
+ {
+- bool ret;
++ struct socket *sock;
++ struct file *file;
++ bool ret = false;
+
+ if (likely(READ_ONCE(sysctl_tstamp_allow_data) || tsonly))
+ return true;
+
+- read_lock_bh(&sk->sk_callback_lock);
+- ret = sk->sk_socket && sk->sk_socket->file &&
+- file_ns_capable(sk->sk_socket->file, &init_user_ns, CAP_NET_RAW);
+- read_unlock_bh(&sk->sk_callback_lock);
++ /* The sk pointer remains valid as long as the skb is. The sk_socket and
++ * file pointer may become NULL if the socket is closed. Both structures
++ * (including file->cred) are RCU freed which means they can be accessed
++ * within a RCU read section.
++ */
++ rcu_read_lock();
++ sock = READ_ONCE(sk->sk_socket);
++ if (!sock)
++ goto out;
++ file = READ_ONCE(sock->file);
++ if (!file)
++ goto out;
++ ret = file_ns_capable(file, &init_user_ns, CAP_NET_RAW);
++out:
++ rcu_read_unlock();
+ return ret;
+ }
+
+diff --git a/net/socket.c b/net/socket.c
+index 24dd5f26585aaa..0c87e99c8e69ab 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -663,7 +663,7 @@ static void __sock_release(struct socket *sock, struct inode *inode)
+ iput(SOCK_INODE(sock));
+ return;
+ }
+- sock->file = NULL;
++ WRITE_ONCE(sock->file, NULL);
+ }
+
+ /**
+--
+2.53.0
+
bluetooth-bnep-pin-l2cap-connection-during-netdev-registration.patch
bluetooth-fix-uaf-in-bt_accept_dequeue.patch
bluetooth-l2cap-validate-option-length-before-reading-conf-opt-value.patch
+net-drop-the-lock-in-skb_may_tx_timestamp.patch
--- /dev/null
+From 42fbf615f12a32b47e6e317066a58ad5d10e0e08 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2026 10:49:12 +0800
+Subject: net: Drop the lock in skb_may_tx_timestamp()
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+commit 983512f3a87fd8dc4c94dfa6b596b6e57df5aad7 upstream.
+
+skb_may_tx_timestamp() may acquire sock::sk_callback_lock. The lock must
+not be taken in IRQ context, only softirq is okay. A few drivers receive
+the timestamp via a dedicated interrupt and complete the TX timestamp
+from that handler. This will lead to a deadlock if the lock is already
+write-locked on the same CPU.
+
+Taking the lock can be avoided. The socket (pointed by the skb) will
+remain valid until the skb is released. The ->sk_socket and ->file
+member will be set to NULL once the user closes the socket which may
+happen before the timestamp arrives.
+If we happen to observe the pointer while the socket is closing but
+before the pointer is set to NULL then we may use it because both
+pointer (and the file's cred member) are RCU freed.
+
+Drop the lock. Use READ_ONCE() to obtain the individual pointer. Add a
+matching WRITE_ONCE() where the pointer are cleared.
+
+Link: https://lore.kernel.org/all/20260205145104.iWinkXHv@linutronix.de
+Fixes: b245be1f4db1a ("net-timestamp: no-payload only sysctl")
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260220183858.N4ERjFW6@linutronix.de
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[ adapted sk_set_socket() in include/net/sock.h to fix the conflict from
+ not having commit 5d6b58c932ec ("net: lockless sock_i_ino()") and the
+ additional previous changes required by it.
+ It comes down to just now having the lines of
+ if (sock) {
+ WRITE_ONCE(sk->sk_uid, SOCK_INODE(sock)->i_uid);
+ WRITE_ONCE(sk->sk_ino, SOCK_INODE(sock)->i_ino);
+ }
+ below the changed line. ]
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/sock.h | 2 +-
+ net/core/skbuff.c | 23 ++++++++++++++++++-----
+ net/socket.c | 2 +-
+ 3 files changed, 20 insertions(+), 7 deletions(-)
+
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 1e7096e9bc4842..9fe621f9857401 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -2181,7 +2181,7 @@ static inline int sk_rx_queue_get(const struct sock *sk)
+
+ static inline void sk_set_socket(struct sock *sk, struct socket *sock)
+ {
+- sk->sk_socket = sock;
++ WRITE_ONCE(sk->sk_socket, sock);
+ }
+
+ static inline wait_queue_head_t *sk_sleep(struct sock *sk)
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index f41dd20991c3df..6575a76a312e11 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -4948,15 +4948,28 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
+
+ static bool skb_may_tx_timestamp(struct sock *sk, bool tsonly)
+ {
+- bool ret;
++ struct socket *sock;
++ struct file *file;
++ bool ret = false;
+
+ if (likely(READ_ONCE(sysctl_tstamp_allow_data) || tsonly))
+ return true;
+
+- read_lock_bh(&sk->sk_callback_lock);
+- ret = sk->sk_socket && sk->sk_socket->file &&
+- file_ns_capable(sk->sk_socket->file, &init_user_ns, CAP_NET_RAW);
+- read_unlock_bh(&sk->sk_callback_lock);
++ /* The sk pointer remains valid as long as the skb is. The sk_socket and
++ * file pointer may become NULL if the socket is closed. Both structures
++ * (including file->cred) are RCU freed which means they can be accessed
++ * within a RCU read section.
++ */
++ rcu_read_lock();
++ sock = READ_ONCE(sk->sk_socket);
++ if (!sock)
++ goto out;
++ file = READ_ONCE(sock->file);
++ if (!file)
++ goto out;
++ ret = file_ns_capable(file, &init_user_ns, CAP_NET_RAW);
++out:
++ rcu_read_unlock();
+ return ret;
+ }
+
+diff --git a/net/socket.c b/net/socket.c
+index f2b4cf9b09a322..8bf415a59e55c2 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -666,7 +666,7 @@ static void __sock_release(struct socket *sock, struct inode *inode)
+ iput(SOCK_INODE(sock));
+ return;
+ }
+- sock->file = NULL;
++ WRITE_ONCE(sock->file, NULL);
+ }
+
+ /**
+--
+2.53.0
+
bluetooth-bnep-pin-l2cap-connection-during-netdev-registration.patch
bluetooth-fix-uaf-in-bt_accept_dequeue.patch
bluetooth-l2cap-validate-option-length-before-reading-conf-opt-value.patch
+net-drop-the-lock-in-skb_may_tx_timestamp.patch
--- /dev/null
+From 7d191768fa33fb373e441a59bea2eba7fe5e7c33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 13:15:46 +0530
+Subject: fs/ntfs3: fix missing run load for vcn0 in
+ attr_data_get_block_locked()
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit d7ea8495fd307b58f8867acd81a1b40075b1d3ba ]
+
+When a compressed or sparse attribute has its clusters frame-aligned,
+vcn is rounded down to the frame start using cmask, which can result
+in vcn != vcn0. In this case, vcn and vcn0 may reside in different
+attribute segments.
+
+The code already handles the case where vcn is in a different segment
+by loading its runs before allocation. However, it fails to load runs
+for vcn0 when vcn0 resides in a different segment than vcn. This causes
+run_lookup_entry() to return SPARSE_LCN for vcn0 since its segment was
+never loaded into the in-memory run list, triggering the WARN_ON(1).
+
+Fix this by adding a missing check for vcn0 after the existing vcn
+segment check. If vcn0 falls outside the current segment range
+[svcn, evcn1), find and load the attribute segment containing vcn0
+before performing the run lookup.
+
+The following scenario triggers the bug:
+ attr_data_get_block_locked()
+ vcn = vcn0 & cmask <- vcn != vcn0 after frame alignment
+ load runs for vcn segment <- vcn0 segment not loaded!
+ attr_allocate_clusters() <- allocation succeeds
+ run_lookup_entry(vcn0) <- vcn0 not in run -> SPARSE_LCN
+ WARN_ON(1) <- bug fires here!
+
+Reported-by: syzbot+c1e9aedbd913fadad617@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=c1e9aedbd913fadad617
+Fixes: c380b52f6c57 ("fs/ntfs3: Change new sparse cluster processing")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/attrib.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c
+index 4390c0e4bfb78a..940a8293abe9c0 100644
+--- a/fs/ntfs3/attrib.c
++++ b/fs/ntfs3/attrib.c
+@@ -1044,6 +1044,20 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
+ if (err)
+ goto out;
+ }
++
++ if (vcn0 < svcn || evcn1 <= vcn0) {
++ struct ATTRIB *attr2;
++
++ attr2 = ni_find_attr(ni, attr_b, &le_b, ATTR_DATA, NULL,
++ 0, &vcn0, &mi);
++ if (!attr2) {
++ err = -EINVAL;
++ goto out;
++ }
++ err = attr_load_runs(attr2, ni, run, NULL);
++ if (err)
++ goto out;
++ }
+ }
+
+ if (vcn + to_alloc > asize)
+--
+2.53.0
+
--- /dev/null
+From be8b152f3289edbe3063864f24cabe86e3e30220 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Dec 2025 14:12:18 +0300
+Subject: fs/ntfs3: fsync files by syncing parent inodes
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+[ Upstream commit dcd9d6a47199565d83d61a11bbf91fa2ade4d676 ]
+
+Some xfstests expect fsync() on a file or directory to also persist
+directory metadata up the parent chain. Using generic_file_fsync() is not
+sufficient for ntfs, because parent directories are not explicitly
+written out.
+
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Stable-dep-of: d7ea8495fd30 ("fs/ntfs3: fix missing run load for vcn0 in attr_data_get_block_locked()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/dir.c | 2 +-
+ fs/ntfs3/file.c | 30 ++++++++++++++++++++++++---
+ fs/ntfs3/frecord.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ fs/ntfs3/ntfs_fs.h | 2 ++
+ 4 files changed, 81 insertions(+), 4 deletions(-)
+
+diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c
+index 522ebc14b1fbd0..652b257e8b0782 100644
+--- a/fs/ntfs3/dir.c
++++ b/fs/ntfs3/dir.c
+@@ -625,7 +625,7 @@ const struct file_operations ntfs_dir_operations = {
+ .llseek = generic_file_llseek,
+ .read = generic_read_dir,
+ .iterate_shared = ntfs_readdir,
+- .fsync = generic_file_fsync,
++ .fsync = ntfs_file_fsync,
+ .open = ntfs_file_open,
+ .unlocked_ioctl = ntfs_ioctl,
+ #ifdef CONFIG_COMPAT
+diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
+index b7d87fd57063c5..13f7d8acecf901 100644
+--- a/fs/ntfs3/file.c
++++ b/fs/ntfs3/file.c
+@@ -1399,13 +1399,37 @@ static ssize_t ntfs_file_splice_write(struct pipe_inode_info *pipe,
+ /*
+ * ntfs_file_fsync - file_operations::fsync
+ */
+-static int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
++int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+ {
+ struct inode *inode = file_inode(file);
+- if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
++ struct super_block *sb = inode->i_sb;
++ struct ntfs_sb_info *sbi = sb->s_fs_info;
++ int err, ret;
++
++ if (unlikely(ntfs3_forced_shutdown(sb)))
+ return -EIO;
+
+- return generic_file_fsync(file, start, end, datasync);
++ ret = file_write_and_wait_range(file, start, end);
++ if (ret)
++ return ret;
++
++ ret = write_inode_now(inode, !datasync);
++
++ if (!ret) {
++ ret = ni_write_parents(ntfs_i(inode), !datasync);
++ }
++
++ if (!ret) {
++ ntfs_set_state(sbi, NTFS_DIRTY_CLEAR);
++ ntfs_update_mftmirr(sbi, false);
++ }
++
++ err = sync_blockdev(sb->s_bdev);
++ if (unlikely(err && !ret))
++ ret = err;
++ if (!ret)
++ ret = blkdev_issue_flush(sb->s_bdev);
++ return ret;
+ }
+
+ // clang-format off
+diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
+index bb1feb80d5cb79..b6528d1e4e51fa 100644
+--- a/fs/ntfs3/frecord.c
++++ b/fs/ntfs3/frecord.c
+@@ -3144,6 +3144,57 @@ bool ni_is_dirty(struct inode *inode)
+ return false;
+ }
+
++/*
++ * ni_write_parents
++ *
++ * Helper function for ntfs_file_fsync.
++ */
++int ni_write_parents(struct ntfs_inode *ni, int sync)
++{
++ int err = 0;
++ struct ATTRIB *attr = NULL;
++ struct ATTR_LIST_ENTRY *le = NULL;
++ struct ntfs_sb_info *sbi = ni->mi.sbi;
++ struct super_block *sb = sbi->sb;
++
++ while ((attr = ni_find_attr(ni, attr, &le, ATTR_NAME, NULL, 0, NULL,
++ NULL))) {
++ struct inode *dir;
++ struct ATTR_FILE_NAME *fname;
++
++ fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
++ if (!fname)
++ continue;
++
++ /* Check simple case when parent inode equals current inode. */
++ if (ino_get(&fname->home) == ni->vfs_inode.i_ino) {
++ if (MFT_REC_ROOT != ni->vfs_inode.i_ino) {
++ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
++ err = -EINVAL;
++ }
++ continue;
++ }
++
++ dir = ntfs_iget5(sb, &fname->home, NULL);
++ if (IS_ERR(dir)) {
++ ntfs_inode_warn(
++ &ni->vfs_inode,
++ "failed to open parent directory r=%lx to write",
++ (long)ino_get(&fname->home));
++ continue;
++ }
++
++ if (!is_bad_inode(dir)) {
++ int err2 = write_inode_now(dir, sync);
++ if (!err)
++ err = err2;
++ }
++ iput(dir);
++ }
++
++ return err;
++}
++
+ /*
+ * ni_update_parent
+ *
+diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
+index e860529e1ff996..7375ea351f0ea7 100644
+--- a/fs/ntfs3/ntfs_fs.h
++++ b/fs/ntfs3/ntfs_fs.h
+@@ -507,6 +507,7 @@ int ntfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+ int ntfs_file_open(struct inode *inode, struct file *file);
+ int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ __u64 start, __u64 len);
++int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
+ long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg);
+ long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg);
+ extern const struct inode_operations ntfs_special_inode_operations;
+@@ -588,6 +589,7 @@ int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
+
+ bool ni_is_dirty(struct inode *inode);
+ int ni_set_compress(struct inode *inode, bool compr);
++int ni_write_parents(struct ntfs_inode *ni, int sync);
+
+ /* Globals from fslog.c */
+ bool check_index_header(const struct INDEX_HDR *hdr, size_t bytes);
+--
+2.53.0
+
--- /dev/null
+From 7ac4ccb0ec2cc433a62cbcf4fd27cc7551595bd3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Dec 2025 22:57:46 +0300
+Subject: fs/ntfs3: rename ni_readpage_cmpr into ni_read_folio_cmpr
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+[ Upstream commit 4248f563f0b76f3fb74b2a28ee068bf66fcbbedf ]
+
+The old "readpage" naming is still used in ni_readpage_cmpr(), even though
+the vfs has transitioned to the folio-based read_folio() API.
+
+This patch performs a straightforward renaming of the helper:
+ni_readpage_cmpr() -> ni_read_folio_cmpr().
+
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Stable-dep-of: d7ea8495fd30 ("fs/ntfs3: fix missing run load for vcn0 in attr_data_get_block_locked()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/frecord.c | 8 ++++----
+ fs/ntfs3/inode.c | 2 +-
+ fs/ntfs3/ntfs_fs.h | 2 +-
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
+index 6b04ad5d5f519c..bb1feb80d5cb79 100644
+--- a/fs/ntfs3/frecord.c
++++ b/fs/ntfs3/frecord.c
+@@ -2101,18 +2101,18 @@ static struct page *ntfs_lock_new_page(struct address_space *mapping,
+ }
+
+ /*
+- * ni_readpage_cmpr
++ * ni_read_folio_cmpr
+ *
+ * When decompressing, we typically obtain more than one page per reference.
+ * We inject the additional pages into the page cache.
+ */
+-int ni_readpage_cmpr(struct ntfs_inode *ni, struct folio *folio)
++int ni_read_folio_cmpr(struct ntfs_inode *ni, struct folio *folio)
+ {
+ int err;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct address_space *mapping = folio->mapping;
+- pgoff_t index = folio->index;
+- u64 frame_vbo, vbo = (u64)index << PAGE_SHIFT;
++ pgoff_t index;
++ u64 frame_vbo, vbo = folio_pos(folio);
+ struct page **pages = NULL; /* Array of at most 16 pages. stack? */
+ u8 frame_bits;
+ CLST frame;
+diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
+index b50c9dff327d28..5e240d7fb03709 100644
+--- a/fs/ntfs3/inode.c
++++ b/fs/ntfs3/inode.c
+@@ -736,7 +736,7 @@ static int ntfs_read_folio(struct file *file, struct folio *folio)
+
+ if (is_compressed(ni)) {
+ ni_lock(ni);
+- err = ni_readpage_cmpr(ni, folio);
++ err = ni_read_folio_cmpr(ni, folio);
+ ni_unlock(ni);
+ return err;
+ }
+diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
+index a1040060b081f5..e860529e1ff996 100644
+--- a/fs/ntfs3/ntfs_fs.h
++++ b/fs/ntfs3/ntfs_fs.h
+@@ -567,7 +567,7 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint);
+ #define _ni_write_inode(i, w) ni_write_inode(i, w, __func__)
+ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
+ __u64 vbo, __u64 len);
+-int ni_readpage_cmpr(struct ntfs_inode *ni, struct folio *folio);
++int ni_read_folio_cmpr(struct ntfs_inode *ni, struct folio *folio);
+ int ni_decompress_file(struct ntfs_inode *ni);
+ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
+ u32 pages_per_frame);
+--
+2.53.0
+
--- /dev/null
+From 09042f1e9f6af3f676108988c50eb11058ffcf79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Dec 2025 14:38:10 +0300
+Subject: fs/ntfs3: zero-fill folios beyond i_valid in ntfs_read_folio()
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+[ Upstream commit 356fa248168be90109b66f32a61b8eaedc98424a ]
+
+Handle ntfs_read_folio() early when the folio offset is beyond i_valid
+by zero-filling the folio and marking it uptodate. This avoids needless
+I/O and locking, improves read performance.
+
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Stable-dep-of: d7ea8495fd30 ("fs/ntfs3: fix missing run load for vcn0 in attr_data_get_block_locked()")
+[ sashal: dropped the is_bad_ni() bail-out; 6.12 lacks is_bad_ni()/ni_bad
+ (introduced upstream by 519b078998ce6e) ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/inode.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
+index 5e240d7fb03709..93cf65db77a015 100644
+--- a/fs/ntfs3/inode.c
++++ b/fs/ntfs3/inode.c
+@@ -723,6 +723,14 @@ static int ntfs_read_folio(struct file *file, struct folio *folio)
+ struct address_space *mapping = folio->mapping;
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
++ loff_t vbo = folio_pos(folio);
++
++ if (ni->i_valid <= vbo) {
++ folio_zero_range(folio, 0, folio_size(folio));
++ folio_mark_uptodate(folio);
++ folio_unlock(folio);
++ return 0;
++ }
+
+ if (is_resident(ni)) {
+ ni_lock(ni);
+--
+2.53.0
+
bluetooth-hci_uart-clear-hci_uart_sending-when-write_work-is-canceled.patch
bluetooth-iso-avoid-null-deref-of-conn-in-iso_conn_big_sync.patch
bluetooth-l2cap-validate-option-length-before-reading-conf-opt-value.patch
+fs-ntfs3-rename-ni_readpage_cmpr-into-ni_read_folio_.patch
+fs-ntfs3-fsync-files-by-syncing-parent-inodes.patch
+fs-ntfs3-zero-fill-folios-beyond-i_valid-in-ntfs_rea.patch
+fs-ntfs3-fix-missing-run-load-for-vcn0-in-attr_data_.patch
--- /dev/null
+From eb93aef94f1843be74bb99b8aee48e330fe391e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 13:15:46 +0530
+Subject: fs/ntfs3: fix missing run load for vcn0 in
+ attr_data_get_block_locked()
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit d7ea8495fd307b58f8867acd81a1b40075b1d3ba ]
+
+When a compressed or sparse attribute has its clusters frame-aligned,
+vcn is rounded down to the frame start using cmask, which can result
+in vcn != vcn0. In this case, vcn and vcn0 may reside in different
+attribute segments.
+
+The code already handles the case where vcn is in a different segment
+by loading its runs before allocation. However, it fails to load runs
+for vcn0 when vcn0 resides in a different segment than vcn. This causes
+run_lookup_entry() to return SPARSE_LCN for vcn0 since its segment was
+never loaded into the in-memory run list, triggering the WARN_ON(1).
+
+Fix this by adding a missing check for vcn0 after the existing vcn
+segment check. If vcn0 falls outside the current segment range
+[svcn, evcn1), find and load the attribute segment containing vcn0
+before performing the run lookup.
+
+The following scenario triggers the bug:
+ attr_data_get_block_locked()
+ vcn = vcn0 & cmask <- vcn != vcn0 after frame alignment
+ load runs for vcn segment <- vcn0 segment not loaded!
+ attr_allocate_clusters() <- allocation succeeds
+ run_lookup_entry(vcn0) <- vcn0 not in run -> SPARSE_LCN
+ WARN_ON(1) <- bug fires here!
+
+Reported-by: syzbot+c1e9aedbd913fadad617@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=c1e9aedbd913fadad617
+Fixes: c380b52f6c57 ("fs/ntfs3: Change new sparse cluster processing")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/attrib.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c
+index 5a7675112e7b8a..501f2ec153ab87 100644
+--- a/fs/ntfs3/attrib.c
++++ b/fs/ntfs3/attrib.c
+@@ -1045,6 +1045,20 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
+ if (err)
+ goto out;
+ }
++
++ if (vcn0 < svcn || evcn1 <= vcn0) {
++ struct ATTRIB *attr2;
++
++ attr2 = ni_find_attr(ni, attr_b, &le_b, ATTR_DATA, NULL,
++ 0, &vcn0, &mi);
++ if (!attr2) {
++ err = -EINVAL;
++ goto out;
++ }
++ err = attr_load_runs(attr2, ni, run, NULL);
++ if (err)
++ goto out;
++ }
+ }
+
+ if (vcn + to_alloc > asize)
+--
+2.53.0
+
--- /dev/null
+From 7e31a5cc9975b7f943d6517695a96829942e5102 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Dec 2025 14:12:18 +0300
+Subject: fs/ntfs3: fsync files by syncing parent inodes
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+[ Upstream commit dcd9d6a47199565d83d61a11bbf91fa2ade4d676 ]
+
+Some xfstests expect fsync() on a file or directory to also persist
+directory metadata up the parent chain. Using generic_file_fsync() is not
+sufficient for ntfs, because parent directories are not explicitly
+written out.
+
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Stable-dep-of: d7ea8495fd30 ("fs/ntfs3: fix missing run load for vcn0 in attr_data_get_block_locked()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/dir.c | 2 +-
+ fs/ntfs3/file.c | 30 ++++++++++++++++++++++++---
+ fs/ntfs3/frecord.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ fs/ntfs3/ntfs_fs.h | 2 ++
+ 4 files changed, 81 insertions(+), 4 deletions(-)
+
+diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c
+index 460df046482c73..d41d02372c747b 100644
+--- a/fs/ntfs3/dir.c
++++ b/fs/ntfs3/dir.c
+@@ -624,7 +624,7 @@ const struct file_operations ntfs_dir_operations = {
+ .llseek = generic_file_llseek,
+ .read = generic_read_dir,
+ .iterate_shared = ntfs_readdir,
+- .fsync = generic_file_fsync,
++ .fsync = ntfs_file_fsync,
+ .open = ntfs_file_open,
+ .unlocked_ioctl = ntfs_ioctl,
+ #ifdef CONFIG_COMPAT
+diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
+index 5042eb321eb891..6a19bb04220809 100644
+--- a/fs/ntfs3/file.c
++++ b/fs/ntfs3/file.c
+@@ -1378,13 +1378,37 @@ static ssize_t ntfs_file_splice_write(struct pipe_inode_info *pipe,
+ /*
+ * ntfs_file_fsync - file_operations::fsync
+ */
+-static int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
++int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+ {
+ struct inode *inode = file_inode(file);
+- if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
++ struct super_block *sb = inode->i_sb;
++ struct ntfs_sb_info *sbi = sb->s_fs_info;
++ int err, ret;
++
++ if (unlikely(ntfs3_forced_shutdown(sb)))
+ return -EIO;
+
+- return generic_file_fsync(file, start, end, datasync);
++ ret = file_write_and_wait_range(file, start, end);
++ if (ret)
++ return ret;
++
++ ret = write_inode_now(inode, !datasync);
++
++ if (!ret) {
++ ret = ni_write_parents(ntfs_i(inode), !datasync);
++ }
++
++ if (!ret) {
++ ntfs_set_state(sbi, NTFS_DIRTY_CLEAR);
++ ntfs_update_mftmirr(sbi, false);
++ }
++
++ err = sync_blockdev(sb->s_bdev);
++ if (unlikely(err && !ret))
++ ret = err;
++ if (!ret)
++ blkdev_issue_flush(sb->s_bdev);
++ return ret;
+ }
+
+ // clang-format off
+diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
+index 480f2ed518a783..e904c5da919222 100644
+--- a/fs/ntfs3/frecord.c
++++ b/fs/ntfs3/frecord.c
+@@ -3090,6 +3090,57 @@ bool ni_is_dirty(struct inode *inode)
+ return false;
+ }
+
++/*
++ * ni_write_parents
++ *
++ * Helper function for ntfs_file_fsync.
++ */
++int ni_write_parents(struct ntfs_inode *ni, int sync)
++{
++ int err = 0;
++ struct ATTRIB *attr = NULL;
++ struct ATTR_LIST_ENTRY *le = NULL;
++ struct ntfs_sb_info *sbi = ni->mi.sbi;
++ struct super_block *sb = sbi->sb;
++
++ while ((attr = ni_find_attr(ni, attr, &le, ATTR_NAME, NULL, 0, NULL,
++ NULL))) {
++ struct inode *dir;
++ struct ATTR_FILE_NAME *fname;
++
++ fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
++ if (!fname)
++ continue;
++
++ /* Check simple case when parent inode equals current inode. */
++ if (ino_get(&fname->home) == ni->vfs_inode.i_ino) {
++ if (MFT_REC_ROOT != ni->vfs_inode.i_ino) {
++ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
++ err = -EINVAL;
++ }
++ continue;
++ }
++
++ dir = ntfs_iget5(sb, &fname->home, NULL);
++ if (IS_ERR(dir)) {
++ ntfs_inode_warn(
++ &ni->vfs_inode,
++ "failed to open parent directory r=%lx to write",
++ (long)ino_get(&fname->home));
++ continue;
++ }
++
++ if (!is_bad_inode(dir)) {
++ int err2 = write_inode_now(dir, sync);
++ if (!err)
++ err = err2;
++ }
++ iput(dir);
++ }
++
++ return err;
++}
++
+ /*
+ * ni_update_parent
+ *
+diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
+index a4466e9641f65d..7fb08bff025491 100644
+--- a/fs/ntfs3/ntfs_fs.h
++++ b/fs/ntfs3/ntfs_fs.h
+@@ -510,6 +510,7 @@ int ntfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+ int ntfs_file_open(struct inode *inode, struct file *file);
+ int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ __u64 start, __u64 len);
++int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
+ long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg);
+ long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg);
+ extern const struct inode_operations ntfs_special_inode_operations;
+@@ -587,6 +588,7 @@ int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
+ struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de);
+
+ bool ni_is_dirty(struct inode *inode);
++int ni_write_parents(struct ntfs_inode *ni, int sync);
+
+ /* Globals from fslog.c */
+ bool check_index_header(const struct INDEX_HDR *hdr, size_t bytes);
+--
+2.53.0
+
--- /dev/null
+From 65ec61b5e713220ea5f4d6ad9ca93d672fbce2a4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Dec 2025 22:57:46 +0300
+Subject: fs/ntfs3: rename ni_readpage_cmpr into ni_read_folio_cmpr
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+[ Upstream commit 4248f563f0b76f3fb74b2a28ee068bf66fcbbedf ]
+
+The old "readpage" naming is still used in ni_readpage_cmpr(), even though
+the vfs has transitioned to the folio-based read_folio() API.
+
+This patch performs a straightforward renaming of the helper:
+ni_readpage_cmpr() -> ni_read_folio_cmpr().
+
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Stable-dep-of: d7ea8495fd30 ("fs/ntfs3: fix missing run load for vcn0 in attr_data_get_block_locked()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/frecord.c | 8 ++++----
+ fs/ntfs3/inode.c | 2 +-
+ fs/ntfs3/ntfs_fs.h | 2 +-
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
+index 295f6936a3e588..480f2ed518a783 100644
+--- a/fs/ntfs3/frecord.c
++++ b/fs/ntfs3/frecord.c
+@@ -2046,18 +2046,18 @@ static struct page *ntfs_lock_new_page(struct address_space *mapping,
+ }
+
+ /*
+- * ni_readpage_cmpr
++ * ni_read_folio_cmpr
+ *
+ * When decompressing, we typically obtain more than one page per reference.
+ * We inject the additional pages into the page cache.
+ */
+-int ni_readpage_cmpr(struct ntfs_inode *ni, struct folio *folio)
++int ni_read_folio_cmpr(struct ntfs_inode *ni, struct folio *folio)
+ {
+ int err;
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
+ struct address_space *mapping = folio->mapping;
+- pgoff_t index = folio->index;
+- u64 frame_vbo, vbo = (u64)index << PAGE_SHIFT;
++ pgoff_t index;
++ u64 frame_vbo, vbo = folio_pos(folio);
+ struct page **pages = NULL; /* Array of at most 16 pages. stack? */
+ u8 frame_bits;
+ CLST frame;
+diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
+index 205baa791f998e..0cf2898334f33b 100644
+--- a/fs/ntfs3/inode.c
++++ b/fs/ntfs3/inode.c
+@@ -736,7 +736,7 @@ static int ntfs_read_folio(struct file *file, struct folio *folio)
+
+ if (is_compressed(ni)) {
+ ni_lock(ni);
+- err = ni_readpage_cmpr(ni, folio);
++ err = ni_read_folio_cmpr(ni, folio);
+ ni_unlock(ni);
+ return err;
+ }
+diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
+index 2649fbe16669de..a4466e9641f65d 100644
+--- a/fs/ntfs3/ntfs_fs.h
++++ b/fs/ntfs3/ntfs_fs.h
+@@ -567,7 +567,7 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint);
+ #define _ni_write_inode(i, w) ni_write_inode(i, w, __func__)
+ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
+ __u64 vbo, __u64 len);
+-int ni_readpage_cmpr(struct ntfs_inode *ni, struct folio *folio);
++int ni_read_folio_cmpr(struct ntfs_inode *ni, struct folio *folio);
+ int ni_decompress_file(struct ntfs_inode *ni);
+ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
+ u32 pages_per_frame);
+--
+2.53.0
+
--- /dev/null
+From 8366ca0c493ea4eead2a95b9e3d7747a916368ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Dec 2025 14:38:10 +0300
+Subject: fs/ntfs3: zero-fill folios beyond i_valid in ntfs_read_folio()
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+[ Upstream commit 356fa248168be90109b66f32a61b8eaedc98424a ]
+
+Handle ntfs_read_folio() early when the folio offset is beyond i_valid
+by zero-filling the folio and marking it uptodate. This avoids needless
+I/O and locking, improves read performance.
+
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Stable-dep-of: d7ea8495fd30 ("fs/ntfs3: fix missing run load for vcn0 in attr_data_get_block_locked()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/inode.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
+index 0cf2898334f33b..1b7bb924fc0025 100644
+--- a/fs/ntfs3/inode.c
++++ b/fs/ntfs3/inode.c
+@@ -723,6 +723,19 @@ static int ntfs_read_folio(struct file *file, struct folio *folio)
+ struct address_space *mapping = folio->mapping;
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
++ loff_t vbo = folio_pos(folio);
++
++ if (unlikely(is_bad_ni(ni))) {
++ folio_unlock(folio);
++ return -EIO;
++ }
++
++ if (ni->i_valid <= vbo) {
++ folio_zero_range(folio, 0, folio_size(folio));
++ folio_mark_uptodate(folio);
++ folio_unlock(folio);
++ return 0;
++ }
+
+ if (is_resident(ni)) {
+ ni_lock(ni);
+--
+2.53.0
+
bluetooth-l2cap-cancel-pending_rx_work-before-taking-conn-lock.patch
bluetooth-l2cap-validate-option-length-before-reading-conf-opt-value.patch
iommu-vt-d-fix-race-condition-during-pasid-entry-replacement.patch
+fs-ntfs3-rename-ni_readpage_cmpr-into-ni_read_folio_.patch
+fs-ntfs3-fsync-files-by-syncing-parent-inodes.patch
+fs-ntfs3-zero-fill-folios-beyond-i_valid-in-ntfs_rea.patch
+fs-ntfs3-fix-missing-run-load-for-vcn0-in-attr_data_.patch
--- /dev/null
+From 44554918e9b9e8f0a7f6fa08b1d459a88e6e9597 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2026 13:15:46 +0530
+Subject: fs/ntfs3: fix missing run load for vcn0 in
+ attr_data_get_block_locked()
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit d7ea8495fd307b58f8867acd81a1b40075b1d3ba ]
+
+When a compressed or sparse attribute has its clusters frame-aligned,
+vcn is rounded down to the frame start using cmask, which can result
+in vcn != vcn0. In this case, vcn and vcn0 may reside in different
+attribute segments.
+
+The code already handles the case where vcn is in a different segment
+by loading its runs before allocation. However, it fails to load runs
+for vcn0 when vcn0 resides in a different segment than vcn. This causes
+run_lookup_entry() to return SPARSE_LCN for vcn0 since its segment was
+never loaded into the in-memory run list, triggering the WARN_ON(1).
+
+Fix this by adding a missing check for vcn0 after the existing vcn
+segment check. If vcn0 falls outside the current segment range
+[svcn, evcn1), find and load the attribute segment containing vcn0
+before performing the run lookup.
+
+The following scenario triggers the bug:
+ attr_data_get_block_locked()
+ vcn = vcn0 & cmask <- vcn != vcn0 after frame alignment
+ load runs for vcn segment <- vcn0 segment not loaded!
+ attr_allocate_clusters() <- allocation succeeds
+ run_lookup_entry(vcn0) <- vcn0 not in run -> SPARSE_LCN
+ WARN_ON(1) <- bug fires here!
+
+Reported-by: syzbot+c1e9aedbd913fadad617@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=c1e9aedbd913fadad617
+Fixes: c380b52f6c57 ("fs/ntfs3: Change new sparse cluster processing")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/attrib.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c
+index 8f033e30e0d799..a590c541861332 100644
+--- a/fs/ntfs3/attrib.c
++++ b/fs/ntfs3/attrib.c
+@@ -1045,6 +1045,20 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
+ if (err)
+ goto out;
+ }
++
++ if (vcn0 < svcn || evcn1 <= vcn0) {
++ struct ATTRIB *attr2;
++
++ attr2 = ni_find_attr(ni, attr_b, &le_b, ATTR_DATA, NULL,
++ 0, &vcn0, &mi);
++ if (!attr2) {
++ err = -EINVAL;
++ goto out;
++ }
++ err = attr_load_runs(attr2, ni, run, NULL);
++ if (err)
++ goto out;
++ }
+ }
+
+ if (vcn + to_alloc > asize)
+--
+2.53.0
+
--- /dev/null
+From 12ba1e2a40735c73a43330858e373fcf4c14cad2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Dec 2025 14:12:18 +0300
+Subject: fs/ntfs3: fsync files by syncing parent inodes
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+[ Upstream commit dcd9d6a47199565d83d61a11bbf91fa2ade4d676 ]
+
+Some xfstests expect fsync() on a file or directory to also persist
+directory metadata up the parent chain. Using generic_file_fsync() is not
+sufficient for ntfs, because parent directories are not explicitly
+written out.
+
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Stable-dep-of: d7ea8495fd30 ("fs/ntfs3: fix missing run load for vcn0 in attr_data_get_block_locked()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/dir.c | 2 +-
+ fs/ntfs3/file.c | 38 +++++++++++++++++++++++++++++++++-
+ fs/ntfs3/frecord.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ fs/ntfs3/ntfs_fs.h | 2 ++
+ 4 files changed, 91 insertions(+), 2 deletions(-)
+
+diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c
+index 894fd44164b48a..4bf851273e3324 100644
+--- a/fs/ntfs3/dir.c
++++ b/fs/ntfs3/dir.c
+@@ -623,7 +623,7 @@ const struct file_operations ntfs_dir_operations = {
+ .llseek = generic_file_llseek,
+ .read = generic_read_dir,
+ .iterate_shared = ntfs_readdir,
+- .fsync = generic_file_fsync,
++ .fsync = ntfs_file_fsync,
+ .open = ntfs_file_open,
+ };
+ // clang-format on
+diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
+index 212737a816d7af..89e35825c5c49d 100644
+--- a/fs/ntfs3/file.c
++++ b/fs/ntfs3/file.c
+@@ -1224,6 +1224,42 @@ int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ return err;
+ }
+
++/*
++ * ntfs_file_fsync - file_operations::fsync
++ */
++int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
++{
++ struct inode *inode = file_inode(file);
++ struct super_block *sb = inode->i_sb;
++ struct ntfs_sb_info *sbi = sb->s_fs_info;
++ int err, ret;
++
++ if (unlikely(ntfs3_forced_shutdown(sb)))
++ return -EIO;
++
++ ret = file_write_and_wait_range(file, start, end);
++ if (ret)
++ return ret;
++
++ ret = write_inode_now(inode, !datasync);
++
++ if (!ret) {
++ ret = ni_write_parents(ntfs_i(inode), !datasync);
++ }
++
++ if (!ret) {
++ ntfs_set_state(sbi, NTFS_DIRTY_CLEAR);
++ ntfs_update_mftmirr(sbi, false);
++ }
++
++ err = sync_blockdev(sb->s_bdev);
++ if (unlikely(err && !ret))
++ ret = err;
++ if (!ret)
++ ret = blkdev_issue_flush(sb->s_bdev);
++ return ret;
++}
++
+ // clang-format off
+ const struct inode_operations ntfs_file_inode_operations = {
+ .getattr = ntfs_getattr,
+@@ -1245,7 +1281,7 @@ const struct file_operations ntfs_file_operations = {
+ .splice_read = ntfs_file_splice_read,
+ .mmap = ntfs_file_mmap,
+ .open = ntfs_file_open,
+- .fsync = generic_file_fsync,
++ .fsync = ntfs_file_fsync,
+ .splice_write = iter_file_splice_write,
+ .fallocate = ntfs_fallocate,
+ .release = ntfs_file_release,
+diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
+index 06b1d82b599759..c265710d25b425 100644
+--- a/fs/ntfs3/frecord.c
++++ b/fs/ntfs3/frecord.c
+@@ -3145,6 +3145,57 @@ bool ni_is_dirty(struct inode *inode)
+ return false;
+ }
+
++/*
++ * ni_write_parents
++ *
++ * Helper function for ntfs_file_fsync.
++ */
++int ni_write_parents(struct ntfs_inode *ni, int sync)
++{
++ int err = 0;
++ struct ATTRIB *attr = NULL;
++ struct ATTR_LIST_ENTRY *le = NULL;
++ struct ntfs_sb_info *sbi = ni->mi.sbi;
++ struct super_block *sb = sbi->sb;
++
++ while ((attr = ni_find_attr(ni, attr, &le, ATTR_NAME, NULL, 0, NULL,
++ NULL))) {
++ struct inode *dir;
++ struct ATTR_FILE_NAME *fname;
++
++ fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
++ if (!fname)
++ continue;
++
++ /* Check simple case when parent inode equals current inode. */
++ if (ino_get(&fname->home) == ni->vfs_inode.i_ino) {
++ if (MFT_REC_ROOT != ni->vfs_inode.i_ino) {
++ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
++ err = -EINVAL;
++ }
++ continue;
++ }
++
++ dir = ntfs_iget5(sb, &fname->home, NULL);
++ if (IS_ERR(dir)) {
++ ntfs_inode_warn(
++ &ni->vfs_inode,
++ "failed to open parent directory r=%lx to write",
++ (long)ino_get(&fname->home));
++ continue;
++ }
++
++ if (!is_bad_inode(dir)) {
++ int err2 = write_inode_now(dir, sync);
++ if (!err)
++ err = err2;
++ }
++ iput(dir);
++ }
++
++ return err;
++}
++
+ /*
+ * ni_update_parent
+ *
+diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
+index 31f57ee9a1a9b4..e534095078e89f 100644
+--- a/fs/ntfs3/ntfs_fs.h
++++ b/fs/ntfs3/ntfs_fs.h
+@@ -503,6 +503,7 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+ int ntfs_file_open(struct inode *inode, struct file *file);
+ int ntfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ __u64 start, __u64 len);
++int ntfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
+ extern const struct inode_operations ntfs_special_inode_operations;
+ extern const struct inode_operations ntfs_file_inode_operations;
+ extern const struct file_operations ntfs_file_operations;
+@@ -580,6 +581,7 @@ int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
+ struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de);
+
+ bool ni_is_dirty(struct inode *inode);
++int ni_write_parents(struct ntfs_inode *ni, int sync);
+
+ /* Globals from fslog.c */
+ bool check_index_header(const struct INDEX_HDR *hdr, size_t bytes);
+--
+2.53.0
+
--- /dev/null
+From 3ba2267f3e6d4e7a5ea3d8fd921e60505a764bd4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Dec 2025 14:33:19 +0300
+Subject: fs/ntfs3: handle attr_set_size() errors when truncating files
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+[ Upstream commit 576248a34b927e93b2fd3fff7df735ba73ad7d01 ]
+
+If attr_set_size() fails while truncating down, the error is silently
+ignored and the inode may be left in an inconsistent state.
+
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Stable-dep-of: d7ea8495fd30 ("fs/ntfs3: fix missing run load for vcn0 in attr_data_get_block_locked()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/file.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
+index 89e35825c5c49d..3eee810c69e2f7 100644
+--- a/fs/ntfs3/file.c
++++ b/fs/ntfs3/file.c
+@@ -371,8 +371,8 @@ static int ntfs_truncate(struct inode *inode, loff_t new_size)
+ {
+ struct super_block *sb = inode->i_sb;
+ struct ntfs_inode *ni = ntfs_i(inode);
+- int err, dirty = 0;
+ u64 new_valid;
++ int err;
+
+ if (!S_ISREG(inode->i_mode))
+ return 0;
+@@ -388,7 +388,6 @@ static int ntfs_truncate(struct inode *inode, loff_t new_size)
+ }
+
+ new_valid = ntfs_up_block(sb, min_t(u64, ni->i_valid, new_size));
+-
+ truncate_setsize(inode, new_size);
+
+ ni_lock(ni);
+@@ -402,20 +401,19 @@ static int ntfs_truncate(struct inode *inode, loff_t new_size)
+ ni->i_valid = new_valid;
+
+ ni_unlock(ni);
++ if (unlikely(err))
++ return err;
+
+ ni->std_fa |= FILE_ATTRIBUTE_ARCHIVE;
+ inode->i_mtime = inode_set_ctime_current(inode);
+ if (!IS_DIRSYNC(inode)) {
+- dirty = 1;
++ mark_inode_dirty(inode);
+ } else {
+ err = ntfs_sync_inode(inode);
+ if (err)
+ return err;
+ }
+
+- if (dirty)
+- mark_inode_dirty(inode);
+-
+ /*ntfs_flush_inodes(inode->i_sb, inode, NULL);*/
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 2074da1280581eb43546d1b920dd62464de87c03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Dec 2025 14:38:10 +0300
+Subject: fs/ntfs3: zero-fill folios beyond i_valid in ntfs_read_folio()
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+[ Upstream commit 356fa248168be90109b66f32a61b8eaedc98424a ]
+
+Handle ntfs_read_folio() early when the folio offset is beyond i_valid
+by zero-filling the folio and marking it uptodate. This avoids needless
+I/O and locking, improves read performance.
+
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Stable-dep-of: d7ea8495fd30 ("fs/ntfs3: fix missing run load for vcn0 in attr_data_get_block_locked()")
+[ sashal: dropped the is_bad_ni() guard, 6.6 lacks 519b078998ce6e
+ ("fs/ntfs3: Exclude call make_bad_inode for live nodes.") which
+ introduces that helper; pre-patch 6.6 had no such check either ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ntfs3/inode.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
+index 787e15ba0ca406..fff604cd952793 100644
+--- a/fs/ntfs3/inode.c
++++ b/fs/ntfs3/inode.c
+@@ -715,6 +715,14 @@ static int ntfs_read_folio(struct file *file, struct folio *folio)
+ struct address_space *mapping = page->mapping;
+ struct inode *inode = mapping->host;
+ struct ntfs_inode *ni = ntfs_i(inode);
++ loff_t vbo = folio_pos(folio);
++
++ if (ni->i_valid <= vbo) {
++ folio_zero_range(folio, 0, folio_size(folio));
++ folio_mark_uptodate(folio);
++ folio_unlock(folio);
++ return 0;
++ }
+
+ if (is_resident(ni)) {
+ ni_lock(ni);
+--
+2.53.0
+
bluetooth-btnxpuart-fix-out-of-bounds-firmware-read-in-nxp_recv_fw_req_v3.patch
bluetooth-fix-uaf-in-bt_accept_dequeue.patch
bluetooth-l2cap-validate-option-length-before-reading-conf-opt-value.patch
+fs-ntfs3-fsync-files-by-syncing-parent-inodes.patch
+fs-ntfs3-handle-attr_set_size-errors-when-truncating.patch
+fs-ntfs3-zero-fill-folios-beyond-i_valid-in-ntfs_rea.patch
+fs-ntfs3-fix-missing-run-load-for-vcn0-in-attr_data_.patch