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