f2fs-tools: fix # of total segments
[platform/upstream/f2fs-tools.git] / fsck / resize.c
1 /**
2  * resize.c
3  *
4  * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 #include "fsck.h"
11
12 static int get_new_sb(struct f2fs_super_block *sb)
13 {
14         uint32_t zone_size_bytes;
15         uint64_t zone_align_start_offset;
16         uint32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa;
17         uint32_t sit_segments, nat_segments, diff, total_meta_segments;
18         uint32_t total_valid_blks_available;
19         uint32_t sit_bitmap_size, max_sit_bitmap_size;
20         uint32_t max_nat_bitmap_size, max_nat_segments;
21         uint32_t segment_size_bytes = 1 << (get_sb(log_blocksize) +
22                                         get_sb(log_blocks_per_seg));
23         uint32_t blks_per_seg = 1 << get_sb(log_blocks_per_seg);
24         uint32_t segs_per_zone = get_sb(segs_per_sec) * get_sb(secs_per_zone);
25
26         set_sb(block_count, c.target_sectors >>
27                                 get_sb(log_sectors_per_block));
28
29         zone_size_bytes = segment_size_bytes * segs_per_zone;
30         zone_align_start_offset =
31                 ((uint64_t) c.start_sector * DEFAULT_SECTOR_SIZE +
32                 2 * F2FS_BLKSIZE + zone_size_bytes - 1) /
33                 zone_size_bytes * zone_size_bytes -
34                 (uint64_t) c.start_sector * DEFAULT_SECTOR_SIZE;
35
36         set_sb(segment_count, (c.target_sectors * c.sector_size -
37                                 zone_align_start_offset) / segment_size_bytes /
38                                 c.segs_per_sec * c.segs_per_sec);
39
40         if (c.safe_resize)
41                 goto safe_resize;
42
43         blocks_for_sit = SIZE_ALIGN(get_sb(segment_count), SIT_ENTRY_PER_BLOCK);
44         sit_segments = SEG_ALIGN(blocks_for_sit);
45         set_sb(segment_count_sit, sit_segments * 2);
46         set_sb(nat_blkaddr, get_sb(sit_blkaddr) +
47                                 get_sb(segment_count_sit) * blks_per_seg);
48
49         total_valid_blks_available = (get_sb(segment_count) -
50                         (get_sb(segment_count_ckpt) +
51                         get_sb(segment_count_sit))) * blks_per_seg;
52         blocks_for_nat = SIZE_ALIGN(total_valid_blks_available,
53                                         NAT_ENTRY_PER_BLOCK);
54
55         if (c.large_nat_bitmap) {
56                 nat_segments = SEG_ALIGN(blocks_for_nat) *
57                                                 DEFAULT_NAT_ENTRY_RATIO / 100;
58                 set_sb(segment_count_nat, nat_segments ? nat_segments : 1);
59
60                 max_nat_bitmap_size = (get_sb(segment_count_nat) <<
61                                                 get_sb(log_blocks_per_seg)) / 8;
62                 set_sb(segment_count_nat, get_sb(segment_count_nat) * 2);
63         } else {
64                 set_sb(segment_count_nat, SEG_ALIGN(blocks_for_nat));
65                 max_nat_bitmap_size = 0;
66         }
67
68         sit_bitmap_size = ((get_sb(segment_count_sit) / 2) <<
69                                 get_sb(log_blocks_per_seg)) / 8;
70         if (sit_bitmap_size > MAX_SIT_BITMAP_SIZE)
71                 max_sit_bitmap_size = MAX_SIT_BITMAP_SIZE;
72         else
73                 max_sit_bitmap_size = sit_bitmap_size;
74
75         if (c.large_nat_bitmap) {
76                 /* use cp_payload if free space of f2fs_checkpoint is not enough */
77                 if (max_sit_bitmap_size + max_nat_bitmap_size >
78                                                 MAX_BITMAP_SIZE_IN_CKPT) {
79                         uint32_t diff =  max_sit_bitmap_size +
80                                                 max_nat_bitmap_size -
81                                                 MAX_BITMAP_SIZE_IN_CKPT;
82                         set_sb(cp_payload, F2FS_BLK_ALIGN(diff));
83                 } else {
84                         set_sb(cp_payload, 0);
85                 }
86         } else {
87                 /*
88                  * It should be reserved minimum 1 segment for nat.
89                  * When sit is too large, we should expand cp area.
90                  * It requires more pages for cp.
91                  */
92                 if (max_sit_bitmap_size > MAX_SIT_BITMAP_SIZE_IN_CKPT) {
93                         max_nat_bitmap_size = MAX_BITMAP_SIZE_IN_CKPT;
94                         set_sb(cp_payload, F2FS_BLK_ALIGN(max_sit_bitmap_size));
95                 } else {
96                         max_nat_bitmap_size = MAX_BITMAP_SIZE_IN_CKPT -
97                                                         max_sit_bitmap_size;
98                         set_sb(cp_payload, 0);
99                 }
100
101                 max_nat_segments = (max_nat_bitmap_size * 8) >>
102                                         get_sb(log_blocks_per_seg);
103
104                 if (get_sb(segment_count_nat) > max_nat_segments)
105                         set_sb(segment_count_nat, max_nat_segments);
106
107                 set_sb(segment_count_nat, get_sb(segment_count_nat) * 2);
108         }
109
110         set_sb(ssa_blkaddr, get_sb(nat_blkaddr) +
111                                 get_sb(segment_count_nat) * blks_per_seg);
112
113         total_valid_blks_available = (get_sb(segment_count) -
114                         (get_sb(segment_count_ckpt) +
115                         get_sb(segment_count_sit) +
116                         get_sb(segment_count_nat))) * blks_per_seg;
117
118         blocks_for_ssa = total_valid_blks_available / blks_per_seg + 1;
119
120         set_sb(segment_count_ssa, SEG_ALIGN(blocks_for_ssa));
121
122         total_meta_segments = get_sb(segment_count_ckpt) +
123                 get_sb(segment_count_sit) +
124                 get_sb(segment_count_nat) +
125                 get_sb(segment_count_ssa);
126
127         diff = total_meta_segments % segs_per_zone;
128         if (diff)
129                 set_sb(segment_count_ssa, get_sb(segment_count_ssa) +
130                         (segs_per_zone - diff));
131
132         set_sb(main_blkaddr, get_sb(ssa_blkaddr) + get_sb(segment_count_ssa) *
133                          blks_per_seg);
134
135 safe_resize:
136         set_sb(segment_count_main, get_sb(segment_count) -
137                         (get_sb(segment_count_ckpt) +
138                          get_sb(segment_count_sit) +
139                          get_sb(segment_count_nat) +
140                          get_sb(segment_count_ssa)));
141
142         set_sb(section_count, get_sb(segment_count_main) /
143                                                 get_sb(segs_per_sec));
144
145         set_sb(segment_count_main, get_sb(section_count) *
146                                                 get_sb(segs_per_sec));
147
148         /* Let's determine the best reserved and overprovisioned space */
149         if (c.new_overprovision == 0)
150                 c.new_overprovision = get_best_overprovision(sb);
151
152         c.new_reserved_segments =
153                 (100 / c.new_overprovision + 1 + NR_CURSEG_TYPE) *
154                                                 get_sb(segs_per_sec);
155
156         if ((get_sb(segment_count_main) - 2) < c.new_reserved_segments ||
157                 get_sb(segment_count_main) * blks_per_seg >
158                                                 get_sb(block_count)) {
159                 MSG(0, "\tError: Device size is not sufficient for F2FS volume, "
160                         "more segment needed =%u",
161                         c.new_reserved_segments -
162                         (get_sb(segment_count_main) - 2));
163                 return -1;
164         }
165         return 0;
166 }
167
168 static void migrate_main(struct f2fs_sb_info *sbi, unsigned int offset)
169 {
170         void *raw = calloc(BLOCK_SZ, 1);
171         struct seg_entry *se;
172         block_t from, to;
173         int i, j, ret;
174         struct f2fs_summary sum;
175
176         ASSERT(raw != NULL);
177
178         for (i = MAIN_SEGS(sbi) - 1; i >= 0; i--) {
179                 se = get_seg_entry(sbi, i);
180                 if (!se->valid_blocks)
181                         continue;
182
183                 for (j = sbi->blocks_per_seg - 1; j >= 0; j--) {
184                         if (!f2fs_test_bit(j, (const char *)se->cur_valid_map))
185                                 continue;
186
187                         from = START_BLOCK(sbi, i) + j;
188                         ret = dev_read_block(raw, from);
189                         ASSERT(ret >= 0);
190
191                         to = from + offset;
192                         ret = dev_write_block(raw, to);
193                         ASSERT(ret >= 0);
194
195                         get_sum_entry(sbi, from, &sum);
196
197                         if (IS_DATASEG(se->type))
198                                 update_data_blkaddr(sbi, le32_to_cpu(sum.nid),
199                                         le16_to_cpu(sum.ofs_in_node), to);
200                         else
201                                 update_nat_blkaddr(sbi, 0,
202                                                 le32_to_cpu(sum.nid), to);
203                 }
204         }
205         free(raw);
206         DBG(0, "Info: Done to migrate Main area: main_blkaddr = 0x%x -> 0x%x\n",
207                                 START_BLOCK(sbi, 0),
208                                 START_BLOCK(sbi, 0) + offset);
209 }
210
211 static void move_ssa(struct f2fs_sb_info *sbi, unsigned int segno,
212                                         block_t new_sum_blk_addr)
213 {
214         struct f2fs_summary_block *sum_blk;
215         int type;
216
217         sum_blk = get_sum_block(sbi, segno, &type);
218         if (type < SEG_TYPE_MAX) {
219                 int ret;
220
221                 ret = dev_write_block(sum_blk, new_sum_blk_addr);
222                 ASSERT(ret >= 0);
223                 DBG(1, "Write summary block: (%d) segno=%x/%x --> (%d) %x\n",
224                                 type, segno, GET_SUM_BLKADDR(sbi, segno),
225                                 IS_SUM_NODE_SEG(sum_blk->footer),
226                                 new_sum_blk_addr);
227         }
228         if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA ||
229                         type == SEG_TYPE_MAX) {
230                 free(sum_blk);
231         }
232         DBG(1, "Info: Done to migrate SSA blocks\n");
233 }
234
235 static void migrate_ssa(struct f2fs_sb_info *sbi,
236                 struct f2fs_super_block *new_sb, unsigned int offset)
237 {
238         struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
239         block_t old_sum_blkaddr = get_sb(ssa_blkaddr);
240         block_t new_sum_blkaddr = get_newsb(ssa_blkaddr);
241         block_t end_sum_blkaddr = get_newsb(main_blkaddr);
242         block_t expand_sum_blkaddr = new_sum_blkaddr +
243                                         MAIN_SEGS(sbi) - offset;
244         block_t blkaddr;
245         int ret;
246         void *zero_block = calloc(BLOCK_SZ, 1);
247         ASSERT(zero_block);
248
249         if (offset && new_sum_blkaddr < old_sum_blkaddr + offset) {
250                 blkaddr = new_sum_blkaddr;
251                 while (blkaddr < end_sum_blkaddr) {
252                         if (blkaddr < expand_sum_blkaddr) {
253                                 move_ssa(sbi, offset++, blkaddr++);
254                         } else {
255                                 ret = dev_write_block(zero_block, blkaddr++);
256                                 ASSERT(ret >=0);
257                         }
258                 }
259         } else {
260                 blkaddr = end_sum_blkaddr - 1;
261                 offset = MAIN_SEGS(sbi) - 1;
262                 while (blkaddr >= new_sum_blkaddr) {
263                         if (blkaddr >= expand_sum_blkaddr) {
264                                 ret = dev_write_block(zero_block, blkaddr--);
265                                 ASSERT(ret >=0);
266                         } else {
267                                 move_ssa(sbi, offset--, blkaddr--);
268                         }
269                 }
270         }
271
272         DBG(0, "Info: Done to migrate SSA blocks: sum_blkaddr = 0x%x -> 0x%x\n",
273                                 old_sum_blkaddr, new_sum_blkaddr);
274         free(zero_block);
275 }
276
277 static int shrink_nats(struct f2fs_sb_info *sbi,
278                                 struct f2fs_super_block *new_sb)
279 {
280         struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
281         struct f2fs_nm_info *nm_i = NM_I(sbi);
282         block_t old_nat_blkaddr = get_sb(nat_blkaddr);
283         unsigned int nat_blocks;
284         void *nat_block, *zero_block;
285         int nid, ret, new_max_nid;
286         pgoff_t block_off;
287         pgoff_t block_addr;
288         int seg_off;
289
290         nat_block = malloc(BLOCK_SZ);
291         ASSERT(nat_block);
292         zero_block = calloc(BLOCK_SZ, 1);
293         ASSERT(zero_block);
294
295         nat_blocks = get_newsb(segment_count_nat) >> 1;
296         nat_blocks = nat_blocks << get_sb(log_blocks_per_seg);
297         new_max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks;
298
299         for (nid = nm_i->max_nid - 1; nid > new_max_nid; nid -= NAT_ENTRY_PER_BLOCK) {
300                 block_off = nid / NAT_ENTRY_PER_BLOCK;
301                 seg_off = block_off >> sbi->log_blocks_per_seg;
302                 block_addr = (pgoff_t)(old_nat_blkaddr +
303                                 (seg_off << sbi->log_blocks_per_seg << 1) +
304                                 (block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
305
306                 if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
307                         block_addr += sbi->blocks_per_seg;
308
309                 ret = dev_read_block(nat_block, block_addr);
310                 ASSERT(ret >= 0);
311
312                 if (memcmp(zero_block, nat_block, BLOCK_SZ)) {
313                         ret = -1;
314                         goto not_avail;
315                 }
316         }
317         ret = 0;
318         nm_i->max_nid = new_max_nid;
319 not_avail:
320         free(nat_block);
321         free(zero_block);
322         return ret;
323 }
324
325 static void migrate_nat(struct f2fs_sb_info *sbi,
326                         struct f2fs_super_block *new_sb)
327 {
328         struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
329         struct f2fs_nm_info *nm_i = NM_I(sbi);
330         block_t old_nat_blkaddr = get_sb(nat_blkaddr);
331         block_t new_nat_blkaddr = get_newsb(nat_blkaddr);
332         unsigned int nat_blocks;
333         void *nat_block;
334         int nid, ret, new_max_nid;
335         pgoff_t block_off;
336         pgoff_t block_addr;
337         int seg_off;
338
339         nat_block = malloc(BLOCK_SZ);
340         ASSERT(nat_block);
341
342         for (nid = nm_i->max_nid - 1; nid >= 0; nid -= NAT_ENTRY_PER_BLOCK) {
343                 block_off = nid / NAT_ENTRY_PER_BLOCK;
344                 seg_off = block_off >> sbi->log_blocks_per_seg;
345                 block_addr = (pgoff_t)(old_nat_blkaddr +
346                                 (seg_off << sbi->log_blocks_per_seg << 1) +
347                                 (block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
348
349                 /* move to set #0 */
350                 if (f2fs_test_bit(block_off, nm_i->nat_bitmap)) {
351                         block_addr += sbi->blocks_per_seg;
352                         f2fs_clear_bit(block_off, nm_i->nat_bitmap);
353                 }
354
355                 ret = dev_read_block(nat_block, block_addr);
356                 ASSERT(ret >= 0);
357
358                 block_addr = (pgoff_t)(new_nat_blkaddr +
359                                 (seg_off << sbi->log_blocks_per_seg << 1) +
360                                 (block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
361
362                 /* new bitmap should be zeros */
363                 ret = dev_write_block(nat_block, block_addr);
364                 ASSERT(ret >= 0);
365         }
366         /* zero out newly assigned nids */
367         memset(nat_block, 0, BLOCK_SZ);
368         nat_blocks = get_newsb(segment_count_nat) >> 1;
369         nat_blocks = nat_blocks << get_sb(log_blocks_per_seg);
370         new_max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks;
371
372         DBG(1, "Write NAT block: %x->%x, max_nid=%x->%x\n",
373                         old_nat_blkaddr, new_nat_blkaddr,
374                         get_sb(segment_count_nat),
375                         get_newsb(segment_count_nat));
376
377         for (nid = nm_i->max_nid; nid < new_max_nid;
378                                 nid += NAT_ENTRY_PER_BLOCK) {
379                 block_off = nid / NAT_ENTRY_PER_BLOCK;
380                 seg_off = block_off >> sbi->log_blocks_per_seg;
381                 block_addr = (pgoff_t)(new_nat_blkaddr +
382                                 (seg_off << sbi->log_blocks_per_seg << 1) +
383                                 (block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
384                 ret = dev_write_block(nat_block, block_addr);
385                 ASSERT(ret >= 0);
386                 DBG(3, "Write NAT: %lx\n", block_addr);
387         }
388         free(nat_block);
389         DBG(0, "Info: Done to migrate NAT blocks: nat_blkaddr = 0x%x -> 0x%x\n",
390                         old_nat_blkaddr, new_nat_blkaddr);
391 }
392
393 static void migrate_sit(struct f2fs_sb_info *sbi,
394                 struct f2fs_super_block *new_sb, unsigned int offset)
395 {
396         struct sit_info *sit_i = SIT_I(sbi);
397         unsigned int ofs = 0, pre_ofs = 0;
398         unsigned int segno, index;
399         struct f2fs_sit_block *sit_blk = calloc(BLOCK_SZ, 1);
400         block_t sit_blks = get_newsb(segment_count_sit) <<
401                                                 (sbi->log_blocks_per_seg - 1);
402         struct seg_entry *se;
403         block_t blk_addr = 0;
404         int ret;
405
406         ASSERT(sit_blk);
407
408         /* initialize with zeros */
409         for (index = 0; index < sit_blks; index++) {
410                 ret = dev_write_block(sit_blk, get_newsb(sit_blkaddr) + index);
411                 ASSERT(ret >= 0);
412                 DBG(3, "Write zero sit: %x\n", get_newsb(sit_blkaddr) + index);
413         }
414
415         for (segno = 0; segno < MAIN_SEGS(sbi); segno++) {
416                 struct f2fs_sit_entry *sit;
417
418                 se = get_seg_entry(sbi, segno);
419                 if (segno < offset) {
420                         ASSERT(se->valid_blocks == 0);
421                         continue;
422                 }
423
424                 ofs = SIT_BLOCK_OFFSET(sit_i, segno - offset);
425
426                 if (ofs != pre_ofs) {
427                         blk_addr = get_newsb(sit_blkaddr) + pre_ofs;
428                         ret = dev_write_block(sit_blk, blk_addr);
429                         ASSERT(ret >= 0);
430                         DBG(1, "Write valid sit: %x\n", blk_addr);
431
432                         pre_ofs = ofs;
433                         memset(sit_blk, 0, BLOCK_SZ);
434                 }
435
436                 sit = &sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno - offset)];
437                 memcpy(sit->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE);
438                 sit->vblocks = cpu_to_le16((se->type << SIT_VBLOCKS_SHIFT) |
439                                                         se->valid_blocks);
440         }
441         blk_addr = get_newsb(sit_blkaddr) + ofs;
442         ret = dev_write_block(sit_blk, blk_addr);
443         DBG(1, "Write valid sit: %x\n", blk_addr);
444         ASSERT(ret >= 0);
445
446         free(sit_blk);
447         DBG(0, "Info: Done to restore new SIT blocks: 0x%x\n",
448                                         get_newsb(sit_blkaddr));
449 }
450
451 static void rebuild_checkpoint(struct f2fs_sb_info *sbi,
452                         struct f2fs_super_block *new_sb, unsigned int offset)
453 {
454         struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
455         unsigned long long cp_ver = get_cp(checkpoint_ver);
456         struct f2fs_checkpoint *new_cp;
457         struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
458         unsigned int free_segment_count, new_segment_count;
459         block_t new_cp_blks = 1 + get_newsb(cp_payload);
460         block_t orphan_blks = 0;
461         block_t new_cp_blk_no, old_cp_blk_no;
462         uint32_t crc = 0;
463         u32 flags;
464         void *buf;
465         int i, ret;
466
467         new_cp = calloc(new_cp_blks * BLOCK_SZ, 1);
468         ASSERT(new_cp);
469
470         buf = malloc(BLOCK_SZ);
471         ASSERT(buf);
472
473         /* ovp / free segments */
474         set_cp(rsvd_segment_count, c.new_reserved_segments);
475         set_cp(overprov_segment_count, (get_newsb(segment_count_main) -
476                         get_cp(rsvd_segment_count)) *
477                         c.new_overprovision / 100);
478
479         /* give 2 sections (DATA and NODE) to trigger GC in advance */
480         if (get_cp(overprov_segment_count) < get_cp(rsvd_segment_count))
481                 set_cp(overprov_segment_count, get_cp(rsvd_segment_count));
482
483         set_cp(overprov_segment_count, get_cp(overprov_segment_count) +
484                                                 2 * get_sb(segs_per_sec));
485
486         DBG(0, "Info: Overprovision ratio = %.3lf%%\n", c.new_overprovision);
487         DBG(0, "Info: Overprovision segments = %u (GC reserved = %u)\n",
488                                         get_cp(overprov_segment_count),
489                                         c.new_reserved_segments);
490
491         free_segment_count = get_free_segments(sbi);
492         new_segment_count = get_newsb(segment_count_main) -
493                                         get_sb(segment_count_main);
494
495         set_cp(free_segment_count, free_segment_count + new_segment_count);
496         set_cp(user_block_count, ((get_newsb(segment_count_main) -
497                         get_cp(overprov_segment_count)) * c.blks_per_seg));
498
499         if (is_set_ckpt_flags(cp, CP_ORPHAN_PRESENT_FLAG))
500                 orphan_blks = __start_sum_addr(sbi) - 1;
501
502         set_cp(cp_pack_start_sum, 1 + get_newsb(cp_payload));
503         set_cp(cp_pack_total_block_count, 8 + orphan_blks + get_newsb(cp_payload));
504
505         /* cur->segno - offset */
506         for (i = 0; i < NO_CHECK_TYPE; i++) {
507                 if (i < CURSEG_HOT_NODE) {
508                         set_cp(cur_data_segno[i],
509                                         CURSEG_I(sbi, i)->segno - offset);
510                 } else {
511                         int n = i - CURSEG_HOT_NODE;
512
513                         set_cp(cur_node_segno[n],
514                                         CURSEG_I(sbi, i)->segno - offset);
515                 }
516         }
517
518         /* sit / nat ver bitmap bytesize */
519         set_cp(sit_ver_bitmap_bytesize,
520                         ((get_newsb(segment_count_sit) / 2) <<
521                         get_newsb(log_blocks_per_seg)) / 8);
522         set_cp(nat_ver_bitmap_bytesize,
523                         ((get_newsb(segment_count_nat) / 2) <<
524                         get_newsb(log_blocks_per_seg)) / 8);
525
526         /* update nat_bits flag */
527         flags = update_nat_bits_flags(new_sb, cp, get_cp(ckpt_flags));
528         if (c.large_nat_bitmap)
529                 flags |= CP_LARGE_NAT_BITMAP_FLAG;
530
531         if (flags & CP_COMPACT_SUM_FLAG)
532                 flags &= ~CP_COMPACT_SUM_FLAG;
533         if (flags & CP_LARGE_NAT_BITMAP_FLAG)
534                 set_cp(checksum_offset, CP_MIN_CHKSUM_OFFSET);
535         else
536                 set_cp(checksum_offset, CP_CHKSUM_OFFSET);
537
538         set_cp(ckpt_flags, flags);
539
540         memcpy(new_cp, cp, (unsigned char *)cp->sit_nat_version_bitmap -
541                                                 (unsigned char *)cp);
542         if (c.safe_resize)
543                 memcpy((void *)new_cp + CP_BITMAP_OFFSET,
544                         (void *)cp + CP_BITMAP_OFFSET,
545                         F2FS_BLKSIZE - CP_BITMAP_OFFSET);
546
547         new_cp->checkpoint_ver = cpu_to_le64(cp_ver + 1);
548
549         crc = f2fs_checkpoint_chksum(new_cp);
550         *((__le32 *)((unsigned char *)new_cp + get_cp(checksum_offset))) =
551                                                         cpu_to_le32(crc);
552
553         /* Write a new checkpoint in the other set */
554         new_cp_blk_no = old_cp_blk_no = get_sb(cp_blkaddr);
555         if (sbi->cur_cp == 2)
556                 old_cp_blk_no += 1 << get_sb(log_blocks_per_seg);
557         else
558                 new_cp_blk_no += 1 << get_sb(log_blocks_per_seg);
559
560         /* write first cp */
561         ret = dev_write_block(new_cp, new_cp_blk_no++);
562         ASSERT(ret >= 0);
563
564         memset(buf, 0, BLOCK_SZ);
565         for (i = 0; i < get_newsb(cp_payload); i++) {
566                 ret = dev_write_block(buf, new_cp_blk_no++);
567                 ASSERT(ret >= 0);
568         }
569
570         for (i = 0; i < orphan_blks; i++) {
571                 block_t orphan_blk_no = old_cp_blk_no + 1 + get_sb(cp_payload);
572
573                 ret = dev_read_block(buf, orphan_blk_no++);
574                 ASSERT(ret >= 0);
575
576                 ret = dev_write_block(buf, new_cp_blk_no++);
577                 ASSERT(ret >= 0);
578         }
579
580         /* update summary blocks having nullified journal entries */
581         for (i = 0; i < NO_CHECK_TYPE; i++) {
582                 struct curseg_info *curseg = CURSEG_I(sbi, i);
583
584                 ret = dev_write_block(curseg->sum_blk, new_cp_blk_no++);
585                 ASSERT(ret >= 0);
586         }
587
588         /* write the last cp */
589         ret = dev_write_block(new_cp, new_cp_blk_no++);
590         ASSERT(ret >= 0);
591
592         /* Write nat bits */
593         if (flags & CP_NAT_BITS_FLAG)
594                 write_nat_bits(sbi, new_sb, new_cp, sbi->cur_cp == 1 ? 2 : 1);
595
596         /* disable old checkpoint */
597         memset(buf, 0, BLOCK_SZ);
598         ret = dev_write_block(buf, old_cp_blk_no);
599         ASSERT(ret >= 0);
600
601         free(buf);
602         free(new_cp);
603         DBG(0, "Info: Done to rebuild checkpoint blocks\n");
604 }
605
606 static int f2fs_resize_check(struct f2fs_sb_info *sbi, struct f2fs_super_block *new_sb)
607 {
608         struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
609         block_t user_block_count;
610         unsigned int overprov_segment_count;
611
612         overprov_segment_count = (get_newsb(segment_count_main) -
613                         c.new_reserved_segments) *
614                         c.new_overprovision / 100;
615
616         overprov_segment_count += 2 * get_newsb(segs_per_sec);
617
618         user_block_count = (get_newsb(segment_count_main) -
619                         overprov_segment_count) * c.blks_per_seg;
620
621         if (get_cp(valid_block_count) > user_block_count)
622                 return -1;
623
624         return 0;
625 }
626
627 static int f2fs_resize_grow(struct f2fs_sb_info *sbi)
628 {
629         struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
630         struct f2fs_super_block new_sb_raw;
631         struct f2fs_super_block *new_sb = &new_sb_raw;
632         block_t end_blkaddr, old_main_blkaddr, new_main_blkaddr;
633         unsigned int offset;
634         unsigned int offset_seg = 0;
635         int err = -1;
636
637         /* flush NAT/SIT journal entries */
638         flush_journal_entries(sbi);
639
640         memcpy(new_sb, F2FS_RAW_SUPER(sbi), sizeof(*new_sb));
641         if (get_new_sb(new_sb))
642                 return -1;
643
644         if (f2fs_resize_check(sbi, new_sb) < 0)
645                 return -1;
646
647         /* check nat availability */
648         if (get_sb(segment_count_nat) > get_newsb(segment_count_nat)) {
649                 err = shrink_nats(sbi, new_sb);
650                 if (err) {
651                         MSG(0, "\tError: Failed to shrink NATs\n");
652                         return err;
653                 }
654         }
655
656         old_main_blkaddr = get_sb(main_blkaddr);
657         new_main_blkaddr = get_newsb(main_blkaddr);
658         offset = new_main_blkaddr - old_main_blkaddr;
659         end_blkaddr = (get_sb(segment_count_main) <<
660                         get_sb(log_blocks_per_seg)) + get_sb(main_blkaddr);
661
662         err = -EAGAIN;
663         if (new_main_blkaddr < end_blkaddr) {
664                 err = f2fs_defragment(sbi, old_main_blkaddr, offset,
665                                                 new_main_blkaddr, 0);
666                 if (!err)
667                         offset_seg = offset >> get_sb(log_blocks_per_seg);
668                 MSG(0, "Try to do defragement: %s\n", err ? "Skip": "Done");
669         }
670         /* move whole data region */
671         if (err)
672                 migrate_main(sbi, offset);
673
674         migrate_ssa(sbi, new_sb, offset_seg);
675         migrate_nat(sbi, new_sb);
676         migrate_sit(sbi, new_sb, offset_seg);
677         rebuild_checkpoint(sbi, new_sb, offset_seg);
678         update_superblock(new_sb, SB_MASK_ALL);
679         print_raw_sb_info(sb);
680         print_raw_sb_info(new_sb);
681
682         return 0;
683 }
684
685 static int f2fs_resize_shrink(struct f2fs_sb_info *sbi)
686 {
687         struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
688         struct f2fs_super_block new_sb_raw;
689         struct f2fs_super_block *new_sb = &new_sb_raw;
690         block_t old_end_blkaddr, old_main_blkaddr;
691         block_t new_end_blkaddr, new_main_blkaddr, tmp_end_blkaddr;
692         unsigned int offset;
693         int err = -1;
694
695         /* flush NAT/SIT journal entries */
696         flush_journal_entries(sbi);
697
698         memcpy(new_sb, F2FS_RAW_SUPER(sbi), sizeof(*new_sb));
699         if (get_new_sb(new_sb))
700                 return -1;
701
702         if (f2fs_resize_check(sbi, new_sb) < 0)
703                 return -1;
704
705         /* check nat availability */
706         if (get_sb(segment_count_nat) > get_newsb(segment_count_nat)) {
707                 err = shrink_nats(sbi, new_sb);
708                 if (err) {
709                         MSG(0, "\tError: Failed to shrink NATs\n");
710                         return err;
711                 }
712         }
713
714         old_main_blkaddr = get_sb(main_blkaddr);
715         new_main_blkaddr = get_newsb(main_blkaddr);
716         offset = old_main_blkaddr - new_main_blkaddr;
717         old_end_blkaddr = (get_sb(segment_count_main) <<
718                         get_sb(log_blocks_per_seg)) + get_sb(main_blkaddr);
719         new_end_blkaddr = (get_newsb(segment_count_main) <<
720                         get_newsb(log_blocks_per_seg)) + get_newsb(main_blkaddr);
721
722         tmp_end_blkaddr = new_end_blkaddr + offset;
723         err = f2fs_defragment(sbi, tmp_end_blkaddr,
724                                 old_end_blkaddr - tmp_end_blkaddr,
725                                 tmp_end_blkaddr, 1);
726         MSG(0, "Try to do defragement: %s\n", err ? "Insufficient Space": "Done");
727
728         if (err) {
729                 return -ENOSPC;
730         }
731
732         update_superblock(new_sb, SB_MASK_ALL);
733         rebuild_checkpoint(sbi, new_sb, 0);
734         /*if (!c.safe_resize) {
735                 migrate_sit(sbi, new_sb, offset_seg);
736                 migrate_nat(sbi, new_sb);
737                 migrate_ssa(sbi, new_sb, offset_seg);
738         }*/
739
740         /* move whole data region */
741         //if (err)
742         //      migrate_main(sbi, offset);
743         print_raw_sb_info(sb);
744         print_raw_sb_info(new_sb);
745
746         return 0;
747 }
748
749 int f2fs_resize(struct f2fs_sb_info *sbi)
750 {
751         struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
752
753         /* may different sector size */
754         if ((c.target_sectors * c.sector_size >>
755                         get_sb(log_blocksize)) < get_sb(block_count))
756                 if (!c.safe_resize) {
757                         ASSERT_MSG("Nothing to resize, now only supports resizing with safe resize flag\n");
758                         return -1;
759                 } else {
760                         return f2fs_resize_shrink(sbi);
761                 }
762         else if (((c.target_sectors * c.sector_size >>
763                         get_sb(log_blocksize)) > get_sb(block_count)) ||
764                         c.force)
765                 return f2fs_resize_grow(sbi);
766         else {
767                 MSG(0, "Nothing to resize.\n");
768                 return 0;
769         }
770 }