From patchwork Mon Apr 15 16:45:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 10901231 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 382BE17E6 for ; Mon, 15 Apr 2019 16:45:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1D5CF288AE for ; Mon, 15 Apr 2019 16:45:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0DA2A28925; Mon, 15 Apr 2019 16:45:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8EB42288AE for ; Mon, 15 Apr 2019 16:45:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727691AbfDOQpT (ORCPT ); Mon, 15 Apr 2019 12:45:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:58114 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727646AbfDOQpT (ORCPT ); Mon, 15 Apr 2019 12:45:19 -0400 Received: from tleilax.poochiereds.net (cpe-71-70-156-158.nc.res.rr.com [71.70.156.158]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id C840A21903; Mon, 15 Apr 2019 16:45:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1555346718; bh=0UbWpcxSqUbmxZ0t4F63iEJjb6wYrrsxeEA5HqtL0sc=; h=From:To:Cc:Subject:Date:From; b=Wm17CJSI7ozvB36LpqCH5bwXEy44+ssuk1y74Jrsp8ElV+1u1g153rneADoxbf1Ap WYuzscFnqzVQ9iy1tf/u4njBhijt9BC/gh0ylIeG4ECrEs1+RNeso0dAmY4BQ+hRk9 NqnuKNrGeZnSqQYrwBN+2fWFPswF6VDx6ZUd+s38= From: Jeff Layton To: zyan@redhat.com, sage@redhat.com, idryomov@gmail.com Cc: ceph-devel@vger.kernel.org, bengland@redhat.com Subject: [PATCH] ceph: always clone dentry name when building MDS request Date: Mon, 15 Apr 2019 12:45:15 -0400 Message-Id: <20190415164515.25767-1-jlayton@kernel.org> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Ben reported tripping the BUG_ON in create_request_message during some performance testing. Analysis of the vmcore showed that the length of the r_dentry->d_name string changed after we allocated the buffer, but before we encoded it. build_dentry_path returns pointers to d_name in the common case of non-snapped dentries, but this optimization isn't safe. Instead, make a copy of the string in this case. That is less efficient, but safe. Reported-by: Ben England Signed-off-by: Jeff Layton --- fs/ceph/mds_client.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index e09feadd2ae1..4cfefe118128 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2159,9 +2159,35 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base, return path; } +/* Duplicate the dentry->d_name.name safely */ +static int clone_dentry_name(struct dentry *dentry, const char **ppath, + int *ppathlen) +{ + u32 len; + char *name; +retry: + len = READ_ONCE(dentry->d_name.len); + name = kmalloc(len + 1, GFP_NOFS); + if (!name) + return -ENOMEM; + + spin_lock(&dentry->d_lock); + if (dentry->d_name.len != len) { + spin_unlock(&dentry->d_lock); + kfree(name); + goto retry; + } + memcpy(name, dentry->d_name.name, len); + spin_unlock(&dentry->d_lock); + + name[len] = '\0'; + *ppath = name; + *ppathlen = len; + return 0; +} + static int build_dentry_path(struct dentry *dentry, struct inode *dir, - const char **ppath, int *ppathlen, u64 *pino, - int *pfreepath) + const char **ppath, int *ppathlen, u64 *pino) { char *path; @@ -2171,16 +2197,13 @@ static int build_dentry_path(struct dentry *dentry, struct inode *dir, if (dir && ceph_snap(dir) == CEPH_NOSNAP) { *pino = ceph_ino(dir); rcu_read_unlock(); - *ppath = dentry->d_name.name; - *ppathlen = dentry->d_name.len; - return 0; + return clone_dentry_name(dentry, ppath, ppathlen); } rcu_read_unlock(); path = ceph_mdsc_build_path(dentry, ppathlen, pino, 1); if (IS_ERR(path)) return PTR_ERR(path); *ppath = path; - *pfreepath = 1; return 0; } @@ -2222,8 +2245,9 @@ static int set_request_path_attr(struct inode *rinode, struct dentry *rdentry, dout(" inode %p %llx.%llx\n", rinode, ceph_ino(rinode), ceph_snap(rinode)); } else if (rdentry) { - r = build_dentry_path(rdentry, rdiri, ppath, pathlen, ino, - freepath); + r = build_dentry_path(rdentry, rdiri, ppath, pathlen, ino); + if (!r) + *freepath = 1; dout(" dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen, *ppath); } else if (rpath || rino) {