Merge tag 'xfs-5.1-merge-4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[sfrench/cifs-2.6.git] / fs / xfs / xfs_trans_extfree.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2000,2005 Silicon Graphics, Inc.
4  * All Rights Reserved.
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_bit.h"
13 #include "xfs_mount.h"
14 #include "xfs_defer.h"
15 #include "xfs_trans.h"
16 #include "xfs_trans_priv.h"
17 #include "xfs_extfree_item.h"
18 #include "xfs_alloc.h"
19 #include "xfs_bmap.h"
20 #include "xfs_trace.h"
21
22 /*
23  * This routine is called to allocate an "extent free done"
24  * log item that will hold nextents worth of extents.  The
25  * caller must use all nextents extents, because we are not
26  * flexible about this at all.
27  */
28 struct xfs_efd_log_item *
29 xfs_trans_get_efd(struct xfs_trans              *tp,
30                   struct xfs_efi_log_item       *efip,
31                   uint                          nextents)
32 {
33         struct xfs_efd_log_item                 *efdp;
34
35         ASSERT(tp != NULL);
36         ASSERT(nextents > 0);
37
38         efdp = xfs_efd_init(tp->t_mountp, efip, nextents);
39         ASSERT(efdp != NULL);
40
41         /*
42          * Get a log_item_desc to point at the new item.
43          */
44         xfs_trans_add_item(tp, &efdp->efd_item);
45         return efdp;
46 }
47
48 /*
49  * Free an extent and log it to the EFD. Note that the transaction is marked
50  * dirty regardless of whether the extent free succeeds or fails to support the
51  * EFI/EFD lifecycle rules.
52  */
53 int
54 xfs_trans_free_extent(
55         struct xfs_trans                *tp,
56         struct xfs_efd_log_item         *efdp,
57         xfs_fsblock_t                   start_block,
58         xfs_extlen_t                    ext_len,
59         const struct xfs_owner_info     *oinfo,
60         bool                            skip_discard)
61 {
62         struct xfs_mount                *mp = tp->t_mountp;
63         struct xfs_extent               *extp;
64         uint                            next_extent;
65         xfs_agnumber_t                  agno = XFS_FSB_TO_AGNO(mp, start_block);
66         xfs_agblock_t                   agbno = XFS_FSB_TO_AGBNO(mp,
67                                                                 start_block);
68         int                             error;
69
70         trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
71
72         error = __xfs_free_extent(tp, start_block, ext_len,
73                                   oinfo, XFS_AG_RESV_NONE, skip_discard);
74         /*
75          * Mark the transaction dirty, even on error. This ensures the
76          * transaction is aborted, which:
77          *
78          * 1.) releases the EFI and frees the EFD
79          * 2.) shuts down the filesystem
80          */
81         tp->t_flags |= XFS_TRANS_DIRTY;
82         set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags);
83
84         next_extent = efdp->efd_next_extent;
85         ASSERT(next_extent < efdp->efd_format.efd_nextents);
86         extp = &(efdp->efd_format.efd_extents[next_extent]);
87         extp->ext_start = start_block;
88         extp->ext_len = ext_len;
89         efdp->efd_next_extent++;
90
91         return error;
92 }
93
94 /* Sort bmap items by AG. */
95 static int
96 xfs_extent_free_diff_items(
97         void                            *priv,
98         struct list_head                *a,
99         struct list_head                *b)
100 {
101         struct xfs_mount                *mp = priv;
102         struct xfs_extent_free_item     *ra;
103         struct xfs_extent_free_item     *rb;
104
105         ra = container_of(a, struct xfs_extent_free_item, xefi_list);
106         rb = container_of(b, struct xfs_extent_free_item, xefi_list);
107         return  XFS_FSB_TO_AGNO(mp, ra->xefi_startblock) -
108                 XFS_FSB_TO_AGNO(mp, rb->xefi_startblock);
109 }
110
111 /* Get an EFI. */
112 STATIC void *
113 xfs_extent_free_create_intent(
114         struct xfs_trans                *tp,
115         unsigned int                    count)
116 {
117         struct xfs_efi_log_item         *efip;
118
119         ASSERT(tp != NULL);
120         ASSERT(count > 0);
121
122         efip = xfs_efi_init(tp->t_mountp, count);
123         ASSERT(efip != NULL);
124
125         /*
126          * Get a log_item_desc to point at the new item.
127          */
128         xfs_trans_add_item(tp, &efip->efi_item);
129         return efip;
130 }
131
132 /* Log a free extent to the intent item. */
133 STATIC void
134 xfs_extent_free_log_item(
135         struct xfs_trans                *tp,
136         void                            *intent,
137         struct list_head                *item)
138 {
139         struct xfs_efi_log_item         *efip = intent;
140         struct xfs_extent_free_item     *free;
141         uint                            next_extent;
142         struct xfs_extent               *extp;
143
144         free = container_of(item, struct xfs_extent_free_item, xefi_list);
145
146         tp->t_flags |= XFS_TRANS_DIRTY;
147         set_bit(XFS_LI_DIRTY, &efip->efi_item.li_flags);
148
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(&efip->efi_next_extent) - 1;
155         ASSERT(next_extent < efip->efi_format.efi_nextents);
156         extp = &efip->efi_format.efi_extents[next_extent];
157         extp->ext_start = free->xefi_startblock;
158         extp->ext_len = free->xefi_blockcount;
159 }
160
161 /* Get an EFD so we can process all the free extents. */
162 STATIC void *
163 xfs_extent_free_create_done(
164         struct xfs_trans                *tp,
165         void                            *intent,
166         unsigned int                    count)
167 {
168         return xfs_trans_get_efd(tp, intent, count);
169 }
170
171 /* Process a free extent. */
172 STATIC int
173 xfs_extent_free_finish_item(
174         struct xfs_trans                *tp,
175         struct list_head                *item,
176         void                            *done_item,
177         void                            **state)
178 {
179         struct xfs_extent_free_item     *free;
180         int                             error;
181
182         free = container_of(item, struct xfs_extent_free_item, xefi_list);
183         error = xfs_trans_free_extent(tp, done_item,
184                         free->xefi_startblock,
185                         free->xefi_blockcount,
186                         &free->xefi_oinfo, free->xefi_skip_discard);
187         kmem_free(free);
188         return error;
189 }
190
191 /* Abort all pending EFIs. */
192 STATIC void
193 xfs_extent_free_abort_intent(
194         void                            *intent)
195 {
196         xfs_efi_release(intent);
197 }
198
199 /* Cancel a free extent. */
200 STATIC void
201 xfs_extent_free_cancel_item(
202         struct list_head                *item)
203 {
204         struct xfs_extent_free_item     *free;
205
206         free = container_of(item, struct xfs_extent_free_item, xefi_list);
207         kmem_free(free);
208 }
209
210 const struct xfs_defer_op_type xfs_extent_free_defer_type = {
211         .max_items      = XFS_EFI_MAX_FAST_EXTENTS,
212         .diff_items     = xfs_extent_free_diff_items,
213         .create_intent  = xfs_extent_free_create_intent,
214         .abort_intent   = xfs_extent_free_abort_intent,
215         .log_item       = xfs_extent_free_log_item,
216         .create_done    = xfs_extent_free_create_done,
217         .finish_item    = xfs_extent_free_finish_item,
218         .cancel_item    = xfs_extent_free_cancel_item,
219 };
220
221 /*
222  * AGFL blocks are accounted differently in the reserve pools and are not
223  * inserted into the busy extent list.
224  */
225 STATIC int
226 xfs_agfl_free_finish_item(
227         struct xfs_trans                *tp,
228         struct list_head                *item,
229         void                            *done_item,
230         void                            **state)
231 {
232         struct xfs_mount                *mp = tp->t_mountp;
233         struct xfs_efd_log_item         *efdp = done_item;
234         struct xfs_extent_free_item     *free;
235         struct xfs_extent               *extp;
236         struct xfs_buf                  *agbp;
237         int                             error;
238         xfs_agnumber_t                  agno;
239         xfs_agblock_t                   agbno;
240         uint                            next_extent;
241
242         free = container_of(item, struct xfs_extent_free_item, xefi_list);
243         ASSERT(free->xefi_blockcount == 1);
244         agno = XFS_FSB_TO_AGNO(mp, free->xefi_startblock);
245         agbno = XFS_FSB_TO_AGBNO(mp, free->xefi_startblock);
246
247         trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, free->xefi_blockcount);
248
249         error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
250         if (!error)
251                 error = xfs_free_agfl_block(tp, agno, agbno, agbp,
252                                             &free->xefi_oinfo);
253
254         /*
255          * Mark the transaction dirty, even on error. This ensures the
256          * transaction is aborted, which:
257          *
258          * 1.) releases the EFI and frees the EFD
259          * 2.) shuts down the filesystem
260          */
261         tp->t_flags |= XFS_TRANS_DIRTY;
262         set_bit(XFS_LI_DIRTY, &efdp->efd_item.li_flags);
263
264         next_extent = efdp->efd_next_extent;
265         ASSERT(next_extent < efdp->efd_format.efd_nextents);
266         extp = &(efdp->efd_format.efd_extents[next_extent]);
267         extp->ext_start = free->xefi_startblock;
268         extp->ext_len = free->xefi_blockcount;
269         efdp->efd_next_extent++;
270
271         kmem_free(free);
272         return error;
273 }
274
275
276 /* sub-type with special handling for AGFL deferred frees */
277 const struct xfs_defer_op_type xfs_agfl_free_defer_type = {
278         .max_items      = XFS_EFI_MAX_FAST_EXTENTS,
279         .diff_items     = xfs_extent_free_diff_items,
280         .create_intent  = xfs_extent_free_create_intent,
281         .abort_intent   = xfs_extent_free_abort_intent,
282         .log_item       = xfs_extent_free_log_item,
283         .create_done    = xfs_extent_free_create_done,
284         .finish_item    = xfs_agfl_free_finish_item,
285         .cancel_item    = xfs_extent_free_cancel_item,
286 };