alloc: upgrade to fallocate
[xfstests-dev.git] / src / alloc.c
index 92139f7837bc7f5b61043ddc511196c732f341df..4a446ca827d8e1d377b53ffd5eb79b157ca541f7 100644 (file)
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2003 Silicon Graphics, Inc.
  * All Rights Reserved.
 /*
  * Copyright (c) 2000-2003 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 "global.h"
  */
  
 #include "global.h"
@@ -130,6 +118,50 @@ bozo!
     }
 }
 
     }
 }
 
+#ifdef HAVE_FALLOCATE
+# define USE_LINUX_PREALLOCATE
+enum linux_opno {
+       FREESP = 0,
+       ALLOCSP,
+       UNRESVSP,
+       RESVSP,
+};
+
+/* emulate the irix preallocation functions with linux vfs calls */
+static int
+linux_preallocate(
+       int                     fd,
+       enum linux_opno         opno,
+       const struct flock64    *f)
+{
+       struct stat             sbuf;
+       int                     ret;
+
+       assert(f->l_whence == SEEK_SET);
+
+       switch (opno) {
+       case FREESP:
+               return ftruncate(fd, f->l_start);
+       case ALLOCSP:
+               ret = fstat(fd, &sbuf);
+               if (ret)
+                       return ret;
+
+               return fallocate(fd, 0, sbuf.st_size,
+                               f->l_start - sbuf.st_size);
+       case UNRESVSP:
+               return fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+                               f->l_start, f->l_len);
+       case RESVSP:
+               return fallocate(fd, FALLOC_FL_KEEP_SIZE, f->l_start, f->l_len);
+       }
+
+       /* should never get here */
+       errno = EINVAL;
+       return -1;
+}
+#endif
+
 int
 main(int argc, char **argv)
 {
 int
 main(int argc, char **argv)
 {
@@ -148,30 +180,30 @@ main(int argc, char **argv)
                                       "resvsp" };
        int             opno;
 
                                       "resvsp" };
        int             opno;
 
-       /* Assume that if we have FREESP64 then we have the rest */
-#ifdef XFS_IOC_FREESP64
+#if defined(HAVE_FALLOCATE)
+       /* see static function above */
+#elif defined(XFS_IOC_FREESP64)
 #define USE_XFSCTL
 #define USE_XFSCTL
+       /* Assume that if we have FREESP64 then we have the rest */
        static int      optab[] = { XFS_IOC_FREESP64,
                                    XFS_IOC_ALLOCSP64,
                                    XFS_IOC_UNRESVSP64,
                                    XFS_IOC_RESVSP64 };
        static int      optab[] = { XFS_IOC_FREESP64,
                                    XFS_IOC_ALLOCSP64,
                                    XFS_IOC_UNRESVSP64,
                                    XFS_IOC_RESVSP64 };
-#else
-#ifdef F_FREESP64
+#elif defined(F_FREESP64)
 #define USE_FCNTL
        static int      optab[] = { F_FREESP64,
                                    F_ALLOCSP64,
                                    F_UNRESVSP64,
                                    F_RESVSP64 };
 #else
 #define USE_FCNTL
        static int      optab[] = { F_FREESP64,
                                    F_ALLOCSP64,
                                    F_UNRESVSP64,
                                    F_RESVSP64 };
 #else
-bozo!
-#endif
+# error Dont know how to preallocate space!
 #endif
        int             rflag = 0;
        struct statvfs64        svfs;
        int             tflag = 0;
         int             nflag = 0;
        int             unlinkit = 0;
 #endif
        int             rflag = 0;
        struct statvfs64        svfs;
        int             tflag = 0;
         int             nflag = 0;
        int             unlinkit = 0;
-       __int64_t       v;
+       int64_t         v;
 
        while ((c = getopt(argc, argv, "b:d:f:rtn")) != -1) {
                switch (c) {
 
        while ((c = getopt(argc, argv, "b:d:f:rtn")) != -1) {
                switch (c) {
@@ -323,14 +355,14 @@ bozo!
                                 opnames[opno], (long long)off, (long long)len);
                         
                        f.l_len = len;
                                 opnames[opno], (long long)off, (long long)len);
                         
                        f.l_len = len;
-#ifdef USE_XFSCTL
+#if defined(USE_LINUX_PREALLOCATE)
+                       c = linux_preallocate(fd, opno, &f);
+#elif defined(USE_XFSCTL)
                        c = xfsctl(filename, fd, optab[opno], &f);
                        c = xfsctl(filename, fd, optab[opno], &f);
-#else
-#ifdef USE_FCNTL
+#elif defined(USE_FCNTL)
                        c = fcntl(fd, optab[opno], &f);
 #else
                        c = fcntl(fd, optab[opno], &f);
 #else
-bozo!
-#endif
+# error Dont know how to preallocate space!
 #endif
                        if (c < 0) {
                                perror(opnames[opno]);
 #endif
                        if (c < 0) {
                                perror(opnames[opno]);