diff options
Diffstat (limited to 'fs/xfs/xfs_extfree_item.c')
-rw-r--r-- | fs/xfs/xfs_extfree_item.c | 668 |
1 files changed, 668 insertions, 0 deletions
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c new file mode 100644 index 000000000000..5eafd5b63211 --- /dev/null +++ b/fs/xfs/xfs_extfree_item.c | |||
@@ -0,0 +1,668 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of version 2 of the GNU General Public License as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it would be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
11 | * | ||
12 | * Further, this software is distributed without any warranty that it is | ||
13 | * free of the rightful claim of any third person regarding infringement | ||
14 | * or the like. Any license provided herein, whether implied or | ||
15 | * otherwise, applies only to this software file. Patent licenses, if | ||
16 | * any, provided herein do not apply to combinations of this program with | ||
17 | * other software, or any other product whatsoever. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write the Free Software Foundation, Inc., 59 | ||
21 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
22 | * | ||
23 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, | ||
24 | * Mountain View, CA 94043, or: | ||
25 | * | ||
26 | * http://www.sgi.com | ||
27 | * | ||
28 | * For further information regarding this notice, see: | ||
29 | * | ||
30 | * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | * This file contains the implementation of the xfs_efi_log_item | ||
35 | * and xfs_efd_log_item items. | ||
36 | */ | ||
37 | |||
38 | #include "xfs.h" | ||
39 | |||
40 | #include "xfs_macros.h" | ||
41 | #include "xfs_types.h" | ||
42 | #include "xfs_inum.h" | ||
43 | #include "xfs_log.h" | ||
44 | #include "xfs_trans.h" | ||
45 | #include "xfs_buf_item.h" | ||
46 | #include "xfs_sb.h" | ||
47 | #include "xfs_dir.h" | ||
48 | #include "xfs_dmapi.h" | ||
49 | #include "xfs_mount.h" | ||
50 | #include "xfs_trans_priv.h" | ||
51 | #include "xfs_extfree_item.h" | ||
52 | |||
53 | |||
54 | kmem_zone_t *xfs_efi_zone; | ||
55 | kmem_zone_t *xfs_efd_zone; | ||
56 | |||
57 | STATIC void xfs_efi_item_unlock(xfs_efi_log_item_t *); | ||
58 | STATIC void xfs_efi_item_abort(xfs_efi_log_item_t *); | ||
59 | STATIC void xfs_efd_item_abort(xfs_efd_log_item_t *); | ||
60 | |||
61 | |||
62 | |||
63 | /* | ||
64 | * This returns the number of iovecs needed to log the given efi item. | ||
65 | * We only need 1 iovec for an efi item. It just logs the efi_log_format | ||
66 | * structure. | ||
67 | */ | ||
68 | /*ARGSUSED*/ | ||
69 | STATIC uint | ||
70 | xfs_efi_item_size(xfs_efi_log_item_t *efip) | ||
71 | { | ||
72 | return 1; | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * This is called to fill in the vector of log iovecs for the | ||
77 | * given efi log item. We use only 1 iovec, and we point that | ||
78 | * at the efi_log_format structure embedded in the efi item. | ||
79 | * It is at this point that we assert that all of the extent | ||
80 | * slots in the efi item have been filled. | ||
81 | */ | ||
82 | STATIC void | ||
83 | xfs_efi_item_format(xfs_efi_log_item_t *efip, | ||
84 | xfs_log_iovec_t *log_vector) | ||
85 | { | ||
86 | uint size; | ||
87 | |||
88 | ASSERT(efip->efi_next_extent == efip->efi_format.efi_nextents); | ||
89 | |||
90 | efip->efi_format.efi_type = XFS_LI_EFI; | ||
91 | |||
92 | size = sizeof(xfs_efi_log_format_t); | ||
93 | size += (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t); | ||
94 | efip->efi_format.efi_size = 1; | ||
95 | |||
96 | log_vector->i_addr = (xfs_caddr_t)&(efip->efi_format); | ||
97 | log_vector->i_len = size; | ||
98 | ASSERT(size >= sizeof(xfs_efi_log_format_t)); | ||
99 | } | ||
100 | |||
101 | |||
102 | /* | ||
103 | * Pinning has no meaning for an efi item, so just return. | ||
104 | */ | ||
105 | /*ARGSUSED*/ | ||
106 | STATIC void | ||
107 | xfs_efi_item_pin(xfs_efi_log_item_t *efip) | ||
108 | { | ||
109 | return; | ||
110 | } | ||
111 | |||
112 | |||
113 | /* | ||
114 | * While EFIs cannot really be pinned, the unpin operation is the | ||
115 | * last place at which the EFI is manipulated during a transaction. | ||
116 | * Here we coordinate with xfs_efi_cancel() to determine who gets to | ||
117 | * free the EFI. | ||
118 | */ | ||
119 | /*ARGSUSED*/ | ||
120 | STATIC void | ||
121 | xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale) | ||
122 | { | ||
123 | int nexts; | ||
124 | int size; | ||
125 | xfs_mount_t *mp; | ||
126 | SPLDECL(s); | ||
127 | |||
128 | mp = efip->efi_item.li_mountp; | ||
129 | AIL_LOCK(mp, s); | ||
130 | if (efip->efi_flags & XFS_EFI_CANCELED) { | ||
131 | /* | ||
132 | * xfs_trans_delete_ail() drops the AIL lock. | ||
133 | */ | ||
134 | xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); | ||
135 | |||
136 | nexts = efip->efi_format.efi_nextents; | ||
137 | if (nexts > XFS_EFI_MAX_FAST_EXTENTS) { | ||
138 | size = sizeof(xfs_efi_log_item_t); | ||
139 | size += (nexts - 1) * sizeof(xfs_extent_t); | ||
140 | kmem_free(efip, size); | ||
141 | } else { | ||
142 | kmem_zone_free(xfs_efi_zone, efip); | ||
143 | } | ||
144 | } else { | ||
145 | efip->efi_flags |= XFS_EFI_COMMITTED; | ||
146 | AIL_UNLOCK(mp, s); | ||
147 | } | ||
148 | |||
149 | return; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * like unpin only we have to also clear the xaction descriptor | ||
154 | * pointing the log item if we free the item. This routine duplicates | ||
155 | * unpin because efi_flags is protected by the AIL lock. Freeing | ||
156 | * the descriptor and then calling unpin would force us to drop the AIL | ||
157 | * lock which would open up a race condition. | ||
158 | */ | ||
159 | STATIC void | ||
160 | xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp) | ||
161 | { | ||
162 | int nexts; | ||
163 | int size; | ||
164 | xfs_mount_t *mp; | ||
165 | xfs_log_item_desc_t *lidp; | ||
166 | SPLDECL(s); | ||
167 | |||
168 | mp = efip->efi_item.li_mountp; | ||
169 | AIL_LOCK(mp, s); | ||
170 | if (efip->efi_flags & XFS_EFI_CANCELED) { | ||
171 | /* | ||
172 | * free the xaction descriptor pointing to this item | ||
173 | */ | ||
174 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t *) efip); | ||
175 | xfs_trans_free_item(tp, lidp); | ||
176 | /* | ||
177 | * pull the item off the AIL. | ||
178 | * xfs_trans_delete_ail() drops the AIL lock. | ||
179 | */ | ||
180 | xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); | ||
181 | /* | ||
182 | * now free the item itself | ||
183 | */ | ||
184 | nexts = efip->efi_format.efi_nextents; | ||
185 | if (nexts > XFS_EFI_MAX_FAST_EXTENTS) { | ||
186 | size = sizeof(xfs_efi_log_item_t); | ||
187 | size += (nexts - 1) * sizeof(xfs_extent_t); | ||
188 | kmem_free(efip, size); | ||
189 | } else { | ||
190 | kmem_zone_free(xfs_efi_zone, efip); | ||
191 | } | ||
192 | } else { | ||
193 | efip->efi_flags |= XFS_EFI_COMMITTED; | ||
194 | AIL_UNLOCK(mp, s); | ||
195 | } | ||
196 | |||
197 | return; | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * Efi items have no locking or pushing. However, since EFIs are | ||
202 | * pulled from the AIL when their corresponding EFDs are committed | ||
203 | * to disk, their situation is very similar to being pinned. Return | ||
204 | * XFS_ITEM_PINNED so that the caller will eventually flush the log. | ||
205 | * This should help in getting the EFI out of the AIL. | ||
206 | */ | ||
207 | /*ARGSUSED*/ | ||
208 | STATIC uint | ||
209 | xfs_efi_item_trylock(xfs_efi_log_item_t *efip) | ||
210 | { | ||
211 | return XFS_ITEM_PINNED; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * Efi items have no locking, so just return. | ||
216 | */ | ||
217 | /*ARGSUSED*/ | ||
218 | STATIC void | ||
219 | xfs_efi_item_unlock(xfs_efi_log_item_t *efip) | ||
220 | { | ||
221 | if (efip->efi_item.li_flags & XFS_LI_ABORTED) | ||
222 | xfs_efi_item_abort(efip); | ||
223 | return; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * The EFI is logged only once and cannot be moved in the log, so | ||
228 | * simply return the lsn at which it's been logged. The canceled | ||
229 | * flag is not paid any attention here. Checking for that is delayed | ||
230 | * until the EFI is unpinned. | ||
231 | */ | ||
232 | /*ARGSUSED*/ | ||
233 | STATIC xfs_lsn_t | ||
234 | xfs_efi_item_committed(xfs_efi_log_item_t *efip, xfs_lsn_t lsn) | ||
235 | { | ||
236 | return lsn; | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * This is called when the transaction logging the EFI is aborted. | ||
241 | * Free up the EFI and return. No need to clean up the slot for | ||
242 | * the item in the transaction. That was done by the unpin code | ||
243 | * which is called prior to this routine in the abort/fs-shutdown path. | ||
244 | */ | ||
245 | STATIC void | ||
246 | xfs_efi_item_abort(xfs_efi_log_item_t *efip) | ||
247 | { | ||
248 | int nexts; | ||
249 | int size; | ||
250 | |||
251 | nexts = efip->efi_format.efi_nextents; | ||
252 | if (nexts > XFS_EFI_MAX_FAST_EXTENTS) { | ||
253 | size = sizeof(xfs_efi_log_item_t); | ||
254 | size += (nexts - 1) * sizeof(xfs_extent_t); | ||
255 | kmem_free(efip, size); | ||
256 | } else { | ||
257 | kmem_zone_free(xfs_efi_zone, efip); | ||
258 | } | ||
259 | return; | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * There isn't much you can do to push on an efi item. It is simply | ||
264 | * stuck waiting for all of its corresponding efd items to be | ||
265 | * committed to disk. | ||
266 | */ | ||
267 | /*ARGSUSED*/ | ||
268 | STATIC void | ||
269 | xfs_efi_item_push(xfs_efi_log_item_t *efip) | ||
270 | { | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * The EFI dependency tracking op doesn't do squat. It can't because | ||
276 | * it doesn't know where the free extent is coming from. The dependency | ||
277 | * tracking has to be handled by the "enclosing" metadata object. For | ||
278 | * example, for inodes, the inode is locked throughout the extent freeing | ||
279 | * so the dependency should be recorded there. | ||
280 | */ | ||
281 | /*ARGSUSED*/ | ||
282 | STATIC void | ||
283 | xfs_efi_item_committing(xfs_efi_log_item_t *efip, xfs_lsn_t lsn) | ||
284 | { | ||
285 | return; | ||
286 | } | ||
287 | |||
288 | /* | ||
289 | * This is the ops vector shared by all efi log items. | ||
290 | */ | ||
291 | struct xfs_item_ops xfs_efi_item_ops = { | ||
292 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_efi_item_size, | ||
293 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | ||
294 | xfs_efi_item_format, | ||
295 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_efi_item_pin, | ||
296 | .iop_unpin = (void(*)(xfs_log_item_t*, int))xfs_efi_item_unpin, | ||
297 | .iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t *)) | ||
298 | xfs_efi_item_unpin_remove, | ||
299 | .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_efi_item_trylock, | ||
300 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_efi_item_unlock, | ||
301 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
302 | xfs_efi_item_committed, | ||
303 | .iop_push = (void(*)(xfs_log_item_t*))xfs_efi_item_push, | ||
304 | .iop_abort = (void(*)(xfs_log_item_t*))xfs_efi_item_abort, | ||
305 | .iop_pushbuf = NULL, | ||
306 | .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
307 | xfs_efi_item_committing | ||
308 | }; | ||
309 | |||
310 | |||
311 | /* | ||
312 | * Allocate and initialize an efi item with the given number of extents. | ||
313 | */ | ||
314 | xfs_efi_log_item_t * | ||
315 | xfs_efi_init(xfs_mount_t *mp, | ||
316 | uint nextents) | ||
317 | |||
318 | { | ||
319 | xfs_efi_log_item_t *efip; | ||
320 | uint size; | ||
321 | |||
322 | ASSERT(nextents > 0); | ||
323 | if (nextents > XFS_EFI_MAX_FAST_EXTENTS) { | ||
324 | size = (uint)(sizeof(xfs_efi_log_item_t) + | ||
325 | ((nextents - 1) * sizeof(xfs_extent_t))); | ||
326 | efip = (xfs_efi_log_item_t*)kmem_zalloc(size, KM_SLEEP); | ||
327 | } else { | ||
328 | efip = (xfs_efi_log_item_t*)kmem_zone_zalloc(xfs_efi_zone, | ||
329 | KM_SLEEP); | ||
330 | } | ||
331 | |||
332 | efip->efi_item.li_type = XFS_LI_EFI; | ||
333 | efip->efi_item.li_ops = &xfs_efi_item_ops; | ||
334 | efip->efi_item.li_mountp = mp; | ||
335 | efip->efi_format.efi_nextents = nextents; | ||
336 | efip->efi_format.efi_id = (__psint_t)(void*)efip; | ||
337 | |||
338 | return (efip); | ||
339 | } | ||
340 | |||
341 | /* | ||
342 | * This is called by the efd item code below to release references to | ||
343 | * the given efi item. Each efd calls this with the number of | ||
344 | * extents that it has logged, and when the sum of these reaches | ||
345 | * the total number of extents logged by this efi item we can free | ||
346 | * the efi item. | ||
347 | * | ||
348 | * Freeing the efi item requires that we remove it from the AIL. | ||
349 | * We'll use the AIL lock to protect our counters as well as | ||
350 | * the removal from the AIL. | ||
351 | */ | ||
352 | void | ||
353 | xfs_efi_release(xfs_efi_log_item_t *efip, | ||
354 | uint nextents) | ||
355 | { | ||
356 | xfs_mount_t *mp; | ||
357 | int extents_left; | ||
358 | uint size; | ||
359 | int nexts; | ||
360 | SPLDECL(s); | ||
361 | |||
362 | mp = efip->efi_item.li_mountp; | ||
363 | ASSERT(efip->efi_next_extent > 0); | ||
364 | ASSERT(efip->efi_flags & XFS_EFI_COMMITTED); | ||
365 | |||
366 | AIL_LOCK(mp, s); | ||
367 | ASSERT(efip->efi_next_extent >= nextents); | ||
368 | efip->efi_next_extent -= nextents; | ||
369 | extents_left = efip->efi_next_extent; | ||
370 | if (extents_left == 0) { | ||
371 | /* | ||
372 | * xfs_trans_delete_ail() drops the AIL lock. | ||
373 | */ | ||
374 | xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); | ||
375 | } else { | ||
376 | AIL_UNLOCK(mp, s); | ||
377 | } | ||
378 | |||
379 | if (extents_left == 0) { | ||
380 | nexts = efip->efi_format.efi_nextents; | ||
381 | if (nexts > XFS_EFI_MAX_FAST_EXTENTS) { | ||
382 | size = sizeof(xfs_efi_log_item_t); | ||
383 | size += (nexts - 1) * sizeof(xfs_extent_t); | ||
384 | kmem_free(efip, size); | ||
385 | } else { | ||
386 | kmem_zone_free(xfs_efi_zone, efip); | ||
387 | } | ||
388 | } | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | * This is called when the transaction that should be committing the | ||
393 | * EFD corresponding to the given EFI is aborted. The committed and | ||
394 | * canceled flags are used to coordinate the freeing of the EFI and | ||
395 | * the references by the transaction that committed it. | ||
396 | */ | ||
397 | STATIC void | ||
398 | xfs_efi_cancel( | ||
399 | xfs_efi_log_item_t *efip) | ||
400 | { | ||
401 | int nexts; | ||
402 | int size; | ||
403 | xfs_mount_t *mp; | ||
404 | SPLDECL(s); | ||
405 | |||
406 | mp = efip->efi_item.li_mountp; | ||
407 | AIL_LOCK(mp, s); | ||
408 | if (efip->efi_flags & XFS_EFI_COMMITTED) { | ||
409 | /* | ||
410 | * xfs_trans_delete_ail() drops the AIL lock. | ||
411 | */ | ||
412 | xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s); | ||
413 | |||
414 | nexts = efip->efi_format.efi_nextents; | ||
415 | if (nexts > XFS_EFI_MAX_FAST_EXTENTS) { | ||
416 | size = sizeof(xfs_efi_log_item_t); | ||
417 | size += (nexts - 1) * sizeof(xfs_extent_t); | ||
418 | kmem_free(efip, size); | ||
419 | } else { | ||
420 | kmem_zone_free(xfs_efi_zone, efip); | ||
421 | } | ||
422 | } else { | ||
423 | efip->efi_flags |= XFS_EFI_CANCELED; | ||
424 | AIL_UNLOCK(mp, s); | ||
425 | } | ||
426 | |||
427 | return; | ||
428 | } | ||
429 | |||
430 | |||
431 | |||
432 | |||
433 | |||
434 | /* | ||
435 | * This returns the number of iovecs needed to log the given efd item. | ||
436 | * We only need 1 iovec for an efd item. It just logs the efd_log_format | ||
437 | * structure. | ||
438 | */ | ||
439 | /*ARGSUSED*/ | ||
440 | STATIC uint | ||
441 | xfs_efd_item_size(xfs_efd_log_item_t *efdp) | ||
442 | { | ||
443 | return 1; | ||
444 | } | ||
445 | |||
446 | /* | ||
447 | * This is called to fill in the vector of log iovecs for the | ||
448 | * given efd log item. We use only 1 iovec, and we point that | ||
449 | * at the efd_log_format structure embedded in the efd item. | ||
450 | * It is at this point that we assert that all of the extent | ||
451 | * slots in the efd item have been filled. | ||
452 | */ | ||
453 | STATIC void | ||
454 | xfs_efd_item_format(xfs_efd_log_item_t *efdp, | ||
455 | xfs_log_iovec_t *log_vector) | ||
456 | { | ||
457 | uint size; | ||
458 | |||
459 | ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents); | ||
460 | |||
461 | efdp->efd_format.efd_type = XFS_LI_EFD; | ||
462 | |||
463 | size = sizeof(xfs_efd_log_format_t); | ||
464 | size += (efdp->efd_format.efd_nextents - 1) * sizeof(xfs_extent_t); | ||
465 | efdp->efd_format.efd_size = 1; | ||
466 | |||
467 | log_vector->i_addr = (xfs_caddr_t)&(efdp->efd_format); | ||
468 | log_vector->i_len = size; | ||
469 | ASSERT(size >= sizeof(xfs_efd_log_format_t)); | ||
470 | } | ||
471 | |||
472 | |||
473 | /* | ||
474 | * Pinning has no meaning for an efd item, so just return. | ||
475 | */ | ||
476 | /*ARGSUSED*/ | ||
477 | STATIC void | ||
478 | xfs_efd_item_pin(xfs_efd_log_item_t *efdp) | ||
479 | { | ||
480 | return; | ||
481 | } | ||
482 | |||
483 | |||
484 | /* | ||
485 | * Since pinning has no meaning for an efd item, unpinning does | ||
486 | * not either. | ||
487 | */ | ||
488 | /*ARGSUSED*/ | ||
489 | STATIC void | ||
490 | xfs_efd_item_unpin(xfs_efd_log_item_t *efdp, int stale) | ||
491 | { | ||
492 | return; | ||
493 | } | ||
494 | |||
495 | /*ARGSUSED*/ | ||
496 | STATIC void | ||
497 | xfs_efd_item_unpin_remove(xfs_efd_log_item_t *efdp, xfs_trans_t *tp) | ||
498 | { | ||
499 | return; | ||
500 | } | ||
501 | |||
502 | /* | ||
503 | * Efd items have no locking, so just return success. | ||
504 | */ | ||
505 | /*ARGSUSED*/ | ||
506 | STATIC uint | ||
507 | xfs_efd_item_trylock(xfs_efd_log_item_t *efdp) | ||
508 | { | ||
509 | return XFS_ITEM_LOCKED; | ||
510 | } | ||
511 | |||
512 | /* | ||
513 | * Efd items have no locking or pushing, so return failure | ||
514 | * so that the caller doesn't bother with us. | ||
515 | */ | ||
516 | /*ARGSUSED*/ | ||
517 | STATIC void | ||
518 | xfs_efd_item_unlock(xfs_efd_log_item_t *efdp) | ||
519 | { | ||
520 | if (efdp->efd_item.li_flags & XFS_LI_ABORTED) | ||
521 | xfs_efd_item_abort(efdp); | ||
522 | return; | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | * When the efd item is committed to disk, all we need to do | ||
527 | * is delete our reference to our partner efi item and then | ||
528 | * free ourselves. Since we're freeing ourselves we must | ||
529 | * return -1 to keep the transaction code from further referencing | ||
530 | * this item. | ||
531 | */ | ||
532 | /*ARGSUSED*/ | ||
533 | STATIC xfs_lsn_t | ||
534 | xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn) | ||
535 | { | ||
536 | uint size; | ||
537 | int nexts; | ||
538 | |||
539 | /* | ||
540 | * If we got a log I/O error, it's always the case that the LR with the | ||
541 | * EFI got unpinned and freed before the EFD got aborted. | ||
542 | */ | ||
543 | if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0) | ||
544 | xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents); | ||
545 | |||
546 | nexts = efdp->efd_format.efd_nextents; | ||
547 | if (nexts > XFS_EFD_MAX_FAST_EXTENTS) { | ||
548 | size = sizeof(xfs_efd_log_item_t); | ||
549 | size += (nexts - 1) * sizeof(xfs_extent_t); | ||
550 | kmem_free(efdp, size); | ||
551 | } else { | ||
552 | kmem_zone_free(xfs_efd_zone, efdp); | ||
553 | } | ||
554 | |||
555 | return (xfs_lsn_t)-1; | ||
556 | } | ||
557 | |||
558 | /* | ||
559 | * The transaction of which this EFD is a part has been aborted. | ||
560 | * Inform its companion EFI of this fact and then clean up after | ||
561 | * ourselves. No need to clean up the slot for the item in the | ||
562 | * transaction. That was done by the unpin code which is called | ||
563 | * prior to this routine in the abort/fs-shutdown path. | ||
564 | */ | ||
565 | STATIC void | ||
566 | xfs_efd_item_abort(xfs_efd_log_item_t *efdp) | ||
567 | { | ||
568 | int nexts; | ||
569 | int size; | ||
570 | |||
571 | /* | ||
572 | * If we got a log I/O error, it's always the case that the LR with the | ||
573 | * EFI got unpinned and freed before the EFD got aborted. So don't | ||
574 | * reference the EFI at all in that case. | ||
575 | */ | ||
576 | if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0) | ||
577 | xfs_efi_cancel(efdp->efd_efip); | ||
578 | |||
579 | nexts = efdp->efd_format.efd_nextents; | ||
580 | if (nexts > XFS_EFD_MAX_FAST_EXTENTS) { | ||
581 | size = sizeof(xfs_efd_log_item_t); | ||
582 | size += (nexts - 1) * sizeof(xfs_extent_t); | ||
583 | kmem_free(efdp, size); | ||
584 | } else { | ||
585 | kmem_zone_free(xfs_efd_zone, efdp); | ||
586 | } | ||
587 | return; | ||
588 | } | ||
589 | |||
590 | /* | ||
591 | * There isn't much you can do to push on an efd item. It is simply | ||
592 | * stuck waiting for the log to be flushed to disk. | ||
593 | */ | ||
594 | /*ARGSUSED*/ | ||
595 | STATIC void | ||
596 | xfs_efd_item_push(xfs_efd_log_item_t *efdp) | ||
597 | { | ||
598 | return; | ||
599 | } | ||
600 | |||
601 | /* | ||
602 | * The EFD dependency tracking op doesn't do squat. It can't because | ||
603 | * it doesn't know where the free extent is coming from. The dependency | ||
604 | * tracking has to be handled by the "enclosing" metadata object. For | ||
605 | * example, for inodes, the inode is locked throughout the extent freeing | ||
606 | * so the dependency should be recorded there. | ||
607 | */ | ||
608 | /*ARGSUSED*/ | ||
609 | STATIC void | ||
610 | xfs_efd_item_committing(xfs_efd_log_item_t *efip, xfs_lsn_t lsn) | ||
611 | { | ||
612 | return; | ||
613 | } | ||
614 | |||
615 | /* | ||
616 | * This is the ops vector shared by all efd log items. | ||
617 | */ | ||
618 | struct xfs_item_ops xfs_efd_item_ops = { | ||
619 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_efd_item_size, | ||
620 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | ||
621 | xfs_efd_item_format, | ||
622 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_efd_item_pin, | ||
623 | .iop_unpin = (void(*)(xfs_log_item_t*, int))xfs_efd_item_unpin, | ||
624 | .iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t*)) | ||
625 | xfs_efd_item_unpin_remove, | ||
626 | .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_efd_item_trylock, | ||
627 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_efd_item_unlock, | ||
628 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
629 | xfs_efd_item_committed, | ||
630 | .iop_push = (void(*)(xfs_log_item_t*))xfs_efd_item_push, | ||
631 | .iop_abort = (void(*)(xfs_log_item_t*))xfs_efd_item_abort, | ||
632 | .iop_pushbuf = NULL, | ||
633 | .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
634 | xfs_efd_item_committing | ||
635 | }; | ||
636 | |||
637 | |||
638 | /* | ||
639 | * Allocate and initialize an efd item with the given number of extents. | ||
640 | */ | ||
641 | xfs_efd_log_item_t * | ||
642 | xfs_efd_init(xfs_mount_t *mp, | ||
643 | xfs_efi_log_item_t *efip, | ||
644 | uint nextents) | ||
645 | |||
646 | { | ||
647 | xfs_efd_log_item_t *efdp; | ||
648 | uint size; | ||
649 | |||
650 | ASSERT(nextents > 0); | ||
651 | if (nextents > XFS_EFD_MAX_FAST_EXTENTS) { | ||
652 | size = (uint)(sizeof(xfs_efd_log_item_t) + | ||
653 | ((nextents - 1) * sizeof(xfs_extent_t))); | ||
654 | efdp = (xfs_efd_log_item_t*)kmem_zalloc(size, KM_SLEEP); | ||
655 | } else { | ||
656 | efdp = (xfs_efd_log_item_t*)kmem_zone_zalloc(xfs_efd_zone, | ||
657 | KM_SLEEP); | ||
658 | } | ||
659 | |||
660 | efdp->efd_item.li_type = XFS_LI_EFD; | ||
661 | efdp->efd_item.li_ops = &xfs_efd_item_ops; | ||
662 | efdp->efd_item.li_mountp = mp; | ||
663 | efdp->efd_efip = efip; | ||
664 | efdp->efd_format.efd_nextents = nextents; | ||
665 | efdp->efd_format.efd_efi_id = efip->efi_format.efi_id; | ||
666 | |||
667 | return (efdp); | ||
668 | } | ||