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
xfs_exchmaps_whichfork(const struct xfs_exchmaps_intent * xmi)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
xfs_exchmaps_reqfork(const struct xfs_exchmaps_req * req)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