Home Home > GIT Browse > SLE15-SP1
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Henriques <lhenriques@suse.com>2019-01-16 16:12:01 +0000
committerLuis Henriques <lhenriques@suse.com>2019-01-18 11:21:08 +0000
commitec0a098f1afec2694386b4412d752fb066f718e9 (patch)
tree4e231bfa3c7f4476eeb9514bdaedda27e3816016
parent98ba0d443875573299456a81255d97c83217fbf8 (diff)
ceph: cleanup splice_dentry() (bsc#1122215).
-rw-r--r--patches.suse/ceph-cleanup-splice_dentry.patch158
-rw-r--r--series.conf1
2 files changed, 159 insertions, 0 deletions
diff --git a/patches.suse/ceph-cleanup-splice_dentry.patch b/patches.suse/ceph-cleanup-splice_dentry.patch
new file mode 100644
index 0000000000..22d78d5620
--- /dev/null
+++ b/patches.suse/ceph-cleanup-splice_dentry.patch
@@ -0,0 +1,158 @@
+From: "Yan, Zheng" <zyan@redhat.com>
+Date: Thu, 25 Oct 2018 17:30:30 +0800
+Subject: ceph: cleanup splice_dentry()
+Git-commit: 2bf996ac48326645ffe5985edfca307838f8eafe
+Patch-mainline: v5.0-rc1
+References: bsc#1122215
+
+splice_dentry() may drop the original dentry and return other
+dentry. It relies on its caller to update pointer that points
+to the dropped dentry. This is error-prone.
+
+Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Acked-by: Luis Henriques <lhenriques@suse.com>
+---
+ fs/ceph/inode.c | 60 ++++++++++++++++++++++----------------------------------
+ 1 file changed, 24 insertions(+), 36 deletions(-)
+
+--- a/fs/ceph/inode.c
++++ b/fs/ceph/inode.c
+@@ -1097,8 +1097,9 @@ out_unlock:
+ * splice a dentry to an inode.
+ * caller must hold directory i_mutex for this to be safe.
+ */
+-static struct dentry *splice_dentry(struct dentry *dn, struct inode *in)
++static int splice_dentry(struct dentry **pdn, struct inode *in)
+ {
++ struct dentry *dn = *pdn;
+ struct dentry *realdn;
+
+ BUG_ON(d_inode(dn));
+@@ -1131,28 +1132,23 @@ static struct dentry *splice_dentry(stru
+ if (IS_ERR(realdn)) {
+ pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n",
+ PTR_ERR(realdn), dn, in, ceph_vinop(in));
+- dn = realdn;
+- /*
+- * Caller should release 'dn' in the case of error.
+- * If 'req->r_dentry' is passed to this function,
+- * caller should leave 'req->r_dentry' untouched.
+- */
+- goto out;
+- } else if (realdn) {
++ return PTR_ERR(realdn);
++ }
++
++ if (realdn) {
+ dout("dn %p (%d) spliced with %p (%d) "
+ "inode %p ino %llx.%llx\n",
+ dn, d_count(dn),
+ realdn, d_count(realdn),
+ d_inode(realdn), ceph_vinop(d_inode(realdn)));
+ dput(dn);
+- dn = realdn;
++ *pdn = realdn;
+ } else {
+ BUG_ON(!ceph_dentry(dn));
+ dout("dn %p attached to %p ino %llx.%llx\n",
+ dn, d_inode(dn), ceph_vinop(d_inode(dn)));
+ }
+-out:
+- return dn;
++ return 0;
+ }
+
+ /*
+@@ -1339,7 +1335,12 @@ retry_lookup:
+ dout("dn %p gets new offset %lld\n", req->r_old_dentry,
+ ceph_dentry(req->r_old_dentry)->offset);
+
+- dn = req->r_old_dentry; /* use old_dentry */
++ /* swap r_dentry and r_old_dentry in case that
++ * splice_dentry() gets called later. This is safe
++ * because no other place will use them */
++ req->r_dentry = req->r_old_dentry;
++ req->r_old_dentry = dn;
++ dn = req->r_dentry;
+ }
+
+ /* null dentry? */
+@@ -1364,12 +1365,10 @@ retry_lookup:
+ if (d_really_is_negative(dn)) {
+ ceph_dir_clear_ordered(dir);
+ ihold(in);
+- dn = splice_dentry(dn, in);
+- if (IS_ERR(dn)) {
+- err = PTR_ERR(dn);
++ err = splice_dentry(&req->r_dentry, in);
++ if (err < 0)
+ goto done;
+- }
+- req->r_dentry = dn; /* may have spliced */
++ dn = req->r_dentry; /* may have spliced */
+ } else if (d_really_is_positive(dn) && d_inode(dn) != in) {
+ dout(" %p links to %p %llx.%llx, not %llx.%llx\n",
+ dn, d_inode(dn), ceph_vinop(d_inode(dn)),
+@@ -1389,22 +1388,18 @@ retry_lookup:
+ } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
+ req->r_op == CEPH_MDS_OP_MKSNAP) &&
+ !test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) {
+- struct dentry *dn = req->r_dentry;
+ struct inode *dir = req->r_parent;
+
+ /* fill out a snapdir LOOKUPSNAP dentry */
+- BUG_ON(!dn);
+ BUG_ON(!dir);
+ BUG_ON(ceph_snap(dir) != CEPH_SNAPDIR);
+- dout(" linking snapped dir %p to dn %p\n", in, dn);
++ BUG_ON(!req->r_dentry);
++ dout(" linking snapped dir %p to dn %p\n", in, req->r_dentry);
+ ceph_dir_clear_ordered(dir);
+ ihold(in);
+- dn = splice_dentry(dn, in);
+- if (IS_ERR(dn)) {
+- err = PTR_ERR(dn);
++ err = splice_dentry(&req->r_dentry, in);
++ if (err < 0)
+ goto done;
+- }
+- req->r_dentry = dn; /* may have spliced */
+ } else if (rinfo->head->is_dentry) {
+ struct ceph_vino *ptvino = NULL;
+
+@@ -1668,8 +1663,6 @@ retry_lookup:
+ }
+
+ if (d_really_is_negative(dn)) {
+- struct dentry *realdn;
+-
+ if (ceph_security_xattr_deadlock(in)) {
+ dout(" skip splicing dn %p to inode %p"
+ " (security xattr deadlock)\n", dn, in);
+@@ -1678,13 +1671,9 @@ retry_lookup:
+ goto next_item;
+ }
+
+- realdn = splice_dentry(dn, in);
+- if (IS_ERR(realdn)) {
+- err = PTR_ERR(realdn);
+- d_drop(dn);
++ err = splice_dentry(&dn, in);
++ if (err < 0)
+ goto next_item;
+- }
+- dn = realdn;
+ }
+
+ ceph_dentry(dn)->offset = rde->offset;
+@@ -1700,8 +1689,7 @@ retry_lookup:
+ err = ret;
+ }
+ next_item:
+- if (dn)
+- dput(dn);
++ dput(dn);
+ }
+ out:
+ if (err == 0 && skipped == 0) {
diff --git a/series.conf b/series.conf
index c242d4469d..199b052110 100644
--- a/series.conf
+++ b/series.conf
@@ -42492,6 +42492,7 @@
patches.drivers/ALSA-hda-realtek-Enable-the-headset-mic-auto-detecti.patch
patches.drivers/ALSA-hda-tegra-clear-pending-irq-handlers.patch
patches.suse/mm-speed-up-mremap-by-20x-on-large-regions.patch
+ patches.suse/ceph-cleanup-splice_dentry.patch
patches.fixes/ceph-don-t-update-importing-cap-s-mseq-when-handing-cap-export.patch
patches.fixes/xfs-xfs_buf-drop-useless-LIST_HEAD.patch
patches.drivers/thermal-bcm2835-enable-hwmon-explicitly.patch