2018-06-05 19:42:14 -07:00
// SPDX-License-Identifier: GPL-2.0
2013-08-12 20:50:02 +10:00
/*
* Copyright ( c ) 2013 Jie Liu .
* All Rights Reserved .
*/
# include "xfs.h"
# include "xfs_fs.h"
2013-10-23 10:36:05 +11:00
# include "xfs_shared.h"
2013-10-23 10:51:50 +11:00
# include "xfs_format.h"
2013-10-23 10:50:10 +11:00
# include "xfs_log_format.h"
# include "xfs_trans_resv.h"
2013-08-12 20:50:02 +10:00
# include "xfs_mount.h"
2013-10-15 09:17:51 +11:00
# include "xfs_da_format.h"
2013-08-12 20:50:02 +10:00
# include "xfs_trans_space.h"
# include "xfs_da_btree.h"
2013-10-23 10:51:50 +11:00
# include "xfs_bmap_btree.h"
2022-04-25 18:38:13 -07:00
# include "xfs_trace.h"
2013-08-12 20:50:02 +10:00
/*
* Calculate the maximum length in bytes that would be required for a local
* attribute value as large attributes out of line are not logged .
*/
STATIC int
xfs_log_calc_max_attrsetm_res (
struct xfs_mount * mp )
{
int size ;
int nblks ;
2014-06-06 15:21:10 +10:00
size = xfs_attr_leaf_entsize_local_max ( mp - > m_attr_geo - > blksize ) -
2013-08-12 20:50:02 +10:00
MAXNAMELEN - 1 ;
nblks = XFS_DAENTER_SPACE_RES ( mp , XFS_ATTR_FORK ) ;
nblks + = XFS_B_TO_FSB ( mp , size ) ;
nblks + = XFS_NEXTENTADD_SPACE_RES ( mp , size , XFS_ATTR_FORK ) ;
return M_RES ( mp ) - > tr_attrsetm . tr_logres +
M_RES ( mp ) - > tr_attrsetrt . tr_logres * nblks ;
}
2022-04-25 18:38:14 -07:00
/*
* Compute an alternate set of log reservation sizes for use exclusively with
* minimum log size calculations .
*/
static void
xfs_log_calc_trans_resv_for_minlogblocks (
struct xfs_mount * mp ,
struct xfs_trans_resv * resv )
{
unsigned int rmap_maxlevels = mp - > m_rmap_maxlevels ;
/*
* In the early days of rmap + reflink , we always set the rmap maxlevels
* to 9 even if the AG was small enough that it would never grow to
* that height . Transaction reservation sizes influence the minimum
* log size calculation , which influences the size of the log that mkfs
* creates . Use the old value here to ensure that newly formatted
* small filesystems will mount on older kernels .
*/
if ( xfs_has_rmapbt ( mp ) & & xfs_has_reflink ( mp ) )
mp - > m_rmap_maxlevels = XFS_OLD_REFLINK_RMAP_MAXLEVELS ;
xfs_trans_resv_calc ( mp , resv ) ;
if ( xfs_has_reflink ( mp ) ) {
/*
* In the early days of reflink , typical log operation counts
* were greatly overestimated .
*/
resv - > tr_write . tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK ;
resv - > tr_itruncate . tr_logcount =
XFS_ITRUNCATE_LOG_COUNT_REFLINK ;
resv - > tr_qm_dqalloc . tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK ;
} else if ( xfs_has_rmapbt ( mp ) ) {
/*
* In the early days of non - reflink rmap , the impact of rmapbt
* updates on log counts were not taken into account at all .
*/
resv - > tr_write . tr_logcount = XFS_WRITE_LOG_COUNT ;
resv - > tr_itruncate . tr_logcount = XFS_ITRUNCATE_LOG_COUNT ;
resv - > tr_qm_dqalloc . tr_logcount = XFS_WRITE_LOG_COUNT ;
}
2022-04-25 18:38:14 -07:00
/*
* In the early days of reflink , we did not use deferred refcount
* update log items , so log reservations must be recomputed using the
* old calculations .
*/
resv - > tr_write . tr_logres =
xfs_calc_write_reservation_minlogsize ( mp ) ;
resv - > tr_itruncate . tr_logres =
xfs_calc_itruncate_reservation_minlogsize ( mp ) ;
resv - > tr_qm_dqalloc . tr_logres =
xfs_calc_qm_dqalloc_reservation_minlogsize ( mp ) ;
2022-04-25 18:38:14 -07:00
/* Put everything back the way it was. This goes at the end. */
mp - > m_rmap_maxlevels = rmap_maxlevels ;
}
2013-08-12 20:50:02 +10:00
/*
* Iterate over the log space reservation table to figure out and return
* the maximum one in terms of the pre - calculated values which were done
* at mount time .
*/
2018-01-08 10:51:26 -08:00
void
2013-08-12 20:50:02 +10:00
xfs_log_get_max_trans_res (
struct xfs_mount * mp ,
struct xfs_trans_res * max_resp )
{
2022-04-25 18:38:14 -07:00
struct xfs_trans_resv resv = { } ;
2013-08-12 20:50:02 +10:00
struct xfs_trans_res * resp ;
struct xfs_trans_res * end_resp ;
2022-04-25 18:38:13 -07:00
unsigned int i ;
2013-08-12 20:50:02 +10:00
int log_space = 0 ;
int attr_space ;
attr_space = xfs_log_calc_max_attrsetm_res ( mp ) ;
2022-04-25 18:38:14 -07:00
xfs_log_calc_trans_resv_for_minlogblocks ( mp , & resv ) ;
2022-04-25 18:38:13 -07:00
resp = ( struct xfs_trans_res * ) & resv ;
end_resp = ( struct xfs_trans_res * ) ( & resv + 1 ) ;
for ( i = 0 ; resp < end_resp ; i + + , resp + + ) {
2013-08-12 20:50:02 +10:00
int tmp = resp - > tr_logcount > 1 ?
resp - > tr_logres * resp - > tr_logcount :
resp - > tr_logres ;
2022-04-25 18:38:13 -07:00
trace_xfs_trans_resv_calc_minlogsize ( mp , i , resp ) ;
2013-08-12 20:50:02 +10:00
if ( log_space < tmp ) {
log_space = tmp ;
* max_resp = * resp ; /* struct copy */
}
}
if ( attr_space > log_space ) {
2022-04-25 18:38:13 -07:00
* max_resp = resv . tr_attrsetm ; /* struct copy */
2013-08-12 20:50:02 +10:00
max_resp - > tr_logres = attr_space ;
}
2022-04-25 18:38:13 -07:00
trace_xfs_log_get_max_trans_res ( mp , max_resp ) ;
2013-08-12 20:50:02 +10:00
}
/*
* Calculate the minimum valid log size for the given superblock configuration .
* Used to calculate the minimum log size at mkfs time , and to determine if
* the log is large enough or not at mount time . Returns the minimum size in
* filesystem block size units .
*/
int
xfs_log_calc_minimum_size (
struct xfs_mount * mp )
{
struct xfs_trans_res tres = { 0 } ;
int max_logres ;
int min_logblks = 0 ;
int lsunit = 0 ;
xfs_log_get_max_trans_res ( mp , & tres ) ;
max_logres = xfs_log_calc_unit_res ( mp , tres . tr_logres ) ;
if ( tres . tr_logcount > 1 )
max_logres * = tres . tr_logcount ;
2021-08-18 18:46:37 -07:00
if ( xfs_has_logv2 ( mp ) & & mp - > m_sb . sb_logsunit > 1 )
2013-08-12 20:50:02 +10:00
lsunit = BTOBB ( mp - > m_sb . sb_logsunit ) ;
/*
* Two factors should be taken into account for calculating the minimum
* log space .
* 1 ) The fundamental limitation is that no single transaction can be
* larger than half size of the log .
*
* From mkfs . xfs , this is considered by the XFS_MIN_LOG_FACTOR
* define , which is set to 3. That means we can definitely fit
* maximally sized 2 transactions in the log . We ' ll use this same
* value here .
*
* 2 ) If the lsunit option is specified , a transaction requires 2 LSU
* for the reservation because there are two log writes that can
* require padding - the transaction data and the commit record which
* are written separately and both can require padding to the LSU .
* Consider that we can have an active CIL reservation holding 2 * LSU ,
* but the CIL is not over a push threshold , in this case , if we
* don ' t have enough log space for at one new transaction , which
* includes another 2 * LSU in the reservation , we will run into dead
* loop situation in log space grant procedure . i . e .
* xlog_grant_head_wait ( ) .
*
* Hence the log size needs to be able to contain two maximally sized
* and padded transactions , which is ( 2 * ( 2 * LSU + maxlres ) ) .
*
* Also , the log size should be a multiple of the log stripe unit , round
* it up to lsunit boundary if lsunit is specified .
*/
2013-08-13 13:32:00 +08:00
if ( lsunit ) {
min_logblks = roundup_64 ( BTOBB ( max_logres ) , lsunit ) +
2 * lsunit ;
} else
2013-08-12 20:50:02 +10:00
min_logblks = BTOBB ( max_logres ) + 2 * BBSIZE ;
min_logblks * = XFS_MIN_LOG_FACTOR ;
2013-08-13 13:32:00 +08:00
2013-08-12 20:50:02 +10:00
return XFS_BB_TO_FSB ( mp , min_logblks ) ;
}