diff options
author | Curt Wohlgemuth <curtw@google.com> | 2009-09-29 11:01:03 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-09-29 11:01:03 -0400 |
commit | d3d1faf6a74496ea4435fd057c6a2cad49f3e523 (patch) | |
tree | 9f1cc0e2efb9a4fe42bb6b57c087d8450a854dc1 /fs/ext4/super.c | |
parent | f3dc272fd5e2ae08244796bb39e7e1ce4b25d3b3 (diff) |
ext4: Handle nested ext4_journal_start/stop calls without a journal
This patch fixes a problem with handling nested calls to
ext4_journal_start/ext4_journal_stop, when there is no journal present.
Signed-off-by: Curt Wohlgemuth <curtw@google.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index f095c60b569e..3f7e7010c098 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -189,6 +189,36 @@ void ext4_itable_unused_set(struct super_block *sb, | |||
189 | bg->bg_itable_unused_hi = cpu_to_le16(count >> 16); | 189 | bg->bg_itable_unused_hi = cpu_to_le16(count >> 16); |
190 | } | 190 | } |
191 | 191 | ||
192 | |||
193 | /* Just increment the non-pointer handle value */ | ||
194 | static handle_t *ext4_get_nojournal(void) | ||
195 | { | ||
196 | handle_t *handle = current->journal_info; | ||
197 | unsigned long ref_cnt = (unsigned long)handle; | ||
198 | |||
199 | BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT); | ||
200 | |||
201 | ref_cnt++; | ||
202 | handle = (handle_t *)ref_cnt; | ||
203 | |||
204 | current->journal_info = handle; | ||
205 | return handle; | ||
206 | } | ||
207 | |||
208 | |||
209 | /* Decrement the non-pointer handle value */ | ||
210 | static void ext4_put_nojournal(handle_t *handle) | ||
211 | { | ||
212 | unsigned long ref_cnt = (unsigned long)handle; | ||
213 | |||
214 | BUG_ON(ref_cnt == 0); | ||
215 | |||
216 | ref_cnt--; | ||
217 | handle = (handle_t *)ref_cnt; | ||
218 | |||
219 | current->journal_info = handle; | ||
220 | } | ||
221 | |||
192 | /* | 222 | /* |
193 | * Wrappers for jbd2_journal_start/end. | 223 | * Wrappers for jbd2_journal_start/end. |
194 | * | 224 | * |
@@ -215,11 +245,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) | |||
215 | } | 245 | } |
216 | return jbd2_journal_start(journal, nblocks); | 246 | return jbd2_journal_start(journal, nblocks); |
217 | } | 247 | } |
218 | /* | 248 | return ext4_get_nojournal(); |
219 | * We're not journaling, return the appropriate indication. | ||
220 | */ | ||
221 | current->journal_info = EXT4_NOJOURNAL_HANDLE; | ||
222 | return current->journal_info; | ||
223 | } | 249 | } |
224 | 250 | ||
225 | /* | 251 | /* |
@@ -235,11 +261,7 @@ int __ext4_journal_stop(const char *where, handle_t *handle) | |||
235 | int rc; | 261 | int rc; |
236 | 262 | ||
237 | if (!ext4_handle_valid(handle)) { | 263 | if (!ext4_handle_valid(handle)) { |
238 | /* | 264 | ext4_put_nojournal(handle); |
239 | * Do this here since we don't call jbd2_journal_stop() in | ||
240 | * no-journal mode. | ||
241 | */ | ||
242 | current->journal_info = NULL; | ||
243 | return 0; | 265 | return 0; |
244 | } | 266 | } |
245 | sb = handle->h_transaction->t_journal->j_private; | 267 | sb = handle->h_transaction->t_journal->j_private; |