From patchwork Wed Apr 23 04:35:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chunwei Chen X-Patchwork-Id: 4038801 Return-Path: X-Original-To: patchwork-ceph-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 95E299F1F4 for ; Wed, 23 Apr 2014 04:36:23 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D326F20211 for ; Wed, 23 Apr 2014 04:36:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2B1C0201F7 for ; Wed, 23 Apr 2014 04:36:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750844AbaDWEfr (ORCPT ); Wed, 23 Apr 2014 00:35:47 -0400 Received: from mail-vc0-f172.google.com ([209.85.220.172]:45105 "EHLO mail-vc0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750734AbaDWEfq (ORCPT ); Wed, 23 Apr 2014 00:35:46 -0400 Received: by mail-vc0-f172.google.com with SMTP id la4so510983vcb.3 for ; Tue, 22 Apr 2014 21:35:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=biTrM3mD3BBvx3ntHfSHRdOdbs1rOK832/JmavFTYWg=; b=jzgwZWQmRtiEUGUPOcSfKuHuYHsWIH+z2ZXbcJ40JzOZQLRdIUDObfmBjoCi5L6Tqh ZQTzLkcwLXg+IHJ0lJ3PCCk1xLHACC4h0DMWU6iLFBaTysypp/J9eqa194KL9OT8bTow 3ZjswEvFz/+v93caLhYrlFjubRZDgxjbsrRlBMuXmk6IlVWq20pKliEQjUOa74vt2h1/ XP2pIlL6FbhbHwOpzsCzzzTy9f5sBRg+qfIU9CsJXnCyAY6qvqSN9rryMqKnGkD9NgiL eGwOVvk1e/1GjX963L48vTAVkVXuuG615ev4udpHrE4vTWJdpgjLXTa+oBMeNtzneb9a YXjQ== X-Received: by 10.52.189.193 with SMTP id gk1mr16816428vdc.12.1398227745161; Tue, 22 Apr 2014 21:35:45 -0700 (PDT) Received: from localhost.localdomain ([118.99.181.141]) by mx.google.com with ESMTPSA id p8sm53872407veq.8.2014.04.22.21.35.40 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 22 Apr 2014 21:35:42 -0700 (PDT) From: Chunwei Chen To: ceph-devel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Chunwei Chen , Sage Weil , Yehuda Sadeh , stable@vger.kernel.org Subject: [PATCH] ceph: fix corruption when using page_count 0 page in rbd Date: Wed, 23 Apr 2014 12:35:09 +0800 Message-Id: <1398227709-4926-1-git-send-email-tuxoko@gmail.com> X-Mailer: git-send-email 1.8.5.2 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.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable 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 It has been reported that using ZFSonLinux on rbd will result in memory corruption. The bug report can be found here: https://github.com/zfsonlinux/spl/issues/241 http://tracker.ceph.com/issues/7790 The reason is that ZFS will send pages with page_count 0 into rbd, which in turns send them to tcp_sendpage. However, tcp_sendpage cannot deal with page_count 0, as it will do get_page and put_page, and erroneously free the page. This type of issue has been noted before, and handled in iscsi, drbd, etc. So, rbd should also handle this. This fix address this issue by fall back to slower sendmsg when page_count 0 detected. Cc: Sage Weil Cc: Yehuda Sadeh Cc: stable@vger.kernel.org Signed-off-by: Chunwei Chen --- net/ceph/messenger.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 4f55f9c..9a964e7 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -557,7 +557,7 @@ static int ceph_tcp_sendmsg(struct socket *sock, struct kvec *iov, return r; } -static int ceph_tcp_sendpage(struct socket *sock, struct page *page, +static int __ceph_tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, bool more) { int flags = MSG_DONTWAIT | MSG_NOSIGNAL | (more ? MSG_MORE : MSG_EOR); @@ -570,6 +570,24 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page, return ret; } +static int ceph_tcp_sendpage(struct socket *sock, struct page *page, + int offset, size_t size, bool more) +{ + int ret; + struct kvec iov; + + /* sendpage cannot properly handle pages with page_count == 0, + * we need to fallback to sendmsg if that's the case */ + if (page_count(page) >= 1) + return __ceph_tcp_sendpage(sock, page, offset, size, more); + + iov.iov_base = kmap(page) + offset; + iov.iov_len = size; + ret = ceph_tcp_sendmsg(sock, &iov, 1, size, more); + kunmap(page); + + return ret; +} /* * Shutdown/close the socket for the given connection.