---- ./fs/ext3/dir.c 2002/03/05 06:18:59 2.1
-+++ ./fs/ext3/dir.c 2002/03/05 06:26:56
-@@ -26,7 +26,7 @@
- DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
- };
-
--static int ext3_readdir(struct file *, void *, filldir_t);
-+int ext3_readdir(struct file *, void *, filldir_t);
-
- struct file_operations ext3_dir_operations = {
- read: generic_read_dir,
-@@ -65,7 +65,7 @@
- return error_msg == NULL ? 1 : 0;
- }
-
--static int ext3_readdir(struct file * filp,
-+int ext3_readdir(struct file * filp,
- void * dirent, filldir_t filldir)
- {
- int error = 0;
--- ./fs/ext3/super.c 2002/03/05 06:18:59 2.1
+++ ./fs/ext3/super.c 2002/03/05 06:26:56
@@ -529,6 +529,12 @@
else if (!strcmp (this_char, "debug"))
set_opt (*mount_options, DEBUG);
else if (!strcmp (this_char, "errors")) {
-@@ -712,6 +718,10 @@
- EXT3_BLOCKS_PER_GROUP(sb),
- EXT3_INODES_PER_GROUP(sb),
- sbi->s_mount_opt);
-+
-+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
+@@ -702,6 +708,12 @@ static int ext3_setup_super(struct super
+ es->s_mtime = cpu_to_le32(CURRENT_TIME);
+ ext3_update_dynamic_rev(sb);
+ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
++
++ if (test_opt(sb, INDEX))
++ EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX);
++ else if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
+ set_opt (EXT3_SB(sb)->s_mount_opt, INDEX);
+
- printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ",
- bdevname(sb->s_dev));
- if (EXT3_SB(sb)->s_journal->j_inode == NULL) {
+ ext3_commit_super (sb, es, 1);
+ if (test_opt (sb, DEBUG))
+ printk (KERN_INFO
--- ./fs/ext3/namei.c 2002/03/05 06:18:59 2.1
+++ ./fs/ext3/namei.c 2002/03/06 00:13:18
@@ -16,6 +16,10 @@
*/
#include <linux/fs.h>
-@@ -38,6 +42,456 @@
+@@ -33,7 +33,7 @@
+ #include <linux/string.h>
+ #include <linux/locks.h>
+ #include <linux/quotaops.h>
+-
++#include <linux/slab.h>
+
+ /*
+ * define how far ahead to read directories while searching them.
+@@ -38,6 +42,433 @@
#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
-+void ext3_add_compat_feature (struct super_block *sb, unsigned feature)
-+{
-+ if (!EXT3_HAS_COMPAT_FEATURE(sb, feature))
-+ {
-+ lock_super(sb);
-+ ext3_update_dynamic_rev(sb);
-+ EXT3_SET_COMPAT_FEATURE(sb, feature);
-+ ext3_write_super(sb);
-+ unlock_super(sb);
-+ }
-+}
-+
+static struct buffer_head *ext3_append(handle_t *handle,
+ struct inode *inode,
+ u32 *block, int *err)
+ return (struct stats) { names, space, bcount};
+}
+
-+static void dx_show_buckets (struct inode *dir)
-+{
-+ struct buffer_head *bh;
-+ struct dx_root *root;
-+ int err;
-+ if (!(bh = ext3_bread (NULL,dir, 0, 0,&err))) return;
-+ root = (struct dx_root *) bh->b_data;
-+ dx_show_entries (dir, root->entries, root->info.indirect_levels);
-+ brelse (bh);
-+}
-+
-+ssize_t hack_show_dir (struct file * filp, void * dirent, filldir_t filldir)
-+{
-+ if (is_dx (filp->f_dentry->d_inode) && !filp->f_pos)
-+ dx_show_buckets (filp->f_dentry->d_inode);
-+ return ext3_readdir(filp,dirent,filldir);
-+}
-+
+/*
+ * Probe for a directory leaf block to search
+ */
+{
+ int count = 0;
+ char *base = (char *) de;
-+ while ((char *) de < base + size)
-+ {
-+ map[count].hash = dx_hash (de->name, de->name_len);
-+ map[count].offs = (u32) ((char *) de - base);
++ while ((char *) de < base + size) {
++ if (de->name_len && de->inode) {
++ map[count].hash = dx_hash (de->name, de->name_len);
++ map[count].offs = (u32) ((char *) de - base);
++ count++;
++ }
+ de = (ext3_dirent *) ((char *) de + le16_to_cpu(de->rec_len));
-+ count++;
+ }
+ return count;
+}
+}
+#endif
+
++static void ext3_update_dx_flag(struct inode *inode)
++{
++ if (!test_opt(inode->i_sb, INDEX))
++ EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL;
++}
++
/*
* NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure.
*
nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
start = dir->u.ext3_i.i_dir_start_lookup;
if (start >= nblocks)
-@@ -237,6 +748,88 @@
+@@ -237,6 +748,92 @@
de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
}
+ u32 newblock;
+ unsigned MAX_DX_MAP = PAGE_CACHE_SIZE/EXT3_DIR_REC_LEN(1) + 1;
+ u32 hash2;
-+ struct dx_map_entry map[MAX_DX_MAP];
++ struct dx_map_entry *map;
+ char *data1 = (*bh)->b_data, *data2, *data3;
+ unsigned split;
+ ext3_dirent *de, *de2;
+
+ data2 = bh2->b_data;
+
++ map = kmalloc(sizeof(*map) * MAX_DX_MAP, GFP_KERNEL);
++ if (!map)
++ panic("no memory for do_split\n");
+ count = dx_make_map ((ext3_dirent *) data1, blocksize, map);
+ split = count/2; // need to adjust to actual middle
+ dx_sort_map (map, count);
+ brelse (bh2);
+ ext3_journal_dirty_metadata (handle, frame->bh);
+ dxtrace(dx_show_index ("frame", frame->entries));
++ kfree(map);
+ return de;
+}
+#endif
static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
struct inode *inode)
{
-@@ -258,117 +852,282 @@
+@@ -258,117 +852,281 @@
const char *name = dentry->d_name.name;
int namelen = dentry->d_name.len;
unsigned long offset;
- */
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-- ext3_mark_inode_dirty(handle, dir);
- dir->i_version = ++event;
+- ext3_mark_inode_dirty(handle, dir);
- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, bh);
+ nlen = EXT3_DIR_REC_LEN(de->name_len);
+ * and/or different from the directory change time.
+ */
+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-+ /* EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL; */
-+ ext3_mark_inode_dirty(handle, dir);
++ ext3_update_dx_flag(dir);
+ dir->i_version = ++event;
++ ext3_mark_inode_dirty(handle, dir);
+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ ext3_journal_dirty_metadata(handle, bh);
+ brelse(bh);
+ ext3_journal_get_write_access(handle, bh);
+ root = (struct dx_root *) bh->b_data;
+
-+ ext3_add_compat_feature (sb, EXT3_FEATURE_COMPAT_DIR_INDEX);
+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
+ bh2 = ext3_append (handle, dir, &block, &retval);
+ if (!(bh2))
if (IS_ERR(handle))
return PTR_ERR(handle);
+@@ -550,7 +1320,7 @@
+ if (err)
+ goto out_no_entry;
+ dir->i_nlink++;
+- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
++ ext3_update_dx_flag(dir);
+ ext3_mark_inode_dirty(handle, dir);
+ d_instantiate(dentry, inode);
+ out_stop:
@@ -832,7 +1596,7 @@
ext3_mark_inode_dirty(handle, inode);
dir->i_nlink--;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ // EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL;
++ ext3_update_dx_flag(dir);
ext3_mark_inode_dirty(handle, dir);
end_rmdir:
goto end_unlink;
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ // EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL;
++ ext3_update_dx_flag(dir);
ext3_mark_inode_dirty(handle, dir);
inode->i_nlink--;
if (!inode->i_nlink)
}
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
- old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ // EXT3_I(old_dir)->i_flags &= ~EXT3_INDEX_FL;
++ ext3_update_dx_flag(old_dir);
if (dir_bh) {
BUFFER_TRACE(dir_bh, "get_write_access");
ext3_journal_get_write_access(handle, dir_bh);
} else {
new_dir->i_nlink++;
- new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ // EXT3_I(new_dir)->i_flags &= ~EXT3_INDEX_FL;
++ ext3_update_dx_flag(new_dir);
ext3_mark_inode_dirty(handle, new_dir);
}
}