h_quota2_tests.c revision 1.3
1/* $NetBSD: h_quota2_tests.c,v 1.3 2011/06/11 18:03:17 christos Exp $ */ 2 3/* 4 * rump server for advanced quota tests 5 * this one includes functions to run against the filesystem before 6 * starting to handle rump requests from clients. 7 */ 8 9#include "../common/h_fsmacros.h" 10 11#include <err.h> 12#include <semaphore.h> 13#include <sys/types.h> 14#include <sys/mount.h> 15 16#include <stdlib.h> 17#include <unistd.h> 18 19#include <ufs/ufs/ufsmount.h> 20#include <dev/fssvar.h> 21 22#include <rump/rump.h> 23#include <rump/rump_syscalls.h> 24 25#include "../../h_macros.h" 26 27int background = 0; 28 29#define TEST_NONROOT_ID 1 30 31static int 32quota_test0(const char *testopts) 33{ 34 static char buf[512]; 35 int fd; 36 int error; 37 rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID); 38 rump_sys_chmod(".", 0777); 39 if (rump_sys_setegid(TEST_NONROOT_ID) != 0) { 40 error = errno; 41 warn("rump_sys_setegid"); 42 return error; 43 } 44 if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) { 45 error = errno; 46 warn("rump_sys_seteuid"); 47 return error; 48 } 49 fd = rump_sys_open("test_fillup", O_CREAT | O_RDWR, 0644); 50 if (fd < 0) { 51 error = errno; 52 warn("rump_sys_open"); 53 } else { 54 while (rump_sys_write(fd, buf, sizeof(buf)) == sizeof(buf)) 55 error = 0; 56 error = errno; 57 } 58 rump_sys_close(fd); 59 rump_sys_seteuid(0); 60 rump_sys_setegid(0); 61 return error; 62} 63 64static int 65quota_test1(const char *testopts) 66{ 67 static char buf[512]; 68 int fd; 69 int error; 70 rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID); 71 rump_sys_chmod(".", 0777); 72 if (rump_sys_setegid(TEST_NONROOT_ID) != 0) { 73 error = errno; 74 warn("rump_sys_setegid"); 75 return error; 76 } 77 if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) { 78 error = errno; 79 warn("rump_sys_seteuid"); 80 return error; 81 } 82 fd = rump_sys_open("test_fillup", O_CREAT | O_RDWR, 0644); 83 if (fd < 0) { 84 error = errno; 85 warn("rump_sys_open"); 86 } else { 87 /* 88 * write up to the soft limit, wait a bit, an try to 89 * keep on writing 90 */ 91 int i; 92 93 /* write 2k: with the directory this makes 2.5K */ 94 for (i = 0; i < 4; i++) { 95 error = rump_sys_write(fd, buf, sizeof(buf)); 96 if (error != sizeof(buf)) 97 err(1, "write failed early"); 98 } 99 sleep(2); 100 /* now try to write an extra .5k */ 101 if (rump_sys_write(fd, buf, sizeof(buf)) != sizeof(buf)) 102 error = errno; 103 else 104 error = 0; 105 } 106 rump_sys_close(fd); 107 rump_sys_seteuid(0); 108 rump_sys_setegid(0); 109 return error; 110} 111 112static int 113quota_test2(const char *testopts) 114{ 115 static char buf[512]; 116 int fd; 117 int error; 118 int i; 119 rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID); 120 rump_sys_chmod(".", 0777); 121 if (rump_sys_setegid(TEST_NONROOT_ID) != 0) { 122 error = errno; 123 warn("rump_sys_setegid"); 124 return error; 125 } 126 if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) { 127 error = errno; 128 warn("rump_sys_seteuid"); 129 return error; 130 } 131 132 for (i = 0; ; i++) { 133 sprintf(buf, "file%d", i); 134 fd = rump_sys_open(buf, O_CREAT | O_RDWR, 0644); 135 if (fd < 0) 136 break; 137 sprintf(buf, "test file no %d", i); 138 rump_sys_write(fd, buf, strlen(buf)); 139 rump_sys_close(fd); 140 } 141 error = errno; 142 143 rump_sys_close(fd); 144 rump_sys_seteuid(0); 145 rump_sys_setegid(0); 146 return error; 147} 148 149static int 150quota_test3(const char *testopts) 151{ 152 static char buf[512]; 153 int fd; 154 int error; 155 int i; 156 rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID); 157 rump_sys_chmod(".", 0777); 158 if (rump_sys_setegid(TEST_NONROOT_ID) != 0) { 159 error = errno; 160 warn("rump_sys_setegid"); 161 return error; 162 } 163 if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) { 164 error = errno; 165 warn("rump_sys_seteuid"); 166 return error; 167 } 168 169 /* 170 * create files one past the soft limit: one less as we already own the 171 * root directory 172 */ 173 for (i = 0; i < 4; i++) { 174 sprintf(buf, "file%d", i); 175 fd = rump_sys_open(buf, O_EXCL| O_CREAT | O_RDWR, 0644); 176 if (fd < 0) 177 err(1, "file create failed early"); 178 sprintf(buf, "test file no %d", i); 179 rump_sys_write(fd, buf, strlen(buf)); 180 rump_sys_close(fd); 181 } 182 /* now create an extra file after grace time: this should fail */ 183 sleep(2); 184 sprintf(buf, "file%d", i); 185 fd = rump_sys_open(buf, O_EXCL| O_CREAT | O_RDWR, 0644); 186 if (fd < 0) 187 error = errno; 188 else 189 error = 0; 190 191 rump_sys_close(fd); 192 rump_sys_seteuid(0); 193 rump_sys_setegid(0); 194 return error; 195} 196 197static int 198quota_test4(const char *testopts) 199{ 200 static char buf[512]; 201 int fd, fssfd; 202 struct fss_set fss; 203 unsigned int i; 204 int unl=0; 205 int unconf=0; 206 207 /* 208 * take an internal snapshot of the filesystem, and create a new 209 * file with some data 210 */ 211 rump_sys_chown(".", 0, 0); 212 rump_sys_chmod(".", 0777); 213 214 for (i =0; testopts && i < strlen(testopts); i++) { 215 switch(testopts[i]) { 216 case 'L': 217 unl++; 218 break; 219 case 'C': 220 unconf++; 221 break; 222 default: 223 errx(1, "test4: unknown option %c", testopts[i]); 224 } 225 } 226 227 /* first create the snapshot */ 228 229 fd = rump_sys_open(FSTEST_MNTNAME "/le_snap", O_CREAT | O_RDWR, 0777); 230 if (fd == -1) 231 err(1, "create " FSTEST_MNTNAME "/le_snap"); 232 rump_sys_close(fd); 233 fssfd = rump_sys_open("/dev/rfss0", O_RDWR); 234 if (fssfd == -1) 235 err(1, "cannot open fss"); 236 memset(&fss, 0, sizeof(fss)); 237 fss.fss_mount = __UNCONST("/mnt"); 238 fss.fss_bstore = __UNCONST(FSTEST_MNTNAME "/le_snap"); 239 fss.fss_csize = 0; 240 if (rump_sys_ioctl(fssfd, FSSIOCSET, &fss) == -1) 241 err(1, "create snapshot"); 242 if (unl) { 243 if (rump_sys_unlink(FSTEST_MNTNAME "/le_snap") == -1) 244 err(1, "unlink snapshot"); 245 } 246 247 /* now create some extra files */ 248 249 for (i = 0; i < 4; i++) { 250 sprintf(buf, "file%d", i); 251 fd = rump_sys_open(buf, O_EXCL| O_CREAT | O_RDWR, 0644); 252 if (fd < 0) 253 err(1, "create %s", buf); 254 sprintf(buf, "test file no %d", i); 255 rump_sys_write(fd, buf, strlen(buf)); 256 rump_sys_close(fd); 257 } 258 if (unconf) 259 if (rump_sys_ioctl(fssfd, FSSIOCCLR, NULL) == -1) 260 err(1, "unconfigure snapshot"); 261 return 0; 262} 263 264static int 265quota_test5(const char *testopts) 266{ 267 static char buf[512]; 268 int fd; 269 int remount = 0; 270 int unlnk = 0; 271 int log = 0; 272 unsigned int i; 273 274 for (i =0; testopts && i < strlen(testopts); i++) { 275 switch(testopts[i]) { 276 case 'L': 277 log++; 278 break; 279 case 'R': 280 remount++; 281 break; 282 case 'U': 283 unlnk++; 284 break; 285 default: 286 errx(1, "test4: unknown option %c", testopts[i]); 287 } 288 } 289 if (remount) { 290 struct ufs_args uargs; 291 uargs.fspec = __UNCONST("/diskdev"); 292 /* remount the fs read/write */ 293 if (rump_sys_mount(MOUNT_FFS, FSTEST_MNTNAME, 294 MNT_UPDATE | (log ? MNT_LOG : 0), 295 &uargs, sizeof(uargs)) == -1) 296 err(1, "mount ffs rw %s", FSTEST_MNTNAME); 297 } 298 299 if (unlnk) { 300 /* 301 * open and unlink a file 302 */ 303 304 fd = rump_sys_open("unlinked_file", 305 O_EXCL| O_CREAT | O_RDWR, 0644); 306 if (fd < 0) 307 err(1, "create %s", "unlinked_file"); 308 sprintf(buf, "test unlinked_file"); 309 rump_sys_write(fd, buf, strlen(buf)); 310 if (rump_sys_unlink("unlinked_file") == -1) 311 err(1, "unlink unlinked_file"); 312 if (rump_sys_fsync(fd) == -1) 313 err(1, "fsync unlinked_file"); 314 rump_sys_reboot(RUMP_RB_NOSYNC, NULL); 315 errx(1, "reboot failed"); 316 return 1; 317 } 318 return 0; 319} 320 321struct quota_test { 322 int (*func)(const char *); 323 const char *desc; 324}; 325 326struct quota_test quota_tests[] = { 327 { quota_test0, "write up to hard limit"}, 328 { quota_test1, "write beyond the soft limit after grace time"}, 329 { quota_test2, "create file up to hard limit"}, 330 { quota_test3, "create file beyond the soft limit after grace time"}, 331 { quota_test4, "take a snapshot and add some data"}, 332 { quota_test5, "open and unlink a file"}, 333}; 334 335static void 336usage(void) 337{ 338 unsigned int test; 339 fprintf(stderr, "usage: %s [-b] [-l] test# diskimage bindurl\n", 340 getprogname()); 341 fprintf(stderr, "available tests:\n"); 342 for (test = 0; test < sizeof(quota_tests) / sizeof(quota_tests[0]); 343 test++) 344 fprintf(stderr, "\t%d: %s\n", test, quota_tests[test].desc); 345 exit(1); 346} 347 348static void 349die(const char *reason, int error) 350{ 351 352 warnx("%s: %s", reason, strerror(error)); 353 if (background) 354 rump_daemonize_done(error); 355 exit(1); 356} 357 358static sem_t sigsem; 359static void 360sigreboot(int sig) 361{ 362 363 sem_post(&sigsem); 364} 365 366int 367main(int argc, char **argv) 368{ 369 int error; 370 u_long test; 371 char *end; 372 struct ufs_args uargs; 373 const char *filename; 374 const char *serverurl; 375 const char *topts = NULL; 376 int mntopts = 0; 377 int ch; 378 379 while ((ch = getopt(argc, argv, "blo:r")) != -1) { 380 switch(ch) { 381 case 'b': 382 background = 1; 383 break; 384 case 'l': 385 mntopts |= MNT_LOG; 386 break; 387 case 'r': 388 mntopts |= MNT_RDONLY; 389 break; 390 case 'o': 391 topts = optarg; 392 break; 393 default: 394 usage(); 395 } 396 } 397 argc -= optind; 398 argv += optind; 399 400 if (argc != 3) 401 usage(); 402 403 filename = argv[1]; 404 serverurl = argv[2]; 405 406 test = strtoul(argv[0], &end, 10); 407 if (*end != '\0') { 408 usage(); 409 } 410 if (test > sizeof(quota_tests) / sizeof(quota_tests[0])) { 411 usage(); 412 } 413 414 if (background) { 415 error = rump_daemonize_begin(); 416 if (error) 417 errx(1, "rump daemonize: %s", strerror(error)); 418 } 419 420 error = rump_init(); 421 if (error) 422 die("rump init failed", error); 423 424 if (rump_sys_mkdir(FSTEST_MNTNAME, 0777) == -1) 425 err(1, "mount point create"); 426 rump_pub_etfs_register("/diskdev", filename, RUMP_ETFS_BLK); 427 uargs.fspec = __UNCONST("/diskdev"); 428 if (rump_sys_mount(MOUNT_FFS, FSTEST_MNTNAME, mntopts, 429 &uargs, sizeof(uargs)) == -1) 430 die("mount ffs", errno); 431 432 if (rump_sys_chdir(FSTEST_MNTNAME) == -1) 433 err(1, "cd %s", FSTEST_MNTNAME); 434 error = quota_tests[test].func(topts); 435 if (error) { 436 fprintf(stderr, " test %lu: %s returned %d: %s\n", 437 test, quota_tests[test].desc, error, strerror(error)); 438 } 439 if (rump_sys_chdir("/") == -1) 440 err(1, "cd /"); 441 442 error = rump_init_server(serverurl); 443 if (error) 444 die("rump server init failed", error); 445 if (background) 446 rump_daemonize_done(RUMP_DAEMONIZE_SUCCESS); 447 448 sem_init(&sigsem, 0, 0); 449 signal(SIGTERM, sigreboot); 450 signal(SIGINT, sigreboot); 451 sem_wait(&sigsem); 452 453 rump_sys_reboot(0, NULL); 454 /*NOTREACHED*/ 455 return 0; 456} 457