1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_log_format.h"
21#include "xfs_trans_resv.h"
22#include "xfs_sb.h"
23#include "xfs_ag.h"
24#include "xfs_mount.h"
25#include "xfs_trans.h"
26#include "xfs_trans_priv.h"
27#include "xfs_buf_item.h"
28#include "xfs_extfree_item.h"
29#include "xfs_log.h"
30
31
32kmem_zone_t *xfs_efi_zone;
33kmem_zone_t *xfs_efd_zone;
34
35static inline struct xfs_efi_log_item *EFI_ITEM(struct xfs_log_item *lip)
36{
37 return container_of(lip, struct xfs_efi_log_item, efi_item);
38}
39
40void
41xfs_efi_item_free(
42 struct xfs_efi_log_item *efip)
43{
44 if (efip->efi_format.efi_nextents > XFS_EFI_MAX_FAST_EXTENTS)
45 kmem_free(efip);
46 else
47 kmem_zone_free(xfs_efi_zone, efip);
48}
49
50
51
52
53
54
55
56
57STATIC void
58__xfs_efi_release(
59 struct xfs_efi_log_item *efip)
60{
61 struct xfs_ail *ailp = efip->efi_item.li_ailp;
62
63 if (atomic_dec_and_test(&efip->efi_refcount)) {
64 spin_lock(&ailp->xa_lock);
65
66 xfs_trans_ail_delete(ailp, &efip->efi_item,
67 SHUTDOWN_LOG_IO_ERROR);
68 xfs_efi_item_free(efip);
69 }
70}
71
72
73
74
75
76
77static inline int
78xfs_efi_item_sizeof(
79 struct xfs_efi_log_item *efip)
80{
81 return sizeof(struct xfs_efi_log_format) +
82 (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t);
83}
84
85STATIC void
86xfs_efi_item_size(
87 struct xfs_log_item *lip,
88 int *nvecs,
89 int *nbytes)
90{
91 *nvecs += 1;
92 *nbytes += xfs_efi_item_sizeof(EFI_ITEM(lip));
93}
94
95
96
97
98
99
100
101
102STATIC void
103xfs_efi_item_format(
104 struct xfs_log_item *lip,
105 struct xfs_log_vec *lv)
106{
107 struct xfs_efi_log_item *efip = EFI_ITEM(lip);
108 struct xfs_log_iovec *vecp = NULL;
109
110 ASSERT(atomic_read(&efip->efi_next_extent) ==
111 efip->efi_format.efi_nextents);
112
113 efip->efi_format.efi_type = XFS_LI_EFI;
114 efip->efi_format.efi_size = 1;
115
116 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFI_FORMAT,
117 &efip->efi_format,
118 xfs_efi_item_sizeof(efip));
119}
120
121
122
123
124
125STATIC void
126xfs_efi_item_pin(
127 struct xfs_log_item *lip)
128{
129}
130
131
132
133
134
135
136
137
138
139STATIC void
140xfs_efi_item_unpin(
141 struct xfs_log_item *lip,
142 int remove)
143{
144 struct xfs_efi_log_item *efip = EFI_ITEM(lip);
145
146 if (remove) {
147 ASSERT(!(lip->li_flags & XFS_LI_IN_AIL));
148 if (lip->li_desc)
149 xfs_trans_del_item(lip);
150 xfs_efi_item_free(efip);
151 return;
152 }
153 __xfs_efi_release(efip);
154}
155
156
157
158
159
160
161
162
163STATIC uint
164xfs_efi_item_push(
165 struct xfs_log_item *lip,
166 struct list_head *buffer_list)
167{
168 return XFS_ITEM_PINNED;
169}
170
171STATIC void
172xfs_efi_item_unlock(
173 struct xfs_log_item *lip)
174{
175 if (lip->li_flags & XFS_LI_ABORTED)
176 xfs_efi_item_free(EFI_ITEM(lip));
177}
178
179
180
181
182
183STATIC xfs_lsn_t
184xfs_efi_item_committed(
185 struct xfs_log_item *lip,
186 xfs_lsn_t lsn)
187{
188 return lsn;
189}
190
191
192
193
194
195
196
197
198STATIC void
199xfs_efi_item_committing(
200 struct xfs_log_item *lip,
201 xfs_lsn_t lsn)
202{
203}
204
205
206
207
208static const struct xfs_item_ops xfs_efi_item_ops = {
209 .iop_size = xfs_efi_item_size,
210 .iop_format = xfs_efi_item_format,
211 .iop_pin = xfs_efi_item_pin,
212 .iop_unpin = xfs_efi_item_unpin,
213 .iop_unlock = xfs_efi_item_unlock,
214 .iop_committed = xfs_efi_item_committed,
215 .iop_push = xfs_efi_item_push,
216 .iop_committing = xfs_efi_item_committing
217};
218
219
220
221
222
223struct xfs_efi_log_item *
224xfs_efi_init(
225 struct xfs_mount *mp,
226 uint nextents)
227
228{
229 struct xfs_efi_log_item *efip;
230 uint size;
231
232 ASSERT(nextents > 0);
233 if (nextents > XFS_EFI_MAX_FAST_EXTENTS) {
234 size = (uint)(sizeof(xfs_efi_log_item_t) +
235 ((nextents - 1) * sizeof(xfs_extent_t)));
236 efip = kmem_zalloc(size, KM_SLEEP);
237 } else {
238 efip = kmem_zone_zalloc(xfs_efi_zone, KM_SLEEP);
239 }
240
241 xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops);
242 efip->efi_format.efi_nextents = nextents;
243 efip->efi_format.efi_id = (__psint_t)(void*)efip;
244 atomic_set(&efip->efi_next_extent, 0);
245 atomic_set(&efip->efi_refcount, 2);
246
247 return efip;
248}
249
250
251
252
253
254
255
256
257int
258xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
259{
260 xfs_efi_log_format_t *src_efi_fmt = buf->i_addr;
261 uint i;
262 uint len = sizeof(xfs_efi_log_format_t) +
263 (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t);
264 uint len32 = sizeof(xfs_efi_log_format_32_t) +
265 (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t);
266 uint len64 = sizeof(xfs_efi_log_format_64_t) +
267 (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t);
268
269 if (buf->i_len == len) {
270 memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len);
271 return 0;
272 } else if (buf->i_len == len32) {
273 xfs_efi_log_format_32_t *src_efi_fmt_32 = buf->i_addr;
274
275 dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type;
276 dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size;
277 dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents;
278 dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id;
279 for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
280 dst_efi_fmt->efi_extents[i].ext_start =
281 src_efi_fmt_32->efi_extents[i].ext_start;
282 dst_efi_fmt->efi_extents[i].ext_len =
283 src_efi_fmt_32->efi_extents[i].ext_len;
284 }
285 return 0;
286 } else if (buf->i_len == len64) {
287 xfs_efi_log_format_64_t *src_efi_fmt_64 = buf->i_addr;
288
289 dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type;
290 dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size;
291 dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents;
292 dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id;
293 for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
294 dst_efi_fmt->efi_extents[i].ext_start =
295 src_efi_fmt_64->efi_extents[i].ext_start;
296 dst_efi_fmt->efi_extents[i].ext_len =
297 src_efi_fmt_64->efi_extents[i].ext_len;
298 }
299 return 0;
300 }
301 return -EFSCORRUPTED;
302}
303
304
305
306
307
308
309
310void
311xfs_efi_release(xfs_efi_log_item_t *efip,
312 uint nextents)
313{
314 ASSERT(atomic_read(&efip->efi_next_extent) >= nextents);
315 if (atomic_sub_and_test(nextents, &efip->efi_next_extent)) {
316
317 if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags))
318 __xfs_efi_release(efip);
319
320 __xfs_efi_release(efip);
321
322 }
323}
324
325static inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip)
326{
327 return container_of(lip, struct xfs_efd_log_item, efd_item);
328}
329
330STATIC void
331xfs_efd_item_free(struct xfs_efd_log_item *efdp)
332{
333 if (efdp->efd_format.efd_nextents > XFS_EFD_MAX_FAST_EXTENTS)
334 kmem_free(efdp);
335 else
336 kmem_zone_free(xfs_efd_zone, efdp);
337}
338
339
340
341
342
343
344static inline int
345xfs_efd_item_sizeof(
346 struct xfs_efd_log_item *efdp)
347{
348 return sizeof(xfs_efd_log_format_t) +
349 (efdp->efd_format.efd_nextents - 1) * sizeof(xfs_extent_t);
350}
351
352STATIC void
353xfs_efd_item_size(
354 struct xfs_log_item *lip,
355 int *nvecs,
356 int *nbytes)
357{
358 *nvecs += 1;
359 *nbytes += xfs_efd_item_sizeof(EFD_ITEM(lip));
360}
361
362
363
364
365
366
367
368
369STATIC void
370xfs_efd_item_format(
371 struct xfs_log_item *lip,
372 struct xfs_log_vec *lv)
373{
374 struct xfs_efd_log_item *efdp = EFD_ITEM(lip);
375 struct xfs_log_iovec *vecp = NULL;
376
377 ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents);
378
379 efdp->efd_format.efd_type = XFS_LI_EFD;
380 efdp->efd_format.efd_size = 1;
381
382 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFD_FORMAT,
383 &efdp->efd_format,
384 xfs_efd_item_sizeof(efdp));
385}
386
387
388
389
390STATIC void
391xfs_efd_item_pin(
392 struct xfs_log_item *lip)
393{
394}
395
396
397
398
399
400STATIC void
401xfs_efd_item_unpin(
402 struct xfs_log_item *lip,
403 int remove)
404{
405}
406
407
408
409
410
411STATIC uint
412xfs_efd_item_push(
413 struct xfs_log_item *lip,
414 struct list_head *buffer_list)
415{
416 return XFS_ITEM_PINNED;
417}
418
419STATIC void
420xfs_efd_item_unlock(
421 struct xfs_log_item *lip)
422{
423 if (lip->li_flags & XFS_LI_ABORTED)
424 xfs_efd_item_free(EFD_ITEM(lip));
425}
426
427
428
429
430
431
432
433
434STATIC xfs_lsn_t
435xfs_efd_item_committed(
436 struct xfs_log_item *lip,
437 xfs_lsn_t lsn)
438{
439 struct xfs_efd_log_item *efdp = EFD_ITEM(lip);
440
441
442
443
444
445 if (!(lip->li_flags & XFS_LI_ABORTED))
446 xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents);
447
448 xfs_efd_item_free(efdp);
449 return (xfs_lsn_t)-1;
450}
451
452
453
454
455
456
457
458
459STATIC void
460xfs_efd_item_committing(
461 struct xfs_log_item *lip,
462 xfs_lsn_t lsn)
463{
464}
465
466
467
468
469static const struct xfs_item_ops xfs_efd_item_ops = {
470 .iop_size = xfs_efd_item_size,
471 .iop_format = xfs_efd_item_format,
472 .iop_pin = xfs_efd_item_pin,
473 .iop_unpin = xfs_efd_item_unpin,
474 .iop_unlock = xfs_efd_item_unlock,
475 .iop_committed = xfs_efd_item_committed,
476 .iop_push = xfs_efd_item_push,
477 .iop_committing = xfs_efd_item_committing
478};
479
480
481
482
483struct xfs_efd_log_item *
484xfs_efd_init(
485 struct xfs_mount *mp,
486 struct xfs_efi_log_item *efip,
487 uint nextents)
488
489{
490 struct xfs_efd_log_item *efdp;
491 uint size;
492
493 ASSERT(nextents > 0);
494 if (nextents > XFS_EFD_MAX_FAST_EXTENTS) {
495 size = (uint)(sizeof(xfs_efd_log_item_t) +
496 ((nextents - 1) * sizeof(xfs_extent_t)));
497 efdp = kmem_zalloc(size, KM_SLEEP);
498 } else {
499 efdp = kmem_zone_zalloc(xfs_efd_zone, KM_SLEEP);
500 }
501
502 xfs_log_item_init(mp, &efdp->efd_item, XFS_LI_EFD, &xfs_efd_item_ops);
503 efdp->efd_efip = efip;
504 efdp->efd_format.efd_nextents = nextents;
505 efdp->efd_format.efd_efi_id = efip->efi_format.efi_id;
506
507 return efdp;
508}
509