diff options
author | Theodore Ts'o <tytso@mit.edu> | 2011-01-10 12:29:43 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-01-10 12:29:43 -0500 |
commit | 8aefcd557d26d0023a36f9ec5afbf55e59f8f26b (patch) | |
tree | e13143306cd64525cddd2cc2513c448275a1d95a | |
parent | 353eb83c1422c6326eaab30ce044a179c6018169 (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.h | 2 | ||||
-rw-r--r-- | fs/ext4/ext4_jbd2.h | 2 | ||||
-rw-r--r-- | fs/ext4/file.c | 22 | ||||
-rw-r--r-- | fs/ext4/inode.c | 17 | ||||
-rw-r--r-- | fs/ext4/super.c | 16 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 20 | ||||
-rw-r--r-- | include/linux/jbd2.h | 20 |
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) | |||
253 | static inline int ext4_jbd2_file_inode(handle_t *handle, struct inode *inode) | 253 | static 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 | ||
64 | static void ext4_invalidatepage(struct page *page, unsigned long offset); | 71 | static 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 | ||
908 | static inline void ext4_show_quota_options(struct seq_file *seq, | 906 | static 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); | |||
94 | EXPORT_SYMBOL(jbd2_journal_init_jbd_inode); | 94 | EXPORT_SYMBOL(jbd2_journal_init_jbd_inode); |
95 | EXPORT_SYMBOL(jbd2_journal_release_jbd_inode); | 95 | EXPORT_SYMBOL(jbd2_journal_release_jbd_inode); |
96 | EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate); | 96 | EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate); |
97 | EXPORT_SYMBOL(jbd2_inode_cache); | ||
97 | 98 | ||
98 | static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); | 99 | static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); |
99 | static void __journal_abort_soft (journal_t *journal, int errno); | 100 | static 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 | ||
2289 | struct kmem_cache *jbd2_handle_cache; | 2290 | struct kmem_cache *jbd2_handle_cache, *jbd2_inode_cache; |
2290 | 2291 | ||
2291 | static int __init journal_init_handle_cache(void) | 2292 | static 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 | **/ |
97 | typedef struct handle_s handle_t; /* Atomic operation type */ | 97 | typedef 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 | ||
419 | struct handle_s | 419 | struct 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 | */ | ||
1165 | extern struct kmem_cache *jbd2_inode_cache; | ||
1166 | |||
1167 | static inline struct jbd2_inode *jbd2_alloc_inode(gfp_t gfp_flags) | ||
1168 | { | ||
1169 | return kmem_cache_alloc(jbd2_inode_cache, gfp_flags); | ||
1170 | } | ||
1171 | |||
1172 | static 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 |
1163 | extern int jbd2_journal_init_revoke(journal_t *, int); | 1179 | extern int jbd2_journal_init_revoke(journal_t *, int); |