[Ocfs2-devel] [PATCH 1/3] ocfs2: new structure to implment discontiguous local alloc bitmap

Joel Becker jlbec at evilplan.org
Mon May 7 17:05:33 PDT 2012


On Mon, May 07, 2012 at 04:21:28PM -0700, Srinivas Eeda wrote:
> Current local alloc handles single contiguous free chunk of clusters. This
> patch enhances local alloc to handle discontigous free chunks. It adds a new
> ocfs2_local_alloc_rec structure which tracks single contiguous free chunk. An
> array of these sit in the bitmap itself and track discontiguous chunks. In
> best case there is only one record and increases as the filesystem gets
> fragmented. Number of records at a time are limited depending on the size
> of the bitmap and the max limit is defined by OCFS2_MAX_LOCAL_ALLOC_RECS.
> 
> Signed-off-by: Srinivas Eeda <srinivas.eeda at oracle.com>
> ---
>  fs/ocfs2/localalloc.c |   10 ++++++++++
>  fs/ocfs2/ocfs2.h      |    8 ++++++++
>  fs/ocfs2/ocfs2_fs.h   |   48 ++++++++++++++++++++++++++++++++++++++++++------
>  3 files changed, 60 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
> index 210c352..4190e53 100644
> --- a/fs/ocfs2/localalloc.c
> +++ b/fs/ocfs2/localalloc.c
> @@ -48,6 +48,16 @@
>  
>  #define OCFS2_LOCAL_ALLOC(dinode)	(&((dinode)->id2.i_lab))
>  
> +#define OCFS2_LOCAL_ALLOC_REC_SZ(la)	(le16_to_cpu(la->la_rec_count) *\
> +					 sizeof(struct ocfs2_local_alloc_rec))
> +#define OCFS2_LOCAL_ALLOC_BITMAP(la)    ((char *)(&(la->la_recs)) +\
> +					 OCFS2_LOCAL_ALLOC_REC_SZ(la))
> +#define OCFS2_LOCAL_ALLOC_BITS_PER_REC (sizeof(struct ocfs2_local_alloc_rec)*8)
> +
> +/* Maximum number of local alloc records */
> +#define OCFS2_MAX_LOCAL_ALLOC_REC_LIMIT	128
> +
> +
>  static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc);
>  
>  static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
> diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
> index d355e6e..d4c36d2 100644
> --- a/fs/ocfs2/ocfs2.h
> +++ b/fs/ocfs2/ocfs2.h
> @@ -367,6 +367,7 @@ struct ocfs2_super
>  							 * by osb_lock */
>  
>  	struct buffer_head *local_alloc_bh;
> +	struct inode	   *local_alloc_inode;
>  
>  	u64 la_last_gd;
>  
> @@ -522,6 +523,13 @@ static inline int ocfs2_supports_discontig_bg(struct ocfs2_super *osb)
>  	return 0;
>  }
>  
> +static inline int ocfs2_supports_discontig_la(struct ocfs2_super *osb)
> +{
> +	if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_DISCONTIG_LA)
> +		return 1;
> +	return 0;
> +}
> +
>  static inline unsigned int ocfs2_link_max(struct ocfs2_super *osb)
>  {
>  	if (ocfs2_supports_indexed_dirs(osb))
> diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
> index 938387a..6a0fe02 100644
> --- a/fs/ocfs2/ocfs2_fs.h
> +++ b/fs/ocfs2/ocfs2_fs.h
> @@ -102,7 +102,8 @@
>  					 | OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS \
>  					 | OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE \
>  					 | OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG	\
> -					 | OCFS2_FEATURE_INCOMPAT_CLUSTERINFO)
> +					 | OCFS2_FEATURE_INCOMPAT_CLUSTERINFO \
> +					 | OCFS2_FEATURE_INCOMPAT_DISCONTIG_LA)
>  #define OCFS2_FEATURE_RO_COMPAT_SUPP	(OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \
>  					 | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \
>  					 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
> @@ -177,6 +178,9 @@
>   */
>  #define OCFS2_FEATURE_INCOMPAT_CLUSTERINFO	0x4000
>  
> +/* Discontiguous local alloc */
> +#define OCFS2_FEATURE_INCOMPAT_DISCONTIG_LA	0x8000

	I really wish this could be an RO_COMPAT flag, but I think that
recovery on RO mounts will break with this.  Mark, please confirm, but I
think it has to be INCOMPAT.

> @@ -664,14 +668,19 @@ struct ocfs2_super_block {
>   * Local allocation bitmap for OCFS2 slots
>   * Note that it exists inside an ocfs2_dinode, so all offsets are
>   * relative to the start of ocfs2_dinode.id2.
> + * Each ocfs2_local_alloc_rec tracks one contigous chunk of clusters.
>   */
> +struct ocfs2_local_alloc_rec {
> +	__le32 la_start;	/* 1st cluster in this extent */
> +	__le32 la_clusters;	/* Number of contiguous clusters */
> +};
> +
>  struct ocfs2_local_alloc
>  {
>  /*00*/	__le32 la_bm_off;	/* Starting bit offset in main bitmap */
>  	__le16 la_size;		/* Size of included bitmap, in bytes */
> -	__le16 la_reserved1;
> -	__le64 la_reserved2;
> -/*10*/	__u8   la_bitmap[0];
> +	__le16 la_rec_count;	/* Number of discontiguous records */
> +	struct ocfs2_local_alloc_rec la_recs[0]; /* Localalloc records */
>  };

	You can't delete la_bitmap.  Any filesystem without DISCONTIG_LA
will be expecting the inline bitmap to start there.

> @@ -1380,11 +1389,24 @@ static inline u16 ocfs2_local_alloc_size(struct super_block *sb)
>  	u16 size;
>  
>  	size = sb->s_blocksize -
> -		offsetof(struct ocfs2_dinode, id2.i_lab.la_bitmap);
> +		offsetof(struct ocfs2_dinode, id2.i_lab.la_recs);
> +	size -= sizeof(struct ocfs2_local_alloc_rec);

	You can't do this without checking for DISCONTIG_LA.  Again,
filesystems without DISCONTIG_LA will be starting at la_bitmap.

Joel


-- 

"If at first you don't succeed, cover all traces that you tried."
                                                        -Unknown

			http://www.jlbec.org/
			jlbec at evilplan.org



More information about the Ocfs2-devel mailing list