generic: add fstests for idmapped mounts
[xfstests-dev.git] / src / feature.c
index df550cf6e1919c4ff6a861ca5689f6d50207dc9a..bc0b0b3026eb546e23e2ea8aea8d24290b95b3e8 100644 (file)
@@ -19,6 +19,7 @@
  *
  * Test for machine features
  *   -A  test whether AIO syscalls are available
+ *   -r  test whether mount_setattr syscall is supported
  *   -R  test whether IO_URING syscalls are available
  *   -o  report a number of online cpus
  *   -s  report pagesize
@@ -30,6 +31,7 @@
 #include <sys/quota.h>
 #include <sys/resource.h>
 #include <signal.h>
+#include <syscall.h>
 #include <unistd.h>
 
 #ifdef HAVE_XFS_XQM_H
@@ -44,6 +46,8 @@
 #include <liburing.h>
 #endif
 
+#include "idmapped-mounts/missing.h"
+
 #ifndef USRQUOTA
 #define USRQUOTA  0
 #endif
@@ -64,7 +68,7 @@ usage(void)
        fprintf(stderr, "Usage: feature [-v] -<q|u|g|p|U|G|P> <filesystem>\n");
        fprintf(stderr, "       feature [-v] -c <file>\n");
        fprintf(stderr, "       feature [-v] -t <file>\n");
-       fprintf(stderr, "       feature -A | -R | -o | -s | -w\n");
+       fprintf(stderr, "       feature -A | -r | -R | -o | -s | -w\n");
        exit(1);
 }
 
@@ -243,6 +247,27 @@ check_uring_support(void)
 #endif
 }
 
+static int
+check_mount_setattr_support(void)
+{
+       int err;
+       struct mount_attr attr = {
+               .attr_set       = MOUNT_ATTR_IDMAP,
+               .userns_fd      = -EBADF,
+       };
+
+       /* mount_setattr() syscall not supported. */
+       err = sys_mount_setattr(-EBADF, "", AT_EMPTY_PATH, NULL, 0);
+       if (err && errno == ENOSYS)
+               return 1;
+
+       /* idmapped mounts not supported */
+        err = sys_mount_setattr(-EBADF, ".", AT_EMPTY_PATH, &attr, sizeof(attr));
+        if (err && errno == E2BIG)
+               return 1;
+
+        return 0;
+}
 
 int
 main(int argc, char **argv)
@@ -256,6 +281,7 @@ main(int argc, char **argv)
        int     pflag = 0;
        int     Pflag = 0;
        int     qflag = 0;
+       int     rflag = 0;
        int     Rflag = 0;
        int     sflag = 0;
        int     uflag = 0;
@@ -264,7 +290,7 @@ main(int argc, char **argv)
        int     oflag = 0;
        char    *fs = NULL;
 
-       while ((c = getopt(argc, argv, "ActgGopPqRsuUvw")) != EOF) {
+       while ((c = getopt(argc, argv, "ActgGopPqrRsuUvw")) != EOF) {
                switch (c) {
                case 'A':
                        Aflag++;
@@ -293,6 +319,9 @@ main(int argc, char **argv)
                case 'q':
                        qflag++;
                        break;
+               case 'r':
+                       rflag++;
+                       break;
                case 'R':
                        Rflag++;
                        break;
@@ -321,10 +350,10 @@ main(int argc, char **argv)
                if (optind != argc-1)   /* need a device */
                        usage();
                fs = argv[argc-1];
-       } else if (Aflag || Rflag || wflag || sflag || oflag) {
+       } else if (Aflag || rflag || Rflag || wflag || sflag || oflag) {
                if (optind != argc)
                        usage();
-       } else 
+       } else
                usage();
 
        if (cflag)
@@ -349,6 +378,9 @@ main(int argc, char **argv)
        if (Aflag)
                return(check_aio_support());
 
+       if (rflag)
+               return(check_mount_setattr_support());
+
        if (Rflag)
                return(check_uring_support());