aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2011-01-10 12:29:43 -0500
committerTheodore Ts'o <tytso@mit.edu>2011-01-10 12:29:43 -0500
commit8aefcd557d26d0023a36f9ec5afbf55e59f8f26b (patch)
treee13143306cd64525cddd2cc2513c448275a1d95a
parent353eb83c1422c6326eaab30ce044a179c6018169 (diff)
ext4: dynamically allocate the jbd2_inode in ext4_inode_info as necessary
Replace the jbd2_inode structure (which is 48 bytes) with a pointer and only allocate the jbd2_inode when it is needed --- that is, when the file system has a journal present and the inode has been opened for writing. This allows us to further slim down the ext4_inode_info structure. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--fs/ext4/ext4.h2
-rw-r--r--fs/ext4/ext4_jbd2.h2
-rw-r--r--fs/ext4/file.c22
-rw-r--r--fs/ext4/inode.c17
-rw-r--r--fs/ext4/super.c16
-rw-r--r--fs/jbd2/journal.c20
-rw-r--r--include/linux/jbd2.h20
7 files changed, 74 insertions, 25 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 2fb531cfd48b..32b7daa41a42 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -811,7 +811,7 @@ struct ext4_inode_info {
811 */ 811 */
812 struct rw_semaphore i_data_sem; 812 struct rw_semaphore i_data_sem;
813 struct inode vfs_inode; 813 struct inode vfs_inode;
814 struct jbd2_inode jinode; 814 struct jbd2_inode *jinode;
815 815
816 struct ext4_ext_cache i_cached_extent; 816 struct ext4_ext_cache i_cached_extent;
817 /* 817 /*
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index b0bd792c58c5..d8b992e658c1 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -253,7 +253,7 @@ static inline int ext4_journal_force_commit(journal_t *journal)
253static inline int ext4_jbd2_file_inode(handle_t *handle, struct inode *inode) 253static inline int ext4_jbd2_file_inode(handle_t *handle, struct inode *inode)
254{ 254{
255 if (ext4_handle_valid(handle)) 255 if (ext4_handle_valid(handle))
256 return jbd2_journal_file_inode(handle, &EXT4_I(inode)->jinode); 256 return jbd2_journal_file_inode(handle, EXT4_I(inode)->jinode);
257 return 0; 257 return 0;
258} 258}
259 259
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 5a5c55ddceef..bb003dc9ffff 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -104,6 +104,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
104{ 104{
105 struct super_block *sb = inode->i_sb; 105 struct super_block *sb = inode->i_sb;
106 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); 106 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
107 struct ext4_inode_info *ei = EXT4_I(inode);
107 struct vfsmount *mnt = filp->f_path.mnt; 108 struct vfsmount *mnt = filp->f_path.mnt;
108 struct path path; 109 struct path path;
109 char buf[64], *cp; 110 char buf[64], *cp;
@@ -127,6 +128,27 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
127 ext4_mark_super_dirty(sb); 128 ext4_mark_super_dirty(sb);
128 } 129 }
129 } 130 }
131 /*
132 * Set up the jbd2_inode if we are opening the inode for
133 * writing and the journal is present
134 */
135 if (sbi->s_journal && !ei->jinode && (filp->f_mode & FMODE_WRITE)) {
136 struct jbd2_inode *jinode = jbd2_alloc_inode(GFP_KERNEL);
137
138 spin_lock(&inode->i_lock);
139 if (!ei->jinode) {
140 if (!jinode) {
141 spin_unlock(&inode->i_lock);
142 return -ENOMEM;
143 }
144 ei->jinode = jinode;
145 jbd2_journal_init_jbd_inode(ei->jinode, inode);
146 jinode = NULL;
147 }
148 spin_unlock(&inode->i_lock);
149 if (unlikely(jinode != NULL))
150 jbd2_free_inode(jinode);
151 }
130 return dquot_file_open(inode, filp); 152 return dquot_file_open(inode, filp);
131} 153}
132 154
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 0801ee6a173e..2693fcda30d8 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -55,10 +55,17 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode,
55 loff_t new_size) 55 loff_t new_size)
56{ 56{
57 trace_ext4_begin_ordered_truncate(inode, new_size); 57 trace_ext4_begin_ordered_truncate(inode, new_size);
58 return jbd2_journal_begin_ordered_truncate( 58 /*
59 EXT4_SB(inode->i_sb)->s_journal, 59 * If jinode is zero, then we never opened the file for
60 &EXT4_I(inode)->jinode, 60 * writing, so there's no need to call
61 new_size); 61 * jbd2_journal_begin_ordered_truncate() since there's no
62 * outstanding writes we need to flush.
63 */
64 if (!EXT4_I(inode)->jinode)
65 return 0;
66 return jbd2_journal_begin_ordered_truncate(EXT4_JOURNAL(inode),
67 EXT4_I(inode)->jinode,
68 new_size);
62} 69}
63 70
64static void ext4_invalidatepage(struct page *page, unsigned long offset); 71static void ext4_invalidatepage(struct page *page, unsigned long offset);
@@ -4054,7 +4061,7 @@ int ext4_block_truncate_page(handle_t *handle,
4054 if (ext4_should_journal_data(inode)) { 4061 if (ext4_should_journal_data(inode)) {
4055 err = ext4_handle_dirty_metadata(handle, inode, bh); 4062 err = ext4_handle_dirty_metadata(handle, inode, bh);
4056 } else { 4063 } else {
4057 if (ext4_should_order_data(inode)) 4064 if (ext4_should_order_data(inode) && EXT4_I(inode)->jinode)
4058 err = ext4_jbd2_file_inode(handle, inode); 4065 err = ext4_jbd2_file_inode(handle, inode);
4059 mark_buffer_dirty(bh); 4066 mark_buffer_dirty(bh);
4060 } 4067 }
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index f5960d673e4e..1cd4326c530b 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -818,12 +818,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
818 memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); 818 memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
819 INIT_LIST_HEAD(&ei->i_prealloc_list); 819 INIT_LIST_HEAD(&ei->i_prealloc_list);
820 spin_lock_init(&ei->i_prealloc_lock); 820 spin_lock_init(&ei->i_prealloc_lock);
821 /*
822 * Note: We can be called before EXT4_SB(sb)->s_journal is set,
823 * therefore it can be null here. Don't check it, just initialize
824 * jinode.
825 */
826 jbd2_journal_init_jbd_inode(&ei->jinode, &ei->vfs_inode);
827 ei->i_reserved_data_blocks = 0; 821 ei->i_reserved_data_blocks = 0;
828 ei->i_reserved_meta_blocks = 0; 822 ei->i_reserved_meta_blocks = 0;
829 ei->i_allocated_meta_blocks = 0; 823 ei->i_allocated_meta_blocks = 0;
@@ -832,6 +826,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
832#ifdef CONFIG_QUOTA 826#ifdef CONFIG_QUOTA
833 ei->i_reserved_quota = 0; 827 ei->i_reserved_quota = 0;
834#endif 828#endif
829 ei->jinode = NULL;
835 INIT_LIST_HEAD(&ei->i_completed_io_list); 830 INIT_LIST_HEAD(&ei->i_completed_io_list);
836 spin_lock_init(&ei->i_completed_io_lock); 831 spin_lock_init(&ei->i_completed_io_lock);
837 ei->cur_aio_dio = NULL; 832 ei->cur_aio_dio = NULL;
@@ -900,9 +895,12 @@ void ext4_clear_inode(struct inode *inode)
900 end_writeback(inode); 895 end_writeback(inode);
901 dquot_drop(inode); 896 dquot_drop(inode);
902 ext4_discard_preallocations(inode); 897 ext4_discard_preallocations(inode);
903 if (EXT4_JOURNAL(inode)) 898 if (EXT4_I(inode)->jinode) {
904 jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal, 899 jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode),
905 &EXT4_I(inode)->jinode); 900 EXT4_I(inode)->jinode);
901 jbd2_free_inode(EXT4_I(inode)->jinode);
902 EXT4_I(inode)->jinode = NULL;
903 }
906} 904}
907 905
908static inline void ext4_show_quota_options(struct seq_file *seq, 906static inline void ext4_show_quota_options(struct seq_file *seq,
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 2447bd86f801..9e4686900f18 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -94,6 +94,7 @@ EXPORT_SYMBOL(jbd2_journal_file_inode);
94EXPORT_SYMBOL(jbd2_journal_init_jbd_inode); 94EXPORT_SYMBOL(jbd2_journal_init_jbd_inode);
95EXPORT_SYMBOL(jbd2_journal_release_jbd_inode); 95EXPORT_SYMBOL(jbd2_journal_release_jbd_inode);
96EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate); 96EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate);
97EXPORT_SYMBOL(jbd2_inode_cache);
97 98
98static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); 99static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
99static void __journal_abort_soft (journal_t *journal, int errno); 100static void __journal_abort_soft (journal_t *journal, int errno);
@@ -2286,17 +2287,19 @@ static void __exit jbd2_remove_jbd_stats_proc_entry(void)
2286 2287
2287#endif 2288#endif
2288 2289
2289struct kmem_cache *jbd2_handle_cache; 2290struct kmem_cache *jbd2_handle_cache, *jbd2_inode_cache;
2290 2291
2291static int __init journal_init_handle_cache(void) 2292static int __init journal_init_handle_cache(void)
2292{ 2293{
2293 jbd2_handle_cache = kmem_cache_create("jbd2_journal_handle", 2294 jbd2_handle_cache = KMEM_CACHE(jbd2_journal_handle, SLAB_TEMPORARY);
2294 sizeof(handle_t),
2295 0, /* offset */
2296 SLAB_TEMPORARY, /* flags */
2297 NULL); /* ctor */
2298 if (jbd2_handle_cache == NULL) { 2295 if (jbd2_handle_cache == NULL) {
2299 printk(KERN_EMERG "JBD: failed to create handle cache\n"); 2296 printk(KERN_EMERG "JBD2: failed to create handle cache\n");
2297 return -ENOMEM;
2298 }
2299 jbd2_inode_cache = KMEM_CACHE(jbd2_inode, 0);
2300 if (jbd2_inode_cache == NULL) {
2301 printk(KERN_EMERG "JBD2: failed to create inode cache\n");
2302 kmem_cache_destroy(jbd2_handle_cache);
2300 return -ENOMEM; 2303 return -ENOMEM;
2301 } 2304 }
2302 return 0; 2305 return 0;
@@ -2306,6 +2309,9 @@ static void jbd2_journal_destroy_handle_cache(void)
2306{ 2309{
2307 if (jbd2_handle_cache) 2310 if (jbd2_handle_cache)
2308 kmem_cache_destroy(jbd2_handle_cache); 2311 kmem_cache_destroy(jbd2_handle_cache);
2312 if (jbd2_inode_cache)
2313 kmem_cache_destroy(jbd2_inode_cache);
2314
2309} 2315}
2310 2316
2311/* 2317/*
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 2ae86aa21fce..27e79c27ba08 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -94,7 +94,7 @@ extern void jbd2_free(void *ptr, size_t size);
94 * 94 *
95 * This is an opaque datatype. 95 * This is an opaque datatype.
96 **/ 96 **/
97typedef struct handle_s handle_t; /* Atomic operation type */ 97typedef struct jbd2_journal_handle handle_t; /* Atomic operation type */
98 98
99 99
100/** 100/**
@@ -416,7 +416,7 @@ struct jbd2_revoke_table_s;
416 * in so it can be fixed later. 416 * in so it can be fixed later.
417 */ 417 */
418 418
419struct handle_s 419struct jbd2_journal_handle
420{ 420{
421 /* Which compound transaction is this update a part of? */ 421 /* Which compound transaction is this update a part of? */
422 transaction_t *h_transaction; 422 transaction_t *h_transaction;
@@ -1158,6 +1158,22 @@ static inline void jbd2_free_handle(handle_t *handle)
1158 kmem_cache_free(jbd2_handle_cache, handle); 1158 kmem_cache_free(jbd2_handle_cache, handle);
1159} 1159}
1160 1160
1161/*
1162 * jbd2_inode management (optional, for those file systems that want to use
1163 * dynamically allocated jbd2_inode structures)
1164 */
1165extern struct kmem_cache *jbd2_inode_cache;
1166
1167static inline struct jbd2_inode *jbd2_alloc_inode(gfp_t gfp_flags)
1168{
1169 return kmem_cache_alloc(jbd2_inode_cache, gfp_flags);
1170}
1171
1172static inline void jbd2_free_inode(struct jbd2_inode *jinode)
1173{
1174 kmem_cache_free(jbd2_inode_cache, jinode);
1175}
1176
1161/* Primary revoke support */ 1177/* Primary revoke support */
1162#define JOURNAL_REVOKE_DEFAULT_HASH 256 1178#define JOURNAL_REVOKE_DEFAULT_HASH 256
1163extern int jbd2_journal_init_revoke(journal_t *, int); 1179extern int jbd2_journal_init_revoke(journal_t *, int);