Whamcloud - gitweb
Add configure --disable-tdb which disables e2fsck's scratch_files feature
[tools/e2fsprogs.git] / lib / ext2fs / icount.c
index bf80eb1..594b1cc 100644 (file)
@@ -4,11 +4,12 @@
  * Copyright (C) 1997 Theodore Ts'o.
  *
  * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
+ * This file may be redistributed under the terms of the GNU Library
+ * General Public License, version 2.
  * %End-Header%
  */
 
+#include "config.h"
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -56,8 +57,10 @@ struct ext2_icount {
        ext2_ino_t              cursor;
        struct ext2_icount_el   *list;
        struct ext2_icount_el   *last_lookup;
+#ifdef CONFIG_TDB
        char                    *tdb_fn;
        TDB_CONTEXT             *tdb;
+#endif
 };
 
 /*
@@ -81,12 +84,14 @@ void ext2fs_free_icount(ext2_icount_t icount)
                ext2fs_free_inode_bitmap(icount->single);
        if (icount->multiple)
                ext2fs_free_inode_bitmap(icount->multiple);
+#ifdef CONFIG_TDB
        if (icount->tdb)
                tdb_close(icount->tdb);
        if (icount->tdb_fn) {
                unlink(icount->tdb_fn);
                free(icount->tdb_fn);
        }
+#endif
 
        ext2fs_free_mem(&icount);
 }
@@ -103,12 +108,12 @@ static errcode_t alloc_icount(ext2_filsys fs, int flags, ext2_icount_t *ret)
                return retval;
        memset(icount, 0, sizeof(struct ext2_icount));
 
-       retval = ext2fs_allocate_inode_bitmap(fs, 0, &icount->single);
+       retval = ext2fs_allocate_inode_bitmap(fs, "icount", &icount->single);
        if (retval)
                goto errout;
 
        if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
-               retval = ext2fs_allocate_inode_bitmap(fs, 0,
+               retval = ext2fs_allocate_inode_bitmap(fs, "icount_inc",
                                                      &icount->multiple);
                if (retval)
                        goto errout;
@@ -126,6 +131,7 @@ errout:
        return(retval);
 }
 
+#ifdef CONFIG_TDB
 struct uuid {
        __u32   time_low;
        __u16   time_mid;
@@ -172,13 +178,19 @@ static void uuid_unparse(void *uu, char *out)
                uuid.node[0], uuid.node[1], uuid.node[2],
                uuid.node[3], uuid.node[4], uuid.node[5]);
 }
+#endif
 
-errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir,
-                                  int flags, ext2_icount_t *ret)
+errcode_t ext2fs_create_icount_tdb(ext2_filsys fs EXT2FS_NO_TDB_UNUSED,
+                                  char *tdb_dir EXT2FS_NO_TDB_UNUSED,
+                                  int flags EXT2FS_NO_TDB_UNUSED,
+                                  ext2_icount_t *ret EXT2FS_NO_TDB_UNUSED)
 {
+#ifdef CONFIG_TDB
        ext2_icount_t   icount;
        errcode_t       retval;
        char            *fn, uuid[40];
+       ext2_ino_t      num_inodes;
+       mode_t          save_umask;
        int             fd;
 
        retval = alloc_icount(fs, flags,  &icount);
@@ -190,23 +202,40 @@ errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir,
                goto errout;
        uuid_unparse(fs->super->s_uuid, uuid);
        sprintf(fn, "%s/%s-icount-XXXXXX", tdb_dir, uuid);
+       save_umask = umask(077);
        fd = mkstemp(fn);
-
-       icount->tdb_fn = fn;
-       icount->tdb = tdb_open(fn, 0, TDB_CLEAR_IF_FIRST,
-                              O_RDWR | O_CREAT | O_TRUNC, 0600);
-       if (icount->tdb) {
-               close(fd);
-               *ret = icount;
-               return 0;
+       if (fd < 0) {
+               retval = errno;
+               ext2fs_free_mem(&fn);
+               goto errout;
        }
+       icount->tdb_fn = fn;
+       umask(save_umask);
+       /*
+        * This is an overestimate of the size that we will need; the
+        * ideal value is the number of used inodes with a count
+        * greater than 1.  OTOH the times when we really need this is
+        * with the backup programs that use lots of hard links, in
+        * which case the number of inodes in use approaches the ideal
+        * value.
+        */
+       num_inodes = fs->super->s_inodes_count - fs->super->s_free_inodes_count;
 
-       retval = errno;
+       icount->tdb = tdb_open(fn, num_inodes, TDB_NOLOCK | TDB_NOSYNC,
+                              O_RDWR | O_CREAT | O_TRUNC, 0600);
        close(fd);
-
+       if (icount->tdb == NULL) {
+               retval = errno;
+               goto errout;
+       }
+       *ret = icount;
+       return 0;
 errout:
        ext2fs_free_icount(icount);
        return(retval);
+#else
+       return EXT2_ET_UNIMPLEMENTED;
+#endif
 }
 
 errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size,
@@ -339,9 +368,7 @@ static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
 static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
                                            ext2_ino_t ino, int create)
 {
-       float   range;
        int     low, high, mid;
-       ext2_ino_t      lowval, highval;
 
        if (!icount || !icount->list)
                return 0;
@@ -363,31 +390,7 @@ static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
        low = 0;
        high = (int) icount->count-1;
        while (low <= high) {
-#if 0
-               mid = (low+high)/2;
-#else
-               if (low == high)
-                       mid = low;
-               else {
-                       /* Interpolate for efficiency */
-                       lowval = icount->list[low].ino;
-                       highval = icount->list[high].ino;
-
-                       if (ino < lowval)
-                               range = 0;
-                       else if (ino > highval)
-                               range = 1;
-                       else {
-                               range = ((float) (ino - lowval)) /
-                                       (highval - lowval);
-                               if (range > 0.9)
-                                       range = 0.9;
-                               if (range < 0.1)
-                                       range = 0.1;
-                       }
-                       mid = low + ((int) (range * (high-low)));
-               }
-#endif
+               mid = ((unsigned)low + (unsigned)high) >> 1;
                if (ino == icount->list[mid].ino) {
                        icount->cursor = mid+1;
                        return &icount->list[mid];
@@ -410,6 +413,7 @@ static errcode_t set_inode_count(ext2_icount_t icount, ext2_ino_t ino,
                                 __u32 count)
 {
        struct ext2_icount_el   *el;
+#ifdef CONFIG_TDB
        TDB_DATA key, data;
 
        if (icount->tdb) {
@@ -428,7 +432,7 @@ static errcode_t set_inode_count(ext2_icount_t icount, ext2_ino_t ino,
                }
                return 0;
        }
-
+#endif
        el = get_icount_el(icount, ino, 1);
        if (!el)
                return EXT2_ET_NO_MEMORY;
@@ -441,6 +445,7 @@ static errcode_t get_inode_count(ext2_icount_t icount, ext2_ino_t ino,
                                 __u32 *count)
 {
        struct ext2_icount_el   *el;
+#ifdef CONFIG_TDB
        TDB_DATA key, data;
 
        if (icount->tdb) {
@@ -457,6 +462,7 @@ static errcode_t get_inode_count(ext2_icount_t icount, ext2_ino_t ino,
                free(data.dptr);
                return 0;
        }
+#endif
        el = get_icount_el(icount, ino, 0);
        if (!el) {
                *count = 0;
@@ -770,6 +776,7 @@ int run_test(int flags, int size, char *dir, struct test_program *prog)
        int             problem = 0;
 
        if (dir) {
+#ifdef CONFIG_TDB
                retval = ext2fs_create_icount_tdb(test_fs, dir,
                                                  flags, &icount);
                if (retval) {
@@ -777,6 +784,10 @@ int run_test(int flags, int size, char *dir, struct test_program *prog)
                                "while creating icount using tdb");
                        exit(1);
                }
+#else
+               printf("Skipped\n");
+               return 0;
+#endif
        } else {
                retval = ext2fs_create_icount2(test_fs, flags, size, 0,
                                               &icount);