+++ /dev/null
-Index: linux-2.6.10/fs/ext3/dir.c
-===================================================================
---- linux-2.6.10.orig/fs/ext3/dir.c 2004-12-25 05:34:57.000000000 +0800
-+++ linux-2.6.10/fs/ext3/dir.c 2005-03-31 18:56:02.961946200 +0800
-@@ -53,6 +53,9 @@
-
- static unsigned char get_dtype(struct super_block *sb, int filetype)
- {
-+ if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM) && filetype == 128)
-+ return 128;
-+
- if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) ||
- (filetype >= EXT3_FT_MAX))
- return DT_UNKNOWN;
-@@ -79,7 +82,8 @@
- error_msg = "directory entry across blocks";
- else if (le32_to_cpu(de->inode) >
- le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
-- error_msg = "inode out of bounds";
-+ if (de->file_type != 128)
-+ error_msg = "inode out of bounds";
-
- if (error_msg != NULL)
- ext3_error (dir->i_sb, function,
-Index: linux-2.6.10/fs/ext3/namei.c
-===================================================================
---- linux-2.6.10.orig/fs/ext3/namei.c 2005-03-31 18:41:15.880803032 +0800
-+++ linux-2.6.10/fs/ext3/namei.c 2005-03-31 18:56:02.960946352 +0800
-@@ -24,6 +24,7 @@
- * Theodore Ts'o, 2002
- */
-
-+#include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/pagemap.h>
- #include <linux/jbd.h>
-@@ -1148,6 +1149,23 @@
- inode = NULL;
- if (bh) {
- unsigned long ino = le32_to_cpu(de->inode);
-+ unsigned type = de->file_type;
-+ __u32 *mds;
-+ mds = (__u32 *)((char *) de + EXT3_DIR_REC_LEN(de->name_len));
-+ if ((type & 128) && EXT3_HAS_INCOMPAT_FEATURE(dir->i_sb,
-+ EXT3_FEATURE_INCOMPAT_MDSNUM) &&
-+ mds[0] != EXT3_SB(dir->i_sb)->s_mdsnum) {
-+ struct ext3_super_block *es;
-+ es = EXT3_SB(dir->i_sb)->s_es;
-+ brelse (bh);
-+ dentry->d_flags |= DCACHE_CROSS_REF;
-+ dentry->d_generation = mds[1];
-+ dentry->d_mdsnum = mds[0];
-+ dentry->d_inum = ino;
-+ ext3_unlock_htree(dir, lock);
-+ d_add(dentry, NULL);
-+ return NULL;
-+ }
- ext3_unlock_htree(dir, lock);
- brelse (bh);
- inode = iget(dir->i_sb, ino);
-@@ -1221,7 +1239,7 @@
- while (count--) {
- struct ext3_dir_entry_2 *de =
- (struct ext3_dir_entry_2 *) (from + map->offs);
-- rec_len = EXT3_DIR_REC_LEN(de->name_len);
-+ rec_len = EXT3_DIR_REC_LEN_DE(de);
- memcpy (to, de, rec_len);
- ((struct ext3_dir_entry_2 *) to)->rec_len =
- cpu_to_le16(rec_len);
-@@ -1243,7 +1261,7 @@
- next = (struct ext3_dir_entry_2 *) ((char *) de +
- le16_to_cpu(de->rec_len));
- if (de->inode && de->name_len) {
-- rec_len = EXT3_DIR_REC_LEN(de->name_len);
-+ rec_len = EXT3_DIR_REC_LEN_DE(de);
- if (de > to)
- memmove(to, de, rec_len);
- to->rec_len = cpu_to_le16(rec_len);
-@@ -1359,6 +1377,7 @@
- struct buffer_head * bh)
- {
- struct inode *dir = dentry->d_parent->d_inode;
-+ struct super_block *sb = dir->i_sb;
- const char *name = dentry->d_name.name;
- int namelen = dentry->d_name.len;
- unsigned long offset = 0;
-@@ -1367,6 +1386,10 @@
- char *top;
-
- reclen = EXT3_DIR_REC_LEN(namelen);
-+ if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM)
-+ && (dentry->d_flags & DCACHE_CROSS_REF)
-+ && (dentry->d_mdsnum != EXT3_SB(sb)->s_mdsnum))
-+ reclen += 8; /* we need space to store mds num */
- if (!de) {
- de = (struct ext3_dir_entry_2 *)bh->b_data;
- top = bh->b_data + dir->i_sb->s_blocksize - reclen;
-@@ -1380,7 +1403,7 @@
- brelse (bh);
- return -EEXIST;
- }
-- nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ nlen = EXT3_DIR_REC_LEN_DE(de);
- rlen = le16_to_cpu(de->rec_len);
- if ((de->inode? rlen - nlen: rlen) >= reclen)
- break;
-@@ -1399,7 +1422,7 @@
- }
-
- /* By now the buffer is marked for journaling */
-- nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ nlen = EXT3_DIR_REC_LEN_DE(de);
- rlen = le16_to_cpu(de->rec_len);
- if (de->inode) {
- struct ext3_dir_entry_2 *de1 =
-@@ -1411,8 +1434,20 @@
- de->file_type = EXT3_FT_UNKNOWN;
- if (inode) {
- de->inode = cpu_to_le32(inode->i_ino);
-- ext3_set_de_type(dir->i_sb, de, inode->i_mode);
-- } else
-+ ext3_set_de_type(sb, de, inode->i_mode);
-+ } else if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM)
-+ && (dentry->d_flags & DCACHE_CROSS_REF)) {
-+ if (dentry->d_mdsnum != EXT3_SB(sb)->s_mdsnum) {
-+ __u32 *mds;
-+ mds = (__u32 *)((char *)de + EXT3_DIR_REC_LEN(namelen));
-+ mds[0] = cpu_to_le32(dentry->d_mdsnum);
-+ mds[1] = cpu_to_le32(dentry->d_generation);
-+ de->inode = cpu_to_le32(dentry->d_inum);
-+ de->file_type = 128;
-+ } else {
-+ de->inode = cpu_to_le32(dentry->d_inum);
-+ }
-+ } else
- de->inode = 0;
- de->name_len = namelen;
- memcpy (de->name, name, namelen);
-@@ -2737,6 +2772,81 @@
- }
-
- /*
-+ * caller has to make sure directory is protected
-+ */
-+int ext3_add_dir_entry(struct dentry *dentry)
-+{
-+ struct inode *dir = dentry->d_parent->d_inode;
-+ handle_t *handle;
-+ int err;
-+
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS);
-+ if (IS_ERR(handle)) {
-+ return PTR_ERR(handle);
-+ }
-+
-+ if (IS_SYNC(dir))
-+ handle->h_sync = 1;
-+
-+ err = ext3_add_entry(handle, dentry, NULL);
-+ ext3_journal_stop(handle);
-+ return err;
-+}
-+EXPORT_SYMBOL(ext3_add_dir_entry);
-+/*
-+ * caller has to make sure directory is protected
-+ */
-+int ext3_del_dir_entry(struct dentry *dentry)
-+{
-+ struct inode * inode;
-+ struct inode * dir = dentry->d_parent->d_inode;
-+ struct buffer_head * bh;
-+ struct ext3_dir_entry_2 * de;
-+ handle_t *handle;
-+ int retval;
-+ void *lock = NULL;
-+
-+ handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
-+ if (IS_ERR(handle)) {
-+ return PTR_ERR(handle);
-+ }
-+
-+ if (IS_SYNC(dir))
-+ handle->h_sync = 1;
-+
-+ retval = -ENOENT;
-+ bh = ext3_find_entry (dentry, &de, 1, &lock);
-+ ext3_unlock_htree(dir, lock);
-+ if (!bh)
-+ goto end_unlink;
-+
-+ inode = dentry->d_inode;
-+ if (inode)
-+ DQUOT_INIT(inode);
-+
-+ retval = ext3_delete_entry(handle, dir, de, bh);
-+ if (retval)
-+ goto end_unlink;
-+ dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-+ ext3_update_dx_flag(dir);
-+ if (inode) {
-+ inode->i_ctime = dir->i_ctime;
-+ ext3_mark_inode_dirty(handle, inode);
-+ if (S_ISDIR(inode->i_mode))
-+ dir->i_nlink--;
-+ }
-+ ext3_mark_inode_dirty(handle, dir);
-+ retval = 0;
-+
-+end_unlink:
-+ ext3_journal_stop(handle);
-+ brelse (bh);
-+ return retval;
-+}
-+
-+EXPORT_SYMBOL(ext3_del_dir_entry);
-+/*
- * directories can handle most operations...
- */
- struct inode_operations ext3_dir_inode_operations = {
-Index: linux-2.6.10/include/linux/ext3_fs.h
-===================================================================
---- linux-2.6.10.orig/include/linux/ext3_fs.h 2005-03-31 18:54:32.497698856 +0800
-+++ linux-2.6.10/include/linux/ext3_fs.h 2005-03-31 18:56:41.955018352 +0800
-@@ -483,7 +483,8 @@
- __u16 s_reserved_word_pad;
- __le32 s_default_mount_opts;
- __le32 s_first_meta_bg; /* First metablock block group */
-- __u32 s_reserved[190]; /* Padding to the end of the block */
-+ __u32 s_mdsnum;
-+ __u32 s_reserved[189]; /* Padding to the end of the block */
- };
-
- #ifdef __KERNEL__
-@@ -563,12 +564,14 @@
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
- #define EXT3_FEATURE_INCOMPAT_META_BG 0x0010
-+#define EXT3_FEATURE_INCOMPAT_MDSNUM 0x0020 /* direntry has mdsnum */
- #define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
-
- #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
- EXT3_FEATURE_INCOMPAT_RECOVER| \
- EXT3_FEATURE_INCOMPAT_META_BG| \
-+ EXT3_FEATURE_INCOMPAT_MDSNUM| \
- EXT3_FEATURE_INCOMPAT_EXTENTS)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
-@@ -643,6 +646,9 @@
- #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1)
- #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \
- ~EXT3_DIR_ROUND)
-+#define EXT3_DIR_REC_LEN_DE(de) (EXT3_DIR_REC_LEN((de)->name_len) + \
-+ (((de)->file_type & 128) ? 8 : 0))
-+
- /*
- * Hash Tree Directory indexing
- * (c) Daniel Phillips, 2001
-@@ -868,6 +874,9 @@
- extern void ext3_ext_release(struct super_block *);
- extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *);
-
-+extern int ext3_add_dir_entry(struct dentry *dentry);
-+
-+extern int ext3_del_dir_entry(struct dentry *dentry);
- #endif /* __KERNEL__ */
-
- #define EXT3_IOC_CREATE_INUM _IOW('f', 5, long)
-Index: linux-2.6.10/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.6.10.orig/include/linux/ext3_fs_sb.h 2005-03-31 18:44:21.076648984 +0800
-+++ linux-2.6.10/include/linux/ext3_fs_sb.h 2005-03-31 18:56:02.964945744 +0800
-@@ -81,6 +81,7 @@
- char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */
- int s_jquota_fmt; /* Format of quota to use */
- #endif
-+ u32 s_mdsnum;
- };
-
- #endif /* _LINUX_EXT3_FS_SB */