blob: a15a5cd867f9b943ead844efb8da4095e6527f51 [file] [log] [blame]
Dave Chinner0b61f8a2018-06-05 19:42:14 -07001// SPDX-License-Identifier: GPL-2.0+
Darrick J. Wong77d61fe2016-10-03 09:11:26 -07002/*
3 * Copyright (C) 2016 Oracle. All Rights Reserved.
Darrick J. Wong77d61fe2016-10-03 09:11:26 -07004 * Author: Darrick J. Wong <darrick.wong@oracle.com>
Darrick J. Wong77d61fe2016-10-03 09:11:26 -07005 */
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"
20
21/*
22 * This routine is called to allocate a "bmap update done"
23 * log item.
24 */
25struct xfs_bud_log_item *
26xfs_trans_get_bud(
27 struct xfs_trans *tp,
28 struct xfs_bui_log_item *buip)
29{
30 struct xfs_bud_log_item *budp;
31
32 budp = xfs_bud_init(tp->t_mountp, buip);
33 xfs_trans_add_item(tp, &budp->bud_item);
34 return budp;
35}
36
37/*
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.
41 */
42int
43xfs_trans_log_finish_bmap_update(
44 struct xfs_trans *tp,
45 struct xfs_bud_log_item *budp,
46 struct xfs_defer_ops *dop,
47 enum xfs_bmap_intent_type type,
48 struct xfs_inode *ip,
49 int whichfork,
50 xfs_fileoff_t startoff,
51 xfs_fsblock_t startblock,
Darrick J. Wonge1a4e372017-06-14 21:25:57 -070052 xfs_filblks_t *blockcount,
Darrick J. Wong77d61fe2016-10-03 09:11:26 -070053 xfs_exntst_t state)
54{
55 int error;
56
Darrick J. Wong9f3afb52016-10-03 09:11:28 -070057 error = xfs_bmap_finish_one(tp, dop, ip, type, whichfork, startoff,
58 startblock, blockcount, state);
Darrick J. Wong77d61fe2016-10-03 09:11:26 -070059
60 /*
61 * Mark the transaction dirty, even on error. This ensures the
62 * transaction is aborted, which:
63 *
64 * 1.) releases the BUI and frees the BUD
65 * 2.) shuts down the filesystem
66 */
67 tp->t_flags |= XFS_TRANS_DIRTY;
Dave Chinnere6631f82018-05-09 07:49:37 -070068 set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
Darrick J. Wong77d61fe2016-10-03 09:11:26 -070069
70 return error;
71}
Darrick J. Wong9f3afb52016-10-03 09:11:28 -070072
73/* Sort bmap intents by inode. */
74static int
75xfs_bmap_update_diff_items(
76 void *priv,
77 struct list_head *a,
78 struct list_head *b)
79{
80 struct xfs_bmap_intent *ba;
81 struct xfs_bmap_intent *bb;
82
83 ba = container_of(a, struct xfs_bmap_intent, bi_list);
84 bb = container_of(b, struct xfs_bmap_intent, bi_list);
85 return ba->bi_owner->i_ino - bb->bi_owner->i_ino;
86}
87
88/* Get an BUI. */
89STATIC void *
90xfs_bmap_update_create_intent(
91 struct xfs_trans *tp,
92 unsigned int count)
93{
94 struct xfs_bui_log_item *buip;
95
96 ASSERT(count == XFS_BUI_MAX_FAST_EXTENTS);
97 ASSERT(tp != NULL);
98
99 buip = xfs_bui_init(tp->t_mountp);
100 ASSERT(buip != NULL);
101
102 /*
103 * Get a log_item_desc to point at the new item.
104 */
105 xfs_trans_add_item(tp, &buip->bui_item);
106 return buip;
107}
108
109/* Set the map extent flags for this mapping. */
110static void
111xfs_trans_set_bmap_flags(
112 struct xfs_map_extent *bmap,
113 enum xfs_bmap_intent_type type,
114 int whichfork,
115 xfs_exntst_t state)
116{
117 bmap->me_flags = 0;
118 switch (type) {
119 case XFS_BMAP_MAP:
120 case XFS_BMAP_UNMAP:
121 bmap->me_flags = type;
122 break;
123 default:
124 ASSERT(0);
125 }
126 if (state == XFS_EXT_UNWRITTEN)
127 bmap->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN;
128 if (whichfork == XFS_ATTR_FORK)
129 bmap->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK;
130}
131
132/* Log bmap updates in the intent item. */
133STATIC void
134xfs_bmap_update_log_item(
135 struct xfs_trans *tp,
136 void *intent,
137 struct list_head *item)
138{
139 struct xfs_bui_log_item *buip = intent;
140 struct xfs_bmap_intent *bmap;
141 uint next_extent;
142 struct xfs_map_extent *map;
143
144 bmap = container_of(item, struct xfs_bmap_intent, bi_list);
145
146 tp->t_flags |= XFS_TRANS_DIRTY;
Dave Chinnere6631f82018-05-09 07:49:37 -0700147 set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
Darrick J. Wong9f3afb52016-10-03 09:11:28 -0700148
149 /*
150 * atomic_inc_return gives us the value after the increment;
151 * we want to use it as an array index so we need to subtract 1 from
152 * it.
153 */
154 next_extent = atomic_inc_return(&buip->bui_next_extent) - 1;
155 ASSERT(next_extent < buip->bui_format.bui_nextents);
156 map = &buip->bui_format.bui_extents[next_extent];
157 map->me_owner = bmap->bi_owner->i_ino;
158 map->me_startblock = bmap->bi_bmap.br_startblock;
159 map->me_startoff = bmap->bi_bmap.br_startoff;
160 map->me_len = bmap->bi_bmap.br_blockcount;
161 xfs_trans_set_bmap_flags(map, bmap->bi_type, bmap->bi_whichfork,
162 bmap->bi_bmap.br_state);
163}
164
165/* Get an BUD so we can process all the deferred rmap updates. */
166STATIC void *
167xfs_bmap_update_create_done(
168 struct xfs_trans *tp,
169 void *intent,
170 unsigned int count)
171{
172 return xfs_trans_get_bud(tp, intent);
173}
174
175/* Process a deferred rmap update. */
176STATIC int
177xfs_bmap_update_finish_item(
178 struct xfs_trans *tp,
179 struct xfs_defer_ops *dop,
180 struct list_head *item,
181 void *done_item,
182 void **state)
183{
184 struct xfs_bmap_intent *bmap;
Darrick J. Wonge1a4e372017-06-14 21:25:57 -0700185 xfs_filblks_t count;
Darrick J. Wong9f3afb52016-10-03 09:11:28 -0700186 int error;
187
188 bmap = container_of(item, struct xfs_bmap_intent, bi_list);
Darrick J. Wonge1a4e372017-06-14 21:25:57 -0700189 count = bmap->bi_bmap.br_blockcount;
Darrick J. Wong9f3afb52016-10-03 09:11:28 -0700190 error = xfs_trans_log_finish_bmap_update(tp, done_item, dop,
191 bmap->bi_type,
192 bmap->bi_owner, bmap->bi_whichfork,
193 bmap->bi_bmap.br_startoff,
194 bmap->bi_bmap.br_startblock,
Darrick J. Wonge1a4e372017-06-14 21:25:57 -0700195 &count,
Darrick J. Wong9f3afb52016-10-03 09:11:28 -0700196 bmap->bi_bmap.br_state);
Darrick J. Wonge1a4e372017-06-14 21:25:57 -0700197 if (!error && count > 0) {
198 ASSERT(bmap->bi_type == XFS_BMAP_UNMAP);
199 bmap->bi_bmap.br_blockcount = count;
200 return -EAGAIN;
201 }
Darrick J. Wong9f3afb52016-10-03 09:11:28 -0700202 kmem_free(bmap);
203 return error;
204}
205
206/* Abort all pending BUIs. */
207STATIC void
208xfs_bmap_update_abort_intent(
209 void *intent)
210{
211 xfs_bui_release(intent);
212}
213
214/* Cancel a deferred rmap update. */
215STATIC void
216xfs_bmap_update_cancel_item(
217 struct list_head *item)
218{
219 struct xfs_bmap_intent *bmap;
220
221 bmap = container_of(item, struct xfs_bmap_intent, bi_list);
222 kmem_free(bmap);
223}
224
225static const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
226 .type = XFS_DEFER_OPS_TYPE_BMAP,
227 .max_items = XFS_BUI_MAX_FAST_EXTENTS,
228 .diff_items = xfs_bmap_update_diff_items,
229 .create_intent = xfs_bmap_update_create_intent,
230 .abort_intent = xfs_bmap_update_abort_intent,
231 .log_item = xfs_bmap_update_log_item,
232 .create_done = xfs_bmap_update_create_done,
233 .finish_item = xfs_bmap_update_finish_item,
234 .cancel_item = xfs_bmap_update_cancel_item,
235};
236
237/* Register the deferred op type. */
238void
239xfs_bmap_update_init_defer_op(void)
240{
241 xfs_defer_init_op_type(&xfs_bmap_update_defer_type);
242}