⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xfs_log.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
xfs_log_reserve(xfs_mount_t	 *mp,		int		 unit_bytes,		int		 cnt,		xfs_log_ticket_t *ticket,		__uint8_t	 client,		uint		 flags,		uint		 t_type){	xlog_t		*log = mp->m_log;	xlog_ticket_t	*internal_ticket;	int		retval = 0;	ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);	ASSERT((flags & XFS_LOG_NOSLEEP) == 0);	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 = (xlog_ticket_t *)*ticket;		xlog_trace_loggrant(log, internal_ticket, "xfs_log_reserve: existing ticket (permanent trans)");		xlog_grant_push_ail(mp, 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_get(log, unit_bytes, cnt,						  client, flags);		internal_ticket->t_trans_type = t_type;		*ticket = internal_ticket;		xlog_trace_loggrant(log, internal_ticket, 			(internal_ticket->t_flags & XLOG_TIC_PERM_RESERV) ?			"xfs_log_reserve: create new ticket (permanent trans)" :			"xfs_log_reserve: create new ticket");		xlog_grant_push_ail(mp,				    (internal_ticket->t_unit_res *				     internal_ticket->t_cnt));		retval = xlog_grant_log_space(log, internal_ticket);	}	return retval;}	/* xfs_log_reserve *//* * Mount a log filesystem * * mp		- ubiquitous xfs mount point structure * log_target	- buftarg of on-disk log device * blk_offset	- Start block # where block size is 512 bytes (BBSIZE) * num_bblocks	- Number of BBSIZE blocks in on-disk log * * Return error or zero. */intxfs_log_mount(xfs_mount_t	*mp,	      xfs_buftarg_t	*log_target,	      xfs_daddr_t	blk_offset,	      int		num_bblks){	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))		cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname);	else {		cmn_err(CE_NOTE,			"!Mounting filesystem \"%s\" in no-recovery mode.  Filesystem will be inconsistent.",			mp->m_fsname);		ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);	}	mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);	/*	 * skip log recovery on a norecovery mount.  pretend it all	 * just worked.	 */	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {		int		error, readonly = (mp->m_flags & XFS_MOUNT_RDONLY);		if (readonly)			mp->m_flags &= ~XFS_MOUNT_RDONLY;		error = xlog_recover(mp->m_log);		if (readonly)			mp->m_flags |= XFS_MOUNT_RDONLY;		if (error) {			cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);			xlog_dealloc_log(mp->m_log);			return error;		}	}	/* Normal transactions can now occur */	mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY;	/* End mounting message in xfs_log_mount_finish */	return 0;}	/* xfs_log_mount *//* * Finish the recovery of the file system.  This is separate from * the xfs_log_mount() call, because it depends on the code in * xfs_mountfs() to read in the root and real-time bitmap inodes * between calling xfs_log_mount() and here. * * mp		- ubiquitous xfs mount point structure */intxfs_log_mount_finish(xfs_mount_t *mp, int mfsi_flags){	int	error;	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))		error = xlog_recover_finish(mp->m_log, mfsi_flags);	else {		error = 0;		ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);	}	return error;}/* * Unmount processing for the log. */intxfs_log_unmount(xfs_mount_t *mp){	int		error;	error = xfs_log_unmount_write(mp);	xfs_log_unmount_dealloc(mp);	return error;}/* * Final log writes as part of unmount. * * Mark the filesystem clean as unmount happens.  Note that during relocation * this routine needs to be executed as part of source-bag while the * deallocation must not be done until source-end. *//* * Unmount record used to have a string "Unmount filesystem--" in the * data section where the "Un" was really a magic number (XLOG_UNMOUNT_TYPE). * We just write the magic number now since that particular field isn't * currently architecture converted and "nUmount" is a bit foo. * As far as I know, there weren't any dependencies on the old behaviour. */intxfs_log_unmount_write(xfs_mount_t *mp){	xlog_t		 *log = mp->m_log;	xlog_in_core_t	 *iclog;#ifdef DEBUG	xlog_in_core_t	 *first_iclog;#endif	xfs_log_iovec_t  reg[1];	xfs_log_ticket_t tic = NULL;	xfs_lsn_t	 lsn;	int		 error;	SPLDECL(s);	/* the data section must be 32 bit size aligned */	struct {	    __uint16_t magic;	    __uint16_t pad1;	    __uint32_t pad2; /* may as well make it 64 bits */	} magic = { XLOG_UNMOUNT_TYPE, 0, 0 };	/*	 * Don't write out unmount record on read-only mounts.	 * Or, if we are doing a forced umount (typically because of IO errors).	 */	if (mp->m_flags & XFS_MOUNT_RDONLY)		return 0;	xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);#ifdef DEBUG	first_iclog = iclog = log->l_iclog;	do {		if (!(iclog->ic_state & XLOG_STATE_IOERROR)) {			ASSERT(iclog->ic_state & XLOG_STATE_ACTIVE);			ASSERT(iclog->ic_offset == 0);		}		iclog = iclog->ic_next;	} while (iclog != first_iclog);#endif	if (! (XLOG_FORCED_SHUTDOWN(log))) {		reg[0].i_addr = (void*)&magic;		reg[0].i_len  = sizeof(magic);		XLOG_VEC_SET_TYPE(&reg[0], XLOG_REG_TYPE_UNMOUNT);		error = xfs_log_reserve(mp, 600, 1, &tic,					XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE);		if (!error) {			/* remove inited flag */			((xlog_ticket_t *)tic)->t_flags = 0;			error = xlog_write(mp, reg, 1, tic, &lsn,					   NULL, XLOG_UNMOUNT_TRANS);			/*			 * At this point, we're umounting anyway,			 * so there's no point in transitioning log state			 * to IOERROR. Just continue...			 */		}		if (error) {			xfs_fs_cmn_err(CE_ALERT, mp,				"xfs_log_unmount: unmount record failed");		}		s = LOG_LOCK(log);		iclog = log->l_iclog;		iclog->ic_refcnt++;		LOG_UNLOCK(log, s);		xlog_state_want_sync(log, iclog);		(void) xlog_state_release_iclog(log, iclog);		s = LOG_LOCK(log);		if (!(iclog->ic_state == XLOG_STATE_ACTIVE ||		      iclog->ic_state == XLOG_STATE_DIRTY)) {			if (!XLOG_FORCED_SHUTDOWN(log)) {				sv_wait(&iclog->ic_forcesema, PMEM,					&log->l_icloglock, s);			} else {				LOG_UNLOCK(log, s);			}		} else {			LOG_UNLOCK(log, s);		}		if (tic) {			xlog_trace_loggrant(log, tic, "unmount rec");			xlog_ungrant_log_space(log, tic);			xlog_state_put_ticket(log, tic);		}	} else {		/*		 * We're already in forced_shutdown mode, couldn't		 * even attempt to write out the unmount transaction.		 *		 * Go through the motions of sync'ing and releasing		 * the iclog, even though no I/O will actually happen,		 * we need to wait for other log I/Os that may already		 * be in progress.  Do this as a separate section of		 * code so we'll know if we ever get stuck here that		 * we're in this odd situation of trying to unmount		 * a file system that went into forced_shutdown as		 * the result of an unmount..		 */		s = LOG_LOCK(log);		iclog = log->l_iclog;		iclog->ic_refcnt++;		LOG_UNLOCK(log, s);		xlog_state_want_sync(log, iclog);		(void) xlog_state_release_iclog(log, iclog);		s = LOG_LOCK(log);		if ( ! (   iclog->ic_state == XLOG_STATE_ACTIVE			|| iclog->ic_state == XLOG_STATE_DIRTY			|| iclog->ic_state == XLOG_STATE_IOERROR) ) {				sv_wait(&iclog->ic_forcesema, PMEM,					&log->l_icloglock, s);		} else {			LOG_UNLOCK(log, s);		}	}	return 0;}	/* xfs_log_unmount_write *//* * Deallocate log structures for unmount/relocation. */voidxfs_log_unmount_dealloc(xfs_mount_t *mp){	xlog_dealloc_log(mp->m_log);}/* * Write region vectors to log.  The write happens using the space reservation * of the ticket (tic).  It is not a requirement that all writes for a given * transaction occur with one call to xfs_log_write(). */intxfs_log_write(xfs_mount_t *	mp,	      xfs_log_iovec_t	reg[],	      int		nentries,	      xfs_log_ticket_t	tic,	      xfs_lsn_t		*start_lsn){	int	error;	xlog_t *log = mp->m_log;	if (XLOG_FORCED_SHUTDOWN(log))		return XFS_ERROR(EIO);	if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) {		xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);	}	return error;}	/* xfs_log_write */voidxfs_log_move_tail(xfs_mount_t	*mp,		  xfs_lsn_t	tail_lsn){	xlog_ticket_t	*tic;	xlog_t		*log = mp->m_log;	int		need_bytes, free_bytes, cycle, bytes;	SPLDECL(s);	if (XLOG_FORCED_SHUTDOWN(log))		return;	ASSERT(!XFS_FORCED_SHUTDOWN(mp));	if (tail_lsn == 0) {		/* needed since sync_lsn is 64 bits */		s = LOG_LOCK(log);		tail_lsn = log->l_last_sync_lsn;		LOG_UNLOCK(log, s);	}	s = GRANT_LOCK(log);	/* Also an invalid lsn.  1 implies that we aren't passing in a valid	 * tail_lsn.	 */	if (tail_lsn != 1) {		log->l_tail_lsn = tail_lsn;	}	if ((tic = log->l_write_headq)) {#ifdef DEBUG		if (log->l_flags & XLOG_ACTIVE_RECOVERY)			panic("Recovery problem");#endif		cycle = log->l_grant_write_cycle;		bytes = log->l_grant_write_bytes;		free_bytes = xlog_space_left(log, cycle, bytes);		do {			ASSERT(tic->t_flags & XLOG_TIC_PERM_RESERV);			if (free_bytes < tic->t_unit_res && tail_lsn != 1)				break;			tail_lsn = 0;			free_bytes -= tic->t_unit_res;			sv_signal(&tic->t_sema);			tic = tic->t_next;		} while (tic != log->l_write_headq);	}	if ((tic = log->l_reserve_headq)) {#ifdef DEBUG		if (log->l_flags & XLOG_ACTIVE_RECOVERY)			panic("Recovery problem");#endif		cycle = log->l_grant_reserve_cycle;		bytes = log->l_grant_reserve_bytes;		free_bytes = xlog_space_left(log, cycle, bytes);		do {			if (tic->t_flags & XLOG_TIC_PERM_RESERV)				need_bytes = tic->t_unit_res*tic->t_cnt;			else				need_bytes = tic->t_unit_res;			if (free_bytes < need_bytes && tail_lsn != 1)				break;			tail_lsn = 0;			free_bytes -= need_bytes;			sv_signal(&tic->t_sema);			tic = tic->t_next;		} while (tic != log->l_reserve_headq);	}	GRANT_UNLOCK(log, s);}	/* xfs_log_move_tail *//* * Determine if we have a transaction that has gone to disk * that needs to be covered. Log activity needs to be idle (no AIL and * nothing in the iclogs). And, we need to be in the right state indicating * something has gone out. */intxfs_log_need_covered(xfs_mount_t *mp){	SPLDECL(s);	int		needed = 0, gen;	xlog_t		*log = mp->m_log;	if (!xfs_fs_writable(mp))		return 0;	s = LOG_LOCK(log);	if (((log->l_covered_state == XLOG_STATE_COVER_NEED) ||		(log->l_covered_state == XLOG_STATE_COVER_NEED2))			&& !xfs_trans_first_ail(mp, &gen)			&& xlog_iclogs_empty(log)) {		if (log->l_covered_state == XLOG_STATE_COVER_NEED)			log->l_covered_state = XLOG_STATE_COVER_DONE;		else {			ASSERT(log->l_covered_state == XLOG_STATE_COVER_NEED2);			log->l_covered_state = XLOG_STATE_COVER_DONE2;		}		needed = 1;	}	LOG_UNLOCK(log, s);	return needed;}/****************************************************************************** * *	local routines * ****************************************************************************** *//* xfs_trans_tail_ail returns 0 when there is nothing in the list. * The log manager must keep track of the last LR which was committed * to disk.  The lsn of this LR will become the new tail_lsn whenever * xfs_trans_tail_ail returns 0.  If we don't do this, we run into * the situation where stuff could be written into the log but nothing * was ever in the AIL when asked.  Eventually, we panic since the * tail hits the head. * * We may be holding the log iclog lock upon entering this routine. */xfs_lsn_txlog_assign_tail_lsn(xfs_mount_t *mp){	xfs_lsn_t tail_lsn;	SPLDECL(s);	xlog_t	  *log = mp->m_log;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -