Message ID | 53b793f2e7a7788f89cda97de565cfc1577cbf75.1733890357.git.wqu@suse.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | btrfs: enhance ordered extent double freeing detection | expand |
Hi Qu, kernel test robot noticed the following build errors: [auto build test ERROR on kdave/for-next] [also build test ERROR on linus/master v6.13-rc2 next-20241211] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Qu-Wenruo/btrfs-enhance-ordered-extent-double-freeing-detection/20241211-121647 base: https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next patch link: https://lore.kernel.org/r/53b793f2e7a7788f89cda97de565cfc1577cbf75.1733890357.git.wqu%40suse.com patch subject: [PATCH] btrfs: enhance ordered extent double freeing detection config: i386-buildonly-randconfig-003-20241211 (https://download.01.org/0day-ci/archive/20241212/202412120136.6OwbbtZf-lkp@intel.com/config) compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241212/202412120136.6OwbbtZf-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202412120136.6OwbbtZf-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from fs/btrfs/ordered-data.c:7: In file included from include/linux/blkdev.h:9: In file included from include/linux/blk_types.h:10: In file included from include/linux/bvec.h:10: In file included from include/linux/highmem.h:8: In file included from include/linux/cacheflush.h:5: In file included from arch/x86/include/asm/cacheflush.h:5: In file included from include/linux/mm.h:2223: include/linux/vmstat.h:518:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion] 518 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" | ~~~~~~~~~~~ ^ ~~~ >> fs/btrfs/ordered-data.c:200:10: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' 200 | entry->finished_bitmap = bitmap_zalloc( | ~~~~~ ^ fs/btrfs/ordered-data.c:202:15: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' 202 | if (!entry->finished_bitmap) { | ~~~~~ ^ fs/btrfs/ordered-data.c:380:38: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' 380 | nr_set = bitmap_count_set(ordered->finished_bitmap, start_bit, nbits); | ~~~~~~~ ^ fs/btrfs/ordered-data.c:388:17: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' 388 | ordered->finished_bitmap); | ~~~~~~~ ^ fs/btrfs/messages.h:44:41: note: expanded from macro 'btrfs_crit' 44 | btrfs_printk(fs_info, KERN_CRIT fmt, ##args) | ^~~~ fs/btrfs/messages.h:27:32: note: expanded from macro 'btrfs_printk' 27 | _btrfs_printk(fs_info, fmt, ##args) | ^~~~ fs/btrfs/ordered-data.c:390:23: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' 390 | bitmap_set(ordered->finished_bitmap, start_bit, nbits); | ~~~~~~~ ^ fs/btrfs/ordered-data.c:418:37: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' 418 | if (WARN_ON(!bitmap_full(ordered->finished_bitmap, | ~~~~~~~ ^ include/asm-generic/bug.h:123:25: note: expanded from macro 'WARN_ON' 123 | int __ret_warn_on = !!(condition); \ | ^~~~~~~~~ fs/btrfs/ordered-data.c:426:14: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' 426 | ordered->finished_bitmap); | ~~~~~~~ ^ fs/btrfs/messages.h:44:41: note: expanded from macro 'btrfs_crit' 44 | btrfs_printk(fs_info, KERN_CRIT fmt, ##args) | ^~~~ fs/btrfs/messages.h:27:32: note: expanded from macro 'btrfs_printk' 27 | _btrfs_printk(fs_info, fmt, ##args) | ^~~~ fs/btrfs/ordered-data.c:675:23: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' 675 | bitmap_free(entry->finished_bitmap); | ~~~~~ ^ 1 warning and 8 errors generated. vim +200 fs/btrfs/ordered-data.c 147 148 static struct btrfs_ordered_extent *alloc_ordered_extent( 149 struct btrfs_inode *inode, u64 file_offset, u64 num_bytes, 150 u64 ram_bytes, u64 disk_bytenr, u64 disk_num_bytes, 151 u64 offset, unsigned long flags, int compress_type) 152 { 153 struct btrfs_ordered_extent *entry; 154 int ret; 155 u64 qgroup_rsv = 0; 156 157 if (flags & 158 ((1 << BTRFS_ORDERED_NOCOW) | (1 << BTRFS_ORDERED_PREALLOC))) { 159 /* For nocow write, we can release the qgroup rsv right now */ 160 ret = btrfs_qgroup_free_data(inode, NULL, file_offset, num_bytes, &qgroup_rsv); 161 if (ret < 0) 162 return ERR_PTR(ret); 163 } else { 164 /* 165 * The ordered extent has reserved qgroup space, release now 166 * and pass the reserved number for qgroup_record to free. 167 */ 168 ret = btrfs_qgroup_release_data(inode, file_offset, num_bytes, &qgroup_rsv); 169 if (ret < 0) 170 return ERR_PTR(ret); 171 } 172 entry = kmem_cache_zalloc(btrfs_ordered_extent_cache, GFP_NOFS); 173 if (!entry) 174 return ERR_PTR(-ENOMEM); 175 176 entry->file_offset = file_offset; 177 entry->num_bytes = num_bytes; 178 entry->ram_bytes = ram_bytes; 179 entry->disk_bytenr = disk_bytenr; 180 entry->disk_num_bytes = disk_num_bytes; 181 entry->offset = offset; 182 entry->bytes_left = num_bytes; 183 entry->inode = BTRFS_I(igrab(&inode->vfs_inode)); 184 entry->compress_type = compress_type; 185 entry->truncated_len = (u64)-1; 186 entry->qgroup_rsv = qgroup_rsv; 187 entry->flags = flags; 188 refcount_set(&entry->refs, 1); 189 init_waitqueue_head(&entry->wait); 190 INIT_LIST_HEAD(&entry->list); 191 INIT_LIST_HEAD(&entry->log_list); 192 INIT_LIST_HEAD(&entry->root_extent_list); 193 INIT_LIST_HEAD(&entry->work_list); 194 INIT_LIST_HEAD(&entry->bioc_list); 195 init_completion(&entry->completion); 196 197 if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) { 198 struct btrfs_fs_info *fs_info = inode->root->fs_info; 199 > 200 entry->finished_bitmap = bitmap_zalloc( 201 num_bytes >> fs_info->sectorsize_bits, GFP_NOFS); 202 if (!entry->finished_bitmap) { 203 kmem_cache_free(btrfs_ordered_extent_cache, entry); 204 return ERR_PTR(-ENOMEM); 205 } 206 } 207 /* 208 * We don't need the count_max_extents here, we can assume that all of 209 * that work has been done at higher layers, so this is truly the 210 * smallest the extent is going to get. 211 */ 212 spin_lock(&inode->lock); 213 btrfs_mod_outstanding_extents(inode, 1); 214 spin_unlock(&inode->lock); 215 216 return entry; 217 } 218
Hi Qu, kernel test robot noticed the following build errors: [auto build test ERROR on kdave/for-next] [also build test ERROR on linus/master v6.13-rc2 next-20241211] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Qu-Wenruo/btrfs-enhance-ordered-extent-double-freeing-detection/20241211-121647 base: https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next patch link: https://lore.kernel.org/r/53b793f2e7a7788f89cda97de565cfc1577cbf75.1733890357.git.wqu%40suse.com patch subject: [PATCH] btrfs: enhance ordered extent double freeing detection config: i386-buildonly-randconfig-005-20241211 (https://download.01.org/0day-ci/archive/20241212/202412120129.tEVBFsR6-lkp@intel.com/config) compiler: gcc-12 (Debian 12.2.0-14) 12.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241212/202412120129.tEVBFsR6-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202412120129.tEVBFsR6-lkp@intel.com/ All errors (new ones prefixed by >>): fs/btrfs/ordered-data.c: In function 'alloc_ordered_extent': >> fs/btrfs/ordered-data.c:200:22: error: 'struct btrfs_ordered_extent' has no member named 'finished_bitmap' 200 | entry->finished_bitmap = bitmap_zalloc( | ^~ fs/btrfs/ordered-data.c:202:27: error: 'struct btrfs_ordered_extent' has no member named 'finished_bitmap' 202 | if (!entry->finished_bitmap) { | ^~ fs/btrfs/ordered-data.c: In function 'can_finish_ordered_extent': fs/btrfs/ordered-data.c:380:50: error: 'struct btrfs_ordered_extent' has no member named 'finished_bitmap' 380 | nr_set = bitmap_count_set(ordered->finished_bitmap, start_bit, nbits); | ^~ In file included from fs/btrfs/ordered-data.c:10: fs/btrfs/ordered-data.c:388:43: error: 'struct btrfs_ordered_extent' has no member named 'finished_bitmap' 388 | ordered->finished_bitmap); | ^~ fs/btrfs/messages.h:36:41: note: in definition of macro 'btrfs_printk' 36 | btrfs_no_printk(fs_info, fmt, ##args) | ^~~~ fs/btrfs/ordered-data.c:382:25: note: in expansion of macro 'btrfs_crit' 382 | btrfs_crit(fs_info, | ^~~~~~~~~~ fs/btrfs/ordered-data.c:390:35: error: 'struct btrfs_ordered_extent' has no member named 'finished_bitmap' 390 | bitmap_set(ordered->finished_bitmap, start_bit, nbits); | ^~ In file included from arch/x86/include/asm/bug.h:99, from include/linux/bug.h:5, from include/linux/thread_info.h:13, from include/linux/spinlock.h:60, from include/linux/mmzone.h:8, from include/linux/gfp.h:7, from include/linux/slab.h:16, from fs/btrfs/ordered-data.c:6: fs/btrfs/ordered-data.c:418:49: error: 'struct btrfs_ordered_extent' has no member named 'finished_bitmap' 418 | if (WARN_ON(!bitmap_full(ordered->finished_bitmap, | ^~ include/asm-generic/bug.h:171:32: note: in definition of macro 'WARN_ON' 171 | int __ret_warn_on = !!(condition); \ | ^~~~~~~~~ fs/btrfs/ordered-data.c:426:40: error: 'struct btrfs_ordered_extent' has no member named 'finished_bitmap' 426 | ordered->finished_bitmap); | ^~ fs/btrfs/messages.h:36:41: note: in definition of macro 'btrfs_printk' 36 | btrfs_no_printk(fs_info, fmt, ##args) | ^~~~ fs/btrfs/ordered-data.c:420:25: note: in expansion of macro 'btrfs_crit' 420 | btrfs_crit(fs_info, | ^~~~~~~~~~ fs/btrfs/ordered-data.c: In function 'btrfs_put_ordered_extent': fs/btrfs/ordered-data.c:675:42: error: 'struct btrfs_ordered_extent' has no member named 'finished_bitmap' 675 | bitmap_free(entry->finished_bitmap); | ^~ vim +200 fs/btrfs/ordered-data.c 147 148 static struct btrfs_ordered_extent *alloc_ordered_extent( 149 struct btrfs_inode *inode, u64 file_offset, u64 num_bytes, 150 u64 ram_bytes, u64 disk_bytenr, u64 disk_num_bytes, 151 u64 offset, unsigned long flags, int compress_type) 152 { 153 struct btrfs_ordered_extent *entry; 154 int ret; 155 u64 qgroup_rsv = 0; 156 157 if (flags & 158 ((1 << BTRFS_ORDERED_NOCOW) | (1 << BTRFS_ORDERED_PREALLOC))) { 159 /* For nocow write, we can release the qgroup rsv right now */ 160 ret = btrfs_qgroup_free_data(inode, NULL, file_offset, num_bytes, &qgroup_rsv); 161 if (ret < 0) 162 return ERR_PTR(ret); 163 } else { 164 /* 165 * The ordered extent has reserved qgroup space, release now 166 * and pass the reserved number for qgroup_record to free. 167 */ 168 ret = btrfs_qgroup_release_data(inode, file_offset, num_bytes, &qgroup_rsv); 169 if (ret < 0) 170 return ERR_PTR(ret); 171 } 172 entry = kmem_cache_zalloc(btrfs_ordered_extent_cache, GFP_NOFS); 173 if (!entry) 174 return ERR_PTR(-ENOMEM); 175 176 entry->file_offset = file_offset; 177 entry->num_bytes = num_bytes; 178 entry->ram_bytes = ram_bytes; 179 entry->disk_bytenr = disk_bytenr; 180 entry->disk_num_bytes = disk_num_bytes; 181 entry->offset = offset; 182 entry->bytes_left = num_bytes; 183 entry->inode = BTRFS_I(igrab(&inode->vfs_inode)); 184 entry->compress_type = compress_type; 185 entry->truncated_len = (u64)-1; 186 entry->qgroup_rsv = qgroup_rsv; 187 entry->flags = flags; 188 refcount_set(&entry->refs, 1); 189 init_waitqueue_head(&entry->wait); 190 INIT_LIST_HEAD(&entry->list); 191 INIT_LIST_HEAD(&entry->log_list); 192 INIT_LIST_HEAD(&entry->root_extent_list); 193 INIT_LIST_HEAD(&entry->work_list); 194 INIT_LIST_HEAD(&entry->bioc_list); 195 init_completion(&entry->completion); 196 197 if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) { 198 struct btrfs_fs_info *fs_info = inode->root->fs_info; 199 > 200 entry->finished_bitmap = bitmap_zalloc( 201 num_bytes >> fs_info->sectorsize_bits, GFP_NOFS); 202 if (!entry->finished_bitmap) { 203 kmem_cache_free(btrfs_ordered_extent_cache, entry); 204 return ERR_PTR(-ENOMEM); 205 } 206 } 207 /* 208 * We don't need the count_max_extents here, we can assume that all of 209 * that work has been done at higher layers, so this is truly the 210 * smallest the extent is going to get. 211 */ 212 spin_lock(&inode->lock); 213 btrfs_mod_outstanding_extents(inode, 1); 214 spin_unlock(&inode->lock); 215 216 return entry; 217 } 218
在 2024/12/12 04:41, kernel test robot 写道: > Hi Qu, > > kernel test robot noticed the following build errors: > > [auto build test ERROR on kdave/for-next] > [also build test ERROR on linus/master v6.13-rc2 next-20241211] > [If your patch is applied to the wrong git tree, kindly drop us a note. > And when submitting patch, we suggest to use '--base' as documented in > https://git-scm.com/docs/git-format-patch#_base_tree_information] > > url: https://github.com/intel-lab-lkp/linux/commits/Qu-Wenruo/btrfs-enhance-ordered-extent-double-freeing-detection/20241211-121647 > base: https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next > patch link: https://lore.kernel.org/r/53b793f2e7a7788f89cda97de565cfc1577cbf75.1733890357.git.wqu%40suse.com > patch subject: [PATCH] btrfs: enhance ordered extent double freeing detection > config: i386-buildonly-randconfig-003-20241211 (https://download.01.org/0day-ci/archive/20241212/202412120136.6OwbbtZf-lkp@intel.com/config) > compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99) > reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241212/202412120136.6OwbbtZf-lkp@intel.com/reproduce) > > If you fix the issue in a separate patch/commit (i.e. not just a new version of > the same patch/commit), kindly add following tags > | Reported-by: kernel test robot <lkp@intel.com> > | Closes: https://lore.kernel.org/oe-kbuild-all/202412120136.6OwbbtZf-lkp@intel.com/ > > All errors (new ones prefixed by >>): > > In file included from fs/btrfs/ordered-data.c:7: > In file included from include/linux/blkdev.h:9: > In file included from include/linux/blk_types.h:10: > In file included from include/linux/bvec.h:10: > In file included from include/linux/highmem.h:8: > In file included from include/linux/cacheflush.h:5: > In file included from arch/x86/include/asm/cacheflush.h:5: > In file included from include/linux/mm.h:2223: > include/linux/vmstat.h:518:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion] > 518 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" > | ~~~~~~~~~~~ ^ ~~~ >>> fs/btrfs/ordered-data.c:200:10: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' > 200 | entry->finished_bitmap = bitmap_zalloc( > | ~~~~~ ^ I don't know why but it looks like IS_ENABLED() is not exactly doing the #ifdef #endif, thus those checks are not fully skipped in this case. Anyway I'll change it to the more traditional #ifdef #endif instead. Thanks for the report. Qu > fs/btrfs/ordered-data.c:202:15: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' > 202 | if (!entry->finished_bitmap) { > | ~~~~~ ^ > fs/btrfs/ordered-data.c:380:38: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' > 380 | nr_set = bitmap_count_set(ordered->finished_bitmap, start_bit, nbits); > | ~~~~~~~ ^ > fs/btrfs/ordered-data.c:388:17: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' > 388 | ordered->finished_bitmap); > | ~~~~~~~ ^ > fs/btrfs/messages.h:44:41: note: expanded from macro 'btrfs_crit' > 44 | btrfs_printk(fs_info, KERN_CRIT fmt, ##args) > | ^~~~ > fs/btrfs/messages.h:27:32: note: expanded from macro 'btrfs_printk' > 27 | _btrfs_printk(fs_info, fmt, ##args) > | ^~~~ > fs/btrfs/ordered-data.c:390:23: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' > 390 | bitmap_set(ordered->finished_bitmap, start_bit, nbits); > | ~~~~~~~ ^ > fs/btrfs/ordered-data.c:418:37: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' > 418 | if (WARN_ON(!bitmap_full(ordered->finished_bitmap, > | ~~~~~~~ ^ > include/asm-generic/bug.h:123:25: note: expanded from macro 'WARN_ON' > 123 | int __ret_warn_on = !!(condition); \ > | ^~~~~~~~~ > fs/btrfs/ordered-data.c:426:14: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' > 426 | ordered->finished_bitmap); > | ~~~~~~~ ^ > fs/btrfs/messages.h:44:41: note: expanded from macro 'btrfs_crit' > 44 | btrfs_printk(fs_info, KERN_CRIT fmt, ##args) > | ^~~~ > fs/btrfs/messages.h:27:32: note: expanded from macro 'btrfs_printk' > 27 | _btrfs_printk(fs_info, fmt, ##args) > | ^~~~ > fs/btrfs/ordered-data.c:675:23: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' > 675 | bitmap_free(entry->finished_bitmap); > | ~~~~~ ^ > 1 warning and 8 errors generated. > > > vim +200 fs/btrfs/ordered-data.c > > 147 > 148 static struct btrfs_ordered_extent *alloc_ordered_extent( > 149 struct btrfs_inode *inode, u64 file_offset, u64 num_bytes, > 150 u64 ram_bytes, u64 disk_bytenr, u64 disk_num_bytes, > 151 u64 offset, unsigned long flags, int compress_type) > 152 { > 153 struct btrfs_ordered_extent *entry; > 154 int ret; > 155 u64 qgroup_rsv = 0; > 156 > 157 if (flags & > 158 ((1 << BTRFS_ORDERED_NOCOW) | (1 << BTRFS_ORDERED_PREALLOC))) { > 159 /* For nocow write, we can release the qgroup rsv right now */ > 160 ret = btrfs_qgroup_free_data(inode, NULL, file_offset, num_bytes, &qgroup_rsv); > 161 if (ret < 0) > 162 return ERR_PTR(ret); > 163 } else { > 164 /* > 165 * The ordered extent has reserved qgroup space, release now > 166 * and pass the reserved number for qgroup_record to free. > 167 */ > 168 ret = btrfs_qgroup_release_data(inode, file_offset, num_bytes, &qgroup_rsv); > 169 if (ret < 0) > 170 return ERR_PTR(ret); > 171 } > 172 entry = kmem_cache_zalloc(btrfs_ordered_extent_cache, GFP_NOFS); > 173 if (!entry) > 174 return ERR_PTR(-ENOMEM); > 175 > 176 entry->file_offset = file_offset; > 177 entry->num_bytes = num_bytes; > 178 entry->ram_bytes = ram_bytes; > 179 entry->disk_bytenr = disk_bytenr; > 180 entry->disk_num_bytes = disk_num_bytes; > 181 entry->offset = offset; > 182 entry->bytes_left = num_bytes; > 183 entry->inode = BTRFS_I(igrab(&inode->vfs_inode)); > 184 entry->compress_type = compress_type; > 185 entry->truncated_len = (u64)-1; > 186 entry->qgroup_rsv = qgroup_rsv; > 187 entry->flags = flags; > 188 refcount_set(&entry->refs, 1); > 189 init_waitqueue_head(&entry->wait); > 190 INIT_LIST_HEAD(&entry->list); > 191 INIT_LIST_HEAD(&entry->log_list); > 192 INIT_LIST_HEAD(&entry->root_extent_list); > 193 INIT_LIST_HEAD(&entry->work_list); > 194 INIT_LIST_HEAD(&entry->bioc_list); > 195 init_completion(&entry->completion); > 196 > 197 if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) { > 198 struct btrfs_fs_info *fs_info = inode->root->fs_info; > 199 > > 200 entry->finished_bitmap = bitmap_zalloc( > 201 num_bytes >> fs_info->sectorsize_bits, GFP_NOFS); > 202 if (!entry->finished_bitmap) { > 203 kmem_cache_free(btrfs_ordered_extent_cache, entry); > 204 return ERR_PTR(-ENOMEM); > 205 } > 206 } > 207 /* > 208 * We don't need the count_max_extents here, we can assume that all of > 209 * that work has been done at higher layers, so this is truly the > 210 * smallest the extent is going to get. > 211 */ > 212 spin_lock(&inode->lock); > 213 btrfs_mod_outstanding_extents(inode, 1); > 214 spin_unlock(&inode->lock); > 215 > 216 return entry; > 217 } > 218 >
On Thu, Dec 12, 2024 at 06:17:37AM +1030, Qu Wenruo wrote: > >>> fs/btrfs/ordered-data.c:200:10: error: no member named 'finished_bitmap' in 'struct btrfs_ordered_extent' > > 200 | entry->finished_bitmap = bitmap_zalloc( > > | ~~~~~ ^ > > I don't know why but it looks like IS_ENABLED() is not exactly doing the > #ifdef #endif, thus those checks are not fully skipped in this case. It's never been equvalent to ifdef/endif, it evaluates to 0 or 1 if the config option is enabled or not but otherwise the source code is still compiled. The compiler then finds out it's dead code and eliminates it.
diff --git a/fs/btrfs/misc.h b/fs/btrfs/misc.h index 0d599fd847c9..438887a1ca32 100644 --- a/fs/btrfs/misc.h +++ b/fs/btrfs/misc.h @@ -163,4 +163,32 @@ static inline bool bitmap_test_range_all_zero(const unsigned long *addr, return (found_set == start + nbits); } +/* + * Count how many bits are set in the bitmap. + * + * Similar to bitmap_weight() but accepts a subrange of the bitmap. + */ +static inline unsigned int bitmap_count_set(const unsigned long *addr, + unsigned long start, + unsigned long nbits) +{ + const unsigned long bitmap_nbits = start + nbits; + unsigned long cur = start; + unsigned long total_set = 0; + + while (cur < bitmap_nbits) { + unsigned long found_zero; + unsigned long found_set; + + found_zero = find_next_zero_bit(addr, bitmap_nbits, cur); + total_set += found_zero - cur; + + cur = found_zero; + if (cur >= bitmap_nbits) + break; + found_set = find_next_bit(addr, bitmap_nbits, cur); + cur = found_set; + } + return total_set; +} #endif diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 30eceaf829a7..1b1f14aa13d5 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -194,6 +194,16 @@ static struct btrfs_ordered_extent *alloc_ordered_extent( INIT_LIST_HEAD(&entry->bioc_list); init_completion(&entry->completion); + if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) { + struct btrfs_fs_info *fs_info = inode->root->fs_info; + + entry->finished_bitmap = bitmap_zalloc( + num_bytes >> fs_info->sectorsize_bits, GFP_NOFS); + if (!entry->finished_bitmap) { + kmem_cache_free(btrfs_ordered_extent_cache, entry); + return ERR_PTR(-ENOMEM); + } + } /* * We don't need the count_max_extents here, we can assume that all of * that work has been done at higher layers, so this is truly the @@ -356,13 +366,38 @@ static bool can_finish_ordered_extent(struct btrfs_ordered_extent *ordered, btrfs_folio_clear_ordered(fs_info, folio, file_offset, len); } + if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) { + unsigned long start_bit; + unsigned long nbits; + unsigned long nr_set; + + ASSERT(file_offset >= ordered->file_offset); + ASSERT(file_offset + len <= ordered->file_offset + ordered->num_bytes); + + start_bit = (file_offset - ordered->file_offset) >> fs_info->sectorsize_bits; + nbits = len >> fs_info->sectorsize_bits; + + nr_set = bitmap_count_set(ordered->finished_bitmap, start_bit, nbits); + if (WARN_ON(nr_set)) { + btrfs_crit(fs_info, +"double ordered extent accounting, root=%llu ino=%llu OE offset=%llu OE len=%llu range offset=%llu range len=%llu already finished len=%lu finish_bitmap=%*pbl", + btrfs_root_id(inode->root), btrfs_ino(inode), + ordered->file_offset, ordered->num_bytes, + file_offset, len, nr_set << fs_info->sectorsize_bits, + (int)(ordered->num_bytes >> fs_info->sectorsize_bits), + ordered->finished_bitmap); + } + bitmap_set(ordered->finished_bitmap, start_bit, nbits); + len -= (nr_set << fs_info->sectorsize_bits); + } + /* Now we're fine to update the accounting. */ if (WARN_ON_ONCE(len > ordered->bytes_left)) { btrfs_crit(fs_info, -"bad ordered extent accounting, root=%llu ino=%llu OE offset=%llu OE len=%llu to_dec=%llu left=%llu", +"bad ordered extent accounting, root=%llu ino=%llu OE offset=%llu OE len=%llu range start=%llu range len=%llu left=%llu", btrfs_root_id(inode->root), btrfs_ino(inode), ordered->file_offset, ordered->num_bytes, - len, ordered->bytes_left); + file_offset, len, ordered->bytes_left); ordered->bytes_left = 0; } else { ordered->bytes_left -= len; @@ -379,6 +414,18 @@ static bool can_finish_ordered_extent(struct btrfs_ordered_extent *ordered, * the finish_func to be executed. */ set_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags); + if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) { + if (WARN_ON(!bitmap_full(ordered->finished_bitmap, + ordered->num_bytes >> fs_info->sectorsize_bits))) { + btrfs_crit(fs_info, +"ordered extent finished bitmap desync, root=%llu ino=%llu OE offset=%llu OE len=%llu bytes_left=%llu bitmap=%*pbl", + btrfs_root_id(inode->root), btrfs_ino(inode), + ordered->file_offset, ordered->num_bytes, + ordered->bytes_left, + (int)(ordered->num_bytes >> fs_info->sectorsize_bits), + ordered->finished_bitmap); + } + } cond_wake_up(&ordered->wait); refcount_inc(&ordered->refs); trace_btrfs_ordered_extent_mark_finished(inode, ordered); @@ -624,6 +671,8 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) list_del(&sum->list); kvfree(sum); } + if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) + bitmap_free(entry->finished_bitmap); kmem_cache_free(btrfs_ordered_extent_cache, entry); } } diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 4e152736d06c..f04a2f7a593a 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h @@ -154,6 +154,15 @@ struct btrfs_ordered_extent { struct list_head work_list; struct list_head bioc_list; + +#ifdef CONFIG_BTRFS_DEBUG + /* + * Set if one block has finished. + * + * To catch double freeing with more accuracy. + */ + unsigned long *finished_bitmap; +#endif }; int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent);
With recent bugs exposed through run_delalloc_range() failure, the importance of detecting double accounting is obvious. Currently the way to detect such errors is to just check if we underflow the btrfs_ordered_extent::bytes_left member. That's fine but that only shows the length we're trying to decrease, not enough to show the problem. Here we enhance the situation by: - Introduce btrfs_ordered_extent::finished_bitmap This is a new bitmap to indicate which blocks are already finished. This bitmap will be initialized at alloc_ordered_extent() and release when the ordered extent is freed. - Detect any already finished block during can_finish_ordered_extent() If double accounting detected, show the full range we're trying and the bitmap. - Make sure the bitmap is all set when the OE is finished - Show the full range we're finishing for the existing double accounting detection This is to enhance the code to work with the new run_delalloc_range() error messages. This will have extra memory and runtime cost, now an ordered extent can have as large as 4K memory just for the finished_bitmap, and extra operations to detect such double accounting. Thus this double accounting detection is only enabled for CONFIG_BTRFS_DEBUG build for developers. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/misc.h | 28 ++++++++++++++++++++++ fs/btrfs/ordered-data.c | 53 +++++++++++++++++++++++++++++++++++++++-- fs/btrfs/ordered-data.h | 9 +++++++ 3 files changed, 88 insertions(+), 2 deletions(-)