All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mingming Cao <cmm@us.ibm.com>
To: "Amit K. Arora" <aarora@linux.vnet.ibm.com>
Cc: Alex Tomas <alex@clusterfs.com>,
	linux-ext4@vger.kernel.org, suparna@in.ibm.com
Subject: Re: [PATCH 1/1 version2] Extent overlap bugfix in ext4
Date: Thu, 04 Jan 2007 10:50:00 -0800	[thread overview]
Message-ID: <459D4C58.5010502@us.ibm.com> (raw)
In-Reply-To: <20070104172329.GA23612@amitarora.in.ibm.com>

Hi, Amit,

Have you looked at ext4_ext_walk_space()? It calculate the right extent 
length to allocate to avoid overlap before calling block allocation 
callback function is called.

Amit K. Arora wrote:
>  /*
> + * ext4_ext_check_overlap:
> + * check if a portion of the "newext" extent overlaps with an
> + * existing extent.
> + *
> + * If there is an overlap discovered, it returns the (logical) block
> + * number of the first block in the next extent (the existing extent
> + * which covers few of the new requested blocks)
> + * If there is no overlap found, it returns 0.
> + */

What if the start logical block of the exisitng extent is 0 and there is 
overlap? I think that is possible. For example, the exisitng extent is 
(0,100) and you want to insert new extent (0,500), this will certainly 
fail to report the overlap.


> +unsigned int ext4_ext_check_overlap(struct inode *inode,

We shall be consistant with other data type used for logical block, 
right now is unsigned long. Probably replace that with ext4_fsblk_t type 
when that cleanup is introduced.

> +					struct ext4_extent *newext,
> +					struct ext4_ext_path *path)
> +{
> +	unsigned int depth, b1, len1, b2;
> +
unsigned long type for b1 and b2.

> +	b1 = le32_to_cpu(newext->ee_block);
> +	len1 = le16_to_cpu(newext->ee_len);
> +	depth = ext_depth(inode);
> +	if (!path[depth].p_ext)
> +		goto out;
> +	b2 = le32_to_cpu(path[depth].p_ext->ee_block);
> +
> +	/* get the next allocated block if the extent in the path
> +	 * is before the requested block(s) */
> +	if (b2 < b1) {
> +		b2 = ext4_ext_next_allocated_block(path);
> +		if (b2 == EXT_MAX_BLOCK)
> +			goto out;
> +	}
> +
> +	if (b1 + len1 > b2)
> +		return b2;
> +out:
> +	return 0;
> +}
> +

Since this overlap check function is called inside 
ext4_ext_insert_extent(), I think this function should check for all 
kinds of overlaps. Here you only check if the new extent is overlap with 
the next extent. Looking at ext4_ext_walk_space(), there are total three 
kinds of overlaps:
1) righ port of new extent overlap with path->p_ext,
2) left port of new extent overlap with path->p_ext
2) right port of new extent overlap with next extent

I think we are almost repeating the same logic in ext4_ext_walk_space() 
here.

> +/*
>   * ext4_ext_insert_extent:
>   * tries to merge requsted extent into the existing extent or
>   * inserts requested extent as new one into the tree,
> @@ -1133,12 +1170,25 @@ int ext4_ext_insert_extent(handle_t *han
>  	struct ext4_extent *nearex; /* nearest extent */
>  	struct ext4_ext_path *npath = NULL;
>  	int depth, len, err, next;
> +	unsigned int oblock;
>
unsigned long type for oblock

>  	BUG_ON(newext->ee_len == 0);
>  	depth = ext_depth(inode);
>  	ex = path[depth].p_ext;
>  	BUG_ON(path[depth].p_hdr == NULL);
> 
> +	/* check for overlap */
> +	oblock = ext4_ext_check_overlap(inode, newext, path);
> +	if (oblock) {
> +		printk(KERN_ERR "ERROR: newext=%u/%u overlaps with an "
> +				"existing extent, which starts with %u\n",
> +				le32_to_cpu(newext->ee_block),
> +				le16_to_cpu(newext->ee_len),
> +				oblock);
> +		ext4_ext_show_leaf(inode, path);
> +		BUG();
> +	}

How about return true or false from ext4_ext_check_overlap()? Inside 
that function put the correct new extent logical block number and extent 
length that safe to insert? Afterall the returning oblock is used in 
ext4_ext_get_blocks() to calculate the safe extent to allocate.

> +
>  	/* try to insert block into found extent and return */
>  	if (ex && ext4_can_extents_be_merged(inode, ex, newext)) {
>  		ext_debug("append %d block to %d:%d (from %llu)\n",
> @@ -1984,6 +2034,10 @@ int ext4_ext_get_blocks(handle_t *handle
>  		 */
>  		if (ee_len > EXT_MAX_LEN)
>  			goto out2;
> +
> +		if (iblock < ee_block && iblock + max_blocks >= ee_block)
> +			allocated = ee_block - iblock;
> +
>  		/* if found extent covers block, simply return it */
>  	        if (iblock >= ee_block && iblock < ee_block + ee_len) {
>  			newblock = iblock - ee_block + ee_start;

Here I realize that the way that ext4_ext_get_blocks() handles the 
requested extent has hole on the right side is: simply returns the left 
port of the extent which already has blocks allocated. This is actually 
what non_extent get_blocks does also. caller of get_blocks() including 
preallocation code in ioctl will continue calling get_blocks to allocate 
blocks for the hole.

Probably we shall make this clear in the comment.
> @@ -2016,7 +2070,17 @@ int ext4_ext_get_blocks(handle_t *handle
> 
>  	/* allocate new block */
>  	goal = ext4_ext_find_goal(inode, path, iblock);
> -	allocated = max_blocks;
> +
> +	/* Check if we can really insert (iblock)::(iblock+max_blocks) extent */
> +	newex.ee_block = cpu_to_le32(iblock);
> +	if (!allocated) {
> +		newex.ee_len = cpu_to_le16(max_blocks);
> +		allocated = ext4_ext_check_overlap(inode, &newex, path);
> +		if (allocated)
> +			allocated = allocated - iblock;
> +		else
> +			allocated = max_blocks;
> +	}
>  	newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err);
>  	if (!newblock)
>  		goto out2;
> @@ -2024,7 +2088,6 @@ int ext4_ext_get_blocks(handle_t *handle
>  			goal, newblock, allocated);
> 
>  	/* try to insert new extent into found leaf and return */
> -	newex.ee_block = cpu_to_le32(iblock);
>  	ext4_ext_store_pblock(&newex, newblock);
>  	newex.ee_len = cpu_to_le16(allocated);
>  	err = ext4_ext_insert_extent(handle, inode, path, &newex);
> Index: linux-2.6.19.prealloc/include/linux/ext4_fs_extents.h
> ===================================================================
> --- linux-2.6.19.prealloc.orig/include/linux/ext4_fs_extents.h
> +++ linux-2.6.19.prealloc/include/linux/ext4_fs_extents.h
> @@ -190,6 +190,7 @@ ext4_ext_invalidate_cache(struct inode *
> 
>  extern int ext4_extent_tree_init(handle_t *, struct inode *);
>  extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *);
> +extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
>  extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
>  extern int ext4_ext_walk_space(struct inode *, unsigned long, unsigned long, ext_prepare_callback, void *);
>  extern struct ext4_ext_path * ext4_ext_find_extent(struct inode *, int, struct ext4_ext_path *);
> 

  reply	other threads:[~2007-01-04 18:50 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-01-02  9:09 [PATCH 1/1] Extent overlap bugfix in ext4 Amit K. Arora
2007-01-02  9:25 ` Alex Tomas
2007-01-02  9:47   ` Amit K. Arora
2007-01-03  9:44     ` Alex Tomas
2007-01-03 18:07       ` Mingming Cao
2007-01-04  8:13         ` Amit K. Arora
2007-01-04 10:04         ` Alex Tomas
2007-01-04 18:23           ` Mingming Cao
2007-01-03  1:35 ` Mingming Cao
2007-01-03  6:06   ` Amit K. Arora
2007-01-04  8:54     ` [PATCH 1/1 version2] " Amit K. Arora
2007-01-04 10:25       ` Alex Tomas
2007-01-04 11:16         ` Amit K. Arora
2007-01-04 10:39       ` Alex Tomas
2007-01-04 11:27         ` Amit K. Arora
2007-01-04 11:37           ` Alex Tomas
2007-01-04 17:23             ` Amit K. Arora
2007-01-04 18:50               ` Mingming Cao [this message]
2007-01-04 19:19                 ` Alex Tomas
2007-01-05 12:13                 ` Amit K. Arora
2007-01-09  5:51                   ` [PATCH 1/1 version3] " Amit K. Arora
2007-01-04 19:03               ` [PATCH 1/1 version2] " Alex Tomas
2007-01-04 19:47                 ` Mingming Cao
2007-01-05  6:18                   ` Amit K. Arora

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=459D4C58.5010502@us.ibm.com \
    --to=cmm@us.ibm.com \
    --cc=aarora@linux.vnet.ibm.com \
    --cc=alex@clusterfs.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=suparna@in.ibm.com \
    /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.