1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2016 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
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_mount.h"
13 #include "xfs_defer.h"
14 #include "xfs_trans.h"
15 #include "xfs_trans_priv.h"
16 #include "xfs_bmap_item.h"
17 #include "xfs_alloc.h"
19 #include "xfs_inode.h"
22 * This routine is called to allocate a "bmap update done"
25 struct xfs_bud_log_item
*
28 struct xfs_bui_log_item
*buip
)
30 struct xfs_bud_log_item
*budp
;
32 budp
= xfs_bud_init(tp
->t_mountp
, buip
);
33 xfs_trans_add_item(tp
, &budp
->bud_item
);
38 * Finish an bmap update and log it to the BUD. Note that the
39 * transaction is marked dirty regardless of whether the bmap update
40 * succeeds or fails to support the BUI/BUD lifecycle rules.
43 xfs_trans_log_finish_bmap_update(
45 struct xfs_bud_log_item
*budp
,
46 enum xfs_bmap_intent_type type
,
49 xfs_fileoff_t startoff
,
50 xfs_fsblock_t startblock
,
51 xfs_filblks_t
*blockcount
,
56 error
= xfs_bmap_finish_one(tp
, ip
, type
, whichfork
, startoff
,
57 startblock
, blockcount
, state
);
60 * Mark the transaction dirty, even on error. This ensures the
61 * transaction is aborted, which:
63 * 1.) releases the BUI and frees the BUD
64 * 2.) shuts down the filesystem
66 tp
->t_flags
|= XFS_TRANS_DIRTY
;
67 set_bit(XFS_LI_DIRTY
, &budp
->bud_item
.li_flags
);
72 /* Sort bmap intents by inode. */
74 xfs_bmap_update_diff_items(
79 struct xfs_bmap_intent
*ba
;
80 struct xfs_bmap_intent
*bb
;
82 ba
= container_of(a
, struct xfs_bmap_intent
, bi_list
);
83 bb
= container_of(b
, struct xfs_bmap_intent
, bi_list
);
84 return ba
->bi_owner
->i_ino
- bb
->bi_owner
->i_ino
;
89 xfs_bmap_update_create_intent(
93 struct xfs_bui_log_item
*buip
;
95 ASSERT(count
== XFS_BUI_MAX_FAST_EXTENTS
);
98 buip
= xfs_bui_init(tp
->t_mountp
);
102 * Get a log_item_desc to point at the new item.
104 xfs_trans_add_item(tp
, &buip
->bui_item
);
108 /* Set the map extent flags for this mapping. */
110 xfs_trans_set_bmap_flags(
111 struct xfs_map_extent
*bmap
,
112 enum xfs_bmap_intent_type type
,
120 bmap
->me_flags
= type
;
125 if (state
== XFS_EXT_UNWRITTEN
)
126 bmap
->me_flags
|= XFS_BMAP_EXTENT_UNWRITTEN
;
127 if (whichfork
== XFS_ATTR_FORK
)
128 bmap
->me_flags
|= XFS_BMAP_EXTENT_ATTR_FORK
;
131 /* Log bmap updates in the intent item. */
133 xfs_bmap_update_log_item(
134 struct xfs_trans
*tp
,
136 struct list_head
*item
)
138 struct xfs_bui_log_item
*buip
= intent
;
139 struct xfs_bmap_intent
*bmap
;
141 struct xfs_map_extent
*map
;
143 bmap
= container_of(item
, struct xfs_bmap_intent
, bi_list
);
145 tp
->t_flags
|= XFS_TRANS_DIRTY
;
146 set_bit(XFS_LI_DIRTY
, &buip
->bui_item
.li_flags
);
149 * atomic_inc_return gives us the value after the increment;
150 * we want to use it as an array index so we need to subtract 1 from
153 next_extent
= atomic_inc_return(&buip
->bui_next_extent
) - 1;
154 ASSERT(next_extent
< buip
->bui_format
.bui_nextents
);
155 map
= &buip
->bui_format
.bui_extents
[next_extent
];
156 map
->me_owner
= bmap
->bi_owner
->i_ino
;
157 map
->me_startblock
= bmap
->bi_bmap
.br_startblock
;
158 map
->me_startoff
= bmap
->bi_bmap
.br_startoff
;
159 map
->me_len
= bmap
->bi_bmap
.br_blockcount
;
160 xfs_trans_set_bmap_flags(map
, bmap
->bi_type
, bmap
->bi_whichfork
,
161 bmap
->bi_bmap
.br_state
);
164 /* Get an BUD so we can process all the deferred rmap updates. */
166 xfs_bmap_update_create_done(
167 struct xfs_trans
*tp
,
171 return xfs_trans_get_bud(tp
, intent
);
174 /* Process a deferred rmap update. */
176 xfs_bmap_update_finish_item(
177 struct xfs_trans
*tp
,
178 struct list_head
*item
,
182 struct xfs_bmap_intent
*bmap
;
186 bmap
= container_of(item
, struct xfs_bmap_intent
, bi_list
);
187 count
= bmap
->bi_bmap
.br_blockcount
;
188 error
= xfs_trans_log_finish_bmap_update(tp
, done_item
,
190 bmap
->bi_owner
, bmap
->bi_whichfork
,
191 bmap
->bi_bmap
.br_startoff
,
192 bmap
->bi_bmap
.br_startblock
,
194 bmap
->bi_bmap
.br_state
);
195 if (!error
&& count
> 0) {
196 ASSERT(bmap
->bi_type
== XFS_BMAP_UNMAP
);
197 bmap
->bi_bmap
.br_blockcount
= count
;
204 /* Abort all pending BUIs. */
206 xfs_bmap_update_abort_intent(
209 xfs_bui_release(intent
);
212 /* Cancel a deferred rmap update. */
214 xfs_bmap_update_cancel_item(
215 struct list_head
*item
)
217 struct xfs_bmap_intent
*bmap
;
219 bmap
= container_of(item
, struct xfs_bmap_intent
, bi_list
);
223 static const struct xfs_defer_op_type xfs_bmap_update_defer_type
= {
224 .type
= XFS_DEFER_OPS_TYPE_BMAP
,
225 .max_items
= XFS_BUI_MAX_FAST_EXTENTS
,
226 .diff_items
= xfs_bmap_update_diff_items
,
227 .create_intent
= xfs_bmap_update_create_intent
,
228 .abort_intent
= xfs_bmap_update_abort_intent
,
229 .log_item
= xfs_bmap_update_log_item
,
230 .create_done
= xfs_bmap_update_create_done
,
231 .finish_item
= xfs_bmap_update_finish_item
,
232 .cancel_item
= xfs_bmap_update_cancel_item
,
235 /* Register the deferred op type. */
237 xfs_bmap_update_init_defer_op(void)
239 xfs_defer_init_op_type(&xfs_bmap_update_defer_type
);