commit 87a4ec3db6097bb3c28e252c24922e38d907fd09
Author: Samuel Thibault <samuel.thibault@ens-lyon.org>
Date:   Sat Mar 7 22:55:19 2026 +0100

    ext2fs: Make sure to flush translator entry before releasing it
    
    If the entry was still pending a write, we want to drop that before
    releasing the block and possibly re-using it for a file pager.

diff --git a/ext2fs/ext2fs.h b/ext2fs/ext2fs.h
index 8054f16f2..350cb14a6 100644
--- a/ext2fs/ext2fs.h
+++ b/ext2fs/ext2fs.h
@@ -473,6 +473,7 @@ extern pthread_spinlock_t modified_global_blocks_lock;
 extern int global_block_modified (block_t block);
 extern void record_global_poke (void *ptr);
 extern void sync_global_ptr (void *bptr, int wait);
+extern void flush_global_ptr (void *ptr, int wait);
 extern void record_indir_poke (struct node *node, void *ptr);
 extern void sync_global (int wait);
 extern void alloc_sync (struct node *np);
@@ -522,6 +523,18 @@ sync_global_ptr (void *ptr, int wait)
   _disk_cache_block_deref (block_ptr);
   pager_sync_some (diskfs_disk_pager,
 		   block_ptr - disk_cache, block_size, wait);
+}
+
+/* This drops data of non-file block.  */
+EXT2FS_EI void
+flush_global_ptr (void *ptr, int wait)
+{
+  block_t block = boffs_block (bptr_offs (ptr));
+  void *block_ptr = bptr (block);
+  ext2_debug ("(%p -> %u)", ptr, block);
+  _disk_cache_block_deref (block_ptr);
+  pager_flush_some (diskfs_disk_pager,
+		    block_ptr - disk_cache, block_size, wait);
 
 }
 
diff --git a/ext2fs/inode.c b/ext2fs/inode.c
index 8d10af013..4e5051186 100644
--- a/ext2fs/inode.c
+++ b/ext2fs/inode.c
@@ -621,6 +621,7 @@ diskfs_set_translator (struct node *np, const char *name, mach_msg_type_number_t
       && use_xattr_translator_records)
     {
       daddr_t blkno;
+      void *block;
       struct ext2_inode *di;
 
       di = dino_ref (np->cache_id);
@@ -635,6 +636,10 @@ diskfs_set_translator (struct node *np, const char *name, mach_msg_type_number_t
 	  di->i_translator = htole32 (0);
 	  diskfs_node_disknode (np)->info_i_translator = 0;
 	  record_global_poke (di);
+
+	  /* Flush any pending write before releasing.  */
+	  block = disk_cache_block_ref (blkno);
+	  flush_global_ptr (block, 1);
 	  ext2_free_blocks (blkno, 1);
 
 	  np->dn_stat.st_blocks -= 1 << log2_stat_blocks_per_fs_block;
@@ -676,6 +681,7 @@ diskfs_set_translator (struct node *np, const char *name, mach_msg_type_number_t
     {
       /* Use legacy translator record when xattr is not supported */
       daddr_t blkno;
+      void *block;
       struct ext2_inode *di;
       char buf[block_size];
 
@@ -738,6 +744,10 @@ diskfs_set_translator (struct node *np, const char *name, mach_msg_type_number_t
 	  di->i_translator = htole32 (0);
 	  diskfs_node_disknode (np)->info_i_translator = 0;
 	  record_global_poke (di);
+
+	  /* Flush any pending write before releasing.  */
+	  block = disk_cache_block_ref (blkno);
+	  flush_global_ptr (block, 1);
 	  ext2_free_blocks (blkno, 1);
 
 	  np->dn_stat.st_blocks -= 1 << log2_stat_blocks_per_fs_block;
diff --git a/ext2fs/xattr.c b/ext2fs/xattr.c
index d3b7d1a7d..a1e02368f 100644
--- a/ext2fs/xattr.c
+++ b/ext2fs/xattr.c
@@ -471,8 +471,10 @@ ext2_free_xattr_block (struct node *np)
     {
        ext2_debug("free block %d", blkno);
 
-       disk_cache_block_deref (block);
-       ext2_free_blocks(blkno, 1);
+       /* Flush any pending write before releasing.  */
+       flush_global_ptr (block, 1);
+
+       ext2_free_blocks (blkno, 1);
 
        np->dn_stat.st_blocks -= 1 << log2_stat_blocks_per_fs_block;
        np->dn_stat.st_mode &= ~S_IPTRANS;
