Linux EXT4 FS development
 help / color / mirror / Atom feed
* [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