Add two tools: mkdoubledirs and gensamehash

mkdoubledirs creates pairs of directories a/a, b/b, c/c etc. This is to
test file lookup code: there must be a directory named blah only if the
current directory is named blah too.

gensamehash generates file names with the same XFS hash to test the
code that resolves collisions. In principle, can be updated for other
hashes: ext*, exfat, etc.
This commit is contained in:
Ivan Baravy 2023-01-02 01:50:02 +00:00
parent cb8c3274af
commit fecf7be637
5 changed files with 264 additions and 8 deletions

10
.gitignore vendored
View File

@ -8,10 +8,12 @@ umka_fuse
umka_os
umka_ping
umka_gen_devices_dat
mkdirrange
mkfilepattern
lfbviewx
randdir
tools/mkdirrange
tools/mkdoubledirs
tools/gensamehash
tools/mkfilepattern
tools/lfbviewx
tools/randdir
*.img
*.img.xz
*.img.gz

View File

@ -1,5 +1,6 @@
RANDDIR=../tools/randdir
MKDIRRANGE=../tools/mkdirrange
MKDOUBLEDIRS=../tools/mkdoubledirs
MKFILEPATTERN=../tools/mkfilepattern
DIRTOTEST=python3 ../tools/dirtotest.py
MOUNT_OPT=-t xfs
@ -15,7 +16,7 @@ s4k: xfs_v4_ftype0_s4k_b4k_n8k.img
unicode: xfs_v4_unicode.img
v5: xfs_v5_ftype1_s05k_b2k_n8k.img xfs_v5_files_s05k_b4k_n8k.img xfs_bigtime.img xfs_nrext64.img
v5: xfs_v5_ftype1_s05k_b2k_n8k.img xfs_v5_files_s05k_b4k_n8k.img xfs_bigtime.img xfs_nrext64.img xfs_lookup_v5.img xfs_lookup_v4.img
coverage: jfs.img xfs_borg_bit.img xfs_short_dir_i8.img
@ -37,6 +38,76 @@ jfs.img:
parted --script $@ mktable gpt
parted --script --align optimal $@ mkpart primary 1MiB 100%
xfs_lookup_v4.img:
fallocate -l 10GiB $@
mkfs.xfs -m crc=0 $@
sudo mount $(MOUNT_OPT) $@ $(TEMP_DIR)
sudo chown $$USER $(TEMP_DIR) -R
#
mkdir $(TEMP_DIR)/dir_sf
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_sf d 5
#
mkdir $(TEMP_DIR)/dir_block
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_block d 50
#
mkdir $(TEMP_DIR)/dir_leaf
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_leaf d 500
#
mkdir $(TEMP_DIR)/dir_node
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_node d 2000
#
mkdir $(TEMP_DIR)/dir_btree_l1a
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_btree_l1a d 5000
#
mkdir $(TEMP_DIR)/dir_btree_l1b
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_btree_l1b d 50000
#
mkdir $(TEMP_DIR)/dir_btree_l1c
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_btree_l1c d 500000
#
mkdir $(TEMP_DIR)/dir_btree_l2
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_btree_l2 d 2000000
#
sudo umount $(TEMP_DIR)
fallocate -i -o 0 -l 1MiB $@
parted --script --align optimal $@ mktable msdos
parted --script --align optimal $@ mkpart primary xfs 1MiB 100%
xfs_lookup_v5.img:
fallocate -l 10GiB $@
mkfs.xfs -m crc=1 $@
sudo mount $(MOUNT_OPT) $@ $(TEMP_DIR)
sudo chown $$USER $(TEMP_DIR) -R
#
mkdir $(TEMP_DIR)/dir_sf
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_sf d 5
#
mkdir $(TEMP_DIR)/dir_block
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_block d 50
#
mkdir $(TEMP_DIR)/dir_leaf
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_leaf d 500
#
mkdir $(TEMP_DIR)/dir_node
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_node d 2000
#
mkdir $(TEMP_DIR)/dir_btree_l1a
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_btree_l1a d 5000
#
mkdir $(TEMP_DIR)/dir_btree_l1b
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_btree_l1b d 50000
#
mkdir $(TEMP_DIR)/dir_btree_l1c
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_btree_l1c d 500000
#
mkdir $(TEMP_DIR)/dir_btree_l2
$(MKDOUBLEDIRS) $(TEMP_DIR)/dir_btree_l2 d 2000000
#
sudo umount $(TEMP_DIR)
fallocate -i -o 0 -l 1MiB $@
parted --script --align optimal $@ mktable msdos
parted --script --align optimal $@ mkpart primary xfs 1MiB 100%
xfs_nrext64.img:
fallocate -l 3000MiB $@
mkfs.xfs -i nrext64=1 $@
@ -118,7 +189,7 @@ xfs_short_dir_i8.img:
#
sudo umount $(TEMP_DIR)
fallocate -i -o 0 -l 1MiB $@
parted --script $@ mktable gpt
parted --script $@ mktable gpt # FIXME: all msdos
parted --script --align optimal $@ mkpart primary 1MiB 100%
xfs_v4_ftype0_s05k_b2k_n8k.img:

117
tools/gensamehash.c Normal file
View File

@ -0,0 +1,117 @@
/*
SPDX-License-Identifier: GPL-2.0-or-later
UMKa - User-Mode KolibriOS developer tools
gensamehash - make directories with same names inside: dirname/dirname,
useful for search testing
Copyright (C) 2022 Ivan Baravy <dunkaist@gmail.com>
*/
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define NUM_LEN 18
#define rol32(x,y) (((x) << (y)) | ((x) >> (32 - (y))))
// the hash function has been taken from XFS docs with minor edits
uint32_t xfs_da_hashname(const char *name, int namelen) {
uint32_t hash;
/*
* Do four characters at a time as long as we can.
*/
for (hash = 0; namelen >= 4; namelen -= 4, name += 4) {
hash = (name[0] << 21) ^ (name[1] << 14) ^ (name[2] << 7) ^
(name[3] << 0) ^ rol32(hash, 7 * 4);
}
/*
* Now do the rest of the characters.
*/
switch (namelen) {
case 3:
return (name[0] << 14) ^ (name[1] << 7) ^ (name[2] << 0) ^
rol32(hash, 7 * 3);
case 2:
return (name[0] << 7) ^ (name[1] << 0) ^ rol32(hash, 7 * 2);
case 1:
return (name[0] << 0) ^ rol32(hash, 7 * 1);
default: /* case 0: */
return hash;
}
}
char name[256];
char hash_filename[256];
void increment(char *num) {
for (char *d = num + NUM_LEN; d > num; d--) {
if (*d < '9') {
d[0]++;
break;
} else {
*d = '0';
}
}
}
void int_handler(int signo, siginfo_t *info, void *context) {
(void)signo;
(void)info;
(void)context;
fprintf(stderr, "# cur name is %s\n", name);
}
int main(int argc, char *argv[])
{
uint32_t hash;
int hash_cnt = 0;
uint64_t start_num;
if (argc != 4) {
fprintf(stderr, "gensamehash <hash> <hash_cnt> <start_num>\n");
exit(1);
}
hash = strtoul(argv[1], NULL, 16);
sscanf(argv[2], "%i", &hash_cnt);
sscanf(argv[3], "%" SCNu64, &start_num);
fprintf(stderr, "pid: %u\n", getpid());
sprintf(hash_filename, "hash_0x%8.8" PRIx32 ".%u", hash, getpid());
sprintf(name, "d%18.18" PRIu64, start_num);
struct sigaction sa;
sa.sa_sigaction = int_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
fprintf(stderr, "Can't install SIGUSR1 handler!\n");
exit(1);
}
while (true) {
uint32_t h = xfs_da_hashname(name, NUM_LEN+1);
if (h == hash) {
FILE *f = fopen(hash_filename, "a+");
fprintf(f, "%7.7i %s\n", hash_cnt, name);
fclose(f);
hash_cnt++;
}
// fprintf(stderr, "# hash of %s is 0x%8.8x\n", name, h);
increment(name);
}
return 0;
}

View File

@ -7,7 +7,14 @@ CFLAGS=$(WARNINGS) $(NOWARNINGS) -std=c11 -O2 \
-DNDEBUG -D_POSIX_C_SOURCE=200809L -fno-pie
LDFLAGS=-no-pie
all: mkdirrange mkfilepattern lfbviewx randdir covpreproc
all: mkdirrange mkfilepattern lfbviewx randdir covpreproc mkdoubledirs \
gensamehash
gensamehash: gensamehash.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
mkdoubledirs: mkdoubledirs.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
mkdirrange: mkdirrange.c
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
@ -27,4 +34,5 @@ covpreproc: covpreproc.c
.PHONY: all clean
clean:
rm -f *.o mkdirrange mkfilepattern lfbviewx randdir covpreproc
rm -f *.o mkdirrange mkfilepattern lfbviewx randdir covpreproc \
mkdoubledirs gensamehash

58
tools/mkdoubledirs.c Normal file
View File

@ -0,0 +1,58 @@
/*
SPDX-License-Identifier: GPL-2.0-or-later
UMKa - User-Mode KolibriOS developer tools
mkdoubledirs - make directories with same names inside: dirname/dirname,
useful for search testing
Copyright (C) 2022 Ivan Baravy <dunkaist@gmail.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
const char *prefix;
const char *path;
unsigned count;
if (argc != 4) {
fprintf(stderr, "mkdoubledirs <directory> <prefix> <count>\n");
exit(1);
}
path = argv[1];
prefix = argv[2];
sscanf(argv[3], "%u", &count);
if (chdir(path)) {
fprintf(stderr, "Can't change dir to %s: %s\n", path, strerror(errno));
exit(1);
}
char dirname[256];
for(unsigned cur = 0; cur < count; cur++) {
sprintf(dirname, "%s%10.10u", prefix, cur);
if(mkdirat(AT_FDCWD, dirname, 0755)) {
fprintf(stderr, "Can't mkdir %s: %s\n", dirname, strerror(errno));
exit(1);
}
int dirfd = open(dirname, O_DIRECTORY);
if (dirfd == -1) {
fprintf(stderr, "Can't open %s: %s\n", dirname, strerror(errno));
exit(1);
}
if(mkdirat(dirfd, dirname, 0755)) {
fprintf(stderr, "Can't mkdir %s: %s\n", dirname, strerror(errno));
exit(1);
}
close(dirfd);
}
return 0;
}