Path: blob/main/tools/regression/ufs/uprintf/ufs_uprintf.c
48261 views
/*-1* Copyright (c) 2005 Robert N. M. Watson2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <err.h>27#include <errno.h>28#include <fcntl.h>29#include <limits.h>30#include <stdio.h>31#include <stdlib.h>32#include <string.h>33#include <unistd.h>3435/*36* This regression test attempts to exercise two instances of uprintf(9) in37* UFS: (1) when blocks are exhausted, and (2) when inodes are exhausted, in38* order to attempt to trigger races in the uprintf(9) code. The test39* accepts a pointer to a path -- ideally, a very small UFS partition -- and40* then proceeds to fill it in various ways.41*42* This tool assumes that it is alright to create, and delete, entries in the43* directory with names of integer values. Don't run this tool against a44* directory that has files with names along those lines if you want to keep45* the files.46*47* Suggested usage is:48*49* mdconfig -a -t malloc -s 51250* newfs /dev/mdX51* mount /dev/mdX /mnt52* ufs_uprintf /mnt53* umount /mnt54* mdconfig -d -u X55*/5657#define NUMTRIES 2005859/*60* Fill up the disk, then generate NUMTRIES additional ENOSPC errors.61*/62#define BLOCKSIZE 102463#define BLOCKS_FILENAME "0"64static void65fill_blocks(void)66{67char block[BLOCKSIZE];68ssize_t len;69int fd, i;7071fd = open(BLOCKS_FILENAME, O_CREAT | O_TRUNC | O_RDWR, 0600);72if (fd < 0)73err(-1, "fill_blocks: open(%s)", BLOCKS_FILENAME);7475/*76* First step: fill the disk device. Keep extending the file until77* we hit our first error, and hope it is ENOSPC.78*/79bzero(block, BLOCKSIZE);80errno = 0;81while (1) {82len = write(fd, block, BLOCKSIZE);83if (len < 0)84break;85if (len != BLOCKSIZE) {86warnx("fill_blocks: write(%d) returned %zd",87BLOCKSIZE, len);88close(fd);89(void)unlink(BLOCKS_FILENAME);90exit(-1);91}9293}94if (errno != ENOSPC) {95warn("fill_blocks: write");96close(fd);97(void)unlink(BLOCKS_FILENAME);98exit(-1);99}100101/*102* Second step: generate NUMTRIES instances of the error by retrying103* the write.104*/105for (i = 0; i < NUMTRIES; i++) {106len = write(fd, block, BLOCKSIZE);107if (len < 0 && errno != ENOSPC) {108warn("fill_blocks: write after ENOSPC");109close(fd);110(void)unlink(BLOCKS_FILENAME);111exit(-1);112}113}114115close(fd);116(void)unlink(BLOCKS_FILENAME);117}118119/*120* Create as many entries in the directory as we can, then once we start121* hitting ENOSPC, try NUMTRIES additional times. Note that we don't be able122* to tell the difference between running out of inodes and running out of123* room to extend the directory, so this is just a best effort.124*/125static void126fill_inodes(void)127{128char path[PATH_MAX];129int fd, i, max;130131/*132* First step, fill the directory.133*/134i = 0;135while (1) {136snprintf(path, PATH_MAX, "%d", i);137fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0600);138if (fd < 0)139break;140close(fd);141i++;142}143max = i;144if (errno != ENOSPC) {145warn("fill_inodes: open(%s)", path);146goto teardown;147}148149for (i = 0; i < NUMTRIES; i++) {150fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0600);151if (fd < 0 && errno != ENOSPC) {152warn("fill_inodes: open(%s) after ENOSPC", path);153goto teardown;154}155if (fd >= 0) {156warnx("fill_inodes: open(%s) after ENOSPC returned "157" %d", path, fd);158close(fd);159goto teardown;160}161}162163teardown:164for (i = 0; i < max; i++) {165snprintf(path, PATH_MAX, "%d", i);166(void)unlink(path);167}168}169170int171main(int argc, char *argv[])172{173174if (argc != 2)175err(-1, "usage: ufs_uprintf /non_optional_path");176177if (chdir(argv[1]) < 0)178err(-1, "chdir(%s)", argv[1]);179180fill_blocks();181182fill_inodes();183184return (0);185}186187188