コード例 #1
0
ファイル: pr33669.c プロジェクト: 0day-ci/gcc
long long
foo (foo_t *const pxp,  long long offset, unsigned int extent)
{
  long long blkoffset = _RNDDOWN(offset, (long long )pxp->blksz);
  unsigned int diff = (unsigned int)(offset - blkoffset);
  unsigned int blkextent = _RNDUP(diff + extent, pxp->blksz);

  if (pxp->blksz < blkextent)
    return -1LL;

  if (pxp->bf_cnt > pxp->blksz)
    pxp->bf_cnt = pxp->blksz;

  return blkoffset;
}
コード例 #2
0
ファイル: posixio.c プロジェクト: ArtisticCoding/libmesh
/* POSIX get. This will "make a region available." Since we're using
   buffered IO, this means that if needed, we'll fetch a new page from
   the file, otherwise, just return a pointer to what's in memory
   already.

   nciop - pointer to ncio struct, containing file info.
   pxp - pointer to ncio_px struct, which contains special metadate
   for posix files without NC_SHARE.
   offset - start byte of region to get.
   extent - how many bytes to read.
   rflags - One of the RGN_* flags defined in ncio.h.
   vpp - pointer to pointer that will recieve data.

   NOTES:

   * For blkoffset round offset down to the nearest pxp->blksz. This
   provides the offset (in bytes) to the beginning of the block that
   holds the current offset.

   * diff tells how far into the current block we are.

   * For blkextent round up to the number of bytes at the beginning of
   the next block, after the one that holds our current position, plus
   whatever extra (i.e. the extent) that we are about to grab.

   * The blkextent can't be more than twice the pxp->blksz. That's
   because the pxp->blksize is the sizehint, and in ncio_px_init2 the
   buffer (pointed to by pxp->bf-base) is allocated with 2 *
   *sizehintp. This is checked (unneccesarily) more than once in
   asserts.

   * If this is called on a newly opened file, pxp->bf_offset will be
   OFF_NONE and we'll jump to label pgin to immediately read in a
   page.
*/
static int
px_get(ncio *const nciop, ncio_px *const pxp,
		off_t offset, size_t extent,
		int rflags,
		void **const vpp)
{
	int status = ENOERR;

	const off_t blkoffset = _RNDDOWN(offset, (off_t)pxp->blksz);
	off_t diff = (size_t)(offset - blkoffset);
	off_t blkextent = _RNDUP(diff + extent, pxp->blksz);

	assert(extent != 0);
	assert(extent < X_INT_MAX); /* sanity check */
	assert(offset >= 0); /* sanity check */

	if(2 * pxp->blksz < blkextent)
		return E2BIG; /* TODO: temporary kludge */
	if(pxp->bf_offset == OFF_NONE)
	{
		/* Uninitialized */
		if(pxp->bf_base == NULL)
		{
			assert(pxp->bf_extent == 0);
			assert(blkextent <= 2 * pxp->blksz);
			pxp->bf_base = malloc(2 * pxp->blksz);
			if(pxp->bf_base == NULL)
				return ENOMEM;
		}
		goto pgin;
	}
	/* else */
	assert(blkextent <= 2 * pxp->blksz);

	if(blkoffset == pxp->bf_offset)
	{
		/* hit */
 		if(blkextent > pxp->bf_extent)
		{
			/* page in upper */
			void *const middle =
			 	(void *)((char *)pxp->bf_base + pxp->blksz);
			assert(pxp->bf_extent == pxp->blksz);
			status = px_pgin(nciop,
				 pxp->bf_offset + (off_t)pxp->blksz,
				 pxp->blksz,
				 middle,
				 &pxp->bf_cnt,
				 &pxp->pos);
			if(status != ENOERR)
				return status;
			pxp->bf_extent = 2 * pxp->blksz;
			pxp->bf_cnt += pxp->blksz;
		}
		goto done;
	}
	/* else */

	if(pxp->bf_extent > pxp->blksz
		 && blkoffset == pxp->bf_offset + (off_t)pxp->blksz)
	{
		/* hit in upper half */
		if(blkextent == pxp->blksz)
		{
			/* all in upper half, no fault needed */
			diff += pxp->blksz;
			goto done;
		}
		/* else */
		if(pxp->bf_cnt > pxp->blksz)
		{
			/* data in upper half */
			void *const middle =
				(void *)((char *)pxp->bf_base + pxp->blksz);
			assert(pxp->bf_extent == 2 * pxp->blksz);
			if(fIsSet(pxp->bf_rflags, RGN_MODIFIED))
			{
				/* page out lower half */
				assert(pxp->bf_refcount <= 0);
				status = px_pgout(nciop,
					pxp->bf_offset,
					pxp->blksz,
					pxp->bf_base,
					&pxp->pos);
				if(status != ENOERR)
					return status;
			}
			pxp->bf_cnt -= pxp->blksz;
			/* copy upper half into lower half */
			(void) memcpy(pxp->bf_base, middle, pxp->bf_cnt);
		}
		else		/* added to fix nofill bug */
		{
			assert(pxp->bf_extent == 2 * pxp->blksz);
			/* still have to page out lower half, if modified */
			if(fIsSet(pxp->bf_rflags, RGN_MODIFIED))
			{
				assert(pxp->bf_refcount <= 0);
				status = px_pgout(nciop,
					pxp->bf_offset,
					pxp->blksz,
					pxp->bf_base,
					&pxp->pos);
				if(status != ENOERR)
					return status;
			}
		}
		pxp->bf_offset = blkoffset;
		/* pxp->bf_extent = pxp->blksz; */

 		assert(blkextent == 2 * pxp->blksz);
		{
			/* page in upper */
			void *const middle =
			 	(void *)((char *)pxp->bf_base + pxp->blksz);
			status = px_pgin(nciop,
				 pxp->bf_offset + (off_t)pxp->blksz,
				 pxp->blksz,
				 middle,
				 &pxp->bf_cnt,
				 &pxp->pos);
			if(status != ENOERR)
				return status;
			pxp->bf_extent = 2 * pxp->blksz;
			pxp->bf_cnt += pxp->blksz;
		}
		goto done;
	}
	/* else */

	if(blkoffset == pxp->bf_offset - (off_t)pxp->blksz)
	{
		/* wants the page below */
		void *const middle =
			(void *)((char *)pxp->bf_base + pxp->blksz);
		size_t upper_cnt = 0;
		if(pxp->bf_cnt > pxp->blksz)
		{
			/* data in upper half */
			assert(pxp->bf_extent == 2 * pxp->blksz);
			if(fIsSet(pxp->bf_rflags, RGN_MODIFIED))
			{
				/* page out upper half */
				assert(pxp->bf_refcount <= 0);
				status = px_pgout(nciop,
					pxp->bf_offset + (off_t)pxp->blksz,
					pxp->bf_cnt - pxp->blksz,
					middle,
					&pxp->pos);
				if(status != ENOERR)
					return status;
			}
			pxp->bf_cnt = pxp->blksz;
			pxp->bf_extent = pxp->blksz;
		}
		if(pxp->bf_cnt > 0)
		{
			/* copy lower half into upper half */
			(void) memcpy(middle, pxp->bf_base, pxp->blksz);
			upper_cnt = pxp->bf_cnt;
		}
		/* read page below into lower half */
		status = px_pgin(nciop,
			 blkoffset,
			 pxp->blksz,
			 pxp->bf_base,
			 &pxp->bf_cnt,
			 &pxp->pos);
		if(status != ENOERR)
			return status;
		pxp->bf_offset = blkoffset;
		if(upper_cnt != 0)
		{
			pxp->bf_extent = 2 * pxp->blksz;
			pxp->bf_cnt = pxp->blksz + upper_cnt;
		}
		else
		{
			pxp->bf_extent = pxp->blksz;
		}
		goto done;
	}
	/* else */

	/* no overlap */
	if(fIsSet(pxp->bf_rflags, RGN_MODIFIED))
	{
		assert(pxp->bf_refcount <= 0);
		status = px_pgout(nciop,
			pxp->bf_offset,
			pxp->bf_cnt,
			pxp->bf_base,
			&pxp->pos);
		if(status != ENOERR)
			return status;
		pxp->bf_rflags = 0;
	}

pgin:
	status = px_pgin(nciop,
		 blkoffset,
		 blkextent,
		 pxp->bf_base,
		 &pxp->bf_cnt,
		 &pxp->pos);
	if(status != ENOERR)
		return status;
	 pxp->bf_offset = blkoffset;
	 pxp->bf_extent = blkextent;

done:
	extent += diff;
	if(pxp->bf_cnt < extent)
		pxp->bf_cnt = extent;
	assert(pxp->bf_cnt <= pxp->bf_extent);

	pxp->bf_rflags |= rflags;
	pxp->bf_refcount++;

	*vpp = (char *)pxp->bf_base + diff;
	return ENOERR;
}