Commit 8aefcd557d26d0023a36f9ec5afbf55e59f8f26b
1 parent
353eb83c14
Exists in
master
and in
39 other branches
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>
Showing 7 changed files with 74 additions and 25 deletions Side-by-side Diff
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.h
... | ... | @@ -253,7 +253,7 @@ |
253 | 253 | static inline int ext4_jbd2_file_inode(handle_t *handle, struct inode *inode) |
254 | 254 | { |
255 | 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 | 257 | return 0; |
258 | 258 | } |
259 | 259 |
fs/ext4/file.c
... | ... | @@ -104,6 +104,7 @@ |
104 | 104 | { |
105 | 105 | struct super_block *sb = inode->i_sb; |
106 | 106 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
107 | + struct ext4_inode_info *ei = EXT4_I(inode); | |
107 | 108 | struct vfsmount *mnt = filp->f_path.mnt; |
108 | 109 | struct path path; |
109 | 110 | char buf[64], *cp; |
... | ... | @@ -126,6 +127,27 @@ |
126 | 127 | sizeof(sbi->s_es->s_last_mounted)); |
127 | 128 | ext4_mark_super_dirty(sb); |
128 | 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); | |
129 | 151 | } |
130 | 152 | return dquot_file_open(inode, filp); |
131 | 153 | } |
fs/ext4/inode.c
... | ... | @@ -55,10 +55,17 @@ |
55 | 55 | loff_t new_size) |
56 | 56 | { |
57 | 57 | trace_ext4_begin_ordered_truncate(inode, new_size); |
58 | - return jbd2_journal_begin_ordered_truncate( | |
59 | - EXT4_SB(inode->i_sb)->s_journal, | |
60 | - &EXT4_I(inode)->jinode, | |
61 | - new_size); | |
58 | + /* | |
59 | + * If jinode is zero, then we never opened the file for | |
60 | + * writing, so there's no need to call | |
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 | 71 | static void ext4_invalidatepage(struct page *page, unsigned long offset); |
... | ... | @@ -4054,7 +4061,7 @@ |
4054 | 4061 | if (ext4_should_journal_data(inode)) { |
4055 | 4062 | err = ext4_handle_dirty_metadata(handle, inode, bh); |
4056 | 4063 | } else { |
4057 | - if (ext4_should_order_data(inode)) | |
4064 | + if (ext4_should_order_data(inode) && EXT4_I(inode)->jinode) | |
4058 | 4065 | err = ext4_jbd2_file_inode(handle, inode); |
4059 | 4066 | mark_buffer_dirty(bh); |
4060 | 4067 | } |
fs/ext4/super.c
... | ... | @@ -818,12 +818,6 @@ |
818 | 818 | memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); |
819 | 819 | INIT_LIST_HEAD(&ei->i_prealloc_list); |
820 | 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 | 821 | ei->i_reserved_data_blocks = 0; |
828 | 822 | ei->i_reserved_meta_blocks = 0; |
829 | 823 | ei->i_allocated_meta_blocks = 0; |
... | ... | @@ -832,6 +826,7 @@ |
832 | 826 | #ifdef CONFIG_QUOTA |
833 | 827 | ei->i_reserved_quota = 0; |
834 | 828 | #endif |
829 | + ei->jinode = NULL; | |
835 | 830 | INIT_LIST_HEAD(&ei->i_completed_io_list); |
836 | 831 | spin_lock_init(&ei->i_completed_io_lock); |
837 | 832 | ei->cur_aio_dio = NULL; |
... | ... | @@ -900,9 +895,12 @@ |
900 | 895 | end_writeback(inode); |
901 | 896 | dquot_drop(inode); |
902 | 897 | ext4_discard_preallocations(inode); |
903 | - if (EXT4_JOURNAL(inode)) | |
904 | - jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal, | |
905 | - &EXT4_I(inode)->jinode); | |
898 | + if (EXT4_I(inode)->jinode) { | |
899 | + jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode), | |
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 | 906 | static inline void ext4_show_quota_options(struct seq_file *seq, |
fs/jbd2/journal.c
... | ... | @@ -94,6 +94,7 @@ |
94 | 94 | EXPORT_SYMBOL(jbd2_journal_init_jbd_inode); |
95 | 95 | EXPORT_SYMBOL(jbd2_journal_release_jbd_inode); |
96 | 96 | EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate); |
97 | +EXPORT_SYMBOL(jbd2_inode_cache); | |
97 | 98 | |
98 | 99 | static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); |
99 | 100 | static void __journal_abort_soft (journal_t *journal, int errno); |
100 | 101 | |
101 | 102 | |
102 | 103 | |
... | ... | @@ -2286,19 +2287,21 @@ |
2286 | 2287 | |
2287 | 2288 | #endif |
2288 | 2289 | |
2289 | -struct kmem_cache *jbd2_handle_cache; | |
2290 | +struct kmem_cache *jbd2_handle_cache, *jbd2_inode_cache; | |
2290 | 2291 | |
2291 | 2292 | static int __init journal_init_handle_cache(void) |
2292 | 2293 | { |
2293 | - jbd2_handle_cache = kmem_cache_create("jbd2_journal_handle", | |
2294 | - sizeof(handle_t), | |
2295 | - 0, /* offset */ | |
2296 | - SLAB_TEMPORARY, /* flags */ | |
2297 | - NULL); /* ctor */ | |
2294 | + jbd2_handle_cache = KMEM_CACHE(jbd2_journal_handle, SLAB_TEMPORARY); | |
2298 | 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"); | |
2300 | 2297 | return -ENOMEM; |
2301 | 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); | |
2303 | + return -ENOMEM; | |
2304 | + } | |
2302 | 2305 | return 0; |
2303 | 2306 | } |
2304 | 2307 | |
... | ... | @@ -2306,6 +2309,9 @@ |
2306 | 2309 | { |
2307 | 2310 | if (jbd2_handle_cache) |
2308 | 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 | /* |
include/linux/jbd2.h
... | ... | @@ -94,7 +94,7 @@ |
94 | 94 | * |
95 | 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 @@ |
416 | 416 | * in so it can be fixed later. |
417 | 417 | */ |
418 | 418 | |
419 | -struct handle_s | |
419 | +struct jbd2_journal_handle | |
420 | 420 | { |
421 | 421 | /* Which compound transaction is this update a part of? */ |
422 | 422 | transaction_t *h_transaction; |
... | ... | @@ -1156,6 +1156,22 @@ |
1156 | 1156 | static inline void jbd2_free_handle(handle_t *handle) |
1157 | 1157 | { |
1158 | 1158 | kmem_cache_free(jbd2_handle_cache, handle); |
1159 | +} | |
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); | |
1159 | 1175 | } |
1160 | 1176 | |
1161 | 1177 | /* Primary revoke support */ |