Viewing: ext4-dirdata-lustre-compat.patch

Index: linux-stage/fs/ext4/ext4.h
===================================================================
--- linux-stage.orig/fs/ext4/ext4.h
+++ linux-stage/fs/ext4/ext4.h
@@ -1170,6 +1170,7 @@ struct ext4_inode_info {
 	__u32 i_csum_seed;
 
 	kprojid_t i_projid;
+	void *i_dirdata;
 };
 
 /*
@@ -2426,6 +2427,13 @@ struct ext4_dir_entry_tail {
 #define EXT4_DIRENT_INO64		0x20
 #define EXT4_DIRENT_CFHASH		0x40
 
+#define EXT4_LUFID_MAGIC    0xAD200907UL
+struct ext4_dentry_param {
+	__u32  edp_magic;	/* EXT4_LUFID_MAGIC */
+	char   edp_len;		/* size of edp_data in bytes */
+	char   edp_data[];	/* packed array of data */
+} __packed;
+
 struct ext4_dirent_data_header {
 	/* length of this header + the whole data blob */
 	__u8	ddh_length;
@@ -2436,6 +2444,17 @@ struct ext4_dirent_hash {
 	struct ext4_dir_entry_hash	dh_hash;
 } __packed;
 
+static inline unsigned char *ext4_dentry_get_data(struct super_block *sb,
+						  struct ext4_dentry_param *p)
+{
+	if (!ext4_has_feature_dirdata(sb))
+		return NULL;
+	if (p && p->edp_magic == EXT4_LUFID_MAGIC)
+		return &p->edp_len;
+	else
+		return NULL;
+}
+
 #define EXT4_FT_DIR_CSUM	0xDE
 
 /*
Index: linux-stage/fs/ext4/namei.c
===================================================================
--- linux-stage.orig/fs/ext4/namei.c
+++ linux-stage/fs/ext4/namei.c
@@ -2254,6 +2254,8 @@ static int add_dirent_to_buf(handle_t *h
 	if (ext4_has_metadata_csum(inode->i_sb))
 		csum_size = sizeof(struct ext4_dir_entry_tail);
 
+	data = ext4_dentry_get_data(inode->i_sb, (struct ext4_dentry_param *)
+						EXT4_I(inode)->i_dirdata);
 	if (!de) {
 		if (data)
 			dlen = (*data) + 1;
@@ -2626,7 +2628,8 @@ static int ext4_update_dotdot(handle_t *
 
 	dotdot_de->inode = cpu_to_le32(inode->i_ino);
 
-	/* Deliver data any appropriate way here. Now it is NULL */
+	data = ext4_dentry_get_data(dir->i_sb,
+			(struct ext4_dentry_param *)dentry->d_fsdata);
 	if (data != NULL) {
 		dlen = *data + 1;
 		if (is_dx(dir)) {
@@ -2686,6 +2689,7 @@ static int ext4_add_entry(handle_t *hand
 	ext4_lblk_t block, blocks;
 	int	csum_size = 0;
 
+	EXT4_I(inode)->i_dirdata = dentry->d_fsdata;
 	if (ext4_has_metadata_csum(inode->i_sb))
 		csum_size = sizeof(struct ext4_dir_entry_tail);
 
@@ -3268,20 +3272,50 @@ struct ext4_dir_entry_2 *ext4_init_dot_d
 			  int blocksize, int csum_size,
 			  unsigned int parent_ino, int dotdot_real_len)
 {
+	void *data1 = NULL, *data2 = NULL;
+	int dot_reclen = 0;
+
+	if (dotdot_real_len == 10) {
+		struct tmp_block *tmpb = (struct tmp_block *)inode;
+		data1 = tmpb->tmpb_data1;
+		data2 = tmpb->tmpb_data2;
+		inode = tmpb->tmpb_inode;
+		dotdot_real_len = 0;
+	}
+
 	de->inode = cpu_to_le32(inode->i_ino);
 	de->name_len = 1;
-	de->rec_len = ext4_rec_len_to_disk(ext4_dir_rec_len(de->name_len, NULL),
-					   blocksize);
 	strcpy(de->name, ".");
 	ext4_set_de_type(inode->i_sb, de, S_IFDIR);
 
+	/* get packed fid data*/
+	data1 = ext4_dentry_get_data(inode->i_sb,
+				(struct ext4_dentry_param *) data1);
+	if (data1) {
+		de->name[1] = 0;
+		memcpy(&de->name[2], data1, *(char *) data1);
+		de->file_type |= EXT4_DIRENT_LUFID;
+	}
+	de->rec_len = cpu_to_le16(ext4_dir_entry_len(de, NULL));
+
+	dot_reclen = cpu_to_le16(de->rec_len);
 	de = ext4_next_entry(de, blocksize);
 	de->inode = cpu_to_le32(parent_ino);
 	de->name_len = 2;
+
+	strcpy(de->name, "..");
+	ext4_set_de_type(inode->i_sb, de, S_IFDIR);
+	data2 = ext4_dentry_get_data(inode->i_sb,
+			(struct ext4_dentry_param *) data2);
+	if (data2) {
+		de->name[2] = 0;
+		memcpy(&de->name[3], data2, *(char *) data2);
+		de->file_type |= EXT4_DIRENT_LUFID;
+	}
+
 	if (!dotdot_real_len)
 		de->rec_len = ext4_rec_len_to_disk(blocksize -
-					(csum_size + ext4_dir_rec_len(1, NULL)),
-					blocksize);
+					(csum_size + dot_reclen), blocksize);
 	else
 		de->rec_len = ext4_rec_len_to_disk(
 					ext4_dir_entry_len(de, NULL),
@@ -3404,6 +3438,29 @@ out_retry:
 	return err;
 }
 
+/* Initialize @inode as a subdirectory of @dir, and add the
+ * "." and ".." entries into the first directory block. */
+int ext4_add_dot_dotdot(handle_t *handle, struct inode *dir,
+			struct inode *inode,
+			const void *data1, const void *data2)
+{
+	int rc;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	if (IS_DIRSYNC(dir))
+		ext4_handle_sync(handle);
+
+	inode->i_op = &ext4_dir_inode_operations;
+	inode->i_fop = &ext4_dir_operations;
+	rc = ext4_init_new_dir(handle, dir, inode, data1, data2);
+	if (!rc)
+		rc = ext4_mark_inode_dirty(handle, inode);
+	return rc;
+}
+EXPORT_SYMBOL(ext4_add_dot_dotdot);
+
 /*
  * routine to check that the specified directory is empty (for rmdir)
  */