1997-04-29 20:17:09 +04:00
|
|
|
/*
|
|
|
|
* icount.c --- an efficient inode count abstraction
|
|
|
|
*
|
|
|
|
* Copyright (C) 1997 Theodore Ts'o.
|
|
|
|
*
|
|
|
|
* %Begin-Header%
|
2010-05-18 05:31:56 +04:00
|
|
|
* This file may be redistributed under the terms of the GNU Library
|
|
|
|
* General Public License, version 2.
|
1997-04-29 20:17:09 +04:00
|
|
|
* %End-Header%
|
|
|
|
*/
|
|
|
|
|
2011-09-19 01:34:37 +04:00
|
|
|
#include "config.h"
|
1997-08-11 03:07:40 +04:00
|
|
|
#if HAVE_UNISTD_H
|
1997-04-29 20:17:09 +04:00
|
|
|
#include <unistd.h>
|
1997-08-11 03:07:40 +04:00
|
|
|
#endif
|
1997-04-29 20:17:09 +04:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2007-04-06 22:30:39 +04:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
1997-04-29 20:17:09 +04:00
|
|
|
|
Many files:
inode.c (ext2fs_open_inode_scan): Initialize the group variables
so that we don't need to call get_next_blockgroup() the first
time around. Saves a bit of time, and prevents us from
needing to assign -1 to current_group (which is an unsigned
value).
icount.c (insert_icount_el): Cast the estimated number of inodes
from a float to an ino_t.
alloc.c, alloc_tables.c, badlbocks.c, bb_compat.c, bb_inode.c,
bitmaps.c, bitops.c, block.c, bmap.c, bmove.c, brel_ma.c,
check_desc.c, closefs.c, cmp_bitmaps.c, dblist.c,
dblist_dir.c, dir_iterate.c, dirblock.c, dupfs.c, expanddir.c,
ext2fs.h, fileio.c, freefs.c, get_pathname.c, getsize.c,
icount.c, initialize.c, inline.c, inode.c, irel_ma.c,
ismounted.c, link.c, lookup.c, mkdir.c, namei.c, native.c,
newdir.c, openfs.c, read_bb.c, read_bb_file.c, rs_bitmap.c,
rw_bitmaps.c, swapfs.c, test_io.c, tst_badblocks.c,
tst_getsize.c, tst_iscan.c, unix_io.c, unlink.c, valid_blk.c,
version.c: If EXT2_FLAT_INCLUDES is defined, then assume all
of the ext2-specific header files are in a flat directory.
block.c, bmove.c, dirblock.c, fileio.c: Explicitly cast
all assignments from void * to be compatible with C++.
closefs.c (ext2fs_flush): Add a call to io_channel_flush() to
make sure the contents of the disk are flushed to disk.
dblist.c (ext2fs_add_dir_block): Change new to be new_entry to
avoid C++ namespace clash.
bitmaps.c (ext2fs_copy_bitmap): Change new to be new_map to
avoid C++ namespace clash.
ext2fs.h, bb_inode.c, block.c, bmove.c, brel.h, brel_ma.c,
irel.h, irel_ma.c, dblist.c, dblist_dir.c, dir_iterate.c,
ext2fsP.h, expanddir.c, get_pathname.c, inode.c, link.c,
unlink.c: Change private to be priv_data (to avoid C++
namespace clash)
1998-01-19 17:47:53 +03:00
|
|
|
#include "ext2_fs.h"
|
1997-04-29 20:17:09 +04:00
|
|
|
#include "ext2fs.h"
|
2007-04-06 22:30:39 +04:00
|
|
|
#include "tdb.h"
|
1997-04-29 20:17:09 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The data storage strategy used by icount relies on the observation
|
|
|
|
* that most inode counts are either zero (for non-allocated inodes),
|
|
|
|
* one (for most files), and only a few that are two or more
|
|
|
|
* (directories and files that are linked to more than one directory).
|
|
|
|
*
|
|
|
|
* Also, e2fsck tends to load the icount data sequentially.
|
|
|
|
*
|
|
|
|
* So, we use an inode bitmap to indicate which inodes have a count of
|
|
|
|
* one, and then use a sorted list to store the counts for inodes
|
|
|
|
* which are greater than one.
|
|
|
|
*
|
|
|
|
* We also use an optional bitmap to indicate which inodes are already
|
|
|
|
* in the sorted list, to speed up the use of this abstraction by
|
|
|
|
* e2fsck's pass 2. Pass 2 increments inode counts as it finds them,
|
|
|
|
* so this extra bitmap avoids searching the sorted list to see if a
|
|
|
|
* particular inode is on the sorted list already.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct ext2_icount_el {
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
ext2_ino_t ino;
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
__u32 count;
|
1997-04-29 20:17:09 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ext2_icount {
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
errcode_t magic;
|
1997-04-29 20:17:09 +04:00
|
|
|
ext2fs_inode_bitmap single;
|
|
|
|
ext2fs_inode_bitmap multiple;
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
ext2_ino_t count;
|
|
|
|
ext2_ino_t size;
|
|
|
|
ext2_ino_t num_inodes;
|
2003-12-07 09:28:50 +03:00
|
|
|
ext2_ino_t cursor;
|
1997-04-29 20:17:09 +04:00
|
|
|
struct ext2_icount_el *list;
|
2007-04-06 22:30:39 +04:00
|
|
|
struct ext2_icount_el *last_lookup;
|
|
|
|
char *tdb_fn;
|
|
|
|
TDB_CONTEXT *tdb;
|
1997-04-29 20:17:09 +04:00
|
|
|
};
|
|
|
|
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
/*
|
|
|
|
* We now use a 32-bit counter field because it doesn't cost us
|
|
|
|
* anything extra for the in-memory data structure, due to alignment
|
|
|
|
* padding. But there's no point changing the interface if most of
|
|
|
|
* the time we only care if the number is bigger than 65,000 or not.
|
|
|
|
* So use the following translation function to return a 16-bit count.
|
|
|
|
*/
|
|
|
|
#define icount_16_xlate(x) (((x) > 65500) ? 65500 : (x))
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
void ext2fs_free_icount(ext2_icount_t icount)
|
|
|
|
{
|
|
|
|
if (!icount)
|
|
|
|
return;
|
|
|
|
|
|
|
|
icount->magic = 0;
|
|
|
|
if (icount->list)
|
2003-08-01 17:41:07 +04:00
|
|
|
ext2fs_free_mem(&icount->list);
|
1997-04-29 20:17:09 +04:00
|
|
|
if (icount->single)
|
|
|
|
ext2fs_free_inode_bitmap(icount->single);
|
|
|
|
if (icount->multiple)
|
|
|
|
ext2fs_free_inode_bitmap(icount->multiple);
|
2007-04-06 22:30:39 +04:00
|
|
|
if (icount->tdb)
|
|
|
|
tdb_close(icount->tdb);
|
|
|
|
if (icount->tdb_fn) {
|
|
|
|
unlink(icount->tdb_fn);
|
|
|
|
free(icount->tdb_fn);
|
|
|
|
}
|
|
|
|
|
2003-08-01 17:41:07 +04:00
|
|
|
ext2fs_free_mem(&icount);
|
1997-04-29 20:17:09 +04:00
|
|
|
}
|
|
|
|
|
2007-04-06 22:30:39 +04:00
|
|
|
static errcode_t alloc_icount(ext2_filsys fs, int flags, ext2_icount_t *ret)
|
1997-04-29 20:17:09 +04:00
|
|
|
{
|
|
|
|
ext2_icount_t icount;
|
|
|
|
errcode_t retval;
|
|
|
|
|
2007-04-06 22:30:39 +04:00
|
|
|
*ret = 0;
|
|
|
|
|
2003-08-01 17:41:07 +04:00
|
|
|
retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount);
|
1997-10-26 06:41:24 +03:00
|
|
|
if (retval)
|
|
|
|
return retval;
|
1997-04-29 20:17:09 +04:00
|
|
|
memset(icount, 0, sizeof(struct ext2_icount));
|
|
|
|
|
2011-12-17 02:31:07 +04:00
|
|
|
retval = ext2fs_allocate_inode_bitmap(fs, "icount", &icount->single);
|
1997-04-29 20:17:09 +04:00
|
|
|
if (retval)
|
|
|
|
goto errout;
|
|
|
|
|
|
|
|
if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
|
2011-12-17 02:31:07 +04:00
|
|
|
retval = ext2fs_allocate_inode_bitmap(fs, "icount_inc",
|
1997-04-29 20:17:09 +04:00
|
|
|
&icount->multiple);
|
|
|
|
if (retval)
|
|
|
|
goto errout;
|
|
|
|
} else
|
|
|
|
icount->multiple = 0;
|
|
|
|
|
2007-04-06 22:30:39 +04:00
|
|
|
icount->magic = EXT2_ET_MAGIC_ICOUNT;
|
|
|
|
icount->num_inodes = fs->super->s_inodes_count;
|
|
|
|
|
|
|
|
*ret = icount;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
errout:
|
|
|
|
ext2fs_free_icount(icount);
|
|
|
|
return(retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct uuid {
|
|
|
|
__u32 time_low;
|
|
|
|
__u16 time_mid;
|
|
|
|
__u16 time_hi_and_version;
|
|
|
|
__u16 clock_seq;
|
|
|
|
__u8 node[6];
|
|
|
|
};
|
|
|
|
|
|
|
|
static void unpack_uuid(void *in, struct uuid *uu)
|
|
|
|
{
|
|
|
|
__u8 *ptr = in;
|
|
|
|
__u32 tmp;
|
|
|
|
|
|
|
|
tmp = *ptr++;
|
|
|
|
tmp = (tmp << 8) | *ptr++;
|
|
|
|
tmp = (tmp << 8) | *ptr++;
|
|
|
|
tmp = (tmp << 8) | *ptr++;
|
|
|
|
uu->time_low = tmp;
|
|
|
|
|
|
|
|
tmp = *ptr++;
|
|
|
|
tmp = (tmp << 8) | *ptr++;
|
|
|
|
uu->time_mid = tmp;
|
|
|
|
|
|
|
|
tmp = *ptr++;
|
|
|
|
tmp = (tmp << 8) | *ptr++;
|
|
|
|
uu->time_hi_and_version = tmp;
|
|
|
|
|
|
|
|
tmp = *ptr++;
|
|
|
|
tmp = (tmp << 8) | *ptr++;
|
|
|
|
uu->clock_seq = tmp;
|
|
|
|
|
|
|
|
memcpy(uu->node, ptr, 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void uuid_unparse(void *uu, char *out)
|
|
|
|
{
|
|
|
|
struct uuid uuid;
|
|
|
|
|
|
|
|
unpack_uuid(uu, &uuid);
|
|
|
|
sprintf(out,
|
|
|
|
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
|
|
|
uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
|
|
|
|
uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
|
|
|
|
uuid.node[0], uuid.node[1], uuid.node[2],
|
|
|
|
uuid.node[3], uuid.node[4], uuid.node[5]);
|
|
|
|
}
|
|
|
|
|
|
|
|
errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir,
|
|
|
|
int flags, ext2_icount_t *ret)
|
|
|
|
{
|
|
|
|
ext2_icount_t icount;
|
|
|
|
errcode_t retval;
|
|
|
|
char *fn, uuid[40];
|
2011-11-29 20:24:52 +04:00
|
|
|
ext2_ino_t num_inodes;
|
2014-01-10 00:18:44 +04:00
|
|
|
mode_t save_umask;
|
2007-04-06 22:30:39 +04:00
|
|
|
int fd;
|
|
|
|
|
|
|
|
retval = alloc_icount(fs, flags, &icount);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
|
|
|
|
|
|
|
retval = ext2fs_get_mem(strlen(tdb_dir) + 64, &fn);
|
|
|
|
if (retval)
|
|
|
|
goto errout;
|
|
|
|
uuid_unparse(fs->super->s_uuid, uuid);
|
|
|
|
sprintf(fn, "%s/%s-icount-XXXXXX", tdb_dir, uuid);
|
2014-01-10 00:18:44 +04:00
|
|
|
save_umask = umask(077);
|
2007-04-06 22:30:39 +04:00
|
|
|
fd = mkstemp(fn);
|
2014-01-07 18:05:03 +04:00
|
|
|
if (fd < 0) {
|
|
|
|
retval = errno;
|
2014-03-14 17:43:11 +04:00
|
|
|
ext2fs_free_mem(&fn);
|
2014-01-07 18:05:03 +04:00
|
|
|
goto errout;
|
|
|
|
}
|
2014-03-14 17:43:11 +04:00
|
|
|
icount->tdb_fn = fn;
|
2014-01-10 00:18:44 +04:00
|
|
|
umask(save_umask);
|
2011-11-29 20:24:52 +04:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
|
|
|
icount->tdb = tdb_open(fn, num_inodes, TDB_NOLOCK | TDB_NOSYNC,
|
2007-04-06 22:30:39 +04:00
|
|
|
O_RDWR | O_CREAT | O_TRUNC, 0600);
|
|
|
|
close(fd);
|
2014-01-07 18:05:03 +04:00
|
|
|
if (icount->tdb == NULL) {
|
|
|
|
retval = errno;
|
|
|
|
goto errout;
|
|
|
|
}
|
|
|
|
*ret = icount;
|
|
|
|
return 0;
|
2007-04-06 22:30:39 +04:00
|
|
|
errout:
|
|
|
|
ext2fs_free_icount(icount);
|
|
|
|
return(retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size,
|
|
|
|
ext2_icount_t hint, ext2_icount_t *ret)
|
|
|
|
{
|
|
|
|
ext2_icount_t icount;
|
|
|
|
errcode_t retval;
|
|
|
|
size_t bytes;
|
|
|
|
ext2_ino_t i;
|
|
|
|
|
|
|
|
if (hint) {
|
|
|
|
EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT);
|
|
|
|
if (hint->size > size)
|
|
|
|
size = (size_t) hint->size;
|
|
|
|
}
|
|
|
|
|
|
|
|
retval = alloc_icount(fs, flags, &icount);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
if (size) {
|
|
|
|
icount->size = size;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Figure out how many special case inode counts we will
|
|
|
|
* have. We know we will need one for each directory;
|
|
|
|
* we also need to reserve some extra room for file links
|
|
|
|
*/
|
|
|
|
retval = ext2fs_get_num_dirs(fs, &icount->size);
|
|
|
|
if (retval)
|
|
|
|
goto errout;
|
|
|
|
icount->size += fs->super->s_inodes_count / 50;
|
|
|
|
}
|
2007-04-06 22:30:39 +04:00
|
|
|
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el));
|
1997-04-29 20:17:09 +04:00
|
|
|
#if 0
|
2006-09-12 22:56:15 +04:00
|
|
|
printf("Icount allocated %u entries, %d bytes.\n",
|
1997-04-29 20:17:09 +04:00
|
|
|
icount->size, bytes);
|
|
|
|
#endif
|
2007-11-10 03:01:06 +03:00
|
|
|
retval = ext2fs_get_array(icount->size, sizeof(struct ext2_icount_el),
|
|
|
|
&icount->list);
|
1997-10-26 06:41:24 +03:00
|
|
|
if (retval)
|
1997-04-29 20:17:09 +04:00
|
|
|
goto errout;
|
|
|
|
memset(icount->list, 0, bytes);
|
|
|
|
|
|
|
|
icount->count = 0;
|
|
|
|
icount->cursor = 0;
|
|
|
|
|
1997-04-29 21:48:10 +04:00
|
|
|
/*
|
|
|
|
* Populate the sorted list with those entries which were
|
|
|
|
* found in the hint icount (since those are ones which will
|
|
|
|
* likely need to be in the sorted list this time around).
|
|
|
|
*/
|
|
|
|
if (hint) {
|
|
|
|
for (i=0; i < hint->count; i++)
|
|
|
|
icount->list[i].ino = hint->list[i].ino;
|
|
|
|
icount->count = hint->count;
|
|
|
|
}
|
1997-04-29 20:17:09 +04:00
|
|
|
|
1997-04-29 21:48:10 +04:00
|
|
|
*ret = icount;
|
1997-04-29 20:17:09 +04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
errout:
|
|
|
|
ext2fs_free_icount(icount);
|
|
|
|
return(retval);
|
|
|
|
}
|
|
|
|
|
2007-04-06 22:30:39 +04:00
|
|
|
errcode_t ext2fs_create_icount(ext2_filsys fs, int flags,
|
2003-12-07 09:28:50 +03:00
|
|
|
unsigned int size,
|
1997-04-29 21:48:10 +04:00
|
|
|
ext2_icount_t *ret)
|
1997-04-29 20:17:09 +04:00
|
|
|
{
|
1997-04-29 21:48:10 +04:00
|
|
|
return ext2fs_create_icount2(fs, flags, size, 0, ret);
|
1997-04-29 20:17:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-04-29 21:48:10 +04:00
|
|
|
* insert_icount_el() --- Insert a new entry into the sorted list at a
|
|
|
|
* specified position.
|
1997-04-29 20:17:09 +04:00
|
|
|
*/
|
1997-04-29 21:48:10 +04:00
|
|
|
static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
ext2_ino_t ino, int pos)
|
1997-04-29 20:17:09 +04:00
|
|
|
{
|
1997-10-26 06:41:24 +03:00
|
|
|
struct ext2_icount_el *el;
|
|
|
|
errcode_t retval;
|
2007-04-06 22:30:39 +04:00
|
|
|
ext2_ino_t new_size = 0;
|
1997-04-29 21:48:10 +04:00
|
|
|
int num;
|
1997-04-29 20:17:09 +04:00
|
|
|
|
2007-04-06 22:30:39 +04:00
|
|
|
if (icount->last_lookup && icount->last_lookup->ino == ino)
|
|
|
|
return icount->last_lookup;
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
if (icount->count >= icount->size) {
|
|
|
|
if (icount->count) {
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
new_size = icount->list[(unsigned)icount->count-1].ino;
|
2007-04-06 22:30:39 +04:00
|
|
|
new_size = (ext2_ino_t) (icount->count *
|
2001-06-08 13:43:40 +04:00
|
|
|
((float) icount->num_inodes / new_size));
|
1997-04-29 20:17:09 +04:00
|
|
|
}
|
|
|
|
if (new_size < (icount->size + 100))
|
|
|
|
new_size = icount->size + 100;
|
|
|
|
#if 0
|
2006-09-12 22:56:15 +04:00
|
|
|
printf("Reallocating icount %u entries...\n", new_size);
|
2007-04-06 22:30:39 +04:00
|
|
|
#endif
|
1998-04-27 05:41:13 +04:00
|
|
|
retval = ext2fs_resize_mem((size_t) icount->size *
|
|
|
|
sizeof(struct ext2_icount_el),
|
|
|
|
(size_t) new_size *
|
1997-10-26 06:41:24 +03:00
|
|
|
sizeof(struct ext2_icount_el),
|
2003-08-01 17:41:07 +04:00
|
|
|
&icount->list);
|
1997-10-26 06:41:24 +03:00
|
|
|
if (retval)
|
1997-04-29 20:17:09 +04:00
|
|
|
return 0;
|
|
|
|
icount->size = new_size;
|
|
|
|
}
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
num = (int) icount->count - pos;
|
1997-04-29 21:48:10 +04:00
|
|
|
if (num < 0)
|
|
|
|
return 0; /* should never happen */
|
|
|
|
if (num) {
|
|
|
|
memmove(&icount->list[pos+1], &icount->list[pos],
|
|
|
|
sizeof(struct ext2_icount_el) * num);
|
|
|
|
}
|
|
|
|
icount->count++;
|
|
|
|
el = &icount->list[pos];
|
|
|
|
el->count = 0;
|
|
|
|
el->ino = ino;
|
2007-04-06 22:30:39 +04:00
|
|
|
icount->last_lookup = el;
|
1997-04-29 21:48:10 +04:00
|
|
|
return el;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* get_icount_el() --- given an inode number, try to find icount
|
|
|
|
* information in the sorted list. If the create flag is set,
|
|
|
|
* and we can't find an entry, create one in the sorted list.
|
|
|
|
*/
|
|
|
|
static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
ext2_ino_t ino, int create)
|
1997-04-29 21:48:10 +04:00
|
|
|
{
|
|
|
|
int low, high, mid;
|
|
|
|
|
|
|
|
if (!icount || !icount->list)
|
|
|
|
return 0;
|
1997-04-29 20:17:09 +04:00
|
|
|
|
1997-04-29 21:48:10 +04:00
|
|
|
if (create && ((icount->count == 0) ||
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
(ino > icount->list[(unsigned)icount->count-1].ino))) {
|
|
|
|
return insert_icount_el(icount, ino, (unsigned) icount->count);
|
1997-04-29 21:48:10 +04:00
|
|
|
}
|
|
|
|
if (icount->count == 0)
|
|
|
|
return 0;
|
2007-04-06 22:30:39 +04:00
|
|
|
|
1997-04-29 21:48:10 +04:00
|
|
|
if (icount->cursor >= icount->count)
|
|
|
|
icount->cursor = 0;
|
|
|
|
if (ino == icount->list[icount->cursor].ino)
|
|
|
|
return &icount->list[icount->cursor++];
|
|
|
|
#if 0
|
|
|
|
printf("Non-cursor get_icount_el: %u\n", ino);
|
|
|
|
#endif
|
|
|
|
low = 0;
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
high = (int) icount->count-1;
|
1997-04-29 21:48:10 +04:00
|
|
|
while (low <= high) {
|
2011-08-31 22:27:21 +04:00
|
|
|
mid = ((unsigned)low + (unsigned)high) >> 1;
|
1997-04-29 21:48:10 +04:00
|
|
|
if (ino == icount->list[mid].ino) {
|
|
|
|
icount->cursor = mid+1;
|
|
|
|
return &icount->list[mid];
|
|
|
|
}
|
|
|
|
if (ino < icount->list[mid].ino)
|
|
|
|
high = mid-1;
|
|
|
|
else
|
|
|
|
low = mid+1;
|
|
|
|
}
|
1997-04-29 20:17:09 +04:00
|
|
|
/*
|
1997-04-29 21:48:10 +04:00
|
|
|
* If we need to create a new entry, it should be right at
|
|
|
|
* low (where high will be left at low-1).
|
1997-04-29 20:17:09 +04:00
|
|
|
*/
|
1997-04-29 21:48:10 +04:00
|
|
|
if (create)
|
|
|
|
return insert_icount_el(icount, ino, low);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-04-06 22:30:39 +04:00
|
|
|
static errcode_t set_inode_count(ext2_icount_t icount, ext2_ino_t ino,
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
__u32 count)
|
2007-04-06 22:30:39 +04:00
|
|
|
{
|
|
|
|
struct ext2_icount_el *el;
|
|
|
|
TDB_DATA key, data;
|
|
|
|
|
|
|
|
if (icount->tdb) {
|
|
|
|
key.dptr = (unsigned char *) &ino;
|
|
|
|
key.dsize = sizeof(ext2_ino_t);
|
|
|
|
data.dptr = (unsigned char *) &count;
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
data.dsize = sizeof(__u32);
|
2007-04-06 22:30:39 +04:00
|
|
|
if (count) {
|
|
|
|
if (tdb_store(icount->tdb, key, data, TDB_REPLACE))
|
|
|
|
return tdb_error(icount->tdb) +
|
|
|
|
EXT2_ET_TDB_SUCCESS;
|
|
|
|
} else {
|
|
|
|
if (tdb_delete(icount->tdb, key))
|
|
|
|
return tdb_error(icount->tdb) +
|
|
|
|
EXT2_ET_TDB_SUCCESS;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
el = get_icount_el(icount, ino, 1);
|
|
|
|
if (!el)
|
|
|
|
return EXT2_ET_NO_MEMORY;
|
|
|
|
|
|
|
|
el->count = count;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static errcode_t get_inode_count(ext2_icount_t icount, ext2_ino_t ino,
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
__u32 *count)
|
2007-04-06 22:30:39 +04:00
|
|
|
{
|
|
|
|
struct ext2_icount_el *el;
|
|
|
|
TDB_DATA key, data;
|
|
|
|
|
|
|
|
if (icount->tdb) {
|
|
|
|
key.dptr = (unsigned char *) &ino;
|
|
|
|
key.dsize = sizeof(ext2_ino_t);
|
|
|
|
|
|
|
|
data = tdb_fetch(icount->tdb, key);
|
|
|
|
if (data.dptr == NULL) {
|
|
|
|
*count = 0;
|
|
|
|
return tdb_error(icount->tdb) + EXT2_ET_TDB_SUCCESS;
|
|
|
|
}
|
|
|
|
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
*count = *((__u32 *) data.dptr);
|
2007-04-07 07:28:30 +04:00
|
|
|
free(data.dptr);
|
2007-04-06 22:30:39 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
el = get_icount_el(icount, ino, 0);
|
|
|
|
if (!el) {
|
|
|
|
*count = 0;
|
|
|
|
return ENOENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
*count = el->count;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1997-04-29 21:48:10 +04:00
|
|
|
errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out)
|
|
|
|
{
|
|
|
|
errcode_t ret = 0;
|
2003-12-07 09:28:50 +03:00
|
|
|
unsigned int i;
|
1997-04-29 21:48:10 +04:00
|
|
|
const char *bad = "bad icount";
|
2007-04-06 22:30:39 +04:00
|
|
|
|
1997-04-29 21:48:10 +04:00
|
|
|
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
|
|
|
|
|
|
|
|
if (icount->count > icount->size) {
|
|
|
|
fprintf(out, "%s: count > size\n", bad);
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_INVALID_ARGUMENT;
|
1997-04-29 21:48:10 +04:00
|
|
|
}
|
|
|
|
for (i=1; i < icount->count; i++) {
|
|
|
|
if (icount->list[i-1].ino >= icount->list[i].ino) {
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n",
|
1997-04-29 21:48:10 +04:00
|
|
|
bad, i-1, icount->list[i-1].ino,
|
|
|
|
i, icount->list[i].ino);
|
1997-10-31 09:07:47 +03:00
|
|
|
ret = EXT2_ET_INVALID_ARGUMENT;
|
1997-04-29 20:17:09 +04:00
|
|
|
}
|
|
|
|
}
|
1997-04-29 21:48:10 +04:00
|
|
|
return ret;
|
1997-04-29 20:17:09 +04:00
|
|
|
}
|
|
|
|
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret)
|
1997-04-29 20:17:09 +04:00
|
|
|
{
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
__u32 val;
|
1997-04-29 20:17:09 +04:00
|
|
|
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
|
|
|
|
|
1997-04-29 21:48:10 +04:00
|
|
|
if (!ino || (ino > icount->num_inodes))
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_INVALID_ARGUMENT;
|
1997-04-29 21:48:10 +04:00
|
|
|
|
2009-08-05 08:27:10 +04:00
|
|
|
if (ext2fs_test_inode_bitmap2(icount->single, ino)) {
|
1997-04-29 20:17:09 +04:00
|
|
|
*ret = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
1997-04-29 21:48:10 +04:00
|
|
|
if (icount->multiple &&
|
2009-08-05 08:27:10 +04:00
|
|
|
!ext2fs_test_inode_bitmap2(icount->multiple, ino)) {
|
1997-04-29 21:48:10 +04:00
|
|
|
*ret = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
get_inode_count(icount, ino, &val);
|
|
|
|
*ret = icount_16_xlate(val);
|
1997-04-29 20:17:09 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino,
|
1997-04-29 20:17:09 +04:00
|
|
|
__u16 *ret)
|
|
|
|
{
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
__u32 curr_value;
|
1997-04-29 20:17:09 +04:00
|
|
|
|
|
|
|
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
|
|
|
|
|
1997-04-29 21:48:10 +04:00
|
|
|
if (!ino || (ino > icount->num_inodes))
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_INVALID_ARGUMENT;
|
1997-04-29 21:48:10 +04:00
|
|
|
|
2009-08-05 08:27:10 +04:00
|
|
|
if (ext2fs_test_inode_bitmap2(icount->single, ino)) {
|
1997-04-29 20:17:09 +04:00
|
|
|
/*
|
|
|
|
* If the existing count is 1, then we know there is
|
1997-04-29 21:48:10 +04:00
|
|
|
* no entry in the list.
|
1997-04-29 20:17:09 +04:00
|
|
|
*/
|
2007-04-06 22:30:39 +04:00
|
|
|
if (set_inode_count(icount, ino, 2))
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_NO_MEMORY;
|
2007-04-06 22:30:39 +04:00
|
|
|
curr_value = 2;
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_unmark_inode_bitmap2(icount->single, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
} else if (icount->multiple) {
|
|
|
|
/*
|
|
|
|
* The count is either zero or greater than 1; if the
|
|
|
|
* inode is set in icount->multiple, then there should
|
2007-04-06 22:30:39 +04:00
|
|
|
* be an entry in the list, so we need to fix it.
|
1997-04-29 20:17:09 +04:00
|
|
|
*/
|
2009-08-05 08:27:10 +04:00
|
|
|
if (ext2fs_test_inode_bitmap2(icount->multiple, ino)) {
|
2007-04-06 22:30:39 +04:00
|
|
|
get_inode_count(icount, ino, &curr_value);
|
|
|
|
curr_value++;
|
|
|
|
if (set_inode_count(icount, ino, curr_value))
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_NO_MEMORY;
|
1997-04-29 20:17:09 +04:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* The count was zero; mark the single bitmap
|
|
|
|
* and return.
|
|
|
|
*/
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_mark_inode_bitmap2(icount->single, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
if (ret)
|
|
|
|
*ret = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* The count is either zero or greater than 1; try to
|
|
|
|
* find an entry in the list to determine which.
|
|
|
|
*/
|
2007-04-06 22:30:39 +04:00
|
|
|
get_inode_count(icount, ino, &curr_value);
|
|
|
|
curr_value++;
|
|
|
|
if (set_inode_count(icount, ino, curr_value))
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_NO_MEMORY;
|
1997-04-29 21:48:10 +04:00
|
|
|
}
|
1997-04-29 20:17:09 +04:00
|
|
|
if (icount->multiple)
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_mark_inode_bitmap2(icount->multiple, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
if (ret)
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
*ret = icount_16_xlate(curr_value);
|
1997-04-29 20:17:09 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
|
1997-04-29 20:17:09 +04:00
|
|
|
__u16 *ret)
|
|
|
|
{
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
__u32 curr_value;
|
1997-04-29 20:17:09 +04:00
|
|
|
|
1997-04-29 21:48:10 +04:00
|
|
|
if (!ino || (ino > icount->num_inodes))
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_INVALID_ARGUMENT;
|
1997-04-29 21:48:10 +04:00
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
|
|
|
|
|
2009-08-05 08:27:10 +04:00
|
|
|
if (ext2fs_test_inode_bitmap2(icount->single, ino)) {
|
|
|
|
ext2fs_unmark_inode_bitmap2(icount->single, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
if (icount->multiple)
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_unmark_inode_bitmap2(icount->multiple, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
else {
|
2007-04-06 22:30:39 +04:00
|
|
|
set_inode_count(icount, ino, 0);
|
1997-04-29 20:17:09 +04:00
|
|
|
}
|
|
|
|
if (ret)
|
|
|
|
*ret = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1997-04-29 21:48:10 +04:00
|
|
|
if (icount->multiple &&
|
2009-08-05 08:27:10 +04:00
|
|
|
!ext2fs_test_inode_bitmap2(icount->multiple, ino))
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_INVALID_ARGUMENT;
|
2007-04-06 22:30:39 +04:00
|
|
|
|
|
|
|
get_inode_count(icount, ino, &curr_value);
|
|
|
|
if (!curr_value)
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_INVALID_ARGUMENT;
|
2007-04-06 22:30:39 +04:00
|
|
|
curr_value--;
|
|
|
|
if (set_inode_count(icount, ino, curr_value))
|
|
|
|
return EXT2_ET_NO_MEMORY;
|
1997-04-29 20:17:09 +04:00
|
|
|
|
2007-04-06 22:30:39 +04:00
|
|
|
if (curr_value == 1)
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_mark_inode_bitmap2(icount->single, ino);
|
2007-04-06 22:30:39 +04:00
|
|
|
if ((curr_value == 0) && icount->multiple)
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_unmark_inode_bitmap2(icount->multiple, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
|
|
|
|
if (ret)
|
libext2fs: Make icount use a 32-bit counter
In order to more accurately count the number of directories, which
with the DIR_NLINKS feature can now be greater than 65,000, change
icount to use a 32-bit counter. This doesn't cost us anything extra
when the icount data structures are stored in memory, since due to
padding for alignment reasons.
If the actual count is greater than 65,500, we return 65,500. This is
because e2fsck doesn't actually need to know the exact count; it only
needs to know if the number of subdirectories is greater than 65,000.
In the future if someone really needs to know the exact number, we
could add a 32-bit interface. One isn't needed now, though.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2008-03-13 20:37:29 +03:00
|
|
|
*ret = icount_16_xlate(curr_value);
|
1997-04-29 20:17:09 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
|
1997-04-29 20:17:09 +04:00
|
|
|
__u16 count)
|
|
|
|
{
|
1997-04-29 21:48:10 +04:00
|
|
|
if (!ino || (ino > icount->num_inodes))
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_INVALID_ARGUMENT;
|
1997-04-29 21:48:10 +04:00
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
|
|
|
|
|
|
|
|
if (count == 1) {
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_mark_inode_bitmap2(icount->single, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
if (icount->multiple)
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_unmark_inode_bitmap2(icount->multiple, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (count == 0) {
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_unmark_inode_bitmap2(icount->single, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
if (icount->multiple) {
|
|
|
|
/*
|
|
|
|
* If the icount->multiple bitmap is enabled,
|
|
|
|
* we can just clear both bitmaps and we're done
|
|
|
|
*/
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_unmark_inode_bitmap2(icount->multiple, ino);
|
2007-04-06 22:30:39 +04:00
|
|
|
} else
|
|
|
|
set_inode_count(icount, ino, 0);
|
1997-04-29 20:17:09 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-04-06 22:30:39 +04:00
|
|
|
if (set_inode_count(icount, ino, count))
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_NO_MEMORY;
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_unmark_inode_bitmap2(icount->single, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
if (icount->multiple)
|
2009-08-05 08:27:10 +04:00
|
|
|
ext2fs_mark_inode_bitmap2(icount->multiple, ino);
|
1997-04-29 20:17:09 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount)
|
1997-04-29 20:17:09 +04:00
|
|
|
{
|
|
|
|
if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return icount->size;
|
|
|
|
}
|
2007-04-06 16:52:49 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
ext2_filsys test_fs;
|
|
|
|
ext2_icount_t icount;
|
|
|
|
|
|
|
|
#define EXIT 0x00
|
|
|
|
#define FETCH 0x01
|
|
|
|
#define STORE 0x02
|
|
|
|
#define INCREMENT 0x03
|
|
|
|
#define DECREMENT 0x04
|
|
|
|
|
|
|
|
struct test_program {
|
|
|
|
int cmd;
|
|
|
|
ext2_ino_t ino;
|
|
|
|
__u16 arg;
|
|
|
|
__u16 expected;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct test_program prog[] = {
|
|
|
|
{ STORE, 42, 42, 42 },
|
|
|
|
{ STORE, 1, 1, 1 },
|
|
|
|
{ STORE, 2, 2, 2 },
|
|
|
|
{ STORE, 3, 3, 3 },
|
|
|
|
{ STORE, 10, 1, 1 },
|
|
|
|
{ STORE, 42, 0, 0 },
|
|
|
|
{ INCREMENT, 5, 0, 1 },
|
|
|
|
{ INCREMENT, 5, 0, 2 },
|
|
|
|
{ INCREMENT, 5, 0, 3 },
|
|
|
|
{ INCREMENT, 5, 0, 4 },
|
|
|
|
{ DECREMENT, 5, 0, 3 },
|
|
|
|
{ DECREMENT, 5, 0, 2 },
|
|
|
|
{ DECREMENT, 5, 0, 1 },
|
|
|
|
{ DECREMENT, 5, 0, 0 },
|
|
|
|
{ FETCH, 10, 0, 1 },
|
|
|
|
{ FETCH, 1, 0, 1 },
|
|
|
|
{ FETCH, 2, 0, 2 },
|
|
|
|
{ FETCH, 3, 0, 3 },
|
|
|
|
{ INCREMENT, 1, 0, 2 },
|
|
|
|
{ DECREMENT, 2, 0, 1 },
|
|
|
|
{ DECREMENT, 2, 0, 0 },
|
|
|
|
{ FETCH, 12, 0, 0 },
|
|
|
|
{ EXIT, 0, 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct test_program extended[] = {
|
|
|
|
{ STORE, 1, 1, 1 },
|
|
|
|
{ STORE, 2, 2, 2 },
|
|
|
|
{ STORE, 3, 3, 3 },
|
|
|
|
{ STORE, 4, 4, 4 },
|
|
|
|
{ STORE, 5, 5, 5 },
|
|
|
|
{ STORE, 6, 1, 1 },
|
|
|
|
{ STORE, 7, 2, 2 },
|
|
|
|
{ STORE, 8, 3, 3 },
|
|
|
|
{ STORE, 9, 4, 4 },
|
|
|
|
{ STORE, 10, 5, 5 },
|
|
|
|
{ STORE, 11, 1, 1 },
|
|
|
|
{ STORE, 12, 2, 2 },
|
|
|
|
{ STORE, 13, 3, 3 },
|
|
|
|
{ STORE, 14, 4, 4 },
|
|
|
|
{ STORE, 15, 5, 5 },
|
|
|
|
{ STORE, 16, 1, 1 },
|
|
|
|
{ STORE, 17, 2, 2 },
|
|
|
|
{ STORE, 18, 3, 3 },
|
|
|
|
{ STORE, 19, 4, 4 },
|
|
|
|
{ STORE, 20, 5, 5 },
|
|
|
|
{ STORE, 21, 1, 1 },
|
|
|
|
{ STORE, 22, 2, 2 },
|
|
|
|
{ STORE, 23, 3, 3 },
|
|
|
|
{ STORE, 24, 4, 4 },
|
|
|
|
{ STORE, 25, 5, 5 },
|
|
|
|
{ STORE, 26, 1, 1 },
|
|
|
|
{ STORE, 27, 2, 2 },
|
|
|
|
{ STORE, 28, 3, 3 },
|
|
|
|
{ STORE, 29, 4, 4 },
|
|
|
|
{ STORE, 30, 5, 5 },
|
|
|
|
{ EXIT, 0, 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup the variables for doing the inode scan test.
|
|
|
|
*/
|
|
|
|
static void setup(void)
|
|
|
|
{
|
|
|
|
errcode_t retval;
|
|
|
|
struct ext2_super_block param;
|
|
|
|
|
|
|
|
initialize_ext2_error_table();
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
2009-09-08 04:46:34 +04:00
|
|
|
ext2fs_blocks_count_set(¶m, 12000);
|
2007-04-06 16:52:49 +04:00
|
|
|
|
2009-08-05 08:27:10 +04:00
|
|
|
retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m,
|
2007-04-06 16:52:49 +04:00
|
|
|
test_io_manager, &test_fs);
|
|
|
|
if (retval) {
|
|
|
|
com_err("setup", retval,
|
|
|
|
"while initializing filesystem");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
retval = ext2fs_allocate_tables(test_fs);
|
|
|
|
if (retval) {
|
|
|
|
com_err("setup", retval,
|
|
|
|
"while allocating tables for test filesystem");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-06 22:30:39 +04:00
|
|
|
int run_test(int flags, int size, char *dir, struct test_program *prog)
|
2007-04-06 16:52:49 +04:00
|
|
|
{
|
|
|
|
errcode_t retval;
|
|
|
|
ext2_icount_t icount;
|
|
|
|
struct test_program *pc;
|
|
|
|
__u16 result;
|
|
|
|
int problem = 0;
|
|
|
|
|
2007-04-06 22:30:39 +04:00
|
|
|
if (dir) {
|
|
|
|
retval = ext2fs_create_icount_tdb(test_fs, dir,
|
|
|
|
flags, &icount);
|
|
|
|
if (retval) {
|
|
|
|
com_err("run_test", retval,
|
|
|
|
"while creating icount using tdb");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
retval = ext2fs_create_icount2(test_fs, flags, size, 0,
|
|
|
|
&icount);
|
|
|
|
if (retval) {
|
|
|
|
com_err("run_test", retval, "while creating icount");
|
|
|
|
exit(1);
|
|
|
|
}
|
2007-04-06 16:52:49 +04:00
|
|
|
}
|
|
|
|
for (pc = prog; pc->cmd != EXIT; pc++) {
|
|
|
|
switch (pc->cmd) {
|
|
|
|
case FETCH:
|
|
|
|
printf("icount_fetch(%u) = ", pc->ino);
|
|
|
|
break;
|
|
|
|
case STORE:
|
|
|
|
retval = ext2fs_icount_store(icount, pc->ino, pc->arg);
|
|
|
|
if (retval) {
|
|
|
|
com_err("run_test", retval,
|
|
|
|
"while calling icount_store");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
printf("icount_store(%u, %u) = ", pc->ino, pc->arg);
|
|
|
|
break;
|
|
|
|
case INCREMENT:
|
|
|
|
retval = ext2fs_icount_increment(icount, pc->ino, 0);
|
|
|
|
if (retval) {
|
|
|
|
com_err("run_test", retval,
|
|
|
|
"while calling icount_increment");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
printf("icount_increment(%u) = ", pc->ino);
|
|
|
|
break;
|
|
|
|
case DECREMENT:
|
|
|
|
retval = ext2fs_icount_decrement(icount, pc->ino, 0);
|
|
|
|
if (retval) {
|
|
|
|
com_err("run_test", retval,
|
|
|
|
"while calling icount_decrement");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
printf("icount_decrement(%u) = ", pc->ino);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
retval = ext2fs_icount_fetch(icount, pc->ino, &result);
|
|
|
|
if (retval) {
|
|
|
|
com_err("run_test", retval,
|
|
|
|
"while calling icount_fetch");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
printf("%u (%s)\n", result, (result == pc->expected) ?
|
|
|
|
"OK" : "NOT OK");
|
|
|
|
if (result != pc->expected)
|
|
|
|
problem++;
|
|
|
|
}
|
|
|
|
printf("icount size is %u\n", ext2fs_get_icount_size(icount));
|
|
|
|
retval = ext2fs_icount_validate(icount, stdout);
|
|
|
|
if (retval) {
|
|
|
|
com_err("run_test", retval, "while calling icount_validate");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
ext2fs_free_icount(icount);
|
|
|
|
return problem;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int failed = 0;
|
|
|
|
|
|
|
|
setup();
|
|
|
|
printf("Standard icount run:\n");
|
2007-04-06 22:30:39 +04:00
|
|
|
failed += run_test(0, 0, 0, prog);
|
2007-04-06 16:52:49 +04:00
|
|
|
printf("\nMultiple bitmap test:\n");
|
2007-04-06 22:30:39 +04:00
|
|
|
failed += run_test(EXT2_ICOUNT_OPT_INCREMENT, 0, 0, prog);
|
2007-04-06 16:52:49 +04:00
|
|
|
printf("\nResizing icount:\n");
|
2007-04-06 22:30:39 +04:00
|
|
|
failed += run_test(0, 3, 0, extended);
|
|
|
|
printf("\nStandard icount run with tdb:\n");
|
|
|
|
failed += run_test(0, 0, ".", prog);
|
|
|
|
printf("\nMultiple bitmap test with tdb:\n");
|
|
|
|
failed += run_test(EXT2_ICOUNT_OPT_INCREMENT, 0, ".", prog);
|
|
|
|
if (failed)
|
2007-04-06 16:52:49 +04:00
|
|
|
printf("FAILED!\n");
|
|
|
|
return failed;
|
|
|
|
}
|
|
|
|
#endif
|