mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	xfs: split and cleanup xfs_log_reserve
Split the log regrant case out of xfs_log_reserve into a separate function, and merge xlog_grant_log_space and xlog_regrant_write_log_space into their respective callers. Also replace the XFS_LOG_PERM_RESERV flag, which easily got misused before the previous cleanups with a simple boolean parameter. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
		
							parent
							
								
									42ceedb3ca
								
							
						
					
					
						commit
						9006fb91cf
					
				
					 5 changed files with 151 additions and 170 deletions
				
			
		
							
								
								
									
										265
									
								
								fs/xfs/xfs_log.c
									
										
									
									
									
								
							
							
						
						
									
										265
									
								
								fs/xfs/xfs_log.c
									
										
									
									
									
								
							|  | @ -67,15 +67,10 @@ STATIC void xlog_state_switch_iclogs(xlog_t		*log, | |||
| 				     int		eventual_size); | ||||
| STATIC void xlog_state_want_sync(xlog_t	*log, xlog_in_core_t *iclog); | ||||
| 
 | ||||
| /* local functions to manipulate grant head */ | ||||
| STATIC int  xlog_grant_log_space(xlog_t		*log, | ||||
| 				 xlog_ticket_t	*xtic); | ||||
| STATIC void xlog_grant_push_ail(struct log	*log, | ||||
| 				int		need_bytes); | ||||
| STATIC void xlog_regrant_reserve_log_space(xlog_t	 *log, | ||||
| 					   xlog_ticket_t *ticket); | ||||
| STATIC int xlog_regrant_write_log_space(xlog_t		*log, | ||||
| 					 xlog_ticket_t  *ticket); | ||||
| STATIC void xlog_ungrant_log_space(xlog_t	 *log, | ||||
| 				   xlog_ticket_t *ticket); | ||||
| 
 | ||||
|  | @ -323,6 +318,128 @@ xlog_tic_add_region(xlog_ticket_t *tic, uint len, uint type) | |||
| 	tic->t_res_num++; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Replenish the byte reservation required by moving the grant write head. | ||||
|  */ | ||||
| int | ||||
| xfs_log_regrant( | ||||
| 	struct xfs_mount	*mp, | ||||
| 	struct xlog_ticket	*tic) | ||||
| { | ||||
| 	struct log		*log = mp->m_log; | ||||
| 	int			need_bytes; | ||||
| 	int			error = 0; | ||||
| 
 | ||||
| 	if (XLOG_FORCED_SHUTDOWN(log)) | ||||
| 		return XFS_ERROR(EIO); | ||||
| 
 | ||||
| 	XFS_STATS_INC(xs_try_logspace); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * This is a new transaction on the ticket, so we need to change the | ||||
| 	 * transaction ID so that the next transaction has a different TID in | ||||
| 	 * the log. Just add one to the existing tid so that we can see chains | ||||
| 	 * of rolling transactions in the log easily. | ||||
| 	 */ | ||||
| 	tic->t_tid++; | ||||
| 
 | ||||
| 	xlog_grant_push_ail(log, tic->t_unit_res); | ||||
| 
 | ||||
| 	tic->t_curr_res = tic->t_unit_res; | ||||
| 	xlog_tic_reset_res(tic); | ||||
| 
 | ||||
| 	if (tic->t_cnt > 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	trace_xfs_log_regrant(log, tic); | ||||
| 
 | ||||
| 	error = xlog_grant_head_check(log, &log->l_write_head, tic, | ||||
| 				      &need_bytes); | ||||
| 	if (error) | ||||
| 		goto out_error; | ||||
| 
 | ||||
| 	xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes); | ||||
| 	trace_xfs_log_regrant_exit(log, tic); | ||||
| 	xlog_verify_grant_tail(log); | ||||
| 	return 0; | ||||
| 
 | ||||
| out_error: | ||||
| 	/*
 | ||||
| 	 * If we are failing, make sure the ticket doesn't have any current | ||||
| 	 * reservations.  We don't want to add this back when the ticket/ | ||||
| 	 * transaction gets cancelled. | ||||
| 	 */ | ||||
| 	tic->t_curr_res = 0; | ||||
| 	tic->t_cnt = 0;	/* ungrant will give back unit_res * t_cnt. */ | ||||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Reserve log space and return a ticket corresponding the reservation. | ||||
|  * | ||||
|  * Each reservation is going to reserve extra space for a log record header. | ||||
|  * When writes happen to the on-disk log, we don't subtract the length of the | ||||
|  * log record header from any reservation.  By wasting space in each | ||||
|  * reservation, we prevent over allocation problems. | ||||
|  */ | ||||
| int | ||||
| xfs_log_reserve( | ||||
| 	struct xfs_mount	*mp, | ||||
| 	int		 	unit_bytes, | ||||
| 	int		 	cnt, | ||||
| 	struct xlog_ticket	**ticp, | ||||
| 	__uint8_t	 	client, | ||||
| 	bool			permanent, | ||||
| 	uint		 	t_type) | ||||
| { | ||||
| 	struct log		*log = mp->m_log; | ||||
| 	struct xlog_ticket	*tic; | ||||
| 	int			need_bytes; | ||||
| 	int			error = 0; | ||||
| 
 | ||||
| 	ASSERT(client == XFS_TRANSACTION || client == XFS_LOG); | ||||
| 
 | ||||
| 	if (XLOG_FORCED_SHUTDOWN(log)) | ||||
| 		return XFS_ERROR(EIO); | ||||
| 
 | ||||
| 	XFS_STATS_INC(xs_try_logspace); | ||||
| 
 | ||||
| 	ASSERT(*ticp == NULL); | ||||
| 	tic = xlog_ticket_alloc(log, unit_bytes, cnt, client, permanent, | ||||
| 				KM_SLEEP | KM_MAYFAIL); | ||||
| 	if (!tic) | ||||
| 		return XFS_ERROR(ENOMEM); | ||||
| 
 | ||||
| 	tic->t_trans_type = t_type; | ||||
| 	*ticp = tic; | ||||
| 
 | ||||
| 	xlog_grant_push_ail(log, tic->t_unit_res * tic->t_cnt); | ||||
| 
 | ||||
| 	trace_xfs_log_reserve(log, tic); | ||||
| 
 | ||||
| 	error = xlog_grant_head_check(log, &log->l_reserve_head, tic, | ||||
| 				      &need_bytes); | ||||
| 	if (error) | ||||
| 		goto out_error; | ||||
| 
 | ||||
| 	xlog_grant_add_space(log, &log->l_reserve_head.grant, need_bytes); | ||||
| 	xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes); | ||||
| 	trace_xfs_log_reserve_exit(log, tic); | ||||
| 	xlog_verify_grant_tail(log); | ||||
| 	return 0; | ||||
| 
 | ||||
| out_error: | ||||
| 	/*
 | ||||
| 	 * If we are failing, make sure the ticket doesn't have any current | ||||
| 	 * reservations.  We don't want to add this back when the ticket/ | ||||
| 	 * transaction gets cancelled. | ||||
| 	 */ | ||||
| 	tic->t_curr_res = 0; | ||||
| 	tic->t_cnt = 0;	/* ungrant will give back unit_res * t_cnt. */ | ||||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * NOTES: | ||||
|  * | ||||
|  | @ -432,88 +549,6 @@ xfs_log_release_iclog( | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  1. Reserve an amount of on-disk log space and return a ticket corresponding | ||||
|  *	to the reservation. | ||||
|  *  2. Potentially, push buffers at tail of log to disk. | ||||
|  * | ||||
|  * Each reservation is going to reserve extra space for a log record header. | ||||
|  * When writes happen to the on-disk log, we don't subtract the length of the | ||||
|  * log record header from any reservation.  By wasting space in each | ||||
|  * reservation, we prevent over allocation problems. | ||||
|  */ | ||||
| int | ||||
| xfs_log_reserve( | ||||
| 	struct xfs_mount	*mp, | ||||
| 	int		 	unit_bytes, | ||||
| 	int		 	cnt, | ||||
| 	struct xlog_ticket	**ticket, | ||||
| 	__uint8_t	 	client, | ||||
| 	uint		 	flags, | ||||
| 	uint		 	t_type) | ||||
| { | ||||
| 	struct log		*log = mp->m_log; | ||||
| 	struct xlog_ticket	*internal_ticket; | ||||
| 	int			retval = 0; | ||||
| 
 | ||||
| 	ASSERT(client == XFS_TRANSACTION || client == XFS_LOG); | ||||
| 
 | ||||
| 	if (XLOG_FORCED_SHUTDOWN(log)) | ||||
| 		return XFS_ERROR(EIO); | ||||
| 
 | ||||
| 	XFS_STATS_INC(xs_try_logspace); | ||||
| 
 | ||||
| 
 | ||||
| 	if (*ticket != NULL) { | ||||
| 		ASSERT(flags & XFS_LOG_PERM_RESERV); | ||||
| 		internal_ticket = *ticket; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * this is a new transaction on the ticket, so we need to | ||||
| 		 * change the transaction ID so that the next transaction has a | ||||
| 		 * different TID in the log. Just add one to the existing tid | ||||
| 		 * so that we can see chains of rolling transactions in the log | ||||
| 		 * easily. | ||||
| 		 */ | ||||
| 		internal_ticket->t_tid++; | ||||
| 
 | ||||
| 		trace_xfs_log_reserve(log, internal_ticket); | ||||
| 
 | ||||
| 		xlog_grant_push_ail(log, internal_ticket->t_unit_res); | ||||
| 		retval = xlog_regrant_write_log_space(log, internal_ticket); | ||||
| 	} else { | ||||
| 		/* may sleep if need to allocate more tickets */ | ||||
| 		internal_ticket = xlog_ticket_alloc(log, unit_bytes, cnt, | ||||
| 						  client, flags, | ||||
| 						  KM_SLEEP|KM_MAYFAIL); | ||||
| 		if (!internal_ticket) | ||||
| 			return XFS_ERROR(ENOMEM); | ||||
| 		internal_ticket->t_trans_type = t_type; | ||||
| 		*ticket = internal_ticket; | ||||
| 
 | ||||
| 		trace_xfs_log_reserve(log, internal_ticket); | ||||
| 
 | ||||
| 		xlog_grant_push_ail(log, | ||||
| 				    (internal_ticket->t_unit_res * | ||||
| 				     internal_ticket->t_cnt)); | ||||
| 		retval = xlog_grant_log_space(log, internal_ticket); | ||||
| 	} | ||||
| 
 | ||||
| 	if (unlikely(retval)) { | ||||
| 		/*
 | ||||
| 		 * If we are failing, make sure the ticket doesn't have any | ||||
| 		 * current reservations.  We don't want to add this back | ||||
| 		 * when the ticket/ transaction gets cancelled. | ||||
| 		 */ | ||||
| 		internal_ticket->t_curr_res = 0; | ||||
| 		/* ungrant will give back unit_res * t_cnt. */ | ||||
| 		internal_ticket->t_cnt = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return retval; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Mount a log filesystem | ||||
|  * | ||||
|  | @ -2565,58 +2600,6 @@ restart: | |||
| 	return 0; | ||||
| }	/* xlog_state_get_iclog_space */ | ||||
| 
 | ||||
| STATIC int | ||||
| xlog_grant_log_space( | ||||
| 	struct log		*log, | ||||
| 	struct xlog_ticket	*tic) | ||||
| { | ||||
| 	int			need_bytes; | ||||
| 	int			error = 0; | ||||
| 
 | ||||
| 	trace_xfs_log_grant_enter(log, tic); | ||||
| 
 | ||||
| 	error = xlog_grant_head_check(log, &log->l_reserve_head, tic, | ||||
| 				      &need_bytes); | ||||
| 	if (error) | ||||
| 		return error; | ||||
| 
 | ||||
| 	xlog_grant_add_space(log, &log->l_reserve_head.grant, need_bytes); | ||||
| 	xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes); | ||||
| 	trace_xfs_log_grant_exit(log, tic); | ||||
| 	xlog_verify_grant_tail(log); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Replenish the byte reservation required by moving the grant write head. | ||||
|  */ | ||||
| STATIC int | ||||
| xlog_regrant_write_log_space( | ||||
| 	struct log		*log, | ||||
| 	struct xlog_ticket	*tic) | ||||
| { | ||||
| 	int			need_bytes; | ||||
| 	int			error = 0; | ||||
| 
 | ||||
| 	tic->t_curr_res = tic->t_unit_res; | ||||
| 	xlog_tic_reset_res(tic); | ||||
| 
 | ||||
| 	if (tic->t_cnt > 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	trace_xfs_log_regrant_write_enter(log, tic); | ||||
| 
 | ||||
| 	error = xlog_grant_head_check(log, &log->l_write_head, tic, | ||||
| 				      &need_bytes); | ||||
| 	if (error) | ||||
| 		return error; | ||||
| 
 | ||||
| 	xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes); | ||||
| 	trace_xfs_log_regrant_write_exit(log, tic); | ||||
| 	xlog_verify_grant_tail(log); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* The first cnt-1 times through here we don't need to
 | ||||
|  * move the grant write head because the permanent | ||||
|  * reservation has reserved cnt times the unit amount. | ||||
|  | @ -3156,7 +3139,7 @@ xlog_ticket_alloc( | |||
| 	int		unit_bytes, | ||||
| 	int		cnt, | ||||
| 	char		client, | ||||
| 	uint		xflags, | ||||
| 	bool		permanent, | ||||
| 	int		alloc_flags) | ||||
| { | ||||
| 	struct xlog_ticket *tic; | ||||
|  | @ -3260,7 +3243,7 @@ xlog_ticket_alloc( | |||
| 	tic->t_clientid		= client; | ||||
| 	tic->t_flags		= XLOG_TIC_INITED; | ||||
| 	tic->t_trans_type	= 0; | ||||
| 	if (xflags & XFS_LOG_PERM_RESERV) | ||||
| 	if (permanent) | ||||
| 		tic->t_flags |= XLOG_TIC_PERM_RESERV; | ||||
| 
 | ||||
| 	xlog_tic_reset_res(tic); | ||||
|  |  | |||
|  | @ -52,15 +52,6 @@ static inline xfs_lsn_t	_lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2) | |||
|  */ | ||||
| #define XFS_LOG_REL_PERM_RESERV	0x1 | ||||
| 
 | ||||
| /*
 | ||||
|  * Flags to xfs_log_reserve() | ||||
|  * | ||||
|  *	XFS_LOG_PERM_RESERV: Permanent reservation.  When writes are | ||||
|  *		performed against this type of reservation, the reservation | ||||
|  *		is not decreased.  Long running transactions should use this. | ||||
|  */ | ||||
| #define XFS_LOG_PERM_RESERV	0x2 | ||||
| 
 | ||||
| /*
 | ||||
|  * Flags to xfs_log_force() | ||||
|  * | ||||
|  | @ -172,8 +163,9 @@ int	  xfs_log_reserve(struct xfs_mount *mp, | |||
| 			  int		   count, | ||||
| 			  struct xlog_ticket **ticket, | ||||
| 			  __uint8_t	   clientid, | ||||
| 			  uint		   flags, | ||||
| 			  bool		   permanent, | ||||
| 			  uint		   t_type); | ||||
| int	  xfs_log_regrant(struct xfs_mount *mp, struct xlog_ticket *tic); | ||||
| int	  xfs_log_unmount_write(struct xfs_mount *mp); | ||||
| void      xfs_log_unmount(struct xfs_mount *mp); | ||||
| int	  xfs_log_force_umount(struct xfs_mount *mp, int logerror); | ||||
|  |  | |||
|  | @ -552,7 +552,7 @@ extern void	 xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int); | |||
| 
 | ||||
| extern kmem_zone_t *xfs_log_ticket_zone; | ||||
| struct xlog_ticket *xlog_ticket_alloc(struct log *log, int unit_bytes, | ||||
| 				int count, char client, uint xflags, | ||||
| 				int count, char client, bool permanent, | ||||
| 				int alloc_flags); | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -826,17 +826,14 @@ DEFINE_EVENT(xfs_loggrant_class, name, \ | |||
| 	TP_ARGS(log, tic)) | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_done_nonperm); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_done_perm); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_reserve); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_umount_write); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_grant_enter); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_grant_exit); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_grant_error); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake_up); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_enter); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_exit); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_error); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_reserve); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_reserve_exit); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_regrant); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_regrant_exit); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_enter); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_exit); | ||||
| DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_sub); | ||||
|  |  | |||
|  | @ -681,7 +681,6 @@ xfs_trans_reserve( | |||
| 	uint		flags, | ||||
| 	uint		logcount) | ||||
| { | ||||
| 	int		log_flags; | ||||
| 	int		error = 0; | ||||
| 	int		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; | ||||
| 
 | ||||
|  | @ -707,24 +706,32 @@ xfs_trans_reserve( | |||
| 	 * Reserve the log space needed for this transaction. | ||||
| 	 */ | ||||
| 	if (logspace > 0) { | ||||
| 		ASSERT((tp->t_log_res == 0) || (tp->t_log_res == logspace)); | ||||
| 		ASSERT((tp->t_log_count == 0) || | ||||
| 			(tp->t_log_count == logcount)); | ||||
| 		bool	permanent = false; | ||||
| 
 | ||||
| 		ASSERT(tp->t_log_res == 0 || tp->t_log_res == logspace); | ||||
| 		ASSERT(tp->t_log_count == 0 || tp->t_log_count == logcount); | ||||
| 
 | ||||
| 		if (flags & XFS_TRANS_PERM_LOG_RES) { | ||||
| 			log_flags = XFS_LOG_PERM_RESERV; | ||||
| 			tp->t_flags |= XFS_TRANS_PERM_LOG_RES; | ||||
| 			permanent = true; | ||||
| 		} else { | ||||
| 			ASSERT(tp->t_ticket == NULL); | ||||
| 			ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES)); | ||||
| 			log_flags = 0; | ||||
| 		} | ||||
| 
 | ||||
| 		error = xfs_log_reserve(tp->t_mountp, logspace, logcount, | ||||
| 					&tp->t_ticket, | ||||
| 					XFS_TRANSACTION, log_flags, tp->t_type); | ||||
| 		if (error) { | ||||
| 			goto undo_blocks; | ||||
| 		if (tp->t_ticket != NULL) { | ||||
| 			ASSERT(flags & XFS_TRANS_PERM_LOG_RES); | ||||
| 			error = xfs_log_regrant(tp->t_mountp, tp->t_ticket); | ||||
| 		} else { | ||||
| 			error = xfs_log_reserve(tp->t_mountp, logspace, | ||||
| 						logcount, &tp->t_ticket, | ||||
| 						XFS_TRANSACTION, permanent, | ||||
| 						tp->t_type); | ||||
| 		} | ||||
| 
 | ||||
| 		if (error) | ||||
| 			goto undo_blocks; | ||||
| 
 | ||||
| 		tp->t_log_res = logspace; | ||||
| 		tp->t_log_count = logcount; | ||||
| 	} | ||||
|  | @ -752,6 +759,8 @@ xfs_trans_reserve( | |||
| 	 */ | ||||
| undo_log: | ||||
| 	if (logspace > 0) { | ||||
| 		int		log_flags; | ||||
| 
 | ||||
| 		if (flags & XFS_TRANS_PERM_LOG_RES) { | ||||
| 			log_flags = XFS_LOG_REL_PERM_RESERV; | ||||
| 		} else { | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Christoph Hellwig
						Christoph Hellwig