mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
ext4: enable scoped NOFS when starting a handle in nojournal mode
The jbd2 layer enables NOFS mode using memalloc_nofs_{save,restore}()
while a handle is active. We need to do the same in nojournal mode so
that it is safe to remove GFP_NOFS flags while a jbd2 handle is
active.
This will require that we actually allocate a real handle, but with an
h_invalid flag set, so there is a place to put the saved memalloc
context.
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Andreas Dilger <adilger@dilger.ca>
This commit is contained in:
+21
-13
@@ -33,14 +33,22 @@ int ext4_inode_journal_mode(struct inode *inode)
|
||||
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);
|
||||
BUG_ON(handle && !handle->h_invalid);
|
||||
|
||||
ref_cnt++;
|
||||
handle = (handle_t *)ref_cnt;
|
||||
|
||||
current->journal_info = handle;
|
||||
if (!handle) {
|
||||
handle = jbd2_alloc_handle(GFP_NOFS);
|
||||
if (!handle)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
handle->h_invalid = 1;
|
||||
/*
|
||||
* This is done by start_this_handle() if journalling
|
||||
* is enabled.
|
||||
*/
|
||||
handle->saved_alloc_context = memalloc_nofs_save();
|
||||
current->journal_info = handle;
|
||||
}
|
||||
handle->h_ref++;
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -48,14 +56,14 @@ static handle_t *ext4_get_nojournal(void)
|
||||
/* Decrement the non-pointer handle value */
|
||||
static void ext4_put_nojournal(handle_t *handle)
|
||||
{
|
||||
unsigned long ref_cnt = (unsigned long)handle;
|
||||
BUG_ON(handle->h_ref == 0);
|
||||
|
||||
BUG_ON(ref_cnt == 0);
|
||||
|
||||
ref_cnt--;
|
||||
handle = (handle_t *)ref_cnt;
|
||||
|
||||
current->journal_info = handle;
|
||||
handle->h_ref--;
|
||||
if (handle->h_ref == 0) {
|
||||
memalloc_nofs_restore(handle->saved_alloc_context);
|
||||
jbd2_free_handle(handle);
|
||||
current->journal_info = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+1
-5
@@ -182,15 +182,11 @@ handle_t *__ext4_journal_start_sb(struct inode *inode, struct super_block *sb,
|
||||
int rsv_blocks, int revoke_creds);
|
||||
int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle);
|
||||
|
||||
#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 ((unsigned long)handle < EXT4_NOJOURNAL_MAX_REF_COUNT)
|
||||
return 0;
|
||||
return 1;
|
||||
return (handle && !handle->h_invalid);
|
||||
}
|
||||
|
||||
static inline void ext4_handle_sync(handle_t *handle)
|
||||
|
||||
@@ -94,6 +94,7 @@ EXPORT_SYMBOL(jbd2_journal_init_jbd_inode);
|
||||
EXPORT_SYMBOL(jbd2_journal_release_jbd_inode);
|
||||
EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate);
|
||||
EXPORT_SYMBOL(jbd2_inode_cache);
|
||||
EXPORT_SYMBOL(jbd2_handle_cache);
|
||||
|
||||
#ifdef CONFIG_JBD2_DEBUG
|
||||
void __jbd2_debug(int level, const char *file, const char *func,
|
||||
|
||||
@@ -513,6 +513,7 @@ struct jbd2_journal_handle
|
||||
unsigned int h_sync: 1;
|
||||
unsigned int h_reserved: 1;
|
||||
unsigned int h_aborted: 1;
|
||||
unsigned int h_invalid: 1;
|
||||
unsigned int h_type: 8;
|
||||
unsigned int h_line_no: 16;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user