]>
Commit | Line | Data |
---|---|---|
959ef981 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
dc3bce02 DW |
2 | /* |
3 | * Copyright (C) 2016 Oracle. All Rights Reserved. | |
dc3bce02 | 4 | * Author: Darrick J. Wong <darrick.wong@oracle.com> |
dc3bce02 DW |
5 | */ |
6 | #include "libxfs_priv.h" | |
7 | #include "xfs_fs.h" | |
8 | #include "xfs_shared.h" | |
9 | #include "xfs_format.h" | |
10 | #include "xfs_log_format.h" | |
11 | #include "xfs_trans_resv.h" | |
12 | #include "xfs_bit.h" | |
13 | #include "xfs_sb.h" | |
14 | #include "xfs_mount.h" | |
15 | #include "xfs_defer.h" | |
16 | #include "xfs_trans.h" | |
17 | #include "xfs_bmap.h" | |
18 | #include "xfs_alloc.h" | |
19 | #include "xfs_rmap.h" | |
cdc9cf25 | 20 | #include "xfs_refcount.h" |
f8f8c8a0 DW |
21 | #include "xfs_bmap.h" |
22 | #include "xfs_inode.h" | |
dc3bce02 DW |
23 | |
24 | /* Dummy defer item ops, since we don't do logging. */ | |
25 | ||
26 | /* Extent Freeing */ | |
27 | ||
28 | /* Sort bmap items by AG. */ | |
29 | static int | |
30 | xfs_extent_free_diff_items( | |
31 | void *priv, | |
32 | struct list_head *a, | |
33 | struct list_head *b) | |
34 | { | |
35 | struct xfs_mount *mp = priv; | |
36 | struct xfs_extent_free_item *ra; | |
37 | struct xfs_extent_free_item *rb; | |
38 | ||
39 | ra = container_of(a, struct xfs_extent_free_item, xefi_list); | |
40 | rb = container_of(b, struct xfs_extent_free_item, xefi_list); | |
41 | return XFS_FSB_TO_AGNO(mp, ra->xefi_startblock) - | |
42 | XFS_FSB_TO_AGNO(mp, rb->xefi_startblock); | |
43 | } | |
44 | ||
45 | /* Get an EFI. */ | |
46 | STATIC void * | |
47 | xfs_extent_free_create_intent( | |
48 | struct xfs_trans *tp, | |
49 | unsigned int count) | |
50 | { | |
51 | return NULL; | |
52 | } | |
53 | ||
54 | /* Log a free extent to the intent item. */ | |
55 | STATIC void | |
56 | xfs_extent_free_log_item( | |
57 | struct xfs_trans *tp, | |
58 | void *intent, | |
59 | struct list_head *item) | |
60 | { | |
61 | } | |
62 | ||
63 | /* Get an EFD so we can process all the free extents. */ | |
64 | STATIC void * | |
65 | xfs_extent_free_create_done( | |
66 | struct xfs_trans *tp, | |
67 | void *intent, | |
68 | unsigned int count) | |
69 | { | |
70 | return NULL; | |
71 | } | |
72 | ||
73 | /* Process a free extent. */ | |
74 | STATIC int | |
75 | xfs_extent_free_finish_item( | |
76 | struct xfs_trans *tp, | |
dc3bce02 DW |
77 | struct list_head *item, |
78 | void *done_item, | |
79 | void **state) | |
80 | { | |
81 | struct xfs_extent_free_item *free; | |
82 | int error; | |
83 | ||
84 | free = container_of(item, struct xfs_extent_free_item, xefi_list); | |
85 | error = xfs_free_extent(tp, free->xefi_startblock, | |
cf8ce220 DW |
86 | free->xefi_blockcount, &free->xefi_oinfo, |
87 | XFS_AG_RESV_NONE); | |
dc3bce02 DW |
88 | kmem_free(free); |
89 | return error; | |
90 | } | |
91 | ||
92 | /* Abort all pending EFIs. */ | |
93 | STATIC void | |
94 | xfs_extent_free_abort_intent( | |
95 | void *intent) | |
96 | { | |
97 | } | |
98 | ||
99 | /* Cancel a free extent. */ | |
100 | STATIC void | |
101 | xfs_extent_free_cancel_item( | |
102 | struct list_head *item) | |
103 | { | |
104 | struct xfs_extent_free_item *free; | |
105 | ||
106 | free = container_of(item, struct xfs_extent_free_item, xefi_list); | |
107 | kmem_free(free); | |
108 | } | |
109 | ||
110 | static const struct xfs_defer_op_type xfs_extent_free_defer_type = { | |
111 | .type = XFS_DEFER_OPS_TYPE_FREE, | |
112 | .diff_items = xfs_extent_free_diff_items, | |
113 | .create_intent = xfs_extent_free_create_intent, | |
114 | .abort_intent = xfs_extent_free_abort_intent, | |
115 | .log_item = xfs_extent_free_log_item, | |
116 | .create_done = xfs_extent_free_create_done, | |
117 | .finish_item = xfs_extent_free_finish_item, | |
118 | .cancel_item = xfs_extent_free_cancel_item, | |
119 | }; | |
120 | ||
121 | /* Register the deferred op type. */ | |
122 | void | |
123 | xfs_extent_free_init_defer_op(void) | |
124 | { | |
125 | xfs_defer_init_op_type(&xfs_extent_free_defer_type); | |
126 | } | |
127 | ||
128 | /* Reverse Mapping */ | |
129 | ||
130 | /* Sort rmap intents by AG. */ | |
131 | static int | |
132 | xfs_rmap_update_diff_items( | |
133 | void *priv, | |
134 | struct list_head *a, | |
135 | struct list_head *b) | |
136 | { | |
137 | struct xfs_mount *mp = priv; | |
138 | struct xfs_rmap_intent *ra; | |
139 | struct xfs_rmap_intent *rb; | |
140 | ||
141 | ra = container_of(a, struct xfs_rmap_intent, ri_list); | |
142 | rb = container_of(b, struct xfs_rmap_intent, ri_list); | |
143 | return XFS_FSB_TO_AGNO(mp, ra->ri_bmap.br_startblock) - | |
144 | XFS_FSB_TO_AGNO(mp, rb->ri_bmap.br_startblock); | |
145 | } | |
146 | ||
147 | /* Get an RUI. */ | |
148 | STATIC void * | |
149 | xfs_rmap_update_create_intent( | |
150 | struct xfs_trans *tp, | |
151 | unsigned int count) | |
152 | { | |
153 | return NULL; | |
154 | } | |
155 | ||
156 | /* Log rmap updates in the intent item. */ | |
157 | STATIC void | |
158 | xfs_rmap_update_log_item( | |
159 | struct xfs_trans *tp, | |
160 | void *intent, | |
161 | struct list_head *item) | |
162 | { | |
163 | } | |
164 | ||
165 | /* Get an RUD so we can process all the deferred rmap updates. */ | |
166 | STATIC void * | |
167 | xfs_rmap_update_create_done( | |
168 | struct xfs_trans *tp, | |
169 | void *intent, | |
170 | unsigned int count) | |
171 | { | |
172 | return NULL; | |
173 | } | |
174 | ||
175 | /* Process a deferred rmap update. */ | |
176 | STATIC int | |
177 | xfs_rmap_update_finish_item( | |
178 | struct xfs_trans *tp, | |
dc3bce02 DW |
179 | struct list_head *item, |
180 | void *done_item, | |
181 | void **state) | |
182 | { | |
183 | struct xfs_rmap_intent *rmap; | |
184 | int error; | |
185 | ||
186 | rmap = container_of(item, struct xfs_rmap_intent, ri_list); | |
187 | error = xfs_rmap_finish_one(tp, | |
188 | rmap->ri_type, | |
189 | rmap->ri_owner, rmap->ri_whichfork, | |
190 | rmap->ri_bmap.br_startoff, | |
191 | rmap->ri_bmap.br_startblock, | |
192 | rmap->ri_bmap.br_blockcount, | |
193 | rmap->ri_bmap.br_state, | |
194 | (struct xfs_btree_cur **)state); | |
195 | kmem_free(rmap); | |
196 | return error; | |
197 | } | |
198 | ||
199 | /* Clean up after processing deferred rmaps. */ | |
200 | STATIC void | |
201 | xfs_rmap_update_finish_cleanup( | |
202 | struct xfs_trans *tp, | |
203 | void *state, | |
204 | int error) | |
205 | { | |
206 | struct xfs_btree_cur *rcur = state; | |
207 | ||
208 | xfs_rmap_finish_one_cleanup(tp, rcur, error); | |
209 | } | |
210 | ||
211 | /* Abort all pending RUIs. */ | |
212 | STATIC void | |
213 | xfs_rmap_update_abort_intent( | |
214 | void *intent) | |
215 | { | |
216 | } | |
217 | ||
218 | /* Cancel a deferred rmap update. */ | |
219 | STATIC void | |
220 | xfs_rmap_update_cancel_item( | |
221 | struct list_head *item) | |
222 | { | |
223 | struct xfs_rmap_intent *rmap; | |
224 | ||
225 | rmap = container_of(item, struct xfs_rmap_intent, ri_list); | |
226 | kmem_free(rmap); | |
227 | } | |
228 | ||
229 | static const struct xfs_defer_op_type xfs_rmap_update_defer_type = { | |
230 | .type = XFS_DEFER_OPS_TYPE_RMAP, | |
231 | .diff_items = xfs_rmap_update_diff_items, | |
232 | .create_intent = xfs_rmap_update_create_intent, | |
233 | .abort_intent = xfs_rmap_update_abort_intent, | |
234 | .log_item = xfs_rmap_update_log_item, | |
235 | .create_done = xfs_rmap_update_create_done, | |
236 | .finish_item = xfs_rmap_update_finish_item, | |
237 | .finish_cleanup = xfs_rmap_update_finish_cleanup, | |
238 | .cancel_item = xfs_rmap_update_cancel_item, | |
239 | }; | |
240 | ||
241 | /* Register the deferred op type. */ | |
242 | void | |
243 | xfs_rmap_update_init_defer_op(void) | |
244 | { | |
245 | xfs_defer_init_op_type(&xfs_rmap_update_defer_type); | |
246 | } | |
cdc9cf25 DW |
247 | |
248 | /* Reference Counting */ | |
249 | ||
250 | /* Sort refcount intents by AG. */ | |
251 | static int | |
252 | xfs_refcount_update_diff_items( | |
253 | void *priv, | |
254 | struct list_head *a, | |
255 | struct list_head *b) | |
256 | { | |
257 | struct xfs_mount *mp = priv; | |
258 | struct xfs_refcount_intent *ra; | |
259 | struct xfs_refcount_intent *rb; | |
260 | ||
261 | ra = container_of(a, struct xfs_refcount_intent, ri_list); | |
262 | rb = container_of(b, struct xfs_refcount_intent, ri_list); | |
263 | return XFS_FSB_TO_AGNO(mp, ra->ri_startblock) - | |
264 | XFS_FSB_TO_AGNO(mp, rb->ri_startblock); | |
265 | } | |
266 | ||
267 | /* Get an CUI. */ | |
268 | STATIC void * | |
269 | xfs_refcount_update_create_intent( | |
270 | struct xfs_trans *tp, | |
271 | unsigned int count) | |
272 | { | |
273 | return NULL; | |
274 | } | |
275 | ||
276 | /* Log refcount updates in the intent item. */ | |
277 | STATIC void | |
278 | xfs_refcount_update_log_item( | |
279 | struct xfs_trans *tp, | |
280 | void *intent, | |
281 | struct list_head *item) | |
282 | { | |
283 | } | |
284 | ||
285 | /* Get an CUD so we can process all the deferred refcount updates. */ | |
286 | STATIC void * | |
287 | xfs_refcount_update_create_done( | |
288 | struct xfs_trans *tp, | |
289 | void *intent, | |
290 | unsigned int count) | |
291 | { | |
292 | return NULL; | |
293 | } | |
294 | ||
295 | /* Process a deferred refcount update. */ | |
296 | STATIC int | |
297 | xfs_refcount_update_finish_item( | |
298 | struct xfs_trans *tp, | |
cdc9cf25 DW |
299 | struct list_head *item, |
300 | void *done_item, | |
301 | void **state) | |
302 | { | |
303 | struct xfs_refcount_intent *refc; | |
304 | xfs_fsblock_t new_fsb; | |
305 | xfs_extlen_t new_aglen; | |
306 | int error; | |
307 | ||
308 | refc = container_of(item, struct xfs_refcount_intent, ri_list); | |
7b3ab230 | 309 | error = xfs_refcount_finish_one(tp, |
cdc9cf25 DW |
310 | refc->ri_type, |
311 | refc->ri_startblock, | |
312 | refc->ri_blockcount, | |
313 | &new_fsb, &new_aglen, | |
314 | (struct xfs_btree_cur **)state); | |
315 | /* Did we run out of reservation? Requeue what we didn't finish. */ | |
316 | if (!error && new_aglen > 0) { | |
317 | ASSERT(refc->ri_type == XFS_REFCOUNT_INCREASE || | |
318 | refc->ri_type == XFS_REFCOUNT_DECREASE); | |
319 | refc->ri_startblock = new_fsb; | |
320 | refc->ri_blockcount = new_aglen; | |
321 | return -EAGAIN; | |
322 | } | |
323 | kmem_free(refc); | |
324 | return error; | |
325 | } | |
326 | ||
327 | /* Clean up after processing deferred refcounts. */ | |
328 | STATIC void | |
329 | xfs_refcount_update_finish_cleanup( | |
330 | struct xfs_trans *tp, | |
331 | void *state, | |
332 | int error) | |
333 | { | |
334 | struct xfs_btree_cur *rcur = state; | |
335 | ||
336 | xfs_refcount_finish_one_cleanup(tp, rcur, error); | |
337 | } | |
338 | ||
339 | /* Abort all pending CUIs. */ | |
340 | STATIC void | |
341 | xfs_refcount_update_abort_intent( | |
342 | void *intent) | |
343 | { | |
344 | } | |
345 | ||
346 | /* Cancel a deferred refcount update. */ | |
347 | STATIC void | |
348 | xfs_refcount_update_cancel_item( | |
349 | struct list_head *item) | |
350 | { | |
351 | struct xfs_refcount_intent *refc; | |
352 | ||
353 | refc = container_of(item, struct xfs_refcount_intent, ri_list); | |
354 | kmem_free(refc); | |
355 | } | |
356 | ||
357 | static const struct xfs_defer_op_type xfs_refcount_update_defer_type = { | |
358 | .type = XFS_DEFER_OPS_TYPE_REFCOUNT, | |
359 | .diff_items = xfs_refcount_update_diff_items, | |
360 | .create_intent = xfs_refcount_update_create_intent, | |
361 | .abort_intent = xfs_refcount_update_abort_intent, | |
362 | .log_item = xfs_refcount_update_log_item, | |
363 | .create_done = xfs_refcount_update_create_done, | |
364 | .finish_item = xfs_refcount_update_finish_item, | |
365 | .finish_cleanup = xfs_refcount_update_finish_cleanup, | |
366 | .cancel_item = xfs_refcount_update_cancel_item, | |
367 | }; | |
368 | ||
369 | /* Register the deferred op type. */ | |
370 | void | |
371 | xfs_refcount_update_init_defer_op(void) | |
372 | { | |
373 | xfs_defer_init_op_type(&xfs_refcount_update_defer_type); | |
374 | } | |
f8f8c8a0 DW |
375 | |
376 | /* Inode Block Mapping */ | |
377 | ||
378 | /* Sort bmap intents by inode. */ | |
379 | static int | |
380 | xfs_bmap_update_diff_items( | |
381 | void *priv, | |
382 | struct list_head *a, | |
383 | struct list_head *b) | |
384 | { | |
385 | struct xfs_bmap_intent *ba; | |
386 | struct xfs_bmap_intent *bb; | |
387 | ||
388 | ba = container_of(a, struct xfs_bmap_intent, bi_list); | |
389 | bb = container_of(b, struct xfs_bmap_intent, bi_list); | |
390 | return ba->bi_owner->i_ino - bb->bi_owner->i_ino; | |
391 | } | |
392 | ||
393 | /* Get an BUI. */ | |
394 | STATIC void * | |
395 | xfs_bmap_update_create_intent( | |
396 | struct xfs_trans *tp, | |
397 | unsigned int count) | |
398 | { | |
399 | return NULL; | |
400 | } | |
401 | ||
402 | /* Log bmap updates in the intent item. */ | |
403 | STATIC void | |
404 | xfs_bmap_update_log_item( | |
405 | struct xfs_trans *tp, | |
406 | void *intent, | |
407 | struct list_head *item) | |
408 | { | |
409 | } | |
410 | ||
411 | /* Get an BUD so we can process all the deferred rmap updates. */ | |
412 | STATIC void * | |
413 | xfs_bmap_update_create_done( | |
414 | struct xfs_trans *tp, | |
415 | void *intent, | |
416 | unsigned int count) | |
417 | { | |
418 | return NULL; | |
419 | } | |
420 | ||
421 | /* Process a deferred rmap update. */ | |
422 | STATIC int | |
423 | xfs_bmap_update_finish_item( | |
424 | struct xfs_trans *tp, | |
f8f8c8a0 DW |
425 | struct list_head *item, |
426 | void *done_item, | |
427 | void **state) | |
428 | { | |
429 | struct xfs_bmap_intent *bmap; | |
594956fa | 430 | xfs_filblks_t count; |
f8f8c8a0 DW |
431 | int error; |
432 | ||
433 | bmap = container_of(item, struct xfs_bmap_intent, bi_list); | |
594956fa | 434 | count = bmap->bi_bmap.br_blockcount; |
7b3ab230 | 435 | error = xfs_bmap_finish_one(tp, |
f8f8c8a0 DW |
436 | bmap->bi_owner, |
437 | bmap->bi_type, bmap->bi_whichfork, | |
438 | bmap->bi_bmap.br_startoff, | |
439 | bmap->bi_bmap.br_startblock, | |
594956fa | 440 | &count, |
f8f8c8a0 | 441 | bmap->bi_bmap.br_state); |
594956fa DW |
442 | if (!error && count > 0) { |
443 | ASSERT(bmap->bi_type == XFS_BMAP_UNMAP); | |
444 | bmap->bi_bmap.br_blockcount = count; | |
445 | return -EAGAIN; | |
446 | } | |
f8f8c8a0 DW |
447 | kmem_free(bmap); |
448 | return error; | |
449 | } | |
450 | ||
451 | /* Abort all pending BUIs. */ | |
452 | STATIC void | |
453 | xfs_bmap_update_abort_intent( | |
454 | void *intent) | |
455 | { | |
456 | } | |
457 | ||
458 | /* Cancel a deferred rmap update. */ | |
459 | STATIC void | |
460 | xfs_bmap_update_cancel_item( | |
461 | struct list_head *item) | |
462 | { | |
463 | struct xfs_bmap_intent *bmap; | |
464 | ||
465 | bmap = container_of(item, struct xfs_bmap_intent, bi_list); | |
466 | kmem_free(bmap); | |
467 | } | |
468 | ||
469 | static const struct xfs_defer_op_type xfs_bmap_update_defer_type = { | |
470 | .type = XFS_DEFER_OPS_TYPE_BMAP, | |
471 | .diff_items = xfs_bmap_update_diff_items, | |
472 | .create_intent = xfs_bmap_update_create_intent, | |
473 | .abort_intent = xfs_bmap_update_abort_intent, | |
474 | .log_item = xfs_bmap_update_log_item, | |
475 | .create_done = xfs_bmap_update_create_done, | |
476 | .finish_item = xfs_bmap_update_finish_item, | |
477 | .cancel_item = xfs_bmap_update_cancel_item, | |
478 | }; | |
479 | ||
480 | /* Register the deferred op type. */ | |
481 | void | |
482 | xfs_bmap_update_init_defer_op(void) | |
483 | { | |
484 | xfs_defer_init_op_type(&xfs_bmap_update_defer_type); | |
485 | } |