Skip to content

Commit

Permalink
ext4: Handle nested ext4_journal_start/stop calls without a journal
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Curt Wohlgemuth authored and Theodore Ts'o committed Sep 29, 2009
1 parent f3dc272 commit d3d1faf
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 13 deletions.
6 changes: 4 additions & 2 deletions fs/ext4/ext4_jbd2.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,13 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle,
handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
int __ext4_journal_stop(const char *where, handle_t *handle);

#define EXT4_NOJOURNAL_HANDLE ((handle_t *) 0x1)
#define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096)

/* Note: Do not use this for NULL handles. This is only to determine if
* a properly allocated handle is using a journal or not. */
static inline int ext4_handle_valid(handle_t *handle)
{
if (handle == EXT4_NOJOURNAL_HANDLE)
if ((unsigned long)handle < EXT4_NOJOURNAL_MAX_REF_COUNT)
return 0;
return 1;
}
Expand Down
3 changes: 2 additions & 1 deletion fs/ext4/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -2076,7 +2076,8 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
struct ext4_iloc iloc;
int err = 0;

if (!ext4_handle_valid(handle))
/* ext4_handle_valid() assumes a valid handle_t pointer */
if (handle && !ext4_handle_valid(handle))
return 0;

mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
Expand Down
42 changes: 32 additions & 10 deletions fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,36 @@ void ext4_itable_unused_set(struct super_block *sb,
bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
}


/* Just increment the non-pointer handle value */
static handle_t *ext4_get_nojournal(void)
{
handle_t *handle = current->journal_info;
unsigned long ref_cnt = (unsigned long)handle;

BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);

ref_cnt++;
handle = (handle_t *)ref_cnt;

current->journal_info = handle;
return handle;
}


/* Decrement the non-pointer handle value */
static void ext4_put_nojournal(handle_t *handle)
{
unsigned long ref_cnt = (unsigned long)handle;

BUG_ON(ref_cnt == 0);

ref_cnt--;
handle = (handle_t *)ref_cnt;

current->journal_info = handle;
}

/*
* Wrappers for jbd2_journal_start/end.
*
Expand All @@ -215,11 +245,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
}
return jbd2_journal_start(journal, nblocks);
}
/*
* We're not journaling, return the appropriate indication.
*/
current->journal_info = EXT4_NOJOURNAL_HANDLE;
return current->journal_info;
return ext4_get_nojournal();
}

/*
Expand All @@ -235,11 +261,7 @@ int __ext4_journal_stop(const char *where, handle_t *handle)
int rc;

if (!ext4_handle_valid(handle)) {
/*
* Do this here since we don't call jbd2_journal_stop() in
* no-journal mode.
*/
current->journal_info = NULL;
ext4_put_nojournal(handle);
return 0;
}
sb = handle->h_transaction->t_journal->j_private;
Expand Down

0 comments on commit d3d1faf

Please sign in to comment.