1 This patch is a spinoff of the old nanosecond patches.
3 It includes some cleanups and addition of a creation timestamp. The
4 EXT3_FEATURE_RO_COMPAT_EXTRA_ISIZE flag has also been added along with
5 s_{min, want}_extra_isize fields in struct ext3_super_block.
7 Signed-off-by: Andreas Dilger <adilger@clusterfs.com>
8 Signed-off-by: Kalpak Shah <kalpak@clusterfs.com>
9 Signed-off-by: Eric Sandeen <sandeen@redhat.com>
10 Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
11 Signed-off-by: Mingming Cao <cmm@us.ibm.com>
13 Index: linux-2.6.22-rc4/fs/ext4/ialloc.c
14 ===================================================================
15 --- linux-2.6.22-rc4.orig/fs/ext4/ialloc.c 2007-06-11 17:22:15.000000000 -0700
16 +++ linux-2.6.22-rc4/fs/ext4/ialloc.c 2007-06-11 17:39:05.000000000 -0700
19 /* This is the optimal IO size (for stat), not the fs block size */
21 - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
22 + inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
23 + ext4_current_time(inode);
25 memset(ei->i_data, 0, sizeof(ei->i_data));
26 ei->i_dir_start_lookup = 0;
28 spin_unlock(&sbi->s_next_gen_lock);
30 ei->i_state = EXT4_STATE_NEW;
32 - (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) ?
33 - sizeof(struct ext4_inode) - EXT4_GOOD_OLD_INODE_SIZE : 0;
35 + ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
38 if(DQUOT_ALLOC_INODE(inode)) {
39 Index: linux-2.6.22-rc4/fs/ext4/inode.c
40 ===================================================================
41 --- linux-2.6.22-rc4.orig/fs/ext4/inode.c 2007-06-11 17:24:28.000000000 -0700
42 +++ linux-2.6.22-rc4/fs/ext4/inode.c 2007-06-11 17:39:05.000000000 -0700
45 /* We are done with atomic stuff, now do the rest of housekeeping */
47 - inode->i_ctime = CURRENT_TIME_SEC;
48 + inode->i_ctime = ext4_current_time(inode);
49 ext4_mark_inode_dirty(handle, inode);
51 /* had we spliced it onto indirect block? */
53 ext4_discard_reservation(inode);
55 mutex_unlock(&ei->truncate_mutex);
56 - inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
57 + inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
58 ext4_mark_inode_dirty(handle, inode);
61 @@ -2629,10 +2629,6 @@
63 inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
64 inode->i_size = le32_to_cpu(raw_inode->i_size);
65 - inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
66 - inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);
67 - inode->i_mtime.tv_sec = (signed)le32_to_cpu(raw_inode->i_mtime);
68 - inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0;
71 ei->i_dir_start_lookup = 0;
72 @@ -2708,6 +2704,11 @@
74 ei->i_extra_isize = 0;
76 + EXT4_INODE_GET_XTIME(i_ctime, inode, raw_inode);
77 + EXT4_INODE_GET_XTIME(i_mtime, inode, raw_inode);
78 + EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode);
79 + EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode);
81 if (S_ISREG(inode->i_mode)) {
82 inode->i_op = &ext4_file_inode_operations;
83 inode->i_fop = &ext4_file_operations;
84 @@ -2789,9 +2790,12 @@
86 raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
87 raw_inode->i_size = cpu_to_le32(ei->i_disksize);
88 - raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
89 - raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
90 - raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
92 + EXT4_INODE_SET_XTIME(i_ctime, inode, raw_inode);
93 + EXT4_INODE_SET_XTIME(i_mtime, inode, raw_inode);
94 + EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode);
95 + EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode);
97 raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
98 raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
99 raw_inode->i_flags = cpu_to_le32(ei->i_flags);
100 Index: linux-2.6.22-rc4/fs/ext4/ioctl.c
101 ===================================================================
102 --- linux-2.6.22-rc4.orig/fs/ext4/ioctl.c 2007-06-11 17:25:11.000000000 -0700
103 +++ linux-2.6.22-rc4/fs/ext4/ioctl.c 2007-06-11 17:39:05.000000000 -0700
107 ext4_set_inode_flags(inode);
108 - inode->i_ctime = CURRENT_TIME_SEC;
109 + inode->i_ctime = ext4_current_time(inode);
111 err = ext4_mark_iloc_dirty(handle, inode, &iloc);
114 return PTR_ERR(handle);
115 err = ext4_reserve_inode_write(handle, inode, &iloc);
117 - inode->i_ctime = CURRENT_TIME_SEC;
118 + inode->i_ctime = ext4_current_time(inode);
119 inode->i_generation = generation;
120 err = ext4_mark_iloc_dirty(handle, inode, &iloc);
122 Index: linux-2.6.22-rc4/fs/ext4/namei.c
123 ===================================================================
124 --- linux-2.6.22-rc4.orig/fs/ext4/namei.c 2007-06-11 17:22:15.000000000 -0700
125 +++ linux-2.6.22-rc4/fs/ext4/namei.c 2007-06-11 17:39:05.000000000 -0700
126 @@ -1285,7 +1285,7 @@
127 * happen is that the times are slightly out of date
128 * and/or different from the directory change time.
130 - dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
131 + dir->i_mtime = dir->i_ctime = ext4_current_time(dir);
132 ext4_update_dx_flag(dir);
134 ext4_mark_inode_dirty(handle, dir);
135 @@ -2046,7 +2046,7 @@
138 ext4_orphan_add(handle, inode);
139 - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
140 + inode->i_ctime = dir->i_ctime = dir->i_mtime = ext4_current_time(inode);
141 ext4_mark_inode_dirty(handle, inode);
143 ext4_update_dx_flag(dir);
144 @@ -2096,13 +2096,13 @@
145 retval = ext4_delete_entry(handle, dir, de, bh);
148 - dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
149 + dir->i_ctime = dir->i_mtime = ext4_current_time(dir);
150 ext4_update_dx_flag(dir);
151 ext4_mark_inode_dirty(handle, dir);
154 ext4_orphan_add(handle, inode);
155 - inode->i_ctime = dir->i_ctime;
156 + inode->i_ctime = ext4_current_time(inode);
157 ext4_mark_inode_dirty(handle, inode);
160 @@ -2193,7 +2193,7 @@
164 - inode->i_ctime = CURRENT_TIME_SEC;
165 + inode->i_ctime = ext4_current_time(inode);
167 atomic_inc(&inode->i_count);
169 @@ -2295,7 +2295,7 @@
170 * Like most other Unix systems, set the ctime for inodes on a
173 - old_inode->i_ctime = CURRENT_TIME_SEC;
174 + old_inode->i_ctime = ext4_current_time(old_inode);
175 ext4_mark_inode_dirty(handle, old_inode);
178 @@ -2328,9 +2328,9 @@
181 drop_nlink(new_inode);
182 - new_inode->i_ctime = CURRENT_TIME_SEC;
183 + new_inode->i_ctime = ext4_current_time(new_inode);
185 - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
186 + old_dir->i_ctime = old_dir->i_mtime = ext4_current_time(old_dir);
187 ext4_update_dx_flag(old_dir);
189 BUFFER_TRACE(dir_bh, "get_write_access");
190 Index: linux-2.6.22-rc4/fs/ext4/super.c
191 ===================================================================
192 --- linux-2.6.22-rc4.orig/fs/ext4/super.c 2007-06-11 17:28:09.000000000 -0700
193 +++ linux-2.6.22-rc4/fs/ext4/super.c 2007-06-11 17:39:05.000000000 -0700
194 @@ -1642,6 +1642,8 @@
198 + if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE)
199 + sb->s_time_gran = 1 << (EXT4_EPOCH_BITS - 2);
201 sbi->s_frag_size = EXT4_MIN_FRAG_SIZE <<
202 le32_to_cpu(es->s_log_frag_size);
203 @@ -1865,6 +1867,32 @@
206 ext4_setup_super (sb, es, sb->s_flags & MS_RDONLY);
208 + /* determine the minimum size of new large inodes, if present */
209 + if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
210 + sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
211 + EXT4_GOOD_OLD_INODE_SIZE;
212 + if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
213 + EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)) {
214 + if (sbi->s_want_extra_isize <
215 + le16_to_cpu(es->s_want_extra_isize))
216 + sbi->s_want_extra_isize =
217 + le16_to_cpu(es->s_want_extra_isize);
218 + if (sbi->s_want_extra_isize <
219 + le16_to_cpu(es->s_min_extra_isize))
220 + sbi->s_want_extra_isize =
221 + le16_to_cpu(es->s_min_extra_isize);
224 + /* Check if enough inode space is available */
225 + if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
226 + sbi->s_inode_size) {
227 + sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
228 + EXT4_GOOD_OLD_INODE_SIZE;
229 + printk(KERN_INFO "EXT4-fs: required extra inode space not"
234 * akpm: core read_super() calls in here with the superblock locked.
235 * That deadlocks, because orphan cleanup needs to lock the superblock
236 Index: linux-2.6.22-rc4/fs/ext4/xattr.c
237 ===================================================================
238 --- linux-2.6.22-rc4.orig/fs/ext4/xattr.c 2007-06-11 17:22:15.000000000 -0700
239 +++ linux-2.6.22-rc4/fs/ext4/xattr.c 2007-06-11 17:39:05.000000000 -0700
240 @@ -1013,7 +1013,7 @@
243 ext4_xattr_update_super_block(handle, inode->i_sb);
244 - inode->i_ctime = CURRENT_TIME_SEC;
245 + inode->i_ctime = ext4_current_time(inode);
246 error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
248 * The bh is consumed by ext4_mark_iloc_dirty, even with
249 Index: linux-2.6.22-rc4/include/linux/ext4_fs.h
250 ===================================================================
251 --- linux-2.6.22-rc4.orig/include/linux/ext4_fs.h 2007-06-11 17:36:13.000000000 -0700
252 +++ linux-2.6.22-rc4/include/linux/ext4_fs.h 2007-06-11 17:41:55.000000000 -0700
254 __le16 i_uid; /* Low 16 bits of Owner Uid */
255 __le32 i_size; /* Size in bytes */
256 __le32 i_atime; /* Access time */
257 - __le32 i_ctime; /* Creation time */
258 + __le32 i_ctime; /* Inode Change time */
259 __le32 i_mtime; /* Modification time */
260 __le32 i_dtime; /* Deletion Time */
261 __le16 i_gid; /* Low 16 bits of Group Id */
262 @@ -337,10 +337,74 @@
263 } osd2; /* OS dependent 2 */
264 __le16 i_extra_isize;
266 + __le32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
267 + __le32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
268 + __le32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
269 + __le32 i_crtime; /* File Creation time */
270 + __le32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
273 #define i_size_high i_dir_acl
275 +#define EXT4_EPOCH_BITS 2
276 +#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
277 +#define EXT4_NSEC_MASK (~0UL << EXT4_EPOCH_BITS)
279 +#define EXT4_FITS_IN_INODE(ext4_inode, einode, field) \
280 + ((offsetof(typeof(*ext4_inode), field) + \
281 + sizeof((ext4_inode)->field)) \
282 + <= (EXT4_GOOD_OLD_INODE_SIZE + \
283 + (einode)->i_extra_isize)) \
285 +static inline __le32 ext4_encode_extra_time(struct timespec *time)
287 + return cpu_to_le32((sizeof(time->tv_sec) > 4 ?
288 + time->tv_sec >> 32 : 0) |
289 + ((time->tv_nsec << 2) & EXT4_NSEC_MASK));
292 +static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
294 + if (sizeof(time->tv_sec) > 4)
295 + time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
297 + time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> 2;
300 +#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
302 + (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec); \
303 + if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
304 + (raw_inode)->xtime ## _extra = \
305 + ext4_encode_extra_time(&(inode)->xtime); \
308 +#define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode) \
310 + if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \
311 + (raw_inode)->xtime = cpu_to_le32((einode)->xtime.tv_sec); \
312 + if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \
313 + (raw_inode)->xtime ## _extra = \
314 + ext4_encode_extra_time(&(einode)->xtime); \
317 +#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \
319 + (inode)->xtime.tv_sec = le32_to_cpu((raw_inode)->xtime); \
320 + if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
321 + ext4_decode_extra_time(&(inode)->xtime, \
322 + raw_inode->xtime ## _extra); \
325 +#define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode) \
327 + if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \
328 + (einode)->xtime.tv_sec = le32_to_cpu((raw_inode)->xtime); \
329 + if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \
330 + ext4_decode_extra_time(&(einode)->xtime, \
331 + raw_inode->xtime ## _extra); \
334 #if defined(__KERNEL__) || defined(__linux__)
335 #define i_reserved1 osd1.linux1.l_i_reserved1
336 #define i_frag osd2.linux2.l_i_frag
338 return container_of(inode, struct ext4_inode_info, vfs_inode);
341 +static inline struct timespec ext4_current_time(struct inode *inode)
343 + return (inode->i_sb->s_time_gran < NSEC_PER_SEC) ?
344 + current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
348 static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
350 return ino == EXT4_ROOT_INO ||
352 #define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
353 #define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
354 #define EXT4_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
355 +#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
357 #define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001
358 #define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002
360 EXT4_FEATURE_INCOMPAT_64BIT)
361 #define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
362 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
363 + EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
364 EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
367 Index: linux-2.6.22-rc4/include/linux/ext4_fs_i.h
368 ===================================================================
369 --- linux-2.6.22-rc4.orig/include/linux/ext4_fs_i.h 2007-06-11 17:22:15.000000000 -0700
370 +++ linux-2.6.22-rc4/include/linux/ext4_fs_i.h 2007-06-11 17:39:05.000000000 -0700
373 unsigned long i_ext_generation;
374 struct ext4_ext_cache i_cached_extent;
375 + struct timespec i_crtime;
378 #endif /* _LINUX_EXT4_FS_I */
379 Index: linux-2.6.22-rc4/include/linux/ext4_fs_sb.h
380 ===================================================================
381 --- linux-2.6.22-rc4.orig/include/linux/ext4_fs_sb.h 2007-06-11 17:28:15.000000000 -0700
382 +++ linux-2.6.22-rc4/include/linux/ext4_fs_sb.h 2007-06-11 17:39:05.000000000 -0700
384 char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */
385 int s_jquota_fmt; /* Format of quota to use */
387 + unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
390 /* ext4 extents stats */