* 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
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
};
/*
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);
}
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;
return(retval);
}
+#ifdef CONFIG_TDB
struct uuid {
__u32 time_low;
__u16 time_mid;
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);
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,
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;
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];
__u32 count)
{
struct ext2_icount_el *el;
+#ifdef CONFIG_TDB
TDB_DATA key, data;
if (icount->tdb) {
}
return 0;
}
-
+#endif
el = get_icount_el(icount, ino, 1);
if (!el)
return EXT2_ET_NO_MEMORY;
__u32 *count)
{
struct ext2_icount_el *el;
+#ifdef CONFIG_TDB
TDB_DATA key, data;
if (icount->tdb) {
free(data.dptr);
return 0;
}
+#endif
el = get_icount_el(icount, ino, 0);
if (!el) {
*count = 0;
int problem = 0;
if (dir) {
+#ifdef CONFIG_TDB
retval = ext2fs_create_icount_tdb(test_fs, dir,
flags, &icount);
if (retval) {
"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);