mirror of
https://github.com/jarun/nnn.git
synced 2024-11-24 11:51:27 +00:00
Multi-threaded FTS-based disk usage calculation
Implements pthreads based du using FTS. Currently 4 threads are used. NFTW is dropped as there is no way to pass any custom values to fn(). FTS does not require any per entry function callback. The performance numbers are best with FTS: ./nnn-fts -T d / 5.29s user 0.94s system 116% cpu 5.335 total 1/21 du:102.402G free:8.476G files:397644 101132550144B ./nnn-ftw -T d / 5.52s user 0.94s system 116% cpu 5.534 total 1/21 du:102.400G free:8.474G files:397653 101133148160B ./nnn-4.0 -T d / 0.20s user 2.27s system 24% cpu 10.241 total 1/21 du:102.400G free:8.475G files:397654 101133299712B
This commit is contained in:
parent
025b570e05
commit
284a3c4866
2
Makefile
2
Makefile
|
@ -119,7 +119,7 @@ CFLAGS += -std=c11 -Wall -Wextra -Wshadow
|
||||||
CFLAGS += $(CFLAGS_OPTIMIZATION)
|
CFLAGS += $(CFLAGS_OPTIMIZATION)
|
||||||
CFLAGS += $(CFLAGS_CURSES)
|
CFLAGS += $(CFLAGS_CURSES)
|
||||||
|
|
||||||
LDLIBS += $(LDLIBS_CURSES)
|
LDLIBS += $(LDLIBS_CURSES) -lpthread
|
||||||
|
|
||||||
# static compilation needs libgpm development package
|
# static compilation needs libgpm development package
|
||||||
ifeq ($(strip $(O_STATIC)),1)
|
ifeq ($(strip $(O_STATIC)),1)
|
||||||
|
|
|
@ -124,8 +124,7 @@ CFLAGS += -std=c11 -Wall -Wextra -Wshadow
|
||||||
CFLAGS += $(CFLAGS_OPTIMIZATION)
|
CFLAGS += $(CFLAGS_OPTIMIZATION)
|
||||||
CFLAGS += $(CFLAGS_CURSES)
|
CFLAGS += $(CFLAGS_CURSES)
|
||||||
|
|
||||||
LDLIBS += $(LDLIBS_CURSES) $(LDLIBS_HAIKU)
|
LDLIBS += $(LDLIBS_CURSES) -lpthread $(LDLIBS_HAIKU)
|
||||||
|
|
||||||
# static compilation needs libgpm development package
|
# static compilation needs libgpm development package
|
||||||
ifeq ($(strip $(O_STATIC)),1)
|
ifeq ($(strip $(O_STATIC)),1)
|
||||||
LDFLAGS += -static
|
LDFLAGS += -static
|
||||||
|
|
207
src/nnn.c
207
src/nnn.c
|
@ -74,11 +74,13 @@
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <fts.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#ifndef NOLC
|
#ifndef NOLC
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#ifndef NORL
|
#ifndef NORL
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
@ -336,7 +338,8 @@ typedef struct {
|
||||||
uint_t dirctx : 1; /* Show dirs in context color */
|
uint_t dirctx : 1; /* Show dirs in context color */
|
||||||
uint_t uidgid : 1; /* Show owner and group info */
|
uint_t uidgid : 1; /* Show owner and group info */
|
||||||
uint_t prstssn : 1; /* Persistent session */
|
uint_t prstssn : 1; /* Persistent session */
|
||||||
uint_t reserved : 8; /* Adjust when adding/removing a field */
|
uint_t duinit : 1; /* Initialize disk usage */
|
||||||
|
uint_t reserved : 7; /* Adjust when adding/removing a field */
|
||||||
} runstate;
|
} runstate;
|
||||||
|
|
||||||
/* Contexts or workspaces */
|
/* Contexts or workspaces */
|
||||||
|
@ -424,9 +427,7 @@ static char *fifopath;
|
||||||
#endif
|
#endif
|
||||||
static unsigned long long *ihashbmp;
|
static unsigned long long *ihashbmp;
|
||||||
static struct entry *pdents;
|
static struct entry *pdents;
|
||||||
static blkcnt_t ent_blocks;
|
|
||||||
static blkcnt_t dir_blocks;
|
static blkcnt_t dir_blocks;
|
||||||
static ulong_t num_files;
|
|
||||||
static kv *bookmark;
|
static kv *bookmark;
|
||||||
static kv *plug;
|
static kv *plug;
|
||||||
static uchar_t tmpfplen, homelen;
|
static uchar_t tmpfplen, homelen;
|
||||||
|
@ -440,6 +441,28 @@ static pcre *archive_pcre;
|
||||||
static regex_t archive_re;
|
static regex_t archive_re;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* pthread related */
|
||||||
|
#define NUM_DU_THREADS (4) /* Can use sysconf(_SC_NPROCESSORS_ONLN) */
|
||||||
|
#define DU_TEST (((node->fts_info & FTS_F) && \
|
||||||
|
(sb->st_nlink <= 1 || test_set_bit((uint_t)sb->st_ino))) || node->fts_info & FTS_DP)
|
||||||
|
|
||||||
|
static int threadbmp = -1; /* Has 1 in the bit position for idle threads */
|
||||||
|
static volatile int active_threads = 0;
|
||||||
|
static pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static pthread_mutex_t hardlink_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static ulong_t *core_files;
|
||||||
|
static blkcnt_t *core_blocks;
|
||||||
|
static _Atomic volatile ulong_t num_files;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char path[PATH_MAX];
|
||||||
|
int entnum;
|
||||||
|
ushort_t core;
|
||||||
|
bool mntpoint;
|
||||||
|
} thread_data;
|
||||||
|
|
||||||
|
static thread_data *core_data;
|
||||||
|
|
||||||
/* Retain old signal handlers */
|
/* Retain old signal handlers */
|
||||||
static struct sigaction oldsighup;
|
static struct sigaction oldsighup;
|
||||||
static struct sigaction oldsigtstp;
|
static struct sigaction oldsigtstp;
|
||||||
|
@ -777,7 +800,6 @@ static haiku_nm_h haiku_hnd;
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
static void redraw(char *path);
|
static void redraw(char *path);
|
||||||
static int spawn(char *file, char *arg1, char *arg2, char *arg3, uchar_t flag);
|
static int spawn(char *file, char *arg1, char *arg2, char *arg3, uchar_t flag);
|
||||||
static int (*nftw_fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
|
|
||||||
static void move_cursor(int target, int ignore_scrolloff);
|
static void move_cursor(int target, int ignore_scrolloff);
|
||||||
static char *load_input(int fd, const char *path);
|
static char *load_input(int fd, const char *path);
|
||||||
static int set_sort_flags(int r);
|
static int set_sort_flags(int r);
|
||||||
|
@ -853,12 +875,16 @@ static bool test_set_bit(uint_t nr)
|
||||||
{
|
{
|
||||||
nr &= HASH_BITS;
|
nr &= HASH_BITS;
|
||||||
|
|
||||||
unsigned long long *m = ((unsigned long long *)ihashbmp) + (nr >> 6);
|
pthread_mutex_lock(&hardlink_mutex);
|
||||||
|
ulong_t *m = ((ulong_t *)ihashbmp) + (nr >> 6);
|
||||||
|
|
||||||
if (*m & (1 << (nr & 63)))
|
if (*m & (1 << (nr & 63))) {
|
||||||
|
pthread_mutex_unlock(&hardlink_mutex);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
*m |= 1 << (nr & 63);
|
*m |= 1 << (nr & 63);
|
||||||
|
pthread_mutex_unlock(&hardlink_mutex);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -4954,36 +4980,63 @@ static bool handle_cmd(enum action sel, const char *current, char *newpath)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sum_bsize(const char *UNUSED(fpath), const struct stat *sb, int typeflag, struct FTW *UNUSED(ftwbuf))
|
|
||||||
{
|
|
||||||
if (sb->st_blocks
|
|
||||||
&& ((typeflag == FTW_F && (sb->st_nlink <= 1 || test_set_bit((uint_t)sb->st_ino)))
|
|
||||||
|| typeflag == FTW_D))
|
|
||||||
ent_blocks += sb->st_blocks;
|
|
||||||
|
|
||||||
++num_files;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sum_asize(const char *UNUSED(fpath), const struct stat *sb, int typeflag, struct FTW *UNUSED(ftwbuf))
|
|
||||||
{
|
|
||||||
if (sb->st_size
|
|
||||||
&& ((typeflag == FTW_F && (sb->st_nlink <= 1 || test_set_bit((uint_t)sb->st_ino)))
|
|
||||||
|| typeflag == FTW_D))
|
|
||||||
ent_blocks += sb->st_size;
|
|
||||||
|
|
||||||
++num_files;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dentfree(void)
|
static void dentfree(void)
|
||||||
{
|
{
|
||||||
free(pnamebuf);
|
free(pnamebuf);
|
||||||
free(pdents);
|
free(pdents);
|
||||||
free(mark);
|
free(mark);
|
||||||
|
|
||||||
|
/* Thread data cleanup */
|
||||||
|
free(core_blocks);
|
||||||
|
free(core_data);
|
||||||
|
free(core_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
static blkcnt_t dirwalk(char *path, struct stat *psb)
|
static void *du_thread(void *p_data)
|
||||||
|
{
|
||||||
|
thread_data *pdata = (thread_data *)p_data;
|
||||||
|
char *path[2] = {pdata->path, NULL};
|
||||||
|
ulong_t tfiles = 0;
|
||||||
|
blkcnt_t tblocks = 0;
|
||||||
|
struct stat *sb;
|
||||||
|
FTS *tree = fts_open(path, FTS_PHYSICAL | FTS_XDEV | FTS_NOCHDIR, 0);
|
||||||
|
FTSENT *node;
|
||||||
|
|
||||||
|
while ((node = fts_read(tree))) {
|
||||||
|
if (node->fts_info & FTS_D)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sb = node->fts_statp;
|
||||||
|
|
||||||
|
if (cfg.apparentsz) {
|
||||||
|
if (sb->st_size && DU_TEST)
|
||||||
|
tblocks += sb->st_size;
|
||||||
|
} else if (sb->st_blocks && DU_TEST)
|
||||||
|
tblocks += sb->st_blocks;
|
||||||
|
|
||||||
|
++tfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
fts_close(tree);
|
||||||
|
|
||||||
|
if (pdata->entnum >= 0)
|
||||||
|
pdents[pdata->entnum].blocks = tblocks;
|
||||||
|
|
||||||
|
if (!pdata->mntpoint) {
|
||||||
|
core_blocks[pdata->core] += tblocks;
|
||||||
|
core_files[pdata->core] += tfiles;
|
||||||
|
} else
|
||||||
|
core_files[pdata->core] += 1;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&running_mutex);
|
||||||
|
threadbmp |= (1 << pdata->core);
|
||||||
|
--active_threads;
|
||||||
|
pthread_mutex_unlock(&running_mutex);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dirwalk(char *dir, char *path, int entnum, bool mountpoint)
|
||||||
{
|
{
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
static uint_t open_max;
|
static uint_t open_max;
|
||||||
|
@ -4993,22 +5046,49 @@ static blkcnt_t dirwalk(char *path, struct stat *psb)
|
||||||
open_max = max_openfds();
|
open_max = max_openfds();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ent_blocks = 0;
|
/* Loop till any core is free */
|
||||||
|
while (active_threads == NUM_DU_THREADS){}
|
||||||
|
|
||||||
|
if (g_state.interrupt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&running_mutex);
|
||||||
|
++active_threads;
|
||||||
|
int core = ffs(threadbmp) - 1;
|
||||||
|
threadbmp &= ~(1 << core);
|
||||||
|
pthread_mutex_unlock(&running_mutex);
|
||||||
|
|
||||||
|
xstrsncpy(core_data[core].path, path, PATH_MAX);
|
||||||
|
core_data[core].entnum = entnum;
|
||||||
|
core_data[core].core = (ushort_t)core;
|
||||||
|
core_data[core].mntpoint = mountpoint;
|
||||||
|
|
||||||
|
pthread_t tid = 0;
|
||||||
|
|
||||||
|
pthread_create(&tid, NULL, du_thread, (void *)&(core_data[core]));
|
||||||
|
|
||||||
|
redraw(dir);
|
||||||
tolastln();
|
tolastln();
|
||||||
addstr(xbasename(path));
|
|
||||||
addstr(" [^C aborts]\n");
|
addstr(" [^C aborts]\n");
|
||||||
refresh();
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef __APPLE__
|
static void prep_threads(void)
|
||||||
if (nftw(path, nftw_fn, open_max, FTW_MOUNT | FTW_PHYS) < 0) {
|
{
|
||||||
#else
|
if (!g_state.duinit) {
|
||||||
if (nftw(path, nftw_fn, OPEN_MAX, FTW_MOUNT | FTW_PHYS) < 0) {
|
/* drop MSB 1s */
|
||||||
#endif
|
threadbmp >>= (32 - NUM_DU_THREADS);
|
||||||
DPRINTF_S("nftw failed");
|
|
||||||
return cfg.apparentsz ? psb->st_size : psb->st_blocks;
|
core_blocks = calloc(NUM_DU_THREADS, sizeof(blkcnt_t));
|
||||||
|
core_data = calloc(NUM_DU_THREADS, sizeof(thread_data));
|
||||||
|
core_files = calloc(NUM_DU_THREADS, sizeof(ulong_t));
|
||||||
|
|
||||||
|
g_state.duinit = TRUE;
|
||||||
|
} else {
|
||||||
|
memset(core_blocks, 0, NUM_DU_THREADS * sizeof(blkcnt_t));
|
||||||
|
memset(core_data, 0, NUM_DU_THREADS * sizeof(thread_data));
|
||||||
|
memset(core_files, 0, NUM_DU_THREADS * sizeof(ulong_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ent_blocks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip self and parent */
|
/* Skip self and parent */
|
||||||
|
@ -5020,8 +5100,7 @@ static bool selforparent(const char *path)
|
||||||
static int dentfill(char *path, struct entry **ppdents)
|
static int dentfill(char *path, struct entry **ppdents)
|
||||||
{
|
{
|
||||||
uchar_t entflags = 0;
|
uchar_t entflags = 0;
|
||||||
int n = 0, flags = 0;
|
int flags = 0;
|
||||||
ulong_t num_saved;
|
|
||||||
struct dirent *dp;
|
struct dirent *dp;
|
||||||
char *namep, *pnb, *buf = NULL;
|
char *namep, *pnb, *buf = NULL;
|
||||||
struct entry *dentp;
|
struct entry *dentp;
|
||||||
|
@ -5029,6 +5108,8 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||||
struct stat sb_path, sb;
|
struct stat sb_path, sb;
|
||||||
DIR *dirp = opendir(path);
|
DIR *dirp = opendir(path);
|
||||||
|
|
||||||
|
ndents = 0;
|
||||||
|
|
||||||
DPRINTF_S(__func__);
|
DPRINTF_S(__func__);
|
||||||
|
|
||||||
if (!dirp)
|
if (!dirp)
|
||||||
|
@ -5053,6 +5134,8 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||||
} else
|
} else
|
||||||
memset(ihashbmp, 0, HASH_OCTETS << 3);
|
memset(ihashbmp, 0, HASH_OCTETS << 3);
|
||||||
|
|
||||||
|
prep_threads();
|
||||||
|
|
||||||
attron(COLOR_PAIR(cfg.curctx + 1));
|
attron(COLOR_PAIR(cfg.curctx + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5095,13 +5178,11 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||||
if (S_ISDIR(sb.st_mode)) {
|
if (S_ISDIR(sb.st_mode)) {
|
||||||
if (sb_path.st_dev == sb.st_dev) { // NOLINT
|
if (sb_path.st_dev == sb.st_dev) { // NOLINT
|
||||||
mkpath(path, namep, buf);
|
mkpath(path, namep, buf);
|
||||||
|
dirwalk(path, buf, -1, FALSE);
|
||||||
dir_blocks += dirwalk(buf, &sb);
|
|
||||||
|
|
||||||
if (g_state.interrupt)
|
if (g_state.interrupt)
|
||||||
goto exit;
|
goto exit;
|
||||||
ndents = n;
|
|
||||||
redraw(path);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Do not recount hard links */
|
/* Do not recount hard links */
|
||||||
|
@ -5128,7 +5209,10 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||||
entflags = SYM_ORPHAN;
|
entflags = SYM_ORPHAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == total_dents) {
|
if (ndents == total_dents) {
|
||||||
|
if (cfg.blkorder)
|
||||||
|
while (active_threads) {}
|
||||||
|
|
||||||
total_dents += ENTRY_INCR;
|
total_dents += ENTRY_INCR;
|
||||||
*ppdents = xrealloc(*ppdents, total_dents * sizeof(**ppdents));
|
*ppdents = xrealloc(*ppdents, total_dents * sizeof(**ppdents));
|
||||||
if (!*ppdents) {
|
if (!*ppdents) {
|
||||||
|
@ -5157,13 +5241,13 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||||
dentp = *ppdents;
|
dentp = *ppdents;
|
||||||
dentp->name = pnamebuf;
|
dentp->name = pnamebuf;
|
||||||
|
|
||||||
for (int count = 1; count < n; ++dentp, ++count)
|
for (int count = 1; count < ndents; ++dentp, ++count)
|
||||||
/* Current file name starts at last file name start + length */
|
/* Current file name starts at last file name start + length */
|
||||||
(dentp + 1)->name = (char *)((size_t)dentp->name + dentp->nlen);
|
(dentp + 1)->name = (char *)((size_t)dentp->name + dentp->nlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dentp = *ppdents + n;
|
dentp = *ppdents + ndents;
|
||||||
|
|
||||||
/* Selection file name */
|
/* Selection file name */
|
||||||
dentp->name = (char *)((size_t)pnamebuf + off);
|
dentp->name = (char *)((size_t)pnamebuf + off);
|
||||||
|
@ -5221,21 +5305,13 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||||
|
|
||||||
if (cfg.blkorder) {
|
if (cfg.blkorder) {
|
||||||
if (S_ISDIR(sb.st_mode)) {
|
if (S_ISDIR(sb.st_mode)) {
|
||||||
num_saved = num_files + 1;
|
|
||||||
mkpath(path, namep, buf);
|
mkpath(path, namep, buf);
|
||||||
|
|
||||||
/* Need to show the disk usage of this dir */
|
/* Need to show the disk usage of this dir */
|
||||||
dentp->blocks = dirwalk(buf, &sb);
|
dirwalk(path, buf, ndents, (sb_path.st_dev != sb.st_dev)); // NOLINT
|
||||||
|
|
||||||
if (sb_path.st_dev == sb.st_dev) // NOLINT
|
|
||||||
dir_blocks += dentp->blocks;
|
|
||||||
else
|
|
||||||
num_files = num_saved;
|
|
||||||
|
|
||||||
if (g_state.interrupt)
|
if (g_state.interrupt)
|
||||||
goto exit;
|
goto exit;
|
||||||
ndents = n;
|
|
||||||
redraw(path);
|
|
||||||
} else {
|
} else {
|
||||||
dentp->blocks = (cfg.apparentsz ? sb.st_size : sb.st_blocks);
|
dentp->blocks = (cfg.apparentsz ? sb.st_size : sb.st_blocks);
|
||||||
/* Do not recount hard links */
|
/* Do not recount hard links */
|
||||||
|
@ -5260,18 +5336,25 @@ static int dentfill(char *path, struct entry **ppdents)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
++n;
|
++ndents;
|
||||||
} while ((dp = readdir(dirp)));
|
} while ((dp = readdir(dirp)));
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (cfg.blkorder)
|
if (cfg.blkorder) {
|
||||||
|
while (active_threads) {}
|
||||||
|
|
||||||
attroff(COLOR_PAIR(cfg.curctx + 1));
|
attroff(COLOR_PAIR(cfg.curctx + 1));
|
||||||
|
for (int i = 0; i < NUM_DU_THREADS; ++i) {
|
||||||
|
num_files += core_files[i];
|
||||||
|
dir_blocks += core_blocks[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Should never be null */
|
/* Should never be null */
|
||||||
if (closedir(dirp) == -1)
|
if (closedir(dirp) == -1)
|
||||||
errexit();
|
errexit();
|
||||||
|
|
||||||
return n;
|
return ndents;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void populate(char *path, char *lastname)
|
static void populate(char *path, char *lastname)
|
||||||
|
@ -5525,7 +5608,6 @@ static int set_sort_flags(int r)
|
||||||
case 'a': /* Apparent du */
|
case 'a': /* Apparent du */
|
||||||
cfg.apparentsz ^= 1;
|
cfg.apparentsz ^= 1;
|
||||||
if (cfg.apparentsz) {
|
if (cfg.apparentsz) {
|
||||||
nftw_fn = &sum_asize;
|
|
||||||
cfg.blkorder = 1;
|
cfg.blkorder = 1;
|
||||||
blk_shift = 0;
|
blk_shift = 0;
|
||||||
} else
|
} else
|
||||||
|
@ -5535,7 +5617,6 @@ static int set_sort_flags(int r)
|
||||||
if (r == 'd') {
|
if (r == 'd') {
|
||||||
if (!cfg.apparentsz)
|
if (!cfg.apparentsz)
|
||||||
cfg.blkorder ^= 1;
|
cfg.blkorder ^= 1;
|
||||||
nftw_fn = &sum_bsize;
|
|
||||||
cfg.apparentsz = 0;
|
cfg.apparentsz = 0;
|
||||||
blk_shift = ffs(S_BLKSIZE) - 1;
|
blk_shift = ffs(S_BLKSIZE) - 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue