Browse Source

checkpoint

toggle-debug
Antonio SJ Musumeci 2 years ago
parent
commit
420252a4db
  1. 3
      libfuse/Makefile
  2. 109
      libfuse/lib/fuse.c
  3. 3
      libfuse/lib/fuse_msgbuf.hpp
  4. 55
      libfuse/lib/fuse_signals.c
  5. 11
      libfuse/lib/lock.h
  6. 24
      libfuse/lib/node.h
  7. 63
      libfuse/lib/node_pool.c
  8. 26
      libfuse/lib/node_pool.h
  9. 17
      src/fuse_ioctl.cpp

3
libfuse/Makefile

@ -44,7 +44,8 @@ SRC_C = \
lib/fuse_session.c \ lib/fuse_session.c \
lib/fuse_signals.c \ lib/fuse_signals.c \
lib/helper.c \ lib/helper.c \
lib/mount.c
lib/mount.c \
lib/node_pool.c
SRC_CPP = \ SRC_CPP = \
lib/format.cpp \ lib/format.cpp \
lib/os.cpp \ lib/os.cpp \

109
libfuse/lib/fuse.c

@ -21,9 +21,11 @@
#include "fuse_kernel.h" #include "fuse_kernel.h"
#include "fuse_lowlevel.h" #include "fuse_lowlevel.h"
#include "fuse_misc.h" #include "fuse_misc.h"
#include "fuse_msgbuf.hpp"
#include "fuse_opt.h" #include "fuse_opt.h"
#include "fuse_pollhandle.h" #include "fuse_pollhandle.h"
#include "fuse_msgbuf.hpp"
#include "lock.h"
#include "node_pool.h"
#include <assert.h> #include <assert.h>
#include <dlfcn.h> #include <dlfcn.h>
@ -46,6 +48,7 @@
#include <sys/uio.h> #include <sys/uio.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <semaphore.h>
#ifdef HAVE_MALLOC_TRIM #ifdef HAVE_MALLOC_TRIM
#include <malloc.h> #include <malloc.h>
@ -59,6 +62,7 @@
#define PARAM(inarg) ((void*)(((char*)(inarg)) + sizeof(*(inarg)))) #define PARAM(inarg) ((void*)(((char*)(inarg)) + sizeof(*(inarg))))
static int g_LOG_METRICS = 0; static int g_LOG_METRICS = 0;
static sem_t g_LOG_SEMAPHORE;
struct fuse_config struct fuse_config
{ {
@ -146,42 +150,9 @@ struct fuse
struct lock_queue_element *lockq; struct lock_queue_element *lockq;
pthread_t maintenance_thread; pthread_t maintenance_thread;
lfmp_t node_fmp;
kvec_t(remembered_node_t) remembered_nodes; kvec_t(remembered_node_t) remembered_nodes;
}; };
struct lock
{
int type;
off_t start;
off_t end;
pid_t pid;
uint64_t owner;
struct lock *next;
};
struct node
{
struct node *name_next;
struct node *id_next;
uint64_t nodeid;
char *name;
struct node *parent;
uint64_t nlookup;
uint32_t refctr;
uint32_t open_count;
uint64_t hidden_fh;
int32_t treelock;
struct lock *locks;
uint32_t stat_crc32b;
uint8_t is_stat_cache_valid:1;
};
#define TREELOCK_WRITE -1 #define TREELOCK_WRITE -1
#define TREELOCK_WAIT_OFFSET INT_MIN #define TREELOCK_WAIT_OFFSET INT_MIN
@ -283,21 +254,6 @@ list_del(struct list_head *entry)
prev->next = next; prev->next = next;
} }
static
struct node*
alloc_node(struct fuse *f)
{
return lfmp_calloc(&f->node_fmp);
}
static
void
free_node_mem(struct fuse *f,
struct node *node)
{
return lfmp_free(&f->node_fmp,node);
}
static static
size_t size_t
id_hash(struct fuse *f, id_hash(struct fuse *f,
@ -409,7 +365,7 @@ free_node(struct fuse *f_,
if(node_->hidden_fh) if(node_->hidden_fh)
f_->fs->op.free_hide(node_->hidden_fh); f_->fs->op.free_hide(node_->hidden_fh);
free_node_mem(f_,node_);
node_free(node_);
} }
static static
@ -786,7 +742,7 @@ find_node(struct fuse *f,
if(node == NULL) if(node == NULL)
{ {
node = alloc_node(f);
node = node_alloc();
if(node == NULL) if(node == NULL)
goto out_err; goto out_err;
@ -3730,10 +3686,21 @@ metrics_log_nodes_info(struct fuse *f_,
FILE *file_) FILE *file_)
{ {
char buf[1024]; char buf[1024];
time_t timestamp;
struct tm timestamp_tm;
char timestamp_str[256];
lfmp_t *lfmp;
timestamp = time(NULL);
localtime_r(&timestamp,&timestamp_tm);
strftime(timestamp_str,sizeof(timestamp_str),"%Y-%m-%dT%H:%M:%S",&timestamp_tm);
lfmp = node_lfmp();
lfmp_lock(&f_->node_fmp);
lfmp_lock(lfmp);
snprintf(buf,sizeof(buf), snprintf(buf,sizeof(buf),
"time: %"PRIu64"\n" "time: %"PRIu64"\n"
"time: %s\n"
"sizeof(node): %"PRIu64"\n" "sizeof(node): %"PRIu64"\n"
"node id_table size: %"PRIu64"\n" "node id_table size: %"PRIu64"\n"
"node id_table usage: %"PRIu64"\n" "node id_table usage: %"PRIu64"\n"
@ -3747,7 +3714,8 @@ metrics_log_nodes_info(struct fuse *f_,
"node memory pool total allocated memory: %"PRIu64"\n" "node memory pool total allocated memory: %"PRIu64"\n"
"\n" "\n"
, ,
(uint64_t)time(NULL),
(uint64_t)timestamp,
timestamp_str,
(uint64_t)sizeof(struct node), (uint64_t)sizeof(struct node),
(uint64_t)f_->id_table.size, (uint64_t)f_->id_table.size,
(uint64_t)f_->id_table.use, (uint64_t)f_->id_table.use,
@ -3755,12 +3723,12 @@ metrics_log_nodes_info(struct fuse *f_,
(uint64_t)f_->name_table.size, (uint64_t)f_->name_table.size,
(uint64_t)f_->name_table.use, (uint64_t)f_->name_table.use,
(uint64_t)(f_->name_table.size * sizeof(struct node*)), (uint64_t)(f_->name_table.size * sizeof(struct node*)),
(uint64_t)fmp_slab_count(&f_->node_fmp.fmp),
fmp_slab_usage_ratio(&f_->node_fmp.fmp),
(uint64_t)fmp_avail_objs(&f_->node_fmp.fmp),
(uint64_t)fmp_total_allocated_memory(&f_->node_fmp.fmp)
(uint64_t)fmp_slab_count(&lfmp->fmp),
fmp_slab_usage_ratio(&lfmp->fmp),
(uint64_t)fmp_avail_objs(&lfmp->fmp),
(uint64_t)fmp_total_allocated_memory(&lfmp->fmp)
); );
lfmp_unlock(&f_->node_fmp);
lfmp_unlock(lfmp);
fputs(buf,file_); fputs(buf,file_);
} }
@ -3793,18 +3761,24 @@ fuse_malloc_trim(void)
#endif #endif
} }
void
fuse_gc()
{
fuse_malloc_trim();
node_gc();
msgbuf_gc();
}
static static
void* void*
fuse_maintenance_loop(void *fuse_) fuse_maintenance_loop(void *fuse_)
{ {
int gc; int gc;
int loops; int loops;
int sleep_time;
struct fuse *f = (struct fuse*)fuse_; struct fuse *f = (struct fuse*)fuse_;
gc = 0; gc = 0;
loops = 0; loops = 0;
sleep_time = 60;
while(1) while(1)
{ {
if(remember_nodes(f)) if(remember_nodes(f))
@ -3818,13 +3792,15 @@ fuse_maintenance_loop(void *fuse_)
// Trigger a followup gc if this gc succeeds // Trigger a followup gc if this gc succeeds
if(!f->conf.nogc && gc) if(!f->conf.nogc && gc)
gc = lfmp_gc(&f->node_fmp);
gc = node_gc();
if(g_LOG_METRICS) if(g_LOG_METRICS)
metrics_log_nodes_info_to_tmp_dir(f); metrics_log_nodes_info_to_tmp_dir(f);
loops++; loops++;
sleep(sleep_time);
struct timespec timeout = {60,0};
sem_timedwait(&g_LOG_SEMAPHORE,&timeout);
} }
return NULL; return NULL;
@ -3902,10 +3878,9 @@ fuse_new_common(struct fuse_chan *ch,
fuse_mutex_init(&f->lock); fuse_mutex_init(&f->lock);
lfmp_init(&f->node_fmp,sizeof(struct node),256);
kv_init(f->remembered_nodes); kv_init(f->remembered_nodes);
root = alloc_node(f);
root = node_alloc();
if(root == NULL) if(root == NULL)
{ {
fprintf(stderr,"fuse: memory allocation failed\n"); fprintf(stderr,"fuse: memory allocation failed\n");
@ -3919,6 +3894,8 @@ fuse_new_common(struct fuse_chan *ch,
inc_nlookup(root); inc_nlookup(root);
hash_id(f,root); hash_id(f,root);
sem_init(&g_LOG_SEMAPHORE,0,0);
return f; return f;
out_free_id_table: out_free_id_table:
@ -3989,11 +3966,11 @@ fuse_destroy(struct fuse *f)
} }
} }
node_gc();
free(f->id_table.array); free(f->id_table.array);
free(f->name_table.array); free(f->name_table.array);
pthread_mutex_destroy(&f->lock); pthread_mutex_destroy(&f->lock);
fuse_session_destroy(f->se); fuse_session_destroy(f->se);
lfmp_destroy(&f->node_fmp);
kv_destroy(f->remembered_nodes); kv_destroy(f->remembered_nodes);
free(f); free(f);
fuse_delete_context_key(); fuse_delete_context_key();
@ -4022,6 +3999,8 @@ void
fuse_log_metrics_set(int log_) fuse_log_metrics_set(int log_)
{ {
g_LOG_METRICS = log_; g_LOG_METRICS = log_;
if(g_LOG_METRICS)
sem_post(&g_LOG_SEMAPHORE);
} }
int int

3
libfuse/lib/fuse_msgbuf.hpp

@ -27,7 +27,8 @@ void msgbuf_set_bufsize(const uint32_t size);
uint32_t msgbuf_get_bufsize(); uint32_t msgbuf_get_bufsize();
fuse_msgbuf_t* msgbuf_alloc(); fuse_msgbuf_t* msgbuf_alloc();
fuse_msgbuf_t* msgbuf_alloc_memonly();
void msgbuf_free(fuse_msgbuf_t *msgbuf); void msgbuf_free(fuse_msgbuf_t *msgbuf);
void msgbuf_gc();
EXTERN_C_END EXTERN_C_END

55
libfuse/lib/fuse_signals.c

@ -6,7 +6,7 @@
See the file COPYING.LIB See the file COPYING.LIB
*/ */
#include "fuse_lowlevel.h"
#include "fuse.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -14,14 +14,31 @@
static struct fuse_session *fuse_instance; static struct fuse_session *fuse_instance;
static void exit_handler(int sig)
static
void
exit_handler(int sig)
{ {
(void) sig; (void) sig;
if (fuse_instance) if (fuse_instance)
fuse_session_exit(fuse_instance); fuse_session_exit(fuse_instance);
} }
static int set_one_signal_handler(int sig, void (*handler)(int), int remove)
static
void
sigusr1_handler(int sig_)
{
int enabled;
enabled = fuse_log_metrics_get();
enabled = !enabled;
fuse_log_metrics_set(enabled);
}
static
int
set_one_signal_handler(int sig,
void (*handler)(int),
int remove)
{ {
struct sigaction sa; struct sigaction sa;
struct sigaction old_sa; struct sigaction old_sa;
@ -33,37 +50,45 @@ static int set_one_signal_handler(int sig, void (*handler)(int), int remove)
if (sigaction(sig, NULL, &old_sa) == -1) { if (sigaction(sig, NULL, &old_sa) == -1) {
perror("fuse: cannot get old signal handler"); perror("fuse: cannot get old signal handler");
return -1;
return 1;
} }
if(old_sa.sa_handler == (remove ? handler : SIG_DFL) && if(old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
sigaction(sig, &sa, NULL) == -1) { sigaction(sig, &sa, NULL) == -1) {
perror("fuse: cannot set signal handler"); perror("fuse: cannot set signal handler");
return -1;
return 1;
} }
return 0; return 0;
} }
int fuse_set_signal_handlers(struct fuse_session *se)
int
fuse_set_signal_handlers(struct fuse_session *se)
{ {
if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 ||
set_one_signal_handler(SIGINT, exit_handler, 0) == -1 ||
set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 ||
set_one_signal_handler(SIGPIPE, SIG_IGN, 0) == -1)
return -1;
int rv;
rv = 0;
rv |= set_one_signal_handler(SIGUSR1,sigusr1_handler,0);
rv |= set_one_signal_handler(SIGHUP,exit_handler,0);
rv |= set_one_signal_handler(SIGINT,exit_handler,0);
rv |= set_one_signal_handler(SIGTERM,exit_handler,0);
rv |= set_one_signal_handler(SIGPIPE,SIG_IGN,0);
if(rv == 0)
fuse_instance = se; fuse_instance = se;
return 0;
return rv;
} }
void fuse_remove_signal_handlers(struct fuse_session *se)
void
fuse_remove_signal_handlers(struct fuse_session *se)
{ {
if(fuse_instance != se) if(fuse_instance != se)
fprintf(stderr,
"fuse: fuse_remove_signal_handlers: unknown session\n");
fprintf(stderr,"fuse: fuse_remove_signal_handlers: unknown session\n");
else else
fuse_instance = NULL; fuse_instance = NULL;
set_one_signal_handler(SIGUSR1,sigusr1_handler,1);
set_one_signal_handler(SIGHUP,exit_handler,1); set_one_signal_handler(SIGHUP,exit_handler,1);
set_one_signal_handler(SIGINT,exit_handler,1); set_one_signal_handler(SIGINT,exit_handler,1);
set_one_signal_handler(SIGTERM,exit_handler,1); set_one_signal_handler(SIGTERM,exit_handler,1);

11
libfuse/lib/lock.h

@ -0,0 +1,11 @@
#pragma once
struct lock
{
int type;
off_t start;
off_t end;
pid_t pid;
uint64_t owner;
struct lock *next;
};

24
libfuse/lib/node.h

@ -0,0 +1,24 @@
#pragma once
#include "lock.h"
struct node
{
struct node *name_next;
struct node *id_next;
uint64_t nodeid;
char *name;
struct node *parent;
uint64_t nlookup;
uint32_t refctr;
uint32_t open_count;
uint64_t hidden_fh;
int32_t treelock;
struct lock *locks;
uint32_t stat_crc32b;
uint8_t is_stat_cache_valid:1;
};

63
libfuse/lib/node_pool.c

@ -0,0 +1,63 @@
/*
ISC License
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "lfmp.h"
#include "node.h"
static lfmp_t g_NODE_FMP;
__attribute__((constructor))
void
__construct_g_NODE_FMP()
{
lfmp_init(&g_NODE_FMP,sizeof(struct node),256);
}
__attribute__((destructor))
void
__destruct__g_NODE_FMP()
{
lfmp_destroy(&g_NODE_FMP);
}
struct node*
node_alloc()
{
return lfmp_calloc(&g_NODE_FMP);
}
void
node_free(struct node *node_)
{
lfmp_free(&g_NODE_FMP,node_);
}
int
node_gc()
{
return lfmp_gc(&g_NODE_FMP);
}
lfmp_t*
node_lfmp()
{
return &g_NODE_FMP;
}

26
libfuse/lib/node_pool.h

@ -0,0 +1,26 @@
/*
ISC License
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "node.h"
struct node* node_alloc();
void node_free(struct node *node_);
int node_gc();
lfmp_t *node_lfmp();

17
src/fuse_ioctl.cpp

@ -25,6 +25,7 @@
#include "fs_open.hpp" #include "fs_open.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "str.hpp" #include "str.hpp"
#include "syslog.hpp"
#include "ugid.hpp" #include "ugid.hpp"
#include <string> #include <string>
@ -43,6 +44,7 @@ using std::vector;
typedef char IOCTL_BUF[4096]; typedef char IOCTL_BUF[4096];
#define IOCTL_APP_TYPE 0xDF #define IOCTL_APP_TYPE 0xDF
#define IOCTL_FILE_INFO _IOWR(IOCTL_APP_TYPE,0,IOCTL_BUF) #define IOCTL_FILE_INFO _IOWR(IOCTL_APP_TYPE,0,IOCTL_BUF)
#define IOCTL_TOGGLE_LOGGING _IO(IOCTL_APP_TYPE,1)
// From linux/btrfs.h // From linux/btrfs.h
#define BTRFS_IOCTL_MAGIC 0x94 #define BTRFS_IOCTL_MAGIC 0x94
@ -310,6 +312,19 @@ namespace l
return -ENOATTR; return -ENOATTR;
} }
static
int
toggle_logging()
{
int enabled;
enabled = fuse_log_metrics_get();
syslog_info("logging %sabled",(enabled ? "dis" : "en"));
fuse_log_metrics_set(!enabled);
return 0;
}
static static
bool bool
is_mergerfs_ioctl_cmd(const unsigned long cmd_) is_mergerfs_ioctl_cmd(const unsigned long cmd_)
@ -334,6 +349,8 @@ namespace l
{ {
case IOCTL_FILE_INFO: case IOCTL_FILE_INFO:
return l::file_info(ffi_,data_); return l::file_info(ffi_,data_);
case IOCTL_TOGGLE_LOGGING:
return l::toggle_logging();
} }
return -ENOTTY; return -ENOTTY;

Loading…
Cancel
Save