aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorCurt Wohlgemuth <curtw@google.com>2009-09-29 11:01:03 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-09-29 11:01:03 -0400
commitd3d1faf6a74496ea4435fd057c6a2cad49f3e523 (patch)
tree9f1cc0e2efb9a4fe42bb6b57c087d8450a854dc1 /fs
parentf3dc272fd5e2ae08244796bb39e7e1ce4b25d3b3 (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')
-rw-r--r--fs/ext4/ext4_jbd2.h6
-rw-r--r--fs/ext4/namei.c3
-rw-r--r--fs/ext4/super.c42
3 files changed, 38 insertions, 13 deletions
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 139fb8cb87e4..a2865980342f 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -161,11 +161,13 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
161handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks); 161handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
162int __ext4_journal_stop(const char *where, handle_t *handle); 162int __ext4_journal_stop(const char *where, handle_t *handle);
163 163
164#define EXT4_NOJOURNAL_HANDLE ((handle_t *) 0x1) 164#define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096)
165 165
166/* Note: Do not use this for NULL handles. This is only to determine if
167 * a properly allocated handle is using a journal or not. */
166static inline int ext4_handle_valid(handle_t *handle) 168static inline int ext4_handle_valid(handle_t *handle)
167{ 169{
168 if (handle == EXT4_NOJOURNAL_HANDLE) 170 if ((unsigned long)handle < EXT4_NOJOURNAL_MAX_REF_COUNT)
169 return 0; 171 return 0;
170 return 1; 172 return 1;
171} 173}
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 42f81d285cd5..7c8fe80bacdd 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2076,7 +2076,8 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
2076 struct ext4_iloc iloc; 2076 struct ext4_iloc iloc;
2077 int err = 0; 2077 int err = 0;
2078 2078
2079 if (!ext4_handle_valid(handle)) 2079 /* ext4_handle_valid() assumes a valid handle_t pointer */
2080 if (handle && !ext4_handle_valid(handle))
2080 return 0; 2081 return 0;
2081 2082
2082 mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock); 2083 mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
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 */
194static 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 */
210static 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;