From patchwork Thu Apr 6 19:16:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203890 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 C5EC6C7618D for ; Thu, 6 Apr 2023 19:16:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240312AbjDFTQt (ORCPT ); Thu, 6 Apr 2023 15:16:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44814 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240209AbjDFTQs (ORCPT ); Thu, 6 Apr 2023 15:16:48 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E1153C1 for ; Thu, 6 Apr 2023 12:16:47 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 7D6946450F for ; Thu, 6 Apr 2023 19:16:47 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E0844C433EF; Thu, 6 Apr 2023 19:16:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808606; bh=C13XxAvacKswiHH0rv2EdrFxa5Ft5pU55XWzxnEm4+I=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=qtVktw+qM2i//IIvnDVIEVn9aVwTlQTxBIVObTkzz30w4XwxW/c80kUjqJUegdsAt MulUjcKFVgJgcpYM+CC1pSMB3B6s9n3JqNfdehxz10PBFwNXlLP+StGlysAuIwaCRG 666yJHXI/WookEXoLhoGJP/feaWaGAc78La8B9pEotlad61xy6C+le6C7RA6lJ23YF bllTWHtig8se+YDplnLl1YhJqIfAxfldKuzviMNolJuR2/Z+qVuGSowNm77arP33H5 ez7eG8ItOGo/O6H1rJLq5U0q62UzV+sIIA4mISzOtJXpqG4wynyRuvBfqF39M/JKDj JSVWUTGEXQChw== Date: Thu, 06 Apr 2023 12:16:46 -0700 Subject: [PATCH 01/12] xfs: check opcode and iovec count match in xlog_recover_attri_commit_pass2 From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823820.613065.9263824985180579900.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Check that the number of recovered log iovecs is what is expected for the xattri opcode is expecting. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_attr_item.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c index 2788a6f2edcd..61ed139af8b1 100644 --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -710,6 +710,7 @@ xlog_recover_attri_commit_pass2( const void *attr_value = NULL; const void *attr_name; size_t len; + unsigned int op; attri_formatp = item->ri_buf[0].i_addr; attr_name = item->ri_buf[1].i_addr; @@ -728,6 +729,32 @@ xlog_recover_attri_commit_pass2( return -EFSCORRUPTED; } + /* Check the number of log iovecs makes sense for the op code. */ + op = attri_formatp->alfi_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK; + switch (op) { + case XFS_ATTRI_OP_FLAGS_SET: + case XFS_ATTRI_OP_FLAGS_REPLACE: + /* Log item, attr name, attr value */ + if (item->ri_total != 3) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + break; + case XFS_ATTRI_OP_FLAGS_REMOVE: + /* Log item, attr name */ + if (item->ri_total != 2) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + break; + default: + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + /* Validate the attr name */ if (item->ri_buf[1].i_len != xlog_calc_iovec_len(attri_formatp->alfi_name_len)) { From patchwork Thu Apr 6 19:17:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203891 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 5DCD8C7618D for ; Thu, 6 Apr 2023 19:17:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240332AbjDFTRF (ORCPT ); Thu, 6 Apr 2023 15:17:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45102 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229714AbjDFTRE (ORCPT ); Thu, 6 Apr 2023 15:17:04 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 89BB7C1 for ; Thu, 6 Apr 2023 12:17:03 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 2818560C99 for ; Thu, 6 Apr 2023 19:17:03 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8628AC433D2; Thu, 6 Apr 2023 19:17:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808622; bh=q6KyTSWLaxU8dptWjMqpsSVBWfIfG7yur1piAMNiAtc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=jTOO8QA2hSsa0JAk6QD6gi/RN5R/5odFP2WnJHAM/gTVmJtSnTSfk94Nupx+2CkNj O1OLobtwPE0vBEoJkpK19ZL/1qob3Rif5oCyA1+EtX2i7OIL/Fl0sW97dZaydPPhwT 9+HLso10Q9qY4ay1+plcMrCtkqQr8qUDVgq6AnYOUBa0VpHPTpEnlvHBg8/JGAuZr3 sESQzSZrzoBbRsHTuN6nXc+g0PgjFch0h4Cp3WvzaZ2zuxJSCmkYN3iBVta8b77Amy zE65zQgD95AwQA7rPdMyg6B9ZDGQdlYPSbKPZYOOBSrNCmD0k31hVlN50Oem4sLiTX bf3VJt5Akp9Vw== Date: Thu, 06 Apr 2023 12:17:02 -0700 Subject: [PATCH 02/12] xfs: make xfs_attr_set require XFS_DA_OP_REMOVE From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823833.613065.377220236636487349.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Quite a few patches from now, we're going to change the parent pointer xattr format to encode as much of the dirent name in the xattr name as fits, and spill the rest of it to the xattr value. To make this work correctly, we'll be adding the ability to look up xattrs based on name /and/ value. Internally, the xattr data structure supports attributes with a zero length value, which is how we're going to store parent pointers for short dirent names. The parent pointer repair code uses xfs_attr_set to add missing and remove dangling parent pointers, so that interface must be capable of setting an xattr with args->value == NULL. The userspace API doesn't support this, so xfs_attr_set currently treats a NULL args->value as a request to remove an attr. However, that's a quirk of the existing callers and the interface. Make the callers of xfs_attr_set to declare explicitly that they want to remove an xattr. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 9 +++++---- fs/xfs/xfs_xattr.c | 5 +++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index e28d93d232de..1518b786cdaa 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -967,6 +967,7 @@ xfs_attr_set( struct xfs_mount *mp = dp->i_mount; struct xfs_trans_res tres; bool rsvd = (args->attr_filter & XFS_ATTR_ROOT); + bool is_remove = args->op_flags & XFS_DA_OP_REMOVE; int error, local; int rmt_blks = 0; unsigned int total; @@ -991,7 +992,7 @@ xfs_attr_set( args->op_flags = XFS_DA_OP_OKNOENT | (args->op_flags & XFS_DA_OP_LOGGED); - if (args->value) { + if (!is_remove) { XFS_STATS_INC(mp, xs_attr_set); args->total = xfs_attr_calc_size(args, &local); @@ -1025,7 +1026,7 @@ xfs_attr_set( if (error) return error; - if (args->value || xfs_inode_hasattr(dp)) { + if (!is_remove || xfs_inode_hasattr(dp)) { error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK, XFS_IEXT_ATTR_MANIP_CNT(rmt_blks)); if (error == -EFBIG) @@ -1039,7 +1040,7 @@ xfs_attr_set( switch (error) { case -EEXIST: /* if no value, we are performing a remove operation */ - if (!args->value) { + if (is_remove) { error = xfs_attr_defer_remove(args); break; } @@ -1051,7 +1052,7 @@ xfs_attr_set( break; case -ENOATTR: /* Can't remove what isn't there. */ - if (!args->value) + if (is_remove) goto out_trans_cancel; /* Pure replace fails if no existing attr to replace. */ diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index 7b9a0ed1b11f..61779d92295f 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -103,6 +103,11 @@ xfs_attr_change( use_logging = true; } + if (args->value) + args->op_flags &= ~XFS_DA_OP_REMOVE; + else + args->op_flags |= XFS_DA_OP_REMOVE; + error = xfs_attr_set(args); if (use_logging) From patchwork Thu Apr 6 19:17:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203892 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 586FAC76196 for ; Thu, 6 Apr 2023 19:17:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240542AbjDFTRY (ORCPT ); Thu, 6 Apr 2023 15:17:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45666 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240460AbjDFTRW (ORCPT ); Thu, 6 Apr 2023 15:17:22 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 32A101FDA for ; Thu, 6 Apr 2023 12:17:19 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B62DF6449B for ; Thu, 6 Apr 2023 19:17:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 24BE2C433D2; Thu, 6 Apr 2023 19:17:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808638; bh=Mt+ijNdXi/3qEmt24E/wMuSxEESGPlALWI0XE9MoeoA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=MHLJIF84foGbP4WDjqQftzA554qYHHqtwzvsc3jTAebFmRKZtl7+tnpfX1wg+izhZ q1z/Zd1EGhd9SCyYAHm4dejgxxG1z+4OXwBPImPOBi56bMd+3lPwE1DhpuRGomO5wr v21ki12qbn8pIwlXn7IM6KlG80T6csx1Wk+YqIn+HfVkOrDFjjA9iGtU0pQnW2vz2B eJzSXnHBhYRgW0VYVMDTacjYwTn9MNpQ4mxcCW70CpRN/hy0PSzxZxwd/0X/CCgycX B2pQ3MgmdsKRlA8+Er8mKOybG/dTNws7TWeMKHB/mMVii8WOKC+EayOglLshnQrUco bdW+YaI/J7W/g== Date: Thu, 06 Apr 2023 12:17:17 -0700 Subject: [PATCH 03/12] xfs: allow xattr matching on name and value for local/sf attrs From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823848.613065.7140979158870437420.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Add a new NVLOOKUP flag to signal that the caller wants to look up an extended attribute by name and value. This only works with shortform and local attributes. Only parent pointers need this functionality and parent pointers cannot be remote xattrs, so this limitation is ok for now. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr_leaf.c | 45 ++++++++++++++++++++++++++++++++++------- fs/xfs/libxfs/xfs_da_btree.h | 4 +++- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index beee51ad75ce..c38caa8cba3a 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c @@ -473,10 +473,12 @@ xfs_attr3_leaf_read( */ static bool xfs_attr_match( - struct xfs_da_args *args, - uint8_t namelen, - unsigned char *name, - int flags) + const struct xfs_da_args *args, + uint8_t namelen, + const unsigned char *name, + unsigned int valuelen, + const void *value, + int flags) { if (args->namelen != namelen) @@ -484,6 +486,23 @@ xfs_attr_match( if (memcmp(args->name, name, namelen) != 0) return false; + if (args->op_flags & XFS_DA_OP_NVLOOKUP) { + if (args->valuelen != valuelen) + return false; + if (args->valuelen && !value) { + /* not implemented for remote values */ + ASSERT(0); + return false; + } + if (valuelen && !args->value) { + /* caller gave us valuelen > 0 but no value?? */ + ASSERT(0); + return false; + } + if (valuelen > 0 && memcmp(args->value, value, valuelen) != 0) + return false; + } + /* Recovery ignores the INCOMPLETE flag. */ if ((args->op_flags & XFS_DA_OP_RECOVERY) && args->attr_filter == (flags & XFS_ATTR_NSP_ONDISK_MASK)) @@ -502,6 +521,10 @@ xfs_attr_copy_value( unsigned char *value, int valuelen) { + /* vlookups already supplied the attr value; don't copy anything */ + if (args->op_flags & XFS_DA_OP_NVLOOKUP) + return 0; + /* * No copy if all we have to do is get the length */ @@ -726,6 +749,7 @@ xfs_attr_sf_findname( base += size, i++) { size = xfs_attr_sf_entsize(sfe); if (!xfs_attr_match(args, sfe->namelen, sfe->nameval, + sfe->valuelen, &sfe->nameval[sfe->namelen], sfe->flags)) continue; break; @@ -894,6 +918,7 @@ xfs_attr_shortform_lookup(xfs_da_args_t *args) for (i = 0; i < sf->hdr.count; sfe = xfs_attr_sf_nextentry(sfe), i++) { if (xfs_attr_match(args, sfe->namelen, sfe->nameval, + sfe->valuelen, &sfe->nameval[sfe->namelen], sfe->flags)) return -EEXIST; } @@ -921,6 +946,7 @@ xfs_attr_shortform_getvalue( for (i = 0; i < sf->hdr.count; sfe = xfs_attr_sf_nextentry(sfe), i++) { if (xfs_attr_match(args, sfe->namelen, sfe->nameval, + sfe->valuelen, &sfe->nameval[sfe->namelen], sfe->flags)) return xfs_attr_copy_value(args, &sfe->nameval[args->namelen], sfe->valuelen); @@ -973,7 +999,7 @@ xfs_attr_shortform_to_leaf( nargs.total = args->total; nargs.whichfork = XFS_ATTR_FORK; nargs.trans = args->trans; - nargs.op_flags = XFS_DA_OP_OKNOENT; + nargs.op_flags = XFS_DA_OP_OKNOENT | XFS_DA_OP_NVLOOKUP; sfe = &sf->list[0]; for (i = 0; i < sf->hdr.count; i++) { @@ -1183,7 +1209,7 @@ xfs_attr3_leaf_to_shortform( nargs.total = args->total; nargs.whichfork = XFS_ATTR_FORK; nargs.trans = args->trans; - nargs.op_flags = XFS_DA_OP_OKNOENT; + nargs.op_flags = XFS_DA_OP_OKNOENT | XFS_DA_OP_NVLOOKUP; for (i = 0; i < ichdr.count; entry++, i++) { if (entry->flags & XFS_ATTR_INCOMPLETE) @@ -2482,14 +2508,17 @@ xfs_attr3_leaf_lookup_int( if (entry->flags & XFS_ATTR_LOCAL) { name_loc = xfs_attr3_leaf_name_local(leaf, probe); if (!xfs_attr_match(args, name_loc->namelen, - name_loc->nameval, entry->flags)) + name_loc->nameval, + be16_to_cpu(name_loc->valuelen), + &name_loc->nameval[name_loc->namelen], + entry->flags)) continue; args->index = probe; return -EEXIST; } else { name_rmt = xfs_attr3_leaf_name_remote(leaf, probe); if (!xfs_attr_match(args, name_rmt->namelen, - name_rmt->name, entry->flags)) + name_rmt->name, 0, NULL, entry->flags)) continue; args->index = probe; args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen); diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h index ffa3df5b2893..94a544fc8a9c 100644 --- a/fs/xfs/libxfs/xfs_da_btree.h +++ b/fs/xfs/libxfs/xfs_da_btree.h @@ -93,6 +93,7 @@ typedef struct xfs_da_args { #define XFS_DA_OP_REMOVE (1u << 6) /* this is a remove operation */ #define XFS_DA_OP_RECOVERY (1u << 7) /* Log recovery operation */ #define XFS_DA_OP_LOGGED (1u << 8) /* Use intent items to track op */ +#define XFS_DA_OP_NVLOOKUP (1u << 9) /* Match local attr on name+value */ #define XFS_DA_OP_FLAGS \ { XFS_DA_OP_JUSTCHECK, "JUSTCHECK" }, \ @@ -103,7 +104,8 @@ typedef struct xfs_da_args { { XFS_DA_OP_NOTIME, "NOTIME" }, \ { XFS_DA_OP_REMOVE, "REMOVE" }, \ { XFS_DA_OP_RECOVERY, "RECOVERY" }, \ - { XFS_DA_OP_LOGGED, "LOGGED" } + { XFS_DA_OP_LOGGED, "LOGGED" }, \ + { XFS_DA_OP_NVLOOKUP, "NVLOOKUP" } /* * Storage for holding state during Btree searches and split/join ops. From patchwork Thu Apr 6 19:17:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203893 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 CD0BEC7618D for ; Thu, 6 Apr 2023 19:17:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239619AbjDFTRi (ORCPT ); Thu, 6 Apr 2023 15:17:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46014 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240532AbjDFTRg (ORCPT ); Thu, 6 Apr 2023 15:17:36 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C81E8E52 for ; Thu, 6 Apr 2023 12:17:34 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 60C7962CE1 for ; Thu, 6 Apr 2023 19:17:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C3B5CC433D2; Thu, 6 Apr 2023 19:17:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808653; bh=iFuqVb0dzu3JQjlamiXHtDl1yG2BCXjQrXAlDkZrLkw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ZfH/210bq0+3OpwVEyLxlMRvkIiK7JMQ80E8Eb92Sx+i6O3USWfQ1JSZfg9JYbxKB 8+ZUz4uFTfXW6V0+YeB7bChr50BmHbZc8GLCkqrcRALzmDNTge91mpSIZNtPrBfgCn VYZtgWyPZ7VJxoJcs5I+vqRN4nHRaWXclwOuTYu3qtvKELwKu/DVkE4ySHFCuwW22w oDRdqLPivrfANF13PudTmJ4yJYIyG37vGumEQNQew9NrkQR6PuKwRUA/A/sVajOPQB cP54e01t/RkMOjk7XenLwUK+MVvI40kW3aeX8jv2QI3BYGm6MNNcgOX3kQlp4vJkYD 90me0sgP0DY+A== Date: Thu, 06 Apr 2023 12:17:33 -0700 Subject: [PATCH 04/12] xfs: preserve NVLOOKUP in xfs_attr_set From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823862.613065.11992563311398110892.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Preserve the attr-value lookup flag when calling xfs_attr_set. Normal xattr users will never use this, but parent pointer fsck will. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 1518b786cdaa..2897fdc8372e 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -986,11 +986,11 @@ xfs_attr_set( /* * We have no control over the attribute names that userspace passes us * to remove, so we have to allow the name lookup prior to attribute - * removal to fail as well. Preserve the logged flag, since we need - * to pass that through to the logging code. + * removal to fail as well. Preserve the logged and vlookup flags, + * since we need to pass them through to the lower levels. */ - args->op_flags = XFS_DA_OP_OKNOENT | - (args->op_flags & XFS_DA_OP_LOGGED); + args->op_flags &= (XFS_DA_OP_LOGGED | XFS_DA_OP_NVLOOKUP); + args->op_flags |= XFS_DA_OP_OKNOENT; if (!is_remove) { XFS_STATS_INC(mp, xs_attr_set); From patchwork Thu Apr 6 19:17:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203894 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 89716C76196 for ; Thu, 6 Apr 2023 19:17:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240529AbjDFTRv (ORCPT ); Thu, 6 Apr 2023 15:17:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46404 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239729AbjDFTRv (ORCPT ); Thu, 6 Apr 2023 15:17:51 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 78D2AF2 for ; Thu, 6 Apr 2023 12:17:50 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 14EA760F9D for ; Thu, 6 Apr 2023 19:17:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6DD17C4339B; Thu, 6 Apr 2023 19:17:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808669; bh=JtGh3u+mk/nNkJFlkU4XQ4L/Y9O+yDk2RryGk/214DU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=jXzPK/VQY/CsAyX7LDaY5fDm2zqSPx2WE9KfQzNWUV3F3aJtFzgzcPxINFSkUWIRg 0jIUuKIRxA9fFj2w8AO9cIns53PXhaODjUdci5eKPdxvHwJ+3I/ultyVu779EXToFy WOOc8q1Bd/RoryKFCXBQQzC/oVhKD6S5cafhReqh/qJNI8gbKQaoLFCikhtOluWCKb /iY3vZkHyJH+ivoWEUheJ64LSYt5g6pxTfdxpG+gps35Xx3pmKu3bJSMXPbDho69wp 1vuXI4Il/epPGr+N2R52gwUCsVBjEswHIxr+7roNB1owJ9HIzn1zeTf6srRdCs0h8s d+dNKyt3hNsjQ== Date: Thu, 06 Apr 2023 12:17:48 -0700 Subject: [PATCH 05/12] xfs: restructure xfs_attr_complete_op a bit From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823876.613065.2848688652399549352.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Reduce the indentation in this function by flattening the nested if statements. We're going to add more code later to this function later, hence the early cleanup. No functional changes. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 2897fdc8372e..b0da2e862ef9 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -421,11 +421,11 @@ xfs_attr_complete_op( bool do_replace = args->op_flags & XFS_DA_OP_REPLACE; args->op_flags &= ~XFS_DA_OP_REPLACE; - if (do_replace) { - args->attr_filter &= ~XFS_ATTR_INCOMPLETE; - return replace_state; - } - return XFS_DAS_DONE; + if (!do_replace) + return XFS_DAS_DONE; + + args->attr_filter &= ~XFS_ATTR_INCOMPLETE; + return replace_state; } static int From patchwork Thu Apr 6 19:18:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203895 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 ECD9AC7618D for ; Thu, 6 Apr 2023 19:18:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239729AbjDFTSI (ORCPT ); Thu, 6 Apr 2023 15:18:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46938 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240423AbjDFTSH (ORCPT ); Thu, 6 Apr 2023 15:18:07 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 11FCE1BEE for ; Thu, 6 Apr 2023 12:18:06 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id A296F60F3E for ; Thu, 6 Apr 2023 19:18:05 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1528DC433EF; Thu, 6 Apr 2023 19:18:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808685; bh=m9mNOFnNGWKM8FrcWIt8Rms0QFVSsgHawLw9cL8fGHs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=jB3iqvM8s3FRP/lz/gtQd4NJHK63jTUclrpngX09ZohdFHfbYT9IkapJl8d01yPRX hvy8AtKTx+7fKL/DtI77S20of5x81a7jygL0E/nv3UqC4RxjKaG8ltN4bE/h+5zC6/ hdXAWIBwelIQLEqiJRBuC4y9hmPARN/fDQU8l6lSDMsLzRMoDvcZKSEoV0ZZJ9UlTG SWoyJSPLi7wY6R3tb8ROkeM1bG1JO4uPlWF4TF1ISSLbYcDiOMdCwGFG/fauHOVza8 S2uF5LHiiY41QIrg2I1S0S2089hmamtzNbnp+x6W6QljfEHaTvac/Kecq9+rFJwa+r Fs6n7TxKPx2kA== Date: Thu, 06 Apr 2023 12:18:04 -0700 Subject: [PATCH 06/12] xfs: use helpers to extract xattr op from opflags From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823889.613065.12567417828619394071.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Create helper functions to extract the xattr op from the ondisk xattri log item and the incore attr intent item. These will get more use in the patches that follow. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.h | 5 +++++ fs/xfs/xfs_attr_item.c | 16 ++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h index 81be9b3e4004..f0aa372ecba1 100644 --- a/fs/xfs/libxfs/xfs_attr.h +++ b/fs/xfs/libxfs/xfs_attr.h @@ -529,6 +529,11 @@ struct xfs_attr_intent { struct xfs_bmbt_irec xattri_map; }; +static inline unsigned int +xfs_attr_intent_op(const struct xfs_attr_intent *attr) +{ + return attr->xattri_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK; +} /*======================================================================== * Function prototypes for the kernel. diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c index 61ed139af8b1..23fee7c0938f 100644 --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -351,6 +351,12 @@ xfs_xattri_finish_update( return error; } +static inline unsigned int +xfs_attr_log_item_op(const struct xfs_attri_log_format *attrp) +{ + return attrp->alfi_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK; +} + /* Log an attr to the intent item. */ STATIC void xfs_attr_log_item( @@ -500,8 +506,7 @@ xfs_attri_validate( struct xfs_mount *mp, struct xfs_attri_log_format *attrp) { - unsigned int op = attrp->alfi_op_flags & - XFS_ATTRI_OP_FLAGS_TYPE_MASK; + unsigned int op = xfs_attr_log_item_op(attrp); if (attrp->__pad != 0) return false; @@ -573,8 +578,7 @@ xfs_attri_item_recover( args = (struct xfs_da_args *)(attr + 1); attr->xattri_da_args = args; - attr->xattri_op_flags = attrp->alfi_op_flags & - XFS_ATTRI_OP_FLAGS_TYPE_MASK; + attr->xattri_op_flags = xfs_attr_log_item_op(attrp); /* * We're reconstructing the deferred work state structure from the @@ -596,7 +600,7 @@ xfs_attri_item_recover( ASSERT(xfs_sb_version_haslogxattrs(&mp->m_sb)); - switch (attr->xattri_op_flags) { + switch (xfs_attr_intent_op(attr)) { case XFS_ATTRI_OP_FLAGS_SET: case XFS_ATTRI_OP_FLAGS_REPLACE: args->value = nv->value.i_addr; @@ -730,7 +734,7 @@ xlog_recover_attri_commit_pass2( } /* Check the number of log iovecs makes sense for the op code. */ - op = attri_formatp->alfi_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK; + op = xfs_attr_log_item_op(attri_formatp); switch (op) { case XFS_ATTRI_OP_FLAGS_SET: case XFS_ATTRI_OP_FLAGS_REPLACE: From patchwork Thu Apr 6 19:18:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203896 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 CB410C76196 for ; Thu, 6 Apr 2023 19:18:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240423AbjDFTSZ (ORCPT ); Thu, 6 Apr 2023 15:18:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47052 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240508AbjDFTSY (ORCPT ); Thu, 6 Apr 2023 15:18:24 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BAAA4E78 for ; Thu, 6 Apr 2023 12:18:21 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 3DC2B60C99 for ; Thu, 6 Apr 2023 19:18:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A1106C433D2; Thu, 6 Apr 2023 19:18:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808700; bh=6Jdy6JzcmHxBlr7NiZgYb1agLDZKmVPF2L33e7uSwCk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ScmwAfxuDZDV7zMPKJGTsrzVZxsOhuD/Uh2dvuG1nVlwq0i4yO08SnMcUJXtSfyZx wETx5rkkZVfOvm6grIIYnEj8O9cCtbY9UbAhkfRFNo2I3SZM3BpchxxcXaYbgD02+s zcI6AzMvocEvtlecDPm+kt3TgDCk6dYYyBNlXdwgykxWjpY/sVoscLeGXKBxYcfwzR FWKqc6oI25fNTcLyM03cgld6V498veg8OFIpa+Pj3Z8QEEdraEZAmHL00mn0FCTU+A yvh2RDz9KSoOZ0HtDqPE4NofuK3cnrN+NSy85hSv+6mwVP4P6C628lzzdn5HGNDxW4 ce98mNVxxBreQ== Date: Thu, 06 Apr 2023 12:18:20 -0700 Subject: [PATCH 07/12] xfs: validate recovered name buffers when recovering xattr items From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823904.613065.4855082202510916891.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Strengthen the xattri log item recovery code by checking that we actually have the required name and newname buffers for whatever operation we're replaying. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_attr_item.c | 58 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c index 23fee7c0938f..082d7790fc2c 100644 --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -714,22 +714,20 @@ xlog_recover_attri_commit_pass2( const void *attr_value = NULL; const void *attr_name; size_t len; - unsigned int op; - - attri_formatp = item->ri_buf[0].i_addr; - attr_name = item->ri_buf[1].i_addr; + unsigned int op, i = 0; /* Validate xfs_attri_log_format before the large memory allocation */ len = sizeof(struct xfs_attri_log_format); - if (item->ri_buf[0].i_len != len) { + if (item->ri_buf[i].i_len != len) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, item->ri_buf[0].i_addr, item->ri_buf[0].i_len); return -EFSCORRUPTED; } + attri_formatp = item->ri_buf[i].i_addr; if (!xfs_attri_validate(mp, attri_formatp)) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, - item->ri_buf[0].i_addr, item->ri_buf[0].i_len); + attri_formatp, len); return -EFSCORRUPTED; } @@ -758,31 +756,69 @@ xlog_recover_attri_commit_pass2( attri_formatp, len); return -EFSCORRUPTED; } + i++; /* Validate the attr name */ - if (item->ri_buf[1].i_len != + if (item->ri_buf[i].i_len != xlog_calc_iovec_len(attri_formatp->alfi_name_len)) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, - item->ri_buf[0].i_addr, item->ri_buf[0].i_len); + attri_formatp, len); return -EFSCORRUPTED; } + attr_name = item->ri_buf[i].i_addr; if (!xfs_attr_namecheck(attr_name, attri_formatp->alfi_name_len)) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, - item->ri_buf[1].i_addr, item->ri_buf[1].i_len); + attri_formatp, len); return -EFSCORRUPTED; } + i++; /* Validate the attr value, if present */ if (attri_formatp->alfi_value_len != 0) { - if (item->ri_buf[2].i_len != xlog_calc_iovec_len(attri_formatp->alfi_value_len)) { + if (item->ri_buf[i].i_len != xlog_calc_iovec_len(attri_formatp->alfi_value_len)) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, item->ri_buf[0].i_addr, item->ri_buf[0].i_len); return -EFSCORRUPTED; } - attr_value = item->ri_buf[2].i_addr; + attr_value = item->ri_buf[i].i_addr; + i++; + } + + /* + * Make sure we got the correct number of buffers for the operation + * that we just loaded. + */ + if (i != item->ri_total) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + + switch (op) { + case XFS_ATTRI_OP_FLAGS_REMOVE: + /* Regular remove operations operate only on names. */ + if (attr_value != NULL || attri_formatp->alfi_value_len != 0) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + fallthrough; + case XFS_ATTRI_OP_FLAGS_SET: + case XFS_ATTRI_OP_FLAGS_REPLACE: + /* + * Regular xattr set/remove/replace operations require a name + * and do not take a newname. Values are optional for set and + * replace. + */ + if (attr_name == NULL || attri_formatp->alfi_name_len == 0) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + break; } /* From patchwork Thu Apr 6 19:18:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203897 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 0B694C76196 for ; Thu, 6 Apr 2023 19:18:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240532AbjDFTSi (ORCPT ); Thu, 6 Apr 2023 15:18:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47134 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240531AbjDFTSh (ORCPT ); Thu, 6 Apr 2023 15:18:37 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3B3B8E78 for ; Thu, 6 Apr 2023 12:18:37 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id CD617644B7 for ; Thu, 6 Apr 2023 19:18:36 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 35F34C433D2; Thu, 6 Apr 2023 19:18:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808716; bh=NJ61IxOToZgaBFW3osjwF/Pn/UK5y2wHTMAd5X3Gmuo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=A/WsqRTSdQ2TdHF+f6ss1/fH41u7+oMds7m8mYpzo3IbKytihQKlVg/SRy5dkaOXm IM6EF9LOUoRX1m+v/sZvNpwdXObarlqF05oTl6C9MQgDcbFR3gPBrROkM2NinZ/b3L zA5o+2iHjRezFcQE1CPlkUNQVVZnoQ65cbpMJgdpYXBcIx+jUtlqBvdsMQa7fMifoR wpmmrXK1WHrEBBF8frn3mZSHgd8prgbbPOE0kuMZr7D8MFZd0zbmDbCdtsp+ebstba qVHUTdbgSVEayfMtLQCptDfhhH33ER310jon2by7BiNa6d2pnkQ2n0iQv04xZ+RnBX SvFGJWBH7DZwg== Date: Thu, 06 Apr 2023 12:18:35 -0700 Subject: [PATCH 08/12] xfs: always set args->value in xfs_attri_item_recover From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823918.613065.14566514432845489888.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Always set args->value to the recovered value buffer. This reduces the amount of code in the switch statement, and hence the amount of thinking that I have to do. We validated the recovered buffers, supposedly. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_attr_item.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c index 082d7790fc2c..07a6cec3dfb9 100644 --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -594,6 +594,8 @@ xfs_attri_item_recover( args->name = nv->name.i_addr; args->namelen = nv->name.i_len; args->hashval = xfs_da_hashname(args->name, args->namelen); + args->value = nv->value.i_addr; + args->valuelen = nv->value.i_len; args->attr_filter = attrp->alfi_attr_filter & XFS_ATTRI_FILTER_MASK; args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT | XFS_DA_OP_LOGGED; @@ -603,8 +605,6 @@ xfs_attri_item_recover( switch (xfs_attr_intent_op(attr)) { case XFS_ATTRI_OP_FLAGS_SET: case XFS_ATTRI_OP_FLAGS_REPLACE: - args->value = nv->value.i_addr; - args->valuelen = nv->value.i_len; args->total = xfs_attr_calc_size(args, &local); if (xfs_inode_hasattr(args->dp)) attr->xattri_dela_state = xfs_attr_init_replace_state(args); From patchwork Thu Apr 6 19:18:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203898 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 DAABAC76196 for ; Thu, 6 Apr 2023 19:18:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240508AbjDFTSy (ORCPT ); Thu, 6 Apr 2023 15:18:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47218 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239634AbjDFTSx (ORCPT ); Thu, 6 Apr 2023 15:18:53 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EB328213E for ; Thu, 6 Apr 2023 12:18:52 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 7652F63D38 for ; Thu, 6 Apr 2023 19:18:52 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4155C433EF; Thu, 6 Apr 2023 19:18:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808731; bh=bRV4nLVs1O4NFsm8YXi+W2kqu6jsgLfSFQcPRAzGGiM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=slTDKLRyNfRYLBzsHDzEm8Zb0PbruMbTWUB6Hw49q90Gl73MkFm9ps5SYG2rniN+y l4PqChiyvSX2s6rdzzZa6ngkj1Ku39eDkcsUqejV6G5Vmicff9lwKbiK+tKCb6b3Dd GJBLNIrUbIR7dqFKFUULlNmsgAyYmWCSHnuW/GAVYwiJ7qmo1uxJXL9YXVrK5tYJaY GuH5UzHz9+gBWlRuWztHSVXSNW2an2JK41rCIvfJIhFmAGT7oDTfCi2nU8tM3Nt3CX WSE5+H/FICSPZzmh6gFX1DizSq68D7EYe9csD8iORO8N5ulG9U0fB9Yr+2o6rWK44K WLg7f3eEHHxRw== Date: Thu, 06 Apr 2023 12:18:51 -0700 Subject: [PATCH 09/12] xfs: use local variables for name and value length in _attri_commit_pass2 From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823932.613065.10645829769671106238.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong We're about to start using tagged unions in the xattr log format, so create a bunch of local variables in the recovery function so we only have to decode the log item fields once. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_attr_item.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c index 07a6cec3dfb9..f756bee9fb73 100644 --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -711,9 +711,11 @@ xlog_recover_attri_commit_pass2( struct xfs_attri_log_item *attrip; struct xfs_attri_log_format *attri_formatp; struct xfs_attri_log_nameval *nv; - const void *attr_value = NULL; const void *attr_name; + const void *attr_value = NULL; size_t len; + unsigned int name_len = 0; + unsigned int value_len = 0; unsigned int op, i = 0; /* Validate xfs_attri_log_format before the large memory allocation */ @@ -742,6 +744,8 @@ xlog_recover_attri_commit_pass2( attri_formatp, len); return -EFSCORRUPTED; } + name_len = attri_formatp->alfi_name_len; + value_len = attri_formatp->alfi_value_len; break; case XFS_ATTRI_OP_FLAGS_REMOVE: /* Log item, attr name */ @@ -750,6 +754,7 @@ xlog_recover_attri_commit_pass2( attri_formatp, len); return -EFSCORRUPTED; } + name_len = attri_formatp->alfi_name_len; break; default: XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, @@ -759,15 +764,14 @@ xlog_recover_attri_commit_pass2( i++; /* Validate the attr name */ - if (item->ri_buf[i].i_len != - xlog_calc_iovec_len(attri_formatp->alfi_name_len)) { + if (item->ri_buf[i].i_len != xlog_calc_iovec_len(name_len)) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, attri_formatp, len); return -EFSCORRUPTED; } attr_name = item->ri_buf[i].i_addr; - if (!xfs_attr_namecheck(attr_name, attri_formatp->alfi_name_len)) { + if (!xfs_attr_namecheck(attr_name, name_len)) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, attri_formatp, len); return -EFSCORRUPTED; @@ -775,8 +779,8 @@ xlog_recover_attri_commit_pass2( i++; /* Validate the attr value, if present */ - if (attri_formatp->alfi_value_len != 0) { - if (item->ri_buf[i].i_len != xlog_calc_iovec_len(attri_formatp->alfi_value_len)) { + if (value_len != 0) { + if (item->ri_buf[i].i_len != xlog_calc_iovec_len(value_len)) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, item->ri_buf[0].i_addr, item->ri_buf[0].i_len); @@ -800,7 +804,7 @@ xlog_recover_attri_commit_pass2( switch (op) { case XFS_ATTRI_OP_FLAGS_REMOVE: /* Regular remove operations operate only on names. */ - if (attr_value != NULL || attri_formatp->alfi_value_len != 0) { + if (attr_value != NULL || value_len != 0) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, attri_formatp, len); return -EFSCORRUPTED; @@ -813,7 +817,7 @@ xlog_recover_attri_commit_pass2( * and do not take a newname. Values are optional for set and * replace. */ - if (attr_name == NULL || attri_formatp->alfi_name_len == 0) { + if (attr_name == NULL || name_len == 0) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, attri_formatp, len); return -EFSCORRUPTED; @@ -826,9 +830,8 @@ xlog_recover_attri_commit_pass2( * name/value buffer to the recovered incore log item and drop our * reference. */ - nv = xfs_attri_log_nameval_alloc(attr_name, - attri_formatp->alfi_name_len, attr_value, - attri_formatp->alfi_value_len); + nv = xfs_attri_log_nameval_alloc(attr_name, name_len, + attr_value, value_len); attrip = xfs_attri_init(mp, nv); memcpy(&attrip->attri_format, attri_formatp, len); From patchwork Thu Apr 6 19:19:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203899 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 E5CF2C7618D for ; Thu, 6 Apr 2023 19:19:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229794AbjDFTTK (ORCPT ); Thu, 6 Apr 2023 15:19:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47364 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240531AbjDFTTJ (ORCPT ); Thu, 6 Apr 2023 15:19:09 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7BE78E78 for ; Thu, 6 Apr 2023 12:19:08 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 0588A63D38 for ; Thu, 6 Apr 2023 19:19:08 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 632B0C433EF; Thu, 6 Apr 2023 19:19:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808747; bh=u4NSqMy17yGRWznyOT8AHPWjOGzvCnWKM+nqdV1r6E4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=cAHQKXeVh/RkTThT3+Veak8C37dDzjOHnIx+D62qhJxgAIooFVZPSYBia6e3hF8xL ltQ3wqZ+ZEidPGXuq4WYqYOvFJ5h/loqLumM2sCdweEDncpQHpsWhcjqotCwQ8/WA6 ct6Lmljf/dr+ajqdoUqSJ4gQZbzrsnyLKUmI+VvLa7NcCzTQ3qmcvPJ+6TUeHFvM05 hpCud3JhXEySKN9W0o0JMeHSJWZBeOSwOZbqQoICeSvbbYPGfkEkT3NuM+m4LiF2Ww OERXVc+xOTNHAuK/3O+0n1kFZzv9FBciBLj6zVNp+JyvXtiQMI028raDbarTBvP7K8 4oFu44vXJQtVg== Date: Thu, 06 Apr 2023 12:19:07 -0700 Subject: [PATCH 10/12] xfs: log NVLOOKUP xattr removal operations From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823946.613065.16786327016716587364.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong If high level code wants to do a deferred xattr remove operation with the NVLOOKUP flag set, we need to push this through the log. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 6 +++++- fs/xfs/libxfs/xfs_log_format.h | 1 + fs/xfs/xfs_attr_item.c | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index b0da2e862ef9..1f4dc6e01e68 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -942,9 +942,13 @@ xfs_attr_defer_remove( { struct xfs_attr_intent *new; + int op_flag = XFS_ATTRI_OP_FLAGS_REMOVE; int error; - error = xfs_attr_intent_init(args, XFS_ATTRI_OP_FLAGS_REMOVE, &new); + if (args->op_flags & XFS_DA_OP_NVLOOKUP) + op_flag = XFS_ATTRI_OP_FLAGS_NVREMOVE; + + error = xfs_attr_intent_init(args, op_flag, &new); if (error) return error; diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index f13e0809dc63..ecf0ac32d752 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -957,6 +957,7 @@ struct xfs_icreate_log { #define XFS_ATTRI_OP_FLAGS_SET 1 /* Set the attribute */ #define XFS_ATTRI_OP_FLAGS_REMOVE 2 /* Remove the attribute */ #define XFS_ATTRI_OP_FLAGS_REPLACE 3 /* Replace the attribute */ +#define XFS_ATTRI_OP_FLAGS_NVREMOVE 4 /* Remove attr w/ vlookup */ #define XFS_ATTRI_OP_FLAGS_TYPE_MASK 0xFF /* Flags type mask */ /* diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c index f756bee9fb73..dd73d30f9e8d 100644 --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -522,6 +522,7 @@ xfs_attri_validate( case XFS_ATTRI_OP_FLAGS_SET: case XFS_ATTRI_OP_FLAGS_REPLACE: case XFS_ATTRI_OP_FLAGS_REMOVE: + case XFS_ATTRI_OP_FLAGS_NVREMOVE: break; default: return false; @@ -611,6 +612,9 @@ xfs_attri_item_recover( else attr->xattri_dela_state = xfs_attr_init_add_state(args); break; + case XFS_ATTRI_OP_FLAGS_NVREMOVE: + args->op_flags |= XFS_DA_OP_NVLOOKUP; + fallthrough; case XFS_ATTRI_OP_FLAGS_REMOVE: if (!xfs_inode_hasattr(args->dp)) goto out; @@ -736,6 +740,16 @@ xlog_recover_attri_commit_pass2( /* Check the number of log iovecs makes sense for the op code. */ op = xfs_attr_log_item_op(attri_formatp); switch (op) { + case XFS_ATTRI_OP_FLAGS_NVREMOVE: + /* Log item, attr name, optional attr value */ + if (item->ri_total != 3 && item->ri_total != 2) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + name_len = attri_formatp->alfi_name_len; + value_len = attri_formatp->alfi_value_len; + break; case XFS_ATTRI_OP_FLAGS_SET: case XFS_ATTRI_OP_FLAGS_REPLACE: /* Log item, attr name, attr value */ @@ -810,12 +824,16 @@ xlog_recover_attri_commit_pass2( return -EFSCORRUPTED; } fallthrough; + case XFS_ATTRI_OP_FLAGS_NVREMOVE: case XFS_ATTRI_OP_FLAGS_SET: case XFS_ATTRI_OP_FLAGS_REPLACE: /* * Regular xattr set/remove/replace operations require a name * and do not take a newname. Values are optional for set and * replace. + * + * Name-value remove operations must have a name, do not + * take a newname, and can take a value. */ if (attr_name == NULL || name_len == 0) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, From patchwork Thu Apr 6 19:19:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203900 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 EFEA8C76196 for ; Thu, 6 Apr 2023 19:19:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239695AbjDFTTZ (ORCPT ); Thu, 6 Apr 2023 15:19:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47756 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240211AbjDFTTZ (ORCPT ); Thu, 6 Apr 2023 15:19:25 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0B9F159EA for ; Thu, 6 Apr 2023 12:19:24 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 98FB160FA1 for ; Thu, 6 Apr 2023 19:19:23 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id F21B6C433D2; Thu, 6 Apr 2023 19:19:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808763; bh=Z+fdO/DqehWQoPg1FAtCSiAKfM20q4a4xrpb2mNoS8Q=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=d3VBZSPsQ7KPy5QO7GfBxvbFgZVe2DyjLRwtWU5A/+ItiUVdLTCtxoBBBXrkRLuxY KtGWOb0VUaA3vJN2AkcRf1MV+eYQq0vP+v8jTRC/wmMAZehlSDDiPjDkAlfe1DERpa KrLml4V44qBnF1pOp4N/D/4RctVhTNNak17dwZ2YQKsb7CQDYwtif3+hNqVdP73ELE oAQqACKh9jHcec4FVVTcWi6VwcHCkaJjtvt+bCCXbuqNeKwjC02nyvw58Us0wUZojD kAGU5HL9Hmi44yYwFsIKN58yETR+fz//2mOdubLqH289oqF22Rz8YKLQOS934FQHQt ibe7qBX2G/GOg== Date: Thu, 06 Apr 2023 12:19:22 -0700 Subject: [PATCH 11/12] xfs: log NVLOOKUP xattr setting operations From: "Darrick J. Wong" To: djwong@kernel.org Cc: allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823960.613065.1632972654900176629.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong If high level code wants to do a deferred xattr set operation with the NVLOOKUP flag set, we need to push this through the log. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 6 +++++- fs/xfs/libxfs/xfs_log_format.h | 1 + fs/xfs/xfs_attr_item.c | 8 +++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 1f4dc6e01e68..287990a9b29d 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -903,9 +903,13 @@ xfs_attr_defer_add( struct xfs_da_args *args) { struct xfs_attr_intent *new; + int op_flag = XFS_ATTRI_OP_FLAGS_SET; int error = 0; - error = xfs_attr_intent_init(args, XFS_ATTRI_OP_FLAGS_SET, &new); + if (args->op_flags & XFS_DA_OP_NVLOOKUP) + op_flag = XFS_ATTRI_OP_FLAGS_NVSET; + + error = xfs_attr_intent_init(args, op_flag, &new); if (error) return error; diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index ecf0ac32d752..7a4226e20dae 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -958,6 +958,7 @@ struct xfs_icreate_log { #define XFS_ATTRI_OP_FLAGS_REMOVE 2 /* Remove the attribute */ #define XFS_ATTRI_OP_FLAGS_REPLACE 3 /* Replace the attribute */ #define XFS_ATTRI_OP_FLAGS_NVREMOVE 4 /* Remove attr w/ vlookup */ +#define XFS_ATTRI_OP_FLAGS_NVSET 5 /* Set attr with w/ vlookup */ #define XFS_ATTRI_OP_FLAGS_TYPE_MASK 0xFF /* Flags type mask */ /* diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c index dd73d30f9e8d..f8def28090f8 100644 --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -523,6 +523,7 @@ xfs_attri_validate( case XFS_ATTRI_OP_FLAGS_REPLACE: case XFS_ATTRI_OP_FLAGS_REMOVE: case XFS_ATTRI_OP_FLAGS_NVREMOVE: + case XFS_ATTRI_OP_FLAGS_NVSET: break; default: return false; @@ -604,6 +605,9 @@ xfs_attri_item_recover( ASSERT(xfs_sb_version_haslogxattrs(&mp->m_sb)); switch (xfs_attr_intent_op(attr)) { + case XFS_ATTRI_OP_FLAGS_NVSET: + args->op_flags |= XFS_DA_OP_NVLOOKUP; + fallthrough; case XFS_ATTRI_OP_FLAGS_SET: case XFS_ATTRI_OP_FLAGS_REPLACE: args->total = xfs_attr_calc_size(args, &local); @@ -740,6 +744,7 @@ xlog_recover_attri_commit_pass2( /* Check the number of log iovecs makes sense for the op code. */ op = xfs_attr_log_item_op(attri_formatp); switch (op) { + case XFS_ATTRI_OP_FLAGS_NVSET: case XFS_ATTRI_OP_FLAGS_NVREMOVE: /* Log item, attr name, optional attr value */ if (item->ri_total != 3 && item->ri_total != 2) { @@ -824,6 +829,7 @@ xlog_recover_attri_commit_pass2( return -EFSCORRUPTED; } fallthrough; + case XFS_ATTRI_OP_FLAGS_NVSET: case XFS_ATTRI_OP_FLAGS_NVREMOVE: case XFS_ATTRI_OP_FLAGS_SET: case XFS_ATTRI_OP_FLAGS_REPLACE: @@ -832,7 +838,7 @@ xlog_recover_attri_commit_pass2( * and do not take a newname. Values are optional for set and * replace. * - * Name-value remove operations must have a name, do not + * Name-value set/remove operations must have a name, do not * take a newname, and can take a value. */ if (attr_name == NULL || name_len == 0) { From patchwork Thu Apr 6 19:19:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13203901 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 8CF76C76196 for ; Thu, 6 Apr 2023 19:19:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240572AbjDFTTs (ORCPT ); Thu, 6 Apr 2023 15:19:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240084AbjDFTTm (ORCPT ); Thu, 6 Apr 2023 15:19:42 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9C59F2127 for ; Thu, 6 Apr 2023 12:19:39 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 28A50643F3 for ; Thu, 6 Apr 2023 19:19:39 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7B487C433D2; Thu, 6 Apr 2023 19:19:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1680808778; bh=Lq9PBu9OMY2Dt+Ch+gbYwUpeA76dGXmxTqcWhnc6L4A=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Kj0tlG0I6A/B2JfeWO2XwkmUHOof0oVVDCyQpkO2/dB7LEK5lOTLZQAKLncBSQ3Rv 5nrjwizaujSBWfptv6Z5N3i6EI8MFuoVyOkR+Lmiy2rKh5/ASAN7mqiVl1imr53nS2 i6yVd2O+UpRjbB1USHZAbNpdfk/3xnUH9nSof+b0+JlfC8XEVHngMS/8PP85oG7zmO prIZ0lDIKfteoa2x4OV4Nv81uyvDkD9QgH78YhmS2AT5+Knm6el4gq+HSEMiVIiRym aPoQYM/9gLp3zVI+KHCHNhZvawpl25VQFmKYHHxnc4fji0Hv2YAhMxBI3sfXD+RQDu osl8eEG1rNVAA== Date: Thu, 06 Apr 2023 12:19:38 -0700 Subject: [PATCH 12/12] xfs: log NVLOOKUP xattr nvreplace operations From: "Darrick J. Wong" To: djwong@kernel.org Cc: Allison Henderson , allison.henderson@oracle.com, linux-xfs@vger.kernel.org Message-ID: <168080823974.613065.178526991534143046.stgit@frogsfrogsfrogs> In-Reply-To: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> References: <168080823794.613065.2971656278555515103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Allison Henderson (Formerly titled "xfs: Add new name to attri/d" and described as follows: This patch adds two new fields to the atti/d. They are nname and nnamelen. This will be used for parent pointer updates since a rename operation may cause the parent pointer to update both the name and value. So we need to carry both the new name as well as the target name in the attri/d.) If high level code wants to do a deferred xattr nvreplace operation with the NVLOOKUP flag set, we need to push this through the log. This log item records the old name/value pair and the new name/value pair, and completely replaces one with the other. Parent pointers will need this ability to handle rename moving a child file between parents. Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: reworked to handle new disk format] Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 20 ++++ fs/xfs/libxfs/xfs_attr.h | 4 - fs/xfs/libxfs/xfs_da_btree.h | 6 + fs/xfs/libxfs/xfs_log_format.h | 28 ++++- fs/xfs/xfs_attr_item.c | 207 +++++++++++++++++++++++++++++++++++----- fs/xfs/xfs_attr_item.h | 2 6 files changed, 233 insertions(+), 34 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 287990a9b29d..d03966796e97 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -425,6 +425,20 @@ xfs_attr_complete_op( return XFS_DAS_DONE; args->attr_filter &= ~XFS_ATTR_INCOMPLETE; + if (xfs_attr_intent_op(attr) != XFS_ATTRI_OP_FLAGS_NVREPLACE) + return replace_state; + + /* + * NVREPLACE operations require the caller to set the old and new names + * and values explicitly. + */ + ASSERT(args->new_namelen > 0); + + args->name = args->new_name; + args->namelen = args->new_namelen; + args->hashval = xfs_da_hashname(args->name, args->namelen); + args->value = args->new_value; + args->valuelen = args->new_valuelen; return replace_state; } @@ -926,9 +940,13 @@ xfs_attr_defer_replace( struct xfs_da_args *args) { struct xfs_attr_intent *new; + int op_flag = XFS_ATTRI_OP_FLAGS_REPLACE; int error = 0; - error = xfs_attr_intent_init(args, XFS_ATTRI_OP_FLAGS_REPLACE, &new); + if (args->op_flags & XFS_DA_OP_NVLOOKUP) + op_flag = XFS_ATTRI_OP_FLAGS_NVREPLACE; + + error = xfs_attr_intent_init(args, op_flag, &new); if (error) return error; diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h index f0aa372ecba1..d543a6a01f08 100644 --- a/fs/xfs/libxfs/xfs_attr.h +++ b/fs/xfs/libxfs/xfs_attr.h @@ -510,8 +510,8 @@ struct xfs_attr_intent { struct xfs_da_args *xattri_da_args; /* - * Shared buffer containing the attr name and value so that the logging - * code can share large memory buffers between log items. + * Shared buffer containing the attr name, new name, and value so that + * the logging code can share large memory buffers between log items. */ struct xfs_attri_log_nameval *xattri_nameval; diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h index 94a544fc8a9c..fc4dc3e87837 100644 --- a/fs/xfs/libxfs/xfs_da_btree.h +++ b/fs/xfs/libxfs/xfs_da_btree.h @@ -54,11 +54,15 @@ enum xfs_dacmp { */ typedef struct xfs_da_args { struct xfs_da_geometry *geo; /* da block geometry */ - const uint8_t *name; /* string (maybe not NULL terminated) */ + const uint8_t *name; /* string (maybe not NULL terminated) */ + const uint8_t *new_name; /* new attr name */ int namelen; /* length of string (maybe no NULL) */ + int new_namelen; /* new attr name len */ uint8_t filetype; /* filetype of inode for directories */ void *value; /* set of bytes (maybe contain NULLs) */ + void *new_value; /* new xattr value (may contain NULLs) */ int valuelen; /* length of value */ + int new_valuelen; /* length of new attr value */ unsigned int attr_filter; /* XFS_ATTR_{ROOT,SECURE,INCOMPLETE} */ unsigned int attr_flags; /* XATTR_{CREATE,REPLACE} */ xfs_dahash_t hashval; /* hash value of name */ diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index 7a4226e20dae..d666bfa5d08c 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -115,10 +115,11 @@ struct xfs_unmount_log_format { #define XLOG_REG_TYPE_BUD_FORMAT 26 #define XLOG_REG_TYPE_ATTRI_FORMAT 27 #define XLOG_REG_TYPE_ATTRD_FORMAT 28 -#define XLOG_REG_TYPE_ATTR_NAME 29 +#define XLOG_REG_TYPE_ATTR_NAME 29 #define XLOG_REG_TYPE_ATTR_VALUE 30 -#define XLOG_REG_TYPE_MAX 30 - +#define XLOG_REG_TYPE_ATTR_NEWNAME 31 +#define XLOG_REG_TYPE_ATTR_NEWVALUE 32 +#define XLOG_REG_TYPE_MAX 32 /* * Flags to log operation header @@ -959,6 +960,7 @@ struct xfs_icreate_log { #define XFS_ATTRI_OP_FLAGS_REPLACE 3 /* Replace the attribute */ #define XFS_ATTRI_OP_FLAGS_NVREMOVE 4 /* Remove attr w/ vlookup */ #define XFS_ATTRI_OP_FLAGS_NVSET 5 /* Set attr with w/ vlookup */ +#define XFS_ATTRI_OP_FLAGS_NVREPLACE 6 /* Replace attr name and val */ #define XFS_ATTRI_OP_FLAGS_TYPE_MASK 0xFF /* Flags type mask */ /* @@ -976,11 +978,27 @@ struct xfs_icreate_log { struct xfs_attri_log_format { uint16_t alfi_type; /* attri log item type */ uint16_t alfi_size; /* size of this item */ - uint32_t __pad; /* pad to 64 bit aligned */ + + /* + * For NVREPLACE, this is the length of the new xattr value. + * alfi_value_len contains the length of the old xattr value. + */ + uint32_t alfi_new_value_len; + uint64_t alfi_id; /* attri identifier */ uint64_t alfi_ino; /* the inode for this attr operation */ uint32_t alfi_op_flags; /* marks the op as a set or remove */ - uint32_t alfi_name_len; /* attr name length */ + union { + uint32_t alfi_name_len; /* attr name length */ + struct { + /* + * For NVREPLACE, these are the lengths of the old and + * new attr name. + */ + uint16_t alfi_old_name_len; + uint16_t alfi_new_name_len; + }; + }; uint32_t alfi_value_len; /* attr value length */ uint32_t alfi_attr_filter;/* attr filter flags */ }; diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c index f8def28090f8..cff8ff66cddc 100644 --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -75,8 +75,12 @@ static inline struct xfs_attri_log_nameval * xfs_attri_log_nameval_alloc( const void *name, unsigned int name_len, + const void *new_name, + unsigned int new_name_len, const void *value, - unsigned int value_len) + unsigned int value_len, + const void *new_value, + unsigned int new_value_len) { struct xfs_attri_log_nameval *nv; @@ -85,15 +89,26 @@ xfs_attri_log_nameval_alloc( * this. But kvmalloc() utterly sucks, so we use our own version. */ nv = xlog_kvmalloc(sizeof(struct xfs_attri_log_nameval) + - name_len + value_len); + name_len + new_name_len + value_len + + new_value_len); nv->name.i_addr = nv + 1; nv->name.i_len = name_len; nv->name.i_type = XLOG_REG_TYPE_ATTR_NAME; memcpy(nv->name.i_addr, name, name_len); + if (new_name_len) { + nv->new_name.i_addr = nv->name.i_addr + name_len; + nv->new_name.i_len = new_name_len; + memcpy(nv->new_name.i_addr, new_name, new_name_len); + } else { + nv->new_name.i_addr = NULL; + nv->new_name.i_len = 0; + } + nv->new_name.i_type = XLOG_REG_TYPE_ATTR_NEWNAME; + if (value_len) { - nv->value.i_addr = nv->name.i_addr + name_len; + nv->value.i_addr = nv->name.i_addr + name_len + new_name_len; nv->value.i_len = value_len; memcpy(nv->value.i_addr, value, value_len); } else { @@ -102,6 +117,17 @@ xfs_attri_log_nameval_alloc( } nv->value.i_type = XLOG_REG_TYPE_ATTR_VALUE; + if (new_value_len) { + nv->new_value.i_addr = nv->name.i_addr + name_len + + new_name_len + value_len; + nv->new_value.i_len = new_value_len; + memcpy(nv->new_value.i_addr, new_value, new_value_len); + } else { + nv->new_value.i_addr = NULL; + nv->new_value.i_len = 0; + } + nv->new_value.i_type = XLOG_REG_TYPE_ATTR_NEWVALUE; + refcount_set(&nv->refcount, 1); return nv; } @@ -147,11 +173,20 @@ xfs_attri_item_size( *nbytes += sizeof(struct xfs_attri_log_format) + xlog_calc_iovec_len(nv->name.i_len); - if (!nv->value.i_len) - return; + if (nv->new_name.i_len) { + *nvecs += 1; + *nbytes += xlog_calc_iovec_len(nv->new_name.i_len); + } - *nvecs += 1; - *nbytes += xlog_calc_iovec_len(nv->value.i_len); + if (nv->value.i_len) { + *nvecs += 1; + *nbytes += xlog_calc_iovec_len(nv->value.i_len); + } + + if (nv->new_value.i_len) { + *nvecs += 1; + *nbytes += xlog_calc_iovec_len(nv->new_value.i_len); + } } /* @@ -181,15 +216,28 @@ xfs_attri_item_format( ASSERT(nv->name.i_len > 0); attrip->attri_format.alfi_size++; + if (nv->new_name.i_len > 0) + attrip->attri_format.alfi_size++; + if (nv->value.i_len > 0) attrip->attri_format.alfi_size++; + if (nv->new_value.i_len > 0) + attrip->attri_format.alfi_size++; + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTRI_FORMAT, &attrip->attri_format, sizeof(struct xfs_attri_log_format)); xlog_copy_from_iovec(lv, &vecp, &nv->name); + + if (nv->new_name.i_len > 0) + xlog_copy_from_iovec(lv, &vecp, &nv->new_name); + if (nv->value.i_len > 0) xlog_copy_from_iovec(lv, &vecp, &nv->value); + + if (nv->new_value.i_len > 0) + xlog_copy_from_iovec(lv, &vecp, &nv->new_value); } /* @@ -379,7 +427,15 @@ xfs_attr_log_item( ASSERT(!(attr->xattri_op_flags & ~XFS_ATTRI_OP_FLAGS_TYPE_MASK)); attrp->alfi_op_flags = attr->xattri_op_flags; attrp->alfi_value_len = attr->xattri_nameval->value.i_len; - attrp->alfi_name_len = attr->xattri_nameval->name.i_len; + + if (xfs_attr_log_item_op(attrp) == XFS_ATTRI_OP_FLAGS_NVREPLACE) { + attrp->alfi_old_name_len = attr->xattri_nameval->name.i_len; + attrp->alfi_new_name_len = attr->xattri_nameval->new_name.i_len; + attrp->alfi_new_value_len = attr->xattri_nameval->new_value.i_len; + } else { + attrp->alfi_name_len = attr->xattri_nameval->name.i_len; + } + ASSERT(!(attr->xattri_da_args->attr_filter & ~XFS_ATTRI_FILTER_MASK)); attrp->alfi_attr_filter = attr->xattri_da_args->attr_filter; } @@ -420,8 +476,11 @@ xfs_attr_create_intent( * Transfer our reference to the name/value buffer to the * deferred work state structure. */ - attr->xattri_nameval = xfs_attri_log_nameval_alloc(args->name, - args->namelen, args->value, args->valuelen); + attr->xattri_nameval = xfs_attri_log_nameval_alloc( + args->name, args->namelen, + args->new_name, args->new_namelen, + args->value, args->valuelen, + args->new_value, args->new_valuelen); } attrip = xfs_attri_init(mp, attr->xattri_nameval); @@ -508,9 +567,6 @@ xfs_attri_validate( { unsigned int op = xfs_attr_log_item_op(attrp); - if (attrp->__pad != 0) - return false; - if (attrp->alfi_op_flags & ~XFS_ATTRI_OP_FLAGS_TYPE_MASK) return false; @@ -519,23 +575,43 @@ xfs_attri_validate( /* alfi_op_flags should be either a set or remove */ switch (op) { + case XFS_ATTRI_OP_FLAGS_REMOVE: + if (attrp->alfi_value_len != 0) + return false; + if (attrp->alfi_name_len == 0 || + attrp->alfi_name_len > XATTR_NAME_MAX) + return false; + if (attrp->alfi_new_value_len != 0) + return false; + break; case XFS_ATTRI_OP_FLAGS_SET: case XFS_ATTRI_OP_FLAGS_REPLACE: - case XFS_ATTRI_OP_FLAGS_REMOVE: case XFS_ATTRI_OP_FLAGS_NVREMOVE: case XFS_ATTRI_OP_FLAGS_NVSET: + if (attrp->alfi_name_len == 0 || + attrp->alfi_name_len > XATTR_NAME_MAX) + return false; + if (attrp->alfi_value_len > XATTR_SIZE_MAX) + return false; + if (attrp->alfi_new_value_len != 0) + return false; + break; + case XFS_ATTRI_OP_FLAGS_NVREPLACE: + if (attrp->alfi_old_name_len == 0 || + attrp->alfi_old_name_len > XATTR_NAME_MAX) + return false; + if (attrp->alfi_new_name_len == 0 || + attrp->alfi_new_name_len > XATTR_NAME_MAX) + return false; + if (attrp->alfi_value_len > XATTR_SIZE_MAX) + return false; + if (attrp->alfi_new_value_len > XATTR_SIZE_MAX) + return false; break; default: return false; } - if (attrp->alfi_value_len > XATTR_SIZE_MAX) - return false; - - if ((attrp->alfi_name_len > XATTR_NAME_MAX) || - (attrp->alfi_name_len == 0)) - return false; - return xfs_verify_ino(mp, attrp->alfi_ino); } @@ -595,9 +671,13 @@ xfs_attri_item_recover( args->whichfork = XFS_ATTR_FORK; args->name = nv->name.i_addr; args->namelen = nv->name.i_len; + args->new_name = nv->new_name.i_addr; + args->new_namelen = nv->new_name.i_len; args->hashval = xfs_da_hashname(args->name, args->namelen); args->value = nv->value.i_addr; args->valuelen = nv->value.i_len; + args->new_value = nv->new_value.i_addr; + args->new_valuelen = nv->new_value.i_len; args->attr_filter = attrp->alfi_attr_filter & XFS_ATTRI_FILTER_MASK; args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT | XFS_DA_OP_LOGGED; @@ -605,6 +685,7 @@ xfs_attri_item_recover( ASSERT(xfs_sb_version_haslogxattrs(&mp->m_sb)); switch (xfs_attr_intent_op(attr)) { + case XFS_ATTRI_OP_FLAGS_NVREPLACE: case XFS_ATTRI_OP_FLAGS_NVSET: args->op_flags |= XFS_DA_OP_NVLOOKUP; fallthrough; @@ -699,7 +780,15 @@ xfs_attri_item_relog( new_attrp->alfi_ino = old_attrp->alfi_ino; new_attrp->alfi_op_flags = old_attrp->alfi_op_flags; new_attrp->alfi_value_len = old_attrp->alfi_value_len; - new_attrp->alfi_name_len = old_attrp->alfi_name_len; + + if (xfs_attr_log_item_op(old_attrp) == XFS_ATTRI_OP_FLAGS_NVREPLACE) { + new_attrp->alfi_new_name_len = old_attrp->alfi_new_name_len; + new_attrp->alfi_old_name_len = old_attrp->alfi_old_name_len; + new_attrp->alfi_new_value_len = old_attrp->alfi_new_value_len; + } else { + new_attrp->alfi_name_len = old_attrp->alfi_name_len; + } + new_attrp->alfi_attr_filter = old_attrp->alfi_attr_filter; xfs_trans_add_item(tp, &new_attrip->attri_item); @@ -721,9 +810,13 @@ xlog_recover_attri_commit_pass2( struct xfs_attri_log_nameval *nv; const void *attr_name; const void *attr_value = NULL; + const void *attr_new_name = NULL; + const void *attr_new_value = NULL; size_t len; unsigned int name_len = 0; unsigned int value_len = 0; + unsigned int new_name_len = 0; + unsigned int new_value_len = 0; unsigned int op, i = 0; /* Validate xfs_attri_log_format before the large memory allocation */ @@ -775,6 +868,21 @@ xlog_recover_attri_commit_pass2( } name_len = attri_formatp->alfi_name_len; break; + case XFS_ATTRI_OP_FLAGS_NVREPLACE: + /* + * Log item, attr name, new attr name, optional attr value, + * optional new attr value + */ + if (item->ri_total < 3 || item->ri_total > 5) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + name_len = attri_formatp->alfi_old_name_len; + new_name_len = attri_formatp->alfi_new_name_len; + value_len = attri_formatp->alfi_value_len; + new_value_len = attri_formatp->alfi_new_value_len; + break; default: XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, attri_formatp, len); @@ -797,12 +905,30 @@ xlog_recover_attri_commit_pass2( } i++; + /* Validate the new attr name */ + if (new_name_len > 0) { + if (item->ri_buf[i].i_len != xlog_calc_iovec_len(new_name_len)) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + item->ri_buf[i].i_addr, + item->ri_buf[i].i_len); + return -EFSCORRUPTED; + } + + attr_new_name = item->ri_buf[i].i_addr; + if (!xfs_attr_namecheck(attr_new_name, new_name_len)) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + item->ri_buf[i].i_addr, + item->ri_buf[i].i_len); + return -EFSCORRUPTED; + } + i++; + } + /* Validate the attr value, if present */ if (value_len != 0) { if (item->ri_buf[i].i_len != xlog_calc_iovec_len(value_len)) { XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, - item->ri_buf[0].i_addr, - item->ri_buf[0].i_len); + attri_formatp, len); return -EFSCORRUPTED; } @@ -810,6 +936,18 @@ xlog_recover_attri_commit_pass2( i++; } + /* Validate the new attr value, if present */ + if (new_value_len != 0) { + if (item->ri_buf[i].i_len != xlog_calc_iovec_len(new_value_len)) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + + attr_new_value = item->ri_buf[i].i_addr; + i++; + } + /* * Make sure we got the correct number of buffers for the operation * that we just loaded. @@ -847,6 +985,23 @@ xlog_recover_attri_commit_pass2( return -EFSCORRUPTED; } break; + case XFS_ATTRI_OP_FLAGS_NVREPLACE: + /* + * Name-value replace operations require the caller to + * specify the old and new names and values explicitly. + * Values are optional. + */ + if (attr_name == NULL || name_len == 0) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + if (attr_new_name == NULL || new_name_len == 0) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; + } + break; } /* @@ -855,7 +1010,9 @@ xlog_recover_attri_commit_pass2( * reference. */ nv = xfs_attri_log_nameval_alloc(attr_name, name_len, - attr_value, value_len); + attr_new_name, new_name_len, + attr_value, value_len, + attr_new_value, new_value_len); attrip = xfs_attri_init(mp, nv); memcpy(&attrip->attri_format, attri_formatp, len); diff --git a/fs/xfs/xfs_attr_item.h b/fs/xfs/xfs_attr_item.h index 3280a7930287..9ae0b3696847 100644 --- a/fs/xfs/xfs_attr_item.h +++ b/fs/xfs/xfs_attr_item.h @@ -13,7 +13,9 @@ struct kmem_zone; struct xfs_attri_log_nameval { struct xfs_log_iovec name; + struct xfs_log_iovec new_name; /* NVREPLACE only */ struct xfs_log_iovec value; + struct xfs_log_iovec new_value; /* NVREPLACE only */ refcount_t refcount; /* name and value follow the end of this struct */