1 /*- 2 * Copyright (c) 2008 Peter Holm <pho@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 /* Get various resource limits for the tests */ 29 30 #include <sys/types.h> 31 #include <sys/sysctl.h> 32 #include <unistd.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <fcntl.h> 36 #include <string.h> 37 #include <sys/stat.h> 38 #include <sys/param.h> 39 #include <sys/mount.h> 40 #include <kvm.h> 41 #include <vm/vm_param.h> 42 #include <errno.h> 43 #include <err.h> 44 #include <stdarg.h> 45 #include <libutil.h> 46 47 #include "stress.h" 48 49 static int lockfd; 50 static int dffd; 51 static int flags; 52 static char lockpath[128]; 53 static char dfpath[128]; 54 55 static int64_t 56 inodes(void) 57 { 58 char path[MAXPATHLEN+1]; 59 struct statfs buf; 60 61 if (op->inodes != 0) 62 return (op->inodes); 63 if (getcwd(path, sizeof(path)) == NULL) 64 err(1, "getcwd()"); 65 66 if (statfs(path, &buf) < 0) 67 err(1, "statfs(%s)", path); 68 if (!strcmp(buf.f_fstypename, "msdosfs")) 69 buf.f_ffree = 9999; 70 flags = buf.f_flags & MNT_VISFLAGMASK; 71 if (op->verbose > 2) 72 printf("Free inodes on %s (%s): %jd\n", path, 73 buf.f_mntonname, buf.f_ffree); 74 return (buf.f_ffree); 75 } 76 77 static int64_t 78 df(void) 79 { 80 char path[MAXPATHLEN+1]; 81 struct statfs buf; 82 83 if (op->kblocks != 0) 84 return (op->kblocks * (uint64_t)1024); 85 86 if (getcwd(path, sizeof(path)) == NULL) 87 err(1, "getcwd()"); 88 89 if (statfs(path, &buf) < 0) 90 err(1, "statfs(%s)", path); 91 if (buf.f_bavail > (int64_t)buf.f_blocks || buf.f_bavail < 0) { 92 warnx("Corrupt statfs(%s). f_bavail = %jd!", path, 93 buf.f_bavail); 94 buf.f_bavail = 100; 95 } 96 if (op->verbose > 2) 97 printf("Free space on %s: %jd Mb\n", path, buf.f_bavail * 98 buf.f_bsize / 1024 / 1024); 99 return (buf.f_bavail * buf.f_bsize); 100 } 101 102 int64_t 103 swap(void) 104 { 105 struct xswdev xsw; 106 size_t mibsize, size; 107 int mib[16], n; 108 int64_t sz; 109 110 mibsize = sizeof mib / sizeof mib[0]; 111 sz = 0; 112 113 if (sysctlnametomib("vm.swap_info", mib, &mibsize) == -1) 114 err(1, "sysctlnametomib()"); 115 116 for (n = 0; ; ++n) { 117 mib[mibsize] = n; 118 size = sizeof xsw; 119 if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1) 120 break; 121 if (xsw.xsw_version != XSWDEV_VERSION) 122 errx(1, "xswdev version mismatch"); 123 sz = sz + xsw.xsw_nblks - xsw.xsw_used; 124 } 125 if (errno != ENOENT) 126 err(1, "sysctl()"); 127 128 if (op->verbose > 2) 129 printf("Total free swap space %jd Mb\n", 130 sz * getpagesize() / 1024 / 1024); 131 132 return (sz * getpagesize()); 133 } 134 135 unsigned long 136 usermem(void) 137 { 138 unsigned long mem; 139 size_t nlen = sizeof(mem); 140 141 if (sysctlbyname("hw.usermem", &mem, &nlen, NULL, 0) == -1) 142 err(1, "sysctlbyname() %s:%d", __FILE__, __LINE__); 143 144 if (op->verbose > 2) 145 printf("Total free user memory %lu Mb\n", 146 mem / 1024 / 1024); 147 148 return (mem); 149 } 150 151 static void 152 cleanupdf(void) 153 { 154 unlink(dfpath); 155 } 156 157 void 158 getdf(int64_t *block, int64_t *inode) 159 { 160 int i, j; 161 char buf[128]; 162 163 snprintf(lockpath, sizeof(lockpath), "%s/lock", op->cd); 164 for (j = 0; j < 2; j++) { 165 for (i = 0; i < 10000; i++) { 166 if ((lockfd = open(lockpath, 167 O_CREAT | O_TRUNC | O_WRONLY | 168 O_EXCL, 0644)) != -1) 169 break; 170 usleep(10000); /* sleep 1/100 sec */ 171 if (i > 0 && i % 1000 == 0) 172 fprintf(stderr, "%s is waiting for lock file" 173 " %s\n", 174 getprogname(), lockpath); 175 } 176 if (lockfd != -1) 177 break; 178 fprintf(stderr, "%s. Removing stale %s\n", getprogname(), 179 lockpath); 180 unlink(lockpath); 181 } 182 if (lockfd == -1) 183 errx(1, "%s. Can not create %s\n", getprogname(), lockpath); 184 snprintf(dfpath, sizeof(dfpath), "%s/df", op->cd); 185 if ((dffd = open(dfpath, O_RDWR, 0644)) == -1) { 186 if ((dffd = open(dfpath, 187 O_CREAT | O_TRUNC | O_WRONLY, 0644)) == -1) { 188 unlink(lockpath); 189 err(1, "creat(%s) %s:%d", dfpath, __FILE__, 190 __LINE__); 191 } 192 atexit(cleanupdf); 193 *block = df(); 194 *inode = inodes(); 195 snprintf(buf, sizeof(buf), "%jd %jd", *block, *inode); 196 197 if (write(dffd, buf, strlen(buf) + 1) != 198 (ssize_t)strlen(buf) +1) 199 err(1, "write df. %s:%d", __FILE__, __LINE__); 200 } else { 201 if (read(dffd, buf, sizeof(buf)) < 1) { 202 system("ls -l /tmp/stressX.control"); 203 unlink(lockpath); 204 err(1, "read df. %s:%d", __FILE__, __LINE__); 205 } 206 sscanf(buf, "%jd %jd", block, inode); 207 } 208 close(dffd); 209 } 210 211 void 212 reservedf(int64_t blks, int64_t inos) 213 { 214 char buf[128]; 215 int64_t blocks, inodes; 216 217 if ((dffd = open(dfpath, O_RDWR, 0644)) == -1) { 218 warn("open(%s) %s:%d. %s", dfpath, __FILE__, __LINE__, 219 getprogname()); 220 goto err; 221 } 222 if (read(dffd, buf, sizeof(buf)) < 1) { 223 warn("read df. %s:%d", __FILE__, __LINE__); 224 goto err; 225 } 226 sscanf(buf, "%jd %jd", &blocks, &inodes); 227 228 if (op->verbose > 2) 229 printf("%-8s: reservefd(%9jdK, %6jd) out of (%9jdK, %6jd)\n", 230 getprogname(), blks/1024, inos, blocks/1024, 231 inodes); 232 blocks -= blks; 233 inodes -= inos; 234 235 snprintf(buf, sizeof(buf), "%jd %jd", blocks, inodes); 236 if (blocks < 0 || inodes < 0) 237 printf("******************************** %s: %s\n", 238 getprogname(), buf); 239 if (lseek(dffd, 0, 0) == -1) 240 err(1, "lseek. %s:%d", __FILE__, __LINE__); 241 if (write(dffd, buf, strlen(buf) + 1) != (ssize_t)strlen(buf) +1) 242 warn("write df. %s:%d", __FILE__, __LINE__); 243 err: 244 close(dffd); 245 close(lockfd); 246 if (unlink(lockpath) == -1) 247 err(1, "unlink(%s)", lockpath); 248 } 249