--- /dev/null
+From 32c05d58b1efaf02576efd954028712c1c6d9266 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Jan 2025 14:39:46 +0200
+Subject: IB/mlx5: Set and get correct qp_num for a DCT QP
+
+From: Mark Zhang <markzhang@nvidia.com>
+
+[ Upstream commit 12d044770e12c4205fa69535b4fa8a9981fea98f ]
+
+When a DCT QP is created on an active lag, it's dctc.port is assigned
+in a round-robin way, which is from 1 to dev->lag_port. In this case
+when querying this QP, we may get qp_attr.port_num > 2.
+Fix this by setting qp->port when modifying a DCT QP, and read port_num
+from qp->port instead of dctc.port when querying it.
+
+Fixes: 7c4b1ab9f167 ("IB/mlx5: Add DCT RoCE LAG support")
+Signed-off-by: Mark Zhang <markzhang@nvidia.com>
+Reviewed-by: Maher Sanalla <msanalla@nvidia.com>
+Link: https://patch.msgid.link/94c76bf0adbea997f87ffa27674e0a7118ad92a9.1737290358.git.leon@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/mlx5/qp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
+index d2b4db783b254..d58ed4a09cd93 100644
+--- a/drivers/infiniband/hw/mlx5/qp.c
++++ b/drivers/infiniband/hw/mlx5/qp.c
+@@ -4461,6 +4461,8 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+
+ set_id = mlx5_ib_get_counters_id(dev, attr->port_num - 1);
+ MLX5_SET(dctc, dctc, counter_set_id, set_id);
++
++ qp->port = attr->port_num;
+ } else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
+ struct mlx5_ib_modify_qp_resp resp = {};
+ u32 out[MLX5_ST_SZ_DW(create_dct_out)] = {};
+@@ -4949,7 +4951,7 @@ static int mlx5_ib_dct_query_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *mqp,
+ }
+
+ if (qp_attr_mask & IB_QP_PORT)
+- qp_attr->port_num = MLX5_GET(dctc, dctc, port);
++ qp_attr->port_num = mqp->port;
+ if (qp_attr_mask & IB_QP_MIN_RNR_TIMER)
+ qp_attr->min_rnr_timer = MLX5_GET(dctc, dctc, min_rnr_nak);
+ if (qp_attr_mask & IB_QP_AV) {
+--
+2.39.5
+
--- /dev/null
+From 8dec2b20fa70493d01edc457f87aab3b9f18aaca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Feb 2025 00:51:48 +0300
+Subject: ovl: fix UAF in ovl_dentry_update_reval by moving dput() in
+ ovl_link_up
+
+From: Vasiliy Kovalev <kovalev@altlinux.org>
+
+[ Upstream commit c84e125fff2615b4d9c259e762596134eddd2f27 ]
+
+The issue was caused by dput(upper) being called before
+ovl_dentry_update_reval(), while upper->d_flags was still
+accessed in ovl_dentry_remote().
+
+Move dput(upper) after its last use to prevent use-after-free.
+
+BUG: KASAN: slab-use-after-free in ovl_dentry_remote fs/overlayfs/util.c:162 [inline]
+BUG: KASAN: slab-use-after-free in ovl_dentry_update_reval+0xd2/0xf0 fs/overlayfs/util.c:167
+
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:88 [inline]
+ dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:114
+ print_address_description mm/kasan/report.c:377 [inline]
+ print_report+0xc3/0x620 mm/kasan/report.c:488
+ kasan_report+0xd9/0x110 mm/kasan/report.c:601
+ ovl_dentry_remote fs/overlayfs/util.c:162 [inline]
+ ovl_dentry_update_reval+0xd2/0xf0 fs/overlayfs/util.c:167
+ ovl_link_up fs/overlayfs/copy_up.c:610 [inline]
+ ovl_copy_up_one+0x2105/0x3490 fs/overlayfs/copy_up.c:1170
+ ovl_copy_up_flags+0x18d/0x200 fs/overlayfs/copy_up.c:1223
+ ovl_rename+0x39e/0x18c0 fs/overlayfs/dir.c:1136
+ vfs_rename+0xf84/0x20a0 fs/namei.c:4893
+...
+ </TASK>
+
+Fixes: b07d5cc93e1b ("ovl: update of dentry revalidate flags after copy up")
+Reported-by: syzbot+316db8a1191938280eb6@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=316db8a1191938280eb6
+Signed-off-by: Vasiliy Kovalev <kovalev@altlinux.org>
+Link: https://lore.kernel.org/r/20250214215148.761147-1-kovalev@altlinux.org
+Reviewed-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/copy_up.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index 205238c73dbc5..5fc32483afed8 100644
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -537,7 +537,6 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
+ err = PTR_ERR(upper);
+ if (!IS_ERR(upper)) {
+ err = ovl_do_link(ofs, ovl_dentry_upper(c->dentry), udir, upper);
+- dput(upper);
+
+ if (!err) {
+ /* Restore timestamps on parent (best effort) */
+@@ -545,6 +544,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
+ ovl_dentry_set_upper_alias(c->dentry);
+ ovl_dentry_update_reval(c->dentry, upper);
+ }
++ dput(upper);
+ }
+ inode_unlock(udir);
+ if (err)
+--
+2.39.5
+
--- /dev/null
+From 37979f156d697a7a89ee79d406457e512e5f4ba9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Apr 2022 12:51:43 +0200
+Subject: ovl: pass ofs to creation operations
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit 576bb263450bbba6601a9f528d0cf601d97a13e6 ]
+
+Pass down struct ovl_fs to all creation helpers so we can ultimately
+retrieve the relevant upper mount and take the mount's idmapping into
+account when creating new filesystem objects. This is needed to support
+idmapped base layers with overlay.
+
+Cc: <linux-unionfs@vger.kernel.org>
+Tested-by: Giuseppe Scrivano <gscrivan@redhat.com>
+Reviewed-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Stable-dep-of: c84e125fff26 ("ovl: fix UAF in ovl_dentry_update_reval by moving dput() in ovl_link_up")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/copy_up.c | 21 +++++-----
+ fs/overlayfs/dir.c | 85 +++++++++++++++++++++-------------------
+ fs/overlayfs/overlayfs.h | 54 +++++++++++++++----------
+ fs/overlayfs/readdir.c | 28 +++++++------
+ fs/overlayfs/super.c | 28 +++++++------
+ fs/overlayfs/util.c | 2 +-
+ 6 files changed, 121 insertions(+), 97 deletions(-)
+
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index 80e7ae8152fdd..205238c73dbc5 100644
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -474,7 +474,7 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin,
+ if (err)
+ return err;
+
+- temp = ovl_create_temp(indexdir, OVL_CATTR(S_IFDIR | 0));
++ temp = ovl_create_temp(ofs, indexdir, OVL_CATTR(S_IFDIR | 0));
+ err = PTR_ERR(temp);
+ if (IS_ERR(temp))
+ goto free_name;
+@@ -487,12 +487,12 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin,
+ if (IS_ERR(index)) {
+ err = PTR_ERR(index);
+ } else {
+- err = ovl_do_rename(dir, temp, dir, index, 0);
++ err = ovl_do_rename(ofs, dir, temp, dir, index, 0);
+ dput(index);
+ }
+ out:
+ if (err)
+- ovl_cleanup(dir, temp);
++ ovl_cleanup(ofs, dir, temp);
+ dput(temp);
+ free_name:
+ kfree(name.name);
+@@ -519,6 +519,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
+ int err;
+ struct dentry *upper;
+ struct dentry *upperdir = ovl_dentry_upper(c->parent);
++ struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb);
+ struct inode *udir = d_inode(upperdir);
+
+ /* Mark parent "impure" because it may now contain non-pure upper */
+@@ -535,7 +536,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
+ c->dentry->d_name.len);
+ err = PTR_ERR(upper);
+ if (!IS_ERR(upper)) {
+- err = ovl_do_link(ovl_dentry_upper(c->dentry), udir, upper);
++ err = ovl_do_link(ofs, ovl_dentry_upper(c->dentry), udir, upper);
+ dput(upper);
+
+ if (!err) {
+@@ -658,6 +659,7 @@ static void ovl_revert_cu_creds(struct ovl_cu_creds *cc)
+ */
+ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
+ {
++ struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb);
+ struct inode *inode;
+ struct inode *udir = d_inode(c->destdir), *wdir = d_inode(c->workdir);
+ struct dentry *temp, *upper;
+@@ -679,7 +681,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
+ if (err)
+ goto unlock;
+
+- temp = ovl_create_temp(c->workdir, &cattr);
++ temp = ovl_create_temp(ofs, c->workdir, &cattr);
+ ovl_revert_cu_creds(&cc);
+
+ err = PTR_ERR(temp);
+@@ -701,7 +703,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
+ if (IS_ERR(upper))
+ goto cleanup;
+
+- err = ovl_do_rename(wdir, temp, udir, upper, 0);
++ err = ovl_do_rename(ofs, wdir, temp, udir, upper, 0);
+ dput(upper);
+ if (err)
+ goto cleanup;
+@@ -718,7 +720,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
+ return err;
+
+ cleanup:
+- ovl_cleanup(wdir, temp);
++ ovl_cleanup(ofs, wdir, temp);
+ dput(temp);
+ goto unlock;
+ }
+@@ -726,6 +728,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c)
+ /* Copyup using O_TMPFILE which does not require cross dir locking */
+ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
+ {
++ struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb);
+ struct inode *udir = d_inode(c->destdir);
+ struct dentry *temp, *upper;
+ struct ovl_cu_creds cc;
+@@ -735,7 +738,7 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
+ if (err)
+ return err;
+
+- temp = ovl_do_tmpfile(c->workdir, c->stat.mode);
++ temp = ovl_do_tmpfile(ofs, c->workdir, c->stat.mode);
+ ovl_revert_cu_creds(&cc);
+
+ if (IS_ERR(temp))
+@@ -750,7 +753,7 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
+ upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len);
+ err = PTR_ERR(upper);
+ if (!IS_ERR(upper)) {
+- err = ovl_do_link(temp, udir, upper);
++ err = ovl_do_link(ofs, temp, udir, upper);
+ dput(upper);
+ }
+ inode_unlock(udir);
+diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
+index 5e9005a0afaad..584b78f0bfa1a 100644
+--- a/fs/overlayfs/dir.c
++++ b/fs/overlayfs/dir.c
+@@ -23,15 +23,15 @@ MODULE_PARM_DESC(redirect_max,
+
+ static int ovl_set_redirect(struct dentry *dentry, bool samedir);
+
+-int ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
++int ovl_cleanup(struct ovl_fs *ofs, struct inode *wdir, struct dentry *wdentry)
+ {
+ int err;
+
+ dget(wdentry);
+ if (d_is_dir(wdentry))
+- err = ovl_do_rmdir(wdir, wdentry);
++ err = ovl_do_rmdir(ofs, wdir, wdentry);
+ else
+- err = ovl_do_unlink(wdir, wdentry);
++ err = ovl_do_unlink(ofs, wdir, wdentry);
+ dput(wdentry);
+
+ if (err) {
+@@ -42,7 +42,7 @@ int ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
+ return err;
+ }
+
+-struct dentry *ovl_lookup_temp(struct dentry *workdir)
++struct dentry *ovl_lookup_temp(struct ovl_fs *ofs, struct dentry *workdir)
+ {
+ struct dentry *temp;
+ char name[20];
+@@ -70,11 +70,11 @@ static struct dentry *ovl_whiteout(struct ovl_fs *ofs)
+ struct inode *wdir = workdir->d_inode;
+
+ if (!ofs->whiteout) {
+- whiteout = ovl_lookup_temp(workdir);
++ whiteout = ovl_lookup_temp(ofs, workdir);
+ if (IS_ERR(whiteout))
+ goto out;
+
+- err = ovl_do_whiteout(wdir, whiteout);
++ err = ovl_do_whiteout(ofs, wdir, whiteout);
+ if (err) {
+ dput(whiteout);
+ whiteout = ERR_PTR(err);
+@@ -84,11 +84,11 @@ static struct dentry *ovl_whiteout(struct ovl_fs *ofs)
+ }
+
+ if (ofs->share_whiteout) {
+- whiteout = ovl_lookup_temp(workdir);
++ whiteout = ovl_lookup_temp(ofs, workdir);
+ if (IS_ERR(whiteout))
+ goto out;
+
+- err = ovl_do_link(ofs->whiteout, wdir, whiteout);
++ err = ovl_do_link(ofs, ofs->whiteout, wdir, whiteout);
+ if (!err)
+ goto out;
+
+@@ -122,27 +122,28 @@ int ovl_cleanup_and_whiteout(struct ovl_fs *ofs, struct inode *dir,
+ if (d_is_dir(dentry))
+ flags = RENAME_EXCHANGE;
+
+- err = ovl_do_rename(wdir, whiteout, dir, dentry, flags);
++ err = ovl_do_rename(ofs, wdir, whiteout, dir, dentry, flags);
+ if (err)
+ goto kill_whiteout;
+ if (flags)
+- ovl_cleanup(wdir, dentry);
++ ovl_cleanup(ofs, wdir, dentry);
+
+ out:
+ dput(whiteout);
+ return err;
+
+ kill_whiteout:
+- ovl_cleanup(wdir, whiteout);
++ ovl_cleanup(ofs, wdir, whiteout);
+ goto out;
+ }
+
+-int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode)
++int ovl_mkdir_real(struct ovl_fs *ofs, struct inode *dir,
++ struct dentry **newdentry, umode_t mode)
+ {
+ int err;
+ struct dentry *d, *dentry = *newdentry;
+
+- err = ovl_do_mkdir(dir, dentry, mode);
++ err = ovl_do_mkdir(ofs, dir, dentry, mode);
+ if (err)
+ return err;
+
+@@ -167,8 +168,8 @@ int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode)
+ return 0;
+ }
+
+-struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
+- struct ovl_cattr *attr)
++struct dentry *ovl_create_real(struct ovl_fs *ofs, struct inode *dir,
++ struct dentry *newdentry, struct ovl_cattr *attr)
+ {
+ int err;
+
+@@ -180,28 +181,28 @@ struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
+ goto out;
+
+ if (attr->hardlink) {
+- err = ovl_do_link(attr->hardlink, dir, newdentry);
++ err = ovl_do_link(ofs, attr->hardlink, dir, newdentry);
+ } else {
+ switch (attr->mode & S_IFMT) {
+ case S_IFREG:
+- err = ovl_do_create(dir, newdentry, attr->mode);
++ err = ovl_do_create(ofs, dir, newdentry, attr->mode);
+ break;
+
+ case S_IFDIR:
+ /* mkdir is special... */
+- err = ovl_mkdir_real(dir, &newdentry, attr->mode);
++ err = ovl_mkdir_real(ofs, dir, &newdentry, attr->mode);
+ break;
+
+ case S_IFCHR:
+ case S_IFBLK:
+ case S_IFIFO:
+ case S_IFSOCK:
+- err = ovl_do_mknod(dir, newdentry, attr->mode,
++ err = ovl_do_mknod(ofs, dir, newdentry, attr->mode,
+ attr->rdev);
+ break;
+
+ case S_IFLNK:
+- err = ovl_do_symlink(dir, newdentry, attr->link);
++ err = ovl_do_symlink(ofs, dir, newdentry, attr->link);
+ break;
+
+ default:
+@@ -223,10 +224,11 @@ struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
+ return newdentry;
+ }
+
+-struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr)
++struct dentry *ovl_create_temp(struct ovl_fs *ofs, struct dentry *workdir,
++ struct ovl_cattr *attr)
+ {
+- return ovl_create_real(d_inode(workdir), ovl_lookup_temp(workdir),
+- attr);
++ return ovl_create_real(ofs, d_inode(workdir),
++ ovl_lookup_temp(ofs, workdir), attr);
+ }
+
+ static int ovl_set_opaque_xerr(struct dentry *dentry, struct dentry *upper,
+@@ -329,7 +331,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
+ attr->mode &= ~current_umask();
+
+ inode_lock_nested(udir, I_MUTEX_PARENT);
+- newdentry = ovl_create_real(udir,
++ newdentry = ovl_create_real(ofs, udir,
+ lookup_one_len(dentry->d_name.name,
+ upperdir,
+ dentry->d_name.len),
+@@ -352,7 +354,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
+ return err;
+
+ out_cleanup:
+- ovl_cleanup(udir, newdentry);
++ ovl_cleanup(ofs, udir, newdentry);
+ dput(newdentry);
+ goto out_unlock;
+ }
+@@ -360,6 +362,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
+ static struct dentry *ovl_clear_empty(struct dentry *dentry,
+ struct list_head *list)
+ {
++ struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
+ struct dentry *workdir = ovl_workdir(dentry);
+ struct inode *wdir = workdir->d_inode;
+ struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
+@@ -390,7 +393,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
+ if (upper->d_parent->d_inode != udir)
+ goto out_unlock;
+
+- opaquedir = ovl_create_temp(workdir, OVL_CATTR(stat.mode));
++ opaquedir = ovl_create_temp(ofs, workdir, OVL_CATTR(stat.mode));
+ err = PTR_ERR(opaquedir);
+ if (IS_ERR(opaquedir))
+ goto out_unlock;
+@@ -409,12 +412,12 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
+ if (err)
+ goto out_cleanup;
+
+- err = ovl_do_rename(wdir, opaquedir, udir, upper, RENAME_EXCHANGE);
++ err = ovl_do_rename(ofs, wdir, opaquedir, udir, upper, RENAME_EXCHANGE);
+ if (err)
+ goto out_cleanup;
+
+- ovl_cleanup_whiteouts(upper, list);
+- ovl_cleanup(wdir, upper);
++ ovl_cleanup_whiteouts(ofs, upper, list);
++ ovl_cleanup(ofs, wdir, upper);
+ unlock_rename(workdir, upperdir);
+
+ /* dentry's upper doesn't match now, get rid of it */
+@@ -423,7 +426,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
+ return opaquedir;
+
+ out_cleanup:
+- ovl_cleanup(wdir, opaquedir);
++ ovl_cleanup(ofs, wdir, opaquedir);
+ dput(opaquedir);
+ out_unlock:
+ unlock_rename(workdir, upperdir);
+@@ -494,7 +497,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
+ if (d_is_negative(upper) || !IS_WHITEOUT(d_inode(upper)))
+ goto out_dput;
+
+- newdentry = ovl_create_temp(workdir, cattr);
++ newdentry = ovl_create_temp(ofs, workdir, cattr);
+ err = PTR_ERR(newdentry);
+ if (IS_ERR(newdentry))
+ goto out_dput;
+@@ -532,20 +535,20 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
+ if (err)
+ goto out_cleanup;
+
+- err = ovl_do_rename(wdir, newdentry, udir, upper,
++ err = ovl_do_rename(ofs, wdir, newdentry, udir, upper,
+ RENAME_EXCHANGE);
+ if (err)
+ goto out_cleanup;
+
+- ovl_cleanup(wdir, upper);
++ ovl_cleanup(ofs, wdir, upper);
+ } else {
+- err = ovl_do_rename(wdir, newdentry, udir, upper, 0);
++ err = ovl_do_rename(ofs, wdir, newdentry, udir, upper, 0);
+ if (err)
+ goto out_cleanup;
+ }
+ err = ovl_instantiate(dentry, inode, newdentry, hardlink);
+ if (err) {
+- ovl_cleanup(udir, newdentry);
++ ovl_cleanup(ofs, udir, newdentry);
+ dput(newdentry);
+ }
+ out_dput:
+@@ -560,7 +563,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
+ return err;
+
+ out_cleanup:
+- ovl_cleanup(wdir, newdentry);
++ ovl_cleanup(ofs, wdir, newdentry);
+ dput(newdentry);
+ goto out_dput;
+ }
+@@ -814,6 +817,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry,
+ static int ovl_remove_upper(struct dentry *dentry, bool is_dir,
+ struct list_head *list)
+ {
++ struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
+ struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
+ struct inode *dir = upperdir->d_inode;
+ struct dentry *upper;
+@@ -840,9 +844,9 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir,
+ goto out_dput_upper;
+
+ if (is_dir)
+- err = vfs_rmdir(&init_user_ns, dir, upper);
++ err = ovl_do_rmdir(ofs, dir, upper);
+ else
+- err = vfs_unlink(&init_user_ns, dir, upper, NULL);
++ err = ovl_do_unlink(ofs, dir, upper);
+ ovl_dir_modified(dentry->d_parent, ovl_type_origin(dentry));
+
+ /*
+@@ -1107,6 +1111,7 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir,
+ bool samedir = olddir == newdir;
+ struct dentry *opaquedir = NULL;
+ const struct cred *old_cred = NULL;
++ struct ovl_fs *ofs = OVL_FS(old->d_sb);
+ LIST_HEAD(list);
+
+ err = -EINVAL;
+@@ -1263,13 +1268,13 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir,
+ if (err)
+ goto out_dput;
+
+- err = ovl_do_rename(old_upperdir->d_inode, olddentry,
++ err = ovl_do_rename(ofs, old_upperdir->d_inode, olddentry,
+ new_upperdir->d_inode, newdentry, flags);
+ if (err)
+ goto out_dput;
+
+ if (cleanup_whiteout)
+- ovl_cleanup(old_upperdir->d_inode, newdentry);
++ ovl_cleanup(ofs, old_upperdir->d_inode, newdentry);
+
+ if (overwrite && d_inode(new)) {
+ if (new_is_dir)
+diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
+index 3f4655b9c71ca..43b211cf437cc 100644
+--- a/fs/overlayfs/overlayfs.h
++++ b/fs/overlayfs/overlayfs.h
+@@ -122,7 +122,8 @@ static inline const char *ovl_xattr(struct ovl_fs *ofs, enum ovl_xattr ox)
+ return ovl_xattr_table[ox][ofs->config.userxattr];
+ }
+
+-static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry)
++static inline int ovl_do_rmdir(struct ovl_fs *ofs,
++ struct inode *dir, struct dentry *dentry)
+ {
+ int err = vfs_rmdir(&init_user_ns, dir, dentry);
+
+@@ -130,7 +131,8 @@ static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry)
+ return err;
+ }
+
+-static inline int ovl_do_unlink(struct inode *dir, struct dentry *dentry)
++static inline int ovl_do_unlink(struct ovl_fs *ofs, struct inode *dir,
++ struct dentry *dentry)
+ {
+ int err = vfs_unlink(&init_user_ns, dir, dentry, NULL);
+
+@@ -138,8 +140,8 @@ static inline int ovl_do_unlink(struct inode *dir, struct dentry *dentry)
+ return err;
+ }
+
+-static inline int ovl_do_link(struct dentry *old_dentry, struct inode *dir,
+- struct dentry *new_dentry)
++static inline int ovl_do_link(struct ovl_fs *ofs, struct dentry *old_dentry,
++ struct inode *dir, struct dentry *new_dentry)
+ {
+ int err = vfs_link(old_dentry, &init_user_ns, dir, new_dentry, NULL);
+
+@@ -147,7 +149,8 @@ static inline int ovl_do_link(struct dentry *old_dentry, struct inode *dir,
+ return err;
+ }
+
+-static inline int ovl_do_create(struct inode *dir, struct dentry *dentry,
++static inline int ovl_do_create(struct ovl_fs *ofs,
++ struct inode *dir, struct dentry *dentry,
+ umode_t mode)
+ {
+ int err = vfs_create(&init_user_ns, dir, dentry, mode, true);
+@@ -156,7 +159,8 @@ static inline int ovl_do_create(struct inode *dir, struct dentry *dentry,
+ return err;
+ }
+
+-static inline int ovl_do_mkdir(struct inode *dir, struct dentry *dentry,
++static inline int ovl_do_mkdir(struct ovl_fs *ofs,
++ struct inode *dir, struct dentry *dentry,
+ umode_t mode)
+ {
+ int err = vfs_mkdir(&init_user_ns, dir, dentry, mode);
+@@ -164,7 +168,8 @@ static inline int ovl_do_mkdir(struct inode *dir, struct dentry *dentry,
+ return err;
+ }
+
+-static inline int ovl_do_mknod(struct inode *dir, struct dentry *dentry,
++static inline int ovl_do_mknod(struct ovl_fs *ofs,
++ struct inode *dir, struct dentry *dentry,
+ umode_t mode, dev_t dev)
+ {
+ int err = vfs_mknod(&init_user_ns, dir, dentry, mode, dev);
+@@ -173,7 +178,8 @@ static inline int ovl_do_mknod(struct inode *dir, struct dentry *dentry,
+ return err;
+ }
+
+-static inline int ovl_do_symlink(struct inode *dir, struct dentry *dentry,
++static inline int ovl_do_symlink(struct ovl_fs *ofs,
++ struct inode *dir, struct dentry *dentry,
+ const char *oldname)
+ {
+ int err = vfs_symlink(&init_user_ns, dir, dentry, oldname);
+@@ -233,9 +239,9 @@ static inline int ovl_removexattr(struct ovl_fs *ofs, struct dentry *dentry,
+ return ovl_do_removexattr(ofs, dentry, ovl_xattr(ofs, ox));
+ }
+
+-static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry,
+- struct inode *newdir, struct dentry *newdentry,
+- unsigned int flags)
++static inline int ovl_do_rename(struct ovl_fs *ofs, struct inode *olddir,
++ struct dentry *olddentry, struct inode *newdir,
++ struct dentry *newdentry, unsigned int flags)
+ {
+ int err;
+ struct renamedata rd = {
+@@ -257,14 +263,16 @@ static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry,
+ return err;
+ }
+
+-static inline int ovl_do_whiteout(struct inode *dir, struct dentry *dentry)
++static inline int ovl_do_whiteout(struct ovl_fs *ofs,
++ struct inode *dir, struct dentry *dentry)
+ {
+ int err = vfs_whiteout(&init_user_ns, dir, dentry);
+ pr_debug("whiteout(%pd2) = %i\n", dentry, err);
+ return err;
+ }
+
+-static inline struct dentry *ovl_do_tmpfile(struct dentry *dentry, umode_t mode)
++static inline struct dentry *ovl_do_tmpfile(struct ovl_fs *ofs,
++ struct dentry *dentry, umode_t mode)
+ {
+ struct dentry *ret = vfs_tmpfile(&init_user_ns, dentry, mode, 0);
+ int err = PTR_ERR_OR_ZERO(ret);
+@@ -483,12 +491,13 @@ static inline int ovl_verify_upper(struct ovl_fs *ofs, struct dentry *index,
+ extern const struct file_operations ovl_dir_operations;
+ struct file *ovl_dir_real_file(const struct file *file, bool want_upper);
+ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list);
+-void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list);
++void ovl_cleanup_whiteouts(struct ovl_fs *ofs, struct dentry *upper,
++ struct list_head *list);
+ void ovl_cache_free(struct list_head *list);
+ void ovl_dir_cache_free(struct inode *inode);
+ int ovl_check_d_type_supported(struct path *realpath);
+-int ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
+- struct dentry *dentry, int level);
++int ovl_workdir_cleanup(struct ovl_fs *ofs, struct inode *dir,
++ struct vfsmount *mnt, struct dentry *dentry, int level);
+ int ovl_indexdir_cleanup(struct ovl_fs *ofs);
+
+ /*
+@@ -583,12 +592,15 @@ struct ovl_cattr {
+
+ #define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) })
+
+-int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode);
+-struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
++int ovl_mkdir_real(struct ovl_fs *ofs, struct inode *dir,
++ struct dentry **newdentry, umode_t mode);
++struct dentry *ovl_create_real(struct ovl_fs *ofs,
++ struct inode *dir, struct dentry *newdentry,
++ struct ovl_cattr *attr);
++int ovl_cleanup(struct ovl_fs *ofs, struct inode *dir, struct dentry *dentry);
++struct dentry *ovl_lookup_temp(struct ovl_fs *ofs, struct dentry *workdir);
++struct dentry *ovl_create_temp(struct ovl_fs *ofs, struct dentry *workdir,
+ struct ovl_cattr *attr);
+-int ovl_cleanup(struct inode *dir, struct dentry *dentry);
+-struct dentry *ovl_lookup_temp(struct dentry *workdir);
+-struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr);
+
+ /* file.c */
+ extern const struct file_operations ovl_file_operations;
+diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
+index c7b542331065c..9c580ef8cd6fc 100644
+--- a/fs/overlayfs/readdir.c
++++ b/fs/overlayfs/readdir.c
+@@ -1001,7 +1001,8 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
+ return err;
+ }
+
+-void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list)
++void ovl_cleanup_whiteouts(struct ovl_fs *ofs, struct dentry *upper,
++ struct list_head *list)
+ {
+ struct ovl_cache_entry *p;
+
+@@ -1020,7 +1021,7 @@ void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list)
+ continue;
+ }
+ if (dentry->d_inode)
+- ovl_cleanup(upper->d_inode, dentry);
++ ovl_cleanup(ofs, upper->d_inode, dentry);
+ dput(dentry);
+ }
+ inode_unlock(upper->d_inode);
+@@ -1064,7 +1065,8 @@ int ovl_check_d_type_supported(struct path *realpath)
+
+ #define OVL_INCOMPATDIR_NAME "incompat"
+
+-static int ovl_workdir_cleanup_recurse(struct path *path, int level)
++static int ovl_workdir_cleanup_recurse(struct ovl_fs *ofs, struct path *path,
++ int level)
+ {
+ int err;
+ struct inode *dir = path->dentry->d_inode;
+@@ -1115,7 +1117,7 @@ static int ovl_workdir_cleanup_recurse(struct path *path, int level)
+ if (IS_ERR(dentry))
+ continue;
+ if (dentry->d_inode)
+- err = ovl_workdir_cleanup(dir, path->mnt, dentry, level);
++ err = ovl_workdir_cleanup(ofs, dir, path->mnt, dentry, level);
+ dput(dentry);
+ if (err)
+ break;
+@@ -1126,24 +1128,24 @@ static int ovl_workdir_cleanup_recurse(struct path *path, int level)
+ return err;
+ }
+
+-int ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
+- struct dentry *dentry, int level)
++int ovl_workdir_cleanup(struct ovl_fs *ofs, struct inode *dir,
++ struct vfsmount *mnt, struct dentry *dentry, int level)
+ {
+ int err;
+
+ if (!d_is_dir(dentry) || level > 1) {
+- return ovl_cleanup(dir, dentry);
++ return ovl_cleanup(ofs, dir, dentry);
+ }
+
+- err = ovl_do_rmdir(dir, dentry);
++ err = ovl_do_rmdir(ofs, dir, dentry);
+ if (err) {
+ struct path path = { .mnt = mnt, .dentry = dentry };
+
+ inode_unlock(dir);
+- err = ovl_workdir_cleanup_recurse(&path, level + 1);
++ err = ovl_workdir_cleanup_recurse(ofs, &path, level + 1);
+ inode_lock_nested(dir, I_MUTEX_PARENT);
+ if (!err)
+- err = ovl_cleanup(dir, dentry);
++ err = ovl_cleanup(ofs, dir, dentry);
+ }
+
+ return err;
+@@ -1187,7 +1189,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs)
+ }
+ /* Cleanup leftover from index create/cleanup attempt */
+ if (index->d_name.name[0] == '#') {
+- err = ovl_workdir_cleanup(dir, path.mnt, index, 1);
++ err = ovl_workdir_cleanup(ofs, dir, path.mnt, index, 1);
+ if (err)
+ break;
+ goto next;
+@@ -1197,7 +1199,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs)
+ goto next;
+ } else if (err == -ESTALE) {
+ /* Cleanup stale index entries */
+- err = ovl_cleanup(dir, index);
++ err = ovl_cleanup(ofs, dir, index);
+ } else if (err != -ENOENT) {
+ /*
+ * Abort mount to avoid corrupting the index if
+@@ -1213,7 +1215,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs)
+ err = ovl_cleanup_and_whiteout(ofs, dir, index);
+ } else {
+ /* Cleanup orphan index entries */
+- err = ovl_cleanup(dir, index);
++ err = ovl_cleanup(ofs, dir, index);
+ }
+
+ if (err)
+diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
+index 1dad3dabe0099..2ad1f8652ce61 100644
+--- a/fs/overlayfs/super.c
++++ b/fs/overlayfs/super.c
+@@ -784,7 +784,7 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
+ goto out_unlock;
+
+ retried = true;
+- err = ovl_workdir_cleanup(dir, mnt, work, 0);
++ err = ovl_workdir_cleanup(ofs, dir, mnt, work, 0);
+ dput(work);
+ if (err == -EINVAL) {
+ work = ERR_PTR(err);
+@@ -793,7 +793,7 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
+ goto retry;
+ }
+
+- err = ovl_mkdir_real(dir, &work, attr.ia_mode);
++ err = ovl_mkdir_real(ofs, dir, &work, attr.ia_mode);
+ if (err)
+ goto out_dput;
+
+@@ -1262,8 +1262,9 @@ static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs,
+ * Returns 1 if RENAME_WHITEOUT is supported, 0 if not supported and
+ * negative values if error is encountered.
+ */
+-static int ovl_check_rename_whiteout(struct dentry *workdir)
++static int ovl_check_rename_whiteout(struct ovl_fs *ofs)
+ {
++ struct dentry *workdir = ofs->workdir;
+ struct inode *dir = d_inode(workdir);
+ struct dentry *temp;
+ struct dentry *dest;
+@@ -1273,12 +1274,12 @@ static int ovl_check_rename_whiteout(struct dentry *workdir)
+
+ inode_lock_nested(dir, I_MUTEX_PARENT);
+
+- temp = ovl_create_temp(workdir, OVL_CATTR(S_IFREG | 0));
++ temp = ovl_create_temp(ofs, workdir, OVL_CATTR(S_IFREG | 0));
+ err = PTR_ERR(temp);
+ if (IS_ERR(temp))
+ goto out_unlock;
+
+- dest = ovl_lookup_temp(workdir);
++ dest = ovl_lookup_temp(ofs, workdir);
+ err = PTR_ERR(dest);
+ if (IS_ERR(dest)) {
+ dput(temp);
+@@ -1287,7 +1288,7 @@ static int ovl_check_rename_whiteout(struct dentry *workdir)
+
+ /* Name is inline and stable - using snapshot as a copy helper */
+ take_dentry_name_snapshot(&name, temp);
+- err = ovl_do_rename(dir, temp, dir, dest, RENAME_WHITEOUT);
++ err = ovl_do_rename(ofs, dir, temp, dir, dest, RENAME_WHITEOUT);
+ if (err) {
+ if (err == -EINVAL)
+ err = 0;
+@@ -1303,11 +1304,11 @@ static int ovl_check_rename_whiteout(struct dentry *workdir)
+
+ /* Best effort cleanup of whiteout and temp file */
+ if (err)
+- ovl_cleanup(dir, whiteout);
++ ovl_cleanup(ofs, dir, whiteout);
+ dput(whiteout);
+
+ cleanup_temp:
+- ovl_cleanup(dir, temp);
++ ovl_cleanup(ofs, dir, temp);
+ release_dentry_name_snapshot(&name);
+ dput(temp);
+ dput(dest);
+@@ -1318,7 +1319,8 @@ static int ovl_check_rename_whiteout(struct dentry *workdir)
+ return err;
+ }
+
+-static struct dentry *ovl_lookup_or_create(struct dentry *parent,
++static struct dentry *ovl_lookup_or_create(struct ovl_fs *ofs,
++ struct dentry *parent,
+ const char *name, umode_t mode)
+ {
+ size_t len = strlen(name);
+@@ -1327,7 +1329,7 @@ static struct dentry *ovl_lookup_or_create(struct dentry *parent,
+ inode_lock_nested(parent->d_inode, I_MUTEX_PARENT);
+ child = lookup_one_len(name, parent, len);
+ if (!IS_ERR(child) && !child->d_inode)
+- child = ovl_create_real(parent->d_inode, child,
++ child = ovl_create_real(ofs, parent->d_inode, child,
+ OVL_CATTR(mode));
+ inode_unlock(parent->d_inode);
+ dput(parent);
+@@ -1349,7 +1351,7 @@ static int ovl_create_volatile_dirty(struct ovl_fs *ofs)
+ const char *const *name = volatile_path;
+
+ for (ctr = ARRAY_SIZE(volatile_path); ctr; ctr--, name++) {
+- d = ovl_lookup_or_create(d, *name, ctr > 1 ? S_IFDIR : S_IFREG);
++ d = ovl_lookup_or_create(ofs, d, *name, ctr > 1 ? S_IFDIR : S_IFREG);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+ }
+@@ -1397,7 +1399,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
+ pr_warn("upper fs needs to support d_type.\n");
+
+ /* Check if upper/work fs supports O_TMPFILE */
+- temp = ovl_do_tmpfile(ofs->workdir, S_IFREG | 0);
++ temp = ovl_do_tmpfile(ofs, ofs->workdir, S_IFREG | 0);
+ ofs->tmpfile = !IS_ERR(temp);
+ if (ofs->tmpfile)
+ dput(temp);
+@@ -1406,7 +1408,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
+
+
+ /* Check if upper/work fs supports RENAME_WHITEOUT */
+- err = ovl_check_rename_whiteout(ofs->workdir);
++ err = ovl_check_rename_whiteout(ofs);
+ if (err < 0)
+ goto out;
+
+diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
+index eea9ec8f8c57a..8a9980ab2ad8f 100644
+--- a/fs/overlayfs/util.c
++++ b/fs/overlayfs/util.c
+@@ -866,7 +866,7 @@ static void ovl_cleanup_index(struct dentry *dentry)
+ dir, index);
+ } else {
+ /* Cleanup orphan index entries */
+- err = ovl_cleanup(dir, index);
++ err = ovl_cleanup(ofs, dir, index);
+ }
+
+ inode_unlock(dir);
+--
+2.39.5
+
--- /dev/null
+From 2e851b734612edad5c0cdbc46191b7cdb13e9efb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Apr 2022 12:51:42 +0200
+Subject: ovl: use wrappers to all vfs_*xattr() calls
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+[ Upstream commit c914c0e27eb0843b7cf3bec71d6f34d53a3a671e ]
+
+Use helpers ovl_*xattr() to access user/trusted.overlay.* xattrs
+and use helpers ovl_do_*xattr() to access generic xattrs. This is a
+preparatory patch for using idmapped base layers with overlay.
+
+Note that a few of those places called vfs_*xattr() calls directly to
+reduce the amount of debug output. But as Miklos pointed out since
+overlayfs has been stable for quite some time the debug output isn't all
+that relevant anymore and the additional debug in all locations was
+actually quite helpful when developing this patch series.
+
+Cc: <linux-unionfs@vger.kernel.org>
+Tested-by: Giuseppe Scrivano <gscrivan@redhat.com>
+Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Stable-dep-of: c84e125fff26 ("ovl: fix UAF in ovl_dentry_update_reval by moving dput() in ovl_link_up")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/copy_up.c | 21 +++++++++++----------
+ fs/overlayfs/dir.c | 15 ++++++++-------
+ fs/overlayfs/inode.c | 17 +++++++++--------
+ fs/overlayfs/namei.c | 6 +++---
+ fs/overlayfs/overlayfs.h | 38 ++++++++++++++++++++++++++++----------
+ fs/overlayfs/readdir.c | 4 ++--
+ fs/overlayfs/super.c | 12 ++++++------
+ fs/overlayfs/util.c | 16 ++++++++--------
+ 8 files changed, 75 insertions(+), 54 deletions(-)
+
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index 0ed70eff9cb9e..80e7ae8152fdd 100644
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -117,7 +117,7 @@ int ovl_copy_xattr(struct super_block *sb, struct dentry *old,
+ goto retry;
+ }
+
+- error = vfs_setxattr(&init_user_ns, new, name, value, size, 0);
++ error = ovl_do_setxattr(OVL_FS(sb), new, name, value, size, 0);
+ if (error) {
+ if (error != -EOPNOTSUPP || ovl_must_copy_xattr(name))
+ break;
+@@ -433,7 +433,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper,
+ if (IS_ERR(fh))
+ return PTR_ERR(fh);
+
+- err = ovl_do_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len);
++ err = ovl_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len);
+
+ kfree(fh);
+ return err;
+@@ -868,12 +868,13 @@ static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode,
+ return true;
+ }
+
+-static ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value)
++static ssize_t ovl_getxattr_value(struct ovl_fs *ofs, struct dentry *dentry,
++ char *name, char **value)
+ {
+ ssize_t res;
+ char *buf;
+
+- res = vfs_getxattr(&init_user_ns, dentry, name, NULL, 0);
++ res = ovl_do_getxattr(ofs, dentry, name, NULL, 0);
+ if (res == -ENODATA || res == -EOPNOTSUPP)
+ res = 0;
+
+@@ -882,7 +883,7 @@ static ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value)
+ if (!buf)
+ return -ENOMEM;
+
+- res = vfs_getxattr(&init_user_ns, dentry, name, buf, res);
++ res = ovl_do_getxattr(ofs, dentry, name, buf, res);
+ if (res < 0)
+ kfree(buf);
+ else
+@@ -909,8 +910,8 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
+ return -EIO;
+
+ if (c->stat.size) {
+- err = cap_size = ovl_getxattr(upperpath.dentry, XATTR_NAME_CAPS,
+- &capability);
++ err = cap_size = ovl_getxattr_value(ofs, upperpath.dentry,
++ XATTR_NAME_CAPS, &capability);
+ if (cap_size < 0)
+ goto out;
+ }
+@@ -924,14 +925,14 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
+ * don't want that to happen for normal copy-up operation.
+ */
+ if (capability) {
+- err = vfs_setxattr(&init_user_ns, upperpath.dentry,
+- XATTR_NAME_CAPS, capability, cap_size, 0);
++ err = ovl_do_setxattr(ofs, upperpath.dentry, XATTR_NAME_CAPS,
++ capability, cap_size, 0);
+ if (err)
+ goto out_free;
+ }
+
+
+- err = ovl_do_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY);
++ err = ovl_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY);
+ if (err)
+ goto out_free;
+
+diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
+index 519193ce7d575..5e9005a0afaad 100644
+--- a/fs/overlayfs/dir.c
++++ b/fs/overlayfs/dir.c
+@@ -431,8 +431,8 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
+ return ERR_PTR(err);
+ }
+
+-static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name,
+- const struct posix_acl *acl)
++static int ovl_set_upper_acl(struct ovl_fs *ofs, struct dentry *upperdentry,
++ const char *name, const struct posix_acl *acl)
+ {
+ void *buffer;
+ size_t size;
+@@ -450,7 +450,7 @@ static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name,
+ if (err < 0)
+ goto out_free;
+
+- err = vfs_setxattr(&init_user_ns, upperdentry, name, buffer, size, XATTR_CREATE);
++ err = ovl_do_setxattr(ofs, upperdentry, name, buffer, size, XATTR_CREATE);
+ out_free:
+ kfree(buffer);
+ return err;
+@@ -459,6 +459,7 @@ static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name,
+ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
+ struct ovl_cattr *cattr)
+ {
++ struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
+ struct dentry *workdir = ovl_workdir(dentry);
+ struct inode *wdir = workdir->d_inode;
+ struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
+@@ -515,13 +516,13 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
+ goto out_cleanup;
+ }
+ if (!hardlink) {
+- err = ovl_set_upper_acl(newdentry, XATTR_NAME_POSIX_ACL_ACCESS,
+- acl);
++ err = ovl_set_upper_acl(ofs, newdentry,
++ XATTR_NAME_POSIX_ACL_ACCESS, acl);
+ if (err)
+ goto out_cleanup;
+
+- err = ovl_set_upper_acl(newdentry, XATTR_NAME_POSIX_ACL_DEFAULT,
+- default_acl);
++ err = ovl_set_upper_acl(ofs, newdentry,
++ XATTR_NAME_POSIX_ACL_DEFAULT, default_acl);
+ if (err)
+ goto out_cleanup;
+ }
+diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
+index 7961d6888c520..aa8513aac4728 100644
+--- a/fs/overlayfs/inode.c
++++ b/fs/overlayfs/inode.c
+@@ -342,6 +342,7 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
+ const void *value, size_t size, int flags)
+ {
+ int err;
++ struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
+ struct dentry *upperdentry = ovl_i_dentry_upper(inode);
+ struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry);
+ const struct cred *old_cred;
+@@ -367,12 +368,12 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
+ }
+
+ old_cred = ovl_override_creds(dentry->d_sb);
+- if (value)
+- err = vfs_setxattr(&init_user_ns, realdentry, name, value, size,
+- flags);
+- else {
++ if (value) {
++ err = ovl_do_setxattr(ofs, realdentry, name, value, size,
++ flags);
++ } else {
+ WARN_ON(flags != XATTR_REPLACE);
+- err = vfs_removexattr(&init_user_ns, realdentry, name);
++ err = ovl_do_removexattr(ofs, realdentry, name);
+ }
+ revert_creds(old_cred);
+
+@@ -887,8 +888,8 @@ static int ovl_set_nlink_common(struct dentry *dentry,
+ if (WARN_ON(len >= sizeof(buf)))
+ return -EIO;
+
+- return ovl_do_setxattr(OVL_FS(inode->i_sb), ovl_dentry_upper(dentry),
+- OVL_XATTR_NLINK, buf, len);
++ return ovl_setxattr(OVL_FS(inode->i_sb), ovl_dentry_upper(dentry),
++ OVL_XATTR_NLINK, buf, len);
+ }
+
+ int ovl_set_nlink_upper(struct dentry *dentry)
+@@ -913,7 +914,7 @@ unsigned int ovl_get_nlink(struct ovl_fs *ofs, struct dentry *lowerdentry,
+ if (!lowerdentry || !upperdentry || d_inode(lowerdentry)->i_nlink == 1)
+ return fallback;
+
+- err = ovl_do_getxattr(ofs, upperdentry, OVL_XATTR_NLINK,
++ err = ovl_getxattr(ofs, upperdentry, OVL_XATTR_NLINK,
+ &buf, sizeof(buf) - 1);
+ if (err < 0)
+ goto fail;
+diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
+index 9c055d11a95de..00d74311aa0d3 100644
+--- a/fs/overlayfs/namei.c
++++ b/fs/overlayfs/namei.c
+@@ -111,7 +111,7 @@ static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *dentry,
+ int res, err;
+ struct ovl_fh *fh = NULL;
+
+- res = ovl_do_getxattr(ofs, dentry, ox, NULL, 0);
++ res = ovl_getxattr(ofs, dentry, ox, NULL, 0);
+ if (res < 0) {
+ if (res == -ENODATA || res == -EOPNOTSUPP)
+ return NULL;
+@@ -125,7 +125,7 @@ static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *dentry,
+ if (!fh)
+ return ERR_PTR(-ENOMEM);
+
+- res = ovl_do_getxattr(ofs, dentry, ox, fh->buf, res);
++ res = ovl_getxattr(ofs, dentry, ox, fh->buf, res);
+ if (res < 0)
+ goto fail;
+
+@@ -464,7 +464,7 @@ int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry,
+
+ err = ovl_verify_fh(ofs, dentry, ox, fh);
+ if (set && err == -ENODATA)
+- err = ovl_do_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len);
++ err = ovl_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len);
+ if (err)
+ goto fail;
+
+diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
+index a96b67586f817..3f4655b9c71ca 100644
+--- a/fs/overlayfs/overlayfs.h
++++ b/fs/overlayfs/overlayfs.h
+@@ -183,10 +183,9 @@ static inline int ovl_do_symlink(struct inode *dir, struct dentry *dentry,
+ }
+
+ static inline ssize_t ovl_do_getxattr(struct ovl_fs *ofs, struct dentry *dentry,
+- enum ovl_xattr ox, void *value,
++ const char *name, void *value,
+ size_t size)
+ {
+- const char *name = ovl_xattr(ofs, ox);
+ int err = vfs_getxattr(&init_user_ns, dentry, name, value, size);
+ int len = (value && err > 0) ? err : 0;
+
+@@ -195,26 +194,45 @@ static inline ssize_t ovl_do_getxattr(struct ovl_fs *ofs, struct dentry *dentry,
+ return err;
+ }
+
++static inline ssize_t ovl_getxattr(struct ovl_fs *ofs, struct dentry *dentry,
++ enum ovl_xattr ox, void *value,
++ size_t size)
++{
++ return ovl_do_getxattr(ofs, dentry, ovl_xattr(ofs, ox), value, size);
++}
++
+ static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
+- enum ovl_xattr ox, const void *value,
+- size_t size)
++ const char *name, const void *value,
++ size_t size, int flags)
+ {
+- const char *name = ovl_xattr(ofs, ox);
+- int err = vfs_setxattr(&init_user_ns, dentry, name, value, size, 0);
+- pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) = %i\n",
+- dentry, name, min((int)size, 48), value, size, err);
++ int err = vfs_setxattr(&init_user_ns, dentry, name, value, size, flags);
++
++ pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, %d) = %i\n",
++ dentry, name, min((int)size, 48), value, size, flags, err);
+ return err;
+ }
+
++static inline int ovl_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
++ enum ovl_xattr ox, const void *value,
++ size_t size)
++{
++ return ovl_do_setxattr(ofs, dentry, ovl_xattr(ofs, ox), value, size, 0);
++}
++
+ static inline int ovl_do_removexattr(struct ovl_fs *ofs, struct dentry *dentry,
+- enum ovl_xattr ox)
++ const char *name)
+ {
+- const char *name = ovl_xattr(ofs, ox);
+ int err = vfs_removexattr(&init_user_ns, dentry, name);
+ pr_debug("removexattr(%pd2, \"%s\") = %i\n", dentry, name, err);
+ return err;
+ }
+
++static inline int ovl_removexattr(struct ovl_fs *ofs, struct dentry *dentry,
++ enum ovl_xattr ox)
++{
++ return ovl_do_removexattr(ofs, dentry, ovl_xattr(ofs, ox));
++}
++
+ static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry,
+ struct inode *newdir, struct dentry *newdentry,
+ unsigned int flags)
+diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
+index 150fdf3bc68d4..c7b542331065c 100644
+--- a/fs/overlayfs/readdir.c
++++ b/fs/overlayfs/readdir.c
+@@ -623,8 +623,8 @@ static struct ovl_dir_cache *ovl_cache_get_impure(struct path *path)
+ * Removing the "impure" xattr is best effort.
+ */
+ if (!ovl_want_write(dentry)) {
+- ovl_do_removexattr(ofs, ovl_dentry_upper(dentry),
+- OVL_XATTR_IMPURE);
++ ovl_removexattr(ofs, ovl_dentry_upper(dentry),
++ OVL_XATTR_IMPURE);
+ ovl_drop_write(dentry);
+ }
+ ovl_clear_flag(OVL_IMPURE, d_inode(dentry));
+diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
+index 5310271cf2e38..1dad3dabe0099 100644
+--- a/fs/overlayfs/super.c
++++ b/fs/overlayfs/super.c
+@@ -815,13 +815,13 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
+ * allowed as upper are limited to "normal" ones, where checking
+ * for the above two errors is sufficient.
+ */
+- err = vfs_removexattr(&init_user_ns, work,
+- XATTR_NAME_POSIX_ACL_DEFAULT);
++ err = ovl_do_removexattr(ofs, work,
++ XATTR_NAME_POSIX_ACL_DEFAULT);
+ if (err && err != -ENODATA && err != -EOPNOTSUPP)
+ goto out_dput;
+
+- err = vfs_removexattr(&init_user_ns, work,
+- XATTR_NAME_POSIX_ACL_ACCESS);
++ err = ovl_do_removexattr(ofs, work,
++ XATTR_NAME_POSIX_ACL_ACCESS);
+ if (err && err != -ENODATA && err != -EOPNOTSUPP)
+ goto out_dput;
+
+@@ -1417,7 +1417,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
+ /*
+ * Check if upper/work fs supports (trusted|user).overlay.* xattr
+ */
+- err = ovl_do_setxattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE, "0", 1);
++ err = ovl_setxattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE, "0", 1);
+ if (err) {
+ pr_warn("failed to set xattr on upper\n");
+ ofs->noxattr = true;
+@@ -1438,7 +1438,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
+ pr_info("try mounting with 'userxattr' option\n");
+ err = 0;
+ } else {
+- ovl_do_removexattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE);
++ ovl_removexattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE);
+ }
+
+ /*
+diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
+index 747b47048b3aa..eea9ec8f8c57a 100644
+--- a/fs/overlayfs/util.c
++++ b/fs/overlayfs/util.c
+@@ -586,7 +586,7 @@ bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry)
+ {
+ int res;
+
+- res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_ORIGIN, NULL, 0);
++ res = ovl_getxattr(ofs, dentry, OVL_XATTR_ORIGIN, NULL, 0);
+
+ /* Zero size value means "copied up but origin unknown" */
+ if (res >= 0)
+@@ -604,7 +604,7 @@ bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry,
+ if (!d_is_dir(dentry))
+ return false;
+
+- res = ovl_do_getxattr(OVL_FS(sb), dentry, ox, &val, 1);
++ res = ovl_getxattr(OVL_FS(sb), dentry, ox, &val, 1);
+ if (res == 1 && val == 'y')
+ return true;
+
+@@ -644,7 +644,7 @@ int ovl_check_setxattr(struct ovl_fs *ofs, struct dentry *upperdentry,
+ if (ofs->noxattr)
+ return xerr;
+
+- err = ovl_do_setxattr(ofs, upperdentry, ox, value, size);
++ err = ovl_setxattr(ofs, upperdentry, ox, value, size);
+
+ if (err == -EOPNOTSUPP) {
+ pr_warn("cannot set %s xattr on upper\n", ovl_xattr(ofs, ox));
+@@ -684,7 +684,7 @@ void ovl_check_protattr(struct inode *inode, struct dentry *upper)
+ char buf[OVL_PROTATTR_MAX+1];
+ int res, n;
+
+- res = ovl_do_getxattr(ofs, upper, OVL_XATTR_PROTATTR, buf,
++ res = ovl_getxattr(ofs, upper, OVL_XATTR_PROTATTR, buf,
+ OVL_PROTATTR_MAX);
+ if (res < 0)
+ return;
+@@ -740,7 +740,7 @@ int ovl_set_protattr(struct inode *inode, struct dentry *upper,
+ err = ovl_check_setxattr(ofs, upper, OVL_XATTR_PROTATTR,
+ buf, len, -EPERM);
+ } else if (inode->i_flags & OVL_PROT_I_FLAGS_MASK) {
+- err = ovl_do_removexattr(ofs, upper, OVL_XATTR_PROTATTR);
++ err = ovl_removexattr(ofs, upper, OVL_XATTR_PROTATTR);
+ if (err == -EOPNOTSUPP || err == -ENODATA)
+ err = 0;
+ }
+@@ -983,7 +983,7 @@ int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct dentry *dentry)
+ if (!S_ISREG(d_inode(dentry)->i_mode))
+ return 0;
+
+- res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_METACOPY, NULL, 0);
++ res = ovl_getxattr(ofs, dentry, OVL_XATTR_METACOPY, NULL, 0);
+ if (res < 0) {
+ if (res == -ENODATA || res == -EOPNOTSUPP)
+ return 0;
+@@ -1025,7 +1025,7 @@ char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry,
+ int res;
+ char *s, *next, *buf = NULL;
+
+- res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, NULL, 0);
++ res = ovl_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, NULL, 0);
+ if (res == -ENODATA || res == -EOPNOTSUPP)
+ return NULL;
+ if (res < 0)
+@@ -1037,7 +1037,7 @@ char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry,
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+- res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, buf, res);
++ res = ovl_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, buf, res);
+ if (res < 0)
+ goto fail;
+ if (res == 0)
+--
+2.39.5
+
--- /dev/null
+From dd16e257721f61a0e279d885ef8a99e1092f2f92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 08:47:10 +0200
+Subject: RDMA/mlx5: Fix bind QP error cleanup flow
+
+From: Patrisious Haddad <phaddad@nvidia.com>
+
+[ Upstream commit e1a0bdbdfdf08428f0ede5ae49c7f4139ac73ef5 ]
+
+When there is a failure during bind QP, the cleanup flow destroys the
+counter regardless if it is the one that created it or not, which is
+problematic since if it isn't the one that created it, that counter could
+still be in use.
+
+Fix that by destroying the counter only if it was created during this call.
+
+Fixes: 45842fc627c7 ("IB/mlx5: Support statistic q counter configuration")
+Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
+Reviewed-by: Mark Zhang <markzhang@nvidia.com>
+Link: https://patch.msgid.link/25dfefddb0ebefa668c32e06a94d84e3216257cf.1740033937.git.leon@kernel.org
+Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/mlx5/counters.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/mlx5/counters.c b/drivers/infiniband/hw/mlx5/counters.c
+index 1a0ecf439c099..870a089198116 100644
+--- a/drivers/infiniband/hw/mlx5/counters.c
++++ b/drivers/infiniband/hw/mlx5/counters.c
+@@ -337,6 +337,7 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter,
+ struct ib_qp *qp)
+ {
+ struct mlx5_ib_dev *dev = to_mdev(qp->device);
++ bool new = false;
+ int err;
+
+ if (!counter->id) {
+@@ -351,6 +352,7 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter,
+ return err;
+ counter->id =
+ MLX5_GET(alloc_q_counter_out, out, counter_set_id);
++ new = true;
+ }
+
+ err = mlx5_ib_qp_set_counter(qp, counter);
+@@ -360,8 +362,10 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter,
+ return 0;
+
+ fail_set_counter:
+- mlx5_ib_counter_dealloc(counter);
+- counter->id = 0;
++ if (new) {
++ mlx5_ib_counter_dealloc(counter);
++ counter->id = 0;
++ }
+
+ return err;
+ }
+--
+2.39.5
+
--- /dev/null
+From a55b12cb7d3b0d403df8996092c40cbe2aa81b51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 10:16:28 +0800
+Subject: scsi: core: Clear driver private data when retrying request
+
+From: Ye Bin <yebin10@huawei.com>
+
+[ Upstream commit dce5c4afd035e8090a26e5d776b1682c0e649683 ]
+
+After commit 1bad6c4a57ef ("scsi: zero per-cmd private driver data for each
+MQ I/O"), the xen-scsifront/virtio_scsi/snic drivers all removed code that
+explicitly zeroed driver-private command data.
+
+In combination with commit 464a00c9e0ad ("scsi: core: Kill DRIVER_SENSE"),
+after virtio_scsi performs a capacity expansion, the first request will
+return a unit attention to indicate that the capacity has changed. And then
+the original command is retried. As driver-private command data was not
+cleared, the request would return UA again and eventually time out and fail.
+
+Zero driver-private command data when a request is retried.
+
+Fixes: f7de50da1479 ("scsi: xen-scsifront: Remove code that zeroes driver-private command data")
+Fixes: c2bb87318baa ("scsi: virtio_scsi: Remove code that zeroes driver-private command data")
+Fixes: c3006a926468 ("scsi: snic: Remove code that zeroes driver-private command data")
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://lore.kernel.org/r/20250217021628.2929248-1-yebin@huaweicloud.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_lib.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index ddaffaea2c32c..c8be41d8eb247 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -1532,13 +1532,6 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
+ if (in_flight)
+ __set_bit(SCMD_STATE_INFLIGHT, &cmd->state);
+
+- /*
+- * Only clear the driver-private command data if the LLD does not supply
+- * a function to initialize that data.
+- */
+- if (!shost->hostt->init_cmd_priv)
+- memset(cmd + 1, 0, shost->hostt->cmd_size);
+-
+ cmd->prot_op = SCSI_PROT_NORMAL;
+ if (blk_rq_bytes(req))
+ cmd->sc_data_direction = rq_dma_dir(req);
+@@ -1675,6 +1668,13 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
+ if (!scsi_host_queue_ready(q, shost, sdev, cmd))
+ goto out_dec_target_busy;
+
++ /*
++ * Only clear the driver-private command data if the LLD does not supply
++ * a function to initialize that data.
++ */
++ if (shost->hostt->cmd_size && !shost->hostt->init_cmd_priv)
++ memset(cmd + 1, 0, shost->hostt->cmd_size);
++
+ if (!(req->rq_flags & RQF_DONTPREP)) {
+ ret = scsi_prepare_cmd(req);
+ if (ret != BLK_STS_OK)
+--
+2.39.5
+
--- /dev/null
+From 3039005b7ab8db780c75d240d5c329f48129722b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 18:55:46 +0100
+Subject: scsi: core: Don't memset() the entire scsi_cmnd in
+ scsi_init_command()
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 71bada345b33b9297e7cc9415db6328c99b554f9 ]
+
+Replace the big fat memset that requires saving and restoring various
+fields with just initializing those fields that need initialization.
+
+All the clearing to 0 is moved to scsi_prepare_cmd() as scsi_ioctl_reset()
+alreadly uses kzalloc() to allocate a pre-zeroed command.
+
+This is still conservative and can probably be optimized further.
+
+Link: https://lore.kernel.org/r/20220224175552.988286-3-hch@lst.de
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Reviewed-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: dce5c4afd035 ("scsi: core: Clear driver private data when retrying request")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_lib.c | 60 +++++++++++++++++++----------------------
+ 1 file changed, 28 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 9721984fd9bc6..ddaffaea2c32c 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -1114,45 +1114,16 @@ static void scsi_cleanup_rq(struct request *rq)
+ /* Called before a request is prepared. See also scsi_mq_prep_fn(). */
+ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd)
+ {
+- void *buf = cmd->sense_buffer;
+- void *prot = cmd->prot_sdb;
+ struct request *rq = scsi_cmd_to_rq(cmd);
+- unsigned int flags = cmd->flags & SCMD_PRESERVED_FLAGS;
+- unsigned long jiffies_at_alloc;
+- int retries, to_clear;
+- bool in_flight;
+- int budget_token = cmd->budget_token;
+-
+- if (!blk_rq_is_passthrough(rq) && !(flags & SCMD_INITIALIZED)) {
+- flags |= SCMD_INITIALIZED;
++
++ if (!blk_rq_is_passthrough(rq) && !(cmd->flags & SCMD_INITIALIZED)) {
++ cmd->flags |= SCMD_INITIALIZED;
+ scsi_initialize_rq(rq);
+ }
+
+- jiffies_at_alloc = cmd->jiffies_at_alloc;
+- retries = cmd->retries;
+- in_flight = test_bit(SCMD_STATE_INFLIGHT, &cmd->state);
+- /*
+- * Zero out the cmd, except for the embedded scsi_request. Only clear
+- * the driver-private command data if the LLD does not supply a
+- * function to initialize that data.
+- */
+- to_clear = sizeof(*cmd) - sizeof(cmd->req);
+- if (!dev->host->hostt->init_cmd_priv)
+- to_clear += dev->host->hostt->cmd_size;
+- memset((char *)cmd + sizeof(cmd->req), 0, to_clear);
+-
+ cmd->device = dev;
+- cmd->sense_buffer = buf;
+- cmd->prot_sdb = prot;
+- cmd->flags = flags;
+ INIT_LIST_HEAD(&cmd->eh_entry);
+ INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler);
+- cmd->jiffies_at_alloc = jiffies_at_alloc;
+- cmd->retries = retries;
+- if (in_flight)
+- __set_bit(SCMD_STATE_INFLIGHT, &cmd->state);
+- cmd->budget_token = budget_token;
+-
+ }
+
+ static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev,
+@@ -1539,10 +1510,35 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
+ struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
+ struct scsi_device *sdev = req->q->queuedata;
+ struct Scsi_Host *shost = sdev->host;
++ bool in_flight = test_bit(SCMD_STATE_INFLIGHT, &cmd->state);
+ struct scatterlist *sg;
+
+ scsi_init_command(sdev, cmd);
+
++ cmd->eh_eflags = 0;
++ cmd->allowed = 0;
++ cmd->prot_type = 0;
++ cmd->prot_flags = 0;
++ cmd->submitter = 0;
++ cmd->cmd_len = 0;
++ cmd->cmnd = NULL;
++ memset(&cmd->sdb, 0, sizeof(cmd->sdb));
++ cmd->underflow = 0;
++ cmd->transfersize = 0;
++ cmd->host_scribble = NULL;
++ cmd->result = 0;
++ cmd->extra_len = 0;
++ cmd->state = 0;
++ if (in_flight)
++ __set_bit(SCMD_STATE_INFLIGHT, &cmd->state);
++
++ /*
++ * Only clear the driver-private command data if the LLD does not supply
++ * a function to initialize that data.
++ */
++ if (!shost->hostt->init_cmd_priv)
++ memset(cmd + 1, 0, shost->hostt->cmd_size);
++
+ cmd->prot_op = SCSI_PROT_NORMAL;
+ if (blk_rq_bytes(req))
+ cmd->sc_data_direction = rq_dma_dir(req);
+--
+2.39.5
+
mtd-rawnand-cadence-use-dma_map_resource-for-sdma-address.patch
mtd-rawnand-cadence-fix-incorrect-device-in-dma_unmap_single.patch
x86-cpu-kvm-srso-fix-possible-missing-ibpb-on-vm-exit.patch
+ib-mlx5-set-and-get-correct-qp_num-for-a-dct-qp.patch
+ovl-use-wrappers-to-all-vfs_-xattr-calls.patch
+ovl-pass-ofs-to-creation-operations.patch
+ovl-fix-uaf-in-ovl_dentry_update_reval-by-moving-dpu.patch
+scsi-core-don-t-memset-the-entire-scsi_cmnd-in-scsi_.patch
+scsi-core-clear-driver-private-data-when-retrying-re.patch
+rdma-mlx5-fix-bind-qp-error-cleanup-flow.patch
+sunrpc-suppress-warnings-for-unused-procfs-functions.patch
--- /dev/null
+From d85cb2eee17af738e1ba719ef712541c12a16ebd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 15:52:21 +0100
+Subject: sunrpc: suppress warnings for unused procfs functions
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 1f7a4f98c11fbeb18ed21f3b3a497e90a50ad2e0 ]
+
+There is a warning about unused variables when building with W=1 and no procfs:
+
+net/sunrpc/cache.c:1660:30: error: 'cache_flush_proc_ops' defined but not used [-Werror=unused-const-variable=]
+ 1660 | static const struct proc_ops cache_flush_proc_ops = {
+ | ^~~~~~~~~~~~~~~~~~~~
+net/sunrpc/cache.c:1622:30: error: 'content_proc_ops' defined but not used [-Werror=unused-const-variable=]
+ 1622 | static const struct proc_ops content_proc_ops = {
+ | ^~~~~~~~~~~~~~~~
+net/sunrpc/cache.c:1598:30: error: 'cache_channel_proc_ops' defined but not used [-Werror=unused-const-variable=]
+ 1598 | static const struct proc_ops cache_channel_proc_ops = {
+ | ^~~~~~~~~~~~~~~~~~~~~~
+
+These are used inside of an #ifdef, so replacing that with an
+IS_ENABLED() check lets the compiler see how they are used while
+still dropping them during dead code elimination.
+
+Fixes: dbf847ecb631 ("knfsd: allow cache_register to return error on failure")
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Acked-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sunrpc/cache.c | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
+index 8c9597b9a3f2e..95aab48d32e67 100644
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@ -1659,12 +1659,14 @@ static void remove_cache_proc_entries(struct cache_detail *cd)
+ }
+ }
+
+-#ifdef CONFIG_PROC_FS
+ static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)
+ {
+ struct proc_dir_entry *p;
+ struct sunrpc_net *sn;
+
++ if (!IS_ENABLED(CONFIG_PROC_FS))
++ return 0;
++
+ sn = net_generic(net, sunrpc_net_id);
+ cd->procfs = proc_mkdir(cd->name, sn->proc_net_rpc);
+ if (cd->procfs == NULL)
+@@ -1692,12 +1694,6 @@ static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)
+ remove_cache_proc_entries(cd);
+ return -ENOMEM;
+ }
+-#else /* CONFIG_PROC_FS */
+-static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)
+-{
+- return 0;
+-}
+-#endif
+
+ void __init cache_initialize(void)
+ {
+--
+2.39.5
+