aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2016-10-03 12:11:25 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2016-10-04 14:05:43 -0400
commit6413a01420c2fbf03b3d059795f541caeb962e86 (patch)
tree314ad92ff0bd3db16bb6b934fcc6aef49a62a531
parent350a27a6a65cc5dd2ba1b220e8641993414816d2 (diff)
xfs: create bmbt update intent log items
Create bmbt update intent/done log items to record redo information in the log. Because we roll transactions multiple times for reflink operations, we also have to track the status of the metadata updates that will be recorded in the post-roll transactions in case we crash before committing the final transaction. This mechanism enables log recovery to finish what was already started. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--fs/xfs/Makefile1
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h58
-rw-r--r--fs/xfs/xfs_bmap_item.c374
-rw-r--r--fs/xfs/xfs_bmap_item.h97
-rw-r--r--fs/xfs/xfs_super.c18
5 files changed, 546 insertions, 2 deletions
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 6a9ea9ed7efc..b85096138539 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -102,6 +102,7 @@ xfs-y += xfs_aops.o \
102# low-level transaction/log code 102# low-level transaction/log code
103xfs-y += xfs_log.o \ 103xfs-y += xfs_log.o \
104 xfs_log_cil.o \ 104 xfs_log_cil.o \
105 xfs_bmap_item.o \
105 xfs_buf_item.o \ 106 xfs_buf_item.o \
106 xfs_extfree_item.o \ 107 xfs_extfree_item.o \
107 xfs_icreate_item.o \ 108 xfs_icreate_item.o \
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h
index 3659f04016c0..5dd7c2e8f439 100644
--- a/fs/xfs/libxfs/xfs_log_format.h
+++ b/fs/xfs/libxfs/xfs_log_format.h
@@ -114,7 +114,9 @@ static inline uint xlog_get_cycle(char *ptr)
114#define XLOG_REG_TYPE_RUD_FORMAT 22 114#define XLOG_REG_TYPE_RUD_FORMAT 22
115#define XLOG_REG_TYPE_CUI_FORMAT 23 115#define XLOG_REG_TYPE_CUI_FORMAT 23
116#define XLOG_REG_TYPE_CUD_FORMAT 24 116#define XLOG_REG_TYPE_CUD_FORMAT 24
117#define XLOG_REG_TYPE_MAX 24 117#define XLOG_REG_TYPE_BUI_FORMAT 25
118#define XLOG_REG_TYPE_BUD_FORMAT 26
119#define XLOG_REG_TYPE_MAX 26
118 120
119/* 121/*
120 * Flags to log operation header 122 * Flags to log operation header
@@ -235,6 +237,8 @@ typedef struct xfs_trans_header {
235#define XFS_LI_RUD 0x1241 237#define XFS_LI_RUD 0x1241
236#define XFS_LI_CUI 0x1242 /* refcount update intent */ 238#define XFS_LI_CUI 0x1242 /* refcount update intent */
237#define XFS_LI_CUD 0x1243 239#define XFS_LI_CUD 0x1243
240#define XFS_LI_BUI 0x1244 /* bmbt update intent */
241#define XFS_LI_BUD 0x1245
238 242
239#define XFS_LI_TYPE_DESC \ 243#define XFS_LI_TYPE_DESC \
240 { XFS_LI_EFI, "XFS_LI_EFI" }, \ 244 { XFS_LI_EFI, "XFS_LI_EFI" }, \
@@ -248,7 +252,9 @@ typedef struct xfs_trans_header {
248 { XFS_LI_RUI, "XFS_LI_RUI" }, \ 252 { XFS_LI_RUI, "XFS_LI_RUI" }, \
249 { XFS_LI_RUD, "XFS_LI_RUD" }, \ 253 { XFS_LI_RUD, "XFS_LI_RUD" }, \
250 { XFS_LI_CUI, "XFS_LI_CUI" }, \ 254 { XFS_LI_CUI, "XFS_LI_CUI" }, \
251 { XFS_LI_CUD, "XFS_LI_CUD" } 255 { XFS_LI_CUD, "XFS_LI_CUD" }, \
256 { XFS_LI_BUI, "XFS_LI_BUI" }, \
257 { XFS_LI_BUD, "XFS_LI_BUD" }
252 258
253/* 259/*
254 * Inode Log Item Format definitions. 260 * Inode Log Item Format definitions.
@@ -725,6 +731,54 @@ struct xfs_cud_log_format {
725}; 731};
726 732
727/* 733/*
734 * BUI/BUD (inode block mapping) log format definitions
735 */
736
737/* bmbt me_flags: upper bits are flags, lower byte is type code */
738/* Type codes are taken directly from enum xfs_bmap_intent_type. */
739#define XFS_BMAP_EXTENT_TYPE_MASK 0xFF
740
741#define XFS_BMAP_EXTENT_ATTR_FORK (1U << 31)
742#define XFS_BMAP_EXTENT_UNWRITTEN (1U << 30)
743
744#define XFS_BMAP_EXTENT_FLAGS (XFS_BMAP_EXTENT_TYPE_MASK | \
745 XFS_BMAP_EXTENT_ATTR_FORK | \
746 XFS_BMAP_EXTENT_UNWRITTEN)
747
748/*
749 * This is the structure used to lay out an bui log item in the
750 * log. The bui_extents field is a variable size array whose
751 * size is given by bui_nextents.
752 */
753struct xfs_bui_log_format {
754 __uint16_t bui_type; /* bui log item type */
755 __uint16_t bui_size; /* size of this item */
756 __uint32_t bui_nextents; /* # extents to free */
757 __uint64_t bui_id; /* bui identifier */
758 struct xfs_map_extent bui_extents[]; /* array of extents to bmap */
759};
760
761static inline size_t
762xfs_bui_log_format_sizeof(
763 unsigned int nr)
764{
765 return sizeof(struct xfs_bui_log_format) +
766 nr * sizeof(struct xfs_map_extent);
767}
768
769/*
770 * This is the structure used to lay out an bud log item in the
771 * log. The bud_extents array is a variable size array whose
772 * size is given by bud_nextents;
773 */
774struct xfs_bud_log_format {
775 __uint16_t bud_type; /* bud log item type */
776 __uint16_t bud_size; /* size of this item */
777 __uint32_t __pad;
778 __uint64_t bud_bui_id; /* id of corresponding bui */
779};
780
781/*
728 * Dquot Log format definitions. 782 * Dquot Log format definitions.
729 * 783 *
730 * The first two fields must be the type and size fitting into 784 * The first two fields must be the type and size fitting into
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
new file mode 100644
index 000000000000..ea736af649de
--- /dev/null
+++ b/fs/xfs/xfs_bmap_item.c
@@ -0,0 +1,374 @@
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_format.h"
23#include "xfs_log_format.h"
24#include "xfs_trans_resv.h"
25#include "xfs_mount.h"
26#include "xfs_trans.h"
27#include "xfs_trans_priv.h"
28#include "xfs_buf_item.h"
29#include "xfs_bmap_item.h"
30#include "xfs_log.h"
31
32
33kmem_zone_t *xfs_bui_zone;
34kmem_zone_t *xfs_bud_zone;
35
36static inline struct xfs_bui_log_item *BUI_ITEM(struct xfs_log_item *lip)
37{
38 return container_of(lip, struct xfs_bui_log_item, bui_item);
39}
40
41void
42xfs_bui_item_free(
43 struct xfs_bui_log_item *buip)
44{
45 kmem_zone_free(xfs_bui_zone, buip);
46}
47
48STATIC void
49xfs_bui_item_size(
50 struct xfs_log_item *lip,
51 int *nvecs,
52 int *nbytes)
53{
54 struct xfs_bui_log_item *buip = BUI_ITEM(lip);
55
56 *nvecs += 1;
57 *nbytes += xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents);
58}
59
60/*
61 * This is called to fill in the vector of log iovecs for the
62 * given bui log item. We use only 1 iovec, and we point that
63 * at the bui_log_format structure embedded in the bui item.
64 * It is at this point that we assert that all of the extent
65 * slots in the bui item have been filled.
66 */
67STATIC void
68xfs_bui_item_format(
69 struct xfs_log_item *lip,
70 struct xfs_log_vec *lv)
71{
72 struct xfs_bui_log_item *buip = BUI_ITEM(lip);
73 struct xfs_log_iovec *vecp = NULL;
74
75 ASSERT(atomic_read(&buip->bui_next_extent) ==
76 buip->bui_format.bui_nextents);
77
78 buip->bui_format.bui_type = XFS_LI_BUI;
79 buip->bui_format.bui_size = 1;
80
81 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUI_FORMAT, &buip->bui_format,
82 xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents));
83}
84
85/*
86 * Pinning has no meaning for an bui item, so just return.
87 */
88STATIC void
89xfs_bui_item_pin(
90 struct xfs_log_item *lip)
91{
92}
93
94/*
95 * The unpin operation is the last place an BUI is manipulated in the log. It is
96 * either inserted in the AIL or aborted in the event of a log I/O error. In
97 * either case, the BUI transaction has been successfully committed to make it
98 * this far. Therefore, we expect whoever committed the BUI to either construct
99 * and commit the BUD or drop the BUD's reference in the event of error. Simply
100 * drop the log's BUI reference now that the log is done with it.
101 */
102STATIC void
103xfs_bui_item_unpin(
104 struct xfs_log_item *lip,
105 int remove)
106{
107 struct xfs_bui_log_item *buip = BUI_ITEM(lip);
108
109 xfs_bui_release(buip);
110}
111
112/*
113 * BUI items have no locking or pushing. However, since BUIs are pulled from
114 * the AIL when their corresponding BUDs are committed to disk, their situation
115 * is very similar to being pinned. Return XFS_ITEM_PINNED so that the caller
116 * will eventually flush the log. This should help in getting the BUI out of
117 * the AIL.
118 */
119STATIC uint
120xfs_bui_item_push(
121 struct xfs_log_item *lip,
122 struct list_head *buffer_list)
123{
124 return XFS_ITEM_PINNED;
125}
126
127/*
128 * The BUI has been either committed or aborted if the transaction has been
129 * cancelled. If the transaction was cancelled, an BUD isn't going to be
130 * constructed and thus we free the BUI here directly.
131 */
132STATIC void
133xfs_bui_item_unlock(
134 struct xfs_log_item *lip)
135{
136 if (lip->li_flags & XFS_LI_ABORTED)
137 xfs_bui_item_free(BUI_ITEM(lip));
138}
139
140/*
141 * The BUI is logged only once and cannot be moved in the log, so simply return
142 * the lsn at which it's been logged.
143 */
144STATIC xfs_lsn_t
145xfs_bui_item_committed(
146 struct xfs_log_item *lip,
147 xfs_lsn_t lsn)
148{
149 return lsn;
150}
151
152/*
153 * The BUI dependency tracking op doesn't do squat. It can't because
154 * it doesn't know where the free extent is coming from. The dependency
155 * tracking has to be handled by the "enclosing" metadata object. For
156 * example, for inodes, the inode is locked throughout the extent freeing
157 * so the dependency should be recorded there.
158 */
159STATIC void
160xfs_bui_item_committing(
161 struct xfs_log_item *lip,
162 xfs_lsn_t lsn)
163{
164}
165
166/*
167 * This is the ops vector shared by all bui log items.
168 */
169static const struct xfs_item_ops xfs_bui_item_ops = {
170 .iop_size = xfs_bui_item_size,
171 .iop_format = xfs_bui_item_format,
172 .iop_pin = xfs_bui_item_pin,
173 .iop_unpin = xfs_bui_item_unpin,
174 .iop_unlock = xfs_bui_item_unlock,
175 .iop_committed = xfs_bui_item_committed,
176 .iop_push = xfs_bui_item_push,
177 .iop_committing = xfs_bui_item_committing,
178};
179
180/*
181 * Allocate and initialize an bui item with the given number of extents.
182 */
183struct xfs_bui_log_item *
184xfs_bui_init(
185 struct xfs_mount *mp)
186
187{
188 struct xfs_bui_log_item *buip;
189
190 buip = kmem_zone_zalloc(xfs_bui_zone, KM_SLEEP);
191
192 xfs_log_item_init(mp, &buip->bui_item, XFS_LI_BUI, &xfs_bui_item_ops);
193 buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS;
194 buip->bui_format.bui_id = (uintptr_t)(void *)buip;
195 atomic_set(&buip->bui_next_extent, 0);
196 atomic_set(&buip->bui_refcount, 2);
197
198 return buip;
199}
200
201/*
202 * Freeing the BUI requires that we remove it from the AIL if it has already
203 * been placed there. However, the BUI may not yet have been placed in the AIL
204 * when called by xfs_bui_release() from BUD processing due to the ordering of
205 * committed vs unpin operations in bulk insert operations. Hence the reference
206 * count to ensure only the last caller frees the BUI.
207 */
208void
209xfs_bui_release(
210 struct xfs_bui_log_item *buip)
211{
212 if (atomic_dec_and_test(&buip->bui_refcount)) {
213 xfs_trans_ail_remove(&buip->bui_item, SHUTDOWN_LOG_IO_ERROR);
214 xfs_bui_item_free(buip);
215 }
216}
217
218static inline struct xfs_bud_log_item *BUD_ITEM(struct xfs_log_item *lip)
219{
220 return container_of(lip, struct xfs_bud_log_item, bud_item);
221}
222
223STATIC void
224xfs_bud_item_size(
225 struct xfs_log_item *lip,
226 int *nvecs,
227 int *nbytes)
228{
229 *nvecs += 1;
230 *nbytes += sizeof(struct xfs_bud_log_format);
231}
232
233/*
234 * This is called to fill in the vector of log iovecs for the
235 * given bud log item. We use only 1 iovec, and we point that
236 * at the bud_log_format structure embedded in the bud item.
237 * It is at this point that we assert that all of the extent
238 * slots in the bud item have been filled.
239 */
240STATIC void
241xfs_bud_item_format(
242 struct xfs_log_item *lip,
243 struct xfs_log_vec *lv)
244{
245 struct xfs_bud_log_item *budp = BUD_ITEM(lip);
246 struct xfs_log_iovec *vecp = NULL;
247
248 budp->bud_format.bud_type = XFS_LI_BUD;
249 budp->bud_format.bud_size = 1;
250
251 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUD_FORMAT, &budp->bud_format,
252 sizeof(struct xfs_bud_log_format));
253}
254
255/*
256 * Pinning has no meaning for an bud item, so just return.
257 */
258STATIC void
259xfs_bud_item_pin(
260 struct xfs_log_item *lip)
261{
262}
263
264/*
265 * Since pinning has no meaning for an bud item, unpinning does
266 * not either.
267 */
268STATIC void
269xfs_bud_item_unpin(
270 struct xfs_log_item *lip,
271 int remove)
272{
273}
274
275/*
276 * There isn't much you can do to push on an bud item. It is simply stuck
277 * waiting for the log to be flushed to disk.
278 */
279STATIC uint
280xfs_bud_item_push(
281 struct xfs_log_item *lip,
282 struct list_head *buffer_list)
283{
284 return XFS_ITEM_PINNED;
285}
286
287/*
288 * The BUD is either committed or aborted if the transaction is cancelled. If
289 * the transaction is cancelled, drop our reference to the BUI and free the
290 * BUD.
291 */
292STATIC void
293xfs_bud_item_unlock(
294 struct xfs_log_item *lip)
295{
296 struct xfs_bud_log_item *budp = BUD_ITEM(lip);
297
298 if (lip->li_flags & XFS_LI_ABORTED) {
299 xfs_bui_release(budp->bud_buip);
300 kmem_zone_free(xfs_bud_zone, budp);
301 }
302}
303
304/*
305 * When the bud item is committed to disk, all we need to do is delete our
306 * reference to our partner bui item and then free ourselves. Since we're
307 * freeing ourselves we must return -1 to keep the transaction code from
308 * further referencing this item.
309 */
310STATIC xfs_lsn_t
311xfs_bud_item_committed(
312 struct xfs_log_item *lip,
313 xfs_lsn_t lsn)
314{
315 struct xfs_bud_log_item *budp = BUD_ITEM(lip);
316
317 /*
318 * Drop the BUI reference regardless of whether the BUD has been
319 * aborted. Once the BUD transaction is constructed, it is the sole
320 * responsibility of the BUD to release the BUI (even if the BUI is
321 * aborted due to log I/O error).
322 */
323 xfs_bui_release(budp->bud_buip);
324 kmem_zone_free(xfs_bud_zone, budp);
325
326 return (xfs_lsn_t)-1;
327}
328
329/*
330 * The BUD dependency tracking op doesn't do squat. It can't because
331 * it doesn't know where the free extent is coming from. The dependency
332 * tracking has to be handled by the "enclosing" metadata object. For
333 * example, for inodes, the inode is locked throughout the extent freeing
334 * so the dependency should be recorded there.
335 */
336STATIC void
337xfs_bud_item_committing(
338 struct xfs_log_item *lip,
339 xfs_lsn_t lsn)
340{
341}
342
343/*
344 * This is the ops vector shared by all bud log items.
345 */
346static const struct xfs_item_ops xfs_bud_item_ops = {
347 .iop_size = xfs_bud_item_size,
348 .iop_format = xfs_bud_item_format,
349 .iop_pin = xfs_bud_item_pin,
350 .iop_unpin = xfs_bud_item_unpin,
351 .iop_unlock = xfs_bud_item_unlock,
352 .iop_committed = xfs_bud_item_committed,
353 .iop_push = xfs_bud_item_push,
354 .iop_committing = xfs_bud_item_committing,
355};
356
357/*
358 * Allocate and initialize an bud item with the given number of extents.
359 */
360struct xfs_bud_log_item *
361xfs_bud_init(
362 struct xfs_mount *mp,
363 struct xfs_bui_log_item *buip)
364
365{
366 struct xfs_bud_log_item *budp;
367
368 budp = kmem_zone_zalloc(xfs_bud_zone, KM_SLEEP);
369 xfs_log_item_init(mp, &budp->bud_item, XFS_LI_BUD, &xfs_bud_item_ops);
370 budp->bud_buip = buip;
371 budp->bud_format.bud_bui_id = buip->bui_format.bui_id;
372
373 return budp;
374}
diff --git a/fs/xfs/xfs_bmap_item.h b/fs/xfs/xfs_bmap_item.h
new file mode 100644
index 000000000000..57c13d3a9b03
--- /dev/null
+++ b/fs/xfs/xfs_bmap_item.h
@@ -0,0 +1,97 @@
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#ifndef __XFS_BMAP_ITEM_H__
21#define __XFS_BMAP_ITEM_H__
22
23/*
24 * There are (currently) two pairs of bmap btree redo item types: map & unmap.
25 * The common abbreviations for these are BUI (bmap update intent) and BUD
26 * (bmap update done). The redo item type is encoded in the flags field of
27 * each xfs_map_extent.
28 *
29 * *I items should be recorded in the *first* of a series of rolled
30 * transactions, and the *D items should be recorded in the same transaction
31 * that records the associated bmbt updates.
32 *
33 * Should the system crash after the commit of the first transaction but
34 * before the commit of the final transaction in a series, log recovery will
35 * use the redo information recorded by the intent items to replay the
36 * bmbt metadata updates in the non-first transaction.
37 */
38
39/* kernel only BUI/BUD definitions */
40
41struct xfs_mount;
42struct kmem_zone;
43
44/*
45 * Max number of extents in fast allocation path.
46 */
47#define XFS_BUI_MAX_FAST_EXTENTS 1
48
49/*
50 * Define BUI flag bits. Manipulated by set/clear/test_bit operators.
51 */
52#define XFS_BUI_RECOVERED 1
53
54/*
55 * This is the "bmap update intent" log item. It is used to log the fact that
56 * some reverse mappings need to change. It is used in conjunction with the
57 * "bmap update done" log item described below.
58 *
59 * These log items follow the same rules as struct xfs_efi_log_item; see the
60 * comments about that structure (in xfs_extfree_item.h) for more details.
61 */
62struct xfs_bui_log_item {
63 struct xfs_log_item bui_item;
64 atomic_t bui_refcount;
65 atomic_t bui_next_extent;
66 unsigned long bui_flags; /* misc flags */
67 struct xfs_bui_log_format bui_format;
68};
69
70static inline size_t
71xfs_bui_log_item_sizeof(
72 unsigned int nr)
73{
74 return offsetof(struct xfs_bui_log_item, bui_format) +
75 xfs_bui_log_format_sizeof(nr);
76}
77
78/*
79 * This is the "bmap update done" log item. It is used to log the fact that
80 * some bmbt updates mentioned in an earlier bui item have been performed.
81 */
82struct xfs_bud_log_item {
83 struct xfs_log_item bud_item;
84 struct xfs_bui_log_item *bud_buip;
85 struct xfs_bud_log_format bud_format;
86};
87
88extern struct kmem_zone *xfs_bui_zone;
89extern struct kmem_zone *xfs_bud_zone;
90
91struct xfs_bui_log_item *xfs_bui_init(struct xfs_mount *);
92struct xfs_bud_log_item *xfs_bud_init(struct xfs_mount *,
93 struct xfs_bui_log_item *);
94void xfs_bui_item_free(struct xfs_bui_log_item *);
95void xfs_bui_release(struct xfs_bui_log_item *);
96
97#endif /* __XFS_BMAP_ITEM_H__ */
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 62346223d04f..071bae0ec499 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -48,6 +48,7 @@
48#include "xfs_ondisk.h" 48#include "xfs_ondisk.h"
49#include "xfs_rmap_item.h" 49#include "xfs_rmap_item.h"
50#include "xfs_refcount_item.h" 50#include "xfs_refcount_item.h"
51#include "xfs_bmap_item.h"
51 52
52#include <linux/namei.h> 53#include <linux/namei.h>
53#include <linux/init.h> 54#include <linux/init.h>
@@ -1800,8 +1801,23 @@ xfs_init_zones(void)
1800 if (!xfs_cui_zone) 1801 if (!xfs_cui_zone)
1801 goto out_destroy_cud_zone; 1802 goto out_destroy_cud_zone;
1802 1803
1804 xfs_bud_zone = kmem_zone_init(sizeof(struct xfs_bud_log_item),
1805 "xfs_bud_item");
1806 if (!xfs_bud_zone)
1807 goto out_destroy_cui_zone;
1808
1809 xfs_bui_zone = kmem_zone_init(
1810 xfs_bui_log_item_sizeof(XFS_BUI_MAX_FAST_EXTENTS),
1811 "xfs_bui_item");
1812 if (!xfs_bui_zone)
1813 goto out_destroy_bud_zone;
1814
1803 return 0; 1815 return 0;
1804 1816
1817 out_destroy_bud_zone:
1818 kmem_zone_destroy(xfs_bud_zone);
1819 out_destroy_cui_zone:
1820 kmem_zone_destroy(xfs_cui_zone);
1805 out_destroy_cud_zone: 1821 out_destroy_cud_zone:
1806 kmem_zone_destroy(xfs_cud_zone); 1822 kmem_zone_destroy(xfs_cud_zone);
1807 out_destroy_rui_zone: 1823 out_destroy_rui_zone:
@@ -1848,6 +1864,8 @@ xfs_destroy_zones(void)
1848 * destroy caches. 1864 * destroy caches.
1849 */ 1865 */
1850 rcu_barrier(); 1866 rcu_barrier();
1867 kmem_zone_destroy(xfs_bui_zone);
1868 kmem_zone_destroy(xfs_bud_zone);
1851 kmem_zone_destroy(xfs_cui_zone); 1869 kmem_zone_destroy(xfs_cui_zone);
1852 kmem_zone_destroy(xfs_cud_zone); 1870 kmem_zone_destroy(xfs_cud_zone);
1853 kmem_zone_destroy(xfs_rui_zone); 1871 kmem_zone_destroy(xfs_rui_zone);