Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:30

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (c) 2016 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include <tmacros.h>
0033 #include <fstest.h>
0034 
0035 #include <sys/stat.h>
0036 #include <string.h>
0037 #include <fcntl.h>
0038 #include <unistd.h>
0039 #include <errno.h>
0040 
0041 #include <rtems/jffs2.h>
0042 
0043 const char rtems_test_name[] = "FSJFFS2GC 1";
0044 const RTEMS_TEST_STATE rtems_test_state = TEST_STATE;
0045 
0046 static const rtems_jffs2_info info_initial = {
0047   .flash_size = 131072,
0048   .flash_blocks = 8,
0049   .flash_block_size = 16384,
0050   .used_size = 96,
0051   .dirty_size = 0,
0052   .wasted_size = 0,
0053   .free_size = 130976,
0054   .bad_size = 0,
0055   .clean_blocks = 0,
0056   .dirty_blocks = 0,
0057   .erasable_blocks = 0,
0058   .free_blocks = 8,
0059   .bad_blocks = 0
0060 };
0061 
0062 static const rtems_jffs2_info info_big_created = {
0063   .flash_size = 131072,
0064   .flash_blocks = 8,
0065   .flash_block_size = 16384,
0066   .used_size = 22292,
0067   .dirty_size = 0,
0068   .wasted_size = 164,
0069   .free_size = 108616,
0070   .bad_size = 0,
0071   .clean_blocks = 1,
0072   .dirty_blocks = 0,
0073   .erasable_blocks = 0,
0074   .free_blocks = 7,
0075   .bad_blocks = 0
0076 };
0077 
0078 static const rtems_jffs2_info info_big_removed = {
0079   .flash_size = 131072,
0080   .flash_blocks = 8,
0081   .flash_block_size = 16384,
0082   .used_size = 72,
0083   .dirty_size = 16384,
0084   .wasted_size = 6000,
0085   .free_size = 108616,
0086   .bad_size = 0,
0087   .clean_blocks = 0,
0088   .dirty_blocks = 0,
0089   .erasable_blocks = 1,
0090   .free_blocks = 7,
0091   .bad_blocks = 0
0092 };
0093 
0094 static const rtems_jffs2_info info_more_files_created = {
0095   .flash_size = 131072,
0096   .flash_blocks = 8,
0097   .flash_block_size = 16384,
0098   .used_size = 54896,
0099   .dirty_size = 23336,
0100   .wasted_size = 36,
0101   .free_size = 52804,
0102   .bad_size = 0,
0103   .clean_blocks = 2,
0104   .dirty_blocks = 1,
0105   .erasable_blocks = 1,
0106   .free_blocks = 4,
0107   .bad_blocks = 0
0108 };
0109 
0110 static const rtems_jffs2_info info_some_files_removed = {
0111   .flash_size = 131072,
0112   .flash_blocks = 8,
0113   .flash_block_size = 16384,
0114   .used_size = 23528,
0115   .dirty_size = 47372,
0116   .wasted_size = 7368,
0117   .free_size = 52804,
0118   .bad_size = 0,
0119   .clean_blocks = 0,
0120   .dirty_blocks = 3,
0121   .erasable_blocks = 1,
0122   .free_blocks = 4,
0123   .bad_blocks = 0
0124 };
0125 
0126 static const rtems_jffs2_info info_after_first_gc = {
0127   .flash_size = 131072,
0128   .flash_blocks = 8,
0129   .flash_block_size = 16384,
0130   .used_size = 23540,
0131   .dirty_size = 30988,
0132   .wasted_size = 7368,
0133   .free_size = 69176,
0134   .bad_size = 0,
0135   .clean_blocks = 0,
0136   .dirty_blocks = 3,
0137   .erasable_blocks = 0,
0138   .free_blocks = 5,
0139   .bad_blocks = 0
0140 };
0141 
0142 static const rtems_jffs2_info info_after_excessive_gc = {
0143   .flash_size = 131072,
0144   .flash_blocks = 8,
0145   .flash_block_size = 16384,
0146   .used_size = 7224,
0147   .dirty_size = 0,
0148   .wasted_size = 12,
0149   .free_size = 123836,
0150   .bad_size = 0,
0151   .clean_blocks = 0,
0152   .dirty_blocks = 0,
0153   .erasable_blocks = 0,
0154   .free_blocks = 8,
0155   .bad_blocks = 0
0156 };
0157 
0158 static char big[] = "big";
0159 
0160 static const char * const more[] = {
0161   "1",
0162   "2",
0163   "3",
0164   "4",
0165   "5",
0166   "6",
0167   "7"
0168 };
0169 
0170 #define ASSERT_INFO(a, b) do { \
0171   rv = ioctl(fd, RTEMS_JFFS2_GET_INFO, &info); \
0172   rtems_test_assert(rv == 0); \
0173   rtems_test_assert(memcmp(a, b, sizeof(*a)) == 0); \
0174 } while (0)
0175 
0176 static const mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
0177 
0178 static char keg[523];
0179 
0180 static uint32_t simple_random(uint32_t v)
0181 {
0182   v *= 1664525;
0183   v += 1013904223;
0184 
0185   return v;
0186 }
0187 
0188 static void init_keg(void)
0189 {
0190   size_t i;
0191   uint32_t v;
0192 
0193   v = 123;
0194   for (i = 0; i < sizeof(keg); ++i) {
0195     v = simple_random(v);
0196     keg[i] = (uint8_t) (v >> 23);
0197   }
0198 }
0199 
0200 static void write_kegs(int fd, int kegs)
0201 {
0202   int i;
0203 
0204   for (i = 0; i < kegs; ++i) {
0205     ssize_t n;
0206 
0207     n = write(fd, &keg[0], sizeof(keg));
0208     rtems_test_assert(n == (ssize_t) sizeof(keg));
0209   }
0210 }
0211 
0212 static void create_big_file(void)
0213 {
0214   int fd;
0215   int rv;
0216 
0217   fd = open(&big[0], O_WRONLY | O_TRUNC | O_CREAT, mode);
0218   rtems_test_assert(fd >= 0);
0219 
0220   write_kegs(fd, 37);
0221 
0222   rv = close(fd);
0223   rtems_test_assert(rv == 0);
0224 }
0225 
0226 static void remove_big_file(void)
0227 {
0228   int rv;
0229 
0230   rv = unlink(&big[0]);
0231   rtems_test_assert(rv == 0);
0232 }
0233 
0234 static void create_more_files(void)
0235 {
0236   int fds[RTEMS_ARRAY_SIZE(more)];
0237   int rv;
0238   size_t i;
0239   int j;
0240 
0241   for (i = 0; i < RTEMS_ARRAY_SIZE(fds); ++i) {
0242     fds[i] = open(more[i], O_WRONLY | O_TRUNC | O_CREAT, mode);
0243     rtems_test_assert(fds[i] >= 0);
0244   }
0245 
0246   for (j = 0; j < 13; ++j) {
0247     for (i = 0; i < RTEMS_ARRAY_SIZE(fds); ++i) {
0248       write_kegs(fds[i], 1);
0249     }
0250   }
0251 
0252   for (i = 0; i < RTEMS_ARRAY_SIZE(fds); ++i) {
0253     rv = close(fds[i]);
0254     rtems_test_assert(rv == 0);
0255   }
0256 }
0257 
0258 static void remove_some_files(void)
0259 {
0260   size_t i;
0261 
0262   for (i = 0; i < RTEMS_ARRAY_SIZE(more); i += 2) {
0263     int rv;
0264 
0265     rv = unlink(more[i]);
0266     rtems_test_assert(rv == 0);
0267   }
0268 }
0269 
0270 void test(void)
0271 {
0272   int fd;
0273   int rv;
0274   int counter;
0275   rtems_jffs2_info info;
0276 
0277   init_keg();
0278 
0279   /*
0280    * Ensure that jiffies != 0, to use most likely path in
0281    * jffs2_mark_node_obsolete().
0282    */
0283   while (rtems_clock_get_ticks_since_boot() == 0) {
0284     /* Wait */
0285   }
0286 
0287   fd = open("/", O_RDONLY);
0288   rtems_test_assert(fd >= 0);
0289 
0290   ASSERT_INFO(&info, &info_initial);
0291 
0292   create_big_file();
0293   ASSERT_INFO(&info, &info_big_created);
0294 
0295   remove_big_file();
0296   ASSERT_INFO(&info, &info_big_removed);
0297 
0298   create_more_files();
0299   ASSERT_INFO(&info, &info_more_files_created);
0300 
0301   remove_some_files();
0302   ASSERT_INFO(&info, &info_some_files_removed);
0303 
0304   rv = ioctl(fd, RTEMS_JFFS2_ON_DEMAND_GARBAGE_COLLECTION);
0305   rtems_test_assert(rv == 0);
0306   ASSERT_INFO(&info, &info_after_first_gc);
0307 
0308   rv = ioctl(fd, RTEMS_JFFS2_ON_DEMAND_GARBAGE_COLLECTION);
0309   rtems_test_assert(rv == 0);
0310   ASSERT_INFO(&info, &info_after_first_gc);
0311 
0312   counter = 0;
0313 
0314   while (true) {
0315     errno = ENXIO;
0316     rv = ioctl(fd, RTEMS_JFFS2_FORCE_GARBAGE_COLLECTION);
0317     if (rv == -1) {
0318       rtems_test_assert(errno == EIO);
0319       break;
0320     }
0321 
0322     ++counter;
0323     rtems_test_assert(rv == 0);
0324   }
0325 
0326   rtems_test_assert(counter == 19);
0327 
0328   rv = ioctl(fd, RTEMS_JFFS2_GET_INFO, &info);
0329   rtems_test_assert(rv == 0);
0330   ASSERT_INFO(&info, &info_after_excessive_gc);
0331 
0332   rv = close(fd);
0333   rtems_test_assert(rv == 0);
0334 }