~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/filesystems/statmount/statmount_test.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 
  3 #define _GNU_SOURCE
  4 
  5 #include <assert.h>
  6 #include <stddef.h>
  7 #include <sched.h>
  8 #include <fcntl.h>
  9 #include <sys/param.h>
 10 #include <sys/mount.h>
 11 #include <sys/stat.h>
 12 #include <sys/statfs.h>
 13 #include <linux/stat.h>
 14 
 15 #include "statmount.h"
 16 #include "../../kselftest.h"
 17 
 18 static const char *const known_fs[] = {
 19         "9p", "adfs", "affs", "afs", "aio", "anon_inodefs", "apparmorfs",
 20         "autofs", "bcachefs", "bdev", "befs", "bfs", "binder", "binfmt_misc",
 21         "bpf", "btrfs", "btrfs_test_fs", "ceph", "cgroup", "cgroup2", "cifs",
 22         "coda", "configfs", "cpuset", "cramfs", "cxl", "dax", "debugfs",
 23         "devpts", "devtmpfs", "dmabuf", "drm", "ecryptfs", "efivarfs", "efs",
 24         "erofs", "exfat", "ext2", "ext3", "ext4", "f2fs", "functionfs",
 25         "fuse", "fuseblk", "fusectl", "gadgetfs", "gfs2", "gfs2meta", "hfs",
 26         "hfsplus", "hostfs", "hpfs", "hugetlbfs", "ibmasmfs", "iomem",
 27         "ipathfs", "iso9660", "jffs2", "jfs", "minix", "mqueue", "msdos",
 28         "nfs", "nfs4", "nfsd", "nilfs2", "nsfs", "ntfs", "ntfs3", "ocfs2",
 29         "ocfs2_dlmfs", "ocxlflash", "omfs", "openpromfs", "overlay", "pipefs",
 30         "proc", "pstore", "pvfs2", "qnx4", "qnx6", "ramfs", "reiserfs",
 31         "resctrl", "romfs", "rootfs", "rpc_pipefs", "s390_hypfs", "secretmem",
 32         "securityfs", "selinuxfs", "smackfs", "smb3", "sockfs", "spufs",
 33         "squashfs", "sysfs", "sysv", "tmpfs", "tracefs", "ubifs", "udf",
 34         "ufs", "v7", "vboxsf", "vfat", "virtiofs", "vxfs", "xenfs", "xfs",
 35         "zonefs", NULL };
 36 
 37 static struct statmount *statmount_alloc(uint64_t mnt_id, uint64_t mask, unsigned int flags)
 38 {
 39         size_t bufsize = 1 << 15;
 40         struct statmount *buf = NULL, *tmp = alloca(bufsize);
 41         int tofree = 0;
 42         int ret;
 43 
 44         for (;;) {
 45                 ret = statmount(mnt_id, 0, mask, tmp, bufsize, flags);
 46                 if (ret != -1)
 47                         break;
 48                 if (tofree)
 49                         free(tmp);
 50                 if (errno != EOVERFLOW)
 51                         return NULL;
 52                 bufsize <<= 1;
 53                 tofree = 1;
 54                 tmp = malloc(bufsize);
 55                 if (!tmp)
 56                         return NULL;
 57         }
 58         buf = malloc(tmp->size);
 59         if (buf)
 60                 memcpy(buf, tmp, tmp->size);
 61         if (tofree)
 62                 free(tmp);
 63 
 64         return buf;
 65 }
 66 
 67 static void write_file(const char *path, const char *val)
 68 {
 69         int fd = open(path, O_WRONLY);
 70         size_t len = strlen(val);
 71         int ret;
 72 
 73         if (fd == -1)
 74                 ksft_exit_fail_msg("opening %s for write: %s\n", path, strerror(errno));
 75 
 76         ret = write(fd, val, len);
 77         if (ret == -1)
 78                 ksft_exit_fail_msg("writing to %s: %s\n", path, strerror(errno));
 79         if (ret != len)
 80                 ksft_exit_fail_msg("short write to %s\n", path);
 81 
 82         ret = close(fd);
 83         if (ret == -1)
 84                 ksft_exit_fail_msg("closing %s\n", path);
 85 }
 86 
 87 static uint64_t get_mnt_id(const char *name, const char *path, uint64_t mask)
 88 {
 89         struct statx sx;
 90         int ret;
 91 
 92         ret = statx(AT_FDCWD, path, 0, mask, &sx);
 93         if (ret == -1)
 94                 ksft_exit_fail_msg("retrieving %s mount ID for %s: %s\n",
 95                                    mask & STATX_MNT_ID_UNIQUE ? "unique" : "old",
 96                                    name, strerror(errno));
 97         if (!(sx.stx_mask & mask))
 98                 ksft_exit_fail_msg("no %s mount ID available for %s\n",
 99                                    mask & STATX_MNT_ID_UNIQUE ? "unique" : "old",
100                                    name);
101 
102         return sx.stx_mnt_id;
103 }
104 
105 
106 static char root_mntpoint[] = "/tmp/statmount_test_root.XXXXXX";
107 static int orig_root;
108 static uint64_t root_id, parent_id;
109 static uint32_t old_root_id, old_parent_id;
110 static FILE *f_mountinfo;
111 
112 static void cleanup_namespace(void)
113 {
114         int ret;
115 
116         ret = fchdir(orig_root);
117         if (ret == -1)
118                 ksft_perror("fchdir to original root");
119 
120         ret = chroot(".");
121         if (ret == -1)
122                 ksft_perror("chroot to original root");
123 
124         umount2(root_mntpoint, MNT_DETACH);
125         rmdir(root_mntpoint);
126 }
127 
128 static void setup_namespace(void)
129 {
130         int ret;
131         char buf[32];
132         uid_t uid = getuid();
133         gid_t gid = getgid();
134 
135         ret = unshare(CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWPID);
136         if (ret == -1)
137                 ksft_exit_fail_msg("unsharing mountns and userns: %s\n",
138                                    strerror(errno));
139 
140         sprintf(buf, "0 %d 1", uid);
141         write_file("/proc/self/uid_map", buf);
142         write_file("/proc/self/setgroups", "deny");
143         sprintf(buf, "0 %d 1", gid);
144         write_file("/proc/self/gid_map", buf);
145 
146         f_mountinfo = fopen("/proc/self/mountinfo", "re");
147         if (!f_mountinfo)
148                 ksft_exit_fail_msg("failed to open mountinfo: %s\n",
149                                    strerror(errno));
150 
151         ret = mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL);
152         if (ret == -1)
153                 ksft_exit_fail_msg("making mount tree private: %s\n",
154                                    strerror(errno));
155 
156         if (!mkdtemp(root_mntpoint))
157                 ksft_exit_fail_msg("creating temporary directory %s: %s\n",
158                                    root_mntpoint, strerror(errno));
159 
160         old_parent_id = get_mnt_id("parent", root_mntpoint, STATX_MNT_ID);
161         parent_id = get_mnt_id("parent", root_mntpoint, STATX_MNT_ID_UNIQUE);
162 
163         orig_root = open("/", O_PATH);
164         if (orig_root == -1)
165                 ksft_exit_fail_msg("opening root directory: %s",
166                                    strerror(errno));
167 
168         atexit(cleanup_namespace);
169 
170         ret = mount(root_mntpoint, root_mntpoint, NULL, MS_BIND, NULL);
171         if (ret == -1)
172                 ksft_exit_fail_msg("mounting temp root %s: %s\n",
173                                    root_mntpoint, strerror(errno));
174 
175         ret = chroot(root_mntpoint);
176         if (ret == -1)
177                 ksft_exit_fail_msg("chroot to temp root %s: %s\n",
178                                    root_mntpoint, strerror(errno));
179 
180         ret = chdir("/");
181         if (ret == -1)
182                 ksft_exit_fail_msg("chdir to root: %s\n", strerror(errno));
183 
184         old_root_id = get_mnt_id("root", "/", STATX_MNT_ID);
185         root_id = get_mnt_id("root", "/", STATX_MNT_ID_UNIQUE);
186 }
187 
188 static int setup_mount_tree(int log2_num)
189 {
190         int ret, i;
191 
192         ret = mount("", "/", NULL, MS_REC|MS_SHARED, NULL);
193         if (ret == -1) {
194                 ksft_test_result_fail("making mount tree shared: %s\n",
195                                    strerror(errno));
196                 return -1;
197         }
198 
199         for (i = 0; i < log2_num; i++) {
200                 ret = mount("/", "/", NULL, MS_BIND, NULL);
201                 if (ret == -1) {
202                         ksft_test_result_fail("mounting submount %s: %s\n",
203                                               root_mntpoint, strerror(errno));
204                         return -1;
205                 }
206         }
207         return 0;
208 }
209 
210 static void test_listmount_empty_root(void)
211 {
212         ssize_t res;
213         const unsigned int size = 32;
214         uint64_t list[size];
215 
216         res = listmount(LSMT_ROOT, 0, 0, list, size, 0);
217         if (res == -1) {
218                 ksft_test_result_fail("listmount: %s\n", strerror(errno));
219                 return;
220         }
221         if (res != 1) {
222                 ksft_test_result_fail("listmount result is %zi != 1\n", res);
223                 return;
224         }
225 
226         if (list[0] != root_id) {
227                 ksft_test_result_fail("listmount ID doesn't match 0x%llx != 0x%llx\n",
228                                       (unsigned long long) list[0],
229                                       (unsigned long long) root_id);
230                 return;
231         }
232 
233         ksft_test_result_pass("listmount empty root\n");
234 }
235 
236 static void test_statmount_zero_mask(void)
237 {
238         struct statmount sm;
239         int ret;
240 
241         ret = statmount(root_id, 0, 0, &sm, sizeof(sm), 0);
242         if (ret == -1) {
243                 ksft_test_result_fail("statmount zero mask: %s\n",
244                                       strerror(errno));
245                 return;
246         }
247         if (sm.size != sizeof(sm)) {
248                 ksft_test_result_fail("unexpected size: %u != %u\n",
249                                       sm.size, (uint32_t) sizeof(sm));
250                 return;
251         }
252         if (sm.mask != 0) {
253                 ksft_test_result_fail("unexpected mask: 0x%llx != 0x0\n",
254                                       (unsigned long long) sm.mask);
255                 return;
256         }
257 
258         ksft_test_result_pass("statmount zero mask\n");
259 }
260 
261 static void test_statmount_mnt_basic(void)
262 {
263         struct statmount sm;
264         int ret;
265         uint64_t mask = STATMOUNT_MNT_BASIC;
266 
267         ret = statmount(root_id, 0, mask, &sm, sizeof(sm), 0);
268         if (ret == -1) {
269                 ksft_test_result_fail("statmount mnt basic: %s\n",
270                                       strerror(errno));
271                 return;
272         }
273         if (sm.size != sizeof(sm)) {
274                 ksft_test_result_fail("unexpected size: %u != %u\n",
275                                       sm.size, (uint32_t) sizeof(sm));
276                 return;
277         }
278         if (sm.mask != mask) {
279                 ksft_test_result_skip("statmount mnt basic unavailable\n");
280                 return;
281         }
282 
283         if (sm.mnt_id != root_id) {
284                 ksft_test_result_fail("unexpected root ID: 0x%llx != 0x%llx\n",
285                                       (unsigned long long) sm.mnt_id,
286                                       (unsigned long long) root_id);
287                 return;
288         }
289 
290         if (sm.mnt_id_old != old_root_id) {
291                 ksft_test_result_fail("unexpected old root ID: %u != %u\n",
292                                       sm.mnt_id_old, old_root_id);
293                 return;
294         }
295 
296         if (sm.mnt_parent_id != parent_id) {
297                 ksft_test_result_fail("unexpected parent ID: 0x%llx != 0x%llx\n",
298                                       (unsigned long long) sm.mnt_parent_id,
299                                       (unsigned long long) parent_id);
300                 return;
301         }
302 
303         if (sm.mnt_parent_id_old != old_parent_id) {
304                 ksft_test_result_fail("unexpected old parent ID: %u != %u\n",
305                                       sm.mnt_parent_id_old, old_parent_id);
306                 return;
307         }
308 
309         if (sm.mnt_propagation != MS_PRIVATE) {
310                 ksft_test_result_fail("unexpected propagation: 0x%llx\n",
311                                       (unsigned long long) sm.mnt_propagation);
312                 return;
313         }
314 
315         ksft_test_result_pass("statmount mnt basic\n");
316 }
317 
318 
319 static void test_statmount_sb_basic(void)
320 {
321         struct statmount sm;
322         int ret;
323         uint64_t mask = STATMOUNT_SB_BASIC;
324         struct statx sx;
325         struct statfs sf;
326 
327         ret = statmount(root_id, 0, mask, &sm, sizeof(sm), 0);
328         if (ret == -1) {
329                 ksft_test_result_fail("statmount sb basic: %s\n",
330                                       strerror(errno));
331                 return;
332         }
333         if (sm.size != sizeof(sm)) {
334                 ksft_test_result_fail("unexpected size: %u != %u\n",
335                                       sm.size, (uint32_t) sizeof(sm));
336                 return;
337         }
338         if (sm.mask != mask) {
339                 ksft_test_result_skip("statmount sb basic unavailable\n");
340                 return;
341         }
342 
343         ret = statx(AT_FDCWD, "/", 0, 0, &sx);
344         if (ret == -1) {
345                 ksft_test_result_fail("stat root failed: %s\n",
346                                       strerror(errno));
347                 return;
348         }
349 
350         if (sm.sb_dev_major != sx.stx_dev_major ||
351             sm.sb_dev_minor != sx.stx_dev_minor) {
352                 ksft_test_result_fail("unexpected sb dev %u:%u != %u:%u\n",
353                                       sm.sb_dev_major, sm.sb_dev_minor,
354                                       sx.stx_dev_major, sx.stx_dev_minor);
355                 return;
356         }
357 
358         ret = statfs("/", &sf);
359         if (ret == -1) {
360                 ksft_test_result_fail("statfs root failed: %s\n",
361                                       strerror(errno));
362                 return;
363         }
364 
365         if (sm.sb_magic != sf.f_type) {
366                 ksft_test_result_fail("unexpected sb magic: 0x%llx != 0x%lx\n",
367                                       (unsigned long long) sm.sb_magic,
368                                       sf.f_type);
369                 return;
370         }
371 
372         ksft_test_result_pass("statmount sb basic\n");
373 }
374 
375 static void test_statmount_mnt_point(void)
376 {
377         struct statmount *sm;
378 
379         sm = statmount_alloc(root_id, STATMOUNT_MNT_POINT, 0);
380         if (!sm) {
381                 ksft_test_result_fail("statmount mount point: %s\n",
382                                       strerror(errno));
383                 return;
384         }
385 
386         if (strcmp(sm->str + sm->mnt_point, "/") != 0) {
387                 ksft_test_result_fail("unexpected mount point: '%s' != '/'\n",
388                                       sm->str + sm->mnt_point);
389                 goto out;
390         }
391         ksft_test_result_pass("statmount mount point\n");
392 out:
393         free(sm);
394 }
395 
396 static void test_statmount_mnt_root(void)
397 {
398         struct statmount *sm;
399         const char *mnt_root, *last_dir, *last_root;
400 
401         last_dir = strrchr(root_mntpoint, '/');
402         assert(last_dir);
403         last_dir++;
404 
405         sm = statmount_alloc(root_id, STATMOUNT_MNT_ROOT, 0);
406         if (!sm) {
407                 ksft_test_result_fail("statmount mount root: %s\n",
408                                       strerror(errno));
409                 return;
410         }
411         mnt_root = sm->str + sm->mnt_root;
412         last_root = strrchr(mnt_root, '/');
413         if (last_root)
414                 last_root++;
415         else
416                 last_root = mnt_root;
417 
418         if (strcmp(last_dir, last_root) != 0) {
419                 ksft_test_result_fail("unexpected mount root last component: '%s' != '%s'\n",
420                                       last_root, last_dir);
421                 goto out;
422         }
423         ksft_test_result_pass("statmount mount root\n");
424 out:
425         free(sm);
426 }
427 
428 static void test_statmount_fs_type(void)
429 {
430         struct statmount *sm;
431         const char *fs_type;
432         const char *const *s;
433 
434         sm = statmount_alloc(root_id, STATMOUNT_FS_TYPE, 0);
435         if (!sm) {
436                 ksft_test_result_fail("statmount fs type: %s\n",
437                                       strerror(errno));
438                 return;
439         }
440         fs_type = sm->str + sm->fs_type;
441         for (s = known_fs; s != NULL; s++) {
442                 if (strcmp(fs_type, *s) == 0)
443                         break;
444         }
445         if (!s)
446                 ksft_print_msg("unknown filesystem type: %s\n", fs_type);
447 
448         ksft_test_result_pass("statmount fs type\n");
449         free(sm);
450 }
451 
452 static void test_statmount_mnt_opts(void)
453 {
454         struct statmount *sm;
455         const char *statmount_opts;
456         char *line = NULL;
457         size_t len = 0;
458 
459         sm = statmount_alloc(root_id, STATMOUNT_MNT_BASIC | STATMOUNT_MNT_OPTS,
460                              0);
461         if (!sm) {
462                 ksft_test_result_fail("statmount mnt opts: %s\n",
463                                       strerror(errno));
464                 return;
465         }
466 
467         while (getline(&line, &len, f_mountinfo) != -1) {
468                 int i;
469                 char *p, *p2;
470                 unsigned int old_mnt_id;
471 
472                 old_mnt_id = atoi(line);
473                 if (old_mnt_id != sm->mnt_id_old)
474                         continue;
475 
476                 for (p = line, i = 0; p && i < 5; i++)
477                         p = strchr(p + 1, ' ');
478                 if (!p)
479                         continue;
480 
481                 p2 = strchr(p + 1, ' ');
482                 if (!p2)
483                         continue;
484                 *p2 = '\0';
485                 p = strchr(p2 + 1, '-');
486                 if (!p)
487                         continue;
488                 for (p++, i = 0; p && i < 2; i++)
489                         p = strchr(p + 1, ' ');
490                 if (!p)
491                         continue;
492                 p++;
493 
494                 /* skip generic superblock options */
495                 if (strncmp(p, "ro", 2) == 0)
496                         p += 2;
497                 else if (strncmp(p, "rw", 2) == 0)
498                         p += 2;
499                 if (*p == ',')
500                         p++;
501                 if (strncmp(p, "sync", 4) == 0)
502                         p += 4;
503                 if (*p == ',')
504                         p++;
505                 if (strncmp(p, "dirsync", 7) == 0)
506                         p += 7;
507                 if (*p == ',')
508                         p++;
509                 if (strncmp(p, "lazytime", 8) == 0)
510                         p += 8;
511                 if (*p == ',')
512                         p++;
513                 p2 = strrchr(p, '\n');
514                 if (p2)
515                         *p2 = '\0';
516 
517                 statmount_opts = sm->str + sm->mnt_opts;
518                 if (strcmp(statmount_opts, p) != 0)
519                         ksft_test_result_fail(
520                                 "unexpected mount options: '%s' != '%s'\n",
521                                 statmount_opts, p);
522                 else
523                         ksft_test_result_pass("statmount mount options\n");
524                 free(sm);
525                 free(line);
526                 return;
527         }
528 
529         ksft_test_result_fail("didnt't find mount entry\n");
530         free(sm);
531         free(line);
532 }
533 
534 static void test_statmount_string(uint64_t mask, size_t off, const char *name)
535 {
536         struct statmount *sm;
537         size_t len, shortsize, exactsize;
538         uint32_t start, i;
539         int ret;
540 
541         sm = statmount_alloc(root_id, mask, 0);
542         if (!sm) {
543                 ksft_test_result_fail("statmount %s: %s\n", name,
544                                       strerror(errno));
545                 goto out;
546         }
547         if (sm->size < sizeof(*sm)) {
548                 ksft_test_result_fail("unexpected size: %u < %u\n",
549                                       sm->size, (uint32_t) sizeof(*sm));
550                 goto out;
551         }
552         if (sm->mask != mask) {
553                 ksft_test_result_skip("statmount %s unavailable\n", name);
554                 goto out;
555         }
556         len = sm->size - sizeof(*sm);
557         start = ((uint32_t *) sm)[off];
558 
559         for (i = start;; i++) {
560                 if (i >= len) {
561                         ksft_test_result_fail("string out of bounds\n");
562                         goto out;
563                 }
564                 if (!sm->str[i])
565                         break;
566         }
567         exactsize = sm->size;
568         shortsize = sizeof(*sm) + i;
569 
570         ret = statmount(root_id, 0, mask, sm, exactsize, 0);
571         if (ret == -1) {
572                 ksft_test_result_fail("statmount exact size: %s\n",
573                                       strerror(errno));
574                 goto out;
575         }
576         errno = 0;
577         ret = statmount(root_id, 0, mask, sm, shortsize, 0);
578         if (ret != -1 || errno != EOVERFLOW) {
579                 ksft_test_result_fail("should have failed with EOVERFLOW: %s\n",
580                                       strerror(errno));
581                 goto out;
582         }
583 
584         ksft_test_result_pass("statmount string %s\n", name);
585 out:
586         free(sm);
587 }
588 
589 static void test_listmount_tree(void)
590 {
591         ssize_t res;
592         const unsigned int log2_num = 4;
593         const unsigned int step = 3;
594         const unsigned int size = (1 << log2_num) + step + 1;
595         size_t num, expect = 1 << log2_num;
596         uint64_t list[size];
597         uint64_t list2[size];
598         size_t i;
599 
600 
601         res = setup_mount_tree(log2_num);
602         if (res == -1)
603                 return;
604 
605         num = res = listmount(LSMT_ROOT, 0, 0, list, size, 0);
606         if (res == -1) {
607                 ksft_test_result_fail("listmount: %s\n", strerror(errno));
608                 return;
609         }
610         if (num != expect) {
611                 ksft_test_result_fail("listmount result is %zi != %zi\n",
612                                       res, expect);
613                 return;
614         }
615 
616         for (i = 0; i < size - step;) {
617                 res = listmount(LSMT_ROOT, 0, i ? list2[i - 1] : 0, list2 + i, step, 0);
618                 if (res == -1)
619                         ksft_test_result_fail("short listmount: %s\n",
620                                               strerror(errno));
621                 i += res;
622                 if (res < step)
623                         break;
624         }
625         if (i != num) {
626                 ksft_test_result_fail("different number of entries: %zu != %zu\n",
627                                       i, num);
628                 return;
629         }
630         for (i = 0; i < num; i++) {
631                 if (list2[i] != list[i]) {
632                         ksft_test_result_fail("different value for entry %zu: 0x%llx != 0x%llx\n",
633                                               i,
634                                               (unsigned long long) list2[i],
635                                               (unsigned long long) list[i]);
636                 }
637         }
638 
639         ksft_test_result_pass("listmount tree\n");
640 }
641 
642 #define str_off(memb) (offsetof(struct statmount, memb) / sizeof(uint32_t))
643 
644 int main(void)
645 {
646         int ret;
647         uint64_t all_mask = STATMOUNT_SB_BASIC | STATMOUNT_MNT_BASIC |
648                 STATMOUNT_PROPAGATE_FROM | STATMOUNT_MNT_ROOT |
649                 STATMOUNT_MNT_POINT | STATMOUNT_FS_TYPE | STATMOUNT_MNT_NS_ID;
650 
651         ksft_print_header();
652 
653         ret = statmount(0, 0, 0, NULL, 0, 0);
654         assert(ret == -1);
655         if (errno == ENOSYS)
656                 ksft_exit_skip("statmount() syscall not supported\n");
657 
658         setup_namespace();
659 
660         ksft_set_plan(15);
661         test_listmount_empty_root();
662         test_statmount_zero_mask();
663         test_statmount_mnt_basic();
664         test_statmount_sb_basic();
665         test_statmount_mnt_root();
666         test_statmount_mnt_point();
667         test_statmount_fs_type();
668         test_statmount_mnt_opts();
669         test_statmount_string(STATMOUNT_MNT_ROOT, str_off(mnt_root), "mount root");
670         test_statmount_string(STATMOUNT_MNT_POINT, str_off(mnt_point), "mount point");
671         test_statmount_string(STATMOUNT_FS_TYPE, str_off(fs_type), "fs type");
672         test_statmount_string(all_mask, str_off(mnt_root), "mount root & all");
673         test_statmount_string(all_mask, str_off(mnt_point), "mount point & all");
674         test_statmount_string(all_mask, str_off(fs_type), "fs type & all");
675 
676         test_listmount_tree();
677 
678 
679         if (ksft_get_fail_cnt() + ksft_get_error_cnt() > 0)
680                 ksft_exit_fail();
681         else
682                 ksft_exit_pass();
683 }
684 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php