mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-14 04:41:26 +00:00
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>
This commit is contained in:
parent
f3dc272fd5
commit
d3d1faf6a7
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*
|
||||
@ -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();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user