All of lore.kernel.org
 help / color / mirror / Atom feed
* Bug?: unlink cause btrfs error but other fs don't
@ 2019-09-04  8:02 Hongzhi, Song
  2019-09-04  8:39 ` Hongzhi, Song
  2019-09-04 10:48 ` Josef Bacik
  0 siblings, 2 replies; 4+ messages in thread
From: Hongzhi, Song @ 2019-09-04  8:02 UTC (permalink / raw)
  To: linux-btrfs, linux-kernel, josef

[-- Attachment #1: Type: text/plain, Size: 1084 bytes --]

Hi ,


*Kernel:*

     After v5.2-rc1, qemux86-64

     make -j40 ARCH=x86_64 CROSS_COMPILE=x86-64-gcc
     use qemu to bootup kernel


*Reproduce:*

     There is a test case failed on btrfs but success on other 
fs(ext4,ext3), see attachment.


     Download attachments:

         gcc test.c -o myout -Wall -lpthread

         copy myout and run.sh to your qemu same directory.

         on qemu:

             ./run.sh


     I found the block device size with btrfs set 512M will cause the error.
     256M and 1G all success.


*Error info:*

     "BTRFS warning (device loop0): could not allocate space for a 
delete; will truncate on mount"


*Related patch:*

     I use git bisect to find the following patch introduces the issue.

     commit c8eaeac7b734347c3afba7008b7af62f37b9c140
     Author: Josef Bacik <josef@toxicpanda.com>
     Date:   Wed Apr 10 15:56:10 2019 -0400

         btrfs: reserve delalloc metadata differently
         ...


Anyone's reply will be appreciated.

--Hongzhi


[-- Attachment #2: run.sh --]
[-- Type: application/x-shellscript, Size: 604 bytes --]

[-- Attachment #3: test.c --]
[-- Type: text/x-csrc, Size: 3912 bytes --]

/**
 * mount a 512M btrfs block device.
 * and then fill the block device to the full with multi threads(ncpus+2).
 * and then unlink the files in the block device with multi threads.
 * 
 */


#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <fcntl.h>
#include <libgen.h>
#include <signal.h>
#include <stdarg.h>
#include <unistd.h>
#include <dirent.h>
#include <grp.h>
#include <sys/ioctl.h>     
#include <dirent.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>

//#define PATH_MAX 512

unsigned int nthreads;
static volatile int run;
struct worker *workers;
static int enospc_cnt;	//no space count
const char *homepath;

struct worker {
    char dir[PATH_MAX];
};

#define MIN(a, b) ({\
    typeof(a) _a = (a); \
    typeof(b) _b = (b); \
    _a < _b ? _a : _b; \
})

#define pr_err(a) do{\
    printf("%s:%d:\n", __FILE__, __LINE__); \
    perror(a); \
}while(0)

unsigned int get_ncpus_conf()
{
	unsigned int ncpus_conf = -1;

	if ( (ncpus_conf = sysconf(_SC_NPROCESSORS_CONF)) == -1 ) {
		pr_err("Fail to get ncpus!");
		exit(1);
	}

	return ncpus_conf;
}

void fill_fs(const char *path)
{
    int i = 0;
    char file[PATH_MAX];
    char buf[4096];
    size_t len;
    ssize_t ret;
    int fd;

    for (;;) {
        len = random() % (1024 * 102400);

        snprintf(file, sizeof(file), "%s/file%i", path, i++);
        printf("%s \n", file);

        fd = open(file, O_WRONLY | O_CREAT, 0700);
        if (fd == -1) {
            if (errno != ENOSPC)
                pr_err("Fail to open()");
				exit(1);

            printf("No space to open() \n");
            return;
        }

        while (len) {
            ret = write(fd, buf, MIN(len, sizeof(buf)));

            if (ret < 0) {
                close(fd);

                if (errno != ENOSPC)
                    pr_err("Fail to write()");

                printf("No space to write() \n");
                return;
            }

            len -= ret;
        }

        close(fd);
    }
}

static void *worker(void *p)
{

    struct worker *w = p;
    DIR *d;
    struct dirent *ent;
    char file[2*PATH_MAX];

    while (run) {
        fill_fs(w->dir);

         __atomic_fetch_add(&enospc_cnt, 1, __ATOMIC_SEQ_CST);

        d = opendir(w->dir);
        while ((ent = readdir(d))) {

            if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
                continue;

            snprintf(file, sizeof(file), "%s/%s", w->dir, ent->d_name);

            printf("Unlinking %s \n", file);

            if( unlink(file) ) {
				pr_err("Fail to unlink");
			}
            break;
        }
        closedir(d);
    }

    return NULL;
}


int main()
{
	unsigned int i, ms;

    homepath = getenv("HOME");

	nthreads = get_ncpus_conf() + 2;
    pthread_t threads[nthreads];

	workers = malloc(sizeof(struct worker) * nthreads);
	if (!workers) {
		pr_err("Fail to malloc workers!");
		exit(1);
	}

	for (i = 0; i < nthreads; i++) {
        snprintf(workers[i].dir, sizeof(workers[i].dir), \
        "%s/tmpmnt/thread%i", homepath, i + 1);

        if( mkdir(workers[i].dir, 0700) ){
			pr_err("Fail to mkdir workerdir");
			exit(1);
		}
    }

	printf("Running %d writer threads \n", nthreads);

	run = 1;
    for (i = 0; i < nthreads; i++) {
        if( pthread_create(&threads[i], NULL, worker, &workers[i]) ) {
			pr_err("Fail to create pthread");
			exit(1);
		}
    }

    for (ms = 0; ; ms++) {
        usleep(1000);

        if (ms >= 1000 && enospc_cnt)
            break;

        if (enospc_cnt > 100)
            break;
    }

    run = 0;
    for (i = 0; i < nthreads; i++){
        if( pthread_join(threads[i], NULL) ) {
			pr_err("Fail to pthread_join");
		}
    }

    printf("Got %d ENOSPC runtime %dms \n", enospc_cnt, ms);
	
	return 0;
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-09-05  1:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-04  8:02 Bug?: unlink cause btrfs error but other fs don't Hongzhi, Song
2019-09-04  8:39 ` Hongzhi, Song
2019-09-04 10:48 ` Josef Bacik
2019-09-05  1:36   ` Hongzhi, Song

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.