* [PATCH -v2] ext4: enable scoped NOFS when starting a handle in nojournal mode
@ 2026-07-16 14:48 Theodore Ts'o
2026-07-16 19:45 ` Andreas Dilger
0 siblings, 1 reply; 2+ messages in thread
From: Theodore Ts'o @ 2026-07-16 14:48 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
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>
---
fs/ext4/ext4_jbd2.c | 36 ++++++++++++++++++++++--------------
fs/ext4/ext4_jbd2.h | 6 +-----
include/linux/jbd2.h | 1 +
3 files changed, 24 insertions(+), 19 deletions(-)
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index 9a8c225f2753..b4dacd1a89e7 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -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);
-
- ref_cnt++;
- handle = (handle_t *)ref_cnt;
-
- current->journal_info = handle;
+ BUG_ON(handle && !handle->h_invalid);
+
+ 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;
+ }
}
/*
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 63d17c5201b5..2fbf48b3dfe2 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -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)
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index b68561187e90..7348fdadc810 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -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;
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH -v2] ext4: enable scoped NOFS when starting a handle in nojournal mode
2026-07-16 14:48 [PATCH -v2] ext4: enable scoped NOFS when starting a handle in nojournal mode Theodore Ts'o
@ 2026-07-16 19:45 ` Andreas Dilger
0 siblings, 0 replies; 2+ messages in thread
From: Andreas Dilger @ 2026-07-16 19:45 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: Ext4 Developers List
On Jul 16, 2026, at 08:48, Theodore Ts'o <tytso@mit.edu> wrote:
>
> 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.
If you wanted to avoid an allocation for each nojournal handle on 64-bit
systems, you could put a magic number in the high 32 bits of the handle
pointer (which is unlikely to conflict with real memory addresses),
and the PF_* flags in the low 32 bits.
While the memory savings would be minimal (32 bytes for minimum kmalloc),
it would avoid a potential new allocation failure path for that mode.
> diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
> index b68561187e90..7348fdadc810 100644
> --- a/include/linux/jbd2.h
> +++ b/include/linux/jbd2.h
> @@ -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;
Not sure if it makes much difference, but should h_line_no be aligned on a
16-bit offset and h_type aligned on an 8-bit offset by adding an
"unsigned int h_unused:4" field before h_type, or reorder them so the 1-bit
fields are at the end? That would allow the integer fields to be accessed
directly rather than also having to shift them.
Cheers, Andreas
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-16 19:46 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16 14:48 [PATCH -v2] ext4: enable scoped NOFS when starting a handle in nojournal mode Theodore Ts'o
2026-07-16 19:45 ` Andreas Dilger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox