Skip to contentSkip to conversation

Separated 64-bit i_version patch

PATCH In review Kalpak Shah 3 participants 13 messages Jun 14, 2007 1 message not in the archive

Subsystems (3)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): 1181835073.7779.9.camel@garfield

#1 lore raw

PATCH 1/6 Separated 64-bit i_version patch

64-bit-i_version.patch which only replaces the 32-bit i_version field in the generic inode with a 64-bit i_version field.

---
 fs.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

P.S. The VFS-level updates of the inode version are still in the i_version_update_vfs.patch and this patch has been moved to the bottom of the patch series.

This patch converts the 32-bit i_version in the generic inode to a 64-bit i_version field.

include/linux/fs.h +1 -1
Index: linux-2.6.21/include/linux/fs.h
===================================================================
@@ -549,7 +549,7 @@ struct inode {
 	uid_t			i_uid;
 	gid_t			i_gid;
 	dev_t			i_rdev;
-	unsigned long		i_version;
+	uint64_t		i_version;
 	loff_t			i_size;
 #ifdef __NEED_I_SIZE_ORDERED
 	seqcount_t		i_size_seqcount;
#2 lore raw
Quoted 14 lines · Kalpak Shah

This patch converts the 32-bit i_version in the generic inode to a 64- bit
i_version field.

Index: linux-2.6.21/include/linux/fs.h
===================================================================

include/linux/fs.h struct inode { · line 555

Quoted 8 lines
include/linux/fs.h +1 -1
@@ -549,7 +549,7 @@ struct inode {
        uid_t                   i_uid;
        gid_t                   i_gid;
        dev_t                   i_rdev;
-       unsigned long           i_version;
+       uint64_t                i_version;
        loff_t                  i_size;
 #ifdef __NEED_I_SIZE_ORDERED
        seqcount_t              i_size_seqcount;

I think u64 is better here. It seems uint64_t is not defined in some cases and rarely being used.

Mingming

#3 lore raw
Quoted 7 lines · Mingming Cao
Quoted 6 lines · Kalpak Shah

This patch converts the 32-bit i_version in the generic inode to a 64- bit i_version field.

Quoted 15 lines

include/linux/fs.h struct inode { · line 555

Quoted 11 lines
include/linux/fs.h +1 -1
@@ -549,7 +549,7 @@ struct inode {
        uid_t                   i_uid;
        gid_t                   i_gid;
        dev_t                   i_rdev;
-       unsigned long           i_version;
+       uint64_t                i_version;
        loff_t                  i_size;
 #ifdef __NEED_I_SIZE_ORDERED
        seqcount_t              i_size_seqcount;

I think u64 is better here. It seems uint64_t is not defined in some cases and rarely being used.

Agreed.

Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.

#4 lore raw

PATCH 2/6 add i_version_hi to ext4_inode

In reply to a message not in the archive

There were whitespace problems in i_version_hi.patch. I am attaching the corrected patch.

---
 ext4_fs.h |    1 +
 1 file changed, 1 insertion(+)

This patch adds a 32-bit i_version_hi field to ext4_inode, which can be used for 64-bit inode versions. This field will store the higher 32 bits of the version, while Jean Noel's patch has added support to store the lower 32-bits in osd1.linux1.l_i_version.

---

include/linux/ext4_fs.h +1 -0
Index: linux-2.6.21/include/linux/ext4_fs.h
===================================================================
@@ -342,6 +342,7 @@ struct ext4_inode {
 	__le32  i_atime_extra;  /* extra Access time      (nsec << 2 | epoch) */
 	__le32  i_crtime;       /* File Creation time */
 	__le32  i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
+	__le32	i_version_hi;	/* high 32 bits for 64-bit version */
 };
 
 #define i_size_high	i_dir_acl
#5 lore raw

PATCH 3/6 Changes for 64-bit i_version

In reply to a message not in the archive

ext4_i_version_hi_2.patch was still using ei->i_fs_version instead of inode->i_version. I have corrected it.

---
fs/ext4/inode.c | 15 ++++++++++++++-

 include/linux/ext4_fs.h |    4 +++-
 2 files changed, 17 insertions(+), 2 deletions(-)

This patch adds 64-bit inode version support to ext4. The lower 32 bits are stored in the osd1.linux1.l_i_version field while the high 32 bits are stored in the i_version_hi field newly created in the ext4_inode.

fs/ext4/inode.c +14 -1
Index: linux-2.6.21/fs/ext4/inode.c
===================================================================
@@ -2709,6 +2709,13 @@ void ext4_read_inode(struct inode * inod
 	EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode);
 	EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode);
 
+	inode->i_version = le32_to_cpu(raw_inode->i_disk_version);
+	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
+		if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
+			inode->i_version |=
+			(__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32;
+	}
+
 	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ext4_file_inode_operations;
 		inode->i_fop = &ext4_file_operations;
@@ -2852,8 +2859,14 @@ static int ext4_do_update_inode(handle_t
 	} else for (block = 0; block < EXT4_N_BLOCKS; block++)
 		raw_inode->i_block[block] = ei->i_data[block];
 
-	if (ei->i_extra_isize)
+	raw_inode->i_disk_version = cpu_to_le32(inode->i_version);
+	if (ei->i_extra_isize) {
+		if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi)) {
+			raw_inode->i_version_hi =
+				cpu_to_le32(inode->i_version >> 32);
+		}
 		raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
+	}
 
 	BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata");
 	rc = ext4_journal_dirty_metadata(handle, bh);
include/linux/ext4_fs.h +3 -1
Index: linux-2.6.21/include/linux/ext4_fs.h
===================================================================
@@ -297,7 +297,7 @@ struct ext4_inode {
 	__le32	i_flags;	/* File flags */
 	union {
 		struct {
-			__u32  l_i_reserved1;
+			__u32  l_i_version;
 		} linux1;
 		struct {
 			__u32  h_i_translator;
@@ -406,6 +406,8 @@ do {									       \
 				       raw_inode->xtime ## _extra);	       \
 } while (0)
 
+#define i_disk_version osd1.linux1.l_i_version
+
 #if defined(__KERNEL__) || defined(__linux__)
 #define i_reserved1	osd1.linux1.l_i_reserved1
 #define i_frag		osd2.linux2.l_i_frag
#6 lore raw

PATCH 4/6 add noversion mount option

In reply to a message not in the archive

This patch adds a "noversion" mount option to disable inode version updates.

---
 fs/ext4/inode.c         |    4 +++-
 fs/ext4/super.c         |    6 +++++-
 include/linux/ext4_fs.h |    1 +
 3 files changed, 9 insertions(+), 2 deletions(-)

Add a "noversion" mount option to disable inode version updates.

fs/ext4/super.c +5 -1
Index: linux-2.6.21/fs/ext4/super.c
===================================================================
@@ -725,7 +725,7 @@ enum {
 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
 	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
-	Opt_grpquota, Opt_extents, Opt_noextents,
+	Opt_grpquota, Opt_extents, Opt_noextents, Opt_noversion,
 };
 
 static match_table_t tokens = {
@@ -777,6 +777,7 @@ static match_table_t tokens = {
 	{Opt_barrier, "barrier=%u"},
 	{Opt_extents, "extents"},
 	{Opt_noextents, "noextents"},
+	{Opt_noversion, "noversion"},
 	{Opt_err, NULL},
 	{Opt_resize, "resize"},
 };
@@ -1115,6 +1116,9 @@ clear_qf_name:
 		case Opt_noextents:
 			clear_opt (sbi->s_mount_opt, EXTENTS);
 			break;
+		case Opt_noversion:
+			set_opt(sbi->s_mount_opt, NOVERSION);
+			break;
 		default:
 			printk (KERN_ERR
 				"EXT4-fs: Unrecognized mount option \"%s\" "
include/linux/ext4_fs.h +1 -0
Index: linux-2.6.21/include/linux/ext4_fs.h
===================================================================
@@ -473,6 +473,7 @@ do {									       \
 #define EXT4_MOUNT_USRQUOTA		0x100000 /* "old" user quota */
 #define EXT4_MOUNT_GRPQUOTA		0x200000 /* "old" group quota */
 #define EXT4_MOUNT_EXTENTS		0x400000 /* Extents support */
+#define EXT4_MOUNT_NOVERSION		0x800000 /* No inode version updates */
 
 /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
 #ifndef _LINUX_EXT2_FS_H
fs/ext4/inode.c +3 -1
Index: linux-2.6.21/fs/ext4/inode.c
===================================================================
@@ -3082,7 +3082,9 @@ int ext4_mark_iloc_dirty(handle_t *handl
 {
 	int err = 0;
 
-	inode->i_version++;
+	if (!test_opt(inode->i_sb, NOVERSION))
+		inode->i_version++;
+
 	/* the do_update_inode consumes one bh->b_count */
 	get_bh(iloc->bh);
 
#7 lore raw

Re: [PATCH 4/6] add noversion mount option

Quoted 2 lines · Kalpak Shah

This patch adds a "noversion" mount option to disable inode version updates.

Can you explain a bit more why we need this mount option? Is it because of performance concern?

Mingming

#8 lore raw

Re: [PATCH 4/6] add noversion mount option

Quoted 6 lines · Mingming Cao
Quoted 2 lines · Kalpak Shah

This patch adds a "noversion" mount option to disable inode version updates.

Can you explain a bit more why we need this mount option? Is it because of performance concern?

This is the "disable i_version updates for Lustre" option we previously agreed on in the concall.

Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.

#9 lore raw

Re: [PATCH 4/6] add noversion mount option

In reply to Mingming Cao
Quoted 6 lines · Mingming Cao
Quoted 2 lines · Kalpak Shah

This patch adds a "noversion" mount option to disable inode version updates.

Can you explain a bit more why we need this mount option? Is it because of performance concern?

Lustre requires the counter to be globally unique on the entire filesystem and hence needs to turnoff per-inode version updates. So in the interlock meeting on 5th June, Ted has suggested the this approach.

"- Ted suggested having a flag in the superblock for i_version, with an additional option of having a global counter for Lustre's requirements. i_version would be on by default, but give users who do not use the feature the option to turn it off and avoid any performance impact."

Thanks,
Kalpak.

Quoted 7 lines

Mingming

-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#10 lore raw

Re: [PATCH 4/6] add noversion mount option

Quoted 8 lines · Kalpak Shah
Quoted 6 lines · Mingming Cao
Quoted 2 lines · Kalpak Shah

This patch adds a "noversion" mount option to disable inode version updates.

Can you explain a bit more why we need this mount option? Is it because of performance concern?

Quoted 9 lines

Lustre requires the counter to be globally unique on the entire filesystem and hence needs to turnoff per-inode version updates. So in the interlock meeting on 5th June, Ted has suggested the this approach.

"- Ted suggested having a flag in the superblock for i_version, with an additional option of having a global counter for Lustre's requirements. i_version would be on by default, but give users who do not use the feature the option to turn it off and avoid any performance impact."

Right. Somehow my impression is that we have agreed to do this through tune2fs. I was just double checking if the mount option is for the Lustre use. Anyway, I am fine with a mount option.

Quoted 15 lines

Thanks,
Kalpak.

Quoted 7 lines

Mingming

-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#11 lore raw

PATCH 4/6 add noversion mount option

In reply to a message not in the archive

This patch adds a "noversion" mount option to disable inode version updates.

---
 fs/ext4/inode.c         |    4 +++-
 fs/ext4/super.c         |    6 +++++-
 include/linux/ext4_fs.h |    1 +
 3 files changed, 9 insertions(+), 2 deletions(-)

Add a "noversion" mount option to disable inode version updates.

fs/ext4/super.c +5 -1
Index: linux-2.6.21/fs/ext4/super.c
===================================================================
@@ -725,7 +725,7 @@ enum {
 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
 	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
-	Opt_grpquota, Opt_extents, Opt_noextents,
+	Opt_grpquota, Opt_extents, Opt_noextents, Opt_noversion,
 };
 
 static match_table_t tokens = {
@@ -777,6 +777,7 @@ static match_table_t tokens = {
 	{Opt_barrier, "barrier=%u"},
 	{Opt_extents, "extents"},
 	{Opt_noextents, "noextents"},
+	{Opt_noversion, "noversion"},
 	{Opt_err, NULL},
 	{Opt_resize, "resize"},
 };
@@ -1115,6 +1116,9 @@ clear_qf_name:
 		case Opt_noextents:
 			clear_opt (sbi->s_mount_opt, EXTENTS);
 			break;
+		case Opt_noversion:
+			set_opt(sbi->s_mount_opt, NOVERSION);
+			break;
 		default:
 			printk (KERN_ERR
 				"EXT4-fs: Unrecognized mount option \"%s\" "
include/linux/ext4_fs.h +1 -0
Index: linux-2.6.21/include/linux/ext4_fs.h
===================================================================
@@ -473,6 +473,7 @@ do {									       \
 #define EXT4_MOUNT_USRQUOTA		0x100000 /* "old" user quota */
 #define EXT4_MOUNT_GRPQUOTA		0x200000 /* "old" group quota */
 #define EXT4_MOUNT_EXTENTS		0x400000 /* Extents support */
+#define EXT4_MOUNT_NOVERSION		0x800000 /* No inode version updates */
 
 /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
 #ifndef _LINUX_EXT2_FS_H
fs/ext4/inode.c +3 -1
Index: linux-2.6.21/fs/ext4/inode.c
===================================================================
@@ -3082,7 +3082,9 @@ int ext4_mark_iloc_dirty(handle_t *handl
 {
 	int err = 0;
 
-	inode->i_version++;
+	if (!test_opt(inode->i_sb, NOVERSION))
+		inode->i_version++;
+
 	/* the do_update_inode consumes one bh->b_count */
 	get_bh(iloc->bh);
 
#12 lore raw

PATCH 5/6 VFS updates to i_version

In reply to a message not in the archive

The VFS-level updates of the inode version. These may not be necessary since the i_version is being updated in ext4_mark_iloc_dirty().

---
 binfmt_misc.c |    1 +
 libfs.c       |    9 +++++++++
 pipe.c        |    1 +
 3 files changed, 11 insertions(+)

The patch modifies the i_version field of the inode on the VFS layer. The i_version field become a 64bit counter that is set on inode creation and that is incremented every time the inode data is modified (similarly to the "ctime" time-stamp).
The aim is to fulfill a NFSv4 requirement for rfc3530:
"5.5. Mandatory Attributes - Definitions
Name # DataType Access Description
___________________________________________________________________
change 3 uint64 READ A value created by the
server that the client can use to determine if file data, directory contents or attributes of the object have been modified. The servermay return the object's time_metadata attribute for this attribute's value but only if the filesystem object can not be updated more frequently than the resolution of time_metadata."

fs/binfmt_misc.c +1 -0
Index: linux-2.6.22-rc4/fs/binfmt_misc.c
===================================================================
@@ -508,6 +508,7 @@ static struct inode *bm_get_inode(struct
 		inode->i_blocks = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime =
 			current_fs_time(inode->i_sb);
+		inode->i_version = 1;
 	}
 	return inode;
 }
fs/libfs.c +9 -0
Index: linux-2.6.22-rc4/fs/libfs.c
===================================================================
@@ -232,6 +232,7 @@ int get_sb_pseudo(struct file_system_typ
 	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
 	root->i_uid = root->i_gid = 0;
 	root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
+	root->i_version = 1;
 	dentry = d_alloc(NULL, &d_name);
 	if (!dentry) {
 		iput(root);
@@ -255,6 +256,8 @@ int simple_link(struct dentry *old_dentr
 	struct inode *inode = old_dentry->d_inode;
 
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	inode->i_version++;
+	dir->i_version++;
 	inc_nlink(inode);
 	atomic_inc(&inode->i_count);
 	dget(dentry);
@@ -287,6 +290,8 @@ int simple_unlink(struct inode *dir, str
 	struct inode *inode = dentry->d_inode;
 
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	inode->i_version++;
+	dir->i_version++;
 	drop_nlink(inode);
 	dput(dentry);
 	return 0;
@@ -323,6 +328,8 @@ int simple_rename(struct inode *old_dir,
 
 	old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
 		new_dir->i_mtime = inode->i_ctime = CURRENT_TIME;
+	old_dir->i_version++;
+	new_dir->i_version++;
 
 	return 0;
 }
@@ -399,6 +406,7 @@ int simple_fill_super(struct super_block
 	inode->i_uid = inode->i_gid = 0;
 	inode->i_blocks = 0;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	inode->i_version = 1;
 	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 	inode->i_nlink = 2;
@@ -427,6 +435,7 @@ int simple_fill_super(struct super_block
 		inode->i_uid = inode->i_gid = 0;
 		inode->i_blocks = 0;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		inode->i_version = 1;
 		inode->i_fop = files->ops;
 		inode->i_ino = i;
 		d_add(dentry, inode);
fs/pipe.c +1 -0
Index: linux-2.6.22-rc4/fs/pipe.c
===================================================================
@@ -882,6 +882,7 @@ static struct inode * get_pipe_inode(voi
 	inode->i_uid = current->fsuid;
 	inode->i_gid = current->fsgid;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	inode->i_version = 1;
 
 	return inode;
 
#13 lore raw

PATCH 6/6 Updated series file

In reply to a message not in the archive

The updated series file.

# Rebased the patches to 2.6.22-rc4

# Add mount option to turn off extents
ext4_noextent_mount_opt.patch

# Mounted ext4dev fs with extents by default for testing purpose,

# for Ext4 product release, extents mount option
# will be turn on only if the fs has EXTENTS feature on
ext4_extents_on_by_default.patch

# Propagate inode flags
ext4-propagate_flags.patch

# Add extent sanity checks
ext4-extent-sanity-checks.patch

# Bug fix:set 64bit JBD2 feature on >32bit ext4 fs ext4_set_jbd2_64bit_feature.patch

# Fix: Rename CONFIG_JBD_DEBUG to CONFIG_JBD2_DEBUG jbd2_config_jbd2_debug_fix.patch

# Export jbd2-debug via debugfs
ext4_CONFIG_JBD2_DEBUG.patch
jbd2_move_jbd2_debug_to_debugfs.patch

# fallocate() syscall patches and ext4 fallocate() implementation # Missing manpages ext4-fallocate-1-syscall_i386_amd64_ppc ext4-fallocate-2-syscall_s390 ext4-fallocate-3-syscall_ia64 ext4-fallocate-5-ext4_support ext4-fallocate-6-uninit_write_support

# Nanosecond timestamp support
ext4-nanosecond-patch

# inode verion patch series
# inode versioning is needed for NFSv4
# vfs changes, 64 bit inode->i_version
64-bit-i_version.patch
# reserve hi 32 bit inode version on ext4 on-disk inode
i_version_hi.patch
# ext4 inode version read/store
ext4_i_version_hi_2.patch
# ext4 inode version update
i_version_update_ext4.patch
# add a noversion mount option to disable inode version updates
ext4_no_version.patch
# VFS-level updates of inode version.
i_version_update_vfs.patch

# New patch to expand inode i_extra_isize to support features

# in high part of inode (>128 bytes)
ext4_expand_inode_extra_isize.patch

# Export jbd stats through procfs
# Shall this move to debugfs?
jbd-stats-through-procfs

# Remove 32000 subdirs limit.
ext4_remove_subdirs_limit.patch

##############################################################
# Unstable patches
# Note: still lots of outstanding comments from linux-ext4 list, 12/2006 # Missing signed-off-by:
booked-page-flag.patch

# Reserve blocks for delalloc
ext4-block-reservation.patch

# Delayed allocation support for data=writeback mode # Needs support for ordered mode and pagesize!= fs block size ext4-delayed-allocation.patch

# 48 bit block number support in delalloc
ext4-delalloc-extents-48bit.patch

# Add mount option to turn off delayed allocation
ext4_nodelalloc_mount_opt.patch