| 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
| 2 | /* |
| 3 | * Copyright (c) 2020-2024 Oracle. All Rights Reserved. |
| 4 | * Author: Darrick J. Wong <djwong@kernel.org> |
| 5 | */ |
| 6 | #ifndef __XFS_EXCHMAPS_H__ |
| 7 | #define __XFS_EXCHMAPS_H__ |
| 8 | |
| 9 | /* In-core deferred operation info about a file mapping exchange request. */ |
| 10 | struct xfs_exchmaps_intent { |
| 11 | /* List of other incore deferred work. */ |
| 12 | struct list_head xmi_list; |
| 13 | |
| 14 | /* Inodes participating in the operation. */ |
| 15 | struct xfs_inode *xmi_ip1; |
| 16 | struct xfs_inode *xmi_ip2; |
| 17 | |
| 18 | /* File offset range information. */ |
| 19 | xfs_fileoff_t xmi_startoff1; |
| 20 | xfs_fileoff_t xmi_startoff2; |
| 21 | xfs_filblks_t xmi_blockcount; |
| 22 | |
| 23 | /* Set these file sizes after the operation, unless negative. */ |
| 24 | xfs_fsize_t xmi_isize1; |
| 25 | xfs_fsize_t xmi_isize2; |
| 26 | |
| 27 | uint64_t xmi_flags; /* XFS_EXCHMAPS_* flags */ |
| 28 | }; |
| 29 | |
| 30 | /* Try to convert inode2 from block to short format at the end, if possible. */ |
| 31 | #define __XFS_EXCHMAPS_INO2_SHORTFORM (1ULL << 63) |
| 32 | |
| 33 | #define XFS_EXCHMAPS_INTERNAL_FLAGS (__XFS_EXCHMAPS_INO2_SHORTFORM) |
| 34 | |
| 35 | /* flags that can be passed to xfs_exchmaps_{estimate,mappings} */ |
| 36 | #define XFS_EXCHMAPS_PARAMS (XFS_EXCHMAPS_ATTR_FORK | \ |
| 37 | XFS_EXCHMAPS_SET_SIZES | \ |
| 38 | XFS_EXCHMAPS_INO1_WRITTEN) |
| 39 | |
| 40 | static inline int |
| 41 | xfs_exchmaps_whichfork(const struct xfs_exchmaps_intent *xmi) |
| 42 | { |
| 43 | if (xmi->xmi_flags & XFS_EXCHMAPS_ATTR_FORK) |
| 44 | return XFS_ATTR_FORK; |
| 45 | return XFS_DATA_FORK; |
| 46 | } |
| 47 | |
| 48 | /* Parameters for a mapping exchange request. */ |
| 49 | struct xfs_exchmaps_req { |
| 50 | /* Inodes participating in the operation. */ |
| 51 | struct xfs_inode *ip1; |
| 52 | struct xfs_inode *ip2; |
| 53 | |
| 54 | /* File offset range information. */ |
| 55 | xfs_fileoff_t startoff1; |
| 56 | xfs_fileoff_t startoff2; |
| 57 | xfs_filblks_t blockcount; |
| 58 | |
| 59 | /* XFS_EXCHMAPS_* operation flags */ |
| 60 | uint64_t flags; |
| 61 | |
| 62 | /* |
| 63 | * Fields below this line are filled out by xfs_exchmaps_estimate; |
| 64 | * callers should initialize this part of the struct to zero. |
| 65 | */ |
| 66 | |
| 67 | /* |
| 68 | * Data device blocks to be moved out of ip1, and free space needed to |
| 69 | * handle the bmbt changes. |
| 70 | */ |
| 71 | xfs_filblks_t ip1_bcount; |
| 72 | |
| 73 | /* |
| 74 | * Data device blocks to be moved out of ip2, and free space needed to |
| 75 | * handle the bmbt changes. |
| 76 | */ |
| 77 | xfs_filblks_t ip2_bcount; |
| 78 | |
| 79 | /* rt blocks to be moved out of ip1. */ |
| 80 | xfs_filblks_t ip1_rtbcount; |
| 81 | |
| 82 | /* rt blocks to be moved out of ip2. */ |
| 83 | xfs_filblks_t ip2_rtbcount; |
| 84 | |
| 85 | /* Free space needed to handle the bmbt changes */ |
| 86 | unsigned long long resblks; |
| 87 | |
| 88 | /* Number of exchanges needed to complete the operation */ |
| 89 | unsigned long long nr_exchanges; |
| 90 | }; |
| 91 | |
| 92 | static inline int |
| 93 | xfs_exchmaps_reqfork(const struct xfs_exchmaps_req *req) |
| 94 | { |
| 95 | if (req->flags & XFS_EXCHMAPS_ATTR_FORK) |
| 96 | return XFS_ATTR_FORK; |
| 97 | return XFS_DATA_FORK; |
| 98 | } |
| 99 | |
| 100 | int xfs_exchmaps_estimate_overhead(struct xfs_exchmaps_req *req); |
| 101 | int xfs_exchmaps_estimate(struct xfs_exchmaps_req *req); |
| 102 | |
| 103 | extern struct kmem_cache *xfs_exchmaps_intent_cache; |
| 104 | |
| 105 | int __init xfs_exchmaps_intent_init_cache(void); |
| 106 | void xfs_exchmaps_intent_destroy_cache(void); |
| 107 | |
| 108 | struct xfs_exchmaps_intent *xfs_exchmaps_init_intent( |
| 109 | const struct xfs_exchmaps_req *req); |
| 110 | void xfs_exchmaps_ensure_reflink(struct xfs_trans *tp, |
| 111 | const struct xfs_exchmaps_intent *xmi); |
| 112 | void xfs_exchmaps_upgrade_extent_counts(struct xfs_trans *tp, |
| 113 | const struct xfs_exchmaps_intent *xmi); |
| 114 | |
| 115 | int xfs_exchmaps_finish_one(struct xfs_trans *tp, |
| 116 | struct xfs_exchmaps_intent *xmi); |
| 117 | |
| 118 | int xfs_exchmaps_check_forks(struct xfs_mount *mp, |
| 119 | const struct xfs_exchmaps_req *req); |
| 120 | |
| 121 | void xfs_exchange_mappings(struct xfs_trans *tp, |
| 122 | const struct xfs_exchmaps_req *req); |
| 123 | |
| 124 | #endif /* __XFS_EXCHMAPS_H__ */ |
| 125 | |