12#include "fuse_config.h"
17#include "fuse_kernel.h"
39#define FUSE_NODE_SLAB 1
45#ifndef RENAME_EXCHANGE
46#define RENAME_EXCHANGE (1 << 1)
49#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
51#define FUSE_UNKNOWN_INO 0xffffffff
52#define OFFSET_MAX 0x7fffffffffffffffLL
54#define NODE_TABLE_MIN_SIZE 8192
67struct lock_queue_element {
68 struct lock_queue_element *next;
89#define container_of(ptr, type, member) ({ \
90 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
91 (type *)( (char *)__mptr - offsetof(type,member) );})
93#define list_entry(ptr, type, member) \
94 container_of(ptr, type, member)
97 struct list_head *next;
98 struct list_head *prev;
102 struct list_head list;
103 struct list_head freelist;
108 struct fuse_session *se;
109 struct node_table name_table;
110 struct node_table id_table;
111 struct list_head lru_table;
113 unsigned int generation;
114 unsigned int hidectr;
115 pthread_mutex_t lock;
119 struct lock_queue_element *lockq;
121 struct list_head partial_slabs;
122 struct list_head full_slabs;
123 pthread_t prune_thread;
136 struct node *name_next;
137 struct node *id_next;
139 unsigned int generation;
145 struct timespec stat_updated;
146 struct timespec mtime;
149 unsigned int is_hidden : 1;
150 unsigned int cache_valid : 1;
152 char inline_name[32];
155#define TREELOCK_WRITE -1
156#define TREELOCK_WAIT_OFFSET INT_MIN
160 struct list_head lru;
161 struct timespec forget_time;
164struct fuse_direntry {
167 struct fuse_direntry *next;
171 pthread_mutex_t lock;
175 struct fuse_direntry *first;
176 struct fuse_direntry **last;
186struct fuse_context_i {
197static pthread_key_t fuse_context_key;
198static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
199static int fuse_context_ref;
202static int fuse_register_module(
const char *name,
204 struct fusemod_so *so)
210 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate module\n");
213 mod->name = strdup(name);
215 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate module name\n");
219 mod->factory = factory;
224 mod->next = fuse_modules;
230static void fuse_unregister_module(
struct fuse_module *m)
233 for (mp = &fuse_modules; *mp; mp = &(*mp)->next) {
243static int fuse_load_so_module(
const char *module)
247 struct fusemod_so *so;
250 tmp = malloc(strlen(module) + 64);
252 fuse_log(FUSE_LOG_ERR,
"fuse: memory allocation failed\n");
255 sprintf(tmp,
"libfusemod_%s.so", module);
256 so = calloc(1,
sizeof(
struct fusemod_so));
258 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate module so\n");
262 so->handle = dlopen(tmp, RTLD_NOW);
263 if (so->handle == NULL) {
264 fuse_log(FUSE_LOG_ERR,
"fuse: dlopen(%s) failed: %s\n",
269 sprintf(tmp,
"fuse_module_%s_factory", module);
271 if (factory == NULL) {
272 fuse_log(FUSE_LOG_ERR,
"fuse: symbol <%s> not found in module: %s\n",
276 ret = fuse_register_module(module, *factory, so);
291static struct fuse_module *fuse_find_module(
const char *module)
294 for (m = fuse_modules; m; m = m->next) {
295 if (strcmp(module, m->name) == 0) {
303static struct fuse_module *fuse_get_module(
const char *module)
307 pthread_mutex_lock(&fuse_context_lock);
308 m = fuse_find_module(module);
310 int err = fuse_load_so_module(module);
312 m = fuse_find_module(module);
314 pthread_mutex_unlock(&fuse_context_lock);
320 pthread_mutex_lock(&fuse_context_lock);
326 if (!m->ctr && m->so) {
327 struct fusemod_so *so = m->so;
332 for (mp = &fuse_modules; *mp;) {
334 fuse_unregister_module(*mp);
341 }
else if (!m->ctr) {
342 fuse_unregister_module(m);
344 pthread_mutex_unlock(&fuse_context_lock);
347static void init_list_head(
struct list_head *list)
353static int list_empty(
const struct list_head *head)
355 return head->next == head;
358static void list_add(
struct list_head *
new,
struct list_head *prev,
359 struct list_head *next)
367static inline void list_add_head(
struct list_head *
new,
struct list_head *head)
369 list_add(
new, head, head->next);
372static inline void list_add_tail(
struct list_head *
new,
struct list_head *head)
374 list_add(
new, head->prev, head);
377static inline void list_del(
struct list_head *entry)
379 struct list_head *prev = entry->prev;
380 struct list_head *next = entry->next;
386static inline int lru_enabled(
struct fuse *f)
388 return f->conf.remember > 0;
391static struct node_lru *node_lru(
struct node *node)
393 return (
struct node_lru *) node;
396static size_t get_node_size(
struct fuse *f)
399 return sizeof(
struct node_lru);
401 return sizeof(
struct node);
405static struct node_slab *list_to_slab(
struct list_head *head)
407 return (
struct node_slab *) head;
410static struct node_slab *node_to_slab(
struct fuse *f,
struct node *node)
412 return (
struct node_slab *) (((uintptr_t) node) & ~((uintptr_t) f->pagesize - 1));
415static int alloc_slab(
struct fuse *f)
418 struct node_slab *slab;
422 size_t node_size = get_node_size(f);
424 mem = mmap(NULL, f->pagesize, PROT_READ | PROT_WRITE,
425 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
427 if (mem == MAP_FAILED)
431 init_list_head(&slab->freelist);
433 num = (f->pagesize -
sizeof(
struct node_slab)) / node_size;
435 start = (
char *) mem + f->pagesize - num * node_size;
436 for (i = 0; i < num; i++) {
439 n = (
struct list_head *) (start + i * node_size);
440 list_add_tail(n, &slab->freelist);
442 list_add_tail(&slab->list, &f->partial_slabs);
447static struct node *alloc_node(
struct fuse *f)
449 struct node_slab *slab;
450 struct list_head *node;
452 if (list_empty(&f->partial_slabs)) {
453 int res = alloc_slab(f);
457 slab = list_to_slab(f->partial_slabs.next);
459 node = slab->freelist.next;
461 if (list_empty(&slab->freelist)) {
462 list_del(&slab->list);
463 list_add_tail(&slab->list, &f->full_slabs);
465 memset(node, 0,
sizeof(
struct node));
467 return (
struct node *) node;
470static void free_slab(
struct fuse *f,
struct node_slab *slab)
474 list_del(&slab->list);
475 res = munmap(slab, f->pagesize);
477 fuse_log(FUSE_LOG_WARNING,
"fuse warning: munmap(%p) failed\n",
481static void free_node_mem(
struct fuse *f,
struct node *node)
483 struct node_slab *slab = node_to_slab(f, node);
484 struct list_head *n = (
struct list_head *) node;
488 if (list_empty(&slab->freelist)) {
489 list_del(&slab->list);
490 list_add_tail(&slab->list, &f->partial_slabs);
492 list_add_head(n, &slab->freelist);
498static struct node *alloc_node(
struct fuse *f)
500 return (
struct node *) calloc(1, get_node_size(f));
503static void free_node_mem(
struct fuse *f,
struct node *node)
510static size_t id_hash(
struct fuse *f,
fuse_ino_t ino)
512 uint64_t hash = ((uint32_t) ino * 2654435761U) % f->id_table.size;
513 uint64_t oldhash = hash % (f->id_table.size / 2);
515 if (oldhash >= f->id_table.split)
521static struct node *get_node_nocheck(
struct fuse *f,
fuse_ino_t nodeid)
523 size_t hash = id_hash(f, nodeid);
526 for (node = f->id_table.array[hash]; node != NULL; node = node->id_next)
527 if (node->nodeid == nodeid)
533static struct node *get_node(
struct fuse *f,
fuse_ino_t nodeid)
535 struct node *node = get_node_nocheck(f, nodeid);
537 fuse_log(FUSE_LOG_ERR,
"fuse internal error: node %llu not found\n",
538 (
unsigned long long) nodeid);
544static void curr_time(
struct timespec *now);
545static double diff_timespec(
const struct timespec *t1,
546 const struct timespec *t2);
548static void remove_node_lru(
struct node *node)
550 struct node_lru *lnode = node_lru(node);
551 list_del(&lnode->lru);
552 init_list_head(&lnode->lru);
555static void set_forget_time(
struct fuse *f,
struct node *node)
557 struct node_lru *lnode = node_lru(node);
559 list_del(&lnode->lru);
560 list_add_tail(&lnode->lru, &f->lru_table);
561 curr_time(&lnode->forget_time);
564static void free_node(
struct fuse *f,
struct node *node)
566 if (node->name != node->inline_name)
568 free_node_mem(f, node);
571static void node_table_reduce(
struct node_table *t)
573 size_t newsize = t->size / 2;
576 if (newsize < NODE_TABLE_MIN_SIZE)
579 newarray = realloc(t->array,
sizeof(
struct node *) * newsize);
580 if (newarray != NULL)
584 t->split = t->size / 2;
587static void remerge_id(
struct fuse *f)
589 struct node_table *t = &f->id_table;
593 node_table_reduce(t);
595 for (iter = 8; t->split > 0 && iter; iter--) {
599 upper = &t->array[t->split + t->size / 2];
603 for (nodep = &t->array[t->split]; *nodep;
604 nodep = &(*nodep)->id_next);
613static void unhash_id(
struct fuse *f,
struct node *node)
615 struct node **nodep = &f->id_table.array[id_hash(f, node->nodeid)];
617 for (; *nodep != NULL; nodep = &(*nodep)->id_next)
618 if (*nodep == node) {
619 *nodep = node->id_next;
622 if(f->id_table.use < f->id_table.size / 4)
628static int node_table_resize(
struct node_table *t)
630 size_t newsize = t->size * 2;
633 newarray = realloc(t->array,
sizeof(
struct node *) * newsize);
634 if (newarray == NULL)
638 memset(t->array + t->size, 0, t->size *
sizeof(
struct node *));
645static void rehash_id(
struct fuse *f)
647 struct node_table *t = &f->id_table;
652 if (t->split == t->size / 2)
657 for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
658 struct node *node = *nodep;
659 size_t newhash = id_hash(f, node->nodeid);
661 if (newhash != hash) {
663 *nodep = node->id_next;
664 node->id_next = t->array[newhash];
665 t->array[newhash] = node;
667 next = &node->id_next;
670 if (t->split == t->size / 2)
671 node_table_resize(t);
674static void hash_id(
struct fuse *f,
struct node *node)
676 size_t hash = id_hash(f, node->nodeid);
677 node->id_next = f->id_table.array[hash];
678 f->id_table.array[hash] = node;
681 if (f->id_table.use >= f->id_table.size / 2)
685static size_t name_hash(
struct fuse *f,
fuse_ino_t parent,
688 uint64_t hash = parent;
691 for (; *name; name++)
692 hash = hash * 31 + (
unsigned char) *name;
694 hash %= f->name_table.size;
695 oldhash = hash % (f->name_table.size / 2);
696 if (oldhash >= f->name_table.split)
702static void unref_node(
struct fuse *f,
struct node *node);
704static void remerge_name(
struct fuse *f)
706 struct node_table *t = &f->name_table;
710 node_table_reduce(t);
712 for (iter = 8; t->split > 0 && iter; iter--) {
716 upper = &t->array[t->split + t->size / 2];
720 for (nodep = &t->array[t->split]; *nodep;
721 nodep = &(*nodep)->name_next);
730static void unhash_name(
struct fuse *f,
struct node *node)
733 size_t hash = name_hash(f, node->parent->nodeid, node->name);
734 struct node **nodep = &f->name_table.array[hash];
736 for (; *nodep != NULL; nodep = &(*nodep)->name_next)
737 if (*nodep == node) {
738 *nodep = node->name_next;
739 node->name_next = NULL;
740 unref_node(f, node->parent);
741 if (node->name != node->inline_name)
747 if (f->name_table.use < f->name_table.size / 4)
752 "fuse internal error: unable to unhash node: %llu\n",
753 (
unsigned long long) node->nodeid);
758static void rehash_name(
struct fuse *f)
760 struct node_table *t = &f->name_table;
765 if (t->split == t->size / 2)
770 for (nodep = &t->array[hash]; *nodep != NULL; nodep = next) {
771 struct node *node = *nodep;
772 size_t newhash = name_hash(f, node->parent->nodeid, node->name);
774 if (newhash != hash) {
776 *nodep = node->name_next;
777 node->name_next = t->array[newhash];
778 t->array[newhash] = node;
780 next = &node->name_next;
783 if (t->split == t->size / 2)
784 node_table_resize(t);
787static int hash_name(
struct fuse *f,
struct node *node,
fuse_ino_t parentid,
790 size_t hash = name_hash(f, parentid, name);
791 struct node *parent = get_node(f, parentid);
792 if (strlen(name) <
sizeof(node->inline_name)) {
793 strcpy(node->inline_name, name);
794 node->name = node->inline_name;
796 node->name = strdup(name);
797 if (node->name == NULL)
802 node->parent = parent;
803 node->name_next = f->name_table.array[hash];
804 f->name_table.array[hash] = node;
807 if (f->name_table.use >= f->name_table.size / 2)
813static void delete_node(
struct fuse *f,
struct node *node)
816 fuse_log(FUSE_LOG_DEBUG,
"DELETE: %llu\n",
817 (
unsigned long long) node->nodeid);
819 assert(node->treelock == 0);
820 unhash_name(f, node);
822 remove_node_lru(node);
827static void unref_node(
struct fuse *f,
struct node *node)
829 assert(node->refctr > 0);
832 delete_node(f, node);
838 f->ctr = (f->ctr + 1) & 0xffffffff;
841 }
while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
842 get_node_nocheck(f, f->ctr) != NULL);
846static struct node *lookup_node(
struct fuse *f,
fuse_ino_t parent,
849 size_t hash = name_hash(f, parent, name);
852 for (node = f->name_table.array[hash]; node != NULL; node = node->name_next)
853 if (node->parent->nodeid == parent &&
854 strcmp(node->name, name) == 0)
860static void inc_nlookup(
struct node *node)
867static struct node *find_node(
struct fuse *f,
fuse_ino_t parent,
872 pthread_mutex_lock(&f->lock);
874 node = get_node(f, parent);
876 node = lookup_node(f, parent, name);
878 node = alloc_node(f);
882 node->nodeid = next_id(f);
883 node->generation = f->generation;
884 if (f->conf.remember)
887 if (hash_name(f, node, parent, name) == -1) {
893 if (lru_enabled(f)) {
894 struct node_lru *lnode = node_lru(node);
895 init_list_head(&lnode->lru);
897 }
else if (lru_enabled(f) && node->nlookup == 1) {
898 remove_node_lru(node);
902 pthread_mutex_unlock(&f->lock);
906static int lookup_path_in_cache(
struct fuse *f,
909 char *tmp = strdup(path);
913 pthread_mutex_lock(&f->lock);
918 char *path_element = strtok_r(tmp,
"/", &save_ptr);
919 while (path_element != NULL) {
920 struct node *node = lookup_node(f, ino, path_element);
926 path_element = strtok_r(NULL,
"/", &save_ptr);
928 pthread_mutex_unlock(&f->lock);
936static char *add_name(
char **buf,
unsigned *bufsize,
char *s,
const char *name)
938 size_t len = strlen(name);
940 if (s - len <= *buf) {
941 unsigned pathlen = *bufsize - (s - *buf);
942 unsigned newbufsize = *bufsize;
945 while (newbufsize < pathlen + len + 1) {
946 if (newbufsize >= 0x80000000)
947 newbufsize = 0xffffffff;
952 newbuf = realloc(*buf, newbufsize);
957 s = newbuf + newbufsize - pathlen;
958 memmove(s, newbuf + *bufsize - pathlen, pathlen);
959 *bufsize = newbufsize;
962 memcpy(s, name, len);
969static void unlock_path(
struct fuse *f,
fuse_ino_t nodeid,
struct node *wnode,
975 assert(wnode->treelock == TREELOCK_WRITE);
979 for (node = get_node(f, nodeid);
980 node != end && node->nodeid !=
FUSE_ROOT_ID; node = node->parent) {
981 assert(node->treelock != 0);
982 assert(node->treelock != TREELOCK_WAIT_OFFSET);
983 assert(node->treelock != TREELOCK_WRITE);
985 if (node->treelock == TREELOCK_WAIT_OFFSET)
990static int try_get_path(
struct fuse *f,
fuse_ino_t nodeid,
const char *name,
991 char **path,
struct node **wnodep,
bool need_lock)
993 unsigned bufsize = 256;
997 struct node *wnode = NULL;
1003 buf = malloc(bufsize);
1007 s = buf + bufsize - 1;
1011 s = add_name(&buf, &bufsize, s, name);
1019 wnode = lookup_node(f, nodeid, name);
1021 if (wnode->treelock != 0) {
1022 if (wnode->treelock > 0)
1023 wnode->treelock += TREELOCK_WAIT_OFFSET;
1027 wnode->treelock = TREELOCK_WRITE;
1031 for (node = get_node(f, nodeid); node->nodeid !=
FUSE_ROOT_ID;
1032 node = node->parent) {
1034 if (node->name == NULL || node->parent == NULL)
1038 s = add_name(&buf, &bufsize, s, node->name);
1044 if (node->treelock < 0)
1052 memmove(buf, s, bufsize - (s - buf));
1064 unlock_path(f, nodeid, wnode, node);
1072static int try_get_path2(
struct fuse *f,
fuse_ino_t nodeid1,
const char *name1,
1074 char **path1,
char **path2,
1075 struct node **wnode1,
struct node **wnode2)
1080 err = try_get_path(f, nodeid1, name1, path1, wnode1,
true);
1082 err = try_get_path(f, nodeid2, name2, path2, wnode2,
true);
1084 struct node *wn1 = wnode1 ? *wnode1 : NULL;
1086 unlock_path(f, nodeid1, wn1, NULL);
1093static void queue_element_wakeup(
struct fuse *f,
struct lock_queue_element *qe)
1099 if (get_node(f, qe->nodeid1)->treelock == 0)
1100 pthread_cond_signal(&qe->cond);
1109 err = try_get_path(f, qe->nodeid1, qe->name1, qe->path1,
1112 err = try_get_path2(f, qe->nodeid1, qe->name1, qe->nodeid2,
1113 qe->name2, qe->path1, qe->path2, qe->wnode1,
1122 pthread_cond_signal(&qe->cond);
1125static void wake_up_queued(
struct fuse *f)
1127 struct lock_queue_element *qe;
1129 for (qe = f->lockq; qe != NULL; qe = qe->next)
1130 queue_element_wakeup(f, qe);
1133static void debug_path(
struct fuse *f,
const char *msg,
fuse_ino_t nodeid,
1134 const char *name,
bool wr)
1136 if (f->conf.debug) {
1137 struct node *wnode = NULL;
1140 wnode = lookup_node(f, nodeid, name);
1143 fuse_log(FUSE_LOG_DEBUG,
"%s %llu (w)\n",
1144 msg, (
unsigned long long) wnode->nodeid);
1146 fuse_log(FUSE_LOG_DEBUG,
"%s %llu\n",
1147 msg, (
unsigned long long) nodeid);
1152static void queue_path(
struct fuse *f,
struct lock_queue_element *qe)
1154 struct lock_queue_element **qp;
1157 pthread_cond_init(&qe->cond, NULL);
1159 for (qp = &f->lockq; *qp != NULL; qp = &(*qp)->next);
1163static void dequeue_path(
struct fuse *f,
struct lock_queue_element *qe)
1165 struct lock_queue_element **qp;
1167 pthread_cond_destroy(&qe->cond);
1168 for (qp = &f->lockq; *qp != qe; qp = &(*qp)->next);
1172static int wait_path(
struct fuse *f,
struct lock_queue_element *qe)
1177 pthread_cond_wait(&qe->cond, &f->lock);
1178 }
while (!qe->done);
1180 dequeue_path(f, qe);
1185static int get_path_common(
struct fuse *f,
fuse_ino_t nodeid,
const char *name,
1186 char **path,
struct node **wnode)
1190 pthread_mutex_lock(&f->lock);
1191 err = try_get_path(f, nodeid, name, path, wnode,
true);
1192 if (err == -EAGAIN) {
1193 struct lock_queue_element qe = {
1199 debug_path(f,
"QUEUE PATH", nodeid, name, !!wnode);
1200 err = wait_path(f, &qe);
1201 debug_path(f,
"DEQUEUE PATH", nodeid, name, !!wnode);
1203 pthread_mutex_unlock(&f->lock);
1208static int get_path(
struct fuse *f,
fuse_ino_t nodeid,
char **path)
1210 return get_path_common(f, nodeid, NULL, path, NULL);
1213static int get_path_nullok(
struct fuse *f,
fuse_ino_t nodeid,
char **path)
1217 if (f->conf.nullpath_ok) {
1220 err = get_path_common(f, nodeid, NULL, path, NULL);
1228static int get_path_name(
struct fuse *f,
fuse_ino_t nodeid,
const char *name,
1231 return get_path_common(f, nodeid, name, path, NULL);
1234static int get_path_wrlock(
struct fuse *f,
fuse_ino_t nodeid,
const char *name,
1235 char **path,
struct node **wnode)
1237 return get_path_common(f, nodeid, name, path, wnode);
1240#if defined(__FreeBSD__)
1241#define CHECK_DIR_LOOP
1244#if defined(CHECK_DIR_LOOP)
1245static int check_dir_loop(
struct fuse *f,
1249 struct node *node, *node1, *node2;
1252 node1 = lookup_node(f, nodeid1, name1);
1253 id1 = node1 ? node1->nodeid : nodeid1;
1255 node2 = lookup_node(f, nodeid2, name2);
1256 id2 = node2 ? node2->nodeid : nodeid2;
1258 for (node = get_node(f, id2); node->nodeid !=
FUSE_ROOT_ID;
1259 node = node->parent) {
1260 if (node->name == NULL || node->parent == NULL)
1263 if (node->nodeid != id2 && node->nodeid == id1)
1269 for (node = get_node(f, id1); node->nodeid !=
FUSE_ROOT_ID;
1270 node = node->parent) {
1271 if (node->name == NULL || node->parent == NULL)
1274 if (node->nodeid != id1 && node->nodeid == id2)
1283static int get_path2(
struct fuse *f,
fuse_ino_t nodeid1,
const char *name1,
1285 char **path1,
char **path2,
1286 struct node **wnode1,
struct node **wnode2)
1290 pthread_mutex_lock(&f->lock);
1292#if defined(CHECK_DIR_LOOP)
1296 err = check_dir_loop(f, nodeid1, name1, nodeid2, name2);
1302 err = try_get_path2(f, nodeid1, name1, nodeid2, name2,
1303 path1, path2, wnode1, wnode2);
1304 if (err == -EAGAIN) {
1305 struct lock_queue_element qe = {
1316 debug_path(f,
"QUEUE PATH1", nodeid1, name1, !!wnode1);
1317 debug_path(f,
" PATH2", nodeid2, name2, !!wnode2);
1318 err = wait_path(f, &qe);
1319 debug_path(f,
"DEQUEUE PATH1", nodeid1, name1, !!wnode1);
1320 debug_path(f,
" PATH2", nodeid2, name2, !!wnode2);
1323#if defined(CHECK_DIR_LOOP)
1326 pthread_mutex_unlock(&f->lock);
1331static void free_path_wrlock(
struct fuse *f,
fuse_ino_t nodeid,
1332 struct node *wnode,
char *path)
1334 pthread_mutex_lock(&f->lock);
1335 unlock_path(f, nodeid, wnode, NULL);
1338 pthread_mutex_unlock(&f->lock);
1342static void free_path(
struct fuse *f,
fuse_ino_t nodeid,
char *path)
1345 free_path_wrlock(f, nodeid, NULL, path);
1349 struct node *wnode1,
struct node *wnode2,
1350 char *path1,
char *path2)
1352 pthread_mutex_lock(&f->lock);
1353 unlock_path(f, nodeid1, wnode1, NULL);
1354 unlock_path(f, nodeid2, wnode2, NULL);
1356 pthread_mutex_unlock(&f->lock);
1361static void forget_node(
struct fuse *f,
fuse_ino_t nodeid, uint64_t nlookup)
1366 pthread_mutex_lock(&f->lock);
1367 node = get_node(f, nodeid);
1373 while (node->nlookup == nlookup && node->treelock) {
1374 struct lock_queue_element qe = {
1378 debug_path(f,
"QUEUE PATH (forget)", nodeid, NULL,
false);
1382 pthread_cond_wait(&qe.cond, &f->lock);
1383 }
while (node->nlookup == nlookup && node->treelock);
1385 dequeue_path(f, &qe);
1386 debug_path(f,
"DEQUEUE_PATH (forget)", nodeid, NULL,
false);
1389 assert(node->nlookup >= nlookup);
1390 node->nlookup -= nlookup;
1391 if (!node->nlookup) {
1392 unref_node(f, node);
1393 }
else if (lru_enabled(f) && node->nlookup == 1) {
1394 set_forget_time(f, node);
1396 pthread_mutex_unlock(&f->lock);
1399static void unlink_node(
struct fuse *f,
struct node *node)
1401 if (f->conf.remember) {
1402 assert(node->nlookup > 1);
1405 unhash_name(f, node);
1408static void remove_node(
struct fuse *f,
fuse_ino_t dir,
const char *name)
1412 pthread_mutex_lock(&f->lock);
1413 node = lookup_node(f, dir, name);
1415 unlink_node(f, node);
1416 pthread_mutex_unlock(&f->lock);
1419static int rename_node(
struct fuse *f,
fuse_ino_t olddir,
const char *oldname,
1420 fuse_ino_t newdir,
const char *newname,
int hide)
1423 struct node *newnode;
1426 pthread_mutex_lock(&f->lock);
1427 node = lookup_node(f, olddir, oldname);
1428 newnode = lookup_node(f, newdir, newname);
1432 if (newnode != NULL) {
1434 fuse_log(FUSE_LOG_ERR,
"fuse: hidden file got created during hiding\n");
1438 unlink_node(f, newnode);
1441 unhash_name(f, node);
1442 if (hash_name(f, node, newdir, newname) == -1) {
1448 node->is_hidden = 1;
1451 pthread_mutex_unlock(&f->lock);
1455static int exchange_node(
struct fuse *f,
fuse_ino_t olddir,
const char *oldname,
1458 struct node *oldnode;
1459 struct node *newnode;
1462 pthread_mutex_lock(&f->lock);
1463 oldnode = lookup_node(f, olddir, oldname);
1464 newnode = lookup_node(f, newdir, newname);
1467 unhash_name(f, oldnode);
1469 unhash_name(f, newnode);
1473 if (hash_name(f, oldnode, newdir, newname) == -1)
1477 if (hash_name(f, newnode, olddir, oldname) == -1)
1482 pthread_mutex_unlock(&f->lock);
1486static void set_stat(
struct fuse *f,
fuse_ino_t nodeid,
struct stat *stbuf)
1488 if (!f->conf.use_ino)
1489 stbuf->st_ino = nodeid;
1490 if (f->conf.set_mode)
1491 stbuf->st_mode = (stbuf->st_mode & S_IFMT) |
1492 (0777 & ~f->conf.umask);
1493 if (f->conf.set_uid)
1494 stbuf->st_uid = f->conf.uid;
1495 if (f->conf.set_gid)
1496 stbuf->st_gid = f->conf.gid;
1504static void fuse_intr_sighandler(
int sig)
1510struct fuse_intr_data {
1512 pthread_cond_t cond;
1516static void fuse_interrupt(
fuse_req_t req,
void *d_)
1518 struct fuse_intr_data *d = d_;
1519 struct fuse *f = req_fuse(req);
1521 if (d->id == pthread_self())
1524 pthread_mutex_lock(&f->lock);
1525 while (!d->finished) {
1527 struct timespec timeout;
1529 pthread_kill(d->id, f->conf.intr_signal);
1530 gettimeofday(&now, NULL);
1531 timeout.tv_sec = now.tv_sec + 1;
1532 timeout.tv_nsec = now.tv_usec * 1000;
1533 pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
1535 pthread_mutex_unlock(&f->lock);
1538static void fuse_do_finish_interrupt(
struct fuse *f,
fuse_req_t req,
1539 struct fuse_intr_data *d)
1541 pthread_mutex_lock(&f->lock);
1543 pthread_cond_broadcast(&d->cond);
1544 pthread_mutex_unlock(&f->lock);
1546 pthread_cond_destroy(&d->cond);
1549static void fuse_do_prepare_interrupt(
fuse_req_t req,
struct fuse_intr_data *d)
1551 d->id = pthread_self();
1552 pthread_cond_init(&d->cond, NULL);
1557static inline void fuse_finish_interrupt(
struct fuse *f,
fuse_req_t req,
1558 struct fuse_intr_data *d)
1561 fuse_do_finish_interrupt(f, req, d);
1564static inline void fuse_prepare_interrupt(
struct fuse *f,
fuse_req_t req,
1565 struct fuse_intr_data *d)
1568 fuse_do_prepare_interrupt(req, d);
1572 char* buf,
size_t len)
1576 snprintf(buf, len,
"%llu", (
unsigned long long) fi->
fh);
1580int fuse_fs_getattr(
struct fuse_fs *fs,
const char *path,
struct stat *buf,
1584 if (fs->op.getattr) {
1587 fuse_log(FUSE_LOG_DEBUG,
"getattr[%s] %s\n",
1588 file_info_string(fi, buf,
sizeof(buf)),
1591 return fs->op.getattr(path, buf, fi);
1597int fuse_fs_rename(
struct fuse_fs *fs,
const char *oldpath,
1598 const char *newpath,
unsigned int flags)
1601 if (fs->op.rename) {
1603 fuse_log(FUSE_LOG_DEBUG,
"rename %s %s 0x%x\n", oldpath, newpath,
1606 return fs->op.rename(oldpath, newpath, flags);
1612int fuse_fs_unlink(
struct fuse_fs *fs,
const char *path)
1615 if (fs->op.unlink) {
1617 fuse_log(FUSE_LOG_DEBUG,
"unlink %s\n", path);
1619 return fs->op.unlink(path);
1625int fuse_fs_rmdir(
struct fuse_fs *fs,
const char *path)
1630 fuse_log(FUSE_LOG_DEBUG,
"rmdir %s\n", path);
1632 return fs->op.rmdir(path);
1638int fuse_fs_symlink(
struct fuse_fs *fs,
const char *linkname,
const char *path)
1641 if (fs->op.symlink) {
1643 fuse_log(FUSE_LOG_DEBUG,
"symlink %s %s\n", linkname, path);
1645 return fs->op.symlink(linkname, path);
1651int fuse_fs_link(
struct fuse_fs *fs,
const char *oldpath,
const char *newpath)
1656 fuse_log(FUSE_LOG_DEBUG,
"link %s %s\n", oldpath, newpath);
1658 return fs->op.link(oldpath, newpath);
1664int fuse_fs_release(
struct fuse_fs *fs,
const char *path,
1668 if (fs->op.release) {
1670 fuse_log(FUSE_LOG_DEBUG,
"release%s[%llu] flags: 0x%x\n",
1671 fi->
flush ?
"+flush" :
"",
1672 (
unsigned long long) fi->
fh, fi->
flags);
1674 return fs->op.release(path, fi);
1680int fuse_fs_opendir(
struct fuse_fs *fs,
const char *path,
1684 if (fs->op.opendir) {
1688 fuse_log(FUSE_LOG_DEBUG,
"opendir flags: 0x%x %s\n", fi->
flags,
1691 err = fs->op.opendir(path, fi);
1693 if (fs->debug && !err)
1694 fuse_log(FUSE_LOG_DEBUG,
" opendir[%llu] flags: 0x%x %s\n",
1695 (
unsigned long long) fi->
fh, fi->
flags, path);
1703int fuse_fs_open(
struct fuse_fs *fs,
const char *path,
1711 fuse_log(FUSE_LOG_DEBUG,
"open flags: 0x%x %s\n", fi->
flags,
1714 err = fs->op.open(path, fi);
1716 if (fs->debug && !err)
1717 fuse_log(FUSE_LOG_DEBUG,
" open[%llu] flags: 0x%x %s\n",
1718 (
unsigned long long) fi->
fh, fi->
flags, path);
1731 for (i = 0; i < buf->
count; i++)
1738int fuse_fs_read_buf(
struct fuse_fs *fs,
const char *path,
1739 struct fuse_bufvec **bufp,
size_t size, off_t off,
1743 if (fs->op.read || fs->op.read_buf) {
1748 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1749 (
unsigned long long) fi->
fh,
1750 size, (
unsigned long long) off, fi->
flags);
1752 if (fs->op.read_buf) {
1753 res = fs->op.read_buf(path, bufp, size, off, fi);
1767 *
buf = FUSE_BUFVEC_INIT(size);
1771 res = fs->op.read(path, mem, size,
off, fi);
1776 if (fs->debug && res >= 0)
1777 fuse_log(FUSE_LOG_DEBUG,
" read[%llu] %zu bytes from %llu\n",
1778 (
unsigned long long) fi->
fh,
1780 (
unsigned long long)
off);
1782 fuse_log(FUSE_LOG_ERR,
"fuse: read too many bytes\n");
1793int fuse_fs_read(
struct fuse_fs *fs,
const char *path,
char *mem,
size_t size,
1797 if (fs->op.read || fs->op.read_buf) {
1802 "read[%llu] %zu bytes from %llu flags: 0x%x\n",
1803 (
unsigned long long) fi->
fh,
1804 size, (
unsigned long long)
off, fi->
flags);
1806 if (fs->op.read_buf) {
1809 res = fs->op.read_buf(path, &
buf, size,
off, fi);
1818 res = fs->op.read(path, mem, size,
off, fi);
1821 if (fs->debug && res >= 0)
1822 fuse_log(FUSE_LOG_DEBUG,
" read[%llu] %u bytes from %llu\n",
1823 (
unsigned long long) fi->
fh,
1825 (
unsigned long long)
off);
1826 if (res >= 0 && res > (
int) size)
1827 fuse_log(FUSE_LOG_ERR,
"fuse: read too many bytes\n");
1835int fuse_fs_write_buf(
struct fuse_fs *fs,
const char *path,
1840 if (fs->op.write_buf || fs->op.write) {
1844 assert(
buf->idx == 0 &&
buf->off == 0);
1847 "write%s[%llu] %zu bytes to %llu flags: 0x%x\n",
1849 (
unsigned long long) fi->
fh,
1851 (
unsigned long long)
off,
1854 if (fs->op.write_buf) {
1855 res = fs->op.write_buf(path,
buf,
off, fi);
1861 if (
buf->count == 1 &&
1863 flatbuf = &
buf->buf[0];
1876 flatbuf = &tmp.
buf[0];
1879 res = fs->op.write(path, flatbuf->
mem, flatbuf->
size,
1885 if (fs->debug && res >= 0)
1886 fuse_log(FUSE_LOG_DEBUG,
" write%s[%llu] %u bytes to %llu\n",
1888 (
unsigned long long) fi->
fh, res,
1889 (
unsigned long long)
off);
1890 if (res > (
int) size)
1891 fuse_log(FUSE_LOG_ERR,
"fuse: wrote too many bytes\n");
1899int fuse_fs_write(
struct fuse_fs *fs,
const char *path,
const char *mem,
1904 bufv.
buf[0].
mem = (
void *) mem;
1906 return fuse_fs_write_buf(fs, path, &bufv,
off, fi);
1909int fuse_fs_fsync(
struct fuse_fs *fs,
const char *path,
int datasync,
1915 fuse_log(FUSE_LOG_DEBUG,
"fsync[%llu] datasync: %i\n",
1916 (
unsigned long long) fi->
fh, datasync);
1918 return fs->op.fsync(path, datasync, fi);
1924int fuse_fs_fsyncdir(
struct fuse_fs *fs,
const char *path,
int datasync,
1928 if (fs->op.fsyncdir) {
1930 fuse_log(FUSE_LOG_DEBUG,
"fsyncdir[%llu] datasync: %i\n",
1931 (
unsigned long long) fi->
fh, datasync);
1933 return fs->op.fsyncdir(path, datasync, fi);
1939int fuse_fs_flush(
struct fuse_fs *fs,
const char *path,
1945 fuse_log(FUSE_LOG_DEBUG,
"flush[%llu]\n",
1946 (
unsigned long long) fi->
fh);
1948 return fs->op.flush(path, fi);
1954int fuse_fs_statfs(
struct fuse_fs *fs,
const char *path,
struct statvfs *
buf)
1957 if (fs->op.statfs) {
1959 fuse_log(FUSE_LOG_DEBUG,
"statfs %s\n", path);
1961 return fs->op.statfs(path,
buf);
1963 buf->f_namemax = 255;
1969int fuse_fs_releasedir(
struct fuse_fs *fs,
const char *path,
1973 if (fs->op.releasedir) {
1975 fuse_log(FUSE_LOG_DEBUG,
"releasedir[%llu] flags: 0x%x\n",
1976 (
unsigned long long) fi->
fh, fi->
flags);
1978 return fs->op.releasedir(path, fi);
1984int fuse_fs_readdir(
struct fuse_fs *fs,
const char *path,
void *
buf,
1990 if (fs->op.readdir) {
1992 fuse_log(FUSE_LOG_DEBUG,
"readdir%s[%llu] from %llu\n",
1994 (
unsigned long long) fi->
fh,
1995 (
unsigned long long)
off);
1998 return fs->op.readdir(path,
buf, filler,
off, fi, flags);
2004int fuse_fs_create(
struct fuse_fs *fs,
const char *path, mode_t mode,
2008 if (fs->op.create) {
2013 "create flags: 0x%x %s 0%o umask=0%03o\n",
2014 fi->
flags, path, mode,
2017 err = fs->op.create(path, mode, fi);
2019 if (fs->debug && !err)
2020 fuse_log(FUSE_LOG_DEBUG,
" create[%llu] flags: 0x%x %s\n",
2021 (
unsigned long long) fi->
fh, fi->
flags, path);
2029int fuse_fs_lock(
struct fuse_fs *fs,
const char *path,
2035 fuse_log(FUSE_LOG_DEBUG,
"lock[%llu] %s %s start: %llu len: %llu pid: %llu\n",
2036 (
unsigned long long) fi->
fh,
2037 (cmd == F_GETLK ?
"F_GETLK" :
2038 (cmd == F_SETLK ?
"F_SETLK" :
2039 (cmd == F_SETLKW ?
"F_SETLKW" :
"???"))),
2040 (lock->l_type == F_RDLCK ?
"F_RDLCK" :
2041 (lock->l_type == F_WRLCK ?
"F_WRLCK" :
2042 (lock->l_type == F_UNLCK ?
"F_UNLCK" :
2044 (
unsigned long long) lock->l_start,
2045 (
unsigned long long) lock->l_len,
2046 (
unsigned long long) lock->l_pid);
2048 return fs->op.lock(path, fi, cmd, lock);
2054int fuse_fs_flock(
struct fuse_fs *fs,
const char *path,
2060 int xop = op & ~LOCK_NB;
2062 fuse_log(FUSE_LOG_DEBUG,
"lock[%llu] %s%s\n",
2063 (
unsigned long long) fi->
fh,
2064 xop == LOCK_SH ?
"LOCK_SH" :
2065 (xop == LOCK_EX ?
"LOCK_EX" :
2066 (xop == LOCK_UN ?
"LOCK_UN" :
"???")),
2067 (op & LOCK_NB) ?
"|LOCK_NB" :
"");
2069 return fs->op.flock(path, fi, op);
2075int fuse_fs_chown(
struct fuse_fs *fs,
const char *path, uid_t uid,
2082 fuse_log(FUSE_LOG_DEBUG,
"chown[%s] %s %lu %lu\n",
2083 file_info_string(fi,
buf,
sizeof(
buf)),
2084 path, (
unsigned long) uid, (
unsigned long) gid);
2086 return fs->op.chown(path, uid, gid, fi);
2092int fuse_fs_truncate(
struct fuse_fs *fs,
const char *path, off_t size,
2096 if (fs->op.truncate) {
2099 fuse_log(FUSE_LOG_DEBUG,
"truncate[%s] %llu\n",
2100 file_info_string(fi,
buf,
sizeof(
buf)),
2101 (
unsigned long long) size);
2103 return fs->op.truncate(path, size, fi);
2109int fuse_fs_utimens(
struct fuse_fs *fs,
const char *path,
2113 if (fs->op.utimens) {
2116 fuse_log(FUSE_LOG_DEBUG,
"utimens[%s] %s %li.%09lu %li.%09lu\n",
2117 file_info_string(fi,
buf,
sizeof(
buf)),
2118 path, tv[0].tv_sec, tv[0].tv_nsec,
2119 tv[1].tv_sec, tv[1].tv_nsec);
2121 return fs->op.utimens(path, tv, fi);
2127int fuse_fs_access(
struct fuse_fs *fs,
const char *path,
int mask)
2130 if (fs->op.access) {
2132 fuse_log(FUSE_LOG_DEBUG,
"access %s 0%o\n", path, mask);
2134 return fs->op.access(path, mask);
2140int fuse_fs_readlink(
struct fuse_fs *fs,
const char *path,
char *
buf,
2144 if (fs->op.readlink) {
2146 fuse_log(FUSE_LOG_DEBUG,
"readlink %s %lu\n", path,
2147 (
unsigned long) len);
2149 return fs->op.readlink(path,
buf, len);
2155int fuse_fs_mknod(
struct fuse_fs *fs,
const char *path, mode_t mode,
2161 fuse_log(FUSE_LOG_DEBUG,
"mknod %s 0%o 0x%llx umask=0%03o\n",
2162 path, mode, (
unsigned long long) rdev,
2165 return fs->op.mknod(path, mode, rdev);
2171int fuse_fs_mkdir(
struct fuse_fs *fs,
const char *path, mode_t mode)
2176 fuse_log(FUSE_LOG_DEBUG,
"mkdir %s 0%o umask=0%03o\n",
2179 return fs->op.mkdir(path, mode);
2185int fuse_fs_setxattr(
struct fuse_fs *fs,
const char *path,
const char *name,
2186 const char *value,
size_t size,
int flags)
2189 if (fs->op.setxattr) {
2191 fuse_log(FUSE_LOG_DEBUG,
"setxattr %s %s %lu 0x%x\n",
2192 path, name, (
unsigned long) size, flags);
2194 return fs->op.setxattr(path, name, value, size, flags);
2200int fuse_fs_getxattr(
struct fuse_fs *fs,
const char *path,
const char *name,
2201 char *value,
size_t size)
2204 if (fs->op.getxattr) {
2206 fuse_log(FUSE_LOG_DEBUG,
"getxattr %s %s %lu\n",
2207 path, name, (
unsigned long) size);
2209 return fs->op.getxattr(path, name, value, size);
2215int fuse_fs_listxattr(
struct fuse_fs *fs,
const char *path,
char *list,
2219 if (fs->op.listxattr) {
2221 fuse_log(FUSE_LOG_DEBUG,
"listxattr %s %lu\n",
2222 path, (
unsigned long) size);
2224 return fs->op.listxattr(path, list, size);
2230int fuse_fs_bmap(
struct fuse_fs *fs,
const char *path,
size_t blocksize,
2236 fuse_log(FUSE_LOG_DEBUG,
"bmap %s blocksize: %lu index: %llu\n",
2237 path, (
unsigned long) blocksize,
2238 (
unsigned long long) *
idx);
2240 return fs->op.bmap(path, blocksize,
idx);
2246int fuse_fs_removexattr(
struct fuse_fs *fs,
const char *path,
const char *name)
2249 if (fs->op.removexattr) {
2251 fuse_log(FUSE_LOG_DEBUG,
"removexattr %s %s\n", path, name);
2253 return fs->op.removexattr(path, name);
2259int fuse_fs_ioctl(
struct fuse_fs *fs,
const char *path,
unsigned int cmd,
2266 fuse_log(FUSE_LOG_DEBUG,
"ioctl[%llu] 0x%x flags: 0x%x\n",
2267 (
unsigned long long) fi->
fh, cmd, flags);
2269 return fs->op.ioctl(path, cmd, arg, fi, flags, data);
2274int fuse_fs_poll(
struct fuse_fs *fs,
const char *path,
2283 fuse_log(FUSE_LOG_DEBUG,
"poll[%llu] ph: %p, events 0x%x\n",
2284 (
unsigned long long) fi->
fh, ph,
2287 res = fs->op.poll(path, fi, ph, reventsp);
2289 if (fs->debug && !res)
2290 fuse_log(FUSE_LOG_DEBUG,
" poll[%llu] revents: 0x%x\n",
2291 (
unsigned long long) fi->
fh, *reventsp);
2298int fuse_fs_fallocate(
struct fuse_fs *fs,
const char *path,
int mode,
2302 if (fs->op.fallocate) {
2304 fuse_log(FUSE_LOG_DEBUG,
"fallocate %s mode %x, offset: %llu, length: %llu\n",
2307 (
unsigned long long) offset,
2308 (
unsigned long long) length);
2310 return fs->op.fallocate(path, mode, offset, length, fi);
2315ssize_t fuse_fs_copy_file_range(
struct fuse_fs *fs,
const char *path_in,
2317 const char *path_out,
2319 size_t len,
int flags)
2322 if (fs->op.copy_file_range) {
2324 fuse_log(FUSE_LOG_DEBUG,
"copy_file_range from %s:%llu to "
2325 "%s:%llu, length: %llu\n",
2327 (
unsigned long long) off_in,
2329 (
unsigned long long) off_out,
2330 (
unsigned long long) len);
2332 return fs->op.copy_file_range(path_in, fi_in, off_in, path_out,
2333 fi_out, off_out, len, flags);
2338off_t fuse_fs_lseek(
struct fuse_fs *fs,
const char *path, off_t
off,
int whence,
2345 fuse_log(FUSE_LOG_DEBUG,
"lseek[%s] %llu %d\n",
2346 file_info_string(fi,
buf,
sizeof(
buf)),
2347 (
unsigned long long)
off, whence);
2349 return fs->op.lseek(path,
off, whence, fi);
2355static int is_open(
struct fuse *f,
fuse_ino_t dir,
const char *name)
2359 pthread_mutex_lock(&f->lock);
2360 node = lookup_node(f, dir, name);
2361 if (node && node->open_count > 0)
2363 pthread_mutex_unlock(&f->lock);
2367static char *hidden_name(
struct fuse *f,
fuse_ino_t dir,
const char *oldname,
2368 char *newname,
size_t bufsize)
2372 struct node *newnode;
2378 pthread_mutex_lock(&f->lock);
2379 node = lookup_node(f, dir, oldname);
2381 pthread_mutex_unlock(&f->lock);
2386 snprintf(newname, bufsize,
".fuse_hidden%08x%08x",
2387 (
unsigned int) node->nodeid, f->hidectr);
2388 newnode = lookup_node(f, dir, newname);
2391 res = try_get_path(f, dir, newname, &newpath, NULL,
false);
2392 pthread_mutex_unlock(&f->lock);
2396 memset(&buf, 0,
sizeof(buf));
2397 res = fuse_fs_getattr(f->fs, newpath, &buf, NULL);
2402 }
while(res == 0 && --failctr);
2407static int hide_node(
struct fuse *f,
const char *oldpath,
2414 newpath = hidden_name(f, dir, oldname, newname,
sizeof(newname));
2416 err = fuse_fs_rename(f->fs, oldpath, newpath, 0);
2418 err = rename_node(f, dir, oldname, dir, newname, 1);
2424static int mtime_eq(
const struct stat *stbuf,
const struct timespec *ts)
2426 return stbuf->st_mtime == ts->tv_sec &&
2427 ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
2430#ifndef CLOCK_MONOTONIC
2431#define CLOCK_MONOTONIC CLOCK_REALTIME
2434static void curr_time(
struct timespec *now)
2436 static clockid_t clockid = CLOCK_MONOTONIC;
2437 int res = clock_gettime(clockid, now);
2438 if (res == -1 && errno == EINVAL) {
2439 clockid = CLOCK_REALTIME;
2440 res = clock_gettime(clockid, now);
2443 perror(
"fuse: clock_gettime");
2448static void update_stat(
struct node *node,
const struct stat *stbuf)
2450 if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
2451 stbuf->st_size != node->size))
2452 node->cache_valid = 0;
2453 node->mtime.tv_sec = stbuf->st_mtime;
2454 node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
2455 node->size = stbuf->st_size;
2456 curr_time(&node->stat_updated);
2459static int do_lookup(
struct fuse *f,
fuse_ino_t nodeid,
const char *name,
2464 node = find_node(f, nodeid, name);
2468 e->
ino = node->nodeid;
2472 if (f->conf.auto_cache) {
2473 pthread_mutex_lock(&f->lock);
2474 update_stat(node, &e->
attr);
2475 pthread_mutex_unlock(&f->lock);
2477 set_stat(f, e->
ino, &e->
attr);
2481static int lookup_path(
struct fuse *f,
fuse_ino_t nodeid,
2482 const char *name,
const char *path,
2488 res = fuse_fs_getattr(f->fs, path, &e->
attr, fi);
2490 res = do_lookup(f, nodeid, name, e);
2491 if (res == 0 && f->conf.debug) {
2492 fuse_log(FUSE_LOG_DEBUG,
" NODEID: %llu\n",
2493 (
unsigned long long) e->
ino);
2499static struct fuse_context_i *fuse_get_context_internal(
void)
2501 return (
struct fuse_context_i *) pthread_getspecific(fuse_context_key);
2504static struct fuse_context_i *fuse_create_context(
struct fuse *f)
2506 struct fuse_context_i *c = fuse_get_context_internal();
2508 c = (
struct fuse_context_i *)
2509 calloc(1,
sizeof(
struct fuse_context_i));
2515 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate thread specific data\n");
2518 pthread_setspecific(fuse_context_key, c);
2520 memset(c, 0,
sizeof(*c));
2527static void fuse_freecontext(
void *data)
2532static int fuse_create_context_key(
void)
2535 pthread_mutex_lock(&fuse_context_lock);
2536 if (!fuse_context_ref) {
2537 err = pthread_key_create(&fuse_context_key, fuse_freecontext);
2539 fuse_log(FUSE_LOG_ERR,
"fuse: failed to create thread specific key: %s\n",
2541 pthread_mutex_unlock(&fuse_context_lock);
2546 pthread_mutex_unlock(&fuse_context_lock);
2550static void fuse_delete_context_key(
void)
2552 pthread_mutex_lock(&fuse_context_lock);
2554 if (!fuse_context_ref) {
2555 free(pthread_getspecific(fuse_context_key));
2556 pthread_key_delete(fuse_context_key);
2558 pthread_mutex_unlock(&fuse_context_lock);
2561static struct fuse *req_fuse_prepare(
fuse_req_t req)
2563 struct fuse_context_i *c = fuse_create_context(req_fuse(req));
2566 c->ctx.uid = ctx->
uid;
2567 c->ctx.gid = ctx->
gid;
2568 c->ctx.pid = ctx->
pid;
2569 c->ctx.umask = ctx->
umask;
2573static inline void reply_err(
fuse_req_t req,
int err)
2583 struct fuse *f = req_fuse(req);
2587 forget_node(f, e->
ino, 1);
2590 reply_err(req, err);
2593void fuse_fs_init(
struct fuse_fs *fs,
struct fuse_conn_info *conn,
2597 if (!fs->op.write_buf)
2598 conn->
want &= ~FUSE_CAP_SPLICE_READ;
2600 conn->
want &= ~FUSE_CAP_POSIX_LOCKS;
2602 conn->
want &= ~FUSE_CAP_FLOCK_LOCKS;
2604 fs->user_data = fs->op.init(conn, cfg);
2607static void fuse_lib_init(
void *data,
struct fuse_conn_info *conn)
2609 struct fuse *f = (
struct fuse *) data;
2611 fuse_create_context(f);
2614 fuse_fs_init(f->fs, conn, &f->conf);
2617void fuse_fs_destroy(
struct fuse_fs *fs)
2621 fs->op.destroy(fs->user_data);
2624static void fuse_lib_destroy(
void *data)
2626 struct fuse *f = (
struct fuse *) data;
2628 fuse_create_context(f);
2629 fuse_fs_destroy(f->fs);
2635 struct fuse *f = req_fuse_prepare(req);
2639 struct node *dot = NULL;
2641 if (name[0] ==
'.') {
2642 int len = strlen(name);
2644 if (len == 1 || (name[1] ==
'.' && len == 2)) {
2645 pthread_mutex_lock(&f->lock);
2648 fuse_log(FUSE_LOG_DEBUG,
"LOOKUP-DOT\n");
2649 dot = get_node_nocheck(f, parent);
2651 pthread_mutex_unlock(&f->lock);
2652 reply_entry(req, &e, -ESTALE);
2658 fuse_log(FUSE_LOG_DEBUG,
"LOOKUP-DOTDOT\n");
2659 parent = get_node(f, parent)->parent->nodeid;
2661 pthread_mutex_unlock(&f->lock);
2666 err = get_path_name(f, parent, name, &path);
2668 struct fuse_intr_data d;
2670 fuse_log(FUSE_LOG_DEBUG,
"LOOKUP %s\n", path);
2671 fuse_prepare_interrupt(f, req, &d);
2672 err = lookup_path(f, parent, name, path, &e, NULL);
2673 if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
2678 fuse_finish_interrupt(f, req, &d);
2679 free_path(f, parent, path);
2682 pthread_mutex_lock(&f->lock);
2684 pthread_mutex_unlock(&f->lock);
2686 reply_entry(req, &e, err);
2689static void do_forget(
struct fuse *f,
fuse_ino_t ino, uint64_t nlookup)
2692 fuse_log(FUSE_LOG_DEBUG,
"FORGET %llu/%llu\n", (
unsigned long long)ino,
2693 (
unsigned long long) nlookup);
2694 forget_node(f, ino, nlookup);
2699 do_forget(req_fuse(req), ino, nlookup);
2703static void fuse_lib_forget_multi(
fuse_req_t req,
size_t count,
2704 struct fuse_forget_data *forgets)
2706 struct fuse *f = req_fuse(req);
2709 for (i = 0; i < count; i++)
2710 do_forget(f, forgets[i].ino, forgets[i].nlookup);
2719 struct fuse *f = req_fuse_prepare(req);
2724 memset(&buf, 0,
sizeof(buf));
2727 err = get_path_nullok(f, ino, &path);
2729 err = get_path(f, ino, &path);
2731 struct fuse_intr_data d;
2732 fuse_prepare_interrupt(f, req, &d);
2733 err = fuse_fs_getattr(f->fs, path, &buf, fi);
2734 fuse_finish_interrupt(f, req, &d);
2735 free_path(f, ino, path);
2740 pthread_mutex_lock(&f->lock);
2741 node = get_node(f, ino);
2742 if (node->is_hidden && buf.st_nlink > 0)
2744 if (f->conf.auto_cache)
2745 update_stat(node, &buf);
2746 pthread_mutex_unlock(&f->lock);
2747 set_stat(f, ino, &buf);
2750 reply_err(req, err);
2753int fuse_fs_chmod(
struct fuse_fs *fs,
const char *path, mode_t mode,
2760 fuse_log(FUSE_LOG_DEBUG,
"chmod[%s] %s %llo\n",
2761 file_info_string(fi, buf,
sizeof(buf)),
2762 path, (
unsigned long long) mode);
2764 return fs->op.chmod(path, mode, fi);
2773 struct fuse *f = req_fuse_prepare(req);
2778 memset(&buf, 0,
sizeof(buf));
2780 err = get_path_nullok(f, ino, &path);
2782 err = get_path(f, ino, &path);
2784 struct fuse_intr_data d;
2785 fuse_prepare_interrupt(f, req, &d);
2787 if (!err && (valid & FUSE_SET_ATTR_MODE))
2788 err = fuse_fs_chmod(f->fs, path, attr->st_mode, fi);
2789 if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
2790 uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
2791 attr->st_uid : (uid_t) -1;
2792 gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
2793 attr->st_gid : (gid_t) -1;
2794 err = fuse_fs_chown(f->fs, path, uid, gid, fi);
2796 if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
2797 err = fuse_fs_truncate(f->fs, path,
2800#ifdef HAVE_UTIMENSAT
2802 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
2803 struct timespec tv[2];
2807 tv[0].tv_nsec = UTIME_OMIT;
2808 tv[1].tv_nsec = UTIME_OMIT;
2810 if (valid & FUSE_SET_ATTR_ATIME_NOW)
2811 tv[0].tv_nsec = UTIME_NOW;
2812 else if (valid & FUSE_SET_ATTR_ATIME)
2813 tv[0] = attr->st_atim;
2815 if (valid & FUSE_SET_ATTR_MTIME_NOW)
2816 tv[1].tv_nsec = UTIME_NOW;
2817 else if (valid & FUSE_SET_ATTR_MTIME)
2818 tv[1] = attr->st_mtim;
2820 err = fuse_fs_utimens(f->fs, path, tv, fi);
2824 (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
2825 (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
2826 struct timespec tv[2];
2827 tv[0].tv_sec = attr->st_atime;
2828 tv[0].tv_nsec = ST_ATIM_NSEC(attr);
2829 tv[1].tv_sec = attr->st_mtime;
2830 tv[1].tv_nsec = ST_MTIM_NSEC(attr);
2831 err = fuse_fs_utimens(f->fs, path, tv, fi);
2834 err = fuse_fs_getattr(f->fs, path, &buf, fi);
2836 fuse_finish_interrupt(f, req, &d);
2837 free_path(f, ino, path);
2840 if (f->conf.auto_cache) {
2841 pthread_mutex_lock(&f->lock);
2842 update_stat(get_node(f, ino), &buf);
2843 pthread_mutex_unlock(&f->lock);
2845 set_stat(f, ino, &buf);
2848 reply_err(req, err);
2853 struct fuse *f = req_fuse_prepare(req);
2857 err = get_path(f, ino, &path);
2859 struct fuse_intr_data d;
2861 fuse_prepare_interrupt(f, req, &d);
2862 err = fuse_fs_access(f->fs, path, mask);
2863 fuse_finish_interrupt(f, req, &d);
2864 free_path(f, ino, path);
2866 reply_err(req, err);
2871 struct fuse *f = req_fuse_prepare(req);
2872 char linkname[PATH_MAX + 1];
2876 err = get_path(f, ino, &path);
2878 struct fuse_intr_data d;
2879 fuse_prepare_interrupt(f, req, &d);
2880 err = fuse_fs_readlink(f->fs, path, linkname,
sizeof(linkname));
2881 fuse_finish_interrupt(f, req, &d);
2882 free_path(f, ino, path);
2885 linkname[PATH_MAX] =
'\0';
2888 reply_err(req, err);
2892 mode_t mode, dev_t rdev)
2894 struct fuse *f = req_fuse_prepare(req);
2899 err = get_path_name(f, parent, name, &path);
2901 struct fuse_intr_data d;
2903 fuse_prepare_interrupt(f, req, &d);
2905 if (S_ISREG(mode)) {
2908 memset(&fi, 0,
sizeof(fi));
2909 fi.
flags = O_CREAT | O_EXCL | O_WRONLY;
2910 err = fuse_fs_create(f->fs, path, mode, &fi);
2912 err = lookup_path(f, parent, name, path, &e,
2914 fuse_fs_release(f->fs, path, &fi);
2917 if (err == -ENOSYS) {
2918 err = fuse_fs_mknod(f->fs, path, mode, rdev);
2920 err = lookup_path(f, parent, name, path, &e,
2923 fuse_finish_interrupt(f, req, &d);
2924 free_path(f, parent, path);
2926 reply_entry(req, &e, err);
2932 struct fuse *f = req_fuse_prepare(req);
2937 err = get_path_name(f, parent, name, &path);
2939 struct fuse_intr_data d;
2941 fuse_prepare_interrupt(f, req, &d);
2942 err = fuse_fs_mkdir(f->fs, path, mode);
2944 err = lookup_path(f, parent, name, path, &e, NULL);
2945 fuse_finish_interrupt(f, req, &d);
2946 free_path(f, parent, path);
2948 reply_entry(req, &e, err);
2954 struct fuse *f = req_fuse_prepare(req);
2959 err = get_path_wrlock(f, parent, name, &path, &wnode);
2961 struct fuse_intr_data d;
2963 fuse_prepare_interrupt(f, req, &d);
2964 if (!f->conf.hard_remove && is_open(f, parent, name)) {
2965 err = hide_node(f, path, parent, name);
2968 if (!is_open(f, parent, wnode->name)) {
2972 if (try_get_path(f, wnode->nodeid, NULL, &unlinkpath, NULL,
false) == 0) {
2973 err = fuse_fs_unlink(f->fs, unlinkpath);
2975 remove_node(f, parent, wnode->name);
2981 err = fuse_fs_unlink(f->fs, path);
2983 remove_node(f, parent, name);
2985 fuse_finish_interrupt(f, req, &d);
2986 free_path_wrlock(f, parent, wnode, path);
2988 reply_err(req, err);
2993 struct fuse *f = req_fuse_prepare(req);
2998 err = get_path_wrlock(f, parent, name, &path, &wnode);
3000 struct fuse_intr_data d;
3002 fuse_prepare_interrupt(f, req, &d);
3003 err = fuse_fs_rmdir(f->fs, path);
3004 fuse_finish_interrupt(f, req, &d);
3006 remove_node(f, parent, name);
3007 free_path_wrlock(f, parent, wnode, path);
3009 reply_err(req, err);
3012static void fuse_lib_symlink(
fuse_req_t req,
const char *linkname,
3015 struct fuse *f = req_fuse_prepare(req);
3020 err = get_path_name(f, parent, name, &path);
3022 struct fuse_intr_data d;
3024 fuse_prepare_interrupt(f, req, &d);
3025 err = fuse_fs_symlink(f->fs, linkname, path);
3027 err = lookup_path(f, parent, name, path, &e, NULL);
3028 fuse_finish_interrupt(f, req, &d);
3029 free_path(f, parent, path);
3031 reply_entry(req, &e, err);
3036 const char *newname,
unsigned int flags)
3038 struct fuse *f = req_fuse_prepare(req);
3041 struct node *wnode1;
3042 struct node *wnode2;
3045 err = get_path2(f, olddir, oldname, newdir, newname,
3046 &oldpath, &newpath, &wnode1, &wnode2);
3048 struct fuse_intr_data d;
3050 fuse_prepare_interrupt(f, req, &d);
3051 if (!f->conf.hard_remove && !(flags & RENAME_EXCHANGE) &&
3052 is_open(f, newdir, newname))
3053 err = hide_node(f, newpath, newdir, newname);
3055 err = fuse_fs_rename(f->fs, oldpath, newpath, flags);
3057 if (flags & RENAME_EXCHANGE) {
3058 err = exchange_node(f, olddir, oldname,
3061 err = rename_node(f, olddir, oldname,
3062 newdir, newname, 0);
3066 fuse_finish_interrupt(f, req, &d);
3067 free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath);
3069 reply_err(req, err);
3073 const char *newname)
3075 struct fuse *f = req_fuse_prepare(req);
3081 err = get_path2(f,
ino, NULL, newparent, newname,
3082 &oldpath, &newpath, NULL, NULL);
3084 struct fuse_intr_data d;
3086 fuse_prepare_interrupt(f, req, &d);
3087 err = fuse_fs_link(f->fs, oldpath, newpath);
3089 err = lookup_path(f, newparent, newname, newpath,
3091 fuse_finish_interrupt(f, req, &d);
3092 free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath);
3094 reply_entry(req, &e, err);
3097static void fuse_do_release(
struct fuse *f,
fuse_ino_t ino,
const char *path,
3101 int unlink_hidden = 0;
3103 fuse_fs_release(f->fs, path, fi);
3105 pthread_mutex_lock(&f->lock);
3106 node = get_node(f, ino);
3107 assert(node->open_count > 0);
3109 if (node->is_hidden && !node->open_count) {
3111 node->is_hidden = 0;
3113 pthread_mutex_unlock(&f->lock);
3117 fuse_fs_unlink(f->fs, path);
3118 }
else if (f->conf.nullpath_ok) {
3121 if (get_path(f, ino, &unlinkpath) == 0)
3122 fuse_fs_unlink(f->fs, unlinkpath);
3124 free_path(f, ino, unlinkpath);
3130 const char *name, mode_t mode,
3133 struct fuse *f = req_fuse_prepare(req);
3134 struct fuse_intr_data d;
3139 err = get_path_name(f, parent, name, &path);
3141 fuse_prepare_interrupt(f, req, &d);
3142 err = fuse_fs_create(f->fs, path, mode, fi);
3144 err = lookup_path(f, parent, name, path, &e, fi);
3146 fuse_fs_release(f->fs, path, fi);
3147 else if (!S_ISREG(e.
attr.st_mode)) {
3149 fuse_fs_release(f->fs, path, fi);
3150 forget_node(f, e.
ino, 1);
3152 if (f->conf.direct_io)
3154 if (f->conf.kernel_cache)
3157 f->conf.parallel_direct_writes)
3161 fuse_finish_interrupt(f, req, &d);
3164 pthread_mutex_lock(&f->lock);
3165 get_node(f, e.
ino)->open_count++;
3166 pthread_mutex_unlock(&f->lock);
3170 fuse_do_release(f, e.
ino, path, fi);
3171 forget_node(f, e.
ino, 1);
3174 reply_err(req, err);
3177 free_path(f, parent, path);
3180static double diff_timespec(
const struct timespec *t1,
3181 const struct timespec *t2)
3183 return (t1->tv_sec - t2->tv_sec) +
3184 ((double) t1->tv_nsec - (
double) t2->tv_nsec) / 1000000000.0;
3187static void open_auto_cache(
struct fuse *f,
fuse_ino_t ino,
const char *path,
3192 pthread_mutex_lock(&f->lock);
3193 node = get_node(f, ino);
3194 if (node->cache_valid) {
3195 struct timespec now;
3198 if (diff_timespec(&now, &node->stat_updated) >
3199 f->conf.ac_attr_timeout) {
3202 pthread_mutex_unlock(&f->lock);
3203 err = fuse_fs_getattr(f->fs, path, &stbuf, fi);
3204 pthread_mutex_lock(&f->lock);
3206 update_stat(node, &stbuf);
3208 node->cache_valid = 0;
3211 if (node->cache_valid)
3214 node->cache_valid = 1;
3215 pthread_mutex_unlock(&f->lock);
3221 struct fuse *f = req_fuse_prepare(req);
3222 struct fuse_intr_data d;
3226 err = get_path(f, ino, &path);
3228 fuse_prepare_interrupt(f, req, &d);
3229 err = fuse_fs_open(f->fs, path, fi);
3231 if (f->conf.direct_io)
3233 if (f->conf.kernel_cache)
3236 if (f->conf.auto_cache)
3237 open_auto_cache(f, ino, path, fi);
3239 if (f->conf.no_rofd_flush &&
3240 (fi->
flags & O_ACCMODE) == O_RDONLY)
3243 if (fi->
direct_io && f->conf.parallel_direct_writes)
3247 fuse_finish_interrupt(f, req, &d);
3250 pthread_mutex_lock(&f->lock);
3251 get_node(f, ino)->open_count++;
3252 pthread_mutex_unlock(&f->lock);
3256 fuse_do_release(f, ino, path, fi);
3259 reply_err(req, err);
3261 free_path(f, ino, path);
3267 struct fuse *f = req_fuse_prepare(req);
3272 res = get_path_nullok(f, ino, &path);
3274 struct fuse_intr_data d;
3276 fuse_prepare_interrupt(f, req, &d);
3277 res = fuse_fs_read_buf(f->fs, path, &buf, size, off, fi);
3278 fuse_finish_interrupt(f, req, &d);
3279 free_path(f, ino, path);
3285 reply_err(req, res);
3294 struct fuse *f = req_fuse_prepare(req);
3298 res = get_path_nullok(f, ino, &path);
3300 struct fuse_intr_data d;
3302 fuse_prepare_interrupt(f, req, &d);
3303 res = fuse_fs_write_buf(f->fs, path, buf, off, fi);
3304 fuse_finish_interrupt(f, req, &d);
3305 free_path(f, ino, path);
3311 reply_err(req, res);
3317 struct fuse *f = req_fuse_prepare(req);
3321 err = get_path_nullok(f, ino, &path);
3323 struct fuse_intr_data d;
3325 fuse_prepare_interrupt(f, req, &d);
3326 err = fuse_fs_fsync(f->fs, path, datasync, fi);
3327 fuse_finish_interrupt(f, req, &d);
3328 free_path(f, ino, path);
3330 reply_err(req, err);
3333static struct fuse_dh *get_dirhandle(
const struct fuse_file_info *llfi,
3336 struct fuse_dh *dh = (
struct fuse_dh *) (uintptr_t) llfi->
fh;
3345 struct fuse *f = req_fuse_prepare(req);
3346 struct fuse_intr_data d;
3352 dh = (
struct fuse_dh *) malloc(
sizeof(
struct fuse_dh));
3354 reply_err(req, -ENOMEM);
3357 memset(dh, 0,
sizeof(
struct fuse_dh));
3359 dh->contents = NULL;
3364 pthread_mutex_init(&dh->lock, NULL);
3366 llfi->
fh = (uintptr_t) dh;
3368 memset(&fi, 0,
sizeof(fi));
3371 err = get_path(f, ino, &path);
3373 fuse_prepare_interrupt(f, req, &d);
3374 err = fuse_fs_opendir(f->fs, path, &fi);
3375 fuse_finish_interrupt(f, req, &d);
3384 fuse_fs_releasedir(f->fs, path, &fi);
3385 pthread_mutex_destroy(&dh->lock);
3389 reply_err(req, err);
3390 pthread_mutex_destroy(&dh->lock);
3393 free_path(f, ino, path);
3396static int extend_contents(
struct fuse_dh *dh,
unsigned minsize)
3398 if (minsize > dh->size) {
3400 unsigned newsize = dh->size;
3403 while (newsize < minsize) {
3404 if (newsize >= 0x80000000)
3405 newsize = 0xffffffff;
3410 newptr = (
char *) realloc(dh->contents, newsize);
3412 dh->error = -ENOMEM;
3415 dh->contents = newptr;
3421static int fuse_add_direntry_to_dh(
struct fuse_dh *dh,
const char *name,
3424 struct fuse_direntry *de;
3426 de = malloc(
sizeof(
struct fuse_direntry));
3428 dh->error = -ENOMEM;
3431 de->name = strdup(name);
3433 dh->error = -ENOMEM;
3441 dh->last = &de->next;
3452 pthread_mutex_lock(&f->lock);
3453 node = lookup_node(f, parent, name);
3456 pthread_mutex_unlock(&f->lock);
3461static int fill_dir(
void *dh_,
const char *name,
const struct stat *statp,
3464 struct fuse_dh *dh = (
struct fuse_dh *) dh_;
3475 memset(&stbuf, 0,
sizeof(stbuf));
3476 stbuf.st_ino = FUSE_UNKNOWN_INO;
3479 if (!dh->fuse->conf.use_ino) {
3480 stbuf.st_ino = FUSE_UNKNOWN_INO;
3481 if (dh->fuse->conf.readdir_ino) {
3482 stbuf.st_ino = (ino_t)
3483 lookup_nodeid(dh->fuse, dh->nodeid, name);
3500 if (extend_contents(dh, dh->needlen) == -1)
3505 dh->needlen - dh->len, name,
3507 if (newlen > dh->needlen)
3514 if (fuse_add_direntry_to_dh(dh, name, &stbuf) == -1)
3520static int is_dot_or_dotdot(
const char *name)
3522 return name[0] ==
'.' && (name[1] ==
'\0' ||
3523 (name[1] ==
'.' && name[2] ==
'\0'));
3526static int fill_dir_plus(
void *dh_,
const char *name,
const struct stat *statp,
3529 struct fuse_dh *dh = (
struct fuse_dh *) dh_;
3534 struct fuse *f = dh->fuse;
3545 if (!is_dot_or_dotdot(name)) {
3546 res = do_lookup(f, dh->nodeid, name, &e);
3553 e.
attr.st_ino = FUSE_UNKNOWN_INO;
3555 e.
attr.st_mode = statp->st_mode;
3556 if (f->conf.use_ino)
3557 e.
attr.st_ino = statp->st_ino;
3559 if (!f->conf.use_ino && f->conf.readdir_ino) {
3560 e.
attr.st_ino = (ino_t)
3561 lookup_nodeid(f, dh->nodeid, name);
3577 if (extend_contents(dh, dh->needlen) == -1)
3582 dh->needlen - dh->len, name,
3584 if (newlen > dh->needlen)
3590 if (fuse_add_direntry_to_dh(dh, name, &e.
attr) == -1)
3597static void free_direntries(
struct fuse_direntry *de)
3600 struct fuse_direntry *next = de->next;
3608 size_t size, off_t off,
struct fuse_dh *dh,
3615 if (f->fs->op.readdir)
3616 err = get_path_nullok(f, ino, &path);
3618 err = get_path(f, ino, &path);
3620 struct fuse_intr_data d;
3624 filler = fill_dir_plus;
3626 free_direntries(dh->first);
3628 dh->last = &dh->first;
3634 fuse_prepare_interrupt(f, req, &d);
3635 err = fuse_fs_readdir(f->fs, path, dh, filler, off, fi, flags);
3636 fuse_finish_interrupt(f, req, &d);
3642 free_path(f, ino, path);
3647static int readdir_fill_from_list(
fuse_req_t req,
struct fuse_dh *dh,
3651 struct fuse_direntry *de = dh->first;
3655 if (extend_contents(dh, dh->needlen) == -1)
3658 for (pos = 0; pos < off; pos++) {
3665 char *p = dh->contents + dh->len;
3666 unsigned rem = dh->needlen - dh->len;
3680 de->name, &de->stat, pos);
3682 newlen = dh->len + thislen;
3683 if (newlen > dh->needlen)
3695 struct fuse *f = req_fuse_prepare(req);
3697 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3700 pthread_mutex_lock(&dh->lock);
3707 err = readdir_fill(f, req, ino, size, off, dh, &fi, flags);
3709 reply_err(req, err);
3715 err = readdir_fill_from_list(req, dh, off, flags);
3717 reply_err(req, err);
3723 pthread_mutex_unlock(&dh->lock);
3729 fuse_readdir_common(req, ino, size, off, llfi, 0);
3741 struct fuse *f = req_fuse_prepare(req);
3742 struct fuse_intr_data d;
3744 struct fuse_dh *dh = get_dirhandle(llfi, &fi);
3747 get_path_nullok(f, ino, &path);
3749 fuse_prepare_interrupt(f, req, &d);
3750 fuse_fs_releasedir(f->fs, path, &fi);
3751 fuse_finish_interrupt(f, req, &d);
3752 free_path(f, ino, path);
3754 pthread_mutex_lock(&dh->lock);
3755 pthread_mutex_unlock(&dh->lock);
3756 pthread_mutex_destroy(&dh->lock);
3757 free_direntries(dh->first);
3766 struct fuse *f = req_fuse_prepare(req);
3771 get_dirhandle(llfi, &fi);
3773 err = get_path_nullok(f, ino, &path);
3775 struct fuse_intr_data d;
3776 fuse_prepare_interrupt(f, req, &d);
3777 err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
3778 fuse_finish_interrupt(f, req, &d);
3779 free_path(f, ino, path);
3781 reply_err(req, err);
3786 struct fuse *f = req_fuse_prepare(req);
3791 memset(&buf, 0,
sizeof(buf));
3793 err = get_path(f, ino, &path);
3796 struct fuse_intr_data d;
3797 fuse_prepare_interrupt(f, req, &d);
3798 err = fuse_fs_statfs(f->fs, path ? path :
"/", &buf);
3799 fuse_finish_interrupt(f, req, &d);
3800 free_path(f, ino, path);
3806 reply_err(req, err);
3810 const char *value,
size_t size,
int flags)
3812 struct fuse *f = req_fuse_prepare(req);
3816 err = get_path(f, ino, &path);
3818 struct fuse_intr_data d;
3819 fuse_prepare_interrupt(f, req, &d);
3820 err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
3821 fuse_finish_interrupt(f, req, &d);
3822 free_path(f, ino, path);
3824 reply_err(req, err);
3828 const char *name,
char *value,
size_t size)
3833 err = get_path(f, ino, &path);
3835 struct fuse_intr_data d;
3836 fuse_prepare_interrupt(f, req, &d);
3837 err = fuse_fs_getxattr(f->fs, path, name, value, size);
3838 fuse_finish_interrupt(f, req, &d);
3839 free_path(f, ino, path);
3847 struct fuse *f = req_fuse_prepare(req);
3851 char *value = (
char *) malloc(size);
3852 if (value == NULL) {
3853 reply_err(req, -ENOMEM);
3856 res = common_getxattr(f, req, ino, name, value, size);
3860 reply_err(req, res);
3863 res = common_getxattr(f, req, ino, name, NULL, 0);
3867 reply_err(req, res);
3872 char *list,
size_t size)
3877 err = get_path(f, ino, &path);
3879 struct fuse_intr_data d;
3880 fuse_prepare_interrupt(f, req, &d);
3881 err = fuse_fs_listxattr(f->fs, path, list, size);
3882 fuse_finish_interrupt(f, req, &d);
3883 free_path(f, ino, path);
3890 struct fuse *f = req_fuse_prepare(req);
3894 char *list = (
char *) malloc(size);
3896 reply_err(req, -ENOMEM);
3899 res = common_listxattr(f, req, ino, list, size);
3903 reply_err(req, res);
3906 res = common_listxattr(f, req, ino, NULL, 0);
3910 reply_err(req, res);
3917 struct fuse *f = req_fuse_prepare(req);
3921 err = get_path(f, ino, &path);
3923 struct fuse_intr_data d;
3924 fuse_prepare_interrupt(f, req, &d);
3925 err = fuse_fs_removexattr(f->fs, path, name);
3926 fuse_finish_interrupt(f, req, &d);
3927 free_path(f, ino, path);
3929 reply_err(req, err);
3932static struct lock *locks_conflict(
struct node *node,
const struct lock *lock)
3936 for (l = node->locks; l; l = l->next)
3937 if (l->owner != lock->owner &&
3938 lock->start <= l->end && l->start <= lock->end &&
3939 (l->type == F_WRLCK || lock->type == F_WRLCK))
3945static void delete_lock(
struct lock **lockp)
3947 struct lock *l = *lockp;
3952static void insert_lock(
struct lock **pos,
struct lock *lock)
3958static int locks_insert(
struct node *node,
struct lock *lock)
3961 struct lock *newl1 = NULL;
3962 struct lock *newl2 = NULL;
3964 if (lock->type != F_UNLCK || lock->start != 0 ||
3965 lock->end != OFFSET_MAX) {
3966 newl1 = malloc(
sizeof(
struct lock));
3967 newl2 = malloc(
sizeof(
struct lock));
3969 if (!newl1 || !newl2) {
3976 for (lp = &node->locks; *lp;) {
3977 struct lock *l = *lp;
3978 if (l->owner != lock->owner)
3981 if (lock->type == l->type) {
3982 if (l->end < lock->start - 1)
3984 if (lock->end < l->start - 1)
3986 if (l->start <= lock->start && lock->end <= l->end)
3988 if (l->start < lock->start)
3989 lock->start = l->start;
3990 if (lock->end < l->end)
3994 if (l->end < lock->start)
3996 if (lock->end < l->start)
3998 if (lock->start <= l->start && l->end <= lock->end)
4000 if (l->end <= lock->end) {
4001 l->end = lock->start - 1;
4004 if (lock->start <= l->start) {
4005 l->start = lock->end + 1;
4009 newl2->start = lock->end + 1;
4010 l->end = lock->start - 1;
4011 insert_lock(&l->next, newl2);
4021 if (lock->type != F_UNLCK) {
4023 insert_lock(lp, newl1);
4032static void flock_to_lock(
struct flock *flock,
struct lock *lock)
4034 memset(lock, 0,
sizeof(
struct lock));
4035 lock->type = flock->l_type;
4036 lock->start = flock->l_start;
4038 flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
4039 lock->pid = flock->l_pid;
4042static void lock_to_flock(
struct lock *lock,
struct flock *flock)
4044 flock->l_type = lock->type;
4045 flock->l_start = lock->start;
4047 (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
4048 flock->l_pid = lock->pid;
4054 struct fuse_intr_data d;
4060 fuse_prepare_interrupt(f, req, &d);
4061 memset(&lock, 0,
sizeof(lock));
4062 lock.l_type = F_UNLCK;
4063 lock.l_whence = SEEK_SET;
4064 err = fuse_fs_flush(f->fs, path, fi);
4065 errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
4066 fuse_finish_interrupt(f, req, &d);
4068 if (errlock != -ENOSYS) {
4069 flock_to_lock(&lock, &l);
4071 pthread_mutex_lock(&f->lock);
4072 locks_insert(get_node(f, ino), &l);
4073 pthread_mutex_unlock(&f->lock);
4086 struct fuse *f = req_fuse_prepare(req);
4087 struct fuse_intr_data d;
4091 get_path_nullok(f, ino, &path);
4093 err = fuse_flush_common(f, req, ino, path, fi);
4098 fuse_prepare_interrupt(f, req, &d);
4099 fuse_do_release(f, ino, path, fi);
4100 fuse_finish_interrupt(f, req, &d);
4101 free_path(f, ino, path);
4103 reply_err(req, err);
4109 struct fuse *f = req_fuse_prepare(req);
4113 get_path_nullok(f, ino, &path);
4114 err = fuse_flush_common(f, req, ino, path, fi);
4115 free_path(f, ino, path);
4117 reply_err(req, err);
4124 struct fuse *f = req_fuse_prepare(req);
4128 err = get_path_nullok(f, ino, &path);
4130 struct fuse_intr_data d;
4131 fuse_prepare_interrupt(f, req, &d);
4132 err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
4133 fuse_finish_interrupt(f, req, &d);
4134 free_path(f, ino, path);
4144 struct lock *conflict;
4145 struct fuse *f = req_fuse(req);
4147 flock_to_lock(lock, &l);
4149 pthread_mutex_lock(&f->lock);
4150 conflict = locks_conflict(get_node(f, ino), &l);
4152 lock_to_flock(conflict, lock);
4153 pthread_mutex_unlock(&f->lock);
4155 err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
4162 reply_err(req, err);
4169 int err = fuse_lock_common(req, ino, fi, lock,
4170 sleep ? F_SETLKW : F_SETLK);
4172 struct fuse *f = req_fuse(req);
4174 flock_to_lock(lock, &l);
4176 pthread_mutex_lock(&f->lock);
4177 locks_insert(get_node(f, ino), &l);
4178 pthread_mutex_unlock(&f->lock);
4180 reply_err(req, err);
4186 struct fuse *f = req_fuse_prepare(req);
4190 err = get_path_nullok(f, ino, &path);
4192 struct fuse_intr_data d;
4193 fuse_prepare_interrupt(f, req, &d);
4194 err = fuse_fs_flock(f->fs, path, fi, op);
4195 fuse_finish_interrupt(f, req, &d);
4196 free_path(f, ino, path);
4198 reply_err(req, err);
4204 struct fuse *f = req_fuse_prepare(req);
4205 struct fuse_intr_data d;
4209 err = get_path(f, ino, &path);
4211 fuse_prepare_interrupt(f, req, &d);
4212 err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
4213 fuse_finish_interrupt(f, req, &d);
4214 free_path(f, ino, path);
4219 reply_err(req, err);
4224 unsigned int flags,
const void *in_buf,
4225 size_t in_bufsz,
size_t out_bufsz)
4227 struct fuse *f = req_fuse_prepare(req);
4228 struct fuse_intr_data d;
4230 char *path, *out_buf = NULL;
4234 if (
flags & FUSE_IOCTL_UNRESTRICTED)
4237 if (
flags & FUSE_IOCTL_DIR)
4238 get_dirhandle(llfi, &fi);
4244 out_buf = malloc(out_bufsz);
4249 assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
4250 if (out_buf && in_bufsz)
4251 memcpy(out_buf, in_buf, in_bufsz);
4253 err = get_path_nullok(f, ino, &path);
4257 fuse_prepare_interrupt(f, req, &d);
4259 err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi,
flags,
4260 out_buf ? out_buf : (
void *)in_buf);
4262 fuse_finish_interrupt(f, req, &d);
4263 free_path(f, ino, path);
4270 reply_err(req, err);
4278 struct fuse *f = req_fuse_prepare(req);
4279 struct fuse_intr_data d;
4282 unsigned revents = 0;
4284 err = get_path_nullok(f, ino, &path);
4286 fuse_prepare_interrupt(f, req, &d);
4287 err = fuse_fs_poll(f->fs, path, fi, ph, &revents);
4288 fuse_finish_interrupt(f, req, &d);
4289 free_path(f, ino, path);
4294 reply_err(req, err);
4300 struct fuse *f = req_fuse_prepare(req);
4301 struct fuse_intr_data d;
4305 err = get_path_nullok(f, ino, &path);
4307 fuse_prepare_interrupt(f, req, &d);
4308 err = fuse_fs_fallocate(f->fs, path, mode, offset, length, fi);
4309 fuse_finish_interrupt(f, req, &d);
4310 free_path(f, ino, path);
4312 reply_err(req, err);
4321 struct fuse *f = req_fuse_prepare(req);
4322 struct fuse_intr_data d;
4323 char *path_in, *path_out;
4327 err = get_path_nullok(f, nodeid_in, &path_in);
4329 reply_err(req, err);
4333 err = get_path_nullok(f, nodeid_out, &path_out);
4335 free_path(f, nodeid_in, path_in);
4336 reply_err(req, err);
4340 fuse_prepare_interrupt(f, req, &d);
4341 res = fuse_fs_copy_file_range(f->fs, path_in, fi_in, off_in, path_out,
4342 fi_out, off_out, len, flags);
4343 fuse_finish_interrupt(f, req, &d);
4348 reply_err(req, res);
4350 free_path(f, nodeid_in, path_in);
4351 free_path(f, nodeid_out, path_out);
4357 struct fuse *f = req_fuse_prepare(req);
4358 struct fuse_intr_data d;
4363 err = get_path(f, ino, &path);
4365 reply_err(req, err);
4369 fuse_prepare_interrupt(f, req, &d);
4370 res = fuse_fs_lseek(f->fs, path, off, whence, fi);
4371 fuse_finish_interrupt(f, req, &d);
4372 free_path(f, ino, path);
4376 reply_err(req, res);
4379static int clean_delay(
struct fuse *f)
4387 int max_sleep = 3600;
4388 int sleep_time = f->conf.remember / 10;
4390 if (sleep_time > max_sleep)
4392 if (sleep_time < min_sleep)
4399 struct node_lru *lnode;
4400 struct list_head *curr, *next;
4402 struct timespec now;
4404 pthread_mutex_lock(&f->lock);
4408 for (curr = f->lru_table.next; curr != &f->lru_table; curr = next) {
4412 lnode = list_entry(curr,
struct node_lru, lru);
4413 node = &lnode->node;
4415 age = diff_timespec(&now, &lnode->forget_time);
4416 if (age <= f->conf.remember)
4419 assert(node->nlookup == 1);
4422 if (node->refctr > 1)
4426 unhash_name(f, node);
4427 unref_node(f, node);
4429 pthread_mutex_unlock(&f->lock);
4431 return clean_delay(f);
4435 .
init = fuse_lib_init,
4436 .destroy = fuse_lib_destroy,
4437 .lookup = fuse_lib_lookup,
4438 .forget = fuse_lib_forget,
4439 .forget_multi = fuse_lib_forget_multi,
4440 .getattr = fuse_lib_getattr,
4441 .setattr = fuse_lib_setattr,
4442 .access = fuse_lib_access,
4443 .readlink = fuse_lib_readlink,
4444 .mknod = fuse_lib_mknod,
4445 .mkdir = fuse_lib_mkdir,
4446 .unlink = fuse_lib_unlink,
4447 .rmdir = fuse_lib_rmdir,
4448 .symlink = fuse_lib_symlink,
4449 .rename = fuse_lib_rename,
4450 .link = fuse_lib_link,
4451 .create = fuse_lib_create,
4452 .open = fuse_lib_open,
4453 .read = fuse_lib_read,
4454 .write_buf = fuse_lib_write_buf,
4455 .flush = fuse_lib_flush,
4456 .release = fuse_lib_release,
4457 .fsync = fuse_lib_fsync,
4458 .opendir = fuse_lib_opendir,
4459 .readdir = fuse_lib_readdir,
4460 .readdirplus = fuse_lib_readdirplus,
4461 .releasedir = fuse_lib_releasedir,
4462 .fsyncdir = fuse_lib_fsyncdir,
4463 .statfs = fuse_lib_statfs,
4464 .setxattr = fuse_lib_setxattr,
4465 .getxattr = fuse_lib_getxattr,
4466 .listxattr = fuse_lib_listxattr,
4467 .removexattr = fuse_lib_removexattr,
4468 .getlk = fuse_lib_getlk,
4469 .setlk = fuse_lib_setlk,
4470 .flock = fuse_lib_flock,
4471 .bmap = fuse_lib_bmap,
4472 .ioctl = fuse_lib_ioctl,
4473 .poll = fuse_lib_poll,
4474 .fallocate = fuse_lib_fallocate,
4475 .copy_file_range = fuse_lib_copy_file_range,
4476 .lseek = fuse_lib_lseek,
4479int fuse_notify_poll(
struct fuse_pollhandle *ph)
4489static int fuse_session_loop_remember(
struct fuse *f)
4491 struct fuse_session *se = f->se;
4493 struct timespec now;
4495 struct pollfd fds = {
4504 next_clean = now.tv_sec;
4509 if (now.tv_sec < next_clean)
4510 timeout = next_clean - now.tv_sec;
4514 res = poll(&fds, 1, timeout * 1000);
4520 }
else if (res > 0) {
4521 res = fuse_session_receive_buf_int(se, &fbuf, NULL);
4528 fuse_session_process_buf_int(se, &fbuf, NULL);
4532 next_clean = now.tv_sec + timeout;
4538 return res < 0 ? -1 : 0;
4547 return fuse_session_loop_remember(f);
4552FUSE_SYMVER(
"fuse_loop_mt_312",
"fuse_loop_mt@@FUSE_3.12")
4567int fuse_loop_mt_32(
struct fuse *f,
struct fuse_loop_config_v1 *config_v1);
4568FUSE_SYMVER(
"fuse_loop_mt_32",
"fuse_loop_mt@FUSE_3.2")
4569int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config_v1 *config_v1)
4577 int res = fuse_loop_mt_312(f, config);
4584int fuse_loop_mt_31(
struct fuse *f,
int clone_fd);
4585FUSE_SYMVER(
"fuse_loop_mt_31",
"fuse_loop_mt@FUSE_3.0")
4586int fuse_loop_mt_31(struct fuse *f,
int clone_fd)
4596 err = fuse_loop_mt_312(f, config);
4610 struct fuse_context_i *c = fuse_get_context_internal();
4620 struct fuse_context_i *c = fuse_get_context_internal();
4629 struct fuse_context_i *c = fuse_get_context_internal();
4639 int err = lookup_path_in_cache(f, path, &ino);
4647#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
4649static const struct fuse_opt fuse_lib_opts[] = {
4652 FUSE_LIB_OPT(
"debug", debug, 1),
4653 FUSE_LIB_OPT(
"-d", debug, 1),
4654 FUSE_LIB_OPT(
"kernel_cache", kernel_cache, 1),
4655 FUSE_LIB_OPT(
"auto_cache", auto_cache, 1),
4656 FUSE_LIB_OPT(
"noauto_cache", auto_cache, 0),
4657 FUSE_LIB_OPT(
"no_rofd_flush", no_rofd_flush, 1),
4658 FUSE_LIB_OPT(
"umask=", set_mode, 1),
4659 FUSE_LIB_OPT(
"umask=%o", umask, 0),
4660 FUSE_LIB_OPT(
"uid=", set_uid, 1),
4661 FUSE_LIB_OPT(
"uid=%d", uid, 0),
4662 FUSE_LIB_OPT(
"gid=", set_gid, 1),
4663 FUSE_LIB_OPT(
"gid=%d", gid, 0),
4664 FUSE_LIB_OPT(
"entry_timeout=%lf", entry_timeout, 0),
4665 FUSE_LIB_OPT(
"attr_timeout=%lf", attr_timeout, 0),
4666 FUSE_LIB_OPT(
"ac_attr_timeout=%lf", ac_attr_timeout, 0),
4667 FUSE_LIB_OPT(
"ac_attr_timeout=", ac_attr_timeout_set, 1),
4668 FUSE_LIB_OPT(
"negative_timeout=%lf", negative_timeout, 0),
4669 FUSE_LIB_OPT(
"noforget", remember, -1),
4670 FUSE_LIB_OPT(
"remember=%u", remember, 0),
4671 FUSE_LIB_OPT(
"modules=%s", modules, 0),
4672 FUSE_LIB_OPT(
"parallel_direct_write=%d", parallel_direct_writes, 0),
4676static int fuse_lib_opt_proc(
void *data,
const char *arg,
int key,
4679 (void) arg; (void) outargs; (void) data; (void) key;
4686static const struct fuse_opt fuse_help_opts[] = {
4687 FUSE_LIB_OPT(
"modules=%s", modules, 1),
4692static void print_module_help(
const char *name,
4699 printf(
"\nOptions for %s module:\n", name);
4709" -o kernel_cache cache files in kernel\n"
4710" -o [no]auto_cache enable caching based on modification times (off)\n"
4711" -o no_rofd_flush disable flushing of read-only fd on close (off)\n"
4712" -o umask=M set file permissions (octal)\n"
4713" -o uid=N set file owner\n"
4714" -o gid=N set file group\n"
4715" -o entry_timeout=T cache timeout for names (1.0s)\n"
4716" -o negative_timeout=T cache timeout for deleted names (0.0s)\n"
4717" -o attr_timeout=T cache timeout for attributes (1.0s)\n"
4718" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
4719" -o noforget never forget cached inodes\n"
4720" -o remember=T remember cached inodes for T seconds (0s)\n"
4721" -o modules=M1[:M2...] names of modules to push onto filesystem stack\n");
4728 print_module_help(
"subdir", &fuse_module_subdir_factory);
4730 print_module_help(
"iconv", &fuse_module_iconv_factory);
4737 fuse_lib_opt_proc) == -1
4746 for (module = conf.modules; module; module = next) {
4748 for (p = module; *p && *p !=
':'; p++);
4749 next = *p ? p + 1 : NULL;
4752 m = fuse_get_module(module);
4754 print_module_help(module, &m->factory);
4760static int fuse_init_intr_signal(
int signum,
int *installed)
4762 struct sigaction old_sa;
4764 if (sigaction(signum, NULL, &old_sa) == -1) {
4765 perror(
"fuse: cannot get old signal handler");
4769 if (old_sa.sa_handler == SIG_DFL) {
4770 struct sigaction sa;
4772 memset(&sa, 0,
sizeof(
struct sigaction));
4773 sa.sa_handler = fuse_intr_sighandler;
4774 sigemptyset(&sa.sa_mask);
4776 if (sigaction(signum, &sa, NULL) == -1) {
4777 perror(
"fuse: cannot set interrupt signal handler");
4785static void fuse_restore_intr_signal(
int signum)
4787 struct sigaction sa;
4789 memset(&sa, 0,
sizeof(
struct sigaction));
4790 sa.sa_handler = SIG_DFL;
4791 sigaction(signum, &sa, NULL);
4795static int fuse_push_module(
struct fuse *f,
const char *module,
4798 struct fuse_fs *fs[2] = { f->fs, NULL };
4799 struct fuse_fs *newfs;
4805 newfs = m->factory(args, fs);
4820 fuse_log(FUSE_LOG_ERR,
"fuse: warning: library too old, some operations may not not work\n");
4824 fs = (
struct fuse_fs *) calloc(1,
sizeof(
struct fuse_fs));
4826 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate fuse_fs object\n");
4830 fs->user_data = user_data;
4832 memcpy(&fs->op, op, op_size);
4836static int node_table_init(
struct node_table *t)
4838 t->size = NODE_TABLE_MIN_SIZE;
4839 t->array = (
struct node **) calloc(1,
sizeof(
struct node *) * t->size);
4840 if (t->array == NULL) {
4841 fuse_log(FUSE_LOG_ERR,
"fuse: memory allocation failed\n");
4850static void *fuse_prune_nodes(
void *fuse)
4852 struct fuse *f = fuse;
4865 return fuse_start_thread(&f->prune_thread, fuse_prune_nodes, f);
4872 if (lru_enabled(f)) {
4873 pthread_mutex_lock(&f->lock);
4874 pthread_cancel(f->prune_thread);
4875 pthread_mutex_unlock(&f->lock);
4876 pthread_join(f->prune_thread, NULL);
4881FUSE_SYMVER(
"fuse_new_31",
"fuse_new@@FUSE_3.1")
4884 size_t op_size,
void *user_data)
4891 f = (
struct fuse *) calloc(1,
sizeof(
struct fuse));
4893 fuse_log(FUSE_LOG_ERR,
"fuse: failed to allocate fuse object\n");
4897 f->conf.entry_timeout = 1.0;
4898 f->conf.attr_timeout = 1.0;
4899 f->conf.negative_timeout = 0.0;
4900 f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
4904 fuse_lib_opt_proc) == -1)
4907 pthread_mutex_lock(&fuse_context_lock);
4908 static int builtin_modules_registered = 0;
4910 if (builtin_modules_registered == 0) {
4912 fuse_register_module(
"subdir", fuse_module_subdir_factory, NULL);
4914 fuse_register_module(
"iconv", fuse_module_iconv_factory, NULL);
4916 builtin_modules_registered= 1;
4918 pthread_mutex_unlock(&fuse_context_lock);
4920 if (fuse_create_context_key() == -1)
4925 goto out_delete_context_key;
4935 f->pagesize = getpagesize();
4936 init_list_head(&f->partial_slabs);
4937 init_list_head(&f->full_slabs);
4938 init_list_head(&f->lru_table);
4940 if (f->conf.modules) {
4944 for (module = f->conf.modules; module; module = next) {
4946 for (p = module; *p && *p !=
':'; p++);
4947 next = *p ? p + 1 : NULL;
4950 fuse_push_module(f, module, args) == -1)
4955 if (!f->conf.ac_attr_timeout_set)
4956 f->conf.ac_attr_timeout = f->conf.attr_timeout;
4958#if defined(__FreeBSD__) || defined(__NetBSD__)
4963 f->conf.readdir_ino = 1;
4970 if (f->conf.debug) {
4971 fuse_log(FUSE_LOG_DEBUG,
"nullpath_ok: %i\n", f->conf.nullpath_ok);
4975 f->fs->debug = f->conf.debug;
4978 if (node_table_init(&f->name_table) == -1)
4979 goto out_free_session;
4981 if (node_table_init(&f->id_table) == -1)
4982 goto out_free_name_table;
4984 pthread_mutex_init(&f->lock, NULL);
4986 root = alloc_node(f);
4988 fuse_log(FUSE_LOG_ERR,
"fuse: memory allocation failed\n");
4989 goto out_free_id_table;
4991 if (lru_enabled(f)) {
4992 struct node_lru *lnode = node_lru(root);
4993 init_list_head(&lnode->lru);
4996 strcpy(root->inline_name,
"/");
4997 root->name = root->inline_name;
5000 fuse_init_intr_signal(f->conf.intr_signal,
5001 &f->intr_installed) == -1)
5004 root->parent = NULL;
5014 free(f->id_table.array);
5016 free(f->name_table.array);
5021 free(f->conf.modules);
5022out_delete_context_key:
5023 fuse_delete_context_key();
5032 size_t op_size,
void *private_data);
5033FUSE_SYMVER(
"fuse_new_30",
"fuse_new@FUSE_3.0")
5034struct fuse *fuse_new_30(struct
fuse_args *args,
5036 size_t op_size,
void *user_data)
5040 memset(&conf, 0,
sizeof(conf));
5043 FUSE_LIB_OPT(
"-h", show_help, 1),
5044 FUSE_LIB_OPT(
"--help", show_help, 1),
5049 fuse_lib_opt_proc) == -1)
5052 if (conf.show_help) {
5063 if (f->conf.intr && f->intr_installed)
5064 fuse_restore_intr_signal(f->conf.intr_signal);
5067 fuse_create_context(f);
5069 for (i = 0; i < f->id_table.size; i++) {
5072 for (node = f->id_table.array[i]; node != NULL;
5073 node = node->id_next) {
5074 if (node->is_hidden) {
5076 if (try_get_path(f, node->nodeid, NULL, &path, NULL,
false) == 0) {
5077 fuse_fs_unlink(f->fs, path);
5084 for (i = 0; i < f->id_table.size; i++) {
5088 for (node = f->id_table.array[i]; node != NULL; node = next) {
5089 next = node->id_next;
5094 assert(list_empty(&f->partial_slabs));
5095 assert(list_empty(&f->full_slabs));
5097 while (fuse_modules) {
5098 fuse_put_module(fuse_modules);
5100 free(f->id_table.array);
5101 free(f->name_table.array);
5102 pthread_mutex_destroy(&f->lock);
5105 free(f->conf.modules);
5107 fuse_delete_context_key();
5121 return FUSE_VERSION;
5126 return PACKAGE_VERSION;
int fuse_getgroups(int size, gid_t list[])
int fuse_mount(struct fuse *f, const char *mountpoint)
int fuse_interrupted(void)
void fuse_destroy(struct fuse *f)
int fuse_start_cleanup_thread(struct fuse *fuse)
int fuse_invalidate_path(struct fuse *f, const char *path)
struct fuse_fs *(* fuse_module_factory_t)(struct fuse_args *args, struct fuse_fs *fs[])
struct fuse_context * fuse_get_context(void)
int fuse_loop(struct fuse *f)
int(* fuse_fill_dir_t)(void *buf, const char *name, const struct stat *stbuf, off_t off, enum fuse_fill_dir_flags flags)
void fuse_exit(struct fuse *f)
int fuse_clean_cache(struct fuse *fuse)
void fuse_lib_help(struct fuse_args *args)
struct fuse_session * fuse_get_session(struct fuse *f)
void fuse_unmount(struct fuse *f)
struct fuse * fuse_new_31(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *private_data)
struct fuse_fs * fuse_fs_new(const struct fuse_operations *op, size_t op_size, void *private_data)
void fuse_stop_cleanup_thread(struct fuse *fuse)
void fuse_loop_cfg_convert(struct fuse_loop_config *config, struct fuse_loop_config_v1 *v1_conf)
struct fuse_loop_config * fuse_loop_cfg_create(void)
size_t fuse_buf_size(const struct fuse_bufvec *bufv)
#define FUSE_CAP_EXPORT_SUPPORT
void fuse_loop_cfg_set_clone_fd(struct fuse_loop_config *config, unsigned int value)
ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, enum fuse_buf_copy_flags flags)
void fuse_loop_cfg_destroy(struct fuse_loop_config *config)
const char * fuse_pkgversion(void)
void fuse_log(enum fuse_log_level level, const char *fmt,...)
void fuse_session_destroy(struct fuse_session *se)
int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv, enum fuse_buf_copy_flags flags)
int fuse_reply_lock(fuse_req_t req, const struct flock *lock)
int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi)
void fuse_session_exit(struct fuse_session *se)
int fuse_reply_poll(fuse_req_t req, unsigned revents)
int fuse_reply_err(fuse_req_t req, int err)
const struct fuse_ctx * fuse_req_ctx(fuse_req_t req)
void * fuse_req_userdata(fuse_req_t req)
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
struct fuse_req * fuse_req_t
size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct fuse_entry_param *e, off_t off)
int fuse_session_exited(struct fuse_session *se)
int fuse_req_interrupted(fuse_req_t req)
int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
int fuse_reply_readlink(fuse_req_t req, const char *link)
int fuse_session_loop(struct fuse_session *se)
int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
void fuse_session_unmount(struct fuse_session *se)
struct fuse_session * fuse_session_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata)
void fuse_reply_none(fuse_req_t req)
void fuse_lowlevel_help(void)
int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino, off_t off, off_t len)
int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
int fuse_reply_write(fuse_req_t req, size_t count)
int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, void *data)
void fuse_session_reset(struct fuse_session *se)
int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, const struct fuse_file_info *fi)
int fuse_reply_lseek(fuse_req_t req, off_t off)
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct stat *stbuf, off_t off)
int fuse_reply_attr(fuse_req_t req, const struct stat *attr, double attr_timeout)
int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
int fuse_reply_xattr(fuse_req_t req, size_t count)
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
void fuse_opt_free_args(struct fuse_args *args)
#define FUSE_OPT_KEY(templ, key)
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
#define FUSE_OPT_KEY_KEEP
#define FUSE_ARGS_INIT(argc, argv)
enum fuse_buf_flags flags
unsigned int parallel_direct_writes
unsigned int cache_readdir
void(* init)(void *userdata, struct fuse_conn_info *conn)
void(* setlk)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock, int sleep)
void(* getlk)(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, struct flock *lock)