2 * Copyright (C) 2016 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it would be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "xfs_shared.h"
23 #include "xfs_format.h"
24 #include "xfs_log_format.h"
25 #include "xfs_trans_resv.h"
26 #include "xfs_mount.h"
27 #include "xfs_defer.h"
28 #include "xfs_trans.h"
29 #include "xfs_trans_priv.h"
30 #include "xfs_bmap_item.h"
31 #include "xfs_alloc.h"
33 #include "xfs_inode.h"
36 * This routine is called to allocate a "bmap update done"
39 struct xfs_bud_log_item
*
42 struct xfs_bui_log_item
*buip
)
44 struct xfs_bud_log_item
*budp
;
46 budp
= xfs_bud_init(tp
->t_mountp
, buip
);
47 xfs_trans_add_item(tp
, &budp
->bud_item
);
52 * Finish an bmap update and log it to the BUD. Note that the
53 * transaction is marked dirty regardless of whether the bmap update
54 * succeeds or fails to support the BUI/BUD lifecycle rules.
57 xfs_trans_log_finish_bmap_update(
59 struct xfs_bud_log_item
*budp
,
60 struct xfs_defer_ops
*dop
,
61 enum xfs_bmap_intent_type type
,
64 xfs_fileoff_t startoff
,
65 xfs_fsblock_t startblock
,
66 xfs_filblks_t
*blockcount
,
71 error
= xfs_bmap_finish_one(tp
, dop
, ip
, type
, whichfork
, startoff
,
72 startblock
, blockcount
, state
);
75 * Mark the transaction dirty, even on error. This ensures the
76 * transaction is aborted, which:
78 * 1.) releases the BUI and frees the BUD
79 * 2.) shuts down the filesystem
81 tp
->t_flags
|= XFS_TRANS_DIRTY
;
82 budp
->bud_item
.li_desc
->lid_flags
|= XFS_LID_DIRTY
;
87 /* Sort bmap intents by inode. */
89 xfs_bmap_update_diff_items(
94 struct xfs_bmap_intent
*ba
;
95 struct xfs_bmap_intent
*bb
;
97 ba
= container_of(a
, struct xfs_bmap_intent
, bi_list
);
98 bb
= container_of(b
, struct xfs_bmap_intent
, bi_list
);
99 return ba
->bi_owner
->i_ino
- bb
->bi_owner
->i_ino
;
104 xfs_bmap_update_create_intent(
105 struct xfs_trans
*tp
,
108 struct xfs_bui_log_item
*buip
;
110 ASSERT(count
== XFS_BUI_MAX_FAST_EXTENTS
);
113 buip
= xfs_bui_init(tp
->t_mountp
);
114 ASSERT(buip
!= NULL
);
117 * Get a log_item_desc to point at the new item.
119 xfs_trans_add_item(tp
, &buip
->bui_item
);
123 /* Set the map extent flags for this mapping. */
125 xfs_trans_set_bmap_flags(
126 struct xfs_map_extent
*bmap
,
127 enum xfs_bmap_intent_type type
,
135 bmap
->me_flags
= type
;
140 if (state
== XFS_EXT_UNWRITTEN
)
141 bmap
->me_flags
|= XFS_BMAP_EXTENT_UNWRITTEN
;
142 if (whichfork
== XFS_ATTR_FORK
)
143 bmap
->me_flags
|= XFS_BMAP_EXTENT_ATTR_FORK
;
146 /* Log bmap updates in the intent item. */
148 xfs_bmap_update_log_item(
149 struct xfs_trans
*tp
,
151 struct list_head
*item
)
153 struct xfs_bui_log_item
*buip
= intent
;
154 struct xfs_bmap_intent
*bmap
;
156 struct xfs_map_extent
*map
;
158 bmap
= container_of(item
, struct xfs_bmap_intent
, bi_list
);
160 tp
->t_flags
|= XFS_TRANS_DIRTY
;
161 buip
->bui_item
.li_desc
->lid_flags
|= XFS_LID_DIRTY
;
164 * atomic_inc_return gives us the value after the increment;
165 * we want to use it as an array index so we need to subtract 1 from
168 next_extent
= atomic_inc_return(&buip
->bui_next_extent
) - 1;
169 ASSERT(next_extent
< buip
->bui_format
.bui_nextents
);
170 map
= &buip
->bui_format
.bui_extents
[next_extent
];
171 map
->me_owner
= bmap
->bi_owner
->i_ino
;
172 map
->me_startblock
= bmap
->bi_bmap
.br_startblock
;
173 map
->me_startoff
= bmap
->bi_bmap
.br_startoff
;
174 map
->me_len
= bmap
->bi_bmap
.br_blockcount
;
175 xfs_trans_set_bmap_flags(map
, bmap
->bi_type
, bmap
->bi_whichfork
,
176 bmap
->bi_bmap
.br_state
);
179 /* Get an BUD so we can process all the deferred rmap updates. */
181 xfs_bmap_update_create_done(
182 struct xfs_trans
*tp
,
186 return xfs_trans_get_bud(tp
, intent
);
189 /* Process a deferred rmap update. */
191 xfs_bmap_update_finish_item(
192 struct xfs_trans
*tp
,
193 struct xfs_defer_ops
*dop
,
194 struct list_head
*item
,
198 struct xfs_bmap_intent
*bmap
;
202 bmap
= container_of(item
, struct xfs_bmap_intent
, bi_list
);
203 count
= bmap
->bi_bmap
.br_blockcount
;
204 error
= xfs_trans_log_finish_bmap_update(tp
, done_item
, dop
,
206 bmap
->bi_owner
, bmap
->bi_whichfork
,
207 bmap
->bi_bmap
.br_startoff
,
208 bmap
->bi_bmap
.br_startblock
,
210 bmap
->bi_bmap
.br_state
);
211 if (!error
&& count
> 0) {
212 ASSERT(bmap
->bi_type
== XFS_BMAP_UNMAP
);
213 bmap
->bi_bmap
.br_blockcount
= count
;
220 /* Abort all pending BUIs. */
222 xfs_bmap_update_abort_intent(
225 xfs_bui_release(intent
);
228 /* Cancel a deferred rmap update. */
230 xfs_bmap_update_cancel_item(
231 struct list_head
*item
)
233 struct xfs_bmap_intent
*bmap
;
235 bmap
= container_of(item
, struct xfs_bmap_intent
, bi_list
);
239 static const struct xfs_defer_op_type xfs_bmap_update_defer_type
= {
240 .type
= XFS_DEFER_OPS_TYPE_BMAP
,
241 .max_items
= XFS_BUI_MAX_FAST_EXTENTS
,
242 .diff_items
= xfs_bmap_update_diff_items
,
243 .create_intent
= xfs_bmap_update_create_intent
,
244 .abort_intent
= xfs_bmap_update_abort_intent
,
245 .log_item
= xfs_bmap_update_log_item
,
246 .create_done
= xfs_bmap_update_create_done
,
247 .finish_item
= xfs_bmap_update_finish_item
,
248 .cancel_item
= xfs_bmap_update_cancel_item
,
251 /* Register the deferred op type. */
253 xfs_bmap_update_init_defer_op(void)
255 xfs_defer_init_op_type(&xfs_bmap_update_defer_type
);