Blame support/support_descriptor_supports_holes.c

Packit Bot 3f3af5
/* Test for file system hole support.
Packit Bot 3f3af5
   Copyright (C) 2018 Free Software Foundation, Inc.
Packit Bot 3f3af5
   This file is part of the GNU C Library.
Packit Bot 3f3af5
Packit Bot 3f3af5
   The GNU C Library is free software; you can redistribute it and/or
Packit Bot 3f3af5
   modify it under the terms of the GNU Lesser General Public
Packit Bot 3f3af5
   License as published by the Free Software Foundation; either
Packit Bot 3f3af5
   version 2.1 of the License, or (at your option) any later version.
Packit Bot 3f3af5
Packit Bot 3f3af5
   The GNU C Library is distributed in the hope that it will be useful,
Packit Bot 3f3af5
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Bot 3f3af5
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Bot 3f3af5
   Lesser General Public License for more details.
Packit Bot 3f3af5
Packit Bot 3f3af5
   You should have received a copy of the GNU Lesser General Public
Packit Bot 3f3af5
   License along with the GNU C Library; if not, see
Packit Bot 3f3af5
   <http://www.gnu.org/licenses/>.  */
Packit Bot 3f3af5
Packit Bot 3f3af5
#include <stdbool.h>
Packit Bot 3f3af5
#include <support.h>
Packit Bot 3f3af5
#include <support/check.h>
Packit Bot 3f3af5
#include <sys/stat.h>
Packit Bot 3f3af5
#include <xunistd.h>
Packit Bot 3f3af5
Packit Bot 3f3af5
int
Packit Bot 3f3af5
support_descriptor_supports_holes (int fd)
Packit Bot 3f3af5
{
Packit Bot 3f3af5
  enum
Packit Bot 3f3af5
    {
Packit Bot 3f3af5
      /* Write offset for the enlarged file.  This value is arbitrary
Packit Bot 3f3af5
         and hopefully large enough to trigger the creation of holes.
Packit Bot 3f3af5
         We cannot use the file system block size as a reference here
Packit Bot 3f3af5
         because it is incorrect for network file systems.  */
Packit Bot 3f3af5
      write_offset = 16 * 1024 * 1024,
Packit Bot 3f3af5
Packit Bot 3f3af5
      /* Our write may add this number of additional blocks (see
Packit Bot 3f3af5
         block_limit below).  */
Packit Bot 3f3af5
      block_headroom = 8,
Packit Bot 3f3af5
    };
Packit Bot 3f3af5
Packit Bot 3f3af5
  struct stat64 st;
Packit Bot 3f3af5
  xfstat (fd, &st);
Packit Bot 3f3af5
  if (!S_ISREG (st.st_mode))
Packit Bot 3f3af5
    FAIL_EXIT1 ("descriptor %d does not refer to a regular file", fd);
Packit Bot 3f3af5
  if (st.st_size != 0)
Packit Bot 3f3af5
    FAIL_EXIT1 ("descriptor %d does not refer to an empty file", fd);
Packit Bot 3f3af5
  if (st.st_blocks > block_headroom)
Packit Bot 3f3af5
    FAIL_EXIT1 ("descriptor %d refers to a pre-allocated file (%lld blocks)",
Packit Bot 3f3af5
                fd, (long long int) st.st_blocks);
Packit Bot 3f3af5
Packit Bot 3f3af5
  /* Write a single byte at the start of the file to compute the block
Packit Bot 3f3af5
     usage for a single byte.  */
Packit Bot 3f3af5
  xlseek (fd, 0, SEEK_SET);
Packit Bot 3f3af5
  char b = '@';
Packit Bot 3f3af5
  xwrite (fd, &b, 1);
Packit Bot 3f3af5
  /* Attempt to bypass delayed allocation.  */
Packit Bot 3f3af5
  TEST_COMPARE (fsync (fd), 0);
Packit Bot 3f3af5
  xfstat (fd, &st);
Packit Bot 3f3af5
Packit Bot 3f3af5
  /* This limit is arbitrary.  The file system needs to store
Packit Bot 3f3af5
     somewhere that data exists at the write offset, and this may
Packit Bot 3f3af5
     moderately increase the number of blocks used by the file, in
Packit Bot 3f3af5
     proportion to the initial block count, but not in proportion to
Packit Bot 3f3af5
     the write offset.  */
Packit Bot 3f3af5
  unsigned long long int block_limit = 2 * st.st_blocks + block_headroom;
Packit Bot 3f3af5
Packit Bot 3f3af5
  /* Write a single byte at 16 megabytes.  */
Packit Bot 3f3af5
  xlseek (fd, write_offset, SEEK_SET);
Packit Bot 3f3af5
  xwrite (fd, &b, 1);
Packit Bot 3f3af5
  /* Attempt to bypass delayed allocation.  */
Packit Bot 3f3af5
  TEST_COMPARE (fsync (fd), 0);
Packit Bot 3f3af5
  xfstat (fd, &st);
Packit Bot 3f3af5
  bool supports_holes = st.st_blocks <= block_limit;
Packit Bot 3f3af5
Packit Bot 3f3af5
  /* Also check that extending the file does not fill up holes.  */
Packit Bot 3f3af5
  xftruncate (fd, 2 * write_offset);
Packit Bot 3f3af5
  /* Attempt to bypass delayed allocation.  */
Packit Bot 3f3af5
  TEST_COMPARE (fsync (fd), 0);
Packit Bot 3f3af5
  xfstat (fd, &st);
Packit Bot 3f3af5
  supports_holes = supports_holes && st.st_blocks <= block_limit;
Packit Bot 3f3af5
Packit Bot 3f3af5
  /* Return to a zero-length file.  */
Packit Bot 3f3af5
  xftruncate (fd, 0);
Packit Bot 3f3af5
  xlseek (fd, 0, SEEK_SET);
Packit Bot 3f3af5
Packit Bot 3f3af5
  return supports_holes;
Packit Bot 3f3af5
}