| // Copyright 2017 The Fuchsia Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include <errno.h> | 
 | #include <fcntl.h> | 
 | #include <limits.h> | 
 | #include <stdint.h> | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 | #include <sys/stat.h> | 
 | #include <unistd.h> | 
 |  | 
 | #include <zircon/compiler.h> | 
 | #include <zircon/syscalls.h> | 
 | #include <fbl/new.h> | 
 | #include <fbl/unique_ptr.h> | 
 | #include <unittest/unittest.h> | 
 |  | 
 | #include "filesystems.h" | 
 | #include "misc.h" | 
 |  | 
 | bool test_use_all_inodes(void) { | 
 |     BEGIN_TEST; | 
 |     ASSERT_TRUE(test_info->supports_resize); | 
 |  | 
 |     // Create 100,000 inodes. | 
 |     // We expect that this will force enough inodes to cause the | 
 |     // filesystem structures to resize partway through. | 
 |     constexpr size_t kFilesPerDirectory = 100; | 
 |     constexpr size_t kDirectoryCount = 1000; | 
 |     for (size_t d = 0; d < kDirectoryCount; d++) { | 
 |         if (d % 100 == 0) { | 
 |             printf("Creating directory (containing 100 files): %lu\n", d); | 
 |         } | 
 |         char dname[128]; | 
 |         snprintf(dname, sizeof(dname), "::%lu", d); | 
 |         ASSERT_EQ(mkdir(dname, 0666), 0); | 
 |         for (size_t f = 0; f < kFilesPerDirectory; f++) { | 
 |             char fname[128]; | 
 |             snprintf(fname, sizeof(fname), "::%lu/%lu", d, f); | 
 |             int fd = open(fname, O_CREAT | O_RDWR | O_EXCL); | 
 |             ASSERT_GT(fd, 0); | 
 |             ASSERT_EQ(close(fd), 0); | 
 |         } | 
 |     } | 
 |  | 
 |     printf("Unmounting, Re-mounting, verifying...\n"); | 
 |     ASSERT_TRUE(check_remount(), "Could not remount filesystem"); | 
 |  | 
 |     for (size_t d = 0; d < kDirectoryCount; d++) { | 
 |         if (d % 100 == 0) { | 
 |             printf("Deleting directory (containing 100 files): %lu\n", d); | 
 |         } | 
 |         for (size_t f = 0; f < kFilesPerDirectory; f++) { | 
 |             char fname[128]; | 
 |             snprintf(fname, sizeof(fname), "::%lu/%lu", d, f); | 
 |             ASSERT_EQ(unlink(fname), 0); | 
 |         } | 
 |         char dname[128]; | 
 |         snprintf(dname, sizeof(dname), "::%lu", d); | 
 |         ASSERT_EQ(rmdir(dname), 0); | 
 |     } | 
 |  | 
 |     END_TEST; | 
 | } | 
 |  | 
 | bool test_use_all_data(void) { | 
 |     BEGIN_TEST; | 
 |     ASSERT_TRUE(test_info->supports_resize); | 
 |  | 
 |     constexpr size_t kBufSize = (1 << 20); | 
 |     constexpr size_t kFileBufCount = (1 << 5); | 
 |     constexpr size_t kFileCount = (1 << 4); | 
 |  | 
 |     fbl::AllocChecker ac; | 
 |     fbl::unique_ptr<uint8_t[]> buf(new (&ac) uint8_t[kBufSize]); | 
 |     ASSERT_TRUE(ac.check()); | 
 |     memset(buf.get(), 0, kBufSize); | 
 |  | 
 |     for (size_t f = 0; f < kFileCount; f++) { | 
 |         printf("Creating 32MB file #%lu\n", f); | 
 |         char fname[128]; | 
 |         snprintf(fname, sizeof(fname), "::%lu", f); | 
 |         int fd = open(fname, O_CREAT | O_RDWR | O_EXCL); | 
 |         ASSERT_GT(fd, 0); | 
 |         for (size_t i = 0; i < kFileBufCount; i++) { | 
 |             ASSERT_EQ(write(fd, buf.get(), kBufSize), kBufSize); | 
 |         } | 
 |         ASSERT_EQ(close(fd), 0); | 
 |     } | 
 |  | 
 |     ASSERT_TRUE(check_remount(), "Could not remount filesystem"); | 
 |  | 
 |     for (size_t f = 0; f < kFileCount; f++) { | 
 |         char fname[128]; | 
 |         snprintf(fname, sizeof(fname), "::%lu", f); | 
 |         ASSERT_EQ(unlink(fname), 0); | 
 |     } | 
 |  | 
 |     END_TEST; | 
 | } | 
 |  | 
 | RUN_FOR_ALL_FILESYSTEMS_TYPE(fs_resize_tests, FS_TEST_FVM, | 
 |     RUN_TEST_LARGE(test_use_all_inodes) | 
 |     RUN_TEST_LARGE(test_use_all_data) | 
 | ) |