From patchwork Tue Mar 1 11:30:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 12764640 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D29CC433F5 for ; Tue, 1 Mar 2022 11:31:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234541AbiCALbl (ORCPT ); Tue, 1 Mar 2022 06:31:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40064 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234517AbiCALbk (ORCPT ); Tue, 1 Mar 2022 06:31:40 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 3551147557 for ; Tue, 1 Mar 2022 03:31:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646134259; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Vnqn/lnaL0weQOeCmAYm9XbVDETkaYhgSXSRNEZdbps=; b=VoaWoW4sxoDTTl8zy8rqe9+VELkz2Ft1xywmB9tX1dN3N983wKFMLn209WdulVgWOnRQ4N AcDzFy5rZEwwJAukDdSrK6BbtzXOnyAMrB6SWVEXYUXNZodHoNtpzD3b9+UtLqqmxolXC6 HO8CEcjSwKinHR1QP+ifdgxbks/MJ4Y= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-595-LlJzjtM0OpiZ-5SJb1j97g-1; Tue, 01 Mar 2022 06:30:58 -0500 X-MC-Unique: LlJzjtM0OpiZ-5SJb1j97g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id EDD15FC86; Tue, 1 Mar 2022 11:30:56 +0000 (UTC) Received: from lxbceph1.gsslab.pek2.redhat.com (unknown [10.72.47.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8588883195; Tue, 1 Mar 2022 11:30:43 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: idryomov@gmail.com, vshankar@redhat.com, lhenriques@suse.de, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v2 1/7] ceph: fail the request when failing to decode dentry names Date: Tue, 1 Mar 2022 19:30:09 +0800 Message-Id: <20220301113015.498041-2-xiubli@redhat.com> In-Reply-To: <20220301113015.498041-1-xiubli@redhat.com> References: <20220301113015.498041-1-xiubli@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li ------------[ cut here ]------------ kernel BUG at fs/ceph/dir.c:537! invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI CPU: 16 PID: 21641 Comm: ls Tainted: G E 5.17.0-rc2+ #92 Hardware name: Red Hat RHEV Hypervisor, BIOS 1.11.0-2.el7 04/01/2014 The corresponding code in ceph_readdir() is: BUG_ON(rde->offset < ctx->pos); Signed-off-by: Xiubo Li --- fs/ceph/dir.c | 13 +++++++------ fs/ceph/inode.c | 5 +++-- fs/ceph/mds_client.c | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index a449f4a07c07..6be0c1f793c2 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -534,6 +534,13 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) .ctext_len = rde->altname_len }; u32 olen = oname.len; + err = ceph_fname_to_usr(&fname, &tname, &oname, NULL); + if (err) { + pr_err("%s unable to decode %.*s, got %d\n", __func__, + rde->name_len, rde->name, err); + goto out; + } + BUG_ON(rde->offset < ctx->pos); BUG_ON(!rde->inode.in); @@ -542,12 +549,6 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) i, rinfo->dir_nr, ctx->pos, rde->name_len, rde->name, &rde->inode.in); - err = ceph_fname_to_usr(&fname, &tname, &oname, NULL); - if (err) { - dout("Unable to decode %.*s. Skipping it.\n", rde->name_len, rde->name); - continue; - } - if (!dir_emit(ctx, oname.name, oname.len, ceph_present_ino(inode->i_sb, le64_to_cpu(rde->inode.in->ino)), le32_to_cpu(rde->inode.in->mode) >> 12)) { diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 8b0832271fdf..2bc2f02b84e8 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1898,8 +1898,9 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, err = ceph_fname_to_usr(&fname, &tname, &oname, &is_nokey); if (err) { - dout("Unable to decode %.*s. Skipping it.", rde->name_len, rde->name); - continue; + pr_err("%s unable to decode %.*s, got %d\n", __func__, + rde->name_len, rde->name, err); + goto out; } dname.name = oname.name; diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 914a6e68bb56..94b4c6508044 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -3474,7 +3474,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) if (err == 0) { if (result == 0 && (req->r_op == CEPH_MDS_OP_READDIR || req->r_op == CEPH_MDS_OP_LSSNAP)) - ceph_readdir_prepopulate(req, req->r_session); + err = ceph_readdir_prepopulate(req, req->r_session); } current->journal_info = NULL; mutex_unlock(&req->r_fill_mutex); From patchwork Tue Mar 1 11:30:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 12764641 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BE48DC433F5 for ; Tue, 1 Mar 2022 11:31:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234548AbiCALbx (ORCPT ); Tue, 1 Mar 2022 06:31:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40288 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234545AbiCALbw (ORCPT ); Tue, 1 Mar 2022 06:31:52 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D39D74756B for ; Tue, 1 Mar 2022 03:31:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646134270; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9C1ZCf8TZ57/xy4FPsEYt8M4QOifCwiy9tDGiT2myFE=; b=FEQ8zXLX9qxEKf2cUNkeNAGX5FxMjWKwR9JdbNGDOP423qz51ElQXU2ZSJBKlFtnsQf9IH Xqzr7UvnA4nQsgfjlT6tFKoqA931CMDw+FHXv3Y/qhkFRfuud9nS8FeCt0A15mCrNehPIj 4RSFYszjmjQXwCAXAIq9ChM6BshOa0E= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-567-FbwP1oLiPZijmWXCSOn7OQ-1; Tue, 01 Mar 2022 06:31:07 -0500 X-MC-Unique: FbwP1oLiPZijmWXCSOn7OQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D6AFC824FA6; Tue, 1 Mar 2022 11:31:05 +0000 (UTC) Received: from lxbceph1.gsslab.pek2.redhat.com (unknown [10.72.47.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4954E83195; Tue, 1 Mar 2022 11:30:57 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: idryomov@gmail.com, vshankar@redhat.com, lhenriques@suse.de, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v2 2/7] ceph: skip the memories when received a higher version of message Date: Tue, 1 Mar 2022 19:30:10 +0800 Message-Id: <20220301113015.498041-3-xiubli@redhat.com> In-Reply-To: <20220301113015.498041-1-xiubli@redhat.com> References: <20220301113015.498041-1-xiubli@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li We should skip the extra memories which are from the higher version just likes the libcephfs client does. URL: https://tracker.ceph.com/issues/54430 Signed-off-by: Xiubo Li --- fs/ceph/mds_client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 94b4c6508044..3dea96df4769 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -326,6 +326,7 @@ static int parse_reply_info_lease(void **p, void *end, goto bad; ceph_decode_32_safe(p, end, struct_len, bad); + end = *p + struct_len; } else { struct_len = sizeof(**lease); *altname_len = 0; @@ -346,6 +347,7 @@ static int parse_reply_info_lease(void **p, void *end, *altname = NULL; *altname_len = 0; } + *p = end; } return 0; bad: From patchwork Tue Mar 1 11:30:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 12764642 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6519C433F5 for ; Tue, 1 Mar 2022 11:31:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234574AbiCALcJ (ORCPT ); Tue, 1 Mar 2022 06:32:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40698 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234587AbiCALcG (ORCPT ); Tue, 1 Mar 2022 06:32:06 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B81195F8E9 for ; Tue, 1 Mar 2022 03:31:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646134280; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aLTIHIi0HP06Qa2fyBPhTC5jp/VPy3itHyu9y+jwyYc=; b=iHP4yvkPKn/DCnTzMQdXkMe8MT3Hav3lr90vdSNTEQo8HBqv6z1lSMfyh7LMeMbL6RyTXY UWLLwb7IpDQIKktJNBCLOea2X2vRJB/crjEm3OjGz9L1fKmT2RDGJCJG5KcmhR14NUyw4S VbJoE9cErQHRuHDclv3ZJNSAQ2nUX30= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-185-fCE_oASyP_aQLzvNB4O_kg-1; Tue, 01 Mar 2022 06:31:17 -0500 X-MC-Unique: fCE_oASyP_aQLzvNB4O_kg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id AED2D1091DA1; Tue, 1 Mar 2022 11:31:16 +0000 (UTC) Received: from lxbceph1.gsslab.pek2.redhat.com (unknown [10.72.47.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 581B183195; Tue, 1 Mar 2022 11:31:06 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: idryomov@gmail.com, vshankar@redhat.com, lhenriques@suse.de, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v2 3/7] ceph: do not dencrypt the dentry name twice for readdir Date: Tue, 1 Mar 2022 19:30:11 +0800 Message-Id: <20220301113015.498041-4-xiubli@redhat.com> In-Reply-To: <20220301113015.498041-1-xiubli@redhat.com> References: <20220301113015.498041-1-xiubli@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li Signed-off-by: Xiubo Li --- fs/ceph/dir.c | 66 +++++++++++++++++++++----------------------- fs/ceph/inode.c | 15 ++++++++++ fs/ceph/mds_client.h | 1 + 3 files changed, 47 insertions(+), 35 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 6be0c1f793c2..e3917b4426e8 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -316,8 +316,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) int err; unsigned frag = -1; struct ceph_mds_reply_info_parsed *rinfo; - struct fscrypt_str tname = FSTR_INIT(NULL, 0); - struct fscrypt_str oname = FSTR_INIT(NULL, 0); + char *dentry_name = NULL; dout("readdir %p file %p pos %llx\n", inode, file, ctx->pos); if (dfi->file_info.flags & CEPH_F_ATEND) @@ -345,10 +344,6 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) ctx->pos = 2; } - err = fscrypt_prepare_readdir(inode); - if (err) - goto out; - spin_lock(&ci->i_ceph_lock); /* request Fx cap. if have Fx, we don't need to release Fs cap * for later create/unlink. */ @@ -369,14 +364,6 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) spin_unlock(&ci->i_ceph_lock); } - err = ceph_fname_alloc_buffer(inode, &tname); - if (err < 0) - goto out; - - err = ceph_fname_alloc_buffer(inode, &oname); - if (err < 0) - goto out; - /* proceed with a normal readdir */ more: /* do we have the correct frag content buffered? */ @@ -525,40 +512,49 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) } } } + + dentry_name = kmalloc(280, GFP_KERNEL); + if (!dentry_name) { + err = -ENOMEM; + goto out; + } + for (; i < rinfo->dir_nr; i++) { struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i; - struct ceph_fname fname = { .dir = inode, - .name = rde->name, - .name_len = rde->name_len, - .ctext = rde->altname, - .ctext_len = rde->altname_len }; - u32 olen = oname.len; - - err = ceph_fname_to_usr(&fname, &tname, &oname, NULL); - if (err) { - pr_err("%s unable to decode %.*s, got %d\n", __func__, - rde->name_len, rde->name, err); - goto out; - } + struct dentry *dn = rde->dentry; + int name_len; BUG_ON(rde->offset < ctx->pos); BUG_ON(!rde->inode.in); + BUG_ON(!rde->dentry); ctx->pos = rde->offset; - dout("readdir (%d/%d) -> %llx '%.*s' %p\n", - i, rinfo->dir_nr, ctx->pos, - rde->name_len, rde->name, &rde->inode.in); - if (!dir_emit(ctx, oname.name, oname.len, + spin_lock(&dn->d_lock); + memcpy(dentry_name, dn->d_name.name, dn->d_name.len); + name_len = dn->d_name.len; + spin_unlock(&dn->d_lock); + + dentry_name[name_len] = '\0'; + dout("readdir (%d/%d) -> %llx '%s' %p\n", + i, rinfo->dir_nr, ctx->pos, dentry_name, &rde->inode.in); + + dput(dn); + rde->dentry = NULL; + + if (!dir_emit(ctx, dentry_name, name_len, ceph_present_ino(inode->i_sb, le64_to_cpu(rde->inode.in->ino)), le32_to_cpu(rde->inode.in->mode) >> 12)) { dout("filldir stopping us...\n"); err = 0; + for (; i < rinfo->dir_nr; i++) { + rde = rinfo->dir_entries + i; + dput(rde->dentry); + rde->dentry = NULL; + } goto out; } - /* Reset the lengths to their original allocated vals */ - oname.len = olen; ctx->pos++; } @@ -616,8 +612,8 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) err = 0; dout("readdir %p file %p done.\n", inode, file); out: - ceph_fname_free_buffer(inode, &tname); - ceph_fname_free_buffer(inode, &oname); + if (dentry_name) + kfree(dentry_name); return err; } diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 2bc2f02b84e8..877e699fe43b 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1903,6 +1903,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, goto out; } + rde->dentry = NULL; dname.name = oname.name; dname.len = oname.len; dname.hash = full_name_hash(parent, dname.name, dname.len); @@ -1963,6 +1964,12 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, goto retry_lookup; } + /* + * ceph_readdir will use the dentry to get the name + * to avoid doing the dencrypt again there. + */ + rde->dentry = dget(dn); + /* inode */ if (d_really_is_positive(dn)) { in = d_inode(dn); @@ -2025,6 +2032,14 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, dput(dn); } out: + if (err) { + for (; i >= 0; i--) { + struct ceph_mds_reply_dir_entry *rde; + + rde = rinfo->dir_entries + i; + dput(rde->dentry); + } + } if (err == 0 && skipped == 0) { set_bit(CEPH_MDS_R_DID_PREPOPULATE, &req->r_req_flags); req->r_readdir_cache_idx = cache_ctl.index; diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 0dfe24f94567..663d7754d57d 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -96,6 +96,7 @@ struct ceph_mds_reply_info_in { }; struct ceph_mds_reply_dir_entry { + struct dentry *dentry; char *name; u8 *altname; u32 name_len; From patchwork Tue Mar 1 11:30:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 12764643 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CCB76C433FE for ; Tue, 1 Mar 2022 11:31:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234565AbiCALcL (ORCPT ); Tue, 1 Mar 2022 06:32:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40702 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234598AbiCALcH (ORCPT ); Tue, 1 Mar 2022 06:32:07 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 38275931A6 for ; Tue, 1 Mar 2022 03:31:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646134283; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7uoyV3UDN+h6T1/T0ayIRoeu/53zPzpKcvLRThO7JGA=; b=dG1TFP1xbj1G2DvUzbUrYi1nrnL5daazyjHF8rIHHeMU0H81s8c5yAWZo0TYg3Ckwc1dw3 af2DhhP09gFDv4dyBesFqPD/M0bau+ZKH1SDzsilPqASP57UIwSM1AnfPOOX1LIbzep+AS KHXoVJw3FTFi6J30tNZxLxWU6syxWbY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-582-8szG7X--MYSCO1jF1qW9YQ-1; Tue, 01 Mar 2022 06:31:20 -0500 X-MC-Unique: 8szG7X--MYSCO1jF1qW9YQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3376E801AB2; Tue, 1 Mar 2022 11:31:19 +0000 (UTC) Received: from lxbceph1.gsslab.pek2.redhat.com (unknown [10.72.47.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3122883195; Tue, 1 Mar 2022 11:31:16 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: idryomov@gmail.com, vshankar@redhat.com, lhenriques@suse.de, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v2 4/7] ceph: add ceph_get_snap_parent_inode() support Date: Tue, 1 Mar 2022 19:30:12 +0800 Message-Id: <20220301113015.498041-5-xiubli@redhat.com> In-Reply-To: <20220301113015.498041-1-xiubli@redhat.com> References: <20220301113015.498041-1-xiubli@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li Get the parent inode for the snap directory ".snap", if the inode is not a snap directory just return it with the reference increased. Signed-off-by: Xiubo Li --- fs/ceph/snap.c | 24 ++++++++++++++++++++++++ fs/ceph/super.h | 1 + 2 files changed, 25 insertions(+) diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 66a1a92cf579..5e9656926dc7 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -1247,3 +1247,27 @@ void ceph_cleanup_snapid_map(struct ceph_mds_client *mdsc) kfree(sm); } } + +/* + * Get the parent inode for the snap directory ".snap", + * if the inode is not a snap directory just return it + * with the reference increased. + */ +struct inode *ceph_get_snap_parent_inode(struct inode *inode) +{ + struct inode *pinode; + + if (ceph_snap(inode) == CEPH_SNAPDIR) { + struct ceph_vino vino = { + .ino = ceph_ino(inode), + .snap = CEPH_NOSNAP, + }; + pinode = ceph_find_inode(inode->i_sb, vino); + BUG_ON(!pinode); + } else { + ihold(inode); + pinode = inode; + } + + return pinode; +} diff --git a/fs/ceph/super.h b/fs/ceph/super.h index d5a4d311f4c2..e7c69ca5e289 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -969,6 +969,7 @@ extern void ceph_put_snapid_map(struct ceph_mds_client* mdsc, struct ceph_snapid_map *sm); extern void ceph_trim_snapid_map(struct ceph_mds_client *mdsc); extern void ceph_cleanup_snapid_map(struct ceph_mds_client *mdsc); +extern struct inode *ceph_get_snap_parent_inode(struct inode *inode); void ceph_umount_begin(struct super_block *sb); From patchwork Tue Mar 1 11:30:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 12764644 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 334D0C433EF for ; Tue, 1 Mar 2022 11:31:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234572AbiCALcL (ORCPT ); Tue, 1 Mar 2022 06:32:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40720 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234581AbiCALcI (ORCPT ); Tue, 1 Mar 2022 06:32:08 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DC0A648884 for ; Tue, 1 Mar 2022 03:31:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646134286; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xj+bqKTTOOEgANLaC4Y+ImOrJ3xRHijIU6BIGXExg8g=; b=EV7UwTXTBdg6hTFZtkCH/YWaG3/T5jMzba8KqF75fGBDvOXigpCiwxguG4Wl6X7Hk612hp 21kVr3sqOfbHlEt4cNKthG5BjIaZ2S8Uu7cN74VhIN4/vNjD0yET964KFx7AtOpZ/YJChM TxLyr4XpBMb+HYKHrjNf7lESubTNt8A= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-256-4RhqtFRzPyiam0j0Thx64w-1; Tue, 01 Mar 2022 06:31:22 -0500 X-MC-Unique: 4RhqtFRzPyiam0j0Thx64w-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C746C1854E21; Tue, 1 Mar 2022 11:31:21 +0000 (UTC) Received: from lxbceph1.gsslab.pek2.redhat.com (unknown [10.72.47.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id A91A783195; Tue, 1 Mar 2022 11:31:19 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: idryomov@gmail.com, vshankar@redhat.com, lhenriques@suse.de, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v2 5/7] ceph: use the parent inode of '.snap' to dencrypt the names for readdir Date: Tue, 1 Mar 2022 19:30:13 +0800 Message-Id: <20220301113015.498041-6-xiubli@redhat.com> In-Reply-To: <20220301113015.498041-1-xiubli@redhat.com> References: <20220301113015.498041-1-xiubli@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li The inode for '.snap' directory will always with no key setup, so we can use the parent inode to do this. Signed-off-by: Xiubo Li --- fs/ceph/inode.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 877e699fe43b..a6c4965e5363 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1817,7 +1817,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info; struct qstr dname; struct dentry *dn; - struct inode *in; + struct inode *in, *pinode; int err = 0, skipped = 0, ret, i; u32 frag = le32_to_cpu(req->r_args.readdir.frag); u32 last_hash = 0; @@ -1876,11 +1876,13 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, cache_ctl.index = req->r_readdir_cache_idx; fpos_offset = req->r_readdir_offset; - err = ceph_fname_alloc_buffer(inode, &tname); + pinode = ceph_get_snap_parent_inode(inode); + + err = ceph_fname_alloc_buffer(pinode, &tname); if (err < 0) goto out; - err = ceph_fname_alloc_buffer(inode, &oname); + err = ceph_fname_alloc_buffer(pinode, &oname); if (err < 0) goto out; @@ -1890,7 +1892,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i; struct ceph_vino tvino; u32 olen = oname.len; - struct ceph_fname fname = { .dir = inode, + struct ceph_fname fname = { .dir = pinode, .name = rde->name, .name_len = rde->name_len, .ctext = rde->altname, @@ -2045,8 +2047,9 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, req->r_readdir_cache_idx = cache_ctl.index; } ceph_readdir_cache_release(&cache_ctl); - ceph_fname_free_buffer(inode, &tname); - ceph_fname_free_buffer(inode, &oname); + ceph_fname_free_buffer(pinode, &tname); + ceph_fname_free_buffer(pinode, &oname); + iput(pinode); dout("readdir_prepopulate done\n"); return err; } From patchwork Tue Mar 1 11:30:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 12764645 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C2D67C433EF for ; Tue, 1 Mar 2022 11:31:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234581AbiCALcO (ORCPT ); Tue, 1 Mar 2022 06:32:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40854 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234562AbiCALcN (ORCPT ); Tue, 1 Mar 2022 06:32:13 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 0A03C4756D for ; Tue, 1 Mar 2022 03:31:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646134291; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ygLpJpFvbsvZc/yCqCvDynfqe5ZVGFqHKCCR9n+1pwY=; b=YO+f/k3gvzf63bX5MJ/nKjbKgiQ2FJzDrvDuW0M5qUuIaVJ0ZnugSJHEuccOsR3HlxboxX wJhH+dA2d9LvsfVrF9FPdfQhOLJs8+btuBibfgNaFK2uUhBfayoExEIrgezhdpUDxzMv7F 8v/yr0WlL2I3To96RnRim+EclZ3fvmw= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-557-VgqCIChiNQ2vnkuEwMQUeQ-1; Tue, 01 Mar 2022 06:31:28 -0500 X-MC-Unique: VgqCIChiNQ2vnkuEwMQUeQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0538D1854E26; Tue, 1 Mar 2022 11:31:27 +0000 (UTC) Received: from lxbceph1.gsslab.pek2.redhat.com (unknown [10.72.47.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 499CB842CB; Tue, 1 Mar 2022 11:31:22 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: idryomov@gmail.com, vshankar@redhat.com, lhenriques@suse.de, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v2 6/7] ceph: use the parent inode of '.snap' to encrypt name to build path Date: Tue, 1 Mar 2022 19:30:14 +0800 Message-Id: <20220301113015.498041-7-xiubli@redhat.com> In-Reply-To: <20220301113015.498041-1-xiubli@redhat.com> References: <20220301113015.498041-1-xiubli@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li The inode for '.snap' directory will always with no key setup, so we can use the parent inode to do this. Signed-off-by: Xiubo Li --- fs/ceph/mds_client.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 3dea96df4769..5433e6050563 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2465,8 +2465,8 @@ static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen) */ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for_wire) { - struct dentry *cur; - struct inode *inode; + struct dentry *cur, *parent; + struct inode *inode, *pinode; char *path; int pos; unsigned seq; @@ -2479,13 +2479,16 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for if (!path) return ERR_PTR(-ENOMEM); retry: + pinode = NULL; + parent = NULL; pos = PATH_MAX - 1; path[pos] = '\0'; seq = read_seqbegin(&rename_lock); cur = dget(dentry); for (;;) { - struct dentry *parent; + parent = dget_parent(cur); + pinode = ceph_get_snap_parent_inode(d_inode(parent)); spin_lock(&cur->d_lock); inode = d_inode(cur); @@ -2493,12 +2496,11 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for dout("build_path path+%d: %p SNAPDIR\n", pos, cur); spin_unlock(&cur->d_lock); - parent = dget_parent(cur); } else if (for_wire && inode && dentry != cur && ceph_snap(inode) == CEPH_NOSNAP) { spin_unlock(&cur->d_lock); pos++; /* get rid of any prepended '/' */ break; - } else if (!for_wire || !IS_ENCRYPTED(d_inode(cur->d_parent))) { + } else if (!for_wire || !IS_ENCRYPTED(pinode)) { pos -= cur->d_name.len; if (pos < 0) { spin_unlock(&cur->d_lock); @@ -2506,7 +2508,6 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for } memcpy(path + pos, cur->d_name.name, cur->d_name.len); spin_unlock(&cur->d_lock); - parent = dget_parent(cur); } else { int len, ret; char buf[FSCRYPT_BASE64URL_CHARS(NAME_MAX)]; @@ -2518,32 +2519,32 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for memcpy(buf, cur->d_name.name, cur->d_name.len); len = cur->d_name.len; spin_unlock(&cur->d_lock); - parent = dget_parent(cur); - ret = __fscrypt_prepare_readdir(d_inode(parent)); + ret = __fscrypt_prepare_readdir(pinode); if (ret < 0) { dput(parent); dput(cur); + iput(pinode); return ERR_PTR(ret); } - if (fscrypt_has_encryption_key(d_inode(parent))) { - len = ceph_encode_encrypted_fname(d_inode(parent), cur, buf); + if (fscrypt_has_encryption_key(pinode)) { + len = ceph_encode_encrypted_fname(pinode, cur, buf); if (len < 0) { dput(parent); dput(cur); + iput(pinode); return ERR_PTR(len); } } pos -= len; - if (pos < 0) { - dput(parent); + if (pos < 0) break; - } memcpy(path + pos, buf, len); } dput(cur); cur = parent; + parent = NULL; /* Are we at the root? */ if (IS_ROOT(cur)) @@ -2554,7 +2555,13 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for break; path[pos] = '/'; + iput(pinode); + pinode = NULL; } + if (pinode) + iput(pinode); + if (parent) + dput(parent); inode = d_inode(cur); base = inode ? ceph_ino(inode) : 0; dput(cur); From patchwork Tue Mar 1 11:30:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiubo Li X-Patchwork-Id: 12764646 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DCF22C433F5 for ; Tue, 1 Mar 2022 11:31:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234577AbiCALcQ (ORCPT ); Tue, 1 Mar 2022 06:32:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40930 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234576AbiCALcQ (ORCPT ); Tue, 1 Mar 2022 06:32:16 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 9A87D4831F for ; Tue, 1 Mar 2022 03:31:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646134293; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OGge9W4vF08bzdYKfr/U0zp+olfejarbp2Ukb1l/1+s=; b=FrGybINzEPoYp2m0s93KGrx/ezQX5tFgZRRQf1Dx0TlD7n55SBydIvIPdQz0Jfi816R42B caO8xuKQrp7DuSfGo9NRN5VHw6zngNT7hWz8hnyfqnSNyP/d7LxFe7SryOrJt/M2O+5lnI dI28y3cnq0rVBfaIoVVZTHDkD0G7HZU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-172-1nex_2gSPKGaS_MDQUCMDA-1; Tue, 01 Mar 2022 06:31:30 -0500 X-MC-Unique: 1nex_2gSPKGaS_MDQUCMDA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 768B41854E27; Tue, 1 Mar 2022 11:31:29 +0000 (UTC) Received: from lxbceph1.gsslab.pek2.redhat.com (unknown [10.72.47.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6CC1A83195; Tue, 1 Mar 2022 11:31:27 +0000 (UTC) From: xiubli@redhat.com To: jlayton@kernel.org Cc: idryomov@gmail.com, vshankar@redhat.com, lhenriques@suse.de, ceph-devel@vger.kernel.org, Xiubo Li Subject: [PATCH v2 7/7] ceph: try to encrypt/decrypt long snap name Date: Tue, 1 Mar 2022 19:30:15 +0800 Message-Id: <20220301113015.498041-8-xiubli@redhat.com> In-Reply-To: <20220301113015.498041-1-xiubli@redhat.com> References: <20220301113015.498041-1-xiubli@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org From: Xiubo Li The child realm will inherit parents' snapshots, and the snapshot names will be in long name format: "_${ENCRYPTED-NAME}_${PARENT-INO}" We need to parse the ENCRYPTED-NAME and to the decryption for readdir and when lookup a snapshot we also need to encrypt the real snapshot name and then switch to the long snap name to do the lookup in MDS. Signed-off-by: Xiubo Li --- fs/ceph/crypto.c | 75 ++++++++++++++++++++++++++++++++++++---- fs/ceph/crypto.h | 2 +- fs/ceph/dir.c | 26 +++++++++++--- fs/ceph/inode.c | 81 ++++++++++++++++++++++++++++++++++++++++---- fs/ceph/mds_client.c | 22 ++++++++---- fs/ceph/mds_client.h | 2 ++ fs/ceph/super.h | 1 + 7 files changed, 184 insertions(+), 25 deletions(-) diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c index 5a87e7385d3f..3af0d7a0ed10 100644 --- a/fs/ceph/crypto.c +++ b/fs/ceph/crypto.c @@ -128,14 +128,61 @@ void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, struct ceph_acl_se swap(req->r_fscrypt_auth, as->fscrypt_auth); } -int ceph_encode_encrypted_fname(const struct inode *parent, struct dentry *dentry, char *buf) +int ceph_encode_encrypted_fname(struct inode *parent, struct dentry *dentry, char *buf) { + struct ceph_dentry_info *di = ceph_dentry(dentry); + struct qstr d_name = {.len = 0, .name = NULL}; + struct inode *pinode = parent; u32 len; int elen; int ret; u8 *cryptbuf; + char *p; + unsigned char *last = NULL; - WARN_ON_ONCE(!fscrypt_has_encryption_key(parent)); + // The long snap name format is "_${SNAP-NAME}_{INO}" + if (di->long_snap_name) { + struct ceph_vino vino = { .snap = CEPH_NOSNAP }; + + last = strrchr(dentry->d_name.name, '_'); + if (!last) + return -EINVAL; + + ret = kstrtou64(last + 1, 0, &vino.ino); + if (ret) { + kfree(d_name.name); + return ret; + } + pinode = ceph_get_inode(parent->i_sb, vino, NULL); + ret = __fscrypt_prepare_readdir(pinode); + if (ret < 0) { + iput(pinode); + return ret; + } + if (!fscrypt_has_encryption_key(pinode)) { + memcpy(buf, dentry->d_name.name, dentry->d_name.len); + buf[dentry->d_name.len] = '\0'; + iput(pinode); + return dentry->d_name.len; + } + + d_name.len = last - dentry->d_name.name - 1; + d_name.name = kstrndup(dentry->d_name.name + 1, + d_name.len, GFP_KERNEL); + if (!d_name.name) + return -ENOMEM; + p = buf + 1; + buf[0] = '_'; + dout(" long_snap_name real snap name: %s, ino: %s\n", + d_name.name, last + 1); + } else { + p = buf; + d_name.name = dentry->d_name.name; + d_name.len = dentry->d_name.len; + ihold(parent); + } + + WARN_ON_ONCE(!fscrypt_has_encryption_key(pinode)); /* * convert cleartext dentry name to ciphertext @@ -144,20 +191,31 @@ int ceph_encode_encrypted_fname(const struct inode *parent, struct dentry *dentr * * See: fscrypt_setup_filename */ - if (!fscrypt_fname_encrypted_size(parent, dentry->d_name.len, NAME_MAX, &len)) + if (!fscrypt_fname_encrypted_size(pinode, d_name.len, NAME_MAX, &len)) { + iput(pinode); return -ENAMETOOLONG; + } /* Allocate a buffer appropriate to hold the result */ cryptbuf = kmalloc(len > CEPH_NOHASH_NAME_MAX ? NAME_MAX : len, GFP_KERNEL); - if (!cryptbuf) + if (!cryptbuf) { + iput(pinode); + if (di->long_snap_name) + kfree(d_name.name); return -ENOMEM; + } - ret = fscrypt_fname_encrypt(parent, &dentry->d_name, cryptbuf, len); + ret = fscrypt_fname_encrypt(pinode, &d_name, cryptbuf, len); if (ret) { + iput(pinode); kfree(cryptbuf); + if (di->long_snap_name) + kfree(d_name.name); return ret; } + iput(pinode); + /* hash the end if the name is long enough */ if (len > CEPH_NOHASH_NAME_MAX) { u8 hash[SHA256_DIGEST_SIZE]; @@ -170,8 +228,13 @@ int ceph_encode_encrypted_fname(const struct inode *parent, struct dentry *dentr } /* base64 encode the encrypted name */ - elen = fscrypt_base64url_encode(cryptbuf, len, buf); + elen = fscrypt_base64url_encode(cryptbuf, len, p); kfree(cryptbuf); + if (di->long_snap_name) { + kfree(d_name.name); + strcpy(p + elen, last); + elen += 1 + strlen(last); + } dout("base64-encoded ciphertext name = %.*s\n", elen, buf); return elen; } diff --git a/fs/ceph/crypto.h b/fs/ceph/crypto.h index 1e08f8a64ad6..e99b457a776a 100644 --- a/fs/ceph/crypto.h +++ b/fs/ceph/crypto.h @@ -90,7 +90,7 @@ void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc); int ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode, struct ceph_acl_sec_ctx *as); void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, struct ceph_acl_sec_ctx *as); -int ceph_encode_encrypted_fname(const struct inode *parent, struct dentry *dentry, char *buf); +int ceph_encode_encrypted_fname(struct inode *parent, struct dentry *dentry, char *buf); static inline int ceph_fname_alloc_buffer(struct inode *parent, struct fscrypt_str *fname) { diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index e3917b4426e8..86c04e248f07 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -50,6 +50,7 @@ static int ceph_d_init(struct dentry *dentry) di->time = jiffies; dentry->d_fsdata = di; INIT_LIST_HEAD(&di->lease_list); + di->long_snap_name = false; atomic64_inc(&mdsc->metric.total_dentries); @@ -547,7 +548,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) le32_to_cpu(rde->inode.in->mode) >> 12)) { dout("filldir stopping us...\n"); err = 0; - for (; i < rinfo->dir_nr; i++) { + for (++i; i < rinfo->dir_nr; i++) { rde = rinfo->dir_entries + i; dput(rde->dentry); rde->dentry = NULL; @@ -775,7 +776,9 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, { struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb); + struct ceph_dentry_info *di = ceph_dentry(dentry); struct ceph_mds_request *req; + struct inode *pinode = dir; int op; int mask; int err; @@ -786,21 +789,22 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, if (dentry->d_name.len > NAME_MAX) return ERR_PTR(-ENAMETOOLONG); - if (IS_ENCRYPTED(dir)) { - err = __fscrypt_prepare_readdir(dir); + pinode = ceph_get_snap_parent_inode(dir); + if (IS_ENCRYPTED(pinode)) { + err = __fscrypt_prepare_readdir(pinode); if (err) return ERR_PTR(err); - if (!fscrypt_has_encryption_key(dir)) { + if (!fscrypt_has_encryption_key(pinode)) { spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_NOKEY_NAME; spin_unlock(&dentry->d_lock); } } + iput(pinode); /* can we conclude ENOENT locally? */ if (d_really_is_negative(dentry)) { struct ceph_inode_info *ci = ceph_inode(dir); - struct ceph_dentry_info *di = ceph_dentry(dentry); spin_lock(&ci->i_ceph_lock); dout(" dir %p flags are 0x%lx\n", dir, ci->i_ceph_flags); @@ -823,6 +827,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, op = ceph_snap(dir) == CEPH_SNAPDIR ? CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP; +retry: req = ceph_mdsc_create_request(mdsc, op, USE_ANY_MDS); if (IS_ERR(req)) return ERR_CAST(req); @@ -841,6 +846,16 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, if (err == -ENOENT) { struct dentry *res; + // long snap name with the format "_${SNAP-NAME}_${INO}" ? + if (IS_ENCRYPTED(pinode) && !di->long_snap_name && + op == CEPH_MDS_OP_LOOKUPSNAP && + dentry->d_name.name[0] == '_') { + di->long_snap_name = true; + ceph_mdsc_put_request(req); + dout("lookup retry with long snap name set.\n"); + goto retry; + } + res = ceph_handle_snapdir(req, dentry); if (IS_ERR(res)) { err = PTR_ERR(res); @@ -848,6 +863,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, dentry = res; err = 0; } + di->long_snap_name = false; } dentry = ceph_finish_lookup(req, dentry, err); ceph_mdsc_put_request(req); /* will dput(dentry) */ diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index a6c4965e5363..ec0c71b08b7c 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1825,6 +1825,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, struct ceph_readdir_cache_control cache_ctl = {}; struct fscrypt_str tname = FSTR_INIT(NULL, 0); struct fscrypt_str oname = FSTR_INIT(NULL, 0); + char *long_snap_name = NULL; if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) return readdir_prepopulate_inodes_only(req, session); @@ -1886,23 +1887,88 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, if (err < 0) goto out; + long_snap_name = kzalloc(512, GFP_NOFS); + if (!long_snap_name) { + err = -ENOMEM; + goto out; + } + /* FIXME: release caps/leases if error occurs */ for (i = 0; i < rinfo->dir_nr; i++) { bool is_nokey = false; struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i; struct ceph_vino tvino; u32 olen = oname.len; + struct ceph_dentry_info *di; struct ceph_fname fname = { .dir = pinode, .name = rde->name, .name_len = rde->name_len, .ctext = rde->altname, .ctext_len = rde->altname_len }; - err = ceph_fname_to_usr(&fname, &tname, &oname, &is_nokey); - if (err) { - pr_err("%s unable to decode %.*s, got %d\n", __func__, - rde->name_len, rde->name, err); - goto out; + /* The long snap name will be "_${SNAP-NAME}_${INO}" */ + if (rde->long_snap_name) { + int len; + char *lsn, *last, ino_str[20]; + struct inode *_pinode; + struct ceph_vino vino = { + .snap = CEPH_NOSNAP, + }; + + // get the inode number of ${INO} + memcpy(long_snap_name, rde->name, rde->name_len); + long_snap_name[rde->name_len] = '\0'; + last = strrchr(long_snap_name, '_'); + if (!last) { + pr_err("%s long snapshot name %.*s badness\n", + __func__, rde->name_len, rde->name); + goto out; + } + last++; + len = rde->name_len - (last - long_snap_name); + memcpy(ino_str, last, len); + ino_str[len] = '\0'; + err = kstrtou64(ino_str, 0, &vino.ino); + if (err) + goto out; + _pinode = ceph_find_inode(inode->i_sb, vino); + BUG_ON(!_pinode); + + // is the ${INO} encrypted ? + if (IS_ENCRYPTED(_pinode)) { + len = rde->name_len - 2 - len; + fname.dir = _pinode; + fname.name = rde->name + 1; + fname.name_len = len; + + err = ceph_fname_to_usr(&fname, &tname, &oname, &is_nokey); + if (err) { + pr_err("%s unable to decode %.*s, got %d\n", __func__, + rde->name_len, rde->name, err); + iput(_pinode); + goto out; + } + lsn = kasprintf(GFP_NOFS, "_%s_%s", oname.name, ino_str); + if (!lsn) { + err = -ENOMEM; + iput(_pinode); + goto out; + } + len = strlen(lsn); + memcpy(oname.name, lsn, len); + oname.len = len; + } else { + memcpy(oname.name, fname.name, fname.name_len); + oname.len = fname.name_len; + } + iput(_pinode); + } else { + err = ceph_fname_to_usr(&fname, &tname, &oname, &is_nokey); + if (err) { + pr_err("%s unable to decode %.*s, got %d\n", __func__, + rde->name_len, rde->name, err); + goto out; + } } rde->dentry = NULL; @@ -1948,7 +2014,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, } else if (d_really_is_positive(dn) && (ceph_ino(d_inode(dn)) != tvino.ino || ceph_snap(d_inode(dn)) != tvino.snap)) { - struct ceph_dentry_info *di = ceph_dentry(dn); + di = ceph_dentry(dn); dout(" dn %p points to wrong inode %p\n", dn, d_inode(dn)); @@ -1971,6 +2037,8 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, * to avoid doing the dencrypt again there. */ rde->dentry = dget(dn); + di = ceph_dentry(dn); + di->long_snap_name = !!rde->long_snap_name; /* inode */ if (d_really_is_positive(dn)) { @@ -2050,6 +2118,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, ceph_fname_free_buffer(pinode, &tname); ceph_fname_free_buffer(pinode, &oname); iput(pinode); + kfree(long_snap_name); dout("readdir_prepopulate done\n"); return err; } diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 5433e6050563..f001d57b0bd0 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -309,7 +309,8 @@ static int parse_reply_info_dir(void **p, void *end, static int parse_reply_info_lease(void **p, void *end, struct ceph_mds_reply_lease **lease, - u64 features, u32 *altname_len, u8 **altname) + u64 features, u32 *altname_len, u8 **altname, + u8 *long_snap_name) { u8 struct_v; u32 struct_len; @@ -338,14 +339,16 @@ static int parse_reply_info_lease(void **p, void *end, *p += sizeof(**lease); if (features == (u64)-1) { + *altname = NULL; + *altname_len = 0; if (struct_v >= 2) { ceph_decode_32_safe(p, end, *altname_len, bad); ceph_decode_need(p, end, *altname_len, bad); *altname = *p; *p += *altname_len; - } else { - *altname = NULL; - *altname_len = 0; + } + if (struct_v >= 3) { + ceph_decode_8_safe(p, end, *long_snap_name, bad); } *p = end; } @@ -379,7 +382,8 @@ static int parse_reply_info_trace(void **p, void *end, *p += info->dname_len; err = parse_reply_info_lease(p, end, &info->dlease, features, - &info->altname_len, &info->altname); + &info->altname_len, &info->altname, + &info->long_snap_name); if (err < 0) goto out_bad; } @@ -447,7 +451,8 @@ static int parse_reply_info_readdir(void **p, void *end, /* dentry lease */ err = parse_reply_info_lease(p, end, &rde->lease, features, - &rde->altname_len, &rde->altname); + &rde->altname_len, &rde->altname, + &rde->long_snap_name); if (err) goto out_bad; @@ -2510,7 +2515,7 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for spin_unlock(&cur->d_lock); } else { int len, ret; - char buf[FSCRYPT_BASE64URL_CHARS(NAME_MAX)]; + char buf[FSCRYPT_BASE64URL_CHARS(NAME_MAX) + 20]; /* * Proactively copy name into buf, in case we need to present @@ -2783,6 +2788,9 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session, if (test_bit(CEPH_MDS_R_FSCRYPT_FILE, &req->r_req_flags)) len += sizeof(__le64); + /* extra chars '_' and '_${INO}' for long snap names */ + len += 60; + msg = ceph_msg_new2(CEPH_MSG_CLIENT_REQUEST, len, 1, GFP_NOFS, false); if (!msg) { msg = ERR_PTR(-ENOMEM); diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 663d7754d57d..5068f85c7505 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -104,6 +104,7 @@ struct ceph_mds_reply_dir_entry { struct ceph_mds_reply_lease *lease; struct ceph_mds_reply_info_in inode; loff_t offset; + u8 long_snap_name; }; struct ceph_mds_reply_xattr { @@ -129,6 +130,7 @@ struct ceph_mds_reply_info_parsed { u32 altname_len; struct ceph_mds_reply_lease *dlease; struct ceph_mds_reply_xattr xattr_info; + u8 long_snap_name; /* extra */ union { diff --git a/fs/ceph/super.h b/fs/ceph/super.h index e7c69ca5e289..f9ae5a1fe6e2 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -297,6 +297,7 @@ struct ceph_dentry_info { unsigned long lease_renew_after, lease_renew_from; unsigned long time; u64 offset; + bool long_snap_name; }; #define CEPH_DENTRY_REFERENCED 1