Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 : /* 3 : * Copyright (C) 2020-2023 Oracle. All Rights Reserved. 4 : * Author: Darrick J. Wong <djwong@kernel.org> 5 : */ 6 : #ifndef __XFS_SWAPEXT_H_ 7 : #define __XFS_SWAPEXT_H_ 1 8 : 9 : /* 10 : * Decide if this filesystem supports using log items to swap file extents and 11 : * restart the operation if the system fails before the operation completes. 12 : * 13 : * This can be done to individual file extents by using the block mapping log 14 : * intent items introduced with reflink and rmap; or to entire file ranges 15 : * using swapext log intent items to track the overall progress across multiple 16 : * extent mappings. 17 : */ 18 : static inline bool xfs_swapext_supported(struct xfs_mount *mp) 19 : { 20 2344390 : return xfs_has_reflink(mp) || xfs_has_rmapbt(mp); 21 : } 22 : 23 : /* 24 : * In-core information about an extent swap request between ranges of two 25 : * inodes. 26 : */ 27 : struct xfs_swapext_intent { 28 : /* List of other incore deferred work. */ 29 : struct list_head sxi_list; 30 : 31 : /* Inodes participating in the operation. */ 32 : struct xfs_inode *sxi_ip1; 33 : struct xfs_inode *sxi_ip2; 34 : 35 : /* File offset range information. */ 36 : xfs_fileoff_t sxi_startoff1; 37 : xfs_fileoff_t sxi_startoff2; 38 : xfs_filblks_t sxi_blockcount; 39 : 40 : /* Set these file sizes after the operation, unless negative. */ 41 : xfs_fsize_t sxi_isize1; 42 : xfs_fsize_t sxi_isize2; 43 : 44 : /* XFS_SWAP_EXT_* log operation flags */ 45 : unsigned int sxi_flags; 46 : 47 : /* XFS_SWAP_EXT_OP_* flags */ 48 : unsigned int sxi_op_flags; 49 : }; 50 : 51 : /* Use log intent items to track and restart the entire operation. */ 52 : #define XFS_SWAP_EXT_OP_LOGGED (1U << 0) 53 : 54 : /* Upgrade files to have large extent counts before proceeding. */ 55 : #define XFS_SWAP_EXT_OP_NREXT64 (1U << 1) 56 : 57 : #define XFS_SWAP_EXT_OP_STRINGS \ 58 : { XFS_SWAP_EXT_OP_LOGGED, "LOGGED" }, \ 59 : { XFS_SWAP_EXT_OP_NREXT64, "NREXT64" } 60 : 61 : static inline int 62 : xfs_swapext_whichfork(const struct xfs_swapext_intent *sxi) 63 : { 64 3561736 : if (sxi->sxi_flags & XFS_SWAP_EXT_ATTR_FORK) 65 206734 : return XFS_ATTR_FORK; 66 : return XFS_DATA_FORK; 67 : } 68 : 69 : /* Parameters for a swapext request. */ 70 : struct xfs_swapext_req { 71 : /* Inodes participating in the operation. */ 72 : struct xfs_inode *ip1; 73 : struct xfs_inode *ip2; 74 : 75 : /* File offset range information. */ 76 : xfs_fileoff_t startoff1; 77 : xfs_fileoff_t startoff2; 78 : xfs_filblks_t blockcount; 79 : 80 : /* Data or attr fork? */ 81 : int whichfork; 82 : 83 : /* XFS_SWAP_REQ_* operation flags */ 84 : unsigned int req_flags; 85 : 86 : /* 87 : * Fields below this line are filled out by xfs_swapext_estimate; 88 : * callers should initialize this part of the struct to zero. 89 : */ 90 : 91 : /* 92 : * Data device blocks to be moved out of ip1, and free space needed to 93 : * handle the bmbt changes. 94 : */ 95 : xfs_filblks_t ip1_bcount; 96 : 97 : /* 98 : * Data device blocks to be moved out of ip2, and free space needed to 99 : * handle the bmbt changes. 100 : */ 101 : xfs_filblks_t ip2_bcount; 102 : 103 : /* rt blocks to be moved out of ip1. */ 104 : xfs_filblks_t ip1_rtbcount; 105 : 106 : /* rt blocks to be moved out of ip2. */ 107 : xfs_filblks_t ip2_rtbcount; 108 : 109 : /* Free space needed to handle the bmbt changes */ 110 : unsigned long long resblks; 111 : 112 : /* Number of extent swaps needed to complete the operation */ 113 : unsigned long long nr_exchanges; 114 : }; 115 : 116 : /* Caller has permission to use log intent items for the swapext operation. */ 117 : #define XFS_SWAP_REQ_LOGGED (1U << 0) 118 : 119 : /* Set the file sizes when finished. */ 120 : #define XFS_SWAP_REQ_SET_SIZES (1U << 1) 121 : 122 : /* 123 : * Swap only the parts of the two files where the file allocation units 124 : * mapped to file1's range have been written to. 125 : */ 126 : #define XFS_SWAP_REQ_INO1_WRITTEN (1U << 2) 127 : 128 : /* Files need to be upgraded to have large extent counts. */ 129 : #define XFS_SWAP_REQ_NREXT64 (1U << 3) 130 : 131 : /* Try to convert inode2's fork to local format, if possible. */ 132 : #define XFS_SWAP_REQ_CVT_INO2_SF (1U << 4) 133 : 134 : #define XFS_SWAP_REQ_FLAGS (XFS_SWAP_REQ_LOGGED | \ 135 : XFS_SWAP_REQ_SET_SIZES | \ 136 : XFS_SWAP_REQ_INO1_WRITTEN | \ 137 : XFS_SWAP_REQ_NREXT64 | \ 138 : XFS_SWAP_REQ_CVT_INO2_SF) 139 : 140 : #define XFS_SWAP_REQ_STRINGS \ 141 : { XFS_SWAP_REQ_LOGGED, "LOGGED" }, \ 142 : { XFS_SWAP_REQ_SET_SIZES, "SETSIZES" }, \ 143 : { XFS_SWAP_REQ_INO1_WRITTEN, "INO1_WRITTEN" }, \ 144 : { XFS_SWAP_REQ_NREXT64, "NREXT64" }, \ 145 : { XFS_SWAP_REQ_CVT_INO2_SF, "CVT_INO2_SF" } 146 : 147 : unsigned int xfs_swapext_reflink_prep(const struct xfs_swapext_req *req); 148 : void xfs_swapext_reflink_finish(struct xfs_trans *tp, 149 : const struct xfs_swapext_req *req, unsigned int reflink_state); 150 : 151 : int xfs_swapext_estimate_overhead(struct xfs_swapext_req *req); 152 : int xfs_swapext_estimate(struct xfs_swapext_req *req); 153 : 154 : extern struct kmem_cache *xfs_swapext_intent_cache; 155 : 156 : int __init xfs_swapext_intent_init_cache(void); 157 : void xfs_swapext_intent_destroy_cache(void); 158 : 159 : struct xfs_swapext_intent *xfs_swapext_init_intent( 160 : const struct xfs_swapext_req *req, unsigned int *reflink_state); 161 : void xfs_swapext_ensure_reflink(struct xfs_trans *tp, 162 : const struct xfs_swapext_intent *sxi, unsigned int reflink_state); 163 : 164 : void xfs_swapext_schedule(struct xfs_trans *tp, 165 : struct xfs_swapext_intent *sxi); 166 : int xfs_swapext_finish_one(struct xfs_trans *tp, 167 : struct xfs_swapext_intent *sxi); 168 : 169 : int xfs_swapext_check_extents(struct xfs_mount *mp, 170 : const struct xfs_swapext_req *req); 171 : 172 : void xfs_swapext(struct xfs_trans *tp, const struct xfs_swapext_req *req); 173 : 174 : #endif /* __XFS_SWAPEXT_H_ */