+++ /dev/null
-Index: linux-2.4.24/fs/ext3/namei.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/namei.c 2004-09-23 13:10:48.181661672 +0400
-+++ linux-2.4.24/fs/ext3/namei.c 2004-09-23 13:10:48.274647536 +0400
-@@ -1099,6 +1099,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;
-+ ext3_unlock_htree(dir, lock);
-+ brelse (bh);
-+ dentry->d_flags |= DCACHE_CROSS_REF;
-+ dentry->d_generation = mds[1];
-+ dentry->d_mdsnum = mds[0];
-+ dentry->d_inum = ino;
-+ d_add(dentry, NULL);
-+ return NULL;
-+ }
- ext3_unlock_htree(dir, lock);
- brelse (bh);
- inode = iget(dir->i_sb, ino);
-@@ -1138,7 +1155,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);
- de->inode = 0;
-@@ -1159,7 +1176,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);
-@@ -1275,6 +1292,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;
-@@ -1283,6 +1301,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;
-@@ -1296,7 +1318,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;
-@@ -1315,7 +1337,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 =
-@@ -1327,8 +1349,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);
-@@ -2662,6 +2696,79 @@
- }
-
- /*
-+ * 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, dir);
-+ return err;
-+}
-+
-+/*
-+ * 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;
-+ void *lock;
-+ int retval;
-+
-+ 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);
-+ if (!bh)
-+ goto end_unlink;
-+
-+ inode = dentry->d_inode;
-+ if (inode)
-+ DQUOT_INIT(inode);
-+
-+ retval = ext3_delete_entry(handle, dir, de, bh);
-+ ext3_unlock_htree(dir, lock);
-+ 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, dir);
-+ brelse (bh);
-+ return retval;
-+}
-+/*
- * directories can handle most operations...
- */
- struct inode_operations ext3_dir_inode_operations = {
-Index: linux-2.4.24/fs/ext3/dir.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/dir.c 2004-09-23 13:10:45.649046688 +0400
-+++ linux-2.4.24/fs/ext3/dir.c 2004-09-23 13:10:48.275647384 +0400
-@@ -42,6 +42,9 @@
-
- static unsigned char get_dtype(struct super_block *sb, int filetype)
- {
-+ if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM))
-+ return DT_UNKNOWN;
-+
- if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) ||
- (filetype >= EXT3_FT_MAX))
- return DT_UNKNOWN;
-@@ -67,8 +70,10 @@
- else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
- error_msg = "directory entry across blocks";
- else if (le32_to_cpu(de->inode) >
-- le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count))
-- error_msg = "inode out of bounds";
-+ le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count)) {
-+ if (de->file_type != 128)
-+ error_msg = "inode out of bounds";
-+ }
-
- if (error_msg != NULL)
- ext3_error (dir->i_sb, function,
-Index: linux-2.4.24/fs/ext3/ext3-exports.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/ext3-exports.c 2004-09-23 13:10:46.365937704 +0400
-+++ linux-2.4.24/fs/ext3/ext3-exports.c 2004-09-23 13:10:48.275647384 +0400
-@@ -26,3 +26,10 @@
- EXPORT_SYMBOL(ext3_decode_error);
- EXPORT_SYMBOL(__ext3_std_error);
-
-+int ext3_add_dir_entry (struct dentry *dentry);
-+EXPORT_SYMBOL(ext3_add_dir_entry);
-+int ext3_del_dir_entry(struct dentry *dentry);
-+EXPORT_SYMBOL(ext3_del_dir_entry);
-+
-+
-+
-Index: linux-2.4.24/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-09-23 13:10:48.188660608 +0400
-+++ linux-2.4.24/include/linux/ext3_fs.h 2004-09-23 13:17:40.703948752 +0400
-@@ -446,7 +446,8 @@
- __u8 s_def_hash_version; /* Default hash version to use */
- __u8 s_reserved_char_pad;
- __u16 s_reserved_word_pad;
-- __u32 s_reserved[192]; /* Padding to the end of the block */
-+ __u32 s_mdsnum;
-+ __u32 s_reserved[191]; /* Padding to the end of the block */
- };
-
- #ifdef __KERNEL__
-@@ -519,11 +520,13 @@
- #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-+#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_MDSNUM| \
- EXT3_FEATURE_INCOMPAT_EXTENTS)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
-@@ -585,6 +588,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
-Index: linux-2.4.24/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs_sb.h 2004-09-23 13:10:46.069982696 +0400
-+++ linux-2.4.24/include/linux/ext3_fs_sb.h 2004-09-23 13:11:21.026668472 +0400
-@@ -86,6 +86,7 @@
- wait_queue_head_t s_delete_thread_queue;
- wait_queue_head_t s_delete_waiter_queue;
- #endif
-+ u32 s_mdsnum;
- };
-
- #endif /* _LINUX_EXT3_FS_SB */
-Index: linux-2.4.24/include/linux/dcache.h
-===================================================================
---- linux-2.4.24.orig/include/linux/dcache.h 2004-09-23 13:10:46.153969928 +0400
-+++ linux-2.4.24/include/linux/dcache.h 2004-09-23 13:11:06.451884176 +0400
-@@ -120,6 +120,9 @@
- atomic_t d_count;
- unsigned int d_flags;
- struct inode * d_inode; /* Where the name belongs to - NULL is negative */
-+ unsigned d_inum; /* for cross-fs references (Lustre) */
-+ unsigned d_mdsnum; /* for cross-fs references (Lustre) */
-+ unsigned d_generation; /* for cross-fs references (Lustre) */
- struct dentry * d_parent; /* parent directory */
- struct list_head d_hash; /* lookup hash list */
- struct list_head d_lru; /* d_count = 0 LRU list */
-@@ -193,6 +196,7 @@
- */
- #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
- #define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */
-+#define DCACHE_CROSS_REF 0x0020 /* entry points to inode on another MDS */
-
- extern spinlock_t dcache_lock;
-