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 351da177e4SLinus Torvalds STATIC void xfs_efi_item_unlock(xfs_efi_log_item_t *); 361da177e4SLinus Torvalds 377d795ca3SChristoph Hellwig void 387d795ca3SChristoph Hellwig xfs_efi_item_free(xfs_efi_log_item_t *efip) 397d795ca3SChristoph Hellwig { 407d795ca3SChristoph Hellwig int nexts = efip->efi_format.efi_nextents; 417d795ca3SChristoph Hellwig 427d795ca3SChristoph Hellwig if (nexts > XFS_EFI_MAX_FAST_EXTENTS) { 43f0e2d93cSDenys Vlasenko kmem_free(efip); 447d795ca3SChristoph Hellwig } else { 457d795ca3SChristoph Hellwig kmem_zone_free(xfs_efi_zone, efip); 467d795ca3SChristoph Hellwig } 477d795ca3SChristoph Hellwig } 481da177e4SLinus Torvalds 491da177e4SLinus Torvalds /* 501da177e4SLinus Torvalds * This returns the number of iovecs needed to log the given efi item. 511da177e4SLinus Torvalds * We only need 1 iovec for an efi item. It just logs the efi_log_format 521da177e4SLinus Torvalds * structure. 531da177e4SLinus Torvalds */ 541da177e4SLinus Torvalds /*ARGSUSED*/ 551da177e4SLinus Torvalds STATIC uint 561da177e4SLinus Torvalds xfs_efi_item_size(xfs_efi_log_item_t *efip) 571da177e4SLinus Torvalds { 581da177e4SLinus Torvalds return 1; 591da177e4SLinus Torvalds } 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds /* 621da177e4SLinus Torvalds * This is called to fill in the vector of log iovecs for the 631da177e4SLinus Torvalds * given efi log item. We use only 1 iovec, and we point that 641da177e4SLinus Torvalds * at the efi_log_format structure embedded in the efi item. 651da177e4SLinus Torvalds * It is at this point that we assert that all of the extent 661da177e4SLinus Torvalds * slots in the efi item have been filled. 671da177e4SLinus Torvalds */ 681da177e4SLinus Torvalds STATIC void 691da177e4SLinus Torvalds xfs_efi_item_format(xfs_efi_log_item_t *efip, 701da177e4SLinus Torvalds xfs_log_iovec_t *log_vector) 711da177e4SLinus Torvalds { 721da177e4SLinus Torvalds uint size; 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds ASSERT(efip->efi_next_extent == efip->efi_format.efi_nextents); 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds efip->efi_format.efi_type = XFS_LI_EFI; 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds size = sizeof(xfs_efi_log_format_t); 791da177e4SLinus Torvalds size += (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t); 801da177e4SLinus Torvalds efip->efi_format.efi_size = 1; 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds log_vector->i_addr = (xfs_caddr_t)&(efip->efi_format); 831da177e4SLinus Torvalds log_vector->i_len = size; 844139b3b3SChristoph Hellwig log_vector->i_type = XLOG_REG_TYPE_EFI_FORMAT; 851da177e4SLinus Torvalds ASSERT(size >= sizeof(xfs_efi_log_format_t)); 861da177e4SLinus Torvalds } 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds /* 901da177e4SLinus Torvalds * Pinning has no meaning for an efi item, so just return. 911da177e4SLinus Torvalds */ 921da177e4SLinus Torvalds /*ARGSUSED*/ 931da177e4SLinus Torvalds STATIC void 941da177e4SLinus Torvalds xfs_efi_item_pin(xfs_efi_log_item_t *efip) 951da177e4SLinus Torvalds { 961da177e4SLinus Torvalds return; 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds /* 1011da177e4SLinus Torvalds * While EFIs cannot really be pinned, the unpin operation is the 1021da177e4SLinus Torvalds * last place at which the EFI is manipulated during a transaction. 1031da177e4SLinus Torvalds * Here we coordinate with xfs_efi_cancel() to determine who gets to 1041da177e4SLinus Torvalds * free the EFI. 1051da177e4SLinus Torvalds */ 1061da177e4SLinus Torvalds STATIC void 1079412e318SChristoph Hellwig xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int remove) 1081da177e4SLinus Torvalds { 109783a2f65SDavid Chinner struct xfs_ail *ailp = efip->efi_item.li_ailp; 1101da177e4SLinus Torvalds 111fc1829f3SDavid Chinner spin_lock(&ailp->xa_lock); 1121da177e4SLinus Torvalds if (efip->efi_flags & XFS_EFI_CANCELED) { 113e98c414fSChristoph Hellwig struct xfs_log_item *lip = &efip->efi_item; 114e98c414fSChristoph Hellwig 1159412e318SChristoph Hellwig if (remove) 116e98c414fSChristoph Hellwig xfs_trans_del_item(lip); 117783a2f65SDavid Chinner 118783a2f65SDavid Chinner /* xfs_trans_ail_delete() drops the AIL lock. */ 119e98c414fSChristoph Hellwig xfs_trans_ail_delete(ailp, lip); 1207d795ca3SChristoph Hellwig xfs_efi_item_free(efip); 1211da177e4SLinus Torvalds } else { 1221da177e4SLinus Torvalds efip->efi_flags |= XFS_EFI_COMMITTED; 123fc1829f3SDavid Chinner spin_unlock(&ailp->xa_lock); 1241da177e4SLinus Torvalds } 1251da177e4SLinus Torvalds } 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds /* 1281da177e4SLinus Torvalds * Efi items have no locking or pushing. However, since EFIs are 1291da177e4SLinus Torvalds * pulled from the AIL when their corresponding EFDs are committed 1301da177e4SLinus Torvalds * to disk, their situation is very similar to being pinned. Return 1311da177e4SLinus Torvalds * XFS_ITEM_PINNED so that the caller will eventually flush the log. 1321da177e4SLinus Torvalds * This should help in getting the EFI out of the AIL. 1331da177e4SLinus Torvalds */ 1341da177e4SLinus Torvalds /*ARGSUSED*/ 1351da177e4SLinus Torvalds STATIC uint 1361da177e4SLinus Torvalds xfs_efi_item_trylock(xfs_efi_log_item_t *efip) 1371da177e4SLinus Torvalds { 1381da177e4SLinus Torvalds return XFS_ITEM_PINNED; 1391da177e4SLinus Torvalds } 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds /* 1421da177e4SLinus Torvalds * Efi items have no locking, so just return. 1431da177e4SLinus Torvalds */ 1441da177e4SLinus Torvalds /*ARGSUSED*/ 1451da177e4SLinus Torvalds STATIC void 1461da177e4SLinus Torvalds xfs_efi_item_unlock(xfs_efi_log_item_t *efip) 1471da177e4SLinus Torvalds { 1481da177e4SLinus Torvalds if (efip->efi_item.li_flags & XFS_LI_ABORTED) 149065d312eSEric Sandeen xfs_efi_item_free(efip); 1501da177e4SLinus Torvalds return; 1511da177e4SLinus Torvalds } 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds /* 1541da177e4SLinus Torvalds * The EFI is logged only once and cannot be moved in the log, so 1551da177e4SLinus Torvalds * simply return the lsn at which it's been logged. The canceled 1561da177e4SLinus Torvalds * flag is not paid any attention here. Checking for that is delayed 1571da177e4SLinus Torvalds * until the EFI is unpinned. 1581da177e4SLinus Torvalds */ 1591da177e4SLinus Torvalds /*ARGSUSED*/ 1601da177e4SLinus Torvalds STATIC xfs_lsn_t 1611da177e4SLinus Torvalds xfs_efi_item_committed(xfs_efi_log_item_t *efip, xfs_lsn_t lsn) 1621da177e4SLinus Torvalds { 1631da177e4SLinus Torvalds return lsn; 1641da177e4SLinus Torvalds } 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds /* 1671da177e4SLinus Torvalds * There isn't much you can do to push on an efi item. It is simply 1681da177e4SLinus Torvalds * stuck waiting for all of its corresponding efd items to be 1691da177e4SLinus Torvalds * committed to disk. 1701da177e4SLinus Torvalds */ 1711da177e4SLinus Torvalds /*ARGSUSED*/ 1721da177e4SLinus Torvalds STATIC void 1731da177e4SLinus Torvalds xfs_efi_item_push(xfs_efi_log_item_t *efip) 1741da177e4SLinus Torvalds { 1751da177e4SLinus Torvalds return; 1761da177e4SLinus Torvalds } 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds /* 1791da177e4SLinus Torvalds * The EFI dependency tracking op doesn't do squat. It can't because 1801da177e4SLinus Torvalds * it doesn't know where the free extent is coming from. The dependency 1811da177e4SLinus Torvalds * tracking has to be handled by the "enclosing" metadata object. For 1821da177e4SLinus Torvalds * example, for inodes, the inode is locked throughout the extent freeing 1831da177e4SLinus Torvalds * so the dependency should be recorded there. 1841da177e4SLinus Torvalds */ 1851da177e4SLinus Torvalds /*ARGSUSED*/ 1861da177e4SLinus Torvalds STATIC void 1871da177e4SLinus Torvalds xfs_efi_item_committing(xfs_efi_log_item_t *efip, xfs_lsn_t lsn) 1881da177e4SLinus Torvalds { 1891da177e4SLinus Torvalds return; 1901da177e4SLinus Torvalds } 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds /* 1931da177e4SLinus Torvalds * This is the ops vector shared by all efi log items. 1941da177e4SLinus Torvalds */ 1957989cb8eSDavid Chinner static struct xfs_item_ops xfs_efi_item_ops = { 1961da177e4SLinus Torvalds .iop_size = (uint(*)(xfs_log_item_t*))xfs_efi_item_size, 1971da177e4SLinus Torvalds .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) 1981da177e4SLinus Torvalds xfs_efi_item_format, 1991da177e4SLinus Torvalds .iop_pin = (void(*)(xfs_log_item_t*))xfs_efi_item_pin, 2009412e318SChristoph Hellwig .iop_unpin = (void(*)(xfs_log_item_t*, int))xfs_efi_item_unpin, 2011da177e4SLinus Torvalds .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_efi_item_trylock, 2021da177e4SLinus Torvalds .iop_unlock = (void(*)(xfs_log_item_t*))xfs_efi_item_unlock, 2031da177e4SLinus Torvalds .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) 2041da177e4SLinus Torvalds xfs_efi_item_committed, 2051da177e4SLinus Torvalds .iop_push = (void(*)(xfs_log_item_t*))xfs_efi_item_push, 2061da177e4SLinus Torvalds .iop_pushbuf = NULL, 2071da177e4SLinus Torvalds .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) 2081da177e4SLinus Torvalds xfs_efi_item_committing 2091da177e4SLinus Torvalds }; 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds /* 2131da177e4SLinus Torvalds * Allocate and initialize an efi item with the given number of extents. 2141da177e4SLinus Torvalds */ 2151da177e4SLinus Torvalds xfs_efi_log_item_t * 2161da177e4SLinus Torvalds xfs_efi_init(xfs_mount_t *mp, 2171da177e4SLinus Torvalds uint nextents) 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds { 2201da177e4SLinus Torvalds xfs_efi_log_item_t *efip; 2211da177e4SLinus Torvalds uint size; 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds ASSERT(nextents > 0); 2241da177e4SLinus Torvalds if (nextents > XFS_EFI_MAX_FAST_EXTENTS) { 2251da177e4SLinus Torvalds size = (uint)(sizeof(xfs_efi_log_item_t) + 2261da177e4SLinus Torvalds ((nextents - 1) * sizeof(xfs_extent_t))); 2271da177e4SLinus Torvalds efip = (xfs_efi_log_item_t*)kmem_zalloc(size, KM_SLEEP); 2281da177e4SLinus Torvalds } else { 2291da177e4SLinus Torvalds efip = (xfs_efi_log_item_t*)kmem_zone_zalloc(xfs_efi_zone, 2301da177e4SLinus Torvalds KM_SLEEP); 2311da177e4SLinus Torvalds } 2321da177e4SLinus Torvalds 23343f5efc5SDave Chinner xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops); 2341da177e4SLinus Torvalds efip->efi_format.efi_nextents = nextents; 2351da177e4SLinus Torvalds efip->efi_format.efi_id = (__psint_t)(void*)efip; 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds return (efip); 2381da177e4SLinus Torvalds } 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds /* 2416d192a9bSTim Shimmin * Copy an EFI format buffer from the given buf, and into the destination 2426d192a9bSTim Shimmin * EFI format structure. 2436d192a9bSTim Shimmin * The given buffer can be in 32 bit or 64 bit form (which has different padding), 2446d192a9bSTim Shimmin * one of which will be the native format for this kernel. 2456d192a9bSTim Shimmin * It will handle the conversion of formats if necessary. 2466d192a9bSTim Shimmin */ 2476d192a9bSTim Shimmin int 2486d192a9bSTim Shimmin xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) 2496d192a9bSTim Shimmin { 2506d192a9bSTim Shimmin xfs_efi_log_format_t *src_efi_fmt = (xfs_efi_log_format_t *)buf->i_addr; 2516d192a9bSTim Shimmin uint i; 2526d192a9bSTim Shimmin uint len = sizeof(xfs_efi_log_format_t) + 2536d192a9bSTim Shimmin (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t); 2546d192a9bSTim Shimmin uint len32 = sizeof(xfs_efi_log_format_32_t) + 2556d192a9bSTim Shimmin (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t); 2566d192a9bSTim Shimmin uint len64 = sizeof(xfs_efi_log_format_64_t) + 2576d192a9bSTim Shimmin (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t); 2586d192a9bSTim Shimmin 2596d192a9bSTim Shimmin if (buf->i_len == len) { 2606d192a9bSTim Shimmin memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len); 2616d192a9bSTim Shimmin return 0; 2626d192a9bSTim Shimmin } else if (buf->i_len == len32) { 2636d192a9bSTim Shimmin xfs_efi_log_format_32_t *src_efi_fmt_32 = 2646d192a9bSTim Shimmin (xfs_efi_log_format_32_t *)buf->i_addr; 2656d192a9bSTim Shimmin 2666d192a9bSTim Shimmin dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; 2676d192a9bSTim Shimmin dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; 2686d192a9bSTim Shimmin dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; 2696d192a9bSTim Shimmin dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; 2706d192a9bSTim Shimmin for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { 2716d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_start = 2726d192a9bSTim Shimmin src_efi_fmt_32->efi_extents[i].ext_start; 2736d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_len = 2746d192a9bSTim Shimmin src_efi_fmt_32->efi_extents[i].ext_len; 2756d192a9bSTim Shimmin } 2766d192a9bSTim Shimmin return 0; 2776d192a9bSTim Shimmin } else if (buf->i_len == len64) { 2786d192a9bSTim Shimmin xfs_efi_log_format_64_t *src_efi_fmt_64 = 2796d192a9bSTim Shimmin (xfs_efi_log_format_64_t *)buf->i_addr; 2806d192a9bSTim Shimmin 2816d192a9bSTim Shimmin dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; 2826d192a9bSTim Shimmin dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; 2836d192a9bSTim Shimmin dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; 2846d192a9bSTim Shimmin dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; 2856d192a9bSTim Shimmin for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { 2866d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_start = 2876d192a9bSTim Shimmin src_efi_fmt_64->efi_extents[i].ext_start; 2886d192a9bSTim Shimmin dst_efi_fmt->efi_extents[i].ext_len = 2896d192a9bSTim Shimmin src_efi_fmt_64->efi_extents[i].ext_len; 2906d192a9bSTim Shimmin } 2916d192a9bSTim Shimmin return 0; 2926d192a9bSTim Shimmin } 2936d192a9bSTim Shimmin return EFSCORRUPTED; 2946d192a9bSTim Shimmin } 2956d192a9bSTim Shimmin 2966d192a9bSTim Shimmin /* 2971da177e4SLinus Torvalds * This is called by the efd item code below to release references to 2981da177e4SLinus Torvalds * the given efi item. Each efd calls this with the number of 2991da177e4SLinus Torvalds * extents that it has logged, and when the sum of these reaches 3001da177e4SLinus Torvalds * the total number of extents logged by this efi item we can free 3011da177e4SLinus Torvalds * the efi item. 3021da177e4SLinus Torvalds * 3031da177e4SLinus Torvalds * Freeing the efi item requires that we remove it from the AIL. 3041da177e4SLinus Torvalds * We'll use the AIL lock to protect our counters as well as 3051da177e4SLinus Torvalds * the removal from the AIL. 3061da177e4SLinus Torvalds */ 3071da177e4SLinus Torvalds void 3081da177e4SLinus Torvalds xfs_efi_release(xfs_efi_log_item_t *efip, 3091da177e4SLinus Torvalds uint nextents) 3101da177e4SLinus Torvalds { 311783a2f65SDavid Chinner struct xfs_ail *ailp = efip->efi_item.li_ailp; 3121da177e4SLinus Torvalds int extents_left; 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds ASSERT(efip->efi_next_extent > 0); 3151da177e4SLinus Torvalds ASSERT(efip->efi_flags & XFS_EFI_COMMITTED); 3161da177e4SLinus Torvalds 317fc1829f3SDavid Chinner spin_lock(&ailp->xa_lock); 3181da177e4SLinus Torvalds ASSERT(efip->efi_next_extent >= nextents); 3191da177e4SLinus Torvalds efip->efi_next_extent -= nextents; 3201da177e4SLinus Torvalds extents_left = efip->efi_next_extent; 3211da177e4SLinus Torvalds if (extents_left == 0) { 322783a2f65SDavid Chinner /* xfs_trans_ail_delete() drops the AIL lock. */ 323783a2f65SDavid Chinner xfs_trans_ail_delete(ailp, (xfs_log_item_t *)efip); 3247d795ca3SChristoph Hellwig xfs_efi_item_free(efip); 3251da177e4SLinus Torvalds } else { 326fc1829f3SDavid Chinner spin_unlock(&ailp->xa_lock); 3271da177e4SLinus Torvalds } 3281da177e4SLinus Torvalds } 3291da177e4SLinus Torvalds 3307d795ca3SChristoph Hellwig STATIC void 3317d795ca3SChristoph Hellwig xfs_efd_item_free(xfs_efd_log_item_t *efdp) 3327d795ca3SChristoph Hellwig { 3337d795ca3SChristoph Hellwig int nexts = efdp->efd_format.efd_nextents; 3341da177e4SLinus Torvalds 3357d795ca3SChristoph Hellwig if (nexts > XFS_EFD_MAX_FAST_EXTENTS) { 336f0e2d93cSDenys Vlasenko kmem_free(efdp); 3377d795ca3SChristoph Hellwig } else { 3387d795ca3SChristoph Hellwig kmem_zone_free(xfs_efd_zone, efdp); 3397d795ca3SChristoph Hellwig } 3407d795ca3SChristoph Hellwig } 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds /* 3431da177e4SLinus Torvalds * This returns the number of iovecs needed to log the given efd item. 3441da177e4SLinus Torvalds * We only need 1 iovec for an efd item. It just logs the efd_log_format 3451da177e4SLinus Torvalds * structure. 3461da177e4SLinus Torvalds */ 3471da177e4SLinus Torvalds /*ARGSUSED*/ 3481da177e4SLinus Torvalds STATIC uint 3491da177e4SLinus Torvalds xfs_efd_item_size(xfs_efd_log_item_t *efdp) 3501da177e4SLinus Torvalds { 3511da177e4SLinus Torvalds return 1; 3521da177e4SLinus Torvalds } 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds /* 3551da177e4SLinus Torvalds * This is called to fill in the vector of log iovecs for the 3561da177e4SLinus Torvalds * given efd log item. We use only 1 iovec, and we point that 3571da177e4SLinus Torvalds * at the efd_log_format structure embedded in the efd item. 3581da177e4SLinus Torvalds * It is at this point that we assert that all of the extent 3591da177e4SLinus Torvalds * slots in the efd item have been filled. 3601da177e4SLinus Torvalds */ 3611da177e4SLinus Torvalds STATIC void 3621da177e4SLinus Torvalds xfs_efd_item_format(xfs_efd_log_item_t *efdp, 3631da177e4SLinus Torvalds xfs_log_iovec_t *log_vector) 3641da177e4SLinus Torvalds { 3651da177e4SLinus Torvalds uint size; 3661da177e4SLinus Torvalds 3671da177e4SLinus Torvalds ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents); 3681da177e4SLinus Torvalds 3691da177e4SLinus Torvalds efdp->efd_format.efd_type = XFS_LI_EFD; 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds size = sizeof(xfs_efd_log_format_t); 3721da177e4SLinus Torvalds size += (efdp->efd_format.efd_nextents - 1) * sizeof(xfs_extent_t); 3731da177e4SLinus Torvalds efdp->efd_format.efd_size = 1; 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds log_vector->i_addr = (xfs_caddr_t)&(efdp->efd_format); 3761da177e4SLinus Torvalds log_vector->i_len = size; 3774139b3b3SChristoph Hellwig log_vector->i_type = XLOG_REG_TYPE_EFD_FORMAT; 3781da177e4SLinus Torvalds ASSERT(size >= sizeof(xfs_efd_log_format_t)); 3791da177e4SLinus Torvalds } 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds /* 3831da177e4SLinus Torvalds * Pinning has no meaning for an efd item, so just return. 3841da177e4SLinus Torvalds */ 3851da177e4SLinus Torvalds /*ARGSUSED*/ 3861da177e4SLinus Torvalds STATIC void 3871da177e4SLinus Torvalds xfs_efd_item_pin(xfs_efd_log_item_t *efdp) 3881da177e4SLinus Torvalds { 3891da177e4SLinus Torvalds return; 3901da177e4SLinus Torvalds } 3911da177e4SLinus Torvalds 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds /* 3941da177e4SLinus Torvalds * Since pinning has no meaning for an efd item, unpinning does 3951da177e4SLinus Torvalds * not either. 3961da177e4SLinus Torvalds */ 3971da177e4SLinus Torvalds /*ARGSUSED*/ 3981da177e4SLinus Torvalds STATIC void 3999412e318SChristoph Hellwig xfs_efd_item_unpin(xfs_efd_log_item_t *efdp, int remove) 4001da177e4SLinus Torvalds { 4011da177e4SLinus Torvalds return; 4021da177e4SLinus Torvalds } 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds /* 4051da177e4SLinus Torvalds * Efd items have no locking, so just return success. 4061da177e4SLinus Torvalds */ 4071da177e4SLinus Torvalds /*ARGSUSED*/ 4081da177e4SLinus Torvalds STATIC uint 4091da177e4SLinus Torvalds xfs_efd_item_trylock(xfs_efd_log_item_t *efdp) 4101da177e4SLinus Torvalds { 4111da177e4SLinus Torvalds return XFS_ITEM_LOCKED; 4121da177e4SLinus Torvalds } 4131da177e4SLinus Torvalds 4141da177e4SLinus Torvalds /* 4151da177e4SLinus Torvalds * Efd items have no locking or pushing, so return failure 4161da177e4SLinus Torvalds * so that the caller doesn't bother with us. 4171da177e4SLinus Torvalds */ 4181da177e4SLinus Torvalds /*ARGSUSED*/ 4191da177e4SLinus Torvalds STATIC void 4201da177e4SLinus Torvalds xfs_efd_item_unlock(xfs_efd_log_item_t *efdp) 4211da177e4SLinus Torvalds { 4221da177e4SLinus Torvalds if (efdp->efd_item.li_flags & XFS_LI_ABORTED) 423065d312eSEric Sandeen xfs_efd_item_free(efdp); 4241da177e4SLinus Torvalds return; 4251da177e4SLinus Torvalds } 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds /* 4281da177e4SLinus Torvalds * When the efd item is committed to disk, all we need to do 4291da177e4SLinus Torvalds * is delete our reference to our partner efi item and then 4301da177e4SLinus Torvalds * free ourselves. Since we're freeing ourselves we must 4311da177e4SLinus Torvalds * return -1 to keep the transaction code from further referencing 4321da177e4SLinus Torvalds * this item. 4331da177e4SLinus Torvalds */ 4341da177e4SLinus Torvalds /*ARGSUSED*/ 4351da177e4SLinus Torvalds STATIC xfs_lsn_t 4361da177e4SLinus Torvalds xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn) 4371da177e4SLinus Torvalds { 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 */ 4421da177e4SLinus Torvalds if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0) 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 /*ARGSUSED*/ 4541da177e4SLinus Torvalds STATIC void 4551da177e4SLinus Torvalds xfs_efd_item_push(xfs_efd_log_item_t *efdp) 4561da177e4SLinus Torvalds { 4571da177e4SLinus Torvalds return; 4581da177e4SLinus Torvalds } 4591da177e4SLinus Torvalds 4601da177e4SLinus Torvalds /* 4611da177e4SLinus Torvalds * The EFD dependency tracking op doesn't do squat. It can't because 4621da177e4SLinus Torvalds * it doesn't know where the free extent is coming from. The dependency 4631da177e4SLinus Torvalds * tracking has to be handled by the "enclosing" metadata object. For 4641da177e4SLinus Torvalds * example, for inodes, the inode is locked throughout the extent freeing 4651da177e4SLinus Torvalds * so the dependency should be recorded there. 4661da177e4SLinus Torvalds */ 4671da177e4SLinus Torvalds /*ARGSUSED*/ 4681da177e4SLinus Torvalds STATIC void 4691da177e4SLinus Torvalds xfs_efd_item_committing(xfs_efd_log_item_t *efip, xfs_lsn_t lsn) 4701da177e4SLinus Torvalds { 4711da177e4SLinus Torvalds return; 4721da177e4SLinus Torvalds } 4731da177e4SLinus Torvalds 4741da177e4SLinus Torvalds /* 4751da177e4SLinus Torvalds * This is the ops vector shared by all efd log items. 4761da177e4SLinus Torvalds */ 4777989cb8eSDavid Chinner static struct xfs_item_ops xfs_efd_item_ops = { 4781da177e4SLinus Torvalds .iop_size = (uint(*)(xfs_log_item_t*))xfs_efd_item_size, 4791da177e4SLinus Torvalds .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) 4801da177e4SLinus Torvalds xfs_efd_item_format, 4811da177e4SLinus Torvalds .iop_pin = (void(*)(xfs_log_item_t*))xfs_efd_item_pin, 4829412e318SChristoph Hellwig .iop_unpin = (void(*)(xfs_log_item_t*, int))xfs_efd_item_unpin, 4831da177e4SLinus Torvalds .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_efd_item_trylock, 4841da177e4SLinus Torvalds .iop_unlock = (void(*)(xfs_log_item_t*))xfs_efd_item_unlock, 4851da177e4SLinus Torvalds .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) 4861da177e4SLinus Torvalds xfs_efd_item_committed, 4871da177e4SLinus Torvalds .iop_push = (void(*)(xfs_log_item_t*))xfs_efd_item_push, 4881da177e4SLinus Torvalds .iop_pushbuf = NULL, 4891da177e4SLinus Torvalds .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) 4901da177e4SLinus Torvalds xfs_efd_item_committing 4911da177e4SLinus Torvalds }; 4921da177e4SLinus Torvalds 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds /* 4951da177e4SLinus Torvalds * Allocate and initialize an efd item with the given number of extents. 4961da177e4SLinus Torvalds */ 4971da177e4SLinus Torvalds xfs_efd_log_item_t * 4981da177e4SLinus Torvalds xfs_efd_init(xfs_mount_t *mp, 4991da177e4SLinus Torvalds xfs_efi_log_item_t *efip, 5001da177e4SLinus Torvalds uint nextents) 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds { 5031da177e4SLinus Torvalds xfs_efd_log_item_t *efdp; 5041da177e4SLinus Torvalds uint size; 5051da177e4SLinus Torvalds 5061da177e4SLinus Torvalds ASSERT(nextents > 0); 5071da177e4SLinus Torvalds if (nextents > XFS_EFD_MAX_FAST_EXTENTS) { 5081da177e4SLinus Torvalds size = (uint)(sizeof(xfs_efd_log_item_t) + 5091da177e4SLinus Torvalds ((nextents - 1) * sizeof(xfs_extent_t))); 5101da177e4SLinus Torvalds efdp = (xfs_efd_log_item_t*)kmem_zalloc(size, KM_SLEEP); 5111da177e4SLinus Torvalds } else { 5121da177e4SLinus Torvalds efdp = (xfs_efd_log_item_t*)kmem_zone_zalloc(xfs_efd_zone, 5131da177e4SLinus Torvalds KM_SLEEP); 5141da177e4SLinus Torvalds } 5151da177e4SLinus Torvalds 51643f5efc5SDave Chinner xfs_log_item_init(mp, &efdp->efd_item, XFS_LI_EFD, &xfs_efd_item_ops); 5171da177e4SLinus Torvalds efdp->efd_efip = efip; 5181da177e4SLinus Torvalds efdp->efd_format.efd_nextents = nextents; 5191da177e4SLinus Torvalds efdp->efd_format.efd_efi_id = efip->efi_format.efi_id; 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds return (efdp); 5221da177e4SLinus Torvalds } 523