Browse Source

Merge pull request #675 from trapexit/fuse_ino

improve nodeid generation
pull/677/head
trapexit 5 years ago
committed by GitHub
parent
commit
026dc5f750
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      libfuse/Makefile
  2. 14
      libfuse/include/fuse_lowlevel.h
  3. 236
      libfuse/lib/fuse.c

2
libfuse/Makefile

@ -1,4 +1,4 @@
VERSION = "2.9.7-mergerfs_2.28.0"
VERSION = "2.9.7-mergerfs_2.29.0"
OPTS = -O2 OPTS = -O2
ifeq ($(DEBUG),1) ifeq ($(DEBUG),1)

14
libfuse/include/fuse_lowlevel.h

@ -25,12 +25,13 @@
#include "fuse_common.h" #include "fuse_common.h"
#include <utime.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h>
#include <stdint.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <utime.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -44,7 +45,7 @@ extern "C" {
#define FUSE_ROOT_ID 1 #define FUSE_ROOT_ID 1
/** Inode number type */ /** Inode number type */
typedef unsigned long fuse_ino_t;
typedef uint64_t fuse_ino_t;
/** Request pointer type */ /** Request pointer type */
typedef struct fuse_req *fuse_req_t; typedef struct fuse_req *fuse_req_t;
@ -88,7 +89,8 @@ struct fuse_entry_param {
* it as an error. * it as an error.
* *
*/ */
unsigned long generation;
uint64_t generation;
/** Inode attributes. /** Inode attributes.
* *
@ -122,7 +124,7 @@ struct fuse_ctx {
}; };
struct fuse_forget_data { struct fuse_forget_data {
uint64_t ino;
fuse_ino_t ino;
uint64_t nlookup; uint64_t nlookup;
}; };
@ -233,7 +235,7 @@ struct fuse_lowlevel_ops {
* @param ino the inode number * @param ino the inode number
* @param nlookup the number of lookups to forget * @param nlookup the number of lookups to forget
*/ */
void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup);
void (*forget) (fuse_req_t req, fuse_ino_t ino, uint64_t nlookup);
/** /**
* Get file attributes * Get file attributes

236
libfuse/lib/fuse.c

@ -19,25 +19,26 @@
#include "fuse_compat.h" #include "fuse_compat.h"
#include "fuse_kernel.h" #include "fuse_kernel.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#include <unistd.h>
#include <time.h>
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <errno.h>
#include <signal.h>
#include <dlfcn.h>
#include <assert.h>
#include <poll.h> #include <poll.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/uio.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/mman.h>
#include <sys/file.h>
#include <sys/uio.h>
#include <time.h>
#include <unistd.h>
#define FUSE_NODE_SLAB 1 #define FUSE_NODE_SLAB 1
@ -47,7 +48,7 @@
#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1 #define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
#define FUSE_UNKNOWN_INO 0xffffffff
#define FUSE_UNKNOWN_INO UINT64_MAX
#define OFFSET_MAX 0x7fffffffffffffffLL #define OFFSET_MAX 0x7fffffffffffffffLL
#define NODE_TABLE_MIN_SIZE 8192 #define NODE_TABLE_MIN_SIZE 8192
@ -122,25 +123,26 @@ struct node_slab {
int used; int used;
}; };
struct fuse {
struct fuse_session *se;
struct node_table name_table;
struct node_table id_table;
struct list_head lru_table;
fuse_ino_t ctr;
unsigned int generation;
unsigned int hidectr;
pthread_mutex_t lock;
struct fuse_config conf;
int intr_installed;
struct fuse_fs *fs;
int nullpath_ok;
int utime_omit_ok;
struct lock_queue_element *lockq;
int pagesize;
struct list_head partial_slabs;
struct list_head full_slabs;
pthread_t prune_thread;
struct fuse
{
struct fuse_session *se;
struct node_table name_table;
struct node_table id_table;
struct list_head lru_table;
fuse_ino_t ctr;
uint64_t generation;
unsigned int hidectr;
pthread_mutex_t lock;
struct fuse_config conf;
int intr_installed;
struct fuse_fs *fs;
int nullpath_ok;
int utime_omit_ok;
struct lock_queue_element *lockq;
int pagesize;
struct list_head partial_slabs;
struct list_head full_slabs;
pthread_t prune_thread;
}; };
struct lock { struct lock {
@ -157,7 +159,7 @@ struct node
struct node *name_next; struct node *name_next;
struct node *id_next; struct node *id_next;
fuse_ino_t nodeid; fuse_ino_t nodeid;
unsigned int generation;
uint64_t generation;
int refctr; int refctr;
struct node *parent; struct node *parent;
char *name; char *name;
@ -396,15 +398,21 @@ static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
return NULL; return NULL;
} }
static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
static
struct node*
get_node(struct fuse *f,
const fuse_ino_t nodeid)
{ {
struct node *node = get_node_nocheck(f, nodeid);
if (!node) {
fprintf(stderr, "fuse internal error: node %llu not found\n",
(unsigned long long) nodeid);
abort();
}
return node;
struct node *node = get_node_nocheck(f, nodeid);
if(!node)
{
fprintf(stderr, "fuse internal error: node %llu not found\n",
(unsigned long long) nodeid);
abort();
}
return node;
} }
static void curr_time(struct timespec *now); static void curr_time(struct timespec *now);
@ -705,15 +713,33 @@ static void unref_node(struct fuse *f, struct node *node)
delete_node(f, node); delete_node(f, node);
} }
static fuse_ino_t next_id(struct fuse *f)
static
uint64_t
rand64(void)
{ {
do {
f->ctr = (f->ctr + 1) & 0xffffffff;
if (!f->ctr)
f->generation ++;
} while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
get_node_nocheck(f, f->ctr) != NULL);
return f->ctr;
uint64_t rv;
rv = rand();
rv <<= 32;
rv |= rand();
return rv;
}
static
fuse_ino_t
next_id(struct fuse *f)
{
do
{
f->ctr = ((f->ctr + 1) & UINT64_MAX);
if(f->ctr == 0)
f->generation++;
} while((f->ctr == 0) ||
(f->ctr == FUSE_UNKNOWN_INO) ||
(get_node_nocheck(f, f->ctr) != NULL));
return f->ctr;
} }
static struct node *lookup_node(struct fuse *f, fuse_ino_t parent, static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
@ -1182,42 +1208,51 @@ static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2,
free(path2); free(path2);
} }
static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
static
void
forget_node(struct fuse *f,
const fuse_ino_t nodeid,
const uint64_t nlookup)
{ {
struct node *node;
if (nodeid == FUSE_ROOT_ID)
return;
pthread_mutex_lock(&f->lock);
node = get_node(f, nodeid);
struct node *node;
/*
* Node may still be locked due to interrupt idiocy in open,
* create and opendir
*/
while (node->nlookup == nlookup && node->treelock) {
struct lock_queue_element qe = {
.nodeid1 = nodeid,
};
if(nodeid == FUSE_ROOT_ID)
return;
debug_path(f, "QUEUE PATH (forget)", nodeid, NULL, false);
queue_path(f, &qe);
pthread_mutex_lock(&f->lock);
node = get_node(f, nodeid);
do {
pthread_cond_wait(&qe.cond, &f->lock);
} while (node->nlookup == nlookup && node->treelock);
/*
* Node may still be locked due to interrupt idiocy in open,
* create and opendir
*/
while(node->nlookup == nlookup && node->treelock)
{
struct lock_queue_element qe = {
.nodeid1 = nodeid,
};
dequeue_path(f, &qe);
debug_path(f, "DEQUEUE_PATH (forget)", nodeid, NULL, false);
}
debug_path(f, "QUEUE PATH (forget)", nodeid, NULL, false);
queue_path(f, &qe);
assert(node->nlookup >= nlookup);
node->nlookup -= nlookup;
if (!node->nlookup) {
unref_node(f, node);
} else if (lru_enabled(f) && node->nlookup == 1) {
set_forget_time(f, node);
}
pthread_mutex_unlock(&f->lock);
do
{
pthread_cond_wait(&qe.cond, &f->lock);
}
while((node->nlookup == nlookup) && node->treelock);
dequeue_path(f, &qe);
debug_path(f, "DEQUEUE_PATH (forget)", nodeid, NULL, false);
}
assert(node->nlookup >= nlookup);
node->nlookup -= nlookup;
if(!node->nlookup)
unref_node(f, node);
else if(lru_enabled(f) && node->nlookup == 1)
set_forget_time(f, node);
pthread_mutex_unlock(&f->lock);
} }
static void unlink_node(struct fuse *f, struct node *node) static void unlink_node(struct fuse *f, struct node *node)
@ -2390,9 +2425,12 @@ static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
update_stat(node, &e->attr); update_stat(node, &e->attr);
pthread_mutex_unlock(&f->lock); pthread_mutex_unlock(&f->lock);
set_stat(f, e->ino, &e->attr); set_stat(f, e->ino, &e->attr);
if (f->conf.debug)
fprintf(stderr, " NODEID: %lu\n",
(unsigned long) e->ino);
if(f->conf.debug)
fprintf(stderr,
" NODEID: %llu\n"
" GEN: %llu\n",
(unsigned long long)e->ino,
(unsigned long long)e->generation);
} }
} }
return res; return res;
@ -2586,19 +2624,28 @@ static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
reply_entry(req, &e, err); reply_entry(req, &e, err);
} }
static void do_forget(struct fuse *f, fuse_ino_t ino, uint64_t nlookup)
static
void
do_forget(struct fuse *f,
const fuse_ino_t ino,
const uint64_t nlookup)
{ {
if (f->conf.debug)
fprintf(stderr, "FORGET %llu/%llu\n", (unsigned long long)ino,
(unsigned long long) nlookup);
forget_node(f, ino, nlookup);
if(f->conf.debug)
fprintf(stderr,
"FORGET %llu/%llu\n",
(unsigned long long)ino,
(unsigned long long)nlookup);
forget_node(f, ino, nlookup);
} }
static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
unsigned long nlookup)
static
void
fuse_lib_forget(fuse_req_t req,
const fuse_ino_t ino,
const uint64_t nlookup)
{ {
do_forget(req_fuse(req), ino, nlookup);
fuse_reply_none(req);
do_forget(req_fuse(req), ino, nlookup);
fuse_reply_none(req);
} }
static void fuse_lib_forget_multi(fuse_req_t req, size_t count, static void fuse_lib_forget_multi(fuse_req_t req, size_t count,
@ -4669,9 +4716,10 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
} }
/* Trace topmost layer by default */ /* Trace topmost layer by default */
srand(time(NULL));
f->fs->debug = f->conf.debug; f->fs->debug = f->conf.debug;
f->ctr = 0; f->ctr = 0;
f->generation = 0;
f->generation = rand64();
if (node_table_init(&f->name_table) == -1) if (node_table_init(&f->name_table) == -1)
goto out_free_session; goto out_free_session;

Loading…
Cancel
Save