diff --git a/liverfs.c b/liverfs.c index cf0de5a..e400066 100644 --- a/liverfs.c +++ b/liverfs.c @@ -35,23 +35,28 @@ * * lustre/utils/llverfs.c * - * ext3 Filesystem Verification Tool. - * This program tests the correct operation of ext3 filesystem. - * This tool have two working modes + * ext3/4 Filesystem Verification Tool. + * + * This program tests some correctness aspects of ext3/4 filesystem + * operation. + * + * This tool has two working modes * 1. full mode * 2. fast mode - * The full mode is basic mode in which program creates a subdirectory - * in the test fileysytem, writes n(files_in_dir, default=16) large(4GB) files - * to the directory with the test pattern at the start of each 4kb block. - * The test pattern contains timestamp, relative file offset and per file - * unique idenfifier(inode number). this continues until whole filesystem is - * full and then this tooll verifies that the data in all of the test files - * is correct. - * In the fast mode the tool creates a test directories with - * EXT3_TOPDIR_FL flag set. the number of directories equals to the number - * of block groups in the filesystem(e.g. 65536 directories for 8TB filesystem) - * and then writes a single 1MB file in each directory. The tool then verifies - * that the data in each file is correct. + * + * In full mode, the program creates a subdirectory in the test + * fileysytem, writes n(files_in_dir, default=32) large(4GB) files to + * the directory with the test pattern at the start of each 4kb block. + * The test pattern contains timestamp, relative file offset and per + * file unique identifier(inode number). This continues until the + * whole filesystem is full and then the tool verifies that the data + * in all of the test files is correct. + * In fast mode, the tool creates test directories with the + * EXT3_TOPDIR_FL flag set. The number of directories equals the + * number of block groups in the filesystem (e.g. 65536 directories + * for an 8TB filesystem) and then writes a single 1MB file in each + * directory. The tool then verifies that the data in each file is + * correct. */ #ifndef _GNU_SOURCE @@ -178,7 +183,7 @@ static int open_file(const char *file, int flag) * Verify_chunk: Verifies test pattern in each 4kB (BLOCKSIZE) is correct. * Returns 0 if test offset and timestamp is correct otherwise 1. */ -int verify_chunk(char *chunk_buf, size_t chunksize,unsigned long long chunk_off, +int verify_chunk(char *chunk_buf, size_t chunksize, unsigned long long chunk_off, unsigned long long time_st, unsigned long long inode_st, char *file) { @@ -231,6 +236,7 @@ int write_chunks(int fd, unsigned long long offset,unsigned long long write_end, ino_t inode_st, const char *file) { unsigned long long stride; + ssize_t nwritten; stride = full ? chunksize : (ONE_GB - chunksize); for (offset = offset & ~(chunksize - 1); offset < write_end; @@ -245,7 +251,7 @@ int write_chunks(int fd, unsigned long long offset,unsigned long long write_end, if (!full && offset > chunksize) { fill_chunk(chunk_buf, chunksize, offset, time_st, inode_st); - if (write(fd, chunk_buf, chunksize) < 0) { + if ((nwritten = write(fd, chunk_buf, chunksize)) < 0) { if (errno == ENOSPC) { errno_local = errno; return 0; @@ -255,12 +261,14 @@ int write_chunks(int fd, unsigned long long offset,unsigned long long write_end, progname, file, offset,strerror(errno)); return errno; } - offset += chunksize; + if (nwritten < chunksize) + fprintf(stderr, "short write: offset=%llu, requested=%ld, written=%ld\n", offset, chunksize, nwritten); + offset += nwritten; if (offset + chunksize > write_end) chunksize = write_end - offset; } fill_chunk(chunk_buf, chunksize, offset, time_st, inode_st); - if (write(fd, (char *) chunk_buf, chunksize) < 0) { + if ((nwritten = write(fd, (char *) chunk_buf, chunksize)) < 0) { if (errno == ENOSPC) { errno_local = errno; return 0; @@ -269,6 +277,8 @@ int write_chunks(int fd, unsigned long long offset,unsigned long long write_end, progname, file, offset, strerror(errno)); return 1; } + if (nwritten < chunksize) + fprintf(stderr, "short write: offset=%llu, requested=%ld, written=%ld\n", offset, chunksize, nwritten); } return 0; } @@ -282,6 +292,7 @@ int read_chunks(int fd, unsigned long long offset, unsigned long long read_end, ino_t inode_st, char *file) { unsigned long long stride; + ssize_t nread; stride = full ? chunksize : (ONE_GB - chunksize); for (offset = offset & ~(chunksize - 1); offset < read_end; @@ -294,25 +305,29 @@ int read_chunks(int fd, unsigned long long offset, unsigned long long read_end, if (offset + chunksize > read_end) chunksize = read_end - offset; if (!full && offset > chunksize) { - if (read(fd, chunk_buf, chunksize) < 0) { + if ((nread = read(fd, chunk_buf, chunksize)) < 0) { fprintf(stderr, "\n%s: read %s+%llu failed: %s\n", progname, file, offset,strerror(errno)); return 1; } - if (verify_chunk(chunk_buf, chunksize, offset, + if (nread < chunksize) + fprintf(stderr, "short read: offset=%llu, requested=%ld, read=%ld\n", offset, chunksize, nread); + if (verify_chunk(chunk_buf, nread, offset, time_st, inode_st, file) != 0) return 1; - offset += chunksize; + offset += nread; if (offset + chunksize >= read_end) chunksize = read_end - offset; } - if (read(fd, chunk_buf, chunksize) < 0) { + if ((nread = read(fd, chunk_buf, chunksize)) < 0) { fprintf(stderr, "\n%s: read %s+%llu failed: %s\n", progname, file, offset, strerror(errno)); return 1; } - if (verify_chunk(chunk_buf, chunksize, offset, time_st, + if (nread < chunksize) + fprintf(stderr, "short read: offset=%llu, requested=%ld, read=%ld\n", offset, chunksize, nread); + if (verify_chunk(chunk_buf, nread, offset, time_st, inode_st, file) != 0) return 1; }