All of lore.kernel.org
 help / color / mirror / Atom feed
From: kernel test robot <lkp@intel.com>
To: Nicolas Bretz <bretznic@gmail.com>,
	tytso@mit.edu, adilger.kernel@dilger.ca
Cc: oe-kbuild-all@lists.linux.dev, linux-ext4@vger.kernel.org,
	Nicolas Bretz <bretznic@gmail.com>,
	kernel test robot <lkp@intel.com>
Subject: Re: [PATCH v2] ext4: clear extent index structure after file delete
Date: Mon, 21 Jul 2025 06:41:09 +0800	[thread overview]
Message-ID: <202507210558.sazSHcm1-lkp@intel.com> (raw)
In-Reply-To: <20250718122654.1431747-1-bretznic@gmail.com>

Hi Nicolas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on tytso-ext4/dev]
[also build test WARNING on linus/master v6.16-rc6 next-20250718]
[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/Nicolas-Bretz/ext4-clear-extent-index-structure-after-file-delete/20250718-202802
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git dev
patch link:    https://lore.kernel.org/r/20250718122654.1431747-1-bretznic%40gmail.com
patch subject: [PATCH v2] ext4: clear extent index structure after file delete
config: csky-randconfig-r121-20250720 (https://download.01.org/0day-ci/archive/20250721/202507210558.sazSHcm1-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 11.5.0
reproduce: (https://download.01.org/0day-ci/archive/20250721/202507210558.sazSHcm1-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/202507210558.sazSHcm1-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> fs/ext4/extents.c:3065:55: sparse: sparse: restricted __le16 degrades to integer

vim +3065 fs/ext4/extents.c

  2818	
  2819	int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
  2820				  ext4_lblk_t end)
  2821	{
  2822		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
  2823		int depth = ext_depth(inode);
  2824		struct ext4_ext_path *path = NULL;
  2825		struct ext4_extent_idx *ix = NULL;
  2826		struct partial_cluster partial;
  2827		handle_t *handle;
  2828		int i = 0, err = 0;
  2829		int flags = EXT4_EX_NOCACHE | EXT4_EX_NOFAIL;
  2830	
  2831		partial.pclu = 0;
  2832		partial.lblk = 0;
  2833		partial.state = initial;
  2834	
  2835		ext_debug(inode, "truncate since %u to %u\n", start, end);
  2836	
  2837		/* probably first extent we're gonna free will be last in block */
  2838		handle = ext4_journal_start_with_revoke(inode, EXT4_HT_TRUNCATE,
  2839				depth + 1,
  2840				ext4_free_metadata_revoke_credits(inode->i_sb, depth));
  2841		if (IS_ERR(handle))
  2842			return PTR_ERR(handle);
  2843	
  2844	again:
  2845		trace_ext4_ext_remove_space(inode, start, end, depth);
  2846	
  2847		/*
  2848		 * Check if we are removing extents inside the extent tree. If that
  2849		 * is the case, we are going to punch a hole inside the extent tree
  2850		 * so we have to check whether we need to split the extent covering
  2851		 * the last block to remove so we can easily remove the part of it
  2852		 * in ext4_ext_rm_leaf().
  2853		 */
  2854		if (end < EXT_MAX_BLOCKS - 1) {
  2855			struct ext4_extent *ex;
  2856			ext4_lblk_t ee_block, ex_end, lblk;
  2857			ext4_fsblk_t pblk;
  2858	
  2859			/* find extent for or closest extent to this block */
  2860			path = ext4_find_extent(inode, end, NULL, flags);
  2861			if (IS_ERR(path)) {
  2862				ext4_journal_stop(handle);
  2863				return PTR_ERR(path);
  2864			}
  2865			depth = ext_depth(inode);
  2866			/* Leaf not may not exist only if inode has no blocks at all */
  2867			ex = path[depth].p_ext;
  2868			if (!ex) {
  2869				if (depth) {
  2870					EXT4_ERROR_INODE(inode,
  2871							 "path[%d].p_hdr == NULL",
  2872							 depth);
  2873					err = -EFSCORRUPTED;
  2874				}
  2875				goto out;
  2876			}
  2877	
  2878			ee_block = le32_to_cpu(ex->ee_block);
  2879			ex_end = ee_block + ext4_ext_get_actual_len(ex) - 1;
  2880	
  2881			/*
  2882			 * See if the last block is inside the extent, if so split
  2883			 * the extent at 'end' block so we can easily remove the
  2884			 * tail of the first part of the split extent in
  2885			 * ext4_ext_rm_leaf().
  2886			 */
  2887			if (end >= ee_block && end < ex_end) {
  2888	
  2889				/*
  2890				 * If we're going to split the extent, note that
  2891				 * the cluster containing the block after 'end' is
  2892				 * in use to avoid freeing it when removing blocks.
  2893				 */
  2894				if (sbi->s_cluster_ratio > 1) {
  2895					pblk = ext4_ext_pblock(ex) + end - ee_block + 1;
  2896					partial.pclu = EXT4_B2C(sbi, pblk);
  2897					partial.state = nofree;
  2898				}
  2899	
  2900				/*
  2901				 * Split the extent in two so that 'end' is the last
  2902				 * block in the first new extent. Also we should not
  2903				 * fail removing space due to ENOSPC so try to use
  2904				 * reserved block if that happens.
  2905				 */
  2906				path = ext4_force_split_extent_at(handle, inode, path,
  2907								  end + 1, 1);
  2908				if (IS_ERR(path)) {
  2909					err = PTR_ERR(path);
  2910					goto out;
  2911				}
  2912			} else if (sbi->s_cluster_ratio > 1 && end >= ex_end &&
  2913				   partial.state == initial) {
  2914				/*
  2915				 * If we're punching, there's an extent to the right.
  2916				 * If the partial cluster hasn't been set, set it to
  2917				 * that extent's first cluster and its state to nofree
  2918				 * so it won't be freed should it contain blocks to be
  2919				 * removed. If it's already set (tofree/nofree), we're
  2920				 * retrying and keep the original partial cluster info
  2921				 * so a cluster marked tofree as a result of earlier
  2922				 * extent removal is not lost.
  2923				 */
  2924				lblk = ex_end + 1;
  2925				err = ext4_ext_search_right(inode, path, &lblk, &pblk,
  2926							    NULL, flags);
  2927				if (err < 0)
  2928					goto out;
  2929				if (pblk) {
  2930					partial.pclu = EXT4_B2C(sbi, pblk);
  2931					partial.state = nofree;
  2932				}
  2933			}
  2934		}
  2935		/*
  2936		 * We start scanning from right side, freeing all the blocks
  2937		 * after i_size and walking into the tree depth-wise.
  2938		 */
  2939		depth = ext_depth(inode);
  2940		if (path) {
  2941			int k = i = depth;
  2942			while (--k > 0)
  2943				path[k].p_block =
  2944					le16_to_cpu(path[k].p_hdr->eh_entries)+1;
  2945		} else {
  2946			path = kcalloc(depth + 1, sizeof(struct ext4_ext_path),
  2947				       GFP_NOFS | __GFP_NOFAIL);
  2948			if (path == NULL) {
  2949				ext4_journal_stop(handle);
  2950				return -ENOMEM;
  2951			}
  2952			path[0].p_maxdepth = path[0].p_depth = depth;
  2953			path[0].p_hdr = ext_inode_hdr(inode);
  2954			i = 0;
  2955	
  2956			if (ext4_ext_check(inode, path[0].p_hdr, depth, 0)) {
  2957				err = -EFSCORRUPTED;
  2958				goto out;
  2959			}
  2960		}
  2961		err = 0;
  2962	
  2963		while (i >= 0 && err == 0) {
  2964			if (i == depth) {
  2965				/* this is leaf block */
  2966				err = ext4_ext_rm_leaf(handle, inode, path,
  2967						       &partial, start, end);
  2968				/* root level has p_bh == NULL, brelse() eats this */
  2969				ext4_ext_path_brelse(path + i);
  2970				i--;
  2971				continue;
  2972			}
  2973	
  2974			/* this is index block */
  2975			if (!path[i].p_hdr) {
  2976				ext_debug(inode, "initialize header\n");
  2977				path[i].p_hdr = ext_block_hdr(path[i].p_bh);
  2978			}
  2979	
  2980			if (!path[i].p_idx) {
  2981				/* this level hasn't been touched yet */
  2982				path[i].p_idx = EXT_LAST_INDEX(path[i].p_hdr);
  2983				path[i].p_block = le16_to_cpu(path[i].p_hdr->eh_entries)+1;
  2984				ext_debug(inode, "init index ptr: hdr 0x%p, num %d\n",
  2985					  path[i].p_hdr,
  2986					  le16_to_cpu(path[i].p_hdr->eh_entries));
  2987			} else {
  2988				/* we were already here, see at next index */
  2989				path[i].p_idx--;
  2990			}
  2991	
  2992			ext_debug(inode, "level %d - index, first 0x%p, cur 0x%p\n",
  2993					i, EXT_FIRST_INDEX(path[i].p_hdr),
  2994					path[i].p_idx);
  2995			if (ext4_ext_more_to_rm(path + i)) {
  2996				struct buffer_head *bh;
  2997				/* go to the next level */
  2998				ext_debug(inode, "move to level %d (block %llu)\n",
  2999					  i + 1, ext4_idx_pblock(path[i].p_idx));
  3000				memset(path + i + 1, 0, sizeof(*path));
  3001				bh = read_extent_tree_block(inode, path[i].p_idx,
  3002							    depth - i - 1, flags);
  3003				if (IS_ERR(bh)) {
  3004					/* should we reset i_size? */
  3005					err = PTR_ERR(bh);
  3006					break;
  3007				}
  3008				/* Yield here to deal with large extent trees.
  3009				 * Should be a no-op if we did IO above. */
  3010				cond_resched();
  3011				if (WARN_ON(i + 1 > depth)) {
  3012					err = -EFSCORRUPTED;
  3013					break;
  3014				}
  3015				path[i + 1].p_bh = bh;
  3016	
  3017				/* save actual number of indexes since this
  3018				 * number is changed at the next iteration */
  3019				path[i].p_block = le16_to_cpu(path[i].p_hdr->eh_entries);
  3020				i++;
  3021			} else {
  3022				/* we finished processing this index, go up */
  3023				if (path[i].p_hdr->eh_entries == 0 && i > 0) {
  3024					/* index is empty, remove it;
  3025					 * handle must be already prepared by the
  3026					 * truncatei_leaf() */
  3027					err = ext4_ext_rm_idx(handle, inode, path, i);
  3028				}
  3029				/* root level has p_bh == NULL, brelse() eats this */
  3030				ext4_ext_path_brelse(path + i);
  3031				i--;
  3032				ext_debug(inode, "return to level %d\n", i);
  3033			}
  3034		}
  3035	
  3036		trace_ext4_ext_remove_space_done(inode, start, end, depth, &partial,
  3037						 path->p_hdr->eh_entries);
  3038	
  3039		/*
  3040		 * if there's a partial cluster and we have removed the first extent
  3041		 * in the file, then we also free the partial cluster, if any
  3042		 */
  3043		if (partial.state == tofree && err == 0) {
  3044			int flags = get_default_free_blocks_flags(inode);
  3045	
  3046			if (ext4_is_pending(inode, partial.lblk))
  3047				flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER;
  3048			ext4_free_blocks(handle, inode, NULL,
  3049					 EXT4_C2B(sbi, partial.pclu),
  3050					 sbi->s_cluster_ratio, flags);
  3051			if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)
  3052				ext4_rereserve_cluster(inode, partial.lblk);
  3053			partial.state = initial;
  3054		}
  3055	
  3056		/* TODO: flexible tree reduction should be here */
  3057		if (path->p_hdr->eh_entries == 0) {
  3058			/*
  3059			 * truncate to zero freed all the tree,
  3060			 * so we need to correct eh_depth
  3061			 */
  3062			err = ext4_ext_get_access(handle, inode, path);
  3063			if (err == 0) {
  3064				ix = EXT_FIRST_INDEX(path->p_hdr);
> 3065				if (ix && ext_inode_hdr(inode)->eh_depth > 0)
  3066					ext4_idx_store_pblock(ix, 0);
  3067				ext_inode_hdr(inode)->eh_depth = 0;
  3068				ext_inode_hdr(inode)->eh_max =
  3069					cpu_to_le16(ext4_ext_space_root(inode, 0));
  3070				err = ext4_ext_dirty(handle, inode, path);
  3071			}
  3072		}
  3073	out:
  3074		ext4_free_ext_path(path);
  3075		path = NULL;
  3076		if (err == -EAGAIN)
  3077			goto again;
  3078		ext4_journal_stop(handle);
  3079	
  3080		return err;
  3081	}
  3082	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

      reply	other threads:[~2025-07-20 22:42 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-18 12:26 [PATCH v2] ext4: clear extent index structure after file delete Nicolas Bretz
2025-07-20 22:41 ` kernel test robot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=202507210558.sazSHcm1-lkp@intel.com \
    --to=lkp@intel.com \
    --cc=adilger.kernel@dilger.ca \
    --cc=bretznic@gmail.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=oe-kbuild-all@lists.linux.dev \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.