1 /*
2 ext2_resize.c -- ext2 resizer
3 Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <config.h>
20
21 #ifndef DISCOVER_ONLY
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include "ext2.h"
26
27 static int ext2_add_group(struct ext2_fs *fs, blk_t groupsize)
28 {
29 blk_t admin;
30 int group;
31 blk_t groupstart;
32 blk_t newgdblocks;
33 int sparse;
34
35 if (fs->opt_verbose)
36 fputs ("ext2_add_group\n", stderr);
37
38 if (!ped_realloc ((void*) &fs->gd,
39 (fs->numgroups+1) * sizeof(struct ext2_group_desc)
40 + fs->blocksize))
41 return 0;
42
43 if (fs->opt_debug)
44 {
45 if (EXT2_SUPER_BLOCKS_COUNT(fs->sb) !=
46 EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)
47 + fs->numgroups * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb))
48 {
49 fputs ("ext2_add_group: last (existing) group "
50 "isn't complete!\n", stderr);
51
52 return 0;
53 }
54 }
55
56 group = fs->numgroups;
57 sparse = ext2_is_group_sparse(fs, group);
58 groupstart = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)
59 + group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
60
61 admin = fs->adminblocks;
62 if (!sparse)
63 admin -= fs->gdblocks + 1;
64
65 if (fs->opt_debug)
66 {
67 if (groupsize < fs->adminblocks ||
68 groupsize > EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb))
69 {
70 fprintf(stderr,
71 "ext2_add_group: groups of %i blocks are "
72 "impossible!\n", groupsize);
73
74 return 0;
75 }
76 }
77
78 newgdblocks = ped_div_round_up((fs->numgroups + 1)
79 * sizeof(struct ext2_group_desc),
80 fs->blocksize);
81 if (newgdblocks != fs->gdblocks)
82 {
83 int i;
84
85 for (i=0;i<fs->numgroups;i++)
86 if (ext2_is_group_sparse(fs, i))
87 {
88 blk_t start;
89
90 start = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)
91 + i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
92 ext2_set_block_state(fs,
93 start + fs->gdblocks + 1, 1, 1);
94 }
95
96 fs->gdblocks++;
97 fs->adminblocks++;
98 if (sparse)
99 admin++;
100 }
101
102 fs->numgroups++;
103
104 fs->sb.s_inodes_count = PED_CPU_TO_LE32(
105 EXT2_SUPER_INODES_COUNT(fs->sb)
106 + EXT2_SUPER_INODES_PER_GROUP(fs->sb));
107 fs->sb.s_blocks_count = PED_CPU_TO_LE32(
108 EXT2_SUPER_BLOCKS_COUNT(fs->sb) + groupsize);
109 fs->sb.s_free_blocks_count = PED_CPU_TO_LE32(
110 EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + groupsize - admin);
111 fs->sb.s_free_inodes_count = PED_CPU_TO_LE32(
112 EXT2_SUPER_FREE_INODES_COUNT(fs->sb)
113 + EXT2_SUPER_INODES_PER_GROUP(fs->sb));
114 fs->metadirty |= EXT2_META_SB;
115
116 {
117 blk_t off;
118 blk_t sparseoff;
119
120 off = groupstart;
121 sparseoff = off + fs->itoffset - 2;
122
123 if (sparse)
124 {
125 fs->gd[group].bg_block_bitmap
126 = PED_CPU_TO_LE32(sparseoff);
127 fs->gd[group].bg_inode_bitmap
128 = PED_CPU_TO_LE32(sparseoff + 1);
129 }
130 else
131 {
132 fs->gd[group].bg_block_bitmap
133 = PED_CPU_TO_LE32(off);
134 fs->gd[group].bg_inode_bitmap
135 = PED_CPU_TO_LE32(off + 1);
136 }
137
138 /* Hey, I don't know _why_ either */
139 fs->gd[group].bg_inode_table = PED_CPU_TO_LE32(sparseoff + 2);
140 }
141
142 fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16(groupsize - admin);
143 fs->gd[group].bg_free_inodes_count = PED_CPU_TO_LE16(
144 EXT2_SUPER_INODES_PER_GROUP(fs->sb));
145 fs->gd[group].bg_used_dirs_count = 0;
146 fs->metadirty |= EXT2_META_SB | EXT2_META_GD;
147
148 {
149 struct ext2_buffer_head *bh;
150 blk_t i;
151
152 bh = ext2_bcreate(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]));
153 if (!bh)
154 return 0;
155
156 if (sparse)
157 {
158 bh->data[0] |= _bitmap[0];
159 for (i=1;i<=fs->gdblocks;i++)
160 bh->data[i>>3] |= _bitmap[i&7];
161 }
162
163 i = EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]) - groupstart;
164 bh->data[i>>3] |= _bitmap[i&7];
165
166 i = EXT2_GROUP_INODE_BITMAP(fs->gd[group]) - groupstart;
167 bh->data[i>>3] |= _bitmap[i&7];
168
169 for (i=0;i<fs->inodeblocks;i++)
170 {
171 blk_t j;
172
173 j = EXT2_GROUP_INODE_TABLE(fs->gd[group])
174 - groupstart + i;
175 bh->data[j>>3] |= _bitmap[j&7];
176 }
177
178 for (i=groupsize;i<EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);i++)
179 bh->data[i>>3] |= _bitmap[i&7];
180
181 ext2_brelse(bh, 0); /* this is a block bitmap */
182 }
183
184 if (!ext2_zero_blocks(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group]), 1))
185 return 0;
186 if (!ext2_zero_blocks(fs, EXT2_GROUP_INODE_TABLE(fs->gd[group]),
187 fs->inodeblocks))
188 return 0;
189
190 if (fs->opt_safe)
191 if (!ext2_sync(fs))
192 return 0;
193
194 return 1;
195 }
196
197 static int ext2_del_group(struct ext2_fs *fs)
198 {
199 blk_t admin;
200 int group;
201 blk_t groupsize;
202 blk_t newgdblocks;
203 int sparse;
204
205 if (fs->opt_verbose)
206 fputs ("ext2_del_group\n", stderr);
207
208 group = fs->numgroups - 1;
209 sparse = ext2_is_group_sparse(fs, group);
210
211 admin = fs->adminblocks;
212 if (!sparse)
213 admin -= fs->gdblocks + 1;
214
215 groupsize = EXT2_SUPER_BLOCKS_COUNT(fs->sb)
216 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)
217 - group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
218
219 if (EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) < groupsize - admin)
220 {
221 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
222 _("File system is too full to remove a group!"));
223
224 return 0;
225 }
226
227 if (EXT2_SUPER_FREE_INODES_COUNT(fs->sb)
228 < EXT2_SUPER_INODES_PER_GROUP(fs->sb))
229 {
230 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
231 _("File system has too many allocated inodes to "
232 "remove a group!"));
233 return 0;
234 }
235
236 if (fs->opt_debug)
237 {
238 if (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[group]) !=
239 EXT2_SUPER_INODES_PER_GROUP(fs->sb))
240 {
241 fputs ("ext2_del_group: this should not "
242 "happen anymore!\n", stderr);
243
244 return 0;
245 }
246 }
247
248 newgdblocks = ped_div_round_up((fs->numgroups - 1) *
249 sizeof(struct ext2_group_desc), fs->blocksize);
250
251 if (newgdblocks != fs->gdblocks)
252 {
253 int i;
254
255 for (i=0;i<fs->numgroups;i++)
256 if (ext2_is_group_sparse(fs, i))
257 {
258 blk_t start;
259
260 start = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) +
261 i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
262 ext2_set_block_state(fs,
263 start + fs->gdblocks,
264 0, 1);
265 }
266
267 fs->gdblocks--;
268 fs->adminblocks--;
269 if (sparse)
270 admin--;
271 }
272
273 if (fs->opt_debug)
274 {
275 if (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group])
276 != groupsize - admin)
277 {
278 blk_t i;
279 blk_t num;
280 blk_t offset;
281
282 offset = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) +
283 group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
284 num = EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
285
286 for (i=0;i<num;i++)
287 if (ext2_is_data_block(fs, offset+i) &&
288 ext2_get_block_state(fs, offset+i))
289 {
290 fprintf(stderr,
291 "error: block relocator "
292 "should have relocated "
293 "%i\n",
294 offset+i);
295
296 return 0;
297 }
298 }
299 }
300
301 fs->numgroups--;
302
303 fs->sb.s_inodes_count = PED_CPU_TO_LE32(
304 EXT2_SUPER_INODES_COUNT(fs->sb)
305 - EXT2_SUPER_INODES_PER_GROUP(fs->sb));
306 fs->sb.s_blocks_count = PED_CPU_TO_LE32(
307 EXT2_SUPER_BLOCKS_COUNT(fs->sb) - groupsize);
308 fs->sb.s_free_blocks_count = PED_CPU_TO_LE32(
309 EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) - (groupsize - admin));
310 fs->sb.s_free_inodes_count = PED_CPU_TO_LE32(
311 EXT2_SUPER_FREE_INODES_COUNT(fs->sb)
312 - EXT2_SUPER_INODES_PER_GROUP(fs->sb));
313 fs->metadirty |= EXT2_META_SB;
314
315 if (fs->opt_safe)
316 ext2_sync(fs);
317
318 ped_realloc ((void*) &fs->gd,
319 fs->numgroups * sizeof(struct ext2_group_desc)
320 + fs->blocksize);
321
322 return 1;
323 }
324
325 static int ext2_grow_group(struct ext2_fs *fs, blk_t newsize)
326 {
327 int group;
328 blk_t groupoff;
329 blk_t gblocks;
330 blk_t i;
331
332 if (fs->opt_verbose)
333 fputs ("ext2_grow_group\n", stderr);
334
335 group = fs->numgroups - 1;
336 groupoff = group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)
337 + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
338 gblocks = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - groupoff;
339
340 if (fs->opt_debug)
341 {
342 if (newsize < gblocks)
343 {
344 fputs ("ext2_grow_group: called to shrink group!\n",
345 stderr);
346
347 return 0;
348 }
349
350 if (gblocks == newsize)
351 {
352 fputs ("ext2_grow_group: nothing to do!\n", stderr);
353 return 0;
354 }
355 }
356
357 for (i=gblocks;i<newsize;i++)
358 ext2_set_block_state(fs, groupoff + i, 0, 1);
359
360 fs->sb.s_blocks_count = PED_CPU_TO_LE32(
361 EXT2_SUPER_BLOCKS_COUNT(fs->sb) + newsize - gblocks);
362 fs->metadirty |= EXT2_META_SB;
363
364 if (fs->opt_safe)
365 ext2_sync(fs);
366
367 return 1;
368 }
369
370 static int ext2_shrink_group(struct ext2_fs *fs, blk_t newsize)
371 {
372 blk_t admin;
373 int group;
374 blk_t groupoff;
375 blk_t gblocks;
376 blk_t i;
377
378 if (fs->opt_verbose)
379 fputs ("ext2_shrink_group\n", stderr);
380
381 group = fs->numgroups - 1;
382
383 admin = fs->adminblocks;
384 if (!ext2_is_group_sparse(fs, group))
385 admin -= fs->gdblocks + 1;
386
387 groupoff = group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)
388 + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
389 gblocks = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - groupoff;
390
391 if (fs->opt_debug)
392 {
393 if (newsize < admin)
394 {
395 fprintf(stderr,
396 "ext2_shrink_group: cant shrink a group "
397 "to %i blocks\n", newsize);
398
399 return 0;
400 }
401
402 if (newsize > gblocks)
403 {
404 fputs ("ext2_shrink_group: called to grow group!\n",
405 stderr);
406
407 return 0;
408 }
409
410 if (gblocks == newsize)
411 {
412 fputs ("ext2_shrink_group: nothing to do!\n",
413 stderr);
414
415 return 0;
416 }
417 }
418
419 for (i=newsize;i<gblocks;i++)
420 {
421 if (fs->opt_debug && ext2_get_block_state(fs, groupoff + i))
422 {
423 fprintf(stderr,
424 "error: block relocator should have relocated "
425 "%i\n",
426 groupoff + i);
427
428 return 0;
429 }
430
431 ext2_set_block_state(fs, groupoff + i, 1, 0);
432 }
433
434 i = gblocks - newsize;
435 fs->sb.s_blocks_count = PED_CPU_TO_LE32(
436 EXT2_SUPER_BLOCKS_COUNT(fs->sb) - i);
437 fs->sb.s_free_blocks_count = PED_CPU_TO_LE32(
438 EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) - i);
439 fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16(
440 EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) - i);
441
442 fs->metadirty |= EXT2_META_SB | EXT2_META_GD;
443
444 if (fs->opt_safe)
445 ext2_sync(fs);
446
447 return 1;
448 }
449
450
451
452
453
454
455 static int ext2_grow_fs(struct ext2_fs *fs, blk_t newsize, PedTimer* timer)
456 {
457 blk_t diff;
458 blk_t sizelast;
459 blk_t origsize = EXT2_SUPER_BLOCKS_COUNT(fs->sb);
460
461 if (fs->opt_verbose)
462 fputs ("ext2_grow_fs\n", stderr);
463
464 if (!ext2_block_relocate(fs, newsize))
465 return 0;
466
467 if (!ext2_metadata_push(fs, newsize))
468 return 0;
469
470 diff = newsize - EXT2_SUPER_BLOCKS_COUNT(fs->sb);
471 sizelast = EXT2_SUPER_BLOCKS_COUNT(fs->sb)
472 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)
473 - (fs->numgroups-1) * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
474
475 if (sizelast != EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb))
476 {
477 blk_t growto;
478
479 growto = sizelast + diff;
480 if (growto > EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb))
481 growto = EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
482
483 if (!ext2_grow_group(fs, growto))
484 return 0;
485
486 diff -= growto - sizelast;
487 }
488
489 ped_timer_reset (timer);
490 ped_timer_set_state_name (timer, _("adding groups"));
491
492 while (diff)
493 {
494 ped_timer_update (timer,
495 1.0 - 1.0 * diff / (newsize - origsize));
496
497 sizelast = PED_MIN(diff, EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb));
498 if (!ext2_add_group(fs, sizelast))
499 return 0;
500
501 diff -= sizelast;
502 }
503
504 ped_timer_update (timer, 1.0);
505
506 return 1;
507 }
508
509 static int ext2_shrink_fs(struct ext2_fs *fs, blk_t newsize,
510 PedTimer* timer)
511 {
512 blk_t origsize = EXT2_SUPER_BLOCKS_COUNT (fs->sb);
513 blk_t diff;
514 int newgroups;
515 blk_t sizelast;
516
517 if (fs->opt_verbose)
518 fputs ("ext2_shrink_fs\n", stderr);
519
520 newgroups = ped_div_round_up (newsize
521 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb),
522 EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb));
523 if (EXT2_SUPER_BLOCKS_COUNT(fs->sb)
524 - EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) > newsize)
525 {
526 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
527 _("Your file system is too full to resize it to %i "
528 "blocks. Sorry."), newsize);
529 return 0;
530 }
531
532 if (EXT2_SUPER_INODES_COUNT(fs->sb)
533 - EXT2_SUPER_FREE_INODES_COUNT(fs->sb)
534 > newgroups * EXT2_SUPER_INODES_PER_GROUP(fs->sb))
535 {
536 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
537 _("Your file system has too many occupied inodes to "
538 "resize it to %i blocks. Sorry."), newsize);
539 return 0;
540 }
541
542 if (!ext2_inode_relocate(fs, newgroups))
543 return 0;
544
545 if (!ext2_block_relocate(fs, newsize))
546 return 0;
547
548 diff = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - newsize;
549
550 ped_timer_reset (timer);
551 ped_timer_set_state_name (timer, _("shrinking"));
552
553 while (diff > 0)
554 {
555 ped_timer_update (timer,
556 1.0 - 1.0 * diff / (origsize - newsize));
557
558 sizelast = EXT2_SUPER_BLOCKS_COUNT(fs->sb)
559 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) -
560 (fs->numgroups - 1)
561 * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
562
563 if (diff < sizelast)
564 {
565 if (!ext2_shrink_group(fs, sizelast - diff))
566 return 0;
567
568 diff = 0;
569 }
570 else
571 {
572 if (!ext2_del_group(fs))
573 return 0;
574
575 diff -= sizelast;
576 }
577 }
578
579 ped_timer_update (timer, 1.0);
580
581 return 1;
582 }
583
584 int ext2_determine_itoffset(struct ext2_fs *fs)
585 {
586 int i;
587
588 fs->itoffset = EXT2_GROUP_INODE_TABLE(fs->gd[0])
589 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
590
591 /*PED_DEBUG (0x20, "itoffset is %d", fs->itoffset);
592
593 PED_DEBUG (0x20, "walking %d groups", fs->numgroups);*/
594
595 for (i=0;i<fs->numgroups;i++)
596 {
597 blk_t start;
598 blk_t bb;
599 blk_t ib;
600 blk_t it;
601
602 start = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)
603 + (i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb));
604 it = start + fs->itoffset;
605
606 /*PED_DEBUG (0x21, "start = %d, it = %d", start, it);*/
607
608 if (ext2_is_group_sparse(fs, i))
609 {
610 /*PED_DEBUG (0x21, "%d has a superblock copy", i);*/
611 bb = it - 2;
612 ib = it - 1;
613 }
614 else
615 {
616 /*PED_DEBUG (0x21, "%d doesn't have a superblock copy",
617 i);*/
618 bb = start;
619 ib = start + 1;
620 }
621
622 if (EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) != bb ||
623 EXT2_GROUP_INODE_BITMAP(fs->gd[i]) != ib ||
624 EXT2_GROUP_INODE_TABLE(fs->gd[i]) != it)
625 {
626 /* ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
627 PED_EXCEPTION_CANCEL,
628 _("This ext2 file system has a rather strange layout! "
629 "Parted can't resize this (yet)."));*/
630
631 /* PED_DEBUG (0x21, "calculated block bitmap to be %d, "
632 "but fs says %d.", bb,
633 EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]));
634 PED_DEBUG (0x21, "calculated inode bitmap to be %d, "
635 "but fs says %d.", ib,
636 EXT2_GROUP_INODE_BITMAP(fs->gd[i]));
637 PED_DEBUG (0x21, "calculated inode table to be %d, "
638 "but fs says %d.", it,
639 EXT2_GROUP_INODE_TABLE(fs->gd[i]));*/
640
641 return 0;
642 }
643 }
644
645 return 1;
646 }
647
648 int ext2_resize_fs(struct ext2_fs *fs, blk_t newsize, PedTimer* timer)
649 {
650 blk_t residue;
651 int status;
652
653 if (EXT2_SUPER_STATE(fs->sb) & EXT2_ERROR_FS)
654 {
655 ped_exception_throw (
656 PED_EXCEPTION_WARNING, PED_EXCEPTION_CANCEL,
657 _("File system has errors! You should run e2fsck."));
658 return 0;
659 }
660
661 if (!(EXT2_SUPER_STATE(fs->sb) & EXT2_VALID_FS))
662 {
663 ped_exception_throw (
664 PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
665 _("File system was not cleanly unmounted! "
666 "You should run e2fsck."));
667 return 0;
668 }
669
670 if (EXT2_SUPER_FEATURE_COMPAT(fs->sb)
671 & EXT2_FEATURE_COMPAT_HAS_DIR_INDEX) {
672 if (ped_exception_throw (
673 PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE_CANCEL,
674 _("The file system has the 'dir_index' feature "
675 "enabled. Parted can only resize the file system "
676 "if it disables this feature. You can enable it "
677 "later by running 'tune2fs -O dir_index DEVICE' "
678 "and then 'e2fsck -fD DEVICE'."))
679 != PED_EXCEPTION_IGNORE)
680 return 0;
681 fs->sb.s_feature_compat
682 = PED_CPU_TO_LE32(EXT2_SUPER_FEATURE_COMPAT(fs->sb)
683 & ~EXT2_FEATURE_COMPAT_HAS_DIR_INDEX);
684 fs->metadirty |= EXT2_META_SB;
685 }
686
687 if (!ext2_determine_itoffset(fs) && ped_exception_throw (
688 PED_EXCEPTION_WARNING,
689 PED_EXCEPTION_OK_CANCEL,
690 _("A resize operation on this file system will "
691 "use EXPERIMENTAL code\n"
692 "that MAY CORRUPT it (although no one has "
693 "reported any such damage yet).\n"
694 "You should at least backup your data first, "
695 "and run 'e2fsck -f' afterwards."))
696 == PED_EXCEPTION_CANCEL)
697 {
698 return 0;
699 }
700
701 if (fs->opt_verbose)
702 fputs ("ext2_resize_fs\n", stderr);
703
704 residue = (newsize - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb))
705 % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
706 if (residue && residue <= fs->adminblocks)
707 newsize -= residue;
708
709 if (newsize == EXT2_SUPER_BLOCKS_COUNT(fs->sb))
710 return 1;
711
712 fs->relocator_pool
713 = (unsigned char *)ped_malloc(ext2_relocator_pool_size << 10);
714 if (!fs->relocator_pool)
715 return 0;
716 fs->relocator_pool_end
717 = fs->relocator_pool + (ext2_relocator_pool_size << 10);
718
719 if (newsize < EXT2_SUPER_BLOCKS_COUNT(fs->sb))
720 status = ext2_shrink_fs(fs, newsize, timer);
721 else
722 status = ext2_grow_fs(fs, newsize, timer);
723
724 ped_free(fs->relocator_pool);
725 fs->relocator_pool = NULL;
726 fs->relocator_pool_end = NULL;
727
728 return status;
729 }
730 #endif /* !DISCOVER_ONLY */