2
ext2.c -- generic ext2 stuff
3
Copyright (C) 1998-2001, 2007, 2009-2010 Free Software Foundation,
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 3 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program. If not, see <http://www.gnu.org/licenses/>.
28
#include <uuid/uuid.h>
31
/* ext2 stuff ****************************************************************/
33
unsigned char _bitmap[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
35
int ext2_copy_block(struct ext2_fs *fs, blk_t from, blk_t to)
37
unsigned char* buf = ped_malloc (fs->blocksize);
39
if (!ext2_bcache_flush(fs, from)) return 0;
40
if (!ext2_bcache_flush(fs, to)) return 0;
42
if (!ext2_read_blocks(fs, buf, from, 1)) return 0;
43
if (!ext2_write_blocks(fs, buf, to, 1)) return 0;
48
int ext2_get_block_state(struct ext2_fs *fs, blk_t block)
50
struct ext2_buffer_head *bh;
55
block -= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
56
group = block / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
57
offset = block % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
59
bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]));
60
state = bh->data[offset>>3] & _bitmap[offset&7];
66
blk_t ext2_find_free_block(struct ext2_fs *fs)
70
for (i=0;i<fs->numgroups;i++)
71
if (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[i]))
76
offset = i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)
77
+ EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
78
for (j=fs->adminblocks;
79
j<EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
81
if (ext2_is_data_block(fs, offset + j) &&
82
!ext2_get_block_state(fs, offset + j))
85
ped_exception_throw (PED_EXCEPTION_ERROR,
87
_("Inconsistent group descriptors!"));
90
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
91
_("File system full!"));
95
ino_t ext2_find_free_inode(struct ext2_fs *fs)
99
for (i=0;i<fs->numgroups;i++)
100
if (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[i]))
105
offset = i * EXT2_SUPER_INODES_PER_GROUP(fs->sb) + 1;
106
for (j=0;j<EXT2_SUPER_INODES_PER_GROUP(fs->sb);j++)
107
if (!ext2_get_inode_state(fs, offset + j))
110
ped_exception_throw (PED_EXCEPTION_ERROR,
111
PED_EXCEPTION_CANCEL,
112
_("Inconsistent group descriptors!"));
115
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
116
_("File system full!"));
120
int ext2_move_blocks(struct ext2_fs *fs, blk_t src, blk_t num, blk_t dest)
125
ped_exception_fetch_all();
126
if ((buf = ped_malloc(num << fs->logsize)) != NULL)
128
ped_exception_leave_all();
130
if (!ext2_bcache_flush_range(fs, src, num)) return 0;
131
if (!ext2_bcache_flush_range(fs, dest, num)) return 0;
133
if (!ext2_read_blocks(fs, buf, src, num)) return 0;
134
if (!ext2_write_blocks(fs, buf, dest, num)) return 0;
139
ped_exception_catch();
140
ped_exception_leave_all();
145
if (!ext2_copy_block(fs, src+i, dest+i))
151
if (!ext2_copy_block(fs, src+i, dest+i))
157
int ext2_read_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num)
159
return fs->devhandle->ops->read(fs->devhandle->cookie, ptr, block, num);
162
int ext2_set_block_state(struct ext2_fs *fs, blk_t block, int state, int updatemetadata)
164
struct ext2_buffer_head *bh;
168
block -= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
169
group = block / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
170
offset = block % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
172
bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]));
175
bh->data[offset>>3] |= _bitmap[offset&7];
177
bh->data[offset>>3] &= ~_bitmap[offset&7];
184
diff = state ? -1 : 1;
186
fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16
187
(EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) + diff);
188
ext2_super_free_blocks_count_set(&fs->sb,
189
EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + diff);
190
fs->metadirty |= EXT2_META_SB | EXT2_META_GD;
195
int ext2_write_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num)
197
return fs->devhandle->ops->write(fs->devhandle->cookie, ptr, block, num);
200
int ext2_zero_blocks(struct ext2_fs *fs, blk_t block, blk_t num)
205
ped_exception_fetch_all();
206
buf = ped_malloc (num << fs->logsize);
209
ped_exception_leave_all();
211
memset(buf, 0, num << fs->logsize);
212
if (!ext2_bcache_flush_range(fs, block, num))
214
if (!ext2_write_blocks(fs, buf, block, num))
219
ped_exception_catch();
221
buf = ped_malloc (fs->blocksize);
224
ped_exception_leave_all();
226
memset(buf, 0, fs->blocksize);
230
if (!ext2_bcache_flush(fs, block+i))
232
if (!ext2_write_blocks(fs, buf, block+i, 1))
239
ped_exception_catch();
240
ped_exception_leave_all();
244
struct ext2_buffer_head *bh;
246
bh = ext2_bcreate(fs, block+i);
250
if (!ext2_brelse(bh, 1))
261
off_t ext2_get_inode_offset(struct ext2_fs *fs, ino_t inode, blk_t *block)
268
group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb);
269
offset = (inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb))
270
* sizeof(struct ext2_inode);
272
*block = EXT2_GROUP_INODE_TABLE(fs->gd[group])
273
+ (offset >> fs->logsize);
275
return offset & (fs->blocksize - 1);
278
int ext2_get_inode_state(struct ext2_fs *fs, ino_t inode)
280
struct ext2_buffer_head *bh;
286
group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb);
287
offset = inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb);
289
bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group]));
290
ret = bh->data[offset>>3] & _bitmap[offset&7];
296
int ext2_read_inode(struct ext2_fs *fs, ino_t inode, struct ext2_inode *data)
298
struct ext2_buffer_head *bh;
302
off = ext2_get_inode_offset(fs, inode, &blk);
304
bh = ext2_bread(fs, blk);
308
memcpy(data, bh->data + off, sizeof(struct ext2_inode));
313
int ext2_set_inode_state(struct ext2_fs *fs, ino_t inode, int state, int updatemetadata)
315
struct ext2_buffer_head *bh;
320
group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb);
321
offset = inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb);
323
bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group]));
328
bh->data[offset>>3] |= _bitmap[offset&7];
330
bh->data[offset>>3] &= ~_bitmap[offset&7];
337
diff = state ? -1 : 1;
339
fs->gd[group].bg_free_inodes_count = PED_CPU_TO_LE16
340
(EXT2_GROUP_FREE_INODES_COUNT(fs->gd[group]) + diff);
341
fs->sb.s_free_inodes_count = PED_CPU_TO_LE32
342
(EXT2_SUPER_FREE_INODES_COUNT(fs->sb) + diff);
343
fs->metadirty = EXT2_META_SB | EXT2_META_GD;
349
_inode_update_size(struct ext2_fs *fs, struct ext2_inode *inode, int delta)
351
int i512perblock = 1 << (fs->logsize - 9);
354
/* i_blocks is in 512 byte blocks */
355
inode->i_blocks = PED_CPU_TO_LE32(EXT2_INODE_BLOCKS(*inode)
356
+ delta * i512perblock);
357
size = EXT2_INODE_SIZE(*inode) + delta * fs->blocksize;
358
inode->i_size = PED_CPU_TO_LE32(size % (1LL << 32));
359
inode->i_size_high = PED_CPU_TO_LE32(size / (1LL << 32));
360
inode->i_mtime = PED_CPU_TO_LE32(time(NULL));
363
int ext2_do_inode(struct ext2_fs *fs, struct ext2_inode *inode, blk_t block,
366
struct ext2_buffer_head *bh;
370
int u32perblock = fs->blocksize >> 2;
371
int i512perblock = 1 << (fs->logsize - 9);
373
if (block == 0 || EXT2_INODE_MODE(*inode) == 0)
379
case EXT2_ACTION_ADD:
380
fprintf(stderr,"adding 0x%04x to inode\n",
383
case EXT2_ACTION_DELETE:
384
fprintf(stderr,"deleting 0x%04x from inode\n",
387
case EXT2_ACTION_FIND:
388
fprintf(stderr,"finding 0x%04x in inode\n",
393
/* Direct blocks for first 12 blocks */
394
for (i = 0; i < EXT2_NDIR_BLOCKS; i++)
396
if (action == EXT2_ACTION_ADD && !EXT2_INODE_BLOCK(*inode, i))
398
inode->i_block[i] = PED_CPU_TO_LE32(block);
399
_inode_update_size (fs, inode, 1);
400
ext2_set_block_state(fs, block, 1, 1);
403
if (EXT2_INODE_BLOCK(*inode, i) == block)
405
if (action == EXT2_ACTION_DELETE)
407
inode->i_block[i] = 0;
408
_inode_update_size (fs, inode, -1);
409
ext2_set_block_state(fs, block, 0, 1);
413
if (EXT2_INODE_BLOCK(*inode, i))
414
count += i512perblock;
417
count += EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK) ? i512perblock : 0;
418
count += EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK) ? i512perblock : 0;
419
count += EXT2_INODE_BLOCK(*inode, EXT2_TIND_BLOCK) ? i512perblock : 0;
421
if (!EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK) ||
422
(count >= EXT2_INODE_BLOCKS(*inode) && action != EXT2_ACTION_ADD))
425
bh = ext2_bread(fs, EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK));
426
udata = (uint32_t *)bh->data;
428
/* Indirect blocks for next 256/512/1024 blocks (for 1k/2k/4k blocks) */
429
for (i = 0; i < u32perblock; i++) {
430
if (action == EXT2_ACTION_ADD && !udata[i]) {
432
udata[i] = PED_CPU_TO_LE32(block);
433
_inode_update_size (fs, inode, 1);
434
ext2_set_block_state(fs, block, 1, 1);
436
return EXT2_NDIR_BLOCKS + i;
438
if (PED_LE32_TO_CPU(udata[i]) == block) {
439
if (action == EXT2_ACTION_DELETE) {
442
_inode_update_size (fs, inode, -1);
443
ext2_set_block_state(fs, block, 0, 1);
446
return EXT2_NDIR_BLOCKS + i;
450
count += i512perblock;
451
if (count >= EXT2_INODE_BLOCKS(*inode) &&
452
action != EXT2_ACTION_ADD)
459
if (!EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK) ||
460
(count >= EXT2_INODE_BLOCKS(*inode) && action != EXT2_ACTION_ADD))
462
bh = ext2_bread(fs, EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK));
463
udata = (uint32_t *)bh->data;
465
/* Double indirect blocks for next 2^16/2^18/2^20 1k/2k/4k blocks */
466
for (i = 0; i < u32perblock; i++) {
467
struct ext2_buffer_head *bh2;
475
bh2 = ext2_bread(fs, PED_LE32_TO_CPU(udata[i]));
476
udata2 = (uint32_t *)bh2->data;
477
count += i512perblock;
479
for (j = 0; j < u32perblock; j++) {
480
if (action == EXT2_ACTION_ADD && !udata2[j]) {
482
udata2[j] = PED_CPU_TO_LE32(block);
483
_inode_update_size (fs, inode, 1);
484
ext2_set_block_state(fs, block, 1, 1);
487
return EXT2_NDIR_BLOCKS + i * u32perblock + j;
489
if (PED_LE32_TO_CPU(udata2[j]) == block) {
490
if (action == EXT2_ACTION_DELETE) {
493
_inode_update_size (fs, inode, -1);
494
ext2_set_block_state(fs, block, 0, 1);
498
return EXT2_NDIR_BLOCKS + i * u32perblock + j;
502
count += i512perblock;
503
if (count >= EXT2_INODE_BLOCKS(*inode) &&
504
action != EXT2_ACTION_ADD)
512
/* FIXME: we should check for triple-indirect blocks here, but it
513
* would be nice to have a better routine to traverse blocks, and
514
* file systems that need triple-indirect blocks for the resize
515
* inode are too big to worry about yet.
521
int ext2_write_inode(struct ext2_fs *fs, ino_t inode, const struct ext2_inode *data)
523
struct ext2_buffer_head *bh;
527
off = ext2_get_inode_offset(fs, inode, &blk);
529
bh = ext2_bread(fs, blk);
533
memcpy(bh->data + off, data, sizeof(struct ext2_inode));
539
int ext2_zero_inode(struct ext2_fs *fs, ino_t inode)
541
struct ext2_inode buf;
543
memset(&buf, 0, sizeof(struct ext2_inode));
544
return ext2_write_inode(fs, inode, &buf);
551
/* check whether y is root of x
552
* (formula grabbed from linux ext2 kernel source) */
553
static int is_root(int x, int y)
570
/* check whether group contains a superblock copy on file systems
571
* where not all groups have one (sparse superblock feature) */
572
int ext2_is_group_sparse(struct ext2_fs *fs, int group)
577
if (is_root(group, 3) || is_root(group, 5) || is_root(group, 7))
583
void ext2_close(struct ext2_fs *fs)
585
ext2_commit_metadata(fs, EXT2_META_PRIMARY | EXT2_META_BACKUP);
588
ext2_bcache_deinit(fs);
590
fs->devhandle->ops->close(fs->devhandle->cookie);
596
int ext2_commit_metadata(struct ext2_fs *fs, int copies)
600
int wmeta = fs->metadirty & copies;
601
unsigned char* sb = ped_malloc(fs->blocksize);
602
struct ext2_super_block *sb_for_io;
605
/* See if there is even anything to write... */
606
if (wmeta == EXT2_META_CLEAN)
609
ext2_super_r_blocks_count_set(&fs->sb,
610
fs->r_frac * (loff_t)EXT2_SUPER_BLOCKS_COUNT(fs->sb)
613
if (!ext2_read_blocks (fs, sb, 0, 1))
616
if (EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)) {
617
memcpy(sb, &fs->sb, 1024);
618
sb_for_io = (struct ext2_super_block *) sb;
620
memcpy(sb+1024, &fs->sb, 1024);
621
sb_for_io = (struct ext2_super_block *) (sb + 1024);
624
num = copies & EXT2_META_BACKUP ? fs->numgroups : 1;
626
for (i = 0, sb_block = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); i < num;
627
i++, sb_block += EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb))
630
if (!ext2_is_group_sparse(fs, i))
633
if (fs->dynamic_version)
634
sb_for_io->s_block_group_nr = PED_CPU_TO_LE16 (i);
636
if ((i == 0 && wmeta & EXT2_META_PRIMARY_SB) ||
637
(i != 0 && wmeta & EXT2_META_SB))
639
if (!ext2_bcache_flush_range(fs, sb_block, 1))
641
if (!ext2_write_blocks(fs, sb, sb_block, 1))
644
if ((i == 0 && wmeta & EXT2_META_PRIMARY_GD) ||
645
(i != 0 && wmeta & EXT2_META_GD))
647
if (!ext2_bcache_flush_range(fs, sb_block + 1,
650
if (!ext2_write_blocks(fs, fs->gd, sb_block + 1,
656
sb_for_io->s_block_group_nr = 0;
658
/* Clear the flags of the components we just finished writing. */
659
fs->metadirty &= ~copies;
664
int ext2_sync(struct ext2_fs *fs)
666
if (!ext2_commit_metadata(fs, EXT2_META_PRIMARY)) return 0;
667
if (!ext2_bcache_sync(fs)) return 0;
668
if (!fs->devhandle->ops->sync(fs->devhandle->cookie)) return 0;
672
struct ext2_fs *ext2_open(struct ext2_dev_handle *handle, int state)
676
if ((fs = (struct ext2_fs *) ped_malloc(sizeof(struct ext2_fs)))
680
handle->ops->set_blocksize(handle->cookie, 10);
682
if (!handle->ops->read(handle->cookie, &fs->sb, 1, 1)
683
|| EXT2_SUPER_MAGIC(fs->sb) != EXT2_SUPER_MAGIC_CONST)
685
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
686
_("Invalid superblock. Are you sure this is an ext2 "
696
if (EXT2_SUPER_STATE(fs->sb) & EXT2_ERROR_FS & ~(state & EXT2_ERROR_FS))
698
if (ped_exception_throw (
699
PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE_CANCEL,
700
_("File system has errors! You should run e2fsck."))
701
== PED_EXCEPTION_CANCEL)
705
if (!((EXT2_SUPER_STATE(fs->sb) | state) & EXT2_VALID_FS)
706
|| (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb)
707
& EXT3_FEATURE_INCOMPAT_RECOVER))
709
if (ped_exception_throw (
710
PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
711
_("File system was not cleanly unmounted! "
712
"You should run e2fsck. Modifying an unclean "
713
"file system could cause severe corruption."))
714
!= PED_EXCEPTION_IGNORE)
718
fs->dynamic_version = EXT2_SUPER_REV_LEVEL (fs->sb) > 0;
720
if ((EXT2_SUPER_FEATURE_COMPAT(fs->sb)
721
& ~(EXT3_FEATURE_COMPAT_HAS_JOURNAL |
722
EXT2_FEATURE_COMPAT_HAS_DIR_INDEX)) ||
723
(EXT2_SUPER_FEATURE_INCOMPAT(fs->sb)
724
& ~(EXT2_FEATURE_INCOMPAT_FILETYPE |
725
EXT3_FEATURE_INCOMPAT_RECOVER |
726
EXT4_FEATURE_INCOMPAT_64BIT)) ||
727
(EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb)
728
& ~(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER |
729
EXT2_FEATURE_RO_COMPAT_LARGE_FILE)))
731
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
732
_("File system has an incompatible feature enabled. "
733
"Compatible features are has_journal, dir_index, "
734
"filetype, sparse_super and large_file. "
735
"Use tune2fs or debugfs to remove features."));
739
fs->devhandle = handle;
740
fs->logsize = EXT2_SUPER_LOG_BLOCK_SIZE(fs->sb) + 10;
741
handle->ops->set_blocksize(handle->cookie, fs->logsize);
743
if (!ext2_bcache_init(fs))
745
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
746
_("Error allocating buffer cache."));
750
fs->blocksize = 1 << fs->logsize;
752
fs->numgroups = ped_div_round_up (EXT2_SUPER_BLOCKS_COUNT(fs->sb)
753
- EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb),
754
EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb));
755
fs->gdblocks = ped_div_round_up (fs->numgroups
756
* sizeof(struct ext2_group_desc),
758
fs->inodeblocks = ped_div_round_up (EXT2_SUPER_INODES_PER_GROUP(fs->sb)
759
* sizeof(struct ext2_inode),
761
fs->r_frac = ped_div_round_up (100 * (loff_t)EXT2_SUPER_R_BLOCKS_COUNT(fs->sb),
762
EXT2_SUPER_BLOCKS_COUNT(fs->sb));
763
fs->adminblocks = 3 + fs->gdblocks + fs->inodeblocks;
766
if (EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb)
767
& EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
770
fs->has_journal = 0 < (EXT2_SUPER_FEATURE_COMPAT(fs->sb)
771
& EXT3_FEATURE_COMPAT_HAS_JOURNAL);
772
fs->has_internal_journal
774
&& uuid_is_null(EXT2_SUPER_JOURNAL_UUID(fs->sb))
775
&& EXT2_SUPER_JOURNAL_INUM(fs->sb);
777
fs->gd = ped_malloc (fs->numgroups * sizeof (struct ext2_group_desc)
780
goto error_deinit_bcache;
782
ext2_read_blocks(fs, fs->gd, EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) + 1,
790
ext2_bcache_deinit(fs);
797
#endif /* !DISCOVER_ONLY */