1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2017 Christoph Hellwig.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include "xfs.h"
7*4882a593Smuzhiyun #include "xfs_shared.h"
8*4882a593Smuzhiyun #include "xfs_format.h"
9*4882a593Smuzhiyun #include "xfs_bit.h"
10*4882a593Smuzhiyun #include "xfs_log_format.h"
11*4882a593Smuzhiyun #include "xfs_inode.h"
12*4882a593Smuzhiyun #include "xfs_trans_resv.h"
13*4882a593Smuzhiyun #include "xfs_mount.h"
14*4882a593Smuzhiyun #include "xfs_trace.h"
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun /*
17*4882a593Smuzhiyun * In-core extent record layout:
18*4882a593Smuzhiyun *
19*4882a593Smuzhiyun * +-------+----------------------------+
20*4882a593Smuzhiyun * | 00:53 | all 54 bits of startoff |
21*4882a593Smuzhiyun * | 54:63 | low 10 bits of startblock |
22*4882a593Smuzhiyun * +-------+----------------------------+
23*4882a593Smuzhiyun * | 00:20 | all 21 bits of length |
24*4882a593Smuzhiyun * | 21 | unwritten extent bit |
25*4882a593Smuzhiyun * | 22:63 | high 42 bits of startblock |
26*4882a593Smuzhiyun * +-------+----------------------------+
27*4882a593Smuzhiyun */
28*4882a593Smuzhiyun #define XFS_IEXT_STARTOFF_MASK xfs_mask64lo(BMBT_STARTOFF_BITLEN)
29*4882a593Smuzhiyun #define XFS_IEXT_LENGTH_MASK xfs_mask64lo(BMBT_BLOCKCOUNT_BITLEN)
30*4882a593Smuzhiyun #define XFS_IEXT_STARTBLOCK_MASK xfs_mask64lo(BMBT_STARTBLOCK_BITLEN)
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun struct xfs_iext_rec {
33*4882a593Smuzhiyun uint64_t lo;
34*4882a593Smuzhiyun uint64_t hi;
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /*
38*4882a593Smuzhiyun * Given that the length can't be a zero, only an empty hi value indicates an
39*4882a593Smuzhiyun * unused record.
40*4882a593Smuzhiyun */
xfs_iext_rec_is_empty(struct xfs_iext_rec * rec)41*4882a593Smuzhiyun static bool xfs_iext_rec_is_empty(struct xfs_iext_rec *rec)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun return rec->hi == 0;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun
xfs_iext_rec_clear(struct xfs_iext_rec * rec)46*4882a593Smuzhiyun static inline void xfs_iext_rec_clear(struct xfs_iext_rec *rec)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun rec->lo = 0;
49*4882a593Smuzhiyun rec->hi = 0;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun static void
xfs_iext_set(struct xfs_iext_rec * rec,struct xfs_bmbt_irec * irec)53*4882a593Smuzhiyun xfs_iext_set(
54*4882a593Smuzhiyun struct xfs_iext_rec *rec,
55*4882a593Smuzhiyun struct xfs_bmbt_irec *irec)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun ASSERT((irec->br_startoff & ~XFS_IEXT_STARTOFF_MASK) == 0);
58*4882a593Smuzhiyun ASSERT((irec->br_blockcount & ~XFS_IEXT_LENGTH_MASK) == 0);
59*4882a593Smuzhiyun ASSERT((irec->br_startblock & ~XFS_IEXT_STARTBLOCK_MASK) == 0);
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun rec->lo = irec->br_startoff & XFS_IEXT_STARTOFF_MASK;
62*4882a593Smuzhiyun rec->hi = irec->br_blockcount & XFS_IEXT_LENGTH_MASK;
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun rec->lo |= (irec->br_startblock << 54);
65*4882a593Smuzhiyun rec->hi |= ((irec->br_startblock & ~xfs_mask64lo(10)) << (22 - 10));
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun if (irec->br_state == XFS_EXT_UNWRITTEN)
68*4882a593Smuzhiyun rec->hi |= (1 << 21);
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun static void
xfs_iext_get(struct xfs_bmbt_irec * irec,struct xfs_iext_rec * rec)72*4882a593Smuzhiyun xfs_iext_get(
73*4882a593Smuzhiyun struct xfs_bmbt_irec *irec,
74*4882a593Smuzhiyun struct xfs_iext_rec *rec)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun irec->br_startoff = rec->lo & XFS_IEXT_STARTOFF_MASK;
77*4882a593Smuzhiyun irec->br_blockcount = rec->hi & XFS_IEXT_LENGTH_MASK;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun irec->br_startblock = rec->lo >> 54;
80*4882a593Smuzhiyun irec->br_startblock |= (rec->hi & xfs_mask64hi(42)) >> (22 - 10);
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun if (rec->hi & (1 << 21))
83*4882a593Smuzhiyun irec->br_state = XFS_EXT_UNWRITTEN;
84*4882a593Smuzhiyun else
85*4882a593Smuzhiyun irec->br_state = XFS_EXT_NORM;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun enum {
89*4882a593Smuzhiyun NODE_SIZE = 256,
90*4882a593Smuzhiyun KEYS_PER_NODE = NODE_SIZE / (sizeof(uint64_t) + sizeof(void *)),
91*4882a593Smuzhiyun RECS_PER_LEAF = (NODE_SIZE - (2 * sizeof(struct xfs_iext_leaf *))) /
92*4882a593Smuzhiyun sizeof(struct xfs_iext_rec),
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun * In-core extent btree block layout:
97*4882a593Smuzhiyun *
98*4882a593Smuzhiyun * There are two types of blocks in the btree: leaf and inner (non-leaf) blocks.
99*4882a593Smuzhiyun *
100*4882a593Smuzhiyun * The leaf blocks are made up by %KEYS_PER_NODE extent records, which each
101*4882a593Smuzhiyun * contain the startoffset, blockcount, startblock and unwritten extent flag.
102*4882a593Smuzhiyun * See above for the exact format, followed by pointers to the previous and next
103*4882a593Smuzhiyun * leaf blocks (if there are any).
104*4882a593Smuzhiyun *
105*4882a593Smuzhiyun * The inner (non-leaf) blocks first contain KEYS_PER_NODE lookup keys, followed
106*4882a593Smuzhiyun * by an equal number of pointers to the btree blocks at the next lower level.
107*4882a593Smuzhiyun *
108*4882a593Smuzhiyun * +-------+-------+-------+-------+-------+----------+----------+
109*4882a593Smuzhiyun * Leaf: | rec 1 | rec 2 | rec 3 | rec 4 | rec N | prev-ptr | next-ptr |
110*4882a593Smuzhiyun * +-------+-------+-------+-------+-------+----------+----------+
111*4882a593Smuzhiyun *
112*4882a593Smuzhiyun * +-------+-------+-------+-------+-------+-------+------+-------+
113*4882a593Smuzhiyun * Inner: | key 1 | key 2 | key 3 | key N | ptr 1 | ptr 2 | ptr3 | ptr N |
114*4882a593Smuzhiyun * +-------+-------+-------+-------+-------+-------+------+-------+
115*4882a593Smuzhiyun */
116*4882a593Smuzhiyun struct xfs_iext_node {
117*4882a593Smuzhiyun uint64_t keys[KEYS_PER_NODE];
118*4882a593Smuzhiyun #define XFS_IEXT_KEY_INVALID (1ULL << 63)
119*4882a593Smuzhiyun void *ptrs[KEYS_PER_NODE];
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun struct xfs_iext_leaf {
123*4882a593Smuzhiyun struct xfs_iext_rec recs[RECS_PER_LEAF];
124*4882a593Smuzhiyun struct xfs_iext_leaf *prev;
125*4882a593Smuzhiyun struct xfs_iext_leaf *next;
126*4882a593Smuzhiyun };
127*4882a593Smuzhiyun
xfs_iext_count(struct xfs_ifork * ifp)128*4882a593Smuzhiyun inline xfs_extnum_t xfs_iext_count(struct xfs_ifork *ifp)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun return ifp->if_bytes / sizeof(struct xfs_iext_rec);
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
xfs_iext_max_recs(struct xfs_ifork * ifp)133*4882a593Smuzhiyun static inline int xfs_iext_max_recs(struct xfs_ifork *ifp)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun if (ifp->if_height == 1)
136*4882a593Smuzhiyun return xfs_iext_count(ifp);
137*4882a593Smuzhiyun return RECS_PER_LEAF;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
cur_rec(struct xfs_iext_cursor * cur)140*4882a593Smuzhiyun static inline struct xfs_iext_rec *cur_rec(struct xfs_iext_cursor *cur)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun return &cur->leaf->recs[cur->pos];
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun
xfs_iext_valid(struct xfs_ifork * ifp,struct xfs_iext_cursor * cur)145*4882a593Smuzhiyun static inline bool xfs_iext_valid(struct xfs_ifork *ifp,
146*4882a593Smuzhiyun struct xfs_iext_cursor *cur)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun if (!cur->leaf)
149*4882a593Smuzhiyun return false;
150*4882a593Smuzhiyun if (cur->pos < 0 || cur->pos >= xfs_iext_max_recs(ifp))
151*4882a593Smuzhiyun return false;
152*4882a593Smuzhiyun if (xfs_iext_rec_is_empty(cur_rec(cur)))
153*4882a593Smuzhiyun return false;
154*4882a593Smuzhiyun return true;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun static void *
xfs_iext_find_first_leaf(struct xfs_ifork * ifp)158*4882a593Smuzhiyun xfs_iext_find_first_leaf(
159*4882a593Smuzhiyun struct xfs_ifork *ifp)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun struct xfs_iext_node *node = ifp->if_u1.if_root;
162*4882a593Smuzhiyun int height;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun if (!ifp->if_height)
165*4882a593Smuzhiyun return NULL;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun for (height = ifp->if_height; height > 1; height--) {
168*4882a593Smuzhiyun node = node->ptrs[0];
169*4882a593Smuzhiyun ASSERT(node);
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun return node;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun static void *
xfs_iext_find_last_leaf(struct xfs_ifork * ifp)176*4882a593Smuzhiyun xfs_iext_find_last_leaf(
177*4882a593Smuzhiyun struct xfs_ifork *ifp)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun struct xfs_iext_node *node = ifp->if_u1.if_root;
180*4882a593Smuzhiyun int height, i;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun if (!ifp->if_height)
183*4882a593Smuzhiyun return NULL;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun for (height = ifp->if_height; height > 1; height--) {
186*4882a593Smuzhiyun for (i = 1; i < KEYS_PER_NODE; i++)
187*4882a593Smuzhiyun if (!node->ptrs[i])
188*4882a593Smuzhiyun break;
189*4882a593Smuzhiyun node = node->ptrs[i - 1];
190*4882a593Smuzhiyun ASSERT(node);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun return node;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun void
xfs_iext_first(struct xfs_ifork * ifp,struct xfs_iext_cursor * cur)197*4882a593Smuzhiyun xfs_iext_first(
198*4882a593Smuzhiyun struct xfs_ifork *ifp,
199*4882a593Smuzhiyun struct xfs_iext_cursor *cur)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun cur->pos = 0;
202*4882a593Smuzhiyun cur->leaf = xfs_iext_find_first_leaf(ifp);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun void
xfs_iext_last(struct xfs_ifork * ifp,struct xfs_iext_cursor * cur)206*4882a593Smuzhiyun xfs_iext_last(
207*4882a593Smuzhiyun struct xfs_ifork *ifp,
208*4882a593Smuzhiyun struct xfs_iext_cursor *cur)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun int i;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun cur->leaf = xfs_iext_find_last_leaf(ifp);
213*4882a593Smuzhiyun if (!cur->leaf) {
214*4882a593Smuzhiyun cur->pos = 0;
215*4882a593Smuzhiyun return;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun for (i = 1; i < xfs_iext_max_recs(ifp); i++) {
219*4882a593Smuzhiyun if (xfs_iext_rec_is_empty(&cur->leaf->recs[i]))
220*4882a593Smuzhiyun break;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun cur->pos = i - 1;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun void
xfs_iext_next(struct xfs_ifork * ifp,struct xfs_iext_cursor * cur)226*4882a593Smuzhiyun xfs_iext_next(
227*4882a593Smuzhiyun struct xfs_ifork *ifp,
228*4882a593Smuzhiyun struct xfs_iext_cursor *cur)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun if (!cur->leaf) {
231*4882a593Smuzhiyun ASSERT(cur->pos <= 0 || cur->pos >= RECS_PER_LEAF);
232*4882a593Smuzhiyun xfs_iext_first(ifp, cur);
233*4882a593Smuzhiyun return;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun ASSERT(cur->pos >= 0);
237*4882a593Smuzhiyun ASSERT(cur->pos < xfs_iext_max_recs(ifp));
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun cur->pos++;
240*4882a593Smuzhiyun if (ifp->if_height > 1 && !xfs_iext_valid(ifp, cur) &&
241*4882a593Smuzhiyun cur->leaf->next) {
242*4882a593Smuzhiyun cur->leaf = cur->leaf->next;
243*4882a593Smuzhiyun cur->pos = 0;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun void
xfs_iext_prev(struct xfs_ifork * ifp,struct xfs_iext_cursor * cur)248*4882a593Smuzhiyun xfs_iext_prev(
249*4882a593Smuzhiyun struct xfs_ifork *ifp,
250*4882a593Smuzhiyun struct xfs_iext_cursor *cur)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun if (!cur->leaf) {
253*4882a593Smuzhiyun ASSERT(cur->pos <= 0 || cur->pos >= RECS_PER_LEAF);
254*4882a593Smuzhiyun xfs_iext_last(ifp, cur);
255*4882a593Smuzhiyun return;
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun ASSERT(cur->pos >= 0);
259*4882a593Smuzhiyun ASSERT(cur->pos <= RECS_PER_LEAF);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun recurse:
262*4882a593Smuzhiyun do {
263*4882a593Smuzhiyun cur->pos--;
264*4882a593Smuzhiyun if (xfs_iext_valid(ifp, cur))
265*4882a593Smuzhiyun return;
266*4882a593Smuzhiyun } while (cur->pos > 0);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun if (ifp->if_height > 1 && cur->leaf->prev) {
269*4882a593Smuzhiyun cur->leaf = cur->leaf->prev;
270*4882a593Smuzhiyun cur->pos = RECS_PER_LEAF;
271*4882a593Smuzhiyun goto recurse;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun static inline int
xfs_iext_key_cmp(struct xfs_iext_node * node,int n,xfs_fileoff_t offset)276*4882a593Smuzhiyun xfs_iext_key_cmp(
277*4882a593Smuzhiyun struct xfs_iext_node *node,
278*4882a593Smuzhiyun int n,
279*4882a593Smuzhiyun xfs_fileoff_t offset)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun if (node->keys[n] > offset)
282*4882a593Smuzhiyun return 1;
283*4882a593Smuzhiyun if (node->keys[n] < offset)
284*4882a593Smuzhiyun return -1;
285*4882a593Smuzhiyun return 0;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun static inline int
xfs_iext_rec_cmp(struct xfs_iext_rec * rec,xfs_fileoff_t offset)289*4882a593Smuzhiyun xfs_iext_rec_cmp(
290*4882a593Smuzhiyun struct xfs_iext_rec *rec,
291*4882a593Smuzhiyun xfs_fileoff_t offset)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun uint64_t rec_offset = rec->lo & XFS_IEXT_STARTOFF_MASK;
294*4882a593Smuzhiyun uint32_t rec_len = rec->hi & XFS_IEXT_LENGTH_MASK;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun if (rec_offset > offset)
297*4882a593Smuzhiyun return 1;
298*4882a593Smuzhiyun if (rec_offset + rec_len <= offset)
299*4882a593Smuzhiyun return -1;
300*4882a593Smuzhiyun return 0;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun static void *
xfs_iext_find_level(struct xfs_ifork * ifp,xfs_fileoff_t offset,int level)304*4882a593Smuzhiyun xfs_iext_find_level(
305*4882a593Smuzhiyun struct xfs_ifork *ifp,
306*4882a593Smuzhiyun xfs_fileoff_t offset,
307*4882a593Smuzhiyun int level)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun struct xfs_iext_node *node = ifp->if_u1.if_root;
310*4882a593Smuzhiyun int height, i;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun if (!ifp->if_height)
313*4882a593Smuzhiyun return NULL;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun for (height = ifp->if_height; height > level; height--) {
316*4882a593Smuzhiyun for (i = 1; i < KEYS_PER_NODE; i++)
317*4882a593Smuzhiyun if (xfs_iext_key_cmp(node, i, offset) > 0)
318*4882a593Smuzhiyun break;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun node = node->ptrs[i - 1];
321*4882a593Smuzhiyun if (!node)
322*4882a593Smuzhiyun break;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun return node;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun static int
xfs_iext_node_pos(struct xfs_iext_node * node,xfs_fileoff_t offset)329*4882a593Smuzhiyun xfs_iext_node_pos(
330*4882a593Smuzhiyun struct xfs_iext_node *node,
331*4882a593Smuzhiyun xfs_fileoff_t offset)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun int i;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun for (i = 1; i < KEYS_PER_NODE; i++) {
336*4882a593Smuzhiyun if (xfs_iext_key_cmp(node, i, offset) > 0)
337*4882a593Smuzhiyun break;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun return i - 1;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun static int
xfs_iext_node_insert_pos(struct xfs_iext_node * node,xfs_fileoff_t offset)344*4882a593Smuzhiyun xfs_iext_node_insert_pos(
345*4882a593Smuzhiyun struct xfs_iext_node *node,
346*4882a593Smuzhiyun xfs_fileoff_t offset)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun int i;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun for (i = 0; i < KEYS_PER_NODE; i++) {
351*4882a593Smuzhiyun if (xfs_iext_key_cmp(node, i, offset) > 0)
352*4882a593Smuzhiyun return i;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun return KEYS_PER_NODE;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun static int
xfs_iext_node_nr_entries(struct xfs_iext_node * node,int start)359*4882a593Smuzhiyun xfs_iext_node_nr_entries(
360*4882a593Smuzhiyun struct xfs_iext_node *node,
361*4882a593Smuzhiyun int start)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun int i;
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun for (i = start; i < KEYS_PER_NODE; i++) {
366*4882a593Smuzhiyun if (node->keys[i] == XFS_IEXT_KEY_INVALID)
367*4882a593Smuzhiyun break;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun return i;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun static int
xfs_iext_leaf_nr_entries(struct xfs_ifork * ifp,struct xfs_iext_leaf * leaf,int start)374*4882a593Smuzhiyun xfs_iext_leaf_nr_entries(
375*4882a593Smuzhiyun struct xfs_ifork *ifp,
376*4882a593Smuzhiyun struct xfs_iext_leaf *leaf,
377*4882a593Smuzhiyun int start)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun int i;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun for (i = start; i < xfs_iext_max_recs(ifp); i++) {
382*4882a593Smuzhiyun if (xfs_iext_rec_is_empty(&leaf->recs[i]))
383*4882a593Smuzhiyun break;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun return i;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun static inline uint64_t
xfs_iext_leaf_key(struct xfs_iext_leaf * leaf,int n)390*4882a593Smuzhiyun xfs_iext_leaf_key(
391*4882a593Smuzhiyun struct xfs_iext_leaf *leaf,
392*4882a593Smuzhiyun int n)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun return leaf->recs[n].lo & XFS_IEXT_STARTOFF_MASK;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun static void
xfs_iext_grow(struct xfs_ifork * ifp)398*4882a593Smuzhiyun xfs_iext_grow(
399*4882a593Smuzhiyun struct xfs_ifork *ifp)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun struct xfs_iext_node *node = kmem_zalloc(NODE_SIZE, KM_NOFS);
402*4882a593Smuzhiyun int i;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun if (ifp->if_height == 1) {
405*4882a593Smuzhiyun struct xfs_iext_leaf *prev = ifp->if_u1.if_root;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun node->keys[0] = xfs_iext_leaf_key(prev, 0);
408*4882a593Smuzhiyun node->ptrs[0] = prev;
409*4882a593Smuzhiyun } else {
410*4882a593Smuzhiyun struct xfs_iext_node *prev = ifp->if_u1.if_root;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun ASSERT(ifp->if_height > 1);
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun node->keys[0] = prev->keys[0];
415*4882a593Smuzhiyun node->ptrs[0] = prev;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun for (i = 1; i < KEYS_PER_NODE; i++)
419*4882a593Smuzhiyun node->keys[i] = XFS_IEXT_KEY_INVALID;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun ifp->if_u1.if_root = node;
422*4882a593Smuzhiyun ifp->if_height++;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun static void
xfs_iext_update_node(struct xfs_ifork * ifp,xfs_fileoff_t old_offset,xfs_fileoff_t new_offset,int level,void * ptr)426*4882a593Smuzhiyun xfs_iext_update_node(
427*4882a593Smuzhiyun struct xfs_ifork *ifp,
428*4882a593Smuzhiyun xfs_fileoff_t old_offset,
429*4882a593Smuzhiyun xfs_fileoff_t new_offset,
430*4882a593Smuzhiyun int level,
431*4882a593Smuzhiyun void *ptr)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun struct xfs_iext_node *node = ifp->if_u1.if_root;
434*4882a593Smuzhiyun int height, i;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun for (height = ifp->if_height; height > level; height--) {
437*4882a593Smuzhiyun for (i = 0; i < KEYS_PER_NODE; i++) {
438*4882a593Smuzhiyun if (i > 0 && xfs_iext_key_cmp(node, i, old_offset) > 0)
439*4882a593Smuzhiyun break;
440*4882a593Smuzhiyun if (node->keys[i] == old_offset)
441*4882a593Smuzhiyun node->keys[i] = new_offset;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun node = node->ptrs[i - 1];
444*4882a593Smuzhiyun ASSERT(node);
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun ASSERT(node == ptr);
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun static struct xfs_iext_node *
xfs_iext_split_node(struct xfs_iext_node ** nodep,int * pos,int * nr_entries)451*4882a593Smuzhiyun xfs_iext_split_node(
452*4882a593Smuzhiyun struct xfs_iext_node **nodep,
453*4882a593Smuzhiyun int *pos,
454*4882a593Smuzhiyun int *nr_entries)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun struct xfs_iext_node *node = *nodep;
457*4882a593Smuzhiyun struct xfs_iext_node *new = kmem_zalloc(NODE_SIZE, KM_NOFS);
458*4882a593Smuzhiyun const int nr_move = KEYS_PER_NODE / 2;
459*4882a593Smuzhiyun int nr_keep = nr_move + (KEYS_PER_NODE & 1);
460*4882a593Smuzhiyun int i = 0;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun /* for sequential append operations just spill over into the new node */
463*4882a593Smuzhiyun if (*pos == KEYS_PER_NODE) {
464*4882a593Smuzhiyun *nodep = new;
465*4882a593Smuzhiyun *pos = 0;
466*4882a593Smuzhiyun *nr_entries = 0;
467*4882a593Smuzhiyun goto done;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun for (i = 0; i < nr_move; i++) {
472*4882a593Smuzhiyun new->keys[i] = node->keys[nr_keep + i];
473*4882a593Smuzhiyun new->ptrs[i] = node->ptrs[nr_keep + i];
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun node->keys[nr_keep + i] = XFS_IEXT_KEY_INVALID;
476*4882a593Smuzhiyun node->ptrs[nr_keep + i] = NULL;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun if (*pos >= nr_keep) {
480*4882a593Smuzhiyun *nodep = new;
481*4882a593Smuzhiyun *pos -= nr_keep;
482*4882a593Smuzhiyun *nr_entries = nr_move;
483*4882a593Smuzhiyun } else {
484*4882a593Smuzhiyun *nr_entries = nr_keep;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun done:
487*4882a593Smuzhiyun for (; i < KEYS_PER_NODE; i++)
488*4882a593Smuzhiyun new->keys[i] = XFS_IEXT_KEY_INVALID;
489*4882a593Smuzhiyun return new;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun static void
xfs_iext_insert_node(struct xfs_ifork * ifp,uint64_t offset,void * ptr,int level)493*4882a593Smuzhiyun xfs_iext_insert_node(
494*4882a593Smuzhiyun struct xfs_ifork *ifp,
495*4882a593Smuzhiyun uint64_t offset,
496*4882a593Smuzhiyun void *ptr,
497*4882a593Smuzhiyun int level)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun struct xfs_iext_node *node, *new;
500*4882a593Smuzhiyun int i, pos, nr_entries;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun again:
503*4882a593Smuzhiyun if (ifp->if_height < level)
504*4882a593Smuzhiyun xfs_iext_grow(ifp);
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun new = NULL;
507*4882a593Smuzhiyun node = xfs_iext_find_level(ifp, offset, level);
508*4882a593Smuzhiyun pos = xfs_iext_node_insert_pos(node, offset);
509*4882a593Smuzhiyun nr_entries = xfs_iext_node_nr_entries(node, pos);
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun ASSERT(pos >= nr_entries || xfs_iext_key_cmp(node, pos, offset) != 0);
512*4882a593Smuzhiyun ASSERT(nr_entries <= KEYS_PER_NODE);
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun if (nr_entries == KEYS_PER_NODE)
515*4882a593Smuzhiyun new = xfs_iext_split_node(&node, &pos, &nr_entries);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun /*
518*4882a593Smuzhiyun * Update the pointers in higher levels if the first entry changes
519*4882a593Smuzhiyun * in an existing node.
520*4882a593Smuzhiyun */
521*4882a593Smuzhiyun if (node != new && pos == 0 && nr_entries > 0)
522*4882a593Smuzhiyun xfs_iext_update_node(ifp, node->keys[0], offset, level, node);
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun for (i = nr_entries; i > pos; i--) {
525*4882a593Smuzhiyun node->keys[i] = node->keys[i - 1];
526*4882a593Smuzhiyun node->ptrs[i] = node->ptrs[i - 1];
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun node->keys[pos] = offset;
529*4882a593Smuzhiyun node->ptrs[pos] = ptr;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun if (new) {
532*4882a593Smuzhiyun offset = new->keys[0];
533*4882a593Smuzhiyun ptr = new;
534*4882a593Smuzhiyun level++;
535*4882a593Smuzhiyun goto again;
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun static struct xfs_iext_leaf *
xfs_iext_split_leaf(struct xfs_iext_cursor * cur,int * nr_entries)540*4882a593Smuzhiyun xfs_iext_split_leaf(
541*4882a593Smuzhiyun struct xfs_iext_cursor *cur,
542*4882a593Smuzhiyun int *nr_entries)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun struct xfs_iext_leaf *leaf = cur->leaf;
545*4882a593Smuzhiyun struct xfs_iext_leaf *new = kmem_zalloc(NODE_SIZE, KM_NOFS);
546*4882a593Smuzhiyun const int nr_move = RECS_PER_LEAF / 2;
547*4882a593Smuzhiyun int nr_keep = nr_move + (RECS_PER_LEAF & 1);
548*4882a593Smuzhiyun int i;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun /* for sequential append operations just spill over into the new node */
551*4882a593Smuzhiyun if (cur->pos == RECS_PER_LEAF) {
552*4882a593Smuzhiyun cur->leaf = new;
553*4882a593Smuzhiyun cur->pos = 0;
554*4882a593Smuzhiyun *nr_entries = 0;
555*4882a593Smuzhiyun goto done;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun for (i = 0; i < nr_move; i++) {
559*4882a593Smuzhiyun new->recs[i] = leaf->recs[nr_keep + i];
560*4882a593Smuzhiyun xfs_iext_rec_clear(&leaf->recs[nr_keep + i]);
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun if (cur->pos >= nr_keep) {
564*4882a593Smuzhiyun cur->leaf = new;
565*4882a593Smuzhiyun cur->pos -= nr_keep;
566*4882a593Smuzhiyun *nr_entries = nr_move;
567*4882a593Smuzhiyun } else {
568*4882a593Smuzhiyun *nr_entries = nr_keep;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun done:
571*4882a593Smuzhiyun if (leaf->next)
572*4882a593Smuzhiyun leaf->next->prev = new;
573*4882a593Smuzhiyun new->next = leaf->next;
574*4882a593Smuzhiyun new->prev = leaf;
575*4882a593Smuzhiyun leaf->next = new;
576*4882a593Smuzhiyun return new;
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun static void
xfs_iext_alloc_root(struct xfs_ifork * ifp,struct xfs_iext_cursor * cur)580*4882a593Smuzhiyun xfs_iext_alloc_root(
581*4882a593Smuzhiyun struct xfs_ifork *ifp,
582*4882a593Smuzhiyun struct xfs_iext_cursor *cur)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun ASSERT(ifp->if_bytes == 0);
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun ifp->if_u1.if_root = kmem_zalloc(sizeof(struct xfs_iext_rec), KM_NOFS);
587*4882a593Smuzhiyun ifp->if_height = 1;
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun /* now that we have a node step into it */
590*4882a593Smuzhiyun cur->leaf = ifp->if_u1.if_root;
591*4882a593Smuzhiyun cur->pos = 0;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun static void
xfs_iext_realloc_root(struct xfs_ifork * ifp,struct xfs_iext_cursor * cur)595*4882a593Smuzhiyun xfs_iext_realloc_root(
596*4882a593Smuzhiyun struct xfs_ifork *ifp,
597*4882a593Smuzhiyun struct xfs_iext_cursor *cur)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun int64_t new_size = ifp->if_bytes + sizeof(struct xfs_iext_rec);
600*4882a593Smuzhiyun void *new;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun /* account for the prev/next pointers */
603*4882a593Smuzhiyun if (new_size / sizeof(struct xfs_iext_rec) == RECS_PER_LEAF)
604*4882a593Smuzhiyun new_size = NODE_SIZE;
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun new = krealloc(ifp->if_u1.if_root, new_size, GFP_NOFS | __GFP_NOFAIL);
607*4882a593Smuzhiyun memset(new + ifp->if_bytes, 0, new_size - ifp->if_bytes);
608*4882a593Smuzhiyun ifp->if_u1.if_root = new;
609*4882a593Smuzhiyun cur->leaf = new;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun /*
613*4882a593Smuzhiyun * Increment the sequence counter on extent tree changes. If we are on a COW
614*4882a593Smuzhiyun * fork, this allows the writeback code to skip looking for a COW extent if the
615*4882a593Smuzhiyun * COW fork hasn't changed. We use WRITE_ONCE here to ensure the update to the
616*4882a593Smuzhiyun * sequence counter is seen before the modifications to the extent tree itself
617*4882a593Smuzhiyun * take effect.
618*4882a593Smuzhiyun */
xfs_iext_inc_seq(struct xfs_ifork * ifp)619*4882a593Smuzhiyun static inline void xfs_iext_inc_seq(struct xfs_ifork *ifp)
620*4882a593Smuzhiyun {
621*4882a593Smuzhiyun WRITE_ONCE(ifp->if_seq, READ_ONCE(ifp->if_seq) + 1);
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun void
xfs_iext_insert(struct xfs_inode * ip,struct xfs_iext_cursor * cur,struct xfs_bmbt_irec * irec,int state)625*4882a593Smuzhiyun xfs_iext_insert(
626*4882a593Smuzhiyun struct xfs_inode *ip,
627*4882a593Smuzhiyun struct xfs_iext_cursor *cur,
628*4882a593Smuzhiyun struct xfs_bmbt_irec *irec,
629*4882a593Smuzhiyun int state)
630*4882a593Smuzhiyun {
631*4882a593Smuzhiyun struct xfs_ifork *ifp = xfs_iext_state_to_fork(ip, state);
632*4882a593Smuzhiyun xfs_fileoff_t offset = irec->br_startoff;
633*4882a593Smuzhiyun struct xfs_iext_leaf *new = NULL;
634*4882a593Smuzhiyun int nr_entries, i;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun xfs_iext_inc_seq(ifp);
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun if (ifp->if_height == 0)
639*4882a593Smuzhiyun xfs_iext_alloc_root(ifp, cur);
640*4882a593Smuzhiyun else if (ifp->if_height == 1)
641*4882a593Smuzhiyun xfs_iext_realloc_root(ifp, cur);
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun nr_entries = xfs_iext_leaf_nr_entries(ifp, cur->leaf, cur->pos);
644*4882a593Smuzhiyun ASSERT(nr_entries <= RECS_PER_LEAF);
645*4882a593Smuzhiyun ASSERT(cur->pos >= nr_entries ||
646*4882a593Smuzhiyun xfs_iext_rec_cmp(cur_rec(cur), irec->br_startoff) != 0);
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun if (nr_entries == RECS_PER_LEAF)
649*4882a593Smuzhiyun new = xfs_iext_split_leaf(cur, &nr_entries);
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun /*
652*4882a593Smuzhiyun * Update the pointers in higher levels if the first entry changes
653*4882a593Smuzhiyun * in an existing node.
654*4882a593Smuzhiyun */
655*4882a593Smuzhiyun if (cur->leaf != new && cur->pos == 0 && nr_entries > 0) {
656*4882a593Smuzhiyun xfs_iext_update_node(ifp, xfs_iext_leaf_key(cur->leaf, 0),
657*4882a593Smuzhiyun offset, 1, cur->leaf);
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun for (i = nr_entries; i > cur->pos; i--)
661*4882a593Smuzhiyun cur->leaf->recs[i] = cur->leaf->recs[i - 1];
662*4882a593Smuzhiyun xfs_iext_set(cur_rec(cur), irec);
663*4882a593Smuzhiyun ifp->if_bytes += sizeof(struct xfs_iext_rec);
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun trace_xfs_iext_insert(ip, cur, state, _RET_IP_);
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun if (new)
668*4882a593Smuzhiyun xfs_iext_insert_node(ifp, xfs_iext_leaf_key(new, 0), new, 2);
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun static struct xfs_iext_node *
xfs_iext_rebalance_node(struct xfs_iext_node * parent,int * pos,struct xfs_iext_node * node,int nr_entries)672*4882a593Smuzhiyun xfs_iext_rebalance_node(
673*4882a593Smuzhiyun struct xfs_iext_node *parent,
674*4882a593Smuzhiyun int *pos,
675*4882a593Smuzhiyun struct xfs_iext_node *node,
676*4882a593Smuzhiyun int nr_entries)
677*4882a593Smuzhiyun {
678*4882a593Smuzhiyun /*
679*4882a593Smuzhiyun * If the neighbouring nodes are completely full, or have different
680*4882a593Smuzhiyun * parents, we might never be able to merge our node, and will only
681*4882a593Smuzhiyun * delete it once the number of entries hits zero.
682*4882a593Smuzhiyun */
683*4882a593Smuzhiyun if (nr_entries == 0)
684*4882a593Smuzhiyun return node;
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun if (*pos > 0) {
687*4882a593Smuzhiyun struct xfs_iext_node *prev = parent->ptrs[*pos - 1];
688*4882a593Smuzhiyun int nr_prev = xfs_iext_node_nr_entries(prev, 0), i;
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun if (nr_prev + nr_entries <= KEYS_PER_NODE) {
691*4882a593Smuzhiyun for (i = 0; i < nr_entries; i++) {
692*4882a593Smuzhiyun prev->keys[nr_prev + i] = node->keys[i];
693*4882a593Smuzhiyun prev->ptrs[nr_prev + i] = node->ptrs[i];
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun return node;
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun if (*pos + 1 < xfs_iext_node_nr_entries(parent, *pos)) {
700*4882a593Smuzhiyun struct xfs_iext_node *next = parent->ptrs[*pos + 1];
701*4882a593Smuzhiyun int nr_next = xfs_iext_node_nr_entries(next, 0), i;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun if (nr_entries + nr_next <= KEYS_PER_NODE) {
704*4882a593Smuzhiyun /*
705*4882a593Smuzhiyun * Merge the next node into this node so that we don't
706*4882a593Smuzhiyun * have to do an additional update of the keys in the
707*4882a593Smuzhiyun * higher levels.
708*4882a593Smuzhiyun */
709*4882a593Smuzhiyun for (i = 0; i < nr_next; i++) {
710*4882a593Smuzhiyun node->keys[nr_entries + i] = next->keys[i];
711*4882a593Smuzhiyun node->ptrs[nr_entries + i] = next->ptrs[i];
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun ++*pos;
715*4882a593Smuzhiyun return next;
716*4882a593Smuzhiyun }
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun return NULL;
720*4882a593Smuzhiyun }
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun static void
xfs_iext_remove_node(struct xfs_ifork * ifp,xfs_fileoff_t offset,void * victim)723*4882a593Smuzhiyun xfs_iext_remove_node(
724*4882a593Smuzhiyun struct xfs_ifork *ifp,
725*4882a593Smuzhiyun xfs_fileoff_t offset,
726*4882a593Smuzhiyun void *victim)
727*4882a593Smuzhiyun {
728*4882a593Smuzhiyun struct xfs_iext_node *node, *parent;
729*4882a593Smuzhiyun int level = 2, pos, nr_entries, i;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun ASSERT(level <= ifp->if_height);
732*4882a593Smuzhiyun node = xfs_iext_find_level(ifp, offset, level);
733*4882a593Smuzhiyun pos = xfs_iext_node_pos(node, offset);
734*4882a593Smuzhiyun again:
735*4882a593Smuzhiyun ASSERT(node->ptrs[pos]);
736*4882a593Smuzhiyun ASSERT(node->ptrs[pos] == victim);
737*4882a593Smuzhiyun kmem_free(victim);
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun nr_entries = xfs_iext_node_nr_entries(node, pos) - 1;
740*4882a593Smuzhiyun offset = node->keys[0];
741*4882a593Smuzhiyun for (i = pos; i < nr_entries; i++) {
742*4882a593Smuzhiyun node->keys[i] = node->keys[i + 1];
743*4882a593Smuzhiyun node->ptrs[i] = node->ptrs[i + 1];
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun node->keys[nr_entries] = XFS_IEXT_KEY_INVALID;
746*4882a593Smuzhiyun node->ptrs[nr_entries] = NULL;
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun if (pos == 0 && nr_entries > 0) {
749*4882a593Smuzhiyun xfs_iext_update_node(ifp, offset, node->keys[0], level, node);
750*4882a593Smuzhiyun offset = node->keys[0];
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun if (nr_entries >= KEYS_PER_NODE / 2)
754*4882a593Smuzhiyun return;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun if (level < ifp->if_height) {
757*4882a593Smuzhiyun /*
758*4882a593Smuzhiyun * If we aren't at the root yet try to find a neighbour node to
759*4882a593Smuzhiyun * merge with (or delete the node if it is empty), and then
760*4882a593Smuzhiyun * recurse up to the next level.
761*4882a593Smuzhiyun */
762*4882a593Smuzhiyun level++;
763*4882a593Smuzhiyun parent = xfs_iext_find_level(ifp, offset, level);
764*4882a593Smuzhiyun pos = xfs_iext_node_pos(parent, offset);
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun ASSERT(pos != KEYS_PER_NODE);
767*4882a593Smuzhiyun ASSERT(parent->ptrs[pos] == node);
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun node = xfs_iext_rebalance_node(parent, &pos, node, nr_entries);
770*4882a593Smuzhiyun if (node) {
771*4882a593Smuzhiyun victim = node;
772*4882a593Smuzhiyun node = parent;
773*4882a593Smuzhiyun goto again;
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun } else if (nr_entries == 1) {
776*4882a593Smuzhiyun /*
777*4882a593Smuzhiyun * If we are at the root and only one entry is left we can just
778*4882a593Smuzhiyun * free this node and update the root pointer.
779*4882a593Smuzhiyun */
780*4882a593Smuzhiyun ASSERT(node == ifp->if_u1.if_root);
781*4882a593Smuzhiyun ifp->if_u1.if_root = node->ptrs[0];
782*4882a593Smuzhiyun ifp->if_height--;
783*4882a593Smuzhiyun kmem_free(node);
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun static void
xfs_iext_rebalance_leaf(struct xfs_ifork * ifp,struct xfs_iext_cursor * cur,struct xfs_iext_leaf * leaf,xfs_fileoff_t offset,int nr_entries)788*4882a593Smuzhiyun xfs_iext_rebalance_leaf(
789*4882a593Smuzhiyun struct xfs_ifork *ifp,
790*4882a593Smuzhiyun struct xfs_iext_cursor *cur,
791*4882a593Smuzhiyun struct xfs_iext_leaf *leaf,
792*4882a593Smuzhiyun xfs_fileoff_t offset,
793*4882a593Smuzhiyun int nr_entries)
794*4882a593Smuzhiyun {
795*4882a593Smuzhiyun /*
796*4882a593Smuzhiyun * If the neighbouring nodes are completely full we might never be able
797*4882a593Smuzhiyun * to merge our node, and will only delete it once the number of
798*4882a593Smuzhiyun * entries hits zero.
799*4882a593Smuzhiyun */
800*4882a593Smuzhiyun if (nr_entries == 0)
801*4882a593Smuzhiyun goto remove_node;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun if (leaf->prev) {
804*4882a593Smuzhiyun int nr_prev = xfs_iext_leaf_nr_entries(ifp, leaf->prev, 0), i;
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun if (nr_prev + nr_entries <= RECS_PER_LEAF) {
807*4882a593Smuzhiyun for (i = 0; i < nr_entries; i++)
808*4882a593Smuzhiyun leaf->prev->recs[nr_prev + i] = leaf->recs[i];
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun if (cur->leaf == leaf) {
811*4882a593Smuzhiyun cur->leaf = leaf->prev;
812*4882a593Smuzhiyun cur->pos += nr_prev;
813*4882a593Smuzhiyun }
814*4882a593Smuzhiyun goto remove_node;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun if (leaf->next) {
819*4882a593Smuzhiyun int nr_next = xfs_iext_leaf_nr_entries(ifp, leaf->next, 0), i;
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun if (nr_entries + nr_next <= RECS_PER_LEAF) {
822*4882a593Smuzhiyun /*
823*4882a593Smuzhiyun * Merge the next node into this node so that we don't
824*4882a593Smuzhiyun * have to do an additional update of the keys in the
825*4882a593Smuzhiyun * higher levels.
826*4882a593Smuzhiyun */
827*4882a593Smuzhiyun for (i = 0; i < nr_next; i++) {
828*4882a593Smuzhiyun leaf->recs[nr_entries + i] =
829*4882a593Smuzhiyun leaf->next->recs[i];
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun if (cur->leaf == leaf->next) {
833*4882a593Smuzhiyun cur->leaf = leaf;
834*4882a593Smuzhiyun cur->pos += nr_entries;
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun offset = xfs_iext_leaf_key(leaf->next, 0);
838*4882a593Smuzhiyun leaf = leaf->next;
839*4882a593Smuzhiyun goto remove_node;
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun return;
844*4882a593Smuzhiyun remove_node:
845*4882a593Smuzhiyun if (leaf->prev)
846*4882a593Smuzhiyun leaf->prev->next = leaf->next;
847*4882a593Smuzhiyun if (leaf->next)
848*4882a593Smuzhiyun leaf->next->prev = leaf->prev;
849*4882a593Smuzhiyun xfs_iext_remove_node(ifp, offset, leaf);
850*4882a593Smuzhiyun }
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun static void
xfs_iext_free_last_leaf(struct xfs_ifork * ifp)853*4882a593Smuzhiyun xfs_iext_free_last_leaf(
854*4882a593Smuzhiyun struct xfs_ifork *ifp)
855*4882a593Smuzhiyun {
856*4882a593Smuzhiyun ifp->if_height--;
857*4882a593Smuzhiyun kmem_free(ifp->if_u1.if_root);
858*4882a593Smuzhiyun ifp->if_u1.if_root = NULL;
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun void
xfs_iext_remove(struct xfs_inode * ip,struct xfs_iext_cursor * cur,int state)862*4882a593Smuzhiyun xfs_iext_remove(
863*4882a593Smuzhiyun struct xfs_inode *ip,
864*4882a593Smuzhiyun struct xfs_iext_cursor *cur,
865*4882a593Smuzhiyun int state)
866*4882a593Smuzhiyun {
867*4882a593Smuzhiyun struct xfs_ifork *ifp = xfs_iext_state_to_fork(ip, state);
868*4882a593Smuzhiyun struct xfs_iext_leaf *leaf = cur->leaf;
869*4882a593Smuzhiyun xfs_fileoff_t offset = xfs_iext_leaf_key(leaf, 0);
870*4882a593Smuzhiyun int i, nr_entries;
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun trace_xfs_iext_remove(ip, cur, state, _RET_IP_);
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun ASSERT(ifp->if_height > 0);
875*4882a593Smuzhiyun ASSERT(ifp->if_u1.if_root != NULL);
876*4882a593Smuzhiyun ASSERT(xfs_iext_valid(ifp, cur));
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun xfs_iext_inc_seq(ifp);
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun nr_entries = xfs_iext_leaf_nr_entries(ifp, leaf, cur->pos) - 1;
881*4882a593Smuzhiyun for (i = cur->pos; i < nr_entries; i++)
882*4882a593Smuzhiyun leaf->recs[i] = leaf->recs[i + 1];
883*4882a593Smuzhiyun xfs_iext_rec_clear(&leaf->recs[nr_entries]);
884*4882a593Smuzhiyun ifp->if_bytes -= sizeof(struct xfs_iext_rec);
885*4882a593Smuzhiyun
886*4882a593Smuzhiyun if (cur->pos == 0 && nr_entries > 0) {
887*4882a593Smuzhiyun xfs_iext_update_node(ifp, offset, xfs_iext_leaf_key(leaf, 0), 1,
888*4882a593Smuzhiyun leaf);
889*4882a593Smuzhiyun offset = xfs_iext_leaf_key(leaf, 0);
890*4882a593Smuzhiyun } else if (cur->pos == nr_entries) {
891*4882a593Smuzhiyun if (ifp->if_height > 1 && leaf->next)
892*4882a593Smuzhiyun cur->leaf = leaf->next;
893*4882a593Smuzhiyun else
894*4882a593Smuzhiyun cur->leaf = NULL;
895*4882a593Smuzhiyun cur->pos = 0;
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun if (nr_entries >= RECS_PER_LEAF / 2)
899*4882a593Smuzhiyun return;
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun if (ifp->if_height > 1)
902*4882a593Smuzhiyun xfs_iext_rebalance_leaf(ifp, cur, leaf, offset, nr_entries);
903*4882a593Smuzhiyun else if (nr_entries == 0)
904*4882a593Smuzhiyun xfs_iext_free_last_leaf(ifp);
905*4882a593Smuzhiyun }
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun /*
908*4882a593Smuzhiyun * Lookup the extent covering bno.
909*4882a593Smuzhiyun *
910*4882a593Smuzhiyun * If there is an extent covering bno return the extent index, and store the
911*4882a593Smuzhiyun * expanded extent structure in *gotp, and the extent cursor in *cur.
912*4882a593Smuzhiyun * If there is no extent covering bno, but there is an extent after it (e.g.
913*4882a593Smuzhiyun * it lies in a hole) return that extent in *gotp and its cursor in *cur
914*4882a593Smuzhiyun * instead.
915*4882a593Smuzhiyun * If bno is beyond the last extent return false, and return an invalid
916*4882a593Smuzhiyun * cursor value.
917*4882a593Smuzhiyun */
918*4882a593Smuzhiyun bool
xfs_iext_lookup_extent(struct xfs_inode * ip,struct xfs_ifork * ifp,xfs_fileoff_t offset,struct xfs_iext_cursor * cur,struct xfs_bmbt_irec * gotp)919*4882a593Smuzhiyun xfs_iext_lookup_extent(
920*4882a593Smuzhiyun struct xfs_inode *ip,
921*4882a593Smuzhiyun struct xfs_ifork *ifp,
922*4882a593Smuzhiyun xfs_fileoff_t offset,
923*4882a593Smuzhiyun struct xfs_iext_cursor *cur,
924*4882a593Smuzhiyun struct xfs_bmbt_irec *gotp)
925*4882a593Smuzhiyun {
926*4882a593Smuzhiyun XFS_STATS_INC(ip->i_mount, xs_look_exlist);
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun cur->leaf = xfs_iext_find_level(ifp, offset, 1);
929*4882a593Smuzhiyun if (!cur->leaf) {
930*4882a593Smuzhiyun cur->pos = 0;
931*4882a593Smuzhiyun return false;
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun for (cur->pos = 0; cur->pos < xfs_iext_max_recs(ifp); cur->pos++) {
935*4882a593Smuzhiyun struct xfs_iext_rec *rec = cur_rec(cur);
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun if (xfs_iext_rec_is_empty(rec))
938*4882a593Smuzhiyun break;
939*4882a593Smuzhiyun if (xfs_iext_rec_cmp(rec, offset) >= 0)
940*4882a593Smuzhiyun goto found;
941*4882a593Smuzhiyun }
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun /* Try looking in the next node for an entry > offset */
944*4882a593Smuzhiyun if (ifp->if_height == 1 || !cur->leaf->next)
945*4882a593Smuzhiyun return false;
946*4882a593Smuzhiyun cur->leaf = cur->leaf->next;
947*4882a593Smuzhiyun cur->pos = 0;
948*4882a593Smuzhiyun if (!xfs_iext_valid(ifp, cur))
949*4882a593Smuzhiyun return false;
950*4882a593Smuzhiyun found:
951*4882a593Smuzhiyun xfs_iext_get(gotp, cur_rec(cur));
952*4882a593Smuzhiyun return true;
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun /*
956*4882a593Smuzhiyun * Returns the last extent before end, and if this extent doesn't cover
957*4882a593Smuzhiyun * end, update end to the end of the extent.
958*4882a593Smuzhiyun */
959*4882a593Smuzhiyun bool
xfs_iext_lookup_extent_before(struct xfs_inode * ip,struct xfs_ifork * ifp,xfs_fileoff_t * end,struct xfs_iext_cursor * cur,struct xfs_bmbt_irec * gotp)960*4882a593Smuzhiyun xfs_iext_lookup_extent_before(
961*4882a593Smuzhiyun struct xfs_inode *ip,
962*4882a593Smuzhiyun struct xfs_ifork *ifp,
963*4882a593Smuzhiyun xfs_fileoff_t *end,
964*4882a593Smuzhiyun struct xfs_iext_cursor *cur,
965*4882a593Smuzhiyun struct xfs_bmbt_irec *gotp)
966*4882a593Smuzhiyun {
967*4882a593Smuzhiyun /* could be optimized to not even look up the next on a match.. */
968*4882a593Smuzhiyun if (xfs_iext_lookup_extent(ip, ifp, *end - 1, cur, gotp) &&
969*4882a593Smuzhiyun gotp->br_startoff <= *end - 1)
970*4882a593Smuzhiyun return true;
971*4882a593Smuzhiyun if (!xfs_iext_prev_extent(ifp, cur, gotp))
972*4882a593Smuzhiyun return false;
973*4882a593Smuzhiyun *end = gotp->br_startoff + gotp->br_blockcount;
974*4882a593Smuzhiyun return true;
975*4882a593Smuzhiyun }
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun void
xfs_iext_update_extent(struct xfs_inode * ip,int state,struct xfs_iext_cursor * cur,struct xfs_bmbt_irec * new)978*4882a593Smuzhiyun xfs_iext_update_extent(
979*4882a593Smuzhiyun struct xfs_inode *ip,
980*4882a593Smuzhiyun int state,
981*4882a593Smuzhiyun struct xfs_iext_cursor *cur,
982*4882a593Smuzhiyun struct xfs_bmbt_irec *new)
983*4882a593Smuzhiyun {
984*4882a593Smuzhiyun struct xfs_ifork *ifp = xfs_iext_state_to_fork(ip, state);
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun xfs_iext_inc_seq(ifp);
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun if (cur->pos == 0) {
989*4882a593Smuzhiyun struct xfs_bmbt_irec old;
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun xfs_iext_get(&old, cur_rec(cur));
992*4882a593Smuzhiyun if (new->br_startoff != old.br_startoff) {
993*4882a593Smuzhiyun xfs_iext_update_node(ifp, old.br_startoff,
994*4882a593Smuzhiyun new->br_startoff, 1, cur->leaf);
995*4882a593Smuzhiyun }
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun trace_xfs_bmap_pre_update(ip, cur, state, _RET_IP_);
999*4882a593Smuzhiyun xfs_iext_set(cur_rec(cur), new);
1000*4882a593Smuzhiyun trace_xfs_bmap_post_update(ip, cur, state, _RET_IP_);
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun /*
1004*4882a593Smuzhiyun * Return true if the cursor points at an extent and return the extent structure
1005*4882a593Smuzhiyun * in gotp. Else return false.
1006*4882a593Smuzhiyun */
1007*4882a593Smuzhiyun bool
xfs_iext_get_extent(struct xfs_ifork * ifp,struct xfs_iext_cursor * cur,struct xfs_bmbt_irec * gotp)1008*4882a593Smuzhiyun xfs_iext_get_extent(
1009*4882a593Smuzhiyun struct xfs_ifork *ifp,
1010*4882a593Smuzhiyun struct xfs_iext_cursor *cur,
1011*4882a593Smuzhiyun struct xfs_bmbt_irec *gotp)
1012*4882a593Smuzhiyun {
1013*4882a593Smuzhiyun if (!xfs_iext_valid(ifp, cur))
1014*4882a593Smuzhiyun return false;
1015*4882a593Smuzhiyun xfs_iext_get(gotp, cur_rec(cur));
1016*4882a593Smuzhiyun return true;
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun /*
1020*4882a593Smuzhiyun * This is a recursive function, because of that we need to be extremely
1021*4882a593Smuzhiyun * careful with stack usage.
1022*4882a593Smuzhiyun */
1023*4882a593Smuzhiyun static void
xfs_iext_destroy_node(struct xfs_iext_node * node,int level)1024*4882a593Smuzhiyun xfs_iext_destroy_node(
1025*4882a593Smuzhiyun struct xfs_iext_node *node,
1026*4882a593Smuzhiyun int level)
1027*4882a593Smuzhiyun {
1028*4882a593Smuzhiyun int i;
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun if (level > 1) {
1031*4882a593Smuzhiyun for (i = 0; i < KEYS_PER_NODE; i++) {
1032*4882a593Smuzhiyun if (node->keys[i] == XFS_IEXT_KEY_INVALID)
1033*4882a593Smuzhiyun break;
1034*4882a593Smuzhiyun xfs_iext_destroy_node(node->ptrs[i], level - 1);
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun }
1037*4882a593Smuzhiyun
1038*4882a593Smuzhiyun kmem_free(node);
1039*4882a593Smuzhiyun }
1040*4882a593Smuzhiyun
1041*4882a593Smuzhiyun void
xfs_iext_destroy(struct xfs_ifork * ifp)1042*4882a593Smuzhiyun xfs_iext_destroy(
1043*4882a593Smuzhiyun struct xfs_ifork *ifp)
1044*4882a593Smuzhiyun {
1045*4882a593Smuzhiyun xfs_iext_destroy_node(ifp->if_u1.if_root, ifp->if_height);
1046*4882a593Smuzhiyun
1047*4882a593Smuzhiyun ifp->if_bytes = 0;
1048*4882a593Smuzhiyun ifp->if_height = 0;
1049*4882a593Smuzhiyun ifp->if_u1.if_root = NULL;
1050*4882a593Smuzhiyun }
1051