11da177e4SLinus Torvalds /* 27b718769SNathan Scott * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 37b718769SNathan Scott * All Rights Reserved. 41da177e4SLinus Torvalds * 57b718769SNathan Scott * This program is free software; you can redistribute it and/or 67b718769SNathan Scott * modify it under the terms of the GNU General Public License as 71da177e4SLinus Torvalds * published by the Free Software Foundation. 81da177e4SLinus Torvalds * 97b718769SNathan Scott * This program is distributed in the hope that it would be useful, 107b718769SNathan Scott * but WITHOUT ANY WARRANTY; without even the implied warranty of 117b718769SNathan Scott * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 127b718769SNathan Scott * GNU General Public License for more details. 131da177e4SLinus Torvalds * 147b718769SNathan Scott * You should have received a copy of the GNU General Public License 157b718769SNathan Scott * along with this program; if not, write the Free Software Foundation, 167b718769SNathan Scott * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 171da177e4SLinus Torvalds */ 181da177e4SLinus Torvalds #include "xfs.h" 19a844f451SNathan Scott #include "xfs_fs.h" 204fb6e8adSChristoph Hellwig #include "xfs_format.h" 21239880efSDave Chinner #include "xfs_log_format.h" 22239880efSDave Chinner #include "xfs_trans_resv.h" 23dc42375dSDarrick J. Wong #include "xfs_bit.h" 241da177e4SLinus Torvalds #include "xfs_mount.h" 25239880efSDave Chinner #include "xfs_trans.h" 261da177e4SLinus Torvalds #include "xfs_trans_priv.h" 27239880efSDave Chinner #include "xfs_buf_item.h" 281da177e4SLinus Torvalds #include "xfs_extfree_item.h" 291234351cSChristoph Hellwig #include "xfs_log.h" 30340785ccSDarrick J. Wong #include "xfs_btree.h" 31340785ccSDarrick J. Wong #include "xfs_rmap.h" 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds kmem_zone_t *xfs_efi_zone; 351da177e4SLinus Torvalds kmem_zone_t *xfs_efd_zone; 361da177e4SLinus Torvalds 377bfa31d8SChristoph Hellwig static inline struct xfs_efi_log_item *EFI_ITEM(struct xfs_log_item *lip) 387bfa31d8SChristoph Hellwig { 397bfa31d8SChristoph Hellwig return container_of(lip, struct xfs_efi_log_item, efi_item); 407bfa31d8SChristoph Hellwig } 411da177e4SLinus Torvalds 427d795ca3SChristoph Hellwig void 437bfa31d8SChristoph Hellwig xfs_efi_item_free( 447bfa31d8SChristoph Hellwig struct xfs_efi_log_item *efip) 457d795ca3SChristoph Hellwig { 46b1c5ebb2SDave Chinner kmem_free(efip->efi_item.li_lv_shadow); 477bfa31d8SChristoph Hellwig if (efip->efi_format.efi_nextents > XFS_EFI_MAX_FAST_EXTENTS) 48f0e2d93cSDenys Vlasenko kmem_free(efip); 497bfa31d8SChristoph Hellwig else 507d795ca3SChristoph Hellwig kmem_zone_free(xfs_efi_zone, efip); 517d795ca3SChristoph Hellwig } 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds /* 541da177e4SLinus Torvalds * This returns the number of iovecs needed to log the given efi item. 551da177e4SLinus Torvalds * We only need 1 iovec for an efi item. It just logs the efi_log_format 561da177e4SLinus Torvalds * structure. 571da177e4SLinus Torvalds */ 58166d1368SDave Chinner static inline int 59166d1368SDave Chinner xfs_efi_item_sizeof( 60166d1368SDave Chinner struct xfs_efi_log_item *efip) 611da177e4SLinus Torvalds { 62166d1368SDave Chinner return sizeof(struct xfs_efi_log_format) + 63166d1368SDave Chinner (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t); 64166d1368SDave Chinner } 65166d1368SDave Chinner 66166d1368SDave Chinner STATIC void 67166d1368SDave Chinner xfs_efi_item_size( 68166d1368SDave Chinner struct xfs_log_item *lip, 69166d1368SDave Chinner int *nvecs, 70166d1368SDave Chinner int *nbytes) 71166d1368SDave Chinner { 72166d1368SDave Chinner *nvecs += 1; 73166d1368SDave Chinner *nbytes += xfs_efi_item_sizeof(EFI_ITEM(lip)); 741da177e4SLinus Torvalds } 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds /* 771da177e4SLinus Torvalds * This is called to fill in the vector of log iovecs for the 781da177e4SLinus Torvalds * given efi log item. We use only 1 iovec, and we point that 791da177e4SLinus Torvalds * at the efi_log_format structure embedded in the efi item. 801da177e4SLinus Torvalds * It is at this point that we assert that all of the extent 811da177e4SLinus Torvalds * slots in the efi item have been filled. 821da177e4SLinus Torvalds */ 831da177e4SLinus Torvalds STATIC void 847bfa31d8SChristoph Hellwig xfs_efi_item_format( 857bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 86bde7cff6SChristoph Hellwig struct xfs_log_vec *lv) 871da177e4SLinus Torvalds { 887bfa31d8SChristoph Hellwig struct xfs_efi_log_item *efip = EFI_ITEM(lip); 89bde7cff6SChristoph Hellwig struct xfs_log_iovec *vecp = NULL; 901da177e4SLinus Torvalds 91b199c8a4SDave Chinner ASSERT(atomic_read(&efip->efi_next_extent) == 92b199c8a4SDave Chinner efip->efi_format.efi_nextents); 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds efip->efi_format.efi_type = XFS_LI_EFI; 951da177e4SLinus Torvalds efip->efi_format.efi_size = 1; 961da177e4SLinus Torvalds 97bde7cff6SChristoph Hellwig xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFI_FORMAT, 981234351cSChristoph Hellwig &efip->efi_format, 991234351cSChristoph Hellwig xfs_efi_item_sizeof(efip)); 1001da177e4SLinus Torvalds } 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds /* 1041da177e4SLinus Torvalds * Pinning has no meaning for an efi item, so just return. 1051da177e4SLinus Torvalds */ 1061da177e4SLinus Torvalds STATIC void 1077bfa31d8SChristoph Hellwig xfs_efi_item_pin( 1087bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 1091da177e4SLinus Torvalds { 1101da177e4SLinus Torvalds } 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds /* 1138d99fe92SBrian Foster * The unpin operation is the last place an EFI is manipulated in the log. It is 1148d99fe92SBrian Foster * either inserted in the AIL or aborted in the event of a log I/O error. In 1158d99fe92SBrian Foster * either case, the EFI transaction has been successfully committed to make it 1168d99fe92SBrian Foster * this far. Therefore, we expect whoever committed the EFI to either construct 1178d99fe92SBrian Foster * and commit the EFD or drop the EFD's reference in the event of error. Simply 1188d99fe92SBrian Foster * drop the log's EFI reference now that the log is done with it. 1191da177e4SLinus Torvalds */ 1201da177e4SLinus Torvalds STATIC void 1217bfa31d8SChristoph Hellwig xfs_efi_item_unpin( 1227bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 1237bfa31d8SChristoph Hellwig int remove) 1241da177e4SLinus Torvalds { 1257bfa31d8SChristoph Hellwig struct xfs_efi_log_item *efip = EFI_ITEM(lip); 1265e4b5386SBrian Foster xfs_efi_release(efip); 1271da177e4SLinus Torvalds } 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds /* 13043ff2122SChristoph Hellwig * Efi items have no locking or pushing. However, since EFIs are pulled from 13143ff2122SChristoph Hellwig * the AIL when their corresponding EFDs are committed to disk, their situation 13243ff2122SChristoph Hellwig * is very similar to being pinned. Return XFS_ITEM_PINNED so that the caller 13343ff2122SChristoph Hellwig * will eventually flush the log. This should help in getting the EFI out of 13443ff2122SChristoph Hellwig * the AIL. 1351da177e4SLinus Torvalds */ 1361da177e4SLinus Torvalds STATIC uint 13743ff2122SChristoph Hellwig xfs_efi_item_push( 13843ff2122SChristoph Hellwig struct xfs_log_item *lip, 13943ff2122SChristoph Hellwig struct list_head *buffer_list) 1401da177e4SLinus Torvalds { 1411da177e4SLinus Torvalds return XFS_ITEM_PINNED; 1421da177e4SLinus Torvalds } 1431da177e4SLinus Torvalds 1448d99fe92SBrian Foster /* 1458d99fe92SBrian Foster * The EFI has been either committed or aborted if the transaction has been 1468d99fe92SBrian Foster * cancelled. If the transaction was cancelled, an EFD isn't going to be 1478d99fe92SBrian Foster * constructed and thus we free the EFI here directly. 1488d99fe92SBrian Foster */ 1491da177e4SLinus Torvalds STATIC void 1507bfa31d8SChristoph Hellwig xfs_efi_item_unlock( 1517bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 1521da177e4SLinus Torvalds { 1537bfa31d8SChristoph Hellwig if (lip->li_flags & XFS_LI_ABORTED) 1547bfa31d8SChristoph Hellwig xfs_efi_item_free(EFI_ITEM(lip)); 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds /* 158b199c8a4SDave Chinner * The EFI is logged only once and cannot be moved in the log, so simply return 159666d644cSDave Chinner * the lsn at which it's been logged. 1601da177e4SLinus Torvalds */ 1611da177e4SLinus Torvalds STATIC xfs_lsn_t 1627bfa31d8SChristoph Hellwig xfs_efi_item_committed( 1637bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 1647bfa31d8SChristoph Hellwig xfs_lsn_t lsn) 1651da177e4SLinus Torvalds { 1661da177e4SLinus Torvalds return lsn; 1671da177e4SLinus Torvalds } 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds /* 1701da177e4SLinus Torvalds * The EFI dependency tracking op doesn't do squat. It can't because 1711da177e4SLinus Torvalds * it doesn't know where the free extent is coming from. The dependency 1721da177e4SLinus Torvalds * tracking has to be handled by the "enclosing" metadata object. For 1731da177e4SLinus Torvalds * example, for inodes, the inode is locked throughout the extent freeing 1741da177e4SLinus Torvalds * so the dependency should be recorded there. 1751da177e4SLinus Torvalds */ 1761da177e4SLinus Torvalds STATIC void 1777bfa31d8SChristoph Hellwig xfs_efi_item_committing( 1787bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 1797bfa31d8SChristoph Hellwig xfs_lsn_t lsn) 1801da177e4SLinus Torvalds { 1811da177e4SLinus Torvalds } 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds /* 1841da177e4SLinus Torvalds * This is the ops vector shared by all efi log items. 1851da177e4SLinus Torvalds */ 186272e42b2SChristoph Hellwig static const struct xfs_item_ops xfs_efi_item_ops = { 1877bfa31d8SChristoph Hellwig .iop_size = xfs_efi_item_size, 1887bfa31d8SChristoph Hellwig .iop_format = xfs_efi_item_format, 1897bfa31d8SChristoph Hellwig .iop_pin = xfs_efi_item_pin, 1907bfa31d8SChristoph Hellwig .iop_unpin = xfs_efi_item_unpin, 1917bfa31d8SChristoph Hellwig .iop_unlock = xfs_efi_item_unlock, 1927bfa31d8SChristoph Hellwig .iop_committed = xfs_efi_item_committed, 1937bfa31d8SChristoph Hellwig .iop_push = xfs_efi_item_push, 1947bfa31d8SChristoph Hellwig .iop_committing = xfs_efi_item_committing 1951da177e4SLinus Torvalds }; 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds /* 1991da177e4SLinus Torvalds * Allocate and initialize an efi item with the given number of extents. 2001da177e4SLinus Torvalds */ 2017bfa31d8SChristoph Hellwig struct xfs_efi_log_item * 2027bfa31d8SChristoph Hellwig xfs_efi_init( 2037bfa31d8SChristoph Hellwig struct xfs_mount *mp, 2041da177e4SLinus Torvalds uint nextents) 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds { 2077bfa31d8SChristoph Hellwig struct xfs_efi_log_item *efip; 2081da177e4SLinus Torvalds uint size; 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds ASSERT(nextents > 0); 2111da177e4SLinus Torvalds if (nextents > XFS_EFI_MAX_FAST_EXTENTS) { 2121da177e4SLinus Torvalds size = (uint)(sizeof(xfs_efi_log_item_t) + 2131da177e4SLinus Torvalds ((nextents - 1) * sizeof(xfs_extent_t))); 2147bfa31d8SChristoph Hellwig efip = kmem_zalloc(size, KM_SLEEP); 2151da177e4SLinus Torvalds } else { 2167bfa31d8SChristoph Hellwig efip = kmem_zone_zalloc(xfs_efi_zone, KM_SLEEP); 2171da177e4SLinus Torvalds } 2181da177e4SLinus Torvalds 21943f5efc5SDave Chinner xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops); 2201da177e4SLinus Torvalds efip->efi_format.efi_nextents = nextents; 221db9d67d6SChristoph Hellwig efip->efi_format.efi_id = (uintptr_t)(void *)efip; 222b199c8a4SDave Chinner atomic_set(&efip->efi_next_extent, 0); 223666d644cSDave Chinner atomic_set(&efip->efi_refcount, 2); 2241da177e4SLinus Torvalds 2257bfa31d8SChristoph Hellwig return efip; 2261da177e4SLinus Torvalds } 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds /* 2296d192a9bSTim Shimmin * Copy an EFI format buffer from the given buf, and into the destination 2306d192a9bSTim Shimmin * EFI format structure. 2316d192a9bSTim Shimmin * The given buffer can be in 32 bit or 64 bit form (which has different padding), 2326d192a9bSTim Shimmin * one of which will be the native format for this kernel. 2336d192a9bSTim Shimmin * It will handle the conversion of formats if necessary. 2346d192a9bSTim Shimmin */ 2356d192a9bSTim Shimmin int 2366d192a9bSTim Shimmin xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) 2376d192a9bSTim Shimmin { 2384e0d5f92SChristoph Hellwig xfs_efi_log_format_t *src_efi_fmt = buf->i_addr; 2396d192a9bSTim Shimmin uint i; 2406d192a9bSTim Shimmin uint len = sizeof(xfs_efi_log_format_t) + 2416d192a9bSTim Shimmin (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t); 2426d192a9bSTim Shimmin uint len32 = sizeof(xfs_efi_log_format_32_t) + 2436d192a9bSTim Shimmin (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t); 2446d192a9bSTim Shimmin uint len64 = sizeof(xfs_efi_log_format_64_t) + 2456d192a9bSTim Shimmin (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t); 2466d192a9bSTim Shimmin 2476d192a9bSTim Shimmin if (buf->i_len == len) { 2486d192a9bSTim Shimmin memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len); 2496d192a9bSTim Shimmin return 0; 2506d192a9bSTim Shimmin } else if (buf->i_len == len32) { 2514e0d5f92SChristoph Hellwig xfs_efi_log_format_32_t *src_efi_fmt_32 = buf->i_addr; 2526d192a9bSTim Shimmin 2536d192a9bSTim Shimmin dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; 2546d192a9bSTim Shimmin dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; 2556d192a9bSTim Shimmin dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; 2566d192a9bSTim Shimmin dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; 2576d192a9bSTim Shimmin for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { 2586d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_start = 2596d192a9bSTim Shimmin src_efi_fmt_32->efi_extents[i].ext_start; 2606d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_len = 2616d192a9bSTim Shimmin src_efi_fmt_32->efi_extents[i].ext_len; 2626d192a9bSTim Shimmin } 2636d192a9bSTim Shimmin return 0; 2646d192a9bSTim Shimmin } else if (buf->i_len == len64) { 2654e0d5f92SChristoph Hellwig xfs_efi_log_format_64_t *src_efi_fmt_64 = buf->i_addr; 2666d192a9bSTim Shimmin 2676d192a9bSTim Shimmin dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; 2686d192a9bSTim Shimmin dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; 2696d192a9bSTim Shimmin dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; 2706d192a9bSTim Shimmin dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; 2716d192a9bSTim Shimmin for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { 2726d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_start = 2736d192a9bSTim Shimmin src_efi_fmt_64->efi_extents[i].ext_start; 2746d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_len = 2756d192a9bSTim Shimmin src_efi_fmt_64->efi_extents[i].ext_len; 2766d192a9bSTim Shimmin } 2776d192a9bSTim Shimmin return 0; 2786d192a9bSTim Shimmin } 2792451337dSDave Chinner return -EFSCORRUPTED; 2806d192a9bSTim Shimmin } 2816d192a9bSTim Shimmin 2826d192a9bSTim Shimmin /* 283e32a1d1fSBrian Foster * Freeing the efi requires that we remove it from the AIL if it has already 284e32a1d1fSBrian Foster * been placed there. However, the EFI may not yet have been placed in the AIL 285e32a1d1fSBrian Foster * when called by xfs_efi_release() from EFD processing due to the ordering of 286e32a1d1fSBrian Foster * committed vs unpin operations in bulk insert operations. Hence the reference 287e32a1d1fSBrian Foster * count to ensure only the last caller frees the EFI. 2881da177e4SLinus Torvalds */ 2891da177e4SLinus Torvalds void 2905e4b5386SBrian Foster xfs_efi_release( 2915e4b5386SBrian Foster struct xfs_efi_log_item *efip) 2921da177e4SLinus Torvalds { 293e32a1d1fSBrian Foster if (atomic_dec_and_test(&efip->efi_refcount)) { 294146e54b7SBrian Foster xfs_trans_ail_remove(&efip->efi_item, SHUTDOWN_LOG_IO_ERROR); 295e32a1d1fSBrian Foster xfs_efi_item_free(efip); 296e32a1d1fSBrian Foster } 297666d644cSDave Chinner } 2981da177e4SLinus Torvalds 2997bfa31d8SChristoph Hellwig static inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip) 3007d795ca3SChristoph Hellwig { 3017bfa31d8SChristoph Hellwig return container_of(lip, struct xfs_efd_log_item, efd_item); 3027d795ca3SChristoph Hellwig } 3037bfa31d8SChristoph Hellwig 3047bfa31d8SChristoph Hellwig STATIC void 3057bfa31d8SChristoph Hellwig xfs_efd_item_free(struct xfs_efd_log_item *efdp) 3067bfa31d8SChristoph Hellwig { 307b1c5ebb2SDave Chinner kmem_free(efdp->efd_item.li_lv_shadow); 3087bfa31d8SChristoph Hellwig if (efdp->efd_format.efd_nextents > XFS_EFD_MAX_FAST_EXTENTS) 3097bfa31d8SChristoph Hellwig kmem_free(efdp); 3107bfa31d8SChristoph Hellwig else 3117bfa31d8SChristoph Hellwig kmem_zone_free(xfs_efd_zone, efdp); 3127d795ca3SChristoph Hellwig } 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds /* 3151da177e4SLinus Torvalds * This returns the number of iovecs needed to log the given efd item. 3161da177e4SLinus Torvalds * We only need 1 iovec for an efd item. It just logs the efd_log_format 3171da177e4SLinus Torvalds * structure. 3181da177e4SLinus Torvalds */ 319166d1368SDave Chinner static inline int 320166d1368SDave Chinner xfs_efd_item_sizeof( 321166d1368SDave Chinner struct xfs_efd_log_item *efdp) 3221da177e4SLinus Torvalds { 323166d1368SDave Chinner return sizeof(xfs_efd_log_format_t) + 324166d1368SDave Chinner (efdp->efd_format.efd_nextents - 1) * sizeof(xfs_extent_t); 325166d1368SDave Chinner } 326166d1368SDave Chinner 327166d1368SDave Chinner STATIC void 328166d1368SDave Chinner xfs_efd_item_size( 329166d1368SDave Chinner struct xfs_log_item *lip, 330166d1368SDave Chinner int *nvecs, 331166d1368SDave Chinner int *nbytes) 332166d1368SDave Chinner { 333166d1368SDave Chinner *nvecs += 1; 334166d1368SDave Chinner *nbytes += xfs_efd_item_sizeof(EFD_ITEM(lip)); 3351da177e4SLinus Torvalds } 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds /* 3381da177e4SLinus Torvalds * This is called to fill in the vector of log iovecs for the 3391da177e4SLinus Torvalds * given efd log item. We use only 1 iovec, and we point that 3401da177e4SLinus Torvalds * at the efd_log_format structure embedded in the efd item. 3411da177e4SLinus Torvalds * It is at this point that we assert that all of the extent 3421da177e4SLinus Torvalds * slots in the efd item have been filled. 3431da177e4SLinus Torvalds */ 3441da177e4SLinus Torvalds STATIC void 3457bfa31d8SChristoph Hellwig xfs_efd_item_format( 3467bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 347bde7cff6SChristoph Hellwig struct xfs_log_vec *lv) 3481da177e4SLinus Torvalds { 3497bfa31d8SChristoph Hellwig struct xfs_efd_log_item *efdp = EFD_ITEM(lip); 350bde7cff6SChristoph Hellwig struct xfs_log_iovec *vecp = NULL; 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents); 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds efdp->efd_format.efd_type = XFS_LI_EFD; 3551da177e4SLinus Torvalds efdp->efd_format.efd_size = 1; 3561da177e4SLinus Torvalds 357bde7cff6SChristoph Hellwig xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFD_FORMAT, 3581234351cSChristoph Hellwig &efdp->efd_format, 3591234351cSChristoph Hellwig xfs_efd_item_sizeof(efdp)); 3601da177e4SLinus Torvalds } 3611da177e4SLinus Torvalds 3621da177e4SLinus Torvalds /* 3631da177e4SLinus Torvalds * Pinning has no meaning for an efd item, so just return. 3641da177e4SLinus Torvalds */ 3651da177e4SLinus Torvalds STATIC void 3667bfa31d8SChristoph Hellwig xfs_efd_item_pin( 3677bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 3681da177e4SLinus Torvalds { 3691da177e4SLinus Torvalds } 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds /* 3721da177e4SLinus Torvalds * Since pinning has no meaning for an efd item, unpinning does 3731da177e4SLinus Torvalds * not either. 3741da177e4SLinus Torvalds */ 3751da177e4SLinus Torvalds STATIC void 3767bfa31d8SChristoph Hellwig xfs_efd_item_unpin( 3777bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 3787bfa31d8SChristoph Hellwig int remove) 3791da177e4SLinus Torvalds { 3801da177e4SLinus Torvalds } 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds /* 38343ff2122SChristoph Hellwig * There isn't much you can do to push on an efd item. It is simply stuck 38443ff2122SChristoph Hellwig * waiting for the log to be flushed to disk. 3851da177e4SLinus Torvalds */ 3861da177e4SLinus Torvalds STATIC uint 38743ff2122SChristoph Hellwig xfs_efd_item_push( 38843ff2122SChristoph Hellwig struct xfs_log_item *lip, 38943ff2122SChristoph Hellwig struct list_head *buffer_list) 3901da177e4SLinus Torvalds { 39143ff2122SChristoph Hellwig return XFS_ITEM_PINNED; 3921da177e4SLinus Torvalds } 3931da177e4SLinus Torvalds 3948d99fe92SBrian Foster /* 3958d99fe92SBrian Foster * The EFD is either committed or aborted if the transaction is cancelled. If 3968d99fe92SBrian Foster * the transaction is cancelled, drop our reference to the EFI and free the EFD. 3978d99fe92SBrian Foster */ 3981da177e4SLinus Torvalds STATIC void 3997bfa31d8SChristoph Hellwig xfs_efd_item_unlock( 4007bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 4011da177e4SLinus Torvalds { 4028d99fe92SBrian Foster struct xfs_efd_log_item *efdp = EFD_ITEM(lip); 4038d99fe92SBrian Foster 4048d99fe92SBrian Foster if (lip->li_flags & XFS_LI_ABORTED) { 4058d99fe92SBrian Foster xfs_efi_release(efdp->efd_efip); 4068d99fe92SBrian Foster xfs_efd_item_free(efdp); 4078d99fe92SBrian Foster } 4081da177e4SLinus Torvalds } 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds /* 4118d99fe92SBrian Foster * When the efd item is committed to disk, all we need to do is delete our 4128d99fe92SBrian Foster * reference to our partner efi item and then free ourselves. Since we're 4138d99fe92SBrian Foster * freeing ourselves we must return -1 to keep the transaction code from further 4148d99fe92SBrian Foster * referencing this item. 4151da177e4SLinus Torvalds */ 4161da177e4SLinus Torvalds STATIC xfs_lsn_t 4177bfa31d8SChristoph Hellwig xfs_efd_item_committed( 4187bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 4197bfa31d8SChristoph Hellwig xfs_lsn_t lsn) 4201da177e4SLinus Torvalds { 4217bfa31d8SChristoph Hellwig struct xfs_efd_log_item *efdp = EFD_ITEM(lip); 4227bfa31d8SChristoph Hellwig 4231da177e4SLinus Torvalds /* 4248d99fe92SBrian Foster * Drop the EFI reference regardless of whether the EFD has been 4258d99fe92SBrian Foster * aborted. Once the EFD transaction is constructed, it is the sole 4268d99fe92SBrian Foster * responsibility of the EFD to release the EFI (even if the EFI is 4278d99fe92SBrian Foster * aborted due to log I/O error). 4281da177e4SLinus Torvalds */ 4295e4b5386SBrian Foster xfs_efi_release(efdp->efd_efip); 4307d795ca3SChristoph Hellwig xfs_efd_item_free(efdp); 4318d99fe92SBrian Foster 4321da177e4SLinus Torvalds return (xfs_lsn_t)-1; 4331da177e4SLinus Torvalds } 4341da177e4SLinus Torvalds 4351da177e4SLinus Torvalds /* 4361da177e4SLinus Torvalds * The EFD dependency tracking op doesn't do squat. It can't because 4371da177e4SLinus Torvalds * it doesn't know where the free extent is coming from. The dependency 4381da177e4SLinus Torvalds * tracking has to be handled by the "enclosing" metadata object. For 4391da177e4SLinus Torvalds * example, for inodes, the inode is locked throughout the extent freeing 4401da177e4SLinus Torvalds * so the dependency should be recorded there. 4411da177e4SLinus Torvalds */ 4421da177e4SLinus Torvalds STATIC void 4437bfa31d8SChristoph Hellwig xfs_efd_item_committing( 4447bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 4457bfa31d8SChristoph Hellwig xfs_lsn_t lsn) 4461da177e4SLinus Torvalds { 4471da177e4SLinus Torvalds } 4481da177e4SLinus Torvalds 4491da177e4SLinus Torvalds /* 4501da177e4SLinus Torvalds * This is the ops vector shared by all efd log items. 4511da177e4SLinus Torvalds */ 452272e42b2SChristoph Hellwig static const struct xfs_item_ops xfs_efd_item_ops = { 4537bfa31d8SChristoph Hellwig .iop_size = xfs_efd_item_size, 4547bfa31d8SChristoph Hellwig .iop_format = xfs_efd_item_format, 4557bfa31d8SChristoph Hellwig .iop_pin = xfs_efd_item_pin, 4567bfa31d8SChristoph Hellwig .iop_unpin = xfs_efd_item_unpin, 4577bfa31d8SChristoph Hellwig .iop_unlock = xfs_efd_item_unlock, 4587bfa31d8SChristoph Hellwig .iop_committed = xfs_efd_item_committed, 4597bfa31d8SChristoph Hellwig .iop_push = xfs_efd_item_push, 4607bfa31d8SChristoph Hellwig .iop_committing = xfs_efd_item_committing 4611da177e4SLinus Torvalds }; 4621da177e4SLinus Torvalds 4631da177e4SLinus Torvalds /* 4641da177e4SLinus Torvalds * Allocate and initialize an efd item with the given number of extents. 4651da177e4SLinus Torvalds */ 4667bfa31d8SChristoph Hellwig struct xfs_efd_log_item * 4677bfa31d8SChristoph Hellwig xfs_efd_init( 4687bfa31d8SChristoph Hellwig struct xfs_mount *mp, 4697bfa31d8SChristoph Hellwig struct xfs_efi_log_item *efip, 4701da177e4SLinus Torvalds uint nextents) 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds { 4737bfa31d8SChristoph Hellwig struct xfs_efd_log_item *efdp; 4741da177e4SLinus Torvalds uint size; 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds ASSERT(nextents > 0); 4771da177e4SLinus Torvalds if (nextents > XFS_EFD_MAX_FAST_EXTENTS) { 4781da177e4SLinus Torvalds size = (uint)(sizeof(xfs_efd_log_item_t) + 4791da177e4SLinus Torvalds ((nextents - 1) * sizeof(xfs_extent_t))); 4807bfa31d8SChristoph Hellwig efdp = kmem_zalloc(size, KM_SLEEP); 4811da177e4SLinus Torvalds } else { 4827bfa31d8SChristoph Hellwig efdp = kmem_zone_zalloc(xfs_efd_zone, KM_SLEEP); 4831da177e4SLinus Torvalds } 4841da177e4SLinus Torvalds 48543f5efc5SDave Chinner xfs_log_item_init(mp, &efdp->efd_item, XFS_LI_EFD, &xfs_efd_item_ops); 4861da177e4SLinus Torvalds efdp->efd_efip = efip; 4871da177e4SLinus Torvalds efdp->efd_format.efd_nextents = nextents; 4881da177e4SLinus Torvalds efdp->efd_format.efd_efi_id = efip->efi_format.efi_id; 4891da177e4SLinus Torvalds 4907bfa31d8SChristoph Hellwig return efdp; 4911da177e4SLinus Torvalds } 492dc42375dSDarrick J. Wong 493dc42375dSDarrick J. Wong /* 494dc42375dSDarrick J. Wong * Process an extent free intent item that was recovered from 495dc42375dSDarrick J. Wong * the log. We need to free the extents that it describes. 496dc42375dSDarrick J. Wong */ 497dc42375dSDarrick J. Wong int 498dc42375dSDarrick J. Wong xfs_efi_recover( 499dc42375dSDarrick J. Wong struct xfs_mount *mp, 500dc42375dSDarrick J. Wong struct xfs_efi_log_item *efip) 501dc42375dSDarrick J. Wong { 502dc42375dSDarrick J. Wong struct xfs_efd_log_item *efdp; 503dc42375dSDarrick J. Wong struct xfs_trans *tp; 504dc42375dSDarrick J. Wong int i; 505dc42375dSDarrick J. Wong int error = 0; 506dc42375dSDarrick J. Wong xfs_extent_t *extp; 507dc42375dSDarrick J. Wong xfs_fsblock_t startblock_fsb; 508340785ccSDarrick J. Wong struct xfs_owner_info oinfo; 509dc42375dSDarrick J. Wong 510dc42375dSDarrick J. Wong ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)); 511dc42375dSDarrick J. Wong 512dc42375dSDarrick J. Wong /* 513dc42375dSDarrick J. Wong * First check the validity of the extents described by the 514dc42375dSDarrick J. Wong * EFI. If any are bad, then assume that all are bad and 515dc42375dSDarrick J. Wong * just toss the EFI. 516dc42375dSDarrick J. Wong */ 517dc42375dSDarrick J. Wong for (i = 0; i < efip->efi_format.efi_nextents; i++) { 518e127fafdSDarrick J. Wong extp = &efip->efi_format.efi_extents[i]; 519dc42375dSDarrick J. Wong startblock_fsb = XFS_BB_TO_FSB(mp, 520dc42375dSDarrick J. Wong XFS_FSB_TO_DADDR(mp, extp->ext_start)); 521e127fafdSDarrick J. Wong if (startblock_fsb == 0 || 522e127fafdSDarrick J. Wong extp->ext_len == 0 || 523e127fafdSDarrick J. Wong startblock_fsb >= mp->m_sb.sb_dblocks || 524e127fafdSDarrick J. Wong extp->ext_len >= mp->m_sb.sb_agblocks) { 525dc42375dSDarrick J. Wong /* 526dc42375dSDarrick J. Wong * This will pull the EFI from the AIL and 527dc42375dSDarrick J. Wong * free the memory associated with it. 528dc42375dSDarrick J. Wong */ 529dc42375dSDarrick J. Wong set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); 530dc42375dSDarrick J. Wong xfs_efi_release(efip); 531dc42375dSDarrick J. Wong return -EIO; 532dc42375dSDarrick J. Wong } 533dc42375dSDarrick J. Wong } 534dc42375dSDarrick J. Wong 535dc42375dSDarrick J. Wong error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); 536dc42375dSDarrick J. Wong if (error) 537dc42375dSDarrick J. Wong return error; 538dc42375dSDarrick J. Wong efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents); 539dc42375dSDarrick J. Wong 540340785ccSDarrick J. Wong xfs_rmap_skip_owner_update(&oinfo); 541dc42375dSDarrick J. Wong for (i = 0; i < efip->efi_format.efi_nextents; i++) { 542e127fafdSDarrick J. Wong extp = &efip->efi_format.efi_extents[i]; 543dc42375dSDarrick J. Wong error = xfs_trans_free_extent(tp, efdp, extp->ext_start, 544340785ccSDarrick J. Wong extp->ext_len, &oinfo); 545dc42375dSDarrick J. Wong if (error) 546dc42375dSDarrick J. Wong goto abort_error; 547dc42375dSDarrick J. Wong 548dc42375dSDarrick J. Wong } 549dc42375dSDarrick J. Wong 550dc42375dSDarrick J. Wong set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); 551dc42375dSDarrick J. Wong error = xfs_trans_commit(tp); 552dc42375dSDarrick J. Wong return error; 553dc42375dSDarrick J. Wong 554dc42375dSDarrick J. Wong abort_error: 555dc42375dSDarrick J. Wong xfs_trans_cancel(tp); 556dc42375dSDarrick J. Wong return error; 557dc42375dSDarrick J. Wong } 558