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

📄 xfs_iomap.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */#include "xfs.h"#include "xfs_fs.h"#include "xfs_bit.h"#include "xfs_log.h"#include "xfs_inum.h"#include "xfs_trans.h"#include "xfs_sb.h"#include "xfs_ag.h"#include "xfs_dir2.h"#include "xfs_alloc.h"#include "xfs_dmapi.h"#include "xfs_quota.h"#include "xfs_mount.h"#include "xfs_bmap_btree.h"#include "xfs_alloc_btree.h"#include "xfs_ialloc_btree.h"#include "xfs_dir2_sf.h"#include "xfs_attr_sf.h"#include "xfs_dinode.h"#include "xfs_inode.h"#include "xfs_ialloc.h"#include "xfs_btree.h"#include "xfs_bmap.h"#include "xfs_rtalloc.h"#include "xfs_error.h"#include "xfs_itable.h"#include "xfs_rw.h"#include "xfs_acl.h"#include "xfs_attr.h"#include "xfs_buf_item.h"#include "xfs_trans_space.h"#include "xfs_utils.h"#include "xfs_iomap.h"#if defined(XFS_RW_TRACE)voidxfs_iomap_enter_trace(	int		tag,	xfs_iocore_t	*io,	xfs_off_t	offset,	ssize_t		count){	xfs_inode_t	*ip = XFS_IO_INODE(io);	if (!ip->i_rwtrace)		return;	ktrace_enter(ip->i_rwtrace,		(void *)((unsigned long)tag),		(void *)ip,		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),		(void *)((unsigned long)(offset & 0xffffffff)),		(void *)((unsigned long)count),		(void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)),		(void *)((unsigned long)(io->io_new_size & 0xffffffff)),		(void *)((unsigned long)current_pid()),		(void *)NULL,		(void *)NULL,		(void *)NULL,		(void *)NULL,		(void *)NULL,		(void *)NULL);}voidxfs_iomap_map_trace(	int		tag,	xfs_iocore_t	*io,	xfs_off_t	offset,	ssize_t		count,	xfs_iomap_t	*iomapp,	xfs_bmbt_irec_t	*imapp,	int		flags){	xfs_inode_t	*ip = XFS_IO_INODE(io);	if (!ip->i_rwtrace)		return;	ktrace_enter(ip->i_rwtrace,		(void *)((unsigned long)tag),		(void *)ip,		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),		(void *)((unsigned long)(offset & 0xffffffff)),		(void *)((unsigned long)count),		(void *)((unsigned long)flags),		(void *)((unsigned long)((iomapp->iomap_offset >> 32) & 0xffffffff)),		(void *)((unsigned long)(iomapp->iomap_offset & 0xffffffff)),		(void *)((unsigned long)(iomapp->iomap_delta)),		(void *)((unsigned long)(iomapp->iomap_bsize)),		(void *)((unsigned long)(iomapp->iomap_bn)),		(void *)(__psint_t)(imapp->br_startoff),		(void *)((unsigned long)(imapp->br_blockcount)),		(void *)(__psint_t)(imapp->br_startblock));}#else#define xfs_iomap_enter_trace(tag, io, offset, count)#define xfs_iomap_map_trace(tag, io, offset, count, iomapp, imapp, flags)#endif#define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \						<< mp->m_writeio_log)#define XFS_STRAT_WRITE_IMAPS	2#define XFS_WRITE_IMAPS		XFS_BMAP_MAX_NMAPSTATIC intxfs_imap_to_bmap(	xfs_iocore_t	*io,	xfs_off_t	offset,	xfs_bmbt_irec_t *imap,	xfs_iomap_t	*iomapp,	int		imaps,			/* Number of imap entries */	int		iomaps,			/* Number of iomap entries */	int		flags){	xfs_mount_t	*mp;	int		pbm;	xfs_fsblock_t	start_block;	mp = io->io_mount;	for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) {		iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff);		iomapp->iomap_delta = offset - iomapp->iomap_offset;		iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount);		iomapp->iomap_flags = flags;		if (io->io_flags & XFS_IOCORE_RT) {			iomapp->iomap_flags |= IOMAP_REALTIME;			iomapp->iomap_target = mp->m_rtdev_targp;		} else {			iomapp->iomap_target = mp->m_ddev_targp;		}		start_block = imap->br_startblock;		if (start_block == HOLESTARTBLOCK) {			iomapp->iomap_bn = IOMAP_DADDR_NULL;			iomapp->iomap_flags |= IOMAP_HOLE;		} else if (start_block == DELAYSTARTBLOCK) {			iomapp->iomap_bn = IOMAP_DADDR_NULL;			iomapp->iomap_flags |= IOMAP_DELAY;		} else {			iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block);			if (ISUNWRITTEN(imap))				iomapp->iomap_flags |= IOMAP_UNWRITTEN;		}		offset += iomapp->iomap_bsize - iomapp->iomap_delta;	}	return pbm;	/* Return the number filled */}intxfs_iomap(	xfs_iocore_t	*io,	xfs_off_t	offset,	ssize_t		count,	int		flags,	xfs_iomap_t	*iomapp,	int		*niomaps){	xfs_mount_t	*mp = io->io_mount;	xfs_fileoff_t	offset_fsb, end_fsb;	int		error = 0;	int		lockmode = 0;	xfs_bmbt_irec_t	imap;	int		nimaps = 1;	int		bmapi_flags = 0;	int		iomap_flags = 0;	if (XFS_FORCED_SHUTDOWN(mp))		return XFS_ERROR(EIO);	switch (flags &		(BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE |		 BMAPI_UNWRITTEN | BMAPI_DEVICE)) {	case BMAPI_READ:		xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count);		lockmode = XFS_LCK_MAP_SHARED(mp, io);		bmapi_flags = XFS_BMAPI_ENTIRE;		break;	case BMAPI_WRITE:		xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count);		lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;		if (flags & BMAPI_IGNSTATE)			bmapi_flags |= XFS_BMAPI_IGSTATE|XFS_BMAPI_ENTIRE;		XFS_ILOCK(mp, io, lockmode);		break;	case BMAPI_ALLOCATE:		xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, io, offset, count);		lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;		bmapi_flags = XFS_BMAPI_ENTIRE;		/* Attempt non-blocking lock */		if (flags & BMAPI_TRYLOCK) {			if (!XFS_ILOCK_NOWAIT(mp, io, lockmode))				return XFS_ERROR(EAGAIN);		} else {			XFS_ILOCK(mp, io, lockmode);		}		break;	case BMAPI_UNWRITTEN:		goto phase2;	case BMAPI_DEVICE:		lockmode = XFS_LCK_MAP_SHARED(mp, io);		iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?			mp->m_rtdev_targp : mp->m_ddev_targp;		error = 0;		*niomaps = 1;		goto out;	default:		BUG();	}	ASSERT(offset <= mp->m_maxioffset);	if ((xfs_fsize_t)offset + count > mp->m_maxioffset)		count = mp->m_maxioffset - offset;	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);	offset_fsb = XFS_B_TO_FSBT(mp, offset);	error = XFS_BMAPI(mp, NULL, io, offset_fsb,			(xfs_filblks_t)(end_fsb - offset_fsb),			bmapi_flags,  NULL, 0, &imap,			&nimaps, NULL, NULL);	if (error)		goto out;phase2:	switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {	case BMAPI_WRITE:		/* If we found an extent, return it */		if (nimaps &&		    (imap.br_startblock != HOLESTARTBLOCK) &&		    (imap.br_startblock != DELAYSTARTBLOCK)) {			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,					offset, count, iomapp, &imap, flags);			break;		}		if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) {			error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset,					count, flags, &imap, &nimaps, nimaps);		} else {			error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count,					flags, &imap, &nimaps);		}		if (!error) {			xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, io,					offset, count, iomapp, &imap, flags);		}		iomap_flags = IOMAP_NEW;		break;	case BMAPI_ALLOCATE:		/* If we found an extent, return it */		XFS_IUNLOCK(mp, io, lockmode);		lockmode = 0;		if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) {			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,					offset, count, iomapp, &imap, flags);			break;		}		error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count,						 &imap, &nimaps);		break;	case BMAPI_UNWRITTEN:		lockmode = 0;		error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count);		nimaps = 0;		break;	}	if (nimaps) {		*niomaps = xfs_imap_to_bmap(io, offset, &imap,					    iomapp, nimaps, *niomaps, iomap_flags);	} else if (niomaps) {		*niomaps = 0;	}out:	if (lockmode)		XFS_IUNLOCK(mp, io, lockmode);	return XFS_ERROR(error);}STATIC intxfs_iomap_eof_align_last_fsb(	xfs_mount_t	*mp,	xfs_iocore_t	*io,	xfs_fsize_t	isize,	xfs_extlen_t	extsize,	xfs_fileoff_t	*last_fsb){	xfs_fileoff_t	new_last_fsb = 0;	xfs_extlen_t	align;	int		eof, error;	if (io->io_flags & XFS_IOCORE_RT)		;	/*	 * If mounted with the "-o swalloc" option, roundup the allocation	 * request to a stripe width boundary if the file size is >=	 * stripe width and we are allocating past the allocation eof.	 */	else if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) &&	        (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)))		new_last_fsb = roundup_64(*last_fsb, mp->m_swidth);	/*	 * Roundup the allocation request to a stripe unit (m_dalign) boundary	 * if the file size is >= stripe unit size, and we are allocating past	 * the allocation eof.	 */	else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)))		new_last_fsb = roundup_64(*last_fsb, mp->m_dalign);	/*	 * Always round up the allocation request to an extent boundary	 * (when file on a real-time subvolume or has di_extsize hint).	 */	if (extsize) {		if (new_last_fsb)			align = roundup_64(new_last_fsb, extsize);		else			align = extsize;		new_last_fsb = roundup_64(*last_fsb, align);	}	if (new_last_fsb) {		error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof);		if (error)			return error;		if (eof)			*last_fsb = new_last_fsb;	}	return 0;}STATIC intxfs_flush_space(	xfs_inode_t	*ip,	int		*fsynced,	int		*ioflags){	switch (*fsynced) {	case 0:		if (ip->i_delayed_blks) {			xfs_iunlock(ip, XFS_ILOCK_EXCL);			xfs_flush_inode(ip);			xfs_ilock(ip, XFS_ILOCK_EXCL);			*fsynced = 1;		} else {			*ioflags |= BMAPI_SYNC;			*fsynced = 2;		}		return 0;	case 1:		*fsynced = 2;		*ioflags |= BMAPI_SYNC;		return 0;	case 2:		xfs_iunlock(ip, XFS_ILOCK_EXCL);		xfs_flush_device(ip);		xfs_ilock(ip, XFS_ILOCK_EXCL);		*fsynced = 3;		return 0;	}	return 1;}STATIC intxfs_cmn_err_fsblock_zero(	xfs_inode_t	*ip,	xfs_bmbt_irec_t	*imap){	xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,			"Access to block zero in inode %llu "			"start_block: %llx start_off: %llx "			"blkcnt: %llx extent-state: %x\n",		(unsigned long long)ip->i_ino,		(unsigned long long)imap->br_startblock,		(unsigned long long)imap->br_startoff,		(unsigned long long)imap->br_blockcount,		imap->br_state);	return EFSCORRUPTED;}intxfs_iomap_write_direct(	xfs_inode_t	*ip,	xfs_off_t	offset,	size_t		count,	int		flags,	xfs_bmbt_irec_t *ret_imap,	int		*nmaps,	int		found){	xfs_mount_t	*mp = ip->i_mount;	xfs_iocore_t	*io = &ip->i_iocore;	xfs_fileoff_t	offset_fsb;	xfs_fileoff_t	last_fsb;	xfs_filblks_t	count_fsb, resaligned;	xfs_fsblock_t	firstfsb;	xfs_extlen_t	extsz, temp;	xfs_fsize_t	isize;	int		nimaps;	int		bmapi_flag;	int		quota_flag;	int		rt;	xfs_trans_t	*tp;	xfs_bmbt_irec_t imap;	xfs_bmap_free_t free_list;	uint		qblocks, resblks, resrtextents;	int		committed;	int		error;	/*	 * Make sure that the dquots are there. This doesn't hold	 * the ilock across a disk read.	 */	error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED);	if (error)		return XFS_ERROR(error);	rt = XFS_IS_REALTIME_INODE(ip);	extsz = xfs_get_extsz_hint(ip);	isize = ip->i_size;	if (io->io_new_size > isize)		isize = io->io_new_size;	offset_fsb = XFS_B_TO_FSBT(mp, offset);	last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));	if ((offset + count) > isize) {		error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz,							&last_fsb);		if (error)			goto error_out;	} else {		if (found && (ret_imap->br_startblock == HOLESTARTBLOCK))			last_fsb = MIN(last_fsb, (xfs_fileoff_t)					ret_imap->br_blockcount +					ret_imap->br_startoff);	}	count_fsb = last_fsb - offset_fsb;	ASSERT(count_fsb > 0);	resaligned = count_fsb;	if (unlikely(extsz)) {		if ((temp = do_mod(offset_fsb, extsz)))			resaligned += temp;		if ((temp = do_mod(resaligned, extsz)))			resaligned += extsz - temp;	}	if (unlikely(rt)) {		resrtextents = qblocks = resaligned;

⌨️ 快捷键说明

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