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