From patchwork Wed Jun 11 16:40:49 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Dryomov X-Patchwork-Id: 4337301 Return-Path: X-Original-To: patchwork-ceph-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 80396BEEAA for ; Wed, 11 Jun 2014 16:40:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9C6A3202DD for ; Wed, 11 Jun 2014 16:40:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7B43D20218 for ; Wed, 11 Jun 2014 16:40:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755753AbaFKQky (ORCPT ); Wed, 11 Jun 2014 12:40:54 -0400 Received: from mail-la0-f43.google.com ([209.85.215.43]:49388 "EHLO mail-la0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755583AbaFKQky (ORCPT ); Wed, 11 Jun 2014 12:40:54 -0400 Received: by mail-la0-f43.google.com with SMTP id e16so297lan.2 for ; Wed, 11 Jun 2014 09:40:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id; bh=GoIXxIHE0vFEEoxfrci4E7hW9nQx2V/iNOCqymwbMRE=; b=dBs0Vq0J/hadgicN7nv+qZVoi9473W0zD5w2ewLmYdOZ8d75QBfzjtjU06G4S7t8fu yDEqLyEjYIEVD+4rXNeT6Sn6jk5WDjFCHsgyjrv+/YQ3gNHNiZsHtW7IrYpYb4rhxT7o m35Zq02aIrBF5i0QooNC+4TrO9ZtlqIAZUDz49WuTgrmUobJITHpS7UUpXseq2+uTj0s cKR+dKBFvIPETK9rwEoIzb6v0KKsAnJaJGx7nnPrxKHaAlO02Iuz9/Mxh0b+R/cgpB5Z VNa23j8uqZDrXoZ06ePa5uqYg60LQ/F2SCE+3BUHmEplEpyXv04G0xW9jjzvashyujCO Lbmg== X-Gm-Message-State: ALoCoQnGEFzuNFz4YnhhoYXzqkJeUvWHya7FRN3NGF7CFMGvrISGErZK4TtH7Mfm0r4JH5a1s6eD X-Received: by 10.152.20.168 with SMTP id o8mr2045858lae.78.1402504852236; Wed, 11 Jun 2014 09:40:52 -0700 (PDT) Received: from localhost ([109.110.66.45]) by mx.google.com with ESMTPSA id x2sm21960705lae.1.2014.06.11.09.40.50 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Wed, 11 Jun 2014 09:40:51 -0700 (PDT) From: Ilya Dryomov To: ceph-devel@vger.kernel.org Subject: [PATCH] rbd: handle parent_overlap on writes correctly Date: Wed, 11 Jun 2014 20:40:49 +0400 Message-Id: <1402504849-9958-1-git-send-email-ilya.dryomov@inktank.com> X-Mailer: git-send-email 1.7.10.4 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The following check in rbd_img_obj_request_submit() rbd_dev->parent_overlap <= obj_request->img_offset allows the fall through to the non-layered write case even if both parent_overlap and obj_request->img_offset belong to the same RADOS object. This leads to data corruption, because the area to the left of parent_overlap ends up unconditionally zero-filled instead of being populated with parent data. Suppose we want to write 1M to offset 6M of image bar, which is a clone of foo@snap; object_size is 4M, parent_overlap is 5M: rbd_data..0000000000000001 ---------------------|----------------------|------------ | should be copyup'ed | should be zeroed out | write ... ---------------------|----------------------|------------ 4M 5M 6M parent_overlap obj_request->img_offset 4..5M should be copyup'ed from foo, yet it is zero-filled, just like 5..6M is. Given that the only striping mode kernel client currently supports is chunking (i.e. stripe_unit == object_size, stripe_count == 1), round parent_overlap up to the next object boundary for the purposes of the overlap check. Signed-off-by: Ilya Dryomov Reviewed-by: Josh Durgin Reviewed-by: Alex Elder --- drivers/block/rbd.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 8295b3afa8e0..813e673d49df 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -1366,6 +1366,14 @@ static bool obj_request_exists_test(struct rbd_obj_request *obj_request) return test_bit(OBJ_REQ_EXISTS, &obj_request->flags) != 0; } +static bool obj_request_overlaps_parent(struct rbd_obj_request *obj_request) +{ + struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev; + + return obj_request->img_offset < + round_up(rbd_dev->parent_overlap, rbd_obj_bytes(&rbd_dev->header)); +} + static void rbd_obj_request_get(struct rbd_obj_request *obj_request) { dout("%s: obj %p (was %d)\n", __func__, obj_request, @@ -2683,7 +2691,7 @@ static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request) */ if (!img_request_write_test(img_request) || !img_request_layered_test(img_request) || - rbd_dev->parent_overlap <= obj_request->img_offset || + !obj_request_overlaps_parent(obj_request) || ((known = obj_request_known_test(obj_request)) && obj_request_exists_test(obj_request))) {