perf intel-pt: Factor out intel_pt_8b_tsc()
[linux/fpc-iii.git] / fs / xfs / xfs_trans_bmap.c
blobe1c7d55b32c37b1db0b15c131937eda73c89396d
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2016 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 */
6 #include "xfs.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_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"
18 #include "xfs_bmap.h"
19 #include "xfs_inode.h"
22 * This routine is called to allocate a "bmap update done"
23 * log item.
25 struct xfs_bud_log_item *
26 xfs_trans_get_bud(
27 struct xfs_trans *tp,
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);
34 return budp;
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.
42 int
43 xfs_trans_log_finish_bmap_update(
44 struct xfs_trans *tp,
45 struct xfs_bud_log_item *budp,
46 enum xfs_bmap_intent_type type,
47 struct xfs_inode *ip,
48 int whichfork,
49 xfs_fileoff_t startoff,
50 xfs_fsblock_t startblock,
51 xfs_filblks_t *blockcount,
52 xfs_exntst_t state)
54 int error;
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);
69 return error;
72 /* Sort bmap intents by inode. */
73 static int
74 xfs_bmap_update_diff_items(
75 void *priv,
76 struct list_head *a,
77 struct list_head *b)
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;
87 /* Get an BUI. */
88 STATIC void *
89 xfs_bmap_update_create_intent(
90 struct xfs_trans *tp,
91 unsigned int count)
93 struct xfs_bui_log_item *buip;
95 ASSERT(count == XFS_BUI_MAX_FAST_EXTENTS);
96 ASSERT(tp != NULL);
98 buip = xfs_bui_init(tp->t_mountp);
99 ASSERT(buip != NULL);
102 * Get a log_item_desc to point at the new item.
104 xfs_trans_add_item(tp, &buip->bui_item);
105 return buip;
108 /* Set the map extent flags for this mapping. */
109 static void
110 xfs_trans_set_bmap_flags(
111 struct xfs_map_extent *bmap,
112 enum xfs_bmap_intent_type type,
113 int whichfork,
114 xfs_exntst_t state)
116 bmap->me_flags = 0;
117 switch (type) {
118 case XFS_BMAP_MAP:
119 case XFS_BMAP_UNMAP:
120 bmap->me_flags = type;
121 break;
122 default:
123 ASSERT(0);
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. */
132 STATIC void
133 xfs_bmap_update_log_item(
134 struct xfs_trans *tp,
135 void *intent,
136 struct list_head *item)
138 struct xfs_bui_log_item *buip = intent;
139 struct xfs_bmap_intent *bmap;
140 uint next_extent;
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
151 * it.
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. */
165 STATIC void *
166 xfs_bmap_update_create_done(
167 struct xfs_trans *tp,
168 void *intent,
169 unsigned int count)
171 return xfs_trans_get_bud(tp, intent);
174 /* Process a deferred rmap update. */
175 STATIC int
176 xfs_bmap_update_finish_item(
177 struct xfs_trans *tp,
178 struct list_head *item,
179 void *done_item,
180 void **state)
182 struct xfs_bmap_intent *bmap;
183 xfs_filblks_t count;
184 int error;
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,
189 bmap->bi_type,
190 bmap->bi_owner, bmap->bi_whichfork,
191 bmap->bi_bmap.br_startoff,
192 bmap->bi_bmap.br_startblock,
193 &count,
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;
198 return -EAGAIN;
200 kmem_free(bmap);
201 return error;
204 /* Abort all pending BUIs. */
205 STATIC void
206 xfs_bmap_update_abort_intent(
207 void *intent)
209 xfs_bui_release(intent);
212 /* Cancel a deferred rmap update. */
213 STATIC void
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);
220 kmem_free(bmap);
223 const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
224 .max_items = XFS_BUI_MAX_FAST_EXTENTS,
225 .diff_items = xfs_bmap_update_diff_items,
226 .create_intent = xfs_bmap_update_create_intent,
227 .abort_intent = xfs_bmap_update_abort_intent,
228 .log_item = xfs_bmap_update_log_item,
229 .create_done = xfs_bmap_update_create_done,
230 .finish_item = xfs_bmap_update_finish_item,
231 .cancel_item = xfs_bmap_update_cancel_item,