diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
| -rw-r--r-- | fs/xfs/xfs_mount.c | 109 | 
1 files changed, 73 insertions, 36 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index df370eb5dc15..09eef1721ef4 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -34,6 +34,7 @@  #include "xfs_health.h"  #include "xfs_trace.h"  #include "xfs_ag.h" +#include "xfs_rtbitmap.h"  #include "scrub/stats.h"  static DEFINE_MUTEX(xfs_uuid_table_mutex); @@ -230,6 +231,13 @@ reread:  	mp->m_features |= xfs_sb_version_to_features(sbp);  	xfs_reinit_percpu_counters(mp); +	/* +	 * If logged xattrs are enabled after log recovery finishes, then set +	 * the opstate so that log recovery will work properly. +	 */ +	if (xfs_sb_version_haslogxattrs(&mp->m_sb)) +		xfs_set_using_logged_xattrs(mp); +  	/* no need to be quiet anymore, so reset the buf ops */  	bp->b_ops = &xfs_sb_buf_ops; @@ -828,6 +836,15 @@ xfs_mountfs(  		goto out_inodegc_shrinker;  	} +	/* +	 * If logged xattrs are still enabled after log recovery finishes, then +	 * they'll be available until unmount.  Otherwise, turn them off. +	 */ +	if (xfs_sb_version_haslogxattrs(&mp->m_sb)) +		xfs_set_using_logged_xattrs(mp); +	else +		xfs_clear_using_logged_xattrs(mp); +  	/* Enable background inode inactivation workers. */  	xfs_inodegc_start(mp);  	xfs_blockgc_start(mp); @@ -1095,6 +1112,11 @@ xfs_unmountfs(  				"Freespace may not be correct on next mount.");  	xfs_unmount_check(mp); +	/* +	 * Indicate that it's ok to clear log incompat bits before cleaning +	 * the log and writing the unmount record. +	 */ +	xfs_set_done_with_log_incompat(mp);  	xfs_log_unmount(mp);  	xfs_da_unmount(mp);  	xfs_uuid_unmount(mp); @@ -1131,16 +1153,44 @@ xfs_fs_writable(  	return true;  } -/* Adjust m_fdblocks or m_frextents. */ +void +xfs_add_freecounter( +	struct xfs_mount	*mp, +	struct percpu_counter	*counter, +	uint64_t		delta) +{ +	bool			has_resv_pool = (counter == &mp->m_fdblocks); +	uint64_t		res_used; + +	/* +	 * If the reserve pool is depleted, put blocks back into it first. +	 * Most of the time the pool is full. +	 */ +	if (!has_resv_pool || mp->m_resblks == mp->m_resblks_avail) { +		percpu_counter_add(counter, delta); +		return; +	} + +	spin_lock(&mp->m_sb_lock); +	res_used = mp->m_resblks - mp->m_resblks_avail; +	if (res_used > delta) { +		mp->m_resblks_avail += delta; +	} else { +		delta -= res_used; +		mp->m_resblks_avail = mp->m_resblks; +		percpu_counter_add(counter, delta); +	} +	spin_unlock(&mp->m_sb_lock); +} +  int -xfs_mod_freecounter( +xfs_dec_freecounter(  	struct xfs_mount	*mp,  	struct percpu_counter	*counter, -	int64_t			delta, +	uint64_t		delta,  	bool			rsvd)  {  	int64_t			lcounter; -	long long		res_used;  	uint64_t		set_aside = 0;  	s32			batch;  	bool			has_resv_pool; @@ -1150,31 +1200,6 @@ xfs_mod_freecounter(  	if (rsvd)  		ASSERT(has_resv_pool); -	if (delta > 0) { -		/* -		 * If the reserve pool is depleted, put blocks back into it -		 * first. Most of the time the pool is full. -		 */ -		if (likely(!has_resv_pool || -			   mp->m_resblks == mp->m_resblks_avail)) { -			percpu_counter_add(counter, delta); -			return 0; -		} - -		spin_lock(&mp->m_sb_lock); -		res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); - -		if (res_used > delta) { -			mp->m_resblks_avail += delta; -		} else { -			delta -= res_used; -			mp->m_resblks_avail = mp->m_resblks; -			percpu_counter_add(counter, delta); -		} -		spin_unlock(&mp->m_sb_lock); -		return 0; -	} -  	/*  	 * Taking blocks away, need to be more accurate the closer we  	 * are to zero. @@ -1202,7 +1227,7 @@ xfs_mod_freecounter(  	 */  	if (has_resv_pool)  		set_aside = xfs_fdblocks_unavailable(mp); -	percpu_counter_add_batch(counter, delta, batch); +	percpu_counter_add_batch(counter, -((int64_t)delta), batch);  	if (__percpu_counter_compare(counter, set_aside,  				     XFS_FDBLOCKS_BATCH) >= 0) {  		/* we had space! */ @@ -1214,11 +1239,11 @@ xfs_mod_freecounter(  	 * that took us to ENOSPC.  	 */  	spin_lock(&mp->m_sb_lock); -	percpu_counter_add(counter, -delta); +	percpu_counter_add(counter, delta);  	if (!has_resv_pool || !rsvd)  		goto fdblocks_enospc; -	lcounter = (long long)mp->m_resblks_avail + delta; +	lcounter = (long long)mp->m_resblks_avail - delta;  	if (lcounter >= 0) {  		mp->m_resblks_avail = lcounter;  		spin_unlock(&mp->m_sb_lock); @@ -1364,7 +1389,8 @@ xfs_clear_incompat_log_features(  	if (!xfs_has_crc(mp) ||  	    !xfs_sb_has_incompat_log_feature(&mp->m_sb,  				XFS_SB_FEAT_INCOMPAT_LOG_ALL) || -	    xfs_is_shutdown(mp)) +	    xfs_is_shutdown(mp) || +	    !xfs_is_done_with_log_incompat(mp))  		return false;  	/* @@ -1399,9 +1425,20 @@ xfs_clear_incompat_log_features(  #define XFS_DELALLOC_BATCH	(4096)  void  xfs_mod_delalloc( -	struct xfs_mount	*mp, -	int64_t			delta) +	struct xfs_inode	*ip, +	int64_t			data_delta, +	int64_t			ind_delta)  { -	percpu_counter_add_batch(&mp->m_delalloc_blks, delta, +	struct xfs_mount	*mp = ip->i_mount; + +	if (XFS_IS_REALTIME_INODE(ip)) { +		percpu_counter_add_batch(&mp->m_delalloc_rtextents, +				xfs_rtb_to_rtx(mp, data_delta), +				XFS_DELALLOC_BATCH); +		if (!ind_delta) +			return; +		data_delta = 0; +	} +	percpu_counter_add_batch(&mp->m_delalloc_blks, data_delta + ind_delta,  			XFS_DELALLOC_BATCH);  }  |