From patchwork Fri May 26 02:22:06 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: 13256302 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 E3C98C77B7E for ; Fri, 26 May 2023 02:22:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234343AbjEZCWV (ORCPT ); Thu, 25 May 2023 22:22:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52292 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234886AbjEZCWU (ORCPT ); Thu, 25 May 2023 22:22:20 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 53A09E49 for ; Thu, 25 May 2023 19:22: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 99F4B6157B for ; Fri, 26 May 2023 02:22:07 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 03DF9C433EF; Fri, 26 May 2023 02:22:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067727; bh=JFIu/w1I24dkPVDrccllkPMvEJvjkVuxOo0jmjVv3jw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=nXFujBkCVAuTwe08wfjdoXfqgxncTKppOJoZxNgwTcWeescHbcIdV6V0hZjH8IjDX 42TSVP4dWqYbzRsTsorXBO185G47+hA3lag5c51LDHE4KQIIPZ/W3CUq/7vOCRJfqm K9GIxQGYxLj4nvGZIrCdWOOAaRnp5Lm+oGa33kqggoxz+Wgcr6L3Hzi3sFOuLOL7fc J3QJP3MLeJLXgX7fc6lUZO8ncmCyULgKeMJGbtEBxpMvJFba+zlm9cz/x7wBQiayms kvayyjRquYg5nXKQHEfD/pG5V0KGf/LrC7JIe5RYsx8o2ufGhMExSeVhyqMEDEOgDg enQrOezgT6yjg== Date: Thu, 25 May 2023 19:22:06 -0700 Subject: [PATCH 01/30] xfs: add parent pointer support to attribute code From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Mark Tinguely , Dave Chinner , Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506077902.3749421.16610562718763614651.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Add the new parent attribute type. XFS_ATTR_PARENT is used only for parent pointer entries; it uses reserved blocks like XFS_ATTR_ROOT. Signed-off-by: Mark Tinguely Signed-off-by: Dave Chinner Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- libxfs/xfs_attr.c | 3 ++- libxfs/xfs_da_format.h | 5 ++++- libxfs/xfs_log_format.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index 2e6b6d6576e..0d0cf274cc7 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -990,7 +990,8 @@ xfs_attr_set( struct xfs_inode *dp = args->dp; struct xfs_mount *mp = dp->i_mount; struct xfs_trans_res tres; - bool rsvd = (args->attr_filter & XFS_ATTR_ROOT); + bool rsvd = (args->attr_filter & (XFS_ATTR_ROOT | + XFS_ATTR_PARENT)); bool is_remove = args->op_flags & XFS_DA_OP_REMOVE; int error, local; int rmt_blks = 0; diff --git a/libxfs/xfs_da_format.h b/libxfs/xfs_da_format.h index e37de511bc2..dd1c70385cf 100644 --- a/libxfs/xfs_da_format.h +++ b/libxfs/xfs_da_format.h @@ -699,12 +699,15 @@ struct xfs_attr3_leafblock { #define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ #define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ #define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ +#define XFS_ATTR_PARENT_BIT 3 /* parent pointer attrs */ #define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ #define XFS_ATTR_LOCAL (1u << XFS_ATTR_LOCAL_BIT) #define XFS_ATTR_ROOT (1u << XFS_ATTR_ROOT_BIT) #define XFS_ATTR_SECURE (1u << XFS_ATTR_SECURE_BIT) +#define XFS_ATTR_PARENT (1u << XFS_ATTR_PARENT_BIT) #define XFS_ATTR_INCOMPLETE (1u << XFS_ATTR_INCOMPLETE_BIT) -#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE) +#define XFS_ATTR_NSP_ONDISK_MASK \ + (XFS_ATTR_ROOT | XFS_ATTR_SECURE | XFS_ATTR_PARENT) #define XFS_ATTR_NAMESPACE_STR \ { XFS_ATTR_LOCAL, "local" }, \ diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h index 21fbe1f49b6..d484a176a76 100644 --- a/libxfs/xfs_log_format.h +++ b/libxfs/xfs_log_format.h @@ -1049,6 +1049,7 @@ struct xfs_icreate_log { */ #define XFS_ATTRI_FILTER_MASK (XFS_ATTR_ROOT | \ XFS_ATTR_SECURE | \ + XFS_ATTR_PARENT | \ XFS_ATTR_INCOMPLETE) /* From patchwork Fri May 26 02:22: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: 13256303 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 15471C77B7E for ; Fri, 26 May 2023 02:22:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234388AbjEZCW3 (ORCPT ); Thu, 25 May 2023 22:22:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52398 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234676AbjEZCW3 (ORCPT ); Thu, 25 May 2023 22:22:29 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8948E1B1 for ; Thu, 25 May 2023 19:22:23 -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 2054464C49 for ; Fri, 26 May 2023 02:22:23 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8499CC4339B; Fri, 26 May 2023 02:22:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067742; bh=OgVYIxfhTNFCRckhNEZRqTOM5uV/LWcESWbN67AKyd0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=dJDdsRIy0KSrm8VSjfd5JkStie0j9E3+k9P+NTXu5Ag0FDfYHrB2FpKEXN4+godM2 /Lbkvqv39vFAhm4IbTnlwRC6MdC2AdflxD+/ozofAmQesS+CjGSeXwBDqe+TQec6ES AqPO+cqhwJRyl0AzUJHErFvFXf1x3gTOxquqJEiuQ4yyMSAVCBTTCgCsRM6UroHlwt a6QnFyqyMc+u6rpbsL1DQ7bUowwG7xvtJtYV250xGq2hKfh6OZQd8nhmBE3g+VRJGI fEI03WeTBmByTJG1rN2tAjps+8yFPVlnh87GUbaPP1PasNTv4KiK07SsTO3yYGSJc0 7JiVD4cchpt0Q== Date: Thu, 25 May 2023 19:22:22 -0700 Subject: [PATCH 02/30] xfs: define parent pointer ondisk extended attribute format From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Dave Chinner , Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506077915.3749421.4452983979387529506.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 We need to define the parent pointer attribute format before we start adding support for it into all the code that needs to use it. The EA format we will use encodes the following information: name={parent inode #, parent inode generation, dirent namehash} value={dirent name} The inode/gen gives all the information we need to reliably identify the parent without requiring child->parent lock ordering, and allows userspace to do pathname component level reconstruction without the kernel ever needing to verify the parent itself as part of ioctl calls. Storing the dirent name hash in the key reduces hash collisions if a file is hardlinked multiple times in the same directory. By using the NVLOOKUP mode in the extended attribute code to match parent pointers using both the xattr name and value, we can identify the exact parent pointer EA we need to modify/remove in rename/unlink operations without searching the entire EA space. By storing the dirent name, we have enough information to be able to validate and reconstruct damaged directory trees. Earlier iterations of this patchset encoded the directory offset in the parent pointer key, but this format required repair to keep that in sync across directory rebuilds, which is unnecessary complexity. Signed-off-by: Dave Chinner Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: replace diroffset with the namehash in the pptr key] Signed-off-by: Darrick J. Wong --- libxfs/xfs_da_format.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libxfs/xfs_da_format.h b/libxfs/xfs_da_format.h index dd1c70385cf..62d75e0f368 100644 --- a/libxfs/xfs_da_format.h +++ b/libxfs/xfs_da_format.h @@ -821,4 +821,25 @@ static inline unsigned int xfs_dir2_dirblock_bytes(struct xfs_sb *sbp) xfs_failaddr_t xfs_da3_blkinfo_verify(struct xfs_buf *bp, struct xfs_da3_blkinfo *hdr3); +/* + * Parent pointer attribute format definition + * + * The xattr name encodes the parent inode number, generation and the crc32c + * hash of the dirent name. + * + * The xattr value contains the dirent name. + */ +struct xfs_parent_name_rec { + __be64 p_ino; + __be32 p_gen; + __be32 p_namehash; +}; + +/* + * Maximum size of the dirent name that can be stored in a parent pointer. + * This matches the maximum dirent name length. + */ +#define XFS_PARENT_DIRENT_NAME_MAX_SIZE \ + (MAXNAMELEN - 1) + #endif /* __XFS_DA_FORMAT_H__ */ From patchwork Fri May 26 02:22:37 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: 13256304 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 76129C77B7E for ; Fri, 26 May 2023 02:22:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230154AbjEZCWl (ORCPT ); Thu, 25 May 2023 22:22:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52476 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230099AbjEZCWk (ORCPT ); Thu, 25 May 2023 22:22:40 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 352159B for ; Thu, 25 May 2023 19:22: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 ADDAB61276 for ; Fri, 26 May 2023 02:22:38 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 18522C433EF; Fri, 26 May 2023 02:22:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067758; bh=EtfJv/pgevDcgdkMAJHkkhcTDu7sq1n9Oa1lxAV1QyA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=OgA/df60bhGCRjH74wNVqrN5g1KtR496PWVPGKlJno/u7zOEP+dh1h1WdGB4swiri aPN3PKDJPJSp6OHfYTGa7kJSFZNqg1xE9waN/NVJBqg6UcM6yN0qGkhLb0waSx96Fy F0RAjj3OLDySKJvl0CfHpJXicZmu25ZWVwdwQ4HXyf2Eh0iuPaxuqp5wxODPehNBMu fPbtUlJFOPVPHPtrSd1OrUgmvASGEF+lbqGjQOGar/7ZPIGKf/B36CNAGzM8CsO2AR dFA8g77axm+xzlgV8zkXbZlYW9NpR/1R/hsIXRW6FebFtQNi2LuSdi35R1FaeUukOm MG+w6WSC+4KMg== Date: Thu, 25 May 2023 19:22:37 -0700 Subject: [PATCH 03/30] xfs: add parent pointer validator functions From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506077929.3749421.2302263993928538690.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Attribute names of parent pointers are not strings. So we need to modify attr_namecheck to verify parent pointer records when the XFS_ATTR_PARENT flag is set. At the same time, we need to validate attr values during log recovery if the xattr is really a parent pointer. Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: move functions to xfs_parent.c, adjust for new disk format] Signed-off-by: Darrick J. Wong --- libxfs/Makefile | 2 + libxfs/xfs_attr.c | 10 ++++- libxfs/xfs_attr.h | 3 +- libxfs/xfs_da_format.h | 8 ++++ libxfs/xfs_parent.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_parent.h | 16 ++++++++ repair/attr_repair.c | 19 ++++++---- 7 files changed, 140 insertions(+), 10 deletions(-) create mode 100644 libxfs/xfs_parent.c create mode 100644 libxfs/xfs_parent.h diff --git a/libxfs/Makefile b/libxfs/Makefile index f485ece835e..a12f43da149 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -49,6 +49,7 @@ HFILES = \ xfs_ialloc_btree.h \ xfs_inode_buf.h \ xfs_inode_fork.h \ + xfs_parent.h \ xfs_quota_defs.h \ xfs_refcount.h \ xfs_refcount_btree.h \ @@ -99,6 +100,7 @@ CFILES = cache.c \ xfs_inode_fork.c \ xfs_ialloc_btree.c \ xfs_log_rlimit.c \ + xfs_parent.c \ xfs_refcount.c \ xfs_refcount_btree.c \ xfs_rmap.c \ diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index 0d0cf274cc7..ba880fb8575 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -24,6 +24,7 @@ #include "xfs_quota_defs.h" #include "xfs_trans_space.h" #include "xfs_trace.h" +#include "xfs_parent.h" struct kmem_cache *xfs_attr_intent_cache; @@ -1594,9 +1595,14 @@ xfs_attr_node_get( /* Returns true if the attribute entry name is valid. */ bool xfs_attr_namecheck( - const void *name, - size_t length) + struct xfs_mount *mp, + const void *name, + size_t length, + unsigned int flags) { + if (flags & XFS_ATTR_PARENT) + return xfs_parent_namecheck(mp, name, length, flags); + /* * MAXNAMELEN includes the trailing null, but (name/length) leave it * out, so use >= for the length check. diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h index bb1776b8a6c..d2165c85f16 100644 --- a/libxfs/xfs_attr.h +++ b/libxfs/xfs_attr.h @@ -552,7 +552,8 @@ int xfs_attr_get(struct xfs_da_args *args); int xfs_attr_set(struct xfs_da_args *args); int xfs_attr_set_iter(struct xfs_attr_intent *attr); int xfs_attr_remove_iter(struct xfs_attr_intent *attr); -bool xfs_attr_namecheck(const void *name, size_t length); +bool xfs_attr_namecheck(struct xfs_mount *mp, const void *name, size_t length, + unsigned int flags); int xfs_attr_calc_size(struct xfs_da_args *args, int *local); void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres, unsigned int *total); diff --git a/libxfs/xfs_da_format.h b/libxfs/xfs_da_format.h index 62d75e0f368..700c87743ae 100644 --- a/libxfs/xfs_da_format.h +++ b/libxfs/xfs_da_format.h @@ -747,6 +747,14 @@ xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx) return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)]; } +static inline int +xfs_attr3_leaf_flags(xfs_attr_leafblock_t *leafp, int idx) +{ + struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp); + + return entries[idx].flags; +} + static inline xfs_attr_leaf_name_remote_t * xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx) { diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c new file mode 100644 index 00000000000..583607c1301 --- /dev/null +++ b/libxfs/xfs_parent.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022-2023 Oracle, Inc. + * All rights reserved. + */ +#include "libxfs_priv.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_inode.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_trace.h" +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_da_format.h" +#include "xfs_bmap_btree.h" +#include "xfs_trans.h" +#include "xfs_da_btree.h" +#include "xfs_attr.h" +#include "xfs_dir2.h" +#include "xfs_attr_sf.h" +#include "xfs_bmap.h" +#include "xfs_parent.h" +#include "xfs_da_format.h" +#include "xfs_format.h" +#include "xfs_trans_space.h" + +/* + * Parent pointer attribute handling. + * + * Because the attribute value is a filename component, it will never be longer + * than 255 bytes. This means the attribute will always be a local format + * attribute as it is xfs_attr_leaf_entsize_local_max() for v5 filesystems will + * always be larger than this (max is 75% of block size). + * + * Creating a new parent attribute will always create a new attribute - there + * should never, ever be an existing attribute in the tree for a new inode. + * ENOSPC behavior is problematic - creating the inode without the parent + * pointer is effectively a corruption, so we allow parent attribute creation + * to dip into the reserve block pool to avoid unexpected ENOSPC errors from + * occurring. + */ + +/* Return true if parent pointer EA name is valid. */ +bool +xfs_parent_namecheck( + struct xfs_mount *mp, + const struct xfs_parent_name_rec *rec, + size_t reclen, + unsigned int attr_flags) +{ + xfs_ino_t p_ino; + + if (!(attr_flags & XFS_ATTR_PARENT)) + return false; + + if (reclen != sizeof(struct xfs_parent_name_rec)) + return false; + + /* Only one namespace bit allowed. */ + if (hweight32(attr_flags & XFS_ATTR_NSP_ONDISK_MASK) > 1) + return false; + + p_ino = be64_to_cpu(rec->p_ino); + if (!xfs_verify_ino(mp, p_ino)) + return false; + + return true; +} + +/* Return true if parent pointer EA value is valid. */ +bool +xfs_parent_valuecheck( + struct xfs_mount *mp, + const void *value, + size_t valuelen) +{ + if (valuelen == 0 || valuelen > XFS_PARENT_DIRENT_NAME_MAX_SIZE) + return false; + + if (value == NULL) + return false; + + /* Valid dirent name? */ + if (!xfs_dir2_namecheck(value, valuelen)) + return false; + + return true; +} diff --git a/libxfs/xfs_parent.h b/libxfs/xfs_parent.h new file mode 100644 index 00000000000..6e2a2528d2d --- /dev/null +++ b/libxfs/xfs_parent.h @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022-2023 Oracle, Inc. + * All Rights Reserved. + */ +#ifndef __XFS_PARENT_H__ +#define __XFS_PARENT_H__ + +/* Metadata validators */ +bool xfs_parent_namecheck(struct xfs_mount *mp, + const struct xfs_parent_name_rec *rec, size_t reclen, + unsigned int attr_flags); +bool xfs_parent_valuecheck(struct xfs_mount *mp, const void *value, + size_t valuelen); + +#endif /* __XFS_PARENT_H__ */ diff --git a/repair/attr_repair.c b/repair/attr_repair.c index c3a6d50267e..afe8073ca8e 100644 --- a/repair/attr_repair.c +++ b/repair/attr_repair.c @@ -293,8 +293,9 @@ process_shortform_attr( } /* namecheck checks for null chars in attr names. */ - if (!libxfs_attr_namecheck(currententry->nameval, - currententry->namelen)) { + if (!libxfs_attr_namecheck(mp, currententry->nameval, + currententry->namelen, + currententry->flags)) { do_warn( _("entry contains illegal character in shortform attribute name\n")); junkit = 1; @@ -454,12 +455,14 @@ process_leaf_attr_local( xfs_dablk_t da_bno, xfs_ino_t ino) { - xfs_attr_leaf_name_local_t *local; + xfs_attr_leaf_name_local_t *local; + int flags; local = xfs_attr3_leaf_name_local(leaf, i); + flags = xfs_attr3_leaf_flags(leaf, i); if (local->namelen == 0 || - !libxfs_attr_namecheck(local->nameval, - local->namelen)) { + !libxfs_attr_namecheck(mp, local->nameval, + local->namelen, flags)) { do_warn( _("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"), i, da_bno, ino, local->namelen); @@ -510,12 +513,14 @@ process_leaf_attr_remote( { xfs_attr_leaf_name_remote_t *remotep; char* value; + int flags; remotep = xfs_attr3_leaf_name_remote(leaf, i); + flags = xfs_attr3_leaf_flags(leaf, i); if (remotep->namelen == 0 || - !libxfs_attr_namecheck(remotep->name, - remotep->namelen) || + !libxfs_attr_namecheck(mp, remotep->name, + remotep->namelen, flags) || be32_to_cpu(entry->hashval) != libxfs_da_hashname((unsigned char *)&remotep->name[0], remotep->namelen) || From patchwork Fri May 26 02:22:53 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: 13256305 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 1D1F2C77B7A for ; Fri, 26 May 2023 02:22:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230091AbjEZCW5 (ORCPT ); Thu, 25 May 2023 22:22:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52530 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229646AbjEZCW4 (ORCPT ); Thu, 25 May 2023 22:22:56 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C4E449B for ; Thu, 25 May 2023 19:22:54 -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 525F564C4C for ; Fri, 26 May 2023 02:22:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B1DDCC433EF; Fri, 26 May 2023 02:22:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067773; bh=WBzf0MVFnZP1CdP/QMg0+Pgu2/9RhDDx4P+8cjSM4s0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=GcR2BQXYmP2dqiP9eyNmsMh9jJx8/qMA/F0zeIcG3tyflAQuUBB3yTkFP8qKke/ip PRJMK2hVSSPcq2PDGcP/XpKYdGCstX9Xiq2O/1YKBd1MEYlknP/s+EobaYihT9ktOs fv2Kq2FDNK84YjCnLjQQPsYY2kYjIV9WmPovPKrmQ2a5oEbGBz7CWTLmBrQwa0ptne MHlGjMk4T2bbimkHErnQWKzXWgWgTxG2llG29OE7OdwOVOBRIcEXKMBLd6SZp0YNdR gSvhMYepg7UDWcgHBDyLV1zwq1lIe8APhA3OTqE3rp9jD74D8LOoRwgkGEmqTWLMHT u/C9bT7Scrl5A== Date: Thu, 25 May 2023 19:22:53 -0700 Subject: [PATCH 04/30] xfs: extend transaction reservations for parent attributes From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Dave Chinner , Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506077943.3749421.3907885810042930441.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 We need to add, remove or modify parent pointer attributes during create/link/unlink/rename operations atomically with the dirents in the parent directories being modified. This means they need to be modified in the same transaction as the parent directories, and so we need to add the required space for the attribute modifications to the transaction reservations. Signed-off-by: Dave Chinner Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: fix indenting errors, adjust for new log format] Signed-off-by: Darrick J. Wong --- libxfs/libxfs_priv.h | 1 libxfs/xfs_trans_resv.c | 324 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 273 insertions(+), 52 deletions(-) diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index 1d5621fc2ee..2690431772d 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -544,6 +544,7 @@ static inline int retzero(void) { return 0; } #define xfs_icreate_log(tp, agno, agbno, cnt, isize, len, gen) ((void) 0) #define xfs_sb_validate_fsb_count(sbp, nblks) (0) +#define xlog_calc_iovec_len(len) roundup(len, sizeof(uint32_t)) /* * Prototypes for kernel static functions that are aren't in their diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c index 04c444806fe..b555d455f23 100644 --- a/libxfs/xfs_trans_resv.c +++ b/libxfs/xfs_trans_resv.c @@ -18,6 +18,7 @@ #include "xfs_trans.h" #include "xfs_trans_space.h" #include "xfs_quota_defs.h" +#include "xfs_da_format.h" #define _ALLOC true #define _FREE false @@ -419,29 +420,110 @@ xfs_calc_itruncate_reservation_minlogsize( return xfs_calc_itruncate_reservation(mp, true); } +static inline unsigned int xfs_calc_pptr_link_overhead(void) +{ + return sizeof(struct xfs_attri_log_format) + + xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) + + xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE); +} +static inline unsigned int xfs_calc_pptr_unlink_overhead(void) +{ + return sizeof(struct xfs_attri_log_format) + + xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) + + xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE); +} +static inline unsigned int xfs_calc_pptr_replace_overhead(void) +{ + return sizeof(struct xfs_attri_log_format) + + xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) + + xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE) + + xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) + + xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE); +} + /* * In renaming a files we can modify: * the five inodes involved: 5 * inode size * the two directory btrees: 2 * (max depth + v2) * dir block size * the two directory bmap btrees: 2 * max depth * block size * And the bmap_finish transaction can free dir and bmap blocks (two sets - * of bmap blocks) giving: + * of bmap blocks) giving (t2): * the agf for the ags in which the blocks live: 3 * sector size * the agfl for the ags in which the blocks live: 3 * sector size * the superblock for the free block count: sector size * the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size + * If parent pointers are enabled (t3), then each transaction in the chain + * must be capable of setting or removing the extended attribute + * containing the parent information. It must also be able to handle + * the three xattr intent items that track the progress of the parent + * pointer update. */ STATIC uint xfs_calc_rename_reservation( struct xfs_mount *mp) { - return XFS_DQUOT_LOGRES(mp) + - max((xfs_calc_inode_res(mp, 5) + - xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp), - XFS_FSB_TO_B(mp, 1))), - (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(xfs_allocfree_block_count(mp, 3), - XFS_FSB_TO_B(mp, 1)))); + unsigned int overhead = XFS_DQUOT_LOGRES(mp); + struct xfs_trans_resv *resp = M_RES(mp); + unsigned int t1, t2, t3 = 0; + + t1 = xfs_calc_inode_res(mp, 5) + + xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp), + XFS_FSB_TO_B(mp, 1)); + + t2 = xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) + + xfs_calc_buf_res(xfs_allocfree_block_count(mp, 3), + XFS_FSB_TO_B(mp, 1)); + + if (xfs_has_parent(mp)) { + unsigned int rename_overhead, exchange_overhead; + + t3 = max(resp->tr_attrsetm.tr_logres, + resp->tr_attrrm.tr_logres); + + /* + * For a standard rename, the three xattr intent log items + * are (1) replacing the pptr for the source file; (2) + * removing the pptr on the dest file; and (3) adding a + * pptr for the whiteout file in the src dir. + * + * For an RENAME_EXCHANGE, there are two xattr intent + * items to replace the pptr for both src and dest + * files. Link counts don't change and there is no + * whiteout. + * + * In the worst case we can end up relogging all log + * intent items to allow the log tail to move ahead, so + * they become overhead added to each transaction in a + * processing chain. + */ + rename_overhead = xfs_calc_pptr_replace_overhead() + + xfs_calc_pptr_unlink_overhead() + + xfs_calc_pptr_link_overhead(); + exchange_overhead = 2 * xfs_calc_pptr_replace_overhead(); + + overhead += max(rename_overhead, exchange_overhead); + } + + return overhead + max3(t1, t2, t3); +} + +static inline unsigned int +xfs_rename_log_count( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + /* One for the rename, one more for freeing blocks */ + unsigned int ret = XFS_RENAME_LOG_COUNT; + + /* + * Pre-reserve enough log reservation to handle the transaction + * rolling needed to remove or add one parent pointer. + */ + if (xfs_has_parent(mp)) + ret += max(resp->tr_attrsetm.tr_logcount, + resp->tr_attrrm.tr_logcount); + + return ret; } /* @@ -458,6 +540,23 @@ xfs_calc_iunlink_remove_reservation( 2 * M_IGEO(mp)->inode_cluster_size; } +static inline unsigned int +xfs_link_log_count( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + unsigned int ret = XFS_LINK_LOG_COUNT; + + /* + * Pre-reserve enough log reservation to handle the transaction + * rolling needed to add one parent pointer. + */ + if (xfs_has_parent(mp)) + ret += resp->tr_attrsetm.tr_logcount; + + return ret; +} + /* * For creating a link to an inode: * the parent directory inode: inode size @@ -474,14 +573,23 @@ STATIC uint xfs_calc_link_reservation( struct xfs_mount *mp) { - return XFS_DQUOT_LOGRES(mp) + - xfs_calc_iunlink_remove_reservation(mp) + - max((xfs_calc_inode_res(mp, 2) + - xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), - XFS_FSB_TO_B(mp, 1))), - (xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1), - XFS_FSB_TO_B(mp, 1)))); + unsigned int overhead = XFS_DQUOT_LOGRES(mp); + struct xfs_trans_resv *resp = M_RES(mp); + unsigned int t1, t2, t3 = 0; + + overhead += xfs_calc_iunlink_remove_reservation(mp); + t1 = xfs_calc_inode_res(mp, 2) + + xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)); + t2 = xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + + xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1), + XFS_FSB_TO_B(mp, 1)); + + if (xfs_has_parent(mp)) { + t3 = resp->tr_attrsetm.tr_logres; + overhead += xfs_calc_pptr_link_overhead(); + } + + return overhead + max3(t1, t2, t3); } /* @@ -496,6 +604,23 @@ xfs_calc_iunlink_add_reservation(xfs_mount_t *mp) M_IGEO(mp)->inode_cluster_size; } +static inline unsigned int +xfs_remove_log_count( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + unsigned int ret = XFS_REMOVE_LOG_COUNT; + + /* + * Pre-reserve enough log reservation to handle the transaction + * rolling needed to add one parent pointer. + */ + if (xfs_has_parent(mp)) + ret += resp->tr_attrrm.tr_logcount; + + return ret; +} + /* * For removing a directory entry we can modify: * the parent directory inode: inode size @@ -512,14 +637,24 @@ STATIC uint xfs_calc_remove_reservation( struct xfs_mount *mp) { - return XFS_DQUOT_LOGRES(mp) + - xfs_calc_iunlink_add_reservation(mp) + - max((xfs_calc_inode_res(mp, 2) + - xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), - XFS_FSB_TO_B(mp, 1))), - (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), - XFS_FSB_TO_B(mp, 1)))); + unsigned int overhead = XFS_DQUOT_LOGRES(mp); + struct xfs_trans_resv *resp = M_RES(mp); + unsigned int t1, t2, t3 = 0; + + overhead += xfs_calc_iunlink_add_reservation(mp); + + t1 = xfs_calc_inode_res(mp, 2) + + xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)); + t2 = xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) + + xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), + XFS_FSB_TO_B(mp, 1)); + + if (xfs_has_parent(mp)) { + t3 = resp->tr_attrrm.tr_logres; + overhead += xfs_calc_pptr_unlink_overhead(); + } + + return overhead + max3(t1, t2, t3); } /* @@ -568,12 +703,40 @@ xfs_calc_icreate_resv_alloc( xfs_calc_finobt_res(mp); } +static inline unsigned int +xfs_icreate_log_count( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + unsigned int ret = XFS_CREATE_LOG_COUNT; + + /* + * Pre-reserve enough log reservation to handle the transaction + * rolling needed to add one parent pointer. + */ + if (xfs_has_parent(mp)) + ret += resp->tr_attrsetm.tr_logcount; + + return ret; +} + STATIC uint -xfs_calc_icreate_reservation(xfs_mount_t *mp) +xfs_calc_icreate_reservation( + struct xfs_mount *mp) { - return XFS_DQUOT_LOGRES(mp) + - max(xfs_calc_icreate_resv_alloc(mp), - xfs_calc_create_resv_modify(mp)); + struct xfs_trans_resv *resp = M_RES(mp); + unsigned int overhead = XFS_DQUOT_LOGRES(mp); + unsigned int t1, t2, t3 = 0; + + t1 = xfs_calc_icreate_resv_alloc(mp); + t2 = xfs_calc_create_resv_modify(mp); + + if (xfs_has_parent(mp)) { + t3 = resp->tr_attrsetm.tr_logres; + overhead += xfs_calc_pptr_link_overhead(); + } + + return overhead + max3(t1, t2, t3); } STATIC uint @@ -586,6 +749,23 @@ xfs_calc_create_tmpfile_reservation( return res + xfs_calc_iunlink_add_reservation(mp); } +static inline unsigned int +xfs_mkdir_log_count( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + unsigned int ret = XFS_MKDIR_LOG_COUNT; + + /* + * Pre-reserve enough log reservation to handle the transaction + * rolling needed to add one parent pointer. + */ + if (xfs_has_parent(mp)) + ret += resp->tr_attrsetm.tr_logcount; + + return ret; +} + /* * Making a new directory is the same as creating a new file. */ @@ -596,6 +776,22 @@ xfs_calc_mkdir_reservation( return xfs_calc_icreate_reservation(mp); } +static inline unsigned int +xfs_symlink_log_count( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + unsigned int ret = XFS_SYMLINK_LOG_COUNT; + + /* + * Pre-reserve enough log reservation to handle the transaction + * rolling needed to add one parent pointer. + */ + if (xfs_has_parent(mp)) + ret += resp->tr_attrsetm.tr_logcount; + + return ret; +} /* * Making a new symplink is the same as creating a new file, but @@ -908,6 +1104,52 @@ xfs_calc_sb_reservation( return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); } +/* + * Namespace reservations. + * + * These get tricky when parent pointers are enabled as we have attribute + * modifications occurring from within these transactions. Rather than confuse + * each of these reservation calculations with the conditional attribute + * reservations, add them here in a clear and concise manner. This requires that + * the attribute reservations have already been calculated. + * + * Note that we only include the static attribute reservation here; the runtime + * reservation will have to be modified by the size of the attributes being + * added/removed/modified. See the comments on the attribute reservation + * calculations for more details. + */ +STATIC void +xfs_calc_namespace_reservations( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + ASSERT(resp->tr_attrsetm.tr_logres > 0); + + resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp); + resp->tr_rename.tr_logcount = xfs_rename_log_count(mp, resp); + resp->tr_rename.tr_logflags |= XFS_TRANS_PERM_LOG_RES; + + resp->tr_link.tr_logres = xfs_calc_link_reservation(mp); + resp->tr_link.tr_logcount = xfs_link_log_count(mp, resp); + resp->tr_link.tr_logflags |= XFS_TRANS_PERM_LOG_RES; + + resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp); + resp->tr_remove.tr_logcount = xfs_remove_log_count(mp, resp); + resp->tr_remove.tr_logflags |= XFS_TRANS_PERM_LOG_RES; + + resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp); + resp->tr_symlink.tr_logcount = xfs_symlink_log_count(mp, resp); + resp->tr_symlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES; + + resp->tr_create.tr_logres = xfs_calc_icreate_reservation(mp); + resp->tr_create.tr_logcount = xfs_icreate_log_count(mp, resp); + resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES; + + resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp); + resp->tr_mkdir.tr_logcount = xfs_mkdir_log_count(mp, resp); + resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES; +} + void xfs_trans_resv_calc( struct xfs_mount *mp, @@ -927,35 +1169,11 @@ xfs_trans_resv_calc( resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT; resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES; - resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp); - resp->tr_rename.tr_logcount = XFS_RENAME_LOG_COUNT; - resp->tr_rename.tr_logflags |= XFS_TRANS_PERM_LOG_RES; - - resp->tr_link.tr_logres = xfs_calc_link_reservation(mp); - resp->tr_link.tr_logcount = XFS_LINK_LOG_COUNT; - resp->tr_link.tr_logflags |= XFS_TRANS_PERM_LOG_RES; - - resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp); - resp->tr_remove.tr_logcount = XFS_REMOVE_LOG_COUNT; - resp->tr_remove.tr_logflags |= XFS_TRANS_PERM_LOG_RES; - - resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp); - resp->tr_symlink.tr_logcount = XFS_SYMLINK_LOG_COUNT; - resp->tr_symlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES; - - resp->tr_create.tr_logres = xfs_calc_icreate_reservation(mp); - resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT; - resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES; - resp->tr_create_tmpfile.tr_logres = xfs_calc_create_tmpfile_reservation(mp); resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT; resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES; - resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp); - resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT; - resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES; - resp->tr_ifree.tr_logres = xfs_calc_ifree_reservation(mp); resp->tr_ifree.tr_logcount = XFS_INACTIVE_LOG_COUNT; resp->tr_ifree.tr_logflags |= XFS_TRANS_PERM_LOG_RES; @@ -985,6 +1203,8 @@ xfs_trans_resv_calc( resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT; resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; + xfs_calc_namespace_reservations(mp, resp); + /* * The following transactions are logged in logical format with * a default log count. From patchwork Fri May 26 02:23:08 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: 13256306 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 5E60FC77B7A for ; Fri, 26 May 2023 02:23:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230099AbjEZCXN (ORCPT ); Thu, 25 May 2023 22:23:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52682 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229646AbjEZCXM (ORCPT ); Thu, 25 May 2023 22:23:12 -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 843E1BC for ; Thu, 25 May 2023 19:23:10 -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 0B29064C56 for ; Fri, 26 May 2023 02:23:10 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 682EEC433EF; Fri, 26 May 2023 02:23:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067789; bh=dKt0/xp3EEesq+x+wwdCRG70LI/cPKft3jZ6KYyyXDs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=vB6Q9ar3wG3L1fpoGP0Gb1Klx0N9HzJUuT9O3TVG30930ODz80jd/Rug+vaoi+b9z 0+FgNwzxUhym+N1eBz7CV1JBUTGjd28XFdgT4I4kWyRpoV8gv27m8arktL7LGxsG2Q xPETvJL0TbMlouMC+e+jqi9N+wAZCG5RktkBXCeRi+yUHa6VJGX2ybZ1jxGN83CDY3 ftqYHErzcmzLlSsCgInLlHkyOFSXAraeR5mNHYpqRJ6l1KU53dcYBlqC3KcsDMFFp2 SZ8qNr2dwyYYPBwxyxJSHknWsFzldpqvTSPFZvc+gSEQZjs/dwPE4tCnaQSN/oQHeO g5dDGWXuYrP7Q== Date: Thu, 25 May 2023 19:23:08 -0700 Subject: [PATCH 05/30] xfs: parent pointer attribute creation From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Dave Chinner , Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506077956.3749421.269466241552163473.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Add parent pointer attribute during xfs_create, and subroutines to initialize attributes Signed-off-by: Dave Chinner Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: shorten names, adjust to new format] Signed-off-by: Darrick J. Wong --- include/libxfs.h | 1 include/xfs_inode.h | 6 +++ libxfs/Makefile | 1 libxfs/init.c | 3 + libxfs/libxfs_api_defs.h | 2 + libxfs/libxfs_priv.h | 5 +- libxfs/xfs_attr.c | 4 +- libxfs/xfs_attr.h | 4 +- libxfs/xfs_parent.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_parent.h | 41 ++++++++++++++++++ libxfs/xfs_trans_space.c | 52 +++++++++++++++++++++++ libxfs/xfs_trans_space.h | 9 ++-- repair/phase6.c | 8 ++-- 13 files changed, 224 insertions(+), 14 deletions(-) create mode 100644 libxfs/xfs_trans_space.c diff --git a/include/libxfs.h b/include/libxfs.h index 3b0f320f4f6..251a52d84ee 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -83,6 +83,7 @@ struct iomap; #include "xfs_btree_staging.h" #include "xfs_symlink_remote.h" #include "xfs_ag_resv.h" +#include "xfs_parent.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) diff --git a/include/xfs_inode.h b/include/xfs_inode.h index 5f6aabe7d4e..7ab3c53e1bf 100644 --- a/include/xfs_inode.h +++ b/include/xfs_inode.h @@ -175,6 +175,12 @@ static inline struct inode *VFS_I(struct xfs_inode *ip) return &ip->i_vnode; } +/* convert from const xfs inode to const vfs inode */ +static inline const struct inode *VFS_IC(const struct xfs_inode *ip) +{ + return &ip->i_vnode; +} + /* We only have i_size in the xfs inode in userspace */ static inline loff_t i_size_read(struct inode *inode) { diff --git a/libxfs/Makefile b/libxfs/Makefile index a12f43da149..f6c7c5c010e 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -111,6 +111,7 @@ CFILES = cache.c \ xfs_symlink_remote.c \ xfs_trans_inode.c \ xfs_trans_resv.c \ + xfs_trans_space.c \ xfs_types.c # diff --git a/libxfs/init.c b/libxfs/init.c index 14a3fdb61ac..26b578134c7 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -258,6 +258,8 @@ init_caches(void) "xfs_extfree_item"); xfs_trans_cache = kmem_cache_init( sizeof(struct xfs_trans), "xfs_trans"); + xfs_parent_intent_cache = kmem_cache_init( + sizeof(struct xfs_parent_defer), "xfs_parent_defer"); } static int @@ -275,6 +277,7 @@ destroy_caches(void) xfs_btree_destroy_cur_caches(); leaked += kmem_cache_destroy(xfs_extfree_item_cache); leaked += kmem_cache_destroy(xfs_trans_cache); + leaked += kmem_cache_destroy(xfs_parent_intent_cache); return leaked; } diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 8360934b784..1e2cfa0ec22 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -87,6 +87,7 @@ #define xfs_bunmapi libxfs_bunmapi #define xfs_bwrite libxfs_bwrite #define xfs_calc_dquots_per_chunk libxfs_calc_dquots_per_chunk +#define xfs_create_space_res libxfs_create_space_res #define xfs_da3_node_hdr_from_disk libxfs_da3_node_hdr_from_disk #define xfs_da_get_buf libxfs_da_get_buf #define xfs_da_hashname libxfs_da_hashname @@ -172,6 +173,7 @@ #define xfs_log_get_max_trans_res libxfs_log_get_max_trans_res #define xfs_log_sb libxfs_log_sb #define xfs_mode_to_ftype libxfs_mode_to_ftype +#define xfs_mkdir_space_res libxfs_mkdir_space_res #define xfs_perag_get libxfs_perag_get #define xfs_perag_put libxfs_perag_put #define xfs_prealloc_blocks libxfs_prealloc_blocks diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index 2690431772d..ff94c5c7350 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -639,8 +639,9 @@ int libxfs_zero_extent(struct xfs_inode *ip, xfs_fsblock_t start_fsb, /* xfs_log.c */ bool xfs_log_check_lsn(struct xfs_mount *, xfs_lsn_t); void xfs_log_item_init(struct xfs_mount *, struct xfs_log_item *, int); -#define xfs_attr_use_log_assist(mp) (0) -#define xlog_drop_incompat_feat(log) do { } while (0) +#define xfs_attr_grab_log_assist(mp) (0) +#define xfs_attr_rele_log_assist(mp) ((void) 0) +#define xlog_drop_incompat_feat(log,w) do { } while (0) #define xfs_log_in_recovery(mp) (false) /* xfs_icache.c */ diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index ba880fb8575..eb32db32b65 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -893,7 +893,7 @@ xfs_attr_lookup( return error; } -static int +int xfs_attr_intent_init( struct xfs_da_args *args, unsigned int op_flags, /* op flag (set or remove) */ @@ -911,7 +911,7 @@ xfs_attr_intent_init( } /* Sets an attribute for an inode as a deferred operation */ -static int +int xfs_attr_defer_add( struct xfs_da_args *args) { diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h index d2165c85f16..d77c132ff54 100644 --- a/libxfs/xfs_attr.h +++ b/libxfs/xfs_attr.h @@ -549,6 +549,7 @@ int xfs_inode_hasattr(struct xfs_inode *ip); bool xfs_attr_is_leaf(struct xfs_inode *ip); int xfs_attr_get_ilocked(struct xfs_da_args *args); int xfs_attr_get(struct xfs_da_args *args); +int xfs_attr_defer_add(struct xfs_da_args *args); int xfs_attr_set(struct xfs_da_args *args); int xfs_attr_set_iter(struct xfs_attr_intent *attr); int xfs_attr_remove_iter(struct xfs_attr_intent *attr); @@ -557,7 +558,8 @@ bool xfs_attr_namecheck(struct xfs_mount *mp, const void *name, size_t length, int xfs_attr_calc_size(struct xfs_da_args *args, int *local); void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres, unsigned int *total); - +int xfs_attr_intent_init(struct xfs_da_args *args, unsigned int op_flags, + struct xfs_attr_intent **attr); /* * Check to see if the attr should be upgraded from non-existent or shortform to * single-leaf-block attribute list. diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c index 583607c1301..88188d282e6 100644 --- a/libxfs/xfs_parent.c +++ b/libxfs/xfs_parent.c @@ -21,6 +21,7 @@ #include "xfs_da_btree.h" #include "xfs_attr.h" #include "xfs_dir2.h" +#include "xfs_dir2_priv.h" #include "xfs_attr_sf.h" #include "xfs_bmap.h" #include "xfs_parent.h" @@ -28,6 +29,8 @@ #include "xfs_format.h" #include "xfs_trans_space.h" +struct kmem_cache *xfs_parent_intent_cache; + /* * Parent pointer attribute handling. * @@ -90,3 +93,102 @@ xfs_parent_valuecheck( return true; } + +/* Initializes a xfs_parent_name_rec to be stored as an attribute name. */ +static inline void +xfs_init_parent_name_rec( + struct xfs_parent_name_rec *rec, + const struct xfs_inode *dp, + const struct xfs_name *name, + struct xfs_inode *ip) +{ + rec->p_ino = cpu_to_be64(dp->i_ino); + rec->p_gen = cpu_to_be32(VFS_IC(dp)->i_generation); + rec->p_namehash = cpu_to_be32(xfs_dir2_hashname(dp->i_mount, name)); +} + +/* Point the da args value fields at the non-key parts of a parent pointer. */ +static inline void +xfs_init_parent_davalue( + struct xfs_da_args *args, + const struct xfs_name *name) +{ + args->valuelen = name->len; + args->value = (void *)name->name; +} + +/* + * Allocate memory to control a logged parent pointer update as part of a + * dirent operation. + */ +int +__xfs_parent_init( + struct xfs_mount *mp, + struct xfs_parent_defer **parentp) +{ + struct xfs_parent_defer *parent; + int error; + + error = xfs_attr_grab_log_assist(mp); + if (error) + return error; + + parent = kmem_cache_zalloc(xfs_parent_intent_cache, GFP_KERNEL); + if (!parent) { + xfs_attr_rele_log_assist(mp); + return -ENOMEM; + } + + /* init parent da_args */ + parent->args.geo = mp->m_attr_geo; + parent->args.whichfork = XFS_ATTR_FORK; + parent->args.attr_filter = XFS_ATTR_PARENT; + parent->args.op_flags = XFS_DA_OP_OKNOENT | XFS_DA_OP_LOGGED | + XFS_DA_OP_NVLOOKUP; + parent->args.name = (const uint8_t *)&parent->rec; + parent->args.namelen = sizeof(struct xfs_parent_name_rec); + + *parentp = parent; + return 0; +} + +static inline xfs_dahash_t +xfs_parent_hashname( + struct xfs_inode *ip, + const struct xfs_parent_defer *parent) +{ + return xfs_da_hashname((const void *)&parent->rec, + sizeof(struct xfs_parent_name_rec)); +} + +/* Add a parent pointer to reflect a dirent addition. */ +int +xfs_parent_add( + struct xfs_trans *tp, + struct xfs_parent_defer *parent, + struct xfs_inode *dp, + const struct xfs_name *parent_name, + struct xfs_inode *child) +{ + struct xfs_da_args *args = &parent->args; + + xfs_init_parent_name_rec(&parent->rec, dp, parent_name, child); + args->hashval = xfs_parent_hashname(dp, parent); + + args->trans = tp; + args->dp = child; + + xfs_init_parent_davalue(&parent->args, parent_name); + + return xfs_attr_defer_add(args); +} + +/* Cancel a parent pointer operation. */ +void +__xfs_parent_cancel( + struct xfs_mount *mp, + struct xfs_parent_defer *parent) +{ + xlog_drop_incompat_feat(mp->m_log, XLOG_INCOMPAT_FEAT_XATTRS); + kmem_cache_free(xfs_parent_intent_cache, parent); +} diff --git a/libxfs/xfs_parent.h b/libxfs/xfs_parent.h index 6e2a2528d2d..43551956508 100644 --- a/libxfs/xfs_parent.h +++ b/libxfs/xfs_parent.h @@ -13,4 +13,43 @@ bool xfs_parent_namecheck(struct xfs_mount *mp, bool xfs_parent_valuecheck(struct xfs_mount *mp, const void *value, size_t valuelen); -#endif /* __XFS_PARENT_H__ */ +extern struct kmem_cache *xfs_parent_intent_cache; + +/* + * Dynamically allocd structure used to wrap the needed data to pass around + * the defer ops machinery + */ +struct xfs_parent_defer { + struct xfs_parent_name_rec rec; + struct xfs_da_args args; +}; + +int __xfs_parent_init(struct xfs_mount *mp, struct xfs_parent_defer **parentp); + +static inline int +xfs_parent_start( + struct xfs_mount *mp, + struct xfs_parent_defer **pp) +{ + *pp = NULL; + + if (xfs_has_parent(mp)) + return __xfs_parent_init(mp, pp); + return 0; +} + +int xfs_parent_add(struct xfs_trans *tp, struct xfs_parent_defer *parent, + struct xfs_inode *dp, const struct xfs_name *parent_name, + struct xfs_inode *child); +void __xfs_parent_cancel(struct xfs_mount *mp, struct xfs_parent_defer *parent); + +static inline void +xfs_parent_finish( + struct xfs_mount *mp, + struct xfs_parent_defer *p) +{ + if (p) + __xfs_parent_cancel(mp, p); +} + +#endif /* __XFS_PARENT_H__ */ diff --git a/libxfs/xfs_trans_space.c b/libxfs/xfs_trans_space.c new file mode 100644 index 00000000000..3408e700f01 --- /dev/null +++ b/libxfs/xfs_trans_space.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2000,2005 Silicon Graphics, Inc. + * All Rights Reserved. + */ +#include "libxfs_priv.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_da_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_da_btree.h" +#include "xfs_bmap_btree.h" +#include "xfs_trans_space.h" + +/* Calculate the disk space required to add a parent pointer. */ +unsigned int +xfs_parent_calc_space_res( + struct xfs_mount *mp, + unsigned int namelen) +{ + /* + * Parent pointers are always the first attr in an attr tree, and never + * larger than a block + */ + return XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK) + + XFS_NEXTENTADD_SPACE_RES(mp, namelen, XFS_ATTR_FORK); +} + +unsigned int +xfs_create_space_res( + struct xfs_mount *mp, + unsigned int namelen) +{ + unsigned int ret; + + ret = XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp, namelen); + if (xfs_has_parent(mp)) + ret += xfs_parent_calc_space_res(mp, namelen); + + return ret; +} + +unsigned int +xfs_mkdir_space_res( + struct xfs_mount *mp, + unsigned int namelen) +{ + return xfs_create_space_res(mp, namelen); +} diff --git a/libxfs/xfs_trans_space.h b/libxfs/xfs_trans_space.h index 9640fc232c1..6cda87153b3 100644 --- a/libxfs/xfs_trans_space.h +++ b/libxfs/xfs_trans_space.h @@ -80,8 +80,6 @@ /* This macro is not used - see inline code in xfs_attr_set */ #define XFS_ATTRSET_SPACE_RES(mp, v) \ (XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK) + XFS_B_TO_FSB(mp, v)) -#define XFS_CREATE_SPACE_RES(mp,nl) \ - (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) #define XFS_DIOSTRAT_SPACE_RES(mp, v) \ (XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + (v)) #define XFS_GROWFS_SPACE_RES(mp) \ @@ -90,8 +88,6 @@ ((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK)) #define XFS_LINK_SPACE_RES(mp,nl) \ XFS_DIRENTER_SPACE_RES(mp,nl) -#define XFS_MKDIR_SPACE_RES(mp,nl) \ - (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) #define XFS_QM_DQALLOC_SPACE_RES(mp) \ (XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + \ XFS_DQUOT_CLUSTER_SIZE_FSB) @@ -106,5 +102,10 @@ #define XFS_IFREE_SPACE_RES(mp) \ (xfs_has_finobt(mp) ? M_IGEO(mp)->inobt_maxlevels : 0) +unsigned int xfs_parent_calc_space_res(struct xfs_mount *mp, + unsigned int namelen); + +unsigned int xfs_create_space_res(struct xfs_mount *mp, unsigned int namelen); +unsigned int xfs_mkdir_space_res(struct xfs_mount *mp, unsigned int namelen); #endif /* __XFS_TRANS_SPACE_H__ */ diff --git a/repair/phase6.c b/repair/phase6.c index 3076378a730..4b49dcaa454 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -908,7 +908,7 @@ mk_orphanage(xfs_mount_t *mp) /* * could not be found, create it */ - nres = XFS_MKDIR_SPACE_RES(mp, xname.len); + nres = libxfs_mkdir_space_res(mp, xname.len); i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp); if (i) res_failed(i); @@ -1319,7 +1319,7 @@ longform_dir2_rebuild( p->name.name[1] == '.')))) continue; - nres = XFS_CREATE_SPACE_RES(mp, p->name.len); + nres = libxfs_create_space_res(mp, p->name.len); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_create, nres, 0, 0, &tp); if (error) @@ -2931,7 +2931,7 @@ _("error %d fixing shortform directory %llu\n"), do_warn(_("recreating root directory .. entry\n")); - nres = XFS_MKDIR_SPACE_RES(mp, 2); + nres = libxfs_mkdir_space_res(mp, 2); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp); if (error) @@ -2986,7 +2986,7 @@ _("error %d fixing shortform directory %llu\n"), do_warn( _("creating missing \".\" entry in dir ino %" PRIu64 "\n"), ino); - nres = XFS_MKDIR_SPACE_RES(mp, 1); + nres = libxfs_mkdir_space_res(mp, 1); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp); if (error) From patchwork Fri May 26 02:23:24 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: 13256307 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 40D8AC77B7E for ; Fri, 26 May 2023 02:23:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229646AbjEZCX1 (ORCPT ); Thu, 25 May 2023 22:23:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52728 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230289AbjEZCX0 (ORCPT ); Thu, 25 May 2023 22:23:26 -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 039B99B for ; Thu, 25 May 2023 19:23:26 -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 8CDE064B7B for ; Fri, 26 May 2023 02:23:25 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id EDF57C433D2; Fri, 26 May 2023 02:23:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067805; bh=9eL7XeYB9EP5CDIDx8VdAXpj6a90rLRSXvxKmQ0tQn4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=OCoe/5/y/WzVVTNiOJk8zVPvvC4iVW6+5bPMDovLx5sguuB1pCb9EftAf+ln9Hj2S kByYgSoSa8Eyiw8nOffaK3JUlwRsTbTco0JIHfeiATWJAu5fzRtAxlr7crKAgjJDbw MZg1L3A3kObzdVEbuGvquU5i3Alj851uOA0iTyKfpFS/IAgwDD4k47YAYyphL/hAMB MiQqJXI+nW5yA86rTJxXsFLd+N1jcNEnJ2/QW0dIqb/hL++NXMbixLXBp8jW72adnO 5emPGW9tgkvCfE1H0xZGdHJWpXZzwki45mXu5K2FutM8JZab5jBYQxlgVqj5X4YApI 7fYV9OwL+8knA== Date: Thu, 25 May 2023 19:23:24 -0700 Subject: [PATCH 06/30] xfs: add parent attributes to link From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Dave Chinner , Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506077970.3749421.4493608855532915792.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 This patch modifies xfs_link to add a parent pointer to the inode. Signed-off-by: Dave Chinner Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: minor rebase fixes] Signed-off-by: Darrick J. Wong --- libxfs/xfs_trans_space.c | 14 ++++++++++++++ libxfs/xfs_trans_space.h | 3 +-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/libxfs/xfs_trans_space.c b/libxfs/xfs_trans_space.c index 3408e700f01..039bbd91e87 100644 --- a/libxfs/xfs_trans_space.c +++ b/libxfs/xfs_trans_space.c @@ -50,3 +50,17 @@ xfs_mkdir_space_res( { return xfs_create_space_res(mp, namelen); } + +unsigned int +xfs_link_space_res( + struct xfs_mount *mp, + unsigned int namelen) +{ + unsigned int ret; + + ret = XFS_DIRENTER_SPACE_RES(mp, namelen); + if (xfs_has_parent(mp)) + ret += xfs_parent_calc_space_res(mp, namelen); + + return ret; +} diff --git a/libxfs/xfs_trans_space.h b/libxfs/xfs_trans_space.h index 6cda87153b3..5539634009f 100644 --- a/libxfs/xfs_trans_space.h +++ b/libxfs/xfs_trans_space.h @@ -86,8 +86,6 @@ (2 * (mp)->m_alloc_maxlevels) #define XFS_GROWFSRT_SPACE_RES(mp,b) \ ((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK)) -#define XFS_LINK_SPACE_RES(mp,nl) \ - XFS_DIRENTER_SPACE_RES(mp,nl) #define XFS_QM_DQALLOC_SPACE_RES(mp) \ (XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + \ XFS_DQUOT_CLUSTER_SIZE_FSB) @@ -107,5 +105,6 @@ unsigned int xfs_parent_calc_space_res(struct xfs_mount *mp, unsigned int xfs_create_space_res(struct xfs_mount *mp, unsigned int namelen); unsigned int xfs_mkdir_space_res(struct xfs_mount *mp, unsigned int namelen); +unsigned int xfs_link_space_res(struct xfs_mount *mp, unsigned int namelen); #endif /* __XFS_TRANS_SPACE_H__ */ From patchwork Fri May 26 02:23:40 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: 13256308 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 80459C77B7A for ; Fri, 26 May 2023 02:23:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231691AbjEZCXn (ORCPT ); Thu, 25 May 2023 22:23:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52764 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230289AbjEZCXm (ORCPT ); Thu, 25 May 2023 22:23:42 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8BE18B6 for ; Thu, 25 May 2023 19:23:41 -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 27A3B64B7B for ; Fri, 26 May 2023 02:23:41 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8E881C433EF; Fri, 26 May 2023 02:23:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067820; bh=p88oZmSqUksJDYfpTyDUx4i/fqc4ihdpJMqTePIY0xg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=u5HMRBFepRkrazzMrWLK2cyN8TvEQ7szgaHw3cmMyVrRp+94MPsRci+0hYaHdEZyD EG8vTsQkEutgmDLrqB0KgRfcsp4URU5+2j4ZjUScxabcBrHgRrdhJnl/YedNJtaI5b dw2/NKJJNyYFAr7Hj8pgDA+mLi5pKTmJ6HnYq6i1ZhEIG21avd5EhAl2vnrpcPPoQL ZG/vFzNGaWBkjsL/jtnG0M6B9GKGXhm3/BhdEVpWrNIcPe7rYFzew96timXs50LAbq d3L3y+z3mfsAreCIoQifQyqUGuUe7+U2KHA+2thtCNb1tVr++W48uz1TPtx0JDXSa/ dQJVTXOwPgWOA== Date: Thu, 25 May 2023 19:23:40 -0700 Subject: [PATCH 07/30] xfs: add parent attributes to symlink From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506077983.3749421.12309775437654603846.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 This patch modifies xfs_symlink to add a parent pointer to the inode. Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: minor rebase fixups] Signed-off-by: Darrick J. Wong --- libxfs/xfs_trans_space.c | 17 +++++++++++++++++ libxfs/xfs_trans_space.h | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/libxfs/xfs_trans_space.c b/libxfs/xfs_trans_space.c index 039bbd91e87..bf4a41492c2 100644 --- a/libxfs/xfs_trans_space.c +++ b/libxfs/xfs_trans_space.c @@ -64,3 +64,20 @@ xfs_link_space_res( return ret; } + +unsigned int +xfs_symlink_space_res( + struct xfs_mount *mp, + unsigned int namelen, + unsigned int fsblocks) +{ + unsigned int ret; + + ret = XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp, namelen) + + fsblocks; + + if (xfs_has_parent(mp)) + ret += xfs_parent_calc_space_res(mp, namelen); + + return ret; +} diff --git a/libxfs/xfs_trans_space.h b/libxfs/xfs_trans_space.h index 5539634009f..354ad1d6e18 100644 --- a/libxfs/xfs_trans_space.h +++ b/libxfs/xfs_trans_space.h @@ -95,8 +95,6 @@ XFS_DIRREMOVE_SPACE_RES(mp) #define XFS_RENAME_SPACE_RES(mp,nl) \ (XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) -#define XFS_SYMLINK_SPACE_RES(mp,nl,b) \ - (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl) + (b)) #define XFS_IFREE_SPACE_RES(mp) \ (xfs_has_finobt(mp) ? M_IGEO(mp)->inobt_maxlevels : 0) @@ -106,5 +104,7 @@ unsigned int xfs_parent_calc_space_res(struct xfs_mount *mp, unsigned int xfs_create_space_res(struct xfs_mount *mp, unsigned int namelen); unsigned int xfs_mkdir_space_res(struct xfs_mount *mp, unsigned int namelen); unsigned int xfs_link_space_res(struct xfs_mount *mp, unsigned int namelen); +unsigned int xfs_symlink_space_res(struct xfs_mount *mp, unsigned int namelen, + unsigned int fsblocks); #endif /* __XFS_TRANS_SPACE_H__ */ From patchwork Fri May 26 02:23:55 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: 13256309 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 B6D10C77B7E for ; Fri, 26 May 2023 02:24:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233106AbjEZCX7 (ORCPT ); Thu, 25 May 2023 22:23:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52824 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230289AbjEZCX6 (ORCPT ); Thu, 25 May 2023 22:23:58 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C5AF9B for ; Thu, 25 May 2023 19:23:57 -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 B09E864C3C for ; Fri, 26 May 2023 02:23:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1B0FBC433D2; Fri, 26 May 2023 02:23:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067836; bh=nnFicAGT37VVFEBL4FSbNqvouXN4gkt/shnnVBsZNtQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=TS7x7fC8LMvybwuwoxYCsJlM4PRcJI/h2AWAme6cSEoYqAptoIGX61nLG1b+7P1x6 J+m1dcl2n5lQpRiFPFf/cUmhsK1HUUxoL/XP23LWKk4rUoCM0in5NqlFK6g5BWfnqQ xEmJxg/bVeFhQO0iOUiMA4tz9Ek6mzW0kWXQZ5mh3KWqOo6oHBQTcAs1E3Ipk3Kkom mloZk2NloDBCqnTFzyr5UG/L0QXoBMYLnYM7Ynk9ytUrpINnEakBpf51z/memBgAlE h71fvG2CVW5lq0xCDqhlyYmpodhxe5owu8h1HPWw0vuIRtJ0aEwxoTy5zqjtdcEFH/ 61zk1+wt+8uMQ== Date: Thu, 25 May 2023 19:23:55 -0700 Subject: [PATCH 08/30] xfs: remove parent pointers in unlink From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Dave Chinner , Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506077997.3749421.11321341527340811231.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 This patch removes the parent pointer attribute during unlink Signed-off-by: Dave Chinner Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: adjust to new ondisk format, minor rebase fixes] Signed-off-by: Darrick J. Wong --- libxfs/libxfs_api_defs.h | 1 + libxfs/xfs_attr.c | 2 +- libxfs/xfs_attr.h | 1 + libxfs/xfs_parent.c | 33 +++++++++++++++++++++++++++++++++ libxfs/xfs_parent.h | 4 ++++ libxfs/xfs_trans_space.c | 13 +++++++++++++ libxfs/xfs_trans_space.h | 3 +-- repair/phase6.c | 6 +++--- 8 files changed, 57 insertions(+), 6 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 1e2cfa0ec22..de653b2656a 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -188,6 +188,7 @@ #define xfs_refcountbt_stage_cursor libxfs_refcountbt_stage_cursor #define xfs_refcount_get_rec libxfs_refcount_get_rec #define xfs_refcount_lookup_le libxfs_refcount_lookup_le +#define xfs_remove_space_res libxfs_remove_space_res #define xfs_rmap_alloc libxfs_rmap_alloc #define xfs_rmapbt_calc_reserves libxfs_rmapbt_calc_reserves diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index eb32db32b65..4663eaa4c54 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -957,7 +957,7 @@ xfs_attr_defer_replace( } /* Removes an attribute for an inode as a deferred operation */ -static int +int xfs_attr_defer_remove( struct xfs_da_args *args) { diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h index d77c132ff54..06b6494511d 100644 --- a/libxfs/xfs_attr.h +++ b/libxfs/xfs_attr.h @@ -550,6 +550,7 @@ bool xfs_attr_is_leaf(struct xfs_inode *ip); int xfs_attr_get_ilocked(struct xfs_da_args *args); int xfs_attr_get(struct xfs_da_args *args); int xfs_attr_defer_add(struct xfs_da_args *args); +int xfs_attr_defer_remove(struct xfs_da_args *args); int xfs_attr_set(struct xfs_da_args *args); int xfs_attr_set_iter(struct xfs_attr_intent *attr); int xfs_attr_remove_iter(struct xfs_attr_intent *attr); diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c index 88188d282e6..ed75f5acf24 100644 --- a/libxfs/xfs_parent.c +++ b/libxfs/xfs_parent.c @@ -28,6 +28,7 @@ #include "xfs_da_format.h" #include "xfs_format.h" #include "xfs_trans_space.h" +#include "xfs_health.h" struct kmem_cache *xfs_parent_intent_cache; @@ -183,6 +184,38 @@ xfs_parent_add( return xfs_attr_defer_add(args); } +/* Remove a parent pointer to reflect a dirent removal. */ +int +xfs_parent_remove( + struct xfs_trans *tp, + struct xfs_parent_defer *parent, + struct xfs_inode *dp, + const struct xfs_name *parent_name, + struct xfs_inode *child) +{ + struct xfs_da_args *args = &parent->args; + + /* + * For regular attrs, removing an attr from a !hasattr inode is a nop. + * For parent pointers, we require that the pointer must exist if the + * caller wants us to remove the pointer. + */ + if (XFS_IS_CORRUPT(child->i_mount, !xfs_inode_hasattr(child))) { + xfs_inode_mark_sick(child, XFS_SICK_INO_PARENT); + return -EFSCORRUPTED; + } + + xfs_init_parent_name_rec(&parent->rec, dp, parent_name, child); + args->hashval = xfs_parent_hashname(dp, parent); + + args->trans = tp; + args->dp = child; + + xfs_init_parent_davalue(&parent->args, parent_name); + + return xfs_attr_defer_remove(args); +} + /* Cancel a parent pointer operation. */ void __xfs_parent_cancel( diff --git a/libxfs/xfs_parent.h b/libxfs/xfs_parent.h index 43551956508..19532935f6c 100644 --- a/libxfs/xfs_parent.h +++ b/libxfs/xfs_parent.h @@ -41,6 +41,10 @@ xfs_parent_start( int xfs_parent_add(struct xfs_trans *tp, struct xfs_parent_defer *parent, struct xfs_inode *dp, const struct xfs_name *parent_name, struct xfs_inode *child); +int xfs_parent_remove(struct xfs_trans *tp, struct xfs_parent_defer *parent, + struct xfs_inode *dp, const struct xfs_name *parent_name, + struct xfs_inode *child); + void __xfs_parent_cancel(struct xfs_mount *mp, struct xfs_parent_defer *parent); static inline void diff --git a/libxfs/xfs_trans_space.c b/libxfs/xfs_trans_space.c index bf4a41492c2..86a91a3a844 100644 --- a/libxfs/xfs_trans_space.c +++ b/libxfs/xfs_trans_space.c @@ -81,3 +81,16 @@ xfs_symlink_space_res( return ret; } + +unsigned int +xfs_remove_space_res( + struct xfs_mount *mp, + unsigned int namelen) +{ + unsigned int ret = XFS_DIRREMOVE_SPACE_RES(mp); + + if (xfs_has_parent(mp)) + ret += xfs_parent_calc_space_res(mp, namelen); + + return ret; +} diff --git a/libxfs/xfs_trans_space.h b/libxfs/xfs_trans_space.h index 354ad1d6e18..a4490813c56 100644 --- a/libxfs/xfs_trans_space.h +++ b/libxfs/xfs_trans_space.h @@ -91,8 +91,6 @@ XFS_DQUOT_CLUSTER_SIZE_FSB) #define XFS_QM_QINOCREATE_SPACE_RES(mp) \ XFS_IALLOC_SPACE_RES(mp) -#define XFS_REMOVE_SPACE_RES(mp) \ - XFS_DIRREMOVE_SPACE_RES(mp) #define XFS_RENAME_SPACE_RES(mp,nl) \ (XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) #define XFS_IFREE_SPACE_RES(mp) \ @@ -106,5 +104,6 @@ unsigned int xfs_mkdir_space_res(struct xfs_mount *mp, unsigned int namelen); unsigned int xfs_link_space_res(struct xfs_mount *mp, unsigned int namelen); unsigned int xfs_symlink_space_res(struct xfs_mount *mp, unsigned int namelen, unsigned int fsblocks); +unsigned int xfs_remove_space_res(struct xfs_mount *mp, unsigned int namelen); #endif /* __XFS_TRANS_SPACE_H__ */ diff --git a/repair/phase6.c b/repair/phase6.c index 4b49dcaa454..b99ce4c2aa4 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -1259,7 +1259,7 @@ longform_dir2_rebuild( libxfs_dir_ino_validate(mp, pip.i_ino)) pip.i_ino = mp->m_sb.sb_rootino; - nres = XFS_REMOVE_SPACE_RES(mp); + nres = libxfs_remove_space_res(mp, 0); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); if (error) res_failed(error); @@ -1365,7 +1365,7 @@ dir2_kill_block( int nres; xfs_trans_t *tp; - nres = XFS_REMOVE_SPACE_RES(mp); + nres = libxfs_remove_space_res(mp, 0); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); if (error) res_failed(error); @@ -2884,7 +2884,7 @@ process_dir_inode( * inode but it's easier than wedging a * new define in ourselves. */ - nres = no_modify ? 0 : XFS_REMOVE_SPACE_RES(mp); + nres = no_modify ? 0 : libxfs_remove_space_res(mp, 0); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); if (error) From patchwork Fri May 26 02:24:11 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: 13256310 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 99899C77B7E for ; Fri, 26 May 2023 02:24:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234360AbjEZCYP (ORCPT ); Thu, 25 May 2023 22:24:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230289AbjEZCYO (ORCPT ); Thu, 25 May 2023 22:24:14 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC286BC for ; Thu, 25 May 2023 19:24:12 -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 57ED064B7B for ; Fri, 26 May 2023 02:24:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B9281C433D2; Fri, 26 May 2023 02:24:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067851; bh=zEbWeecy1XgBP0RHw5H3LmUoWR4HJ3qhA2nO5nESjuA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=EpM8N/7b7agLpLXvsJOBl7psyMt4eEqVTOwr3pw3UNSiD9vnGLJFwcorpVBR9Pcj0 M7utWG76XfhBMKalWbkIakGkQos4mk/4Y6tUJ2+eCwyj8YcNWINkbnemcwimd1Iqxa tflJwabmeZLcO8t25akNiBkAuJV/EgL9jiUvsewuY79P+3ovme5NWG2trk1FsCccrA Yfg/MUDK6zQ4HKVV8CgY15xEDg0Pf3s9X0Dn8rqemzs53LKzq9c5l3RdEyK049Q9/l TIIZAz6qSIBQLjJZ/HsyehEYBdwGyxX9+ixIKKhaOCrPrOwBgCxbeO43ZIJgp67k6g bozWKNQ2urIew== Date: Thu, 25 May 2023 19:24:11 -0700 Subject: [PATCH 09/30] xfs: Add parent pointers to rename From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078010.3749421.13702370511328365450.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 This patch removes the old parent pointer attribute during the rename operation, and re-adds the updated parent pointer. Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: adjust to new ondisk format] Signed-off-by: Darrick J. Wong --- libxfs/xfs_attr.c | 2 + libxfs/xfs_attr.h | 1 + libxfs/xfs_parent.c | 68 +++++++++++++++++++++++++++++++++++++++++++--- libxfs/xfs_parent.h | 23 ++++++++++++++-- libxfs/xfs_trans_space.c | 25 +++++++++++++++++ libxfs/xfs_trans_space.h | 6 +++- 6 files changed, 115 insertions(+), 10 deletions(-) diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index 4663eaa4c54..3aabca58b14 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -934,7 +934,7 @@ xfs_attr_defer_add( } /* Sets an attribute for an inode as a deferred operation */ -static int +int xfs_attr_defer_replace( struct xfs_da_args *args) { diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h index 06b6494511d..24616bb07e9 100644 --- a/libxfs/xfs_attr.h +++ b/libxfs/xfs_attr.h @@ -551,6 +551,7 @@ int xfs_attr_get_ilocked(struct xfs_da_args *args); int xfs_attr_get(struct xfs_da_args *args); int xfs_attr_defer_add(struct xfs_da_args *args); int xfs_attr_defer_remove(struct xfs_da_args *args); +int xfs_attr_defer_replace(struct xfs_da_args *args); int xfs_attr_set(struct xfs_da_args *args); int xfs_attr_set_iter(struct xfs_attr_intent *attr); int xfs_attr_remove_iter(struct xfs_attr_intent *attr); diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c index ed75f5acf24..fe27dabc50d 100644 --- a/libxfs/xfs_parent.c +++ b/libxfs/xfs_parent.c @@ -118,6 +118,19 @@ xfs_init_parent_davalue( args->value = (void *)name->name; } +/* + * Point the da args new value fields at the non-key parts of a replacement + * parent pointer. + */ +static inline void +xfs_init_parent_danewvalue( + struct xfs_da_args *args, + const struct xfs_name *name) +{ + args->new_valuelen = name->len; + args->new_value = (void *)name->name; +} + /* * Allocate memory to control a logged parent pointer update as part of a * dirent operation. @@ -125,22 +138,27 @@ xfs_init_parent_davalue( int __xfs_parent_init( struct xfs_mount *mp, + bool grab_log, struct xfs_parent_defer **parentp) { struct xfs_parent_defer *parent; int error; - error = xfs_attr_grab_log_assist(mp); - if (error) - return error; + if (grab_log) { + error = xfs_attr_grab_log_assist(mp); + if (error) + return error; + } parent = kmem_cache_zalloc(xfs_parent_intent_cache, GFP_KERNEL); if (!parent) { - xfs_attr_rele_log_assist(mp); + if (grab_log) + xfs_attr_rele_log_assist(mp); return -ENOMEM; } /* init parent da_args */ + parent->have_log = grab_log; parent->args.geo = mp->m_attr_geo; parent->args.whichfork = XFS_ATTR_FORK; parent->args.attr_filter = XFS_ATTR_PARENT; @@ -216,12 +234,52 @@ xfs_parent_remove( return xfs_attr_defer_remove(args); } +/* Replace one parent pointer with another to reflect a rename. */ +int +xfs_parent_replace( + struct xfs_trans *tp, + struct xfs_parent_defer *parent, + struct xfs_inode *old_dp, + const struct xfs_name *old_name, + struct xfs_inode *new_dp, + const struct xfs_name *new_name, + struct xfs_inode *child) +{ + struct xfs_da_args *args = &parent->args; + + /* + * For regular attrs, replacing an attr from a !hasattr inode becomes + * an attr-set operation. For replacing a parent pointer, however, we + * require that the old pointer must exist. + */ + if (XFS_IS_CORRUPT(child->i_mount, !xfs_inode_hasattr(child))) { + xfs_inode_mark_sick(child, XFS_SICK_INO_PARENT); + return -EFSCORRUPTED; + } + + xfs_init_parent_name_rec(&parent->rec, old_dp, old_name, child); + args->hashval = xfs_parent_hashname(old_dp, parent); + + xfs_init_parent_name_rec(&parent->new_rec, new_dp, new_name, child); + args->new_name = (const uint8_t *)&parent->new_rec; + args->new_namelen = sizeof(struct xfs_parent_name_rec); + + args->trans = tp; + args->dp = child; + + xfs_init_parent_davalue(&parent->args, old_name); + xfs_init_parent_danewvalue(&parent->args, new_name); + + return xfs_attr_defer_replace(args); +} + /* Cancel a parent pointer operation. */ void __xfs_parent_cancel( struct xfs_mount *mp, struct xfs_parent_defer *parent) { - xlog_drop_incompat_feat(mp->m_log, XLOG_INCOMPAT_FEAT_XATTRS); + if (parent->have_log) + xlog_drop_incompat_feat(mp->m_log, XLOG_INCOMPAT_FEAT_XATTRS); kmem_cache_free(xfs_parent_intent_cache, parent); } diff --git a/libxfs/xfs_parent.h b/libxfs/xfs_parent.h index 19532935f6c..637f99fba9d 100644 --- a/libxfs/xfs_parent.h +++ b/libxfs/xfs_parent.h @@ -21,10 +21,13 @@ extern struct kmem_cache *xfs_parent_intent_cache; */ struct xfs_parent_defer { struct xfs_parent_name_rec rec; + struct xfs_parent_name_rec new_rec; struct xfs_da_args args; + bool have_log; }; -int __xfs_parent_init(struct xfs_mount *mp, struct xfs_parent_defer **parentp); +int __xfs_parent_init(struct xfs_mount *mp, bool grab_log, + struct xfs_parent_defer **parentp); static inline int xfs_parent_start( @@ -34,7 +37,19 @@ xfs_parent_start( *pp = NULL; if (xfs_has_parent(mp)) - return __xfs_parent_init(mp, pp); + return __xfs_parent_init(mp, true, pp); + return 0; +} + +static inline int +xfs_parent_start_locked( + struct xfs_mount *mp, + struct xfs_parent_defer **pp) +{ + *pp = NULL; + + if (xfs_has_parent(mp)) + return __xfs_parent_init(mp, false, pp); return 0; } @@ -44,6 +59,10 @@ int xfs_parent_add(struct xfs_trans *tp, struct xfs_parent_defer *parent, int xfs_parent_remove(struct xfs_trans *tp, struct xfs_parent_defer *parent, struct xfs_inode *dp, const struct xfs_name *parent_name, struct xfs_inode *child); +int xfs_parent_replace(struct xfs_trans *tp, struct xfs_parent_defer *parent, + struct xfs_inode *old_dp, const struct xfs_name *old_name, + struct xfs_inode *new_dp, const struct xfs_name *new_name, + struct xfs_inode *child); void __xfs_parent_cancel(struct xfs_mount *mp, struct xfs_parent_defer *parent); diff --git a/libxfs/xfs_trans_space.c b/libxfs/xfs_trans_space.c index 86a91a3a844..373f5cc2497 100644 --- a/libxfs/xfs_trans_space.c +++ b/libxfs/xfs_trans_space.c @@ -94,3 +94,28 @@ xfs_remove_space_res( return ret; } + +unsigned int +xfs_rename_space_res( + struct xfs_mount *mp, + unsigned int src_namelen, + bool target_exists, + unsigned int target_namelen, + bool has_whiteout) +{ + unsigned int ret; + + ret = XFS_DIRREMOVE_SPACE_RES(mp) + + XFS_DIRENTER_SPACE_RES(mp, target_namelen); + + if (xfs_has_parent(mp)) { + if (has_whiteout) + ret += xfs_parent_calc_space_res(mp, src_namelen); + ret += 2 * xfs_parent_calc_space_res(mp, target_namelen); + } + + if (target_exists) + ret += xfs_parent_calc_space_res(mp, target_namelen); + + return ret; +} diff --git a/libxfs/xfs_trans_space.h b/libxfs/xfs_trans_space.h index a4490813c56..1155ff2d37e 100644 --- a/libxfs/xfs_trans_space.h +++ b/libxfs/xfs_trans_space.h @@ -91,8 +91,6 @@ XFS_DQUOT_CLUSTER_SIZE_FSB) #define XFS_QM_QINOCREATE_SPACE_RES(mp) \ XFS_IALLOC_SPACE_RES(mp) -#define XFS_RENAME_SPACE_RES(mp,nl) \ - (XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) #define XFS_IFREE_SPACE_RES(mp) \ (xfs_has_finobt(mp) ? M_IGEO(mp)->inobt_maxlevels : 0) @@ -106,4 +104,8 @@ unsigned int xfs_symlink_space_res(struct xfs_mount *mp, unsigned int namelen, unsigned int fsblocks); unsigned int xfs_remove_space_res(struct xfs_mount *mp, unsigned int namelen); +unsigned int xfs_rename_space_res(struct xfs_mount *mp, + unsigned int src_namelen, bool target_exists, + unsigned int target_namelen, bool has_whiteout); + #endif /* __XFS_TRANS_SPACE_H__ */ From patchwork Fri May 26 02:24:26 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: 13256311 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 D6551C77B7A for ; Fri, 26 May 2023 02:24:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234031AbjEZCYa (ORCPT ); Thu, 25 May 2023 22:24:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52962 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233245AbjEZCY3 (ORCPT ); Thu, 25 May 2023 22:24:29 -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 622BA9B for ; Thu, 25 May 2023 19:24:28 -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 EB43564C1F for ; Fri, 26 May 2023 02:24:27 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 50C3CC433A0; Fri, 26 May 2023 02:24:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067867; bh=8hyf1QOgRtFSZQJVdyDwJ4d3NdB9gJh9tEV2NIp4T+E=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=L7tb14bN40H7fGL6TmWaHm3iae/lIPHSsc5AmK9dlWW32GX7h61UY5FCQIv9g5f+X hi+21L9y7u0eSj0fAWG8YB7MNXoYA+Gd8mUQ/Q5hYwYfvEt3WH6xoh4ePp8k4fRlAS Af98DGh3edRrn6UWPDWieLhhsk9QTNl1a3ieMcKJ4GOXMtXj8S3qoRl2sFlMF/YOdo yYeYe7/W91ako9G+Pfk6f3rThihQoRK1reA31H6XybtDN1C047bzZJ6koeLkVMAiGv gKpDd/F0mp7ycIczU3vMcGknpLlvGBVIUfeRfJnUPGGYOwyIQPyTU0ABxqbuR3pZ1f C6nyk4Uay6/cg== Date: Thu, 25 May 2023 19:24:26 -0700 Subject: [PATCH 10/30] xfs: pass the attr value to put_listent when possible From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078024.3749421.12872085514659465571.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Pass the attr value to put_listent when we have local xattrs or shortform xattrs. Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- libxfs/xfs_attr.h | 5 +++-- libxfs/xfs_attr_sf.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h index 24616bb07e9..f3906d5690d 100644 --- a/libxfs/xfs_attr.h +++ b/libxfs/xfs_attr.h @@ -47,8 +47,9 @@ struct xfs_attrlist_cursor_kern { /* void; state communicated via *context */ -typedef void (*put_listent_func_t)(struct xfs_attr_list_context *, int, - unsigned char *, int, int); +typedef void (*put_listent_func_t)(struct xfs_attr_list_context *context, + int flags, unsigned char *name, int namelen, void *value, + int valuelen); struct xfs_attr_list_context { struct xfs_trans *tp; diff --git a/libxfs/xfs_attr_sf.h b/libxfs/xfs_attr_sf.h index 37578b369d9..c6e259791bc 100644 --- a/libxfs/xfs_attr_sf.h +++ b/libxfs/xfs_attr_sf.h @@ -24,6 +24,7 @@ typedef struct xfs_attr_sf_sort { uint8_t flags; /* flags bits (see xfs_attr_leaf.h) */ xfs_dahash_t hash; /* this entry's hash value */ unsigned char *name; /* name value, pointer into buffer */ + void *value; } xfs_attr_sf_sort_t; #define XFS_ATTR_SF_ENTSIZE_MAX /* max space for name&value */ \ From patchwork Fri May 26 02:24:42 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: 13256312 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 065B6C77B7E for ; Fri, 26 May 2023 02:24:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233245AbjEZCYq (ORCPT ); Thu, 25 May 2023 22:24:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53018 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230289AbjEZCYp (ORCPT ); Thu, 25 May 2023 22:24:45 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ECE599B for ; Thu, 25 May 2023 19:24:43 -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 7C3E564C1F for ; Fri, 26 May 2023 02:24:43 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DCCA2C433D2; Fri, 26 May 2023 02:24:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067882; bh=4AtpfouBPprLqz68MPnhTVZXGa/u5A7PV6OU3W3FHYE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=p9Ir+9y3nTp0JUPOJeNzl6tFqhUOwiZwV6A/l9McBgG6tVZyPcBMcUBeWYCDJV806 DZSz8cqro1uJ918RYfW1q0ZGMWbgo98Zzr91OXkOWooNgFsco8zSj04Be2Kdh/bBnn 4GoLTTQrTu1P+ZPX5vFUf/PmfhumDz5Svu6wNr3vEXJw6jlUGD1ZvneCcuPL8N3gZY huGuStzv6D3jETQ1dIYvlfXtYP7otSC2zBo7PIN/XihEDB1mtU98wsrFrWh18H+rT0 2NgJQtCNQI3Ex7xM9I51500MolUj8otp16xHiaQnonf8Sf4e3ZHRQ5YU8xiDgD29iO jvC8shLZ5BOLA== Date: Thu, 25 May 2023 19:24:42 -0700 Subject: [PATCH 11/30] xfs: Add parent pointer ioctl From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078037.3749421.14369016032968756040.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 This patch adds a new file ioctl to retrieve the parent pointer of a given inode Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: move new ioctl to xfs_fs_staging.h, adjust to new ondisk format] Signed-off-by: Darrick J. Wong --- libxfs/xfs_fs.h | 1 + libxfs/xfs_fs_staging.h | 66 +++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_parent.c | 40 ++++++++++++++++++++++++++++ libxfs/xfs_parent.h | 23 ++++++++++++++++ man/man3/xfsctl.3 | 63 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 193 insertions(+) diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h index cf909dbeed8..51b31e987a0 100644 --- a/libxfs/xfs_fs.h +++ b/libxfs/xfs_fs.h @@ -807,6 +807,7 @@ struct xfs_scrub_metadata { /* XFS_IOC_GETFSMAP ------ hoisted 59 */ #define XFS_IOC_SCRUB_METADATA _IOWR('X', 60, struct xfs_scrub_metadata) #define XFS_IOC_AG_GEOMETRY _IOWR('X', 61, struct xfs_ag_geometry) +/* XFS_IOC_GETPARENTS ---- staging 62 */ /* * ioctl commands that replace IRIX syssgi()'s diff --git a/libxfs/xfs_fs_staging.h b/libxfs/xfs_fs_staging.h index 0453e7f31af..5a9236334c3 100644 --- a/libxfs/xfs_fs_staging.h +++ b/libxfs/xfs_fs_staging.h @@ -104,4 +104,70 @@ struct xfs_exch_range { #define XFS_IOC_EXCHANGE_RANGE _IOWR('X', 129, struct xfs_exch_range) +/* Iterating parent pointers of files. */ + +/* return parents of the handle, not the open fd */ +#define XFS_GETPARENTS_IFLAG_HANDLE (1U << 0) + +/* target was the root directory */ +#define XFS_GETPARENTS_OFLAG_ROOT (1U << 1) + +/* Cursor is done iterating pptrs */ +#define XFS_GETPARENTS_OFLAG_DONE (1U << 2) + +#define XFS_GETPARENTS_FLAG_ALL (XFS_GETPARENTS_IFLAG_HANDLE | \ + XFS_GETPARENTS_OFLAG_ROOT | \ + XFS_GETPARENTS_OFLAG_DONE) + +/* Get an inode parent pointer through ioctl */ +struct xfs_getparents_rec { + __u64 gpr_ino; /* Inode number */ + __u32 gpr_gen; /* Inode generation */ + __u32 gpr_pad; /* Reserved */ + __u64 gpr_rsvd; /* Reserved */ + __u8 gpr_name[]; /* File name and null terminator */ +}; + +/* Iterate through an inodes parent pointers */ +struct xfs_getparents { + /* File handle, if XFS_GETPARENTS_IFLAG_HANDLE is set */ + struct xfs_handle gp_handle; + + /* + * Structure to track progress in iterating the parent pointers. + * Must be initialized to zeroes before the first ioctl call, and + * not touched by callers after that. + */ + struct xfs_attrlist_cursor gp_cursor; + + /* Operational flags: XFS_GETPARENTS_*FLAG* */ + __u32 gp_flags; + + /* Must be set to zero */ + __u32 gp_reserved; + + /* Size of the buffer in bytes, including this header */ + __u32 gp_bufsize; + + /* # of entries filled in (output) */ + __u32 gp_count; + + /* Must be set to zero */ + __u64 gp_reserved2[5]; + + /* Byte offset of each record within the buffer */ + __u32 gp_offsets[]; +}; + +static inline struct xfs_getparents_rec* +xfs_getparents_rec( + struct xfs_getparents *info, + unsigned int idx) +{ + return (struct xfs_getparents_rec *)((char *)info + + info->gp_offsets[idx]); +} + +#define XFS_IOC_GETPARENTS _IOWR('X', 62, struct xfs_getparents) + #endif /* __XFS_FS_STAGING_H__ */ diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c index fe27dabc50d..b1890f48722 100644 --- a/libxfs/xfs_parent.c +++ b/libxfs/xfs_parent.c @@ -283,3 +283,43 @@ __xfs_parent_cancel( xlog_drop_incompat_feat(mp->m_log, XLOG_INCOMPAT_FEAT_XATTRS); kmem_cache_free(xfs_parent_intent_cache, parent); } + +/* Convert an ondisk parent pointer to the incore format. */ +void +xfs_parent_irec_from_disk( + struct xfs_parent_name_irec *irec, + const struct xfs_parent_name_rec *rec, + const void *value, + unsigned int valuelen) +{ + irec->p_ino = be64_to_cpu(rec->p_ino); + irec->p_gen = be32_to_cpu(rec->p_gen); + irec->p_namehash = be32_to_cpu(rec->p_namehash); + irec->p_namelen = valuelen; + memcpy(irec->p_name, value, valuelen); +} + +/* Convert an incore parent pointer to the ondisk attr name format. */ +void +xfs_parent_irec_to_disk( + struct xfs_parent_name_rec *rec, + const struct xfs_parent_name_irec *irec) +{ + rec->p_ino = cpu_to_be64(irec->p_ino); + rec->p_gen = cpu_to_be32(irec->p_gen); + rec->p_namehash = cpu_to_be32(irec->p_namehash); +} + +/* Compute p_namehash for the this parent pointer. */ +void +xfs_parent_irec_hashname( + struct xfs_mount *mp, + struct xfs_parent_name_irec *irec) +{ + struct xfs_name dname = { + .name = irec->p_name, + .len = irec->p_namelen, + }; + + irec->p_namehash = xfs_dir2_hashname(mp, &dname); +} diff --git a/libxfs/xfs_parent.h b/libxfs/xfs_parent.h index 637f99fba9d..0f4808990ce 100644 --- a/libxfs/xfs_parent.h +++ b/libxfs/xfs_parent.h @@ -75,4 +75,27 @@ xfs_parent_finish( __xfs_parent_cancel(mp, p); } +/* + * Incore version of a parent pointer, also contains dirent name so callers + * can pass/obtain all the parent pointer information in a single structure + */ +struct xfs_parent_name_irec { + /* Parent pointer attribute name fields */ + xfs_ino_t p_ino; + uint32_t p_gen; + xfs_dahash_t p_namehash; + + /* Parent pointer attribute value fields */ + uint8_t p_namelen; + unsigned char p_name[MAXNAMELEN]; +}; + +void xfs_parent_irec_from_disk(struct xfs_parent_name_irec *irec, + const struct xfs_parent_name_rec *rec, const void *value, + unsigned int valuelen); +void xfs_parent_irec_to_disk(struct xfs_parent_name_rec *rec, + const struct xfs_parent_name_irec *irec); +void xfs_parent_irec_hashname(struct xfs_mount *mp, + struct xfs_parent_name_irec *irec); + #endif /* __XFS_PARENT_H__ */ diff --git a/man/man3/xfsctl.3 b/man/man3/xfsctl.3 index 4a0d4d08d08..e663b64a81b 100644 --- a/man/man3/xfsctl.3 +++ b/man/man3/xfsctl.3 @@ -321,6 +321,69 @@ They are all subject to change and should not be called directly by applications. XFS_IOC_FSSETDM_BY_HANDLE is not supported as of Linux 5.5. +.PP +.TP +.B XFS_IOC_GETPARENTS +This command is used to get a file's parent pointers. +Parent pointers point upwards in the directory tree towards directories that +have entries pointing downwards. + +Calling programs should allocate a large memory buffer, initialize the head +structure to zeroes, set gp_bufsize to the size of the buffer, and call the +ioctl. +The kernel will fill out the gp_offsets array with integer offsets to +struct xfs_getparents_rec objects that are written within the provided memory +buffer. +The size of the gp_offsets array is given by gp_count. +The XFS_GETPARENTS_OFLAG_DONE flag will be set in gp_flags when there are no +more parent pointers to be read. +The below code is an example of XFS_IOC_GETPARENTS usage: + +.nf +#include +#include +#include +#include +#include +#include +#include +#include + +int main() { + struct xfs_getparents *pi; + struct xfs_getparents_rec *p; + int i, error, fd, nr_ptrs = 4; + + error = malloc(65536); + if (!error) { + perror("malloc"); + return 1; + } + + memset(pi, 0, sizeof(*pi)); + pi->gp_bufsize = 65536; + + fd = open("/mnt/test/foo.txt", O_RDONLY | O_CREAT); + if (fd == -1) + return errno; + + do { + error = ioctl(fd, XFS_IOC_GETPARENTS, pi); + if (error) + return error; + + for (i = 0; i < pi->gp_count; i++) { + p = xfs_getparents_rec(pi, i); + printf("inode = %llu\\n", (unsigned long long)p->gpr_ino); + printf("generation = %u\\n", (unsigned int)p->gpr_gen); + printf("name = \\"%s\\"\\n\\n", (char *)p->gpr_name); + } + } while (!(pi->gp_flags & XFS_GETPARENTS_OFLAG_DONE)); + + return 0; +} +.fi + .SS Filesystem Operations In order to effect one of the following operations, the pathname and descriptor arguments passed to From patchwork Fri May 26 02:24:58 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: 13256313 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 6F12FC77B7A for ; Fri, 26 May 2023 02:25:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230077AbjEZCZB (ORCPT ); Thu, 25 May 2023 22:25:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53062 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229999AbjEZCZB (ORCPT ); Thu, 25 May 2023 22:25:01 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81415B6 for ; Thu, 25 May 2023 19:24:59 -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 0F82F64C3C for ; Fri, 26 May 2023 02:24:59 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6E6AAC433EF; Fri, 26 May 2023 02:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067898; bh=AvxsvRmimiBNU64DKb9WFdoT1Nrkes+D96GkIOYg7l4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=bW0e/w1c9gbQy6E2QBMEu+74/mq8y+wCRNx4STYmrPBIxACwBJ0tHxqihmN7+Ajcx 8h4g3t7BOGaUFiTYBuMz2y9e6ar2oyGcVFHPsCS3UoWU9J9P//EZrmZsjuewqKwqP/ cGABeU+058G4/KRi4y4AEOBxqGfiLyNo5qtr1gnacAjkZIc28brUzuo7Tioo/rdY29 vPwJOp7dKUK3ph8XlXdH/1+7BODy5ahkZepYY0dJusuo77924uD1YcaZxiCho1YHiP a25soaKam5m1AWCORtEAY2pmIv29r8WNRRF3jZt5CbENb7kgV10Xh5aGlWfd2FyOQH YCdbjCRitUn8A== Date: Thu, 25 May 2023 19:24:58 -0700 Subject: [PATCH 12/30] xfs: fix unit conversion error in xfs_log_calc_max_attrsetm_res From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078051.3749421.473768210508032882.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Dave and I were discussing some recent test regressions as a result of me turning on nrext64=1 on realtime filesystems, when we noticed that the minimum log size of a 32M filesystem jumped from 954 blocks to 4287 blocks. Digging through xfs_log_calc_max_attrsetm_res, Dave noticed that @size contains the maximum estimated amount of space needed for a local format xattr, in bytes, but we feed this quantity to XFS_NEXTENTADD_SPACE_RES, which requires units of blocks. This has resulted in an overestimation of the minimum log size over the years. We should nominally correct this, but there's a backwards compatibility problem -- if we enable it now, the minimum log size will decrease. If a corrected mkfs formats a filesystem with this new smaller log size, a user will encounter mount failures on an uncorrected kernel due to the larger minimum log size computations there. However, the large extent counters feature is still EXPERIMENTAL, so we can gate the correction on that feature (or any features that get added after that) being enabled. Any filesystem with nrext64 or any of the as-yet-undefined feature bits turned on will be rejected by old uncorrected kernels, so this should be safe even in the upgrade case. Signed-off-by: Darrick J. Wong Reviewed-by: Allison Henderson --- libxfs/xfs_log_rlimit.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/libxfs/xfs_log_rlimit.c b/libxfs/xfs_log_rlimit.c index cba24493f86..6ecb9ad5111 100644 --- a/libxfs/xfs_log_rlimit.c +++ b/libxfs/xfs_log_rlimit.c @@ -16,6 +16,39 @@ #include "xfs_bmap_btree.h" #include "xfs_trace.h" +/* + * Decide if the filesystem has the parent pointer feature or any feature + * added after that. + */ +static inline bool +xfs_has_parent_or_newer_feature( + struct xfs_mount *mp) +{ + if (!xfs_sb_is_v5(&mp->m_sb)) + return false; + + if (xfs_sb_has_compat_feature(&mp->m_sb, ~0)) + return true; + + if (xfs_sb_has_ro_compat_feature(&mp->m_sb, + ~(XFS_SB_FEAT_RO_COMPAT_FINOBT | + XFS_SB_FEAT_RO_COMPAT_RMAPBT | + XFS_SB_FEAT_RO_COMPAT_REFLINK | + XFS_SB_FEAT_RO_COMPAT_INOBTCNT))) + return true; + + if (xfs_sb_has_incompat_feature(&mp->m_sb, + ~(XFS_SB_FEAT_INCOMPAT_FTYPE | + XFS_SB_FEAT_INCOMPAT_SPINODES | + XFS_SB_FEAT_INCOMPAT_META_UUID | + XFS_SB_FEAT_INCOMPAT_BIGTIME | + XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR | + XFS_SB_FEAT_INCOMPAT_NREXT64))) + return true; + + return false; +} + /* * Calculate the maximum length in bytes that would be required for a local * attribute value as large attributes out of line are not logged. @@ -31,6 +64,16 @@ xfs_log_calc_max_attrsetm_res( MAXNAMELEN - 1; nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); nblks += XFS_B_TO_FSB(mp, size); + + /* + * Starting with the parent pointer feature, every new fs feature + * corrects a unit conversion error in the xattr transaction + * reservation code that resulted in oversized minimum log size + * computations. + */ + if (xfs_has_parent_or_newer_feature(mp)) + size = XFS_B_TO_FSB(mp, size); + nblks += XFS_NEXTENTADD_SPACE_RES(mp, size, XFS_ATTR_FORK); return M_RES(mp)->tr_attrsetm.tr_logres + From patchwork Fri May 26 02:25:13 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: 13256314 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 BD6E4C77B7E for ; Fri, 26 May 2023 02:25:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229999AbjEZCZS (ORCPT ); Thu, 25 May 2023 22:25:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53114 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234501AbjEZCZQ (ORCPT ); Thu, 25 May 2023 22:25:16 -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 17F7913D for ; Thu, 25 May 2023 19:25:15 -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 A176A64C3C for ; Fri, 26 May 2023 02:25:14 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 14407C433D2; Fri, 26 May 2023 02:25:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067914; bh=Kd928IKNpr/KPVwjCp9YvkUq95ykWdj/vAIRzlzbgLU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=V6/pWSzxUctF0XGcctGCNvsrMK3hTJ3RPXvAnDBvyQ66upi3qjNV08lE6y5Zm8E8Z 7BDDNeSuPRbYxZtkFuEwbBpEpIqhq+dIBdK8iHKGhLhY+EJlSU7RLmdG96tgYazSYJ yBuLIZsQZ1rxDM42hxpXll42UCnl/7b4BtV2iAMJFvZJ0Dl+DXNTDy+YY768bodpNd p9/I3S9itAcj2f5hU7Jhpf7PdpCllnUoDTtwRlL3Ln3mtiT0hJYRfFFfhCIGBxEw6t JPMSLMV+O8x4zqaeGmR+WhpeXzGZ+zs7CbxZ5BFM+yPOow3b9cPTctSRlyO5rYV74+ h2vO4QifypoKQ== Date: Thu, 25 May 2023 19:25:13 -0700 Subject: [PATCH 13/30] xfs: drop compatibility minimum log size computations for reflink From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078064.3749421.2036217039904070986.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Having established that we can reduce the minimum log size computation for filesystems with parent pointers or any newer feature, we should also drop the compat minlogsize code that we added when we reduced the transaction reservation size for rmap and reflink. Signed-off-by: Darrick J. Wong Reviewed-by: Allison Henderson --- libxfs/xfs_log_rlimit.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libxfs/xfs_log_rlimit.c b/libxfs/xfs_log_rlimit.c index 6ecb9ad5111..59605f0dc97 100644 --- a/libxfs/xfs_log_rlimit.c +++ b/libxfs/xfs_log_rlimit.c @@ -91,6 +91,16 @@ xfs_log_calc_trans_resv_for_minlogblocks( { unsigned int rmap_maxlevels = mp->m_rmap_maxlevels; + /* + * Starting with the parent pointer feature, every new fs feature + * drops the oversized minimum log size computation introduced by the + * original reflink code. + */ + if (xfs_has_parent_or_newer_feature(mp)) { + xfs_trans_resv_calc(mp, resv); + return; + } + /* * In the early days of rmap+reflink, we always set the rmap maxlevels * to 9 even if the AG was small enough that it would never grow to From patchwork Fri May 26 02:25:29 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: 13256315 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 D5566C77B7E for ; Fri, 26 May 2023 02:25:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232645AbjEZCZc (ORCPT ); Thu, 25 May 2023 22:25:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53150 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230289AbjEZCZb (ORCPT ); Thu, 25 May 2023 22:25:31 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9849EB2 for ; Thu, 25 May 2023 19:25:30 -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 361DA64C4C for ; Fri, 26 May 2023 02:25:30 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9A287C433D2; Fri, 26 May 2023 02:25:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067929; bh=bZtEIHYsGtTj1COEIFN2PanEklGygPPwmg3dvRp9GYQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=boWL5x11FZGNICQ+IqYWlTlIljmSSMDDn2B/lUEIYlWxpCUzCIul1v4lUnPC4nWGz S9SvdIL0MyG5laCGNl59AGpRZa/SAdNF49CY730yZ77ayyxKqaFkuFTsSAAASbad03 m6nr/ZUxvjO3WTAM3rpmvV15se6R1JF4aYfoVPNt+hNsTKoQCmYddeLiDMT2baq4Cg rgwoofQmtgD4TcTM++fVXp8amMwhmx1OucpWfqqk2jvFuGDEQz5c7/g0uiPTLOysIo WL4LFbNqJ4dXVV+cQzZJpsLHcAjs0MM84+SAmMfV5H63wVtoOHf3tUgWIqyBj3Nn8Q cjJbKe7Ko6n8Q== Date: Thu, 25 May 2023 19:25:29 -0700 Subject: [PATCH 14/30] xfs: don't remove the attr fork when parent pointers are enabled From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078078.3749421.2850981743882573422.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 When an inode is removed, it may also cause the attribute fork to be removed if it is the last attribute. This transaction gets flushed to the log, but if the system goes down before we could inactivate the symlink, the log recovery tries to inactivate this inode (since it is on the unlinked list) but the verifier trips over the remote value and leaks it. Hence we ended up with a file in this odd state on a "clean" mount. The "obvious" fix is to prohibit erasure of the attr fork to avoid tripping over the verifiers when pptrs are enabled. Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- libxfs/xfs_attr_leaf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c index d737d4163dd..a7845da9bcc 100644 --- a/libxfs/xfs_attr_leaf.c +++ b/libxfs/xfs_attr_leaf.c @@ -910,7 +910,8 @@ xfs_attr_sf_removename( totsize -= size; if (totsize == sizeof(xfs_attr_sf_hdr_t) && xfs_has_attr2(mp) && (dp->i_df.if_format != XFS_DINODE_FMT_BTREE) && - !(args->op_flags & (XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE))) { + !(args->op_flags & (XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE)) && + !xfs_has_parent(mp)) { xfs_attr_fork_remove(dp, args->trans); } else { xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); @@ -919,7 +920,8 @@ xfs_attr_sf_removename( ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || (args->op_flags & XFS_DA_OP_ADDNAME) || !xfs_has_attr2(mp) || - dp->i_df.if_format == XFS_DINODE_FMT_BTREE); + dp->i_df.if_format == XFS_DINODE_FMT_BTREE || + xfs_has_parent(mp)); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA); } From patchwork Fri May 26 02:25:44 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: 13256316 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 0570CC77B7E for ; Fri, 26 May 2023 02:25:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233734AbjEZCZt (ORCPT ); Thu, 25 May 2023 22:25:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53300 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234501AbjEZCZr (ORCPT ); Thu, 25 May 2023 22:25:47 -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 499BFB6 for ; Thu, 25 May 2023 19:25:46 -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 C447264C3C for ; Fri, 26 May 2023 02:25:45 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 30AADC433EF; Fri, 26 May 2023 02:25:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067945; bh=WDsJgxC+zbYfyBR8aMGH/5xXTwdo+1FGnljKtgndAsY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=c3b65zQmmQ/UHLmT1wXK7Yvh+BW2ALWV1/yUbimEOXIg8PF/EWMrQ1plbD7gEl214 0WPLnLVTZdVI9Rpv2Gpgo0YaTpwW9wTgju2DrIJ1885rH0Zj0086K44oVspJXupWax 33aUneNUliF54H6QEy2vDNyj0afP2w1xeAhhqREQXdXLeZmRSomFksTKzev5078/t6 SmtpgBeEt6tZj+U2SKCh7646q2ttoeUev3LV+t8c8rZvuBHdnGrj7S1xqhAav80+tn 6RbizCD3XQWL7aOkdMShSMi4KAuBMMWqC3GrtsSuPzTMJ0A7jgYgrklSF8J0oGuNgQ +0LEIOZ9h5SkA== Date: Thu, 25 May 2023 19:25:44 -0700 Subject: [PATCH 15/30] xfs: Add the parent pointer support to the superblock version 5. From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Mark Tinguely , Dave Chinner , Allison Henderson , "Darrick J. Wong" , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078091.3749421.13725045985508253144.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Add the parent pointer superblock flag so that we can actually mount filesystems with this feature enabled. Signed-off-by: Mark Tinguely Signed-off-by: Dave Chinner Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- libfrog/fsgeom.c | 4 ++++ libxfs/xfs_format.h | 4 +++- libxfs/xfs_fs.h | 1 + libxfs/xfs_sb.c | 4 ++++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c index 6980d3ffab6..297900e1724 100644 --- a/libfrog/fsgeom.c +++ b/libfrog/fsgeom.c @@ -31,6 +31,7 @@ xfs_report_geom( int bigtime_enabled; int inobtcount; int nrext64; + int parent; isint = geo->logstart > 0; lazycount = geo->flags & XFS_FSOP_GEOM_FLAGS_LAZYSB ? 1 : 0; @@ -49,12 +50,14 @@ xfs_report_geom( bigtime_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_BIGTIME ? 1 : 0; inobtcount = geo->flags & XFS_FSOP_GEOM_FLAGS_INOBTCNT ? 1 : 0; nrext64 = geo->flags & XFS_FSOP_GEOM_FLAGS_NREXT64 ? 1 : 0; + parent = geo->flags & XFS_FSOP_GEOM_FLAGS_PARENT ? 1 : 0; printf(_( "meta-data=%-22s isize=%-6d agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u\n" " =%-22s reflink=%-4u bigtime=%u inobtcount=%u nrext64=%u\n" +" =%-22s parent=%d\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d, ftype=%d\n" @@ -65,6 +68,7 @@ xfs_report_geom( "", geo->sectsize, attrversion, projid32bit, "", crcs_enabled, finobt_enabled, spinodes, rmapbt_enabled, "", reflink_enabled, bigtime_enabled, inobtcount, nrext64, + "", parent, "", geo->blocksize, (unsigned long long)geo->datablocks, geo->imaxpct, "", geo->sunit, geo->swidth, diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 977d3051973..1f1fde6720d 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -373,13 +373,15 @@ xfs_sb_has_ro_compat_feature( #define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */ #define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */ #define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */ +#define XFS_SB_FEAT_INCOMPAT_PARENT (1 << 6) /* parent pointers */ #define XFS_SB_FEAT_INCOMPAT_ALL \ (XFS_SB_FEAT_INCOMPAT_FTYPE| \ XFS_SB_FEAT_INCOMPAT_SPINODES| \ XFS_SB_FEAT_INCOMPAT_META_UUID| \ XFS_SB_FEAT_INCOMPAT_BIGTIME| \ XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR| \ - XFS_SB_FEAT_INCOMPAT_NREXT64) + XFS_SB_FEAT_INCOMPAT_NREXT64| \ + XFS_SB_FEAT_INCOMPAT_PARENT) #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL static inline bool diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h index 51b31e987a0..41badf3a0be 100644 --- a/libxfs/xfs_fs.h +++ b/libxfs/xfs_fs.h @@ -239,6 +239,7 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_BIGTIME (1 << 21) /* 64-bit nsec timestamps */ #define XFS_FSOP_GEOM_FLAGS_INOBTCNT (1 << 22) /* inobt btree counter */ #define XFS_FSOP_GEOM_FLAGS_NREXT64 (1 << 23) /* large extent counters */ +#define XFS_FSOP_GEOM_FLAGS_PARENT (1U << 30) /* parent pointers */ #define XFS_FSOP_GEOM_FLAGS_ATOMIC_SWAP (1U << 31) /* atomic file extent swap */ /* diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index 9b229a2db58..ada000c1ad6 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -173,6 +173,8 @@ xfs_sb_version_to_features( features |= XFS_FEAT_NEEDSREPAIR; if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_NREXT64) features |= XFS_FEAT_NREXT64; + if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_PARENT) + features |= XFS_FEAT_PARENT; return features; } @@ -1190,6 +1192,8 @@ xfs_fs_geometry( geo->flags |= XFS_FSOP_GEOM_FLAGS_BIGTIME; if (xfs_has_inobtcounts(mp)) geo->flags |= XFS_FSOP_GEOM_FLAGS_INOBTCNT; + if (xfs_has_parent(mp)) + geo->flags |= XFS_FSOP_GEOM_FLAGS_PARENT; if (xfs_has_sector(mp)) { geo->flags |= XFS_FSOP_GEOM_FLAGS_SECTOR; geo->logsectsize = sbp->sb_logsectsize; From patchwork Fri May 26 02:26:00 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: 13256317 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 59781C77B7A for ; Fri, 26 May 2023 02:26:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234343AbjEZC0F (ORCPT ); Thu, 25 May 2023 22:26:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53466 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230289AbjEZC0E (ORCPT ); Thu, 25 May 2023 22:26:04 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1309BB2 for ; Thu, 25 May 2023 19:26:02 -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 64BE964C3C for ; Fri, 26 May 2023 02:26:01 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C49C5C433D2; Fri, 26 May 2023 02:26:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067960; bh=8WwNvmRJbT6AqNyIrSE/79OTIiaYFHbRuI0WE6ONiYw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=KtN0MBLDbeYnZz/b3Dg0hxRysdLDXna3toNaRyLxxJ55Opr5sqYEl28Ee5lxlNCMQ Rul9aIC/Z8Mn0P6mqdxV3sIRWE1V+xItJm7FZJe9lscvEQx2o1w+xnGRCQRi3AQEck e0hJ41kfpHn15fIN2HmncSNPSIsTkgzGpimXnITWSXY1DKd+uzEjGy+m6GYbFcVqrt MQR/DlPFrVjE6tXb9+B2xwl1r20DKIdOXBENBBKymM4h5T/L0WitjyUnjOq3fhNPFr JSSM1LO6RLd0o/zg2qgocghn/6M5sU0Ra6RP9GDY1Kwl3du6hmBb099MqnJ2KQbCr6 CLNnu1oStdTsg== Date: Thu, 25 May 2023 19:26:00 -0700 Subject: [PATCH 16/30] libfrog: add parent pointer support code From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078105.3749421.17833661810820399534.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 some support code to libfrog so that client programs can walk file descriptors and handles upwards through the directory tree; and obtain a reasonable file path from a file descriptor/handle. This code will be used in xfsprogs utilities. Signed-off-by: Darrick J. Wong Reviewed-by: Allison Henderson --- include/handle.h | 1 libfrog/Makefile | 2 libfrog/getparents.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++ libfrog/getparents.h | 36 +++++ libfrog/paths.c | 167 ++++++++++++++++++++++++ libfrog/paths.h | 25 ++++ libhandle/handle.c | 7 + 7 files changed, 580 insertions(+), 3 deletions(-) create mode 100644 libfrog/getparents.c create mode 100644 libfrog/getparents.h diff --git a/include/handle.h b/include/handle.h index 34246f3854d..ba06500516c 100644 --- a/include/handle.h +++ b/include/handle.h @@ -17,6 +17,7 @@ struct parent; extern int path_to_handle (char *__path, void **__hanp, size_t *__hlen); extern int path_to_fshandle (char *__path, void **__fshanp, size_t *__fshlen); extern int fd_to_handle (int fd, void **hanp, size_t *hlen); +extern int handle_to_fsfd(void *, char **); extern int handle_to_fshandle (void *__hanp, size_t __hlen, void **__fshanp, size_t *__fshlen); extern void free_handle (void *__hanp, size_t __hlen); diff --git a/libfrog/Makefile b/libfrog/Makefile index ad32b0674b2..8dd6ed68510 100644 --- a/libfrog/Makefile +++ b/libfrog/Makefile @@ -20,6 +20,7 @@ convert.c \ crc32.c \ file_exchange.c \ fsgeom.c \ +getparents.c \ histogram.c \ list_sort.c \ linux.c \ @@ -45,6 +46,7 @@ crc32table.h \ dahashselftest.h \ file_exchange.h \ fsgeom.h \ +getparents.h \ histogram.h \ logging.h \ paths.h \ diff --git a/libfrog/getparents.c b/libfrog/getparents.c new file mode 100644 index 00000000000..89e1d3fa875 --- /dev/null +++ b/libfrog/getparents.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2017-2023 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include "platform_defs.h" +#include "xfs.h" +#include "xfs_arch.h" +#include "list.h" +#include "libfrog/paths.h" +#include "handle.h" +#include "libfrog/getparents.h" + +/* Allocate a buffer large enough for some parent pointer records. */ +static inline struct xfs_getparents * +alloc_pptr_buf( + size_t bufsize) +{ + struct xfs_getparents *pi; + + pi = calloc(bufsize, 1); + if (!pi) + return NULL; + pi->gp_bufsize = bufsize; + return pi; +} + +/* + * Walk all parents of the given file handle. Returns 0 on success or positive + * errno. + */ +static int +call_getparents( + int fd, + struct xfs_handle *handle, + walk_parent_fn fn, + void *arg) +{ + struct xfs_getparents *pi; + struct xfs_getparents_rec *p; + unsigned int i; + ssize_t ret = -1; + + pi = alloc_pptr_buf(XFS_XATTR_LIST_MAX); + if (!pi) + return errno; + + if (handle) { + memcpy(&pi->gp_handle, handle, sizeof(struct xfs_handle)); + pi->gp_flags = XFS_GETPARENTS_IFLAG_HANDLE; + } + + ret = ioctl(fd, XFS_IOC_GETPARENTS, pi); + while (!ret) { + if (pi->gp_flags & XFS_GETPARENTS_OFLAG_ROOT) { + struct parent_rec rec = { + .p_flags = PARENT_IS_ROOT, + }; + + ret = fn(&rec, arg); + goto out_pi; + } + + for (i = 0; i < pi->gp_count; i++) { + struct parent_rec rec = { 0 }; + + p = xfs_getparents_rec(pi, i); + rec.p_ino = p->gpr_ino; + rec.p_gen = p->gpr_gen; + strncpy((char *)rec.p_name, (char *)p->gpr_name, + MAXNAMELEN - 1); + + ret = fn(&rec, arg); + if (ret) + goto out_pi; + } + + if (pi->gp_flags & XFS_GETPARENTS_OFLAG_DONE) + break; + + ret = ioctl(fd, XFS_IOC_GETPARENTS, pi); + } + if (ret) + ret = errno; + +out_pi: + free(pi); + return ret; +} + +/* Walk all parent pointers of this handle. Returns 0 or positive errno. */ +int +handle_walk_parents( + void *hanp, + size_t hlen, + walk_parent_fn fn, + void *arg) +{ + char *mntpt; + int fd; + + if (hlen != sizeof(struct xfs_handle)) + return EINVAL; + + fd = handle_to_fsfd(hanp, &mntpt); + if (fd < 0) + return errno; + + return call_getparents(fd, hanp, fn, arg); +} + +/* Walk all parent pointers of this fd. Returns 0 or positive errno. */ +int +fd_walk_parents( + int fd, + walk_parent_fn fn, + void *arg) +{ + return call_getparents(fd, NULL, fn, arg); +} + +struct walk_ppaths_info { + walk_path_fn fn; + void *arg; + char *mntpt; + struct path_list *path; + int fd; +}; + +struct walk_ppath_level_info { + struct xfs_handle newhandle; + struct path_component *pc; + struct walk_ppaths_info *wpi; +}; + +static int handle_walk_ppath(struct walk_ppaths_info *wpi, + struct xfs_handle *handle); + +static int +handle_walk_ppath_rec( + const struct parent_rec *rec, + void *arg) +{ + struct walk_ppath_level_info *wpli = arg; + struct walk_ppaths_info *wpi = wpli->wpi; + int ret = 0; + + if (rec->p_flags & PARENT_IS_ROOT) + return wpi->fn(wpi->mntpt, wpi->path, wpi->arg); + + ret = path_component_change(wpli->pc, rec->p_name, + strlen((char *)rec->p_name), rec->p_ino); + if (ret) + return ret; + + wpli->newhandle.ha_fid.fid_ino = rec->p_ino; + wpli->newhandle.ha_fid.fid_gen = rec->p_gen; + + path_list_add_parent_component(wpi->path, wpli->pc); + ret = handle_walk_ppath(wpi, &wpli->newhandle); + path_list_del_component(wpi->path, wpli->pc); + + return ret; +} + +/* + * Recursively walk all parents of the given file handle; if we hit the + * fs root then we call the associated function with the constructed path. + * Returns 0 for success or positive errno. + */ +static int +handle_walk_ppath( + struct walk_ppaths_info *wpi, + struct xfs_handle *handle) +{ + struct walk_ppath_level_info *wpli; + int ret; + + wpli = malloc(sizeof(struct walk_ppath_level_info)); + if (!wpli) + return errno; + wpli->pc = path_component_init("", 0); + if (!wpli->pc) { + ret = errno; + free(wpli); + return ret; + } + wpli->wpi = wpi; + memcpy(&wpli->newhandle, handle, sizeof(struct xfs_handle)); + + ret = call_getparents(wpi->fd, handle, handle_walk_ppath_rec, wpli); + + path_component_free(wpli->pc); + free(wpli); + return ret; +} + +/* + * Call the given function on all known paths from the vfs root to the inode + * described in the handle. Returns 0 for success or positive errno. + */ +int +handle_walk_parent_paths( + void *hanp, + size_t hlen, + walk_path_fn fn, + void *arg) +{ + struct walk_ppaths_info wpi; + ssize_t ret; + + if (hlen != sizeof(struct xfs_handle)) + return EINVAL; + + wpi.fd = handle_to_fsfd(hanp, &wpi.mntpt); + if (wpi.fd < 0) + return errno; + wpi.path = path_list_init(); + if (!wpi.path) + return errno; + wpi.fn = fn; + wpi.arg = arg; + + ret = handle_walk_ppath(&wpi, hanp); + path_list_free(wpi.path); + + return ret; +} + +/* + * Call the given function on all known paths from the vfs root to the inode + * referred to by the file description. Returns 0 or positive errno. + */ +int +fd_walk_parent_paths( + int fd, + walk_path_fn fn, + void *arg) +{ + struct walk_ppaths_info wpi; + void *hanp; + size_t hlen; + int fsfd; + int ret; + + ret = fd_to_handle(fd, &hanp, &hlen); + if (ret) + return errno; + + fsfd = handle_to_fsfd(hanp, &wpi.mntpt); + if (fsfd < 0) + return errno; + wpi.fd = fd; + wpi.path = path_list_init(); + if (!wpi.path) + return errno; + wpi.fn = fn; + wpi.arg = arg; + + ret = handle_walk_ppath(&wpi, hanp); + path_list_free(wpi.path); + + return ret; +} + +struct path_walk_info { + char *buf; + size_t len; + size_t written; +}; + +/* Helper that stringifies the first full path that we find. */ +static int +handle_to_path_walk( + const char *mntpt, + const struct path_list *path, + void *arg) +{ + struct path_walk_info *pwi = arg; + int mntpt_len = strlen(mntpt); + int ret; + + /* Trim trailing slashes from the mountpoint */ + while (mntpt_len > 0 && mntpt[mntpt_len - 1] == '/') + mntpt_len--; + + ret = snprintf(pwi->buf, pwi->len, "%.*s", mntpt_len, mntpt); + if (ret != mntpt_len) + return ENAMETOOLONG; + pwi->written += ret; + + ret = path_list_to_string(path, pwi->buf + ret, pwi->len - ret); + if (ret < 0) + return ENAMETOOLONG; + + pwi->written += ret; + return ECANCELED; +} + +/* + * Return any eligible path to this file handle. Returns 0 for success or + * positive errno. + */ +int +handle_to_path( + void *hanp, + size_t hlen, + char *path, + size_t pathlen) +{ + struct path_walk_info pwi = { .buf = path, .len = pathlen }; + int ret; + + ret = handle_walk_parent_paths(hanp, hlen, handle_to_path_walk, &pwi); + if (ret && ret != ECANCELED) + return ret; + if (!pwi.written) + return ENODATA; + + path[pwi.written] = 0; + return 0; +} + +/* + * Return any eligible path to this file description. Returns 0 for success + * or positive errno. + */ +int +fd_to_path( + int fd, + char *path, + size_t pathlen) +{ + struct path_walk_info pwi = { .buf = path, .len = pathlen }; + int ret; + + ret = fd_walk_parent_paths(fd, handle_to_path_walk, &pwi); + if (ret && ret != ECANCELED) + return ret; + if (!pwi.written) + return ENODATA; + + path[pwi.written] = 0; + return ret; +} diff --git a/libfrog/getparents.h b/libfrog/getparents.h new file mode 100644 index 00000000000..c95efed245a --- /dev/null +++ b/libfrog/getparents.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#ifndef __LIBFROG_GETPARENTS_H_ +#define __LIBFROG_GETPARENTS_H_ + +struct path_list; + +struct parent_rec { + uint64_t p_ino; + uint32_t p_gen; + uint32_t p_flags; + unsigned char p_name[MAXNAMELEN]; +}; + +/* This is the root directory. */ +#define PARENT_IS_ROOT (1U << 0) + +typedef int (*walk_parent_fn)(const struct parent_rec *rec, void *arg); +typedef int (*walk_path_fn)(const char *mntpt, const struct path_list *path, + void *arg); + +int fd_walk_parents(int fd, walk_parent_fn fn, void *arg); +int handle_walk_parents(void *hanp, size_t hanlen, walk_parent_fn fn, + void *arg); + +int fd_walk_parent_paths(int fd, walk_path_fn fn, void *arg); +int handle_walk_parent_paths(void *hanp, size_t hanlen, walk_path_fn fn, + void *arg); + +int fd_to_path(int fd, char *path, size_t pathlen); +int handle_to_path(void *hanp, size_t hlen, char *path, size_t pathlen); + +#endif /* __LIBFROG_GETPARENTS_H_ */ diff --git a/libfrog/paths.c b/libfrog/paths.c index abb29a237e8..4b9c8c64489 100644 --- a/libfrog/paths.c +++ b/libfrog/paths.c @@ -15,6 +15,7 @@ #include "paths.h" #include "input.h" #include "projects.h" +#include "list.h" #include extern char *progname; @@ -563,3 +564,169 @@ fs_table_insert_project_path( return error; } + +/* Structured path components. */ + +struct path_list { + struct list_head p_head; +}; + +struct path_component { + struct list_head pc_list; + uint64_t pc_ino; + char *pc_fname; +}; + +/* Initialize a path component with a given name. */ +struct path_component * +path_component_init( + const char *name, + uint64_t ino) +{ + struct path_component *pc; + + pc = malloc(sizeof(struct path_component)); + if (!pc) + return NULL; + INIT_LIST_HEAD(&pc->pc_list); + pc->pc_fname = strdup(name); + if (!pc->pc_fname) { + free(pc); + return NULL; + } + pc->pc_ino = ino; + return pc; +} + +/* Free a path component. */ +void +path_component_free( + struct path_component *pc) +{ + free(pc->pc_fname); + free(pc); +} + +/* Change a path component's filename or returns positive errno. */ +int +path_component_change( + struct path_component *pc, + const void *name, + size_t namelen, + uint64_t ino) +{ + void *p; + + p = realloc(pc->pc_fname, namelen + 1); + if (!p) + return errno; + pc->pc_fname = p; + memcpy(pc->pc_fname, name, namelen); + pc->pc_fname[namelen] = 0; + pc->pc_ino = ino; + return 0; +} + +/* Initialize a pathname or returns positive errno. */ +struct path_list * +path_list_init(void) +{ + struct path_list *path; + + path = malloc(sizeof(struct path_list)); + if (!path) + return NULL; + INIT_LIST_HEAD(&path->p_head); + return path; +} + +/* Empty out a pathname. */ +void +path_list_free( + struct path_list *path) +{ + struct path_component *pos; + struct path_component *n; + + list_for_each_entry_safe(pos, n, &path->p_head, pc_list) { + path_list_del_component(path, pos); + path_component_free(pos); + } + free(path); +} + +/* Add a parent component to a pathname. */ +void +path_list_add_parent_component( + struct path_list *path, + struct path_component *pc) +{ + list_add(&pc->pc_list, &path->p_head); +} + +/* Add a component to a pathname. */ +void +path_list_add_component( + struct path_list *path, + struct path_component *pc) +{ + list_add_tail(&pc->pc_list, &path->p_head); +} + +/* Remove a component from a pathname. */ +void +path_list_del_component( + struct path_list *path, + struct path_component *pc) +{ + list_del_init(&pc->pc_list); +} + +/* + * Convert a pathname into a string or returns -1 if the buffer isn't long + * enough. + */ +ssize_t +path_list_to_string( + const struct path_list *path, + char *buf, + size_t buflen) +{ + struct path_component *pos; + char *buf_end = buf + buflen; + ssize_t bytes = 0; + int ret; + + list_for_each_entry(pos, &path->p_head, pc_list) { + if (buf >= buf_end) + return -1; + + ret = snprintf(buf, buflen, "/%s", pos->pc_fname); + if (ret < 0 || ret >= buflen) + return -1; + + bytes += ret; + buf += ret; + buflen -= ret; + } + return bytes; +} + +/* Walk each component of a path. */ +int +path_walk_components( + const struct path_list *path, + path_walk_fn_t fn, + void *arg) +{ + struct path_component *pos; + int ret; + + list_for_each_entry(pos, &path->p_head, pc_list) { + ret = fn(pos->pc_fname, pos->pc_ino, arg); + if (ret) + return ret; + } + + return 0; +} diff --git a/libfrog/paths.h b/libfrog/paths.h index f20a2c3ef58..6be74c42b07 100644 --- a/libfrog/paths.h +++ b/libfrog/paths.h @@ -58,4 +58,29 @@ typedef struct fs_cursor { extern void fs_cursor_initialise(char *__dir, uint __flags, fs_cursor_t *__cp); extern fs_path_t *fs_cursor_next_entry(fs_cursor_t *__cp); +/* Path information. */ + +struct path_list; +struct path_component; + +struct path_component *path_component_init(const char *name, uint64_t ino); +void path_component_free(struct path_component *pc); +int path_component_change(struct path_component *pc, const void *name, + size_t namelen, uint64_t ino); + +struct path_list *path_list_init(void); +void path_list_free(struct path_list *path); +void path_list_add_parent_component(struct path_list *path, + struct path_component *pc); +void path_list_add_component(struct path_list *path, struct path_component *pc); +void path_list_del_component(struct path_list *path, struct path_component *pc); + +ssize_t path_list_to_string(const struct path_list *path, char *buf, + size_t buflen); + +typedef int (*path_walk_fn_t)(const char *name, uint64_t ino, void *arg); + +int path_walk_components(const struct path_list *path, path_walk_fn_t fn, + void *arg); + #endif /* __LIBFROG_PATH_H__ */ diff --git a/libhandle/handle.c b/libhandle/handle.c index 333c2190900..1e8fe9ac5f1 100644 --- a/libhandle/handle.c +++ b/libhandle/handle.c @@ -29,7 +29,6 @@ typedef union { } comarg_t; static int obj_to_handle(char *, int, unsigned int, comarg_t, void**, size_t*); -static int handle_to_fsfd(void *, char **); static char *path_to_fspath(char *path); @@ -203,8 +202,10 @@ handle_to_fshandle( return 0; } -static int -handle_to_fsfd(void *hanp, char **path) +int +handle_to_fsfd( + void *hanp, + char **path) { struct fdhash *fdhp; From patchwork Fri May 26 02:26:15 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: 13256318 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 8A7A0C77B7E for ; Fri, 26 May 2023 02:26:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230289AbjEZC0U (ORCPT ); Thu, 25 May 2023 22:26:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53504 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229865AbjEZC0T (ORCPT ); Thu, 25 May 2023 22:26:19 -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 815819B for ; Thu, 25 May 2023 19:26:17 -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 08FB164C3C for ; Fri, 26 May 2023 02:26:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 68A92C433D2; Fri, 26 May 2023 02:26:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067976; bh=K3NXF9iVqUL26/9+qFjvffEfBWAf5wDPEYD4XHmyh+U=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=D6Oztxcj+Vew5rH6qo39xkHj63q1TDAvFRnZYec3JaICfQW5yy5aLIuI5kX+gJnmq 8FMReGniyniPZOC7RoujJQOiNy3/plEtiwBnvtld9tr53ytFXnZ4jNXQeVZw5zxPBj K0eJ+yI0/XVg2H5fSaU2UPnLHPiFP8qtjHgHp8sVm2ebmS60meS52329zkwf53+8zU I2/NQ+vGgYBQuv1oZbxGH3ac3Uu8Veex5vSHqQE1dfb9aWCOeqg9qUkEbLYZY4WjhF +lpEiGu869jv6pwHb/zugwIgr/fh4ogIpJlqMTPPsy1cuHEeJGXgWpPnjOYE37wgLy xQOfJUcbGRiBw== Date: Thu, 25 May 2023 19:26:15 -0700 Subject: [PATCH 17/30] xfs_io: adapt parent command to new parent pointer ioctls From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078119.3749421.12166603001052436745.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 For ages, xfs_io has had a totally useless 'parent' command that enabled callers to walk the parents or print the directory tree path of an open file. This code used the ioctl interface presented by SGI's version of parent pointers that was never merged. Rework the code in here to use the new ioctl interfaces that we've settled upon. Get rid of the old parent pointer checking code since xfs_repair/xfs_scrub will take care of that. (This originally was in the "xfsprogs: implement the upper half of parent pointers" megapatch.) Signed-off-by: Darrick J. Wong Reviewed-by: Allison Henderson --- io/parent.c | 470 ++++++++++++++--------------------------------------- man/man8/xfs_io.8 | 21 +- 2 files changed, 133 insertions(+), 358 deletions(-) diff --git a/io/parent.c b/io/parent.c index 8f63607ffec..65fd892bffc 100644 --- a/io/parent.c +++ b/io/parent.c @@ -7,365 +7,112 @@ #include "command.h" #include "input.h" #include "libfrog/paths.h" -#include "parent.h" +#include "libfrog/getparents.h" #include "handle.h" -#include "jdm.h" #include "init.h" #include "io.h" -#define PARENTBUF_SZ 16384 -#define BSTATBUF_SZ 16384 - static cmdinfo_t parent_cmd; -static int verbose_flag; -static int err_status; -static __u64 inodes_checked; static char *mntpt; -/* - * check out a parent entry to see if the values seem valid - */ -static void -check_parent_entry(struct xfs_bstat *bstatp, parent_t *parent) +static int +pptr_print( + const struct parent_rec *rec, + void *arg) { - int sts; - char fullpath[PATH_MAX]; - struct stat statbuf; - char *str; - - sprintf(fullpath, _("%s%s"), mntpt, parent->p_name); - - sts = lstat(fullpath, &statbuf); - if (sts != 0) { - fprintf(stderr, - _("inode-path for inode: %llu is incorrect - path \"%s\" non-existent\n"), - (unsigned long long) bstatp->bs_ino, fullpath); - if (verbose_flag) { - fprintf(stderr, - _("path \"%s\" does not stat for inode: %llu; err = %s\n"), - fullpath, - (unsigned long long) bstatp->bs_ino, - strerror(errno)); - } - err_status++; - return; - } else { - if (verbose_flag > 1) { - printf(_("path \"%s\" found\n"), fullpath); - } - } - - if (statbuf.st_ino != bstatp->bs_ino) { - fprintf(stderr, - _("inode-path for inode: %llu is incorrect - wrong inode#\n"), - (unsigned long long) bstatp->bs_ino); - if (verbose_flag) { - fprintf(stderr, - _("ino mismatch for path \"%s\" %llu vs %llu\n"), - fullpath, - (unsigned long long)statbuf.st_ino, - (unsigned long long)bstatp->bs_ino); - } - err_status++; - return; - } else if (verbose_flag > 1) { - printf(_("inode number match: %llu\n"), - (unsigned long long)statbuf.st_ino); - } + const char *name = (char *)rec->p_name; + unsigned int namelen; - /* get parent path */ - str = strrchr(fullpath, '/'); - *str = '\0'; - sts = stat(fullpath, &statbuf); - if (sts != 0) { - fprintf(stderr, - _("parent path \"%s\" does not stat: %s\n"), - fullpath, - strerror(errno)); - err_status++; - return; - } else { - if (parent->p_ino != statbuf.st_ino) { - fprintf(stderr, - _("inode-path for inode: %llu is incorrect - wrong parent inode#\n"), - (unsigned long long) bstatp->bs_ino); - if (verbose_flag) { - fprintf(stderr, - _("ino mismatch for path \"%s\" %llu vs %llu\n"), - fullpath, - (unsigned long long)parent->p_ino, - (unsigned long long)statbuf.st_ino); - } - err_status++; - return; - } else { - if (verbose_flag > 1) { - printf(_("parent ino match for %llu\n"), - (unsigned long long) parent->p_ino); - } - } + if (rec->p_flags & PARENT_IS_ROOT) { + printf(_("Root directory.\n")); + return 0; } -} - -static void -check_parents(parent_t *parentbuf, size_t *parentbuf_size, - jdm_fshandle_t *fshandlep, struct xfs_bstat *statp) -{ - int error, i; - __u32 count; - parent_t *entryp; - - do { - error = jdm_parentpaths(fshandlep, statp, parentbuf, *parentbuf_size, &count); - - if (error == ERANGE) { - *parentbuf_size *= 2; - parentbuf = (parent_t *)realloc(parentbuf, *parentbuf_size); - } else if (error) { - fprintf(stderr, _("parentpaths failed for ino %llu: %s\n"), - (unsigned long long) statp->bs_ino, - strerror(errno)); - err_status++; - break; - } - } while (error == ERANGE); - - if (count == 0) { - /* no links for inode - something wrong here */ - fprintf(stderr, _("inode-path for inode: %llu is missing\n"), - (unsigned long long) statp->bs_ino); - err_status++; - } + namelen = strlen(name); + printf(_("p_ino = %llu\n"), (unsigned long long)rec->p_ino); + printf(_("p_gen = %u\n"), (unsigned int)rec->p_gen); + printf(_("p_namelen = %u\n"), namelen); + printf(_("p_name = \"%s\"\n\n"), rec->p_name); - entryp = parentbuf; - for (i = 0; i < count; i++) { - check_parent_entry(statp, entryp); - entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen); - } + return 0; } static int -do_bulkstat(parent_t *parentbuf, size_t *parentbuf_size, - struct xfs_bstat *bstatbuf, int fsfd, jdm_fshandle_t *fshandlep) +print_parents( + struct xfs_handle *handle) { - __s32 buflenout; - __u64 lastino = 0; - struct xfs_bstat *p; - struct xfs_bstat *endp; - struct xfs_fsop_bulkreq bulkreq; - struct stat mntstat; - - if (stat(mntpt, &mntstat)) { - fprintf(stderr, _("can't stat mount point \"%s\": %s\n"), - mntpt, strerror(errno)); - return 1; - } - - bulkreq.lastip = &lastino; - bulkreq.icount = BSTATBUF_SZ; - bulkreq.ubuffer = (void *)bstatbuf; - bulkreq.ocount = &buflenout; - - while (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq) == 0) { - if (*(bulkreq.ocount) == 0) { - return 0; - } - for (p = bstatbuf, endp = bstatbuf + *bulkreq.ocount; p < endp; p++) { - - /* inode being modified, get synced data with iget */ - if ( (!p->bs_nlink || !p->bs_mode) && p->bs_ino != 0 ) { - - if (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq) < 0) { - fprintf(stderr, - _("failed to get bulkstat information for inode %llu\n"), - (unsigned long long) p->bs_ino); - continue; - } - if (!p->bs_nlink || !p->bs_mode || !p->bs_ino) { - fprintf(stderr, - _("failed to get valid bulkstat information for inode %llu\n"), - (unsigned long long) p->bs_ino); - continue; - } - } - - /* skip root */ - if (p->bs_ino == mntstat.st_ino) { - continue; - } - - if (verbose_flag > 1) { - printf(_("checking inode %llu\n"), - (unsigned long long) p->bs_ino); - } - - /* print dotted progress */ - if ((inodes_checked % 100) == 0 && verbose_flag == 1) { - printf("."); fflush(stdout); - } - inodes_checked++; - - check_parents(parentbuf, parentbuf_size, fshandlep, p); - } + int ret; - }/*while*/ + if (handle) + ret = handle_walk_parents(handle, sizeof(*handle), pptr_print, + NULL); + else + ret = fd_walk_parents(file->fd, pptr_print, NULL); + if (ret) + fprintf(stderr, "%s: %s\n", file->name, strerror(ret)); - fprintf(stderr, _("syssgi bulkstat failed: %s\n"), strerror(errno)); - return 1; + return 0; } static int -parent_check(void) +path_print( + const char *mntpt, + const struct path_list *path, + void *arg) { - int fsfd; - jdm_fshandle_t *fshandlep; - parent_t *parentbuf; - size_t parentbuf_size = PARENTBUF_SZ; - struct xfs_bstat *bstatbuf; - - err_status = 0; - inodes_checked = 0; - - sync(); - - fsfd = file->fd; - - fshandlep = jdm_getfshandle(mntpt); - if (fshandlep == NULL) { - fprintf(stderr, _("unable to open \"%s\" for jdm: %s\n"), - mntpt, - strerror(errno)); - return 1; - } + char buf[PATH_MAX]; + size_t len = PATH_MAX; + int mntpt_len = strlen(mntpt); + int ret; - /* allocate buffers */ - bstatbuf = (struct xfs_bstat *)calloc(BSTATBUF_SZ, sizeof(struct xfs_bstat)); - parentbuf = (parent_t *)malloc(parentbuf_size); - if (!bstatbuf || !parentbuf) { - fprintf(stderr, _("unable to allocate buffers: %s\n"), - strerror(errno)); - err_status = 1; - goto out; - } - - if (do_bulkstat(parentbuf, &parentbuf_size, bstatbuf, fsfd, fshandlep) != 0) - err_status++; + /* Trim trailing slashes from the mountpoint */ + while (mntpt_len > 0 && mntpt[mntpt_len - 1] == '/') + mntpt_len--; - if (err_status > 0) - fprintf(stderr, _("num errors: %d\n"), err_status); - else - printf(_("succeeded checking %llu inodes\n"), - (unsigned long long) inodes_checked); + ret = snprintf(buf, len, "%.*s", mntpt_len, mntpt); + if (ret != mntpt_len) + return ENAMETOOLONG; -out: - free(bstatbuf); - free(parentbuf); - free(fshandlep); - return err_status; -} + ret = path_list_to_string(path, buf + ret, len - ret); + if (ret < 0) + return ENAMETOOLONG; -static void -print_parent_entry(parent_t *parent, int fullpath) -{ - printf(_("p_ino = %llu\n"), (unsigned long long) parent->p_ino); - printf(_("p_gen = %u\n"), parent->p_gen); - printf(_("p_reclen = %u\n"), parent->p_reclen); - if (fullpath) - printf(_("p_name = \"%s%s\"\n"), mntpt, parent->p_name); - else - printf(_("p_name = \"%s\"\n"), parent->p_name); + printf("%s\n", buf); + return 0; } static int -parent_list(int fullpath) +print_paths( + struct xfs_handle *handle) { - void *handlep = NULL; - size_t handlen; - int error, i; - int retval = 1; - __u32 count; - parent_t *entryp; - parent_t *parentbuf = NULL; - char *path = file->name; - int pb_size = PARENTBUF_SZ; + int ret; - /* XXXX for linux libhandle version - to set libhandle fsfd cache */ - { - void *fshandle; - size_t fshlen; - - if (path_to_fshandle(mntpt, &fshandle, &fshlen) != 0) { - fprintf(stderr, _("%s: failed path_to_fshandle \"%s\": %s\n"), - progname, path, strerror(errno)); - goto error; - } - free_handle(fshandle, fshlen); - } - - if (path_to_handle(path, &handlep, &handlen) != 0) { - fprintf(stderr, _("%s: path_to_handle failed for \"%s\"\n"), progname, path); - goto error; - } - - do { - parentbuf = (parent_t *)realloc(parentbuf, pb_size); - if (!parentbuf) { - fprintf(stderr, _("%s: unable to allocate parent buffer: %s\n"), - progname, strerror(errno)); - goto error; - } - - if (fullpath) { - error = parentpaths_by_handle(handlep, - handlen, - parentbuf, - pb_size, - &count); - } else { - error = parents_by_handle(handlep, - handlen, - parentbuf, - pb_size, - &count); - } - if (error == ERANGE) { - pb_size *= 2; - } else if (error) { - fprintf(stderr, _("%s: %s call failed for \"%s\": %s\n"), - progname, fullpath ? "parentpaths" : "parents", - path, strerror(errno)); - goto error; - } - } while (error == ERANGE); - - if (count == 0) { - /* no links for inode - something wrong here */ - fprintf(stderr, _("%s: inode-path is missing\n"), progname); - goto error; - } - - entryp = parentbuf; - for (i = 0; i < count; i++) { - print_parent_entry(entryp, fullpath); - entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen); - } - - retval = 0; -error: - free(handlep); - free(parentbuf); - return retval; + if (handle) + ret = handle_walk_parent_paths(handle, sizeof(*handle), + path_print, NULL); + else + ret = fd_walk_parent_paths(file->fd, path_print, NULL); + if (ret) + fprintf(stderr, "%s: %s\n", file->name, strerror(ret)); + return 0; } static int -parent_f(int argc, char **argv) +parent_f( + int argc, + char **argv) { - int c; - int listpath_flag = 0; - int check_flag = 0; - fs_path_t *fs; - static int tab_init; + struct xfs_handle handle; + void *hanp = NULL; + size_t hlen; + struct fs_path *fs; + char *p; + uint64_t ino = 0; + uint32_t gen = 0; + int c; + int listpath_flag = 0; + int ret; + static int tab_init; if (!tab_init) { tab_init = 1; @@ -380,46 +127,74 @@ parent_f(int argc, char **argv) } mntpt = fs->fs_dir; - verbose_flag = 0; - - while ((c = getopt(argc, argv, "cpv")) != EOF) { + while ((c = getopt(argc, argv, "p")) != EOF) { switch (c) { - case 'c': - check_flag = 1; - break; case 'p': listpath_flag = 1; break; - case 'v': - verbose_flag++; - break; default: return command_usage(&parent_cmd); } } - if (!check_flag && !listpath_flag) /* default case */ - exitcode = parent_list(listpath_flag); - else { - if (listpath_flag) - exitcode = parent_list(listpath_flag); - if (check_flag) - exitcode = parent_check(); + /* + * Always initialize the fshandle table because we need it for + * the ppaths functions to work. + */ + ret = path_to_fshandle((char *)mntpt, &hanp, &hlen); + if (ret) { + perror(mntpt); + return 0; } + if (optind + 2 == argc) { + ino = strtoull(argv[optind], &p, 0); + if (*p != '\0' || ino == 0) { + fprintf(stderr, + _("Bad inode number '%s'.\n"), + argv[optind]); + return 0; + } + gen = strtoul(argv[optind + 1], &p, 0); + if (*p != '\0') { + fprintf(stderr, + _("Bad generation number '%s'.\n"), + argv[optind + 1]); + return 0; + } + + memcpy(&handle, hanp, sizeof(handle)); + handle.ha_fid.fid_len = sizeof(xfs_fid_t) - + sizeof(handle.ha_fid.fid_len); + handle.ha_fid.fid_pad = 0; + handle.ha_fid.fid_ino = ino; + handle.ha_fid.fid_gen = gen; + + } else if (optind != argc) { + return command_usage(&parent_cmd); + } + + if (listpath_flag) + exitcode = print_paths(ino ? &handle : NULL); + else + exitcode = print_parents(ino ? &handle : NULL); + + if (hanp) + free_handle(hanp, hlen); + return 0; } static void parent_help(void) { - printf(_( +printf(_( "\n" " list the current file's parents and their filenames\n" "\n" -" -c -- check the current file's file system for parent consistency\n" -" -p -- list the current file's parents and their full paths\n" -" -v -- verbose mode\n" +" -p -- list the current file's paths up to the root\n" +"\n" +"If ino and gen are supplied, use them instead.\n" "\n")); } @@ -430,11 +205,10 @@ parent_init(void) parent_cmd.cfunc = parent_f; parent_cmd.argmin = 0; parent_cmd.argmax = -1; - parent_cmd.args = _("[-cpv]"); + parent_cmd.args = _("[-p] [ino gen]"); parent_cmd.flags = CMD_NOMAP_OK; - parent_cmd.oneline = _("print or check parent inodes"); + parent_cmd.oneline = _("print parent inodes"); parent_cmd.help = parent_help; - if (expert) - add_command(&parent_cmd); + add_command(&parent_cmd); } diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8 index ac214ab4405..8b2ad588ebc 100644 --- a/man/man8/xfs_io.8 +++ b/man/man8/xfs_io.8 @@ -1013,25 +1013,26 @@ and options behave as described above, in .B chproj. .TP -.BR parent " [ " \-cpv " ]" +.BR parent " [ " \-p " ] [" " ino gen " "]" By default this command prints out the parent inode numbers, inode generation numbers and basenames of all the hardlinks which point to the inode of the current file. + +If the optional +.B ino +and +.B gen +parameters are provided, they will be used to create a file handle on the same +filesystem as the open file. +The parents of the file represented by the handle will be reported instead of +the open file. + .RS 1.0i .PD 0 .TP 0.4i .B \-p the output is similar to the default output except pathnames up to the mount-point are printed out instead of the component name. -.TP -.B \-c -the file's filesystem will check all the parent attributes for consistency. -.TP -.B \-v -verbose output will be printed. -.RE -.IP -.B [NOTE: Not currently operational on Linux.] .RE .PD .TP From patchwork Fri May 26 02:26:31 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: 13256319 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 3BA12C77B7E for ; Fri, 26 May 2023 02:26:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234575AbjEZC0f (ORCPT ); Thu, 25 May 2023 22:26:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230099AbjEZC0e (ORCPT ); Thu, 25 May 2023 22:26:34 -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 19E67B2 for ; Thu, 25 May 2023 19:26:33 -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 A3A7B64C4C for ; Fri, 26 May 2023 02:26:32 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0B6E0C433D2; Fri, 26 May 2023 02:26:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685067992; bh=B3egwM7GlJVDCiUAozeNem6XHbsksUwzx0LIvWM/7v0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=QQfUKHToGC5ukYLAa1ph5P4I9ryGC3Klz0WKrtTt5iVC10I/MYBHY8IhsEAYj9ENv CeQWpqvrDs2j5/fvvtrgZA/zaesG3uVEonL7+yLKckL+J+r8Sd40qDBhE/0xh8/p2V Y8P8BPFebtNCJ0QE3713fox8SMC7/qHavGZLE7s9DmDQCCc+YPhyROB0K87yYeV0XG FTvDt6eZ493ydVEt05n/6Wn1a18AYq/n7QyXve/YQmX8xpvOsbmvrF9N9fmfja1WDd jTq3p/wx+VefVcOxnCZEvzpkHaSG3ZAaBBWcqp7QKyQNK67wDb+htR5rnK+TZsgH44 /yAT9RqofRMIg== Date: Thu, 25 May 2023 19:26:31 -0700 Subject: [PATCH 18/30] xfs_io: Add i, n and f flags to parent command From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078132.3749421.10237359376930581514.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 This patch adds the flags i, n, and f to the parent command. These flags add filtering options that are used by the new parent pointer tests in xfstests, and help to improve the test run time. The flags are: -i: Only show parent pointer records containing the given inode -n: Only show parent pointer records containing the given filename -f: Print records in short format: ino/gen/namelen/name Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: adapt to new getparents ioctl] Signed-off-by: Darrick J. Wong --- io/parent.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++------ man/man8/xfs_io.8 | 11 ++++++- 2 files changed, 89 insertions(+), 11 deletions(-) diff --git a/io/parent.c b/io/parent.c index 65fd892bffc..6bb7571e1bd 100644 --- a/io/parent.c +++ b/io/parent.c @@ -15,11 +15,18 @@ static cmdinfo_t parent_cmd; static char *mntpt; +struct pptr_args { + uint64_t filter_ino; + char *filter_name; + bool shortformat; +}; + static int pptr_print( const struct parent_rec *rec, void *arg) { + struct pptr_args *args = arg; const char *name = (char *)rec->p_name; unsigned int namelen; @@ -28,7 +35,22 @@ pptr_print( return 0; } + if (args->filter_ino && rec->p_ino != args->filter_ino) + return 0; + if (args->filter_name && strcmp(args->filter_name, name)) + return 0; + namelen = strlen(name); + + if (args->shortformat) { + printf("%llu/%u/%u/%s\n", + (unsigned long long)rec->p_ino, + (unsigned int)rec->p_gen, + namelen, + rec->p_name); + return 0; + } + printf(_("p_ino = %llu\n"), (unsigned long long)rec->p_ino); printf(_("p_gen = %u\n"), (unsigned int)rec->p_gen); printf(_("p_namelen = %u\n"), namelen); @@ -39,32 +61,55 @@ pptr_print( static int print_parents( - struct xfs_handle *handle) + struct xfs_handle *handle, + struct pptr_args *args) { int ret; if (handle) ret = handle_walk_parents(handle, sizeof(*handle), pptr_print, - NULL); + args); else - ret = fd_walk_parents(file->fd, pptr_print, NULL); + ret = fd_walk_parents(file->fd, pptr_print, args); if (ret) fprintf(stderr, "%s: %s\n", file->name, strerror(ret)); return 0; } +static int +filter_path_components( + const char *name, + uint64_t ino, + void *arg) +{ + struct pptr_args *args = arg; + + if (args->filter_ino && ino == args->filter_ino) + return ECANCELED; + if (args->filter_name && !strcmp(args->filter_name, name)) + return ECANCELED; + return 0; +} + static int path_print( const char *mntpt, const struct path_list *path, void *arg) { + struct pptr_args *args = arg; char buf[PATH_MAX]; size_t len = PATH_MAX; int mntpt_len = strlen(mntpt); int ret; + if (args->filter_ino || args->filter_name) { + ret = path_walk_components(path, filter_path_components, args); + if (ret != ECANCELED) + return 0; + } + /* Trim trailing slashes from the mountpoint */ while (mntpt_len > 0 && mntpt[mntpt_len - 1] == '/') mntpt_len--; @@ -83,15 +128,16 @@ path_print( static int print_paths( - struct xfs_handle *handle) + struct xfs_handle *handle, + struct pptr_args *args) { int ret; if (handle) ret = handle_walk_parent_paths(handle, sizeof(*handle), - path_print, NULL); + path_print, args); else - ret = fd_walk_parent_paths(file->fd, path_print, NULL); + ret = fd_walk_parent_paths(file->fd, path_print, args); if (ret) fprintf(stderr, "%s: %s\n", file->name, strerror(ret)); return 0; @@ -103,6 +149,7 @@ parent_f( char **argv) { struct xfs_handle handle; + struct pptr_args args = { 0 }; void *hanp = NULL; size_t hlen; struct fs_path *fs; @@ -127,11 +174,27 @@ parent_f( } mntpt = fs->fs_dir; - while ((c = getopt(argc, argv, "p")) != EOF) { + while ((c = getopt(argc, argv, "pfi:n:")) != EOF) { switch (c) { case 'p': listpath_flag = 1; break; + case 'i': + args.filter_ino = strtoull(optarg, &p, 0); + if (*p != '\0' || args.filter_ino == 0) { + fprintf(stderr, + _("Bad inode number '%s'.\n"), + optarg); + return 0; + } + + break; + case 'n': + args.filter_name = optarg; + break; + case 'f': + args.shortformat = true; + break; default: return command_usage(&parent_cmd); } @@ -175,9 +238,9 @@ parent_f( } if (listpath_flag) - exitcode = print_paths(ino ? &handle : NULL); + exitcode = print_paths(ino ? &handle : NULL, &args); else - exitcode = print_parents(ino ? &handle : NULL); + exitcode = print_parents(ino ? &handle : NULL, &args); if (hanp) free_handle(hanp, hlen); @@ -195,6 +258,12 @@ printf(_( " -p -- list the current file's paths up to the root\n" "\n" "If ino and gen are supplied, use them instead.\n" +"\n" +" -i -- Only show parent pointer records containing the given inode\n" +"\n" +" -n -- Only show parent pointer records containing the given filename\n" +"\n" +" -f -- Print records in short format: ino/gen/namelen/filename\n" "\n")); } @@ -205,7 +274,7 @@ parent_init(void) parent_cmd.cfunc = parent_f; parent_cmd.argmin = 0; parent_cmd.argmax = -1; - parent_cmd.args = _("[-p] [ino gen]"); + parent_cmd.args = _("[-p] [ino gen] [-i ino] [-n name] [-f]"); parent_cmd.flags = CMD_NOMAP_OK; parent_cmd.oneline = _("print parent inodes"); parent_cmd.help = parent_help; diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8 index 8b2ad588ebc..c8ccf6ddce4 100644 --- a/man/man8/xfs_io.8 +++ b/man/man8/xfs_io.8 @@ -1013,7 +1013,7 @@ and options behave as described above, in .B chproj. .TP -.BR parent " [ " \-p " ] [" " ino gen " "]" +.BR parent " [ " \-fp " ] [-i " ino "] [-n " name "] [" " ino gen " "]" By default this command prints out the parent inode numbers, inode generation numbers and basenames of all the hardlinks which point to the inode of the current file. @@ -1030,6 +1030,15 @@ the open file. .RS 1.0i .PD 0 .TP 0.4i +.B \-f +Print records in short format: ino/gen/namelen/name +.TP 0.4i +.B \-i +Only show parent pointer records containing this inode number. +.TP 0.4i +.B \-n +Only show parent pointer records containing this directory entry name. +.TP 0.4i .B \-p the output is similar to the default output except pathnames up to the mount-point are printed out instead of the component name. From patchwork Fri May 26 02:26:47 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: 13256320 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 50105C77B7A for ; Fri, 26 May 2023 02:26:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234667AbjEZC0x (ORCPT ); Thu, 25 May 2023 22:26:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53572 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230099AbjEZC0w (ORCPT ); Thu, 25 May 2023 22:26:52 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AA0F9B6 for ; Thu, 25 May 2023 19:26:48 -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 41C8464C56 for ; Fri, 26 May 2023 02:26:48 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A5C1CC433D2; Fri, 26 May 2023 02:26:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068007; bh=tz7htGd6tRE71q8K3RXBsHEqT1fbKe9Jilh1tSS4YpI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ItLAKqDUxBY3xKTSS7wyfLOe88thaG1kK/usUT3ykQmtvwEvNzyI3jRLI4Y5uUEON geIISWEq7hvH0jaU9HtNxwHBnPK3x9FyZIcXMaZnR9wEO6aQuKKciwYiWAqeXnbNfj YbNkDmqDnC5PqW25D7mzkAOGu3po/5v1vnG4Gp6WtaOgDRL1SwwxbP8sX4nZLxdIAg DjjnupJF3x3i08LCNrSJGDl4guybsdwsygzi7AA8qMiLDn3dDbgi/TbZ3NhP5uLVju dN7Ycwf+SQd2y6O3UDG7royQFkNckxsxkwOe3IbFMnO+uZNGyuMfcGX6gjDe7ZKVcf BSfP3qnDDAREA== Date: Thu, 25 May 2023 19:26:47 -0700 Subject: [PATCH 19/30] xfs_logprint: decode parent pointers in ATTRI items fully From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078146.3749421.7281608739028648669.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 This patch modifies the ATTRI print routines to look for the parent pointer flag, and decode logged parent pointers fully when dumping log contents. Between the existing ATTRI: printouts and the new ones introduced here, we can figure out what was stored in each log iovec, as well as the higher level parent pointer that was logged. Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: adjust to new ondisk format] Signed-off-by: Darrick J. Wong --- libxfs/libxfs_api_defs.h | 4 ++ logprint/log_redo.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index de653b2656a..70db72b0a37 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -174,6 +174,10 @@ #define xfs_log_sb libxfs_log_sb #define xfs_mode_to_ftype libxfs_mode_to_ftype #define xfs_mkdir_space_res libxfs_mkdir_space_res +#define xfs_parent_add libxfs_parent_add +#define xfs_parent_finish libxfs_parent_finish +#define xfs_parent_irec_from_disk libxfs_parent_irec_from_disk +#define xfs_parent_start libxfs_parent_start #define xfs_perag_get libxfs_perag_get #define xfs_perag_put libxfs_perag_put #define xfs_prealloc_blocks libxfs_prealloc_blocks diff --git a/logprint/log_redo.c b/logprint/log_redo.c index e6401bb293e..948924d5bcb 100644 --- a/logprint/log_redo.c +++ b/logprint/log_redo.c @@ -674,6 +674,59 @@ xfs_attri_copy_log_format( return 1; } +static void +dump_pptr( + const char *tag, + const void *name_ptr, + unsigned int name_len, + const void *value_ptr, + unsigned int value_len) +{ + struct xfs_parent_name_irec irec; + + if (name_len < sizeof(struct xfs_parent_name_rec)) { + printf("PPTR: %s CORRUPT\n", tag); + return; + } + + libxfs_parent_irec_from_disk(&irec, name_ptr, value_ptr, value_len); + + printf("PPTR: %s attr_namelen %u attr_valuelen %u\n", tag, name_len, value_len); + printf("PPTR: %s parent_ino %llu parent_gen %u namehash 0x%x namelen %u name '%.*s'\n", + tag, + (unsigned long long)irec.p_ino, + irec.p_gen, + irec.p_namehash, + irec.p_namelen, + irec.p_namelen, + irec.p_name); +} + +static void +dump_pptr_update( + const void *name_ptr, + unsigned int name_len, + const void *new_name_ptr, + unsigned int new_name_len, + const void *value_ptr, + unsigned int value_len, + const void *new_value_ptr, + unsigned int new_value_len) +{ + if (new_name_ptr && name_ptr) { + dump_pptr("OLDNAME", name_ptr, name_len, value_ptr, value_len); + dump_pptr("NEWNAME", new_name_ptr, new_name_len, new_value_ptr, + new_value_len); + return; + } + + if (name_ptr) + dump_pptr("NAME", name_ptr, name_len, value_ptr, value_len); + if (new_name_ptr) + dump_pptr("NEWNAME", new_name_ptr, new_name_len, new_value_ptr, + new_value_len); +} + static inline unsigned int xfs_attr_log_item_op(const struct xfs_attri_log_format *attrp) { @@ -688,6 +741,10 @@ xlog_print_trans_attri( { struct xfs_attri_log_format *src_f = NULL; xlog_op_header_t *head = NULL; + void *name_ptr = NULL; + void *new_name_ptr = NULL; + void *value_ptr = NULL; + void *new_value_ptr = NULL; uint dst_len; unsigned int name_len = 0; unsigned int new_name_len = 0; @@ -741,6 +798,7 @@ xlog_print_trans_attri( (*i)++; head = (xlog_op_header_t *)*ptr; xlog_print_op_header(head, *i, ptr); + name_ptr = *ptr; error = xlog_print_trans_attri_name(ptr, be32_to_cpu(head->oh_len), "name"); if (error) @@ -752,6 +810,7 @@ xlog_print_trans_attri( (*i)++; head = (xlog_op_header_t *)*ptr; xlog_print_op_header(head, *i, ptr); + new_name_ptr = *ptr; error = xlog_print_trans_attri_name(ptr, be32_to_cpu(head->oh_len), "newname"); if (error) @@ -763,6 +822,7 @@ xlog_print_trans_attri( (*i)++; head = (xlog_op_header_t *)*ptr; xlog_print_op_header(head, *i, ptr); + value_ptr = *ptr; error = xlog_print_trans_attri_value(ptr, be32_to_cpu(head->oh_len), value_len, "value"); if (error) @@ -774,12 +834,19 @@ xlog_print_trans_attri( (*i)++; head = (xlog_op_header_t *)*ptr; xlog_print_op_header(head, *i, ptr); + new_value_ptr = *ptr; error = xlog_print_trans_attri_value(ptr, be32_to_cpu(head->oh_len), new_value_len, "newvalue"); if (error) goto error; } + + if (src_f->alfi_attr_filter & XFS_ATTR_PARENT) + dump_pptr_update(name_ptr, name_len, + new_name_ptr, new_name_len, + value_ptr, value_len, + new_value_ptr, new_value_len); error: free(src_f); @@ -822,6 +889,10 @@ xlog_recover_print_attri( struct xlog_recover_item *item) { struct xfs_attri_log_format *f, *src_f = NULL; + void *name_ptr = NULL; + void *new_name_ptr = NULL; + void *value_ptr = NULL; + void *new_value_ptr = NULL; uint src_len, dst_len; unsigned int name_len = 0; unsigned int new_name_len = 0; @@ -872,6 +943,7 @@ xlog_recover_print_attri( printf(_("ATTRI: name len:%u\n"), name_len); print_or_dump((char *)item->ri_buf[region].i_addr, name_len); + name_ptr = item->ri_buf[region].i_addr; } if (new_name_len > 0) { @@ -879,6 +951,7 @@ xlog_recover_print_attri( printf(_("ATTRI: newname len:%u\n"), new_name_len); print_or_dump((char *)item->ri_buf[region].i_addr, new_name_len); + new_name_ptr = item->ri_buf[region].i_addr; } if (value_len > 0) { @@ -887,6 +960,7 @@ xlog_recover_print_attri( region++; printf(_("ATTRI: value len:%u\n"), value_len); print_or_dump((char *)item->ri_buf[region].i_addr, len); + value_ptr = item->ri_buf[region].i_addr; } if (new_value_len > 0) { @@ -895,8 +969,15 @@ xlog_recover_print_attri( region++; printf(_("ATTRI: newvalue len:%u\n"), new_value_len); print_or_dump((char *)item->ri_buf[region].i_addr, len); + new_value_ptr = item->ri_buf[region].i_addr; } + if (src_f->alfi_attr_filter & XFS_ATTR_PARENT) + dump_pptr_update(name_ptr, name_len, + new_name_ptr, new_name_len, + value_ptr, value_len, + new_value_ptr, new_value_len); + out: free(f); From patchwork Fri May 26 02:27: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: 13256321 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 0F53FC77B7A for ; Fri, 26 May 2023 02:27:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229865AbjEZC1G (ORCPT ); Thu, 25 May 2023 22:27:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53606 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229689AbjEZC1F (ORCPT ); Thu, 25 May 2023 22:27:05 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 30067BC for ; Thu, 25 May 2023 19:27:04 -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 BE90064B7B for ; Fri, 26 May 2023 02:27:03 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2AB4FC433D2; Fri, 26 May 2023 02:27:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068023; bh=U7z4y8T9+1Rw1IMDc5zOon910TJ8rIpcBRVdZFBHi7w=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=BoQvKt1tW/c6557+NOd1+6PoTOQIpToFuifUzKLLFbRTB6m0GJfx59eL+N9AkYRzy AAIrg9IujDZpLJHpOngAjcyomec535SmldccXfsSGqGgP35LHkqhhsHj3EP3BTAVad RUMKJUoHZy4618a/Sfi/OvzBL2H652b2U3DYzAXFJIDzmzhAx0r4CjskfUMLReC5E7 gLQ3mpJGZ/EcrH1Vpw/34vx7rP3mjziJkx6iXd7fEe99VHe75dvkPiDfsA5HNgbID1 VK9gpIrJtU0bVoLAKunvCVAY33T0euTrWB4xTuY5QpCs0v+9o1rBma/ob5PgaJyOhP VaFnMPk+UBb4Q== Date: Thu, 25 May 2023 19:27:02 -0700 Subject: [PATCH 20/30] xfs_spaceman: report file paths From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078160.3749421.15510849733955957305.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Teach the health command to report file paths when possible. Signed-off-by: Darrick J. Wong --- man/man8/xfs_spaceman.8 | 7 +++++- spaceman/Makefile | 4 ++-- spaceman/file.c | 7 ++++++ spaceman/health.c | 53 ++++++++++++++++++++++++++++++++++++++--------- spaceman/space.h | 3 +++ 5 files changed, 61 insertions(+), 13 deletions(-) diff --git a/man/man8/xfs_spaceman.8 b/man/man8/xfs_spaceman.8 index ece840d7300..0d299132a78 100644 --- a/man/man8/xfs_spaceman.8 +++ b/man/man8/xfs_spaceman.8 @@ -91,7 +91,7 @@ The output will have the same format that .BR "xfs_info" "(8)" prints when querying a filesystem. .TP -.BI "health [ \-a agno] [ \-c ] [ \-f ] [ \-i inum ] [ \-q ] [ paths ]" +.BI "health [ \-a agno] [ \-c ] [ \-f ] [ \-i inum ] [ \-n ] [ \-q ] [ paths ]" Reports the health of the given group of filesystem metadata. .RS 1.0i .PD 0 @@ -111,6 +111,11 @@ Report on the health of metadata that affect the entire filesystem. .B \-i inum Report on the health of a specific inode. .TP +.B \-n +When reporting on the health of a file, try to report the full file path, +if possible. +This option is disabled by default to minimize runtime. +.TP .B \-q Report only unhealthy metadata. .TP diff --git a/spaceman/Makefile b/spaceman/Makefile index 1f048d54a4d..d6fccc361cf 100644 --- a/spaceman/Makefile +++ b/spaceman/Makefile @@ -10,8 +10,8 @@ HFILES = init.h space.h CFILES = info.c init.c file.c health.c prealloc.c trim.c LSRCFILES = xfs_info.sh -LLDLIBS = $(LIBXCMD) $(LIBFROG) -LTDEPENDENCIES = $(LIBXCMD) $(LIBFROG) +LLDLIBS = $(LIBHANDLE) $(LIBXCMD) $(LIBFROG) +LTDEPENDENCIES = $(LIBHANDLE) $(LIBXCMD) $(LIBFROG) LLDFLAGS = -static ifeq ($(ENABLE_EDITLINE),yes) diff --git a/spaceman/file.c b/spaceman/file.c index eec7ee9f4ba..850688ace15 100644 --- a/spaceman/file.c +++ b/spaceman/file.c @@ -14,6 +14,7 @@ #include "libfrog/paths.h" #include "libfrog/fsgeom.h" #include "space.h" +#include "handle.h" static cmdinfo_t print_cmd; @@ -106,6 +107,12 @@ addfile( file->name = filename; memcpy(&file->xfd, xfd, sizeof(struct xfs_fd)); memcpy(&file->fs_path, fs_path, sizeof(file->fs_path)); + + /* Try to capture a fs handle for reporting paths. */ + file->fshandle = NULL; + file->fshandle_len = 0; + path_to_fshandle(filename, &file->fshandle, &file->fshandle_len); + return 0; } diff --git a/spaceman/health.c b/spaceman/health.c index 12fb67bab28..ab5bc074988 100644 --- a/spaceman/health.c +++ b/spaceman/health.c @@ -13,11 +13,13 @@ #include "libfrog/fsgeom.h" #include "libfrog/bulkstat.h" #include "space.h" +#include "libfrog/getparents.h" static cmdinfo_t health_cmd; static unsigned long long reported; static bool comprehensive; static bool quiet; +static bool report_paths; static bool has_realtime(const struct xfs_fsop_geom *g) { @@ -269,6 +271,38 @@ report_file_health( #define BULKSTAT_NR (128) +static void +report_inode( + const struct xfs_bulkstat *bs) +{ + char descr[PATH_MAX]; + int ret; + + if (report_paths && file->fshandle && + (file->xfd.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_PARENT)) { + struct xfs_handle handle; + + memcpy(&handle.ha_fsid, file->fshandle, sizeof(handle.ha_fsid)); + handle.ha_fid.fid_len = sizeof(xfs_fid_t) - + sizeof(handle.ha_fid.fid_len); + handle.ha_fid.fid_pad = 0; + handle.ha_fid.fid_ino = bs->bs_ino; + handle.ha_fid.fid_gen = bs->bs_gen; + + ret = handle_to_path(&handle, sizeof(struct xfs_handle), descr, + sizeof(descr) - 1); + if (ret) + goto report_inum; + + goto report_status; + } + +report_inum: + snprintf(descr, sizeof(descr) - 1, _("inode %"PRIu64), bs->bs_ino); +report_status: + report_sick(descr, inode_flags, bs->bs_sick, bs->bs_checked); +} + /* * Report on all files' health for a given @agno. If @agno is NULLAGNUMBER, * report on all files in the filesystem. @@ -278,7 +312,6 @@ report_bulkstat_health( xfs_agnumber_t agno) { struct xfs_bulkstat_req *breq; - char descr[256]; uint32_t i; int error; @@ -296,13 +329,8 @@ report_bulkstat_health( error = -xfrog_bulkstat(&file->xfd, breq); if (error) break; - for (i = 0; i < breq->hdr.ocount; i++) { - snprintf(descr, sizeof(descr) - 1, _("inode %"PRIu64), - breq->bulkstat[i].bs_ino); - report_sick(descr, inode_flags, - breq->bulkstat[i].bs_sick, - breq->bulkstat[i].bs_checked); - } + for (i = 0; i < breq->hdr.ocount; i++) + report_inode(&breq->bulkstat[i]); } while (breq->hdr.ocount > 0); if (error) @@ -312,7 +340,7 @@ report_bulkstat_health( return error; } -#define OPT_STRING ("a:cfi:q") +#define OPT_STRING ("a:cfi:nq") /* Report on health problems in XFS filesystem. */ static int @@ -327,6 +355,7 @@ health_f( int ret; reported = 0; + report_paths = false; if (file->xfd.fsgeom.version != XFS_FSOP_GEOM_VERSION_V5) { perror("health"); @@ -362,6 +391,9 @@ health_f( return 1; } break; + case 'n': + report_paths = true; + break; case 'q': quiet = true; break; @@ -449,6 +481,7 @@ health_help(void) " -c -- Report on the health of all inodes.\n" " -f -- Report health of the overall filesystem.\n" " -i inum -- Report health of a given inode number.\n" +" -n -- Try to report file names.\n" " -q -- Only report unhealthy metadata.\n" " paths -- Report health of the given file path.\n" "\n")); @@ -460,7 +493,7 @@ static cmdinfo_t health_cmd = { .cfunc = health_f, .argmin = 0, .argmax = -1, - .args = "[-a agno] [-c] [-f] [-i inum] [-q] [paths]", + .args = "[-a agno] [-c] [-f] [-i inum] [-n] [-q] [paths]", .flags = CMD_FLAG_ONESHOT, .help = health_help, }; diff --git a/spaceman/space.h b/spaceman/space.h index 723209edd99..28fa35a3047 100644 --- a/spaceman/space.h +++ b/spaceman/space.h @@ -10,6 +10,9 @@ struct fileio { struct xfs_fd xfd; /* XFS runtime support context */ struct fs_path fs_path; /* XFS path information */ char *name; /* file name at time of open */ + + void *fshandle; + size_t fshandle_len; }; extern struct fileio *filetable; /* open file table */ From patchwork Fri May 26 02:27:18 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: 13256322 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 662B2C7EE2E for ; Fri, 26 May 2023 02:27:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235092AbjEZC1X (ORCPT ); Thu, 25 May 2023 22:27:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53632 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234739AbjEZC1U (ORCPT ); Thu, 25 May 2023 22:27:20 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C351EB6 for ; Thu, 25 May 2023 19:27: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 4C9C064C57 for ; Fri, 26 May 2023 02:27:19 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AA6A2C433D2; Fri, 26 May 2023 02:27:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068038; bh=U6Wvbr0mdCHckgOsQ426C60BTt+nws8WM0wXulPw1j4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=n2W6focVgSvV4O0q6S6rIp/U854RdqBm0tD2Lc1jk3pRSjUi3LuH92q/c7QDtt+P2 +xsyVwrfpy5Ij8ZECUIgw1ksBdOLNGfil3lp0Lspv3af/wmEny3ub19E7CNFpoUbdd enhAOTitbFS19pXYMeFRund0T/ukzmkkBxUdEh1HhgnIB+8O0jzUDiXy298VkUxxG0 9m6/O1SFWxEiuE2yR9F9vzsbzUhDmfDRzOUHv9IXIK4eCNrkCFA0Vl8S1RBUjvnobU zZJjCbP6hbppGmMapiSPHltxhOyR1Hg+ReSA/n3A38QtNxwqymFggXhGrFsBVMg5dW wRNLBZbWnlDRg== Date: Thu, 25 May 2023 19:27:18 -0700 Subject: [PATCH 21/30] xfs_scrub: use parent pointers when possible to report file operations From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078173.3749421.6504474976701985673.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 parent pointers are available, use them to supply file paths when doing things to files, instead of merely printing the inode number. Signed-off-by: Darrick J. Wong --- scrub/common.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/scrub/common.c b/scrub/common.c index f38829ea253..ae22bbd1775 100644 --- a/scrub/common.c +++ b/scrub/common.c @@ -9,6 +9,7 @@ #include #include "platform_defs.h" #include "libfrog/paths.h" +#include "libfrog/getparents.h" #include "xfs_scrub.h" #include "common.h" #include "progress.h" @@ -403,19 +404,55 @@ scrub_render_ino_descr( ...) { va_list args; + size_t pathlen = 0; uint32_t agno; uint32_t agino; int ret; + if (ctx->mnt.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_PARENT) { + struct xfs_handle handle; + + memcpy(&handle.ha_fsid, ctx->fshandle, sizeof(handle.ha_fsid)); + handle.ha_fid.fid_len = sizeof(xfs_fid_t) - + sizeof(handle.ha_fid.fid_len); + handle.ha_fid.fid_pad = 0; + handle.ha_fid.fid_ino = ino; + handle.ha_fid.fid_gen = gen; + + ret = handle_to_path(&handle, sizeof(struct xfs_handle), buf, + buflen); + if (ret) + goto report_inum; + + /* + * Leave at least 16 bytes for the description of what went + * wrong. If we can't do that, we'll use the inode number. + */ + pathlen = strlen(buf); + if (pathlen >= buflen - 16) + goto report_inum; + + if (format) { + buf[pathlen] = ' '; + buf[pathlen + 1] = 0; + pathlen++; + } + + goto report_format; + } + +report_inum: agno = cvt_ino_to_agno(&ctx->mnt, ino); agino = cvt_ino_to_agino(&ctx->mnt, ino); ret = snprintf(buf, buflen, _("inode %"PRIu64" (%"PRIu32"/%"PRIu32")%s"), ino, agno, agino, format ? " " : ""); if (ret < 0 || ret >= buflen || format == NULL) return ret; + pathlen = ret; +report_format: va_start(args, format); - ret += vsnprintf(buf + ret, buflen - ret, format, args); + pathlen += vsnprintf(buf + pathlen, buflen - pathlen, format, args); va_end(args); - return ret; + return pathlen; } From patchwork Fri May 26 02:27: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: 13256323 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 6BA35C77B7E for ; Fri, 26 May 2023 02:27:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233448AbjEZC1g (ORCPT ); Thu, 25 May 2023 22:27:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53834 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235169AbjEZC1g (ORCPT ); Thu, 25 May 2023 22:27:36 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4B66C9B for ; Thu, 25 May 2023 19:27:35 -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 D458064C56 for ; Fri, 26 May 2023 02:27:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4587FC433D2; Fri, 26 May 2023 02:27:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068054; bh=6fLNIenh/+izzgOksenA4UfhR4GURe07oqoTTNmox+c=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=bnuvnnQ6EXTl4dGqMHlFBMv+tA7GMrd/yhyRz7oxg96vnzQyZvCa3PmHSGj6YVjbC o1MUkRlxRUlo8lx6ISoCXYrnVgMj4V96y77C6jUwEYwYwZIWlvr3lvjxGOVczg3eOQ mUGfnbYejgKzrkzqfaIcSxrSRCTJnyxfbfM0e3DgxWeG3JIxfvX1FUBOF7MZX+9wFR a11us3Yafb01GTn3Zs1sKn8HA2DNq2UJVTxhaqEDSlRl//Y8Sh0zwd9YuGiZZ8wwf9 vATZjlPSp/ModxLfl5aLapnWfWEmevrfZuvmO0UK0AwkGJDkaPFZO3gy7gNmH0cPwi wWMtZ5bHMbJ4A== Date: Thu, 25 May 2023 19:27:33 -0700 Subject: [PATCH 22/30] xfs_db: report parent bit on xattrs From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078187.3749421.15484403053645276279.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Display the parent bit on xattr keys Signed-off-by: Darrick J. Wong Reviewed-by: Allison Henderson --- db/attr.c | 3 +++ db/attrshort.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/db/attr.c b/db/attr.c index ba722e146e2..f29e4a54454 100644 --- a/db/attr.c +++ b/db/attr.c @@ -82,6 +82,9 @@ const field_t attr_leaf_entry_flds[] = { { "local", FLDT_UINT1, OI(LEOFF(flags) + bitsz(uint8_t) - XFS_ATTR_LOCAL_BIT - 1), C1, 0, TYP_NONE }, + { "parent", FLDT_UINT1, + OI(LEOFF(flags) + bitsz(uint8_t) - XFS_ATTR_PARENT_BIT - 1), C1, 0, + TYP_NONE }, { "pad2", FLDT_UINT8X, OI(LEOFF(pad2)), C1, FLD_SKIPALL, TYP_NONE }, { NULL } }; diff --git a/db/attrshort.c b/db/attrshort.c index e234fbd8365..872d771d5ed 100644 --- a/db/attrshort.c +++ b/db/attrshort.c @@ -44,6 +44,9 @@ const field_t attr_sf_entry_flds[] = { { "secure", FLDT_UINT1, OI(EOFF(flags) + bitsz(uint8_t) - XFS_ATTR_SECURE_BIT - 1), C1, 0, TYP_NONE }, + { "parent", FLDT_UINT1, + OI(EOFF(flags) + bitsz(uint8_t) - XFS_ATTR_PARENT_BIT - 1), C1, 0, + TYP_NONE }, { "name", FLDT_CHARNS, OI(EOFF(nameval)), attr_sf_entry_name_count, FLD_COUNT, TYP_NONE }, { "value", FLDT_CHARNS, attr_sf_entry_value_offset, From patchwork Fri May 26 02:27:49 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: 13256324 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 6E730C77B7E for ; Fri, 26 May 2023 02:27:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230091AbjEZC1x (ORCPT ); Thu, 25 May 2023 22:27:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54016 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229530AbjEZC1w (ORCPT ); Thu, 25 May 2023 22:27:52 -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 E1C99B6 for ; Thu, 25 May 2023 19:27: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 6956C64C27 for ; Fri, 26 May 2023 02:27:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CA280C433EF; Fri, 26 May 2023 02:27:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068069; bh=MEZDtEHAaTzBfu3pxZnYFoYz7wdnlbra0j+KO0FNyc0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=toy/I0nTT6WJR6hciL9ncdhvvuuFDRsH1Lf+nWzgeaBJM8Snv1QVFFxX0dd7T9StC jgVlM38QULTDuByh2F2OFGOzikK4BcR5NI2eBmzgcR0eU9C+yh9s62+UozOskUcDHK CeXRyio9JxONyoZl7ICSbfkMggIjyxEfWDaovv6C8fbJ0JFzdRfGCSku77cN7oNcA/ JuExNd1kOtrUBcZnFyqgKR6MwgbKZzn1t53lBeNIGO1J2WTQbyZaCKftZVLHqleIqv 7ImCAoQeVF5G7H5nYYE+10fKInzFLj6VgRkyXHivgXPKGbK1/YYTvNuJdcbWAqsipd BgU54xPxSrjew== Date: Thu, 25 May 2023 19:27:49 -0700 Subject: [PATCH 23/30] xfs_db: report parent pointers embedded in xattrs From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078200.3749421.13126733773665454626.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Decode the parent pointer inode, generation, namehash, and name fields if the parent pointer passes basic validation checks. Signed-off-by: Darrick J. Wong --- db/attr.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ db/attrshort.c | 48 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/db/attr.c b/db/attr.c index f29e4a54454..9e7bbd164df 100644 --- a/db/attr.c +++ b/db/attr.c @@ -19,6 +19,8 @@ static int attr_leaf_entries_count(void *obj, int startoff); static int attr_leaf_hdr_count(void *obj, int startoff); static int attr_leaf_name_local_count(void *obj, int startoff); static int attr_leaf_name_local_name_count(void *obj, int startoff); +static int attr_leaf_name_pptr_count(void *obj, int startoff); +static int attr_leaf_name_pptr_namelen(void *obj, int startoff); static int attr_leaf_name_local_value_count(void *obj, int startoff); static int attr_leaf_name_local_value_offset(void *obj, int startoff, int idx); @@ -111,6 +113,8 @@ const field_t attr_leaf_map_flds[] = { #define LNOFF(f) bitize(offsetof(xfs_attr_leaf_name_local_t, f)) #define LVOFF(f) bitize(offsetof(xfs_attr_leaf_name_remote_t, f)) +#define PPOFF(f) bitize(offsetof(xfs_attr_leaf_name_local_t, nameval) + \ + offsetof(struct xfs_parent_name_rec, f)) const field_t attr_leaf_name_flds[] = { { "valuelen", FLDT_UINT16D, OI(LNOFF(valuelen)), attr_leaf_name_local_count, FLD_COUNT, TYP_NONE }, @@ -118,6 +122,14 @@ const field_t attr_leaf_name_flds[] = { attr_leaf_name_local_count, FLD_COUNT, TYP_NONE }, { "name", FLDT_CHARNS, OI(LNOFF(nameval)), attr_leaf_name_local_name_count, FLD_COUNT, TYP_NONE }, + { "parent_ino", FLDT_INO, OI(PPOFF(p_ino)), + attr_leaf_name_pptr_count, FLD_COUNT, TYP_INODE }, + { "parent_gen", FLDT_UINT32D, OI(PPOFF(p_gen)), + attr_leaf_name_pptr_count, FLD_COUNT, TYP_NONE }, + { "parent_namehash", FLDT_UINT32X, OI(PPOFF(p_namehash)), + attr_leaf_name_pptr_count, FLD_COUNT, TYP_NONE }, + { "parent_name", FLDT_CHARNS, attr_leaf_name_local_value_offset, + attr_leaf_name_pptr_namelen, FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "value", FLDT_CHARNS, attr_leaf_name_local_value_offset, attr_leaf_name_local_value_count, FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "valueblk", FLDT_UINT32X, OI(LVOFF(valueblk)), @@ -273,6 +285,26 @@ attr_leaf_name_local_count( __attr_leaf_name_local_count); } +static int +__attr_leaf_name_pptr_count( + struct xfs_attr_leafblock *leaf, + struct xfs_attr_leaf_entry *e, + int i) +{ + if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) == XFS_ATTR_PARENT) + return 1; + return 0; +} + +static int +attr_leaf_name_pptr_count( + void *obj, + int startoff) +{ + return attr_leaf_entry_walk(obj, startoff, + __attr_leaf_name_pptr_count); +} + static int __attr_leaf_name_local_name_count( struct xfs_attr_leafblock *leaf, @@ -283,6 +315,8 @@ __attr_leaf_name_local_name_count( if (!(e->flags & XFS_ATTR_LOCAL)) return 0; + if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) == XFS_ATTR_PARENT) + return 0; l = xfs_attr3_leaf_name_local(leaf, i); return l->namelen; @@ -297,6 +331,32 @@ attr_leaf_name_local_name_count( __attr_leaf_name_local_name_count); } +static int +__attr_leaf_name_pptr_namelen( + struct xfs_attr_leafblock *leaf, + struct xfs_attr_leaf_entry *e, + int i) +{ + struct xfs_attr_leaf_name_local *l; + + if (!(e->flags & XFS_ATTR_LOCAL)) + return 0; + if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) != XFS_ATTR_PARENT) + return 0; + + l = xfs_attr3_leaf_name_local(leaf, i); + return be16_to_cpu(l->valuelen); +} + +static int +attr_leaf_name_pptr_namelen( + void *obj, + int startoff) +{ + return attr_leaf_entry_walk(obj, startoff, + __attr_leaf_name_pptr_namelen); +} + static int __attr_leaf_name_local_value_count( struct xfs_attr_leafblock *leaf, @@ -307,6 +367,8 @@ __attr_leaf_name_local_value_count( if (!(e->flags & XFS_ATTR_LOCAL)) return 0; + if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) == XFS_ATTR_PARENT) + return 0; l = xfs_attr3_leaf_name_local(leaf, i); return be16_to_cpu(l->valuelen); diff --git a/db/attrshort.c b/db/attrshort.c index 872d771d5ed..9cd3411bee4 100644 --- a/db/attrshort.c +++ b/db/attrshort.c @@ -13,6 +13,8 @@ #include "attrshort.h" static int attr_sf_entry_name_count(void *obj, int startoff); +static int attr_sf_entry_pptr_count(void *obj, int startoff); +static int attr_sf_entry_pptr_namelen(void *obj, int startoff); static int attr_sf_entry_value_count(void *obj, int startoff); static int attr_sf_entry_value_offset(void *obj, int startoff, int idx); static int attr_shortform_list_count(void *obj, int startoff); @@ -34,6 +36,8 @@ const field_t attr_sf_hdr_flds[] = { }; #define EOFF(f) bitize(offsetof(struct xfs_attr_sf_entry, f)) +#define PPOFF(f) bitize(offsetof(struct xfs_attr_sf_entry, nameval) + \ + offsetof(struct xfs_parent_name_rec, f)) const field_t attr_sf_entry_flds[] = { { "namelen", FLDT_UINT8D, OI(EOFF(namelen)), C1, 0, TYP_NONE }, { "valuelen", FLDT_UINT8D, OI(EOFF(valuelen)), C1, 0, TYP_NONE }, @@ -49,11 +53,33 @@ const field_t attr_sf_entry_flds[] = { TYP_NONE }, { "name", FLDT_CHARNS, OI(EOFF(nameval)), attr_sf_entry_name_count, FLD_COUNT, TYP_NONE }, + { "parent_ino", FLDT_INO, OI(PPOFF(p_ino)), attr_sf_entry_pptr_count, + FLD_COUNT, TYP_INODE }, + { "parent_gen", FLDT_UINT32D, OI(PPOFF(p_gen)), attr_sf_entry_pptr_count, + FLD_COUNT, TYP_NONE }, + { "parent_namehash", FLDT_UINT32X, OI(PPOFF(p_namehash)), + attr_sf_entry_pptr_count, FLD_COUNT, TYP_NONE }, + { "parent_name", FLDT_CHARNS, attr_sf_entry_value_offset, + attr_sf_entry_pptr_namelen, FLD_COUNT|FLD_OFFSET, TYP_NONE }, { "value", FLDT_CHARNS, attr_sf_entry_value_offset, attr_sf_entry_value_count, FLD_COUNT|FLD_OFFSET, TYP_NONE }, { NULL } }; +static int +attr_sf_entry_pptr_count( + void *obj, + int startoff) +{ + struct xfs_attr_sf_entry *e; + + ASSERT(bitoffs(startoff) == 0); + e = (struct xfs_attr_sf_entry *)((char *)obj + byteize(startoff)); + if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) == XFS_ATTR_PARENT) + return 1; + return 0; +} + static int attr_sf_entry_name_count( void *obj, @@ -63,6 +89,8 @@ attr_sf_entry_name_count( ASSERT(bitoffs(startoff) == 0); e = (struct xfs_attr_sf_entry *)((char *)obj + byteize(startoff)); + if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) == XFS_ATTR_PARENT) + return 0; return e->namelen; } @@ -84,6 +112,22 @@ attr_sf_entry_size( return bitize((int)xfs_attr_sf_entsize(e)); } +static int +attr_sf_entry_pptr_namelen( + void *obj, + int startoff) +{ + struct xfs_attr_sf_entry *e; + + ASSERT(bitoffs(startoff) == 0); + e = (struct xfs_attr_sf_entry *)((char *)obj + byteize(startoff)); + + if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) != XFS_ATTR_PARENT) + return 0; + + return e->valuelen; +} + static int attr_sf_entry_value_count( void *obj, @@ -93,6 +137,10 @@ attr_sf_entry_value_count( ASSERT(bitoffs(startoff) == 0); e = (struct xfs_attr_sf_entry *)((char *)obj + byteize(startoff)); + + if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) == XFS_ATTR_PARENT) + return 0; + return e->valuelen; } From patchwork Fri May 26 02:28: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: 13256325 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 76183C77B7A for ; Fri, 26 May 2023 02:28:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229689AbjEZC2I (ORCPT ); Thu, 25 May 2023 22:28:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54078 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229530AbjEZC2I (ORCPT ); Thu, 25 May 2023 22:28:08 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81985B2 for ; Thu, 25 May 2023 19:28: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 0F19E64C5C for ; Fri, 26 May 2023 02:28:06 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 67218C433EF; Fri, 26 May 2023 02:28:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068085; bh=0vMObdV7obgG+ZT81TUDDT33IfTpxmCWSWZFHuPV6ek=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=JX/gRYbOwvG7bsN9tLa7aE5dJpfppo1AKMNHfS/wjoTSxm4y6ENNyu2QUGw9Q6MJ4 YuQcNZGhnCqtphr6EtMY2/u4CoKLJhX/ifmoquDjh0SMbeXsQRiVjPrA1bms542c8g V73ZQY3fcR265YviuNaJFnYUa1clt6D5LCX3+9OYNOmgpTE2oQUy9zvIBz2KRN5rcp BRLrZWCnREy+3Y8hUN4IOB4YlvPSJASd4Q2jUNNkPVja1S1eNRaQANRhdLXoOXQfIK KWUJvsUdzO2rwfdcaMcbgOFmqwJa6S9FOSTYHfYoriUDzM90YUdLqBapaCN8WEQ4V8 BvSUo0xNFQm7A== Date: Thu, 25 May 2023 19:28:04 -0700 Subject: [PATCH 24/30] xfs_db: obfuscate dirent and parent pointer names consistently From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078214.3749421.36805463282468678.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 When someone wants to perform an obfuscated metadump of a filesystem where parent pointers are enabled, we have to use the *exact* same obfuscated name for both the directory entry and the parent pointer. Create a name remapping table so that when we obfuscate a dirent name or a parent pointer name, we can apply the same obfuscation when we find the corresponding parent pointer or dirent. Signed-off-by: Darrick J. Wong --- db/metadump.c | 314 ++++++++++++++++++++++++++++++++++++++++++++-- libxfs/libxfs_api_defs.h | 2 2 files changed, 305 insertions(+), 11 deletions(-) diff --git a/db/metadump.c b/db/metadump.c index d9a616a9296..9b036c7b5db 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -21,6 +21,14 @@ #include "dir2.h" #include "obfuscate.h" +#undef REMAP_DEBUG + +#ifdef REMAP_DEBUG +# define remap_debug printf +#else +# define remap_debug(...) ((void)0) +#endif + #define DEFAULT_MAX_EXT_SIZE XFS_MAX_BMBT_EXTLEN /* copy all metadata structures to/from a file */ @@ -737,6 +745,111 @@ nametable_add(xfs_dahash_t hash, int namelen, unsigned char *name) return ent; } +/* + * Obfuscated name remapping table for parent pointer-enabled filesystems. + * When this feature is enabled, we have to maintain consistency between the + * names that appears in the dirent and the corresponding parent pointer. + */ + +struct remap_ent { + struct remap_ent *next; + xfs_ino_t dir_ino; + xfs_dahash_t namehash; + uint8_t namelen; + + uint8_t names[]; +}; + +static inline uint8_t *remap_ent_before(struct remap_ent *ent) +{ + return &ent->names[0]; +} + +static inline uint8_t *remap_ent_after(struct remap_ent *ent) +{ + return &ent->names[ent->namelen]; +} + +#define REMAP_TABLE_SIZE 4096 + +static struct remap_ent *remaptable[REMAP_TABLE_SIZE]; + +static void +remaptable_clear(void) +{ + int i; + struct remap_ent *ent, *next; + + for (i = 0; i < REMAP_TABLE_SIZE; i++) { + ent = remaptable[i]; + + while (ent) { + next = ent->next; + free(ent); + ent = next; + } + } +} + +/* Try to find a remapping table entry. */ +static struct remap_ent * +remaptable_find( + xfs_ino_t dir_ino, + xfs_dahash_t namehash, + const unsigned char *name, + unsigned int namelen) +{ + struct remap_ent *ent = remaptable[namehash % REMAP_TABLE_SIZE]; + + remap_debug("REMAP FIND: 0x%lx hash 0x%x '%.*s'\n", + dir_ino, namehash, namelen, name); + + while (ent) { + remap_debug("REMAP ENT: 0x%lx hash 0x%x '%.*s'\n", + ent->dir_ino, ent->namehash, ent->namelen, + remap_ent_before(ent)); + + if (ent->dir_ino == dir_ino && + ent->namehash == namehash && + ent->namelen == namelen && + !memcmp(remap_ent_before(ent), name, namelen)) + return ent; + ent = ent->next; + } + + return NULL; +} + +/* Remember the remapping for a particular dirent that we obfuscated. */ +static struct remap_ent * +remaptable_add( + xfs_ino_t dir_ino, + xfs_dahash_t namehash, + const unsigned char *old_name, + unsigned int namelen, + const unsigned char *new_name) +{ + struct remap_ent *ent; + + ent = malloc(sizeof(struct remap_ent) + (namelen * 2)); + if (!ent) + return NULL; + + ent->dir_ino = dir_ino; + ent->namehash = namehash; + ent->namelen = namelen; + memcpy(remap_ent_before(ent), old_name, namelen); + memcpy(remap_ent_after(ent), new_name, namelen); + ent->next = remaptable[namehash % REMAP_TABLE_SIZE]; + + remaptable[namehash % REMAP_TABLE_SIZE] = ent; + + remap_debug("REMAP ADD: 0x%lx hash 0x%x '%.*s' -> '%.*s'\n", + dir_ino, namehash, namelen, old_name, namelen, + new_name); + return ent; +} + #define ORPHANAGE "lost+found" #define ORPHANAGE_LEN (sizeof (ORPHANAGE) - 1) @@ -861,6 +974,7 @@ generate_obfuscated_name( int namelen, unsigned char *name) { + unsigned char *old_name = NULL; xfs_dahash_t hash; /* @@ -882,8 +996,33 @@ generate_obfuscated_name( name++; /* Obfuscate the name (if possible) */ - hash = dirattr_hashname(ino != 0, name, namelen); + + /* + * If we're obfuscating a dirent name on a pptrs filesystem, see if we + * already processed the parent pointer and use the same name. + */ + if (xfs_has_parent(mp) && ino) { + struct remap_ent *remap; + + remap = remaptable_find(cur_ino, hash, name, namelen); + if (remap) { + remap_debug("found obfuscated dir 0x%lx '%.*s' -> 0x%lx -> '%.*s' \n", + cur_ino, namelen, + remap_ent_before(remap), ino, namelen, + remap_ent_after(remap)); + memcpy(name, remap_ent_after(remap), namelen); + return; + } + + /* + * If we haven't procesed this dirent name before, save the + * old name for a remap table entry. Obfuscate the name. + */ + old_name = alloca(namelen); + memcpy(old_name, name, namelen); + } + obfuscate_name(hash, namelen, name, ino != 0); ASSERT(hash == dirattr_hashname(ino != 0, name, namelen)); @@ -908,6 +1047,23 @@ generate_obfuscated_name( "in dir inode %llu\n", (unsigned long long) ino, (unsigned long long) cur_ino); + + /* + * We've obfuscated a name in the directory entry. Remember this + * remapping for when we come across the parent pointer later. + */ + if (!old_name) + return; + + remap_debug("obfuscating dir 0x%lx '%.*s' -> 0x%lx -> '%.*s' \n", + cur_ino, namelen, old_name, ino, namelen, + name); + + if (!remaptable_add(cur_ino, hash, old_name, namelen, name)) + print_warning("unable to record remapped dirent name for inode %llu " + "in dir inode %llu\n", + (unsigned long long) ino, + (unsigned long long) cur_ino); } static void @@ -1041,6 +1197,123 @@ process_sf_symlink( memset(&buf[len], 0, XFS_DFORK_DSIZE(dip, mp) - len); } +static inline bool +want_obfuscate_pptr( + unsigned int nsp_flags, + const void *name, + unsigned int namelen, + const void *value, + unsigned int valuelen) +{ + if (!obfuscate) + return false; + + /* Ignore if parent pointers aren't enabled. */ + if (!xfs_has_parent(mp)) + return false; + + /* Ignore anything not claiming to be a parent pointer. */ + if (!(nsp_flags & XFS_ATTR_PARENT)) + return false; + + /* Obfuscate this parent pointer if it passes basic checks. */ + if (libxfs_parent_namecheck(mp, name, namelen, nsp_flags) && + libxfs_parent_valuecheck(mp, value, valuelen)) + return true; + + /* Ignore otherwise. */ + return false; +} + +static void +obfuscate_parent_pointer( + const struct xfs_parent_name_rec *rec, + unsigned char *value, + unsigned int valuelen) +{ + struct xfs_parent_name_irec irec; + struct remap_ent *remap; + char *old_name = irec.p_name; + xfs_dahash_t hash; + xfs_ino_t child_ino = cur_ino; + + libxfs_parent_irec_from_disk(&irec, rec, value, valuelen); + + /* + * We don't obfuscate "lost+found" or any orphan files + * therein. If When the name table is used for extended + * attributes, the inode number provided is 0, in which + * case we don't need to make this check. + */ + cur_ino = irec.p_ino; + if (in_lost_found(child_ino, valuelen, value)) { + cur_ino = child_ino; + return; + } + cur_ino = child_ino; + + /* + * If the name starts with a slash, just skip over it. It isn't + * included in the hash and we don't record it in the name table. + */ + if (*value == '/') { + old_name++; + value++; + valuelen--; + } + + hash = libxfs_da_hashname(value, valuelen); + + /* + * If we already processed the dirent, use the same name for the parent + * pointer. + */ + remap = remaptable_find(irec.p_ino, hash, value, valuelen); + if (remap) { + remap_debug("found obfuscated pptr 0x%lx '%.*s' -> 0x%lx -> '%.*s' \n", + irec.p_ino, valuelen, remap_ent_before(remap), + cur_ino, valuelen, remap_ent_after(remap)); + memcpy(value, remap_ent_after(remap), valuelen); + return; + } + + /* + * Obfuscate the parent pointer name and remember this for later + * in case we encounter the dirent and need to reuse the name there. + */ + obfuscate_name(hash, valuelen, value, true); + + remap_debug("obfuscated pptr 0x%lx '%.*s' -> 0x%lx -> '%.*s'\n", + irec.p_ino, valuelen, old_name, cur_ino, valuelen, + value); + if (!remaptable_add(irec.p_ino, hash, old_name, valuelen, value)) + print_warning("unable to record remapped pptr name for inode %llu " + "in dir inode %llu\n", + (unsigned long long) cur_ino, + (unsigned long long) irec.p_ino); +} + +static inline bool +want_obfuscate_attr( + unsigned int nsp_flags, + const void *name, + unsigned int namelen, + const void *value, + unsigned int valuelen) +{ + if (!obfuscate) + return false; + + /* + * If we didn't already obfuscate the parent pointer, it's probably + * corrupt. Leave it intact for analysis. + */ + if (nsp_flags & XFS_ATTR_PARENT) + return false; + + return true; +} + static void process_sf_attr( struct xfs_dinode *dip) @@ -1070,7 +1343,7 @@ process_sf_attr( asfep = &asfp->list[0]; for (i = 0; (i < asfp->hdr.count) && ((char *)asfep - (char *)asfp < ino_attr_size); i++) { - + void *name, *value; int namelen = asfep->namelen; if (namelen == 0) { @@ -1086,11 +1359,16 @@ process_sf_attr( break; } - if (obfuscate) { - generate_obfuscated_name(0, asfep->namelen, - &asfep->nameval[0]); - memset(&asfep->nameval[asfep->namelen], 'v', - asfep->valuelen); + name = &asfep->nameval[0]; + value = &asfep->nameval[asfep->namelen]; + + if (want_obfuscate_pptr(asfep->flags, name, namelen, value, + asfep->valuelen)) { + obfuscate_parent_pointer(name, value, asfep->valuelen); + } else if (want_obfuscate_attr(asfep->flags, name, namelen, + value, asfep->valuelen)) { + generate_obfuscated_name(0, asfep->namelen, name); + memset(value, 'v', asfep->valuelen); } asfep = (struct xfs_attr_sf_entry *)((char *)asfep + @@ -1457,6 +1735,9 @@ process_attr_block( break; } if (entry->flags & XFS_ATTR_LOCAL) { + void *name, *value; + unsigned int valuelen; + local = xfs_attr3_leaf_name_local(leaf, i); if (local->namelen == 0) { if (show_warnings) @@ -1465,11 +1746,21 @@ process_attr_block( (long long)cur_ino); break; } - if (obfuscate) { + + name = &local->nameval[0]; + value = &local->nameval[local->namelen]; + valuelen = be16_to_cpu(local->valuelen); + + if (want_obfuscate_pptr(entry->flags, name, + local->namelen, value, + valuelen)) { + obfuscate_parent_pointer(name, value, valuelen); + } else if (want_obfuscate_attr(entry->flags, name, + local->namelen, value, + valuelen)) { generate_obfuscated_name(0, local->namelen, - &local->nameval[0]); - memset(&local->nameval[local->namelen], 'v', - be16_to_cpu(local->valuelen)); + name); + memset(value, 'v', valuelen); } /* zero from end of nameval[] to next name start */ nlen = local->namelen; @@ -2846,6 +3137,7 @@ metadump_f( pop_cur(); out: free(metablock); + remaptable_clear(); return 0; } diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 70db72b0a37..7779040f0ba 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -178,6 +178,8 @@ #define xfs_parent_finish libxfs_parent_finish #define xfs_parent_irec_from_disk libxfs_parent_irec_from_disk #define xfs_parent_start libxfs_parent_start +#define xfs_parent_namecheck libxfs_parent_namecheck +#define xfs_parent_valuecheck libxfs_parent_valuecheck #define xfs_perag_get libxfs_perag_get #define xfs_perag_put libxfs_perag_put #define xfs_prealloc_blocks libxfs_prealloc_blocks From patchwork Fri May 26 02:28: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: 13256326 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 950BDC77B7A for ; Fri, 26 May 2023 02:28:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229842AbjEZC2X (ORCPT ); Thu, 25 May 2023 22:28:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54176 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229530AbjEZC2X (ORCPT ); Thu, 25 May 2023 22:28:23 -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 2F60DB2 for ; Thu, 25 May 2023 19:28:22 -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 A381764C5C for ; Fri, 26 May 2023 02:28:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0F0E5C433EF; Fri, 26 May 2023 02:28:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068101; bh=ahvvS9EeB9uSJnNm+zUaZt85i9Nh/470VuB/yww1Cp8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=UDgJ/UsXoql92gY4zgQIyzt4DrbnOKDBcL73xq37qw3yzL03Dg+KYDhfraE1IYXRw Xp8/oOlMts1TCA6v4aJeDI3thVYUNsGFSu7/vMIIQC8hF09MVoE0HS9OZmaVlqFWO8 uWwwl7Form+j0XHPLaP4bv1K1dh81Iqq8E8gcYu6W819JrrgxD+yov+3RqCe/FqzlF IhjKU8O9akAdMmgETsatkrskznQcU5mX883jfm73KbhvtEdicJA45cnpoyTGro9lXb 0CujYm/3oPbEuzNUeL5OvjEe3W8mrwvFNpeTS5I7FxP7e0apfSLLSDmb/4AknyYNUs sGmrjCjW3XdWA== Date: Thu, 25 May 2023 19:28:20 -0700 Subject: [PATCH 25/30] libxfs: export attr3_leaf_hdr_from_disk via libxfs_api_defs.h From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078228.3749421.1486690706353918248.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Do the xfs -> libxfs switcheroo and cleanups separately so the next patch doesn't become an even larger mess. Signed-off-by: Darrick J. Wong --- db/attr.c | 2 +- db/metadump.c | 2 +- libxfs/libxfs_api_defs.h | 5 +++++ repair/attr_repair.c | 6 +++--- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/db/attr.c b/db/attr.c index 9e7bbd164df..95969d115d4 100644 --- a/db/attr.c +++ b/db/attr.c @@ -256,7 +256,7 @@ attr_leaf_entry_walk( return 0; off = byteize(startoff); - xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); + libxfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); entries = xfs_attr3_leaf_entryp(leaf); for (i = 0; i < leafhdr.count; i++) { diff --git a/db/metadump.c b/db/metadump.c index 9b036c7b5db..dc0c29ae45e 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -1704,7 +1704,7 @@ process_attr_block( } /* Ok, it's a leaf - get header; accounts for crc & non-crc */ - xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &hdr, leaf); + libxfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &hdr, leaf); nentries = hdr.count; if (nentries == 0 || diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 7779040f0ba..7d1d1ddf624 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -36,7 +36,10 @@ #define xfs_ascii_ci_hashname libxfs_ascii_ci_hashname +#define xfs_attr3_leaf_hdr_from_disk libxfs_attr3_leaf_hdr_from_disk +#define xfs_attr3_leaf_read libxfs_attr3_leaf_read #define xfs_attr_get libxfs_attr_get +#define xfs_attr_is_leaf libxfs_attr_is_leaf #define xfs_attr_leaf_newentsize libxfs_attr_leaf_newentsize #define xfs_attr_namecheck libxfs_attr_namecheck #define xfs_attr_set libxfs_attr_set @@ -89,6 +92,7 @@ #define xfs_calc_dquots_per_chunk libxfs_calc_dquots_per_chunk #define xfs_create_space_res libxfs_create_space_res #define xfs_da3_node_hdr_from_disk libxfs_da3_node_hdr_from_disk +#define xfs_da3_node_read libxfs_da3_node_read #define xfs_da_get_buf libxfs_da_get_buf #define xfs_da_hashname libxfs_da_hashname #define xfs_da_read_buf libxfs_da_read_buf @@ -161,6 +165,7 @@ #define xfs_inobt_stage_cursor libxfs_inobt_stage_cursor #define xfs_inode_from_disk libxfs_inode_from_disk #define xfs_inode_from_disk_ts libxfs_inode_from_disk_ts +#define xfs_inode_hasattr libxfs_inode_hasattr #define xfs_inode_to_disk libxfs_inode_to_disk #define xfs_inode_validate_cowextsize libxfs_inode_validate_cowextsize #define xfs_inode_validate_extsize libxfs_inode_validate_extsize diff --git a/repair/attr_repair.c b/repair/attr_repair.c index afe8073ca8e..d3fd7a47a5b 100644 --- a/repair/attr_repair.c +++ b/repair/attr_repair.c @@ -579,7 +579,7 @@ process_leaf_attr_block( da_freemap_t *attr_freemap; struct xfs_attr3_icleaf_hdr leafhdr; - xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); + libxfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); clearit = usedbs = 0; firstb = mp->m_sb.sb_blocksize; stop = xfs_attr3_leaf_hdr_size(leaf); @@ -802,7 +802,7 @@ process_leaf_attr_level(xfs_mount_t *mp, } leaf = bp->b_addr; - xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); + libxfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); /* check magic number for leaf directory btree block */ if (!(leafhdr.magic == XFS_ATTR_LEAF_MAGIC || @@ -1000,7 +1000,7 @@ process_longform_leaf_root( * check sibling pointers in leaf block or root block 0 before * we have to release the btree block */ - xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, bp->b_addr); + libxfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, bp->b_addr); if (leafhdr.forw != 0 || leafhdr.back != 0) { if (!no_modify) { do_warn( From patchwork Fri May 26 02:28:36 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: 13256327 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 C135BC77B7E for ; Fri, 26 May 2023 02:28:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229523AbjEZC2k (ORCPT ); Thu, 25 May 2023 22:28:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54232 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229530AbjEZC2j (ORCPT ); Thu, 25 May 2023 22:28:39 -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 A0FC6B6 for ; Thu, 25 May 2023 19:28: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 37D0A64C27 for ; Fri, 26 May 2023 02:28:37 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9A8E5C433D2; Fri, 26 May 2023 02:28:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068116; bh=DAAZ341DIx3UjFA5xhmBn3NRx+ebxxrqJ8Kx0EATkJs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=nm4T9UeFcrVhKmTGyrMFagK5toI6vCy5QJ5+7NKaSrAcYt+zTmMdzmq1YMaqK19yd YDN2dnmbpBMjDDy/I2FKk5+W3SmsxpIoGWLTwej/kfNMaMOkRAoypEl5ZT7bRGrq0X 98FstUf8d6SKEa8E/epVbtXP0iSxgq7lnap3f5dfUlwsHkoc9yy9+Xr128JtPDCmgX HaIjxjJ8WQpIAt0vUmqigSrbeUF9Us6EAyj1uV+tfx8hzJRkcDiAy0OImuFcigy5C3 17hYBN7UcBiTNislpLZI9kfsSS7OLiKPgQrstNbnTssDdlfhlTM0mGfTawD35VI7Kn ukjOihhBLqEfQ== Date: Thu, 25 May 2023 19:28:36 -0700 Subject: [PATCH 26/30] xfs_db: add a parents command to list the parents of a file From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078241.3749421.12102041306764419938.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 a command to dump the parents of a file. Signed-off-by: Darrick J. Wong --- db/namei.c | 335 +++++++++++++++++++++++++++++++++++++++++++++++++++++ man/man8/xfs_db.8 | 9 + 2 files changed, 344 insertions(+) diff --git a/db/namei.c b/db/namei.c index a8577b97222..caca7ecf6fe 100644 --- a/db/namei.c +++ b/db/namei.c @@ -598,6 +598,338 @@ static struct cmdinfo ls_cmd = { .help = ls_help, }; +static void +pptr_emit( + struct xfs_mount *mp, + const struct xfs_parent_name_irec *irec) +{ + struct xfs_name xname = { + .name = irec->p_name, + .len = irec->p_namelen, + }; + xfs_dahash_t hash; + bool good; + + hash = libxfs_dir2_hashname(mp, &xname); + good = hash == irec->p_namehash && + libxfs_dir2_namecheck(irec->p_name, irec->p_namelen); + + dbprintf("%18llu:0x%08x 0x%08x:0x%08x %3d %.*s %s\n", + irec->p_ino, irec->p_gen, irec->p_namehash, hash, + xname.len, xname.len, xname.name, + good ? _("(good)") : _("(corrupt)")); +} + +static int +list_sf_pptrs( + struct xfs_inode *ip) +{ + struct xfs_parent_name_irec irec; + struct xfs_attr_shortform *sf; + struct xfs_attr_sf_entry *sfe; + unsigned int i; + + sf = (struct xfs_attr_shortform *)ip->i_af.if_u1.if_data; + for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { + void *name = sfe->nameval; + void *value = &sfe->nameval[sfe->namelen]; + + if ((sfe->flags & XFS_ATTR_PARENT) && + libxfs_parent_namecheck(mp, name, sfe->namelen, sfe->flags) && + libxfs_parent_valuecheck(mp, value, sfe->valuelen)) { + libxfs_parent_irec_from_disk(&irec, name, value, + sfe->valuelen); + pptr_emit(mp, &irec); + } + + sfe = xfs_attr_sf_nextentry(sfe); + } + + return 0; +} + +static void +list_leaf_pptr_entries( + struct xfs_inode *ip, + struct xfs_buf *bp) +{ + struct xfs_parent_name_irec irec; + struct xfs_attr3_icleaf_hdr ichdr; + struct xfs_mount *mp = ip->i_mount; + struct xfs_attr_leafblock *leaf = bp->b_addr; + struct xfs_attr_leaf_entry *entry; + unsigned int i; + + libxfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf); + entry = xfs_attr3_leaf_entryp(leaf); + + for (i = 0; i < ichdr.count; entry++, i++) { + struct xfs_attr_leaf_name_local *name_loc; + void *value; + void *name; + unsigned int namelen, valuelen; + + if (!(entry->flags & XFS_ATTR_LOCAL) || + !(entry->flags & XFS_ATTR_PARENT)) + continue; + + name_loc = xfs_attr3_leaf_name_local(leaf, i); + name = name_loc->nameval; + namelen = name_loc->namelen; + value = &name_loc->nameval[name_loc->namelen]; + valuelen = be16_to_cpu(name_loc->valuelen); + + if (libxfs_parent_namecheck(mp, name, namelen, entry->flags) && + libxfs_parent_valuecheck(mp, value, valuelen)) { + libxfs_parent_irec_from_disk(&irec, name, value, + valuelen); + pptr_emit(mp, &irec); + } + } +} + +static int +list_leaf_pptrs( + struct xfs_inode *ip) +{ + struct xfs_buf *leaf_bp; + int error; + + error = -libxfs_attr3_leaf_read(NULL, ip, ip->i_ino, 0, &leaf_bp); + if (error) + return error; + + list_leaf_pptr_entries(ip, leaf_bp); + libxfs_trans_brelse(NULL, leaf_bp); + return 0; +} + +static int +find_leftmost_attr_leaf( + struct xfs_inode *ip, + struct xfs_buf **leaf_bpp) +{ + struct xfs_da3_icnode_hdr nodehdr; + struct xfs_mount *mp = ip->i_mount; + struct xfs_da_intnode *node; + struct xfs_da_node_entry *btree; + struct xfs_buf *bp; + xfs_dablk_t blkno = 0; + unsigned int expected_level = 0; + int error; + + for (;;) { + uint16_t magic; + + error = -libxfs_da3_node_read(NULL, ip, blkno, &bp, + XFS_ATTR_FORK); + if (error) + return error; + + node = bp->b_addr; + magic = be16_to_cpu(node->hdr.info.magic); + if (magic == XFS_ATTR_LEAF_MAGIC || + magic == XFS_ATTR3_LEAF_MAGIC) + break; + + error = EFSCORRUPTED; + if (magic != XFS_DA_NODE_MAGIC && + magic != XFS_DA3_NODE_MAGIC) + goto out_buf; + + libxfs_da3_node_hdr_from_disk(mp, &nodehdr, node); + + if (nodehdr.count == 0 || nodehdr.level >= XFS_DA_NODE_MAXDEPTH) + goto out_buf; + + /* Check the level from the root node. */ + if (blkno == 0) + expected_level = nodehdr.level - 1; + else if (expected_level != nodehdr.level) + goto out_buf; + else + expected_level--; + + /* Find the next level towards the leaves of the dabtree. */ + btree = nodehdr.btree; + blkno = be32_to_cpu(btree->before); + libxfs_trans_brelse(NULL, bp); + } + + error = EFSCORRUPTED; + if (expected_level != 0) + goto out_buf; + + *leaf_bpp = bp; + return 0; + +out_buf: + libxfs_trans_brelse(NULL, bp); + return error; +} + +static int +list_node_pptrs( + struct xfs_inode *ip) +{ + struct xfs_attr3_icleaf_hdr leafhdr; + struct xfs_mount *mp = ip->i_mount; + struct xfs_attr_leafblock *leaf; + struct xfs_buf *leaf_bp; + int error; + + error = find_leftmost_attr_leaf(ip, &leaf_bp); + if (error) + return error; + + for (;;) { + list_leaf_pptr_entries(ip, leaf_bp); + + /* Find the right sibling of this leaf block. */ + leaf = leaf_bp->b_addr; + libxfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); + if (leafhdr.forw == 0) + goto out_leaf; + + libxfs_trans_brelse(NULL, leaf_bp); + + error = -libxfs_attr3_leaf_read(NULL, ip, ip->i_ino, + leafhdr.forw, &leaf_bp); + if (error) + return error; + } + +out_leaf: + libxfs_trans_brelse(NULL, leaf_bp); + return error; +} + +static int +list_pptrs( + struct xfs_inode *ip) +{ + int error; + + if (!libxfs_inode_hasattr(ip)) + return 0; + + if (ip->i_af.if_format == XFS_DINODE_FMT_LOCAL) + return list_sf_pptrs(ip); + + /* attr functions require that the attr fork is loaded */ + error = -libxfs_iread_extents(NULL, ip, XFS_ATTR_FORK); + if (error) + return error; + + if (libxfs_attr_is_leaf(ip)) + return list_leaf_pptrs(ip); + + return list_node_pptrs(ip); +} + +/* If the io cursor points to a file, list its parents. */ +static int +parent_cur( + char *tag) +{ + struct xfs_inode *ip; + int error = 0; + + if (!xfs_has_parent(mp)) + return 0; + + if (iocur_top->typ != &typtab[TYP_INODE]) + return ENOTDIR; + + error = -libxfs_iget(mp, NULL, iocur_top->ino, 0, &ip); + if (error) + return error; + + /* List the parents of a file. */ + if (tag) + dbprintf(_("%s:\n"), tag); + + error = list_pptrs(ip); + if (error) + goto rele; + +rele: + libxfs_irele(ip); + return error; +} + +static void +parent_help(void) +{ + dbprintf(_( +"\n" +" List the parents of the currently selected file.\n" +"\n" +" Parent pointers will be listed in the format:\n" +" inode_number:inode_gen ondisk_namehash:namehash name_length name\n" + )); +} + +static int +parent_f( + int argc, + char **argv) +{ + int c; + int error = 0; + + while ((c = getopt(argc, argv, "")) != -1) { + switch (c) { + default: + ls_help(); + return 0; + } + } + + if (optind == argc) { + error = parent_cur(NULL); + if (error) { + dbprintf("%s\n", strerror(error)); + exitcode = 1; + } + + return 0; + } + + for (c = optind; c < argc; c++) { + push_cur(); + + error = path_walk(argv[c]); + if (error) + goto err_cur; + + error = parent_cur(argv[c]); + if (error) + goto err_cur; + + pop_cur(); + } + + return 0; +err_cur: + pop_cur(); + if (error) { + dbprintf("%s: %s\n", argv[c], strerror(error)); + exitcode = 1; + } + return 0; +} + +static struct cmdinfo parent_cmd = { + .name = "parent", + .altname = "pptr", + .cfunc = parent_f, + .argmin = 0, + .argmax = -1, + .canpush = 0, + .args = "[paths...]", + .help = parent_help, +}; void namei_init(void) { @@ -606,4 +938,7 @@ namei_init(void) ls_cmd.oneline = _("list directory contents"); add_command(&ls_cmd); + + parent_cmd.oneline = _("list parent pointers"); + add_command(&parent_cmd); } diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index aec898b001e..ec98acdffff 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -913,6 +913,15 @@ See the .B print command. .TP +.BI "parent [" paths "]..." +List the parents of a file. +If a path resolves to a file, the parents of that file will be listed. +If no paths are supplied and the IO cursor points at an inode, the parents of +that file will be listed. + +The output format is: +inode number, inode generation, ondisk namehash, namehash, name length, name. +.TP .BI "path " dir_path Walk the directory tree to an inode using the supplied path. Absolute and relative paths are supported. From patchwork Fri May 26 02:28: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: 13256328 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 24C92C7EE2F for ; Fri, 26 May 2023 02:28:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233648AbjEZC2z (ORCPT ); Thu, 25 May 2023 22:28:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54294 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233507AbjEZC2y (ORCPT ); Thu, 25 May 2023 22:28:54 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 28DA39B for ; Thu, 25 May 2023 19:28:53 -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 BA3BE64C57 for ; Fri, 26 May 2023 02:28:52 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2D7F7C4339C; Fri, 26 May 2023 02:28:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068132; bh=lJJ4DACK1m6otcHwC0gnlXrzdkBajhtIFQco8dKHqJY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=KZzTkwmsHLqKi738Xbo6cz+Z86HpdaW8MUp8qFMHd+FDvWfi5fjWdfYvUcPgJ9n7t 5Ey8gAUhsLqKpWsu1mjKgqx+agI5ZtiK9p2W8POPdtm2G1+/EdtFeAuzFALJ9NIQv1 TEp0wdSGo5Y+it1CDoWS0+kCCICcfbQWBG++eM/pJNhRRjuhXmcOvj24cMPvl8vD4M vKIwKt89Y2PZGDEZutG/+XZTXnDGNDEA8q3fZTdU3Ttiwyz059zvd2/rjz4t5ZbDUV /pNUfy18d9FMGS1B/rwxwOyXy9xijYTpNVfEjJyV0nlkUeCqAjI6qZawh94v7oLrgs z0dT8bHC/qI7g== Date: Thu, 25 May 2023 19:28:51 -0700 Subject: [PATCH 27/30] libxfs: create new files with attr forks if necessary From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078255.3749421.6274535805643049447.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 new files with attr forks if they're going to have parent pointers. In the next patch we'll fix mkfs to use the same parent creation functions as the kernel, so we're going to need this. Signed-off-by: Darrick J. Wong --- libxfs/init.c | 4 ++++ libxfs/util.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/libxfs/init.c b/libxfs/init.c index 26b578134c7..1d28c7b3824 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -819,14 +819,18 @@ void libxfs_compute_all_maxlevels( struct xfs_mount *mp) { + struct xfs_ino_geometry *igeo = M_IGEO(mp); + xfs_alloc_compute_maxlevels(mp); xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK); + igeo->attr_fork_offset = xfs_bmap_compute_attr_offset(mp); xfs_ialloc_setup_geometry(mp); xfs_rmapbt_compute_maxlevels(mp); xfs_refcountbt_compute_maxlevels(mp); xfs_agbtree_compute_maxlevels(mp); + } /* diff --git a/libxfs/util.c b/libxfs/util.c index febbd84ab92..75166508d06 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -340,6 +340,20 @@ libxfs_init_new_inode( ASSERT(0); } + /* + * If we need to create attributes immediately after allocating the + * inode, initialise an empty attribute fork right now. We use the + * default fork offset for attributes here as we don't know exactly what + * size or how many attributes we might be adding. We can do this + * safely here because we know the data fork is completely empty and + * this saves us from needing to run a separate transaction to set the + * fork offset in the immediate future. + */ + if (xfs_has_parent(tp->t_mountp) && xfs_has_attr(tp->t_mountp)) { + ip->i_forkoff = xfs_default_attroffset(ip) >> 3; + xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0); + } + /* * Log the new values stuffed into the inode. */ From patchwork Fri May 26 02:29: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: 13256329 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 648CAC77B7A for ; Fri, 26 May 2023 02:29:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234031AbjEZC3K (ORCPT ); Thu, 25 May 2023 22:29:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54462 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230154AbjEZC3J (ORCPT ); Thu, 25 May 2023 22:29:09 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC06A9B for ; Thu, 25 May 2023 19:29: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 4C40A64C27 for ; Fri, 26 May 2023 02:29:08 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD646C4339B; Fri, 26 May 2023 02:29:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068147; bh=lwkarbGOdDEX/E16amenOkw3MgR6dA2IlSNgfWpfGFg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=fp4zevTesmy+sxZZ0EfAftg6QuY40hwBMJjLeSeTVxHX9Fby0hI+ewCaNTRR+zkYx sH/sstoNajYUoddQ3nf9CMaxp1uwJa2wztQpjO4mI1bgTP/9CKXVSWH+SAEXu2UIQv IuS0kUQzGvTVGXUQDWOC5W+NnlKZWyguEJ9IbV2O5j3TgdAfx6oSoaDusva8uunriw n9H2hfDL9qI25DJBX3fw9fIIubSxnXfp4QL1LEHM0iBUoLeP7eZKDp2g6dtgfYq6TH FJ+STl2TefhvwQSX5Svg47CdsNQuLXbfngCSwijMoJHwvaBThkenzLnpsdNuE7VlDD Cj+KACh8fLVQg== Date: Thu, 25 May 2023 19:29:07 -0700 Subject: [PATCH 28/30] xfsprogs: Fix default superblock attr bits From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078268.3749421.1971130920300572465.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Recent parent pointer testing discovered that the default attr configuration has XFS_SB_VERSION2_ATTR2BIT enabled but XFS_SB_VERSION_ATTRBIT disabled. This is incorrect since XFS_SB_VERSION2_ATTR2BIT describes the format of the attr where as XFS_SB_VERSION_ATTRBIT enables or disables attrs. Fix this by enableing XFS_SB_VERSION_ATTRBIT for either attr version 1 or 2 Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- mkfs/xfs_mkfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 19868eff9db..89b1f2c27a6 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -3468,7 +3468,7 @@ sb_set_features( sbp->sb_versionnum |= XFS_SB_VERSION_DALIGNBIT; if (fp->log_version == 2) sbp->sb_versionnum |= XFS_SB_VERSION_LOGV2BIT; - if (fp->attr_version == 1) + if (fp->attr_version >= 1) sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT; if (fp->nci) sbp->sb_versionnum |= XFS_SB_VERSION_BORGBIT; From patchwork Fri May 26 02:29: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: 13256330 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 098C8C77B7A for ; Fri, 26 May 2023 02:29:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229567AbjEZC33 (ORCPT ); Thu, 25 May 2023 22:29:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229631AbjEZC32 (ORCPT ); Thu, 25 May 2023 22:29:28 -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 47B9B13D for ; Thu, 25 May 2023 19:29: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 D2FEE64C4C for ; Fri, 26 May 2023 02:29:23 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 43C60C433D2; Fri, 26 May 2023 02:29:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068163; bh=ZRCZ9sJ/4GjssgGYDEUNmu2OTPsBQvS7IogjGSupxgM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=swPnbgoNvmOXlXM69lZZVWdIbglrZ/ApHG9htJ+OSP6sDFPg9Dw6U3Z5YPzI5djqI l9n4IjZAvOksPAkpR5J6TdZhKUVRUO8hXfkiPi3xA/eg+A5Xc1jqgrX8iMYv7yTIic +tJqnfNVztj2NLx7TDho0oju0CiuR6uY4+I4ffRKVitb69lO18f2lof4DYMKpPVEH8 bfTwtITZK4k9mYuf5QZOPiAJnizuzsht+UitNAjwCtnEh1XJVxqeroSwngj4f3OO2K Jnxb0txRg/FEPgHLqMYcmK/aa855ijGd7riOcxRGmPnPT6SxdeDEQ7IqzSdLGG0pVz Aqbwt2+xWEQvg== Date: Thu, 25 May 2023 19:29:22 -0700 Subject: [PATCH 29/30] mkfs: Add parent pointers during protofile creation From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078282.3749421.188426515286394970.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Inodes created from protofile parsing will also need to add the appropriate parent pointers. Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: use xfs_parent_add from libxfs instead of open-coding xfs_attr_set] Signed-off-by: Darrick J. Wong --- mkfs/proto.c | 63 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/mkfs/proto.c b/mkfs/proto.c index b127bb5cedc..c0e887993e5 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -346,11 +346,12 @@ newregfile( static void newdirent( - xfs_mount_t *mp, - xfs_trans_t *tp, - xfs_inode_t *pip, - struct xfs_name *name, - xfs_ino_t inum) + struct xfs_mount *mp, + struct xfs_trans *tp, + struct xfs_inode *pip, + struct xfs_name *name, + struct xfs_inode *ip, + struct xfs_parent_defer *parent) { int error; int rsv; @@ -363,9 +364,16 @@ newdirent( rsv = XFS_DIRENTER_SPACE_RES(mp, name->len); - error = -libxfs_dir_createname(tp, pip, name, inum, rsv); + error = -libxfs_dir_createname(tp, pip, name, ip->i_ino, rsv); if (error) fail(_("directory createname error"), error); + + if (parent) { + error = -libxfs_parent_add(tp, parent, pip, name, ip); + if (error) + fail(_("committing parent pointers failed."), + error); + } } static void @@ -382,6 +390,20 @@ newdirectory( fail(_("directory create error"), error); } +static struct xfs_parent_defer * +newpptr( + struct xfs_mount *mp) +{ + struct xfs_parent_defer *ret; + int error; + + error = -libxfs_parent_start(mp, &ret); + if (error) + fail(_("initializing parent pointer"), error); + + return ret; +} + static void parseproto( xfs_mount_t *mp, @@ -416,6 +438,7 @@ parseproto( struct cred creds; char *value; struct xfs_name xname; + struct xfs_parent_defer *parent = NULL; memset(&creds, 0, sizeof(creds)); mstr = getstr(pp); @@ -490,6 +513,7 @@ parseproto( case IF_REGULAR: buf = newregfile(pp, &len); tp = getres(mp, XFS_B_TO_FSB(mp, len)); + parent = newpptr(mp); error = -libxfs_dir_ialloc(&tp, pip, mode|S_IFREG, 1, 0, &creds, fsxp, &ip); if (error) @@ -499,7 +523,7 @@ parseproto( free(buf); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_REG_FILE; - newdirent(mp, tp, pip, &xname, ip->i_ino); + newdirent(mp, tp, pip, &xname, ip, parent); break; case IF_RESERVED: /* pre-allocated space only */ @@ -513,7 +537,7 @@ parseproto( exit(1); } tp = getres(mp, XFS_B_TO_FSB(mp, llen)); - + parent = newpptr(mp); error = -libxfs_dir_ialloc(&tp, pip, mode|S_IFREG, 1, 0, &creds, fsxp, &ip); if (error) @@ -522,17 +546,19 @@ parseproto( libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_REG_FILE; - newdirent(mp, tp, pip, &xname, ip->i_ino); + newdirent(mp, tp, pip, &xname, ip, parent); libxfs_trans_log_inode(tp, ip, flags); error = -libxfs_trans_commit(tp); if (error) fail(_("Space preallocation failed."), error); + libxfs_parent_finish(mp, parent); rsvfile(mp, ip, llen); libxfs_irele(ip); return; case IF_BLOCK: tp = getres(mp, 0); + parent = newpptr(mp); majdev = getnum(getstr(pp), 0, 0, false); mindev = getnum(getstr(pp), 0, 0, false); error = -libxfs_dir_ialloc(&tp, pip, mode|S_IFBLK, 1, @@ -542,12 +568,13 @@ parseproto( } libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_BLKDEV; - newdirent(mp, tp, pip, &xname, ip->i_ino); + newdirent(mp, tp, pip, &xname, ip, parent); flags |= XFS_ILOG_DEV; break; case IF_CHAR: tp = getres(mp, 0); + parent = newpptr(mp); majdev = getnum(getstr(pp), 0, 0, false); mindev = getnum(getstr(pp), 0, 0, false); error = -libxfs_dir_ialloc(&tp, pip, mode|S_IFCHR, 1, @@ -556,24 +583,26 @@ parseproto( fail(_("Inode allocation failed"), error); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_CHRDEV; - newdirent(mp, tp, pip, &xname, ip->i_ino); + newdirent(mp, tp, pip, &xname, ip, parent); flags |= XFS_ILOG_DEV; break; case IF_FIFO: tp = getres(mp, 0); + parent = newpptr(mp); error = -libxfs_dir_ialloc(&tp, pip, mode|S_IFIFO, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_FIFO; - newdirent(mp, tp, pip, &xname, ip->i_ino); + newdirent(mp, tp, pip, &xname, ip, parent); break; case IF_SYMLINK: buf = getstr(pp); len = (int)strlen(buf); tp = getres(mp, XFS_B_TO_FSB(mp, len)); + parent = newpptr(mp); error = -libxfs_dir_ialloc(&tp, pip, mode|S_IFLNK, 1, 0, &creds, fsxp, &ip); if (error) @@ -581,7 +610,7 @@ parseproto( writesymlink(tp, ip, buf, len); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_SYMLINK; - newdirent(mp, tp, pip, &xname, ip->i_ino); + newdirent(mp, tp, pip, &xname, ip, parent); break; case IF_DIRECTORY: tp = getres(mp, 0); @@ -596,9 +625,10 @@ parseproto( libxfs_log_sb(tp); isroot = 1; } else { + parent = newpptr(mp); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_DIR; - newdirent(mp, tp, pip, &xname, ip->i_ino); + newdirent(mp, tp, pip, &xname, ip, parent); libxfs_bumplink(tp, pip); libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE); } @@ -607,6 +637,9 @@ parseproto( error = -libxfs_trans_commit(tp); if (error) fail(_("Directory inode allocation failed."), error); + + libxfs_parent_finish(mp, parent); + /* * RT initialization. Do this here to ensure that * the RT inodes get placed after the root inode. @@ -634,6 +667,8 @@ parseproto( fail(_("Error encountered creating file from prototype file"), error); } + + libxfs_parent_finish(mp, parent); libxfs_irele(ip); } From patchwork Fri May 26 02:29: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: 13256331 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 F378DC77B7E for ; Fri, 26 May 2023 02:29:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233106AbjEZC3l (ORCPT ); Thu, 25 May 2023 22:29:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54804 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233245AbjEZC3k (ORCPT ); Thu, 25 May 2023 22:29:40 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D1182B2 for ; Thu, 25 May 2023 19:29: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 6F9D264C57 for ; Fri, 26 May 2023 02:29:39 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1245C433EF; Fri, 26 May 2023 02:29:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1685068178; bh=ciNgXCbN6/kwXMTeqf5dIYjgDEaeKjVngaH898wmNAE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=NnhVcxlkFNR8IGjvLAl+v/nPU4lBLVazJW9sYz8t2KV7FIPPhpQgl/tX48kC/QuN/ 0+tr9tPfXg5atC+hCKH0gJI6/WI1pl64CV3ebfONZ3UhXV+mXc9hjwhfs2Ru3etp+L blQrqEQ0EAzvQzy4vrkumQJqyyIN1QxwHubaBicExwkPM8efF9F1PthUdit/0tFoSi xeiSfJrubwnQQq0ZPPhE5t5Ik1P9KNZ46jT7ZYCpGeIZkIiwieJWW9u7/vUObtJAfk yKKSQwTvGnK+OjWXIp/44R4qbJnsoCwW1GV6pM/urDzzFgrzeQ9/Q3A1CqZKmkUCnq UpXLmP7rgW/XQ== Date: Thu, 25 May 2023 19:29:38 -0700 Subject: [PATCH 30/30] mkfs: enable formatting with parent pointers From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <168506078296.3749421.10263563788583854501.stgit@frogsfrogsfrogs> In-Reply-To: <168506077876.3749421.7883085669588003826.stgit@frogsfrogsfrogs> References: <168506077876.3749421.7883085669588003826.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 Enable parent pointer support in mkfs via the '-n parent' parameter. Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- mkfs/xfs_mkfs.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 89b1f2c27a6..0f61699bf35 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -113,6 +113,7 @@ enum { N_SIZE = 0, N_VERSION, N_FTYPE, + N_PARENT, N_MAX_OPTS, }; @@ -648,6 +649,7 @@ static struct opt_params nopts = { [N_SIZE] = "size", [N_VERSION] = "version", [N_FTYPE] = "ftype", + [N_PARENT] = "parent", [N_MAX_OPTS] = NULL, }, .subopt_params = { @@ -671,6 +673,14 @@ static struct opt_params nopts = { .maxval = 1, .defaultval = 1, }, + { .index = N_PARENT, + .conflicts = { { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, + + }, }; @@ -1030,7 +1040,7 @@ usage( void ) sunit=value|su=num,sectsize=num,lazy-count=0|1,\n\ concurrency=num]\n\ /* label */ [-L label (maximum 12 characters)]\n\ -/* naming */ [-n size=num,version=2|ci,ftype=0|1]\n\ +/* naming */ [-n size=num,version=2|ci,ftype=0|1,parent=0|1]]\n\ /* no-op info only */ [-N]\n\ /* prototype file */ [-p fname]\n\ /* quiet */ [-q]\n\ @@ -1871,6 +1881,9 @@ naming_opts_parser( case N_FTYPE: cli->sb_feat.dirftype = getnum(value, opts, subopt); break; + case N_PARENT: + cli->sb_feat.parent_pointers = getnum(value, &nopts, N_PARENT); + break; default: return -EINVAL; } @@ -2394,6 +2407,14 @@ _("inode btree counters not supported without finobt support\n")); cli->sb_feat.inobtcnt = false; } + if ((cli->sb_feat.parent_pointers) && + cli->sb_feat.dir_version == 4) { + fprintf(stderr, +_("parent pointers not supported on v4 filesystems\n")); + usage(); + cli->sb_feat.parent_pointers = false; + } + if (cli->xi->rtname) { if (cli->sb_feat.reflink && cli_opt_set(&mopts, M_REFLINK)) { fprintf(stderr, @@ -3487,8 +3508,6 @@ sb_set_features( sbp->sb_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT; if (fp->projid32bit) sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT; - if (fp->parent_pointers) - sbp->sb_features2 |= XFS_SB_VERSION2_PARENTBIT; if (fp->crcs_enabled) sbp->sb_features2 |= XFS_SB_VERSION2_CRCBIT; if (fp->attr_version == 2) @@ -3529,6 +3548,10 @@ sb_set_features( sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_INOBTCNT; if (fp->bigtime) sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_BIGTIME; + if (fp->parent_pointers) { + sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_PARENT; + sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT; + } /* * Sparse inode chunk support has two main inode alignment requirements.