From patchwork Tue Jul 2 00:53: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: 13718751 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 61A5CD50F for ; Tue, 2 Jul 2024 00:53:45 +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=1719881625; cv=none; b=JXL3xCGy+jX2wXea16wxB4icekF/GqG3JQMuhPQYVjl+WhBM7/QRMZWzrBvAkxRVFYBFLLD6/nGKriFFGw4Ye+v0QDUluBqJUGrDgaynV9GB/DySU3FN7RvCOS/XQeX1DS36R38K0SLDivo1lDqV3fuFWKgqakQYHHAZT5tBIA4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881625; c=relaxed/simple; bh=8/gMQPTBN/sabomYY3UypayLB+aYsg98BOFKGMqYlNs=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WiG3Ep0InAIWkPJNVIP6ez2SWycBpEtuHrezK6v9IB3NfClDs+eF55WsNbNtGGbad9iCsNzLEgrnygIcwqP6O0S3L1iK98LvW/bBYwqkvm7tgde+gZ3U5l7O9C2MlJmcp0Smao/gA1kYGO0RKbTQa7aH+eBCIKfMeOI3Z5b+HNI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FzFr4OAl; 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="FzFr4OAl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 39165C116B1; Tue, 2 Jul 2024 00:53:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881625; bh=8/gMQPTBN/sabomYY3UypayLB+aYsg98BOFKGMqYlNs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=FzFr4OAl3V8Y0MW2NuOXcmBOkhY1cmcRdb+32oO8m4HZS53ac9gcd4Vf0NYEFrNjF X9Put1ZMRM1hR4qfPZpLlvd498sYbXwJgZsz0WJG74p2iIAhhmWpvzvab2371QZruO avg998WDAyrnvR5gAXj9OllTcSjCiXbEvLPNJlh0eZPy6wDFXBHGFSjqhoWoRnq1W0 PcSQ1pRYmxCTOoJT9o+2TUFrH1jIBfPiqlJqn0pORXbCYXEV64M6/LLPBZyjWlkm2W pJPqdsnwwj6jV9pdpJTUOpUGZJJCFJ7UEZ/EYzxnc3LoDJqWeoj89mRKR9hv7z+XeY QYPv4rJCb5NLQ== Date: Mon, 01 Jul 2024 17:53:44 -0700 Subject: [PATCH 01/12] man: document the exchange-range ioctl From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116726.2006519.12422589085600264393.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 the new file data exchange ioctl. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- man/man2/ioctl_xfs_exchange_range.2 | 278 +++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 man/man2/ioctl_xfs_exchange_range.2 diff --git a/man/man2/ioctl_xfs_exchange_range.2 b/man/man2/ioctl_xfs_exchange_range.2 new file mode 100644 index 000000000000..450db9c25c12 --- /dev/null +++ b/man/man2/ioctl_xfs_exchange_range.2 @@ -0,0 +1,278 @@ +.\" Copyright (c) 2020-2024 Oracle. All rights reserved. +.\" +.\" %%%LICENSE_START(GPLv2+_DOC_FULL) +.\" This is free documentation; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License as +.\" published by the Free Software Foundation; either version 2 of +.\" the License, or (at your option) any later version. +.\" +.\" The GNU General Public License's references to "object code" +.\" and "executables" are to be interpreted as the output of any +.\" document formatting or typesetting system, including +.\" intermediate and printed output. +.\" +.\" This manual is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public +.\" License along with this manual; if not, see +.\" . +.\" %%%LICENSE_END +.TH IOCTL-XFS-EXCHANGE-RANGE 2 2024-02-10 "XFS" +.SH NAME +ioctl_xfs_exchange_range \- exchange the contents of parts of two files +.SH SYNOPSIS +.br +.B #include +.br +.B #include +.PP +.BI "int ioctl(int " file2_fd ", XFS_IOC_EXCHANGE_RANGE, struct xfs_exchange_range *" arg ); +.SH DESCRIPTION +Given a range of bytes in a first file +.B file1_fd +and a second range of bytes in a second file +.BR file2_fd , +this +.BR ioctl (2) +exchanges the contents of the two ranges. +.PP +Exchanges are atomic with regards to concurrent file operations. +Implementations must guarantee that readers see either the old contents or the +new contents in their entirety, even if the system fails. +.PP +The system call parameters are conveyed in structures of the following form: +.PP +.in +4n +.EX +struct xfs_exchange_range { + __s32 file1_fd; + __u32 pad; + __u64 file1_offset; + __u64 file2_offset; + __u64 length; + __u64 flags; +}; +.EE +.in +.PP +The field +.I pad +must be zero. +.PP +The fields +.IR file1_fd ", " file1_offset ", and " length +define the first range of bytes to be exchanged. +.PP +The fields +.IR file2_fd ", " file2_offset ", and " length +define the second range of bytes to be exchanged. +.PP +Both files must be from the same filesystem mount. +If the two file descriptors represent the same file, the byte ranges must not +overlap. +Most disk-based filesystems require that the starts of both ranges must be +aligned to the file block size. +If this is the case, the ends of the ranges must also be so aligned unless the +.B XFS_EXCHANGE_RANGE_TO_EOF +flag is set. + +.PP +The field +.I flags +control the behavior of the exchange operation. +.RS 0.4i +.TP +.B XFS_EXCHANGE_RANGE_TO_EOF +Ignore the +.I length +parameter. +All bytes in +.I file1_fd +from +.I file1_offset +to EOF are moved to +.IR file2_fd , +and file2's size is set to +.RI ( file2_offset "+(" file1_length - file1_offset )). +Meanwhile, all bytes in file2 from +.I file2_offset +to EOF are moved to file1 and file1's size is set to +.RI ( file1_offset "+(" file2_length - file2_offset )). +.TP +.B XFS_EXCHANGE_RANGE_DSYNC +Ensure that all modified in-core data in both file ranges and all metadata +updates pertaining to the exchange operation are flushed to persistent storage +before the call returns. +Opening either file descriptor with +.BR O_SYNC " or " O_DSYNC +will have the same effect. +.TP +.B XFS_EXCHANGE_RANGE_FILE1_WRITTEN +Only exchange sub-ranges of +.I file1_fd +that are known to contain data written by application software. +Each sub-range may be expanded (both upwards and downwards) to align with the +file allocation unit. +For files on the data device, this is one filesystem block. +For files on the realtime device, this is the realtime extent size. +This facility can be used to implement fast atomic scatter-gather writes of any +complexity for software-defined storage targets if all writes are aligned to +the file allocation unit. +.TP +.B XFS_EXCHANGE_RANGE_DRY_RUN +Check the parameters and the feasibility of the operation, but do not change +anything. +.RE +.PP +.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 EBADF +.IR file1_fd +is not open for reading and writing or is open for append-only writes; or +.IR file2_fd +is not open for reading and writing or is open for append-only writes. +.TP +.B EINVAL +The parameters are not correct for these files. +This error can also appear if either file descriptor represents +a device, FIFO, or socket. +Disk filesystems generally require the offset and length arguments +to be aligned to the fundamental block sizes of both files. +.TP +.B EIO +An I/O error occurred. +.TP +.B EISDIR +One of the files is a directory. +.TP +.B ENOMEM +The kernel was unable to allocate sufficient memory to perform the +operation. +.TP +.B ENOSPC +There is not enough free space in the filesystem exchange the contents safely. +.TP +.B EOPNOTSUPP +The filesystem does not support exchanging bytes between the two +files. +.TP +.B EPERM +.IR file1_fd " or " file2_fd +are immutable. +.TP +.B ETXTBSY +One of the files is a swap file. +.TP +.B EUCLEAN +The filesystem is corrupt. +.TP +.B EXDEV +.IR file1_fd " and " file2_fd +are not on the same mounted filesystem. +.SH CONFORMING TO +This API is XFS-specific. +.SH USE CASES +.PP +Several use cases are imagined for this system call. +In all cases, application software must coordinate updates to the file +because the exchange is performed unconditionally. +.PP +The first is a data storage program that wants to commit non-contiguous updates +to a file atomically and coordinates write access to that file. +This can be done by creating a temporary file, calling +.BR FICLONE (2) +to share the contents, and staging the updates into the temporary file. +The +.B FULL_FILES +flag is recommended for this purpose. +The temporary file can be deleted or punched out afterwards. +.PP +An example program might look like this: +.PP +.in +4n +.EX +int fd = open("/some/file", O_RDWR); +int temp_fd = open("/some", O_TMPFILE | O_RDWR); + +ioctl(temp_fd, FICLONE, fd); + +/* append 1MB of records */ +lseek(temp_fd, 0, SEEK_END); +write(temp_fd, data1, 1000000); + +/* update record index */ +pwrite(temp_fd, data1, 600, 98765); +pwrite(temp_fd, data2, 320, 54321); +pwrite(temp_fd, data2, 15, 0); + +/* commit the entire update */ +struct xfs_exchange_range args = { + .file1_fd = temp_fd, + .flags = XFS_EXCHANGE_RANGE_TO_EOF, +}; + +ioctl(fd, XFS_IOC_EXCHANGE_RANGE, &args); +.EE +.in +.PP +The second is a software-defined storage host (e.g. a disk jukebox) which +implements an atomic scatter-gather write command. +Provided the exported disk's logical block size matches the file's allocation +unit size, this can be done by creating a temporary file and writing the data +at the appropriate offsets. +It is recommended that the temporary file be truncated to the size of the +regular file before any writes are staged to the temporary file to avoid issues +with zeroing during EOF extension. +Use this call with the +.B FILE1_WRITTEN +flag to exchange only the file allocation units involved in the emulated +device's write command. +The temporary file should be truncated or punched out completely before being +reused to stage another write. +.PP +An example program might look like this: +.PP +.in +4n +.EX +int fd = open("/some/file", O_RDWR); +int temp_fd = open("/some", O_TMPFILE | O_RDWR); +struct stat sb; +int blksz; + +fstat(fd, &sb); +blksz = sb.st_blksize; + +/* land scatter gather writes between 100fsb and 500fsb */ +pwrite(temp_fd, data1, blksz * 2, blksz * 100); +pwrite(temp_fd, data2, blksz * 20, blksz * 480); +pwrite(temp_fd, data3, blksz * 7, blksz * 257); + +/* commit the entire update */ +struct xfs_exchange_range args = { + .file1_fd = temp_fd, + .file1_offset = blksz * 100, + .file2_offset = blksz * 100, + .length = blksz * 400, + .flags = XFS_EXCHANGE_RANGE_FILE1_WRITTEN | + XFS_EXCHANGE_RANGE_FILE1_DSYNC, +}; + +ioctl(fd, XFS_IOC_EXCHANGE_RANGE, &args); +.EE +.in +.B +.SH NOTES +.PP +Some filesystems may limit the amount of data or the number of extents that can +be exchanged in a single call. +.SH SEE ALSO +.BR ioctl (2) From patchwork Tue Jul 2 00:54:00 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: 13718752 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 37948D50F for ; Tue, 2 Jul 2024 00:54:01 +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=1719881641; cv=none; b=ba2mL7kzh/ZmyReBD+mStW1K19QJIuZHt8DaNkq2QgIvpv4BKlfkEJB9RlBBo9w1K8WQFN8OfelqgwtzI9LSvYa4ePFONnue8fR7Sa78t8rPSRreFjQwbe8cwPZ2AJI+CA4P7RMymjJ97y1BQr0zIos/nK7sPqeK+I33NgtA0RM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881641; c=relaxed/simple; bh=Xt9/MDLb/ODLkAhoKWy3KEAz+FLpPn9xyp9Ae1tccc4=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DORIQzl5EFiJflJf80VgnSQVv2o7KwkSwY4QzebZ6ppkN6JKEy+OTu2ftgNaUNpWqrcMdVFkv56kKyeMu0686TVw7hZOHNgHukAMEuESzk0z8ZayUyHShLkfBJCU0i24sQI5/cJT9NN2vqz1PEDBWsLYNokUDET/z8cRcdUcREI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cExTIcCi; 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="cExTIcCi" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D2636C116B1; Tue, 2 Jul 2024 00:54:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881640; bh=Xt9/MDLb/ODLkAhoKWy3KEAz+FLpPn9xyp9Ae1tccc4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=cExTIcCi4FIVjjHETYz+am2w/+DtFHyUXWSAIuCL5RZxiyxDidusvycHApbNElO3u uUFNIVyUkfQrLalzjzrn8dOx0QBUTtr/hykhvumW2tZGB02TeuKce+39eMBAo+81NZ dSXMscziGciM6QnNrCZRmvRp63Nz9cB0iCa2MLT9a35IOoDt6EvHOgUEe3pC0S4+D0 3TfVu5Blx+XPFAU+kJDy7oIDC0BYEmHqHwu4tahI3bUcm31CXs9MInVEl4L6YueMep vT1GuXjBz3e1/D93Lrm4Mvp7PI5bB0V0ksaXreiy1JNJPv/TeOom3N3EoBjw4cbu/H LdUsx2JJrvqXw== Date: Mon, 01 Jul 2024 17:54:00 -0700 Subject: [PATCH 02/12] man: document XFS_FSOP_GEOM_FLAGS_EXCHRANGE From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116741.2006519.5093845148682277814.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 this new feature flag in the fs geometry ioctl. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- man/man2/ioctl_xfs_fsgeometry.2 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/man/man2/ioctl_xfs_fsgeometry.2 b/man/man2/ioctl_xfs_fsgeometry.2 index f59a6e8a6a20..54fd89390883 100644 --- a/man/man2/ioctl_xfs_fsgeometry.2 +++ b/man/man2/ioctl_xfs_fsgeometry.2 @@ -211,6 +211,9 @@ Filesystem stores reverse mappings of blocks to owners. .TP .B XFS_FSOP_GEOM_FLAGS_REFLINK Filesystem supports sharing blocks between files. +.TP +.B XFS_FSOP_GEOM_FLAGS_EXCHRANGE +Filesystem can exchange file contents atomically via XFS_IOC_EXCHANGE_RANGE. .RE .SH XFS METADATA HEALTH REPORTING .PP From patchwork Tue Jul 2 00:54:16 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: 13718753 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 F3468D50F for ; Tue, 2 Jul 2024 00:54:16 +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=1719881657; cv=none; b=tYw5xG3R909URXt6raXMuPzGkzrRjbavhsHH3tdtHBxv9vRW7YWNu4xZkRWIn6UIuHhFq9l+epnjQp5JVeI5Pv5x9zYri+f4u/kJe3/kRNjuAm53UXWjTSAhB/l2E++9jJz+n0IlGrbrPRR9uW8SgkmkmoDaF7OrqjvVJfmgIWg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881657; c=relaxed/simple; bh=yY4T8VhpKvz+9XmPpMI9zDFb48sJjKsY/z1dVD6kkNw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JcYhjQ8geAxANRVAuRnRi/q6t15oi3fJhtsLDEdZig0kZkO7ZJL0eDeODeNujlceAW7LwGebui52yelPKjxakiCE7xOFnqfl8rHy0Y3m46BDuJJffL1rM9jmBeDMWx/mmAmiO14ZwYyddbZYjunqEgr53LnaFAs1p7ULaRo0Xj8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nhiPKYSu; 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="nhiPKYSu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 777A5C116B1; Tue, 2 Jul 2024 00:54:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881656; bh=yY4T8VhpKvz+9XmPpMI9zDFb48sJjKsY/z1dVD6kkNw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=nhiPKYSuOfA5x4RuO0kdaK2Z2alEhozRNPrJqoelpJ4RqdcEhAQpiJRf5bl/j8vRN Nb5hB40wFXeby4IZRMMhcf6J8mr2LJ8fINFo6UYH7K+RkrESoCbrIdV0BIMpmyz/Bb BIIHw5/Yuy+ZAixLkhyOxb/mx5pmi+AuibZuGpKp2U9A3tyMkUwyEKZpDZoN/r5RVt rjF2ktJL/j3rRrK2MuaQKh6/Gwtdtb5zYXfTftj8I6DHu+GtGYYF5UJdIXWZ60Sa7s FHVl2zcLK1iriuNPrRwO0sHjEuzCw/6kqF0jXOM6ihpl67qCKuCVVkgxK3E8+aCW3d X8pn9kGqXTLcg== Date: Mon, 01 Jul 2024 17:54:16 -0700 Subject: [PATCH 03/12] libhandle: add support for bulkstat v5 From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116756.2006519.10115349070206614078.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 support to libhandle for generating file handles with bulkstat v5 structures. xfs_fsr will need this to be able to interface with the new vfs range swap ioctl, and other client programs will probably want this over time. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- include/jdm.h | 24 +++++++++++ libhandle/jdm.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) diff --git a/include/jdm.h b/include/jdm.h index c57fcae7fcac..445737a6b5f8 100644 --- a/include/jdm.h +++ b/include/jdm.h @@ -11,6 +11,7 @@ typedef void jdm_fshandle_t; /* filesystem handle */ typedef void jdm_filehandle_t; /* filehandle */ struct xfs_bstat; +struct xfs_bulkstat; struct attrlist_cursor; struct parent; @@ -23,6 +24,9 @@ jdm_new_filehandle( jdm_filehandle_t **handlep, /* new filehandle */ jdm_fshandle_t *fshandlep, /* filesystem filehandle */ struct xfs_bstat *sp); /* bulkstat info */ +extern void jdm_new_filehandle_v5(jdm_filehandle_t **handlep, size_t *hlen, + jdm_fshandle_t *fshandlep, struct xfs_bulkstat *sp); + extern void jdm_delete_filehandle( jdm_filehandle_t *handlep,/* filehandle to delete */ size_t hlen); /* filehandle size */ @@ -32,35 +36,55 @@ jdm_open( jdm_fshandle_t *fshandlep, struct xfs_bstat *sp, intgen_t oflags); +extern intgen_t jdm_open_v5(jdm_fshandle_t *fshandlep, struct xfs_bulkstat *sp, + intgen_t oflags); + extern intgen_t jdm_readlink( jdm_fshandle_t *fshandlep, struct xfs_bstat *sp, char *bufp, size_t bufsz); +extern intgen_t jdm_readlink_v5(jdm_fshandle_t *fshandlep, + struct xfs_bulkstat *sp, char *bufp, size_t bufsz); + extern intgen_t jdm_attr_multi( jdm_fshandle_t *fshp, struct xfs_bstat *statp, char *bufp, int rtrvcnt, int flags); +extern intgen_t jdm_attr_multi_v5(jdm_fshandle_t *fshp, + struct xfs_bulkstat *statp, char *bufp, int rtrvcnt, + int flags); + extern intgen_t jdm_attr_list( jdm_fshandle_t *fshp, struct xfs_bstat *statp, char *bufp, size_t bufsz, int flags, struct attrlist_cursor *cursor); +extern intgen_t jdm_attr_list_v5(jdm_fshandle_t *fshp, + struct xfs_bulkstat *statp, char *bufp, size_t bufsz, int + flags, struct attrlist_cursor *cursor); + extern int jdm_parents( jdm_fshandle_t *fshp, struct xfs_bstat *statp, struct parent *bufp, size_t bufsz, unsigned int *count); +extern int jdm_parents_v5(jdm_fshandle_t *fshp, struct xfs_bulkstat *statp, + struct parent *bufp, size_t bufsz, unsigned int *count); + extern int jdm_parentpaths( jdm_fshandle_t *fshp, struct xfs_bstat *statp, struct parent *bufp, size_t bufsz, unsigned int *count); +extern int jdm_parentpaths_v5(jdm_fshandle_t *fshp, struct xfs_bulkstat *statp, + struct parent *bufp, size_t bufsz, unsigned int *count); + /* macro for determining the size of a structure member */ #define sizeofmember( t, m ) sizeof( ( ( t * )0 )->m ) diff --git a/libhandle/jdm.c b/libhandle/jdm.c index 07b0c60985ee..e21aff2b2c19 100644 --- a/libhandle/jdm.c +++ b/libhandle/jdm.c @@ -41,6 +41,19 @@ jdm_fill_filehandle( filehandle_t *handlep, handlep->fh_ino = statp->bs_ino; } +static void +jdm_fill_filehandle_v5( + struct filehandle *handlep, + struct fshandle *fshandlep, + struct xfs_bulkstat *statp) +{ + handlep->fh_fshandle = *fshandlep; + handlep->fh_sz_following = FILEHANDLE_SZ_FOLLOWING; + memset(handlep->fh_pad, 0, FILEHANDLE_SZ_PAD); + handlep->fh_gen = statp->bs_gen; + handlep->fh_ino = statp->bs_ino; +} + jdm_fshandle_t * jdm_getfshandle( char *mntpnt ) { @@ -90,6 +103,22 @@ jdm_new_filehandle( jdm_filehandle_t **handlep, jdm_fill_filehandle(*handlep, (fshandle_t *) fshandlep, statp); } +void +jdm_new_filehandle_v5( + jdm_filehandle_t **handlep, + size_t *hlen, + jdm_fshandle_t *fshandlep, + struct xfs_bulkstat *statp) +{ + /* allocate and fill filehandle */ + *hlen = sizeof(filehandle_t); + *handlep = (filehandle_t *) malloc(*hlen); + if (!*handlep) + return; + + jdm_fill_filehandle_v5(*handlep, (struct fshandle *)fshandlep, statp); +} + /* ARGSUSED */ void jdm_delete_filehandle( jdm_filehandle_t *handlep, size_t hlen ) @@ -111,6 +140,19 @@ jdm_open( jdm_fshandle_t *fshp, struct xfs_bstat *statp, intgen_t oflags ) return fd; } +intgen_t +jdm_open_v5( + jdm_fshandle_t *fshp, + struct xfs_bulkstat *statp, + intgen_t oflags) +{ + struct fshandle *fshandlep = (struct fshandle *)fshp; + struct filehandle filehandle; + + jdm_fill_filehandle_v5(&filehandle, fshandlep, statp); + return open_by_fshandle(&filehandle, sizeof(filehandle), oflags); +} + intgen_t jdm_readlink( jdm_fshandle_t *fshp, struct xfs_bstat *statp, @@ -128,6 +170,20 @@ jdm_readlink( jdm_fshandle_t *fshp, return rval; } +intgen_t +jdm_readlink_v5( + jdm_fshandle_t *fshp, + struct xfs_bulkstat *statp, + char *bufp, + size_t bufsz) +{ + struct fshandle *fshandlep = (struct fshandle *)fshp; + struct filehandle filehandle; + + jdm_fill_filehandle_v5(&filehandle, fshandlep, statp); + return readlink_by_handle(&filehandle, sizeof(filehandle), bufp, bufsz); +} + int jdm_attr_multi( jdm_fshandle_t *fshp, struct xfs_bstat *statp, @@ -145,6 +201,22 @@ jdm_attr_multi( jdm_fshandle_t *fshp, return rval; } +int +jdm_attr_multi_v5( + jdm_fshandle_t *fshp, + struct xfs_bulkstat *statp, + char *bufp, + int rtrvcnt, + int flags) +{ + struct fshandle *fshandlep = (struct fshandle *)fshp; + struct filehandle filehandle; + + jdm_fill_filehandle_v5(&filehandle, fshandlep, statp); + return attr_multi_by_handle(&filehandle, sizeof(filehandle), bufp, + rtrvcnt, flags); +} + int jdm_attr_list( jdm_fshandle_t *fshp, struct xfs_bstat *statp, @@ -166,6 +238,27 @@ jdm_attr_list( jdm_fshandle_t *fshp, return rval; } +int +jdm_attr_list_v5( + jdm_fshandle_t *fshp, + struct xfs_bulkstat *statp, + char *bufp, + size_t bufsz, + int flags, + struct attrlist_cursor *cursor) +{ + struct fshandle *fshandlep = (struct fshandle *)fshp; + struct filehandle filehandle; + + /* prevent needless EINVAL from the kernel */ + if (bufsz > XFS_XATTR_LIST_MAX) + bufsz = XFS_XATTR_LIST_MAX; + + jdm_fill_filehandle_v5(&filehandle, fshandlep, statp); + return attr_list_by_handle(&filehandle, sizeof(filehandle), bufp, + bufsz, flags, cursor); +} + int jdm_parents( jdm_fshandle_t *fshp, struct xfs_bstat *statp, @@ -176,6 +269,18 @@ jdm_parents( jdm_fshandle_t *fshp, return -1; } +int +jdm_parents_v5( + jdm_fshandle_t *fshp, + struct xfs_bulkstat *statp, + struct parent *bufp, + size_t bufsz, + unsigned int *count) +{ + errno = EOPNOTSUPP; + return -1; +} + int jdm_parentpaths( jdm_fshandle_t *fshp, struct xfs_bstat *statp, @@ -185,3 +290,15 @@ jdm_parentpaths( jdm_fshandle_t *fshp, errno = EOPNOTSUPP; return -1; } + +int +jdm_parentpaths_v5( + jdm_fshandle_t *fshp, + struct xfs_bulkstat *statp, + struct parent *bufp, + size_t bufsz, + unsigned int *count) +{ + errno = EOPNOTSUPP; + return -1; +} From patchwork Tue Jul 2 00:54:31 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: 13718754 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 3E525D50F for ; Tue, 2 Jul 2024 00:54:32 +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=1719881672; cv=none; b=ra7sQeqhl5gSPuYms2KI04BHJeIweukBqrEaCf0nzdHbA3HF84EXaCpGxUU7F9LDZEU+IETz6C0gUE++K6d9/YwzBStmaGcMht/PGuiapk9Nv9d8Kn0vCd6zYWAQMsYaZYLk4wZ+KfMeb0avoKmurEJ9jUxXrOdVUrXjbaBXg7U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881672; c=relaxed/simple; bh=f62pDQoKp+ZtYgKFLAMpi3/rOqRQzJXs15f4rp7RjDE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nGOH/Mv10Ks2+Gk9Ey/xNJjdnbQL/9Jl7fNqFfnOWNt3KQU3FI6C8Q47n20k5twhld/RpYC7pfOR7IbJzlsyZQQ1+x9TvKq7e2S3RbXj8b0pepVzcaFGIsTdM/97r0N/7SZWr8z8TwBBB7M2nmE8S7ccseJm7EABDVF4vayWjtE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=onc6RzYL; 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="onc6RzYL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1ACC9C116B1; Tue, 2 Jul 2024 00:54:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881672; bh=f62pDQoKp+ZtYgKFLAMpi3/rOqRQzJXs15f4rp7RjDE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=onc6RzYLAx7zkV5HLFeOFA/ehrZpsWnwRvd8wwOcOtOImz0R8G84j8OyENtbOwyjf F3DSJYWKpFvy8rAHpSo3XknjovN9jJB9QGobhf1G4BuCUF8JxrwO1NyZjMi5PUlWqq 9fMxcTWu0AlwjG9FEFlPU1WG+4VU0YcOk56Swsc93UsMdqBUTE6Kj62hh3hOvI6iBS Nwxple8tZVM0/8EUNNO+wRGKOKqycYvjf6UHUbfdTdZesaOr6RNiUZJrzBkAEGkJ5C ktUvRx1CIa/NH8fGX9tJT4fnUEtrYp2rMVju9vTltk+0HYyHvNJm6poiRnHEBfFcye O4BzhhLWWlxZw== Date: Mon, 01 Jul 2024 17:54:31 -0700 Subject: [PATCH 04/12] libfrog: add support for exchange range ioctl family From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116771.2006519.532946760546599337.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 library code to support the new file range exchange and commit ioctls. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- libfrog/Makefile | 2 ++ libfrog/file_exchange.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ libfrog/file_exchange.h | 15 ++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 libfrog/file_exchange.c create mode 100644 libfrog/file_exchange.h diff --git a/libfrog/Makefile b/libfrog/Makefile index cafee073fe3c..53e3c3492377 100644 --- a/libfrog/Makefile +++ b/libfrog/Makefile @@ -18,6 +18,7 @@ bitmap.c \ bulkstat.c \ convert.c \ crc32.c \ +file_exchange.c \ fsgeom.c \ list_sort.c \ linux.c \ @@ -42,6 +43,7 @@ crc32defs.h \ crc32table.h \ dahashselftest.h \ div64.h \ +file_exchange.h \ fsgeom.h \ logging.h \ paths.h \ diff --git a/libfrog/file_exchange.c b/libfrog/file_exchange.c new file mode 100644 index 000000000000..29fdc17e598c --- /dev/null +++ b/libfrog/file_exchange.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020-2024 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include +#include +#include +#include +#include +#include "xfs.h" +#include "fsgeom.h" +#include "bulkstat.h" +#include "libfrog/file_exchange.h" + +/* Prepare for a file contents exchange. */ +void +xfrog_exchangerange_prep( + struct xfs_exchange_range *fxr, + off_t file2_offset, + int file1_fd, + off_t file1_offset, + uint64_t length) +{ + memset(fxr, 0, sizeof(*fxr)); + + fxr->file1_fd = file1_fd; + fxr->file1_offset = file1_offset; + fxr->length = length; + fxr->file2_offset = file2_offset; +} + +/* + * Execute an exchange-range operation. Returns 0 for success or a negative + * errno. + */ +int +xfrog_exchangerange( + int file2_fd, + struct xfs_exchange_range *fxr, + uint64_t flags) +{ + int ret; + + fxr->flags = flags; + + ret = ioctl(file2_fd, XFS_IOC_EXCHANGE_RANGE, fxr); + if (ret) + return -errno; + + return 0; +} diff --git a/libfrog/file_exchange.h b/libfrog/file_exchange.h new file mode 100644 index 000000000000..b6f6f9f698a8 --- /dev/null +++ b/libfrog/file_exchange.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2020-2024 Oracle. All rights reserved. + * All Rights Reserved. + */ +#ifndef __LIBFROG_FILE_EXCHANGE_H__ +#define __LIBFROG_FILE_EXCHANGE_H__ + +void xfrog_exchangerange_prep(struct xfs_exchange_range *fxr, + off_t file2_offset, int file1_fd, + off_t file1_offset, uint64_t length); +int xfrog_exchangerange(int file2_fd, struct xfs_exchange_range *fxr, + uint64_t flags); + +#endif /* __LIBFROG_FILE_EXCHANGE_H__ */ From patchwork Tue Jul 2 00:54:47 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: 13718755 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 E0CC0D50F for ; Tue, 2 Jul 2024 00:54: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=1719881688; cv=none; b=aCnmTbFQ6/z8KWuXWLrp/32lnQrwoN/qeJq8phZxUpFrGYWKF20QVjUonEhpiKtaRDrWRD/oRjs9TFX3AFzFG7wjzPQAiG2PMMAPRSgh8T0IeahRnkA4sU4mm2IJspmpgOa5c4pBuyGfEY+bDNxiTnxh3DAl39PlpJrpSX94K34= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881688; c=relaxed/simple; bh=yE6I7n0u7gAhzDpnEXStsFeVPmU9aUdrobTEZmriWYo=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=j7/fmdWs2YnpooqcMvlzujqKFxvvCOzQbdGXbp3jw9nPvYUhhZpgpGUtnN2oKURu4NSD0aD1hNcjlAGeGPFe6D5O/1hOujmNZQE/wo4VvUKfx2qIP9T7xmwjkX7s+vEmJDb2n9p2wE6G9Yx7Pqs9wE4mG1UXmjqOiQNESEVr/FU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=amM1Ocyu; 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="amM1Ocyu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD79BC116B1; Tue, 2 Jul 2024 00:54:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881687; bh=yE6I7n0u7gAhzDpnEXStsFeVPmU9aUdrobTEZmriWYo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=amM1Ocyuyag7g3I7TLIEMCed1N8Xi+1+9RYm7fqiHU6phV+V7A7nywm4Qp7EJHKm7 c6Hj/QtUj0TlLdaEcF0wi0/abpojdxzFL6i9eCgslseDxzM5w4Bsn72JuVVlkkDSTH 3KBUSgisqlzNnNTz3OAhPCPvBr84B+qD6LUK72V4kpSOp+yUGsKaUIvTX6aKcEA2lC W+GclsaPNCTBwu7TlsL9oFR2buysJ5I0XozuLp+yE/nbyoi1JCrE4ChGGUBUZV9h1F mi+Zf+eTloZPjWHXUoRbf3ZjGLsljlwejEc6cE9kBOiAk7dsoqjAPpt0Y9QQqxkSmG YA3wD5mmn6XkQ== Date: Mon, 01 Jul 2024 17:54:47 -0700 Subject: [PATCH 05/12] xfs_db: advertise exchange-range in the version command From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116786.2006519.17065535694551373149.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 Amend the version command to advertise exchange-range support. 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 b48767f47fe9..c39011634198 100644 --- a/db/sb.c +++ b/db/sb.c @@ -706,6 +706,8 @@ version_string( strcat(s, ",NEEDSREPAIR"); if (xfs_has_large_extent_counts(mp)) strcat(s, ",NREXT64"); + if (xfs_has_exchange_range(mp)) + strcat(s, ",EXCHANGE"); return s; } From patchwork Tue Jul 2 00:55: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: 13718756 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 7EDD2393 for ; Tue, 2 Jul 2024 00:55:03 +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=1719881703; cv=none; b=ZDxbqJ+bPM4STh0EKQ3jQVwQoXsSjmG1nNGGJRujI/xU14ZHb0WfFbcnnh7PkruEEbvlR8qmbAl8ztbzab2pMyKKiVO7EHRI2IQbT9+XEe1PXEdeK2Jss9XseZNhXwZMGuHQn1xPQ5DAoQMYa9uPtMZgeR3v20YFHvLfM161LuY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881703; c=relaxed/simple; bh=NXGpydbxye97G+m7PSTVceX8+QzEJpOD7ffs2tpd9jY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=h7enYEjZkeSPOR5m8mgM37rzHobk4dDOXP5bGCTK+rCrgkcNLFEGIi6eBz8ah8CHmUlkBtDM0cBIemnmijIRW+GrvL2Q/TPPkCGjbhtKga4sS5Z+VXC4iMXXDibKhaV7OmTbY3JfhcWxJ1QVBObrkIIFDKUeYHpaPig+NRgz5Ds= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nqI+kH5n; 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="nqI+kH5n" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5B1C1C116B1; Tue, 2 Jul 2024 00:55:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881703; bh=NXGpydbxye97G+m7PSTVceX8+QzEJpOD7ffs2tpd9jY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=nqI+kH5nb5nnpElgUJHqlUJ2l7ccvt2/mboKk9aWV7/vDwMx2fDT3DkJx41cQgg44 X1sfcJl/nQX4d5txU10Y5wlrme0AP2Ms/VRuySj02YULNQRLvV00kHPiKJ6nKPnFR6 BXg0mmuEZxYyZlcmDQUy/cUUNL9AFg/c70lIWfdIV6R2QyktCO3CC7GF1o5x0zRc18 t0kykmq3aUaX0YZH+P7ipVS0ZUmTtKp5AEknnLaooIbewXj61DaRbw3CB7Q47IPiFm sXhe43CVrDuGzIa/dIdJ0taJKdDwvDop77eLGH9h5Ws6A4slRX8AvTR44I+OhhDTXN qWtGvE3kpLffQ== Date: Mon, 01 Jul 2024 17:55:02 -0700 Subject: [PATCH 06/12] xfs_logprint: support dumping exchmaps log items From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116801.2006519.17657789199852782439.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 Support dumping exchmaps log items. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- logprint/log_misc.c | 11 ++++ logprint/log_print_all.c | 12 ++++ logprint/log_redo.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++ logprint/logprint.h | 6 ++ 4 files changed, 157 insertions(+) diff --git a/logprint/log_misc.c b/logprint/log_misc.c index 9d38113402f4..8e86ac347fa9 100644 --- a/logprint/log_misc.c +++ b/logprint/log_misc.c @@ -1052,6 +1052,17 @@ xlog_print_record( be32_to_cpu(op_head->oh_len)); break; } + case XFS_LI_XMI: { + skip = xlog_print_trans_xmi(&ptr, + be32_to_cpu(op_head->oh_len), + continued); + break; + } + case XFS_LI_XMD: { + skip = xlog_print_trans_xmd(&ptr, + be32_to_cpu(op_head->oh_len)); + break; + } case XFS_LI_QUOTAOFF: { skip = xlog_print_trans_qoff(&ptr, be32_to_cpu(op_head->oh_len)); diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c index f436e10917d8..a4a5e41f17fa 100644 --- a/logprint/log_print_all.c +++ b/logprint/log_print_all.c @@ -440,6 +440,12 @@ xlog_recover_print_logitem( case XFS_LI_BUI: xlog_recover_print_bui(item); break; + case XFS_LI_XMD: + xlog_recover_print_xmd(item); + break; + case XFS_LI_XMI: + xlog_recover_print_xmi(item); + break; case XFS_LI_DQUOT: xlog_recover_print_dquot(item); break; @@ -498,6 +504,12 @@ xlog_recover_print_item( case XFS_LI_BUI: printf("BUI"); break; + case XFS_LI_XMD: + printf("XMD"); + break; + case XFS_LI_XMI: + printf("XMI"); + break; case XFS_LI_DQUOT: printf("DQ "); break; diff --git a/logprint/log_redo.c b/logprint/log_redo.c index edf7e0fbfa90..ca6dadd7551a 100644 --- a/logprint/log_redo.c +++ b/logprint/log_redo.c @@ -847,3 +847,131 @@ xlog_recover_print_attrd( f->alfd_size, (unsigned long long)f->alfd_alf_id); } + +/* Atomic Extent Swapping Items */ + +static int +xfs_xmi_copy_format( + struct xfs_xmi_log_format *xmi, + uint len, + struct xfs_xmi_log_format *dst_fmt, + int continued) +{ + if (len == sizeof(struct xfs_xmi_log_format) || continued) { + memcpy(dst_fmt, xmi, len); + return 0; + } + fprintf(stderr, _("%s: bad size of XMI format: %u; expected %zu\n"), + progname, len, sizeof(struct xfs_xmi_log_format)); + return 1; +} + +int +xlog_print_trans_xmi( + char **ptr, + uint src_len, + int continued) +{ + struct xfs_xmi_log_format *src_f, *f = NULL; + int error = 0; + + src_f = malloc(src_len); + if (src_f == NULL) { + fprintf(stderr, _("%s: %s: malloc failed\n"), + progname, __func__); + exit(1); + } + memcpy(src_f, *ptr, src_len); + *ptr += src_len; + + /* convert to native format */ + if (continued && src_len < sizeof(struct xfs_xmi_log_format)) { + printf(_("XMI: Not enough data to decode further\n")); + error = 1; + goto error; + } + + f = malloc(sizeof(struct xfs_xmi_log_format)); + if (f == NULL) { + fprintf(stderr, _("%s: %s: malloc failed\n"), + progname, __func__); + exit(1); + } + if (xfs_xmi_copy_format(src_f, src_len, f, continued)) { + error = 1; + goto error; + } + + printf(_("XMI: #regs: %d num_extents: 1 id: 0x%llx\n"), + f->xmi_size, (unsigned long long)f->xmi_id); + + if (continued) { + printf(_("XMI extent data skipped (CONTINUE set, no space)\n")); + goto error; + } + + printf("(ino1: 0x%llx, igen1: 0x%x, ino2: 0x%llx, igen2: 0x%x, off1: %lld, off2: %lld, len: %lld, flags: 0x%llx)\n", + (unsigned long long)f->xmi_inode1, + (unsigned int)f->xmi_igen1, + (unsigned long long)f->xmi_inode2, + (unsigned int)f->xmi_igen2, + (unsigned long long)f->xmi_startoff1, + (unsigned long long)f->xmi_startoff2, + (unsigned long long)f->xmi_blockcount, + (unsigned long long)f->xmi_flags); +error: + free(src_f); + free(f); + return error; +} + +void +xlog_recover_print_xmi( + struct xlog_recover_item *item) +{ + char *src_f; + uint src_len; + + src_f = item->ri_buf[0].i_addr; + src_len = item->ri_buf[0].i_len; + + xlog_print_trans_xmi(&src_f, src_len, 0); +} + +int +xlog_print_trans_xmd( + char **ptr, + uint len) +{ + struct xfs_xmd_log_format *f; + struct xfs_xmd_log_format lbuf; + + /* size without extents at end */ + uint core_size = sizeof(struct xfs_xmd_log_format); + + memcpy(&lbuf, *ptr, min(core_size, len)); + f = &lbuf; + *ptr += len; + if (len >= core_size) { + printf(_("XMD: #regs: %d id: 0x%llx\n"), + f->xmd_size, + (unsigned long long)f->xmd_xmi_id); + + /* don't print extents as they are not used */ + + return 0; + } else { + printf(_("XMD: Not enough data to decode further\n")); + return 1; + } +} + +void +xlog_recover_print_xmd( + struct xlog_recover_item *item) +{ + char *f; + + f = item->ri_buf[0].i_addr; + xlog_print_trans_xmd(&f, sizeof(struct xfs_xmd_log_format)); +} diff --git a/logprint/logprint.h b/logprint/logprint.h index b4479c240d94..8867b110ecaf 100644 --- a/logprint/logprint.h +++ b/logprint/logprint.h @@ -65,4 +65,10 @@ 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); extern void xlog_print_op_header(xlog_op_header_t *op_head, int i, char **ptr); + +extern int xlog_print_trans_xmi(char **ptr, uint src_len, int continued); +extern void xlog_recover_print_xmi(struct xlog_recover_item *item); +extern int xlog_print_trans_xmd(char **ptr, uint len); +extern void xlog_recover_print_xmd(struct xlog_recover_item *item); + #endif /* LOGPRINT_H */ From patchwork Tue Jul 2 00:55:18 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: 13718757 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 2C756EDE for ; Tue, 2 Jul 2024 00:55:19 +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=1719881719; cv=none; b=E/LE0k1Syrpnm4P5KOzxMxuOedXBi8uBKJbREvUXW0hZtHqctVBqZhG2SczoFWetxVMAxYCtLF2heGvP+p3K5iii5Qi0DUtHfqujfa+HZPUi5alrpUm3CiqRS0xhKAUU5auhSL5AQs6fm62AXD3ldXmuXRvBQS1sfX8/v6XnIzU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881719; c=relaxed/simple; bh=8X/GWtQ++TFQXqkAYTXOv3hggpXdk5j4tAtxQTZHxWQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ect0xFDm/gunVcCZkC/aIpPIvc1fmZjSD0q6CU3SQbWS+dQaZe1GKY3An3N8fbiCKY12vBnkUhMp2mgHtHYl0TbEn9B77bAz+uv5wdKO95lmhr28cVM2gxOYLfMItLdB761eEIfm0aE3Tm3jslSVVRengHarOPTVYLakkHOuxtk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gcjXFR9t; 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="gcjXFR9t" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F3913C116B1; Tue, 2 Jul 2024 00:55:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881719; bh=8X/GWtQ++TFQXqkAYTXOv3hggpXdk5j4tAtxQTZHxWQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=gcjXFR9tzqTW3EQPyDNIVHhZWm5ofAot6T/kVSllCmqoSEOPwynkzrDijq7+DB+AI RO4xY9HS/H3dV9RkBzUshX0TXpui8l4TemaKsIUEioVzubFWFRaqfHYj7G/Oy/Bx7W Tud+iyGJexbta/qNPew+BjmAv+GDaWwD5apDDwhsTK7gUE6ELo7KwaNImOB/QTtAQ/ 2Mjc8hRcWXvb5uj0mgWCBNmP4p0Z55unnj8Ib73nX4E9pYqZJscnyLTVVwrgFaQy0V IYrwkr9wzZGYLpSzUZqG4sdeS2+dxNKX9wOrfH/zc8bHZChN9vs/i2eLC08Oy8C56A vHNwnxCtrXv/Q== Date: Mon, 01 Jul 2024 17:55:18 -0700 Subject: [PATCH 07/12] xfs_fsr: convert to bulkstat v5 ioctls From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116816.2006519.15287670811039475666.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 libhandle can, er, handle bulkstat information coming from the v5 bulkstat ioctl, port xfs_fsr to use the new interfaces instead of repeatedly converting things back and forth. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fsr/xfs_fsr.c | 148 ++++++++++++++++++++++++++++++------------------------ libfrog/fsgeom.c | 45 ++++++++++++---- libfrog/fsgeom.h | 1 3 files changed, 117 insertions(+), 77 deletions(-) diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c index 06cc0552f9f1..2989e4c989bf 100644 --- a/fsr/xfs_fsr.c +++ b/fsr/xfs_fsr.c @@ -65,10 +65,10 @@ static int pagesize; void usage(int ret); static int fsrfile(char *fname, xfs_ino_t ino); -static int fsrfile_common( char *fname, char *tname, char *mnt, - int fd, struct xfs_bstat *statp); -static int packfile(char *fname, char *tname, int fd, - struct xfs_bstat *statp, struct fsxattr *fsxp); +static int fsrfile_common(char *fname, char *tname, char *mnt, + struct xfs_fd *file_fd, struct xfs_bulkstat *statp); +static int packfile(char *fname, char *tname, struct xfs_fd *file_fd, + struct xfs_bulkstat *statp, struct fsxattr *fsxp); static void fsrdir(char *dirname); static int fsrfs(char *mntdir, xfs_ino_t ino, int targetrange); static void initallfs(char *mtab); @@ -80,7 +80,7 @@ int xfs_getrt(int fd, struct statvfs *sfbp); char * gettmpname(char *fname); char * getparent(char *fname); int fsrprintf(const char *fmt, ...); -int read_fd_bmap(int, struct xfs_bstat *, int *); +int read_fd_bmap(int, struct xfs_bulkstat *, int *); static void tmp_init(char *mnt); static char * tmp_next(char *mnt); static void tmp_close(char *mnt); @@ -102,6 +102,26 @@ static int nfrags = 0; /* Debug option: Coerse into specific number * of extents */ static int openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT; +/* + * Open a file on an XFS filesystem from file handle components and fs geometry + * data. Returns zero or a negative error code. + */ +static int +open_handle( + struct xfs_fd *xfd, + jdm_fshandle_t *fshandle, + struct xfs_bulkstat *bulkstat, + struct xfs_fsop_geom *fsgeom, + int flags) +{ + xfd->fd = jdm_open_v5(fshandle, bulkstat, flags); + if (xfd->fd < 0) + return errno; + + xfd_install_geometry(xfd, fsgeom); + return 0; +} + static int xfs_swapext(int fd, xfs_swapext_t *sx) { @@ -627,7 +647,6 @@ static int fsrfs(char *mntdir, xfs_ino_t startino, int targetrange) { struct xfs_fd fsxfd = XFS_FD_INIT_EMPTY; - int fd; int count = 0; int ret; char fname[64]; @@ -665,10 +684,10 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange) } while ((ret = -xfrog_bulkstat(&fsxfd, breq) == 0)) { - struct xfs_bstat bs1; struct xfs_bulkstat *buf = breq->bulkstat; struct xfs_bulkstat *p; struct xfs_bulkstat *endp; + struct xfs_fd file_fd = XFS_FD_INIT_EMPTY; uint32_t buflenout = breq->hdr.ocount; if (buflenout == 0) @@ -685,15 +704,9 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange) (p->bs_extents64 < 2)) continue; - ret = -xfrog_bulkstat_v5_to_v1(&fsxfd, &bs1, p); + ret = open_handle(&file_fd, fshandlep, p, + &fsxfd.fsgeom, O_RDWR | O_DIRECT); if (ret) { - fsrprintf(_("bstat conversion error: %s\n"), - strerror(ret)); - continue; - } - - fd = jdm_open(fshandlep, &bs1, O_RDWR | O_DIRECT); - if (fd < 0) { /* This probably means the file was * removed while in progress of handling * it. Just quietly ignore this file. @@ -710,11 +723,12 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange) /* Get a tmp file name */ tname = tmp_next(mntdir); - ret = fsrfile_common(fname, tname, mntdir, fd, &bs1); + ret = fsrfile_common(fname, tname, mntdir, &file_fd, + p); leftoffino = p->bs_ino; - close(fd); + xfd_close(&file_fd); if (ret == 0) { if (--count <= 0) @@ -762,9 +776,8 @@ fsrfile( { struct xfs_fd fsxfd = XFS_FD_INIT_EMPTY; struct xfs_bulkstat bulkstat; - struct xfs_bstat statbuf; + struct xfs_fd file_fd = XFS_FD_INIT_EMPTY; jdm_fshandle_t *fshandlep; - int fd = -1; int error = -1; char *tname; @@ -792,17 +805,12 @@ fsrfile( fname, strerror(error)); goto out; } - error = -xfrog_bulkstat_v5_to_v1(&fsxfd, &statbuf, &bulkstat); - if (error) { - fsrprintf(_("bstat conversion error on %s: %s\n"), - fname, strerror(error)); - goto out; - } - fd = jdm_open(fshandlep, &statbuf, O_RDWR|O_DIRECT); - if (fd < 0) { + error = open_handle(&file_fd, fshandlep, &bulkstat, &fsxfd.fsgeom, + O_RDWR | O_DIRECT); + if (error) { fsrprintf(_("unable to open handle %s: %s\n"), - fname, strerror(errno)); + fname, strerror(error)); goto out; } @@ -810,14 +818,13 @@ fsrfile( memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom)); tname = gettmpname(fname); - if (tname) - error = fsrfile_common(fname, tname, NULL, fd, &statbuf); + error = fsrfile_common(fname, tname, NULL, &file_fd, + &bulkstat); out: xfd_close(&fsxfd); - if (fd >= 0) - close(fd); + xfd_close(&file_fd); free(fshandlep); return error; @@ -843,8 +850,8 @@ fsrfile_common( char *fname, char *tname, char *fsname, - int fd, - struct xfs_bstat *statp) + struct xfs_fd *file_fd, + struct xfs_bulkstat *statp) { int error; struct statvfs vfss; @@ -854,7 +861,7 @@ fsrfile_common( if (vflag) fsrprintf("%s\n", fname); - if (fsync(fd) < 0) { + if (fsync(file_fd->fd) < 0) { fsrprintf(_("sync failed: %s: %s\n"), fname, strerror(errno)); return -1; } @@ -878,7 +885,7 @@ fsrfile_common( fl.l_whence = SEEK_SET; fl.l_start = (off_t)0; fl.l_len = 0; - if ((fcntl(fd, F_GETLK, &fl)) < 0 ) { + if ((fcntl(file_fd->fd, F_GETLK, &fl)) < 0 ) { if (vflag) fsrprintf(_("locking check failed: %s\n"), fname); @@ -896,7 +903,7 @@ fsrfile_common( /* * Check if there is room to copy the file. * - * Note that xfs_bstat.bs_blksize returns the filesystem blocksize, + * Note that xfs_bulkstat.bs_blksize returns the filesystem blocksize, * not the optimal I/O size as struct stat. */ if (statvfs(fsname ? fsname : fname, &vfss) < 0) { @@ -913,7 +920,7 @@ fsrfile_common( return 1; } - if ((ioctl(fd, FS_IOC_FSGETXATTR, &fsx)) < 0) { + if ((ioctl(file_fd->fd, FS_IOC_FSGETXATTR, &fsx)) < 0) { fsrprintf(_("failed to get inode attrs: %s\n"), fname); return(-1); } @@ -929,7 +936,7 @@ fsrfile_common( return(0); } if (fsx.fsx_xflags & FS_XFLAG_REALTIME) { - if (xfs_getrt(fd, &vfss) < 0) { + if (xfs_getrt(file_fd->fd, &vfss) < 0) { fsrprintf(_("cannot get realtime geometry for: %s\n"), fname); return(-1); @@ -955,7 +962,7 @@ fsrfile_common( * file we're defragging, in packfile(). */ - if ((error = packfile(fname, tname, fd, statp, &fsx))) + if ((error = packfile(fname, tname, file_fd, statp, &fsx))) return error; return -1; /* no error */ } @@ -979,7 +986,7 @@ static int fsr_setup_attr_fork( int fd, int tfd, - struct xfs_bstat *bstatp) + struct xfs_bulkstat *bstatp) { struct xfs_fd txfd = XFS_FD_INIT(tfd); struct stat tstatbuf; @@ -1161,23 +1168,28 @@ fsr_setup_attr_fork( * 1: No change / No Error */ static int -packfile(char *fname, char *tname, int fd, - struct xfs_bstat *statp, struct fsxattr *fsxp) +packfile( + char *fname, + char *tname, + struct xfs_fd *file_fd, + struct xfs_bulkstat *statp, + struct fsxattr *fsxp) { - int tfd = -1; - int srval; - int retval = -1; /* Failure is the default */ - int nextents, extent, cur_nextents, new_nextents; - unsigned blksz_dio; - unsigned dio_min; - struct dioattr dio; - static xfs_swapext_t sx; - struct xfs_flock64 space; - off_t cnt, pos; - void *fbuf = NULL; - int ct, wc, wc_b4; - char ffname[SMBUFSZ]; - int ffd = -1; + int tfd = -1; + int srval; + int retval = -1; /* Failure is the default */ + int nextents, extent, cur_nextents, new_nextents; + unsigned blksz_dio; + unsigned dio_min; + struct dioattr dio; + static xfs_swapext_t sx; + struct xfs_flock64 space; + off_t cnt, pos; + void *fbuf = NULL; + int ct, wc, wc_b4; + char ffname[SMBUFSZ]; + int ffd = -1; + int error; /* * Work out the extent map - nextents will be set to the @@ -1185,7 +1197,7 @@ packfile(char *fname, char *tname, int fd, * into account holes), cur_nextents is the current number * of extents. */ - nextents = read_fd_bmap(fd, statp, &cur_nextents); + nextents = read_fd_bmap(file_fd->fd, statp, &cur_nextents); if (cur_nextents == 1 || cur_nextents <= nextents) { if (vflag) @@ -1208,7 +1220,7 @@ packfile(char *fname, char *tname, int fd, unlink(tname); /* Setup extended attributes */ - if (fsr_setup_attr_fork(fd, tfd, statp) != 0) { + if (fsr_setup_attr_fork(file_fd->fd, tfd, statp) != 0) { fsrprintf(_("failed to set ATTR fork on tmp: %s:\n"), tname); goto out; } @@ -1326,7 +1338,7 @@ packfile(char *fname, char *tname, int fd, tname, strerror(errno)); goto out; } - if (lseek(fd, outmap[extent].bmv_length, SEEK_CUR) < 0) { + if (lseek(file_fd->fd, outmap[extent].bmv_length, SEEK_CUR) < 0) { fsrprintf(_("could not lseek in file: %s : %s\n"), fname, strerror(errno)); goto out; @@ -1346,7 +1358,7 @@ packfile(char *fname, char *tname, int fd, ct = min(cnt + dio_min - (cnt % dio_min), blksz_dio); } - ct = read(fd, fbuf, ct); + ct = read(file_fd->fd, fbuf, ct); if (ct == 0) { /* EOF, stop trying to read */ extent = nextents; @@ -1417,9 +1429,15 @@ packfile(char *fname, char *tname, int fd, goto out; } - sx.sx_stat = *statp; /* struct copy */ + error = -xfrog_bulkstat_v5_to_v1(file_fd, &sx.sx_stat, statp); + if (error) { + fsrprintf(_("bstat conversion error on %s: %s\n"), + fname, strerror(error)); + goto out; + } + sx.sx_version = XFS_SX_VERSION; - sx.sx_fdtarget = fd; + sx.sx_fdtarget = file_fd->fd; sx.sx_fdtmp = tfd; sx.sx_offset = 0; sx.sx_length = statp->bs_size; @@ -1433,7 +1451,7 @@ packfile(char *fname, char *tname, int fd, } /* Swap the extents */ - srval = xfs_swapext(fd, &sx); + srval = xfs_swapext(file_fd->fd, &sx); if (srval < 0) { if (errno == ENOTSUP) { if (vflag || dflag) @@ -1529,7 +1547,7 @@ getparent(char *fname) #define MAPSIZE 128 #define OUTMAP_SIZE_INCREMENT MAPSIZE -int read_fd_bmap(int fd, struct xfs_bstat *sin, int *cur_nextents) +int read_fd_bmap(int fd, struct xfs_bulkstat *sin, int *cur_nextents) { int i, cnt; struct getbmap map[MAPSIZE]; diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c index 3e7f0797d8bd..6980d3ffab69 100644 --- a/libfrog/fsgeom.c +++ b/libfrog/fsgeom.c @@ -102,29 +102,50 @@ xfrog_geometry( return -errno; } -/* - * Prepare xfs_fd structure for future ioctl operations by computing the xfs - * geometry for @xfd->fd. Returns zero or a negative error code. - */ -int -xfd_prepare_geometry( +/* Compute conversion factors of an xfs_fd structure. */ +static void +xfd_compute_conversion_factors( struct xfs_fd *xfd) { - int ret; - - ret = xfrog_geometry(xfd->fd, &xfd->fsgeom); - if (ret) - return ret; - xfd->agblklog = log2_roundup(xfd->fsgeom.agblocks); xfd->blocklog = highbit32(xfd->fsgeom.blocksize); xfd->inodelog = highbit32(xfd->fsgeom.inodesize); xfd->inopblog = xfd->blocklog - xfd->inodelog; xfd->aginolog = xfd->agblklog + xfd->inopblog; xfd->blkbb_log = xfd->blocklog - BBSHIFT; +} + +/* + * Prepare xfs_fd structure for future ioctl operations by computing the xfs + * geometry for @xfd->fd. Returns zero or a negative error code. + */ +int +xfd_prepare_geometry( + struct xfs_fd *xfd) +{ + int ret; + + ret = xfrog_geometry(xfd->fd, &xfd->fsgeom); + if (ret) + return ret; + + xfd_compute_conversion_factors(xfd); return 0; } +/* + * Prepare xfs_fd structure for future ioctl operations by computing the xfs + * geometry for @xfd->fd. Returns zero or a negative error code. + */ +void +xfd_install_geometry( + struct xfs_fd *xfd, + struct xfs_fsop_geom *fsgeom) +{ + memcpy(&xfd->fsgeom, fsgeom, sizeof(*fsgeom)); + xfd_compute_conversion_factors(xfd); +} + /* Open a file on an XFS filesystem. Returns zero or a negative error code. */ int xfd_open( diff --git a/libfrog/fsgeom.h b/libfrog/fsgeom.h index ca38324e8533..f327dc7d70d0 100644 --- a/libfrog/fsgeom.h +++ b/libfrog/fsgeom.h @@ -55,6 +55,7 @@ struct xfs_fd { #define XFS_FD_INIT_EMPTY XFS_FD_INIT(-1) int xfd_prepare_geometry(struct xfs_fd *xfd); +void xfd_install_geometry(struct xfs_fd *xfd, struct xfs_fsop_geom *fsgeom); int xfd_open(struct xfs_fd *xfd, const char *pathname, int flags); int xfd_close(struct xfs_fd *xfd); From patchwork Tue Jul 2 00:55:34 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: 13718758 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 CB03CEDE for ; Tue, 2 Jul 2024 00:55: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=1719881734; cv=none; b=VgMS2AK8RoLWaRDN/1yOsSdT2xcALmXfwvXYGZrQoh/rCiG/uHj4A9ZMAmZZCET+7zDQps+v6zU/zUiLSAez7UhGlJWIWZQHcmgqjljLeSpzjACobodd0YqzPObfHT1+wJrQscNW6/inPKljZSF3/WaNKXxdtkxu78Yrlg3XWIk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881734; c=relaxed/simple; bh=jJseJ5sV9RLVL+Ozw8qF/CtwyDTYN+sHuQObOmVizwQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JS5MOvoLlm3bp88kpUz49qRiyPCAiMMbkydx+mWNoGHcFUJvw4ul+sFCh3VLYiVqHssExCe/NfC65TCxGcjFwwBwEtsm2+sOO2LCyAfFtJg5Yr6BX4YkXN3a4YsnSzO28vTV3agf+Kh1PHtlJLxpJk/iK1P4JSsGMNv/TLrjqZQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ab1BABdx; 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="ab1BABdx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A4A10C116B1; Tue, 2 Jul 2024 00:55:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881734; bh=jJseJ5sV9RLVL+Ozw8qF/CtwyDTYN+sHuQObOmVizwQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ab1BABdxRQV2/QpqySTycAD8wSf+0YQCoc5YvOWKXtQKCNkgqhJZ+BQeZ6RLmlQIz om1Pn+kcrSvKeFmFw14zlAFWfZGZUsaexuZ6TuOBa+tYnPIP3bpxFZAHMk7Qt/tSzn be1aji695Gh1CW/VHskXftf4ZWrEI0RjlnTXndjzX/uQ5KdkQxTxODk/bL7CpiiRUO L/XZUfHa7vjqOO5r4lwk8os68iTmuYHE3Jyt/NbMNBrr24Ds0IW9QQEHv5ga59Oh6G LB2IULbs+o7r5zuFf380FWltA5wmYH/we2uEpekCY6zV4kdEnXfj/2oPEnEeAjUuJv OfPDdkQUT87ng== Date: Mon, 01 Jul 2024 17:55:34 -0700 Subject: [PATCH 08/12] xfs_fsr: skip the xattr/forkoff levering with the newer swapext implementations From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116831.2006519.7545128226159019978.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 newer swapext implementations in the kernel run at a high enough level (above the bmap layer) that it's no longer required to manipulate bs_forkoff by creating garbage xattrs to get the extent tree that we want. If we detect the newer algorithms, skip this error prone step. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fsr/xfs_fsr.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c index 2989e4c989bf..7d0639868258 100644 --- a/fsr/xfs_fsr.c +++ b/fsr/xfs_fsr.c @@ -999,6 +999,20 @@ fsr_setup_attr_fork( if (!(bstatp->bs_xflags & FS_XFLAG_HASATTR)) return 0; + /* + * If the filesystem has the ability to perform atomic file mapping + * exchanges, the file extent swap implementation uses a higher level + * algorithm that calls into the bmap code instead of playing games + * with swapping the extent forks. + * + * This new functionality does not require specific values of + * bs_forkoff, unlike the old fork swap code. Leave the extended + * attributes alone if we know we're not using the old fork swap + * strategy. This eliminates a major source of runtime errors in fsr. + */ + if (fsgeom.flags & XFS_FSOP_GEOM_FLAGS_EXCHANGE_RANGE) + return 0; + /* * use the old method if we have attr1 or the kernel does not yet * support passing the fork offset in the bulkstat data. From patchwork Tue Jul 2 00:55: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: 13718759 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 AB1F86FCB for ; Tue, 2 Jul 2024 00:55:50 +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=1719881750; cv=none; b=T5LxYTg0ffj61PUhTLqeW2Nf+vhVkeJ0d0WZD2E8vbAy1ZJ9rLUQ/bS5MF4Ai3D246YkkXgUwhjquuqSiyx/vPW4AzcfX6fDLi/If7Vt80vlL2timsYoE/2QZhZ5v+tsesUGAUXXlVwLfTB7R2kZrdPH8XO0437nz1uCymETQUM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881750; c=relaxed/simple; bh=fi8dOuGL77TOr7HQzG1T3BE0vEbRgYtkmmJrpG4pXPo=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=M/PtJ7Hj+eJ26FJGxPA/FLK6Elz+rYAorlFAR9zqCiLZS2TeFqWBvciHsGmNerQ3zPr8o9/SkijWGuPcZaoYqX2ypMBT7sd7GbQh72jA50/St+326unBCv8bdS3ofUVAt4qLb6CtaanByWiSzq6rS34hXGjHrkjr1mJx1qsKmAE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tb2gRyiD; 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="tb2gRyiD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 47E38C116B1; Tue, 2 Jul 2024 00:55:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881750; bh=fi8dOuGL77TOr7HQzG1T3BE0vEbRgYtkmmJrpG4pXPo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=tb2gRyiD6zHkw+ZkH/6pq2fdjPeji21ivPOUxGG+vrSEWl9KW6KlHL3xbEVEQDxLa hKIfNSimJM+uA7Wjcq6LPUmrVqcCKo4EfRA23JNLvAOWOlGAdUIzLUMDUpWQApPcIi 25Z2MfpRM39kIieJbUmImWevV5bnuFcpsBc5tU0fSUMYYhrCJ39rH+sohPEsZooxF4 wfV2i78Ytgd3dXyr5ClkBamo8GhdXDpYly5QGUc3wbX7r5Ely8R0BFqafZ04dMfGaQ 8DlgTsgEbiwh9iZCEYs1d6+qk2Wz2pIsHD24cY9Mu2ksX75kzmQfp7+V7/pNZbTL4J 5SEM6yWQtTFuA== Date: Mon, 01 Jul 2024 17:55:49 -0700 Subject: [PATCH 09/12] xfs_io: create exchangerange command to test file range exchange ioctl From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116847.2006519.4476289388418471452.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 new xfs_Io command to make raw calls to the XFS_IOC_EXCHANGE_RANGE ioctl. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- io/Makefile | 48 ++++++++++++++-- io/exchrange.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++ io/init.c | 1 io/io.h | 1 man/man8/xfs_io.8 | 40 ++++++++++++++ 5 files changed, 239 insertions(+), 7 deletions(-) create mode 100644 io/exchrange.c diff --git a/io/Makefile b/io/Makefile index 17d499de9ab9..3192b813c740 100644 --- a/io/Makefile +++ b/io/Makefile @@ -8,13 +8,47 @@ include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_io LSRCFILES = xfs_bmap.sh xfs_freeze.sh xfs_mkfile.sh HFILES = init.h io.h -CFILES = init.c \ - attr.c bmap.c bulkstat.c crc32cselftest.c cowextsize.c encrypt.c \ - file.c freeze.c fsuuid.c fsync.c getrusage.c imap.c inject.c label.c \ - link.c mmap.c open.c parent.c pread.c prealloc.c pwrite.c reflink.c \ - resblks.c scrub.c seek.c shutdown.c stat.c swapext.c sync.c \ - truncate.c utimes.c fadvise.c sendfile.c madvise.c mincore.c fiemap.c \ - sync_file_range.c readdir.c +CFILES = \ + attr.c \ + bmap.c \ + bulkstat.c \ + cowextsize.c \ + crc32cselftest.c \ + encrypt.c \ + exchrange.c \ + fadvise.c \ + fiemap.c \ + file.c \ + freeze.c \ + fsuuid.c \ + fsync.c \ + getrusage.c \ + imap.c \ + init.c \ + inject.c \ + label.c \ + link.c \ + madvise.c \ + mincore.c \ + mmap.c \ + open.c \ + parent.c \ + pread.c \ + prealloc.c \ + pwrite.c \ + readdir.c \ + reflink.c \ + resblks.c \ + scrub.c \ + seek.c \ + sendfile.c \ + shutdown.c \ + stat.c \ + swapext.c \ + sync.c \ + sync_file_range.c \ + truncate.c \ + utimes.c LLDLIBS = $(LIBXCMD) $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD) $(LIBUUID) LTDEPENDENCIES = $(LIBXCMD) $(LIBHANDLE) $(LIBFROG) diff --git a/io/exchrange.c b/io/exchrange.c new file mode 100644 index 000000000000..016429280e27 --- /dev/null +++ b/io/exchrange.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020-2024 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include "command.h" +#include "input.h" +#include "init.h" +#include "io.h" +#include "libfrog/logging.h" +#include "libfrog/fsgeom.h" +#include "libfrog/file_exchange.h" +#include "libfrog/bulkstat.h" + +static void +exchangerange_help(void) +{ + printf(_( +"\n" +" Exchange file data between the open file descriptor and the supplied filename.\n" +" -C -- Print timing information in a condensed format\n" +" -d N -- Start exchanging contents at this position in the open file\n" +" -f -- Flush changed file data and metadata to disk\n" +" -l N -- Exchange this many bytes between the two files instead of to EOF\n" +" -n -- Dry run; do all the parameter validation but do not change anything.\n" +" -s N -- Start exchanging contents at this position in the supplied file\n" +" -t -- Print timing information\n" +" -w -- Only exchange written ranges in the supplied file\n" +)); +} + +static int +exchangerange_f( + int argc, + char **argv) +{ + struct xfs_exchange_range fxr; + struct stat stat; + struct timeval t1, t2; + uint64_t flags = XFS_EXCHANGE_RANGE_TO_EOF; + int64_t src_offset = 0; + int64_t dest_offset = 0; + int64_t length = -1; + size_t fsblocksize, fssectsize; + int condensed = 0, quiet_flag = 1; + int c; + int fd; + int ret; + + init_cvtnum(&fsblocksize, &fssectsize); + while ((c = getopt(argc, argv, "Ccd:fl:ns:tw")) != -1) { + switch (c) { + case 'C': + condensed = 1; + break; + case 'd': + dest_offset = cvtnum(fsblocksize, fssectsize, optarg); + if (dest_offset < 0) { + printf( + _("non-numeric open file offset argument -- %s\n"), + optarg); + return 0; + } + break; + case 'f': + flags |= XFS_EXCHANGE_RANGE_DSYNC; + break; + case 'l': + length = cvtnum(fsblocksize, fssectsize, optarg); + if (length < 0) { + printf( + _("non-numeric length argument -- %s\n"), + optarg); + return 0; + } + flags &= ~XFS_EXCHANGE_RANGE_TO_EOF; + break; + case 'n': + flags |= XFS_EXCHANGE_RANGE_DRY_RUN; + break; + case 's': + src_offset = cvtnum(fsblocksize, fssectsize, optarg); + if (src_offset < 0) { + printf( + _("non-numeric supplied file offset argument -- %s\n"), + optarg); + return 0; + } + break; + case 't': + quiet_flag = 0; + break; + case 'w': + flags |= XFS_EXCHANGE_RANGE_FILE1_WRITTEN; + break; + default: + exchangerange_help(); + return 0; + } + } + if (optind != argc - 1) { + exchangerange_help(); + return 0; + } + + /* open the donor file */ + fd = openfile(argv[optind], NULL, 0, 0, NULL); + if (fd < 0) + return 0; + + ret = fstat(file->fd, &stat); + if (ret) { + perror("fstat"); + exitcode = 1; + goto out; + } + if (length < 0) + length = stat.st_size; + + xfrog_exchangerange_prep(&fxr, dest_offset, fd, src_offset, length); + ret = xfrog_exchangerange(file->fd, &fxr, flags); + if (ret) { + xfrog_perror(ret, "exchangerange"); + exitcode = 1; + goto out; + } + if (quiet_flag) + goto out; + + gettimeofday(&t2, NULL); + t2 = tsub(t2, t1); + + report_io_times("exchangerange", &t2, dest_offset, length, length, 1, + condensed); +out: + close(fd); + return 0; +} + +static struct cmdinfo exchangerange_cmd = { + .name = "exchangerange", + .cfunc = exchangerange_f, + .argmin = 1, + .argmax = -1, + .flags = CMD_FLAG_ONESHOT | CMD_NOMAP_OK, + .help = exchangerange_help, +}; + +void +exchangerange_init(void) +{ + exchangerange_cmd.args = _("[-Cfntw] [-d dest_offset] [-s src_offset] [-l length] "); + exchangerange_cmd.oneline = _("Exchange contents between files."); + + add_command(&exchangerange_cmd); +} diff --git a/io/init.c b/io/init.c index 104cd2c12152..37e0f093c526 100644 --- a/io/init.c +++ b/io/init.c @@ -88,6 +88,7 @@ init_commands(void) truncate_init(); utimes_init(); crc32cselftest_init(); + exchangerange_init(); } /* diff --git a/io/io.h b/io/io.h index e06dff53f895..fb28bb896d61 100644 --- a/io/io.h +++ b/io/io.h @@ -149,3 +149,4 @@ extern void scrub_init(void); extern void repair_init(void); extern void crc32cselftest_init(void); extern void bulkstat_init(void); +extern void exchangerange_init(void); diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8 index 3ce280a75b4a..2a7c67f7cf3a 100644 --- a/man/man8/xfs_io.8 +++ b/man/man8/xfs_io.8 @@ -713,6 +713,46 @@ Swaps extent forks between files. The current open file is the target. The donor file is specified by path. Note that file data is not copied (file content moves with the fork(s)). .TP +.BI "exchangerange [OPTIONS]" donor_file " +Exchanges contents between files. +The current open file is the target. +The donor file is specified by path. +Note that file data is not copied (file content moves with the fork(s)). +Options include: +.RS 1.0i +.PD 0 +.TP 0.4i +.TP +.B \-C +Print timing information in a condensed format. +.TP +.BI \-d " dest_offset" +Swap extents with open file beginning at +.IR dest_offset . +.TP +.B \-f +Flush changed file data and file metadata to disk. +.TP +.BI \-l " length" +Swap up to +.I length +bytes of data. +.TP +.B \-n +Perform all the parameter validation checks but don't change anything. +.TP +.BI \-s " src_offset" +Swap extents with donor file beginning at +.IR src_offset . +.TP +.B \-t +Print timing information. +.TP +.B \-w +Only exchange written ranges in the supplied file. +.RE +.PD +.TP .BI "set_encpolicy [ \-c " mode " ] [ \-n " mode " ] [ \-f " flags " ] [ \-s " log2_dusize " ] [ \-v " version " ] [ " keyspec " ]" On filesystems that support encryption, assign an encryption policy to the current file. From patchwork Tue Jul 2 00:56:05 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: 13718760 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 6F3BB7464 for ; Tue, 2 Jul 2024 00:56:06 +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=1719881766; cv=none; b=VyGjDch1XxXLz0e+2Ns4Ny6zbqZtiml9RZTwwG/NRTbvxzEqf0ecIkUHP73plmcM8lz/2MvAuBk55TcPiqKtIwOzNOXxxWdxLX/KtLYd2csGIBePdzXcLx1cXp9SdCzNMe6rfOD9y8dxkTYqiH5pugYIsOSpEZsohdV+8yETAj0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881766; c=relaxed/simple; bh=hCIaWNVWJUOdrIjZxqUz7KdboLbT84wdBK3De7iRoPA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=J9LVv962aXJrVqtpyNKwzw6N/IaJNsD8IVS5Gm+4IM2HfOlMrXXwRqDP6a2al5faz8uh2AICvO7jX+pUGEJk6wl+w0FSo1Fpg3ZDGHbU5BqNlz7TQlqxzmauzu4ppozVD+lCrwq/eaYSCBn8DUbMEIoXXpj43fS4yEdihzZ/qVs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bX57iwb5; 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="bX57iwb5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E4274C116B1; Tue, 2 Jul 2024 00:56:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881766; bh=hCIaWNVWJUOdrIjZxqUz7KdboLbT84wdBK3De7iRoPA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=bX57iwb5LV8xlEdcZY6cEH5tFFeHGPIg7B6YSDQuPbpPyTOxKvfMn1VZaoUrav6tb LZICUtRwNetLLGGWHxWU+/u+xIh7qvCK7sA4lP95gt2DLXwUTaRW4ZzTACMxvWF9/y lq1MK8h/fMbaVTrAfwt/fQz9ypKAvZDloohZXywEdhQJQrCVarQOfF0idz4OJQL/uc +zBUKYhcMjRbo5ZhMpppGQOmCVTs12oxrlJ08IwD29PDye/9x8givFZB/O+NTj5OHn lW5QsyVcmqnZ3toi+FVKkUsb1w6oVt0R/uAVZvAJ+/dNBA6XIOhU9m+J9mXDbFjMjQ V1q2F7GDWgDHA== Date: Mon, 01 Jul 2024 17:56:05 -0700 Subject: [PATCH 10/12] libfrog: advertise exchange-range support From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116862.2006519.2459746611478539000.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 exchange range for a given filesystem. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- libfrog/fsgeom.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c index 6980d3ffab69..71a8e4bb9980 100644 --- a/libfrog/fsgeom.c +++ b/libfrog/fsgeom.c @@ -31,6 +31,7 @@ xfs_report_geom( int bigtime_enabled; int inobtcount; int nrext64; + int exchangerange; isint = geo->logstart > 0; lazycount = geo->flags & XFS_FSOP_GEOM_FLAGS_LAZYSB ? 1 : 0; @@ -49,12 +50,14 @@ xfs_report_geom( bigtime_enabled = geo->flags & XFS_FSOP_GEOM_FLAGS_BIGTIME ? 1 : 0; inobtcount = geo->flags & XFS_FSOP_GEOM_FLAGS_INOBTCNT ? 1 : 0; nrext64 = geo->flags & XFS_FSOP_GEOM_FLAGS_NREXT64 ? 1 : 0; + exchangerange = geo->flags & XFS_FSOP_GEOM_FLAGS_EXCHANGE_RANGE ? 1 : 0; printf(_( "meta-data=%-22s isize=%-6d agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u\n" " =%-22s reflink=%-4u bigtime=%u inobtcount=%u nrext64=%u\n" +" =%-22s 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" @@ -65,6 +68,7 @@ xfs_report_geom( "", geo->sectsize, attrversion, projid32bit, "", crcs_enabled, finobt_enabled, spinodes, rmapbt_enabled, "", reflink_enabled, bigtime_enabled, inobtcount, nrext64, + "", exchangerange, "", geo->blocksize, (unsigned long long)geo->datablocks, geo->imaxpct, "", geo->sunit, geo->swidth, From patchwork Tue Jul 2 00:56:21 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: 13718761 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 02A973209 for ; Tue, 2 Jul 2024 00:56: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=1719881782; cv=none; b=utohG443nbcEgczQnpo/NPB+31xj14/QPaDXRAkcArgDSF5QFJlb4+CbuO1/kNF8wNF1UfM6Lz5RnXRY9rheA6RvQg0eHmVwUCRIZEUCSt4Fji7pUD8BVMCspcfyiJrqEIRNu0zRX/8kcgRCv5RhkTy1IV34cDc4JSBh5+U+XXA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881782; c=relaxed/simple; bh=wRPbY3jMYtkFyz4ATCQsOqF3eexuCauivPgiA9vncVc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bWO+EE1jxTpxHh56tD5BEqF+lMluMeSYXC5Pzpz33G0rdEgmpU8mchd/kp0ZA2pTXHXnm3fWmmBN3/h0AXpX+u75h9WcLHIZmccv7hOPhKA2lzwFt7ZiTuk636zsUcF5PkvSiqEoQAVRqY+YzfJjRUmUb/ndRyKKp4nyNQS2whk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=u0wTtdO3; 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="u0wTtdO3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8257BC116B1; Tue, 2 Jul 2024 00:56:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881781; bh=wRPbY3jMYtkFyz4ATCQsOqF3eexuCauivPgiA9vncVc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=u0wTtdO3H9o89r/7T5VTgMhEYoW6+vwBi45ZR2Zn3Fi2cc4/FpCryOOKaG3jfNCwL 6Tw2iUeUklwBjxgFAZsgzZz2oCeABNGyWYuUUP0Tubu52ZyrdxrxjuWXLkYdwPE8ja AMR2g1oinjYmFF0ytzG76hSz3hAFcZQ5/wMUdzkNq8IBztdq2pJ969z2MO5qi987wq 1en/n5Wcc4IdsoerrSeohuEAe/alpUrGtxC5X1Bq+Y4Ccl97wE2QeIrRzHRZW2H3yr d4rHqXhsxpC+OS9qZfIbtZpSAnvtjuaRahrbpx65YPXKxtLrKoE8w65cfwiHMLKzHd FkyL4pyiVGAhA== Date: Mon, 01 Jul 2024 17:56:21 -0700 Subject: [PATCH 11/12] xfs_repair: add exchange-range to file systems From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116878.2006519.18408749679790867720.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 Enable upgrading existing filesystems to support the file exchange range feature. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- man/man8/xfs_admin.8 | 7 +++++++ repair/globals.c | 1 + repair/globals.h | 1 + repair/phase2.c | 30 ++++++++++++++++++++++++++++++ repair/xfs_repair.c | 11 +++++++++++ 5 files changed, 50 insertions(+) diff --git a/man/man8/xfs_admin.8 b/man/man8/xfs_admin.8 index 4794d6774ede..63f8ee90307b 100644 --- a/man/man8/xfs_admin.8 +++ b/man/man8/xfs_admin.8 @@ -156,6 +156,13 @@ data fork extent count will be 2^48 - 1, while the maximum attribute fork extent count will be 2^32 - 1. The filesystem cannot be downgraded after this feature is enabled. Once enabled, the filesystem will not be mountable by older kernels. This feature was added to Linux 5.19. +.TP 0.4i +.B exchange +Upgrade a filesystem to support atomic file content exchanges through the +XFS_IOC_EXCHANGE_RANGE ioctl, and to support online repairs of directories, +extended attributes, symbolic links, and realtime free space metadata. +The filesystem cannot be downgraded after this feature is enabled. +Once enabled, the filesystem will not be mountable by older kernels. .RE .TP .BI \-U " uuid" diff --git a/repair/globals.c b/repair/globals.c index 24f720c46afb..c0c45df51d56 100644 --- a/repair/globals.c +++ b/repair/globals.c @@ -52,6 +52,7 @@ bool features_changed; /* did we change superblock feature bits? */ bool add_inobtcount; /* add inode btree counts to AGI */ bool add_bigtime; /* add support for timestamps up to 2486 */ bool add_nrext64; +bool add_exchrange; /* add file content exchange support */ /* misc status variables */ diff --git a/repair/globals.h b/repair/globals.h index b83a8ae65942..1eadfdbf9ae4 100644 --- a/repair/globals.h +++ b/repair/globals.h @@ -93,6 +93,7 @@ extern bool features_changed; /* did we change superblock feature bits? */ extern bool add_inobtcount; /* add inode btree counts to AGI */ extern bool add_bigtime; /* add support for timestamps up to 2486 */ extern bool add_nrext64; +extern bool add_exchrange; /* add file content exchange support */ /* misc status variables */ diff --git a/repair/phase2.c b/repair/phase2.c index 06374817964c..83f0c539bb5d 100644 --- a/repair/phase2.c +++ b/repair/phase2.c @@ -182,6 +182,34 @@ set_nrext64( return true; } +static bool +set_exchrange( + struct xfs_mount *mp, + struct xfs_sb *new_sb) +{ + if (xfs_has_exchange_range(mp)) { + printf(_("Filesystem already supports exchange-range.\n")); + exit(0); + } + + if (!xfs_has_crc(mp)) { + printf( + _("File exchange-range feature only supported on V5 filesystems.\n")); + exit(0); + } + + if (!xfs_has_reflink(mp)) { + printf( + _("File exchange-range feature cannot be added without reflink.\n")); + exit(0); + } + + printf(_("Adding file exchange-range support to filesystem.\n")); + new_sb->sb_features_ro_compat |= XFS_SB_FEAT_INCOMPAT_EXCHRANGE; + new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR; + return true; +} + struct check_state { struct xfs_sb sb; uint64_t features; @@ -290,6 +318,8 @@ upgrade_filesystem( dirty |= set_bigtime(mp, &new_sb); if (add_nrext64) dirty |= set_nrext64(mp, &new_sb); + if (add_exchrange) + dirty |= set_exchrange(mp, &new_sb); if (!dirty) return; diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index cf774964381e..39884015300a 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -69,6 +69,7 @@ enum c_opt_nums { CONVERT_INOBTCOUNT, CONVERT_BIGTIME, CONVERT_NREXT64, + CONVERT_EXCHRANGE, C_MAX_OPTS, }; @@ -77,6 +78,7 @@ static char *c_opts[] = { [CONVERT_INOBTCOUNT] = "inobtcount", [CONVERT_BIGTIME] = "bigtime", [CONVERT_NREXT64] = "nrext64", + [CONVERT_EXCHRANGE] = "exchange", [C_MAX_OPTS] = NULL, }; @@ -360,6 +362,15 @@ process_args(int argc, char **argv) _("-c nrext64 only supports upgrades\n")); add_nrext64 = true; break; + case CONVERT_EXCHRANGE: + if (!val) + do_abort( + _("-c exchange requires a parameter\n")); + if (strtol(val, NULL, 0) != 1) + do_abort( + _("-c exchange only supports upgrades\n")); + add_exchrange = true; + break; default: unknown('c', val); break; From patchwork Tue Jul 2 00:56: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: 13718762 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 8F6C18C07 for ; Tue, 2 Jul 2024 00:56:37 +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=1719881797; cv=none; b=hCTWDhEQK6eqWp/+8bbdGFugX8Rf6/e99VGazDNEIIRE/dS01iqkGXiCxLyWmGqG8kZXWfANkbRGBkSEEfgVwQC+p5YYKwPDuGgfVWV4d+rj4gXQD8QpCAghJRU7vVlnaNhjxsZG74J+STo6pIZfxfBZtOUz1vavOPWCSRTeDhI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719881797; c=relaxed/simple; bh=6hvurFtnDZ8ox500BcSYOHUSV/fHO38gddCVRw3z4NU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qB0XBzwoxM5ms+OR8IYLQ369W0SY63QnFOs+7pwKkXEw/x1ej5gAbzV0p7GPOIlzBI8SQ2mePvajP5EJzLQXtb1Zcv8sMKLvbAzTGl4UxDF0W3ztoh46SJuhL5askXUYDAsiARBIIg9auJzxiMipWU1MmuXRLWnPL3WB4+/uWIM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KOiSEyW6; 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="KOiSEyW6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 238A8C116B1; Tue, 2 Jul 2024 00:56:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1719881797; bh=6hvurFtnDZ8ox500BcSYOHUSV/fHO38gddCVRw3z4NU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=KOiSEyW6+hKlWdChKLybD7QZEbsLlaxoNneNC8uNR5ZzfG46w6/LCwbgQd8g0ZRk6 kMMTshq658qttgK4KXr9knsuCVq5ZLjUUd8lNkOIFFE8XsK8iBzBeVwilcUibBIaRo fHVKs1atk+9AZKfPUAbiYAOxmzJcU7nkKjcJUqIF8bnZSq0/d60obCQtEGLfsqMIHW ab4URRVAn+yS6IS/5ef0v92/N/bw3whFR50yKli65nkNjF6sSl6z3iN69DCxCXDGSt 9ilFkxrX9rU2CtkdrDmxrTF1gOa7vyrqrxCWdgeOSZzxw1ux3ZIuR5et5pFrQMR06o GI0hIix5qFC0g== Date: Mon, 01 Jul 2024 17:56:36 -0700 Subject: [PATCH 12/12] mkfs: add a formatting option for exchange-range From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <171988116893.2006519.8574742517764976343.stgit@frogsfrogsfrogs> In-Reply-To: <171988116691.2006519.4962618271620440482.stgit@frogsfrogsfrogs> References: <171988116691.2006519.4962618271620440482.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 Allow users to enable the logged file mapping exchange intent items on a filesystem, which in turn enables XFS_IOC_EXCHANGE_RANGE and online repair of metadata that lives in files, e.g. directories and xattrs. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- man/man8/mkfs.xfs.8.in | 7 +++++++ mkfs/lts_4.19.conf | 1 + mkfs/lts_5.10.conf | 1 + mkfs/lts_5.15.conf | 1 + mkfs/lts_5.4.conf | 1 + mkfs/lts_6.1.conf | 1 + mkfs/lts_6.6.conf | 1 + mkfs/xfs_mkfs.c | 26 ++++++++++++++++++++++++-- 8 files changed, 37 insertions(+), 2 deletions(-) diff --git a/man/man8/mkfs.xfs.8.in b/man/man8/mkfs.xfs.8.in index 8060d342c2a4..d5a0783ac5d6 100644 --- a/man/man8/mkfs.xfs.8.in +++ b/man/man8/mkfs.xfs.8.in @@ -670,6 +670,13 @@ If the value is omitted, 1 is assumed. This feature will be enabled when possible. This feature is only available for filesystems formatted with -m crc=1. .TP +.BI exchange[= value] +When enabled, application programs can exchange file contents atomically +via the XFS_IOC_EXCHANGE_RANGE ioctl. +Online repair uses this functionality to rebuild extended attributes, +directories, symbolic links, and realtime metadata files. +This feature is disabled by default. +This feature is only available for filesystems formatted with -m crc=1. .RE .PP .PD 0 diff --git a/mkfs/lts_4.19.conf b/mkfs/lts_4.19.conf index 8b2bdd7a3471..92e8eba6ba8f 100644 --- a/mkfs/lts_4.19.conf +++ b/mkfs/lts_4.19.conf @@ -12,3 +12,4 @@ rmapbt=0 [inode] sparse=1 nrext64=0 +exchange=0 diff --git a/mkfs/lts_5.10.conf b/mkfs/lts_5.10.conf index 40189310af2a..34e7662cd671 100644 --- a/mkfs/lts_5.10.conf +++ b/mkfs/lts_5.10.conf @@ -12,3 +12,4 @@ rmapbt=0 [inode] sparse=1 nrext64=0 +exchange=0 diff --git a/mkfs/lts_5.15.conf b/mkfs/lts_5.15.conf index aeecc0355673..a36a5c2b7850 100644 --- a/mkfs/lts_5.15.conf +++ b/mkfs/lts_5.15.conf @@ -12,3 +12,4 @@ rmapbt=0 [inode] sparse=1 nrext64=0 +exchange=0 diff --git a/mkfs/lts_5.4.conf b/mkfs/lts_5.4.conf index 0a40718b8f62..4204d5b8f235 100644 --- a/mkfs/lts_5.4.conf +++ b/mkfs/lts_5.4.conf @@ -12,3 +12,4 @@ rmapbt=0 [inode] sparse=1 nrext64=0 +exchange=0 diff --git a/mkfs/lts_6.1.conf b/mkfs/lts_6.1.conf index 452abdf82e62..9a90def8f489 100644 --- a/mkfs/lts_6.1.conf +++ b/mkfs/lts_6.1.conf @@ -12,3 +12,4 @@ rmapbt=0 [inode] sparse=1 nrext64=0 +exchange=0 diff --git a/mkfs/lts_6.6.conf b/mkfs/lts_6.6.conf index 244f8eaf7645..3f7fb651937d 100644 --- a/mkfs/lts_6.6.conf +++ b/mkfs/lts_6.6.conf @@ -12,3 +12,4 @@ rmapbt=1 [inode] sparse=1 nrext64=1 +exchange=0 diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 6d2469c3c81f..991ecbdd03ff 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -90,6 +90,7 @@ enum { I_PROJID32BIT, I_SPINODES, I_NREXT64, + I_EXCHANGE, I_MAX_OPTS, }; @@ -469,6 +470,7 @@ static struct opt_params iopts = { [I_PROJID32BIT] = "projid32bit", [I_SPINODES] = "sparse", [I_NREXT64] = "nrext64", + [I_EXCHANGE] = "exchange", [I_MAX_OPTS] = NULL, }, .subopt_params = { @@ -523,7 +525,13 @@ static struct opt_params iopts = { .minval = 0, .maxval = 1, .defaultval = 1, - } + }, + { .index = I_EXCHANGE, + .conflicts = { { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, }, }; @@ -889,6 +897,7 @@ struct sb_feat_args { bool nodalign; bool nortalign; bool nrext64; + bool exchrange; /* XFS_SB_FEAT_INCOMPAT_EXCHRANGE */ }; struct cli_params { @@ -1024,7 +1033,8 @@ usage( void ) sectsize=num,concurrency=num]\n\ /* force overwrite */ [-f]\n\ /* inode size */ [-i perblock=n|size=num,maxpct=n,attr=0|1|2,\n\ - projid32bit=0|1,sparse=0|1,nrext64=0|1]\n\ + projid32bit=0|1,sparse=0|1,nrext64=0|1,\n\ + exchange=0|1]\n\ /* no discard */ [-K]\n\ /* log subvol */ [-l agnum=n,internal,size=num,logdev=xxx,version=n\n\ sunit=value|su=num,sectsize=num,lazy-count=0|1,\n\ @@ -1722,6 +1732,9 @@ inode_opts_parser( case I_NREXT64: cli->sb_feat.nrext64 = getnum(value, opts, subopt); break; + case I_EXCHANGE: + cli->sb_feat.exchrange = getnum(value, opts, subopt); + break; default: return -EINVAL; } @@ -2365,6 +2378,13 @@ _("64 bit extent count not supported without CRC support\n")); usage(); } cli->sb_feat.nrext64 = false; + + if (cli->sb_feat.exchrange && cli_opt_set(&iopts, I_EXCHANGE)) { + fprintf(stderr, +_("exchange-range not supported without CRC support\n")); + usage(); + } + cli->sb_feat.exchrange = false; } if (!cli->sb_feat.finobt) { @@ -3498,6 +3518,8 @@ sb_set_features( if (fp->nrext64) sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NREXT64; + if (fp->exchrange) + sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_EXCHRANGE; } /*