From patchwork Tue Jul 2 01:20: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: 13718869 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 49E496FC3 for ; Tue, 2 Jul 2024 01:20: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=1719883252; cv=none; b=QK2Wju5JHUdKsKzj/CN6ryQhQKV5fSIfGNzNKgMuO1C0dSqKewVK5B+wyh30M+62SNip4joFiJa9JX/Uq87t9DrVoaRHERQXA/lvDQv4nXF3SmuLb0kpaWNM+XSzz8FseNNE6kno5QC/lOFEgOVzRrekWWFaNWY82GKw+6HZIgo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719883252; c=relaxed/simple; bh=+3JbXZjUWLTyJ58HHQKXIpRhgli05+2XX93BzM5jlIE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=f3o15dgg8HaEvgTiRj1B+zN/PHuBCfUsSJLfgerzIefv6atI3SUHo4aZYq/crYdKGK/cGLkimlmnrwdt8qK0lOQPQwii8yZHqkHAUrcJg65lVXBIwnynDUY16Zj6AeZ7JETZy/NWuS2RAdJbPa0NCsBD2fYbuUZVmreOTj+Gt9U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HHqD/2NZ; 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="HHqD/2NZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1F569C116B1; Tue, 2 Jul 2024 01:20:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719883252; bh=+3JbXZjUWLTyJ58HHQKXIpRhgli05+2XX93BzM5jlIE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=HHqD/2NZoLpEfCmMmdpSR9Zy0+qspqefTWvChTlnjUTNG0j0Q2iokL8L3TaxQmsB2 E8Bg2RJGFOcHWVMFfV2gL93dlMpptNr4xv+98CWKrVpT1j49ylU7Efgkd04L8/aBtr XXszUBM9bffldd2ww4799gT0wN/CwBtHAhxv/x547bXapkJs/kT9MPU8i0URg2+7yI 5+U6krOHJIfLf9pnmd2Dh4gsJRlKOuBo5fxTa3PWNePciyxYULLhEoRB9Yq5dRcQNx 8aMm8ncRd6al7YwKd7wNqFPVNmcEVGZCVaQjOBLJrmYbudFDSKtlawL/2kZ0ybmPbq 5tl/D0WfEsqng== Date: Mon, 01 Jul 2024 18:20:51 -0700 Subject: [PATCH 1/5] libfrog: add directory tree structure scrubber to scrub library From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988122711.2012320.2904107384951874903.stgit@frogsfrogsfrogs> In-Reply-To: <171988122691.2012320.13207835630113271818.stgit@frogsfrogsfrogs> References: <171988122691.2012320.13207835630113271818.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 scrub clients can detect corruptions within the directory tree structure itself. Update the documentation for the scrub ioctl to mention this new functionality. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- libfrog/scrub.c | 5 +++++ man/man2/ioctl_xfs_scrub_metadata.2 | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/libfrog/scrub.c b/libfrog/scrub.c index baaa4b4d9402..a2146e228f5b 100644 --- a/libfrog/scrub.c +++ b/libfrog/scrub.c @@ -149,6 +149,11 @@ const struct xfrog_scrub_descr xfrog_scrubbers[XFS_SCRUB_TYPE_NR] = { .descr = "retained health records", .group = XFROG_SCRUB_GROUP_NONE, }, + [XFS_SCRUB_TYPE_DIRTREE] = { + .name = "dirtree", + .descr = "directory tree structure", + .group = XFROG_SCRUB_GROUP_INODE, + }, }; #undef DEP diff --git a/man/man2/ioctl_xfs_scrub_metadata.2 b/man/man2/ioctl_xfs_scrub_metadata.2 index 75ae52bb5847..44aa139b297a 100644 --- a/man/man2/ioctl_xfs_scrub_metadata.2 +++ b/man/man2/ioctl_xfs_scrub_metadata.2 @@ -148,6 +148,20 @@ that points back to the subdirectory. The inode to examine can be specified in the same manner as .BR XFS_SCRUB_TYPE_INODE "." +.TP +.B XFS_SCRUB_TYPE_DIRTREE +This scrubber looks for problems in the directory tree structure such as loops +and directories accessible through more than one path. +Problems are detected by walking parent pointers upwards towards the root. +Loops are detected by comparing the parent directory at each step against the +directories already examined. +Directories with multiple paths are detected by counting the parent pointers +attached to a directory. +Non-directories do not have links pointing away from the directory tree root +and can be skipped. +The directory to examine can be specified in the same manner as +.BR XFS_SCRUB_TYPE_INODE "." + .TP .B XFS_SCRUB_TYPE_SYMLINK Examine the target of a symbolic link for obvious pathname problems. From patchwork Tue Jul 2 01:21: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: 13718870 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 29B158830 for ; Tue, 2 Jul 2024 01:21:07 +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=1719883268; cv=none; b=cUdvkcNwvv0pAIpa4WmHTXMFEThSiTJazyYUL/pEN1cLxxp9gUeoQ9pX5HzeGztZqggjWjhRt7turyJZs63D339fL7aXrJp0/Uam8parqJLWE5kO6/d9VZQzFF9/Z0R7KeLuKg7QBjExkDY7nY70Q6dSMPDQyWBeuiPnmoL0akE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719883268; c=relaxed/simple; bh=+VixRE9pqsB5eW8ueESvKjr9fdo43XK2IoQ4eThEqo0=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=FTD9ilrE9lR1dWvUdSANvcfqWjxwtt7nR6rQBAzyuALbYhxwBXPbQHrW4yrJI6JH7t0jsquYn3cJFE/QymuMFeaVmuQOP4ABiuL7U5RNAx4IlzeB1mQTj9RJL4utl7ltb8EnJ7786aAMzRJFQydiS4PZKJcVmVQhLG1IDPj3JSc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dZ0Ezn8P; 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="dZ0Ezn8P" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B3114C116B1; Tue, 2 Jul 2024 01:21:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719883267; bh=+VixRE9pqsB5eW8ueESvKjr9fdo43XK2IoQ4eThEqo0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=dZ0Ezn8Pzbt2++ZyWzZa1cWvsleduWFqlx6YMqFE6vy9sGgJk0gY7bhkK79gLZNaj 1wIWVsM+j4En3RM6A8OaQnCUXTOXAL86hzwsZKgb93EBP+TXpI409gESv9KFuAm+fV b+Fowh2+1KnnHVJFL+nUYIKQBIWM9s0qAXiZnC5wg0MLFTyPGJ2kDtEAIN7bARAtMp AbjG1gADYBieEnHbnhejk5iCEK3oW1cNTUDbuNrXE727Nb/WpE6zYQzMwYvU+9p0bg 1oeXOHC/GIxQhqMFiOP0dvqLFfBmSoez0N/xpJ+qgUtbyTvHrwBhrZTkdjyV+yOyhS STQfDlGy8dM/A== Date: Mon, 01 Jul 2024 18:21:07 -0700 Subject: [PATCH 2/5] xfs_spaceman: report directory tree corruption in the health information From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988122726.2012320.799724181764249157.stgit@frogsfrogsfrogs> In-Reply-To: <171988122691.2012320.13207835630113271818.stgit@frogsfrogsfrogs> References: <171988122691.2012320.13207835630113271818.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 directories that are the source of corruption in the directory tree. While we're at it, add the documentation updates for the new reporting flags and scrub type. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- man/man2/ioctl_xfs_bulkstat.2 | 3 +++ man/man2/ioctl_xfs_fsbulkstat.2 | 3 +++ spaceman/health.c | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/man/man2/ioctl_xfs_bulkstat.2 b/man/man2/ioctl_xfs_bulkstat.2 index 3203ca0c5d27..b6d51aa43811 100644 --- a/man/man2/ioctl_xfs_bulkstat.2 +++ b/man/man2/ioctl_xfs_bulkstat.2 @@ -326,6 +326,9 @@ Symbolic link target. .TP .B XFS_BS_SICK_PARENT Parent pointers. +.TP +.B XFS_BS_SICK_DIRTREE +Directory is the source of corruption in the directory tree. .RE .SH ERRORS Error codes can be one of, but are not limited to, the following: diff --git a/man/man2/ioctl_xfs_fsbulkstat.2 b/man/man2/ioctl_xfs_fsbulkstat.2 index 3f059942a219..cd38d2fd6f26 100644 --- a/man/man2/ioctl_xfs_fsbulkstat.2 +++ b/man/man2/ioctl_xfs_fsbulkstat.2 @@ -239,6 +239,9 @@ Symbolic link target. .TP .B XFS_BS_SICK_PARENT Parent pointers. +.TP +.B XFS_BS_SICK_DIRTREE +Directory is the source of corruption in the directory tree. .RE .SH RETURN VALUE On error, \-1 is returned, and diff --git a/spaceman/health.c b/spaceman/health.c index 6722babf5888..d88a7f6c6e53 100644 --- a/spaceman/health.c +++ b/spaceman/health.c @@ -165,6 +165,10 @@ static const struct flag_map inode_flags[] = { .mask = XFS_BS_SICK_PARENT, .descr = "parent pointers", }, + { + .mask = XFS_BS_SICK_DIRTREE, + .descr = "directory tree structure", + }, {0}, }; From patchwork Tue Jul 2 01:21:22 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: 13718871 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 78EDC8BFA for ; Tue, 2 Jul 2024 01:21: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=1719883283; cv=none; b=DXIPgYN/4wmv7c38bzsfH0mqPmFQM94PlpeW6b4zbrftl4WOkgE6SzvHxYMwMOdRlvOnK4sxNqfVjSPXvMdIfJCXFvnhwg8U32qHfeir2hwgkF4KDeYa7YoD+KxHX/1BwJawhafv7XuEv8Uk20uoVRlmnEwOojt2a/frwhTz0Eg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719883283; c=relaxed/simple; bh=kWBuzrfN2kzwsXSEL8+0dWlUfQgf9bgCZk0Pug+BcBM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=h9jNYovtcd5shmUvvziMlYdQl04cqn42pcIS18glO8bkJZIwh2+W2lYkn9v2KkOafUAY+7wZ5k9fFcgQtNvLBiyvQKHY3JDFEMhwsVKVuoHXeFc+iPmH2OXyhg7XUU9GCiIHIUgH9Tb8H8C3LIBpL7Zq0mYLLc/nXdn7ztY636s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ubM6Tn21; 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="ubM6Tn21" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 56BB2C116B1; Tue, 2 Jul 2024 01:21:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719883283; bh=kWBuzrfN2kzwsXSEL8+0dWlUfQgf9bgCZk0Pug+BcBM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ubM6Tn21nCcdhx82lmcDTdCb6KwqJso3E2naxoxMaflN/xVSzCJv/Td4UeaN02tWE c+XzvSEcLTHqLfXPaOqA9jSAG59vmiJ1/+7ei868852CzBWPmgpmcH1e354NRw30Iq sOeDiBGITyRy/UrGUd9OtrtRXHRlYVwTz/d6vh5iqxWvdz86T47DF7XpaH4A05/4R4 8KvSI3HvVUmahaI/mw05PrTISVYqxIO6VT3ZxmD0KVrheEdQEImmPTMRuftbUnMTnC J7qrRbdMPpfYdpRYewhxCoLX0wTgN1AdbU1poWeyj748cRA3jaUI+yr53DRwYpQ+Tz jjiWBxcenn1Lg== Date: Mon, 01 Jul 2024 18:21:22 -0700 Subject: [PATCH 3/5] xfs_scrub: fix erroring out of check_inode_names From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988122742.2012320.2358555456931426968.stgit@frogsfrogsfrogs> In-Reply-To: <171988122691.2012320.13207835630113271818.stgit@frogsfrogsfrogs> References: <171988122691.2012320.13207835630113271818.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 The early exit logic in this function is a bit suboptimal -- we don't need to close the @fd if we haven't even opened it, and since all errors are fatal, we don't need to bump the progress counter. The logic in this function is about to get more involved due to the addition of the directory tree structure checker, so clean up these warts. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- scrub/phase5.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scrub/phase5.c b/scrub/phase5.c index 0df8c46e9f5b..b37196277554 100644 --- a/scrub/phase5.c +++ b/scrub/phase5.c @@ -279,7 +279,7 @@ check_inode_names( if (bstat->bs_xflags & FS_XFLAG_HASATTR) { error = check_xattr_names(ctx, &dsc, handle, bstat); if (error) - goto out; + goto err; } /* @@ -295,16 +295,16 @@ check_inode_names( if (error == ESTALE) return ESTALE; str_errno(ctx, descr_render(&dsc)); - goto out; + goto err; } error = check_dirent_names(ctx, &dsc, &fd, bstat); if (error) - goto out; + goto err_fd; } -out: progress_add(1); +err_fd: if (fd >= 0) { err2 = close(fd); if (err2) @@ -312,7 +312,7 @@ check_inode_names( if (!error && err2) error = err2; } - +err: if (error) *aborted = true; if (!error && *aborted) From patchwork Tue Jul 2 01:21: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: 13718872 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 214BD8F4E for ; Tue, 2 Jul 2024 01:21: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=1719883299; cv=none; b=ePCsRvGXxxDYgF06nk3HHmmUc/8ITLXoISvGXVFLj5WkQbeLVQNfhCOjllGBhBryzO2e8+PQojyn7XW9xHiYT2ZSwYnQymlYWDw5WK5IErya7gDSq60TTpqYhRpb+m0FPEjaoikWD8pXkQm18/QN8y6eq5XeUPF+mSjW+o7N9AY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719883299; c=relaxed/simple; bh=GEWQc9LmccJ/ZKCqwV2bd7rpOLXXdioFC8pBNdHivJk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mhkVcAHomVrrIiANLOffIDuMRRlYyeBKjYobNAQzR8Sm5hpLRJXxSMtlZtye1wuY7zWqg4v7xWdkbcNKks9JJ334L5cexBUJ/9hZWuDLEiUgqo9IRWSBSDSOBy0FM/vH+fmCoE1HX6B7mnx7jz72uNS8ijhWrSdF/ece8r/htP8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=p7XG1/J9; 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="p7XG1/J9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 00CB6C116B1; Tue, 2 Jul 2024 01:21:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719883299; bh=GEWQc9LmccJ/ZKCqwV2bd7rpOLXXdioFC8pBNdHivJk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=p7XG1/J9+xNGEksmVVY0HOTV6nUxyb78mba+M2gRouh7h+3UT3nwmYtQiQ52VphHN dKil8WMI5g1SspG9uZyhQOzAnrkgYmpKtEKtYjnvHsfZ9IxL+WBh48Z1a/r6pGi33P gXhsNv/KdQPZuV7W6mJMKT3KosTPAvNYLS94K7bRvjnRvN64YWRpshDEBoXYgALknc MQ92AKJWuepwVnH+9VVl0o3/6WOSsylgsV54iCairwjK4e+Q91ZZKRouuvIcmPKyKW wr2AmSgdCQ8M52aqNmSv+XiRctl3KdjFPXcO5NG5Oq5LW6040IfTvTdPKfKhnuBK3R JO7YKFem8uG1Q== Date: Mon, 01 Jul 2024 18:21:38 -0700 Subject: [PATCH 4/5] xfs_scrub: detect and repair directory tree corruptions From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988122757.2012320.11258096209141176786.stgit@frogsfrogsfrogs> In-Reply-To: <171988122691.2012320.13207835630113271818.stgit@frogsfrogsfrogs> References: <171988122691.2012320.13207835630113271818.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 Now that we have online fsck for directory tree structure problems, we need to find a place to call it. The scanner requires that parent pointers are enabled, that directory link counts are correct, and that every directory entry has a corresponding parent pointer. Therefore, we can only run it after phase 4 fixes every file, and phase 5 resets the link counts. In other words, we call it as part of the phase 5 file scan that we do to warn about weird looking file names. This has the added benefit that opening the directory by handle is less likely to fail if there are loops in the directory structure. For now, only plumb in enough to try to fix directory tree problems right away; the next patch will make phase 5 retry the dirloop scanner until the problems are fixed or we stop making forward progress. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- scrub/phase5.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/scrub/phase5.c b/scrub/phase5.c index b37196277554..6c8dee66e6e2 100644 --- a/scrub/phase5.c +++ b/scrub/phase5.c @@ -252,6 +252,47 @@ render_ino_from_handle( bstat->bs_gen, NULL); } +/* + * Check the directory structure for problems that could cause open_by_handle + * not to work. Returns 0 for no problems; EADDRNOTAVAIL if the there are + * problems that would prevent name checking. + */ +static int +check_dir_connection( + struct scrub_ctx *ctx, + struct descr *dsc, + const struct xfs_bulkstat *bstat) +{ + struct scrub_item sri = { }; + int error; + + /* The dirtree scrubber only works when parent pointers are enabled */ + if (!(ctx->mnt.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_PARENT)) + return 0; + + scrub_item_init_file(&sri, bstat); + scrub_item_schedule(&sri, XFS_SCRUB_TYPE_DIRTREE); + + error = scrub_item_check_file(ctx, &sri, -1); + if (error) { + str_liberror(ctx, error, _("checking directory loops")); + return error; + } + + error = repair_file_corruption(ctx, &sri, -1); + if (error) { + str_liberror(ctx, error, _("repairing directory loops")); + return error; + } + + /* No directory tree problems? Clear this inode if it was deferred. */ + if (repair_item_count_needsrepair(&sri) == 0) + return 0; + + str_corrupt(ctx, descr_render(dsc), _("directory loop uncorrected!")); + return EADDRNOTAVAIL; +} + /* * Verify the connectivity of the directory tree. * We know that the kernel's open-by-handle function will try to reconnect @@ -275,6 +316,20 @@ check_inode_names( descr_set(&dsc, bstat); background_sleep(); + /* + * Try to fix directory loops before we have problems opening files by + * handle. + */ + if (S_ISDIR(bstat->bs_mode)) { + error = check_dir_connection(ctx, &dsc, bstat); + if (error == EADDRNOTAVAIL) { + error = 0; + goto out; + } + if (error) + goto err; + } + /* Warn about naming problems in xattrs. */ if (bstat->bs_xflags & FS_XFLAG_HASATTR) { error = check_xattr_names(ctx, &dsc, handle, bstat); @@ -315,6 +370,7 @@ check_inode_names( err: if (error) *aborted = true; +out: if (!error && *aborted) error = ECANCELED; From patchwork Tue Jul 2 01:21: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: 13718873 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 C026738B for ; Tue, 2 Jul 2024 01:21: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=1719883314; cv=none; b=fmfVl0hgaHCGYCXdpI+N6Sh8YQDIbIqrSisofGjSY4jRUsjfun6Iv+Jrfp/UEe+HzjWCEYR7pGcLQr5q9I1O+IdpithssaKsp/7tNaaqB05sKmfp3iy4gN6IONduAmr3CNu29IsRfWmLOjXA1JCROp/9iTFbmoB4ui/i9ZiXyAU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719883314; c=relaxed/simple; bh=kpDGN0wIARA3m7TmCqr/0YWxMBhZoMs2JGVfmAc+toI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EES/w2stoQrqoCvMP2swG0EqY/0SI7YYJ23IevW4nl3olSc8RGqXEx03Gj7/8GpjMJvJOStDZ/yJp/hdgIhzOjJEfia2LnQwuhmJ+zv9TUpWGdGVv3ElkrE5BIkk40yJshKD+xRYBQU63txtmzYwlZiPJa6PxSGoZVLaW1QctbA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=J4PomM3+; 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="J4PomM3+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 94B63C116B1; Tue, 2 Jul 2024 01:21:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719883314; bh=kpDGN0wIARA3m7TmCqr/0YWxMBhZoMs2JGVfmAc+toI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=J4PomM3+fVSv2BXjd9sDU+3bQJ2YOj8+czX59pj8qx+ChkQ7ceA1M4QHxTPhTs7n+ /ectKlfTIwMiASn/Ceoz7sTYQ2MaIC8s63j3i981MhLBNV9r54gufY4+iN/4JU0uV+ T007NX2b+PoibVqmRx/p0zK8XXzyoq2Vq6PYlPWz9aJ2qcKYynoMPaioZEj0r78Gnt x1NfOmaLRzns/c6zPTxrLiJwCsyCj0eSWI7Me/AUjtRHHds0g0WWi8kBkWaf3hEKRD G1SPEymKIe0itdqDPoUolaMOR0WhuxnEkR9ZXSHsIoKD+NzTaXFpEYT1Cqpz4DFPhk osSRyY42sCQ/g== Date: Mon, 01 Jul 2024 18:21:54 -0700 Subject: [PATCH 5/5] xfs_scrub: defer phase5 file scans if dirloop fails From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988122772.2012320.15047134515177396515.stgit@frogsfrogsfrogs> In-Reply-To: <171988122691.2012320.13207835630113271818.stgit@frogsfrogsfrogs> References: <171988122691.2012320.13207835630113271818.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 we cannot fix dirloop problems during the initial phase 5 inode scan, defer them until later. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- scrub/phase5.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- scrub/repair.c | 13 +++ scrub/repair.h | 2 + 3 files changed, 216 insertions(+), 14 deletions(-) diff --git a/scrub/phase5.c b/scrub/phase5.c index 6c8dee66e6e2..f6c295c64ada 100644 --- a/scrub/phase5.c +++ b/scrub/phase5.c @@ -18,6 +18,8 @@ #include "libfrog/workqueue.h" #include "libfrog/fsgeom.h" #include "libfrog/scrub.h" +#include "libfrog/bitmap.h" +#include "libfrog/bulkstat.h" #include "xfs_scrub.h" #include "common.h" #include "inodes.h" @@ -29,6 +31,36 @@ /* Phase 5: Full inode scans and check directory connectivity. */ +struct ncheck_state { + struct scrub_ctx *ctx; + + /* Have we aborted this scan? */ + bool aborted; + + /* Is this the last time we're going to process deferred inodes? */ + bool last_call; + + /* Did we fix at least one thing while walking @cur->deferred? */ + bool fixed_something; + + /* Lock for this structure */ + pthread_mutex_t lock; + + /* + * Inodes that are involved with directory tree structure corruptions + * are marked here. This will be NULL until the first corruption is + * noted. + */ + struct bitmap *new_deferred; + + /* + * Inodes that we're reprocessing due to earlier directory tree + * structure corruption problems are marked here. This will be NULL + * during the first (parallel) inode scan. + */ + struct bitmap *cur_deferred; +}; + /* * Warn about problematic bytes in a directory/attribute name. That means * terminal control characters and escape sequences, since that could be used @@ -252,6 +284,26 @@ render_ino_from_handle( bstat->bs_gen, NULL); } +/* Defer this inode until later. */ +static inline int +defer_inode( + struct ncheck_state *ncs, + uint64_t ino) +{ + int error; + + pthread_mutex_lock(&ncs->lock); + if (!ncs->new_deferred) { + error = -bitmap_alloc(&ncs->new_deferred); + if (error) + goto unlock; + } + error = -bitmap_set(ncs->new_deferred, ino, 1); +unlock: + pthread_mutex_unlock(&ncs->lock); + return error; +} + /* * Check the directory structure for problems that could cause open_by_handle * not to work. Returns 0 for no problems; EADDRNOTAVAIL if the there are @@ -260,7 +312,7 @@ render_ino_from_handle( static int check_dir_connection( struct scrub_ctx *ctx, - struct descr *dsc, + struct ncheck_state *ncs, const struct xfs_bulkstat *bstat) { struct scrub_item sri = { }; @@ -279,17 +331,31 @@ check_dir_connection( return error; } - error = repair_file_corruption(ctx, &sri, -1); + if (ncs->last_call) + error = repair_file_corruption_now(ctx, &sri, -1); + else + error = repair_file_corruption(ctx, &sri, -1); if (error) { str_liberror(ctx, error, _("repairing directory loops")); return error; } /* No directory tree problems? Clear this inode if it was deferred. */ - if (repair_item_count_needsrepair(&sri) == 0) + if (repair_item_count_needsrepair(&sri) == 0) { + if (ncs->cur_deferred) + ncs->fixed_something = true; return 0; + } + + /* Don't defer anything during last call. */ + if (ncs->last_call) + return 0; + + /* Directory tree structure problems exist; do not check names yet. */ + error = defer_inode(ncs, bstat->bs_ino); + if (error) + return error; - str_corrupt(ctx, descr_render(dsc), _("directory loop uncorrected!")); return EADDRNOTAVAIL; } @@ -308,7 +374,7 @@ check_inode_names( void *arg) { DEFINE_DESCR(dsc, ctx, render_ino_from_handle); - bool *aborted = arg; + struct ncheck_state *ncs = arg; int fd = -1; int error = 0; int err2; @@ -321,7 +387,7 @@ check_inode_names( * handle. */ if (S_ISDIR(bstat->bs_mode)) { - error = check_dir_connection(ctx, &dsc, bstat); + error = check_dir_connection(ctx, ncs, bstat); if (error == EADDRNOTAVAIL) { error = 0; goto out; @@ -369,14 +435,120 @@ check_inode_names( } err: if (error) - *aborted = true; + ncs->aborted = true; out: - if (!error && *aborted) + if (!error && ncs->aborted) error = ECANCELED; return error; } +/* Try to check_inode_names on a specific inode. */ +static int +retry_deferred_inode( + struct ncheck_state *ncs, + struct xfs_handle *handle, + uint64_t ino) +{ + struct xfs_bulkstat bstat; + struct scrub_ctx *ctx = ncs->ctx; + unsigned int flags = 0; + int error; + + error = -xfrog_bulkstat_single(&ctx->mnt, ino, flags, &bstat); + if (error == ENOENT) { + /* Directory is gone, mark it clear. */ + ncs->fixed_something = true; + return 0; + } + if (error) + return error; + + handle->ha_fid.fid_ino = bstat.bs_ino; + handle->ha_fid.fid_gen = bstat.bs_gen; + + return check_inode_names(ncs->ctx, handle, &bstat, ncs); +} + +/* Try to check_inode_names on a range of inodes from the bitmap. */ +static int +retry_deferred_inode_range( + uint64_t ino, + uint64_t len, + void *arg) +{ + struct xfs_handle handle = { }; + struct ncheck_state *ncs = arg; + struct scrub_ctx *ctx = ncs->ctx; + uint64_t i; + int error; + + 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; + + for (i = 0; i < len; i++) { + error = retry_deferred_inode(ncs, &handle, ino + i); + if (error) + return error; + } + + return 0; +} + +/* + * Try to check_inode_names on inodes that were deferred due to directory tree + * problems until we stop making progress. + */ +static int +retry_deferred_inodes( + struct scrub_ctx *ctx, + struct ncheck_state *ncs) +{ + int error; + + if (!ncs->new_deferred) + return 0; + + /* + * Try to repair things until we stop making forward progress or we + * don't observe any new corruptions. During the loop, we do not + * complain about the corruptions that do not get fixed. + */ + do { + ncs->cur_deferred = ncs->new_deferred; + ncs->new_deferred = NULL; + ncs->fixed_something = false; + + error = -bitmap_iterate(ncs->cur_deferred, + retry_deferred_inode_range, ncs); + if (error) + return error; + + bitmap_free(&ncs->cur_deferred); + } while (ncs->fixed_something && ncs->new_deferred); + + /* + * Try one last time to fix things, and complain about any problems + * that remain. + */ + if (!ncs->new_deferred) + return 0; + + ncs->cur_deferred = ncs->new_deferred; + ncs->new_deferred = NULL; + ncs->last_call = true; + + error = -bitmap_iterate(ncs->cur_deferred, + retry_deferred_inode_range, ncs); + if (error) + return error; + + bitmap_free(&ncs->cur_deferred); + return 0; +} + #ifndef FS_IOC_GETFSLABEL # define FSLABEL_MAX 256 # define FS_IOC_GETFSLABEL _IOR(0x94, 49, char[FSLABEL_MAX]) @@ -568,9 +740,10 @@ int phase5_func( struct scrub_ctx *ctx) { - bool aborted = false; + struct ncheck_state ncs = { .ctx = ctx }; int ret; + /* * Check and fix anything that requires a full filesystem scan. We do * this after we've checked all inodes and repaired anything that could @@ -590,14 +763,28 @@ _("Filesystem has errors, skipping connectivity checks.")); if (ret) return ret; - ret = scrub_scan_all_inodes(ctx, check_inode_names, &aborted); + pthread_mutex_init(&ncs.lock, NULL); + + ret = scrub_scan_all_inodes(ctx, check_inode_names, &ncs); if (ret) - return ret; - if (aborted) - return ECANCELED; + goto out_lock; + if (ncs.aborted) { + ret = ECANCELED; + goto out_lock; + } + + ret = retry_deferred_inodes(ctx, &ncs); + if (ret) + goto out_lock; scrub_report_preen_triggers(ctx); - return 0; +out_lock: + pthread_mutex_destroy(&ncs.lock); + if (ncs.new_deferred) + bitmap_free(&ncs.new_deferred); + if (ncs.cur_deferred) + bitmap_free(&ncs.cur_deferred); + return ret; } /* Estimate how much work we're going to do. */ diff --git a/scrub/repair.c b/scrub/repair.c index 0258210722ba..4fed86134eda 100644 --- a/scrub/repair.c +++ b/scrub/repair.c @@ -732,6 +732,19 @@ repair_file_corruption( XRM_REPAIR_ONLY | XRM_NOPROGRESS); } +/* Repair all parts of this file or complain if we cannot. */ +int +repair_file_corruption_now( + struct scrub_ctx *ctx, + struct scrub_item *sri, + int override_fd) +{ + repair_item_boost_priorities(sri); + + return repair_item_class(ctx, sri, override_fd, SCRUB_ITEM_CORRUPT, + XRM_REPAIR_ONLY | XRM_NOPROGRESS | XRM_FINAL_WARNING); +} + /* * Repair everything in this filesystem object that needs it. This includes * cross-referencing and preening. diff --git a/scrub/repair.h b/scrub/repair.h index 411a379f6faa..ec4aa381a82d 100644 --- a/scrub/repair.h +++ b/scrub/repair.h @@ -76,6 +76,8 @@ int action_list_process(struct scrub_ctx *ctx, struct action_list *alist, int repair_item_corruption(struct scrub_ctx *ctx, struct scrub_item *sri); int repair_file_corruption(struct scrub_ctx *ctx, struct scrub_item *sri, int override_fd); +int repair_file_corruption_now(struct scrub_ctx *ctx, struct scrub_item *sri, + int override_fd); int repair_item(struct scrub_ctx *ctx, struct scrub_item *sri, unsigned int repair_flags); int repair_item_to_action_item(struct scrub_ctx *ctx,