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" 201da177e4SLinus Torvalds #include "xfs_types.h" 211da177e4SLinus Torvalds #include "xfs_log.h" 22a844f451SNathan Scott #include "xfs_inum.h" 231da177e4SLinus Torvalds #include "xfs_trans.h" 241da177e4SLinus Torvalds #include "xfs_buf_item.h" 251da177e4SLinus Torvalds #include "xfs_sb.h" 26da353b0dSDavid Chinner #include "xfs_ag.h" 271da177e4SLinus Torvalds #include "xfs_mount.h" 281da177e4SLinus Torvalds #include "xfs_trans_priv.h" 291da177e4SLinus Torvalds #include "xfs_extfree_item.h" 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds kmem_zone_t *xfs_efi_zone; 331da177e4SLinus Torvalds kmem_zone_t *xfs_efd_zone; 341da177e4SLinus Torvalds 357bfa31d8SChristoph Hellwig static inline struct xfs_efi_log_item *EFI_ITEM(struct xfs_log_item *lip) 367bfa31d8SChristoph Hellwig { 377bfa31d8SChristoph Hellwig return container_of(lip, struct xfs_efi_log_item, efi_item); 387bfa31d8SChristoph Hellwig } 391da177e4SLinus Torvalds 407d795ca3SChristoph Hellwig void 417bfa31d8SChristoph Hellwig xfs_efi_item_free( 427bfa31d8SChristoph Hellwig struct xfs_efi_log_item *efip) 437d795ca3SChristoph Hellwig { 447bfa31d8SChristoph Hellwig if (efip->efi_format.efi_nextents > XFS_EFI_MAX_FAST_EXTENTS) 45f0e2d93cSDenys Vlasenko kmem_free(efip); 467bfa31d8SChristoph Hellwig else 477d795ca3SChristoph Hellwig kmem_zone_free(xfs_efi_zone, efip); 487d795ca3SChristoph Hellwig } 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds /* 511da177e4SLinus Torvalds * This returns the number of iovecs needed to log the given efi item. 521da177e4SLinus Torvalds * We only need 1 iovec for an efi item. It just logs the efi_log_format 531da177e4SLinus Torvalds * structure. 541da177e4SLinus Torvalds */ 551da177e4SLinus Torvalds STATIC uint 567bfa31d8SChristoph Hellwig xfs_efi_item_size( 577bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 581da177e4SLinus Torvalds { 591da177e4SLinus Torvalds return 1; 601da177e4SLinus Torvalds } 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds /* 631da177e4SLinus Torvalds * This is called to fill in the vector of log iovecs for the 641da177e4SLinus Torvalds * given efi log item. We use only 1 iovec, and we point that 651da177e4SLinus Torvalds * at the efi_log_format structure embedded in the efi item. 661da177e4SLinus Torvalds * It is at this point that we assert that all of the extent 671da177e4SLinus Torvalds * slots in the efi item have been filled. 681da177e4SLinus Torvalds */ 691da177e4SLinus Torvalds STATIC void 707bfa31d8SChristoph Hellwig xfs_efi_item_format( 717bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 727bfa31d8SChristoph Hellwig struct xfs_log_iovec *log_vector) 731da177e4SLinus Torvalds { 747bfa31d8SChristoph Hellwig struct xfs_efi_log_item *efip = EFI_ITEM(lip); 751da177e4SLinus Torvalds uint size; 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds ASSERT(efip->efi_next_extent == efip->efi_format.efi_nextents); 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds efip->efi_format.efi_type = XFS_LI_EFI; 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds size = sizeof(xfs_efi_log_format_t); 821da177e4SLinus Torvalds size += (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t); 831da177e4SLinus Torvalds efip->efi_format.efi_size = 1; 841da177e4SLinus Torvalds 857bfa31d8SChristoph Hellwig log_vector->i_addr = (xfs_caddr_t)&efip->efi_format; 861da177e4SLinus Torvalds log_vector->i_len = size; 874139b3b3SChristoph Hellwig log_vector->i_type = XLOG_REG_TYPE_EFI_FORMAT; 881da177e4SLinus Torvalds ASSERT(size >= sizeof(xfs_efi_log_format_t)); 891da177e4SLinus Torvalds } 901da177e4SLinus Torvalds 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds /* 931da177e4SLinus Torvalds * Pinning has no meaning for an efi item, so just return. 941da177e4SLinus Torvalds */ 951da177e4SLinus Torvalds STATIC void 967bfa31d8SChristoph Hellwig xfs_efi_item_pin( 977bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 981da177e4SLinus Torvalds { 991da177e4SLinus Torvalds } 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds /* 1021da177e4SLinus Torvalds * While EFIs cannot really be pinned, the unpin operation is the 1031da177e4SLinus Torvalds * last place at which the EFI is manipulated during a transaction. 1041da177e4SLinus Torvalds * Here we coordinate with xfs_efi_cancel() to determine who gets to 1051da177e4SLinus Torvalds * free the EFI. 1061da177e4SLinus Torvalds */ 1071da177e4SLinus Torvalds STATIC void 1087bfa31d8SChristoph Hellwig xfs_efi_item_unpin( 1097bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 1107bfa31d8SChristoph Hellwig int remove) 1111da177e4SLinus Torvalds { 1127bfa31d8SChristoph Hellwig struct xfs_efi_log_item *efip = EFI_ITEM(lip); 1137bfa31d8SChristoph Hellwig struct xfs_ail *ailp = lip->li_ailp; 1141da177e4SLinus Torvalds 115fc1829f3SDavid Chinner spin_lock(&ailp->xa_lock); 1161da177e4SLinus Torvalds if (efip->efi_flags & XFS_EFI_CANCELED) { 1179412e318SChristoph Hellwig if (remove) 118e98c414fSChristoph Hellwig xfs_trans_del_item(lip); 119783a2f65SDavid Chinner 120783a2f65SDavid Chinner /* xfs_trans_ail_delete() drops the AIL lock. */ 121e98c414fSChristoph Hellwig xfs_trans_ail_delete(ailp, lip); 1227d795ca3SChristoph Hellwig xfs_efi_item_free(efip); 1231da177e4SLinus Torvalds } else { 1241da177e4SLinus Torvalds efip->efi_flags |= XFS_EFI_COMMITTED; 125fc1829f3SDavid Chinner spin_unlock(&ailp->xa_lock); 1261da177e4SLinus Torvalds } 1271da177e4SLinus Torvalds } 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds /* 1301da177e4SLinus Torvalds * Efi items have no locking or pushing. However, since EFIs are 1311da177e4SLinus Torvalds * pulled from the AIL when their corresponding EFDs are committed 1321da177e4SLinus Torvalds * to disk, their situation is very similar to being pinned. Return 1331da177e4SLinus Torvalds * XFS_ITEM_PINNED so that the caller will eventually flush the log. 1341da177e4SLinus Torvalds * This should help in getting the EFI out of the AIL. 1351da177e4SLinus Torvalds */ 1361da177e4SLinus Torvalds STATIC uint 1377bfa31d8SChristoph Hellwig xfs_efi_item_trylock( 1387bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 1391da177e4SLinus Torvalds { 1401da177e4SLinus Torvalds return XFS_ITEM_PINNED; 1411da177e4SLinus Torvalds } 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds /* 1441da177e4SLinus Torvalds * Efi items have no locking, so just return. 1451da177e4SLinus Torvalds */ 1461da177e4SLinus Torvalds STATIC void 1477bfa31d8SChristoph Hellwig xfs_efi_item_unlock( 1487bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 1491da177e4SLinus Torvalds { 1507bfa31d8SChristoph Hellwig if (lip->li_flags & XFS_LI_ABORTED) 1517bfa31d8SChristoph Hellwig xfs_efi_item_free(EFI_ITEM(lip)); 1521da177e4SLinus Torvalds } 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds /* 1551da177e4SLinus Torvalds * The EFI is logged only once and cannot be moved in the log, so 1561da177e4SLinus Torvalds * simply return the lsn at which it's been logged. The canceled 1571da177e4SLinus Torvalds * flag is not paid any attention here. Checking for that is delayed 1581da177e4SLinus Torvalds * until the EFI is unpinned. 1591da177e4SLinus Torvalds */ 1601da177e4SLinus Torvalds STATIC xfs_lsn_t 1617bfa31d8SChristoph Hellwig xfs_efi_item_committed( 1627bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 1637bfa31d8SChristoph Hellwig xfs_lsn_t lsn) 1641da177e4SLinus Torvalds { 1651da177e4SLinus Torvalds return lsn; 1661da177e4SLinus Torvalds } 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds /* 1691da177e4SLinus Torvalds * There isn't much you can do to push on an efi item. It is simply 1701da177e4SLinus Torvalds * stuck waiting for all of its corresponding efd items to be 1711da177e4SLinus Torvalds * committed to disk. 1721da177e4SLinus Torvalds */ 1731da177e4SLinus Torvalds STATIC void 1747bfa31d8SChristoph Hellwig xfs_efi_item_push( 1757bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 1761da177e4SLinus Torvalds { 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds /* 1801da177e4SLinus Torvalds * The EFI dependency tracking op doesn't do squat. It can't because 1811da177e4SLinus Torvalds * it doesn't know where the free extent is coming from. The dependency 1821da177e4SLinus Torvalds * tracking has to be handled by the "enclosing" metadata object. For 1831da177e4SLinus Torvalds * example, for inodes, the inode is locked throughout the extent freeing 1841da177e4SLinus Torvalds * so the dependency should be recorded there. 1851da177e4SLinus Torvalds */ 1861da177e4SLinus Torvalds STATIC void 1877bfa31d8SChristoph Hellwig xfs_efi_item_committing( 1887bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 1897bfa31d8SChristoph Hellwig xfs_lsn_t lsn) 1901da177e4SLinus Torvalds { 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds /* 1941da177e4SLinus Torvalds * This is the ops vector shared by all efi log items. 1951da177e4SLinus Torvalds */ 1967989cb8eSDavid Chinner static struct xfs_item_ops xfs_efi_item_ops = { 1977bfa31d8SChristoph Hellwig .iop_size = xfs_efi_item_size, 1987bfa31d8SChristoph Hellwig .iop_format = xfs_efi_item_format, 1997bfa31d8SChristoph Hellwig .iop_pin = xfs_efi_item_pin, 2007bfa31d8SChristoph Hellwig .iop_unpin = xfs_efi_item_unpin, 2017bfa31d8SChristoph Hellwig .iop_trylock = xfs_efi_item_trylock, 2027bfa31d8SChristoph Hellwig .iop_unlock = xfs_efi_item_unlock, 2037bfa31d8SChristoph Hellwig .iop_committed = xfs_efi_item_committed, 2047bfa31d8SChristoph Hellwig .iop_push = xfs_efi_item_push, 2057bfa31d8SChristoph Hellwig .iop_committing = xfs_efi_item_committing 2061da177e4SLinus Torvalds }; 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds 2091da177e4SLinus Torvalds /* 2101da177e4SLinus Torvalds * Allocate and initialize an efi item with the given number of extents. 2111da177e4SLinus Torvalds */ 2127bfa31d8SChristoph Hellwig struct xfs_efi_log_item * 2137bfa31d8SChristoph Hellwig xfs_efi_init( 2147bfa31d8SChristoph Hellwig struct xfs_mount *mp, 2151da177e4SLinus Torvalds uint nextents) 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds { 2187bfa31d8SChristoph Hellwig struct xfs_efi_log_item *efip; 2191da177e4SLinus Torvalds uint size; 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds ASSERT(nextents > 0); 2221da177e4SLinus Torvalds if (nextents > XFS_EFI_MAX_FAST_EXTENTS) { 2231da177e4SLinus Torvalds size = (uint)(sizeof(xfs_efi_log_item_t) + 2241da177e4SLinus Torvalds ((nextents - 1) * sizeof(xfs_extent_t))); 2257bfa31d8SChristoph Hellwig efip = kmem_zalloc(size, KM_SLEEP); 2261da177e4SLinus Torvalds } else { 2277bfa31d8SChristoph Hellwig efip = kmem_zone_zalloc(xfs_efi_zone, KM_SLEEP); 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds 23043f5efc5SDave Chinner xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops); 2311da177e4SLinus Torvalds efip->efi_format.efi_nextents = nextents; 2321da177e4SLinus Torvalds efip->efi_format.efi_id = (__psint_t)(void*)efip; 2331da177e4SLinus Torvalds 2347bfa31d8SChristoph Hellwig return efip; 2351da177e4SLinus Torvalds } 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds /* 2386d192a9bSTim Shimmin * Copy an EFI format buffer from the given buf, and into the destination 2396d192a9bSTim Shimmin * EFI format structure. 2406d192a9bSTim Shimmin * The given buffer can be in 32 bit or 64 bit form (which has different padding), 2416d192a9bSTim Shimmin * one of which will be the native format for this kernel. 2426d192a9bSTim Shimmin * It will handle the conversion of formats if necessary. 2436d192a9bSTim Shimmin */ 2446d192a9bSTim Shimmin int 2456d192a9bSTim Shimmin xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) 2466d192a9bSTim Shimmin { 2476d192a9bSTim Shimmin xfs_efi_log_format_t *src_efi_fmt = (xfs_efi_log_format_t *)buf->i_addr; 2486d192a9bSTim Shimmin uint i; 2496d192a9bSTim Shimmin uint len = sizeof(xfs_efi_log_format_t) + 2506d192a9bSTim Shimmin (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t); 2516d192a9bSTim Shimmin uint len32 = sizeof(xfs_efi_log_format_32_t) + 2526d192a9bSTim Shimmin (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t); 2536d192a9bSTim Shimmin uint len64 = sizeof(xfs_efi_log_format_64_t) + 2546d192a9bSTim Shimmin (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t); 2556d192a9bSTim Shimmin 2566d192a9bSTim Shimmin if (buf->i_len == len) { 2576d192a9bSTim Shimmin memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len); 2586d192a9bSTim Shimmin return 0; 2596d192a9bSTim Shimmin } else if (buf->i_len == len32) { 2606d192a9bSTim Shimmin xfs_efi_log_format_32_t *src_efi_fmt_32 = 2616d192a9bSTim Shimmin (xfs_efi_log_format_32_t *)buf->i_addr; 2626d192a9bSTim Shimmin 2636d192a9bSTim Shimmin dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; 2646d192a9bSTim Shimmin dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; 2656d192a9bSTim Shimmin dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; 2666d192a9bSTim Shimmin dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; 2676d192a9bSTim Shimmin for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { 2686d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_start = 2696d192a9bSTim Shimmin src_efi_fmt_32->efi_extents[i].ext_start; 2706d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_len = 2716d192a9bSTim Shimmin src_efi_fmt_32->efi_extents[i].ext_len; 2726d192a9bSTim Shimmin } 2736d192a9bSTim Shimmin return 0; 2746d192a9bSTim Shimmin } else if (buf->i_len == len64) { 2756d192a9bSTim Shimmin xfs_efi_log_format_64_t *src_efi_fmt_64 = 2766d192a9bSTim Shimmin (xfs_efi_log_format_64_t *)buf->i_addr; 2776d192a9bSTim Shimmin 2786d192a9bSTim Shimmin dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; 2796d192a9bSTim Shimmin dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; 2806d192a9bSTim Shimmin dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; 2816d192a9bSTim Shimmin dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; 2826d192a9bSTim Shimmin for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { 2836d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_start = 2846d192a9bSTim Shimmin src_efi_fmt_64->efi_extents[i].ext_start; 2856d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_len = 2866d192a9bSTim Shimmin src_efi_fmt_64->efi_extents[i].ext_len; 2876d192a9bSTim Shimmin } 2886d192a9bSTim Shimmin return 0; 2896d192a9bSTim Shimmin } 2906d192a9bSTim Shimmin return EFSCORRUPTED; 2916d192a9bSTim Shimmin } 2926d192a9bSTim Shimmin 2936d192a9bSTim Shimmin /* 2941da177e4SLinus Torvalds * This is called by the efd item code below to release references to 2951da177e4SLinus Torvalds * the given efi item. Each efd calls this with the number of 2961da177e4SLinus Torvalds * extents that it has logged, and when the sum of these reaches 2971da177e4SLinus Torvalds * the total number of extents logged by this efi item we can free 2981da177e4SLinus Torvalds * the efi item. 2991da177e4SLinus Torvalds * 3001da177e4SLinus Torvalds * Freeing the efi item requires that we remove it from the AIL. 3011da177e4SLinus Torvalds * We'll use the AIL lock to protect our counters as well as 3021da177e4SLinus Torvalds * the removal from the AIL. 3031da177e4SLinus Torvalds */ 3041da177e4SLinus Torvalds void 3051da177e4SLinus Torvalds xfs_efi_release(xfs_efi_log_item_t *efip, 3061da177e4SLinus Torvalds uint nextents) 3071da177e4SLinus Torvalds { 308783a2f65SDavid Chinner struct xfs_ail *ailp = efip->efi_item.li_ailp; 3091da177e4SLinus Torvalds int extents_left; 3101da177e4SLinus Torvalds 3111da177e4SLinus Torvalds ASSERT(efip->efi_next_extent > 0); 3121da177e4SLinus Torvalds ASSERT(efip->efi_flags & XFS_EFI_COMMITTED); 3131da177e4SLinus Torvalds 314fc1829f3SDavid Chinner spin_lock(&ailp->xa_lock); 3151da177e4SLinus Torvalds ASSERT(efip->efi_next_extent >= nextents); 3161da177e4SLinus Torvalds efip->efi_next_extent -= nextents; 3171da177e4SLinus Torvalds extents_left = efip->efi_next_extent; 3181da177e4SLinus Torvalds if (extents_left == 0) { 319783a2f65SDavid Chinner /* xfs_trans_ail_delete() drops the AIL lock. */ 320783a2f65SDavid Chinner xfs_trans_ail_delete(ailp, (xfs_log_item_t *)efip); 3217d795ca3SChristoph Hellwig xfs_efi_item_free(efip); 3221da177e4SLinus Torvalds } else { 323fc1829f3SDavid Chinner spin_unlock(&ailp->xa_lock); 3241da177e4SLinus Torvalds } 3251da177e4SLinus Torvalds } 3261da177e4SLinus Torvalds 3277bfa31d8SChristoph Hellwig static inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip) 3287d795ca3SChristoph Hellwig { 3297bfa31d8SChristoph Hellwig return container_of(lip, struct xfs_efd_log_item, efd_item); 3307d795ca3SChristoph Hellwig } 3317bfa31d8SChristoph Hellwig 3327bfa31d8SChristoph Hellwig STATIC void 3337bfa31d8SChristoph Hellwig xfs_efd_item_free(struct xfs_efd_log_item *efdp) 3347bfa31d8SChristoph Hellwig { 3357bfa31d8SChristoph Hellwig if (efdp->efd_format.efd_nextents > XFS_EFD_MAX_FAST_EXTENTS) 3367bfa31d8SChristoph Hellwig kmem_free(efdp); 3377bfa31d8SChristoph Hellwig else 3387bfa31d8SChristoph Hellwig kmem_zone_free(xfs_efd_zone, efdp); 3397d795ca3SChristoph Hellwig } 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds /* 3421da177e4SLinus Torvalds * This returns the number of iovecs needed to log the given efd item. 3431da177e4SLinus Torvalds * We only need 1 iovec for an efd item. It just logs the efd_log_format 3441da177e4SLinus Torvalds * structure. 3451da177e4SLinus Torvalds */ 3461da177e4SLinus Torvalds STATIC uint 3477bfa31d8SChristoph Hellwig xfs_efd_item_size( 3487bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 3491da177e4SLinus Torvalds { 3501da177e4SLinus Torvalds return 1; 3511da177e4SLinus Torvalds } 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds /* 3541da177e4SLinus Torvalds * This is called to fill in the vector of log iovecs for the 3551da177e4SLinus Torvalds * given efd log item. We use only 1 iovec, and we point that 3561da177e4SLinus Torvalds * at the efd_log_format structure embedded in the efd item. 3571da177e4SLinus Torvalds * It is at this point that we assert that all of the extent 3581da177e4SLinus Torvalds * slots in the efd item have been filled. 3591da177e4SLinus Torvalds */ 3601da177e4SLinus Torvalds STATIC void 3617bfa31d8SChristoph Hellwig xfs_efd_item_format( 3627bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 3637bfa31d8SChristoph Hellwig struct xfs_log_iovec *log_vector) 3641da177e4SLinus Torvalds { 3657bfa31d8SChristoph Hellwig struct xfs_efd_log_item *efdp = EFD_ITEM(lip); 3661da177e4SLinus Torvalds uint size; 3671da177e4SLinus Torvalds 3681da177e4SLinus Torvalds ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents); 3691da177e4SLinus Torvalds 3701da177e4SLinus Torvalds efdp->efd_format.efd_type = XFS_LI_EFD; 3711da177e4SLinus Torvalds 3721da177e4SLinus Torvalds size = sizeof(xfs_efd_log_format_t); 3731da177e4SLinus Torvalds size += (efdp->efd_format.efd_nextents - 1) * sizeof(xfs_extent_t); 3741da177e4SLinus Torvalds efdp->efd_format.efd_size = 1; 3751da177e4SLinus Torvalds 3767bfa31d8SChristoph Hellwig log_vector->i_addr = (xfs_caddr_t)&efdp->efd_format; 3771da177e4SLinus Torvalds log_vector->i_len = size; 3784139b3b3SChristoph Hellwig log_vector->i_type = XLOG_REG_TYPE_EFD_FORMAT; 3791da177e4SLinus Torvalds ASSERT(size >= sizeof(xfs_efd_log_format_t)); 3801da177e4SLinus Torvalds } 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds /* 3831da177e4SLinus Torvalds * Pinning has no meaning for an efd item, so just return. 3841da177e4SLinus Torvalds */ 3851da177e4SLinus Torvalds STATIC void 3867bfa31d8SChristoph Hellwig xfs_efd_item_pin( 3877bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 3881da177e4SLinus Torvalds { 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds /* 3921da177e4SLinus Torvalds * Since pinning has no meaning for an efd item, unpinning does 3931da177e4SLinus Torvalds * not either. 3941da177e4SLinus Torvalds */ 3951da177e4SLinus Torvalds STATIC void 3967bfa31d8SChristoph Hellwig xfs_efd_item_unpin( 3977bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 3987bfa31d8SChristoph Hellwig int remove) 3991da177e4SLinus Torvalds { 4001da177e4SLinus Torvalds } 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds /* 4031da177e4SLinus Torvalds * Efd items have no locking, so just return success. 4041da177e4SLinus Torvalds */ 4051da177e4SLinus Torvalds STATIC uint 4067bfa31d8SChristoph Hellwig xfs_efd_item_trylock( 4077bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 4081da177e4SLinus Torvalds { 4091da177e4SLinus Torvalds return XFS_ITEM_LOCKED; 4101da177e4SLinus Torvalds } 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds /* 4131da177e4SLinus Torvalds * Efd items have no locking or pushing, so return failure 4141da177e4SLinus Torvalds * so that the caller doesn't bother with us. 4151da177e4SLinus Torvalds */ 4161da177e4SLinus Torvalds STATIC void 4177bfa31d8SChristoph Hellwig xfs_efd_item_unlock( 4187bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 4191da177e4SLinus Torvalds { 4207bfa31d8SChristoph Hellwig if (lip->li_flags & XFS_LI_ABORTED) 4217bfa31d8SChristoph Hellwig xfs_efd_item_free(EFD_ITEM(lip)); 4221da177e4SLinus Torvalds } 4231da177e4SLinus Torvalds 4241da177e4SLinus Torvalds /* 4251da177e4SLinus Torvalds * When the efd item is committed to disk, all we need to do 4261da177e4SLinus Torvalds * is delete our reference to our partner efi item and then 4271da177e4SLinus Torvalds * free ourselves. Since we're freeing ourselves we must 4281da177e4SLinus Torvalds * return -1 to keep the transaction code from further referencing 4291da177e4SLinus Torvalds * this item. 4301da177e4SLinus Torvalds */ 4311da177e4SLinus Torvalds STATIC xfs_lsn_t 4327bfa31d8SChristoph Hellwig xfs_efd_item_committed( 4337bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 4347bfa31d8SChristoph Hellwig xfs_lsn_t lsn) 4351da177e4SLinus Torvalds { 4367bfa31d8SChristoph Hellwig struct xfs_efd_log_item *efdp = EFD_ITEM(lip); 4377bfa31d8SChristoph Hellwig 4381da177e4SLinus Torvalds /* 4391da177e4SLinus Torvalds * If we got a log I/O error, it's always the case that the LR with the 4401da177e4SLinus Torvalds * EFI got unpinned and freed before the EFD got aborted. 4411da177e4SLinus Torvalds */ 4427bfa31d8SChristoph Hellwig if (!(lip->li_flags & XFS_LI_ABORTED)) 4431da177e4SLinus Torvalds xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents); 4441da177e4SLinus Torvalds 4457d795ca3SChristoph Hellwig xfs_efd_item_free(efdp); 4461da177e4SLinus Torvalds return (xfs_lsn_t)-1; 4471da177e4SLinus Torvalds } 4481da177e4SLinus Torvalds 4491da177e4SLinus Torvalds /* 4501da177e4SLinus Torvalds * There isn't much you can do to push on an efd item. It is simply 4511da177e4SLinus Torvalds * stuck waiting for the log to be flushed to disk. 4521da177e4SLinus Torvalds */ 4531da177e4SLinus Torvalds STATIC void 4547bfa31d8SChristoph Hellwig xfs_efd_item_push( 4557bfa31d8SChristoph Hellwig struct xfs_log_item *lip) 4561da177e4SLinus Torvalds { 4571da177e4SLinus Torvalds } 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds /* 4601da177e4SLinus Torvalds * The EFD dependency tracking op doesn't do squat. It can't because 4611da177e4SLinus Torvalds * it doesn't know where the free extent is coming from. The dependency 4621da177e4SLinus Torvalds * tracking has to be handled by the "enclosing" metadata object. For 4631da177e4SLinus Torvalds * example, for inodes, the inode is locked throughout the extent freeing 4641da177e4SLinus Torvalds * so the dependency should be recorded there. 4651da177e4SLinus Torvalds */ 4661da177e4SLinus Torvalds STATIC void 4677bfa31d8SChristoph Hellwig xfs_efd_item_committing( 4687bfa31d8SChristoph Hellwig struct xfs_log_item *lip, 4697bfa31d8SChristoph Hellwig xfs_lsn_t lsn) 4701da177e4SLinus Torvalds { 4711da177e4SLinus Torvalds } 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds /* 4741da177e4SLinus Torvalds * This is the ops vector shared by all efd log items. 4751da177e4SLinus Torvalds */ 4767989cb8eSDavid Chinner static struct xfs_item_ops xfs_efd_item_ops = { 4777bfa31d8SChristoph Hellwig .iop_size = xfs_efd_item_size, 4787bfa31d8SChristoph Hellwig .iop_format = xfs_efd_item_format, 4797bfa31d8SChristoph Hellwig .iop_pin = xfs_efd_item_pin, 4807bfa31d8SChristoph Hellwig .iop_unpin = xfs_efd_item_unpin, 4817bfa31d8SChristoph Hellwig .iop_trylock = xfs_efd_item_trylock, 4827bfa31d8SChristoph Hellwig .iop_unlock = xfs_efd_item_unlock, 4837bfa31d8SChristoph Hellwig .iop_committed = xfs_efd_item_committed, 4847bfa31d8SChristoph Hellwig .iop_push = xfs_efd_item_push, 4857bfa31d8SChristoph Hellwig .iop_committing = xfs_efd_item_committing 4861da177e4SLinus Torvalds }; 4871da177e4SLinus Torvalds 4881da177e4SLinus Torvalds /* 4891da177e4SLinus Torvalds * Allocate and initialize an efd item with the given number of extents. 4901da177e4SLinus Torvalds */ 4917bfa31d8SChristoph Hellwig struct xfs_efd_log_item * 4927bfa31d8SChristoph Hellwig xfs_efd_init( 4937bfa31d8SChristoph Hellwig struct xfs_mount *mp, 4947bfa31d8SChristoph Hellwig struct xfs_efi_log_item *efip, 4951da177e4SLinus Torvalds uint nextents) 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds { 4987bfa31d8SChristoph Hellwig struct xfs_efd_log_item *efdp; 4991da177e4SLinus Torvalds uint size; 5001da177e4SLinus Torvalds 5011da177e4SLinus Torvalds ASSERT(nextents > 0); 5021da177e4SLinus Torvalds if (nextents > XFS_EFD_MAX_FAST_EXTENTS) { 5031da177e4SLinus Torvalds size = (uint)(sizeof(xfs_efd_log_item_t) + 5041da177e4SLinus Torvalds ((nextents - 1) * sizeof(xfs_extent_t))); 5057bfa31d8SChristoph Hellwig efdp = kmem_zalloc(size, KM_SLEEP); 5061da177e4SLinus Torvalds } else { 5077bfa31d8SChristoph Hellwig efdp = kmem_zone_zalloc(xfs_efd_zone, KM_SLEEP); 5081da177e4SLinus Torvalds } 5091da177e4SLinus Torvalds 51043f5efc5SDave Chinner xfs_log_item_init(mp, &efdp->efd_item, XFS_LI_EFD, &xfs_efd_item_ops); 5111da177e4SLinus Torvalds efdp->efd_efip = efip; 5121da177e4SLinus Torvalds efdp->efd_format.efd_nextents = nextents; 5131da177e4SLinus Torvalds efdp->efd_format.efd_efi_id = efip->efi_format.efi_id; 5141da177e4SLinus Torvalds 5157bfa31d8SChristoph Hellwig return efdp; 5161da177e4SLinus Torvalds } 517