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 <[email protected]>
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 <[email protected]>
---
 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


------------------------------------------------------------------------------
The best possible search technologies are now affordable for all companies.
Download your FREE open source Enterprise Search Engine today!
Our experts will assist you in its installation for $59/mo, no commitment.
Test it for FREE on our Cloud platform anytime!
http://pubads.g.doubleclick.net/gampad/clk?id=145328191&iu=/4140/ostg.clktrk
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to