11da177e4SLinus Torvalds /* 27b718769SNathan Scott * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 3e98c414fSChristoph Hellwig * Copyright (C) 2010 Red Hat, Inc. 47b718769SNathan Scott * All Rights Reserved. 51da177e4SLinus Torvalds * 67b718769SNathan Scott * This program is free software; you can redistribute it and/or 77b718769SNathan Scott * modify it under the terms of the GNU General Public License as 81da177e4SLinus Torvalds * published by the Free Software Foundation. 91da177e4SLinus Torvalds * 107b718769SNathan Scott * This program is distributed in the hope that it would be useful, 117b718769SNathan Scott * but WITHOUT ANY WARRANTY; without even the implied warranty of 127b718769SNathan Scott * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 137b718769SNathan Scott * GNU General Public License for more details. 141da177e4SLinus Torvalds * 157b718769SNathan Scott * You should have received a copy of the GNU General Public License 167b718769SNathan Scott * along with this program; if not, write the Free Software Foundation, 177b718769SNathan Scott * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 181da177e4SLinus Torvalds */ 191da177e4SLinus Torvalds #include "xfs.h" 20a844f451SNathan Scott #include "xfs_fs.h" 211da177e4SLinus Torvalds #include "xfs_types.h" 221da177e4SLinus Torvalds #include "xfs_log.h" 231da177e4SLinus Torvalds #include "xfs_trans.h" 241da177e4SLinus Torvalds #include "xfs_sb.h" 251da177e4SLinus Torvalds #include "xfs_ag.h" 261da177e4SLinus Torvalds #include "xfs_mount.h" 271da177e4SLinus Torvalds #include "xfs_error.h" 28a844f451SNathan Scott #include "xfs_da_btree.h" 291da177e4SLinus Torvalds #include "xfs_bmap_btree.h" 30a844f451SNathan Scott #include "xfs_alloc_btree.h" 311da177e4SLinus Torvalds #include "xfs_ialloc_btree.h" 32a844f451SNathan Scott #include "xfs_dinode.h" 33a844f451SNathan Scott #include "xfs_inode.h" 341da177e4SLinus Torvalds #include "xfs_btree.h" 351da177e4SLinus Torvalds #include "xfs_ialloc.h" 361da177e4SLinus Torvalds #include "xfs_alloc.h" 37efc27b52SDave Chinner #include "xfs_extent_busy.h" 381da177e4SLinus Torvalds #include "xfs_bmap.h" 391da177e4SLinus Torvalds #include "xfs_quota.h" 40a844f451SNathan Scott #include "xfs_trans_priv.h" 411da177e4SLinus Torvalds #include "xfs_trans_space.h" 42322ff6b8SNiv Sardi #include "xfs_inode_item.h" 43ed3b4d6cSDave Chinner #include "xfs_trace.h" 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds kmem_zone_t *xfs_trans_zone; 46e98c414fSChristoph Hellwig kmem_zone_t *xfs_log_item_desc_zone; 471da177e4SLinus Torvalds 48025101dcSChristoph Hellwig 491da177e4SLinus Torvalds /* 50025101dcSChristoph Hellwig * Various log reservation values. 51025101dcSChristoph Hellwig * 52025101dcSChristoph Hellwig * These are based on the size of the file system block because that is what 53025101dcSChristoph Hellwig * most transactions manipulate. Each adds in an additional 128 bytes per 54025101dcSChristoph Hellwig * item logged to try to account for the overhead of the transaction mechanism. 55025101dcSChristoph Hellwig * 56025101dcSChristoph Hellwig * Note: Most of the reservations underestimate the number of allocation 57025101dcSChristoph Hellwig * groups into which they could free extents in the xfs_bmap_finish() call. 58025101dcSChristoph Hellwig * This is because the number in the worst case is quite high and quite 59025101dcSChristoph Hellwig * unusual. In order to fix this we need to change xfs_bmap_finish() to free 60025101dcSChristoph Hellwig * extents in only a single AG at a time. This will require changes to the 61025101dcSChristoph Hellwig * EFI code as well, however, so that the EFI for the extents not freed is 62025101dcSChristoph Hellwig * logged again in each transaction. See SGI PV #261917. 63025101dcSChristoph Hellwig * 64025101dcSChristoph Hellwig * Reservation functions here avoid a huge stack in xfs_trans_init due to 65025101dcSChristoph Hellwig * register overflow from temporaries in the calculations. 66025101dcSChristoph Hellwig */ 67025101dcSChristoph Hellwig 68025101dcSChristoph Hellwig 69025101dcSChristoph Hellwig /* 70025101dcSChristoph Hellwig * In a write transaction we can allocate a maximum of 2 71025101dcSChristoph Hellwig * extents. This gives: 72025101dcSChristoph Hellwig * the inode getting the new extents: inode size 73025101dcSChristoph Hellwig * the inode's bmap btree: max depth * block size 74025101dcSChristoph Hellwig * the agfs of the ags from which the extents are allocated: 2 * sector 75025101dcSChristoph Hellwig * the superblock free block counter: sector size 76025101dcSChristoph Hellwig * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size 77025101dcSChristoph Hellwig * And the bmap_finish transaction can free bmap blocks in a join: 78025101dcSChristoph Hellwig * the agfs of the ags containing the blocks: 2 * sector size 79025101dcSChristoph Hellwig * the agfls of the ags containing the blocks: 2 * sector size 80025101dcSChristoph Hellwig * the super block free block counter: sector size 81025101dcSChristoph Hellwig * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size 828f794055SNathan Scott */ 838f794055SNathan Scott STATIC uint 84025101dcSChristoph Hellwig xfs_calc_write_reservation( 85025101dcSChristoph Hellwig struct xfs_mount *mp) 868f794055SNathan Scott { 87025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 88025101dcSChristoph Hellwig MAX((mp->m_sb.sb_inodesize + 89025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + 90025101dcSChristoph Hellwig 2 * mp->m_sb.sb_sectsize + 91025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 92025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 2) + 93025101dcSChristoph Hellwig 128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 94025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_COUNT(mp, 2))), 95025101dcSChristoph Hellwig (2 * mp->m_sb.sb_sectsize + 96025101dcSChristoph Hellwig 2 * mp->m_sb.sb_sectsize + 97025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 98025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 2) + 99025101dcSChristoph Hellwig 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2)))); 1008f794055SNathan Scott } 1018f794055SNathan Scott 102025101dcSChristoph Hellwig /* 103025101dcSChristoph Hellwig * In truncating a file we free up to two extents at once. We can modify: 104025101dcSChristoph Hellwig * the inode being truncated: inode size 105025101dcSChristoph Hellwig * the inode's bmap btree: (max depth + 1) * block size 106025101dcSChristoph Hellwig * And the bmap_finish transaction can free the blocks and bmap blocks: 107025101dcSChristoph Hellwig * the agf for each of the ags: 4 * sector size 108025101dcSChristoph Hellwig * the agfl for each of the ags: 4 * sector size 109025101dcSChristoph Hellwig * the super block to reflect the freed blocks: sector size 110025101dcSChristoph Hellwig * worst case split in allocation btrees per extent assuming 4 extents: 111025101dcSChristoph Hellwig * 4 exts * 2 trees * (2 * max depth - 1) * block size 112025101dcSChristoph Hellwig * the inode btree: max depth * blocksize 113025101dcSChristoph Hellwig * the allocation btrees: 2 trees * (max depth - 1) * block size 114025101dcSChristoph Hellwig */ 1158f794055SNathan Scott STATIC uint 116025101dcSChristoph Hellwig xfs_calc_itruncate_reservation( 117025101dcSChristoph Hellwig struct xfs_mount *mp) 1188f794055SNathan Scott { 119025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 120025101dcSChristoph Hellwig MAX((mp->m_sb.sb_inodesize + 121025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) + 122025101dcSChristoph Hellwig 128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))), 123025101dcSChristoph Hellwig (4 * mp->m_sb.sb_sectsize + 124025101dcSChristoph Hellwig 4 * mp->m_sb.sb_sectsize + 125025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 126025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 4) + 127025101dcSChristoph Hellwig 128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4)) + 128025101dcSChristoph Hellwig 128 * 5 + 129025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 1) + 130025101dcSChristoph Hellwig 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels + 131025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_COUNT(mp, 1)))); 1328f794055SNathan Scott } 1338f794055SNathan Scott 134025101dcSChristoph Hellwig /* 135025101dcSChristoph Hellwig * In renaming a files we can modify: 136025101dcSChristoph Hellwig * the four inodes involved: 4 * inode size 137025101dcSChristoph Hellwig * the two directory btrees: 2 * (max depth + v2) * dir block size 138025101dcSChristoph Hellwig * the two directory bmap btrees: 2 * max depth * block size 139025101dcSChristoph Hellwig * And the bmap_finish transaction can free dir and bmap blocks (two sets 140025101dcSChristoph Hellwig * of bmap blocks) giving: 141025101dcSChristoph Hellwig * the agf for the ags in which the blocks live: 3 * sector size 142025101dcSChristoph Hellwig * the agfl for the ags in which the blocks live: 3 * sector size 143025101dcSChristoph Hellwig * the superblock for the free block count: sector size 144025101dcSChristoph Hellwig * the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size 145025101dcSChristoph Hellwig */ 1468f794055SNathan Scott STATIC uint 147025101dcSChristoph Hellwig xfs_calc_rename_reservation( 148025101dcSChristoph Hellwig struct xfs_mount *mp) 1498f794055SNathan Scott { 150025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 151025101dcSChristoph Hellwig MAX((4 * mp->m_sb.sb_inodesize + 152025101dcSChristoph Hellwig 2 * XFS_DIROP_LOG_RES(mp) + 153025101dcSChristoph Hellwig 128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp))), 154025101dcSChristoph Hellwig (3 * mp->m_sb.sb_sectsize + 155025101dcSChristoph Hellwig 3 * mp->m_sb.sb_sectsize + 156025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 157025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 3) + 158025101dcSChristoph Hellwig 128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3)))); 1598f794055SNathan Scott } 1608f794055SNathan Scott 161025101dcSChristoph Hellwig /* 162025101dcSChristoph Hellwig * For creating a link to an inode: 163025101dcSChristoph Hellwig * the parent directory inode: inode size 164025101dcSChristoph Hellwig * the linked inode: inode size 165025101dcSChristoph Hellwig * the directory btree could split: (max depth + v2) * dir block size 166025101dcSChristoph Hellwig * the directory bmap btree could join or split: (max depth + v2) * blocksize 167025101dcSChristoph Hellwig * And the bmap_finish transaction can free some bmap blocks giving: 168025101dcSChristoph Hellwig * the agf for the ag in which the blocks live: sector size 169025101dcSChristoph Hellwig * the agfl for the ag in which the blocks live: sector size 170025101dcSChristoph Hellwig * the superblock for the free block count: sector size 171025101dcSChristoph Hellwig * the allocation btrees: 2 trees * (2 * max depth - 1) * block size 172025101dcSChristoph Hellwig */ 1738f794055SNathan Scott STATIC uint 174025101dcSChristoph Hellwig xfs_calc_link_reservation( 175025101dcSChristoph Hellwig struct xfs_mount *mp) 1768f794055SNathan Scott { 177025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 178025101dcSChristoph Hellwig MAX((mp->m_sb.sb_inodesize + 179025101dcSChristoph Hellwig mp->m_sb.sb_inodesize + 180025101dcSChristoph Hellwig XFS_DIROP_LOG_RES(mp) + 181025101dcSChristoph Hellwig 128 * (2 + XFS_DIROP_LOG_COUNT(mp))), 182025101dcSChristoph Hellwig (mp->m_sb.sb_sectsize + 183025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 184025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 185025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 1) + 186025101dcSChristoph Hellwig 128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1)))); 1878f794055SNathan Scott } 1888f794055SNathan Scott 189025101dcSChristoph Hellwig /* 190025101dcSChristoph Hellwig * For removing a directory entry we can modify: 191025101dcSChristoph Hellwig * the parent directory inode: inode size 192025101dcSChristoph Hellwig * the removed inode: inode size 193025101dcSChristoph Hellwig * the directory btree could join: (max depth + v2) * dir block size 194025101dcSChristoph Hellwig * the directory bmap btree could join or split: (max depth + v2) * blocksize 195025101dcSChristoph Hellwig * And the bmap_finish transaction can free the dir and bmap blocks giving: 196025101dcSChristoph Hellwig * the agf for the ag in which the blocks live: 2 * sector size 197025101dcSChristoph Hellwig * the agfl for the ag in which the blocks live: 2 * sector size 198025101dcSChristoph Hellwig * the superblock for the free block count: sector size 199025101dcSChristoph Hellwig * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size 200025101dcSChristoph Hellwig */ 2018f794055SNathan Scott STATIC uint 202025101dcSChristoph Hellwig xfs_calc_remove_reservation( 203025101dcSChristoph Hellwig struct xfs_mount *mp) 2048f794055SNathan Scott { 205025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 206025101dcSChristoph Hellwig MAX((mp->m_sb.sb_inodesize + 207025101dcSChristoph Hellwig mp->m_sb.sb_inodesize + 208025101dcSChristoph Hellwig XFS_DIROP_LOG_RES(mp) + 209025101dcSChristoph Hellwig 128 * (2 + XFS_DIROP_LOG_COUNT(mp))), 210025101dcSChristoph Hellwig (2 * mp->m_sb.sb_sectsize + 211025101dcSChristoph Hellwig 2 * mp->m_sb.sb_sectsize + 212025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 213025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 2) + 214025101dcSChristoph Hellwig 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2)))); 2158f794055SNathan Scott } 2168f794055SNathan Scott 217025101dcSChristoph Hellwig /* 218025101dcSChristoph Hellwig * For symlink we can modify: 219025101dcSChristoph Hellwig * the parent directory inode: inode size 220025101dcSChristoph Hellwig * the new inode: inode size 221025101dcSChristoph Hellwig * the inode btree entry: 1 block 222025101dcSChristoph Hellwig * the directory btree: (max depth + v2) * dir block size 223025101dcSChristoph Hellwig * the directory inode's bmap btree: (max depth + v2) * block size 224025101dcSChristoph Hellwig * the blocks for the symlink: 1 kB 225025101dcSChristoph Hellwig * Or in the first xact we allocate some inodes giving: 226025101dcSChristoph Hellwig * the agi and agf of the ag getting the new inodes: 2 * sectorsize 227025101dcSChristoph Hellwig * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize 228025101dcSChristoph Hellwig * the inode btree: max depth * blocksize 229025101dcSChristoph Hellwig * the allocation btrees: 2 trees * (2 * max depth - 1) * block size 230025101dcSChristoph Hellwig */ 2318f794055SNathan Scott STATIC uint 232025101dcSChristoph Hellwig xfs_calc_symlink_reservation( 233025101dcSChristoph Hellwig struct xfs_mount *mp) 2348f794055SNathan Scott { 235025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 236025101dcSChristoph Hellwig MAX((mp->m_sb.sb_inodesize + 237025101dcSChristoph Hellwig mp->m_sb.sb_inodesize + 238025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, 1) + 239025101dcSChristoph Hellwig XFS_DIROP_LOG_RES(mp) + 240025101dcSChristoph Hellwig 1024 + 241025101dcSChristoph Hellwig 128 * (4 + XFS_DIROP_LOG_COUNT(mp))), 242025101dcSChristoph Hellwig (2 * mp->m_sb.sb_sectsize + 243025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) + 244025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, mp->m_in_maxlevels) + 245025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 1) + 246025101dcSChristoph Hellwig 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels + 247025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_COUNT(mp, 1)))); 2488f794055SNathan Scott } 2498f794055SNathan Scott 250025101dcSChristoph Hellwig /* 251025101dcSChristoph Hellwig * For create we can modify: 252025101dcSChristoph Hellwig * the parent directory inode: inode size 253025101dcSChristoph Hellwig * the new inode: inode size 254025101dcSChristoph Hellwig * the inode btree entry: block size 255025101dcSChristoph Hellwig * the superblock for the nlink flag: sector size 256025101dcSChristoph Hellwig * the directory btree: (max depth + v2) * dir block size 257025101dcSChristoph Hellwig * the directory inode's bmap btree: (max depth + v2) * block size 258025101dcSChristoph Hellwig * Or in the first xact we allocate some inodes giving: 259025101dcSChristoph Hellwig * the agi and agf of the ag getting the new inodes: 2 * sectorsize 260025101dcSChristoph Hellwig * the superblock for the nlink flag: sector size 261025101dcSChristoph Hellwig * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize 262025101dcSChristoph Hellwig * the inode btree: max depth * blocksize 263025101dcSChristoph Hellwig * the allocation btrees: 2 trees * (max depth - 1) * block size 264025101dcSChristoph Hellwig */ 2658f794055SNathan Scott STATIC uint 266025101dcSChristoph Hellwig xfs_calc_create_reservation( 267025101dcSChristoph Hellwig struct xfs_mount *mp) 2688f794055SNathan Scott { 269025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 270025101dcSChristoph Hellwig MAX((mp->m_sb.sb_inodesize + 271025101dcSChristoph Hellwig mp->m_sb.sb_inodesize + 272025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 273025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, 1) + 274025101dcSChristoph Hellwig XFS_DIROP_LOG_RES(mp) + 275025101dcSChristoph Hellwig 128 * (3 + XFS_DIROP_LOG_COUNT(mp))), 276025101dcSChristoph Hellwig (3 * mp->m_sb.sb_sectsize + 277025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) + 278025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, mp->m_in_maxlevels) + 279025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 1) + 280025101dcSChristoph Hellwig 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels + 281025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_COUNT(mp, 1)))); 2828f794055SNathan Scott } 2838f794055SNathan Scott 284025101dcSChristoph Hellwig /* 285025101dcSChristoph Hellwig * Making a new directory is the same as creating a new file. 286025101dcSChristoph Hellwig */ 2878f794055SNathan Scott STATIC uint 288025101dcSChristoph Hellwig xfs_calc_mkdir_reservation( 289025101dcSChristoph Hellwig struct xfs_mount *mp) 2908f794055SNathan Scott { 291025101dcSChristoph Hellwig return xfs_calc_create_reservation(mp); 2928f794055SNathan Scott } 2938f794055SNathan Scott 294025101dcSChristoph Hellwig /* 295025101dcSChristoph Hellwig * In freeing an inode we can modify: 296025101dcSChristoph Hellwig * the inode being freed: inode size 297025101dcSChristoph Hellwig * the super block free inode counter: sector size 298025101dcSChristoph Hellwig * the agi hash list and counters: sector size 299025101dcSChristoph Hellwig * the inode btree entry: block size 300025101dcSChristoph Hellwig * the on disk inode before ours in the agi hash list: inode cluster size 301025101dcSChristoph Hellwig * the inode btree: max depth * blocksize 302025101dcSChristoph Hellwig * the allocation btrees: 2 trees * (max depth - 1) * block size 303025101dcSChristoph Hellwig */ 3048f794055SNathan Scott STATIC uint 305025101dcSChristoph Hellwig xfs_calc_ifree_reservation( 306025101dcSChristoph Hellwig struct xfs_mount *mp) 3078f794055SNathan Scott { 308025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 309025101dcSChristoph Hellwig mp->m_sb.sb_inodesize + 310025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 311025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 312025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, 1) + 313025101dcSChristoph Hellwig MAX((__uint16_t)XFS_FSB_TO_B(mp, 1), 314025101dcSChristoph Hellwig XFS_INODE_CLUSTER_SIZE(mp)) + 315025101dcSChristoph Hellwig 128 * 5 + 316025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 1) + 317025101dcSChristoph Hellwig 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels + 318025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_COUNT(mp, 1)); 3198f794055SNathan Scott } 3208f794055SNathan Scott 321025101dcSChristoph Hellwig /* 322025101dcSChristoph Hellwig * When only changing the inode we log the inode and possibly the superblock 323025101dcSChristoph Hellwig * We also add a bit of slop for the transaction stuff. 324025101dcSChristoph Hellwig */ 3258f794055SNathan Scott STATIC uint 326025101dcSChristoph Hellwig xfs_calc_ichange_reservation( 327025101dcSChristoph Hellwig struct xfs_mount *mp) 3288f794055SNathan Scott { 329025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 330025101dcSChristoph Hellwig mp->m_sb.sb_inodesize + 331025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 332025101dcSChristoph Hellwig 512; 333025101dcSChristoph Hellwig 3348f794055SNathan Scott } 3358f794055SNathan Scott 336025101dcSChristoph Hellwig /* 337025101dcSChristoph Hellwig * Growing the data section of the filesystem. 338025101dcSChristoph Hellwig * superblock 339025101dcSChristoph Hellwig * agi and agf 340025101dcSChristoph Hellwig * allocation btrees 341025101dcSChristoph Hellwig */ 3428f794055SNathan Scott STATIC uint 343025101dcSChristoph Hellwig xfs_calc_growdata_reservation( 344025101dcSChristoph Hellwig struct xfs_mount *mp) 3458f794055SNathan Scott { 346025101dcSChristoph Hellwig return mp->m_sb.sb_sectsize * 3 + 347025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 1) + 348025101dcSChristoph Hellwig 128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1)); 3498f794055SNathan Scott } 3508f794055SNathan Scott 351025101dcSChristoph Hellwig /* 352025101dcSChristoph Hellwig * Growing the rt section of the filesystem. 353025101dcSChristoph Hellwig * In the first set of transactions (ALLOC) we allocate space to the 354025101dcSChristoph Hellwig * bitmap or summary files. 355025101dcSChristoph Hellwig * superblock: sector size 356025101dcSChristoph Hellwig * agf of the ag from which the extent is allocated: sector size 357025101dcSChristoph Hellwig * bmap btree for bitmap/summary inode: max depth * blocksize 358025101dcSChristoph Hellwig * bitmap/summary inode: inode size 359025101dcSChristoph Hellwig * allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize 360025101dcSChristoph Hellwig */ 3618f794055SNathan Scott STATIC uint 362025101dcSChristoph Hellwig xfs_calc_growrtalloc_reservation( 363025101dcSChristoph Hellwig struct xfs_mount *mp) 3648f794055SNathan Scott { 365025101dcSChristoph Hellwig return 2 * mp->m_sb.sb_sectsize + 366025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + 367025101dcSChristoph Hellwig mp->m_sb.sb_inodesize + 368025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 1) + 369025101dcSChristoph Hellwig 128 * (3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 370025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_COUNT(mp, 1)); 3718f794055SNathan Scott } 3728f794055SNathan Scott 373025101dcSChristoph Hellwig /* 374025101dcSChristoph Hellwig * Growing the rt section of the filesystem. 375025101dcSChristoph Hellwig * In the second set of transactions (ZERO) we zero the new metadata blocks. 376025101dcSChristoph Hellwig * one bitmap/summary block: blocksize 377025101dcSChristoph Hellwig */ 3788f794055SNathan Scott STATIC uint 379025101dcSChristoph Hellwig xfs_calc_growrtzero_reservation( 380025101dcSChristoph Hellwig struct xfs_mount *mp) 3818f794055SNathan Scott { 382025101dcSChristoph Hellwig return mp->m_sb.sb_blocksize + 128; 3838f794055SNathan Scott } 3848f794055SNathan Scott 385025101dcSChristoph Hellwig /* 386025101dcSChristoph Hellwig * Growing the rt section of the filesystem. 387025101dcSChristoph Hellwig * In the third set of transactions (FREE) we update metadata without 388025101dcSChristoph Hellwig * allocating any new blocks. 389025101dcSChristoph Hellwig * superblock: sector size 390025101dcSChristoph Hellwig * bitmap inode: inode size 391025101dcSChristoph Hellwig * summary inode: inode size 392025101dcSChristoph Hellwig * one bitmap block: blocksize 393025101dcSChristoph Hellwig * summary blocks: new summary size 394025101dcSChristoph Hellwig */ 3958f794055SNathan Scott STATIC uint 396025101dcSChristoph Hellwig xfs_calc_growrtfree_reservation( 397025101dcSChristoph Hellwig struct xfs_mount *mp) 3988f794055SNathan Scott { 399025101dcSChristoph Hellwig return mp->m_sb.sb_sectsize + 400025101dcSChristoph Hellwig 2 * mp->m_sb.sb_inodesize + 401025101dcSChristoph Hellwig mp->m_sb.sb_blocksize + 402025101dcSChristoph Hellwig mp->m_rsumsize + 403025101dcSChristoph Hellwig 128 * 5; 4048f794055SNathan Scott } 4058f794055SNathan Scott 406025101dcSChristoph Hellwig /* 407025101dcSChristoph Hellwig * Logging the inode modification timestamp on a synchronous write. 408025101dcSChristoph Hellwig * inode 409025101dcSChristoph Hellwig */ 4108f794055SNathan Scott STATIC uint 411025101dcSChristoph Hellwig xfs_calc_swrite_reservation( 412025101dcSChristoph Hellwig struct xfs_mount *mp) 4138f794055SNathan Scott { 414025101dcSChristoph Hellwig return mp->m_sb.sb_inodesize + 128; 4158f794055SNathan Scott } 4168f794055SNathan Scott 417025101dcSChristoph Hellwig /* 418025101dcSChristoph Hellwig * Logging the inode mode bits when writing a setuid/setgid file 419025101dcSChristoph Hellwig * inode 420025101dcSChristoph Hellwig */ 4218f794055SNathan Scott STATIC uint 4228f794055SNathan Scott xfs_calc_writeid_reservation(xfs_mount_t *mp) 4238f794055SNathan Scott { 424025101dcSChristoph Hellwig return mp->m_sb.sb_inodesize + 128; 4258f794055SNathan Scott } 4268f794055SNathan Scott 427025101dcSChristoph Hellwig /* 428025101dcSChristoph Hellwig * Converting the inode from non-attributed to attributed. 429025101dcSChristoph Hellwig * the inode being converted: inode size 430025101dcSChristoph Hellwig * agf block and superblock (for block allocation) 431025101dcSChristoph Hellwig * the new block (directory sized) 432025101dcSChristoph Hellwig * bmap blocks for the new directory block 433025101dcSChristoph Hellwig * allocation btrees 434025101dcSChristoph Hellwig */ 4358f794055SNathan Scott STATIC uint 436025101dcSChristoph Hellwig xfs_calc_addafork_reservation( 437025101dcSChristoph Hellwig struct xfs_mount *mp) 4388f794055SNathan Scott { 439025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 440025101dcSChristoph Hellwig mp->m_sb.sb_inodesize + 441025101dcSChristoph Hellwig mp->m_sb.sb_sectsize * 2 + 442025101dcSChristoph Hellwig mp->m_dirblksize + 443025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + 444025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 1) + 445025101dcSChristoph Hellwig 128 * (4 + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1 + 446025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_COUNT(mp, 1)); 4478f794055SNathan Scott } 4488f794055SNathan Scott 449025101dcSChristoph Hellwig /* 450025101dcSChristoph Hellwig * Removing the attribute fork of a file 451025101dcSChristoph Hellwig * the inode being truncated: inode size 452025101dcSChristoph Hellwig * the inode's bmap btree: max depth * block size 453025101dcSChristoph Hellwig * And the bmap_finish transaction can free the blocks and bmap blocks: 454025101dcSChristoph Hellwig * the agf for each of the ags: 4 * sector size 455025101dcSChristoph Hellwig * the agfl for each of the ags: 4 * sector size 456025101dcSChristoph Hellwig * the super block to reflect the freed blocks: sector size 457025101dcSChristoph Hellwig * worst case split in allocation btrees per extent assuming 4 extents: 458025101dcSChristoph Hellwig * 4 exts * 2 trees * (2 * max depth - 1) * block size 459025101dcSChristoph Hellwig */ 4608f794055SNathan Scott STATIC uint 461025101dcSChristoph Hellwig xfs_calc_attrinval_reservation( 462025101dcSChristoph Hellwig struct xfs_mount *mp) 4638f794055SNathan Scott { 464025101dcSChristoph Hellwig return MAX((mp->m_sb.sb_inodesize + 465025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + 466025101dcSChristoph Hellwig 128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))), 467025101dcSChristoph Hellwig (4 * mp->m_sb.sb_sectsize + 468025101dcSChristoph Hellwig 4 * mp->m_sb.sb_sectsize + 469025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 470025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 4) + 471025101dcSChristoph Hellwig 128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4)))); 4728f794055SNathan Scott } 4738f794055SNathan Scott 474025101dcSChristoph Hellwig /* 475025101dcSChristoph Hellwig * Setting an attribute. 476025101dcSChristoph Hellwig * the inode getting the attribute 477025101dcSChristoph Hellwig * the superblock for allocations 478025101dcSChristoph Hellwig * the agfs extents are allocated from 479025101dcSChristoph Hellwig * the attribute btree * max depth 480025101dcSChristoph Hellwig * the inode allocation btree 481025101dcSChristoph Hellwig * Since attribute transaction space is dependent on the size of the attribute, 482025101dcSChristoph Hellwig * the calculation is done partially at mount time and partially at runtime. 483025101dcSChristoph Hellwig */ 4848f794055SNathan Scott STATIC uint 485025101dcSChristoph Hellwig xfs_calc_attrset_reservation( 486025101dcSChristoph Hellwig struct xfs_mount *mp) 4878f794055SNathan Scott { 488025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 489025101dcSChristoph Hellwig mp->m_sb.sb_inodesize + 490025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 491025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) + 492025101dcSChristoph Hellwig 128 * (2 + XFS_DA_NODE_MAXDEPTH); 4938f794055SNathan Scott } 4948f794055SNathan Scott 495025101dcSChristoph Hellwig /* 496025101dcSChristoph Hellwig * Removing an attribute. 497025101dcSChristoph Hellwig * the inode: inode size 498025101dcSChristoph Hellwig * the attribute btree could join: max depth * block size 499025101dcSChristoph Hellwig * the inode bmap btree could join or split: max depth * block size 500025101dcSChristoph Hellwig * And the bmap_finish transaction can free the attr blocks freed giving: 501025101dcSChristoph Hellwig * the agf for the ag in which the blocks live: 2 * sector size 502025101dcSChristoph Hellwig * the agfl for the ag in which the blocks live: 2 * sector size 503025101dcSChristoph Hellwig * the superblock for the free block count: sector size 504025101dcSChristoph Hellwig * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size 505025101dcSChristoph Hellwig */ 5068f794055SNathan Scott STATIC uint 507025101dcSChristoph Hellwig xfs_calc_attrrm_reservation( 508025101dcSChristoph Hellwig struct xfs_mount *mp) 5098f794055SNathan Scott { 510025101dcSChristoph Hellwig return XFS_DQUOT_LOGRES(mp) + 511025101dcSChristoph Hellwig MAX((mp->m_sb.sb_inodesize + 512025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) + 513025101dcSChristoph Hellwig XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + 514025101dcSChristoph Hellwig 128 * (1 + XFS_DA_NODE_MAXDEPTH + 515025101dcSChristoph Hellwig XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))), 516025101dcSChristoph Hellwig (2 * mp->m_sb.sb_sectsize + 517025101dcSChristoph Hellwig 2 * mp->m_sb.sb_sectsize + 518025101dcSChristoph Hellwig mp->m_sb.sb_sectsize + 519025101dcSChristoph Hellwig XFS_ALLOCFREE_LOG_RES(mp, 2) + 520025101dcSChristoph Hellwig 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2)))); 5218f794055SNathan Scott } 5228f794055SNathan Scott 523025101dcSChristoph Hellwig /* 524025101dcSChristoph Hellwig * Clearing a bad agino number in an agi hash bucket. 525025101dcSChristoph Hellwig */ 5268f794055SNathan Scott STATIC uint 527025101dcSChristoph Hellwig xfs_calc_clear_agi_bucket_reservation( 528025101dcSChristoph Hellwig struct xfs_mount *mp) 5298f794055SNathan Scott { 530025101dcSChristoph Hellwig return mp->m_sb.sb_sectsize + 128; 5318f794055SNathan Scott } 5328f794055SNathan Scott 5338f794055SNathan Scott /* 5341da177e4SLinus Torvalds * Initialize the precomputed transaction reservation values 5351da177e4SLinus Torvalds * in the mount structure. 5361da177e4SLinus Torvalds */ 5371da177e4SLinus Torvalds void 5381da177e4SLinus Torvalds xfs_trans_init( 539025101dcSChristoph Hellwig struct xfs_mount *mp) 5401da177e4SLinus Torvalds { 541025101dcSChristoph Hellwig struct xfs_trans_reservations *resp = &mp->m_reservations; 5421da177e4SLinus Torvalds 5438f794055SNathan Scott resp->tr_write = xfs_calc_write_reservation(mp); 5448f794055SNathan Scott resp->tr_itruncate = xfs_calc_itruncate_reservation(mp); 5458f794055SNathan Scott resp->tr_rename = xfs_calc_rename_reservation(mp); 5468f794055SNathan Scott resp->tr_link = xfs_calc_link_reservation(mp); 5478f794055SNathan Scott resp->tr_remove = xfs_calc_remove_reservation(mp); 5488f794055SNathan Scott resp->tr_symlink = xfs_calc_symlink_reservation(mp); 5498f794055SNathan Scott resp->tr_create = xfs_calc_create_reservation(mp); 5508f794055SNathan Scott resp->tr_mkdir = xfs_calc_mkdir_reservation(mp); 5518f794055SNathan Scott resp->tr_ifree = xfs_calc_ifree_reservation(mp); 5528f794055SNathan Scott resp->tr_ichange = xfs_calc_ichange_reservation(mp); 5538f794055SNathan Scott resp->tr_growdata = xfs_calc_growdata_reservation(mp); 5548f794055SNathan Scott resp->tr_swrite = xfs_calc_swrite_reservation(mp); 5558f794055SNathan Scott resp->tr_writeid = xfs_calc_writeid_reservation(mp); 5568f794055SNathan Scott resp->tr_addafork = xfs_calc_addafork_reservation(mp); 5578f794055SNathan Scott resp->tr_attrinval = xfs_calc_attrinval_reservation(mp); 5588f794055SNathan Scott resp->tr_attrset = xfs_calc_attrset_reservation(mp); 5598f794055SNathan Scott resp->tr_attrrm = xfs_calc_attrrm_reservation(mp); 5608f794055SNathan Scott resp->tr_clearagi = xfs_calc_clear_agi_bucket_reservation(mp); 5618f794055SNathan Scott resp->tr_growrtalloc = xfs_calc_growrtalloc_reservation(mp); 5628f794055SNathan Scott resp->tr_growrtzero = xfs_calc_growrtzero_reservation(mp); 5638f794055SNathan Scott resp->tr_growrtfree = xfs_calc_growrtfree_reservation(mp); 5641da177e4SLinus Torvalds } 5651da177e4SLinus Torvalds 5661da177e4SLinus Torvalds /* 5671da177e4SLinus Torvalds * This routine is called to allocate a transaction structure. 5681da177e4SLinus Torvalds * The type parameter indicates the type of the transaction. These 5691da177e4SLinus Torvalds * are enumerated in xfs_trans.h. 570b2ce3974SAlex Elder * 571b2ce3974SAlex Elder * Dynamically allocate the transaction structure from the transaction 572b2ce3974SAlex Elder * zone, initialize it, and return it to the caller. 5731da177e4SLinus Torvalds */ 574b2ce3974SAlex Elder xfs_trans_t * 575b2ce3974SAlex Elder xfs_trans_alloc( 576b2ce3974SAlex Elder xfs_mount_t *mp, 577b2ce3974SAlex Elder uint type) 5781da177e4SLinus Torvalds { 579*d9457dc0SJan Kara xfs_trans_t *tp; 580*d9457dc0SJan Kara 581*d9457dc0SJan Kara sb_start_intwrite(mp->m_super); 582*d9457dc0SJan Kara tp = _xfs_trans_alloc(mp, type, KM_SLEEP); 583*d9457dc0SJan Kara tp->t_flags |= XFS_TRANS_FREEZE_PROT; 584*d9457dc0SJan Kara return tp; 585b2ce3974SAlex Elder } 586b2ce3974SAlex Elder 587b2ce3974SAlex Elder xfs_trans_t * 588b2ce3974SAlex Elder _xfs_trans_alloc( 589b2ce3974SAlex Elder xfs_mount_t *mp, 590b2ce3974SAlex Elder uint type, 59177ba7877SAl Viro xfs_km_flags_t memflags) 592b2ce3974SAlex Elder { 593b2ce3974SAlex Elder xfs_trans_t *tp; 5941da177e4SLinus Torvalds 595*d9457dc0SJan Kara WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); 59634327e13SNathan Scott atomic_inc(&mp->m_active_trans); 5971da177e4SLinus Torvalds 59880641dc6SChristoph Hellwig tp = kmem_zone_zalloc(xfs_trans_zone, memflags); 5991da177e4SLinus Torvalds tp->t_magic = XFS_TRANS_MAGIC; 6001da177e4SLinus Torvalds tp->t_type = type; 6011da177e4SLinus Torvalds tp->t_mountp = mp; 602e98c414fSChristoph Hellwig INIT_LIST_HEAD(&tp->t_items); 603ed3b4d6cSDave Chinner INIT_LIST_HEAD(&tp->t_busy); 60434327e13SNathan Scott return tp; 6051da177e4SLinus Torvalds } 6061da177e4SLinus Torvalds 6071da177e4SLinus Torvalds /* 608b1c1b5b6SDave Chinner * Free the transaction structure. If there is more clean up 609b1c1b5b6SDave Chinner * to do when the structure is freed, add it here. 610b1c1b5b6SDave Chinner */ 611b1c1b5b6SDave Chinner STATIC void 612b1c1b5b6SDave Chinner xfs_trans_free( 613ed3b4d6cSDave Chinner struct xfs_trans *tp) 614b1c1b5b6SDave Chinner { 6154ecbfe63SDave Chinner xfs_extent_busy_sort(&tp->t_busy); 6164ecbfe63SDave Chinner xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false); 617ed3b4d6cSDave Chinner 618b1c1b5b6SDave Chinner atomic_dec(&tp->t_mountp->m_active_trans); 619*d9457dc0SJan Kara if (tp->t_flags & XFS_TRANS_FREEZE_PROT) 620*d9457dc0SJan Kara sb_end_intwrite(tp->t_mountp->m_super); 621b1c1b5b6SDave Chinner xfs_trans_free_dqinfo(tp); 622b1c1b5b6SDave Chinner kmem_zone_free(xfs_trans_zone, tp); 623b1c1b5b6SDave Chinner } 624b1c1b5b6SDave Chinner 625b1c1b5b6SDave Chinner /* 6261da177e4SLinus Torvalds * This is called to create a new transaction which will share the 6271da177e4SLinus Torvalds * permanent log reservation of the given transaction. The remaining 6281da177e4SLinus Torvalds * unused block and rt extent reservations are also inherited. This 6291da177e4SLinus Torvalds * implies that the original transaction is no longer allowed to allocate 6301da177e4SLinus Torvalds * blocks. Locks and log items, however, are no inherited. They must 6311da177e4SLinus Torvalds * be added to the new transaction explicitly. 6321da177e4SLinus Torvalds */ 6331da177e4SLinus Torvalds xfs_trans_t * 6341da177e4SLinus Torvalds xfs_trans_dup( 6351da177e4SLinus Torvalds xfs_trans_t *tp) 6361da177e4SLinus Torvalds { 6371da177e4SLinus Torvalds xfs_trans_t *ntp; 6381da177e4SLinus Torvalds 6391da177e4SLinus Torvalds ntp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); 6401da177e4SLinus Torvalds 6411da177e4SLinus Torvalds /* 6421da177e4SLinus Torvalds * Initialize the new transaction structure. 6431da177e4SLinus Torvalds */ 6441da177e4SLinus Torvalds ntp->t_magic = XFS_TRANS_MAGIC; 6451da177e4SLinus Torvalds ntp->t_type = tp->t_type; 6461da177e4SLinus Torvalds ntp->t_mountp = tp->t_mountp; 647e98c414fSChristoph Hellwig INIT_LIST_HEAD(&ntp->t_items); 648ed3b4d6cSDave Chinner INIT_LIST_HEAD(&ntp->t_busy); 6491da177e4SLinus Torvalds 6501da177e4SLinus Torvalds ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); 6511da177e4SLinus Torvalds ASSERT(tp->t_ticket != NULL); 652cfcbbbd0SNathan Scott 653*d9457dc0SJan Kara ntp->t_flags = XFS_TRANS_PERM_LOG_RES | 654*d9457dc0SJan Kara (tp->t_flags & XFS_TRANS_RESERVE) | 655*d9457dc0SJan Kara (tp->t_flags & XFS_TRANS_FREEZE_PROT); 656*d9457dc0SJan Kara /* We gave our writer reference to the new transaction */ 657*d9457dc0SJan Kara tp->t_flags &= ~XFS_TRANS_FREEZE_PROT; 658cc09c0dcSDave Chinner ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket); 6591da177e4SLinus Torvalds ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used; 6601da177e4SLinus Torvalds tp->t_blk_res = tp->t_blk_res_used; 6611da177e4SLinus Torvalds ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; 6621da177e4SLinus Torvalds tp->t_rtx_res = tp->t_rtx_res_used; 66359c1b082SNathan Scott ntp->t_pflags = tp->t_pflags; 6641da177e4SLinus Torvalds 6657d095257SChristoph Hellwig xfs_trans_dup_dqinfo(tp, ntp); 6661da177e4SLinus Torvalds 6671da177e4SLinus Torvalds atomic_inc(&tp->t_mountp->m_active_trans); 6681da177e4SLinus Torvalds return ntp; 6691da177e4SLinus Torvalds } 6701da177e4SLinus Torvalds 6711da177e4SLinus Torvalds /* 6721da177e4SLinus Torvalds * This is called to reserve free disk blocks and log space for the 6731da177e4SLinus Torvalds * given transaction. This must be done before allocating any resources 6741da177e4SLinus Torvalds * within the transaction. 6751da177e4SLinus Torvalds * 6761da177e4SLinus Torvalds * This will return ENOSPC if there are not enough blocks available. 6771da177e4SLinus Torvalds * It will sleep waiting for available log space. 6781da177e4SLinus Torvalds * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which 6791da177e4SLinus Torvalds * is used by long running transactions. If any one of the reservations 6801da177e4SLinus Torvalds * fails then they will all be backed out. 6811da177e4SLinus Torvalds * 6821da177e4SLinus Torvalds * This does not do quota reservations. That typically is done by the 6831da177e4SLinus Torvalds * caller afterwards. 6841da177e4SLinus Torvalds */ 6851da177e4SLinus Torvalds int 6861da177e4SLinus Torvalds xfs_trans_reserve( 6871da177e4SLinus Torvalds xfs_trans_t *tp, 6881da177e4SLinus Torvalds uint blocks, 6891da177e4SLinus Torvalds uint logspace, 6901da177e4SLinus Torvalds uint rtextents, 6911da177e4SLinus Torvalds uint flags, 6921da177e4SLinus Torvalds uint logcount) 6931da177e4SLinus Torvalds { 69459c1b082SNathan Scott int error = 0; 69559c1b082SNathan Scott int rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; 6961da177e4SLinus Torvalds 6971da177e4SLinus Torvalds /* Mark this thread as being in a transaction */ 69859c1b082SNathan Scott current_set_flags_nested(&tp->t_pflags, PF_FSTRANS); 6991da177e4SLinus Torvalds 7001da177e4SLinus Torvalds /* 7011da177e4SLinus Torvalds * Attempt to reserve the needed disk blocks by decrementing 7021da177e4SLinus Torvalds * the number needed from the number available. This will 7031da177e4SLinus Torvalds * fail if the count would go below zero. 7041da177e4SLinus Torvalds */ 7051da177e4SLinus Torvalds if (blocks > 0) { 70696540c78SChristoph Hellwig error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS, 70720f4ebf2SDavid Chinner -((int64_t)blocks), rsvd); 7081da177e4SLinus Torvalds if (error != 0) { 70959c1b082SNathan Scott current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); 7101da177e4SLinus Torvalds return (XFS_ERROR(ENOSPC)); 7111da177e4SLinus Torvalds } 7121da177e4SLinus Torvalds tp->t_blk_res += blocks; 7131da177e4SLinus Torvalds } 7141da177e4SLinus Torvalds 7151da177e4SLinus Torvalds /* 7161da177e4SLinus Torvalds * Reserve the log space needed for this transaction. 7171da177e4SLinus Torvalds */ 7181da177e4SLinus Torvalds if (logspace > 0) { 7199006fb91SChristoph Hellwig bool permanent = false; 7209006fb91SChristoph Hellwig 7219006fb91SChristoph Hellwig ASSERT(tp->t_log_res == 0 || tp->t_log_res == logspace); 7229006fb91SChristoph Hellwig ASSERT(tp->t_log_count == 0 || tp->t_log_count == logcount); 7239006fb91SChristoph Hellwig 7241da177e4SLinus Torvalds if (flags & XFS_TRANS_PERM_LOG_RES) { 7251da177e4SLinus Torvalds tp->t_flags |= XFS_TRANS_PERM_LOG_RES; 7269006fb91SChristoph Hellwig permanent = true; 7271da177e4SLinus Torvalds } else { 7281da177e4SLinus Torvalds ASSERT(tp->t_ticket == NULL); 7291da177e4SLinus Torvalds ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES)); 7301da177e4SLinus Torvalds } 7311da177e4SLinus Torvalds 7329006fb91SChristoph Hellwig if (tp->t_ticket != NULL) { 7339006fb91SChristoph Hellwig ASSERT(flags & XFS_TRANS_PERM_LOG_RES); 7349006fb91SChristoph Hellwig error = xfs_log_regrant(tp->t_mountp, tp->t_ticket); 7359006fb91SChristoph Hellwig } else { 7369006fb91SChristoph Hellwig error = xfs_log_reserve(tp->t_mountp, logspace, 7379006fb91SChristoph Hellwig logcount, &tp->t_ticket, 7389006fb91SChristoph Hellwig XFS_TRANSACTION, permanent, 7399006fb91SChristoph Hellwig tp->t_type); 7401da177e4SLinus Torvalds } 7419006fb91SChristoph Hellwig 7429006fb91SChristoph Hellwig if (error) 7439006fb91SChristoph Hellwig goto undo_blocks; 7449006fb91SChristoph Hellwig 7451da177e4SLinus Torvalds tp->t_log_res = logspace; 7461da177e4SLinus Torvalds tp->t_log_count = logcount; 7471da177e4SLinus Torvalds } 7481da177e4SLinus Torvalds 7491da177e4SLinus Torvalds /* 7501da177e4SLinus Torvalds * Attempt to reserve the needed realtime extents by decrementing 7511da177e4SLinus Torvalds * the number needed from the number available. This will 7521da177e4SLinus Torvalds * fail if the count would go below zero. 7531da177e4SLinus Torvalds */ 7541da177e4SLinus Torvalds if (rtextents > 0) { 7551da177e4SLinus Torvalds error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS, 75620f4ebf2SDavid Chinner -((int64_t)rtextents), rsvd); 7571da177e4SLinus Torvalds if (error) { 7581da177e4SLinus Torvalds error = XFS_ERROR(ENOSPC); 7591da177e4SLinus Torvalds goto undo_log; 7601da177e4SLinus Torvalds } 7611da177e4SLinus Torvalds tp->t_rtx_res += rtextents; 7621da177e4SLinus Torvalds } 7631da177e4SLinus Torvalds 7641da177e4SLinus Torvalds return 0; 7651da177e4SLinus Torvalds 7661da177e4SLinus Torvalds /* 7671da177e4SLinus Torvalds * Error cases jump to one of these labels to undo any 7681da177e4SLinus Torvalds * reservations which have already been performed. 7691da177e4SLinus Torvalds */ 7701da177e4SLinus Torvalds undo_log: 7711da177e4SLinus Torvalds if (logspace > 0) { 7729006fb91SChristoph Hellwig int log_flags; 7739006fb91SChristoph Hellwig 7741da177e4SLinus Torvalds if (flags & XFS_TRANS_PERM_LOG_RES) { 7751da177e4SLinus Torvalds log_flags = XFS_LOG_REL_PERM_RESERV; 7761da177e4SLinus Torvalds } else { 7771da177e4SLinus Torvalds log_flags = 0; 7781da177e4SLinus Torvalds } 7791da177e4SLinus Torvalds xfs_log_done(tp->t_mountp, tp->t_ticket, NULL, log_flags); 7801da177e4SLinus Torvalds tp->t_ticket = NULL; 7811da177e4SLinus Torvalds tp->t_log_res = 0; 7821da177e4SLinus Torvalds tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES; 7831da177e4SLinus Torvalds } 7841da177e4SLinus Torvalds 7851da177e4SLinus Torvalds undo_blocks: 7861da177e4SLinus Torvalds if (blocks > 0) { 78796540c78SChristoph Hellwig xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS, 78820f4ebf2SDavid Chinner (int64_t)blocks, rsvd); 7891da177e4SLinus Torvalds tp->t_blk_res = 0; 7901da177e4SLinus Torvalds } 7911da177e4SLinus Torvalds 79259c1b082SNathan Scott current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); 7931da177e4SLinus Torvalds 79459c1b082SNathan Scott return error; 7951da177e4SLinus Torvalds } 7961da177e4SLinus Torvalds 7971da177e4SLinus Torvalds /* 7981da177e4SLinus Torvalds * Record the indicated change to the given field for application 7991da177e4SLinus Torvalds * to the file system's superblock when the transaction commits. 8001da177e4SLinus Torvalds * For now, just store the change in the transaction structure. 8011da177e4SLinus Torvalds * 8021da177e4SLinus Torvalds * Mark the transaction structure to indicate that the superblock 8031da177e4SLinus Torvalds * needs to be updated before committing. 80492821e2bSDavid Chinner * 80592821e2bSDavid Chinner * Because we may not be keeping track of allocated/free inodes and 80692821e2bSDavid Chinner * used filesystem blocks in the superblock, we do not mark the 80792821e2bSDavid Chinner * superblock dirty in this transaction if we modify these fields. 80892821e2bSDavid Chinner * We still need to update the transaction deltas so that they get 80992821e2bSDavid Chinner * applied to the incore superblock, but we don't want them to 81092821e2bSDavid Chinner * cause the superblock to get locked and logged if these are the 81192821e2bSDavid Chinner * only fields in the superblock that the transaction modifies. 8121da177e4SLinus Torvalds */ 8131da177e4SLinus Torvalds void 8141da177e4SLinus Torvalds xfs_trans_mod_sb( 8151da177e4SLinus Torvalds xfs_trans_t *tp, 8161da177e4SLinus Torvalds uint field, 81720f4ebf2SDavid Chinner int64_t delta) 8181da177e4SLinus Torvalds { 81992821e2bSDavid Chinner uint32_t flags = (XFS_TRANS_DIRTY|XFS_TRANS_SB_DIRTY); 82092821e2bSDavid Chinner xfs_mount_t *mp = tp->t_mountp; 8211da177e4SLinus Torvalds 8221da177e4SLinus Torvalds switch (field) { 8231da177e4SLinus Torvalds case XFS_TRANS_SB_ICOUNT: 8241da177e4SLinus Torvalds tp->t_icount_delta += delta; 82592821e2bSDavid Chinner if (xfs_sb_version_haslazysbcount(&mp->m_sb)) 82692821e2bSDavid Chinner flags &= ~XFS_TRANS_SB_DIRTY; 8271da177e4SLinus Torvalds break; 8281da177e4SLinus Torvalds case XFS_TRANS_SB_IFREE: 8291da177e4SLinus Torvalds tp->t_ifree_delta += delta; 83092821e2bSDavid Chinner if (xfs_sb_version_haslazysbcount(&mp->m_sb)) 83192821e2bSDavid Chinner flags &= ~XFS_TRANS_SB_DIRTY; 8321da177e4SLinus Torvalds break; 8331da177e4SLinus Torvalds case XFS_TRANS_SB_FDBLOCKS: 8341da177e4SLinus Torvalds /* 8351da177e4SLinus Torvalds * Track the number of blocks allocated in the 8361da177e4SLinus Torvalds * transaction. Make sure it does not exceed the 8371da177e4SLinus Torvalds * number reserved. 8381da177e4SLinus Torvalds */ 8391da177e4SLinus Torvalds if (delta < 0) { 8401da177e4SLinus Torvalds tp->t_blk_res_used += (uint)-delta; 8411da177e4SLinus Torvalds ASSERT(tp->t_blk_res_used <= tp->t_blk_res); 8421da177e4SLinus Torvalds } 8431da177e4SLinus Torvalds tp->t_fdblocks_delta += delta; 84492821e2bSDavid Chinner if (xfs_sb_version_haslazysbcount(&mp->m_sb)) 84592821e2bSDavid Chinner flags &= ~XFS_TRANS_SB_DIRTY; 8461da177e4SLinus Torvalds break; 8471da177e4SLinus Torvalds case XFS_TRANS_SB_RES_FDBLOCKS: 8481da177e4SLinus Torvalds /* 8491da177e4SLinus Torvalds * The allocation has already been applied to the 8501da177e4SLinus Torvalds * in-core superblock's counter. This should only 8511da177e4SLinus Torvalds * be applied to the on-disk superblock. 8521da177e4SLinus Torvalds */ 8531da177e4SLinus Torvalds ASSERT(delta < 0); 8541da177e4SLinus Torvalds tp->t_res_fdblocks_delta += delta; 85592821e2bSDavid Chinner if (xfs_sb_version_haslazysbcount(&mp->m_sb)) 85692821e2bSDavid Chinner flags &= ~XFS_TRANS_SB_DIRTY; 8571da177e4SLinus Torvalds break; 8581da177e4SLinus Torvalds case XFS_TRANS_SB_FREXTENTS: 8591da177e4SLinus Torvalds /* 8601da177e4SLinus Torvalds * Track the number of blocks allocated in the 8611da177e4SLinus Torvalds * transaction. Make sure it does not exceed the 8621da177e4SLinus Torvalds * number reserved. 8631da177e4SLinus Torvalds */ 8641da177e4SLinus Torvalds if (delta < 0) { 8651da177e4SLinus Torvalds tp->t_rtx_res_used += (uint)-delta; 8661da177e4SLinus Torvalds ASSERT(tp->t_rtx_res_used <= tp->t_rtx_res); 8671da177e4SLinus Torvalds } 8681da177e4SLinus Torvalds tp->t_frextents_delta += delta; 8691da177e4SLinus Torvalds break; 8701da177e4SLinus Torvalds case XFS_TRANS_SB_RES_FREXTENTS: 8711da177e4SLinus Torvalds /* 8721da177e4SLinus Torvalds * The allocation has already been applied to the 873c41564b5SNathan Scott * in-core superblock's counter. This should only 8741da177e4SLinus Torvalds * be applied to the on-disk superblock. 8751da177e4SLinus Torvalds */ 8761da177e4SLinus Torvalds ASSERT(delta < 0); 8771da177e4SLinus Torvalds tp->t_res_frextents_delta += delta; 8781da177e4SLinus Torvalds break; 8791da177e4SLinus Torvalds case XFS_TRANS_SB_DBLOCKS: 8801da177e4SLinus Torvalds ASSERT(delta > 0); 8811da177e4SLinus Torvalds tp->t_dblocks_delta += delta; 8821da177e4SLinus Torvalds break; 8831da177e4SLinus Torvalds case XFS_TRANS_SB_AGCOUNT: 8841da177e4SLinus Torvalds ASSERT(delta > 0); 8851da177e4SLinus Torvalds tp->t_agcount_delta += delta; 8861da177e4SLinus Torvalds break; 8871da177e4SLinus Torvalds case XFS_TRANS_SB_IMAXPCT: 8881da177e4SLinus Torvalds tp->t_imaxpct_delta += delta; 8891da177e4SLinus Torvalds break; 8901da177e4SLinus Torvalds case XFS_TRANS_SB_REXTSIZE: 8911da177e4SLinus Torvalds tp->t_rextsize_delta += delta; 8921da177e4SLinus Torvalds break; 8931da177e4SLinus Torvalds case XFS_TRANS_SB_RBMBLOCKS: 8941da177e4SLinus Torvalds tp->t_rbmblocks_delta += delta; 8951da177e4SLinus Torvalds break; 8961da177e4SLinus Torvalds case XFS_TRANS_SB_RBLOCKS: 8971da177e4SLinus Torvalds tp->t_rblocks_delta += delta; 8981da177e4SLinus Torvalds break; 8991da177e4SLinus Torvalds case XFS_TRANS_SB_REXTENTS: 9001da177e4SLinus Torvalds tp->t_rextents_delta += delta; 9011da177e4SLinus Torvalds break; 9021da177e4SLinus Torvalds case XFS_TRANS_SB_REXTSLOG: 9031da177e4SLinus Torvalds tp->t_rextslog_delta += delta; 9041da177e4SLinus Torvalds break; 9051da177e4SLinus Torvalds default: 9061da177e4SLinus Torvalds ASSERT(0); 9071da177e4SLinus Torvalds return; 9081da177e4SLinus Torvalds } 9091da177e4SLinus Torvalds 910210c6f1cSDavid Chinner tp->t_flags |= flags; 9111da177e4SLinus Torvalds } 9121da177e4SLinus Torvalds 9131da177e4SLinus Torvalds /* 9141da177e4SLinus Torvalds * xfs_trans_apply_sb_deltas() is called from the commit code 9151da177e4SLinus Torvalds * to bring the superblock buffer into the current transaction 9161da177e4SLinus Torvalds * and modify it as requested by earlier calls to xfs_trans_mod_sb(). 9171da177e4SLinus Torvalds * 9181da177e4SLinus Torvalds * For now we just look at each field allowed to change and change 9191da177e4SLinus Torvalds * it if necessary. 9201da177e4SLinus Torvalds */ 9211da177e4SLinus Torvalds STATIC void 9221da177e4SLinus Torvalds xfs_trans_apply_sb_deltas( 9231da177e4SLinus Torvalds xfs_trans_t *tp) 9241da177e4SLinus Torvalds { 9252bdf7cd0SChristoph Hellwig xfs_dsb_t *sbp; 9261da177e4SLinus Torvalds xfs_buf_t *bp; 9271da177e4SLinus Torvalds int whole = 0; 9281da177e4SLinus Torvalds 9291da177e4SLinus Torvalds bp = xfs_trans_getsb(tp, tp->t_mountp, 0); 9301da177e4SLinus Torvalds sbp = XFS_BUF_TO_SBP(bp); 9311da177e4SLinus Torvalds 9321da177e4SLinus Torvalds /* 9331da177e4SLinus Torvalds * Check that superblock mods match the mods made to AGF counters. 9341da177e4SLinus Torvalds */ 9351da177e4SLinus Torvalds ASSERT((tp->t_fdblocks_delta + tp->t_res_fdblocks_delta) == 9361da177e4SLinus Torvalds (tp->t_ag_freeblks_delta + tp->t_ag_flist_delta + 9371da177e4SLinus Torvalds tp->t_ag_btree_delta)); 9381da177e4SLinus Torvalds 93992821e2bSDavid Chinner /* 94092821e2bSDavid Chinner * Only update the superblock counters if we are logging them 94192821e2bSDavid Chinner */ 94292821e2bSDavid Chinner if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) { 9432bdf7cd0SChristoph Hellwig if (tp->t_icount_delta) 944413d57c9SMarcin Slusarz be64_add_cpu(&sbp->sb_icount, tp->t_icount_delta); 9452bdf7cd0SChristoph Hellwig if (tp->t_ifree_delta) 946413d57c9SMarcin Slusarz be64_add_cpu(&sbp->sb_ifree, tp->t_ifree_delta); 9472bdf7cd0SChristoph Hellwig if (tp->t_fdblocks_delta) 948413d57c9SMarcin Slusarz be64_add_cpu(&sbp->sb_fdblocks, tp->t_fdblocks_delta); 9492bdf7cd0SChristoph Hellwig if (tp->t_res_fdblocks_delta) 950413d57c9SMarcin Slusarz be64_add_cpu(&sbp->sb_fdblocks, tp->t_res_fdblocks_delta); 9511da177e4SLinus Torvalds } 9521da177e4SLinus Torvalds 9532bdf7cd0SChristoph Hellwig if (tp->t_frextents_delta) 954413d57c9SMarcin Slusarz be64_add_cpu(&sbp->sb_frextents, tp->t_frextents_delta); 9552bdf7cd0SChristoph Hellwig if (tp->t_res_frextents_delta) 956413d57c9SMarcin Slusarz be64_add_cpu(&sbp->sb_frextents, tp->t_res_frextents_delta); 9571da177e4SLinus Torvalds 9582bdf7cd0SChristoph Hellwig if (tp->t_dblocks_delta) { 959413d57c9SMarcin Slusarz be64_add_cpu(&sbp->sb_dblocks, tp->t_dblocks_delta); 9601da177e4SLinus Torvalds whole = 1; 9611da177e4SLinus Torvalds } 9622bdf7cd0SChristoph Hellwig if (tp->t_agcount_delta) { 963413d57c9SMarcin Slusarz be32_add_cpu(&sbp->sb_agcount, tp->t_agcount_delta); 9641da177e4SLinus Torvalds whole = 1; 9651da177e4SLinus Torvalds } 9662bdf7cd0SChristoph Hellwig if (tp->t_imaxpct_delta) { 9672bdf7cd0SChristoph Hellwig sbp->sb_imax_pct += tp->t_imaxpct_delta; 9681da177e4SLinus Torvalds whole = 1; 9691da177e4SLinus Torvalds } 9702bdf7cd0SChristoph Hellwig if (tp->t_rextsize_delta) { 971413d57c9SMarcin Slusarz be32_add_cpu(&sbp->sb_rextsize, tp->t_rextsize_delta); 9721da177e4SLinus Torvalds whole = 1; 9731da177e4SLinus Torvalds } 9742bdf7cd0SChristoph Hellwig if (tp->t_rbmblocks_delta) { 975413d57c9SMarcin Slusarz be32_add_cpu(&sbp->sb_rbmblocks, tp->t_rbmblocks_delta); 9761da177e4SLinus Torvalds whole = 1; 9771da177e4SLinus Torvalds } 9782bdf7cd0SChristoph Hellwig if (tp->t_rblocks_delta) { 979413d57c9SMarcin Slusarz be64_add_cpu(&sbp->sb_rblocks, tp->t_rblocks_delta); 9801da177e4SLinus Torvalds whole = 1; 9811da177e4SLinus Torvalds } 9822bdf7cd0SChristoph Hellwig if (tp->t_rextents_delta) { 983413d57c9SMarcin Slusarz be64_add_cpu(&sbp->sb_rextents, tp->t_rextents_delta); 9841da177e4SLinus Torvalds whole = 1; 9851da177e4SLinus Torvalds } 9862bdf7cd0SChristoph Hellwig if (tp->t_rextslog_delta) { 9872bdf7cd0SChristoph Hellwig sbp->sb_rextslog += tp->t_rextslog_delta; 9881da177e4SLinus Torvalds whole = 1; 9891da177e4SLinus Torvalds } 9901da177e4SLinus Torvalds 9911da177e4SLinus Torvalds if (whole) 9921da177e4SLinus Torvalds /* 993c41564b5SNathan Scott * Log the whole thing, the fields are noncontiguous. 9941da177e4SLinus Torvalds */ 9952bdf7cd0SChristoph Hellwig xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_dsb_t) - 1); 9961da177e4SLinus Torvalds else 9971da177e4SLinus Torvalds /* 9981da177e4SLinus Torvalds * Since all the modifiable fields are contiguous, we 9991da177e4SLinus Torvalds * can get away with this. 10001da177e4SLinus Torvalds */ 10012bdf7cd0SChristoph Hellwig xfs_trans_log_buf(tp, bp, offsetof(xfs_dsb_t, sb_icount), 10022bdf7cd0SChristoph Hellwig offsetof(xfs_dsb_t, sb_frextents) + 10031da177e4SLinus Torvalds sizeof(sbp->sb_frextents) - 1); 10041da177e4SLinus Torvalds } 10051da177e4SLinus Torvalds 10061da177e4SLinus Torvalds /* 100745c34141SDavid Chinner * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations 100845c34141SDavid Chinner * and apply superblock counter changes to the in-core superblock. The 100945c34141SDavid Chinner * t_res_fdblocks_delta and t_res_frextents_delta fields are explicitly NOT 101045c34141SDavid Chinner * applied to the in-core superblock. The idea is that that has already been 101145c34141SDavid Chinner * done. 10121da177e4SLinus Torvalds * 10131da177e4SLinus Torvalds * This is done efficiently with a single call to xfs_mod_incore_sb_batch(). 101445c34141SDavid Chinner * However, we have to ensure that we only modify each superblock field only 101545c34141SDavid Chinner * once because the application of the delta values may not be atomic. That can 101645c34141SDavid Chinner * lead to ENOSPC races occurring if we have two separate modifcations of the 101745c34141SDavid Chinner * free space counter to put back the entire reservation and then take away 101845c34141SDavid Chinner * what we used. 101945c34141SDavid Chinner * 102045c34141SDavid Chinner * If we are not logging superblock counters, then the inode allocated/free and 102145c34141SDavid Chinner * used block counts are not updated in the on disk superblock. In this case, 102245c34141SDavid Chinner * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we 102345c34141SDavid Chinner * still need to update the incore superblock with the changes. 10241da177e4SLinus Torvalds */ 102571e330b5SDave Chinner void 10261da177e4SLinus Torvalds xfs_trans_unreserve_and_mod_sb( 10271da177e4SLinus Torvalds xfs_trans_t *tp) 10281da177e4SLinus Torvalds { 10291b040712SChristoph Hellwig xfs_mod_sb_t msb[9]; /* If you add cases, add entries */ 10301da177e4SLinus Torvalds xfs_mod_sb_t *msbp; 103192821e2bSDavid Chinner xfs_mount_t *mp = tp->t_mountp; 10321da177e4SLinus Torvalds /* REFERENCED */ 10331da177e4SLinus Torvalds int error; 10341da177e4SLinus Torvalds int rsvd; 103545c34141SDavid Chinner int64_t blkdelta = 0; 103645c34141SDavid Chinner int64_t rtxdelta = 0; 10371b040712SChristoph Hellwig int64_t idelta = 0; 10381b040712SChristoph Hellwig int64_t ifreedelta = 0; 10391da177e4SLinus Torvalds 10401da177e4SLinus Torvalds msbp = msb; 10411da177e4SLinus Torvalds rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; 10421da177e4SLinus Torvalds 10431b040712SChristoph Hellwig /* calculate deltas */ 104445c34141SDavid Chinner if (tp->t_blk_res > 0) 104545c34141SDavid Chinner blkdelta = tp->t_blk_res; 104645c34141SDavid Chinner if ((tp->t_fdblocks_delta != 0) && 104745c34141SDavid Chinner (xfs_sb_version_haslazysbcount(&mp->m_sb) || 104845c34141SDavid Chinner (tp->t_flags & XFS_TRANS_SB_DIRTY))) 104945c34141SDavid Chinner blkdelta += tp->t_fdblocks_delta; 105045c34141SDavid Chinner 105145c34141SDavid Chinner if (tp->t_rtx_res > 0) 105245c34141SDavid Chinner rtxdelta = tp->t_rtx_res; 105345c34141SDavid Chinner if ((tp->t_frextents_delta != 0) && 105445c34141SDavid Chinner (tp->t_flags & XFS_TRANS_SB_DIRTY)) 105545c34141SDavid Chinner rtxdelta += tp->t_frextents_delta; 105645c34141SDavid Chinner 10571b040712SChristoph Hellwig if (xfs_sb_version_haslazysbcount(&mp->m_sb) || 10581b040712SChristoph Hellwig (tp->t_flags & XFS_TRANS_SB_DIRTY)) { 10591b040712SChristoph Hellwig idelta = tp->t_icount_delta; 10601b040712SChristoph Hellwig ifreedelta = tp->t_ifree_delta; 10611b040712SChristoph Hellwig } 10621b040712SChristoph Hellwig 10631b040712SChristoph Hellwig /* apply the per-cpu counters */ 10641b040712SChristoph Hellwig if (blkdelta) { 10651b040712SChristoph Hellwig error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, 10661b040712SChristoph Hellwig blkdelta, rsvd); 10671b040712SChristoph Hellwig if (error) 10681b040712SChristoph Hellwig goto out; 10691b040712SChristoph Hellwig } 10701b040712SChristoph Hellwig 10711b040712SChristoph Hellwig if (idelta) { 10721b040712SChristoph Hellwig error = xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, 10731b040712SChristoph Hellwig idelta, rsvd); 10741b040712SChristoph Hellwig if (error) 10751b040712SChristoph Hellwig goto out_undo_fdblocks; 10761b040712SChristoph Hellwig } 10771b040712SChristoph Hellwig 10781b040712SChristoph Hellwig if (ifreedelta) { 10791b040712SChristoph Hellwig error = xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, 10801b040712SChristoph Hellwig ifreedelta, rsvd); 10811b040712SChristoph Hellwig if (error) 10821b040712SChristoph Hellwig goto out_undo_icount; 10831b040712SChristoph Hellwig } 10841b040712SChristoph Hellwig 10851b040712SChristoph Hellwig /* apply remaining deltas */ 108645c34141SDavid Chinner if (rtxdelta != 0) { 10871da177e4SLinus Torvalds msbp->msb_field = XFS_SBS_FREXTENTS; 108845c34141SDavid Chinner msbp->msb_delta = rtxdelta; 10891da177e4SLinus Torvalds msbp++; 10901da177e4SLinus Torvalds } 10911da177e4SLinus Torvalds 109292821e2bSDavid Chinner if (tp->t_flags & XFS_TRANS_SB_DIRTY) { 10931da177e4SLinus Torvalds if (tp->t_dblocks_delta != 0) { 10941da177e4SLinus Torvalds msbp->msb_field = XFS_SBS_DBLOCKS; 109520f4ebf2SDavid Chinner msbp->msb_delta = tp->t_dblocks_delta; 10961da177e4SLinus Torvalds msbp++; 10971da177e4SLinus Torvalds } 10981da177e4SLinus Torvalds if (tp->t_agcount_delta != 0) { 10991da177e4SLinus Torvalds msbp->msb_field = XFS_SBS_AGCOUNT; 110020f4ebf2SDavid Chinner msbp->msb_delta = tp->t_agcount_delta; 11011da177e4SLinus Torvalds msbp++; 11021da177e4SLinus Torvalds } 11031da177e4SLinus Torvalds if (tp->t_imaxpct_delta != 0) { 11041da177e4SLinus Torvalds msbp->msb_field = XFS_SBS_IMAX_PCT; 110520f4ebf2SDavid Chinner msbp->msb_delta = tp->t_imaxpct_delta; 11061da177e4SLinus Torvalds msbp++; 11071da177e4SLinus Torvalds } 11081da177e4SLinus Torvalds if (tp->t_rextsize_delta != 0) { 11091da177e4SLinus Torvalds msbp->msb_field = XFS_SBS_REXTSIZE; 111020f4ebf2SDavid Chinner msbp->msb_delta = tp->t_rextsize_delta; 11111da177e4SLinus Torvalds msbp++; 11121da177e4SLinus Torvalds } 11131da177e4SLinus Torvalds if (tp->t_rbmblocks_delta != 0) { 11141da177e4SLinus Torvalds msbp->msb_field = XFS_SBS_RBMBLOCKS; 111520f4ebf2SDavid Chinner msbp->msb_delta = tp->t_rbmblocks_delta; 11161da177e4SLinus Torvalds msbp++; 11171da177e4SLinus Torvalds } 11181da177e4SLinus Torvalds if (tp->t_rblocks_delta != 0) { 11191da177e4SLinus Torvalds msbp->msb_field = XFS_SBS_RBLOCKS; 112020f4ebf2SDavid Chinner msbp->msb_delta = tp->t_rblocks_delta; 11211da177e4SLinus Torvalds msbp++; 11221da177e4SLinus Torvalds } 11231da177e4SLinus Torvalds if (tp->t_rextents_delta != 0) { 11241da177e4SLinus Torvalds msbp->msb_field = XFS_SBS_REXTENTS; 112520f4ebf2SDavid Chinner msbp->msb_delta = tp->t_rextents_delta; 11261da177e4SLinus Torvalds msbp++; 11271da177e4SLinus Torvalds } 11281da177e4SLinus Torvalds if (tp->t_rextslog_delta != 0) { 11291da177e4SLinus Torvalds msbp->msb_field = XFS_SBS_REXTSLOG; 113020f4ebf2SDavid Chinner msbp->msb_delta = tp->t_rextslog_delta; 11311da177e4SLinus Torvalds msbp++; 11321da177e4SLinus Torvalds } 11331da177e4SLinus Torvalds } 11341da177e4SLinus Torvalds 11351da177e4SLinus Torvalds /* 11361da177e4SLinus Torvalds * If we need to change anything, do it. 11371da177e4SLinus Torvalds */ 11381da177e4SLinus Torvalds if (msbp > msb) { 11391da177e4SLinus Torvalds error = xfs_mod_incore_sb_batch(tp->t_mountp, msb, 11401da177e4SLinus Torvalds (uint)(msbp - msb), rsvd); 11411b040712SChristoph Hellwig if (error) 11421b040712SChristoph Hellwig goto out_undo_ifreecount; 11431da177e4SLinus Torvalds } 11441b040712SChristoph Hellwig 11451b040712SChristoph Hellwig return; 11461b040712SChristoph Hellwig 11471b040712SChristoph Hellwig out_undo_ifreecount: 11481b040712SChristoph Hellwig if (ifreedelta) 11491b040712SChristoph Hellwig xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd); 11501b040712SChristoph Hellwig out_undo_icount: 11511b040712SChristoph Hellwig if (idelta) 11521b040712SChristoph Hellwig xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd); 11531b040712SChristoph Hellwig out_undo_fdblocks: 11541b040712SChristoph Hellwig if (blkdelta) 11551b040712SChristoph Hellwig xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd); 11561b040712SChristoph Hellwig out: 11571884bd83SJesper Juhl ASSERT(error == 0); 11581b040712SChristoph Hellwig return; 11591da177e4SLinus Torvalds } 11601da177e4SLinus Torvalds 11611da177e4SLinus Torvalds /* 1162e98c414fSChristoph Hellwig * Add the given log item to the transaction's list of log items. 1163e98c414fSChristoph Hellwig * 1164e98c414fSChristoph Hellwig * The log item will now point to its new descriptor with its li_desc field. 1165e98c414fSChristoph Hellwig */ 1166e98c414fSChristoph Hellwig void 1167e98c414fSChristoph Hellwig xfs_trans_add_item( 1168e98c414fSChristoph Hellwig struct xfs_trans *tp, 1169e98c414fSChristoph Hellwig struct xfs_log_item *lip) 1170e98c414fSChristoph Hellwig { 1171e98c414fSChristoph Hellwig struct xfs_log_item_desc *lidp; 1172e98c414fSChristoph Hellwig 1173f65020a8SJesper Juhl ASSERT(lip->li_mountp == tp->t_mountp); 1174f65020a8SJesper Juhl ASSERT(lip->li_ailp == tp->t_mountp->m_ail); 1175e98c414fSChristoph Hellwig 117643869706SDave Chinner lidp = kmem_zone_zalloc(xfs_log_item_desc_zone, KM_SLEEP | KM_NOFS); 1177e98c414fSChristoph Hellwig 1178e98c414fSChristoph Hellwig lidp->lid_item = lip; 1179e98c414fSChristoph Hellwig lidp->lid_flags = 0; 1180e98c414fSChristoph Hellwig list_add_tail(&lidp->lid_trans, &tp->t_items); 1181e98c414fSChristoph Hellwig 1182e98c414fSChristoph Hellwig lip->li_desc = lidp; 1183e98c414fSChristoph Hellwig } 1184e98c414fSChristoph Hellwig 1185e98c414fSChristoph Hellwig STATIC void 1186e98c414fSChristoph Hellwig xfs_trans_free_item_desc( 1187e98c414fSChristoph Hellwig struct xfs_log_item_desc *lidp) 1188e98c414fSChristoph Hellwig { 1189e98c414fSChristoph Hellwig list_del_init(&lidp->lid_trans); 1190e98c414fSChristoph Hellwig kmem_zone_free(xfs_log_item_desc_zone, lidp); 1191e98c414fSChristoph Hellwig } 1192e98c414fSChristoph Hellwig 1193e98c414fSChristoph Hellwig /* 1194e98c414fSChristoph Hellwig * Unlink and free the given descriptor. 1195e98c414fSChristoph Hellwig */ 1196e98c414fSChristoph Hellwig void 1197e98c414fSChristoph Hellwig xfs_trans_del_item( 1198e98c414fSChristoph Hellwig struct xfs_log_item *lip) 1199e98c414fSChristoph Hellwig { 1200e98c414fSChristoph Hellwig xfs_trans_free_item_desc(lip->li_desc); 1201e98c414fSChristoph Hellwig lip->li_desc = NULL; 1202e98c414fSChristoph Hellwig } 1203e98c414fSChristoph Hellwig 1204e98c414fSChristoph Hellwig /* 1205e98c414fSChristoph Hellwig * Unlock all of the items of a transaction and free all the descriptors 1206e98c414fSChristoph Hellwig * of that transaction. 1207e98c414fSChristoph Hellwig */ 1208d17c701cSDave Chinner void 1209e98c414fSChristoph Hellwig xfs_trans_free_items( 1210e98c414fSChristoph Hellwig struct xfs_trans *tp, 1211e98c414fSChristoph Hellwig xfs_lsn_t commit_lsn, 1212e98c414fSChristoph Hellwig int flags) 1213e98c414fSChristoph Hellwig { 1214e98c414fSChristoph Hellwig struct xfs_log_item_desc *lidp, *next; 1215e98c414fSChristoph Hellwig 1216e98c414fSChristoph Hellwig list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) { 1217e98c414fSChristoph Hellwig struct xfs_log_item *lip = lidp->lid_item; 1218e98c414fSChristoph Hellwig 1219e98c414fSChristoph Hellwig lip->li_desc = NULL; 1220e98c414fSChristoph Hellwig 1221e98c414fSChristoph Hellwig if (commit_lsn != NULLCOMMITLSN) 1222e98c414fSChristoph Hellwig IOP_COMMITTING(lip, commit_lsn); 1223e98c414fSChristoph Hellwig if (flags & XFS_TRANS_ABORT) 1224e98c414fSChristoph Hellwig lip->li_flags |= XFS_LI_ABORTED; 1225e98c414fSChristoph Hellwig IOP_UNLOCK(lip); 1226e98c414fSChristoph Hellwig 1227e98c414fSChristoph Hellwig xfs_trans_free_item_desc(lidp); 1228e98c414fSChristoph Hellwig } 1229e98c414fSChristoph Hellwig } 1230e98c414fSChristoph Hellwig 12310e57f6a3SDave Chinner static inline void 12320e57f6a3SDave Chinner xfs_log_item_batch_insert( 12330e57f6a3SDave Chinner struct xfs_ail *ailp, 12341d8c95a3SDave Chinner struct xfs_ail_cursor *cur, 12350e57f6a3SDave Chinner struct xfs_log_item **log_items, 12360e57f6a3SDave Chinner int nr_items, 12370e57f6a3SDave Chinner xfs_lsn_t commit_lsn) 12380e57f6a3SDave Chinner { 12390e57f6a3SDave Chinner int i; 12400e57f6a3SDave Chinner 12410e57f6a3SDave Chinner spin_lock(&ailp->xa_lock); 12420e57f6a3SDave Chinner /* xfs_trans_ail_update_bulk drops ailp->xa_lock */ 12431d8c95a3SDave Chinner xfs_trans_ail_update_bulk(ailp, cur, log_items, nr_items, commit_lsn); 12440e57f6a3SDave Chinner 12450e57f6a3SDave Chinner for (i = 0; i < nr_items; i++) 12460e57f6a3SDave Chinner IOP_UNPIN(log_items[i], 0); 12470e57f6a3SDave Chinner } 12480e57f6a3SDave Chinner 12490e57f6a3SDave Chinner /* 12500e57f6a3SDave Chinner * Bulk operation version of xfs_trans_committed that takes a log vector of 12510e57f6a3SDave Chinner * items to insert into the AIL. This uses bulk AIL insertion techniques to 12520e57f6a3SDave Chinner * minimise lock traffic. 1253e34a314cSDave Chinner * 1254e34a314cSDave Chinner * If we are called with the aborted flag set, it is because a log write during 1255e34a314cSDave Chinner * a CIL checkpoint commit has failed. In this case, all the items in the 1256e34a314cSDave Chinner * checkpoint have already gone through IOP_COMMITED and IOP_UNLOCK, which 1257e34a314cSDave Chinner * means that checkpoint commit abort handling is treated exactly the same 1258e34a314cSDave Chinner * as an iclog write error even though we haven't started any IO yet. Hence in 1259e34a314cSDave Chinner * this case all we need to do is IOP_COMMITTED processing, followed by an 1260e34a314cSDave Chinner * IOP_UNPIN(aborted) call. 12611d8c95a3SDave Chinner * 12621d8c95a3SDave Chinner * The AIL cursor is used to optimise the insert process. If commit_lsn is not 12631d8c95a3SDave Chinner * at the end of the AIL, the insert cursor avoids the need to walk 12641d8c95a3SDave Chinner * the AIL to find the insertion point on every xfs_log_item_batch_insert() 12651d8c95a3SDave Chinner * call. This saves a lot of needless list walking and is a net win, even 12661d8c95a3SDave Chinner * though it slightly increases that amount of AIL lock traffic to set it up 12671d8c95a3SDave Chinner * and tear it down. 12680e57f6a3SDave Chinner */ 12690e57f6a3SDave Chinner void 12700e57f6a3SDave Chinner xfs_trans_committed_bulk( 12710e57f6a3SDave Chinner struct xfs_ail *ailp, 12720e57f6a3SDave Chinner struct xfs_log_vec *log_vector, 12730e57f6a3SDave Chinner xfs_lsn_t commit_lsn, 12740e57f6a3SDave Chinner int aborted) 12750e57f6a3SDave Chinner { 12760e57f6a3SDave Chinner #define LOG_ITEM_BATCH_SIZE 32 12770e57f6a3SDave Chinner struct xfs_log_item *log_items[LOG_ITEM_BATCH_SIZE]; 12780e57f6a3SDave Chinner struct xfs_log_vec *lv; 12791d8c95a3SDave Chinner struct xfs_ail_cursor cur; 12800e57f6a3SDave Chinner int i = 0; 12810e57f6a3SDave Chinner 12821d8c95a3SDave Chinner spin_lock(&ailp->xa_lock); 12831d8c95a3SDave Chinner xfs_trans_ail_cursor_last(ailp, &cur, commit_lsn); 12841d8c95a3SDave Chinner spin_unlock(&ailp->xa_lock); 12851d8c95a3SDave Chinner 12860e57f6a3SDave Chinner /* unpin all the log items */ 12870e57f6a3SDave Chinner for (lv = log_vector; lv; lv = lv->lv_next ) { 12880e57f6a3SDave Chinner struct xfs_log_item *lip = lv->lv_item; 12890e57f6a3SDave Chinner xfs_lsn_t item_lsn; 12900e57f6a3SDave Chinner 12910e57f6a3SDave Chinner if (aborted) 12920e57f6a3SDave Chinner lip->li_flags |= XFS_LI_ABORTED; 12930e57f6a3SDave Chinner item_lsn = IOP_COMMITTED(lip, commit_lsn); 12940e57f6a3SDave Chinner 12951316d4daSDave Chinner /* item_lsn of -1 means the item needs no further processing */ 12960e57f6a3SDave Chinner if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0) 12970e57f6a3SDave Chinner continue; 12980e57f6a3SDave Chinner 1299e34a314cSDave Chinner /* 1300e34a314cSDave Chinner * if we are aborting the operation, no point in inserting the 1301e34a314cSDave Chinner * object into the AIL as we are in a shutdown situation. 1302e34a314cSDave Chinner */ 1303e34a314cSDave Chinner if (aborted) { 1304e34a314cSDave Chinner ASSERT(XFS_FORCED_SHUTDOWN(ailp->xa_mount)); 1305e34a314cSDave Chinner IOP_UNPIN(lip, 1); 1306e34a314cSDave Chinner continue; 1307e34a314cSDave Chinner } 1308e34a314cSDave Chinner 13090e57f6a3SDave Chinner if (item_lsn != commit_lsn) { 13100e57f6a3SDave Chinner 13110e57f6a3SDave Chinner /* 13120e57f6a3SDave Chinner * Not a bulk update option due to unusual item_lsn. 13130e57f6a3SDave Chinner * Push into AIL immediately, rechecking the lsn once 13141d8c95a3SDave Chinner * we have the ail lock. Then unpin the item. This does 13151d8c95a3SDave Chinner * not affect the AIL cursor the bulk insert path is 13161d8c95a3SDave Chinner * using. 13170e57f6a3SDave Chinner */ 13180e57f6a3SDave Chinner spin_lock(&ailp->xa_lock); 13190e57f6a3SDave Chinner if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0) 13200e57f6a3SDave Chinner xfs_trans_ail_update(ailp, lip, item_lsn); 13210e57f6a3SDave Chinner else 13220e57f6a3SDave Chinner spin_unlock(&ailp->xa_lock); 13230e57f6a3SDave Chinner IOP_UNPIN(lip, 0); 13240e57f6a3SDave Chinner continue; 13250e57f6a3SDave Chinner } 13260e57f6a3SDave Chinner 13270e57f6a3SDave Chinner /* Item is a candidate for bulk AIL insert. */ 13280e57f6a3SDave Chinner log_items[i++] = lv->lv_item; 13290e57f6a3SDave Chinner if (i >= LOG_ITEM_BATCH_SIZE) { 13301d8c95a3SDave Chinner xfs_log_item_batch_insert(ailp, &cur, log_items, 13310e57f6a3SDave Chinner LOG_ITEM_BATCH_SIZE, commit_lsn); 13320e57f6a3SDave Chinner i = 0; 13330e57f6a3SDave Chinner } 13340e57f6a3SDave Chinner } 13350e57f6a3SDave Chinner 13360e57f6a3SDave Chinner /* make sure we insert the remainder! */ 13370e57f6a3SDave Chinner if (i) 13381d8c95a3SDave Chinner xfs_log_item_batch_insert(ailp, &cur, log_items, i, commit_lsn); 13391d8c95a3SDave Chinner 13401d8c95a3SDave Chinner spin_lock(&ailp->xa_lock); 13411d8c95a3SDave Chinner xfs_trans_ail_cursor_done(ailp, &cur); 13421d8c95a3SDave Chinner spin_unlock(&ailp->xa_lock); 13430e57f6a3SDave Chinner } 13440e57f6a3SDave Chinner 1345b1c1b5b6SDave Chinner /* 1346b1037058SChristoph Hellwig * Commit the given transaction to the log. 13470924378aSDave Chinner * 13480924378aSDave Chinner * XFS disk error handling mechanism is not based on a typical 13490924378aSDave Chinner * transaction abort mechanism. Logically after the filesystem 13500924378aSDave Chinner * gets marked 'SHUTDOWN', we can't let any new transactions 13510924378aSDave Chinner * be durable - ie. committed to disk - because some metadata might 13520924378aSDave Chinner * be inconsistent. In such cases, this returns an error, and the 13530924378aSDave Chinner * caller may assume that all locked objects joined to the transaction 13540924378aSDave Chinner * have already been unlocked as if the commit had succeeded. 13550924378aSDave Chinner * Do not reference the transaction structure after this call. 13560924378aSDave Chinner */ 13570924378aSDave Chinner int 1358b1037058SChristoph Hellwig xfs_trans_commit( 1359a3ccd2caSChristoph Hellwig struct xfs_trans *tp, 1360b1037058SChristoph Hellwig uint flags) 13610924378aSDave Chinner { 1362a3ccd2caSChristoph Hellwig struct xfs_mount *mp = tp->t_mountp; 13630924378aSDave Chinner xfs_lsn_t commit_lsn = -1; 1364a3ccd2caSChristoph Hellwig int error = 0; 13650924378aSDave Chinner int log_flags = 0; 13660924378aSDave Chinner int sync = tp->t_flags & XFS_TRANS_SYNC; 13670924378aSDave Chinner 13680924378aSDave Chinner /* 13690924378aSDave Chinner * Determine whether this commit is releasing a permanent 13700924378aSDave Chinner * log reservation or not. 13710924378aSDave Chinner */ 13720924378aSDave Chinner if (flags & XFS_TRANS_RELEASE_LOG_RES) { 13730924378aSDave Chinner ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); 13740924378aSDave Chinner log_flags = XFS_LOG_REL_PERM_RESERV; 13750924378aSDave Chinner } 13760924378aSDave Chinner 13770924378aSDave Chinner /* 13780924378aSDave Chinner * If there is nothing to be logged by the transaction, 13790924378aSDave Chinner * then unlock all of the items associated with the 13800924378aSDave Chinner * transaction and free the transaction structure. 13810924378aSDave Chinner * Also make sure to return any reserved blocks to 13820924378aSDave Chinner * the free pool. 13830924378aSDave Chinner */ 1384a3ccd2caSChristoph Hellwig if (!(tp->t_flags & XFS_TRANS_DIRTY)) 1385a3ccd2caSChristoph Hellwig goto out_unreserve; 1386a3ccd2caSChristoph Hellwig 1387a3ccd2caSChristoph Hellwig if (XFS_FORCED_SHUTDOWN(mp)) { 1388a3ccd2caSChristoph Hellwig error = XFS_ERROR(EIO); 1389a3ccd2caSChristoph Hellwig goto out_unreserve; 13900924378aSDave Chinner } 1391a3ccd2caSChristoph Hellwig 13920924378aSDave Chinner ASSERT(tp->t_ticket != NULL); 13930924378aSDave Chinner 13940924378aSDave Chinner /* 13950924378aSDave Chinner * If we need to update the superblock, then do it now. 13960924378aSDave Chinner */ 13970924378aSDave Chinner if (tp->t_flags & XFS_TRANS_SB_DIRTY) 13980924378aSDave Chinner xfs_trans_apply_sb_deltas(tp); 13990924378aSDave Chinner xfs_trans_apply_dquot_deltas(tp); 14000924378aSDave Chinner 14010244b960SChristoph Hellwig error = xfs_log_commit_cil(mp, tp, &commit_lsn, flags); 14020924378aSDave Chinner if (error == ENOMEM) { 14030924378aSDave Chinner xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); 1404a3ccd2caSChristoph Hellwig error = XFS_ERROR(EIO); 1405a3ccd2caSChristoph Hellwig goto out_unreserve; 14060924378aSDave Chinner } 14071da177e4SLinus Torvalds 14080244b960SChristoph Hellwig current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); 14090244b960SChristoph Hellwig xfs_trans_free(tp); 14100244b960SChristoph Hellwig 14111da177e4SLinus Torvalds /* 14121da177e4SLinus Torvalds * If the transaction needs to be synchronous, then force the 14131da177e4SLinus Torvalds * log out now and wait for it. 14141da177e4SLinus Torvalds */ 14151da177e4SLinus Torvalds if (sync) { 1416f538d4daSChristoph Hellwig if (!error) { 1417a14a348bSChristoph Hellwig error = _xfs_log_force_lsn(mp, commit_lsn, 1418b1037058SChristoph Hellwig XFS_LOG_SYNC, NULL); 1419f538d4daSChristoph Hellwig } 14201da177e4SLinus Torvalds XFS_STATS_INC(xs_trans_sync); 14211da177e4SLinus Torvalds } else { 14221da177e4SLinus Torvalds XFS_STATS_INC(xs_trans_async); 14231da177e4SLinus Torvalds } 14241da177e4SLinus Torvalds 1425a3ccd2caSChristoph Hellwig return error; 1426a3ccd2caSChristoph Hellwig 1427a3ccd2caSChristoph Hellwig out_unreserve: 1428a3ccd2caSChristoph Hellwig xfs_trans_unreserve_and_mod_sb(tp); 1429a3ccd2caSChristoph Hellwig 1430a3ccd2caSChristoph Hellwig /* 1431a3ccd2caSChristoph Hellwig * It is indeed possible for the transaction to be not dirty but 1432a3ccd2caSChristoph Hellwig * the dqinfo portion to be. All that means is that we have some 1433a3ccd2caSChristoph Hellwig * (non-persistent) quota reservations that need to be unreserved. 1434a3ccd2caSChristoph Hellwig */ 1435a3ccd2caSChristoph Hellwig xfs_trans_unreserve_and_mod_dquots(tp); 1436a3ccd2caSChristoph Hellwig if (tp->t_ticket) { 1437a3ccd2caSChristoph Hellwig commit_lsn = xfs_log_done(mp, tp->t_ticket, NULL, log_flags); 1438a3ccd2caSChristoph Hellwig if (commit_lsn == -1 && !error) 1439a3ccd2caSChristoph Hellwig error = XFS_ERROR(EIO); 1440a3ccd2caSChristoph Hellwig } 1441a3ccd2caSChristoph Hellwig current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); 144271e330b5SDave Chinner xfs_trans_free_items(tp, NULLCOMMITLSN, error ? XFS_TRANS_ABORT : 0); 1443a3ccd2caSChristoph Hellwig xfs_trans_free(tp); 1444a3ccd2caSChristoph Hellwig 1445a3ccd2caSChristoph Hellwig XFS_STATS_INC(xs_trans_empty); 1446a3ccd2caSChristoph Hellwig return error; 14471da177e4SLinus Torvalds } 14481da177e4SLinus Torvalds 14491da177e4SLinus Torvalds /* 14501da177e4SLinus Torvalds * Unlock all of the transaction's items and free the transaction. 14511da177e4SLinus Torvalds * The transaction must not have modified any of its items, because 14521da177e4SLinus Torvalds * there is no way to restore them to their previous state. 14531da177e4SLinus Torvalds * 14541da177e4SLinus Torvalds * If the transaction has made a log reservation, make sure to release 14551da177e4SLinus Torvalds * it as well. 14561da177e4SLinus Torvalds */ 14571da177e4SLinus Torvalds void 14581da177e4SLinus Torvalds xfs_trans_cancel( 14591da177e4SLinus Torvalds xfs_trans_t *tp, 14601da177e4SLinus Torvalds int flags) 14611da177e4SLinus Torvalds { 14621da177e4SLinus Torvalds int log_flags; 14630733af21SRyan Hankins xfs_mount_t *mp = tp->t_mountp; 14641da177e4SLinus Torvalds 14651da177e4SLinus Torvalds /* 14661da177e4SLinus Torvalds * See if the caller is being too lazy to figure out if 14671da177e4SLinus Torvalds * the transaction really needs an abort. 14681da177e4SLinus Torvalds */ 14691da177e4SLinus Torvalds if ((flags & XFS_TRANS_ABORT) && !(tp->t_flags & XFS_TRANS_DIRTY)) 14701da177e4SLinus Torvalds flags &= ~XFS_TRANS_ABORT; 14711da177e4SLinus Torvalds /* 14721da177e4SLinus Torvalds * See if the caller is relying on us to shut down the 14731da177e4SLinus Torvalds * filesystem. This happens in paths where we detect 14741da177e4SLinus Torvalds * corruption and decide to give up. 14751da177e4SLinus Torvalds */ 147660a204f0SNathan Scott if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) { 14770733af21SRyan Hankins XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp); 14787d04a335SNathan Scott xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 147960a204f0SNathan Scott } 14801da177e4SLinus Torvalds #ifdef DEBUG 1481e98c414fSChristoph Hellwig if (!(flags & XFS_TRANS_ABORT) && !XFS_FORCED_SHUTDOWN(mp)) { 1482e98c414fSChristoph Hellwig struct xfs_log_item_desc *lidp; 14831da177e4SLinus Torvalds 1484e98c414fSChristoph Hellwig list_for_each_entry(lidp, &tp->t_items, lid_trans) 1485e98c414fSChristoph Hellwig ASSERT(!(lidp->lid_item->li_type == XFS_LI_EFD)); 14861da177e4SLinus Torvalds } 14871da177e4SLinus Torvalds #endif 14881da177e4SLinus Torvalds xfs_trans_unreserve_and_mod_sb(tp); 14897d095257SChristoph Hellwig xfs_trans_unreserve_and_mod_dquots(tp); 14901da177e4SLinus Torvalds 14911da177e4SLinus Torvalds if (tp->t_ticket) { 14921da177e4SLinus Torvalds if (flags & XFS_TRANS_RELEASE_LOG_RES) { 14931da177e4SLinus Torvalds ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); 14941da177e4SLinus Torvalds log_flags = XFS_LOG_REL_PERM_RESERV; 14951da177e4SLinus Torvalds } else { 14961da177e4SLinus Torvalds log_flags = 0; 14971da177e4SLinus Torvalds } 14980733af21SRyan Hankins xfs_log_done(mp, tp->t_ticket, NULL, log_flags); 14991da177e4SLinus Torvalds } 15001da177e4SLinus Torvalds 15011da177e4SLinus Torvalds /* mark this thread as no longer being in a transaction */ 150259c1b082SNathan Scott current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); 15031da177e4SLinus Torvalds 150471e330b5SDave Chinner xfs_trans_free_items(tp, NULLCOMMITLSN, flags); 15051da177e4SLinus Torvalds xfs_trans_free(tp); 15061da177e4SLinus Torvalds } 15071da177e4SLinus Torvalds 1508322ff6b8SNiv Sardi /* 1509322ff6b8SNiv Sardi * Roll from one trans in the sequence of PERMANENT transactions to 1510322ff6b8SNiv Sardi * the next: permanent transactions are only flushed out when 1511322ff6b8SNiv Sardi * committed with XFS_TRANS_RELEASE_LOG_RES, but we still want as soon 1512322ff6b8SNiv Sardi * as possible to let chunks of it go to the log. So we commit the 1513322ff6b8SNiv Sardi * chunk we've been working on and get a new transaction to continue. 1514322ff6b8SNiv Sardi */ 1515322ff6b8SNiv Sardi int 1516322ff6b8SNiv Sardi xfs_trans_roll( 1517322ff6b8SNiv Sardi struct xfs_trans **tpp, 1518322ff6b8SNiv Sardi struct xfs_inode *dp) 1519322ff6b8SNiv Sardi { 1520322ff6b8SNiv Sardi struct xfs_trans *trans; 1521322ff6b8SNiv Sardi unsigned int logres, count; 1522322ff6b8SNiv Sardi int error; 1523322ff6b8SNiv Sardi 1524322ff6b8SNiv Sardi /* 1525322ff6b8SNiv Sardi * Ensure that the inode is always logged. 1526322ff6b8SNiv Sardi */ 1527322ff6b8SNiv Sardi trans = *tpp; 1528322ff6b8SNiv Sardi xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE); 1529322ff6b8SNiv Sardi 1530322ff6b8SNiv Sardi /* 1531322ff6b8SNiv Sardi * Copy the critical parameters from one trans to the next. 1532322ff6b8SNiv Sardi */ 1533322ff6b8SNiv Sardi logres = trans->t_log_res; 1534322ff6b8SNiv Sardi count = trans->t_log_count; 1535322ff6b8SNiv Sardi *tpp = xfs_trans_dup(trans); 1536322ff6b8SNiv Sardi 1537322ff6b8SNiv Sardi /* 1538322ff6b8SNiv Sardi * Commit the current transaction. 1539322ff6b8SNiv Sardi * If this commit failed, then it'd just unlock those items that 1540322ff6b8SNiv Sardi * are not marked ihold. That also means that a filesystem shutdown 1541322ff6b8SNiv Sardi * is in progress. The caller takes the responsibility to cancel 1542322ff6b8SNiv Sardi * the duplicate transaction that gets returned. 1543322ff6b8SNiv Sardi */ 1544322ff6b8SNiv Sardi error = xfs_trans_commit(trans, 0); 1545322ff6b8SNiv Sardi if (error) 1546322ff6b8SNiv Sardi return (error); 1547322ff6b8SNiv Sardi 1548322ff6b8SNiv Sardi trans = *tpp; 1549322ff6b8SNiv Sardi 1550322ff6b8SNiv Sardi /* 1551cc09c0dcSDave Chinner * transaction commit worked ok so we can drop the extra ticket 1552cc09c0dcSDave Chinner * reference that we gained in xfs_trans_dup() 1553cc09c0dcSDave Chinner */ 1554cc09c0dcSDave Chinner xfs_log_ticket_put(trans->t_ticket); 1555cc09c0dcSDave Chinner 1556cc09c0dcSDave Chinner 1557cc09c0dcSDave Chinner /* 1558322ff6b8SNiv Sardi * Reserve space in the log for th next transaction. 1559322ff6b8SNiv Sardi * This also pushes items in the "AIL", the list of logged items, 1560322ff6b8SNiv Sardi * out to disk if they are taking up space at the tail of the log 1561322ff6b8SNiv Sardi * that we want to use. This requires that either nothing be locked 1562322ff6b8SNiv Sardi * across this call, or that anything that is locked be logged in 1563322ff6b8SNiv Sardi * the prior and the next transactions. 1564322ff6b8SNiv Sardi */ 1565322ff6b8SNiv Sardi error = xfs_trans_reserve(trans, 0, logres, 0, 1566322ff6b8SNiv Sardi XFS_TRANS_PERM_LOG_RES, count); 1567322ff6b8SNiv Sardi /* 1568322ff6b8SNiv Sardi * Ensure that the inode is in the new transaction and locked. 1569322ff6b8SNiv Sardi */ 1570322ff6b8SNiv Sardi if (error) 1571322ff6b8SNiv Sardi return error; 1572322ff6b8SNiv Sardi 1573ddc3415aSChristoph Hellwig xfs_trans_ijoin(trans, dp, 0); 1574322ff6b8SNiv Sardi return 0; 1575322ff6b8SNiv Sardi } 1576