cluster-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
From: Steven Whitehouse <swhiteho@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [GFS2 PATCH][v2] GFS2: Add function gfs2_get_iomap
Date: Mon, 15 Aug 2016 09:41:54 +0100	[thread overview]
Message-ID: <57B18052.4060101@redhat.com> (raw)
In-Reply-To: <225698410.3303717.1471031879076.JavaMail.zimbra@redhat.com>

Hi,


On 12/08/16 20:57, Bob Peterson wrote:
> ----- Original Message -----
> | > +int gfs2_get_iomap(struct inode *inode, loff_t pos, ssize_t length,
> | > +		   struct iomap *iomap)
> | This function should be merged with gfs2_block_map() I think, so that
> | gfs2_block_map just becomes a wrapper (which will eventually go away)
> | for this function. Otherwise we will have two parallel but slightly
> | different implementations of block mapping to maintain.
>
> Yes, I guess that's worth doing. I did this and included the revised
> patch below.
That wasn't quite what I was thinking of... comments below

> | Is there a better way to pass the gh from the begin function to the end
> | function? I'm sure that will work, but it is the kind of thing that
> | might trip up the unwary in the future,
>
> Yeah, I would have passed the gh another way, but Christoph didn't
> leave a good way in the iomap interface or other bits to do it.
> At least not that I can see. It might be worth changing the interface to
> add that flexibility for other file systems that might want to do this
> as well. It would be easy enough to add a (void *)private pointer or
> something that can be passed around. Christoph and Steve: Would you
> prefer I plumb something before I do the GFS2 bits?
>
> For now, here's a replacement patch which still does it the only way possible.
I think there is a possible race in case a single process opens the same 
file twice, unless I'm missing something there? It is an unlikely thing 
for someone to do, but we should allow for it anyway.

> Bob Peterson
> Red Hat File Systems
> ---
> This patch replaces the GFS2 fiemap implementation that used vfs
> function __generic_block_fiemap with a new implementation that uses
> the new iomap-based fiemap interface. This allows GFS2's fiemap to
> skip holes. The time to do filefrag on a file with a 1 petabyte hole
> is reduced from several days or weeks, to milliseconds. Note that
> there are Kconfig changes that affect everyone.
>
> Signed-off-by: Bob Peterson <rpeterso@redhat.com>
> ---
> diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
> index 90c6a8f..f8fa955 100644
> --- a/fs/gfs2/Kconfig
> +++ b/fs/gfs2/Kconfig
> @@ -25,6 +25,7 @@ config GFS2_FS
>   config GFS2_FS_LOCKING_DLM
>   	bool "GFS2 DLM locking"
>   	depends on (GFS2_FS!=n) && NET && INET && (IPV6 || IPV6=n) && \
> +		FS_IOMAP && \
>   		CONFIGFS_FS && SYSFS && (DLM=y || DLM=GFS2_FS)
>   	help
>   	  Multiple node locking module for GFS2
> diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
> index 6e2bec1..839f2a6 100644
> --- a/fs/gfs2/bmap.c
> +++ b/fs/gfs2/bmap.c
> @@ -588,6 +588,66 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
>   }
>   
>   /**
> + * hole_size - figure out the size of a hole
> + * @ip: The inode
> + * @lblock: The logical starting block number
> + * @mp: The metapath
> + *
> + * Returns: The hole size in bytes
> + *
> + */
> +static u64 hole_size(struct inode *inode, sector_t lblock, struct metapath *mp)
> +{
> +	struct gfs2_inode *ip = GFS2_I(inode);
> +	struct gfs2_sbd *sdp = GFS2_SB(inode);
> +	struct metapath mp_eof;
> +	unsigned int end_of_metadata = ip->i_height - 1;
> +	u64 factor = 1;
> +	int hgt = end_of_metadata;
> +	u64 holesz = 0, holestep;
> +	const __be64 *first, *end, *ptr;
> +	const struct buffer_head *bh;
> +	u64 isize = i_size_read(inode);
> +	int zeroptrs;
> +	bool done = false;
> +
> +	/* Get another metapath, to the very last byte */
> +	find_metapath(sdp, (isize - 1) >> inode->i_blkbits, &mp_eof,
> +		      ip->i_height);
> +	for (hgt = end_of_metadata; hgt >= 0 && !done; hgt--) {
> +		bh = mp->mp_bh[hgt];
> +		if (bh) {
> +			zeroptrs = 0;
> +			first = metapointer(hgt, mp);
> +			end = (const __be64 *)(bh->b_data + bh->b_size);
> +
> +			for (ptr = first; ptr < end; ptr++) {
> +				if (*ptr) {
> +					done = true;
> +					break;
> +				} else {
> +					zeroptrs++;
> +				}
> +			}
> +		} else {
> +			zeroptrs = sdp->sd_inptrs;
> +		}
> +		holestep = min(factor * zeroptrs,
> +			       isize - (lblock + (zeroptrs * holesz)));
> +		holesz += holestep;
> +		if (lblock + holesz >= isize)
> +			return holesz << inode->i_blkbits;
> +
> +		factor *= sdp->sd_inptrs;
> +		if (hgt && (mp->mp_list[hgt - 1] < mp_eof.mp_list[hgt - 1]))
> +			(mp->mp_list[hgt - 1])++;
> +	}
> +	return holesz << inode->i_blkbits;
> +}
> +
> +enum gfs2_map_type { maptype_iomap = 1, maptype_bhmap = 2, };
> +
> +/**
>    * gfs2_block_map - Map a block from an inode to a disk block
>    * @inode: The inode
>    * @lblock: The logical block number
> @@ -601,13 +661,14 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
>    * Returns: errno
>    */
>   
> -int gfs2_block_map(struct inode *inode, sector_t lblock,
> -		   struct buffer_head *bh_map, int create)
> +static int _gfs2_block_map(struct inode *inode, loff_t pos, ssize_t length,
> +			   int create, enum gfs2_map_type maptype,
> +			   void *iomap_or_bh)
>   {
Lets just call this gfs2_iomap() and make it take a struct iomap only. 
Then we'd have a new function with
the original name:

int gfs2_block_map(struct inode *inode, sector_t lblock,
		   struct buffer_head *bh_map, int create)

{
     struct iomap *iom;

     /* Set up iomap based on bh */

     ret = gfs2_iomap(inode, pos, length, create, &iom);

     /* Copy iomap data back into bh */

    return ret;
}

That way we use iomap as the main structure through our block mapping 
functions, removing the bh from those code paths entirely and 
gfs2_block_map() becomes a function for backwards compatibility that 
we'd eventually be able to remove. It also means that you don't need the 
gfs2_map_type enum either,

Steve.




  reply	other threads:[~2016-08-15  8:41 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1311582922.2518701.1470926538032.JavaMail.zimbra@redhat.com>
2016-08-11 14:59 ` [Cluster-devel] [GFS2 PATCH] GFS2: Add function gfs2_get_iomap Bob Peterson
2016-08-11 15:26   ` Steven Whitehouse
2016-08-12 19:57     ` [Cluster-devel] [GFS2 PATCH][v2] " Bob Peterson
2016-08-15  8:41       ` Steven Whitehouse [this message]
2016-08-18 18:21       ` Christoph Hellwig
2016-08-11 17:17   ` [Cluster-devel] [GFS2 PATCH] " Christoph Hellwig

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=57B18052.4060101@redhat.com \
    --to=swhiteho@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).