alloc: upgrade to fallocate
[xfstests-dev.git] / src / alloc.c
index 17359fdf038467d76545b4e4eacf3a68beb2fecd..4a446ca827d8e1d377b53ffd5eb79b157ca541f7 100644 (file)
@@ -1,33 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
 /*
- * 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 version 2 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.
- * 
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- * 
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- * 
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- * 
- * http://www.sgi.com 
- * 
- * For further information regarding this notice, see: 
- * 
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.
+ * All Rights Reserved.
  */
  
 #include "global.h"
  */
  
 #include "global.h"
  * filesystem allocation, and must equal 512.  Length units given to bio
  * routines are in BB's.
  */
  * filesystem allocation, and must equal 512.  Length units given to bio
  * routines are in BB's.
  */
+
+/* Assume that if we have BTOBB, then we have the rest */
+#ifndef BTOBB
 #define BBSHIFT         9
 #define BBSIZE          (1<<BBSHIFT)
 #define BBMASK          (BBSIZE-1)
 #define BTOBB(bytes)    (((__u64)(bytes) + BBSIZE - 1) >> BBSHIFT)
 #define BTOBBT(bytes)   ((__u64)(bytes) >> BBSHIFT)
 #define BBTOB(bbs)      ((bbs) << BBSHIFT)
 #define BBSHIFT         9
 #define BBSIZE          (1<<BBSHIFT)
 #define BBMASK          (BBSIZE-1)
 #define BTOBB(bytes)    (((__u64)(bytes) + BBSIZE - 1) >> BBSHIFT)
 #define BTOBBT(bytes)   ((__u64)(bytes) >> BBSHIFT)
 #define BBTOB(bbs)      ((bbs) << BBSHIFT)
-#define OFFTOBB(bytes)  (((__u64)(bytes) + BBSIZE - 1) >> BBSHIFT)
 #define OFFTOBBT(bytes) ((__u64)(bytes) >> BBSHIFT)
 #define OFFTOBBT(bytes) ((__u64)(bytes) >> BBSHIFT)
-#define BBTOOFF(bbs)    ((__u64)(bbs) << BBSHIFT)
 
 #define SEEKLIMIT32     0x7fffffff
 #define BBSEEKLIMIT32   BTOBBT(SEEKLIMIT32)
 #define SEEKLIMIT       0x7fffffffffffffffLL
 #define BBSEEKLIMIT     OFFTOBBT(SEEKLIMIT)
 
 #define SEEKLIMIT32     0x7fffffff
 #define BBSEEKLIMIT32   BTOBBT(SEEKLIMIT32)
 #define SEEKLIMIT       0x7fffffffffffffffLL
 #define BBSEEKLIMIT     OFFTOBBT(SEEKLIMIT)
+#endif
+
+#ifndef OFFTOBB
+#define OFFTOBB(bytes)  (((__u64)(bytes) + BBSIZE - 1) >> BBSHIFT)
+#define BBTOOFF(bbs)    ((__u64)(bbs) << BBSHIFT)
+#endif
 
 #define        FSBTOBB(f)      (OFFTOBBT(FSBTOOFF(f)))
 #define        BBTOFSB(b)      (OFFTOFSB(BBTOOFF(b)))
 
 #define        FSBTOBB(f)      (OFFTOBBT(FSBTOOFF(f)))
 #define        BBTOFSB(b)      (OFFTOFSB(BBTOOFF(b)))
@@ -85,45 +66,102 @@ char               *filename;
 /* params are in bytes */
 void map(off64_t off, off64_t len)
 {
 /* params are in bytes */
 void map(off64_t off, off64_t len)
 {
-    struct getbmap     bm[2]={{0}};
+    struct getbmap     bm[2];
     
     
+    bzero(bm, sizeof(bm));
+
     bm[0].bmv_count = 2;
     bm[0].bmv_offset = OFFTOBB(off);
     if (len==(off64_t)-1) { /* unsigned... */
         bm[0].bmv_length = -1;
         printf("    MAP off=%lld, len=%lld [%lld-]\n", 
     bm[0].bmv_count = 2;
     bm[0].bmv_offset = OFFTOBB(off);
     if (len==(off64_t)-1) { /* unsigned... */
         bm[0].bmv_length = -1;
         printf("    MAP off=%lld, len=%lld [%lld-]\n", 
-                (__s64)off, (__s64)len,
-                (__s64)BBTOFSB(bm[0].bmv_offset));
+                (long long)off, (long long)len,
+                (long long)BBTOFSB(bm[0].bmv_offset));
     } else {
         bm[0].bmv_length = OFFTOBB(len);
         printf("    MAP off=%lld, len=%lld [%lld,%lld]\n", 
     } else {
         bm[0].bmv_length = OFFTOBB(len);
         printf("    MAP off=%lld, len=%lld [%lld,%lld]\n", 
-                (__s64)off, (__s64)len,
-                (__s64)BBTOFSB(bm[0].bmv_offset),
-                (__s64)BBTOFSB(bm[0].bmv_length));
+                (long long)off, (long long)len,
+                (long long)BBTOFSB(bm[0].bmv_offset),
+                (long long)BBTOFSB(bm[0].bmv_length));
     }
     
     printf("        [ofs,count]: start..end\n");
     for (;;) {
     }
     
     printf("        [ofs,count]: start..end\n");
     for (;;) {
+#ifdef XFS_IOC_GETBMAP
            if (xfsctl(filename, fd, XFS_IOC_GETBMAP, bm) < 0) {
            if (xfsctl(filename, fd, XFS_IOC_GETBMAP, bm) < 0) {
+#else
+#ifdef F_GETBMAP
+           if (fcntl(fd, F_GETBMAP, bm) < 0) {
+#else
+bozo!
+#endif
+#endif
                    perror("getbmap");
                    break;
            }
                    perror("getbmap");
                    break;
            }
+
            if (bm[0].bmv_entries == 0)
                    break;
            if (bm[0].bmv_entries == 0)
                    break;
+
            printf("        [%lld,%lld]: ",
            printf("        [%lld,%lld]: ",
-                   (__s64)BBTOFSB(bm[1].bmv_offset),
-                   (__s64)BBTOFSB(bm[1].bmv_length));
+                   (long long)BBTOFSB(bm[1].bmv_offset),
+                   (long long)BBTOFSB(bm[1].bmv_length));
+
            if (bm[1].bmv_block == -1)
                    printf("hole");
            else
                    printf("%lld..%lld",
            if (bm[1].bmv_block == -1)
                    printf("hole");
            else
                    printf("%lld..%lld",
-                           (__s64)BBTOFSB(bm[1].bmv_block),
-                           (__s64)BBTOFSB(bm[1].bmv_block +
+                           (long long)BBTOFSB(bm[1].bmv_block),
+                           (long long)BBTOFSB(bm[1].bmv_block +
                                    bm[1].bmv_length - 1));
            printf("\n");
     }
 }
 
                                    bm[1].bmv_length - 1));
            printf("\n");
     }
 }
 
+#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)
 {
@@ -136,17 +174,36 @@ main(int argc, char **argv)
        char            line[1024];
        off64_t         off;
        int             oflags;
        char            line[1024];
        off64_t         off;
        int             oflags;
-       static char     *opnames[] =
-               { "freesp", "allocsp", "unresvsp", "resvsp" };
+       static char     *opnames[] = { "freesp",
+                                      "allocsp",
+                                      "unresvsp",
+                                      "resvsp" };
        int             opno;
        int             opno;
-       static int      optab[] =
-               { XFS_IOC_FREESP64, XFS_IOC_ALLOCSP64, XFS_IOC_UNRESVSP64, XFS_IOC_RESVSP64 };
+
+#if defined(HAVE_FALLOCATE)
+       /* see static function above */
+#elif defined(XFS_IOC_FREESP64)
+#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 };
+#elif defined(F_FREESP64)
+#define USE_FCNTL
+       static int      optab[] = { F_FREESP64,
+                                   F_ALLOCSP64,
+                                   F_UNRESVSP64,
+                                   F_RESVSP64 };
+#else
+# error Dont know how to preallocate space!
+#endif
        int             rflag = 0;
        struct statvfs64        svfs;
        int             tflag = 0;
         int             nflag = 0;
        int             unlinkit = 0;
        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) {
@@ -219,17 +276,43 @@ main(int argc, char **argv)
        if (rflag) {
                struct fsxattr a;
 
        if (rflag) {
                struct fsxattr a;
 
+#ifdef XFS_IOC_FSGETXATTR
                if (xfsctl(filename, fd, XFS_IOC_FSGETXATTR, &a) < 0) {
                        perror("XFS_IOC_FSGETXATTR");
                        status = 1;
                        goto done;
                }
                if (xfsctl(filename, fd, XFS_IOC_FSGETXATTR, &a) < 0) {
                        perror("XFS_IOC_FSGETXATTR");
                        status = 1;
                        goto done;
                }
+#else
+#ifdef F_FSGETXATTR
+               if (fcntl(fd, F_FSGETXATTR, &a) < 0) {
+                       perror("F_FSGETXATTR");
+                       status = 1;
+                       goto done;
+               }
+#else
+bozo!
+#endif
+#endif
+
                a.fsx_xflags |= XFS_XFLAG_REALTIME;
                a.fsx_xflags |= XFS_XFLAG_REALTIME;
+
+#ifdef XFS_IOC_FSSETXATTR
                if (xfsctl(filename, fd, XFS_IOC_FSSETXATTR, &a) < 0) {
                        perror("XFS_IOC_FSSETXATTR");
                        status = 1;
                        goto done;
                }
                if (xfsctl(filename, fd, XFS_IOC_FSSETXATTR, &a) < 0) {
                        perror("XFS_IOC_FSSETXATTR");
                        status = 1;
                        goto done;
                }
+#else
+#ifdef F_FSSETXATTR
+               if (fcntl(fd, F_FSSETXATTR, &a) < 0) {
+                       perror("F_FSSETXATTR");
+                       status = 1;
+                       goto done;
+               }
+#else
+bozo!
+#endif
+#endif
        }
        while (!done) {
                 char *p;
        }
        while (!done) {
                 char *p;
@@ -269,10 +352,18 @@ main(int argc, char **argv)
                                len = v;
                         
                         printf("    CMD %s, off=%lld, len=%lld\n", 
                                len = v;
                         
                         printf("    CMD %s, off=%lld, len=%lld\n", 
-                                opnames[opno], (__s64)off, (__s64)len);
+                                opnames[opno], (long long)off, (long long)len);
                         
                        f.l_len = len;
                         
                        f.l_len = len;
+#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);
+#elif defined(USE_FCNTL)
+                       c = fcntl(fd, optab[opno], &f);
+#else
+# error Dont know how to preallocate space!
+#endif
                        if (c < 0) {
                                perror(opnames[opno]);
                                break;
                        if (c < 0) {
                                perror(opnames[opno]);
                                break;
@@ -307,7 +398,7 @@ main(int argc, char **argv)
                                off = FSBTOOFF(v);
                        else
                                off = v;
                                off = FSBTOOFF(v);
                        else
                                off = v;
-                        printf("    TRUNCATE off=%lld\n", (__s64)off);
+                        printf("    TRUNCATE off=%lld\n", (long long)off);
                        if (ftruncate64(fd, off) < 0) {
                                perror("ftruncate");
                                break;
                        if (ftruncate64(fd, off) < 0) {
                                perror("ftruncate");
                                break;