1/* 2 * Copyright (c) 2013 Jie Liu. 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18#include "xfs.h" 19#include "xfs_fs.h" 20#include "xfs_shared.h" 21#include "xfs_format.h" 22#include "xfs_log_format.h" 23#include "xfs_trans_resv.h" 24#include "xfs_mount.h" 25#include "xfs_da_format.h" 26#include "xfs_trans_space.h" 27#include "xfs_inode.h" 28#include "xfs_da_btree.h" 29#include "xfs_attr_leaf.h" 30#include "xfs_bmap_btree.h" 31 32/* 33 * Calculate the maximum length in bytes that would be required for a local 34 * attribute value as large attributes out of line are not logged. 35 */ 36STATIC int 37xfs_log_calc_max_attrsetm_res( 38 struct xfs_mount *mp) 39{ 40 int size; 41 int nblks; 42 43 size = xfs_attr_leaf_entsize_local_max(mp->m_attr_geo->blksize) - 44 MAXNAMELEN - 1; 45 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); 46 nblks += XFS_B_TO_FSB(mp, size); 47 nblks += XFS_NEXTENTADD_SPACE_RES(mp, size, XFS_ATTR_FORK); 48 49 return M_RES(mp)->tr_attrsetm.tr_logres + 50 M_RES(mp)->tr_attrsetrt.tr_logres * nblks; 51} 52 53/* 54 * Iterate over the log space reservation table to figure out and return 55 * the maximum one in terms of the pre-calculated values which were done 56 * at mount time. 57 */ 58STATIC void 59xfs_log_get_max_trans_res( 60 struct xfs_mount *mp, 61 struct xfs_trans_res *max_resp) 62{ 63 struct xfs_trans_res *resp; 64 struct xfs_trans_res *end_resp; 65 int log_space = 0; 66 int attr_space; 67 68 attr_space = xfs_log_calc_max_attrsetm_res(mp); 69 70 resp = (struct xfs_trans_res *)M_RES(mp); 71 end_resp = (struct xfs_trans_res *)(M_RES(mp) + 1); 72 for (; resp < end_resp; resp++) { 73 int tmp = resp->tr_logcount > 1 ? 74 resp->tr_logres * resp->tr_logcount : 75 resp->tr_logres; 76 if (log_space < tmp) { 77 log_space = tmp; 78 *max_resp = *resp; /* struct copy */ 79 } 80 } 81 82 if (attr_space > log_space) { 83 *max_resp = M_RES(mp)->tr_attrsetm; /* struct copy */ 84 max_resp->tr_logres = attr_space; 85 } 86} 87 88/* 89 * Calculate the minimum valid log size for the given superblock configuration. 90 * Used to calculate the minimum log size at mkfs time, and to determine if 91 * the log is large enough or not at mount time. Returns the minimum size in 92 * filesystem block size units. 93 */ 94int 95xfs_log_calc_minimum_size( 96 struct xfs_mount *mp) 97{ 98 struct xfs_trans_res tres = {0}; 99 int max_logres; 100 int min_logblks = 0; 101 int lsunit = 0; 102 103 xfs_log_get_max_trans_res(mp, &tres); 104 105 max_logres = xfs_log_calc_unit_res(mp, tres.tr_logres); 106 if (tres.tr_logcount > 1) 107 max_logres *= tres.tr_logcount; 108 109 if (xfs_sb_version_haslogv2(&mp->m_sb) && mp->m_sb.sb_logsunit > 1) 110 lsunit = BTOBB(mp->m_sb.sb_logsunit); 111 112 /* 113 * Two factors should be taken into account for calculating the minimum 114 * log space. 115 * 1) The fundamental limitation is that no single transaction can be 116 * larger than half size of the log. 117 * 118 * From mkfs.xfs, this is considered by the XFS_MIN_LOG_FACTOR 119 * define, which is set to 3. That means we can definitely fit 120 * maximally sized 2 transactions in the log. We'll use this same 121 * value here. 122 * 123 * 2) If the lsunit option is specified, a transaction requires 2 LSU 124 * for the reservation because there are two log writes that can 125 * require padding - the transaction data and the commit record which 126 * are written separately and both can require padding to the LSU. 127 * Consider that we can have an active CIL reservation holding 2*LSU, 128 * but the CIL is not over a push threshold, in this case, if we 129 * don't have enough log space for at one new transaction, which 130 * includes another 2*LSU in the reservation, we will run into dead 131 * loop situation in log space grant procedure. i.e. 132 * xlog_grant_head_wait(). 133 * 134 * Hence the log size needs to be able to contain two maximally sized 135 * and padded transactions, which is (2 * (2 * LSU + maxlres)). 136 * 137 * Also, the log size should be a multiple of the log stripe unit, round 138 * it up to lsunit boundary if lsunit is specified. 139 */ 140 if (lsunit) { 141 min_logblks = roundup_64(BTOBB(max_logres), lsunit) + 142 2 * lsunit; 143 } else 144 min_logblks = BTOBB(max_logres) + 2 * BBSIZE; 145 min_logblks *= XFS_MIN_LOG_FACTOR; 146 147 return XFS_BB_TO_FSB(mp, min_logblks); 148} 149