lessfs  1.7.0
About: Lessfs is a inline data deduplicating file system for Linux (implemented in user space with FUSE; especially useful for backup purposes).
  Fossies Dox: lessfs-1.7.0.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

lib_tc.c
Go to the documentation of this file.
1 /*
2  * Lessfs: A data deduplicating filesystem.
3  * Copyright (C) 2008 Mark Ruijter <mruijter@lessfs.com>
4  *
5  * This program is s_free software.
6  * You can redistribute lessfs and/or modify it under the terms of either
7  * (1) the GNU General Public License; either version 3 of the License,
8  * or (at your option) any later version as published by
9  * the Free Software Foundation; or (2) obtain a commercial license
10  * by contacting the Author.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15  * the GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #ifndef LFATAL
26 #include "lib_log.h"
27 #endif
28 
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <time.h>
38 #include <sys/file.h>
39 #include <fuse.h>
40 
41 #include <fcntl.h>
42 #include <pthread.h>
43 
44 #include <tcutil.h>
45 #include <tcbdb.h>
46 #include <tchdb.h>
47 #include <stdlib.h>
48 #include <stdbool.h>
49 #include <stdint.h>
50 #include <aio.h>
51 #include <mhash.h>
52 #include <mutils/mhash.h>
53 
54 #include "lib_safe.h"
55 #include "lib_cfg.h"
56 #include "retcodes.h"
57 #ifdef LZO
58 #include "lib_lzo.h"
59 #endif
60 #include "lib_qlz.h"
61 #include "lib_qlz15.h"
62 #include "lib_common.h"
63 #include "lib_tc.h"
64 #include "lib_crypto.h"
65 #include "file_io.h"
66 #include "lib_repl.h"
67 
68 #ifndef BERKELEYDB
69 #ifndef HAMSTERDB
70 extern char *logname;
71 extern char *function;
72 extern int debug;
73 extern int BLKSIZE;
74 extern int max_threads;
75 extern char *passwd;
76 
77 TCHDB *dbb;
78 TCHDB *dbu;
79 TCHDB *dbp;
80 TCBDB *dbl;
81 TCHDB *dbs;
82 TCHDB *dbdta;
83 TCBDB *dbdirent;
84 TCBDB *freelist;
85 
86 extern TCTREE *workqtree; // Used to buffer incoming data (writes)
87 extern TCTREE *readcachetree; // Used to cache chunks of data that are likely to be read
88 extern TCTREE *metatree; // Used to cache file metadata (e.g. inode -> struct stat).
89 extern TCTREE *hashtree; // Used to lock hashes
90 extern TCTREE *inodetree; // Used to lock inodes
91 extern TCTREE *path2inotree; // Used to cache path to inode translations
92 int fdbdta = 0;
93 int frepl = 0;
94 int freplbl = 0;
95 
96 extern unsigned long long nextoffset;
97 int written = 0;
98 
99 const char *offset_lockedby;
100 
101 u_int32_t db_flags, env_flags;
102 
103 int btree_test_transaction(TCBDB * bdb)
104 {
105  char *testtransaction = "LESSFSTESTTRANSACTION";
106  int ecode;
107  int retcode = 0;
108 
109  if (config->transactions) {
110  if (!tcbdbtranbegin(bdb))
111  goto e_exit;
112  if (!tcbdbput
113  (bdb, testtransaction, strlen(testtransaction),
114  testtransaction, strlen(testtransaction)))
115  goto e_exit;
116  if (!tcbdbtrancommit(bdb))
117  goto e_exit;
118  if (!tcbdbtranbegin(bdb))
119  goto e_exit;
120  if (!tcbdbout(bdb, testtransaction, strlen(testtransaction))) {
121  ecode = tcbdbecode(bdb);
123  ("check_hash_database - Failed to delete the initial test transaction");
124  }
125  if (!tcbdbtrancommit(bdb))
126  goto e_exit;
127  }
128  retcode = 1;
129  e_exit:
130  return (retcode);
131 }
132 
133 TCHDB *tc_set_hashdb(int database)
134 {
135  TCHDB *db;
136  switch (database) {
137  case DBU:
138  db = dbu;
139  break;
140  case DBB:
141  db = dbb;
142  break;
143  case DBDTA:
144  db = dbdta;
145  break;
146  case DBP:
147  db = dbp;
148  break;
149  case DBS:
150  db = dbs;
151  break;
152  default:
153  die_syserr();
154  }
155  return db;
156 }
157 
158 TCBDB *tc_set_btreedb(int database)
159 {
160  TCBDB *db;
161  switch (database) {
162  case DBDIRENT:
163  db = dbdirent;
164  break;
165  case DBL:
166  db = dbl;
167  break;
168  case FREELIST:
169  db = freelist;
170  break;
171  default:
172  die_syserr();
173  }
174  return db;
175 }
176 
177 int hash_test_transaction(TCHDB * hdb, char *dbpath)
178 {
179  char *testtransaction = "LESSFSTESTTRANSACTION";
180  int ecode;
181  int retcode = 0;
182 
183  if (config->transactions) {
184  if (!tchdbtranbegin(hdb))
185  goto e_exit;
186  if (!tchdbput
187  (hdb, testtransaction, strlen(testtransaction),
188  testtransaction, strlen(testtransaction)))
189  goto e_exit;
190  if (!tchdbtrancommit(hdb))
191  goto e_exit;
192  tchdbsync(hdb);
193  if (!tchdbtranbegin(hdb))
194  goto e_exit;
195  if (!tchdbout(hdb, testtransaction, strlen(testtransaction))) {
196  ecode = tchdbecode(hdb);
198  ("check_hash_database - Failed to delete the initial test transaction");
199  }
200  if (!tchdbtrancommit(hdb))
201  goto e_exit;
202  }
203  retcode = 1;
204  e_exit:
205  return (1);
206 }
207 
208 void repair_hash_database(TCHDB * hdb, char *dbpath,
209  unsigned long long bucketsize)
210 {
211  LFATAL
212  ("repair_hash_database : database %s failed the initial test transaction : executing automatic repair",
213  dbpath);
214  if (!tchdboptimize(hdb, bucketsize, 0, 0, HDBTLARGE))
215  die_dberr("Could not recover database : %s", dbpath);
216 }
217 
218 void repair_btree_database(TCBDB * bdb, char *dbpath,
219  unsigned long long bucketsize)
220 {
221  LFATAL
222  ("repair_btree_database : database %s failed the initial test transaction : executing automatic repair",
223  dbpath);
224  if (!tcbdboptimize(bdb, 0, 0, bucketsize, -1, -1, BDBTLARGE))
225  die_dberr("Could not recover database : %s", dbpath);
226 }
227 
228 TCHDB *hashdb_open(char *dbpath, int cacherow,
229  unsigned long long bucketsize, bool force_optimize)
230 {
231  TCHDB *hdb;
232  int ecode;
233  int count = 0;
234 
235  FUNC;
236 
237 
238 //retry_open:
239  hdb = tchdbnew();
240  if (cacherow > 0) {
241  tchdbsetcache(hdb, cacherow);
242  }
243 
244  if (config->defrag == 1) {
245  if (!tchdbsetdfunit(hdb, 1)) {
246  ecode = tchdbecode(hdb);
247  die_dberr("Error on setting defragmentation : %s",
248  tchdberrmsg(ecode));
249  }
250  }
251  tchdbsetmutex(hdb);
252  LINFO("Tuning the bucketsize for %s to %llu", dbpath, bucketsize);
253  if (!tchdbtune(hdb, bucketsize, 0, 0, HDBTLARGE)) {
254  ecode = tchdbecode(hdb);
255  die_dberr("Failed to tune database buckets : %s",
256  tchdberrmsg(ecode));
257  }
258  if (!tchdbsetxmsiz(hdb, bucketsize)) {
259  ecode = tchdbecode(hdb);
260  die_dberr("Failed to set extra mapped memory : %s",
261  tchdberrmsg(ecode));
262  }
263  if (!tchdbopen(hdb, dbpath, HDBOWRITER | HDBOCREAT) || force_optimize) {
264  repair_hash_database(hdb, dbpath, bucketsize);
265  count++;
266  }
267 
268  if (!hash_test_transaction(hdb, dbpath)) {
269  if (count == 0) {
270  repair_hash_database(hdb, dbpath, bucketsize);
271  count++;
272  } else
273  die_dberr
274  ("hash_test_transaction failed on a database that was 'repaired'");
275  }
276  if (count == 1)
277  LFATAL
278  ("Database : %s, has been repaired : running lessfsck is recommended",
279  dbpath);
280  EFUNC;
281  return hdb;
282 }
283 
284 TCBDB *btreedb_open(char *dbpath, int cacherow,
285  unsigned long long bucketsize, bool force_optimize)
286 {
287  TCBDB *bdb;
288  int ecode;
289  int count = 0;
290 
291  FUNC;
292 
293  bdb = tcbdbnew();
294  if (config->defrag == 1) {
295  if (!tcbdbsetdfunit(bdb, 1)) {
296  ecode = tcbdbecode(bdb);
297  die_dberr("Error on setting defragmentation : %s",
298  tcbdberrmsg(ecode));
299  }
300  }
301  tcbdbsetmutex(bdb);
302  tcbdbtune(bdb, 0, 0, bucketsize, -1, -1, BDBTLARGE);
303  tcbdbsetxmsiz(bdb, bucketsize);
304 
305  if (!tcbdbopen(bdb, dbpath, BDBOWRITER | BDBOCREAT) || force_optimize) {
306  repair_btree_database(bdb, dbpath, bucketsize);
307  count++;
308  }
309 
310  if (!btree_test_transaction(bdb)) {
311  if (count == 0) {
312  repair_btree_database(bdb, dbpath, bucketsize);
313  } else
314  die_dberr
315  ("btree_test_transaction failed on a database that was 'repaired'");
316  }
317  if (count == 1)
318  LFATAL
319  ("Database : %s, has been repaired : running lessfsck is recommended",
320  dbpath);
321  EFUNC;
322  return bdb;
323 }
324 
325 void tc_defrag()
326 {
328  if (!tchdboptimize(dbb, atol(config->fileblockbs), 0, 0, HDBTLARGE))
329  LINFO("fileblock.tch not optimized");
330  if (!tchdboptimize(dbu, atol(config->blockusagebs), 0, 0, HDBTLARGE))
331  LINFO("blockusage.tch not optimized");
332  if (!tchdboptimize(dbp, atol(config->metabs), 0, 0, HDBTLARGE))
333  LINFO("metadata.tcb not optimized");
334  if (!tchdboptimize(dbs, atol(config->symlinkbs), 0, 0, HDBTLARGE))
335  LINFO("symlink.tch not optimized");
336  if (config->blockdatabs) {
337  if (!tchdboptimize
338  (dbdta, atol(config->blockdatabs), 0, 0, HDBTLARGE))
339  LINFO("blockdata.tch not optimized");
340  }
341  if (!tcbdboptimize
342  (freelist, 0, 0, atol(config->freelistbs), -1, -1, BDBTLARGE))
343  LINFO("freelist.tcb not optimized");
344  if (!tcbdboptimize
345  (dbdirent, 0, 0, atol(config->direntbs), -1, -1, BDBTLARGE))
346  LINFO("dirent.tcb not optimized");
347  if (!tcbdboptimize
348  (dbl, 0, 0, atol(config->hardlinkbs), -1, -1, BDBTLARGE))
349  LINFO("hardlink.tcb not optimized");
351 }
352 
353 void tc_open(bool defrag, bool createpath, bool force_optimize)
354 {
355  char *dbpath;
356  struct stat stbuf;
357  char *sp;
358  char *hashstr;
359  DAT *data;
360 
361 
362  FUNC;
363  LINFO("Lessfs with tokyocabinet is no longer recommended, please consider using BerkeleyDB");
364  if ( config->blockdata_io_type == FILE_IO ) {
365  sp = s_dirname(config->blockdata);
366  } else sp=s_strdup(config->blockdata);
367  if (createpath)
368  mkpath(sp, 0744);
369  dbpath = as_sprintf(__FILE__, __LINE__, "%s/replog.dta", sp);
371  if (-1 == (frepl = s_open2(dbpath, O_CREAT | O_RDWR, S_IRWXU)))
372  die_syserr();
373  if (0 != flock(frepl, LOCK_EX | LOCK_NB)) {
374  LFATAL
375  ("Failed to lock the replication logfile %s\nlessfs must be unmounted before using this option!",
377  exit(EXIT_USAGE);
378  }
379 
380  if (config->replication && config->replication_role == 0) {
381  if (-1 == (freplbl = s_open2(dbpath, O_RDWR, S_IRWXU)))
382  die_syserr();
383  }
384  s_free(dbpath);
385  s_free(sp);
386 
387  dbpath =
388  as_sprintf(__FILE__, __LINE__, "%s/fileblock.tch",
389  config->fileblock);
390  if (createpath)
391  mkpath(config->fileblock, 0744);
392  LDEBUG("Open database %s", dbpath);
393  dbb =
394  hashdb_open(dbpath, 0, atol(config->fileblockbs), force_optimize);
395  s_free(dbpath);
396 
397  dbpath =
398  as_sprintf(__FILE__, __LINE__, "%s/blockusage.tch",
399  config->blockusage);
400  if (createpath)
401  mkpath(config->blockusage, 0744);
402  LDEBUG("Open database %s", dbpath);
403  dbu =
404  hashdb_open(dbpath, 0, atol(config->blockusagebs), force_optimize);
405  s_free(dbpath);
406 
407  dbpath =
408  as_sprintf(__FILE__, __LINE__, "%s/metadata.tcb", config->meta);
409  if (createpath)
410  mkpath(config->meta, 0744);
411  LDEBUG("Open database %s", dbpath);
412  dbp = hashdb_open(dbpath, 0, atol(config->metabs), force_optimize);
413  s_free(dbpath);
414  if (config->blockdatabs) {
415  dbpath =
416  as_sprintf(__FILE__, __LINE__, "%s/blockdata.tch",
417  config->blockdata);
418  if (createpath)
419  mkpath(config->blockdata, 0744);
420  LDEBUG("Open database %s", dbpath);
421  dbdta =
422  hashdb_open(dbpath, 0, atol(config->blockdatabs),
423  force_optimize);
424  s_free(dbpath);
425  }
426  dbpath =
427  as_sprintf(__FILE__, __LINE__, "%s/freelist.tcb",
428  config->freelist);
429  if (createpath)
430  mkpath(config->freelist, 0744);
431  freelist =
432  btreedb_open(dbpath, 0, atol(config->freelistbs), force_optimize);
433  LDEBUG("Open database %s", dbpath);
434  s_free(dbpath);
435  dbpath =
436  as_sprintf(__FILE__, __LINE__, "%s/symlink.tch", config->symlink);
437  if (createpath)
438  mkpath(config->symlink, 0744);
439  LDEBUG("Open database %s", dbpath);
440  dbs = hashdb_open(dbpath, 0, atol(config->symlinkbs), force_optimize);
441  s_free(dbpath);
442  /* The dirent database is a B-TREE DB with cursors */
443  dbpath =
444  as_sprintf(__FILE__, __LINE__, "%s/dirent.tcb", config->dirent);
445  if (createpath)
446  mkpath(config->dirent, 0744);
447  dbdirent =
448  btreedb_open(dbpath, 0, atol(config->direntbs), force_optimize);
449  s_free(dbpath);
450  /* The dbl database is a B-TREE DB with cursors */
451  dbpath =
452  as_sprintf(__FILE__, __LINE__, "%s/hardlink.tcb",
453  config->hardlink);
454  if (createpath)
455  mkpath(config->hardlink, 0744);
456  dbl =
457  btreedb_open(dbpath, 0, atol(config->hardlinkbs), force_optimize);
458  LDEBUG("Open database %s", dbpath);
459  s_free(dbpath);
460 
461  if (!defrag) {
462  open_trees();
463  if ( config->blockdata_io_type == FILE_IO ) {
464  if (-1 ==
465  (fdbdta =
466  s_open2(config->blockdata, O_CREAT | O_RDWR, S_IRWXU)))
467  die_syserr();
468  if (-1 == (stat(config->blockdata, &stbuf)))
469  die_syserr();
470  if (config->transactions) {
472  }
473  }
475  hashstr = as_sprintf(__FILE__, __LINE__, "NEXTOFFSET");
476  config->nexthash =
477  (char *) thash((unsigned char *) hashstr, strlen(hashstr));
478  data =
480  NOLOCK);
481  if (NULL == data) {
482  LINFO("Filesystem upgraded to support transactions");
483  nextoffset = stbuf.st_size;
484  } else {
485  memcpy(&nextoffset, data->data,
486  sizeof(unsigned long long));
487  DATfree(data);
488  }
489  }
490  }
491  LDEBUG("All databases are open");
492  if (config->transactions) {
493  if (config->blockdatabs) {
494  tchdbtranbegin(dbdta);
495  }
496  tcbdbtranbegin(freelist);
497  tchdbtranbegin(dbu);
498  tchdbtranbegin(dbb);
499  tchdbtranbegin(dbs);
500  tchdbtranbegin(dbp);
501  tcbdbtranbegin(dbdirent);
502  tcbdbtranbegin(dbl);
503  }
504  EFUNC;
505  return;
506 }
507 
508 void hashdb_close(TCHDB * hdb)
509 {
510  int ecode;
511 
512  FUNC;
513  /* close the database */
514  if (!tchdbclose(hdb)) {
515  ecode = tchdbecode(hdb);
516  die_dberr("close error: %s", tchdberrmsg(ecode));
517  }
518  /* delete the object */
519  tchdbdel(hdb);
520 }
521 
522 void tc_close(bool defrag)
523 {
524  int ecode;
525 
526  FUNC;
527 
530  (unsigned char *) &nextoffset,
531  sizeof(unsigned long long));
532  }
534  hashdb_close(dbb);
535  hashdb_close(dbp);
536  hashdb_close(dbu);
537  hashdb_close(dbs);
540  }
541  /* close the B-TREE database */
542  if (!tcbdbclose(freelist)) {
543  ecode = tcbdbecode(freelist);
544  die_dberr("close error: %s", tchdberrmsg(ecode));
545  }
546  /* delete the object */
547  tcbdbdel(freelist);
548 
549  /* close the B-TREE database */
550  if (!tcbdbclose(dbdirent)) {
551  ecode = tcbdbecode(dbdirent);
552  die_dberr("close error: %s", tchdberrmsg(ecode));
553  }
554  /* delete the object */
555  tcbdbdel(dbdirent);
556 
557  /* close the B-TREE database */
558  if (!tcbdbclose(dbl)) {
559  ecode = tcbdbecode(dbl);
560  die_dberr("close error: %s", tchdberrmsg(ecode));
561  }
562  /* delete the object */
563  tcbdbdel(dbl);
564 
565  if (!defrag) {
566  close_trees();
568  fsync(fdbdta);
569  close(fdbdta);
571  }
572  }
573  fsync(frepl);
574  close(frepl);
576  close(freplbl);
577  EFUNC;
578 }
579 
580 // lock is not used
581 void btbin_write_dup(int database, void *keydata, int keylen,
582  void *dataData, int datalen, bool lock)
583 {
584  TCBDB *tcdb;
585  int ecode;
586  FUNC;
587 
588  tcdb = tc_set_btreedb(database);
589  if (!tcbdbputdup(tcdb, keydata, keylen, dataData, datalen)) {
590  ecode = tcbdbecode(tcdb);
591  die_dberr("tcbdbputdup failed : %s", tcbdberrmsg(ecode));
592  }
593  if (0 == config->relax)
594  tcbdbsync(tcdb);
595  if (config->replication == 1 && config->replication_role == 0) {
596  if (database == DBDIRENT) {
597  write_repl_data(DBDIRENT, REPLDUPWRITE, keydata, keylen,
598  dataData, datalen, MAX_ALLOWED_THREADS - 2);
599  }
600  if (database == DBL) {
601  write_repl_data(DBL, REPLDUPWRITE, keydata, keylen, dataData,
602  datalen, MAX_ALLOWED_THREADS - 2);
603  }
604  if (database == FREELIST) {
605  write_repl_data(FREELIST, REPLDUPWRITE, keydata, keylen,
606  dataData, datalen, MAX_ALLOWED_THREADS - 2);
607  }
608  }
609  EFUNC;
610 }
611 
612 void btbin_write_dbdata(int database, void *keydata, int keylen,
613  void *dataData, int datalen)
614 {
615  TCBDB *tcdb;
616  int ecode;
617  FUNC;
618  tcdb = tc_set_btreedb(database);
619  if (!tcbdbput(tcdb, keydata, keylen, dataData, datalen)) {
620  ecode = tcbdbecode(tcdb);
621  die_dberr("tcbdbput failed : %s", tchdberrmsg(ecode));
622  }
623  if (0 == config->relax)
624  tcbdbsync(tcdb);
625  if (config->replication == 1 && config->replication_role == 0) {
626  if (database == DBDIRENT) {
627  write_repl_data(DBDIRENT, REPLWRITE, keydata, keylen, dataData,
628  datalen, MAX_ALLOWED_THREADS - 2);
629  }
630  if (database == DBL) {
631  write_repl_data(DBL, REPLWRITE, keydata, keylen, dataData,
632  datalen, MAX_ALLOWED_THREADS - 2);
633  }
634  if (database == FREELIST) {
635  write_repl_data(FREELIST, REPLWRITE, keydata, keylen, dataData,
636  datalen, MAX_ALLOWED_THREADS - 2);
637  }
638  }
639  EFUNC;
640 }
641 
642 void mbin_write_dbdata(TCMDB * db, void *keydata, int keylen,
643  void *dataData, int datalen)
644 {
645  FUNC;
646  tcmdbput(db, keydata, keylen, dataData, datalen);
647  EFUNC;
648 }
649 
650 void nbin_write_dbdata(TCNDB * db, void *keydata, int keylen,
651  void *dataData, int datalen)
652 {
653  FUNC;
654  tcndbput(db, keydata, keylen, dataData, datalen);
655  EFUNC;
656 }
657 
658 void bin_write_dbdata(int database, void *keydata, int keylen,
659  void *dataData, int datalen)
660 {
661  TCHDB *db;
662  int ecode;
663  db = tc_set_hashdb(database);
664  if (!tchdbput(db, keydata, keylen, dataData, datalen)) {
665  ecode = tchdbecode(db);
666  die_dberr("tchdbput failed : %s", tchdberrmsg(ecode));
667  }
668  if (config->replication == 1 && config->replication_role == 0) {
669  if (database == DBDTA) {
670  write_repl_data(DBDTA, REPLWRITE, keydata, keylen, dataData,
671  datalen, MAX_ALLOWED_THREADS - 2);
672  }
673  if (database == DBU) {
674  write_repl_data(DBU, REPLWRITE, keydata, keylen, dataData,
675  datalen, MAX_ALLOWED_THREADS - 2);
676  }
677  if (database == DBB) {
678  write_repl_data(DBB, REPLWRITE, keydata, keylen, dataData,
679  datalen, MAX_ALLOWED_THREADS - 2);
680  }
681  if (database == DBP) {
682  write_repl_data(DBP, REPLWRITE, keydata, keylen, dataData,
683  datalen, MAX_ALLOWED_THREADS - 2);
684  }
685  if (database == DBS) {
686  write_repl_data(DBS, REPLWRITE, keydata, keylen, dataData,
687  datalen, MAX_ALLOWED_THREADS - 2);
688  }
689  }
690 }
691 
692 void bin_write(int database, void *keydata, int keylen,
693  void *dataData, int datalen)
694 {
695  TCHDB *db;
696  int ecode;
697  db = tc_set_hashdb(database);
698  if (!tchdbput(db, keydata, keylen, dataData, datalen)) {
699  ecode = tchdbecode(db);
700  die_dberr("tchdbput failed : %s", tchdberrmsg(ecode));
701  }
702 }
703 
704 /* Search in directory with inode dinode or key dinode for name bname
705  Return the inode of file bname */
706 DDSTAT *dnode_bname_to_inode(void *dinode, int dlen, char *bname)
707 {
708  BDBCUR *cur;
709  char *dbkey;
710  int dbsize;
711  char *dbvalue;
712  DAT *statdata;
713  DDSTAT *filestat = NULL, *lfilestat;
714  DAT *fname;
715  DINOINO dinoino;
716  unsigned long long keynode;
717  unsigned long long valnode;
718  unsigned long long *inode;
719  unsigned long long *curinode;
720 #ifdef ENABLE_CRYPTO
721  DAT *decrypted;
722 #endif
723 
724  FUNC;
725  cur = tcbdbcurnew(dbdirent);
726  if (!tcbdbcurjump(cur, (char *) dinode, dlen)
727  && tcbdbecode(dbdirent) != TCESUCCESS) {
728  tcbdbcurdel(cur);
729  return NULL;
730  }
731 
732  inode = (unsigned long long *) dinode;
733  /* traverse records */
734  while (dbkey = tcbdbcurkey(cur, &dbsize)) {
735  curinode = (unsigned long long *) dbkey;
736  if (*curinode != *inode) {
737  //if (0 != memcmp(dbkey, dinode, dlen)) {
738  s_free(dbkey);
739  break;
740  }
741  dbvalue = tcbdbcurval(cur, &dbsize);
742  if (dbvalue) {
743  memcpy(&valnode, dbvalue, sizeof(valnode));
744  memcpy(&keynode, dbkey, sizeof(keynode));
745  if (keynode == valnode && keynode != 1) {
746  s_free(dbvalue);
747  s_free(dbkey);
748  tcbdbcurnext(cur);
749  continue;
750  }
751  statdata =
752  search_dbdata(DBP, &valnode, sizeof(unsigned long long),
753  NOLOCK);
754  if (NULL == statdata) {
755  LINFO("Unable to find file existing in dbp.\n");
756  tcbdbcurdel(cur);
757  s_free(dbvalue);
758  s_free(dbkey);
759  return NULL;
760  }
761 #ifdef ENABLE_CRYPTO
763  decrypted = lfsdecrypt(statdata);
764  DATfree(statdata);
765  statdata = decrypted;
766  }
767 #endif
768  filestat = (DDSTAT *) statdata->data;
769  s_free(dbvalue);
770  if (0 != filestat->filename[0]) {
771  s_free(statdata);
772  LDEBUG("compare bname %s with filestat->filename %s",
773  bname, filestat->filename);
774  if (0 == strcmp(bname, filestat->filename)) {
775  s_free(dbkey);
776  break;
777  }
778  } else {
779  memcpy(&dinoino.dirnode, dinode,
780  sizeof(unsigned long long));
781  dinoino.inode = filestat->stbuf.st_ino;
782  fname =
783  btsearch_keyval(DBL, &dinoino, sizeof(DINOINO), bname,
784  strlen(bname), NOLOCK);
785  if (fname) {
786  lfilestat = s_zmalloc(sizeof(DDSTAT));
787  memcpy(lfilestat, statdata->data, statdata->size);
788  s_free(statdata);
789  ddstatfree(filestat);
790  memcpy(&lfilestat->filename, fname->data, fname->size);
791  lfilestat->filename[fname->size + 1] = 0;
792  filestat = lfilestat;
793  DATfree(fname);
794  s_free(dbkey);
795  break;
796  } else
797  s_free(statdata);
798  }
799  ddstatfree(filestat);
800  filestat = NULL;
801  }
802  s_free(dbkey);
803  tcbdbcurnext(cur);
804  }
805  tcbdbcurdel(cur);
806  if (filestat) {
807  LDEBUG("dnode_bname_to_inode : filestat->filename=%s inode %lu",
808  filestat->filename, filestat->stbuf.st_ino);
809  } else {
810  LDEBUG("dnode_bname_to_inode : return NULL");
811  }
812  return filestat;
813 }
814 
815 // lock is not used with tc
816 DAT *search_dbdata(int database, void *key, int len, bool lock)
817 {
818  TCHDB *tcdb;
819  DAT *data;
820  int size;
821 
822  tcdb = tc_set_hashdb(database);
823  data = s_malloc(sizeof(DAT));
824  data->data = tchdbget(tcdb, key, len, &size);
825  data->size = (unsigned long) size;
826  if (NULL == data->data) {
827  LDEBUG("search_dbdata : return NULL");
828  s_free(data);
829  data = NULL;
830  } else
831  LDEBUG("search_dbdata : return %lu bytes", data->size);
832  return data;
833 }
834 
835 DAT *search_memhash(TCMDB * db, void *key, int len)
836 {
837  DAT *data;
838  int size;
839 
840  FUNC;
841  data = s_malloc(sizeof(DAT));
842  data->data = tcmdbget(db, key, len, &size);
843  data->size = (unsigned long) size;
844  if (NULL == data->data) {
845  LDEBUG("search_memhash : return NULL");
846  s_free(data);
847  data = NULL;
848  } else
849  LDEBUG("search_memhash : return %lu bytes", data->size);
850  EFUNC;
851  return data;
852 }
853 
854 int btdelete_curkey(int database, void *key, int keylen, void *kvalue,
855  int kvallen, const char *msg)
856 {
857  TCBDB *db;
858  BDBCUR *cur;
859  char *value;
860  int vsize;
861  int ksize;
862  char *dbkey;
863  int ret = 1;
864 
865  FUNC;
866 
867  db = tc_set_btreedb(database);
868  cur = tcbdbcurnew(db);
869  if (!tcbdbcurjump(cur, key, keylen)) {
870  tcbdbcurdel(cur);
871  return (-ENOENT);
872  }
873  /* traverse records */
874  while (dbkey = tcbdbcurkey(cur, &ksize)) {
875  if (0 != memcmp(dbkey, key, ksize)) {
876  s_free(dbkey);
877  break;
878  }
879  value = tcbdbcurval(cur, &vsize);
880  if (value) {
881  if (kvallen == vsize) {
882  if (0 == memcmp(value, kvalue, kvallen)) {
883  ret = 0;
884  if (!tcbdbcurout(cur)) {
886  ("btdelete_curkey : Failed to delete key, this should never happen : caller %s",
887  msg);
888  ret = -ENOENT;
889  }
890  s_free(value);
891  s_free(dbkey);
892  break;
893  }
894  }
895  s_free(value);
896  }
897  s_free(dbkey);
898  tcbdbcurnext(cur);
899  }
900  tcbdbcurdel(cur);
901  if (config->replication == 1 && config->replication_role == 0) {
902  if (db == dbdirent) {
904  kvalue, kvallen, MAX_ALLOWED_THREADS - 2);
905  }
906  if (db == dbl) {
907  write_repl_data(DBL, REPLDELETECURKEY, key, keylen, kvalue,
908  kvallen, MAX_ALLOWED_THREADS - 2);
909  }
910  if (db == freelist) {
912  kvalue, kvallen, MAX_ALLOWED_THREADS - 2);
913  }
914  }
915  return (ret);
916 }
917 
918 /* lock is not used with tc */
919 DAT *btsearch_keyval(int database, void *key, int keylen, void *val,
920  int vallen, bool lock)
921 {
922  TCBDB *db;
923  BDBCUR *cur;
924  char *dbkey;
925  char *dbvalue;
926  DAT *ret = NULL;
927  int size;
928 
929  FUNC;
930  db = tc_set_btreedb(database);
931  cur = tcbdbcurnew(db);
932  if (!tcbdbcurjump(cur, key, keylen) && tcbdbecode(db) != TCESUCCESS) {
933  tcbdbcurdel(cur);
934  return ret;
935  }
936  /* traverse records */
937  while (dbkey = tcbdbcurkey(cur, &size)) {
938  if (0 != memcmp(dbkey, key, keylen)) {
939  s_free(dbkey);
940  break;
941  }
942  dbvalue = tcbdbcurval(cur, &size);
943  if (dbvalue) {
944  if (val) {
945  if (vallen == size) {
946  if (0 == memcmp(val, dbvalue, size)) {
947  ret = s_zmalloc(sizeof(DAT));
948  ret->data = s_zmalloc(size + 1);
949  ret->size = size;
950  memcpy(ret->data, dbvalue, size);
951  s_free(dbvalue);
952  s_free(dbkey);
953  break;
954  }
955  }
956  } else {
957  ret = s_zmalloc(sizeof(DAT));
958  ret->data = s_zmalloc(size + 1);
959  ret->size = size;
960  memcpy(ret->data, dbvalue, size);
961  s_free(dbvalue);
962  s_free(dbkey);
963  break;
964  }
965  s_free(dbvalue);
966  }
967  s_free(dbkey);
968  tcbdbcurnext(cur);
969  }
970  tcbdbcurdel(cur);
971  EFUNC;
972  return ret;
973 }
974 
975 /* return 0, 1 or 2 if more then 2 we stop counting */
976 int count_dirlinks(void *linkstr, int len)
977 {
978  BDBCUR *cur;
979  char *key;
980  int size;
981  int count = 0;
982 
983  cur = tcbdbcurnew(dbl);
984  if (!tcbdbcurjump(cur, linkstr, len)
985  && tcbdbecode(dbl) != TCESUCCESS) {
986  tcbdbcurdel(cur);
987  return (-ENOENT);
988  }
989  /* traverse records */
990  while (key = tcbdbcurkey(cur, &size)) {
991  if (len == size) {
992  if (0 == memcmp(key, linkstr, len)) {
993  count++;
994  }
995  }
996  s_free(key);
997  tcbdbcurnext(cur);
998  if (count > 1)
999  break;
1000  }
1001  tcbdbcurdel(cur);
1002  return (count);
1003 }
1004 
1005 // Delete key from database, if caller (msg) is defined this operation
1006 // must be successfull, otherwise we log and exit.
1007 void delete_key(int database, void *keydata, int len, const char *msg)
1008 {
1009  TCHDB *db;
1010  int ecode;
1011 
1012  db = tc_set_hashdb(database);
1013  if (!tchdbout(db, keydata, len)) {
1014  ecode = tchdbecode(db);
1015  if (msg)
1016  die_dataerr("Delete of key failed %s:%s", msg,
1017  tchdberrmsg(ecode));
1018  }
1019  if (config->replication == 1 && config->replication_role == 0) {
1020  write_repl_data(database, REPLDELETE, keydata, len, NULL, 0,
1021  MAX_ALLOWED_THREADS - 2);
1022  }
1023 }
1024 
1026 {
1027  BDBCUR *cur;
1028  char *dbkey;
1029  char *key = "TRNCTD";
1030  int ksize;
1031  int keylen;
1032  pthread_t truncate_thread;
1033  struct truncate_thread_data *trunc_data;
1034 
1035 
1036  FUNC;
1037  if (!config->background_delete)
1038  return;
1039  keylen = strlen(key);
1040 
1041  cur = tcbdbcurnew(freelist);
1042  if (!tcbdbcurjump(cur, key, keylen)
1043  && tcbdbecode(dbdirent) != TCESUCCESS) {
1044  tcbdbcurdel(cur);
1045  return;
1046  }
1047  /* traverse records */
1048  while (dbkey = tcbdbcurkey(cur, &ksize)) {
1049  if (0 != memcmp(dbkey, key, keylen) || ksize != keylen) {
1050  s_free(dbkey);
1051  break;
1052  }
1053  trunc_data =
1054  (struct truncate_thread_data *) tcbdbcurval(cur, &ksize);
1055  if (0 == trunc_data->inode)
1056  break;
1057  LINFO("Resume truncation of inode %llu", trunc_data->inode);
1058  create_inode_note(trunc_data->inode);
1059  if (config->blockdatabs) {
1060  if (0 !=
1061  pthread_create(&truncate_thread, NULL, tc_truncate_worker,
1062  (void *) trunc_data))
1063  die_syserr();
1064  } else {
1065  if (0 !=
1066  pthread_create(&truncate_thread, NULL,
1067  file_truncate_worker, (void *) trunc_data))
1068  die_syserr();
1069  }
1070  if (0 != pthread_detach(truncate_thread))
1071  die_syserr();
1072  s_free(dbkey);
1073  tcbdbcurnext(cur);
1074  }
1075  tcbdbcurdel(cur);
1076 }
1077 
1078 /* Return 0 when the directory is empty, 1 when it contains files */
1079 unsigned long long has_nodes(unsigned long long inode)
1080 {
1081  unsigned long long res = 0;
1082  BDBCUR *cur;
1083  unsigned long long filenode;
1084  char *filenodestr;
1085  DAT *filedata;
1086  bool dotdir = 0;
1087  char *key;
1088  DDSTAT *ddstat;
1089  int size;
1090  unsigned long long keyval;
1091 
1092  FUNC;
1093  cur = tcbdbcurnew(dbdirent);
1094  if (!tcbdbcurjump(cur, &inode, sizeof(unsigned long long))
1095  && tcbdbecode(dbdirent) != TCESUCCESS) {
1096  tcbdbcurdel(cur);
1097  return (-ENOENT);
1098  }
1099  while (key = tcbdbcurkey(cur, &size)) {
1100  memcpy(&keyval, key, sizeof(unsigned long long));
1101  if (keyval != inode) {
1102  s_free(key);
1103  break;
1104  }
1105  filenodestr = (char *) tcbdbcurval(cur, &size);
1106  memcpy(&filenode, filenodestr, sizeof(unsigned long long));
1107  filedata =
1108  search_dbdata(DBP, &filenode, sizeof(unsigned long long),
1109  NOLOCK);
1110  if (filedata) {
1111  ddstat = value_to_ddstat(filedata);
1112  DATfree(filedata);
1113  LDEBUG("Compare : %llu %llu", filenode, inode);
1114  if (filenode == inode)
1115  dotdir = 1;
1116  if (ddstat->filename) {
1117  if (0 == strcmp(ddstat->filename, "."))
1118  dotdir = 1;
1119  if (0 == strcmp(ddstat->filename, ".."))
1120  dotdir = 1;
1121  }
1122  if (!dotdir) {
1123  LDEBUG
1124  ("has_nodes : Found file in directory %s filenode %llu inode %llu",
1125  ddstat->filename, filenode, inode);
1126  res++;
1127  }
1128  ddstatfree(ddstat);
1129  }
1130  s_free(key);
1131  s_free(filenodestr);
1132  dotdir = 0;
1133  if (0 != res)
1134  break;
1135  tcbdbcurnext(cur);
1136  }
1137  tcbdbcurdel(cur);
1138  LDEBUG("inode %llu contains files", inode);
1139  EFUNC;
1140  return (res);
1141 }
1142 
1143 void fs_read_hardlink(struct stat stbuf, DDSTAT * ddstat, void *buf,
1144  fuse_fill_dir_t filler, struct fuse_file_info *fi)
1145 {
1146  BDBCUR *cur;
1147  char *linkkey;
1148  int ksize;
1149  DINOINO dinoino;
1150  char *filename;
1151 
1152  FUNC;
1153  cur = tcbdbcurnew(dbl);
1154  dinoino.dirnode = stbuf.st_ino;
1155  dinoino.inode = ddstat->stbuf.st_ino;
1156  if (!tcbdbcurjump(cur, &dinoino, sizeof(DINOINO))
1157  && tcbdbecode(dbl) != TCESUCCESS)
1158  die_dataerr("Unable to find linkname, run fsck.");
1159  while (linkkey = tcbdbcurkey(cur, &ksize)) {
1160  if (0 != memcmp(linkkey, &dinoino, sizeof(DINOINO))) {
1161  LDEBUG("fs_read_hardlink : linkkey != dinoino");
1162  s_free(linkkey);
1163  break;
1164  }
1165  filename = (char *) tcbdbcurval(cur, &ksize);
1166  memcpy(&ddstat->filename, filename, ksize);
1167  ddstat->filename[ksize] = 0;
1168  s_free(filename);
1169  LDEBUG("fs_read_hardlink : fil_fuse_info %s size %i",
1170  ddstat->filename, ksize);
1171  fil_fuse_info(ddstat, buf, filler, fi);
1172  ddstat->filename[0] = 0;
1173  s_free(linkkey);
1174  tcbdbcurnext(cur);
1175  }
1176  tcbdbcurdel(cur);
1177  EFUNC;
1178  return;
1179 }
1180 
1181 int fs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
1182  off_t offset, struct fuse_file_info *fi)
1183 {
1184  int retcode = 0;
1185  BDBCUR *cur;
1186  int size, res;
1187  int ksize;
1188  char *key;
1189  struct stat stbuf;
1190  unsigned long long keynode;
1191  unsigned long long filenode;
1192  char *filenodestr;
1193  DAT *filedata;
1194  DDSTAT *ddstat;
1195  FUNC;
1196 
1197  (void) offset;
1198  (void) fi;
1199  LDEBUG("Called fs_readdir with path %s", (char *) path);
1200 
1201  res = dbstat(path, &stbuf, 1);
1202  if (0 != res)
1203  return -ENOENT;
1204 
1205  if (0 == strcmp(path, "/.lessfs/locks")) {
1206  LDEBUG("fs_readdir : reading locks");
1207  locks_to_dir(buf, filler, fi);
1208  }
1209 
1210  cur = tcbdbcurnew(dbdirent);
1211  if (!tcbdbcurjump(cur, &stbuf.st_ino, sizeof(unsigned long long))
1212  && tcbdbecode(dbdirent) != TCESUCCESS) {
1213  tcbdbcurdel(cur);
1214  return (-ENOENT);
1215  }
1216  while (key = tcbdbcurkey(cur, &ksize)) {
1217  memcpy(&keynode, key, sizeof(unsigned long long));
1218  if (stbuf.st_ino != keynode) {
1219  s_free(key);
1220  break;
1221  }
1222  filenodestr = tcbdbcurval(cur, &size);
1223  memcpy(&filenode, filenodestr, sizeof(unsigned long long));
1224  if (filenode == keynode) {
1225  s_free(filenodestr);
1226  s_free(key);
1227  tcbdbcurnext(cur);
1228  continue;
1229  }
1230  LDEBUG("GOT filenode %llu", filenode);
1231  filedata =
1232  search_dbdata(DBP, &filenode, sizeof(unsigned long long),
1233  NOLOCK);
1234  if (filedata) {
1235  ddstat = value_to_ddstat(filedata);
1236  DATfree(filedata);
1237  if (ddstat->filename[0] == 0) {
1238  fs_read_hardlink(stbuf, ddstat, buf, filler, fi);
1239  } else {
1240  fil_fuse_info(ddstat, buf, filler, fi);
1241  }
1242  ddstatfree(ddstat);
1243  }
1244  s_free(key);
1245  s_free(filenodestr);
1246  tcbdbcurnext(cur);
1247  }
1248  tcbdbcurdel(cur);
1249  LDEBUG("fs_readdir: return");
1250  return (retcode);
1251 }
1252 
1253 int bt_entry_exists(int database, void *parent, int parentlen, void *value,
1254  int vallen)
1255 {
1256  TCBDB *db;
1257  int res = 0;
1258  BDBCUR *cur;
1259  char *dbvalue;
1260  char *key;
1261  int ksize;
1262 
1263  FUNC;
1264 
1265  db = tc_set_btreedb(database);
1266  cur = tcbdbcurnew(db);
1267  if (!tcbdbcurjump(cur, parent, parentlen)
1268  && tcbdbecode(db) != TCESUCCESS) {
1269  tcbdbcurdel(cur);
1270  return (res);
1271  }
1272  while (key = tcbdbcurkey(cur, &ksize)) {
1273  if (ksize != parentlen) {
1274  s_free(key);
1275  break;
1276  }
1277  if (0 != memcmp(key, parent, parentlen)) {
1278  s_free(key);
1279  break;
1280  }
1281  dbvalue = tcbdbcurval2(cur);
1282  if (dbvalue) {
1283  if (0 == memcmp(value, dbvalue, vallen))
1284  res = 1;
1285  s_free(dbvalue);
1286  }
1287  s_free(key);
1288  tcbdbcurnext(cur);
1289  if (res == 1)
1290  break;
1291  }
1292  tcbdbcurdel(cur);
1293  LDEBUG("bt_entry_exists : returns %i", res);
1294  EFUNC;
1295  return (res);
1296 }
1297 
1299 {
1300  char *dbpath;
1301  struct stat stbuf;
1302 
1303  dbpath =
1304  as_sprintf(__FILE__, __LINE__, "%s/fileblock.tch",
1305  config->fileblock);
1306  if (-1 != stat(dbpath, &stbuf))
1307  unlink(dbpath);
1308  s_free(dbpath);
1309  dbpath =
1310  as_sprintf(__FILE__, __LINE__, "%s/blockusage.tch",
1311  config->blockusage);
1312  if (-1 != stat(dbpath, &stbuf))
1313  unlink(dbpath);
1314  s_free(dbpath);
1315  dbpath =
1316  as_sprintf(__FILE__, __LINE__, "%s/metadata.tcb", config->meta);
1317  if (-1 != stat(dbpath, &stbuf))
1318  unlink(dbpath);
1319  s_free(dbpath);
1320  dbpath =
1321  as_sprintf(__FILE__, __LINE__, "%s/symlink.tch", config->symlink);
1322  if (-1 != stat(dbpath, &stbuf))
1323  unlink(dbpath);
1324  s_free(dbpath);
1325  dbpath =
1326  as_sprintf(__FILE__, __LINE__, "%s/dirent.tcb", config->dirent);
1327  if (-1 != stat(dbpath, &stbuf))
1328  unlink(dbpath);
1329  s_free(dbpath);
1330  dbpath =
1331  as_sprintf(__FILE__, __LINE__, "%s/hardlink.tcb",
1332  config->hardlink);
1333  if (-1 != stat(dbpath, &stbuf))
1334  unlink(dbpath);
1335  s_free(dbpath);
1336  if (config->blockdatabs) {
1337  dbpath =
1338  as_sprintf(__FILE__, __LINE__, "%s/blockdata.tch",
1339  config->blockdata);
1340  if (-1 != stat(dbpath, &stbuf))
1341  unlink(dbpath);
1342  s_free(dbpath);
1343  } else {
1344  dbpath =
1345  as_sprintf(__FILE__, __LINE__, "%s/freelist.tcb",
1346  config->freelist);
1347  if (-1 != stat(dbpath, &stbuf))
1348  unlink(dbpath);
1349  s_free(dbpath);
1350  unlink(config->blockdata);
1351  }
1352 }
1353 
1354 DAT *search_nhash(TCNDB * db, void *key, int len)
1355 {
1356  DAT *data;
1357  int size;
1358 
1359  FUNC;
1360  data = s_malloc(sizeof(DAT));
1361  data->data = tcndbget(db, key, len, &size);
1362  data->size = (unsigned long) size;
1363  if (NULL == data->data) {
1364  LDEBUG("search_nhash : return NULL");
1365  s_free(data);
1366  data = NULL;
1367  } else
1368  LDEBUG("search_nhash : return %lu bytes", data->size);
1369  EFUNC;
1370  return data;
1371 }
1372 
1374 {
1375  if (config->blockdatabs) {
1376  if (config->transactions)
1377  if (!tchdbtranabort(dbdta))
1378  die_dataerr
1379  ("IO error, unable to abort dbdta transaction");
1380  } else {
1381  fsync(fdbdta);
1382  if (config->transactions)
1383  if (!tcbdbtranabort(freelist))
1384  die_dataerr
1385  ("IO error, unable to abort freelist transaction");
1386  }
1387  if (config->transactions) {
1388  if (!tchdbtranabort(dbu))
1389  die_dataerr
1390  ("IO error, unable to abort blockusage transaction");
1391  if (!tchdbtranabort(dbb))
1392  die_dataerr
1393  ("IO error, unable to abort fileblock transaction");
1394  if (!tchdbtranabort(dbp))
1395  die_dataerr("IO error, unable to abort metadata transaction");
1396  if (!tchdbtranabort(dbs))
1397  die_dataerr("IO error, unable to abort symlink transaction");
1398  if (!tcbdbtranabort(dbdirent))
1399  die_dataerr("IO error, unable to abort dirent transaction");
1400  if (!tcbdbtranabort(dbl))
1401  die_dataerr("IO error, unable to abort hardlink transaction");
1402  }
1404  return;
1405 }
1406 
1408 {
1409  if (config->blockdatabs) {
1410  if (config->transactions)
1411  if (!tchdbtrancommit(dbdta))
1412  die_dataerr
1413  ("IO error, unable to commit dbdta transaction");
1414  } else {
1415  fsync(fdbdta);
1416  if (config->transactions)
1417  if (!tcbdbtrancommit(freelist))
1418  die_dataerr
1419  ("IO error, unable to commit freelist transaction");
1420  }
1421  if (config->transactions) {
1422  if (!tchdbtrancommit(dbu))
1423  die_dataerr
1424  ("IO error, unable to commit blockusage transaction");
1425  if (!tchdbtrancommit(dbb))
1426  die_dataerr
1427  ("IO error, unable to commit fileblock transaction");
1428  if (!tchdbtrancommit(dbp))
1429  die_dataerr("IO error, unable to commit metadata transaction");
1430  if (!tchdbtrancommit(dbs))
1431  die_dataerr("IO error, unable to commit symlink transaction");
1432  if (!tcbdbtrancommit(dbdirent))
1433  die_dataerr("IO error, unable to commit dirent transaction");
1434  if (!tcbdbtrancommit(dbl))
1435  die_dataerr("IO error, unable to commit hardlink transaction");
1436  }
1437  return;
1438 }
1439 
1441 {
1442  unsigned long long lastoffset = 0;
1443  if (config->transactions)
1445  if (NULL == config->blockdatabs) {
1446  if (lastoffset != nextoffset) {
1447  LDEBUG("write nextoffset=%llu", nextoffset);
1449  (unsigned char *) &nextoffset,
1450  sizeof(unsigned long long));
1451  lastoffset = nextoffset;
1452  }
1453  }
1456  /* Make sure that the meta data is updated every once in a while */
1457  tcbdbsync(dbdirent);
1458  tcbdbsync(dbl);
1459  tchdbsync(dbp);
1460  tchdbsync(dbs);
1461 }
1462 
1464 {
1465  if (config->transactions) {
1466  if (config->blockdatabs) {
1467  tchdbtranbegin(dbdta);
1468  } else
1469  tcbdbtranbegin(freelist);
1470  tchdbtranbegin(dbu);
1471  tchdbtranbegin(dbb);
1472  tchdbtranbegin(dbp);
1473  tchdbtranbegin(dbs);
1474  tcbdbtranbegin(dbdirent);
1475  tcbdbtranbegin(dbl);
1476  }
1477  return;
1478 }
1479 
1481 {
1482  if (config->blockdatabs == NULL) {
1483  tcbdbsync(freelist);
1484  } else
1485  tchdbsync(dbdta);
1486  tchdbsync(dbu);
1487  tchdbsync(dbb);
1489 }
1490 
1492 {
1493  char *lfsmsg;
1494  char *line;
1495  char *key;
1496  int ksize;
1497  DDSTAT *ddstat;
1498  DAT *data;
1499  float ratio;
1500  unsigned long long *inode;
1501  char *nfi = "NFI";
1502  char *seq = "SEQ";
1503  const char **lines = NULL;
1504  int count = 1;
1505 
1506  lines = s_malloc((tchdbrnum(dbp) + 1) * sizeof(char *));
1507  lines[0] =
1508  as_sprintf(__FILE__, __LINE__,
1509  " INODE SIZE COMPRESSED_SIZE RATIO FILENAME\n");
1510  /* traverse records */
1511  tchdbiterinit(dbp);
1512  while (key = tchdbiternext(dbp, &ksize)) {
1513  if (0 != memcmp(key, nfi, 3) && 0 != memcmp(key, seq, 3)) {
1514  inode = (unsigned long long *) key;
1515  data =
1516  search_dbdata(DBP, (void *) inode,
1517  sizeof(unsigned long long), NOLOCK);
1518  if (*inode != 0) {
1519  ddstat = value_to_ddstat(data);
1520  ratio=0;
1521  if ( ddstat->stbuf.st_size != 0 ) {
1522  if ( ddstat->real_size == 0 ) {
1523  ratio=1000; // 100% dedup requires datasize/1000 metadata space
1524  } else ratio=(float)ddstat->stbuf.st_size/(float)ddstat->real_size;
1525  } else ratio=0;
1526  if (S_ISREG(ddstat->stbuf.st_mode)) {
1527 #ifdef x86_64
1528  line = as_sprintf
1529  (__FILE__, __LINE__, "%7lu %15lu %15llu %15.2f %s\n",
1530  ddstat->stbuf.st_ino, ddstat->stbuf.st_size,
1531  ddstat->real_size, ratio, ddstat->filename);
1532 #else
1533  line = as_sprintf
1534  (__FILE__, __LINE__, "%7llu %15llu %15llu %15.2f %s\n",
1535  ddstat->stbuf.st_ino, ddstat->stbuf.st_size,
1536  ddstat->real_size, ratio, ddstat->filename);
1537 #endif
1538  lines[count++] = line;
1539  }
1540  ddstatfree(ddstat);
1541  }
1542  DATfree(data);
1543  }
1544  s_free(key);
1545  }
1546  lfsmsg = as_strarrcat(lines, count);
1547  while (count) {
1548  s_free((char *) lines[--count]);
1549  }
1550  s_free(lines);
1551  return lfsmsg;
1552 }
1553 
1554 INUSE *get_offset_reclaim(unsigned long long mbytes,
1555  unsigned long long offset)
1556 {
1557  BDBCUR *cur;
1558  unsigned long long *dbkey;
1559  unsigned long long *dboffset;
1560  int dbsize;
1561  FREEBLOCK *freeblock;
1562  INUSE *inuse = NULL;
1563  time_t thetime;
1564  bool hasone = 0;
1565 
1566  FUNC;
1567  thetime = time(NULL);
1568  LDEBUG("get_offset_reclaim : search for %llu blocks on the freelist",
1569  mbytes);
1570  while (1) {
1571  cur = tcbdbcurnew(freelist);
1572  tcbdbcurfirst(cur);
1573  while (dbkey = tcbdbcurkey(cur, &dbsize)) {
1574  if (dbsize == strlen("TRNCTD") || *dbkey < mbytes) {
1575  s_free(dbkey);
1576  tcbdbcurnext(cur);
1577  continue;
1578  } else
1579  LDEBUG("Search %llu got %llu", mbytes, *dbkey);
1580  if ((dboffset = tcbdbcurval(cur, &dbsize)) == NULL)
1581  die_dataerr("get_offset_reclaim : No value for key");
1582  if (dbsize < sizeof(FREEBLOCK)) {
1583  memcpy(&offset, dboffset, sizeof(unsigned long long));
1584  if (config->replication == 1
1585  && config->replication_role == 0) {
1587  (char *) dbkey,
1588  sizeof(unsigned long long),
1589  (char *) &offset,
1590  sizeof(unsigned long long),
1591  MAX_ALLOWED_THREADS - 2);
1592  }
1593  } else {
1594  freeblock = (FREEBLOCK *) dboffset;
1595  if (freeblock->reuseafter > thetime && hasone == 0) {
1596  tcbdbcurnext(cur);
1597  hasone = 1;
1598  s_free(dbkey);
1599  s_free(dboffset);
1600  continue;
1601  }
1602  if (freeblock->reuseafter > thetime && hasone == 1)
1603  LINFO
1604  ("get_offset_reclaim : early space reclaim, low on space");
1605  offset = freeblock->offset;
1606  if (config->replication == 1
1607  && config->replication_role == 0) {
1609  (char *) dbkey,
1610  sizeof(unsigned long long),
1611  (char *) freeblock,
1612  sizeof(FREEBLOCK),
1613  MAX_ALLOWED_THREADS - 2);
1614  }
1615  }
1616  inuse = s_zmalloc(sizeof(INUSE));
1617  inuse->allocated_size = *dbkey * 512;
1618  LDEBUG("*dbkey=%llu, inuse->allocated_size %llu", *dbkey,
1619  inuse->allocated_size);
1620  inuse->offset = offset;
1621 
1622  LDEBUG
1623  ("get_offset_reclaim : reclaim %llu blocks on the freelist at offset %llu",
1624  mbytes, offset);
1625  if (!tcbdbcurout(cur)) {
1626  die_dataerr
1627  ("get_offset_reclaim : failed to delete key, this should never happen!");
1628  }
1629  s_free(dboffset);
1630  break;
1631  s_free(dbkey);
1632  tcbdbcurnext(cur);
1633  }
1634  tcbdbcurdel(cur);
1635  if (!hasone)
1636  break;
1637  if (inuse)
1638  break;
1639  }
1640  LDEBUG("get_offset_reclaim returns = %llu", offset);
1641  return inuse;
1642 }
1643 
1644 unsigned long long get_offset_fast(unsigned long long mbytes)
1645 {
1646  unsigned long long offset;
1647  BDBCUR *cur;
1648  unsigned long long *dbkey;
1649  unsigned long long *dboffset;
1650  int dbsize;
1651  bool found = 0;
1652  time_t thetime;
1653  FREEBLOCK *freeblock;
1654 
1655  FUNC;
1656 
1657  thetime = time(NULL);
1658  offset = nextoffset;
1659  LDEBUG("get_offset_fast : search for %llu blocks on the freelist",
1660  mbytes);
1661  cur = tcbdbcurnew(freelist);
1662  if (tcbdbcurjump(cur, (void *) &mbytes, sizeof(unsigned long long))) {
1663  while (dbkey = tcbdbcurkey(cur, &dbsize)) {
1664  if (0 == memcmp(dbkey, &mbytes, sizeof(unsigned long long))) {
1665  if ((dboffset = tcbdbcurval(cur, &dbsize)) == NULL)
1666  die_dataerr("get_offset_fast : No value for key");
1667  if (dbsize < sizeof(FREELIST)) {
1668  memcpy(&offset, dboffset, sizeof(unsigned long long));
1669  if (config->replication == 1
1670  && config->replication_role == 0) {
1672  (char *) &mbytes,
1673  sizeof(unsigned long long),
1674  (char *) &offset,
1675  sizeof(unsigned long long),
1676  MAX_ALLOWED_THREADS - 2);
1677  }
1678  } else {
1679  freeblock = (FREEBLOCK *) dboffset;
1680  if (freeblock->reuseafter > thetime) {
1681  tcbdbcurnext(cur);
1682  continue;
1683  }
1684  offset = freeblock->offset;
1685  if (config->replication == 1
1686  && config->replication_role == 0) {
1688  (char *) &mbytes,
1689  sizeof(unsigned long long),
1690  (char *) freelist,
1691  sizeof(FREELIST),
1692  MAX_ALLOWED_THREADS - 2);
1693  }
1694  }
1695  found = 1;
1696  LDEBUG
1697  ("get_offset_fast : reclaim %llu blocks on the freelist at offset %llu",
1698  mbytes, offset);
1699  if (!tcbdbcurout(cur)) {
1700  die_dataerr
1701  ("get_offset_fast : failed to delete key, this should never happen!");
1702  }
1703  s_free(dboffset);
1704  break;
1705  } else
1706  break;
1707  s_free(dbkey);
1708  }
1709  }
1710  if (!found)
1711  offset = (0 - 1);
1712  tcbdbcurdel(cur);
1713  LDEBUG("get_offset_fast returns = %llu", offset);
1714  return (offset);
1715 }
1716 
1718 {
1719  BDBCUR *cur;
1720  char *key, *value;
1721  int size;
1722  unsigned long long dir;
1723  unsigned long long ent;
1724 
1725  /* traverse records */
1726  cur = tcbdbcurnew(dbdirent);
1727  tcbdbcurfirst(cur);
1728  while (key = tcbdbcurkey2(cur)) {
1729  memcpy(&dir, key, sizeof(dir));
1730  value = tcbdbcurval(cur, &size);;
1731  if (value) {
1732  memcpy(&ent, value, sizeof(ent));
1733  printf("%llu:%llu\n", dir, ent);
1734  s_free(value);
1735  }
1736  s_free(key);
1737  tcbdbcurnext(cur);
1738  }
1739  tcbdbcurdel(cur);
1740 }
1741 
1742 void listfree(int freespace_summary)
1743 {
1744  unsigned long long mbytes;
1745  unsigned long long offset;
1746  unsigned long freespace=0;
1747  BDBCUR *cur;
1748  unsigned long long *dbkey;
1749  unsigned long long *dboffset;
1750  struct truncate_thread_data *trunc_data;
1751  int dbsize;
1752  FREEBLOCK *freeblock;
1753 
1754  cur = tcbdbcurnew(freelist);
1755  tcbdbcurfirst(cur);
1756  while (dbkey = tcbdbcurkey(cur, &dbsize)) {
1757  if (dbsize == strlen("TRNCTD")) {
1758  trunc_data =
1759  (struct truncate_thread_data *) tcbdbcurval(cur, &dbsize);
1760  printf
1761  ("Truncation not finished for inode %llu : start %llu -> end %llu size %llu\n",
1762  trunc_data->inode, trunc_data->blocknr,
1763  trunc_data->lastblocknr,
1764  (unsigned long long) trunc_data->stbuf.st_size);
1765  s_free(trunc_data);
1766  } else {
1767  if ((dboffset = tcbdbcurval(cur, &dbsize)) == NULL) {
1768  fprintf(stderr, "No value for key");
1769  exit(EXIT_SYSTEM);
1770  }
1771  memcpy(&mbytes, dbkey, sizeof(unsigned long long));
1772  freespace+=(mbytes * 512);
1773  if (dbsize < sizeof(FREEBLOCK)) {
1774  memcpy(&offset, dboffset, sizeof(unsigned long long));
1775  if ( !freespace_summary) {
1776  printf("offset = %llu : blocks = %llu : bytes = %llu\n",
1777  offset, mbytes, mbytes * 512);
1778  }
1779  } else {
1780  freeblock = (FREEBLOCK *) dboffset;
1781  if ( !freespace_summary) {
1782  printf
1783  ("offset = %llu : blocks = %llu : bytes = %llu reuseafter %lu\n",
1784  freeblock->offset, mbytes, mbytes * 512,
1785  freeblock->reuseafter);
1786  }
1787  }
1788  s_free(dboffset);
1789  }
1790  s_free(dbkey);
1791  tcbdbcurnext(cur);
1792  }
1793  printf("Total available space in %s : %lu\n\n",config->blockdata,freespace);
1794  tcbdbcurdel(cur);
1795  return;
1796 }
1797 
1798 void listdbp()
1799 {
1800  char *key, *value;
1801  int size;
1802  int ksize;
1803  DDSTAT *ddstat;
1804  DAT *data;
1805  unsigned long long inode;
1806  char *nfi = "NFI";
1807  char *seq = "SEQ";
1808  CRYPTO *crypto;
1809 
1810 
1811  /* traverse records */
1812  tchdbiterinit(dbp);
1813  while (key = tchdbiternext(dbp, &ksize)) {
1814  if (0 == memcmp(key, nfi, 3) || 0 == memcmp(key, seq, 3)) {
1815  value = tchdbget(dbp, key, strlen(key), &size);
1816  memcpy(&inode, value, sizeof(unsigned long long));
1817  printf("%s : %llu\n", key, inode);
1818  s_free(value);
1819  } else {
1820  memcpy(&inode, key, sizeof(unsigned long long));
1821  data =
1822  search_dbdata(DBP, &inode, sizeof(unsigned long long),
1823  LOCK);
1824  if (inode == 0) {
1825  crypto = (CRYPTO *) data->data;
1826  } else {
1827  ddstat = value_to_ddstat(data);
1828 #ifdef x86_64
1829  printf
1830  ("ddstat->filename %s \n ->inode %lu -> size %lu -> real_size %llu time %lu mode %u\n",
1831  ddstat->filename, ddstat->stbuf.st_ino,
1832  ddstat->stbuf.st_size, ddstat->real_size,
1833  ddstat->stbuf.st_atim.tv_sec, ddstat->stbuf.st_mode);
1834 #else
1835  printf
1836  ("ddstat->filename %s \n ->inode %llu -> size %llu -> real_size %llu time %lu mode %u\n",
1837  ddstat->filename, ddstat->stbuf.st_ino,
1838  ddstat->stbuf.st_size, ddstat->real_size,
1839  ddstat->stbuf.st_atim.tv_sec, ddstat->stbuf.st_mode);
1840 #endif
1841  if (S_ISDIR(ddstat->stbuf.st_mode)) {
1842  printf(" ->filename %s is a directory\n",
1843  ddstat->filename);
1844  }
1845  ddstatfree(ddstat);
1846  }
1847  DATfree(data);
1848  }
1849  s_free(key);
1850  }
1851 }
1852 
1854 {
1855  char *key, *value;
1856  int size;
1857  int ksize;
1858  unsigned long long inode;
1859  DINOINO dinoino;
1860  BDBCUR *cur;
1861 
1862  /* traverse records */
1863  cur = tcbdbcurnew(dbl);
1864  tcbdbcurfirst(cur);
1865  while (key = tcbdbcurkey(cur, &ksize)) {
1866  value = tcbdbcurval(cur, &size);
1867  if (ksize == sizeof(DINOINO)) {
1868  memcpy(&dinoino, key, sizeof(DINOINO));
1869  printf("dinoino %llu-%llu : inode %s\n", dinoino.dirnode,
1870  dinoino.inode, value);
1871  } else {
1872  memcpy(&inode, key, sizeof(unsigned long long));
1873  memcpy(&dinoino, value, sizeof(DINOINO));
1874  printf("inode %llu : %llu-%llu dinoino\n", inode,
1875  dinoino.dirnode, dinoino.inode);
1876  }
1877  s_free(value);
1878  s_free(key);
1879  tcbdbcurnext(cur);
1880  }
1881  tcbdbcurdel(cur);
1882 }
1883 
1884 /* List the symlink database */
1886 {
1887  char *key, *value;
1888  int size;
1889  int sp;
1890 
1891  unsigned long long inode;
1892  /* traverse records */
1893  tchdbiterinit(dbs);
1894  while (key = tchdbiternext(dbs, &size)) {
1895  value = tchdbget(dbs, key, size, &sp);
1896  memcpy(&inode, key, sizeof(unsigned long long));
1897  printf("%llu : %s\n", inode, value);
1898  s_free(value);
1899  s_free(key);
1900  }
1901 }
1902 
1903 void listdbb()
1904 {
1905  char *asc_hash = NULL;
1906  char *key, *value;
1907  int size;
1908  int vsize;
1909  unsigned long long inode;
1910  unsigned long long blocknr;
1911 
1912  /* traverse records */
1913  tchdbiterinit(dbb);
1914  while (key = tchdbiternext(dbb, &size)) {
1915  value = tchdbget(dbb, key, size, &vsize);
1916  asc_hash = ascii_hash((unsigned char *) value);
1917  memcpy(&inode, key, sizeof(unsigned long long));
1918  memcpy(&blocknr, key + sizeof(unsigned long long),
1919  sizeof(unsigned long long));
1920  printf("%llu-%llu : %s\n", inode, blocknr, asc_hash);
1921  s_free(asc_hash);
1922  s_free(value);
1923  s_free(key);
1924  }
1925 }
1926 
1927 
1928 void listdta()
1929 {
1930  char *asc_hash;
1931  char *key;
1932 
1933  /* traverse records */
1934  tchdbiterinit(dbdta);
1935  while (key = tchdbiternext2(dbdta)) {
1936  asc_hash = ascii_hash((unsigned char *) key);
1937  printf("%s\n", asc_hash);
1938  s_free(asc_hash);
1939  s_free(key);
1940  }
1941 }
1942 
1943 void flistdbu()
1944 {
1945  char *asc_hash;
1946  char *key;
1947  int size;
1948  INUSE *inuse;
1949  unsigned long rsize;
1950  unsigned long long nextoffet;
1951 
1952  /* traverse records */
1953  tchdbiterinit(dbu);
1954  while (key = tchdbiternext2(dbu)) {
1955  if (0 == memcmp(config->nexthash, key, config->hashlen)) {
1956  inuse = tchdbget(dbu, key, config->hashlen, &size);
1957  memcpy(&nextoffet, inuse, sizeof(unsigned long long));
1958  printf("\nnextoffset = %llu\n\n", nextoffset);
1959  } else {
1960  inuse = tchdbget(dbu, key, config->hashlen, &size);
1961  asc_hash = ascii_hash((unsigned char *) key);
1962  printf("%s : %llu\n", asc_hash, inuse->inuse);
1963  printf
1964  ("offset : %llu\n",
1965  inuse->offset);
1966  printf("size : %lu\n",
1967  inuse->size);
1968  rsize = round_512(inuse->size);
1969  printf
1970  ("round size : %lu\n\n",
1971  rsize);
1972  s_free(asc_hash);
1973  s_free(inuse);
1974  }
1975  s_free(key);
1976  }
1977 }
1978 
1979 void listdbu()
1980 {
1981  char *asc_hash;
1982  char *key, *value;
1983  int size;
1984  unsigned long long counter;
1985 
1986  /* traverse records */
1987  tchdbiterinit(dbu);
1988  while (key = tchdbiternext2(dbu)) {
1989  value = tchdbget(dbu, key, config->hashlen, &size);
1990  asc_hash = ascii_hash((unsigned char *) key);
1991  memcpy(&counter, value, sizeof(counter));
1992  printf("%s : %llu\n", asc_hash, counter);
1993  s_free(asc_hash);
1994  s_free(value);
1995  s_free(key);
1996  }
1997 }
1998 #endif
1999 #endif
tc_close
void tc_close(bool defrag)
Definition: lib_tc.c:522
mbin_write_dbdata
void mbin_write_dbdata(TCMDB *db, void *keydata, int keylen, void *dataData, int datalen)
Definition: lib_tc.c:642
lib_qlz.h
repair_btree_database
void repair_btree_database(TCBDB *bdb, char *dbpath, unsigned long long bucketsize)
Definition: lib_tc.c:218
bin_write
void bin_write(int database, void *keydata, int keylen, void *dataData, int datalen)
Definition: lib_tc.c:692
lib_safe.h
search_memhash
DAT * search_memhash(TCMDB *db, void *key, int len)
Definition: lib_tc.c:835
BLKSIZE
int BLKSIZE
Definition: commons.h:8
lib_common.h
DBL
#define DBL
Definition: lib_repl.h:26
FUNC
#define FUNC
Definition: lib_log.h:76
MAX_ALLOWED_THREADS
#define MAX_ALLOWED_THREADS
Definition: lib_common.h:13
dbb
TCHDB * dbb
Definition: lib_tc.c:77
configdata::freelist
char * freelist
Definition: lib_cfg.h:40
DATfree
void DATfree(DAT *data)
Definition: lib_common.c:1744
list_hardlinks
void list_hardlinks()
Definition: lib_tc.c:1853
FILE_IO
Definition: lib_common.h:33
EFUNC
#define EFUNC
Definition: lib_log.h:77
dnode_bname_to_inode
DDSTAT * dnode_bname_to_inode(void *dinode, int dlen, char *bname)
Definition: lib_tc.c:706
flistdbu
void flistdbu()
Definition: lib_tc.c:1943
DAT
Definition: lib_common.h:59
configdata::background_delete
int background_delete
Definition: lib_cfg.h:69
CRYPTO
Definition: lib_common.h:70
configdata::freelistbs
char * freelistbs
Definition: lib_cfg.h:41
nextoffset
unsigned long long nextoffset
Definition: lib_common.c:90
logname
char * logname
Definition: commons.h:5
configdata::encryptmeta
unsigned int encryptmeta
Definition: lib_cfg.h:58
configdata::replication
int replication
Definition: lib_cfg.h:62
dbs
TCHDB * dbs
Definition: lib_tc.c:81
truncate_thread_data::stbuf
struct stat stbuf
Definition: lib_common.h:89
FREEBLOCK::reuseafter
time_t reuseafter
Definition: file_io.h:24
has_nodes
unsigned long long has_nodes(unsigned long long inode)
Definition: lib_tc.c:1079
DAT::data
unsigned char * data
Definition: lib_common.h:61
INUSE::size
unsigned long size
Definition: lib_common.h:37
ddstatfree
void ddstatfree(DDSTAT *ddstat)
Definition: lib_common.c:1261
REPLDELETE
#define REPLDELETE
Definition: lib_repl.h:13
configdata::direntbs
char * direntbs
Definition: lib_cfg.h:31
listdirent
void listdirent()
Definition: lib_tc.c:1717
DBDTA
#define DBDTA
Definition: lib_repl.h:21
configdata::fileblockbs
char * fileblockbs
Definition: lib_cfg.h:33
nbin_write_dbdata
void nbin_write_dbdata(TCNDB *db, void *keydata, int keylen, void *dataData, int datalen)
Definition: lib_tc.c:650
die_dataerr
#define die_dataerr(f...)
Definition: file_io.c:94
start_transactions
void start_transactions()
Definition: lib_tc.c:1463
lib_log.h
written
int written
Definition: lib_tc.c:97
offset_lockedby
const char * offset_lockedby
Definition: lib_tc.c:99
delete_key
void delete_key(int database, void *keydata, int len, const char *msg)
Definition: lib_tc.c:1007
sync_all_filesizes
void sync_all_filesizes()
Definition: lib_common.c:3789
tc_restart_truncation
void tc_restart_truncation()
Definition: lib_tc.c:1025
lfsdecrypt
DAT * lfsdecrypt(DAT *)
passwd
char * passwd
listdta
void listdta()
Definition: lib_tc.c:1928
INUSE::offset
unsigned long long offset
Definition: lib_common.h:36
commit_transactions
void commit_transactions()
Definition: lib_tc.c:1407
freplbl
int freplbl
Definition: lib_tc.c:94
search_dbdata
DAT * search_dbdata(int database, void *key, int len, bool lock)
Definition: lib_tc.c:816
configdata::blockusagebs
char * blockusagebs
Definition: lib_cfg.h:29
path2inotree
TCTREE * path2inotree
Definition: lib_common.c:110
btsearch_keyval
DAT * btsearch_keyval(int database, void *key, int keylen, void *val, int vallen, bool lock)
Definition: lib_tc.c:919
NOLOCK
#define NOLOCK
Definition: lib_common.h:6
configdata::fileblock
char * fileblock
Definition: lib_cfg.h:32
dbdirent
TCBDB * dbdirent
Definition: lib_tc.c:83
fil_fuse_info
void fil_fuse_info(DDSTAT *ddstat, void *buf, fuse_fill_dir_t filler, struct fuse_file_info *fi)
Definition: lib_common.c:2927
lessfs_trans_stamp
void lessfs_trans_stamp()
Definition: lib_common.c:2771
hash_test_transaction
int hash_test_transaction(TCHDB *hdb, char *dbpath)
Definition: lib_tc.c:177
create_inode_note
void create_inode_note(unsigned long long inode)
Definition: lib_common.c:530
freelist
TCBDB * freelist
Definition: lib_tc.c:84
truncate_thread_data::inode
unsigned long long inode
Definition: lib_common.h:87
bt_entry_exists
int bt_entry_exists(int database, void *parent, int parentlen, void *value, int vallen)
Definition: lib_tc.c:1253
hashdb_close
void hashdb_close(TCHDB *hdb)
Definition: lib_tc.c:508
listdbu
void listdbu()
Definition: lib_tc.c:1979
hashdb_open
TCHDB * hashdb_open(char *dbpath, int cacherow, unsigned long long bucketsize, bool force_optimize)
Definition: lib_tc.c:228
value_to_ddstat
DDSTAT * value_to_ddstat(DAT *vddstat)
Definition: lib_common.c:986
DDSTAT::filename
char filename[256+1]
Definition: lib_common.h:67
DDSTAT::stbuf
struct stat stbuf
Definition: lib_common.h:65
lessfs_stats
char * lessfs_stats()
Definition: lib_tc.c:1491
get_offset_reclaim
INUSE * get_offset_reclaim(unsigned long long mbytes, unsigned long long offset)
Definition: lib_tc.c:1554
configdata::nexthash
char * nexthash
Definition: lib_cfg.h:42
tc_set_btreedb
TCBDB * tc_set_btreedb(int database)
Definition: lib_tc.c:158
tc_open
void tc_open(bool defrag, bool createpath, bool force_optimize)
Definition: lib_tc.c:353
file_truncate_worker
void * file_truncate_worker(void *threadarg)
Definition: file_io.c:580
configdata::defrag
unsigned int defrag
Definition: lib_cfg.h:55
configdata::blockdata
char * blockdata
Definition: lib_cfg.h:25
dbl
TCBDB * dbl
Definition: lib_tc.c:80
asc_hash
char * asc_hash(unsigned char *bhash, int hashlen)
Definition: replogtool.c:152
listfree
void listfree(int freespace_summary)
Definition: lib_tc.c:1742
DINOINO::dirnode
unsigned long long dirnode
Definition: lib_common.h:55
as_sprintf
void * as_sprintf(char *file, unsigned int line, const char *fmt,...)
Definition: lib_safe.c:564
fdbdta
int fdbdta
Definition: lib_tc.c:92
end_flush_commit
void end_flush_commit()
Definition: lib_tc.c:1480
btbin_write_dup
void btbin_write_dup(int database, void *keydata, int keylen, void *dataData, int datalen, bool lock)
Definition: lib_tc.c:581
listdbb
void listdbb()
Definition: lib_tc.c:1903
s_dirname
#define s_dirname(path)
Definition: lib_safe.h:27
frepl
int frepl
Definition: lib_tc.c:93
inodetree
TCTREE * inodetree
Definition: lib_common.c:112
DBB
#define DBB
Definition: lib_repl.h:23
dbp
TCHDB * dbp
Definition: lib_tc.c:79
configdata::meta
char * meta
Definition: lib_cfg.h:34
btreedb_open
TCBDB * btreedb_open(char *dbpath, int cacherow, unsigned long long bucketsize, bool force_optimize)
Definition: lib_tc.c:284
readcachetree
TCTREE * readcachetree
Definition: lib_common.c:109
dbu
TCHDB * dbu
Definition: lib_tc.c:78
dbdta
TCHDB * dbdta
Definition: lib_tc.c:82
lib_tc.h
LINFO
#define LINFO(f...)
Definition: lib_log.h:69
configdata::blockdata_io_type
int blockdata_io_type
Definition: lib_cfg.h:27
configdata::encryptdata
unsigned int encryptdata
Definition: lib_cfg.h:57
s_zmalloc
#define s_zmalloc(size)
Definition: lib_safe.h:24
DINOINO
Definition: lib_common.h:53
locks_to_dir
void locks_to_dir(void *buf, fuse_fill_dir_t filler, struct fuse_file_info *fi)
Definition: lib_common.c:2944
start_flush_commit
void start_flush_commit()
Definition: lib_tc.c:1440
configdata::metabs
char * metabs
Definition: lib_cfg.h:35
die_dberr
#define die_dberr(f...)
Definition: lib_common.h:1
search_nhash
DAT * search_nhash(TCNDB *db, void *key, int len)
Definition: lib_tc.c:1354
ascii_hash
char * ascii_hash(unsigned char *bhash)
Definition: lib_common.c:3880
tc_defrag
void tc_defrag()
Definition: lib_tc.c:325
check_datafile_sanity
void check_datafile_sanity()
Definition: lib_common.c:230
configdata::transactions
int transactions
Definition: lib_cfg.h:61
LFATAL
#define LFATAL(f...)
Definition: lib_log.h:68
list_symlinks
void list_symlinks()
Definition: lib_tc.c:1885
lib_crypto.h
get_offset_fast
unsigned long long get_offset_fast(unsigned long long mbytes)
Definition: lib_tc.c:1644
FREEBLOCK
Definition: file_io.h:22
truncate_thread_data::lastblocknr
unsigned long long lastblocknr
Definition: lib_common.h:86
configdata::hardlink
char * hardlink
Definition: lib_cfg.h:36
debug
int debug
Definition: commons.h:7
LOCK
#define LOCK
Definition: lib_common.h:5
LDEBUG
#define LDEBUG(f...)
Definition: lib_log.h:78
dbstat
int dbstat(const char *filename, struct stat *stbuf, bool cache_request)
Definition: lib_common.c:1204
fs_read_hardlink
void fs_read_hardlink(struct stat stbuf, DDSTAT *ddstat, void *buf, fuse_fill_dir_t filler, struct fuse_file_info *fi)
Definition: lib_tc.c:1143
EXIT_SYSTEM
#define EXIT_SYSTEM
Definition: retcodes.h:22
s_malloc
#define s_malloc(size)
Definition: lib_safe.h:23
REPLDUPWRITE
#define REPLDUPWRITE
Definition: lib_repl.h:15
mkpath
int mkpath(const char *s, mode_t mode)
Definition: lib_safe.c:681
file_io.h
hashtree
TCTREE * hashtree
Definition: lib_common.c:111
close_trees
void close_trees()
Definition: lib_common.c:3912
drop_databases
void drop_databases()
Definition: lib_tc.c:1298
DAT::size
unsigned long size
Definition: lib_common.h:60
DDSTAT::real_size
unsigned long long real_size
Definition: lib_common.h:66
REPLWRITE
#define REPLWRITE
Definition: lib_repl.h:12
DBP
#define DBP
Definition: lib_repl.h:24
tc_truncate_worker
void * tc_truncate_worker(void *threadarg)
Definition: lib_common.c:2337
retcodes.h
truncate_thread_data::blocknr
unsigned long long blocknr
Definition: lib_common.h:85
thash
unsigned char * thash(unsigned char *buf, int size)
Definition: lib_common.c:216
btree_test_transaction
int btree_test_transaction(TCBDB *bdb)
Definition: lib_tc.c:103
open_trees
void open_trees()
Definition: lib_common.c:3902
config
struct configdata * config
Definition: lib_cfg.h:91
INUSE
Definition: lib_common.h:35
btbin_write_dbdata
void btbin_write_dbdata(int database, void *keydata, int keylen, void *dataData, int datalen)
Definition: lib_tc.c:612
configdata::hardlinkbs
char * hardlinkbs
Definition: lib_cfg.h:37
configdata::hashlen
int hashlen
Definition: lib_cfg.h:60
abort_transactions
void abort_transactions()
Definition: lib_tc.c:1373
lib_repl.h
EXIT_USAGE
#define EXIT_USAGE
Definition: retcodes.h:23
INUSE::allocated_size
unsigned long long allocated_size
Definition: lib_common.h:38
DBDIRENT
#define DBDIRENT
Definition: lib_repl.h:28
configdata::relax
unsigned int relax
Definition: lib_cfg.h:56
DDSTAT
Definition: lib_common.h:64
lib_cfg.h
DBS
#define DBS
Definition: lib_repl.h:25
configdata::symlinkbs
char * symlinkbs
Definition: lib_cfg.h:39
s_strdup
#define s_strdup(size)
Definition: lib_safe.h:26
TOKYOCABINET
Definition: lib_common.h:33
truncate_thread_data
Definition: lib_common.h:84
bin_write_dbdata
void bin_write_dbdata(int database, void *keydata, int keylen, void *dataData, int datalen)
Definition: lib_tc.c:658
lib_qlz15.h
max_threads
int max_threads
Definition: commons.h:9
as_strarrcat
char * as_strarrcat(const char **strarr, ssize_t count)
Definition: lib_safe.c:545
DINOINO::inode
unsigned long long inode
Definition: lib_common.h:56
workqtree
TCTREE * workqtree
Definition: lib_common.c:108
REPLDELETECURKEY
#define REPLDELETECURKEY
Definition: lib_repl.h:16
DBU
#define DBU
Definition: lib_repl.h:22
fs_readdir
int fs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
Definition: lib_tc.c:1181
tc_set_hashdb
TCHDB * tc_set_hashdb(int database)
Definition: lib_tc.c:133
die_syserr
#define die_syserr()
Definition: lessfsck.c:71
INUSE::inuse
unsigned long long inuse
Definition: lib_common.h:39
configdata::blockdatabs
char * blockdatabs
Definition: lib_cfg.h:26
configdata::symlink
char * symlink
Definition: lib_cfg.h:38
s_open2
int s_open2(const char *pathname, int flags, mode_t mode)
Definition: lib_safe.c:489
btdelete_curkey
int btdelete_curkey(int database, void *key, int keylen, void *kvalue, int kvallen, const char *msg)
Definition: lib_tc.c:854
round_512
unsigned long long round_512(unsigned long long size)
Definition: file_io.c:140
configdata::replication_logfile
char * replication_logfile
Definition: lib_cfg.h:43
repair_hash_database
void repair_hash_database(TCHDB *hdb, char *dbpath, unsigned long long bucketsize)
Definition: lib_tc.c:208
lib_lzo.h
env_flags
u_int32_t env_flags
Definition: lib_tc.c:101
FREELIST
#define FREELIST
Definition: lib_repl.h:27
metatree
TCTREE * metatree
Definition: lib_common.c:113
listdbp
void listdbp()
Definition: lib_tc.c:1798
write_repl_data
void write_repl_data(unsigned char db, unsigned char op, char *key, int ksize, char *value, int vsize, int threadnr)
Definition: lib_repl.c:450
configdata::dirent
char * dirent
Definition: lib_cfg.h:30
configdata::replication_role
int replication_role
Definition: lib_cfg.h:63
FREEBLOCK::offset
unsigned long long offset
Definition: file_io.h:23
s_free
#define s_free(mem_ref)
Definition: lib_safe.h:25
configdata::blockusage
char * blockusage
Definition: lib_cfg.h:28
count_dirlinks
int count_dirlinks(void *linkstr, int len)
Definition: lib_tc.c:976
db_flags
u_int32_t db_flags
Definition: lib_tc.c:101