* [f2fs-dev] [PATCH] f2fs_io: add fragread command to evaluate fragmented buffer for reads @ 2025-03-04 1:10 Jaegeuk Kim via Linux-f2fs-devel 2025-03-11 12:10 ` Chao Yu via Linux-f2fs-devel 2025-03-17 21:27 ` [f2fs-dev] [f2fs-dev v2] " Jaegeuk Kim via Linux-f2fs-devel 0 siblings, 2 replies; 7+ messages in thread From: Jaegeuk Kim via Linux-f2fs-devel @ 2025-03-04 1:10 UTC (permalink / raw) To: linux-f2fs-devel; +Cc: Jaegeuk Kim From: Jaegeuk Kim <jaegeuk@google.com> This adds a fragread command in f2fs_io, which is able to measure the read performance on fragmented data buffer. Signed-off-by: Jaegeuk Kim <jaegeuk@google.com> --- tools/f2fs_io/f2fs_io.c | 110 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c index b72c26648f56..8431262575e0 100644 --- a/tools/f2fs_io/f2fs_io.c +++ b/tools/f2fs_io/f2fs_io.c @@ -1018,6 +1018,115 @@ static void do_read(int argc, char **argv, const struct cmd_desc *cmd) exit(0); } +#define fragread_desc "read data with a fragmented buffer from file" +#define fragread_help \ +"f2fs_io fragread [chunk_size in 4kb] [offset in chunk_size] [count] [advice] [file_path]\n\n" \ +"Read data in file_path and print nbytes\n" \ +"advice can be\n" \ +" 1 : set sequential|willneed\n" \ +" 0 : none\n" \ + +#ifndef PAGE_SIZE +#define PAGE_SIZE sysconf(_SC_PAGESIZE) +#endif +#define ALLOC_SIZE (2 * 1024 * 1024 - 4 * 1024) // 2MB - 4KB + +static void do_fragread(int argc, char **argv, const struct cmd_desc *cmd) +{ + u64 buf_size = 0, ret = 0, read_cnt = 0; + u64 offset; + char *buf = NULL; + uintptr_t idx, ptr; + unsigned bs, count, i; + u64 total_time = 0; + int flags = 0, alloc_count = 0; + void *mem_hole, **mem_holes; + int fd, advice; + + if (argc != 6) { + fputs("Excess arguments\n\n", stderr); + fputs(cmd->cmd_help, stderr); + exit(1); + } + + bs = atoi(argv[1]); + if (bs > 256 * 1024) + die("Too big chunk size - limit: 1GB"); + buf_size = bs * F2FS_DEFAULT_BLKSIZE; + + offset = atoi(argv[2]) * buf_size; + count = atoi(argv[3]); + advice = atoi(argv[4]); + mem_holes = xmalloc(sizeof(void *) * (buf_size / PAGE_SIZE)); + + /* 1. Allocate the buffer using mmap. */ + buf = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + /* 2. Loop and touch each page. */ + for (idx = (uintptr_t)buf; idx < (uintptr_t)buf + buf_size; + idx += PAGE_SIZE) + { + /* Touch the current page. */ + volatile char *page = (volatile char *)idx; + *page; + + /* 3. Allocate (2M - 4K) memory using mmap and touch all of it. */ + mem_hole = mmap(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (mem_hole == MAP_FAILED) + die_errno("map failed"); + + /* Store the allocated memory pointer. */ + mem_holes[alloc_count++] = mem_hole; + + /* Touch all allocated memory. */ + for (ptr = (uintptr_t)mem_hole; + ptr < (uintptr_t)mem_hole + ALLOC_SIZE; + ptr += PAGE_SIZE) { + volatile char *alloc_page = (volatile char *)ptr; + *alloc_page; + } + } + printf("Touched allocated memory: count = %u\n", alloc_count); + printf(" - allocated memory: = "); + for (idx = 0; idx < 5; idx++) + printf(" %p", mem_holes[idx]); + printf("\n"); + + fd = xopen(argv[5], O_RDONLY | flags, 0); + + if (advice) { + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, + POSIX_FADV_SEQUENTIAL) != 0) + die_errno("fadvise failed"); + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, + POSIX_FADV_WILLNEED) != 0) + die_errno("fadvise failed"); + printf("fadvise SEQUENTIAL|WILLNEED to a file: %s\n", argv[5]); + } + + total_time = get_current_us(); + + for (i = 0; i < count; i++) { + ret = pread(fd, buf, buf_size, offset + buf_size * i); + if (ret != buf_size) { + printf("pread expected: %"PRIu64", readed: %"PRIu64"\n", + buf_size, ret); + if (ret > 0) + read_cnt += ret; + break; + } + + read_cnt += ret; + } + printf("Fragmented_Read %"PRIu64" bytes total_time = %"PRIu64" us, BW = %.Lf MB/s\n", + read_cnt, get_current_us() - total_time, + ((long double)read_cnt / (get_current_us() - total_time))); + printf("\n"); + exit(0); +} + #define randread_desc "random read data from file" #define randread_help \ "f2fs_io randread [chunk_size in 4kb] [count] [IO] [advise] [file_path]\n\n" \ @@ -2002,6 +2111,7 @@ const struct cmd_desc cmd_list[] = { CMD(write_advice), CMD(read), CMD(randread), + CMD(fragread), CMD(fiemap), CMD(gc_urgent), CMD(defrag_file), -- 2.48.1.711.g2feabab25a-goog _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [f2fs-dev] [PATCH] f2fs_io: add fragread command to evaluate fragmented buffer for reads 2025-03-04 1:10 [f2fs-dev] [PATCH] f2fs_io: add fragread command to evaluate fragmented buffer for reads Jaegeuk Kim via Linux-f2fs-devel @ 2025-03-11 12:10 ` Chao Yu via Linux-f2fs-devel 2025-03-11 19:36 ` Jaegeuk Kim via Linux-f2fs-devel 2025-03-17 21:27 ` [f2fs-dev] [f2fs-dev v2] " Jaegeuk Kim via Linux-f2fs-devel 1 sibling, 1 reply; 7+ messages in thread From: Chao Yu via Linux-f2fs-devel @ 2025-03-11 12:10 UTC (permalink / raw) To: Jaegeuk Kim, linux-f2fs-devel; +Cc: Jaegeuk Kim On 3/4/25 09:10, Jaegeuk Kim via Linux-f2fs-devel wrote: > From: Jaegeuk Kim <jaegeuk@google.com> > > This adds a fragread command in f2fs_io, which is able to measure the > read performance on fragmented data buffer. > > Signed-off-by: Jaegeuk Kim <jaegeuk@google.com> > --- > tools/f2fs_io/f2fs_io.c | 110 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 110 insertions(+) > > diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c > index b72c26648f56..8431262575e0 100644 > --- a/tools/f2fs_io/f2fs_io.c > +++ b/tools/f2fs_io/f2fs_io.c > @@ -1018,6 +1018,115 @@ static void do_read(int argc, char **argv, const struct cmd_desc *cmd) > exit(0); > } > > +#define fragread_desc "read data with a fragmented buffer from file" > +#define fragread_help \ > +"f2fs_io fragread [chunk_size in 4kb] [offset in chunk_size] [count] [advice] [file_path]\n\n" \ > +"Read data in file_path and print nbytes\n" \ > +"advice can be\n" \ > +" 1 : set sequential|willneed\n" \ > +" 0 : none\n" \ > + > +#ifndef PAGE_SIZE > +#define PAGE_SIZE sysconf(_SC_PAGESIZE) > +#endif > +#define ALLOC_SIZE (2 * 1024 * 1024 - 4 * 1024) // 2MB - 4KB > + > +static void do_fragread(int argc, char **argv, const struct cmd_desc *cmd) > +{ > + u64 buf_size = 0, ret = 0, read_cnt = 0; > + u64 offset; > + char *buf = NULL; > + uintptr_t idx, ptr; > + unsigned bs, count, i; > + u64 total_time = 0; > + int flags = 0, alloc_count = 0; > + void *mem_hole, **mem_holes; > + int fd, advice; > + > + if (argc != 6) { > + fputs("Excess arguments\n\n", stderr); > + fputs(cmd->cmd_help, stderr); > + exit(1); > + } > + > + bs = atoi(argv[1]); > + if (bs > 256 * 1024) > + die("Too big chunk size - limit: 1GB"); > + buf_size = bs * F2FS_DEFAULT_BLKSIZE; > + > + offset = atoi(argv[2]) * buf_size; > + count = atoi(argv[3]); > + advice = atoi(argv[4]); > + mem_holes = xmalloc(sizeof(void *) * (buf_size / PAGE_SIZE)); > + > + /* 1. Allocate the buffer using mmap. */ > + buf = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > + > + /* 2. Loop and touch each page. */ > + for (idx = (uintptr_t)buf; idx < (uintptr_t)buf + buf_size; > + idx += PAGE_SIZE) > + { > + /* Touch the current page. */ > + volatile char *page = (volatile char *)idx; > + *page; > + > + /* 3. Allocate (2M - 4K) memory using mmap and touch all of it. */ > + mem_hole = mmap(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > + if (mem_hole == MAP_FAILED) > + die_errno("map failed"); > + > + /* Store the allocated memory pointer. */ > + mem_holes[alloc_count++] = mem_hole; Do we need to call mlock to hold allocated cache in the memory, if administrator enables swap, memory fragment will be gone once anonymous pages are swapped to device? Thanks, > + > + /* Touch all allocated memory. */ > + for (ptr = (uintptr_t)mem_hole; > + ptr < (uintptr_t)mem_hole + ALLOC_SIZE; > + ptr += PAGE_SIZE) { > + volatile char *alloc_page = (volatile char *)ptr; > + *alloc_page; > + } > + } > + printf("Touched allocated memory: count = %u\n", alloc_count); > + printf(" - allocated memory: = "); > + for (idx = 0; idx < 5; idx++) > + printf(" %p", mem_holes[idx]); > + printf("\n"); > + > + fd = xopen(argv[5], O_RDONLY | flags, 0); > + > + if (advice) { > + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, > + POSIX_FADV_SEQUENTIAL) != 0) > + die_errno("fadvise failed"); > + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, > + POSIX_FADV_WILLNEED) != 0) > + die_errno("fadvise failed"); > + printf("fadvise SEQUENTIAL|WILLNEED to a file: %s\n", argv[5]); > + } > + > + total_time = get_current_us(); > + > + for (i = 0; i < count; i++) { > + ret = pread(fd, buf, buf_size, offset + buf_size * i); > + if (ret != buf_size) { > + printf("pread expected: %"PRIu64", readed: %"PRIu64"\n", > + buf_size, ret); > + if (ret > 0) > + read_cnt += ret; > + break; > + } > + > + read_cnt += ret; > + } > + printf("Fragmented_Read %"PRIu64" bytes total_time = %"PRIu64" us, BW = %.Lf MB/s\n", > + read_cnt, get_current_us() - total_time, > + ((long double)read_cnt / (get_current_us() - total_time))); > + printf("\n"); > + exit(0); > +} > + > #define randread_desc "random read data from file" > #define randread_help \ > "f2fs_io randread [chunk_size in 4kb] [count] [IO] [advise] [file_path]\n\n" \ > @@ -2002,6 +2111,7 @@ const struct cmd_desc cmd_list[] = { > CMD(write_advice), > CMD(read), > CMD(randread), > + CMD(fragread), > CMD(fiemap), > CMD(gc_urgent), > CMD(defrag_file), _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [f2fs-dev] [PATCH] f2fs_io: add fragread command to evaluate fragmented buffer for reads 2025-03-11 12:10 ` Chao Yu via Linux-f2fs-devel @ 2025-03-11 19:36 ` Jaegeuk Kim via Linux-f2fs-devel 2025-03-12 3:02 ` Chao Yu via Linux-f2fs-devel 0 siblings, 1 reply; 7+ messages in thread From: Jaegeuk Kim via Linux-f2fs-devel @ 2025-03-11 19:36 UTC (permalink / raw) To: Chao Yu; +Cc: linux-f2fs-devel On 03/11, Chao Yu wrote: > On 3/4/25 09:10, Jaegeuk Kim via Linux-f2fs-devel wrote: > > From: Jaegeuk Kim <jaegeuk@google.com> > > > > This adds a fragread command in f2fs_io, which is able to measure the > > read performance on fragmented data buffer. > > > > Signed-off-by: Jaegeuk Kim <jaegeuk@google.com> > > --- > > tools/f2fs_io/f2fs_io.c | 110 ++++++++++++++++++++++++++++++++++++++++ > > 1 file changed, 110 insertions(+) > > > > diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c > > index b72c26648f56..8431262575e0 100644 > > --- a/tools/f2fs_io/f2fs_io.c > > +++ b/tools/f2fs_io/f2fs_io.c > > @@ -1018,6 +1018,115 @@ static void do_read(int argc, char **argv, const struct cmd_desc *cmd) > > exit(0); > > } > > > > +#define fragread_desc "read data with a fragmented buffer from file" > > +#define fragread_help \ > > +"f2fs_io fragread [chunk_size in 4kb] [offset in chunk_size] [count] [advice] [file_path]\n\n" \ > > +"Read data in file_path and print nbytes\n" \ > > +"advice can be\n" \ > > +" 1 : set sequential|willneed\n" \ > > +" 0 : none\n" \ > > + > > +#ifndef PAGE_SIZE > > +#define PAGE_SIZE sysconf(_SC_PAGESIZE) > > +#endif > > +#define ALLOC_SIZE (2 * 1024 * 1024 - 4 * 1024) // 2MB - 4KB > > + > > +static void do_fragread(int argc, char **argv, const struct cmd_desc *cmd) > > +{ > > + u64 buf_size = 0, ret = 0, read_cnt = 0; > > + u64 offset; > > + char *buf = NULL; > > + uintptr_t idx, ptr; > > + unsigned bs, count, i; > > + u64 total_time = 0; > > + int flags = 0, alloc_count = 0; > > + void *mem_hole, **mem_holes; > > + int fd, advice; > > + > > + if (argc != 6) { > > + fputs("Excess arguments\n\n", stderr); > > + fputs(cmd->cmd_help, stderr); > > + exit(1); > > + } > > + > > + bs = atoi(argv[1]); > > + if (bs > 256 * 1024) > > + die("Too big chunk size - limit: 1GB"); > > + buf_size = bs * F2FS_DEFAULT_BLKSIZE; > > + > > + offset = atoi(argv[2]) * buf_size; > > + count = atoi(argv[3]); > > + advice = atoi(argv[4]); > > + mem_holes = xmalloc(sizeof(void *) * (buf_size / PAGE_SIZE)); > > + > > + /* 1. Allocate the buffer using mmap. */ > > + buf = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, > > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > > + > > + /* 2. Loop and touch each page. */ > > + for (idx = (uintptr_t)buf; idx < (uintptr_t)buf + buf_size; > > + idx += PAGE_SIZE) > > + { > > + /* Touch the current page. */ > > + volatile char *page = (volatile char *)idx; > > + *page; > > + > > + /* 3. Allocate (2M - 4K) memory using mmap and touch all of it. */ > > + mem_hole = mmap(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE, > > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > > + if (mem_hole == MAP_FAILED) > > + die_errno("map failed"); > > + > > + /* Store the allocated memory pointer. */ > > + mem_holes[alloc_count++] = mem_hole; > > Do we need to call mlock to hold allocated cache in the memory, if > administrator enables swap, memory fragment will be gone once anonymous > pages are swapped to device? Hmm, the test is going to use this very intensively, so is it possible? > > Thanks, > > > + > > + /* Touch all allocated memory. */ > > + for (ptr = (uintptr_t)mem_hole; > > + ptr < (uintptr_t)mem_hole + ALLOC_SIZE; > > + ptr += PAGE_SIZE) { > > + volatile char *alloc_page = (volatile char *)ptr; > > + *alloc_page; > > + } > > + } > > + printf("Touched allocated memory: count = %u\n", alloc_count); > > + printf(" - allocated memory: = "); > > + for (idx = 0; idx < 5; idx++) > > + printf(" %p", mem_holes[idx]); > > + printf("\n"); > > + > > + fd = xopen(argv[5], O_RDONLY | flags, 0); > > + > > + if (advice) { > > + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, > > + POSIX_FADV_SEQUENTIAL) != 0) > > + die_errno("fadvise failed"); > > + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, > > + POSIX_FADV_WILLNEED) != 0) > > + die_errno("fadvise failed"); > > + printf("fadvise SEQUENTIAL|WILLNEED to a file: %s\n", argv[5]); > > + } > > + > > + total_time = get_current_us(); > > + > > + for (i = 0; i < count; i++) { > > + ret = pread(fd, buf, buf_size, offset + buf_size * i); > > + if (ret != buf_size) { > > + printf("pread expected: %"PRIu64", readed: %"PRIu64"\n", > > + buf_size, ret); > > + if (ret > 0) > > + read_cnt += ret; > > + break; > > + } > > + > > + read_cnt += ret; > > + } > > + printf("Fragmented_Read %"PRIu64" bytes total_time = %"PRIu64" us, BW = %.Lf MB/s\n", > > + read_cnt, get_current_us() - total_time, > > + ((long double)read_cnt / (get_current_us() - total_time))); > > + printf("\n"); > > + exit(0); > > +} > > + > > #define randread_desc "random read data from file" > > #define randread_help \ > > "f2fs_io randread [chunk_size in 4kb] [count] [IO] [advise] [file_path]\n\n" \ > > @@ -2002,6 +2111,7 @@ const struct cmd_desc cmd_list[] = { > > CMD(write_advice), > > CMD(read), > > CMD(randread), > > + CMD(fragread), > > CMD(fiemap), > > CMD(gc_urgent), > > CMD(defrag_file), _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [f2fs-dev] [PATCH] f2fs_io: add fragread command to evaluate fragmented buffer for reads 2025-03-11 19:36 ` Jaegeuk Kim via Linux-f2fs-devel @ 2025-03-12 3:02 ` Chao Yu via Linux-f2fs-devel 2025-03-17 3:30 ` Chao Yu via Linux-f2fs-devel 0 siblings, 1 reply; 7+ messages in thread From: Chao Yu via Linux-f2fs-devel @ 2025-03-12 3:02 UTC (permalink / raw) To: Jaegeuk Kim; +Cc: linux-f2fs-devel On 3/12/25 03:36, Jaegeuk Kim wrote: > On 03/11, Chao Yu wrote: >> On 3/4/25 09:10, Jaegeuk Kim via Linux-f2fs-devel wrote: >>> From: Jaegeuk Kim <jaegeuk@google.com> >>> >>> This adds a fragread command in f2fs_io, which is able to measure the >>> read performance on fragmented data buffer. >>> >>> Signed-off-by: Jaegeuk Kim <jaegeuk@google.com> >>> --- >>> tools/f2fs_io/f2fs_io.c | 110 ++++++++++++++++++++++++++++++++++++++++ >>> 1 file changed, 110 insertions(+) >>> >>> diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c >>> index b72c26648f56..8431262575e0 100644 >>> --- a/tools/f2fs_io/f2fs_io.c >>> +++ b/tools/f2fs_io/f2fs_io.c >>> @@ -1018,6 +1018,115 @@ static void do_read(int argc, char **argv, const struct cmd_desc *cmd) >>> exit(0); >>> } >>> >>> +#define fragread_desc "read data with a fragmented buffer from file" >>> +#define fragread_help \ >>> +"f2fs_io fragread [chunk_size in 4kb] [offset in chunk_size] [count] [advice] [file_path]\n\n" \ >>> +"Read data in file_path and print nbytes\n" \ >>> +"advice can be\n" \ >>> +" 1 : set sequential|willneed\n" \ >>> +" 0 : none\n" \ >>> + >>> +#ifndef PAGE_SIZE >>> +#define PAGE_SIZE sysconf(_SC_PAGESIZE) >>> +#endif >>> +#define ALLOC_SIZE (2 * 1024 * 1024 - 4 * 1024) // 2MB - 4KB >>> + >>> +static void do_fragread(int argc, char **argv, const struct cmd_desc *cmd) >>> +{ >>> + u64 buf_size = 0, ret = 0, read_cnt = 0; >>> + u64 offset; >>> + char *buf = NULL; >>> + uintptr_t idx, ptr; >>> + unsigned bs, count, i; >>> + u64 total_time = 0; >>> + int flags = 0, alloc_count = 0; >>> + void *mem_hole, **mem_holes; >>> + int fd, advice; >>> + >>> + if (argc != 6) { >>> + fputs("Excess arguments\n\n", stderr); >>> + fputs(cmd->cmd_help, stderr); >>> + exit(1); >>> + } >>> + >>> + bs = atoi(argv[1]); >>> + if (bs > 256 * 1024) >>> + die("Too big chunk size - limit: 1GB"); >>> + buf_size = bs * F2FS_DEFAULT_BLKSIZE; >>> + >>> + offset = atoi(argv[2]) * buf_size; >>> + count = atoi(argv[3]); >>> + advice = atoi(argv[4]); >>> + mem_holes = xmalloc(sizeof(void *) * (buf_size / PAGE_SIZE)); >>> + >>> + /* 1. Allocate the buffer using mmap. */ >>> + buf = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, >>> + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); >>> + >>> + /* 2. Loop and touch each page. */ >>> + for (idx = (uintptr_t)buf; idx < (uintptr_t)buf + buf_size; >>> + idx += PAGE_SIZE) >>> + { >>> + /* Touch the current page. */ >>> + volatile char *page = (volatile char *)idx; >>> + *page; >>> + >>> + /* 3. Allocate (2M - 4K) memory using mmap and touch all of it. */ >>> + mem_hole = mmap(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE, >>> + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); >>> + if (mem_hole == MAP_FAILED) >>> + die_errno("map failed"); >>> + >>> + /* Store the allocated memory pointer. */ >>> + mem_holes[alloc_count++] = mem_hole; >> >> Do we need to call mlock to hold allocated cache in the memory, if >> administrator enables swap, memory fragment will be gone once anonymous >> pages are swapped to device? > > Hmm, the test is going to use this very intensively, so is it possible? Not sure, but I doubt it is possible to happen in low-end device? due to it has very less memory and system may has already token the most of memory. Thanks, > >> >> Thanks, >> >>> + >>> + /* Touch all allocated memory. */ >>> + for (ptr = (uintptr_t)mem_hole; >>> + ptr < (uintptr_t)mem_hole + ALLOC_SIZE; >>> + ptr += PAGE_SIZE) { >>> + volatile char *alloc_page = (volatile char *)ptr; >>> + *alloc_page; >>> + } >>> + } >>> + printf("Touched allocated memory: count = %u\n", alloc_count); >>> + printf(" - allocated memory: = "); >>> + for (idx = 0; idx < 5; idx++) >>> + printf(" %p", mem_holes[idx]); >>> + printf("\n"); >>> + >>> + fd = xopen(argv[5], O_RDONLY | flags, 0); >>> + >>> + if (advice) { >>> + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, >>> + POSIX_FADV_SEQUENTIAL) != 0) >>> + die_errno("fadvise failed"); >>> + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, >>> + POSIX_FADV_WILLNEED) != 0) >>> + die_errno("fadvise failed"); >>> + printf("fadvise SEQUENTIAL|WILLNEED to a file: %s\n", argv[5]); >>> + } >>> + >>> + total_time = get_current_us(); >>> + >>> + for (i = 0; i < count; i++) { >>> + ret = pread(fd, buf, buf_size, offset + buf_size * i); >>> + if (ret != buf_size) { >>> + printf("pread expected: %"PRIu64", readed: %"PRIu64"\n", >>> + buf_size, ret); >>> + if (ret > 0) >>> + read_cnt += ret; >>> + break; >>> + } >>> + >>> + read_cnt += ret; >>> + } >>> + printf("Fragmented_Read %"PRIu64" bytes total_time = %"PRIu64" us, BW = %.Lf MB/s\n", >>> + read_cnt, get_current_us() - total_time, >>> + ((long double)read_cnt / (get_current_us() - total_time))); >>> + printf("\n"); >>> + exit(0); >>> +} >>> + >>> #define randread_desc "random read data from file" >>> #define randread_help \ >>> "f2fs_io randread [chunk_size in 4kb] [count] [IO] [advise] [file_path]\n\n" \ >>> @@ -2002,6 +2111,7 @@ const struct cmd_desc cmd_list[] = { >>> CMD(write_advice), >>> CMD(read), >>> CMD(randread), >>> + CMD(fragread), >>> CMD(fiemap), >>> CMD(gc_urgent), >>> CMD(defrag_file), _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [f2fs-dev] [PATCH] f2fs_io: add fragread command to evaluate fragmented buffer for reads 2025-03-12 3:02 ` Chao Yu via Linux-f2fs-devel @ 2025-03-17 3:30 ` Chao Yu via Linux-f2fs-devel 0 siblings, 0 replies; 7+ messages in thread From: Chao Yu via Linux-f2fs-devel @ 2025-03-17 3:30 UTC (permalink / raw) To: Jaegeuk Kim; +Cc: linux-f2fs-devel On 3/12/25 11:02, Chao Yu wrote: > On 3/12/25 03:36, Jaegeuk Kim wrote: >> On 03/11, Chao Yu wrote: >>> On 3/4/25 09:10, Jaegeuk Kim via Linux-f2fs-devel wrote: >>>> From: Jaegeuk Kim <jaegeuk@google.com> >>>> >>>> This adds a fragread command in f2fs_io, which is able to measure the >>>> read performance on fragmented data buffer. >>>> >>>> Signed-off-by: Jaegeuk Kim <jaegeuk@google.com> >>>> --- >>>> tools/f2fs_io/f2fs_io.c | 110 ++++++++++++++++++++++++++++++++++++++++ >>>> 1 file changed, 110 insertions(+) >>>> >>>> diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c >>>> index b72c26648f56..8431262575e0 100644 >>>> --- a/tools/f2fs_io/f2fs_io.c >>>> +++ b/tools/f2fs_io/f2fs_io.c >>>> @@ -1018,6 +1018,115 @@ static void do_read(int argc, char **argv, const struct cmd_desc *cmd) >>>> exit(0); >>>> } >>>> >>>> +#define fragread_desc "read data with a fragmented buffer from file" >>>> +#define fragread_help \ >>>> +"f2fs_io fragread [chunk_size in 4kb] [offset in chunk_size] [count] [advice] [file_path]\n\n" \ >>>> +"Read data in file_path and print nbytes\n" \ >>>> +"advice can be\n" \ >>>> +" 1 : set sequential|willneed\n" \ >>>> +" 0 : none\n" \ >>>> + >>>> +#ifndef PAGE_SIZE >>>> +#define PAGE_SIZE sysconf(_SC_PAGESIZE) >>>> +#endif >>>> +#define ALLOC_SIZE (2 * 1024 * 1024 - 4 * 1024) // 2MB - 4KB >>>> + >>>> +static void do_fragread(int argc, char **argv, const struct cmd_desc *cmd) >>>> +{ >>>> + u64 buf_size = 0, ret = 0, read_cnt = 0; >>>> + u64 offset; >>>> + char *buf = NULL; >>>> + uintptr_t idx, ptr; >>>> + unsigned bs, count, i; >>>> + u64 total_time = 0; >>>> + int flags = 0, alloc_count = 0; >>>> + void *mem_hole, **mem_holes; >>>> + int fd, advice; >>>> + >>>> + if (argc != 6) { >>>> + fputs("Excess arguments\n\n", stderr); >>>> + fputs(cmd->cmd_help, stderr); >>>> + exit(1); >>>> + } >>>> + >>>> + bs = atoi(argv[1]); >>>> + if (bs > 256 * 1024) >>>> + die("Too big chunk size - limit: 1GB"); >>>> + buf_size = bs * F2FS_DEFAULT_BLKSIZE; >>>> + >>>> + offset = atoi(argv[2]) * buf_size; >>>> + count = atoi(argv[3]); >>>> + advice = atoi(argv[4]); >>>> + mem_holes = xmalloc(sizeof(void *) * (buf_size / PAGE_SIZE)); >>>> + >>>> + /* 1. Allocate the buffer using mmap. */ >>>> + buf = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, >>>> + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); >>>> + >>>> + /* 2. Loop and touch each page. */ >>>> + for (idx = (uintptr_t)buf; idx < (uintptr_t)buf + buf_size; >>>> + idx += PAGE_SIZE) >>>> + { >>>> + /* Touch the current page. */ >>>> + volatile char *page = (volatile char *)idx; >>>> + *page; >>>> + >>>> + /* 3. Allocate (2M - 4K) memory using mmap and touch all of it. */ >>>> + mem_hole = mmap(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE, >>>> + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); >>>> + if (mem_hole == MAP_FAILED) >>>> + die_errno("map failed"); >>>> + >>>> + /* Store the allocated memory pointer. */ >>>> + mem_holes[alloc_count++] = mem_hole; >>> >>> Do we need to call mlock to hold allocated cache in the memory, if >>> administrator enables swap, memory fragment will be gone once anonymous >>> pages are swapped to device? >> >> Hmm, the test is going to use this very intensively, so is it possible? > > Not sure, but I doubt it is possible to happen in low-end device? due to it has > very less memory and system may has already token the most of memory. Anyway, code looks clean, I think we can take a look at this later. Reviewed-by: Chao Yu <chao@kernel.org> Thanks, > > Thanks, > >> >>> >>> Thanks, >>> >>>> + >>>> + /* Touch all allocated memory. */ >>>> + for (ptr = (uintptr_t)mem_hole; >>>> + ptr < (uintptr_t)mem_hole + ALLOC_SIZE; >>>> + ptr += PAGE_SIZE) { >>>> + volatile char *alloc_page = (volatile char *)ptr; >>>> + *alloc_page; >>>> + } >>>> + } >>>> + printf("Touched allocated memory: count = %u\n", alloc_count); >>>> + printf(" - allocated memory: = "); >>>> + for (idx = 0; idx < 5; idx++) >>>> + printf(" %p", mem_holes[idx]); >>>> + printf("\n"); >>>> + >>>> + fd = xopen(argv[5], O_RDONLY | flags, 0); >>>> + >>>> + if (advice) { >>>> + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, >>>> + POSIX_FADV_SEQUENTIAL) != 0) >>>> + die_errno("fadvise failed"); >>>> + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, >>>> + POSIX_FADV_WILLNEED) != 0) >>>> + die_errno("fadvise failed"); >>>> + printf("fadvise SEQUENTIAL|WILLNEED to a file: %s\n", argv[5]); >>>> + } >>>> + >>>> + total_time = get_current_us(); >>>> + >>>> + for (i = 0; i < count; i++) { >>>> + ret = pread(fd, buf, buf_size, offset + buf_size * i); >>>> + if (ret != buf_size) { >>>> + printf("pread expected: %"PRIu64", readed: %"PRIu64"\n", >>>> + buf_size, ret); >>>> + if (ret > 0) >>>> + read_cnt += ret; >>>> + break; >>>> + } >>>> + >>>> + read_cnt += ret; >>>> + } >>>> + printf("Fragmented_Read %"PRIu64" bytes total_time = %"PRIu64" us, BW = %.Lf MB/s\n", >>>> + read_cnt, get_current_us() - total_time, >>>> + ((long double)read_cnt / (get_current_us() - total_time))); >>>> + printf("\n"); >>>> + exit(0); >>>> +} >>>> + >>>> #define randread_desc "random read data from file" >>>> #define randread_help \ >>>> "f2fs_io randread [chunk_size in 4kb] [count] [IO] [advise] [file_path]\n\n" \ >>>> @@ -2002,6 +2111,7 @@ const struct cmd_desc cmd_list[] = { >>>> CMD(write_advice), >>>> CMD(read), >>>> CMD(randread), >>>> + CMD(fragread), >>>> CMD(fiemap), >>>> CMD(gc_urgent), >>>> CMD(defrag_file), > _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [f2fs-dev] [f2fs-dev v2] [PATCH] f2fs_io: add fragread command to evaluate fragmented buffer for reads 2025-03-04 1:10 [f2fs-dev] [PATCH] f2fs_io: add fragread command to evaluate fragmented buffer for reads Jaegeuk Kim via Linux-f2fs-devel 2025-03-11 12:10 ` Chao Yu via Linux-f2fs-devel @ 2025-03-17 21:27 ` Jaegeuk Kim via Linux-f2fs-devel 2025-03-18 3:12 ` Jaegeuk Kim via Linux-f2fs-devel 1 sibling, 1 reply; 7+ messages in thread From: Jaegeuk Kim via Linux-f2fs-devel @ 2025-03-17 21:27 UTC (permalink / raw) To: linux-f2fs-devel This adds a fragread command in f2fs_io, which is able to measure the read performance on fragmented data buffer. Signed-off-by: Jaegeuk Kim <jaegeuk@google.com> --- Change log from v1: - add mlock tools/f2fs_io/f2fs_io.c | 114 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c index 44d389dbd771..57a931d5769c 100644 --- a/tools/f2fs_io/f2fs_io.c +++ b/tools/f2fs_io/f2fs_io.c @@ -1005,6 +1005,119 @@ static void do_read(int argc, char **argv, const struct cmd_desc *cmd) exit(0); } +#define fragread_desc "read data with a fragmented buffer from file" +#define fragread_help \ +"f2fs_io fragread [chunk_size in 4kb] [offset in chunk_size] [count] [advice] [file_path]\n\n" \ +"Read data in file_path and print nbytes\n" \ +"advice can be\n" \ +" 1 : set sequential|willneed\n" \ +" 0 : none\n" \ + +#ifndef PAGE_SIZE +#define PAGE_SIZE sysconf(_SC_PAGESIZE) +#endif +#define ALLOC_SIZE (2 * 1024 * 1024 - 4 * 1024) // 2MB - 4KB + +static void do_fragread(int argc, char **argv, const struct cmd_desc *cmd) +{ + u64 buf_size = 0, ret = 0, read_cnt = 0; + u64 offset; + char *buf = NULL; + uintptr_t idx, ptr; + unsigned bs, count, i; + u64 total_time = 0; + int flags = 0, alloc_count = 0; + void *mem_hole, **mem_holes; + int fd, advice; + + if (argc != 6) { + fputs("Excess arguments\n\n", stderr); + fputs(cmd->cmd_help, stderr); + exit(1); + } + + bs = atoi(argv[1]); + if (bs > 256 * 1024) + die("Too big chunk size - limit: 1GB"); + buf_size = bs * F2FS_DEFAULT_BLKSIZE; + + offset = atoi(argv[2]) * buf_size; + count = atoi(argv[3]); + advice = atoi(argv[4]); + mem_holes = xmalloc(sizeof(void *) * (buf_size / PAGE_SIZE)); + + /* 1. Allocate the buffer using mmap. */ + buf = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + /* 2. Loop and touch each page. */ + for (idx = (uintptr_t)buf; idx < (uintptr_t)buf + buf_size; + idx += PAGE_SIZE) + { + /* Touch the current page. */ + volatile char *page = (volatile char *)idx; + *page; + + /* 3. Allocate (2M - 4K) memory using mmap and touch all of it. */ + mem_hole = mmap(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (mem_hole == MAP_FAILED) + die_errno("map failed"); + + /* Store the allocated memory pointer. */ + mem_holes[alloc_count++] = mem_hole; + + /* Touch all allocated memory. */ + for (ptr = (uintptr_t)mem_hole; + ptr < (uintptr_t)mem_hole + ALLOC_SIZE; + ptr += PAGE_SIZE) { + volatile char *alloc_page = (volatile char *)ptr; + *alloc_page; + } + } + printf("Touched allocated memory: count = %u\n", alloc_count); + printf(" - allocated memory: = "); + for (idx = 0; idx < 5; idx++) + printf(" %p", mem_holes[idx]); + printf("\n"); + + /* Pin the pages. */ + if (mlock(buf, buf_size)) + die_errno("mlock failed"); + + fd = xopen(argv[5], O_RDONLY | flags, 0); + + if (advice) { + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, + POSIX_FADV_SEQUENTIAL) != 0) + die_errno("fadvise failed"); + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, + POSIX_FADV_WILLNEED) != 0) + die_errno("fadvise failed"); + printf("fadvise SEQUENTIAL|WILLNEED to a file: %s\n", argv[5]); + } + + total_time = get_current_us(); + + for (i = 0; i < count; i++) { + ret = pread(fd, buf, buf_size, offset + buf_size * i); + if (ret != buf_size) { + printf("pread expected: %"PRIu64", readed: %"PRIu64"\n", + buf_size, ret); + if (ret > 0) + read_cnt += ret; + break; + } + + read_cnt += ret; + } + printf("Fragmented_Read %"PRIu64" bytes total_time = %"PRIu64" us, BW = %.Lf MB/s\n", + read_cnt, get_current_us() - total_time, + ((long double)read_cnt / (get_current_us() - total_time))); + printf("\n"); + exit(0); +} + #define randread_desc "random read data from file" #define randread_help \ "f2fs_io randread [chunk_size in 4kb] [count] [IO] [advise] [file_path]\n\n" \ @@ -1989,6 +2102,7 @@ const struct cmd_desc cmd_list[] = { CMD(write_advice), CMD(read), CMD(randread), + CMD(fragread), CMD(fiemap), CMD(gc_urgent), CMD(defrag_file), -- 2.49.0.rc1.451.g8f38331e32-goog _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [f2fs-dev] [f2fs-dev v2] [PATCH] f2fs_io: add fragread command to evaluate fragmented buffer for reads 2025-03-17 21:27 ` [f2fs-dev] [f2fs-dev v2] " Jaegeuk Kim via Linux-f2fs-devel @ 2025-03-18 3:12 ` Jaegeuk Kim via Linux-f2fs-devel 0 siblings, 0 replies; 7+ messages in thread From: Jaegeuk Kim via Linux-f2fs-devel @ 2025-03-18 3:12 UTC (permalink / raw) To: linux-f2fs-devel Ping. On 03/17, Jaegeuk Kim via Linux-f2fs-devel wrote: > This adds a fragread command in f2fs_io, which is able to measure the > read performance on fragmented data buffer. > > Signed-off-by: Jaegeuk Kim <jaegeuk@google.com> > --- > > Change log from v1: > - add mlock > > tools/f2fs_io/f2fs_io.c | 114 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 114 insertions(+) > > diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c > index 44d389dbd771..57a931d5769c 100644 > --- a/tools/f2fs_io/f2fs_io.c > +++ b/tools/f2fs_io/f2fs_io.c > @@ -1005,6 +1005,119 @@ static void do_read(int argc, char **argv, const struct cmd_desc *cmd) > exit(0); > } > > +#define fragread_desc "read data with a fragmented buffer from file" > +#define fragread_help \ > +"f2fs_io fragread [chunk_size in 4kb] [offset in chunk_size] [count] [advice] [file_path]\n\n" \ > +"Read data in file_path and print nbytes\n" \ > +"advice can be\n" \ > +" 1 : set sequential|willneed\n" \ > +" 0 : none\n" \ > + > +#ifndef PAGE_SIZE > +#define PAGE_SIZE sysconf(_SC_PAGESIZE) > +#endif > +#define ALLOC_SIZE (2 * 1024 * 1024 - 4 * 1024) // 2MB - 4KB > + > +static void do_fragread(int argc, char **argv, const struct cmd_desc *cmd) > +{ > + u64 buf_size = 0, ret = 0, read_cnt = 0; > + u64 offset; > + char *buf = NULL; > + uintptr_t idx, ptr; > + unsigned bs, count, i; > + u64 total_time = 0; > + int flags = 0, alloc_count = 0; > + void *mem_hole, **mem_holes; > + int fd, advice; > + > + if (argc != 6) { > + fputs("Excess arguments\n\n", stderr); > + fputs(cmd->cmd_help, stderr); > + exit(1); > + } > + > + bs = atoi(argv[1]); > + if (bs > 256 * 1024) > + die("Too big chunk size - limit: 1GB"); > + buf_size = bs * F2FS_DEFAULT_BLKSIZE; > + > + offset = atoi(argv[2]) * buf_size; > + count = atoi(argv[3]); > + advice = atoi(argv[4]); > + mem_holes = xmalloc(sizeof(void *) * (buf_size / PAGE_SIZE)); > + > + /* 1. Allocate the buffer using mmap. */ > + buf = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > + > + /* 2. Loop and touch each page. */ > + for (idx = (uintptr_t)buf; idx < (uintptr_t)buf + buf_size; > + idx += PAGE_SIZE) > + { > + /* Touch the current page. */ > + volatile char *page = (volatile char *)idx; > + *page; > + > + /* 3. Allocate (2M - 4K) memory using mmap and touch all of it. */ > + mem_hole = mmap(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > + if (mem_hole == MAP_FAILED) > + die_errno("map failed"); > + > + /* Store the allocated memory pointer. */ > + mem_holes[alloc_count++] = mem_hole; > + > + /* Touch all allocated memory. */ > + for (ptr = (uintptr_t)mem_hole; > + ptr < (uintptr_t)mem_hole + ALLOC_SIZE; > + ptr += PAGE_SIZE) { > + volatile char *alloc_page = (volatile char *)ptr; > + *alloc_page; > + } > + } > + printf("Touched allocated memory: count = %u\n", alloc_count); > + printf(" - allocated memory: = "); > + for (idx = 0; idx < 5; idx++) > + printf(" %p", mem_holes[idx]); > + printf("\n"); > + > + /* Pin the pages. */ > + if (mlock(buf, buf_size)) > + die_errno("mlock failed"); > + > + fd = xopen(argv[5], O_RDONLY | flags, 0); > + > + if (advice) { > + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, > + POSIX_FADV_SEQUENTIAL) != 0) > + die_errno("fadvise failed"); > + if (posix_fadvise(fd, 0, F2FS_DEFAULT_BLKSIZE, > + POSIX_FADV_WILLNEED) != 0) > + die_errno("fadvise failed"); > + printf("fadvise SEQUENTIAL|WILLNEED to a file: %s\n", argv[5]); > + } > + > + total_time = get_current_us(); > + > + for (i = 0; i < count; i++) { > + ret = pread(fd, buf, buf_size, offset + buf_size * i); > + if (ret != buf_size) { > + printf("pread expected: %"PRIu64", readed: %"PRIu64"\n", > + buf_size, ret); > + if (ret > 0) > + read_cnt += ret; > + break; > + } > + > + read_cnt += ret; > + } > + printf("Fragmented_Read %"PRIu64" bytes total_time = %"PRIu64" us, BW = %.Lf MB/s\n", > + read_cnt, get_current_us() - total_time, > + ((long double)read_cnt / (get_current_us() - total_time))); > + printf("\n"); > + exit(0); > +} > + > #define randread_desc "random read data from file" > #define randread_help \ > "f2fs_io randread [chunk_size in 4kb] [count] [IO] [advise] [file_path]\n\n" \ > @@ -1989,6 +2102,7 @@ const struct cmd_desc cmd_list[] = { > CMD(write_advice), > CMD(read), > CMD(randread), > + CMD(fragread), > CMD(fiemap), > CMD(gc_urgent), > CMD(defrag_file), > -- > 2.49.0.rc1.451.g8f38331e32-goog > > > > _______________________________________________ > Linux-f2fs-devel mailing list > Linux-f2fs-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-03-18 3:13 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-03-04 1:10 [f2fs-dev] [PATCH] f2fs_io: add fragread command to evaluate fragmented buffer for reads Jaegeuk Kim via Linux-f2fs-devel 2025-03-11 12:10 ` Chao Yu via Linux-f2fs-devel 2025-03-11 19:36 ` Jaegeuk Kim via Linux-f2fs-devel 2025-03-12 3:02 ` Chao Yu via Linux-f2fs-devel 2025-03-17 3:30 ` Chao Yu via Linux-f2fs-devel 2025-03-17 21:27 ` [f2fs-dev] [f2fs-dev v2] " Jaegeuk Kim via Linux-f2fs-devel 2025-03-18 3:12 ` Jaegeuk Kim via Linux-f2fs-devel
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.