From patchwork Tue Jul 2 01:10:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718825 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D42D1523D for ; Tue, 2 Jul 2024 01:10:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882657; cv=none; b=pMDAS1Qj7YyVG5WC/n6IsM2UB4k41Rdr4xcNHarGq3+YOXyeuw1xdWN+Yk1Rj/EjOwBqejvQz/3GS3VUywjgEtBquckqRubM+mMt2lXNLvlxnH/ZMckLnZIzbYqMPRz7/mP0XuamcvMtNymArqSsb2Pp36A8aOeNMoNW9CF1t/0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882657; c=relaxed/simple; bh=0yLw1UmLgVAEsVrXEQ6ewWeAhNGYevMaBioQrKVR8sQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EIDK//YG/wqVAE6ioKXBRJjkDDhBnn3lRCvjpPu6KSdQaigCZbXUI2FBe8I57cVdQCBcKhAwvw12pTK8l7j3rQlqMQjNMVO3CJY7Ow9LnLNBqJVZ/Ya4U17JsHGdyuSLFupm/V++WUn/m/1hiaO9IvefYvdcoGtYJP3vwymYmBA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YgTgvDXg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YgTgvDXg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 87567C116B1; Tue, 2 Jul 2024 01:10:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882657; bh=0yLw1UmLgVAEsVrXEQ6ewWeAhNGYevMaBioQrKVR8sQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=YgTgvDXg7/Codbk9mSSp34VuNi5Th07rbAAH0OxtaS0Kgph1ut+MrnmjKJNZQOJN3 WU+sJDphhbR6bgzhqG9Re4PjKQmzCSR0zElWyqVFgaC0kGFid5ev3ETyMXg0YE9f8S bFUU47VVf7yKD/1XFLtq0MtHIgOySL7JFHhqYFFpnVLZwLdNXdnAvcS1mZaAACqMeE 4mH5aJ5PUE0nDltUwm0fgby7GAbhRs2KMlS5qrYm8LvxHqMLyRDT0IYXyKB374kRIF 24m7cKnNkXC/h50upTgAMGTGHG16Dbqa3O2NkbAca1n3EuT9v/nzLn4OBfraF+KQ4W GMS0WKYmEzgKw== Date: Mon, 01 Jul 2024 18:10:57 -0700 Subject: [PATCH 01/24] libxfs: create attr log item opcodes and formats for parent pointers From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121078.2009260.1928679002077059727.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Update xfs_attr_defer_add to use the pptr-specific opcodes if it's reading or writing parent pointers. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- libxfs/defer_item.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c index 9955e189dfe1..8cdf57eac900 100644 --- a/libxfs/defer_item.c +++ b/libxfs/defer_item.c @@ -676,21 +676,61 @@ xfs_attr_defer_add( enum xfs_attr_defer_op op) { struct xfs_attr_intent *new; + unsigned int log_op = 0; + bool is_pptr = args->attr_filter & XFS_ATTR_PARENT; - new = kmem_cache_zalloc(xfs_attr_intent_cache, GFP_NOFS | __GFP_NOFAIL); + if (is_pptr) { + ASSERT(xfs_has_parent(args->dp->i_mount)); + ASSERT((args->attr_filter & ~XFS_ATTR_PARENT) != 0); + ASSERT(args->op_flags & XFS_DA_OP_LOGGED); + ASSERT(args->valuelen == sizeof(struct xfs_parent_rec)); + } + + new = kmem_cache_zalloc(xfs_attr_intent_cache, + GFP_NOFS | __GFP_NOFAIL); new->xattri_da_args = args; + /* Compute log operation from the higher level op and namespace. */ switch (op) { case XFS_ATTR_DEFER_SET: - new->xattri_op_flags = XFS_ATTRI_OP_FLAGS_SET; - new->xattri_dela_state = xfs_attr_init_add_state(args); + if (is_pptr) + log_op = XFS_ATTRI_OP_FLAGS_PPTR_SET; + else + log_op = XFS_ATTRI_OP_FLAGS_SET; break; case XFS_ATTR_DEFER_REPLACE: - new->xattri_op_flags = XFS_ATTRI_OP_FLAGS_REPLACE; - new->xattri_dela_state = xfs_attr_init_replace_state(args); + if (is_pptr) + log_op = XFS_ATTRI_OP_FLAGS_PPTR_REPLACE; + else + log_op = XFS_ATTRI_OP_FLAGS_REPLACE; break; case XFS_ATTR_DEFER_REMOVE: - new->xattri_op_flags = XFS_ATTRI_OP_FLAGS_REMOVE; + if (is_pptr) + log_op = XFS_ATTRI_OP_FLAGS_PPTR_REMOVE; + else + log_op = XFS_ATTRI_OP_FLAGS_REMOVE; + break; + default: + ASSERT(0); + break; + } + new->xattri_op_flags = log_op; + + /* Set up initial attr operation state. */ + switch (log_op) { + case XFS_ATTRI_OP_FLAGS_PPTR_SET: + case XFS_ATTRI_OP_FLAGS_SET: + new->xattri_dela_state = xfs_attr_init_add_state(args); + break; + case XFS_ATTRI_OP_FLAGS_PPTR_REPLACE: + ASSERT(args->new_valuelen == args->valuelen); + new->xattri_dela_state = xfs_attr_init_replace_state(args); + break; + case XFS_ATTRI_OP_FLAGS_REPLACE: + new->xattri_dela_state = xfs_attr_init_replace_state(args); + break; + case XFS_ATTRI_OP_FLAGS_PPTR_REMOVE: + case XFS_ATTRI_OP_FLAGS_REMOVE: new->xattri_dela_state = xfs_attr_init_remove_state(args); break; } From patchwork Tue Jul 2 01:11:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718826 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 51F5779CC for ; Tue, 2 Jul 2024 01:11:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882673; cv=none; b=YskPL28Y6Ys9MGM1fpKvRwUie5fMiAfnaulqnDppc4k4hP4JJ6kMA2i3n6MbvKkp7UkwXAk/7hLROELiz07kDByoAvMPvdrqfJPD5zm0WokWAsWPnzFM0INFw5z2gusamfIsYa9+Xr3juGPVQ5urkV9YY9NeeEsS6R2kf6hHI54= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882673; c=relaxed/simple; bh=4FxuukcafAOvmgxtFs4sNID+kztlgmKG1hhV6FsVifA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sotaA8r/9dBNEcpOkahxHa60pMoqhwgAmgynm25kYkJ3L7mKRDiWqXhotY3x6IfpiGxAXnGhGCFgWgbVCe3pswfE4Odj9YSz0Aqqc3dO/UKlBLXE5MCb95UwBQFFYRtYIWh/wXo6b+9oMrSRu7G9AyF6smOd1/fbC6OfDqdSk/U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sgszWyJc; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sgszWyJc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 283E9C116B1; Tue, 2 Jul 2024 01:11:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882673; bh=4FxuukcafAOvmgxtFs4sNID+kztlgmKG1hhV6FsVifA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=sgszWyJc5mJjHVhWKlEokYJ5d7kyjbe2y53lE1Znq1qRNQ9e9BiinrwZ66VuvJ39J wxZRx8B7ATLhCMrCQLKNMQE2YaeyoQRV/n9akhYE1xBZiObsR2Bc0AkjzQylahJM0f icvGEB7Ol+698ARWqB71/YPI8a6V8eKZ/vYWs+JScnXQDBHj/MlpmBnZgjFQySp39j Tr00+Vl6eAkHHQH79qXByW+AGwkGodXM+sWsxPoYVpWWSo0rbZ6+bGQuOyCv6sAU4y 7N0Q42SWlqPu2s2rXJpZ3xtgMTDQzLTpXHFVzXrLMjn45KLYO3gLo2jZf7r2pLamz5 RLXV/GOKzWRlg== Date: Mon, 01 Jul 2024 18:11:12 -0700 Subject: [PATCH 02/24] xfs_{db,repair}: implement new attr hash value function From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121093.2009260.4332172990916225703.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Port existing utilities to use libxfs_attr_hashname instead of calling libxfs_da_hashname directly. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- db/hash.c | 8 ++++---- db/metadump.c | 10 +++++----- libxfs/libxfs_api_defs.h | 2 ++ repair/attr_repair.c | 18 ++++++++++++------ 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/db/hash.c b/db/hash.c index 9b3fdea6c413..1500a6032fd7 100644 --- a/db/hash.c +++ b/db/hash.c @@ -73,7 +73,7 @@ hash_f( if (use_dir2_hash) hashval = libxfs_dir2_hashname(mp, &xname); else - hashval = libxfs_da_hashname(xname.name, xname.len); + hashval = libxfs_attr_hashname(xname.name, xname.len); dbprintf("0x%x\n", hashval); } @@ -306,7 +306,7 @@ collide_xattrs( unsigned long i; int error = 0; - old_hash = libxfs_da_hashname((uint8_t *)name, namelen); + old_hash = libxfs_attr_hashname((uint8_t *)name, namelen); if (fd >= 0) { /* @@ -331,8 +331,8 @@ collide_xattrs( snprintf(xattrname, MAXNAMELEN + 5, "user.%s", name); obfuscate_name(old_hash, namelen, (uint8_t *)xattrname + 5, false); - ASSERT(old_hash == libxfs_da_hashname((uint8_t *)xattrname + 5, - namelen)); + ASSERT(old_hash == libxfs_attr_hashname( + (uint8_t *)xattrname + 5, namelen)); if (fd >= 0) { error = fsetxattr(fd, xattrname, "1", 1, 0); diff --git a/db/metadump.c b/db/metadump.c index 9457e02e8288..c1bf5d002751 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -835,7 +835,7 @@ dirattr_hashname( return libxfs_dir2_hashname(mp, &xname); } - return libxfs_da_hashname(name, namelen); + return libxfs_attr_hashname(name, namelen); } static void @@ -982,9 +982,9 @@ obfuscate_path_components( if (!slash) { /* last (or single) component */ namelen = strnlen((char *)comp, len); - hash = libxfs_da_hashname(comp, namelen); + hash = dirattr_hashname(true, comp, namelen); obfuscate_name(hash, namelen, comp, false); - ASSERT(hash == libxfs_da_hashname(comp, namelen)); + ASSERT(hash == dirattr_hashname(true, comp, namelen)); break; } namelen = slash - (char *)comp; @@ -994,9 +994,9 @@ obfuscate_path_components( len--; continue; } - hash = libxfs_da_hashname(comp, namelen); + hash = dirattr_hashname(true, comp, namelen); obfuscate_name(hash, namelen, comp, false); - ASSERT(hash == libxfs_da_hashname(comp, namelen)); + ASSERT(hash == dirattr_hashname(true, comp, namelen)); comp += namelen + 1; len -= namelen + 1; } diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 2d858580abfe..c36a6ac81a7b 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -38,6 +38,8 @@ #define xfs_attr_check_namespace libxfs_attr_check_namespace #define xfs_attr_get libxfs_attr_get +#define xfs_attr_hashname libxfs_attr_hashname +#define xfs_attr_hashval libxfs_attr_hashval #define xfs_attr_leaf_newentsize libxfs_attr_leaf_newentsize #define xfs_attr_namecheck libxfs_attr_namecheck #define xfs_attr_set libxfs_attr_set diff --git a/repair/attr_repair.c b/repair/attr_repair.c index 37b5852b885e..8321c9b679b2 100644 --- a/repair/attr_repair.c +++ b/repair/attr_repair.c @@ -485,6 +485,7 @@ process_leaf_attr_local( xfs_ino_t ino) { xfs_attr_leaf_name_local_t *local; + xfs_dahash_t computed; local = xfs_attr3_leaf_name_local(leaf, i); if (local->namelen == 0 || @@ -504,9 +505,12 @@ process_leaf_attr_local( * ordering anyway in case both the name value and the * hashvalue were wrong but matched. Unlikely, however. */ - if (be32_to_cpu(entry->hashval) != libxfs_da_hashname( - &local->nameval[0], local->namelen) || - be32_to_cpu(entry->hashval) < last_hashval) { + computed = libxfs_attr_hashval(mp, entry->flags, local->nameval, + local->namelen, + local->nameval + local->namelen, + be16_to_cpu(local->valuelen)); + if (be32_to_cpu(entry->hashval) != computed || + be32_to_cpu(entry->hashval) < last_hashval) { do_warn( _("bad hashvalue for attribute entry %d in attr block %u, inode %" PRIu64 "\n"), i, da_bno, ino); @@ -540,15 +544,17 @@ process_leaf_attr_remote( { xfs_attr_leaf_name_remote_t *remotep; char* value; + xfs_dahash_t computed; remotep = xfs_attr3_leaf_name_remote(leaf, i); + computed = libxfs_attr_hashval(mp, entry->flags, remotep->name, + remotep->namelen, NULL, + be32_to_cpu(remotep->valuelen)); if (remotep->namelen == 0 || !libxfs_attr_namecheck(entry->flags, remotep->name, remotep->namelen) || - be32_to_cpu(entry->hashval) != - libxfs_da_hashname((unsigned char *)&remotep->name[0], - remotep->namelen) || + be32_to_cpu(entry->hashval) != computed || be32_to_cpu(entry->hashval) < last_hashval || be32_to_cpu(remotep->valueblk) == 0) { do_warn( From patchwork Tue Jul 2 01:11:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718827 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 095B6883D for ; Tue, 2 Jul 2024 01:11:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882689; cv=none; b=Bz6hJXKsT+w2fzgmMg+x1a3BbXQS7cRY3eeC02wuuSf6hEGdrbDo0nJHL0IULpYEeaVqwH1jaSdlY+GBvhLH6/lZIw7SlldpD4kpWhS4CGKAt+laQfxt7n/TmVd4BY1iuFBMYwUZ07aThkS+H/asHqVaR4wgVFMXkFzpRMxD5Ns= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882689; c=relaxed/simple; bh=k3/E8ahruVyWCLFc4xS1M1AXmAmXhrcmBhNaJt4WCFs=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BnK2p/j+Lmivwzb0wtdsXZVcOfVio3LITbuIIMKO3MDbGiCMClu4pRkBbYmsxLbQshiB1JO1nvMgseVmntcanzNMzzCJQyo4wWgRaUtN0zn1ZKqFXNEqVjkLE/+pd9u36seCb+HBvPG2hMAiZpAU6Jdw2geaislk2BwLu1h0p/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rJKtbEVV; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="rJKtbEVV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4519C116B1; Tue, 2 Jul 2024 01:11:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882688; bh=k3/E8ahruVyWCLFc4xS1M1AXmAmXhrcmBhNaJt4WCFs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=rJKtbEVVU6jj68YPfwAFGszMao2kIy0Huhl4vXUpmRfs3BOKSmaZWeqRchgBnjeQp zkhAaMadykp00kK7/CGuNVFVvu1xJCj4/dQmTS3ateB4KaVC768SXMQBBbwpBPzva4 QqIRaejyFtPaCJFK5GuceKpfTrT+h0f3jErhLk9qckjrNh0vVa/LCNG4tPz+IwC76V lpBCJV6qdZ6L6KV/WTh8xsRbn6SM7gUfspZYAjtCno1IwQRDp6kuhPrlnr17sUp+ET 3hZ2VYKe05hEZcggNFNYjMEz1f16jlgTqGoOYB/520c0k48Qr0NsFO+JNvlFTeqVX3 Z3PkU+uMzlNCw== Date: Mon, 01 Jul 2024 18:11:28 -0700 Subject: [PATCH 03/24] xfs_logprint: dump new attr log item fields From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121108.2009260.6026012075133524751.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Dump the new extended attribute log item fields. This was split out from the previous patch to make libxfs resyncing easier. This code needs more cleaning, which we'll do in the next few patches before moving on to the parent pointer code. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- logprint/log_redo.c | 140 ++++++++++++++++++++++++++++++++++++++++++--------- logprint/logprint.h | 6 +- 2 files changed, 119 insertions(+), 27 deletions(-) diff --git a/logprint/log_redo.c b/logprint/log_redo.c index ca6dadd7551a..1d55164a90ff 100644 --- a/logprint/log_redo.c +++ b/logprint/log_redo.c @@ -674,6 +674,12 @@ xfs_attri_copy_log_format( return 1; } +static inline unsigned int +xfs_attr_log_item_op(const struct xfs_attri_log_format *attrp) +{ + return attrp->alfi_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK; +} + int xlog_print_trans_attri( char **ptr, @@ -683,6 +689,10 @@ xlog_print_trans_attri( struct xfs_attri_log_format *src_f = NULL; xlog_op_header_t *head = NULL; uint dst_len; + unsigned int name_len = 0; + unsigned int new_name_len = 0; + unsigned int value_len = 0; + unsigned int new_value_len = 0; int error = 0; dst_len = sizeof(struct xfs_attri_log_format); @@ -705,27 +715,71 @@ xlog_print_trans_attri( memmove((char*)src_f, *ptr, src_len); *ptr += src_len; - printf(_("ATTRI: #regs: %d name_len: %d, value_len: %d id: 0x%llx\n"), - src_f->alfi_size, src_f->alfi_name_len, src_f->alfi_value_len, - (unsigned long long)src_f->alfi_id); + if (xfs_attr_log_item_op(src_f) == XFS_ATTRI_OP_FLAGS_PPTR_REPLACE) { + name_len = src_f->alfi_old_name_len; + new_name_len = src_f->alfi_new_name_len; + value_len = src_f->alfi_value_len; + new_value_len = src_f->alfi_value_len; + } else { + name_len = src_f->alfi_name_len; + value_len = src_f->alfi_value_len; + } + + printf(_("ATTRI: #regs: %d f: 0x%x, ino: 0x%llx, igen: 0x%x, attr_filter: 0x%x, name_len: %u, new_name_len: %u, value_len: %u, new_value_len: %u id: 0x%llx\n"), + src_f->alfi_size, + src_f->alfi_op_flags, + (unsigned long long)src_f->alfi_ino, + (unsigned int)src_f->alfi_igen, + src_f->alfi_attr_filter, + name_len, + new_name_len, + value_len, + new_value_len, + (unsigned long long)src_f->alfi_id); + + if (name_len > 0) { + printf(_("\n")); + (*i)++; + head = (xlog_op_header_t *)*ptr; + xlog_print_op_header(head, *i, ptr); + error = xlog_print_trans_attri_name(ptr, + be32_to_cpu(head->oh_len), "name"); + if (error) + goto error; + } - if (src_f->alfi_name_len > 0) { + if (new_name_len > 0) { printf(_("\n")); (*i)++; head = (xlog_op_header_t *)*ptr; xlog_print_op_header(head, *i, ptr); - error = xlog_print_trans_attri_name(ptr, be32_to_cpu(head->oh_len)); + error = xlog_print_trans_attri_name(ptr, + be32_to_cpu(head->oh_len), "newname"); if (error) goto error; } - if (src_f->alfi_value_len > 0) { + if (value_len > 0) { printf(_("\n")); (*i)++; head = (xlog_op_header_t *)*ptr; xlog_print_op_header(head, *i, ptr); - error = xlog_print_trans_attri_value(ptr, be32_to_cpu(head->oh_len), - src_f->alfi_value_len); + error = xlog_print_trans_attri_value(ptr, + be32_to_cpu(head->oh_len), value_len, "value"); + if (error) + goto error; + } + + if (new_value_len > 0) { + printf(_("\n")); + (*i)++; + head = (xlog_op_header_t *)*ptr; + xlog_print_op_header(head, *i, ptr); + error = xlog_print_trans_attri_value(ptr, + be32_to_cpu(head->oh_len), new_value_len, + "newvalue"); + if (error) + goto error; } error: free(src_f); @@ -736,31 +790,33 @@ xlog_print_trans_attri( int xlog_print_trans_attri_name( char **ptr, - uint src_len) + uint src_len, + const char *tag) { - printf(_("ATTRI: name len:%u\n"), src_len); + printf(_("ATTRI: %s len:%u\n"), tag, src_len); print_or_dump(*ptr, src_len); *ptr += src_len; return 0; -} /* xlog_print_trans_attri */ +} int xlog_print_trans_attri_value( char **ptr, uint src_len, - int value_len) + int value_len, + const char *tag) { int len = min(value_len, src_len); - printf(_("ATTRI: value len:%u\n"), value_len); + printf(_("ATTRI: %s len:%u\n"), tag, value_len); print_or_dump(*ptr, len); *ptr += src_len; return 0; -} /* xlog_print_trans_attri_value */ +} void xlog_recover_print_attri( @@ -768,7 +824,10 @@ xlog_recover_print_attri( { struct xfs_attri_log_format *f, *src_f = NULL; uint src_len, dst_len; - + unsigned int name_len = 0; + unsigned int new_name_len = 0; + unsigned int value_len = 0; + unsigned int new_value_len = 0; int region = 0; src_f = (struct xfs_attri_log_format *)item->ri_buf[0].i_addr; @@ -788,24 +847,55 @@ xlog_recover_print_attri( if (xfs_attri_copy_log_format((char*)src_f, src_len, f)) goto out; - printf(_("ATTRI: #regs: %d name_len: %d, value_len: %d id: 0x%llx\n"), - f->alfi_size, f->alfi_name_len, f->alfi_value_len, (unsigned long long)f->alfi_id); + if (xfs_attr_log_item_op(f) == XFS_ATTRI_OP_FLAGS_PPTR_REPLACE) { + name_len = f->alfi_old_name_len; + new_name_len = f->alfi_new_name_len; + value_len = f->alfi_value_len; + new_value_len = f->alfi_value_len; + } else { + name_len = f->alfi_name_len; + value_len = f->alfi_value_len; + } + + printf(_("ATTRI: #regs: %d f: 0x%x, ino: 0x%llx, igen: 0x%x, attr_filter: 0x%x, name_len: %u, new_name_len: %u, value_len: %d, new_value_len: %u id: 0x%llx\n"), + f->alfi_size, + f->alfi_op_flags, + (unsigned long long)f->alfi_ino, + (unsigned int)f->alfi_igen, + f->alfi_attr_filter, + name_len, + new_name_len, + value_len, + new_value_len, + (unsigned long long)f->alfi_id); - if (f->alfi_name_len > 0) { + if (name_len > 0) { region++; - printf(_("ATTRI: name len:%u\n"), f->alfi_name_len); + printf(_("ATTRI: name len:%u\n"), name_len); print_or_dump((char *)item->ri_buf[region].i_addr, - f->alfi_name_len); + name_len); } - if (f->alfi_value_len > 0) { - int len = f->alfi_value_len; + if (new_name_len > 0) { + region++; + printf(_("ATTRI: newname len:%u\n"), new_name_len); + print_or_dump((char *)item->ri_buf[region].i_addr, + new_name_len); + } + + if (value_len > 0) { + int len = min(MAX_ATTR_VAL_PRINT, value_len); + + region++; + printf(_("ATTRI: value len:%u\n"), value_len); + print_or_dump((char *)item->ri_buf[region].i_addr, len); + } - if (len > MAX_ATTR_VAL_PRINT) - len = MAX_ATTR_VAL_PRINT; + if (new_value_len > 0) { + int len = min(MAX_ATTR_VAL_PRINT, new_value_len); region++; - printf(_("ATTRI: value len:%u\n"), f->alfi_value_len); + printf(_("ATTRI: newvalue len:%u\n"), new_value_len); print_or_dump((char *)item->ri_buf[region].i_addr, len); } diff --git a/logprint/logprint.h b/logprint/logprint.h index 8867b110ecaf..9715cdb9e27b 100644 --- a/logprint/logprint.h +++ b/logprint/logprint.h @@ -59,8 +59,10 @@ extern void xlog_recover_print_bud(struct xlog_recover_item *item); #define MAX_ATTR_VAL_PRINT 128 extern int xlog_print_trans_attri(char **ptr, uint src_len, int *i); -extern int xlog_print_trans_attri_name(char **ptr, uint src_len); -extern int xlog_print_trans_attri_value(char **ptr, uint src_len, int value_len); +extern int xlog_print_trans_attri_name(char **ptr, uint src_len, + const char *tag); +extern int xlog_print_trans_attri_value(char **ptr, uint src_len, int value_len, + const char *tag); extern void xlog_recover_print_attri(struct xlog_recover_item *item); extern int xlog_print_trans_attrd(char **ptr, uint len); extern void xlog_recover_print_attrd(struct xlog_recover_item *item); From patchwork Tue Jul 2 01:11:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718833 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F381CBE5A for ; Tue, 2 Jul 2024 01:11:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882705; cv=none; b=uuCKvUoVv7U5ivhdWa49zGNQccToDNz6HmYbTdzOxiIYK4tF007ToNXpEr1bLQp2Y/QNMS0KqjIov5G7pReaAltZ/IQHAMWg0geg4wt/6ovENhCoshDhItnBcSJzchJf5CNXzwNrCSmuaog8c/Gahc7keGwTZ62tf3pXbPOMPzI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882705; c=relaxed/simple; bh=kM0sA3rB2LBZtgEhnYrAPe2vtkHPzHg+8/hQeQoXnXk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YXgCW8hIcs+MhD21GyjTkrRvRBYSGDPnRUFtuaVBtbmRYo8SzVOAJdD/GWFJPm98XmqPC2lXjoKE+qBtGB19+O6IhjYNgK46e3gSRdzxnla+uZDonyqU7mFXziYbkcrbOTDs1iciQ4nBwDHWgDuwn2c96N3RcP0E3Kr2DCN9qLU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WILGoIo1; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WILGoIo1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7A507C116B1; Tue, 2 Jul 2024 01:11:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882704; bh=kM0sA3rB2LBZtgEhnYrAPe2vtkHPzHg+8/hQeQoXnXk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=WILGoIo1JDn1QYNd25nAOk5R9UQITgkIoU1WodHMheWzHQS8hjBLgMTS2keqGfb+Y Q72yyP9io9xXsb6kI5QWBLogmQRhtzHuytrwQigRx9SbaBpFgmx6LkhCwxytI3W6zc yZc/Wc3pO3wauyqp0RnrsKbR2VNjRD6soc3Z5ESAcTomFLooRwdFDW2307NiXIfKME llGn3Gt5vH0rgN6XMkwYCV3Q0TFdWmk3cesrXD+b/iZ/AY0MQbNnjpkB8OuLtL2vCT D05SLTlvy7CFpNZ/iuDfaQtIxeEzPh0s+JfSCdJ6ZJm6wmW9c8yY4LIGsb8lf0dLUy zxWFvTXk+W9dg== Date: Mon, 01 Jul 2024 18:11:44 -0700 Subject: [PATCH 04/24] man: document the XFS_IOC_GETPARENTS ioctl From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121124.2009260.4591726766214900623.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Document how this new ioctl works. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- man/man2/ioctl_xfs_getparents.2 | 212 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 man/man2/ioctl_xfs_getparents.2 diff --git a/man/man2/ioctl_xfs_getparents.2 b/man/man2/ioctl_xfs_getparents.2 new file mode 100644 index 000000000000..5bb9b96a0c95 --- /dev/null +++ b/man/man2/ioctl_xfs_getparents.2 @@ -0,0 +1,212 @@ +.\" Copyright (c) 2019-2024 Oracle. All rights reserved. +.\" +.\" %%%LICENSE_START(GPLv2+_DOC_FULL) +.\" SPDX-License-Identifier: GPL-2.0-or-later +.\" %%%LICENSE_END +.TH IOCTL-XFS-GETPARENTS 2 2024-04-09 "XFS" +.SH NAME +ioctl_xfs_getparents \- query XFS directory parent information +.SH SYNOPSIS +.br +.B #include +.PP +.BI "int ioctl(int " fd ", XFS_IOC_GETPARENTS, struct xfs_getparents *" arg ); +.PP +.BI "int ioctl(int " fd ", XFS_IOC_GETPARENTS_BY_HANDLE, struct xfs_getparents_by_handle *" arg ); +.SH DESCRIPTION +This command is used to retrieve the directory parent pointers of either the +currently opened file or a file handle. +Parent pointers point upwards in the directory tree from a child file towards a +parent directories. +Each entry in a parent directory must have a corresponding parent pointer in +the child. + +Calling programs should allocate a large memory buffer and initialize a header +of the following form: +.PP +.in +4n +.nf +struct xfs_getparents { + struct xfs_attrlist_cursor gp_cursor; + __u16 gp_iflags; + __u16 gp_oflags; + __u32 gp_bufsize; + __u64 __pad; + __u64 gp_buffer; +}; + +struct xfs_getparents { + struct xfs_handle gph_handle; + struct xfs_getparents gph_request; +}; +.fi +.in + +.PP +The field +.I gp_cursor +tracks the progress of iterating through the parent pointers. +Calling programs must initialize this to zero before the first system call +and must not touch it after that. + +.PP +The field +.I gp_iflags +control the behavior of the query operation and provide more information +about the outcome of the operation. +There are no input flags currently defined; this field must be zero. + +.PP +The field +.I gp_oflags +contains information about the query itself. +Possibly output flags are: +.RS 0.4i +.TP +.B XFS_GETPARENTS_OFLAG_ROOT +The file queried was the root directory. +.TP +.B XFS_GETPARENTS_OFLAG_DONE +There are no more parent pointers to query. +.RE + +.PP +The field +.I __pad +must be zero. + +.PP +The field +.I gp_bufsize +should be set to the size of the buffer, in bytes. + +.PP +The field +.I gp_buffer +should point to an output buffer for the parent pointer records. + +Parent pointer records are returned in the following form: +.PP +.in +4n +.nf + +struct xfs_getparents_rec { + struct xfs_handle gpr_parent; + __u16 gpr_reclen; + char gpr_name[]; +}; +.fi +.in + +.PP +The field +.I gpr_parent +is a file handle that can be used to open the parent directory. + +.PP +The field +.I gpr_reclen +will be set to the number of bytes used by this parent record. + +.PP +The array +.I gpr_name +will be set to a NULL-terminated byte sequence representing the filename +stored in the parent pointer. +If the name is a zero-length string, the file queried has no parents. + +.SH SAMPLE PROGRAM +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 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 + +int main() { + struct xfs_getparents gp = { }; + struct xfs_getparents_rec *gpr; + int error, fd; + + gp.gp_buffer = (uintptr_t)malloc(65536); + if (!gp.gp_buffer) { + perror("malloc"); + return 1; + } + gp->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, gp); + if (error) + return error; + + for (gpr = xfs_getparents_first_rec(&gp); + gpr != NULL; + gpr = xfs_getparents_next_rec(&gp, gpr)) { + if (gpr->gpr_name[0] == 0) + break; + + printf("inode = %llu\\n", + gpr->gpr_parent.ha_fid.fid_ino); + printf("generation = %u\\n", + gpr->gpr_parent.ha_fid.fid_gen); + printf("name = \\"%s\\"\\n\\n", + gpr->gpr_name); + } + } while (!(gp.gp_flags & XFS_GETPARENTS_OFLAG_DONE)); + + return 0; +} +.fi + +.SH RETURN VALUE +On error, \-1 is returned, and +.I errno +is set to indicate the error. +.PP +.SH ERRORS +Error codes can be one of, but are not limited to, the following: +.TP +.B EFSBADCRC +Metadata checksum validation failed while performing the query. +.TP +.B EFSCORRUPTED +Metadata corruption was encountered while performing the query. +.TP +.B EINVAL +One or more of the arguments specified is invalid. +.TP +.B EMSGSIZE +The record buffer was not large enough to store even a single record. +.TP +.B ENOMEM +Not enough memory to retrieve parent pointers. +.TP +.B EOPNOTSUPP +Repairs of the requested metadata object are not supported. +.TP +.B EROFS +Filesystem is read-only and a repair was requested. +.TP +.B ESHUTDOWN +Filesystem is shut down due to previous errors. +.TP +.B EIO +An I/O error was encountered while performing the query. +.SH CONFORMING TO +This API is specific to XFS filesystem on the Linux kernel. +.SH SEE ALSO +.BR ioctl (2) From patchwork Tue Jul 2 01:11:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718834 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 82E506FCB for ; Tue, 2 Jul 2024 01:12:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882720; cv=none; b=jTIGIxoscRW6Xye5tM2wIn++HQwelReoWeqZOpP/djhrL2mo987CTFJp+OKm+bMySA6mm4ri+HfSt/cGs0mZZs2QVnCdGlpLaPZCUtKNP2pdskp5bCD6TlJYAOwJUtCr5GDpPi3SJrVElv7wz0admcOP4cfx6agAYb4Q12a9DqA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882720; c=relaxed/simple; bh=4pH0F1o51RC20cQd9Vm1JxX247NMtnxtzYPiQgc2/YA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BbSYOARozywiwwHFjxTY2zcoACu3zPa4Js5V6Gt9xWnzOZwT8wW6qP3kEI/ey4AzwzZ0EzKCQEqE0NcQ30H5nfnBkQUXgzd0FaRYh4uYVkJx2GqaANSpfHo0a/rQ9XOCt4e+iJLDhbwDDg5MFPmckTCr+FnyzUGXQ+GTI4aLu+k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kjoFvVN6; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kjoFvVN6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1D8FAC116B1; Tue, 2 Jul 2024 01:12:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882720; bh=4pH0F1o51RC20cQd9Vm1JxX247NMtnxtzYPiQgc2/YA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=kjoFvVN6NkxaLxBQWp5Ckmkh9ZmLSsbgmeQt+x9mOI0YjZDLbkoeAN+Kku6YLHiW+ h4OvNANW9/ciTEjoZxwyvagzHkcH0EiQo35bbaHPzsJOGojhtx9lDyQcqjCf77eK0m PbvG1sJMXcQKqQDUHDPiqvj/vdKPm6P+SRAofP2bOkcphihw3VHnAgtiKsoSx9ZlTB FsXt5GI1Y3LscCTnfMPC3LrLImTF++5JnJFdv80SSPK2EiNe3oVua4FPcHrvuq2/Uo 4nSIsic2/jcI+tsya+AjH5D9Y77LfUPktKJlJ5xPWKkAapoSCgdOh2abak97thGDvc tW5es6a2kdmNw== Date: Mon, 01 Jul 2024 18:11:59 -0700 Subject: [PATCH 05/24] libfrog: report parent pointers to userspace From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121139.2009260.15042250941832877051.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Report the presence of parent pointer to userspace. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- libfrog/fsgeom.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c index 71a8e4bb9980..597c38b11402 100644 --- a/libfrog/fsgeom.c +++ b/libfrog/fsgeom.c @@ -32,6 +32,7 @@ xfs_report_geom( int inobtcount; int nrext64; int exchangerange; + int parent; isint = geo->logstart > 0; lazycount = geo->flags & XFS_FSOP_GEOM_FLAGS_LAZYSB ? 1 : 0; @@ -51,6 +52,7 @@ xfs_report_geom( inobtcount = geo->flags & XFS_FSOP_GEOM_FLAGS_INOBTCNT ? 1 : 0; nrext64 = geo->flags & XFS_FSOP_GEOM_FLAGS_NREXT64 ? 1 : 0; exchangerange = geo->flags & XFS_FSOP_GEOM_FLAGS_EXCHANGE_RANGE ? 1 : 0; + parent = geo->flags & XFS_FSOP_GEOM_FLAGS_PARENT ? 1 : 0; printf(_( "meta-data=%-22s isize=%-6d agcount=%u, agsize=%u blks\n" @@ -60,7 +62,7 @@ xfs_report_geom( " =%-22s exchange=%-3u\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" +"naming =version %-14u bsize=%-6u ascii-ci=%d, ftype=%d, parent=%d\n" "log =%-22s bsize=%-6d blocks=%u, version=%d\n" " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"), @@ -72,7 +74,7 @@ xfs_report_geom( "", geo->blocksize, (unsigned long long)geo->datablocks, geo->imaxpct, "", geo->sunit, geo->swidth, - dirversion, geo->dirblocksize, cimode, ftype_enabled, + dirversion, geo->dirblocksize, cimode, ftype_enabled, parent, isint ? _("internal log") : logname ? logname : _("external"), geo->blocksize, geo->logblocks, logversion, "", geo->logsectsize, geo->logsunit / geo->blocksize, lazycount, From patchwork Tue Jul 2 01:12:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718835 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37E963C38 for ; Tue, 2 Jul 2024 01:12:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882736; cv=none; b=WcJSbOgIXNQnYjUV5Kp5AAoDmgFdIPi+ifp6ylDV2ypR2sJ1hmR7+ebnD2XUSZ4MnSH/hJIsxxo+nHrlKKyaTai27Mq6d4RyJnTMK4mNHoQTuFZ+E/I3ukB6V58a3Y0MiiniQBQ23lYdfaylGtCqZ2k7rdG6hL7mMSu+kNuPH3k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882736; c=relaxed/simple; bh=xrxj8DXM1ApaBQn4w3PcgqFK79WgIoCYdwgl7olxiIk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=d6vFlBwJsHFzqkQKqCuafHXiY9KD49hQDTA5b70Op/a8ua+rPElTwbXDFkHcbfaiop6TA0QhlQNrpdJ8iQQG1SzHk1MOmHLpzEh8uHZSwxoa/dq+LrIGfOOdHOIugO8B+URVcuU9SMIt74ChKwce3QexFITBUWsrfiww9k5tGVI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=U/U2LoSh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="U/U2LoSh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BCE8FC116B1; Tue, 2 Jul 2024 01:12:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882735; bh=xrxj8DXM1ApaBQn4w3PcgqFK79WgIoCYdwgl7olxiIk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=U/U2LoShcQpg/jV90Va9M8FLguIj5HGih8OptX8AmXSDPG0dys0wy+nmQJRQUQsdC KP2B+tF96ctBTRzT1Oyoq/uUg91xbPnuDMjUwNtlS/izQEc4ffEnHcpbTY5jcFUBVd PcIrBdw+lYg0Z3rZNDwkX5M4luj02rIyy6UKHLmBVCFwe9m6/3l0mJUz/FiMdKZsox 0bnGeY1uxpEK9JoEtm8D02dTHcXMUWCtAu/sA4hZdlHBw9p4QtrfO0xmL7Ay1FKkWD 8QgximSEwUKgXPTo+8tgDnnlOGE4eXvwMMEE4gpKFuK2uKnb2nnZGk0sibjLDEsgDx 1RARScd1bLW8A== Date: Mon, 01 Jul 2024 18:12:15 -0700 Subject: [PATCH 06/24] libfrog: add parent pointer support code From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121155.2009260.6759812584905155328.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: Christoph Hellwig --- include/handle.h | 1 libfrog/Makefile | 2 libfrog/getparents.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++ libfrog/getparents.h | 42 ++++++ libfrog/paths.c | 168 ++++++++++++++++++++++++ libfrog/paths.h | 25 ++++ libhandle/handle.c | 7 + 7 files changed, 597 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 34246f3854de..ba06500516cf 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 acfa228bc8ec..0b5b23893a13 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 \ @@ -46,6 +47,7 @@ dahashselftest.h \ div64.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 000000000000..9118b0ff32db --- /dev/null +++ b/libfrog/getparents.c @@ -0,0 +1,355 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2017-2024 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include "platform_defs.h" +#include "xfs.h" +#include "xfs_arch.h" +#include "list.h" +#include "paths.h" +#include "handle.h" +#include "libfrog/getparents.h" + +/* Allocate a buffer for the xfs_getparent_rec array. */ +static void * +alloc_records( + struct xfs_getparents *gp, + size_t bufsize) +{ + void *buf; + + if (bufsize >= UINT32_MAX) { + errno = ENOMEM; + return NULL; + } else if (!bufsize) { + bufsize = XFS_XATTR_LIST_MAX; + } + + buf = malloc(bufsize); + if (!buf) + return NULL; + + gp->gp_buffer = (uintptr_t)buf; + gp->gp_bufsize = bufsize; + return buf; +} + +/* Copy a file handle. */ +static inline void +copy_handle( + struct xfs_handle *dest, + const struct xfs_handle *src) +{ + memcpy(dest, src, sizeof(struct xfs_handle)); +} + +/* Initiate a callback for each parent pointer. */ +static int +walk_parent_records( + struct xfs_getparents *gp, + walk_parent_fn fn, + void *arg) +{ + struct xfs_getparents_rec *gpr; + int ret; + + if (gp->gp_oflags & XFS_GETPARENTS_OFLAG_ROOT) { + struct parent_rec rec = { + .p_flags = PARENTREC_FILE_IS_ROOT, + }; + + return fn(&rec, arg); + } + + for (gpr = xfs_getparents_first_rec(gp); + gpr != NULL; + gpr = xfs_getparents_next_rec(gp, gpr)) { + struct parent_rec rec = { }; + + if (gpr->gpr_name[0] == 0) + break; + + copy_handle(&rec.p_handle, &gpr->gpr_parent); + rec.p_name = gpr->gpr_name; + + ret = fn(&rec, arg); + if (ret) + return ret; + } + + return 0; +} + +/* Walk all parent pointers of this fd. Returns 0 or positive errno. */ +int +fd_walk_parents( + int fd, + size_t bufsize, + walk_parent_fn fn, + void *arg) +{ + struct xfs_getparents gp = { }; + void *buf; + int ret; + + buf = alloc_records(&gp, bufsize); + if (!buf) + return errno; + + while ((ret = ioctl(fd, XFS_IOC_GETPARENTS, &gp)) == 0) { + ret = walk_parent_records(&gp, fn, arg); + if (ret) + goto out_buf; + if (gp.gp_oflags & XFS_GETPARENTS_OFLAG_DONE) + break; + } + if (ret) + ret = errno; + +out_buf: + free(buf); + return ret; +} + +/* Walk all parent pointers of this handle. Returns 0 or positive errno. */ +int +handle_walk_parents( + const void *hanp, + size_t hlen, + size_t bufsize, + walk_parent_fn fn, + void *arg) +{ + struct xfs_getparents_by_handle gph = { }; + void *buf; + char *mntpt; + int fd; + int ret; + + if (hlen != sizeof(struct xfs_handle)) + return EINVAL; + + /* + * This function doesn't modify the handle, but we don't want to have + * to bump the libhandle major version just to change that. + */ + fd = handle_to_fsfd((void *)hanp, &mntpt); + if (fd < 0) + return errno; + + buf = alloc_records(&gph.gph_request, bufsize); + if (!buf) + return errno; + + copy_handle(&gph.gph_handle, hanp); + while ((ret = ioctl(fd, XFS_IOC_GETPARENTS_BY_HANDLE, &gph)) == 0) { + ret = walk_parent_records(&gph.gph_request, fn, arg); + if (ret) + goto out_buf; + if (gph.gph_request.gp_oflags & XFS_GETPARENTS_OFLAG_DONE) + break; + } + if (ret) + ret = errno; + +out_buf: + free(buf); + return ret; +} + +struct walk_ppaths_info { + /* Callback */ + walk_path_fn fn; + void *arg; + + /* Mountpoint of this filesystem. */ + char *mntpt; + + /* Path that we're constructing. */ + struct path_list *path; + + size_t ioctl_bufsize; +}; + +/* + * Recursively walk upwards through the directory tree, changing out the path + * components as needed. Call the callback when we have a complete path. + */ +static int +find_parent_component( + const struct parent_rec *rec, + void *arg) +{ + struct walk_ppaths_info *wpi = arg; + struct path_component *pc; + int ret; + + if (rec->p_flags & PARENTREC_FILE_IS_ROOT) + return wpi->fn(wpi->mntpt, wpi->path, wpi->arg); + + /* + * If we detect a directory tree cycle, give up. We never made any + * guarantees about concurrent tree updates. + */ + if (path_will_loop(wpi->path, rec->p_handle.ha_fid.fid_ino)) + return 0; + + pc = path_component_init(rec->p_name, rec->p_handle.ha_fid.fid_ino); + if (!pc) + return errno; + path_list_add_parent_component(wpi->path, pc); + + ret = handle_walk_parents(&rec->p_handle, sizeof(rec->p_handle), + wpi->ioctl_bufsize, find_parent_component, wpi); + + path_list_del_component(wpi->path, pc); + path_component_free(pc); + 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_paths( + const void *hanp, + size_t hlen, + size_t ioctl_bufsize, + walk_path_fn fn, + void *arg) +{ + struct walk_ppaths_info wpi = { + .ioctl_bufsize = ioctl_bufsize, + }; + int ret; + + /* + * This function doesn't modify the handle, but we don't want to have + * to bump the libhandle major version just to change that. + */ + ret = handle_to_fsfd((void *)hanp, &wpi.mntpt); + if (ret < 0) + return errno; + + wpi.path = path_list_init(); + if (!wpi.path) + return errno; + wpi.fn = fn; + wpi.arg = arg; + + ret = handle_walk_parents(hanp, hlen, ioctl_bufsize, + find_parent_component, &wpi); + + 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_paths( + int fd, + size_t ioctl_bufsize, + walk_path_fn fn, + void *arg) +{ + void *hanp; + size_t hlen; + int ret; + + ret = fd_to_handle(fd, &hanp, &hlen); + if (ret) + return errno; + + ret = handle_walk_paths(hanp, hlen, ioctl_bufsize, fn, arg); + free_handle(hanp, hlen); + return ret; +} + +struct gather_path_info { + char *buf; + size_t len; + size_t written; +}; + +/* Helper that stringifies the first full path that we find. */ +static int +path_to_string( + const char *mntpt, + const struct path_list *path, + void *arg) +{ + struct gather_path_info *gpi = 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(gpi->buf, gpi->len, "%.*s", mntpt_len, mntpt); + if (ret != mntpt_len) + return ENAMETOOLONG; + gpi->written += ret; + + ret = path_list_to_string(path, gpi->buf + ret, gpi->len - ret); + if (ret < 0) + return ENAMETOOLONG; + + gpi->written += ret; + return ECANCELED; +} + +/* + * Return any eligible path to this file handle. Returns 0 for success or + * positive errno. + */ +int +handle_to_path( + const void *hanp, + size_t hlen, + size_t ioctl_bufsize, + char *path, + size_t pathlen) +{ + struct gather_path_info gpi = { .buf = path, .len = pathlen }; + int ret; + + ret = handle_walk_paths(hanp, hlen, ioctl_bufsize, path_to_string, + &gpi); + if (ret && ret != ECANCELED) + return ret; + if (!gpi.written) + return ENODATA; + + path[gpi.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, + size_t ioctl_bufsize, + char *path, + size_t pathlen) +{ + struct gather_path_info gpi = { .buf = path, .len = pathlen }; + int ret; + + ret = fd_walk_paths(fd, ioctl_bufsize, path_to_string, &gpi); + if (ret && ret != ECANCELED) + return ret; + if (!gpi.written) + return ENODATA; + + path[gpi.written] = 0; + return 0; +} diff --git a/libfrog/getparents.h b/libfrog/getparents.h new file mode 100644 index 000000000000..8098d594219b --- /dev/null +++ b/libfrog/getparents.h @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023-2024 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#ifndef __LIBFROG_GETPARENTS_H_ +#define __LIBFROG_GETPARENTS_H_ + +struct path_list; + +struct parent_rec { + /* File handle to parent directory */ + struct xfs_handle p_handle; + + /* Null-terminated directory entry name in the parent */ + char *p_name; + + /* Flags for this record; see PARENTREC_* below */ + uint32_t p_flags; +}; + +/* This is the root directory. */ +#define PARENTREC_FILE_IS_ROOT (1U << 0) + +typedef int (*walk_parent_fn)(const struct parent_rec *rec, void *arg); + +int fd_walk_parents(int fd, size_t ioctl_bufsize, walk_parent_fn fn, void *arg); +int handle_walk_parents(const void *hanp, size_t hanlen, size_t ioctl_bufsize, + walk_parent_fn fn, void *arg); + +typedef int (*walk_path_fn)(const char *mntpt, const struct path_list *path, + void *arg); + +int fd_walk_paths(int fd, size_t ioctl_bufsize, walk_path_fn fn, void *arg); +int handle_walk_paths(const void *hanp, size_t hanlen, size_t ioctl_bufsize, + walk_path_fn fn, void *arg); + +int fd_to_path(int fd, size_t ioctl_bufsize, char *path, size_t pathlen); +int handle_to_path(const void *hanp, size_t hlen, size_t ioctl_bufsize, + char *path, size_t pathlen); + +#endif /* __LIBFROG_GETPARENTS_H_ */ diff --git a/libfrog/paths.c b/libfrog/paths.c index 320b26dbf25b..a5dfab48ec1e 100644 --- a/libfrog/paths.c +++ b/libfrog/paths.c @@ -16,6 +16,7 @@ #include "input.h" #include "projects.h" #include +#include "list.h" #include extern char *progname; @@ -560,3 +561,170 @@ 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); +} + +/* 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; +} + +/* Will this path contain a loop if we add this inode? */ +bool +path_will_loop( + const struct path_list *path_list, + uint64_t ino) +{ + struct path_component *pc; + unsigned int nr = 0; + + list_for_each_entry(pc, &path_list->p_head, pc_list) { + if (pc->pc_ino == ino) + return true; + + /* 256 path components should be enough for anyone. */ + if (++nr > 256) + return true; + } + + return false; +} diff --git a/libfrog/paths.h b/libfrog/paths.h index f20a2c3ef582..306fd3cb8fde 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); + +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); + +bool path_will_loop(const struct path_list *path, uint64_t ino); + #endif /* __LIBFROG_PATH_H__ */ diff --git a/libhandle/handle.c b/libhandle/handle.c index 333c21909007..1e8fe9ac5f10 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 Tue Jul 2 01:12:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718836 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF0984436 for ; Tue, 2 Jul 2024 01:12:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882751; cv=none; b=cMtc/nSwDf5NMOnJFcG4E7mU70AHCszldO617Gi5rSLFAPDxHi0sgsrDljWlir4OCkeQKUKQ9s382OF3WsiDODGugiTochAIMXYkVk9wH1vVttUXknGrP3naMeD+BhddfyH6UI4e2WMLiYfqMGAoA3QYykaaW0WQ6mkbtvqZGng= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882751; c=relaxed/simple; bh=0tf2oWYYeMll0EL0sEn9S3WLSDvj+JrqkWKCrmkqUoU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DTotMhOj5NfIGbbd2PeZxxAPhzvNOz99qtroQsY3PnTyDXQ6PAYGKBaOgPdtf2WkKe9+Hg9NZCYtz29v77jN9FSFPbdyL1zWKHQjQICyiDBBEKOedKF5IuXc/aUZh9foO6HjnmgZa15CDBpJwjE3o48S2TihbF9pYuVhR9WIWkU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=o52A51q8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="o52A51q8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 76731C116B1; Tue, 2 Jul 2024 01:12:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882751; bh=0tf2oWYYeMll0EL0sEn9S3WLSDvj+JrqkWKCrmkqUoU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=o52A51q8lgHUdFv4oE+GTwsWzGwCSSnkCHKEj5NbOqg8nWl/PGrLqjYLCBMdC2Wbf gpfEw16aXPEBJIa2AbbJcPrsa0apmLDHAoOHVO0l0e7uOwoCde72kbfV9GDnL3NRh0 GwBLN2C+PZ+0mhMdYvPfQ4nd19yF0+s1Knjz7FlygLVu1S7Ne/Lmpu3IGrWL26LFpb BhVrzUq2y0EZuqQjgXlkqFrM9nggm8aVwN/suaMPUBn3e5K6EDPJe4tVN45Ywy50Ze G2nhX0hBv8s27RlZsjKe3ZDKY5vRPcceEiM/KhImvRt5smpSda3r0xLgDnUlNTaF5n wgyURPc20Lznw== Date: Mon, 01 Jul 2024 18:12:30 -0700 Subject: [PATCH 07/24] xfs_io: adapt parent command to new parent pointer ioctls From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121170.2009260.13120086561599609138.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 Reviewed-by: Christoph Hellwig --- io/parent.c | 504 +++++++++++++++-------------------------------------- man/man8/xfs_io.8 | 25 ++- 2 files changed, 161 insertions(+), 368 deletions(-) diff --git a/io/parent.c b/io/parent.c index 8f63607ffec2..927d05d70b0c 100644 --- a/io/parent.c +++ b/io/parent.c @@ -7,365 +7,88 @@ #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) -{ - 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); - } - - /* 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); - } - } - } -} - -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++; - } - - entryp = parentbuf; - for (i = 0; i < count; i++) { - check_parent_entry(statp, entryp); - entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen); - } -} - -static int -do_bulkstat(parent_t *parentbuf, size_t *parentbuf_size, - struct xfs_bstat *bstatbuf, int fsfd, jdm_fshandle_t *fshandlep) -{ - __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); - } - - }/*while*/ - - fprintf(stderr, _("syssgi bulkstat failed: %s\n"), strerror(errno)); - return 1; -} +struct pptr_args { + char *pathbuf; +}; static int -parent_check(void) +pptr_print( + const struct parent_rec *rec, + void *arg) { - int fsfd; - jdm_fshandle_t *fshandlep; - parent_t *parentbuf; - size_t parentbuf_size = PARENTBUF_SZ; - struct xfs_bstat *bstatbuf; + const struct xfs_fid *fid = &rec->p_handle.ha_fid; - 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; + if (rec->p_flags & PARENTREC_FILE_IS_ROOT) { + printf(_("Root directory.\n")); + return 0; } - /* 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++; - - if (err_status > 0) - fprintf(stderr, _("num errors: %d\n"), err_status); - else - printf(_("succeeded checking %llu inodes\n"), - (unsigned long long) inodes_checked); - -out: - free(bstatbuf); - free(parentbuf); - free(fshandlep); - return err_status; -} + printf(_("p_ino = %llu\n"), (unsigned long long)fid->fid_ino); + printf(_("p_gen = %u\n"), (unsigned int)fid->fid_gen); + printf(_("p_namelen = %zu\n"), strlen(rec->p_name)); + printf(_("p_name = \"%s\"\n\n"), rec->p_name); -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); + return 0; } static int -parent_list(int fullpath) +paths_print( + const char *mntpt, + const struct path_list *path, + void *arg) { - 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; - - /* 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; + struct pptr_args *args = arg; + char *buf = args->pathbuf; + size_t len = MAXPATHLEN; + 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(buf, len, "%.*s", mntpt_len, mntpt); + if (ret != mntpt_len) + return ENAMETOOLONG; + + ret = path_list_to_string(path, buf + ret, len - ret); + if (ret < 0) + return ENAMETOOLONG; + + printf("%s\n", buf); + 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; + char pathbuf[MAXPATHLEN + 1]; + struct pptr_args args = { + .pathbuf = pathbuf, + }; + 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; + size_t ioctl_bufsize = 8192; + bool single_path = false; + static int tab_init; if (!tab_init) { tab_init = 1; @@ -380,46 +103,110 @@ 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, "b:pz")) != EOF) { switch (c) { - case 'c': - check_flag = 1; + case 'b': + errno = 0; + ioctl_bufsize = atoi(optarg); + if (errno) { + perror(optarg); + exitcode = 1; + return 1; + } break; case 'p': listpath_flag = 1; break; - case 'v': - verbose_flag++; + case 'z': + single_path = true; 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 (single_path) { + if (ino) + ret = handle_to_path(&handle, sizeof(handle), + ioctl_bufsize, pathbuf, MAXPATHLEN); + else + ret = fd_to_path(file->fd, ioctl_bufsize, + pathbuf, MAXPATHLEN); + if (!ret) + printf("%s\n", pathbuf); + } else if (listpath_flag) { + if (ino) + ret = handle_walk_paths(&handle, sizeof(handle), + ioctl_bufsize, paths_print, &args); + else + ret = fd_walk_paths(file->fd, ioctl_bufsize, + paths_print, &args); + } else { + if (ino) + ret = handle_walk_parents(&handle, sizeof(handle), + ioctl_bufsize, pptr_print, &args); + else + ret = fd_walk_parents(file->fd, ioctl_bufsize, + pptr_print, &args); + } + + if (hanp) + free_handle(hanp, hlen); + if (ret) { + exitcode = 1; + fprintf(stderr, "%s: %s\n", file->name, strerror(ret)); + } 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" +" -b -- use this many bytes to hold parent pointer records\n" +" -p -- list the current file's paths up to the root\n" +" -z -- print only the first path from the root\n" +"\n" +"If ino and gen are supplied, use them instead.\n" "\n")); } @@ -430,11 +217,10 @@ parent_init(void) parent_cmd.cfunc = parent_f; parent_cmd.argmin = 0; parent_cmd.argmax = -1; - parent_cmd.args = _("[-cpv]"); + parent_cmd.args = _("[-pz] [-b bufsize] [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 2a7c67f7cf3a..b9d5447703fc 100644 --- a/man/man8/xfs_io.8 +++ b/man/man8/xfs_io.8 @@ -1004,25 +1004,32 @@ and options behave as described above, in .B chproj. .TP -.BR parent " [ " \-cpv " ]" +.BR parent " [ " \-pz " ] [ " \-b " bufsize ] [" " 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 \-b +Use a buffer of this size to receive parent pointer records from the kernel. +.TP .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.] +.B \-z +Print only the first path from the root. .RE .PD .TP From patchwork Tue Jul 2 01:12:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718837 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 825006FCB for ; Tue, 2 Jul 2024 01:12:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882767; cv=none; b=P8tEcXaEu2tkVwKWwfDnGU1EV7muNuup80QEa7vnyS2Kb3S4iAKr0nLNDpdQ42lh/dPV25tFLL2G4mM0XhV3HYjI/dt7fOSyR74M9/sakiB/HYUF6kTukMt2X2F9Q8LinkhlDC+0G95AxQDTbInGbWCZkO2bRjbmMRzT0YWRPMk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882767; c=relaxed/simple; bh=LCcWDjxTgvVnIzW8Xj7JafJCfBgAovgIlGnKXCFbF2U=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LSA57d365oNiFtIfht+fTqH7zZrwf0duF0PS0HAnAlcBnSxjTy+HInJlS+gH4X3OrwegFflCr+vOYfkwCuI4nMOgM6TRj1GGx3AoMfIbZG3Hbd3WD2tgwupp9/1Rya5d27bzx3YzFlitR2NXomkQ9vUT4S3IuXTXmUF2ucQ70o0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jeoltbar; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jeoltbar" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 227C3C116B1; Tue, 2 Jul 2024 01:12:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882767; bh=LCcWDjxTgvVnIzW8Xj7JafJCfBgAovgIlGnKXCFbF2U=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=jeoltbarkhR3gsyBnn2xm6bHdMMJMDi343RwtUNDJUXfbnhuJxzPEmx9LbpZ8g1fq VhvYtdWuNl3Q4/3lYqTWOj+IIQm02UULhsZvwMLYSUc23GjrV0E1BolzBK1cJNhazv JkAPUVr2Rwpg8mYIhaUljphmFVxwXKHEl4Tm4q+drbHRPXhcAO7BUHZdCyyRir/cqn CQLZU3EQDp9UvO5fFRWMu8kCBHIvtV5g8BCO9qjGS+S4q7IlojIrzg6s2yjiiLAW/V s/XCxwNMFCSWiY5VStRXgHvCX01P3IMSMmvyXaDIgto6FLn0/MUsa65Hxf7OcFf0PB A/IBZP0Nsi0Gw== Date: Mon, 01 Jul 2024 18:12:46 -0700 Subject: [PATCH 08/24] 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 , catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121186.2009260.9875037290460504464.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 Reviewed-by: Christoph Hellwig --- io/parent.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++-- man/man8/xfs_io.8 | 13 ++++++++++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/io/parent.c b/io/parent.c index 927d05d70b0c..8db93d987552 100644 --- a/io/parent.c +++ b/io/parent.c @@ -17,6 +17,9 @@ static char *mntpt; struct pptr_args { char *pathbuf; + char *filter_name; + uint64_t filter_ino; + bool shortformat; }; static int @@ -25,12 +28,27 @@ pptr_print( void *arg) { const struct xfs_fid *fid = &rec->p_handle.ha_fid; + struct pptr_args *args = arg; if (rec->p_flags & PARENTREC_FILE_IS_ROOT) { printf(_("Root directory.\n")); return 0; } + if (args->filter_ino && fid->fid_ino != args->filter_ino) + return 0; + if (args->filter_name && strcmp(args->filter_name, rec->p_name)) + return 0; + + if (args->shortformat) { + printf("%llu:%u:%zu:%s\n", + (unsigned long long)fid->fid_ino, + (unsigned int)fid->fid_gen, + strlen(rec->p_name), + rec->p_name); + return 0; + } + printf(_("p_ino = %llu\n"), (unsigned long long)fid->fid_ino); printf(_("p_gen = %u\n"), (unsigned int)fid->fid_gen); printf(_("p_namelen = %zu\n"), strlen(rec->p_name)); @@ -39,6 +57,21 @@ pptr_print( 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 paths_print( const char *mntpt, @@ -51,6 +84,12 @@ paths_print( 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--; @@ -103,7 +142,7 @@ parent_f( } mntpt = fs->fs_dir; - while ((c = getopt(argc, argv, "b:pz")) != EOF) { + while ((c = getopt(argc, argv, "b:i:n:psz")) != EOF) { switch (c) { case 'b': errno = 0; @@ -114,9 +153,24 @@ parent_f( return 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); + exitcode = 1; + return 1; + } + break; + case 'n': + args.filter_name = optarg; + break; case 'p': listpath_flag = 1; break; + case 's': + args.shortformat = true; + break; case 'z': single_path = true; break; @@ -203,7 +257,10 @@ printf(_( " list the current file's parents and their filenames\n" "\n" " -b -- use this many bytes to hold parent pointer records\n" +" -i -- Only show parent pointer records containing the given inode\n" +" -n -- Only show parent pointer records containing the given filename\n" " -p -- list the current file's paths up to the root\n" +" -s -- Print records in short format: ino/gen/namelen/filename\n" " -z -- print only the first path from the root\n" "\n" "If ino and gen are supplied, use them instead.\n" @@ -217,7 +274,7 @@ parent_init(void) parent_cmd.cfunc = parent_f; parent_cmd.argmin = 0; parent_cmd.argmax = -1; - parent_cmd.args = _("[-pz] [-b bufsize] [ino gen]"); + parent_cmd.args = _("[-psz] [-b bufsize] [-i ino] [-n name] [ino gen]"); 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 b9d5447703fc..02036e3d093b 100644 --- a/man/man8/xfs_io.8 +++ b/man/man8/xfs_io.8 @@ -1004,7 +1004,7 @@ and options behave as described above, in .B chproj. .TP -.BR parent " [ " \-pz " ] [ " \-b " bufsize ] [" " ino gen " "]" +.BR parent " [ " \-fpz " ] [ " \-b " bufsize ] [ " \-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. @@ -1023,11 +1023,20 @@ the open file. .TP 0.4i .B \-b Use a buffer of this size to receive parent pointer records from the kernel. -.TP +.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. .TP +.B \-s +Print records in short format: ino/gen/namelen/name +.TP .B \-z Print only the first path from the root. .RE From patchwork Tue Jul 2 01:13:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718838 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4C96379CC for ; Tue, 2 Jul 2024 01:13:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882783; cv=none; b=th0C55xyTH+F2fPVMd81fkLR/DreY2rh4yjwtbUr7XNxbdL7roiLErqbB1o6s+VmHEegI6Z0HomBI/tZXDlqP0bIgybwAbDyu7VyGzptxXsTmeYHA7XwWuHxJpG2/7Ty1hRWB6a38QdFUH0KIT2gEQihTqL3Rcg3EQfoLp93fx8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882783; c=relaxed/simple; bh=XYWAKG9CVPIfRSWwPd/1KkWYR0++suMMkcFKP/cvl0w=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oVGPkyXPtR6Qi5IrQi5HwqiLfP6SmzHZ7QZO9fOZx9ABXQ8bSYY7g63qrzSJerI+gfKHpb0hMJzLjRW2wwABNZrXQgBvbh99r6tnF7p7fxB6yW05xPC3/wgM93+WOHqTWYaypspKy1QgiNNsKYwte2TN9h/UXkNUui+ona+CXOE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZouVzsTL; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ZouVzsTL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B8503C116B1; Tue, 2 Jul 2024 01:13:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882782; bh=XYWAKG9CVPIfRSWwPd/1KkWYR0++suMMkcFKP/cvl0w=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ZouVzsTLrExh65mX/z3B+fF5yxXQCdQeZ5azrItgzPOysRJebyspDCAQTJv77QF1N renxgSGDeBY2LU0RD78mn+gc2sJrelYF4kwSD18R26BQDFUsAt8FMXAL4ADXb1Lytz E12cHYGyZTfZgSa3nJ10vfY3H9dn/9JDYHORmbqBNGRQ/fH8OvGJdbXSY0ovr9KE9Z CeuYxv/LtQDVLLG7RC93qP6BsItjxxno913LeStJkB4sQjR1SHJnVIQhw6N6ML7H2x NugaXXRvhWSD+dKXG0YmnS1J2eT6Wgg9ZcaMF8vMgj9JPJWqWVxrRREE7xg0heg9Ud fmAqP1y2wGh1w== Date: Mon, 01 Jul 2024 18:13:02 -0700 Subject: [PATCH 09/24] xfs_logprint: decode parent pointers in ATTRI items fully From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121202.2009260.6158755392578479304.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 Reviewed-by: Christoph Hellwig --- libxfs/libxfs_api_defs.h | 3 ++ logprint/log_redo.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index c36a6ac81a7b..b7947591d2db 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -190,6 +190,9 @@ #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_start libxfs_parent_start #define xfs_perag_get libxfs_perag_get #define xfs_perag_hold libxfs_perag_hold #define xfs_perag_put libxfs_perag_put diff --git a/logprint/log_redo.c b/logprint/log_redo.c index 1d55164a90ff..684e5f4a3f32 100644 --- a/logprint/log_redo.c +++ b/logprint/log_redo.c @@ -674,6 +674,55 @@ 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) +{ + const struct xfs_parent_rec *rec = value_ptr; + + if (value_len < sizeof(struct xfs_parent_rec)) { + printf("PPTR: %s CORRUPT\n", tag); + return; + } + + printf("PPTR: %s attr_namelen %u attr_valuelen %u\n", tag, name_len, value_len); + printf("PPTR: %s parent_ino %llu parent_gen %u name '%.*s'\n", + tag, + (unsigned long long)be64_to_cpu(rec->p_ino), + (unsigned int)be32_to_cpu(rec->p_gen), + name_len, + (char *)name_ptr); +} + +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 +737,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; @@ -742,6 +795,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) @@ -753,6 +807,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) @@ -764,6 +819,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) @@ -775,12 +831,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); @@ -823,6 +886,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; @@ -874,6 +941,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) { @@ -881,6 +949,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) { @@ -889,6 +958,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) { @@ -897,8 +967,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 Tue Jul 2 01:13:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718839 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C0AD8B66E for ; Tue, 2 Jul 2024 01:13:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882798; cv=none; b=RzBsmXZc2G0IHFO+faR43C+Fa9pvK0Bu+Z0lB0NntGEJkt+P6kXtH++CKI/7+WHMnYrj41QMPqxEcWXCwYMlAYBwAoSxGhqCd9qGi50DDGD9cen8GrTu9CaSrS7BsXZqasIA7AJ/K/cCwQSr2YgHEVl2O4YAHQavqwGn0Iivdr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882798; c=relaxed/simple; bh=lXtzBXzTNvbiaFXJdR7M1sBwBTlCLj1ZQZ7U+KmghNk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=OtQLugRPuHupPZn4TgfFEmOiKcUvg3+jsn8cnVjf3xN+OqciQz/Rys028VwGO1+M98e1T6tTFnhAI9u41+VxJ1FikOSKLr9pgOroZC1s+wmSvtFRt4kZM5Nhwb0P+OPtj4rSBxulW4A4aBlQCCzjR9SEmnLI4ltXym0pyGGfMCw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FFZJ/d8I; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FFZJ/d8I" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5E441C116B1; Tue, 2 Jul 2024 01:13:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882798; bh=lXtzBXzTNvbiaFXJdR7M1sBwBTlCLj1ZQZ7U+KmghNk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=FFZJ/d8Ib7ObY78dEtL/pZN11kX4xgelJL4GGsFafXEorrVijGRicbuQ/uay3PaWa nfa2AuQ9cWY3dj9J+g5kIUKW5XqRLk3LrXndzmRIgBzWj8i6lwZSsC1hH1ulumZYaq He/5k3Biy7j/1RxGaLB35QHoC7q89U9zMz++sT9VtSFtF/lOTIvlSPKRzJ0rHiu7Sy 9SaIu7zJ27opJJim9dxxVZcVhV8Cj6Bo3K9r0ulbFZk94NtE3/TodX5x6FgmBgK3DG 1uQcHiDDoy4YAGdAPQgGHINh3athlE3cZfrSbs5rMUe2dMUZdPx8S5GhbcyLNbhPVT MOn+GU/a38P4Q== Date: Mon, 01 Jul 2024 18:13:17 -0700 Subject: [PATCH 10/24] xfs_spaceman: report file paths From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121217.2009260.18429552066421688989.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Teach the health command to report file paths when possible. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- man/man8/xfs_spaceman.8 | 7 +++++- spaceman/Makefile | 16 +++++++++++--- spaceman/file.c | 7 ++++++ spaceman/health.c | 53 ++++++++++++++++++++++++++++++++++++++--------- spaceman/space.h | 3 +++ 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/man/man8/xfs_spaceman.8 b/man/man8/xfs_spaceman.8 index ece840d7300a..0d299132a788 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 1f048d54a4d2..358db9edf5cb 100644 --- a/spaceman/Makefile +++ b/spaceman/Makefile @@ -6,12 +6,20 @@ TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_spaceman -HFILES = init.h space.h -CFILES = info.c init.c file.c health.c prealloc.c trim.c +HFILES = \ + init.h \ + space.h +CFILES = \ + file.c \ + health.c \ + info.c \ + init.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 eec7ee9f4ba9..850688ace15d 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 88b12c0b0ea3..6722babf5888 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) { @@ -265,6 +267,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), 0, + 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. @@ -274,7 +308,6 @@ report_bulkstat_health( xfs_agnumber_t agno) { struct xfs_bulkstat_req *breq; - char descr[256]; uint32_t i; int error; @@ -292,13 +325,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) @@ -308,7 +336,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 @@ -323,6 +351,7 @@ health_f( int ret; reported = 0; + report_paths = false; if (file->xfd.fsgeom.version != XFS_FSOP_GEOM_VERSION_V5) { perror("health"); @@ -358,6 +387,9 @@ health_f( return 1; } break; + case 'n': + report_paths = true; + break; case 'q': quiet = true; break; @@ -445,6 +477,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")); @@ -456,7 +489,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 723209edd998..28fa35a30479 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 Tue Jul 2 01:13:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718840 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 461459449 for ; Tue, 2 Jul 2024 01:13:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882814; cv=none; b=QJpLwUPvU9IhKMdbeaEOKm2h4yduxZro6NNu7pbvRdZ4U91IK/Wt4wV9HD85ng9AsS44Pi4+CuG3TrizV4ZHxp2mQ97RxDeeDp3hUcwoJQAyRYL14QssJo1MYLhHRJr421OZ81n9H/j8Akddho8/oN+VJDRCh7Yz49TBU++wrWo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882814; c=relaxed/simple; bh=VPywzmkvVhI8y9iWxPSYdUURV04jNhKfIULxEyLIndo=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=p/4iflmPqYdP44dx5qpTzezR2+3qFfYmOhOIrN+ZWRuL5G4ybuBE5EHGRFYE1dONQ2kqboGVW9T76gslu3CvU/xfStElBTs5sRQjYLqco/owi+tWdnmxy3mC9r6ersX5t91C2oTzbw2w1/9kxI2bN6iZSsGC/ldzpvhh7TGhS4A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uN6sKxBf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uN6sKxBf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 129B2C116B1; Tue, 2 Jul 2024 01:13:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882814; bh=VPywzmkvVhI8y9iWxPSYdUURV04jNhKfIULxEyLIndo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=uN6sKxBfBblbvtUY2VT6+NYD7ogufJ8+0+HL78YNhayenMh9t3yosUf/oJZBmcbp5 BwWS6ZIAai2/D9NSpmUMtmY76FJ29PzSVUx3n9P5st3WF2HuBP34qh6XhdUXrtlq2w lJEhVm5tH295UdAbfuiTkaf9mzDj2macqesgaQEMLjHmxccX0fjGRTo2n8q9Edrh76 CXmvK8Rkx1WGfyo5xQIG3rOFNR6UT5PnBg94NpBn2kv9S4xN7UTfG0M/QA8BYeEWjv htsLyj+JZr+3kpKdy7lNhghsRL+UkbSlVqbhH+4ORjTTXw3+9UTtqKrk/z/FDnuTDN 5RXJSS0s1i1rg== Date: Mon, 01 Jul 2024 18:13:33 -0700 Subject: [PATCH 11/24] xfs_scrub: use parent pointers when possible to report file operations From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121232.2009260.944702210373077283.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 Reviewed-by: Christoph Hellwig --- scrub/common.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/scrub/common.c b/scrub/common.c index aca596487113..f86546556f46 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" @@ -405,19 +406,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), 4096, + 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 Tue Jul 2 01:13:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718841 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E1086B64A for ; Tue, 2 Jul 2024 01:13:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882830; cv=none; b=NqX1IhW5ab+Ig/RIcXsLL0am22dLbxjdF90ix6tqMKuHw0TZ6JSVAX7KPjz1EKoV4DUuocdEKzvKQkJvsfdFs3x6sWfwz+7s1ClWXIOo2F/Rhnb2/jrpvvCub+yO9+gN34uyyRdaGI0RpMsTdD58dPnyzis987p3vvfIcqWisAo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882830; c=relaxed/simple; bh=M5oLKLzDHuQZAm6KPyy4q/Sf5bAiLLsP/lsfmmT7FSs=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ub1kRlxchxUWfxssp3i0MUpv7u2Ul6ZdXbCDcgz+oo02+/fZ1BmANduFDrJ2uLRv3GMD/03qtB8kFov9R0uK0ToTvNBiKSVnWlh+rtsK2IM75Z4O0IPo2vxXlTY9gbUkPkHGMpRxGN1BRuSECLEgNVQT+vAq15VVSy60b5iaEH4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SVwsqxdu; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SVwsqxdu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B3171C116B1; Tue, 2 Jul 2024 01:13:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882829; bh=M5oLKLzDHuQZAm6KPyy4q/Sf5bAiLLsP/lsfmmT7FSs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=SVwsqxduC4gPPTohlojYV5kUBqbaJP8EiEVQztCj7tU8blPlo+P8jFqwUjwrhHjkw CZZOKoGe+qgMJ/FdOOIGt4r2O8oEVFkCUGz6jYuGEb6YYQSw+nB89ALW/yNPTY4Dw0 iv8UZMIdSSF1n0Bo5MbMJSGk9wA46tfZkifOLtp/OKaGC+3GmUpc9W3QO6iSZ26yRR Fs0GSOlptuoRlP1EDQ6q5Yukly4DjCs8lUlp52sFGLIabLzS7fRKnnvUtJWFbYjeX/ tNKlPOF3+8Ao4w8AhOe8uYN4cJjcJx6HhnhLl39RtX91kCp+PdVKDSXh4uzg+NRh1G DR0yh01/65Mjw== Date: Mon, 01 Jul 2024 18:13:49 -0700 Subject: [PATCH 12/24] xfs_scrub: use parent pointers to report lost file data From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121248.2009260.17262926858268275665.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong If parent pointers are enabled, compute the path to the file while we're doing the fsmap scan and report that, instead of walking the entire directory tree to print the paths of the (hopefully few) files that lost data. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- scrub/phase6.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/scrub/phase6.c b/scrub/phase6.c index 193d3b4e9083..a61853019e29 100644 --- a/scrub/phase6.c +++ b/scrub/phase6.c @@ -22,6 +22,7 @@ #include "spacemap.h" #include "vfs.h" #include "common.h" +#include "libfrog/bulkstat.h" /* * Phase 6: Verify data file integrity. @@ -381,6 +382,24 @@ report_dirent_loss( return error; } +struct ioerr_filerange { + uint64_t physical; + uint64_t length; +}; + +/* + * If reverse mapping and parent pointers are enabled, we can map media errors + * directly back to a filename and a file position without needing to walk the + * directory tree. + */ +static inline bool +can_use_pptrs( + const struct scrub_ctx *ctx) +{ + return (ctx->mnt.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_PARENT) && + (ctx->mnt.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_RMAPBT); +} + /* Use a fsmap to report metadata lost to a media error. */ static int report_ioerr_fsmap( @@ -389,16 +408,18 @@ report_ioerr_fsmap( void *arg) { const char *type; + struct xfs_bulkstat bs = { }; char buf[DESCR_BUFSZ]; - uint64_t err_physical = *(uint64_t *)arg; + struct ioerr_filerange *fr = arg; uint64_t err_off; + int ret; /* Don't care about unwritten extents. */ if (map->fmr_flags & FMR_OF_PREALLOC) return 0; - if (err_physical > map->fmr_physical) - err_off = err_physical - map->fmr_physical; + if (fr->physical > map->fmr_physical) + err_off = fr->physical - map->fmr_physical; else err_off = 0; @@ -421,23 +442,43 @@ report_ioerr_fsmap( } } + if (can_use_pptrs(ctx)) { + ret = -xfrog_bulkstat_single(&ctx->mnt, map->fmr_owner, 0, &bs); + if (ret) + str_liberror(ctx, ret, + _("bulkstat for media error report")); + } + /* Report extent maps */ if (map->fmr_flags & FMR_OF_EXTENT_MAP) { bool attr = (map->fmr_flags & FMR_OF_ATTR_FORK); scrub_render_ino_descr(ctx, buf, DESCR_BUFSZ, - map->fmr_owner, 0, " %s", + map->fmr_owner, bs.bs_gen, " %s", attr ? _("extended attribute") : _("file data")); str_corrupt(ctx, buf, _("media error in extent map")); } /* - * XXX: If we had a getparent() call we could report IO errors - * efficiently. Until then, we'll have to scan the dir tree - * to find the bad file's pathname. + * If directory parent pointers are available, use that to find the + * pathname to a file, and report that path as having lost its + * extended attributes, or the precise offset of the lost file data. */ + if (!can_use_pptrs(ctx)) + return 0; + scrub_render_ino_descr(ctx, buf, DESCR_BUFSZ, map->fmr_owner, + bs.bs_gen, NULL); + + if (map->fmr_flags & FMR_OF_ATTR_FORK) { + str_corrupt(ctx, buf, _("media error in extended attributes")); + return 0; + } + + str_unfixable_error(ctx, buf, + _("media error at data offset %llu length %llu."), + err_off, fr->length); return 0; } @@ -452,6 +493,10 @@ report_ioerr( void *arg) { struct fsmap keys[2]; + struct ioerr_filerange fr = { + .physical = start, + .length = length, + }; struct disk_ioerr_report *dioerr = arg; dev_t dev; @@ -467,7 +512,7 @@ report_ioerr( (keys + 1)->fmr_offset = ULLONG_MAX; (keys + 1)->fmr_flags = UINT_MAX; return -scrub_iterate_fsmap(dioerr->ctx, keys, report_ioerr_fsmap, - &start); + &fr); } /* Report all the media errors found on a disk. */ @@ -511,10 +556,16 @@ report_all_media_errors( return ret; } - /* Scan the directory tree to get file paths. */ - ret = scan_fs_tree(ctx, report_dir_loss, report_dirent_loss, vs); - if (ret) - return ret; + /* + * Scan the directory tree to get file paths if we didn't already use + * directory parent pointers to report the loss. + */ + if (!can_use_pptrs(ctx)) { + ret = scan_fs_tree(ctx, report_dir_loss, report_dirent_loss, + vs); + if (ret) + return ret; + } /* Scan for unlinked files. */ return scrub_scan_all_inodes(ctx, report_inode_loss, vs); From patchwork Tue Jul 2 01:14:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718842 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8671A8BE2 for ; Tue, 2 Jul 2024 01:14:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882845; cv=none; b=K3OSPh3Gux9lqw3G4GEsRUk/74mKpp3NIZS0Oae8wNPHqYw9hGfQzK8aK/Q1y8VMBdshkmB3O7vOxMVweZfvvwUkZyUQ40AXn9hvdZthK4eqRaH1eGP4KeMV7H2GSq8BnXj2/0PWwmmZ4rQ9D/bhlgYIOIBdQNfskJNmWdPVscY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882845; c=relaxed/simple; bh=u/qgYqcFuq90H1YCmaR6ejeF7k52AVhghPEc/hOq9Gc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=G84RO0X6EfB+aD6xhIR+Wz7UGuMZrUzIZWPYBk7bRK+YE4ME6UK4beBwz1i9WbWz+eEd2Ai7FMB4mvTK5lp0PFoNWKppnO0D2Dy1f0LJL2iCg1zr+PhqfcIfSCA6z7UyPP/guNPivbRdvRwICdbZvqGaWUyTqBuLcP79xWAsQxY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hggEtzMg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hggEtzMg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5CE51C116B1; Tue, 2 Jul 2024 01:14:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882845; bh=u/qgYqcFuq90H1YCmaR6ejeF7k52AVhghPEc/hOq9Gc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=hggEtzMg9E2Rtp0rXGuNGK4fy2/EB7NRyJaWuPz3JTAU0wHTWTzRxAEXjflA8X5Jr nBkWZv/ubjR1Bmd0hwn9d0I0hKYVcUk+gm/r6Fj/w2rgxAxHQkcwLv3+Yo2YlCccSC o0VjMzekfFLITgK5o2UUzvfpPaEHb2xAQjJvpiC35sbnMV3QQlrXBh0aLhcDmG23eL PfevO4Ds2lhpochPVOCpVfSjZc7ojrUDgsTfOLx6f1MYCfHAFIRdhx2O70TATVVhof iSnM8HZ1puWmAT4CTaLGtuo3hRv8ckZYg9To0aneIWq6A7jM9Nt/DowJP/6ptIKHmp NWhM14uPJzQrQ== Date: Mon, 01 Jul 2024 18:14:04 -0700 Subject: [PATCH 13/24] xfs_db: report parent pointers in version command From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121263.2009260.1429651097097993711.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Report the presents of PARENT pointers from the version subcommand. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- db/sb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/sb.c b/db/sb.c index c39011634198..7836384a1faa 100644 --- a/db/sb.c +++ b/db/sb.c @@ -708,6 +708,8 @@ version_string( strcat(s, ",NREXT64"); if (xfs_has_exchange_range(mp)) strcat(s, ",EXCHANGE"); + if (xfs_has_parent(mp)) + strcat(s, ",PARENT"); return s; } From patchwork Tue Jul 2 01:14:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718843 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 58D2479DF for ; Tue, 2 Jul 2024 01:14:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882861; cv=none; b=KJtwR4+Cqu0WwJnHSeFiDYpvPLdyqjGxbHHvknsrOKGtN+bndHp9Kqh/4gY2ugqkqGRTJSh4KuEsQsO5XlDlVr+l0yIwDhjE6uLcsHdoYD9DXmGvcenRkgjCkm9Ld156ybSa3a2P5+PUnulqcjuFkhldLbrVQu60sRyA+rpzzTU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882861; c=relaxed/simple; bh=/Rz1GR2Wqnj3QjDNwIOMbkufBLPVQcJfesnOXIa9qxU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UlIuEQvXZlugdukSDQBjHgsyIkx81yyjzZOtGwvAs27wynS4MqztdzyMI07Nuq5/ctPTdnnKWoXF5qM2haI2xpXsLLd8mLCN/WGFIy+ykF+94XHf50ohY8Go54rPu2xTfbCImXT40ZgKE+1W29bUDpfkA9wnFfcgZzetELEIuC0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ACeTzFuv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ACeTzFuv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 05885C116B1; Tue, 2 Jul 2024 01:14:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882861; bh=/Rz1GR2Wqnj3QjDNwIOMbkufBLPVQcJfesnOXIa9qxU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ACeTzFuvsxbMkAYeF1MPwzNj1gemeS32YveSZMTyVCtY1CGTYL6vcdnqbE6VO1ZR5 TvkbmmK5CZSyHV6ma0OrlgO0ESR2xkIXWZJODL5gPwOqsj7eqNCrrC/vfSHWl0LOQu PndQvSpc8WNgpM84MClODtNsYIhWGvIlYCASqnIwJt1HHe+GHj4nijqx8MwBNZs22x XmBfq00N+pyiASyV0GljBjk2kvh7Adq7Fb1rNkUvfYSNSIwzG9zSUg6QfSkq8F84K/ yhlly0cjKumwA6CMPbEaTm81+NtiMAOExRQxeijz9tIne+mxYn1xvkrP3ABCc2MICQ pCukKB0SXQ3qQ== Date: Mon, 01 Jul 2024 18:14:20 -0700 Subject: [PATCH 14/24] xfs_db: report parent bit on xattrs From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121279.2009260.4036237222136719544.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Display the parent bit on xattr keys Signed-off-by: Darrick J. Wong Reviewed-by: Allison Henderson Reviewed-by: Christoph Hellwig --- db/attr.c | 3 +++ db/attrshort.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/db/attr.c b/db/attr.c index de68d6276337..3252f388614e 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 7c386d46f88f..978f58d67a7b 100644 --- a/db/attrshort.c +++ b/db/attrshort.c @@ -43,6 +43,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 Tue Jul 2 01:14:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718844 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0E871BA37 for ; Tue, 2 Jul 2024 01:14:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882877; cv=none; b=iMygXlfvD8dOzyjfjuQXizBRoXDSl79fkuBnInKEpA8wwnQxyZswD0MPdt5St3uX0d/xJiVJZcD5m2rZKc5SuGOIyvTJmb6La04mqX6Uwnb1yTa/a1i4zI8ELZ4rJ7Tv5kYxJYyPRJkokA6ToETPG0/V9qiyEFOVj/wC0tXGbNY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882877; c=relaxed/simple; bh=x/YKCqkecDeWSv+arrm4Z5AHy3Kdgg7x5E2trBYI1ss=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ne0vSNu4iHtxK/vMoBK1PVe5Yt0ZWN3+FdfnrQeFIiJrC91Mly9EDn0vIJg0e8oZR9r13I6qpNMqrgayHa4L0pjCo0O3CNdRPiVbXp8i1s0arD/x/QNjH44FAGUNi4OkFJrPKLxVfcVNEtumS/UoIYTtxBK12llyLC0nMe/EcFo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lklIMIkU; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lklIMIkU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 97B13C116B1; Tue, 2 Jul 2024 01:14:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882876; bh=x/YKCqkecDeWSv+arrm4Z5AHy3Kdgg7x5E2trBYI1ss=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=lklIMIkU3kENcRO8IaSFMddDJNWLH3RsJTB1JkXbF4xFPYJomjpVetr0Zi3Ckl6Y4 VgW3e3sPzg51uMfmItY3BHn9dk6JTUoIYUexPXPLekSfHUauzRptB4tgzQL7VfCzMH dAwsu6pJ9+fH+VcWZFswyBnpIeZrCIqEJpHl8E3poK4RO1/JLACL/X9cKp619yqloS jihv6kPBPVAdQxWeIIkkSSlbhSqv5jCo4QAcJjTPkqs5aGxCUo3ygFp7ofVfynepBs 6XVCDU/Dsni5qe2WOK6b2gW6sHqE4c6y/MihzBNJxfApOX3/bRPnwO/ZMerEvIlWi6 6rdAQ1rTYd0nw== Date: Mon, 01 Jul 2024 18:14:36 -0700 Subject: [PATCH 15/24] xfs_db: report parent pointers embedded in xattrs From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121294.2009260.6773463880437891539.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Decode the parent pointer inode, generation, and name fields if the parent pointer passes basic validation checks. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- db/attr.c | 28 ++++++++++++++++++++++++++++ db/attrshort.c | 24 ++++++++++++++++++++++++ db/field.c | 10 ++++++++++ db/field.h | 3 +++ 4 files changed, 65 insertions(+) diff --git a/db/attr.c b/db/attr.c index 3252f388614e..3b556c43def5 100644 --- a/db/attr.c +++ b/db/attr.c @@ -33,6 +33,8 @@ static int attr_remote_data_count(void *obj, int startoff); static int attr3_remote_hdr_count(void *obj, int startoff); static int attr3_remote_data_count(void *obj, int startoff); +static int attr_leaf_value_pptr_count(void *obj, int startoff); + const field_t attr_hfld[] = { { "", FLDT_ATTR, OI(0), C1, 0, TYP_NONE }, { NULL } @@ -118,6 +120,8 @@ 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_dir", FLDT_PARENT_REC, attr_leaf_name_local_value_offset, + attr_leaf_value_pptr_count, 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)), @@ -307,6 +311,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); @@ -514,6 +520,28 @@ attr3_remote_hdr_count( return be32_to_cpu(node->rm_magic) == XFS_ATTR3_RMT_MAGIC; } +static int +__leaf_pptr_count( + struct xfs_attr_leafblock *leaf, + struct xfs_attr_leaf_entry *e, + int i) +{ + if (!(e->flags & XFS_ATTR_LOCAL)) + return 0; + if ((e->flags & XFS_ATTR_NSP_ONDISK_MASK) != XFS_ATTR_PARENT) + return 0; + + return 1; +} + +static int +attr_leaf_value_pptr_count( + void *obj, + int startoff) +{ + return attr_leaf_entry_walk(obj, startoff, __leaf_pptr_count); +} + int attr_size( void *obj, diff --git a/db/attrshort.c b/db/attrshort.c index 978f58d67a7b..7e5c94ca533d 100644 --- a/db/attrshort.c +++ b/db/attrshort.c @@ -18,6 +18,8 @@ static int attr_sf_entry_value_offset(void *obj, int startoff, int idx); static int attr_shortform_list_count(void *obj, int startoff); static int attr_shortform_list_offset(void *obj, int startoff, int idx); +static int attr_sf_entry_pptr_count(void *obj, int startoff); + const field_t attr_shortform_flds[] = { { "hdr", FLDT_ATTR_SF_HDR, OI(0), C1, 0, TYP_NONE }, { "list", FLDT_ATTR_SF_ENTRY, attr_shortform_list_offset, @@ -48,6 +50,8 @@ 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_dir", FLDT_PARENT_REC, attr_sf_entry_value_offset, + attr_sf_entry_pptr_count, 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 } @@ -92,6 +96,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; } @@ -159,3 +167,19 @@ attrshort_size( e = xfs_attr_sf_nextentry(e); return bitize((int)((char *)e - (char *)hdr)); } + +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 0; + + return 1; +} diff --git a/db/field.c b/db/field.c index a3e47ee81ccf..a61ccc9ef6d0 100644 --- a/db/field.c +++ b/db/field.c @@ -24,6 +24,14 @@ #include "dir2sf.h" #include "symlink.h" +#define PPOFF(f) bitize(offsetof(struct xfs_parent_rec, f)) +const field_t parent_flds[] = { + { "inumber", FLDT_INO, OI(PPOFF(p_ino)), C1, 0, TYP_INODE }, + { "gen", FLDT_UINT32D, OI(PPOFF(p_gen)), C1, 0, TYP_NONE }, + { NULL } +}; +#undef PPOFF + const ftattr_t ftattrtab[] = { { FLDT_AGBLOCK, "agblock", fp_num, "%u", SI(bitsz(xfs_agblock_t)), FTARG_DONULL, fa_agblock, NULL }, @@ -384,6 +392,8 @@ const ftattr_t ftattrtab[] = { { FLDT_UINT8X, "uint8x", fp_num, "%#x", SI(bitsz(uint8_t)), 0, NULL, NULL }, { FLDT_UUID, "uuid", fp_uuid, NULL, SI(bitsz(uuid_t)), 0, NULL, NULL }, + { FLDT_PARENT_REC, "parent", NULL, (char *)parent_flds, + SI(bitsz(struct xfs_parent_rec)), 0, NULL, parent_flds }, { FLDT_ZZZ, NULL } }; diff --git a/db/field.h b/db/field.h index 634742a572c8..b1bfdbed19ce 100644 --- a/db/field.h +++ b/db/field.h @@ -187,6 +187,9 @@ typedef enum fldt { FLDT_UINT8O, FLDT_UINT8X, FLDT_UUID, + + FLDT_PARENT_REC, + FLDT_ZZZ /* mark last entry */ } fldt_t; From patchwork Tue Jul 2 01:14:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718845 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 63D79C129 for ; Tue, 2 Jul 2024 01:14:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882892; cv=none; b=Ibx0FfZBGxZdupMv259/Y+hsBlv+sFcApf9MRR95HM3G+a1u3XZj23uGLesLJbsLkh0xzRTWI7n/kroLAcpMvEYRE9v4XxTQZBi6xgB7YFFeLywq4vBeijODyqjHpFxUsqLMdHczrSkpqRCK8UYhe3zeLB5T3IN4xcrHTJfxt/8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882892; c=relaxed/simple; bh=pl5B5fcHgWV7epWapYJoHWGdbJenh+0yT7vyIk4A1qE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sqFMqJrcQutL45ccjhW5J9FL7UTVVE/IbA7j7JMS0+dbiFnzwNH78s0w+SACUb7aCVZieP+jaI4R9lOXgEsRD3IIY5b6wSrY3jEusY0uZFeDC6C2YjQCKrs2QaJkmD2ARANAxENCLmMD5rhj4akrYOFhDHzNuL18PLRLtq2o548= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=INqTXsHu; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="INqTXsHu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 40749C116B1; Tue, 2 Jul 2024 01:14:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882892; bh=pl5B5fcHgWV7epWapYJoHWGdbJenh+0yT7vyIk4A1qE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=INqTXsHuh709M8HLxQd/D0nLsXXJTgIIZYopZLCx3H4dBBxMXW75BidxKM2Dxf+md 5s/gbzAqCzuI5auiarY+FI1oPDH1zKjv6KMsciz5EdPvZmzI2Q8mcdZCC/hsAhecDM ekAQBMvH961s7Oi8ssEAQ3kTTJW8sar3N/RPNzvnRuiMGraBXEE/G1L6bMUdiuvFog LNCCWhPeknMvhU0+y8w/vKA7FWOhl7c/CrzHB5DnbLNtQODMmEFRnZ1fGexig3LZYe G0Y/5HyE6moG59mGXrMutHM+7DKRd6aJ/ABRu5UhJUa7egA9Ie/GROnsfdO2W01XYm vRzX2leLHXcuA== Date: Mon, 01 Jul 2024 18:14:51 -0700 Subject: [PATCH 16/24] xfs_db: obfuscate dirent and parent pointer names consistently From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121310.2009260.13863957257257204611.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 Reviewed-by: Christoph Hellwig --- db/metadump.c | 310 ++++++++++++++++++++++++++++++++++++++++++++-- libxfs/libxfs_api_defs.h | 1 2 files changed, 299 insertions(+), 12 deletions(-) diff --git a/db/metadump.c b/db/metadump.c index c1bf5d002751..e95238fb0471 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 */ @@ -719,6 +727,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) @@ -844,6 +957,7 @@ generate_obfuscated_name( int namelen, unsigned char *name) { + unsigned char *orig_name = NULL; xfs_dahash_t hash; /* @@ -865,8 +979,37 @@ 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(metadump.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. + */ + orig_name = malloc(namelen); + if (!orig_name) { + orig_name = name; + goto add_remap; + } + memcpy(orig_name, name, namelen); + } + obfuscate_name(hash, namelen, name, ino != 0); ASSERT(hash == dirattr_hashname(ino != 0, name, namelen)); @@ -891,6 +1034,26 @@ generate_obfuscated_name( "in dir inode %llu\n", (unsigned long long) ino, (unsigned long long) metadump.cur_ino); + + /* + * We've obfuscated a name in the directory entry. Remember this + * remapping for when we come across the parent pointer later. + */ + if (!orig_name) + return; + +add_remap: + remap_debug("obfuscating dir 0x%lx '%.*s' -> 0x%lx -> '%.*s' \n", + metadump.cur_ino, namelen, orig_name, ino, namelen, + name); + + if (!remaptable_add(metadump.cur_ino, hash, orig_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) metadump.cur_ino); + if (orig_name && orig_name != name) + free(orig_name); } static void @@ -1026,6 +1189,106 @@ process_sf_symlink( memset(&buf[len], 0, XFS_DFORK_DSIZE(dip, mp) - len); } +/* + * Decide if we want to obfuscate this parent pointer. If we do, either find + * the obfuscated name that we created when we scanned the corresponding dirent + * and replace the name with that; or create a new obfuscated name for later + * use. + */ +static void +maybe_obfuscate_pptr( + unsigned int attr_flags, + uint8_t *name, + int namelen, + const void *value, + int valuelen) +{ + unsigned char old_name[MAXNAMELEN]; + struct remap_ent *remap; + xfs_dahash_t hash; + xfs_ino_t child_ino = metadump.cur_ino; + xfs_ino_t parent_ino; + int error; + + if (!metadump.obfuscate) + return; + + if (!(attr_flags & XFS_ATTR_PARENT)) + return; + + /* Do not obfuscate this parent pointer if it fails basic checks. */ + error = -libxfs_parent_from_attr(mp, attr_flags, name, namelen, value, + valuelen, &parent_ino, NULL); + if (error) + return; + memcpy(old_name, name, namelen); + + /* + * We don't obfuscate "lost+found" or any orphan files therein. 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. + */ + metadump.cur_ino = parent_ino; + if (in_lost_found(child_ino, namelen, name)) { + metadump.cur_ino = child_ino; + return; + } + metadump.cur_ino = child_ino; + + hash = dirattr_hashname(true, name, namelen); + + /* + * If we already processed the dirent, use the same name for the parent + * pointer. + */ + remap = remaptable_find(parent_ino, hash, name, namelen); + if (remap) { + remap_debug( + "found obfuscated pptr 0x%lx '%.*s' -> 0x%lx -> '%.*s' \n", + parent_ino, namelen, remap_ent_before(remap), + metadump.cur_ino, namelen, + remap_ent_after(remap)); + memcpy(name, remap_ent_after(remap), namelen); + 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, namelen, name, true); + + remap_debug("obfuscated pptr 0x%lx '%.*s' -> 0x%lx -> '%.*s'\n", + parent_ino, namelen, old_name, metadump.cur_ino, + namelen, name); + if (!remaptable_add(parent_ino, hash, old_name, namelen, name)) + print_warning( + "unable to record remapped pptr name for inode %llu in dir inode %llu\n", + (unsigned long long) metadump.cur_ino, + (unsigned long long) parent_ino); +} + +static inline bool +want_obfuscate_attr( + unsigned int nsp_flags, + const void *name, + unsigned int namelen, + const void *value, + unsigned int valuelen) +{ + if (!metadump.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) @@ -1053,7 +1316,7 @@ process_sf_attr( for (i = 0; (i < hdr->count) && ((char *)asfep - (char *)hdr < ino_attr_size); i++) { - + void *name, *value; int namelen = asfep->namelen; if (namelen == 0) { @@ -1070,11 +1333,16 @@ process_sf_attr( break; } - if (metadump.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 (asfep->flags & XFS_ATTR_PARENT) { + maybe_obfuscate_pptr(asfep->flags, name, namelen, + 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 + @@ -1443,6 +1711,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 (metadump.show_warnings) @@ -1451,11 +1722,21 @@ process_attr_block( (long long)metadump.cur_ino); break; } - if (metadump.obfuscate) { + + name = &local->nameval[0]; + value = &local->nameval[local->namelen]; + valuelen = be16_to_cpu(local->valuelen); + + if (entry->flags & XFS_ATTR_PARENT) { + maybe_obfuscate_pptr(entry->flags, name, + local->namelen, 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; @@ -1474,7 +1755,11 @@ process_attr_block( (long long)metadump.cur_ino); break; } - if (metadump.obfuscate) { + if (entry->flags & XFS_ATTR_PARENT) { + /* do not obfuscate obviously busted pptr */ + add_remote_vals(be32_to_cpu(remote->valueblk), + be32_to_cpu(remote->valuelen)); + } else if (metadump.obfuscate) { generate_obfuscated_name(0, remote->namelen, &remote->name[0]); add_remote_vals(be32_to_cpu(remote->valueblk), @@ -3044,5 +3329,6 @@ metadump_f( metadump.mdops->release(); out: + remaptable_clear(); return 0; } diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index b7947591d2db..c3dde15116c4 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -193,6 +193,7 @@ #define xfs_parent_add libxfs_parent_add #define xfs_parent_finish libxfs_parent_finish #define xfs_parent_start libxfs_parent_start +#define xfs_parent_from_attr libxfs_parent_from_attr #define xfs_perag_get libxfs_perag_get #define xfs_perag_hold libxfs_perag_hold #define xfs_perag_put libxfs_perag_put From patchwork Tue Jul 2 01:15:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718846 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3AF1B20E3 for ; Tue, 2 Jul 2024 01:15:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882908; cv=none; b=Ie2zNsN/7kkYwSO8XxF0Wpvx7991bp6Gxr5IXs8B7Ionq6G8FWW3G8VXhGihv6OCuseJ/QpXRywTUoYLYNAdDmtAl70S7ytBe+AhQQgd+00n5J+tgywMVgMNDK6w17WGvAGbiDdat2/gFUNA/saw35feSugtvH5x2Qb26BjaivQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882908; c=relaxed/simple; bh=oGsR+F1e4i6D5NWCpoqH6xTf5h+0qqETh/n0NSmbYUc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=SMF1ePddpobPL5XlIUaonr1oP+VBs9iSLXNVJ45FEnjbwcuReJoYKeThcUQEBtxZlivsj5PW9NpJHKXsvCXOPz5EVoc52OmQ+Hne4/wgkDWKR6I9MAkJKJ7/dglSouFKP0vdqYy3DVUEgfoOyl5t8I2CPBejBakw4RqVb7CWAsw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gw6OLYOZ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gw6OLYOZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D28E7C2BD10; Tue, 2 Jul 2024 01:15:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882907; bh=oGsR+F1e4i6D5NWCpoqH6xTf5h+0qqETh/n0NSmbYUc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=gw6OLYOZ+Tr4BmO2tgs0Zw8u+8ctQhk7d8r5LT3Gk/wtcEsAAI/j48lAxv0CRhx2Y cngm7YOWq2PCIiaBaoJDtOGx9sbYTZzISOc2laEX2OKHk5lU0dqK3Zh85/XFdhYFUY XQ0OAHB0BJn6JvVInmcjHPfG4DYTjW8SgpgHHslz8e14cCXbVi+navaWtPlQHhiovB 2GQg+KdbrWniAH0717i6kEvG/xXz5LbTEAy6BiMguyeXFjghY2DocIZMK3aGVVXrzk QASL8j7Pva/qWOFeMeuUiGsBEy8j802axW5S11V4ZmNRUay3u9rAmnJw/mStgvuveb hEggsJkelyHwQ== Date: Mon, 01 Jul 2024 18:15:07 -0700 Subject: [PATCH 17/24] libxfs: export attr3_leaf_hdr_from_disk via libxfs_api_defs.h From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121326.2009260.10614225579834518986.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 Reviewed-by: Christoph Hellwig --- 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 3b556c43def5..0b1f498e457c 100644 --- a/db/attr.c +++ b/db/attr.c @@ -248,7 +248,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 e95238fb0471..424544f9f032 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -1680,7 +1680,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 c3dde15116c4..5713e5221fe6 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -36,10 +36,13 @@ #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_check_namespace libxfs_attr_check_namespace #define xfs_attr_get libxfs_attr_get #define xfs_attr_hashname libxfs_attr_hashname #define xfs_attr_hashval libxfs_attr_hashval +#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 @@ -103,6 +106,7 @@ #define xfs_compute_rextslog libxfs_compute_rextslog #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 @@ -177,6 +181,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 8321c9b679b2..2e97fd9775ba 100644 --- a/repair/attr_repair.c +++ b/repair/attr_repair.c @@ -610,7 +610,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); @@ -849,7 +849,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 || @@ -1052,7 +1052,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 Tue Jul 2 01:15:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718847 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 000DE38B for ; Tue, 2 Jul 2024 01:15:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882924; cv=none; b=It6a7Rq8YqJrvbiea7uC50rNN9vcmUB3oO4MCCUDKhxUYYmjm2wBWUFMtF042gNQP3BtLXV48u6I+mggJTL5D0Wxj/r6BZN7cvo/Ya6IbfxEDN37HxeaUTVJgkzSXJVH2EmlZXdPLgZ1bnyDsBXVu1Dti/9huqYEpMRl6X6p+Qk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882924; c=relaxed/simple; bh=ntz+HwYe99tClo3SjhQfXVosinXMaJ8BJlAWcsD9IWU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NKZsO35wpJr7VdL/d8cik7gAzoHkRI3DwHxx5pR9LoNdySxey52AnCkq///eRYMrrcWRuRKY1wMX2Qwq8t6p/mS1ZrNm+kDExqBic8Gl1l5CiacZyDVxdHgRJeGRl2hTkIXJ+RzMnuAs/7P3+Z3qlM+uR2doPd3oe4yX7YRkDAM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JFozp0MG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JFozp0MG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7F1CDC116B1; Tue, 2 Jul 2024 01:15:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882923; bh=ntz+HwYe99tClo3SjhQfXVosinXMaJ8BJlAWcsD9IWU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=JFozp0MGd9BZOEsUnwNkQl754B6KS6fw67kx8Fy4IUIxt/5xEcvbKMBnN38EGazJP PY9sWq53DzK7yWyJ9I4sRNsTBHfmqRr1fcf65Yrw5s8c26Kf3kpuYc0aDDrfeiEByn 8kboGhvvovol5Ka5WaXBW0CzCVrf/NamKXvdaRHYh/HIoYenlNtixjLRLp8EZSdKxb lTJEFaIFdQ5uO38as70AKQWa36Sk0NZFOqpVCiCUZ/PYDScnSI+A6BVH8yWF0Z78zD riyIgxADw/8F2w4XUzQj2XD01jSPp2uE4DbIh3Js1VvpShVuBv/17iu+jnC+M+ZqLf 8Dq6YrYkS+H6w== Date: Mon, 01 Jul 2024 18:15:23 -0700 Subject: [PATCH 18/24] 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: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121341.2009260.989865979378157675.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Create a command to dump the parents of a file. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- db/namei.c | 323 +++++++++++++++++++++++++++++++++++++++++++++++++++++ man/man8/xfs_db.8 | 9 + 2 files changed, 332 insertions(+) diff --git a/db/namei.c b/db/namei.c index 41ccaa04b659..46b4cacb507e 100644 --- a/db/namei.c +++ b/db/namei.c @@ -596,6 +596,326 @@ static struct cmdinfo ls_cmd = { .help = ls_help, }; +static void +pptr_emit( + struct xfs_inode *ip, + unsigned int attr_flags, + const uint8_t *name, + unsigned int namelen, + const void *value, + unsigned int valuelen) +{ + struct xfs_mount *mp = ip->i_mount; + xfs_ino_t parent_ino; + uint32_t parent_gen; + int error; + + if (!(attr_flags & XFS_ATTR_PARENT)) + return; + + error = -libxfs_parent_from_attr(mp, attr_flags, name, namelen, value, + valuelen, &parent_ino, &parent_gen); + if (error) + return; + + dbprintf("%18llu:0x%08x %3d %.*s\n", parent_ino, parent_gen, namelen, + namelen, name); +} + +static int +list_sf_pptrs( + struct xfs_inode *ip) +{ + struct xfs_attr_sf_hdr *hdr = ip->i_af.if_data; + struct xfs_attr_sf_entry *sfe; + unsigned int i; + + sfe = libxfs_attr_sf_firstentry(hdr); + for (i = 0; i < hdr->count; i++) { + pptr_emit(ip, sfe->flags, sfe->nameval, sfe->namelen, + sfe->nameval + sfe->valuelen, sfe->valuelen); + + sfe = xfs_attr_sf_nextentry(sfe); + } + + return 0; +} + +static void +list_leaf_pptr_entries( + struct xfs_inode *ip, + struct xfs_buf *bp) +{ + 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; + + /* + * Parent pointers cannot be remote values; don't bother + * decoding this xattr name. + */ + if (!(entry->flags & XFS_ATTR_LOCAL)) + continue; + + name_loc = xfs_attr3_leaf_name_local(leaf, i); + pptr_emit(ip, entry->flags, name_loc->nameval, + name_loc->namelen, + name_loc->nameval + name_loc->namelen, + be16_to_cpu(name_loc->valuelen)); + } +} + +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) { @@ -604,4 +924,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 a7f6d55ed8be..937b17e79a35 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -943,6 +943,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 Tue Jul 2 01:15:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718848 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 53DFC38B for ; Tue, 2 Jul 2024 01:15:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882939; cv=none; b=cVtGVIDX76xcJfG4wDIgrgpas2xnrkQXQNxLbGTFJ8fRaH9nvTxfMsn+bE/zpU8ei2pppwrNTU9t8uQcbv0hSmMuUDwjX4LqFwP8LCedhEeEhug3kQTMtWlBUdoGBUaUZlmy7Do/ZU9axyT++zo4w4ur8QrmX1hY3aOVQmHZPWM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882939; c=relaxed/simple; bh=/QMzyBdU4LzVZTPUJYR7RdCek1zglB/kXGCSulx9Yx4=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lC7dqo9EQm9TgZxJDeqrgwDgWV23+tQQJdb25882Iv3SEqVfuibj0LgR/fe1QB5/JU4EAZkdifkFAvlgotStW5mCRbpPJZRjCZoaoJ6Ps6mKPgpY0tvD3v7YMg6Hpq5OQakk0DO9jsZUWetL1glt1cBWzKFpRWZmWrWsiWXqBJI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WL7K8nsS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WL7K8nsS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 28412C116B1; Tue, 2 Jul 2024 01:15:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882939; bh=/QMzyBdU4LzVZTPUJYR7RdCek1zglB/kXGCSulx9Yx4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=WL7K8nsSxZG9vxXxxn+K256i2FusPgZ4UPWNRHBZxRDgV/64Rvp+x0192742JMXl0 ms6nRsOLj/pp26ImugIPc+f7t1PUxsJWGofZaurRvzOgnEaBASvZHp9UkosZvalwPI mxAX5nsHCyQSWgBbIxTuNQVGJI44ZHWj2HeC96nymOxLBNzOW43BQi5N9EnDH+fYU9 SBXxgk4P/lkfOiQ/QtgWlS+IdeLtGHY2+HdKYDYM2a957fWmhetHJCOIMxY9w5C6ug xhzy3fjdxg524sR0tQPeWpW6zLeSvKhjHN9uz2pGKy9ja+Z4wpP1weROGhLB1jEFCh RkuCisWkKyOWA== Date: Mon, 01 Jul 2024 18:15:38 -0700 Subject: [PATCH 19/24] xfs_db: make attr_set and attr_remove handle parent pointers From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121357.2009260.1818577364230485511.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Make it so that xfs_db can load up the filesystem (somewhat uselessly) with parent pointers. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- db/attrset.c | 202 +++++++++++++++++++++++++++++++++++++--------- libxfs/libxfs_api_defs.h | 1 man/man8/xfs_db.8 | 21 ++++- 3 files changed, 181 insertions(+), 43 deletions(-) diff --git a/db/attrset.c b/db/attrset.c index 3b5db7c2aedb..d9ab79fa7849 100644 --- a/db/attrset.c +++ b/db/attrset.c @@ -24,11 +24,11 @@ static void attrset_help(void); static const cmdinfo_t attr_set_cmd = { "attr_set", "aset", attr_set_f, 1, -1, 0, - N_("[-r|-s|-u] [-n] [-R|-C] [-v n] name"), + N_("[-r|-s|-u|-p] [-n] [-R|-C] [-v n] name"), N_("set the named attribute on the current inode"), attrset_help }; static const cmdinfo_t attr_remove_cmd = { "attr_remove", "aremove", attr_remove_f, 1, -1, 0, - N_("[-r|-s|-u] [-n] name"), + N_("[-r|-s|-u|-p] [-n] name"), N_("remove the named attribute from the current inode"), attrset_help }; static void @@ -44,6 +44,7 @@ attrset_help(void) " -r -- 'root'\n" " -u -- 'user' (default)\n" " -s -- 'secure'\n" +" -p -- 'parent'\n" "\n" " For attr_set, these options further define the type of set operation:\n" " -C -- 'create' - create attribute, fail if it already exists\n" @@ -62,6 +63,49 @@ attrset_init(void) add_command(&attr_remove_cmd); } +static unsigned char * +get_buf_from_file( + const char *fname, + size_t bufsize, + int *namelen) +{ + FILE *fp; + unsigned char *buf; + size_t sz; + + buf = malloc(bufsize + 1); + if (!buf) { + perror("malloc"); + return NULL; + } + + fp = fopen(fname, "r"); + if (!fp) { + perror(fname); + goto out_free; + } + + sz = fread(buf, sizeof(char), bufsize, fp); + if (sz == 0) { + printf("%s: Could not read anything from file\n", fname); + goto out_fp; + } + + fclose(fp); + + *namelen = sz; + return buf; +out_fp: + fclose(fp); +out_free: + free(buf); + return NULL; +} + +#define LIBXFS_ATTR_NS (LIBXFS_ATTR_SECURE | \ + LIBXFS_ATTR_ROOT | \ + LIBXFS_ATTR_PARENT) + static int attr_set_f( int argc, @@ -69,6 +113,8 @@ attr_set_f( { struct xfs_da_args args = { }; char *sp; + char *name_from_file = NULL; + char *value_from_file = NULL; enum xfs_attr_update op = XFS_ATTRUPDATE_UPSERT; int c; @@ -81,20 +127,23 @@ attr_set_f( return 0; } - while ((c = getopt(argc, argv, "rusCRnv:")) != EOF) { + while ((c = getopt(argc, argv, "ruspCRnN:v:V:")) != EOF) { switch (c) { /* namespaces */ case 'r': + args.attr_filter &= ~LIBXFS_ATTR_NS; args.attr_filter |= LIBXFS_ATTR_ROOT; - args.attr_filter &= ~LIBXFS_ATTR_SECURE; break; case 'u': - args.attr_filter &= ~(LIBXFS_ATTR_ROOT | - LIBXFS_ATTR_SECURE); + args.attr_filter &= ~LIBXFS_ATTR_NS; break; case 's': + args.attr_filter &= ~LIBXFS_ATTR_NS; args.attr_filter |= LIBXFS_ATTR_SECURE; - args.attr_filter &= ~LIBXFS_ATTR_ROOT; + break; + case 'p': + args.attr_filter &= ~LIBXFS_ATTR_NS; + args.attr_filter |= XFS_ATTR_PARENT; break; /* modifiers */ @@ -105,6 +154,10 @@ attr_set_f( op = XFS_ATTRUPDATE_REPLACE; break; + case 'N': + name_from_file = optarg; + break; + case 'n': /* * We never touch attr2 these days; leave this here to @@ -114,6 +167,11 @@ attr_set_f( /* value length */ case 'v': + if (value_from_file) { + dbprintf(_("already set value file\n")); + return 0; + } + args.valuelen = strtol(optarg, &sp, 0); if (*sp != '\0' || args.valuelen < 0 || args.valuelen > 64 * 1024) { @@ -122,30 +180,64 @@ attr_set_f( } break; + case 'V': + if (args.valuelen != 0) { + dbprintf(_("already set valuelen\n")); + return 0; + } + + value_from_file = optarg; + break; + default: dbprintf(_("bad option for attr_set command\n")); return 0; } } - if (optind != argc - 1) { - dbprintf(_("too few options for attr_set (no name given)\n")); - return 0; - } + if (name_from_file) { + int namelen; - args.name = (const unsigned char *)argv[optind]; - if (!args.name) { - dbprintf(_("invalid name\n")); - return 0; - } + if (optind != argc) { + dbprintf(_("too many options for attr_set (no name needed)\n")); + return 0; + } + + args.name = get_buf_from_file(name_from_file, MAXNAMELEN, + &namelen); + if (!args.name) + return 0; + + args.namelen = namelen; + } else { + if (optind != argc - 1) { + dbprintf(_("too few options for attr_set (no name given)\n")); + return 0; + } - args.namelen = strlen(argv[optind]); - if (args.namelen >= MAXNAMELEN) { - dbprintf(_("name too long\n")); - return 0; + args.name = (const unsigned char *)argv[optind]; + if (!args.name) { + dbprintf(_("invalid name\n")); + return 0; + } + + args.namelen = strlen(argv[optind]); + if (args.namelen >= MAXNAMELEN) { + dbprintf(_("name too long\n")); + goto out; + } } - if (args.valuelen) { + if (value_from_file) { + int valuelen; + + args.value = get_buf_from_file(value_from_file, + XFS_XATTR_SIZE_MAX, &valuelen); + if (!args.value) + goto out; + + args.valuelen = valuelen; + } else if (args.valuelen) { args.value = memalign(getpagesize(), args.valuelen); if (!args.value) { dbprintf(_("cannot allocate buffer (%d)\n"), @@ -175,6 +267,8 @@ attr_set_f( libxfs_irele(args.dp); if (args.value) free(args.value); + if (name_from_file) + free((void *)args.name); return 0; } @@ -184,6 +278,7 @@ attr_remove_f( char **argv) { struct xfs_da_args args = { }; + char *name_from_file = NULL; int c; if (cur_typ == NULL) { @@ -195,20 +290,27 @@ attr_remove_f( return 0; } - while ((c = getopt(argc, argv, "rusn")) != EOF) { + while ((c = getopt(argc, argv, "ruspnN:")) != EOF) { switch (c) { /* namespaces */ case 'r': + args.attr_filter &= ~LIBXFS_ATTR_NS; args.attr_filter |= LIBXFS_ATTR_ROOT; - args.attr_filter &= ~LIBXFS_ATTR_SECURE; break; case 'u': - args.attr_filter &= ~(LIBXFS_ATTR_ROOT | - LIBXFS_ATTR_SECURE); + args.attr_filter &= ~LIBXFS_ATTR_NS; break; case 's': + args.attr_filter &= ~LIBXFS_ATTR_NS; args.attr_filter |= LIBXFS_ATTR_SECURE; - args.attr_filter &= ~LIBXFS_ATTR_ROOT; + break; + case 'p': + args.attr_filter &= ~LIBXFS_ATTR_NS; + args.attr_filter |= XFS_ATTR_PARENT; + break; + + case 'N': + name_from_file = optarg; break; case 'n': @@ -224,21 +326,37 @@ attr_remove_f( } } - if (optind != argc - 1) { - dbprintf(_("too few options for attr_remove (no name given)\n")); - return 0; - } - - args.name = (const unsigned char *)argv[optind]; - if (!args.name) { - dbprintf(_("invalid name\n")); - return 0; - } - - args.namelen = strlen(argv[optind]); - if (args.namelen >= MAXNAMELEN) { - dbprintf(_("name too long\n")); - return 0; + if (name_from_file) { + int namelen; + + if (optind != argc) { + dbprintf(_("too many options for attr_set (no name needed)\n")); + return 0; + } + + args.name = get_buf_from_file(name_from_file, MAXNAMELEN, + &namelen); + if (!args.name) + return 0; + + args.namelen = namelen; + } else { + if (optind != argc - 1) { + dbprintf(_("too few options for attr_remove (no name given)\n")); + return 0; + } + + args.name = (const unsigned char *)argv[optind]; + if (!args.name) { + dbprintf(_("invalid name\n")); + return 0; + } + + args.namelen = strlen(argv[optind]); + if (args.namelen >= MAXNAMELEN) { + dbprintf(_("name too long\n")); + return 0; + } } if (libxfs_iget(mp, NULL, iocur_top->ino, 0, &args.dp)) { @@ -260,5 +378,7 @@ attr_remove_f( out: if (args.dp) libxfs_irele(args.dp); + if (name_from_file) + free((void *)args.name); return 0; } diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 5713e5221fe6..bceaab8baa8c 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -15,6 +15,7 @@ */ #define LIBXFS_ATTR_ROOT XFS_ATTR_ROOT #define LIBXFS_ATTR_SECURE XFS_ATTR_SECURE +#define LIBXFS_ATTR_PARENT XFS_ATTR_PARENT #define xfs_agfl_size libxfs_agfl_size #define xfs_agfl_walk libxfs_agfl_walk diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index 937b17e79a35..a561bdc492d4 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -184,10 +184,14 @@ Displays the length, free block count, per-AG reservation size, and per-AG reservation usage for a given AG. If no argument is given, display information for all AGs. .TP -.BI "attr_remove [\-r|\-u|\-s] [\-n] " name +.BI "attr_remove [\-p|\-r|\-u|\-s] [\-n] [\-N " namefile "|" name "] " Remove the specified extended attribute from the current file. .RS 1.0i .TP 0.4i +.B \-p +Sets the attribute in the parent namespace. +Only one namespace option can be specified. +.TP .B \-r Sets the attribute in the root namespace. Only one namespace option can be specified. @@ -200,14 +204,21 @@ Only one namespace option can be specified. Sets the attribute in the secure namespace. Only one namespace option can be specified. .TP +.B \-N +Read the name from this file. +.TP .B \-n Do not enable 'noattr2' mode on V4 filesystems. .RE .TP -.BI "attr_set [\-r|\-u|\-s] [\-n] [\-R|\-C] [\-v " namelen "] " name +.BI "attr_set [\-p\-r|\-u|\-s] [\-n] [\-R|\-C] [\-v " valuelen "|\-V " valuefile "] [\-N " namefile "|" name "] " Sets an extended attribute on the current file with the given name. .RS 1.0i .TP 0.4i +.B \-p +Sets the attribute in the parent namespace. +Only one namespace option can be specified. +.TP .B \-r Sets the attribute in the root namespace. Only one namespace option can be specified. @@ -220,6 +231,9 @@ Only one namespace option can be specified. Sets the attribute in the secure namespace. Only one namespace option can be specified. .TP +.B \-N +Read the name from this file. +.TP .B \-n Do not enable 'noattr2' mode on V4 filesystems. .TP @@ -231,6 +245,9 @@ The command will fail if the attribute does not already exist. Create the attribute. The command will fail if the attribute already exists. .TP +.B \-V +Read the value from this file. +.TP .B \-v Set the attribute value to a string of this length containing the letter 'v'. .RE From patchwork Tue Jul 2 01:15:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718849 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 57D258F4E for ; Tue, 2 Jul 2024 01:15:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882955; cv=none; b=kiYuIJLVTqRAo3dG4360yuPSGpkSNm7J+DAjR6GSVYM9drXs8SZMhUdiO0UEItMigU75B7CXo0oMDWFA+V0GKLyBWFQLfhO9cjLRgDsu6mEbF0bvk5wnlf+U0JvbufXhOZtY6PbyC2VefL2KDvJ4c6a9n1RA00M7vksaFCMN9z8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882955; c=relaxed/simple; bh=gAQnP3/VJlpRBd9/LvxMWtrhY6k5OiRXffgUL5pJIZI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tFbKcC1ah+MDhb7i3GrJKwHS0ZoVQlatZSEGa2TF7ZPUaUYjGJGFOcy7kaLxqf0scBB9HZT+QQz5P0kQZVCfp1MZQ7XmU5Hy4t+RCf/pzhjcqqb1j0M2IPRTzdkY0hJlZxlhfk7NwIvXOrzgujHxhqZW75qQmNODXQnUyxeKu2k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Sdp/pIO8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Sdp/pIO8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C588EC116B1; Tue, 2 Jul 2024 01:15:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882954; bh=gAQnP3/VJlpRBd9/LvxMWtrhY6k5OiRXffgUL5pJIZI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Sdp/pIO8i3d1P2LohN6INbKa2fU2GP5wGbpi2+1Aj8QT/ask1VJp4HJvAkmBon1jE Pr3z4miOEdq6K+nffUzej1c3ktB/Ozdn/ncSezwvelAzTzMnHewM4u+C53tCPA1wmg Q0b9ORcyCOcdWVh9j5bMPtsCSHp+sHz+dbu6jO7DcD6gB2x/xoXBkT1CFSI70bOAEP toSAKEeAoBh9L5DKOg4AYEH8L7B149Qe2aDyYEIdjbhuMTO+1tqMiN0HH+1GQqhi02 HYvPOTGXOa2e039AoCvkTW0Zeat+2QVhmHCxItQy3ABaNtcllakV7IQR3meRVHbZcp NqBxjcT7M+ogQ== Date: Mon, 01 Jul 2024 18:15:54 -0700 Subject: [PATCH 20/24] xfs_db: add link and unlink expert commands From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121372.2009260.6118201962786865664.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Create a pair of commands to create and remove directory entries to support functional testing of directory tree corruption. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- db/namei.c | 378 ++++++++++++++++++++++++++++++++++++++++++++++ include/xfs_inode.h | 4 libxfs/libxfs_api_defs.h | 8 + man/man8/xfs_db.8 | 20 ++ 4 files changed, 409 insertions(+), 1 deletion(-) diff --git a/db/namei.c b/db/namei.c index 46b4cacb507e..d57ead4f165d 100644 --- a/db/namei.c +++ b/db/namei.c @@ -916,6 +916,376 @@ static struct cmdinfo parent_cmd = { .help = parent_help, }; +static void +link_help(void) +{ + dbprintf(_( +"\n" +" Create a directory entry in the current directory that points to the\n" +" specified file.\n" +"\n" +" Options:\n" +" -i -- Point to this specific inode number.\n" +" -p -- Point to the inode given by this path.\n" +" -t -- Set the file type to this value.\n" +" name -- Create this directory entry with this name.\n" + )); +} + +static int +create_child( + struct xfs_mount *mp, + xfs_ino_t parent_ino, + const char *name, + unsigned int ftype, + xfs_ino_t child_ino) +{ + struct xfs_name xname = { + .name = (const unsigned char *)name, + .len = strlen(name), + .type = ftype, + }; + struct xfs_parent_args *ppargs = NULL; + struct xfs_trans *tp; + struct xfs_inode *dp, *ip; + unsigned int resblks; + bool isdir; + int error; + + error = -libxfs_iget(mp, NULL, parent_ino, 0, &dp); + if (error) + return error; + + if (!S_ISDIR(VFS_I(dp)->i_mode)) { + error = -ENOTDIR; + goto out_dp; + } + + error = -libxfs_iget(mp, NULL, child_ino, 0, &ip); + if (error) + goto out_dp; + isdir = S_ISDIR(VFS_I(ip)->i_mode); + + if (xname.type == XFS_DIR3_FT_UNKNOWN) + xname.type = libxfs_mode_to_ftype(VFS_I(ip)->i_mode); + + error = -libxfs_parent_start(mp, &ppargs); + if (error) + goto out_ip; + + resblks = libxfs_link_space_res(mp, MAXNAMELEN); + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_link, resblks, 0, 0, + &tp); + if (error) + goto out_parent; + + libxfs_trans_ijoin(tp, dp, 0); + libxfs_trans_ijoin(tp, ip, 0); + + error = -libxfs_dir_createname(tp, dp, &xname, ip->i_ino, resblks); + if (error) + goto out_trans; + + /* bump dp's link to ip */ + libxfs_bumplink(tp, ip); + + /* bump ip's dotdot link to dp */ + if (isdir) + libxfs_bumplink(tp, dp); + + /* Replace the dotdot entry in the child directory. */ + if (isdir) { + error = -libxfs_dir_replace(tp, ip, &xfs_name_dotdot, + dp->i_ino, resblks); + if (error) + goto out_trans; + } + + if (ppargs) { + error = -libxfs_parent_addname(tp, ppargs, dp, &xname, ip); + if (error) + goto out_trans; + } + + error = -libxfs_trans_commit(tp); + goto out_parent; + +out_trans: + libxfs_trans_cancel(tp); +out_parent: + libxfs_parent_finish(mp, ppargs); +out_ip: + libxfs_irele(ip); +out_dp: + libxfs_irele(dp); + return error; +} + +static const char *ftype_map[] = { + [XFS_DIR3_FT_REG_FILE] = "reg", + [XFS_DIR3_FT_DIR] = "dir", + [XFS_DIR3_FT_CHRDEV] = "cdev", + [XFS_DIR3_FT_BLKDEV] = "bdev", + [XFS_DIR3_FT_FIFO] = "fifo", + [XFS_DIR3_FT_SOCK] = "sock", + [XFS_DIR3_FT_SYMLINK] = "symlink", + [XFS_DIR3_FT_WHT] = "whiteout", +}; + +static int +link_f( + int argc, + char **argv) +{ + xfs_ino_t child_ino = NULLFSINO; + int ftype = XFS_DIR3_FT_UNKNOWN; + unsigned int i; + int c; + int error = 0; + + while ((c = getopt(argc, argv, "i:p:t:")) != -1) { + switch (c) { + case 'i': + errno = 0; + child_ino = strtoull(optarg, NULL, 0); + if (errno == ERANGE) { + printf("%s: unknown inode number\n", optarg); + exitcode = 1; + return 0; + } + break; + case 'p': + push_cur(); + error = path_walk(optarg); + if (error) { + printf("%s: %s\n", optarg, strerror(error)); + exitcode = 1; + return 0; + } else if (iocur_top->typ != &typtab[TYP_INODE]) { + printf("%s: does not point to an inode\n", + optarg); + exitcode = 1; + return 0; + } else { + child_ino = iocur_top->ino; + } + pop_cur(); + break; + case 't': + for (i = 0; i < ARRAY_SIZE(ftype_map); i++) { + if (ftype_map[i] && + !strcmp(ftype_map[i], optarg)) { + ftype = i; + break; + } + } + if (i == ARRAY_SIZE(ftype_map)) { + printf("%s: unknown file type\n", optarg); + exitcode = 1; + return 0; + } + break; + default: + link_help(); + return 0; + } + } + + if (child_ino == NULLFSINO) { + printf("link: need to specify child via -i or -p\n"); + exitcode = 1; + return 0; + } + + if (iocur_top->typ != &typtab[TYP_INODE]) { + printf("io cursor does not point to an inode.\n"); + exitcode = 1; + return 0; + } + + if (optind + 1 != argc) { + printf("link: need directory entry name"); + exitcode = 1; + return 0; + } + + error = create_child(mp, iocur_top->ino, argv[optind], ftype, + child_ino); + if (error) { + printf("link failed: %s\n", strerror(error)); + exitcode = 1; + return 0; + } + + return 0; +} + +static struct cmdinfo link_cmd = { + .name = "link", + .cfunc = link_f, + .argmin = 0, + .argmax = -1, + .canpush = 0, + .args = "[-i ino] [-p path] [-t ftype] name", + .help = link_help, +}; + +static void +unlink_help(void) +{ + dbprintf(_( +"\n" +" Remove a directory entry from the current directory.\n" +"\n" +" Options:\n" +" name -- Remove the directory entry with this name.\n" + )); +} + +static void +droplink( + struct xfs_trans *tp, + struct xfs_inode *ip) +{ + struct inode *inode = VFS_I(ip); + + libxfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); + + if (inode->i_nlink != XFS_NLINK_PINNED) + drop_nlink(VFS_I(ip)); + + libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); +} + +static int +remove_child( + struct xfs_mount *mp, + xfs_ino_t parent_ino, + const char *name) +{ + struct xfs_name xname = { + .name = (const unsigned char *)name, + .len = strlen(name), + }; + struct xfs_parent_args *ppargs; + struct xfs_trans *tp; + struct xfs_inode *dp, *ip; + xfs_ino_t child_ino; + unsigned int resblks; + int error; + + error = -libxfs_iget(mp, NULL, parent_ino, 0, &dp); + if (error) + return error; + + if (!S_ISDIR(VFS_I(dp)->i_mode)) { + error = -ENOTDIR; + goto out_dp; + } + + error = -libxfs_dir_lookup(NULL, dp, &xname, &child_ino, NULL); + if (error) + goto out_dp; + + error = -libxfs_iget(mp, NULL, child_ino, 0, &ip); + if (error) + goto out_dp; + + error = -libxfs_parent_start(mp, &ppargs); + if (error) + goto out_ip; + + resblks = libxfs_remove_space_res(mp, MAXNAMELEN); + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, resblks, 0, 0, + &tp); + if (error) + goto out_parent; + + libxfs_trans_ijoin(tp, dp, 0); + libxfs_trans_ijoin(tp, ip, 0); + + if (S_ISDIR(VFS_I(ip)->i_mode)) { + /* drop ip's dotdot link to dp */ + droplink(tp, dp); + } else { + libxfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); + } + + /* drop dp's link to ip */ + droplink(tp, ip); + + error = -libxfs_dir_removename(tp, dp, &xname, ip->i_ino, resblks); + if (error) + goto out_trans; + + if (ppargs) { + error = -libxfs_parent_removename(tp, ppargs, dp, &xname, ip); + if (error) + goto out_trans; + } + + error = -libxfs_trans_commit(tp); + goto out_parent; + +out_trans: + libxfs_trans_cancel(tp); +out_parent: + libxfs_parent_finish(mp, ppargs); +out_ip: + libxfs_irele(ip); +out_dp: + libxfs_irele(dp); + return error; +} + +static int +unlink_f( + int argc, + char **argv) +{ + int c; + int error = 0; + + while ((c = getopt(argc, argv, "")) != -1) { + switch (c) { + default: + unlink_help(); + return 0; + } + } + + if (iocur_top->typ != &typtab[TYP_INODE]) { + printf("io cursor does not point to an inode.\n"); + exitcode = 1; + return 0; + } + + if (optind + 1 != argc) { + printf("unlink: need directory entry name"); + exitcode = 1; + return 0; + } + + error = remove_child(mp, iocur_top->ino, argv[optind]); + if (error) { + printf("unlink failed: %s\n", strerror(error)); + exitcode = 1; + return 0; + } + + return 0; +} + +static struct cmdinfo unlink_cmd = { + .name = "unlink", + .cfunc = unlink_f, + .argmin = 0, + .argmax = -1, + .canpush = 0, + .args = "name", + .help = unlink_help, +}; + void namei_init(void) { @@ -927,4 +1297,12 @@ namei_init(void) parent_cmd.oneline = _("list parent pointers"); add_command(&parent_cmd); + + if (expert_mode) { + link_cmd.oneline = _("create directory link"); + add_command(&link_cmd); + + unlink_cmd.oneline = _("remove directory link"); + add_command(&unlink_cmd); + } } diff --git a/include/xfs_inode.h b/include/xfs_inode.h index 45339b42621a..9bbf37225197 100644 --- a/include/xfs_inode.h +++ b/include/xfs_inode.h @@ -315,6 +315,10 @@ static inline void inc_nlink(struct inode *inode) { inode->i_nlink++; } +static inline void drop_nlink(struct inode *inode) +{ + inode->i_nlink--; +} static inline bool xfs_is_reflink_inode(struct xfs_inode *ip) { diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index bceaab8baa8c..b7edaf788051 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -147,12 +147,16 @@ #define xfs_dir_init libxfs_dir_init #define xfs_dir_ino_validate libxfs_dir_ino_validate #define xfs_dir_lookup libxfs_dir_lookup +#define xfs_dir_removename libxfs_dir_removename #define xfs_dir_replace libxfs_dir_replace #define xfs_dqblk_repair libxfs_dqblk_repair #define xfs_dquot_from_disk_ts libxfs_dquot_from_disk_ts #define xfs_dquot_verify libxfs_dquot_verify +#define xfs_bumplink libxfs_bumplink +#define xfs_droplink libxfs_droplink + #define xfs_finobt_calc_reserves libxfs_finobt_calc_reserves #define xfs_finobt_init_cursor libxfs_finobt_init_cursor #define xfs_free_extent libxfs_free_extent @@ -191,13 +195,15 @@ #define xfs_iread_extents libxfs_iread_extents #define xfs_irele libxfs_irele +#define xfs_link_space_res libxfs_link_space_res #define xfs_log_calc_minimum_size libxfs_log_calc_minimum_size #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_parent_add libxfs_parent_add +#define xfs_parent_addname libxfs_parent_addname #define xfs_parent_finish libxfs_parent_finish +#define xfs_parent_removename libxfs_parent_removename #define xfs_parent_start libxfs_parent_start #define xfs_parent_from_attr libxfs_parent_from_attr #define xfs_perag_get libxfs_perag_get diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index a561bdc492d4..f8db6c36f40a 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -901,6 +901,21 @@ will result in truncation and a warning will be issued. If no .I label is given, the current filesystem label is printed. .TP +.BI "link [-i " ino "] [-p " path "] [-t " ftype "] name" +In the current directory, create a directory entry with the given +.I name +pointing to a file. +The file must be specified either as a directory tree path as given by the +.I path +option; or directly as an inode number as given by the +.I ino +option. +The file type in the directory entry will be determined from the mode of the +child file unless the +.I ftype +option is given. +The file being targetted must not be on the iunlink list. +.TP .BI "log [stop | start " filename ] Start logging output to .IR filename , @@ -1052,6 +1067,11 @@ Print the timestamps in the current locale's date and time format instead of raw seconds since the Unix epoch. .RE .TP +.BI "unlink name" +In the current directory, remove a directory entry with the given +.IR name . +The file being targetted will not be put on the iunlink list. +.TP .BI "uuid [" uuid " | " generate " | " rewrite " | " restore ] Set the filesystem universally unique identifier (UUID). The filesystem UUID can be used by From patchwork Tue Jul 2 01:16:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718850 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9B2FC9441 for ; Tue, 2 Jul 2024 01:16:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882970; cv=none; b=TFbdKpatCcvzgW6kEmOQjFd9kvr3T+MMjTf+Cmpe+q8mJpPXx+pu00BYDXoWHiYp3bOf3gbHEJ+ev96SL14VqHrkk9jma3Bh6/x1lu1uA1IwEkErt4iQumZq0OaLf1eV7jG/7/0QL3vzral05WYowYGTfU8lwVnT9VKL0B5gV7k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882970; c=relaxed/simple; bh=RBQUdUhWy29PogdMIHQtpJ/shXdCchrRX6Acj6Bas2Q=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Vlq3NQRSwRdBee13qaOch3H40+uL71VCgdpi1IM/I4uurfERKcCHv1udy0vLedQZwwlpJsF46IjPTM0rQjI80cn0tBCQ6jFrp2ATEL7XljCc+Z9NYxGwisBc+XIAathlIO3OTFsUfSybFZ3Bm7EF9fbFnMdRVGfBQba+F0PcWps= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Fyxu+scv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Fyxu+scv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 767A9C116B1; Tue, 2 Jul 2024 01:16:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882970; bh=RBQUdUhWy29PogdMIHQtpJ/shXdCchrRX6Acj6Bas2Q=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Fyxu+scvWlFXCssF8nooA+rDT0FODyOKBGXyl7oO1q/L8054rbl1mzUDgOl6h7wnN 26T0y0rI0Nx5YdIvbmlJbCdF7o/vKvFNO9cSvL1OVOXC+zdEi3qly0KhoiAr4HHSFC gaimAZdVgPmJ6KYzb9fBkNYBXMhwTJNsODk5KvLYwa1n2BSv7gjY2bYXzUzGa3byB2 QHQbV450kaCuiOBkgvjSzsY4NPPuAT8CjVwIDXmq1prEOFsznQu5/ASVwVOYl5bsnX kPNFteC5ZusSrO/Pw6LJ5VJ9QF00R+OqXdVhNQd5GJSlYtUq7b0gqHQaD1j5jhkx+w OifmhT6FrSJ0g== Date: Mon, 01 Jul 2024 18:16:09 -0700 Subject: [PATCH 21/24] xfs_db: compute hashes of parent pointers From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121387.2009260.17240012773714059969.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Enhance the hash command to compute the hashes of parent pointers. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- db/hash.c | 36 ++++++++++++++++++++++++++++++------ libxfs/libxfs_api_defs.h | 1 + man/man8/xfs_db.8 | 9 ++++++++- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/db/hash.c b/db/hash.c index 1500a6032fd7..50f6da0b1a20 100644 --- a/db/hash.c +++ b/db/hash.c @@ -36,26 +36,42 @@ hash_help(void) " 'hash' prints out the calculated hash value for a string using the\n" "directory/attribute code hash function.\n" "\n" -" Usage: \"hash \"\n" +" Usage: \"hash [-d|-p parent_ino] \"\n" "\n" )); } +enum hash_what { + ATTR, + DIRECTORY, + PPTR, +}; + /* ARGSUSED */ static int hash_f( int argc, char **argv) { + xfs_ino_t p_ino = 0; xfs_dahash_t hashval; - bool use_dir2_hash = false; + enum hash_what what = ATTR; int c; - while ((c = getopt(argc, argv, "d")) != EOF) { + while ((c = getopt(argc, argv, "dp:")) != EOF) { switch (c) { case 'd': - use_dir2_hash = true; + what = DIRECTORY; + break; + case 'p': + errno = 0; + p_ino = strtoull(optarg, NULL, 0); + if (errno) { + perror(optarg); + return 1; + } + what = PPTR; break; default: exitcode = 1; @@ -70,10 +86,18 @@ hash_f( .len = strlen(argv[c]), }; - if (use_dir2_hash) + switch (what) { + case DIRECTORY: hashval = libxfs_dir2_hashname(mp, &xname); - else + break; + case PPTR: + hashval = libxfs_parent_hashval(mp, xname.name, + xname.len, p_ino); + break; + case ATTR: hashval = libxfs_attr_hashname(xname.name, xname.len); + break; + } dbprintf("0x%x\n", hashval); } diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index b7edaf788051..df83aabdc13d 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -203,6 +203,7 @@ #define xfs_mkdir_space_res libxfs_mkdir_space_res #define xfs_parent_addname libxfs_parent_addname #define xfs_parent_finish libxfs_parent_finish +#define xfs_parent_hashval libxfs_parent_hashval #define xfs_parent_removename libxfs_parent_removename #define xfs_parent_start libxfs_parent_start #define xfs_parent_from_attr libxfs_parent_from_attr diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index f8db6c36f40a..9f6fea5748d4 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -822,7 +822,7 @@ Skip write verifiers but perform CRC recalculation; allows invalid data to be written to disk to test detection of invalid data. .RE .TP -.BI hash [-d]" strings +.BI hash [-d|-p parent_ino]" strings Prints the hash value of .I string using the hash function of the XFS directory and attribute implementation. @@ -832,6 +832,13 @@ If the option is specified, the directory-specific hash function is used. This only makes a difference on filesystems with ascii case-insensitive lookups enabled. + +If the +.B \-p +option is specified, the parent pointer-specific hash function is used. +The parent directory inumber must be specified as an argument. +This only makes a difference on filesystems with ascii case-insensitive +lookups enabled. .TP .BI "hashcoll [-a] [-s seed] [-n " nr "] [-p " path "] -i | " names... Create directory entries or extended attributes names that all have the same From patchwork Tue Jul 2 01:16:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718851 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 81DC99441 for ; Tue, 2 Jul 2024 01:16:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882987; cv=none; b=u0UEu4/aRvAT9NYTOJU1XPckESBuTvNm+MKK95zPRLCbS/AEGuPTqXOezcvSap84+cqbWeigtgvLRRERPN/a8dbdnz5B4MA8rRVNa4GDn1W8fzHBvfRssiAj6ioI6Ky6OPgj34gTibr1V21mK8SvEMvggRWIhCNK/o0xh4GuLsQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719882987; c=relaxed/simple; bh=ri2ifs8s1+vUD8EK0cABpzG+bi+ir42D0++/MjWroCw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AL6TQaJDNVvdai1sR9apFZqumiLn1OPZfuIUctum1iRDaRDLf7rIDZy6Gz77q8nJST/P7R6Im97gyvPqZQ7rWo8JRO7wICUNN0K/heUd3ClVhBr/zK2NlP1wb3eLLh5xaO2bPrTKOc3SkWveWleKWuZ2xq2J1OZrhigGV+7yV/A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RvXgq+xd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RvXgq+xd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 13022C116B1; Tue, 2 Jul 2024 01:16:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719882986; bh=ri2ifs8s1+vUD8EK0cABpzG+bi+ir42D0++/MjWroCw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=RvXgq+xdWxDjXRclQvDv+BvMxWa+EbeEP5ITN3px9GaQMidU9ydyNwvtPoAzIaYKh ClaTm99sjkih3vJUGSyWApd3wHDSiKzQV2HzZuyDL1+AWWj2hSOjCBNo7eFlQ7DJ05 Z8xHBCkL+vvGgoYqD7Vl+BwqowRovbq2OHWSU/hOaxvMwTna7k7RaSkcNtkEIeeKbn i32PVOEDKM6tStDW0YdlFeq+OEg51j9ywuyvsEKOt1LarKPdnZQsxJQfPErN0xaSS7 kXU1AwCj90FQmhRSX76eWS7GFb1A0bZ2RNePOhMLXjx74IT/xcj5dqDH5Pk7/e4BaX eWLsTIJUIRDqA== Date: Mon, 01 Jul 2024 18:16:25 -0700 Subject: [PATCH 22/24] libxfs: create new files with attr forks if necessary From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121402.2009260.4605471859392366056.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 Reviewed-by: Christoph Hellwig --- libxfs/init.c | 4 ++++ libxfs/util.c | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/libxfs/init.c b/libxfs/init.c index 95de1e6d1d4f..90a539e04161 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -602,14 +602,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 74eea0fcbe07..373749457cc1 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -274,11 +274,12 @@ libxfs_init_new_inode( struct fsxattr *fsx, struct xfs_inode **ipp) { + struct xfs_mount *mp = tp->t_mountp; struct xfs_inode *ip; unsigned int flags; int error; - error = libxfs_iget(tp->t_mountp, tp, ino, XFS_IGET_CREATE, &ip); + error = libxfs_iget(mp, tp, ino, XFS_IGET_CREATE, &ip); if (error != 0) return error; ASSERT(ip != NULL); @@ -340,6 +341,22 @@ libxfs_init_new_inode( ASSERT(0); } + /* + * If we're going to set a parent pointer on this file, we need to + * create an attr fork to receive that parent pointer. + */ + if (pip && xfs_has_parent(mp)) { + ip->i_forkoff = xfs_default_attroffset(ip) >> 3; + xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0); + + if (!xfs_has_attr(mp)) { + spin_lock(&mp->m_sb_lock); + xfs_add_attr(mp); + spin_unlock(&mp->m_sb_lock); + xfs_log_sb(tp); + } + } + /* * Log the new values stuffed into the inode. */ From patchwork Tue Jul 2 01:16:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718852 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F5154A06 for ; Tue, 2 Jul 2024 01:16:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719883002; cv=none; b=GHMtH9AAnqNXiJSby+aZWf9yIAhpWzA6PyG+Y3x63G2l8XbKtoZ0dlCX2pEWHpomonXdLWVeXellpzrLZ/9BIceLpCSQ2c1lKYxA7KxHACs04upioOW/zZbFj8rF0Xfot258uszouCEFt0vUGv6Pg4Y7jpRfUEi9Uv/P5qQQrzQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719883002; c=relaxed/simple; bh=cXbTjsgfAVy1FjDG9TBq+blq492+KtfuuheEa3TxPks=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Zx8znLZlR14j8kJV/1g9puMDFfBjBFVkmCvan6hbmrKMHKcBaMMVrOIAoHnhosoxsXkChh6rx4udSBEV/HPkuC8N8qBVvXHBh/s7zsHVEuu4xkcV7kaTdRcHl1S2w2BoaxpvRw1irRAcnvQRqX6mlqVLqS1D6gMKDoZHQjymxn0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bC9m59m+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bC9m59m+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B10CDC116B1; Tue, 2 Jul 2024 01:16:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719883001; bh=cXbTjsgfAVy1FjDG9TBq+blq492+KtfuuheEa3TxPks=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=bC9m59m+zkFL1WOwxph529cEGIHRoMBKyq8j7Kw06/9mTdo+/wYXKQz2zvz3iWAEw IRbqpctL2cd+s2Y4sXuR2i3AgSo1FKAqueC0Iomzjp46AGKnbf5kseaMwZrVslsARr ZwdrvLPoIDiCKPPvwqSvaxw4kr5AgTZeZH2MO97Islzf6Pp/U16DR1ptJpnYQj2HhY hiVS+BmTpDAcH8t3fQE+I9gHcwYc/ESOXOiZs5i2CxLU9a6+1UYb7xswNghzCX51u+ tpW+ki9paDv8Nnulgb2wG99ehAzq6uh/cW76a0M54NDX6dmZtosBVJFmO9GoQ2xs9V fg/Cq8U0FZnBQ== Date: Mon, 01 Jul 2024 18:16:41 -0700 Subject: [PATCH 23/24] mkfs: Add parent pointers during protofile creation From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121418.2009260.2932252649175356725.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 Reviewed-by: Christoph Hellwig --- mkfs/proto.c | 62 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/mkfs/proto.c b/mkfs/proto.c index a9a9b704a3ca..8e16eb1506f1 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -348,11 +348,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_args *ppargs) { int error; int rsv; @@ -365,9 +366,15 @@ 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 (ppargs) { + error = -libxfs_parent_addname(tp, ppargs, pip, name, ip); + if (error) + fail(_("parent addname error"), error); + } } static void @@ -384,6 +391,20 @@ newdirectory( fail(_("directory create error"), error); } +static struct xfs_parent_args * +newpptr( + struct xfs_mount *mp) +{ + struct xfs_parent_args *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, @@ -418,6 +439,7 @@ parseproto( struct cred creds; char *value; struct xfs_name xname; + struct xfs_parent_args *ppargs = NULL; memset(&creds, 0, sizeof(creds)); mstr = getstr(pp); @@ -492,6 +514,7 @@ parseproto( case IF_REGULAR: buf = newregfile(pp, &len); tp = getres(mp, XFS_B_TO_FSB(mp, len)); + ppargs = newpptr(mp); error = -libxfs_dir_ialloc(&tp, pip, mode|S_IFREG, 1, 0, &creds, fsxp, &ip); if (error) @@ -501,7 +524,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, ppargs); break; case IF_RESERVED: /* pre-allocated space only */ @@ -515,7 +538,7 @@ parseproto( exit(1); } tp = getres(mp, XFS_B_TO_FSB(mp, llen)); - + ppargs = newpptr(mp); error = -libxfs_dir_ialloc(&tp, pip, mode|S_IFREG, 1, 0, &creds, fsxp, &ip); if (error) @@ -524,17 +547,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, ppargs); libxfs_trans_log_inode(tp, ip, flags); error = -libxfs_trans_commit(tp); if (error) fail(_("Space preallocation failed."), error); + libxfs_parent_finish(mp, ppargs); rsvfile(mp, ip, llen); libxfs_irele(ip); return; case IF_BLOCK: tp = getres(mp, 0); + ppargs = 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, @@ -544,12 +569,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, ppargs); flags |= XFS_ILOG_DEV; break; case IF_CHAR: tp = getres(mp, 0); + ppargs = 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, @@ -558,24 +584,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, ppargs); flags |= XFS_ILOG_DEV; break; case IF_FIFO: tp = getres(mp, 0); + ppargs = 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, ppargs); break; case IF_SYMLINK: buf = getstr(pp); len = (int)strlen(buf); tp = getres(mp, XFS_B_TO_FSB(mp, len)); + ppargs = newpptr(mp); error = -libxfs_dir_ialloc(&tp, pip, mode|S_IFLNK, 1, 0, &creds, fsxp, &ip); if (error) @@ -583,7 +611,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, ppargs); break; case IF_DIRECTORY: tp = getres(mp, 0); @@ -598,9 +626,10 @@ parseproto( libxfs_log_sb(tp); isroot = 1; } else { + ppargs = 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, ppargs); libxfs_bumplink(tp, pip); libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE); } @@ -609,6 +638,9 @@ parseproto( error = -libxfs_trans_commit(tp); if (error) fail(_("Directory inode allocation failed."), error); + + libxfs_parent_finish(mp, ppargs); + /* * RT initialization. Do this here to ensure that * the RT inodes get placed after the root inode. @@ -636,6 +668,8 @@ parseproto( fail(_("Error encountered creating file from prototype file"), error); } + + libxfs_parent_finish(mp, ppargs); libxfs_irele(ip); } From patchwork Tue Jul 2 01:16:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13718854 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF62F6FCB for ; Tue, 2 Jul 2024 01:16:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719883017; cv=none; b=i7q1qlBFrrGe1c6leX/VORU8HNmfW23qGYCO7Zv8UzWt7USQUK83jyCzajrKH5NHeUpE8BAIBfS8FCpq6pOAZohgoSl+C4H3LG906ns6SbCoiTy3fwpkySGBKz3Op1akLlKJ77gItZH46LkOfTrBu7j72vfefegi5aMqe0PdM/4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719883017; c=relaxed/simple; bh=PU0pNOeEBHrPzaVNhRjJT9EaRMrH0udakCTn87x942I=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=olh1DWVA0F3u86vcalIuFDtX5a6QKR5VCRg4iuvy8xExDLMrWLOkTCOHH+38wZsoPzR84ycsEKx5SfUHwAm5P3rX2ksO6cvwq5ZvU0gC5wCMRRYsbqFWvOlaxg+TaAi6ks9DKzwBNGIhCj3S31KT5h20oJBvcpSxlddZSjmZ4AM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dcHOxICl; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dcHOxICl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 571BCC116B1; Tue, 2 Jul 2024 01:16:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719883017; bh=PU0pNOeEBHrPzaVNhRjJT9EaRMrH0udakCTn87x942I=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=dcHOxIClgei0ZUb/sS7y7WDkf8n9IvlQ0txvx9U6a7ewhlejeqHEE6M/lUvcL8/SZ M09BJQ1WfClLwCJpJACsbOEDyW/IsB9lgws/BTz0UfXfJj/2ThuqWjMQfMn7/N0egw HU7a6VOPCrAAVuFti6tJgh9Ac3bsvGXyQfCMYRMGoGbb2rrlRBbHESDwVYta4bQS48 weYgReYyXO95fkKxuRMo7piFNTAl4Kx2s0rDKnAzOeR4D6s4GmBdX0OVGsA775c5El PKTkc8CWeScSWwy/s6ILc1wN8+S0n0GLK40XQjUjo3jQgE5CQUUZrfnAdJwM28igrT wNkalkfuZfldQ== Date: Mon, 01 Jul 2024 18:16:56 -0700 Subject: [PATCH 24/24] mkfs: enable formatting with parent pointers From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: Allison Henderson , catherine.hoang@oracle.com, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, hch@lst.de Message-ID: <171988121434.2009260.2474734396646436248.stgit@frogsfrogsfrogs> In-Reply-To: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> References: <171988121023.2009260.1161835936170460985.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Allison Henderson Enable parent pointer support in mkfs via the '-n parent' parameter. Signed-off-by: Allison Henderson Reviewed-by: Darrick J. Wong [djwong: move the no-V4 filesystem check to join the rest] Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- mkfs/lts_4.19.conf | 3 +++ mkfs/lts_5.10.conf | 3 +++ mkfs/lts_5.15.conf | 3 +++ mkfs/lts_5.4.conf | 3 +++ mkfs/lts_6.1.conf | 3 +++ mkfs/lts_6.6.conf | 3 +++ mkfs/xfs_mkfs.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 7 files changed, 60 insertions(+), 3 deletions(-) diff --git a/mkfs/lts_4.19.conf b/mkfs/lts_4.19.conf index 92e8eba6ba8f..9fa1f9378f32 100644 --- a/mkfs/lts_4.19.conf +++ b/mkfs/lts_4.19.conf @@ -13,3 +13,6 @@ rmapbt=0 sparse=1 nrext64=0 exchange=0 + +[naming] +parent=0 diff --git a/mkfs/lts_5.10.conf b/mkfs/lts_5.10.conf index 34e7662cd671..d64bcdf8c46b 100644 --- a/mkfs/lts_5.10.conf +++ b/mkfs/lts_5.10.conf @@ -13,3 +13,6 @@ rmapbt=0 sparse=1 nrext64=0 exchange=0 + +[naming] +parent=0 diff --git a/mkfs/lts_5.15.conf b/mkfs/lts_5.15.conf index a36a5c2b7850..775fd9ab91b8 100644 --- a/mkfs/lts_5.15.conf +++ b/mkfs/lts_5.15.conf @@ -13,3 +13,6 @@ rmapbt=0 sparse=1 nrext64=0 exchange=0 + +[naming] +parent=0 diff --git a/mkfs/lts_5.4.conf b/mkfs/lts_5.4.conf index 4204d5b8f235..6f43a6c6d469 100644 --- a/mkfs/lts_5.4.conf +++ b/mkfs/lts_5.4.conf @@ -13,3 +13,6 @@ rmapbt=0 sparse=1 nrext64=0 exchange=0 + +[naming] +parent=0 diff --git a/mkfs/lts_6.1.conf b/mkfs/lts_6.1.conf index 9a90def8f489..a78a4f9e35dc 100644 --- a/mkfs/lts_6.1.conf +++ b/mkfs/lts_6.1.conf @@ -13,3 +13,6 @@ rmapbt=0 sparse=1 nrext64=0 exchange=0 + +[naming] +parent=0 diff --git a/mkfs/lts_6.6.conf b/mkfs/lts_6.6.conf index 3f7fb651937d..91a25bd8121f 100644 --- a/mkfs/lts_6.6.conf +++ b/mkfs/lts_6.6.conf @@ -13,3 +13,6 @@ rmapbt=1 sparse=1 nrext64=1 exchange=0 + +[naming] +parent=0 diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 991ecbdd03ff..394a35771246 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -114,6 +114,7 @@ enum { N_SIZE = 0, N_VERSION, N_FTYPE, + N_PARENT, N_MAX_OPTS, }; @@ -656,6 +657,7 @@ static struct opt_params nopts = { [N_SIZE] = "size", [N_VERSION] = "version", [N_FTYPE] = "ftype", + [N_PARENT] = "parent", [N_MAX_OPTS] = NULL, }, .subopt_params = { @@ -679,6 +681,14 @@ static struct opt_params nopts = { .maxval = 1, .defaultval = 1, }, + { .index = N_PARENT, + .conflicts = { { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, + + }, }; @@ -1040,7 +1050,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\ @@ -1878,6 +1888,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; } @@ -2385,6 +2398,14 @@ _("exchange-range not supported without CRC support\n")); usage(); } cli->sb_feat.exchrange = false; + + if (cli->sb_feat.parent_pointers && + cli_opt_set(&nopts, N_PARENT)) { + fprintf(stderr, +_("parent pointers not supported without CRC support\n")); + usage(); + } + cli->sb_feat.parent_pointers = false; } if (!cli->sb_feat.finobt) { @@ -2419,6 +2440,17 @@ _("cowextsize not supported without reflink support\n")); usage(); } + /* + * Turn on exchange-range if parent pointers are enabled and the caller + * did not provide an explicit exchange-range parameter so that users + * can take advantage of online repair. It's not required for correct + * operation, but it costs us nothing to enable it. + */ + if (cli->sb_feat.parent_pointers && !cli->sb_feat.exchrange && + !cli_opt_set(&iopts, I_EXCHANGE)) { + cli->sb_feat.exchrange = true; + } + /* * Copy features across to config structure now. */ @@ -3458,8 +3490,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) @@ -3520,6 +3550,15 @@ sb_set_features( sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NREXT64; if (fp->exchrange) sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_EXCHRANGE; + if (fp->parent_pointers) { + sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_PARENT; + /* + * Set ATTRBIT even if mkfs doesn't write out a single parent + * pointer so that the kernel doesn't have to do that for us + * with a synchronous write to the primary super at runtime. + */ + sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT; + } } /*