예제 #1
0
static bool
preallocate_file_sparse (int fd, uint64_t length)
{
    const char zero = '\0';
    bool success = 0;

    if (!length)
        success = true;

#ifdef HAVE_FALLOCATE64
    if (!success) /* fallocate64 is always preferred, so try it first */
        success = !fallocate64 (fd, 0, 0, length);
#endif

    if (!success) /* fallback: the old-style seek-and-write */
        success = (lseek (fd, length-1, SEEK_SET) != -1)
               && (write (fd, &zero, 1) != -1)
               && (ftruncate (fd, length) != -1);

    return success;
}
예제 #2
0
TEST(fcntl, fallocate_EINVAL) {
  TemporaryFile tf;

#if !defined(__GLIBC__)
  errno = 0;
  ASSERT_EQ(-1, fallocate(tf.fd, 0, 0, -1));
  ASSERT_EQ(EINVAL, errno);

  errno = 0;
  ASSERT_EQ(-1, fallocate64(tf.fd, 0, 0, -1));
  ASSERT_EQ(EINVAL, errno);
#endif

  errno = 0;
  ASSERT_EQ(EINVAL, posix_fallocate(tf.fd, 0, -1));
  ASSERT_EQ(0, errno);

  errno = 0;
  ASSERT_EQ(EINVAL, posix_fallocate64(tf.fd, 0, -1));
  ASSERT_EQ(0, errno);
}
예제 #3
0
TEST(fcntl, fallocate) {
  TemporaryFile tf;
  struct stat sb;
  ASSERT_EQ(0, fstat(tf.fd, &sb));
  ASSERT_EQ(0, sb.st_size);

#if !defined(__GLIBC__)
  ASSERT_EQ(0, fallocate(tf.fd, 0, 0, 1));
  ASSERT_EQ(0, fstat(tf.fd, &sb));
  ASSERT_EQ(1, sb.st_size);

  ASSERT_EQ(0, fallocate64(tf.fd, 0, 0, 2));
  ASSERT_EQ(0, fstat(tf.fd, &sb));
  ASSERT_EQ(2, sb.st_size);
#endif

  ASSERT_EQ(0, posix_fallocate(tf.fd, 0, 3));
  ASSERT_EQ(0, fstat(tf.fd, &sb));
  ASSERT_EQ(3, sb.st_size);

  ASSERT_EQ(0, posix_fallocate64(tf.fd, 0, 4));
  ASSERT_EQ(0, fstat(tf.fd, &sb));
  ASSERT_EQ(4, sb.st_size);
}
예제 #4
0
static bool
preallocate_file_full (const char * filename, uint64_t length)
{
    bool success = 0;

#ifdef WIN32

    HANDLE hFile = CreateFile (filename, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        LARGE_INTEGER li;
        li.QuadPart = length;
        success = SetFilePointerEx (hFile, li, NULL, FILE_BEGIN) && SetEndOfFile (hFile);
        CloseHandle (hFile);
    }

#else

    int flags = O_RDWR | O_CREAT | O_LARGEFILE;
    int fd = open (filename, flags, 0666);
    if (fd >= 0)
    {
# ifdef HAVE_FALLOCATE64
       if (!success)
       {
           success = !fallocate64 (fd, 0, 0, length);
       }
# endif
# ifdef HAVE_XFS_XFS_H
        if (!success && platform_test_xfs_fd (fd))
        {
            xfs_flock64_t fl;
            fl.l_whence = 0;
            fl.l_start = 0;
            fl.l_len = length;
            success = !xfsctl (NULL, fd, XFS_IOC_RESVSP64, &fl);
        }
# endif
# ifdef SYS_DARWIN
        if (!success)
        {
            fstore_t fst;
            fst.fst_flags = F_ALLOCATECONTIG;
            fst.fst_posmode = F_PEOFPOSMODE;
            fst.fst_offset = 0;
            fst.fst_length = length;
            fst.fst_bytesalloc = 0;
            success = !fcntl (fd, F_PREALLOCATE, &fst);
        }
# endif
#undef HAVE_POSIX_FALLOCATE
# ifdef HAVE_POSIX_FALLOCATE
        if (!success)
        {
            success = !posix_fallocate (fd, 0, length);
        }
# endif

#define MINSLEEP 3
#define MAXSLEEP 40000
#define INCRFACT 1.9
#define DECRFACT 3
#define BLCKSIZE 32768
#define TSTEVERYBYTES 524288
#define TSTEVERYBLKS TSTEVERYBYTES/BLCKSIZE
        if (!success) /* if nothing else works, do it the old-fashioned way */
        {
	  struct timeval lastTime, thisTime;
	  // Set up buffer with 0s.
	  unsigned int block_size = BLCKSIZE;
	  uint8_t buf[ block_size ];
	  memset (buf, 0, sizeof (buf));

	  // Set up speed test counters.
	  unsigned int testEveryBytes = TSTEVERYBYTES;
	  unsigned int testEveryIters = TSTEVERYBLKS;
	  unsigned int itersUntilTest = testEveryIters;
	  long         lastTook = 0;
	  long         currentTook = 0;
	  gettimeofday(&lastTime, NULL);
	  unsigned int sleep = MINSLEEP;
	  unsigned int lastSlept = 0;
	  unsigned int size=length;

	  success = true;
	  while (success && (length > 0))
	  {
	      if (itersUntilTest == 0) {
		gettimeofday(&thisTime, NULL);
		currentTook = thisTime.tv_sec*1000000 + thisTime.tv_usec - lastTime.tv_sec*1000000 - lastTime.tv_usec - lastSlept;
		if (currentTook > lastTook) {
		  sleep = MIN(sleep * INCRFACT, MAXSLEEP);
		} else if (currentTook < lastTook) {
		  sleep = MAX(sleep / DECRFACT, MINSLEEP);
		}
		lastSlept = 0;
		lastTook = currentTook;
		lastTime = thisTime;
		itersUntilTest = testEveryIters;
		fprintf (stderr, "{\"TR_PREALLOC\":%d,\"filename\":\"%s\"}\n", (int)(100.f*(float)(size - length)/(float)size), filename);
		//fprintf (stderr, "Will sleep %d usec on every write.\n", sleep);
	      }

	      const int thisPass = MIN (length, sizeof (buf));
	      success = write (fd, buf, thisPass) == thisPass;
	      length -= thisPass;

	      --itersUntilTest;
	      usleep(sleep);
	      lastSlept = lastSlept + sleep;
	    }
        }

/*
        if (!success) // if nothing else works, do it the old-fashioned way 
        {
            uint8_t buf[ 32768 ];
            memset (buf, 0, sizeof (buf));
            success = true;
            while (success && (length > 0))
            {
                const int thisPass = MIN (length, sizeof (buf));
                success = write (fd, buf, thisPass) == thisPass;
                length -= thisPass;
		usleep(9000);
            }
        }
*/



        close (fd);
    }

#endif

    return success;
}
static bool
preallocate_file_full( const char * filename, uint64_t length )
{
    bool success = 0;

#ifdef WIN32

    HANDLE hFile = CreateFile( filename, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0 );
    if( hFile != INVALID_HANDLE_VALUE )
    {
        LARGE_INTEGER li;
        li.QuadPart = length;
        success = SetFilePointerEx( hFile, li, NULL, FILE_BEGIN ) && SetEndOfFile( hFile );
        CloseHandle( hFile );
    }

#else

    int flags = O_RDWR | O_CREAT | O_LARGEFILE;
    int fd = open( filename, flags, 0666 );
    if( fd >= 0 )
    {
# ifdef HAVE_FALLOCATE64
       if( !success )
       {
           success = !fallocate64( fd, 0, 0, length );
       }
# endif
# ifdef HAVE_XFS_XFS_H
        if( !success && platform_test_xfs_fd( fd ) )
        {
            xfs_flock64_t fl;
            fl.l_whence = 0;
            fl.l_start = 0;
            fl.l_len = length;
            success = !xfsctl( NULL, fd, XFS_IOC_RESVSP64, &fl );
        }
# endif
# ifdef SYS_DARWIN
        if( !success )
        {
            fstore_t fst;
            fst.fst_flags = F_ALLOCATECONTIG;
            fst.fst_posmode = F_PEOFPOSMODE;
            fst.fst_offset = 0;
            fst.fst_length = length;
            fst.fst_bytesalloc = 0;
            success = !fcntl( fd, F_PREALLOCATE, &fst );
        }
# endif
# ifdef HAVE_POSIX_FALLOCATE
        if( !success )
        {
            success = !posix_fallocate( fd, 0, length );
        }
# endif

        if( !success ) /* if nothing else works, do it the old-fashioned way */
        {
            uint8_t buf[ 4096 ];
            memset( buf, 0, sizeof( buf ) );
            success = true;
            while ( success && ( length > 0 ) )
            {
                const int thisPass = MIN( length, sizeof( buf ) );
                success = write( fd, buf, thisPass ) == thisPass;
                length -= thisPass;
            }
        }

        close( fd );
    }

#endif

    return success;
}
// There is no fallocate for 32-bit off_t, so we need to widen and call fallocate64.
int fallocate(int fd, int mode, off_t offset, off_t length) {
  return fallocate64(fd, mode, static_cast<off64_t>(offset), static_cast<off64_t>(length));
}