1 /* 2 * Copyright (c) 2014 Fujitsu Ltd. 3 * Author: Xiaoguang Wang <wangxg.fnst (at) cn.fujitsu.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 */ 17 18 #include <string.h> 19 #include <errno.h> 20 #include <sys/types.h> 21 #include <sys/stat.h> 22 #include <unistd.h> 23 24 #include "test.h" 25 #include "usctest.h" 26 #include "safe_macros.h" 27 28 #define MAX_SANE_HARD_LINKS 65535 29 30 /* 31 * filesystems whose subdir limit is less than MAX_SANE_HARD_LINKS 32 * XXX: we cannot filter ext4 out, because ext2/ext3/ext4 have the 33 * same magic number 34 */ 35 const long subdir_limit_whitelist[] = { 36 TST_EXT2_OLD_MAGIC, TST_EXT234_MAGIC, TST_MINIX_MAGIC, 37 TST_MINIX_MAGIC2, TST_MINIX2_MAGIC, TST_MINIX2_MAGIC2, 38 TST_MINIX3_MAGIC, TST_UDF_MAGIC, TST_SYSV2_MAGIC, 39 TST_SYSV4_MAGIC, TST_UFS_MAGIC, TST_UFS2_MAGIC, 40 TST_F2FS_MAGIC, TST_NILFS_MAGIC, TST_EXOFS_MAGIC 41 }; 42 43 int tst_fs_fill_hardlinks_(void (*cleanup) (void), const char *dir) 44 { 45 unsigned int i, j; 46 char base_filename[PATH_MAX], link_filename[PATH_MAX]; 47 struct stat s; 48 49 if (stat(dir, &s) == -1 && errno == ENOENT) 50 SAFE_MKDIR(cleanup, dir, 0744); 51 52 SAFE_STAT(cleanup, dir, &s); 53 if (!S_ISDIR(s.st_mode)) 54 tst_brkm(TBROK, cleanup, "%s is not directory", dir); 55 56 sprintf(base_filename, "%s/testfile0", dir); 57 SAFE_TOUCH(cleanup, base_filename, 0644, NULL); 58 59 for (i = 1; i < MAX_SANE_HARD_LINKS; i++) { 60 sprintf(link_filename, "%s/testfile%d", dir, i); 61 62 if (link(base_filename, link_filename) == 0) 63 continue; 64 65 switch (errno) { 66 case EMLINK: 67 SAFE_STAT(cleanup, base_filename, &s); 68 if (s.st_nlink != i) { 69 tst_brkm(TBROK, cleanup, "wrong number of " 70 "hard links for %s have %i, should be" 71 " %d", base_filename, 72 (int)s.st_nlink, i); 73 } else { 74 tst_resm(TINFO, "the maximum number of hard " 75 "links to %s is hit: %d", 76 base_filename, (int)s.st_nlink); 77 return s.st_nlink; 78 } 79 case ENOSPC: 80 case EDQUOT: 81 tst_resm(TINFO | TERRNO, "link(%s, %s) failed", 82 base_filename, link_filename); 83 goto max_hardlinks_cleanup; 84 default: 85 tst_brkm(TBROK, cleanup, "link(%s, %s) failed " 86 "unexpectedly: %s", base_filename, 87 link_filename, strerror(errno)); 88 } 89 } 90 91 tst_resm(TINFO, "Failed reach the hardlinks limit"); 92 93 max_hardlinks_cleanup: 94 for (j = 0; j < i; j++) { 95 sprintf(link_filename, "%s/testfile%d", dir, j); 96 SAFE_UNLINK(cleanup, link_filename); 97 } 98 99 return 0; 100 } 101 102 int tst_fs_fill_subdirs_(void (*cleanup) (void), const char *dir) 103 { 104 unsigned int i, j, whitelist_size; 105 char dirname[PATH_MAX]; 106 struct stat s; 107 long fs_type; 108 109 if (stat(dir, &s) == -1 && errno == ENOENT) 110 SAFE_MKDIR(cleanup, dir, 0744); 111 112 SAFE_STAT(cleanup, dir, &s); 113 if (!S_ISDIR(s.st_mode)) 114 tst_brkm(TBROK, cleanup, "%s is not directory", dir); 115 116 /* for current kernel, subdir limit is not availiable for all fs */ 117 fs_type = tst_fs_type(cleanup, dir); 118 119 whitelist_size = ARRAY_SIZE(subdir_limit_whitelist); 120 for (i = 0; i < whitelist_size; i++) { 121 if (fs_type == subdir_limit_whitelist[i]) 122 break; 123 } 124 if (i == whitelist_size) { 125 tst_resm(TINFO, "subdir limit is not availiable for " 126 "%s filesystem", tst_fs_type_name(fs_type)); 127 return 0; 128 } 129 130 for (i = 0; i < MAX_SANE_HARD_LINKS; i++) { 131 sprintf(dirname, "%s/testdir%d", dir, i); 132 133 if (mkdir(dirname, 0755) == 0) 134 continue; 135 136 switch (errno) { 137 case EMLINK: 138 SAFE_STAT(cleanup, dir, &s); 139 /* 140 * i+2 because there are two links to each newly 141 * created directory (the '.' and link from parent dir) 142 */ 143 if (s.st_nlink != (i + 2)) { 144 tst_brkm(TBROK, cleanup, "%s link counts have" 145 "%d, should be %d", dir, 146 (int)s.st_nlink, i + 2); 147 } else { 148 tst_resm(TINFO, "the maximum subdirectories in " 149 "%s is hit: %d", dir, (int)s.st_nlink); 150 return s.st_nlink; 151 } 152 case ENOSPC: 153 case EDQUOT: 154 tst_resm(TINFO | TERRNO, "mkdir(%s, 0755) failed", 155 dirname); 156 goto max_subdirs_cleanup; 157 default: 158 tst_brkm(TBROK, cleanup, "mkdir(%s, 0755) failed " 159 "unexpectedly: %s", dirname, 160 strerror(errno)); 161 } 162 163 } 164 165 tst_resm(TINFO, "Failed reach the subdirs limit on %s filesystem", 166 tst_fs_type_name(fs_type)); 167 168 max_subdirs_cleanup: 169 for (j = 0; j < i; j++) { 170 sprintf(dirname, "%s/testdir%d", dir, j); 171 SAFE_RMDIR(cleanup, dirname); 172 } 173 174 return 0; 175 } 176