Merge branch 'drm-next-5.1' of git://people.freedesktop.org/~agd5f/linux into drm...
[linux-2.6-block.git] / fs / xfs / xfs_trans_rmap.c
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_rmap_item.h"
17 #include "xfs_alloc.h"
18 #include "xfs_rmap.h"
19 #include "xfs_defer.h"
20
21 /* Set the map extent flags for this reverse mapping. */
22 static void
23 xfs_trans_set_rmap_flags(
24         struct xfs_map_extent           *rmap,
25         enum xfs_rmap_intent_type       type,
26         int                             whichfork,
27         xfs_exntst_t                    state)
28 {
29         rmap->me_flags = 0;
30         if (state == XFS_EXT_UNWRITTEN)
31                 rmap->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN;
32         if (whichfork == XFS_ATTR_FORK)
33                 rmap->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK;
34         switch (type) {
35         case XFS_RMAP_MAP:
36                 rmap->me_flags |= XFS_RMAP_EXTENT_MAP;
37                 break;
38         case XFS_RMAP_MAP_SHARED:
39                 rmap->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED;
40                 break;
41         case XFS_RMAP_UNMAP:
42                 rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP;
43                 break;
44         case XFS_RMAP_UNMAP_SHARED:
45                 rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED;
46                 break;
47         case XFS_RMAP_CONVERT:
48                 rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT;
49                 break;
50         case XFS_RMAP_CONVERT_SHARED:
51                 rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED;
52                 break;
53         case XFS_RMAP_ALLOC:
54                 rmap->me_flags |= XFS_RMAP_EXTENT_ALLOC;
55                 break;
56         case XFS_RMAP_FREE:
57                 rmap->me_flags |= XFS_RMAP_EXTENT_FREE;
58                 break;
59         default:
60                 ASSERT(0);
61         }
62 }
63
64 struct xfs_rud_log_item *
65 xfs_trans_get_rud(
66         struct xfs_trans                *tp,
67         struct xfs_rui_log_item         *ruip)
68 {
69         struct xfs_rud_log_item         *rudp;
70
71         rudp = xfs_rud_init(tp->t_mountp, ruip);
72         xfs_trans_add_item(tp, &rudp->rud_item);
73         return rudp;
74 }
75
76 /*
77  * Finish an rmap update and log it to the RUD. Note that the transaction is
78  * marked dirty regardless of whether the rmap update succeeds or fails to
79  * support the RUI/RUD lifecycle rules.
80  */
81 int
82 xfs_trans_log_finish_rmap_update(
83         struct xfs_trans                *tp,
84         struct xfs_rud_log_item         *rudp,
85         enum xfs_rmap_intent_type       type,
86         uint64_t                        owner,
87         int                             whichfork,
88         xfs_fileoff_t                   startoff,
89         xfs_fsblock_t                   startblock,
90         xfs_filblks_t                   blockcount,
91         xfs_exntst_t                    state,
92         struct xfs_btree_cur            **pcur)
93 {
94         int                             error;
95
96         error = xfs_rmap_finish_one(tp, type, owner, whichfork, startoff,
97                         startblock, blockcount, state, pcur);
98
99         /*
100          * Mark the transaction dirty, even on error. This ensures the
101          * transaction is aborted, which:
102          *
103          * 1.) releases the RUI and frees the RUD
104          * 2.) shuts down the filesystem
105          */
106         tp->t_flags |= XFS_TRANS_DIRTY;
107         set_bit(XFS_LI_DIRTY, &rudp->rud_item.li_flags);
108
109         return error;
110 }
111
112 /* Sort rmap intents by AG. */
113 static int
114 xfs_rmap_update_diff_items(
115         void                            *priv,
116         struct list_head                *a,
117         struct list_head                *b)
118 {
119         struct xfs_mount                *mp = priv;
120         struct xfs_rmap_intent          *ra;
121         struct xfs_rmap_intent          *rb;
122
123         ra = container_of(a, struct xfs_rmap_intent, ri_list);
124         rb = container_of(b, struct xfs_rmap_intent, ri_list);
125         return  XFS_FSB_TO_AGNO(mp, ra->ri_bmap.br_startblock) -
126                 XFS_FSB_TO_AGNO(mp, rb->ri_bmap.br_startblock);
127 }
128
129 /* Get an RUI. */
130 STATIC void *
131 xfs_rmap_update_create_intent(
132         struct xfs_trans                *tp,
133         unsigned int                    count)
134 {
135         struct xfs_rui_log_item         *ruip;
136
137         ASSERT(tp != NULL);
138         ASSERT(count > 0);
139
140         ruip = xfs_rui_init(tp->t_mountp, count);
141         ASSERT(ruip != NULL);
142
143         /*
144          * Get a log_item_desc to point at the new item.
145          */
146         xfs_trans_add_item(tp, &ruip->rui_item);
147         return ruip;
148 }
149
150 /* Log rmap updates in the intent item. */
151 STATIC void
152 xfs_rmap_update_log_item(
153         struct xfs_trans                *tp,
154         void                            *intent,
155         struct list_head                *item)
156 {
157         struct xfs_rui_log_item         *ruip = intent;
158         struct xfs_rmap_intent          *rmap;
159         uint                            next_extent;
160         struct xfs_map_extent           *map;
161
162         rmap = container_of(item, struct xfs_rmap_intent, ri_list);
163
164         tp->t_flags |= XFS_TRANS_DIRTY;
165         set_bit(XFS_LI_DIRTY, &ruip->rui_item.li_flags);
166
167         /*
168          * atomic_inc_return gives us the value after the increment;
169          * we want to use it as an array index so we need to subtract 1 from
170          * it.
171          */
172         next_extent = atomic_inc_return(&ruip->rui_next_extent) - 1;
173         ASSERT(next_extent < ruip->rui_format.rui_nextents);
174         map = &ruip->rui_format.rui_extents[next_extent];
175         map->me_owner = rmap->ri_owner;
176         map->me_startblock = rmap->ri_bmap.br_startblock;
177         map->me_startoff = rmap->ri_bmap.br_startoff;
178         map->me_len = rmap->ri_bmap.br_blockcount;
179         xfs_trans_set_rmap_flags(map, rmap->ri_type, rmap->ri_whichfork,
180                         rmap->ri_bmap.br_state);
181 }
182
183 /* Get an RUD so we can process all the deferred rmap updates. */
184 STATIC void *
185 xfs_rmap_update_create_done(
186         struct xfs_trans                *tp,
187         void                            *intent,
188         unsigned int                    count)
189 {
190         return xfs_trans_get_rud(tp, intent);
191 }
192
193 /* Process a deferred rmap update. */
194 STATIC int
195 xfs_rmap_update_finish_item(
196         struct xfs_trans                *tp,
197         struct list_head                *item,
198         void                            *done_item,
199         void                            **state)
200 {
201         struct xfs_rmap_intent          *rmap;
202         int                             error;
203
204         rmap = container_of(item, struct xfs_rmap_intent, ri_list);
205         error = xfs_trans_log_finish_rmap_update(tp, done_item,
206                         rmap->ri_type,
207                         rmap->ri_owner, rmap->ri_whichfork,
208                         rmap->ri_bmap.br_startoff,
209                         rmap->ri_bmap.br_startblock,
210                         rmap->ri_bmap.br_blockcount,
211                         rmap->ri_bmap.br_state,
212                         (struct xfs_btree_cur **)state);
213         kmem_free(rmap);
214         return error;
215 }
216
217 /* Clean up after processing deferred rmaps. */
218 STATIC void
219 xfs_rmap_update_finish_cleanup(
220         struct xfs_trans        *tp,
221         void                    *state,
222         int                     error)
223 {
224         struct xfs_btree_cur    *rcur = state;
225
226         xfs_rmap_finish_one_cleanup(tp, rcur, error);
227 }
228
229 /* Abort all pending RUIs. */
230 STATIC void
231 xfs_rmap_update_abort_intent(
232         void                            *intent)
233 {
234         xfs_rui_release(intent);
235 }
236
237 /* Cancel a deferred rmap update. */
238 STATIC void
239 xfs_rmap_update_cancel_item(
240         struct list_head                *item)
241 {
242         struct xfs_rmap_intent          *rmap;
243
244         rmap = container_of(item, struct xfs_rmap_intent, ri_list);
245         kmem_free(rmap);
246 }
247
248 const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
249         .max_items      = XFS_RUI_MAX_FAST_EXTENTS,
250         .diff_items     = xfs_rmap_update_diff_items,
251         .create_intent  = xfs_rmap_update_create_intent,
252         .abort_intent   = xfs_rmap_update_abort_intent,
253         .log_item       = xfs_rmap_update_log_item,
254         .create_done    = xfs_rmap_update_create_done,
255         .finish_item    = xfs_rmap_update_finish_item,
256         .finish_cleanup = xfs_rmap_update_finish_cleanup,
257         .cancel_item    = xfs_rmap_update_cancel_item,
258 };