linux-f2fs-devel.lists.sourceforge.net archive mirror
 help / color / mirror / Atom feed
* [PATCH] f2fs: large volume support
@ 2014-05-12  6:59 Changman Lee
  2014-05-21  4:33 ` [f2fs-dev] " Jaegeuk Kim
  0 siblings, 1 reply; 5+ messages in thread
From: Changman Lee @ 2014-05-12  6:59 UTC (permalink / raw)
  To: linux-f2fs-devel, linux-fsdevel

f2fs's cp has one page which consists of struct f2fs_checkpoint and
version bitmap of sit and nat. To support lots of segments, we need more
blocks for sit bitmap. So let's arrange sit bitmap as following:
+-----------------+------------+
| f2fs_checkpoint | sit bitmap |
| + nat bitmap    |            |
+-----------------+------------+
0                 4k        N blocks

Signed-off-by: Changman Lee <cm224.lee@samsung.com>
---
 fs/f2fs/checkpoint.c    |   47 ++++++++++++++++++++++++++++++++++++++++++++---
 fs/f2fs/f2fs.h          |   13 +++++++++++--
 include/linux/f2fs_fs.h |    2 ++
 3 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index fe968c7..f418243 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -544,6 +544,32 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
 	cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
 	memcpy(sbi->ckpt, cp_block, blk_size);
 
+	if (is_set_ckpt_flags(sbi->ckpt, CP_LARGE_VOL_FLAG)) {
+		int i, cp_blks;
+		block_t cp_blk_no;
+
+		cp_blk_no = le32_to_cpu(fsb->cp_blkaddr);
+		if (cur_page == cp2)
+			cp_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
+
+		cp_blks = 1 + F2FS_BLK_ALIGN(cp_block->sit_ver_bitmap_bytesize);
+
+		kfree(sbi->ckpt);
+		sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL);
+
+		memcpy(sbi->ckpt, cp_block, blk_size);
+
+		for (i = 1; i < cp_blks; i++) {
+			void *sit_bitmap_ptr;
+			unsigned char *ckpt = (unsigned char *)sbi->ckpt;
+
+			cur_page = get_meta_page(sbi, cp_blk_no + i);
+			sit_bitmap_ptr = page_address(cur_page);
+			memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
+			f2fs_put_page(cur_page, 1);
+		}
+	}
+
 	f2fs_put_page(cp1, 1);
 	f2fs_put_page(cp2, 1);
 	return 0;
@@ -736,6 +762,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 	__u32 crc32 = 0;
 	void *kaddr;
 	int i;
+	int sit_bitmap_blks = 0;
 
 	/*
 	 * This avoids to conduct wrong roll-forward operations and uses
@@ -786,16 +813,21 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 
 	orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
 					/ F2FS_ORPHANS_PER_BLOCK;
-	ckpt->cp_pack_start_sum = cpu_to_le32(1 + orphan_blocks);
+	if (is_set_ckpt_flags(ckpt, CP_LARGE_VOL_FLAG))
+		sit_bitmap_blks = F2FS_BLK_ALIGN(ckpt->sit_ver_bitmap_bytesize);
+	ckpt->cp_pack_start_sum = cpu_to_le32(1 + sit_bitmap_blks +
+			orphan_blocks);
 
 	if (is_umount) {
 		set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
 		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
-			data_sum_blocks + orphan_blocks + NR_CURSEG_NODE_TYPE);
+				sit_bitmap_blks + data_sum_blocks +
+				orphan_blocks + NR_CURSEG_NODE_TYPE);
 	} else {
 		clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
 		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
-			data_sum_blocks + orphan_blocks);
+				sit_bitmap_blks + data_sum_blocks +
+				orphan_blocks);
 	}
 
 	if (sbi->n_orphans)
@@ -821,6 +853,15 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 	set_page_dirty(cp_page);
 	f2fs_put_page(cp_page, 1);
 
+	for (i = 1; i < 1 + sit_bitmap_blks; i++) {
+		cp_page = grab_meta_page(sbi, start_blk++);
+		kaddr = page_address(cp_page);
+		memcpy(kaddr, (char *)ckpt + i * F2FS_BLKSIZE,
+				(1 << sbi->log_blocksize));
+		set_page_dirty(cp_page);
+		f2fs_put_page(cp_page, 1);
+	}
+
 	if (sbi->n_orphans) {
 		write_orphan_inodes(sbi, start_blk);
 		start_blk += orphan_blocks;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 676a2c6..9e147ae 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -764,9 +764,18 @@ static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
 static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
 {
 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
-	int offset = (flag == NAT_BITMAP) ?
+	int offset;
+
+	if (ckpt->ckpt_flags & CP_LARGE_VOL_FLAG) {
+		if (flag == NAT_BITMAP)
+			return &ckpt->sit_nat_version_bitmap;
+		else
+			return ((unsigned char *)ckpt + F2FS_BLKSIZE);
+	} else {
+		offset = (flag == NAT_BITMAP) ?
 			le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
-	return &ckpt->sit_nat_version_bitmap + offset;
+		return &ckpt->sit_nat_version_bitmap + offset;
+	}
 }
 
 static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index 8c03f71..0f0b788 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -19,6 +19,7 @@
 #define F2FS_LOG_SECTORS_PER_BLOCK	3	/* 4KB: F2FS_BLKSIZE */
 #define F2FS_BLKSIZE			4096	/* support only 4KB block */
 #define F2FS_MAX_EXTENSION		64	/* # of extension entries */
+#define F2FS_BLK_ALIGN(x)	(((x) + F2FS_BLKSIZE - 1) / F2FS_BLKSIZE)
 
 #define NULL_ADDR		((block_t)0)	/* used as block_t addresses */
 #define NEW_ADDR		((block_t)-1)	/* used as block_t addresses */
@@ -80,6 +81,7 @@ struct f2fs_super_block {
 /*
  * For checkpoint
  */
+#define CP_LARGE_VOL_FLAG	0x00000010
 #define CP_ERROR_FLAG		0x00000008
 #define CP_COMPACT_SUM_FLAG	0x00000004
 #define CP_ORPHAN_PRESENT_FLAG	0x00000002
-- 
1.7.9.5


------------------------------------------------------------------------------
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [f2fs-dev] [PATCH] f2fs: large volume support
  2014-05-12  6:59 [PATCH] f2fs: large volume support Changman Lee
@ 2014-05-21  4:33 ` Jaegeuk Kim
  2014-05-21  6:46   ` Changman Lee
  0 siblings, 1 reply; 5+ messages in thread
From: Jaegeuk Kim @ 2014-05-21  4:33 UTC (permalink / raw)
  To: Changman Lee; +Cc: linux-f2fs-devel, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 5845 bytes --]

Hi Changman,

2014-05-12 (월), 15:59 +0900, Changman Lee:
> f2fs's cp has one page which consists of struct f2fs_checkpoint and
> version bitmap of sit and nat. To support lots of segments, we need more
> blocks for sit bitmap. So let's arrange sit bitmap as following:
> +-----------------+------------+
> | f2fs_checkpoint | sit bitmap |
> | + nat bitmap    |            |
> +-----------------+------------+
> 0                 4k        N blocks
> 
> Signed-off-by: Changman Lee <cm224.lee@samsung.com>
> ---
>  fs/f2fs/checkpoint.c    |   47 ++++++++++++++++++++++++++++++++++++++++++++---
>  fs/f2fs/f2fs.h          |   13 +++++++++++--
>  include/linux/f2fs_fs.h |    2 ++
>  3 files changed, 57 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> index fe968c7..f418243 100644
> --- a/fs/f2fs/checkpoint.c
> +++ b/fs/f2fs/checkpoint.c
> @@ -544,6 +544,32 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
>  	cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
>  	memcpy(sbi->ckpt, cp_block, blk_size);
>  
> +	if (is_set_ckpt_flags(sbi->ckpt, CP_LARGE_VOL_FLAG)) {
> +		int i, cp_blks;
> +		block_t cp_blk_no;
> +
> +		cp_blk_no = le32_to_cpu(fsb->cp_blkaddr);
> +		if (cur_page == cp2)
> +			cp_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
> +
> +		cp_blks = 1 + F2FS_BLK_ALIGN(cp_block->sit_ver_bitmap_bytesize);

Should covert le32_to_cpu(cp_block->sit_ver_bitmap_bytesize).

> +
> +		kfree(sbi->ckpt);
> +		sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL);

Why does it have to reallocate this and not to handle -ENOMEM correctly?

> +
> +		memcpy(sbi->ckpt, cp_block, blk_size);
> +
> +		for (i = 1; i < cp_blks; i++) {
> +			void *sit_bitmap_ptr;
> +			unsigned char *ckpt = (unsigned char *)sbi->ckpt;
> +
> +			cur_page = get_meta_page(sbi, cp_blk_no + i);
> +			sit_bitmap_ptr = page_address(cur_page);
> +			memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
> +			f2fs_put_page(cur_page, 1);
> +		}
> +	}
> +
>  	f2fs_put_page(cp1, 1);
>  	f2fs_put_page(cp2, 1);
>  	return 0;
> @@ -736,6 +762,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
>  	__u32 crc32 = 0;
>  	void *kaddr;
>  	int i;
> +	int sit_bitmap_blks = 0;
>  
>  	/*
>  	 * This avoids to conduct wrong roll-forward operations and uses
> @@ -786,16 +813,21 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
>  
>  	orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
>  					/ F2FS_ORPHANS_PER_BLOCK;
> -	ckpt->cp_pack_start_sum = cpu_to_le32(1 + orphan_blocks);
> +	if (is_set_ckpt_flags(ckpt, CP_LARGE_VOL_FLAG))
> +		sit_bitmap_blks = F2FS_BLK_ALIGN(ckpt->sit_ver_bitmap_bytesize);
> +	ckpt->cp_pack_start_sum = cpu_to_le32(1 + sit_bitmap_blks +
> +			orphan_blocks);
>  
>  	if (is_umount) {
>  		set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
>  		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
> -			data_sum_blocks + orphan_blocks + NR_CURSEG_NODE_TYPE);
> +				sit_bitmap_blks + data_sum_blocks +
> +				orphan_blocks + NR_CURSEG_NODE_TYPE);
>  	} else {
>  		clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
>  		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
> -			data_sum_blocks + orphan_blocks);
> +				sit_bitmap_blks + data_sum_blocks +
> +				orphan_blocks);
>  	}
>  
>  	if (sbi->n_orphans)
> @@ -821,6 +853,15 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
>  	set_page_dirty(cp_page);
>  	f2fs_put_page(cp_page, 1);
>  
> +	for (i = 1; i < 1 + sit_bitmap_blks; i++) {
> +		cp_page = grab_meta_page(sbi, start_blk++);
> +		kaddr = page_address(cp_page);
> +		memcpy(kaddr, (char *)ckpt + i * F2FS_BLKSIZE,
> +				(1 << sbi->log_blocksize));
> +		set_page_dirty(cp_page);
> +		f2fs_put_page(cp_page, 1);
> +	}
> +
>  	if (sbi->n_orphans) {
>  		write_orphan_inodes(sbi, start_blk);
>  		start_blk += orphan_blocks;
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 676a2c6..9e147ae 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -764,9 +764,18 @@ static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
>  static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
>  {
>  	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
> -	int offset = (flag == NAT_BITMAP) ?
> +	int offset;
> +
> +	if (ckpt->ckpt_flags & CP_LARGE_VOL_FLAG) {

Should call is_set_ckpt_flag(ckpt, CP_LARGE_VOL_FLAG) to avoid endian
conversion issue.

Thanks,

> +		if (flag == NAT_BITMAP)
> +			return &ckpt->sit_nat_version_bitmap;
> +		else
> +			return ((unsigned char *)ckpt + F2FS_BLKSIZE);
> +	} else {
> +		offset = (flag == NAT_BITMAP) ?
>  			le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
> -	return &ckpt->sit_nat_version_bitmap + offset;
> +		return &ckpt->sit_nat_version_bitmap + offset;
> +	}
>  }
>  
>  static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
> diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> index 8c03f71..0f0b788 100644
> --- a/include/linux/f2fs_fs.h
> +++ b/include/linux/f2fs_fs.h
> @@ -19,6 +19,7 @@
>  #define F2FS_LOG_SECTORS_PER_BLOCK	3	/* 4KB: F2FS_BLKSIZE */
>  #define F2FS_BLKSIZE			4096	/* support only 4KB block */
>  #define F2FS_MAX_EXTENSION		64	/* # of extension entries */
> +#define F2FS_BLK_ALIGN(x)	(((x) + F2FS_BLKSIZE - 1) / F2FS_BLKSIZE)
>  
>  #define NULL_ADDR		((block_t)0)	/* used as block_t addresses */
>  #define NEW_ADDR		((block_t)-1)	/* used as block_t addresses */
> @@ -80,6 +81,7 @@ struct f2fs_super_block {
>  /*
>   * For checkpoint
>   */
> +#define CP_LARGE_VOL_FLAG	0x00000010
>  #define CP_ERROR_FLAG		0x00000008
>  #define CP_COMPACT_SUM_FLAG	0x00000004
>  #define CP_ORPHAN_PRESENT_FLAG	0x00000002

-- 
Jaegeuk Kim

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [f2fs-dev] [PATCH] f2fs: large volume support
  2014-05-21  4:33 ` [f2fs-dev] " Jaegeuk Kim
@ 2014-05-21  6:46   ` Changman Lee
  2014-05-22  8:31     ` [PATCH V3] " Changman Lee
  0 siblings, 1 reply; 5+ messages in thread
From: Changman Lee @ 2014-05-21  6:46 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-f2fs-devel, linux-fsdevel

On 수, 2014-05-21 at 13:33 +0900, Jaegeuk Kim wrote:
> Hi Changman,
> 
> 2014-05-12 (월), 15:59 +0900, Changman Lee:
> > f2fs's cp has one page which consists of struct f2fs_checkpoint and
> > version bitmap of sit and nat. To support lots of segments, we need more
> > blocks for sit bitmap. So let's arrange sit bitmap as following:
> > +-----------------+------------+
> > | f2fs_checkpoint | sit bitmap |
> > | + nat bitmap    |            |
> > +-----------------+------------+
> > 0                 4k        N blocks
> > 
> > Signed-off-by: Changman Lee <cm224.lee@samsung.com>
> > ---
> >  fs/f2fs/checkpoint.c    |   47 ++++++++++++++++++++++++++++++++++++++++++++---
> >  fs/f2fs/f2fs.h          |   13 +++++++++++--
> >  include/linux/f2fs_fs.h |    2 ++
> >  3 files changed, 57 insertions(+), 5 deletions(-)
> > 
> > diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> > index fe968c7..f418243 100644
> > --- a/fs/f2fs/checkpoint.c
> > +++ b/fs/f2fs/checkpoint.c
> > @@ -544,6 +544,32 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
> >  	cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
> >  	memcpy(sbi->ckpt, cp_block, blk_size);
> >  
> > +	if (is_set_ckpt_flags(sbi->ckpt, CP_LARGE_VOL_FLAG)) {
> > +		int i, cp_blks;
> > +		block_t cp_blk_no;
> > +
> > +		cp_blk_no = le32_to_cpu(fsb->cp_blkaddr);
> > +		if (cur_page == cp2)
> > +			cp_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
> > +
> > +		cp_blks = 1 + F2FS_BLK_ALIGN(cp_block->sit_ver_bitmap_bytesize);
> 
> Should covert le32_to_cpu(cp_block->sit_ver_bitmap_bytesize).
> 
Got it.
> > +
> > +		kfree(sbi->ckpt);
> > +		sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL);
> 
> Why does it have to reallocate this and not to handle -ENOMEM correctly?

I think it's more simple than using another variable to point
sit_ver_bitmap and it doesn't require alloc and free for the variable.

> 
> > +
> > +		memcpy(sbi->ckpt, cp_block, blk_size);
> > +
> > +		for (i = 1; i < cp_blks; i++) {
> > +			void *sit_bitmap_ptr;
> > +			unsigned char *ckpt = (unsigned char *)sbi->ckpt;
> > +
> > +			cur_page = get_meta_page(sbi, cp_blk_no + i);
> > +			sit_bitmap_ptr = page_address(cur_page);
> > +			memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
> > +			f2fs_put_page(cur_page, 1);
> > +		}
> > +	}
> > +
> >  	f2fs_put_page(cp1, 1);
> >  	f2fs_put_page(cp2, 1);
> >  	return 0;
> > @@ -736,6 +762,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
> >  	__u32 crc32 = 0;
> >  	void *kaddr;
> >  	int i;
> > +	int sit_bitmap_blks = 0;
> >  
> >  	/*
> >  	 * This avoids to conduct wrong roll-forward operations and uses
> > @@ -786,16 +813,21 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
> >  
> >  	orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
> >  					/ F2FS_ORPHANS_PER_BLOCK;
> > -	ckpt->cp_pack_start_sum = cpu_to_le32(1 + orphan_blocks);
> > +	if (is_set_ckpt_flags(ckpt, CP_LARGE_VOL_FLAG))
> > +		sit_bitmap_blks = F2FS_BLK_ALIGN(ckpt->sit_ver_bitmap_bytesize);
> > +	ckpt->cp_pack_start_sum = cpu_to_le32(1 + sit_bitmap_blks +
> > +			orphan_blocks);
> >  
> >  	if (is_umount) {
> >  		set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
> >  		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
> > -			data_sum_blocks + orphan_blocks + NR_CURSEG_NODE_TYPE);
> > +				sit_bitmap_blks + data_sum_blocks +
> > +				orphan_blocks + NR_CURSEG_NODE_TYPE);
> >  	} else {
> >  		clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
> >  		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
> > -			data_sum_blocks + orphan_blocks);
> > +				sit_bitmap_blks + data_sum_blocks +
> > +				orphan_blocks);
> >  	}
> >  
> >  	if (sbi->n_orphans)
> > @@ -821,6 +853,15 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
> >  	set_page_dirty(cp_page);
> >  	f2fs_put_page(cp_page, 1);
> >  
> > +	for (i = 1; i < 1 + sit_bitmap_blks; i++) {
> > +		cp_page = grab_meta_page(sbi, start_blk++);
> > +		kaddr = page_address(cp_page);
> > +		memcpy(kaddr, (char *)ckpt + i * F2FS_BLKSIZE,
> > +				(1 << sbi->log_blocksize));
> > +		set_page_dirty(cp_page);
> > +		f2fs_put_page(cp_page, 1);
> > +	}
> > +
> >  	if (sbi->n_orphans) {
> >  		write_orphan_inodes(sbi, start_blk);
> >  		start_blk += orphan_blocks;
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index 676a2c6..9e147ae 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -764,9 +764,18 @@ static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
> >  static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
> >  {
> >  	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
> > -	int offset = (flag == NAT_BITMAP) ?
> > +	int offset;
> > +
> > +	if (ckpt->ckpt_flags & CP_LARGE_VOL_FLAG) {
> 
> Should call is_set_ckpt_flag(ckpt, CP_LARGE_VOL_FLAG) to avoid endian
> conversion issue.
> 
> Thanks,
> 

My mistake. Thanks.

> > +		if (flag == NAT_BITMAP)
> > +			return &ckpt->sit_nat_version_bitmap;
> > +		else
> > +			return ((unsigned char *)ckpt + F2FS_BLKSIZE);
> > +	} else {
> > +		offset = (flag == NAT_BITMAP) ?
> >  			le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
> > -	return &ckpt->sit_nat_version_bitmap + offset;
> > +		return &ckpt->sit_nat_version_bitmap + offset;
> > +	}
> >  }
> >  
> >  static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
> > diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
> > index 8c03f71..0f0b788 100644
> > --- a/include/linux/f2fs_fs.h
> > +++ b/include/linux/f2fs_fs.h
> > @@ -19,6 +19,7 @@
> >  #define F2FS_LOG_SECTORS_PER_BLOCK	3	/* 4KB: F2FS_BLKSIZE */
> >  #define F2FS_BLKSIZE			4096	/* support only 4KB block */
> >  #define F2FS_MAX_EXTENSION		64	/* # of extension entries */
> > +#define F2FS_BLK_ALIGN(x)	(((x) + F2FS_BLKSIZE - 1) / F2FS_BLKSIZE)
> >  
> >  #define NULL_ADDR		((block_t)0)	/* used as block_t addresses */
> >  #define NEW_ADDR		((block_t)-1)	/* used as block_t addresses */
> > @@ -80,6 +81,7 @@ struct f2fs_super_block {
> >  /*
> >   * For checkpoint
> >   */
> > +#define CP_LARGE_VOL_FLAG	0x00000010
> >  #define CP_ERROR_FLAG		0x00000008
> >  #define CP_COMPACT_SUM_FLAG	0x00000004
> >  #define CP_ORPHAN_PRESENT_FLAG	0x00000002
> 


--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH V3] f2fs: large volume support
  2014-05-21  6:46   ` Changman Lee
@ 2014-05-22  8:31     ` Changman Lee
  2014-05-26 23:49       ` [f2fs-dev] " Changman Lee
  0 siblings, 1 reply; 5+ messages in thread
From: Changman Lee @ 2014-05-22  8:31 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-fsdevel, linux-f2fs-devel


Changes from V2
 o fix conversion like le32_to_cpu
 o use is_set_ckpt_flags instead of bit operation
 o check return value after memory allocation

Changes from V1
 o fix orphan node blkaddr for large volume

Jaegeuk,
What is your opinion about reallocation of sbi->ckpt ? If you have any
idea, let me know.
Thanks.

--> 8 --

>From 5a821fcec79fb9570a26104238b3c2391f6160ae Mon Sep 17 00:00:00 2001
From: Changman Lee <cm224.lee@samsung.com>
Date: Mon, 12 May 2014 12:27:43 +0900
Subject: [PATCH] f2fs: large volume support

f2fs's cp has one page which consists of struct f2fs_checkpoint and
version bitmap of sit and nat. To support lots of segments, we need more
blocks for sit bitmap. So let's arrange sit bitmap as following:
+-----------------+------------+
| f2fs_checkpoint | sit bitmap |
| + nat bitmap    |            |
+-----------------+------------+
0                 4k        N blocks

Signed-off-by: Changman Lee <cm224.lee@samsung.com>
---
 fs/f2fs/checkpoint.c    |   59
+++++++++++++++++++++++++++++++++++++++++++----
 fs/f2fs/f2fs.h          |   13 +++++++++--
 include/linux/f2fs_fs.h |    2 ++
 3 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index fe968c7..cf2d1a7 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -366,12 +366,18 @@ static void recover_orphan_inode(struct
f2fs_sb_info *sbi, nid_t ino)
 void recover_orphan_inodes(struct f2fs_sb_info *sbi)
 {
 	block_t start_blk, orphan_blkaddr, i, j;
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
 
 	if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
 		return;
 
 	sbi->por_doing = true;
-	start_blk = __start_cp_addr(sbi) + 1;
+
+	if (is_set_ckpt_flags(ckpt, CP_LARGE_VOL_FLAG))
+		start_blk = __start_cp_addr(sbi) + F2FS_BLK_ALIGN(
+				le32_to_cpu(ckpt->sit_ver_bitmap_bytesize));
+	else
+		start_blk = __start_cp_addr(sbi) + 1;
 	orphan_blkaddr = __start_sum_addr(sbi) - 1;
 
 	ra_meta_pages(sbi, start_blk, orphan_blkaddr, META_CP);
@@ -544,6 +550,35 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
 	cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
 	memcpy(sbi->ckpt, cp_block, blk_size);
 
+	if (is_set_ckpt_flags(sbi->ckpt, CP_LARGE_VOL_FLAG)) {
+		int i, cp_blks;
+		block_t cp_blk_no;
+
+		cp_blk_no = le32_to_cpu(fsb->cp_blkaddr);
+		if (cur_page == cp2)
+			cp_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
+
+		cp_blks = 1 + F2FS_BLK_ALIGN(
+				le32_to_cpu(cp_block->sit_ver_bitmap_bytesize));
+
+		kfree(sbi->ckpt);
+		sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL);
+		if (!sbi->ckpt)
+			return -ENOMEM;
+
+		memcpy(sbi->ckpt, cp_block, blk_size);
+
+		for (i = 1; i < cp_blks; i++) {
+			void *sit_bitmap_ptr;
+			unsigned char *ckpt = (unsigned char *)sbi->ckpt;
+
+			cur_page = get_meta_page(sbi, cp_blk_no + i);
+			sit_bitmap_ptr = page_address(cur_page);
+			memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
+			f2fs_put_page(cur_page, 1);
+		}
+	}
+
 	f2fs_put_page(cp1, 1);
 	f2fs_put_page(cp2, 1);
 	return 0;
@@ -736,6 +771,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi,
bool is_umount)
 	__u32 crc32 = 0;
 	void *kaddr;
 	int i;
+	int sit_bitmap_blks = 0;
 
 	/*
 	 * This avoids to conduct wrong roll-forward operations and uses
@@ -786,16 +822,22 @@ static void do_checkpoint(struct f2fs_sb_info
*sbi, bool is_umount)
 
 	orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
 					/ F2FS_ORPHANS_PER_BLOCK;
-	ckpt->cp_pack_start_sum = cpu_to_le32(1 + orphan_blocks);
+	if (is_set_ckpt_flags(ckpt, CP_LARGE_VOL_FLAG))
+		sit_bitmap_blks = F2FS_BLK_ALIGN(
+				le32_to_cpu(ckpt->sit_ver_bitmap_bytesize));
+	ckpt->cp_pack_start_sum = cpu_to_le32(1 + sit_bitmap_blks +
+			orphan_blocks);
 
 	if (is_umount) {
 		set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
 		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
-			data_sum_blocks + orphan_blocks + NR_CURSEG_NODE_TYPE);
+				sit_bitmap_blks + data_sum_blocks +
+				orphan_blocks + NR_CURSEG_NODE_TYPE);
 	} else {
 		clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
 		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
-			data_sum_blocks + orphan_blocks);
+				sit_bitmap_blks + data_sum_blocks +
+				orphan_blocks);
 	}
 
 	if (sbi->n_orphans)
@@ -821,6 +863,15 @@ static void do_checkpoint(struct f2fs_sb_info *sbi,
bool is_umount)
 	set_page_dirty(cp_page);
 	f2fs_put_page(cp_page, 1);
 
+	for (i = 1; i < 1 + sit_bitmap_blks; i++) {
+		cp_page = grab_meta_page(sbi, start_blk++);
+		kaddr = page_address(cp_page);
+		memcpy(kaddr, (char *)ckpt + i * F2FS_BLKSIZE,
+				(1 << sbi->log_blocksize));
+		set_page_dirty(cp_page);
+		f2fs_put_page(cp_page, 1);
+	}
+
 	if (sbi->n_orphans) {
 		write_orphan_inodes(sbi, start_blk);
 		start_blk += orphan_blocks;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 676a2c6..3aec601 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -764,9 +764,18 @@ static inline unsigned long __bitmap_size(struct
f2fs_sb_info *sbi, int flag)
 static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
 {
 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
-	int offset = (flag == NAT_BITMAP) ?
+	int offset;
+
+	if (is_set_ckpt_flags(ckpt, CP_LARGE_VOL_FLAG)) {
+		if (flag == NAT_BITMAP)
+			return &ckpt->sit_nat_version_bitmap;
+		else
+			return ((unsigned char *)ckpt + F2FS_BLKSIZE);
+	} else {
+		offset = (flag == NAT_BITMAP) ?
 			le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
-	return &ckpt->sit_nat_version_bitmap + offset;
+		return &ckpt->sit_nat_version_bitmap + offset;
+	}
 }
 
 static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index 8c03f71..0f0b788 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -19,6 +19,7 @@
 #define F2FS_LOG_SECTORS_PER_BLOCK	3	/* 4KB: F2FS_BLKSIZE */
 #define F2FS_BLKSIZE			4096	/* support only 4KB block */
 #define F2FS_MAX_EXTENSION		64	/* # of extension entries */
+#define F2FS_BLK_ALIGN(x)	(((x) + F2FS_BLKSIZE - 1) / F2FS_BLKSIZE)
 
 #define NULL_ADDR		((block_t)0)	/* used as block_t addresses */
 #define NEW_ADDR		((block_t)-1)	/* used as block_t addresses */
@@ -80,6 +81,7 @@ struct f2fs_super_block {
 /*
  * For checkpoint
  */
+#define CP_LARGE_VOL_FLAG	0x00000010
 #define CP_ERROR_FLAG		0x00000008
 #define CP_COMPACT_SUM_FLAG	0x00000004
 #define CP_ORPHAN_PRESENT_FLAG	0x00000002
-- 
1.7.10.4




^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [f2fs-dev] [PATCH V3] f2fs: large volume support
  2014-05-22  8:31     ` [PATCH V3] " Changman Lee
@ 2014-05-26 23:49       ` Changman Lee
  0 siblings, 0 replies; 5+ messages in thread
From: Changman Lee @ 2014-05-26 23:49 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-fsdevel, linux-f2fs-devel

Changes from V3
 o remove CP_LARGE_VOL_FLAG instead, use cp_payload in superblock
   because disk size is determined at format

Changes from V2
 o fix conversion like le32_to_cpu
 o use is_set_ckpt_flags instead of bit operation
 o check return value after memory allocation

Changes from V1
 o fix orphan node blkaddr for large volume

-- >8 --

>From b1610f32c472cb11f025e0997b7633d5c45b87e9 Mon Sep 17 00:00:00 2001
From: Changman Lee <cm224.lee@samsung.com>
Date: Mon, 12 May 2014 12:27:43 +0900
Subject: [PATCH] f2fs: large volume support

f2fs's cp has one page which consists of struct f2fs_checkpoint and
version bitmap of sit and nat. To support lots of segments, we need more
blocks for sit bitmap. So let's arrange sit bitmap as following:
+-----------------+------------+
| f2fs_checkpoint | sit bitmap |
| + nat bitmap    |            |
+-----------------+------------+
0                 4k        N blocks

Signed-off-by: Changman Lee <cm224.lee@samsung.com>
---
 fs/f2fs/checkpoint.c    |   45 ++++++++++++++++++++++++++++++++++++++++-----
 fs/f2fs/f2fs.h          |   13 +++++++++++--
 include/linux/f2fs_fs.h |    2 ++
 3 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index fe968c7..c559946 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -371,7 +371,9 @@ void recover_orphan_inodes(struct f2fs_sb_info *sbi)
 		return;
 
 	sbi->por_doing = true;
-	start_blk = __start_cp_addr(sbi) + 1;
+
+	start_blk = __start_cp_addr(sbi) + 1 +
+		le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload);
 	orphan_blkaddr = __start_sum_addr(sbi) - 1;
 
 	ra_meta_pages(sbi, start_blk, orphan_blkaddr, META_CP);
@@ -512,8 +514,9 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
 	unsigned long blk_size = sbi->blocksize;
 	unsigned long long cp1_version = 0, cp2_version = 0;
 	unsigned long long cp_start_blk_no;
+	unsigned int cp_blks = 1 + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload);
 
-	sbi->ckpt = kzalloc(blk_size, GFP_KERNEL);
+	sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL);
 	if (!sbi->ckpt)
 		return -ENOMEM;
 	/*
@@ -544,6 +547,25 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
 	cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
 	memcpy(sbi->ckpt, cp_block, blk_size);
 
+	if (cp_blks > 1) {
+		int i;
+		block_t cp_blk_no;
+
+		cp_blk_no = le32_to_cpu(fsb->cp_blkaddr);
+		if (cur_page == cp2)
+			cp_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
+
+		for (i = 1; i < cp_blks; i++) {
+			void *sit_bitmap_ptr;
+			unsigned char *ckpt = (unsigned char *)sbi->ckpt;
+
+			cur_page = get_meta_page(sbi, cp_blk_no + i);
+			sit_bitmap_ptr = page_address(cur_page);
+			memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
+			f2fs_put_page(cur_page, 1);
+		}
+	}
+
 	f2fs_put_page(cp1, 1);
 	f2fs_put_page(cp2, 1);
 	return 0;
@@ -736,6 +758,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 	__u32 crc32 = 0;
 	void *kaddr;
 	int i;
+	int cp_payload_blks = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload);
 
 	/*
 	 * This avoids to conduct wrong roll-forward operations and uses
@@ -786,16 +809,19 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 
 	orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
 					/ F2FS_ORPHANS_PER_BLOCK;
-	ckpt->cp_pack_start_sum = cpu_to_le32(1 + orphan_blocks);
+	ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks +
+			orphan_blocks);
 
 	if (is_umount) {
 		set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
 		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
-			data_sum_blocks + orphan_blocks + NR_CURSEG_NODE_TYPE);
+				cp_payload_blks + data_sum_blocks +
+				orphan_blocks + NR_CURSEG_NODE_TYPE);
 	} else {
 		clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
 		ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
-			data_sum_blocks + orphan_blocks);
+				cp_payload_blks + data_sum_blocks +
+				orphan_blocks);
 	}
 
 	if (sbi->n_orphans)
@@ -821,6 +847,15 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 	set_page_dirty(cp_page);
 	f2fs_put_page(cp_page, 1);
 
+	for (i = 1; i < 1 + cp_payload_blks; i++) {
+		cp_page = grab_meta_page(sbi, start_blk++);
+		kaddr = page_address(cp_page);
+		memcpy(kaddr, (char *)ckpt + i * F2FS_BLKSIZE,
+				(1 << sbi->log_blocksize));
+		set_page_dirty(cp_page);
+		f2fs_put_page(cp_page, 1);
+	}
+
 	if (sbi->n_orphans) {
 		write_orphan_inodes(sbi, start_blk);
 		start_blk += orphan_blocks;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 676a2c6..9684b1f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -764,9 +764,18 @@ static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
 static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
 {
 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
-	int offset = (flag == NAT_BITMAP) ?
+	int offset;
+
+	if (le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload) > 0) {
+		if (flag == NAT_BITMAP)
+			return &ckpt->sit_nat_version_bitmap;
+		else
+			return ((unsigned char *)ckpt + F2FS_BLKSIZE);
+	} else {
+		offset = (flag == NAT_BITMAP) ?
 			le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0;
-	return &ckpt->sit_nat_version_bitmap + offset;
+		return &ckpt->sit_nat_version_bitmap + offset;
+	}
 }
 
 static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index 8c03f71..23ba0b5 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -19,6 +19,7 @@
 #define F2FS_LOG_SECTORS_PER_BLOCK	3	/* 4KB: F2FS_BLKSIZE */
 #define F2FS_BLKSIZE			4096	/* support only 4KB block */
 #define F2FS_MAX_EXTENSION		64	/* # of extension entries */
+#define F2FS_BLK_ALIGN(x)	(((x) + F2FS_BLKSIZE - 1) / F2FS_BLKSIZE)
 
 #define NULL_ADDR		((block_t)0)	/* used as block_t addresses */
 #define NEW_ADDR		((block_t)-1)	/* used as block_t addresses */
@@ -75,6 +76,7 @@ struct f2fs_super_block {
 	__le16 volume_name[512];	/* volume name */
 	__le32 extension_count;		/* # of extensions below */
 	__u8 extension_list[F2FS_MAX_EXTENSION][8];	/* extension array */
+	__le32 cp_payload;
 } __packed;
 
 /*
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-05-26 23:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-12  6:59 [PATCH] f2fs: large volume support Changman Lee
2014-05-21  4:33 ` [f2fs-dev] " Jaegeuk Kim
2014-05-21  6:46   ` Changman Lee
2014-05-22  8:31     ` [PATCH V3] " Changman Lee
2014-05-26 23:49       ` [f2fs-dev] " Changman Lee

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).