---- ./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 @@
+#ifdef CONFIG_EXT3_INDEX
+ set_opt (*mount_options, INDEX);
+#else
-+ printk("EXT3 Index option not supported\n");
++ printk("EXT3 index option not supported\n");
+#endif
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,436 @@
+@@ -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,432 @@
#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,
++static struct buffer_head *ext3_append(handle_t *handle,
+ struct inode *inode,
+ u32 *block, int *err)
+{
+ struct buffer_head *bh;
++
+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
-+ if((bh = ext3_bread (handle,inode, *block, 1, err))) {
++
++ if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
+ inode->i_size += inode->i_sb->s_blocksize;
++ EXT3_I(inode)->i_disksize = inode->i_size;
+ ext3_journal_get_write_access(handle,bh);
+ }
+ return bh;
+}
+
+#ifndef assert
-+#define assert(test) do if (!(test)) BUG(); while (0)
++#define assert(test) J_ASSERT(test)
+#endif
+
+#ifndef swap
+
+struct dx_root
+{
-+ struct fake_dirent fake1;
-+ char dot1[4];
-+ struct fake_dirent fake2;
-+ char dot2[4];
++ struct fake_dirent dot;
++ char dot_name[4];
++ struct fake_dirent dotdot;
++ char dotdot_name[4];
+ struct dx_root_info
+ {
+ le_u32 reserved_zero;
+};
+
+typedef struct ext3_dir_entry_2 ext3_dirent;
-+/* dx_static exists purely to suppress compiler warnings */
+static inline unsigned dx_get_block (struct dx_entry *entry);
+static void dx_set_block (struct dx_entry *entry, unsigned value);
+static inline unsigned dx_get_hash (struct dx_entry *entry);
+
+static inline unsigned dx_get_block (struct dx_entry *entry)
+{
-+ return le32_to_cpu(entry->block.v) & 0x0fffffff;
++ return le32_to_cpu(entry->block.v) & 0x00ffffff;
+}
+
+static inline void dx_set_block (struct dx_entry *entry, unsigned value)
+
+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
+{
-+ unsigned entry_space = dir->i_sb->s_blocksize - 24 - infosize;
++ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) -
++ EXT3_DIR_REC_LEN(2) - infosize;
+ return 0? 20: entry_space / sizeof(struct dx_entry);
+}
+
+static inline unsigned dx_node_limit (struct inode *dir)
+{
-+ unsigned entry_space = dir->i_sb->s_blocksize - sizeof(struct fake_dirent);
++ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0);
+ return 0? 22: entry_space / sizeof(struct dx_entry);
+}
+
+ hash1 = hash0;
+ hash0 = hash;
+ }
-+ return 80; /* FIXME: for test only */
+ return hash0;
+}
+
+ 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
+ */
+
-+static struct dx_frame *dx_probe (struct inode *dir, u32 hash, struct dx_frame *frame)
++static struct dx_frame *
++dx_probe(struct inode *dir, u32 hash, struct dx_frame *frame_in)
+{
+ unsigned count, indirect;
+ struct dx_entry *at, *entries, *p, *q, *m;
+ struct dx_root *root;
+ struct buffer_head *bh;
++ struct dx_frame *frame = frame_in;
+ int err;
-+ if (!(bh = ext3_bread (NULL,dir, 0, 0,&err)))
++
++ frame->bh = NULL;
++ if (!(bh = ext3_bread(NULL, dir, 0, 0, &err)))
+ goto fail;
+ root = (struct dx_root *) bh->b_data;
-+ if (root->info.hash_version > 0 || root->info.unused_flags & 1)
++ if (root->info.hash_version > 0 || root->info.unused_flags & 1) {
++ brelse(bh);
+ goto fail;
-+ if ((indirect = root->info.indirect_levels) > 1)
++ }
++ if ((indirect = root->info.indirect_levels) > 1) {
++ brelse(bh);
+ goto fail;
++ }
+ entries = (struct dx_entry *) (((char *) &root->info) + root->info.info_length);
+ assert (dx_get_limit(entries) == dx_root_limit(dir, root->info.info_length));
+ dxtrace (printk("Look up %x", hash));
+ frame++;
+ }
+fail2:
-+ brelse(frame->bh);
++ while (frame >= frame_in) {
++ brelse(frame->bh);
++ frame--;
++ }
+fail:
+ return NULL;
+}
+
+static void dx_release (struct dx_frame *frames)
+{
-+ if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
++ if (frames[0].bh == NULL)
++ return;
++
++ if (((struct dx_root *)frames[0].bh->b_data)->info.indirect_levels)
+ brelse (frames[1].bh);
+ brelse (frames[0].bh);
+}
+ } while(more);
+}
+
-+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block)
++static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
+{
-+ struct dx_entry *entries = frame->entries, *at = frame->at;
-+ assert (dx_get_count (entries) < dx_get_limit (entries));
-+ memmove (at + 2, at+1, (char *) (entries + dx_get_count(entries)) - (char *) (at));
-+ dx_set_hash(at + 1, hash);
-+ dx_set_block(at + 1, block);
-+ dx_set_count(entries, dx_get_count(entries) + 1);
++ struct dx_entry *entries = frame->entries;
++ struct dx_entry *old = frame->at, *new = old + 1;
++ int count = dx_get_count(entries);
++
++ assert(count < dx_get_limit(entries));
++ assert(old < entries + count);
++ memmove(new + 1, new, (char *)(entries + count) - (char *)(new));
++ dx_set_hash(new, hash);
++ dx_set_block(new, block);
++ dx_set_count(entries, count + 1);
+}
+#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.
*
+ block = dx_get_block(frame->at);
+ if (!(bh = ext3_bread (NULL,dir, block, 0, &err)))
+ goto dxfail;
-+ de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ top = (struct ext3_dir_entry_2 *) ((char *) de + blocksize
-+ - EXT3_DIR_REC_LEN(0));
++ de = (ext3_dirent *) bh->b_data;
++ top = (ext3_dirent *) ((char *) de + blocksize -
++ EXT3_DIR_REC_LEN(0));
+ for (; de < top; de = ext3_next_entry(de))
+ if (ext3_match (namelen, name, de)) {
+ if (!ext3_check_dir_entry("ext3_find_entry",
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);
+ de = (ext3_dirent *) ((char *) de - data3 + data1); // relocate de
+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
-+ dxtrace_on(dx_show_leaf ((ext3_dirent *) data1, blocksize, 1));
-+ dxtrace_on(dx_show_leaf ((ext3_dirent *) data2, blocksize, 1));
++ dxtrace(dx_show_leaf ((ext3_dirent *) data1, blocksize, 1));
++ dxtrace(dx_show_leaf ((ext3_dirent *) data2, blocksize, 1));
+
+ /* Which block gets the new entry? */
+ if (hash >= hash2)
+ ext3_journal_dirty_metadata (handle, bh2);
+ brelse (bh2);
+ ext3_journal_dirty_metadata (handle, frame->bh);
-+ dxtrace_on(dx_show_index ("frame", frame->entries));
++ 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,284 @@
+@@ -258,117 +852,281 @@
const char *name = dentry->d_name.name;
int namelen = dentry->d_name.len;
unsigned long offset;
- unsigned short rec_len;
struct buffer_head * bh;
- struct ext3_dir_entry_2 * de, * de1;
+- struct ext3_dir_entry_2 * de, * de1;
- struct super_block * sb;
++ ext3_dirent *de;
+ struct super_block * sb = dir->i_sb;
int retval;
+ unsigned short reclen = EXT3_DIR_REC_LEN(namelen);
- sb = dir->i_sb;
+ unsigned blocksize = sb->s_blocksize;
+ unsigned nlen, rlen;
-+ u32 block;
++ u32 block, blocks;
+ char *top;
if (!namelen)
- if (dir->i_size == 0) {
- brelse(bh);
- return -ENOENT;
-+ if (ext3_dx && is_dx(dir))
-+ {
++ if (ext3_dx && is_dx(dir)) {
+ struct dx_frame frames[2], *frame;
+ struct dx_entry *entries, *at;
+ u32 hash;
+ char *data1;
+
-+ hash = dx_hash (name, namelen);
-+ frame = dx_probe (dir, hash, frames); // do something if null
++ hash = dx_hash(name, namelen);
++ /* FIXME: do something if dx_probe() fails here */
++ frame = dx_probe(dir, hash, frames);
+ entries = frame->entries;
+ at = frame->at;
+
-+ if (!(bh = ext3_bread (handle,dir, dx_get_block(frame->at), 0,&retval)))
++ if (!(bh = ext3_bread(handle,dir, dx_get_block(at), 0,&retval)))
+ goto dxfail1;
+
+ BUFFER_TRACE(bh, "get_write_access");
+ de = (ext3_dirent *) ((char *) de + rlen);
+ }
+ /* Block full, should compress but for now just split */
-+ dxtrace_on(printk("using %u of %u node entries\n",
++ dxtrace(printk("using %u of %u node entries\n",
+ dx_get_count(entries), dx_get_limit(entries)));
+ /* Need to split index? */
+ if (dx_get_count(entries) == dx_get_limit(entries))
+ {
+ u32 newblock;
+ unsigned icount = dx_get_count(entries);
-+ char *idata2;
+ int levels = frame - frames;
+ struct dx_entry *entries2;
++ struct dx_node *node2;
+ struct buffer_head *bh2;
+ if (levels && dx_get_count(frames->entries) == dx_get_limit(frames->entries))
+ goto dxfull;
+ bh2 = ext3_append (handle, dir, &newblock, &retval);
+ if (!(bh2))
+ goto dxfail2;
-+ idata2 = bh2->b_data;
-+ entries2 = ((struct dx_node *) idata2)->entries;
-+ ((struct dx_node *) idata2)->fake.rec_len = cpu_to_le16(blocksize);
-+ /* fake.inode already 0 */
-+ /* Seems that is not true. We still need to set inode = 0 -Chrisl*/
-+ ((struct dx_node *) idata2)->fake.inode = 0;
++ node2 = (struct dx_node *)(bh2->b_data);
++ entries2 = node2->entries;
++ node2->fake.rec_len = cpu_to_le16(blocksize);
++ node2->fake.inode = 0;
+ BUFFER_TRACE(frame->bh, "get_write_access");
+ ext3_journal_get_write_access(handle, frame->bh);
+ if (levels)
+ {
+ unsigned icount1 = icount/2, icount2 = icount - icount1;
+ unsigned hash2 = dx_get_hash(entries + icount1);
-+ dxtrace_on(printk("Split index %i/%i\n", icount1, icount2));
++ dxtrace(printk("Split index %i/%i\n", icount1, icount2));
+
+ BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
+ ext3_journal_get_write_access(handle, frames[0].bh);
+ dx_set_limit (entries2, dx_node_limit(dir));
+
+ /* Which index block gets the new entry? */
-+ if (at - entries > icount1) {
++ if (at - entries >= icount1) {
+ frame->at = at = at - entries - icount1 + entries2;
+ frame->entries = entries = entries2;
+ swap(frame->bh, bh2);
- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
- ext3_mark_inode_dirty(handle, dir);
+ dx_insert_block (frames + 0, hash2, newblock);
-+ dxtrace_on(dx_show_index ("node", frames[1].entries));
-+ dxtrace_on(dx_show_index ("node",
++ dxtrace(dx_show_index ("node", frames[1].entries));
++ dxtrace(dx_show_index ("node",
+ ((struct dx_node *) bh2->b_data)->entries));
+ ext3_journal_dirty_metadata(handle, bh2);
+ brelse (bh2);
- ext3_debug ("skipping to next block\n");
-
- de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ dxtrace_on(printk("Creating second level index...\n"));
++ dxtrace(printk("Creating second level index...\n"));
+ memcpy((char *) entries2, (char *) entries,
+ icount * sizeof(struct dx_entry));
+ dx_set_limit(entries2, dx_node_limit(dir));
+ goto add;
+
+dxfull:
-+ dxtrace_on(printk("Directory index full!\n"));
++ ext3_warning(sb, __FUNCTION__, "Directory index full!\n");
+ retval = -ENOSPC;
+dxfail2:
+ brelse(bh);
+ dx_release (frames);
+ goto fail1;
+ }
-+ block = offset = 0;
-+ while (offset < dir->i_size) {
-+ bh = ext3_bread (handle, dir, block, 0, &retval);
++
++ blocks = dir->i_size >> sb->s_blocksize_bits;
++ for (block = 0, offset = 0; block < blocks; block++) {
++ bh = ext3_bread(handle, dir, block, 0, &retval);
+ if(!bh)
-+ return retval;
-+ de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ top = bh->b_data+blocksize-reclen;
++ return retval;
++ de = (ext3_dirent *)bh->b_data;
++ top = bh->b_data + blocksize - reclen;
+ while ((char *) de <= top) {
-+
-+ if (!ext3_check_dir_entry ("ext3_add_entry", dir, de,
-+ bh,offset)) {
++ if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
++ bh, offset)) {
+ brelse (bh);
-+ return -ENOENT;
++ return -EIO;
+ }
+ if (ext3_match (namelen, name, de)) {
brelse (bh);
- */
- 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);
+ rlen = le16_to_cpu(de->rec_len);
+ if ((de->inode? rlen - nlen: rlen) >= reclen)
+ goto add;
-+ de = (struct ext3_dir_entry_2 *) ((char *) de + rlen);
++ de = (ext3_dirent *)((char *)de + rlen);
+ offset += rlen;
+ }
-+ if (ext3_dx && dir->i_size==blocksize && test_opt(sb, INDEX))
++ if (ext3_dx && blocks == 1 && test_opt(sb, INDEX))
+ goto dx_make_index;
+ brelse(bh);
+ }
+ bh = ext3_append(handle, dir, &block, &retval);
+ if (!bh)
+ return retval;
-+ de = (struct ext3_dir_entry_2 *) bh->b_data;
++ de = (ext3_dirent *) bh->b_data;
+ de->inode = 0;
+ de->rec_len = cpu_to_le16(rlen = blocksize);
+ nlen = 0;
+ ext3_journal_get_write_access(handle, bh);
+ /* By now the buffer is marked for journaling */
+ if (de->inode) {
-+ de1 = (struct ext3_dir_entry_2 *) ((char *) de + nlen);
++ ext3_dirent *de1 = (ext3_dirent *)((char *)de + nlen);
+ de1->rec_len = cpu_to_le16(rlen - nlen);
+ de->rec_len = cpu_to_le16(nlen);
+ de = de1;
+ * and/or different from the directory change time.
+ */
+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-+ /* dir->u.ext3_i.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);
+ struct dx_root *root;
+ struct dx_frame frames[2], *frame;
+ struct dx_entry *entries;
-+ struct ext3_dir_entry_2 *de2;
++ ext3_dirent *de2;
+ char *data1;
+ unsigned len;
+ u32 hash;
+
-+ dxtrace_on(printk("Creating index\n"));
++ dxtrace(printk("Creating index\n"));
+ ext3_journal_get_write_access(handle, bh);
+ root = (struct dx_root *) bh->b_data;
+
-+ ext3_add_compat_feature (sb, EXT3_FEATURE_COMPAT_DIR_INDEX);
-+ dir->u.ext3_i.i_flags |= EXT3_INDEX_FL;
++ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
+ bh2 = ext3_append (handle, dir, &block, &retval);
+ if (!(bh2))
+ {
+ de = de2;
+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+ /* Initialize the root; the dot dirents already exist */
-+ de = (ext3_dirent *) (&root->fake2);
++ de = (ext3_dirent *) (&root->dotdot);
+ de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
+ memset (&root->info, 0, sizeof(root->info));
+ root->info.info_length = sizeof(root->info);
- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS+3);
++ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
if (IS_ERR(handle))
return PTR_ERR(handle);
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;
-+ // dir->u.ext3_i.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;
-+ // dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
++ ext3_update_dx_flag(dir);
ext3_mark_inode_dirty(handle, dir);
inode->i_nlink--;
if (!inode->i_nlink)
- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2);
+ handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS+ 2);
++ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
if (IS_ERR(handle))
return PTR_ERR(handle);
}
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
- old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ // old_dir->u.ext3_i.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;
-+ // new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
++ ext3_update_dx_flag(new_dir);
ext3_mark_inode_dirty(handle, new_dir);
}
}
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef _LINUX_EXT2_FS_H
-@@ -575,6 +576,26 @@
+@@ -575,6 +576,24 @@
#define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1)
#define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \
~EXT3_DIR_ROUND)
+
+#ifdef CONFIG_EXT3_INDEX
+ enum {ext3_dx = 1};
-+ #define dx_static static
-+ #define is_dx(dir) ((dir)->u.ext3_i.i_flags & EXT3_INDEX_FL)
++ #define is_dx(dir) (EXT3_I(dir)->i_flags & EXT3_INDEX_FL)
+#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX)
+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
+#else
+ enum {ext3_dx = 0};
-+ #define dx_static
+ #define is_dx(dir) 0
+#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX)
+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)