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 return 0; 56 } 57 58 sprintf(base_filename, "%s/testfile0", dir); 59 SAFE_TOUCH(cleanup, base_filename, 0644, NULL); 60 61 for (i = 1; i < MAX_SANE_HARD_LINKS; i++) { 62 sprintf(link_filename, "%s/testfile%d", dir, i); 63 64 if (link(base_filename, link_filename) == 0) 65 continue; 66 67 switch (errno) { 68 case EMLINK: 69 SAFE_STAT(cleanup, base_filename, &s); 70 if (s.st_nlink != i) { 71 tst_brkm(TBROK, cleanup, "wrong number of " 72 "hard links for %s have %i, should be" 73 " %d", base_filename, 74 (int)s.st_nlink, i); 75 return 0; 76 } else { 77 tst_resm(TINFO, "the maximum number of hard " 78 "links to %s is hit: %d", 79 base_filename, (int)s.st_nlink); 80 return s.st_nlink; 81 } 82 case ENOSPC: 83 case EDQUOT: 84 tst_resm(TINFO | TERRNO, "link(%s, %s) failed", 85 base_filename, link_filename); 86 goto max_hardlinks_cleanup; 87 default: 88 tst_brkm(TBROK, cleanup, "link(%s, %s) failed " 89 "unexpectedly: %s", base_filename, 90 link_filename, strerror(errno)); 91 return 0; 92 } 93 } 94 95 tst_resm(TINFO, "Failed reach the hardlinks limit"); 96 97 max_hardlinks_cleanup: 98 for (j = 0; j < i; j++) { 99 sprintf(link_filename, "%s/testfile%d", dir, j); 100 SAFE_UNLINK(cleanup, link_filename); 101 } 102 103 return 0; 104 } 105 106 int tst_fs_fill_subdirs_(void (*cleanup) (void), const char *dir) 107 { 108 unsigned int i, j, whitelist_size; 109 char dirname[PATH_MAX]; 110 struct stat s; 111 long fs_type; 112 113 if (stat(dir, &s) == -1 && errno == ENOENT) 114 SAFE_MKDIR(cleanup, dir, 0744); 115 116 SAFE_STAT(cleanup, dir, &s); 117 if (!S_ISDIR(s.st_mode)) { 118 tst_brkm(TBROK, cleanup, "%s is not directory", dir); 119 return 0; 120 } 121 122 /* for current kernel, subdir limit is not availiable for all fs */ 123 fs_type = tst_fs_type(cleanup, dir); 124 125 whitelist_size = ARRAY_SIZE(subdir_limit_whitelist); 126 for (i = 0; i < whitelist_size; i++) { 127 if (fs_type == subdir_limit_whitelist[i]) 128 break; 129 } 130 if (i == whitelist_size) { 131 tst_resm(TINFO, "subdir limit is not availiable for " 132 "%s filesystem", tst_fs_type_name(fs_type)); 133 return 0; 134 } 135 136 for (i = 0; i < MAX_SANE_HARD_LINKS; i++) { 137 sprintf(dirname, "%s/testdir%d", dir, i); 138 139 if (mkdir(dirname, 0755) == 0) 140 continue; 141 142 switch (errno) { 143 case EMLINK: 144 SAFE_STAT(cleanup, dir, &s); 145 /* 146 * i+2 because there are two links to each newly 147 * created directory (the '.' and link from parent dir) 148 */ 149 if (s.st_nlink != (i + 2)) { 150 tst_brkm(TBROK, cleanup, "%s link counts have" 151 "%d, should be %d", dir, 152 (int)s.st_nlink, i + 2); 153 return 0; 154 } else { 155 tst_resm(TINFO, "the maximum subdirectories in " 156 "%s is hit: %d", dir, (int)s.st_nlink); 157 return s.st_nlink; 158 } 159 case ENOSPC: 160 case EDQUOT: 161 tst_resm(TINFO | TERRNO, "mkdir(%s, 0755) failed", 162 dirname); 163 goto max_subdirs_cleanup; 164 default: 165 tst_brkm(TBROK, cleanup, "mkdir(%s, 0755) failed " 166 "unexpectedly: %s", dirname, 167 strerror(errno)); 168 return 0; 169 } 170 171 } 172 173 tst_resm(TINFO, "Failed reach the subdirs limit on %s filesystem", 174 tst_fs_type_name(fs_type)); 175 176 max_subdirs_cleanup: 177 for (j = 0; j < i; j++) { 178 sprintf(dirname, "%s/testdir%d", dir, j); 179 SAFE_RMDIR(cleanup, dirname); 180 } 181 182 return 0; 183 } 184