stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Alex Elder <elder@linaro.org>,
	Ilya Dryomov <idryomov@gmail.com>
Subject: [PATCH 3.10 20/35] rbd: fix copyup completion race
Date: Fri, 14 Aug 2015 10:44:58 -0700	[thread overview]
Message-ID: <20150814174354.492845501@linuxfoundation.org> (raw)
In-Reply-To: <20150814174353.835241087@linuxfoundation.org>

3.10-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Ilya Dryomov <idryomov@gmail.com>

commit 2761713d35e370fd640b5781109f753066b746c4 upstream.

For write/discard obj_requests that involved a copyup method call, the
opcode of the first op is CEPH_OSD_OP_CALL and the ->callback is
rbd_img_obj_copyup_callback().  The latter frees copyup pages, sets
->xferred and delegates to rbd_img_obj_callback(), the "normal" image
object callback, for reporting to block layer and putting refs.

rbd_osd_req_callback() however treats CEPH_OSD_OP_CALL as a trivial op,
which means obj_request is marked done in rbd_osd_trivial_callback(),
*before* ->callback is invoked and rbd_img_obj_copyup_callback() has
a chance to run.  Marking obj_request done essentially means giving
rbd_img_obj_callback() a license to end it at any moment, so if another
obj_request from the same img_request is being completed concurrently,
rbd_img_obj_end_request() may very well be called on such prematurally
marked done request:

<obj_request-1/2 reply>
handle_reply()
  rbd_osd_req_callback()
    rbd_osd_trivial_callback()
    rbd_obj_request_complete()
    rbd_img_obj_copyup_callback()
    rbd_img_obj_callback()
                                    <obj_request-2/2 reply>
                                    handle_reply()
                                      rbd_osd_req_callback()
                                        rbd_osd_trivial_callback()
      for_each_obj_request(obj_request->img_request) {
        rbd_img_obj_end_request(obj_request-1/2)
        rbd_img_obj_end_request(obj_request-2/2) <--
      }

Calling rbd_img_obj_end_request() on such a request leads to trouble,
in particular because its ->xfferred is 0.  We report 0 to the block
layer with blk_update_request(), get back 1 for "this request has more
data in flight" and then trip on

    rbd_assert(more ^ (which == img_request->obj_request_count));

with rhs (which == ...) being 1 because rbd_img_obj_end_request() has
been called for both requests and lhs (more) being 1 because we haven't
got a chance to set ->xfferred in rbd_img_obj_copyup_callback() yet.

To fix this, leverage that rbd wants to call class methods in only two
cases: one is a generic method call wrapper (obj_request is standalone)
and the other is a copyup (obj_request is part of an img_request).  So
make a dedicated handler for CEPH_OSD_OP_CALL and directly invoke
rbd_img_obj_copyup_callback() from it if obj_request is part of an
img_request, similar to how CEPH_OSD_OP_READ handler invokes
rbd_img_obj_request_read_callback().

Since rbd_img_obj_copyup_callback() is now being called from the OSD
request callback (only), it is renamed to rbd_osd_copyup_callback().

Cc: Alex Elder <elder@linaro.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Reviewed-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 drivers/block/rbd.c |   22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -457,6 +457,7 @@ void rbd_warn(struct rbd_device *rbd_dev
 #  define rbd_assert(expr)	((void) 0)
 #endif /* !RBD_DEBUG */
 
+static void rbd_osd_copyup_callback(struct rbd_obj_request *obj_request);
 static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request);
 static void rbd_img_parent_read(struct rbd_obj_request *obj_request);
 static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
@@ -1670,6 +1671,16 @@ static void rbd_osd_stat_callback(struct
 	obj_request_done_set(obj_request);
 }
 
+static void rbd_osd_call_callback(struct rbd_obj_request *obj_request)
+{
+	dout("%s: obj %p\n", __func__, obj_request);
+
+	if (obj_request_img_data_test(obj_request))
+		rbd_osd_copyup_callback(obj_request);
+	else
+		obj_request_done_set(obj_request);
+}
+
 static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
 				struct ceph_msg *msg)
 {
@@ -1708,6 +1719,8 @@ static void rbd_osd_req_callback(struct
 		rbd_osd_stat_callback(obj_request);
 		break;
 	case CEPH_OSD_OP_CALL:
+		rbd_osd_call_callback(obj_request);
+		break;
 	case CEPH_OSD_OP_NOTIFY_ACK:
 	case CEPH_OSD_OP_WATCH:
 		rbd_osd_trivial_callback(obj_request);
@@ -2305,13 +2318,15 @@ out_unwind:
 }
 
 static void
-rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request)
+rbd_osd_copyup_callback(struct rbd_obj_request *obj_request)
 {
 	struct rbd_img_request *img_request;
 	struct rbd_device *rbd_dev;
 	struct page **pages;
 	u32 page_count;
 
+	dout("%s: obj %p\n", __func__, obj_request);
+
 	rbd_assert(obj_request->type == OBJ_REQUEST_BIO);
 	rbd_assert(obj_request_img_data_test(obj_request));
 	img_request = obj_request->img_request;
@@ -2337,9 +2352,7 @@ rbd_img_obj_copyup_callback(struct rbd_o
 	if (!obj_request->result)
 		obj_request->xferred = obj_request->length;
 
-	/* Finish up with the normal image object callback */
-
-	rbd_img_obj_callback(obj_request);
+	obj_request_done_set(obj_request);
 }
 
 static void
@@ -2436,7 +2449,6 @@ rbd_img_obj_parent_read_full_callback(st
 
 	/* All set, send it off. */
 
-	orig_request->callback = rbd_img_obj_copyup_callback;
 	osdc = &rbd_dev->rbd_client->client->osdc;
 	img_result = rbd_obj_request_submit(osdc, orig_request);
 	if (!img_result)



  parent reply	other threads:[~2015-08-14 17:45 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-14 17:44 [PATCH 3.10 00/35] 3.10.87-stable review Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 01/35] ARM: realview: fix sparsemem build Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 02/35] MIPS: Fix sched_getaffinity with MT FPAFF enabled Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 03/35] MIPS: Make set_pte() SMP safe Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 04/35] fsnotify: fix oops in fsnotify_clear_marks_by_group_flags() Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 05/35] drm/radeon/combios: add some validation of lvds values Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 06/35] ipr: Fix locking for unit attention handling Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 07/35] ipr: Fix incorrect trace indexing Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 08/35] ipr: Fix invalid array indexing for HRRQ Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 10/35] USB: sierra: add 1199:68AB device ID Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 11/35] md: use kzalloc() when bitmap is disabled Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 12/35] ipmi: fix timeout calculation when bmc is disconnected Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 13/35] mfd: sm501: dbg_regs attribute must be read-only Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 14/35] perf/x86/amd: Rework AMD PMU init code Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 15/35] sparc64: Fix FPU register corruption with AES crypto offload Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 16/35] sparc64: Fix userspace FPU register corruptions Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 17/35] x86/xen: Probe target addresses in set_aliased_prot() before the hypercall Greg Kroah-Hartman
2015-08-14 17:44 ` [PATCH 3.10 19/35] crypto: ixp4xx - Remove bogus BUG_ON on scattered dst buffer Greg Kroah-Hartman
2015-08-14 17:44 ` Greg Kroah-Hartman [this message]
2015-08-14 17:44 ` [PATCH 3.10 21/35] iscsi-target: Fix iscsit_start_kthreads failure OOPs Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 22/35] ALSA: hda - fix cs4210_spdif_automute() Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 23/35] ipc: modify message queue accounting to not take kernel data structures into account Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 24/35] ocfs2: fix BUG in ocfs2_downconvert_thread_do_work() Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 25/35] md/raid1: extend spinlock to protect raid1_end_read_request against inconsistencies Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 26/35] sg_start_req(): make sure that theres not too many elements in iovec Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 27/35] ARM: Fix !kuser helpers case Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 28/35] ARM: Fix FIQ code on VIVT CPUs Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 29/35] ARM: 7819/1: fiq: Cast the first argument of flush_icache_range() Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 30/35] signalfd: fix information leak in signalfd_copyinfo Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 31/35] signal: fix information leak in copy_siginfo_to_user Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 32/35] signal: fix information leak in copy_siginfo_from_user32 Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 33/35] kvm: x86: fix kvm_apic_has_events to check for NULL pointer Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 34/35] md/bitmap: return an error when bitmap superblock is corrupt Greg Kroah-Hartman
2015-08-14 17:45 ` [PATCH 3.10 35/35] mm, vmscan: Do not wait for page writeback for GFP_NOFS allocations Greg Kroah-Hartman
     [not found] ` <55ce3244.6a6ab40a.1286.60de@mx.google.com>
2015-08-14 18:25   ` [PATCH 3.10 00/35] 3.10.87-stable review Kevin Hilman
2015-08-14 19:15     ` Greg Kroah-Hartman
2015-08-14 19:25       ` Tyler Baker
2015-08-14 18:36   ` Kevin Hilman
     [not found] ` <55ce7ee9.c365b40a.aac67.ffffc07a@mx.google.com>
2015-08-14 23:52   ` Kevin Hilman
2015-08-15  0:46     ` Greg Kroah-Hartman
2015-08-15  0:12 ` Shuah Khan
2015-08-15 15:15 ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150814174354.492845501@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=elder@linaro.org \
    --cc=idryomov@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).