if (prealloced && map[i].br_startblock == HOLESTARTBLOCK && out.bmv_offset + out.bmv_length == bmvend) { /* * came to hole at end of file */ 
if (map[i].br_startblock == HOLESTARTBLOCK && ((prealloced && out.bmv_offset + out.bmv_length == bmvend) || whichfork == XFS_ATTR_FORK )) { /* * came to hole at end of file or the end of attribute fork */ 
xfs_getbmap(	bhv_desc_t		*bdp,		/* XFS behavior descriptor*/	struct getbmap		*bmv,		/* user bmap structure */	void			__user *ap,	/* pointer to user's array */	int			interface)	/* interface flags */{	__int64_t		bmvend;		/* last block requested */	int			error;		/* return value */	__int64_t		fixlen;		/* length for -1 case */	int			i;		/* extent number */	xfs_inode_t		*ip;		/* xfs incore inode pointer */	vnode_t			*vp;		/* corresponding vnode */	int			lock;		/* lock state */	xfs_bmbt_irec_t		*map;		/* buffer for user's data */	xfs_mount_t		*mp;		/* file system mount point */	int			nex;		/* # of user extents can do */	int			nexleft;	/* # of user extents left */	int			subnex;		/* # of bmapi's can do */	int			nmap;		/* number of map entries */	struct getbmap		out;		/* output structure */	int			whichfork;	/* data or attr fork */	int			prealloced;	/* this is a file with						 * preallocated data space */	int			sh_unwritten;	/* true, if unwritten */						/* extents listed separately */	int			bmapi_flags;	/* flags for xfs_bmapi */	__int32_t		oflags;		/* getbmapx bmv_oflags field */	vp = BHV_TO_VNODE(bdp);	ip = XFS_BHVTOI(bdp);	mp = ip->i_mount;	whichfork = interface & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;	sh_unwritten = (interface & BMV_IF_PREALLOC) != 0;	/*	If the BMV_IF_NO_DMAPI_READ interface bit specified, do not	 *	generate a DMAPI read event.  Otherwise, if the DM_EVENT_READ	 *	bit is set for the file, generate a read event in order	 *	that the DMAPI application may do its thing before we return	 *	the extents.  Usually this means restoring user file data to	 *	regions of the file that look like holes.	 *	 *	The "old behavior" (from XFS_IOC_GETBMAP) is to not specify	 *	BMV_IF_NO_DMAPI_READ so that read events are generated.	 *	If this were not true, callers of ioctl( XFS_IOC_GETBMAP )	 *	could misinterpret holes in a DMAPI file as true holes,	 *	when in fact they may represent offline user data.	 */	if (   (interface & BMV_IF_NO_DMAPI_READ) == 0	    && DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)	    && whichfork == XFS_DATA_FORK) {		error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 0, 0, 0, NULL);		if (error)			return XFS_ERROR(error);	}	if (whichfork == XFS_ATTR_FORK) {		if (XFS_IFORK_Q(ip)) {			if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS &&			    ip->i_d.di_aformat != XFS_DINODE_FMT_BTREE &&			    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)				return XFS_ERROR(EINVAL);		} else if (unlikely(			   ip->i_d.di_aformat != 0 &&			   ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS)) {			XFS_ERROR_REPORT("xfs_getbmap", XFS_ERRLEVEL_LOW,					 ip->i_mount);			return XFS_ERROR(EFSCORRUPTED);		}	} else if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&		   ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&		   ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)		return XFS_ERROR(EINVAL);	if (whichfork == XFS_DATA_FORK) {		if (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC) {			prealloced = 1;			fixlen = XFS_MAXIOFFSET(mp);		} else {			prealloced = 0;			fixlen = ip->i_d.di_size;		}	} else {		prealloced = 0;		fixlen = 1LL << 32;	}	if (bmv->bmv_length == -1) {		fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen));		bmv->bmv_length = MAX( (__int64_t)(fixlen - bmv->bmv_offset),					(__int64_t)0);	} else if (bmv->bmv_length < 0)		return XFS_ERROR(EINVAL);	if (bmv->bmv_length == 0) {		bmv->bmv_entries = 0;		return 0;	}	nex = bmv->bmv_count - 1;	if (nex <= 0)		return XFS_ERROR(EINVAL);	bmvend = bmv->bmv_offset + bmv->bmv_length;	xfs_ilock(ip, XFS_IOLOCK_SHARED);	if (whichfork == XFS_DATA_FORK && ip->i_delayed_blks) {		/* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */		VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error);	}	ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0);	lock = xfs_ilock_map_shared(ip);	/*	 * Don't let nex be bigger than the number of extents	 * we can have assuming alternating holes and real extents.	 */	if (nex > XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1)		nex = XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1;	bmapi_flags = XFS_BMAPI_AFLAG(whichfork) |			((sh_unwritten) ? 0 : XFS_BMAPI_IGSTATE);	/*	 * Allocate enough space to handle "subnex" maps at a time.	 */	subnex = 16;	map = kmem_alloc(subnex * sizeof(*map), KM_SLEEP);	bmv->bmv_entries = 0;	if (XFS_IFORK_NEXTENTS(ip, whichfork) == 0) {		error = 0;		goto unlock_and_return;	}	nexleft = nex;	do {		nmap = (nexleft > subnex) ? subnex : nexleft;		error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),				  XFS_BB_TO_FSB(mp, bmv->bmv_length),				  bmapi_flags, NULL, 0, map, &nmap, NULL);		if (error)			goto unlock_and_return;		ASSERT(nmap <= subnex);		for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) {			nexleft--;			oflags = (map[i].br_state == XFS_EXT_UNWRITTEN) ?					BMV_OF_PREALLOC : 0;			out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff);			out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount);			ASSERT(map[i].br_startblock != DELAYSTARTBLOCK);			if (prealloced &&			    map[i].br_startblock == HOLESTARTBLOCK &&			    out.bmv_offset + out.bmv_length == bmvend) {				/*				 * came to hole at end of file				 */				goto unlock_and_return;			} else {				out.bmv_block =				    (map[i].br_startblock == HOLESTARTBLOCK) ?					-1 :					XFS_FSB_TO_DB(ip, map[i].br_startblock);				/* return either getbmap/getbmapx structure. */				if (interface & BMV_IF_EXTENDED) {					struct	getbmapx	outx;					GETBMAP_CONVERT(out,outx);					outx.bmv_oflags = oflags;					outx.bmv_unused1 = outx.bmv_unused2 = 0;					if (copy_to_user(ap, &outx,							sizeof(outx))) {						error = XFS_ERROR(EFAULT);						goto unlock_and_return;					}				} else {					if (copy_to_user(ap, &out,							sizeof(out))) {						error = XFS_ERROR(EFAULT);						goto unlock_and_return;					}				}				bmv->bmv_offset =					out.bmv_offset + out.bmv_length;				bmv->bmv_length = MAX((__int64_t)0,					(__int64_t)(bmvend - bmv->bmv_offset));				bmv->bmv_entries++;				ap = (interface & BMV_IF_EXTENDED) ?						(void __user *)					((struct getbmapx __user *)ap + 1) :						(void __user *)					((struct getbmap __user *)ap + 1);			}		}	} while (nmap && nexleft && bmv->bmv_length);unlock_and_return:	xfs_iunlock_map_shared(ip, lock);	xfs_iunlock(ip, XFS_IOLOCK_SHARED);	kmem_free(map, subnex * sizeof(*map));	return error;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/9af0a70c07a0e7575ebbdb42ca9fb29ffaaf77c9/xfs_bmap.c/buggy/fs/xfs/xfs_bmap.c