]>
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" | |
c6ad4bc1 | 11 | #include "xfs_da_format.h" |
dc3bce02 DW |
12 | #include "xfs_trans_resv.h" |
13 | #include "xfs_bit.h" | |
14 | #include "xfs_sb.h" | |
15 | #include "xfs_mount.h" | |
16 | #include "xfs_defer.h" | |
17 | #include "xfs_trans.h" | |
18 | #include "xfs_bmap.h" | |
19 | #include "xfs_alloc.h" | |
20 | #include "xfs_rmap.h" | |
cdc9cf25 | 21 | #include "xfs_refcount.h" |
f8f8c8a0 DW |
22 | #include "xfs_bmap.h" |
23 | #include "xfs_inode.h" | |
c6ad4bc1 AH |
24 | #include "xfs_da_btree.h" |
25 | #include "xfs_attr.h" | |
f9084bd9 | 26 | #include "libxfs.h" |
dc3bce02 DW |
27 | |
28 | /* Dummy defer item ops, since we don't do logging. */ | |
29 | ||
30 | /* Extent Freeing */ | |
31 | ||
32 | /* Sort bmap items by AG. */ | |
33 | static int | |
34 | xfs_extent_free_diff_items( | |
35 | void *priv, | |
c6b593ee DW |
36 | const struct list_head *a, |
37 | const struct list_head *b) | |
dc3bce02 | 38 | { |
c6b593ee DW |
39 | const struct xfs_extent_free_item *ra; |
40 | const struct xfs_extent_free_item *rb; | |
dc3bce02 DW |
41 | |
42 | ra = container_of(a, struct xfs_extent_free_item, xefi_list); | |
43 | rb = container_of(b, struct xfs_extent_free_item, xefi_list); | |
7fef0c11 DW |
44 | |
45 | return ra->xefi_pag->pag_agno - rb->xefi_pag->pag_agno; | |
dc3bce02 DW |
46 | } |
47 | ||
48 | /* Get an EFI. */ | |
18d0d657 | 49 | static struct xfs_log_item * |
dc3bce02 DW |
50 | xfs_extent_free_create_intent( |
51 | struct xfs_trans *tp, | |
8d81fcd0 | 52 | struct list_head *items, |
74a7f5fa CH |
53 | unsigned int count, |
54 | bool sort) | |
dc3bce02 | 55 | { |
74a7f5fa CH |
56 | struct xfs_mount *mp = tp->t_mountp; |
57 | ||
58 | if (sort) | |
59 | list_sort(mp, items, xfs_extent_free_diff_items); | |
dc3bce02 DW |
60 | return NULL; |
61 | } | |
62 | ||
dc3bce02 | 63 | /* Get an EFD so we can process all the free extents. */ |
95e01274 | 64 | static struct xfs_log_item * |
dc3bce02 DW |
65 | xfs_extent_free_create_done( |
66 | struct xfs_trans *tp, | |
18d0d657 | 67 | struct xfs_log_item *intent, |
dc3bce02 DW |
68 | unsigned int count) |
69 | { | |
70 | return NULL; | |
71 | } | |
72 | ||
4d3226b6 | 73 | /* Take an active ref to the AG containing the space we're freeing. */ |
7fef0c11 DW |
74 | void |
75 | xfs_extent_free_get_group( | |
76 | struct xfs_mount *mp, | |
77 | struct xfs_extent_free_item *xefi) | |
78 | { | |
79 | xfs_agnumber_t agno; | |
80 | ||
81 | agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock); | |
4d3226b6 | 82 | xefi->xefi_pag = xfs_perag_intent_get(mp, agno); |
7fef0c11 DW |
83 | } |
84 | ||
4d3226b6 | 85 | /* Release an active AG ref after some freeing work. */ |
7fef0c11 DW |
86 | static inline void |
87 | xfs_extent_free_put_group( | |
88 | struct xfs_extent_free_item *xefi) | |
89 | { | |
4d3226b6 | 90 | xfs_perag_intent_put(xefi->xefi_pag); |
7fef0c11 DW |
91 | } |
92 | ||
dc3bce02 DW |
93 | /* Process a free extent. */ |
94 | STATIC int | |
95 | xfs_extent_free_finish_item( | |
96 | struct xfs_trans *tp, | |
95e01274 | 97 | struct xfs_log_item *done, |
dc3bce02 | 98 | struct list_head *item, |
4371b480 | 99 | struct xfs_btree_cur **state) |
dc3bce02 | 100 | { |
6d72c6ea | 101 | struct xfs_owner_info oinfo = { }; |
36100197 | 102 | struct xfs_extent_free_item *xefi; |
42c1e5c1 | 103 | xfs_agblock_t agbno; |
dc3bce02 DW |
104 | int error; |
105 | ||
36100197 | 106 | xefi = container_of(item, struct xfs_extent_free_item, xefi_list); |
4d3226b6 | 107 | |
36100197 CM |
108 | oinfo.oi_owner = xefi->xefi_owner; |
109 | if (xefi->xefi_flags & XFS_EFI_ATTR_FORK) | |
6d72c6ea | 110 | oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK; |
36100197 | 111 | if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK) |
6d72c6ea | 112 | oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK; |
42c1e5c1 | 113 | |
42c1e5c1 | 114 | agbno = XFS_FSB_TO_AGBNO(tp->t_mountp, xefi->xefi_startblock); |
7fef0c11 DW |
115 | error = xfs_free_extent(tp, xefi->xefi_pag, agbno, |
116 | xefi->xefi_blockcount, &oinfo, XFS_AG_RESV_NONE); | |
42c1e5c1 | 117 | |
b9166aea DW |
118 | /* |
119 | * Don't free the XEFI if we need a new transaction to complete | |
120 | * processing of it. | |
121 | */ | |
122 | if (error == -EAGAIN) | |
123 | return error; | |
124 | ||
7fef0c11 | 125 | xfs_extent_free_put_group(xefi); |
36100197 | 126 | kmem_cache_free(xfs_extfree_item_cache, xefi); |
dc3bce02 DW |
127 | return error; |
128 | } | |
129 | ||
130 | /* Abort all pending EFIs. */ | |
131 | STATIC void | |
132 | xfs_extent_free_abort_intent( | |
18d0d657 | 133 | struct xfs_log_item *intent) |
dc3bce02 DW |
134 | { |
135 | } | |
136 | ||
137 | /* Cancel a free extent. */ | |
138 | STATIC void | |
139 | xfs_extent_free_cancel_item( | |
140 | struct list_head *item) | |
141 | { | |
36100197 | 142 | struct xfs_extent_free_item *xefi; |
dc3bce02 | 143 | |
36100197 | 144 | xefi = container_of(item, struct xfs_extent_free_item, xefi_list); |
7fef0c11 DW |
145 | |
146 | xfs_extent_free_put_group(xefi); | |
36100197 | 147 | kmem_cache_free(xfs_extfree_item_cache, xefi); |
dc3bce02 DW |
148 | } |
149 | ||
29ce8c42 | 150 | const struct xfs_defer_op_type xfs_extent_free_defer_type = { |
dc3bce02 DW |
151 | .create_intent = xfs_extent_free_create_intent, |
152 | .abort_intent = xfs_extent_free_abort_intent, | |
dc3bce02 DW |
153 | .create_done = xfs_extent_free_create_done, |
154 | .finish_item = xfs_extent_free_finish_item, | |
155 | .cancel_item = xfs_extent_free_cancel_item, | |
156 | }; | |
157 | ||
c8dc76e2 DW |
158 | /* |
159 | * AGFL blocks are accounted differently in the reserve pools and are not | |
160 | * inserted into the busy extent list. | |
161 | */ | |
162 | STATIC int | |
163 | xfs_agfl_free_finish_item( | |
164 | struct xfs_trans *tp, | |
95e01274 | 165 | struct xfs_log_item *done, |
c8dc76e2 | 166 | struct list_head *item, |
4371b480 | 167 | struct xfs_btree_cur **state) |
c8dc76e2 | 168 | { |
6d72c6ea | 169 | struct xfs_owner_info oinfo = { }; |
c8dc76e2 | 170 | struct xfs_mount *mp = tp->t_mountp; |
36100197 | 171 | struct xfs_extent_free_item *xefi; |
c8dc76e2 DW |
172 | struct xfs_buf *agbp; |
173 | int error; | |
c8dc76e2 DW |
174 | xfs_agblock_t agbno; |
175 | ||
36100197 | 176 | xefi = container_of(item, struct xfs_extent_free_item, xefi_list); |
4d3226b6 | 177 | |
36100197 | 178 | ASSERT(xefi->xefi_blockcount == 1); |
36100197 CM |
179 | agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock); |
180 | oinfo.oi_owner = xefi->xefi_owner; | |
c8dc76e2 | 181 | |
7fef0c11 | 182 | error = xfs_alloc_read_agf(xefi->xefi_pag, tp, 0, &agbp); |
c8dc76e2 | 183 | if (!error) |
7fef0c11 DW |
184 | error = xfs_free_agfl_block(tp, xefi->xefi_pag->pag_agno, |
185 | agbno, agbp, &oinfo); | |
186 | ||
187 | xfs_extent_free_put_group(xefi); | |
36100197 | 188 | kmem_cache_free(xfs_extfree_item_cache, xefi); |
c8dc76e2 DW |
189 | return error; |
190 | } | |
191 | ||
192 | /* sub-type with special handling for AGFL deferred frees */ | |
29ce8c42 | 193 | const struct xfs_defer_op_type xfs_agfl_free_defer_type = { |
c8dc76e2 DW |
194 | .create_intent = xfs_extent_free_create_intent, |
195 | .abort_intent = xfs_extent_free_abort_intent, | |
c8dc76e2 DW |
196 | .create_done = xfs_extent_free_create_done, |
197 | .finish_item = xfs_agfl_free_finish_item, | |
198 | .cancel_item = xfs_extent_free_cancel_item, | |
199 | }; | |
200 | ||
dc3bce02 DW |
201 | /* Reverse Mapping */ |
202 | ||
203 | /* Sort rmap intents by AG. */ | |
204 | static int | |
205 | xfs_rmap_update_diff_items( | |
206 | void *priv, | |
c6b593ee DW |
207 | const struct list_head *a, |
208 | const struct list_head *b) | |
dc3bce02 | 209 | { |
c6b593ee DW |
210 | const struct xfs_rmap_intent *ra; |
211 | const struct xfs_rmap_intent *rb; | |
dc3bce02 DW |
212 | |
213 | ra = container_of(a, struct xfs_rmap_intent, ri_list); | |
214 | rb = container_of(b, struct xfs_rmap_intent, ri_list); | |
818f0c29 DW |
215 | |
216 | return ra->ri_pag->pag_agno - rb->ri_pag->pag_agno; | |
dc3bce02 DW |
217 | } |
218 | ||
219 | /* Get an RUI. */ | |
18d0d657 | 220 | static struct xfs_log_item * |
dc3bce02 DW |
221 | xfs_rmap_update_create_intent( |
222 | struct xfs_trans *tp, | |
8d81fcd0 | 223 | struct list_head *items, |
74a7f5fa CH |
224 | unsigned int count, |
225 | bool sort) | |
dc3bce02 | 226 | { |
74a7f5fa CH |
227 | struct xfs_mount *mp = tp->t_mountp; |
228 | ||
229 | if (sort) | |
230 | list_sort(mp, items, xfs_rmap_update_diff_items); | |
dc3bce02 DW |
231 | return NULL; |
232 | } | |
233 | ||
dc3bce02 | 234 | /* Get an RUD so we can process all the deferred rmap updates. */ |
95e01274 | 235 | static struct xfs_log_item * |
dc3bce02 DW |
236 | xfs_rmap_update_create_done( |
237 | struct xfs_trans *tp, | |
18d0d657 | 238 | struct xfs_log_item *intent, |
dc3bce02 DW |
239 | unsigned int count) |
240 | { | |
241 | return NULL; | |
242 | } | |
243 | ||
4d3226b6 | 244 | /* Take an active ref to the AG containing the space we're rmapping. */ |
818f0c29 DW |
245 | void |
246 | xfs_rmap_update_get_group( | |
247 | struct xfs_mount *mp, | |
248 | struct xfs_rmap_intent *ri) | |
249 | { | |
250 | xfs_agnumber_t agno; | |
251 | ||
252 | agno = XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock); | |
4d3226b6 | 253 | ri->ri_pag = xfs_perag_intent_get(mp, agno); |
818f0c29 DW |
254 | } |
255 | ||
4d3226b6 | 256 | /* Release an active AG ref after finishing rmapping work. */ |
818f0c29 DW |
257 | static inline void |
258 | xfs_rmap_update_put_group( | |
259 | struct xfs_rmap_intent *ri) | |
260 | { | |
4d3226b6 | 261 | xfs_perag_intent_put(ri->ri_pag); |
818f0c29 DW |
262 | } |
263 | ||
dc3bce02 DW |
264 | /* Process a deferred rmap update. */ |
265 | STATIC int | |
266 | xfs_rmap_update_finish_item( | |
267 | struct xfs_trans *tp, | |
95e01274 | 268 | struct xfs_log_item *done, |
dc3bce02 | 269 | struct list_head *item, |
4371b480 | 270 | struct xfs_btree_cur **state) |
dc3bce02 | 271 | { |
74492d88 | 272 | struct xfs_rmap_intent *ri; |
dc3bce02 DW |
273 | int error; |
274 | ||
74492d88 | 275 | ri = container_of(item, struct xfs_rmap_intent, ri_list); |
818f0c29 | 276 | |
74492d88 | 277 | error = xfs_rmap_finish_one(tp, ri, state); |
818f0c29 DW |
278 | |
279 | xfs_rmap_update_put_group(ri); | |
74492d88 | 280 | kmem_cache_free(xfs_rmap_intent_cache, ri); |
dc3bce02 DW |
281 | return error; |
282 | } | |
283 | ||
dc3bce02 DW |
284 | /* Abort all pending RUIs. */ |
285 | STATIC void | |
286 | xfs_rmap_update_abort_intent( | |
18d0d657 | 287 | struct xfs_log_item *intent) |
dc3bce02 DW |
288 | { |
289 | } | |
290 | ||
291 | /* Cancel a deferred rmap update. */ | |
292 | STATIC void | |
293 | xfs_rmap_update_cancel_item( | |
294 | struct list_head *item) | |
295 | { | |
74492d88 | 296 | struct xfs_rmap_intent *ri; |
dc3bce02 | 297 | |
74492d88 | 298 | ri = container_of(item, struct xfs_rmap_intent, ri_list); |
818f0c29 DW |
299 | |
300 | xfs_rmap_update_put_group(ri); | |
74492d88 | 301 | kmem_cache_free(xfs_rmap_intent_cache, ri); |
dc3bce02 DW |
302 | } |
303 | ||
29ce8c42 | 304 | const struct xfs_defer_op_type xfs_rmap_update_defer_type = { |
dc3bce02 DW |
305 | .create_intent = xfs_rmap_update_create_intent, |
306 | .abort_intent = xfs_rmap_update_abort_intent, | |
dc3bce02 DW |
307 | .create_done = xfs_rmap_update_create_done, |
308 | .finish_item = xfs_rmap_update_finish_item, | |
4371b480 | 309 | .finish_cleanup = xfs_rmap_finish_one_cleanup, |
dc3bce02 DW |
310 | .cancel_item = xfs_rmap_update_cancel_item, |
311 | }; | |
312 | ||
cdc9cf25 DW |
313 | /* Reference Counting */ |
314 | ||
315 | /* Sort refcount intents by AG. */ | |
316 | static int | |
317 | xfs_refcount_update_diff_items( | |
318 | void *priv, | |
c6b593ee DW |
319 | const struct list_head *a, |
320 | const struct list_head *b) | |
cdc9cf25 | 321 | { |
c6b593ee DW |
322 | const struct xfs_refcount_intent *ra; |
323 | const struct xfs_refcount_intent *rb; | |
cdc9cf25 DW |
324 | |
325 | ra = container_of(a, struct xfs_refcount_intent, ri_list); | |
326 | rb = container_of(b, struct xfs_refcount_intent, ri_list); | |
b2c5c83d DW |
327 | |
328 | return ra->ri_pag->pag_agno - rb->ri_pag->pag_agno; | |
cdc9cf25 DW |
329 | } |
330 | ||
331 | /* Get an CUI. */ | |
18d0d657 | 332 | static struct xfs_log_item * |
cdc9cf25 DW |
333 | xfs_refcount_update_create_intent( |
334 | struct xfs_trans *tp, | |
8d81fcd0 | 335 | struct list_head *items, |
74a7f5fa CH |
336 | unsigned int count, |
337 | bool sort) | |
cdc9cf25 | 338 | { |
74a7f5fa CH |
339 | struct xfs_mount *mp = tp->t_mountp; |
340 | ||
341 | if (sort) | |
342 | list_sort(mp, items, xfs_refcount_update_diff_items); | |
cdc9cf25 DW |
343 | return NULL; |
344 | } | |
345 | ||
cdc9cf25 | 346 | /* Get an CUD so we can process all the deferred refcount updates. */ |
95e01274 | 347 | static struct xfs_log_item * |
cdc9cf25 DW |
348 | xfs_refcount_update_create_done( |
349 | struct xfs_trans *tp, | |
18d0d657 | 350 | struct xfs_log_item *intent, |
cdc9cf25 DW |
351 | unsigned int count) |
352 | { | |
353 | return NULL; | |
354 | } | |
355 | ||
4d3226b6 | 356 | /* Take an active ref to the AG containing the space we're refcounting. */ |
b2c5c83d DW |
357 | void |
358 | xfs_refcount_update_get_group( | |
359 | struct xfs_mount *mp, | |
360 | struct xfs_refcount_intent *ri) | |
361 | { | |
362 | xfs_agnumber_t agno; | |
363 | ||
364 | agno = XFS_FSB_TO_AGNO(mp, ri->ri_startblock); | |
4d3226b6 | 365 | ri->ri_pag = xfs_perag_intent_get(mp, agno); |
b2c5c83d DW |
366 | } |
367 | ||
4d3226b6 | 368 | /* Release an active AG ref after finishing refcounting work. */ |
b2c5c83d DW |
369 | static inline void |
370 | xfs_refcount_update_put_group( | |
371 | struct xfs_refcount_intent *ri) | |
372 | { | |
4d3226b6 | 373 | xfs_perag_intent_put(ri->ri_pag); |
b2c5c83d DW |
374 | } |
375 | ||
cdc9cf25 DW |
376 | /* Process a deferred refcount update. */ |
377 | STATIC int | |
378 | xfs_refcount_update_finish_item( | |
379 | struct xfs_trans *tp, | |
95e01274 | 380 | struct xfs_log_item *done, |
cdc9cf25 | 381 | struct list_head *item, |
4371b480 | 382 | struct xfs_btree_cur **state) |
cdc9cf25 | 383 | { |
f72f073f | 384 | struct xfs_refcount_intent *ri; |
cdc9cf25 DW |
385 | int error; |
386 | ||
f72f073f DW |
387 | ri = container_of(item, struct xfs_refcount_intent, ri_list); |
388 | error = xfs_refcount_finish_one(tp, ri, state); | |
389 | ||
cdc9cf25 | 390 | /* Did we run out of reservation? Requeue what we didn't finish. */ |
f72f073f DW |
391 | if (!error && ri->ri_blockcount > 0) { |
392 | ASSERT(ri->ri_type == XFS_REFCOUNT_INCREASE || | |
393 | ri->ri_type == XFS_REFCOUNT_DECREASE); | |
cdc9cf25 DW |
394 | return -EAGAIN; |
395 | } | |
b2c5c83d DW |
396 | |
397 | xfs_refcount_update_put_group(ri); | |
f72f073f | 398 | kmem_cache_free(xfs_refcount_intent_cache, ri); |
cdc9cf25 DW |
399 | return error; |
400 | } | |
401 | ||
cdc9cf25 DW |
402 | /* Abort all pending CUIs. */ |
403 | STATIC void | |
404 | xfs_refcount_update_abort_intent( | |
18d0d657 | 405 | struct xfs_log_item *intent) |
cdc9cf25 DW |
406 | { |
407 | } | |
408 | ||
409 | /* Cancel a deferred refcount update. */ | |
410 | STATIC void | |
411 | xfs_refcount_update_cancel_item( | |
412 | struct list_head *item) | |
413 | { | |
f72f073f | 414 | struct xfs_refcount_intent *ri; |
cdc9cf25 | 415 | |
f72f073f | 416 | ri = container_of(item, struct xfs_refcount_intent, ri_list); |
b2c5c83d DW |
417 | |
418 | xfs_refcount_update_put_group(ri); | |
f72f073f | 419 | kmem_cache_free(xfs_refcount_intent_cache, ri); |
cdc9cf25 DW |
420 | } |
421 | ||
29ce8c42 | 422 | const struct xfs_defer_op_type xfs_refcount_update_defer_type = { |
cdc9cf25 DW |
423 | .create_intent = xfs_refcount_update_create_intent, |
424 | .abort_intent = xfs_refcount_update_abort_intent, | |
cdc9cf25 DW |
425 | .create_done = xfs_refcount_update_create_done, |
426 | .finish_item = xfs_refcount_update_finish_item, | |
4371b480 | 427 | .finish_cleanup = xfs_refcount_finish_one_cleanup, |
cdc9cf25 DW |
428 | .cancel_item = xfs_refcount_update_cancel_item, |
429 | }; | |
430 | ||
f8f8c8a0 DW |
431 | /* Inode Block Mapping */ |
432 | ||
433 | /* Sort bmap intents by inode. */ | |
434 | static int | |
435 | xfs_bmap_update_diff_items( | |
436 | void *priv, | |
c6b593ee DW |
437 | const struct list_head *a, |
438 | const struct list_head *b) | |
f8f8c8a0 | 439 | { |
c6b593ee DW |
440 | const struct xfs_bmap_intent *ba; |
441 | const struct xfs_bmap_intent *bb; | |
f8f8c8a0 DW |
442 | |
443 | ba = container_of(a, struct xfs_bmap_intent, bi_list); | |
444 | bb = container_of(b, struct xfs_bmap_intent, bi_list); | |
445 | return ba->bi_owner->i_ino - bb->bi_owner->i_ino; | |
446 | } | |
447 | ||
448 | /* Get an BUI. */ | |
18d0d657 | 449 | static struct xfs_log_item * |
f8f8c8a0 DW |
450 | xfs_bmap_update_create_intent( |
451 | struct xfs_trans *tp, | |
8d81fcd0 | 452 | struct list_head *items, |
74a7f5fa CH |
453 | unsigned int count, |
454 | bool sort) | |
f8f8c8a0 | 455 | { |
74a7f5fa CH |
456 | struct xfs_mount *mp = tp->t_mountp; |
457 | ||
458 | if (sort) | |
459 | list_sort(mp, items, xfs_bmap_update_diff_items); | |
f8f8c8a0 DW |
460 | return NULL; |
461 | } | |
462 | ||
f8f8c8a0 | 463 | /* Get an BUD so we can process all the deferred rmap updates. */ |
95e01274 | 464 | static struct xfs_log_item * |
f8f8c8a0 DW |
465 | xfs_bmap_update_create_done( |
466 | struct xfs_trans *tp, | |
18d0d657 | 467 | struct xfs_log_item *intent, |
f8f8c8a0 DW |
468 | unsigned int count) |
469 | { | |
470 | return NULL; | |
471 | } | |
472 | ||
4d3226b6 | 473 | /* Take an active ref to the AG containing the space we're mapping. */ |
32debad7 DW |
474 | void |
475 | xfs_bmap_update_get_group( | |
476 | struct xfs_mount *mp, | |
477 | struct xfs_bmap_intent *bi) | |
478 | { | |
479 | xfs_agnumber_t agno; | |
480 | ||
481 | agno = XFS_FSB_TO_AGNO(mp, bi->bi_bmap.br_startblock); | |
4d3226b6 DW |
482 | |
483 | /* | |
484 | * Bump the intent count on behalf of the deferred rmap and refcount | |
485 | * intent items that that we can queue when we finish this bmap work. | |
486 | * This new intent item will bump the intent count before the bmap | |
487 | * intent drops the intent count, ensuring that the intent count | |
488 | * remains nonzero across the transaction roll. | |
489 | */ | |
490 | bi->bi_pag = xfs_perag_intent_get(mp, agno); | |
32debad7 DW |
491 | } |
492 | ||
4d3226b6 | 493 | /* Release an active AG ref after finishing mapping work. */ |
32debad7 DW |
494 | static inline void |
495 | xfs_bmap_update_put_group( | |
496 | struct xfs_bmap_intent *bi) | |
497 | { | |
4d3226b6 | 498 | xfs_perag_intent_put(bi->bi_pag); |
32debad7 DW |
499 | } |
500 | ||
f8f8c8a0 DW |
501 | /* Process a deferred rmap update. */ |
502 | STATIC int | |
503 | xfs_bmap_update_finish_item( | |
504 | struct xfs_trans *tp, | |
95e01274 | 505 | struct xfs_log_item *done, |
f8f8c8a0 | 506 | struct list_head *item, |
4371b480 | 507 | struct xfs_btree_cur **state) |
f8f8c8a0 | 508 | { |
afe1175f | 509 | struct xfs_bmap_intent *bi; |
f8f8c8a0 DW |
510 | int error; |
511 | ||
afe1175f DW |
512 | bi = container_of(item, struct xfs_bmap_intent, bi_list); |
513 | error = xfs_bmap_finish_one(tp, bi); | |
514 | if (!error && bi->bi_bmap.br_blockcount > 0) { | |
515 | ASSERT(bi->bi_type == XFS_BMAP_UNMAP); | |
594956fa DW |
516 | return -EAGAIN; |
517 | } | |
32debad7 DW |
518 | |
519 | xfs_bmap_update_put_group(bi); | |
afe1175f | 520 | kmem_cache_free(xfs_bmap_intent_cache, bi); |
f8f8c8a0 DW |
521 | return error; |
522 | } | |
523 | ||
524 | /* Abort all pending BUIs. */ | |
525 | STATIC void | |
526 | xfs_bmap_update_abort_intent( | |
18d0d657 | 527 | struct xfs_log_item *intent) |
f8f8c8a0 DW |
528 | { |
529 | } | |
530 | ||
531 | /* Cancel a deferred rmap update. */ | |
532 | STATIC void | |
533 | xfs_bmap_update_cancel_item( | |
534 | struct list_head *item) | |
535 | { | |
afe1175f | 536 | struct xfs_bmap_intent *bi; |
f8f8c8a0 | 537 | |
afe1175f | 538 | bi = container_of(item, struct xfs_bmap_intent, bi_list); |
32debad7 DW |
539 | |
540 | xfs_bmap_update_put_group(bi); | |
afe1175f | 541 | kmem_cache_free(xfs_bmap_intent_cache, bi); |
f8f8c8a0 DW |
542 | } |
543 | ||
29ce8c42 | 544 | const struct xfs_defer_op_type xfs_bmap_update_defer_type = { |
f8f8c8a0 DW |
545 | .create_intent = xfs_bmap_update_create_intent, |
546 | .abort_intent = xfs_bmap_update_abort_intent, | |
f8f8c8a0 DW |
547 | .create_done = xfs_bmap_update_create_done, |
548 | .finish_item = xfs_bmap_update_finish_item, | |
549 | .cancel_item = xfs_bmap_update_cancel_item, | |
550 | }; | |
c6ad4bc1 AH |
551 | |
552 | /* Get an ATTRI. */ | |
553 | static struct xfs_log_item * | |
554 | xfs_attr_create_intent( | |
555 | struct xfs_trans *tp, | |
556 | struct list_head *items, | |
557 | unsigned int count, | |
558 | bool sort) | |
559 | { | |
560 | return NULL; | |
561 | } | |
562 | ||
563 | /* Abort all pending ATTRs. */ | |
564 | static void | |
565 | xfs_attr_abort_intent( | |
566 | struct xfs_log_item *intent) | |
567 | { | |
568 | } | |
569 | ||
570 | /* Get an ATTRD so we can process all the attrs. */ | |
571 | static struct xfs_log_item * | |
572 | xfs_attr_create_done( | |
573 | struct xfs_trans *tp, | |
574 | struct xfs_log_item *intent, | |
575 | unsigned int count) | |
576 | { | |
577 | return NULL; | |
578 | } | |
579 | ||
5b391189 DW |
580 | static inline void |
581 | xfs_attr_free_item( | |
eff5933f | 582 | struct xfs_attr_intent *attr) |
5b391189 DW |
583 | { |
584 | if (attr->xattri_da_state) | |
585 | xfs_da_state_free(attr->xattri_da_state); | |
3b0ca632 DW |
586 | if (attr->xattri_da_args->op_flags & XFS_DA_OP_RECOVERY) |
587 | kmem_free(attr); | |
588 | else | |
589 | kmem_cache_free(xfs_attr_intent_cache, attr); | |
5b391189 DW |
590 | } |
591 | ||
c6ad4bc1 AH |
592 | /* Process an attr. */ |
593 | static int | |
594 | xfs_attr_finish_item( | |
595 | struct xfs_trans *tp, | |
596 | struct xfs_log_item *done, | |
597 | struct list_head *item, | |
598 | struct xfs_btree_cur **state) | |
599 | { | |
eff5933f | 600 | struct xfs_attr_intent *attr; |
c6ad4bc1 | 601 | int error; |
c6ad4bc1 | 602 | struct xfs_da_args *args; |
c6ad4bc1 | 603 | |
eff5933f | 604 | attr = container_of(item, struct xfs_attr_intent, xattri_list); |
a951e052 | 605 | args = attr->xattri_da_args; |
c6ad4bc1 AH |
606 | |
607 | /* | |
608 | * Always reset trans after EAGAIN cycle | |
609 | * since the transaction is new | |
610 | */ | |
611 | args->trans = tp; | |
612 | ||
a2832031 AH |
613 | if (XFS_TEST_ERROR(false, args->dp->i_mount, XFS_ERRTAG_LARP)) { |
614 | error = -EIO; | |
615 | goto out; | |
616 | } | |
617 | ||
fc32183a DC |
618 | error = xfs_attr_set_iter(attr); |
619 | if (!error && attr->xattri_dela_state != XFS_DAS_DONE) | |
620 | error = -EAGAIN; | |
a2832031 | 621 | out: |
c6ad4bc1 | 622 | if (error != -EAGAIN) |
5b391189 | 623 | xfs_attr_free_item(attr); |
c6ad4bc1 AH |
624 | |
625 | return error; | |
626 | } | |
627 | ||
628 | /* Cancel an attr */ | |
629 | static void | |
630 | xfs_attr_cancel_item( | |
631 | struct list_head *item) | |
632 | { | |
eff5933f | 633 | struct xfs_attr_intent *attr; |
c6ad4bc1 | 634 | |
eff5933f | 635 | attr = container_of(item, struct xfs_attr_intent, xattri_list); |
5b391189 | 636 | xfs_attr_free_item(attr); |
c6ad4bc1 AH |
637 | } |
638 | ||
639 | const struct xfs_defer_op_type xfs_attr_defer_type = { | |
640 | .max_items = 1, | |
641 | .create_intent = xfs_attr_create_intent, | |
642 | .abort_intent = xfs_attr_abort_intent, | |
643 | .create_done = xfs_attr_create_done, | |
644 | .finish_item = xfs_attr_finish_item, | |
645 | .cancel_item = xfs_attr_cancel_item, | |
646 | }; |