0001
0002
0003
0004
0005
0006
0007 #include "ext4.h"
0008 #include <linux/fsmap.h>
0009 #include "fsmap.h"
0010 #include "mballoc.h"
0011 #include <linux/sort.h>
0012 #include <linux/list_sort.h>
0013 #include <trace/events/ext4.h>
0014
0015
0016 void ext4_fsmap_from_internal(struct super_block *sb, struct fsmap *dest,
0017 struct ext4_fsmap *src)
0018 {
0019 dest->fmr_device = src->fmr_device;
0020 dest->fmr_flags = src->fmr_flags;
0021 dest->fmr_physical = src->fmr_physical << sb->s_blocksize_bits;
0022 dest->fmr_owner = src->fmr_owner;
0023 dest->fmr_offset = 0;
0024 dest->fmr_length = src->fmr_length << sb->s_blocksize_bits;
0025 dest->fmr_reserved[0] = 0;
0026 dest->fmr_reserved[1] = 0;
0027 dest->fmr_reserved[2] = 0;
0028 }
0029
0030
0031 void ext4_fsmap_to_internal(struct super_block *sb, struct ext4_fsmap *dest,
0032 struct fsmap *src)
0033 {
0034 dest->fmr_device = src->fmr_device;
0035 dest->fmr_flags = src->fmr_flags;
0036 dest->fmr_physical = src->fmr_physical >> sb->s_blocksize_bits;
0037 dest->fmr_owner = src->fmr_owner;
0038 dest->fmr_length = src->fmr_length >> sb->s_blocksize_bits;
0039 }
0040
0041
0042 struct ext4_getfsmap_info {
0043 struct ext4_fsmap_head *gfi_head;
0044 ext4_fsmap_format_t gfi_formatter;
0045 void *gfi_format_arg;
0046 ext4_fsblk_t gfi_next_fsblk;
0047 u32 gfi_dev;
0048 ext4_group_t gfi_agno;
0049 struct ext4_fsmap gfi_low;
0050 struct ext4_fsmap gfi_high;
0051 struct ext4_fsmap gfi_lastfree;
0052 struct list_head gfi_meta_list;
0053 bool gfi_last;
0054 };
0055
0056
0057 struct ext4_getfsmap_dev {
0058 int (*gfd_fn)(struct super_block *sb,
0059 struct ext4_fsmap *keys,
0060 struct ext4_getfsmap_info *info);
0061 u32 gfd_dev;
0062 };
0063
0064
0065 static int ext4_getfsmap_dev_compare(const void *p1, const void *p2)
0066 {
0067 const struct ext4_getfsmap_dev *d1 = p1;
0068 const struct ext4_getfsmap_dev *d2 = p2;
0069
0070 return d1->gfd_dev - d2->gfd_dev;
0071 }
0072
0073
0074 static bool ext4_getfsmap_rec_before_low_key(struct ext4_getfsmap_info *info,
0075 struct ext4_fsmap *rec)
0076 {
0077 return rec->fmr_physical < info->gfi_low.fmr_physical;
0078 }
0079
0080
0081
0082
0083
0084 static int ext4_getfsmap_helper(struct super_block *sb,
0085 struct ext4_getfsmap_info *info,
0086 struct ext4_fsmap *rec)
0087 {
0088 struct ext4_fsmap fmr;
0089 struct ext4_sb_info *sbi = EXT4_SB(sb);
0090 ext4_fsblk_t rec_fsblk = rec->fmr_physical;
0091 ext4_group_t agno;
0092 ext4_grpblk_t cno;
0093 int error;
0094
0095 if (fatal_signal_pending(current))
0096 return -EINTR;
0097
0098
0099
0100
0101
0102 if (ext4_getfsmap_rec_before_low_key(info, rec)) {
0103 rec_fsblk += rec->fmr_length;
0104 if (info->gfi_next_fsblk < rec_fsblk)
0105 info->gfi_next_fsblk = rec_fsblk;
0106 return EXT4_QUERY_RANGE_CONTINUE;
0107 }
0108
0109
0110 if (info->gfi_head->fmh_count == 0) {
0111 if (info->gfi_head->fmh_entries == UINT_MAX)
0112 return EXT4_QUERY_RANGE_ABORT;
0113
0114 if (rec_fsblk > info->gfi_next_fsblk)
0115 info->gfi_head->fmh_entries++;
0116
0117 if (info->gfi_last)
0118 return EXT4_QUERY_RANGE_CONTINUE;
0119
0120 info->gfi_head->fmh_entries++;
0121
0122 rec_fsblk += rec->fmr_length;
0123 if (info->gfi_next_fsblk < rec_fsblk)
0124 info->gfi_next_fsblk = rec_fsblk;
0125 return EXT4_QUERY_RANGE_CONTINUE;
0126 }
0127
0128
0129
0130
0131
0132
0133 if (rec_fsblk > info->gfi_next_fsblk) {
0134 if (info->gfi_head->fmh_entries >= info->gfi_head->fmh_count)
0135 return EXT4_QUERY_RANGE_ABORT;
0136
0137 ext4_get_group_no_and_offset(sb, info->gfi_next_fsblk,
0138 &agno, &cno);
0139 trace_ext4_fsmap_mapping(sb, info->gfi_dev, agno,
0140 EXT4_C2B(sbi, cno),
0141 rec_fsblk - info->gfi_next_fsblk,
0142 EXT4_FMR_OWN_UNKNOWN);
0143
0144 fmr.fmr_device = info->gfi_dev;
0145 fmr.fmr_physical = info->gfi_next_fsblk;
0146 fmr.fmr_owner = EXT4_FMR_OWN_UNKNOWN;
0147 fmr.fmr_length = rec_fsblk - info->gfi_next_fsblk;
0148 fmr.fmr_flags = FMR_OF_SPECIAL_OWNER;
0149 error = info->gfi_formatter(&fmr, info->gfi_format_arg);
0150 if (error)
0151 return error;
0152 info->gfi_head->fmh_entries++;
0153 }
0154
0155 if (info->gfi_last)
0156 goto out;
0157
0158
0159 if (info->gfi_head->fmh_entries >= info->gfi_head->fmh_count)
0160 return EXT4_QUERY_RANGE_ABORT;
0161
0162 ext4_get_group_no_and_offset(sb, rec_fsblk, &agno, &cno);
0163 trace_ext4_fsmap_mapping(sb, info->gfi_dev, agno, EXT4_C2B(sbi, cno),
0164 rec->fmr_length, rec->fmr_owner);
0165
0166 fmr.fmr_device = info->gfi_dev;
0167 fmr.fmr_physical = rec_fsblk;
0168 fmr.fmr_owner = rec->fmr_owner;
0169 fmr.fmr_flags = FMR_OF_SPECIAL_OWNER;
0170 fmr.fmr_length = rec->fmr_length;
0171 error = info->gfi_formatter(&fmr, info->gfi_format_arg);
0172 if (error)
0173 return error;
0174 info->gfi_head->fmh_entries++;
0175
0176 out:
0177 rec_fsblk += rec->fmr_length;
0178 if (info->gfi_next_fsblk < rec_fsblk)
0179 info->gfi_next_fsblk = rec_fsblk;
0180 return EXT4_QUERY_RANGE_CONTINUE;
0181 }
0182
0183 static inline ext4_fsblk_t ext4_fsmap_next_pblk(struct ext4_fsmap *fmr)
0184 {
0185 return fmr->fmr_physical + fmr->fmr_length;
0186 }
0187
0188
0189 static int ext4_getfsmap_datadev_helper(struct super_block *sb,
0190 ext4_group_t agno, ext4_grpblk_t start,
0191 ext4_grpblk_t len, void *priv)
0192 {
0193 struct ext4_fsmap irec;
0194 struct ext4_getfsmap_info *info = priv;
0195 struct ext4_fsmap *p;
0196 struct ext4_fsmap *tmp;
0197 struct ext4_sb_info *sbi = EXT4_SB(sb);
0198 ext4_fsblk_t fsb;
0199 ext4_fsblk_t fslen;
0200 int error;
0201
0202 fsb = (EXT4_C2B(sbi, start) + ext4_group_first_block_no(sb, agno));
0203 fslen = EXT4_C2B(sbi, len);
0204
0205
0206 if (info->gfi_lastfree.fmr_owner) {
0207
0208 if (ext4_fsmap_next_pblk(&info->gfi_lastfree) == fsb) {
0209 info->gfi_lastfree.fmr_length += fslen;
0210 return 0;
0211 }
0212
0213
0214
0215
0216
0217 error = ext4_getfsmap_helper(sb, info, &info->gfi_lastfree);
0218 if (error)
0219 return error;
0220 info->gfi_lastfree.fmr_owner = 0;
0221 }
0222
0223
0224 list_for_each_entry_safe(p, tmp, &info->gfi_meta_list, fmr_list) {
0225 if (p->fmr_physical + p->fmr_length <= info->gfi_next_fsblk) {
0226 list_del(&p->fmr_list);
0227 kfree(p);
0228 } else if (p->fmr_physical < fsb) {
0229 error = ext4_getfsmap_helper(sb, info, p);
0230 if (error)
0231 return error;
0232
0233 list_del(&p->fmr_list);
0234 kfree(p);
0235 }
0236 }
0237
0238 irec.fmr_device = 0;
0239 irec.fmr_physical = fsb;
0240 irec.fmr_length = fslen;
0241 irec.fmr_owner = EXT4_FMR_OWN_FREE;
0242 irec.fmr_flags = 0;
0243
0244
0245 if (ext4_fsmap_next_pblk(&irec) ==
0246 ext4_group_first_block_no(sb, agno + 1)) {
0247 info->gfi_lastfree = irec;
0248 return 0;
0249 }
0250
0251
0252 return ext4_getfsmap_helper(sb, info, &irec);
0253 }
0254
0255
0256 static int ext4_getfsmap_logdev(struct super_block *sb, struct ext4_fsmap *keys,
0257 struct ext4_getfsmap_info *info)
0258 {
0259 journal_t *journal = EXT4_SB(sb)->s_journal;
0260 struct ext4_fsmap irec;
0261
0262
0263 info->gfi_low = keys[0];
0264 info->gfi_low.fmr_length = 0;
0265
0266 memset(&info->gfi_high, 0xFF, sizeof(info->gfi_high));
0267
0268 trace_ext4_fsmap_low_key(sb, info->gfi_dev, 0,
0269 info->gfi_low.fmr_physical,
0270 info->gfi_low.fmr_length,
0271 info->gfi_low.fmr_owner);
0272
0273 trace_ext4_fsmap_high_key(sb, info->gfi_dev, 0,
0274 info->gfi_high.fmr_physical,
0275 info->gfi_high.fmr_length,
0276 info->gfi_high.fmr_owner);
0277
0278 if (keys[0].fmr_physical > 0)
0279 return 0;
0280
0281
0282 irec.fmr_physical = journal->j_blk_offset;
0283 irec.fmr_length = journal->j_total_len;
0284 irec.fmr_owner = EXT4_FMR_OWN_LOG;
0285 irec.fmr_flags = 0;
0286
0287 return ext4_getfsmap_helper(sb, info, &irec);
0288 }
0289
0290
0291 static inline int ext4_getfsmap_fill(struct list_head *meta_list,
0292 ext4_fsblk_t fsb, ext4_fsblk_t len,
0293 uint64_t owner)
0294 {
0295 struct ext4_fsmap *fsm;
0296
0297 fsm = kmalloc(sizeof(*fsm), GFP_NOFS);
0298 if (!fsm)
0299 return -ENOMEM;
0300 fsm->fmr_device = 0;
0301 fsm->fmr_flags = 0;
0302 fsm->fmr_physical = fsb;
0303 fsm->fmr_owner = owner;
0304 fsm->fmr_length = len;
0305 list_add_tail(&fsm->fmr_list, meta_list);
0306
0307 return 0;
0308 }
0309
0310
0311
0312
0313
0314 static unsigned int ext4_getfsmap_find_sb(struct super_block *sb,
0315 ext4_group_t agno,
0316 struct list_head *meta_list)
0317 {
0318 struct ext4_sb_info *sbi = EXT4_SB(sb);
0319 ext4_fsblk_t fsb = ext4_group_first_block_no(sb, agno);
0320 ext4_fsblk_t len;
0321 unsigned long first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
0322 unsigned long metagroup = agno / EXT4_DESC_PER_BLOCK(sb);
0323 int error;
0324
0325
0326 if (ext4_bg_has_super(sb, agno)) {
0327 error = ext4_getfsmap_fill(meta_list, fsb, 1, EXT4_FMR_OWN_FS);
0328 if (error)
0329 return error;
0330 fsb++;
0331 }
0332
0333
0334 len = ext4_bg_num_gdb(sb, agno);
0335 if (!len)
0336 return 0;
0337 error = ext4_getfsmap_fill(meta_list, fsb, len,
0338 EXT4_FMR_OWN_GDT);
0339 if (error)
0340 return error;
0341 fsb += len;
0342
0343
0344 if (!ext4_has_feature_meta_bg(sb) || metagroup < first_meta_bg) {
0345 len = le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks);
0346 error = ext4_getfsmap_fill(meta_list, fsb, len,
0347 EXT4_FMR_OWN_RESV_GDT);
0348 if (error)
0349 return error;
0350 }
0351
0352 return 0;
0353 }
0354
0355
0356 static int ext4_getfsmap_compare(void *priv,
0357 const struct list_head *a,
0358 const struct list_head *b)
0359 {
0360 struct ext4_fsmap *fa;
0361 struct ext4_fsmap *fb;
0362
0363 fa = container_of(a, struct ext4_fsmap, fmr_list);
0364 fb = container_of(b, struct ext4_fsmap, fmr_list);
0365 if (fa->fmr_physical < fb->fmr_physical)
0366 return -1;
0367 else if (fa->fmr_physical > fb->fmr_physical)
0368 return 1;
0369 return 0;
0370 }
0371
0372
0373 static void ext4_getfsmap_merge_fixed_metadata(struct list_head *meta_list)
0374 {
0375 struct ext4_fsmap *p;
0376 struct ext4_fsmap *prev = NULL;
0377 struct ext4_fsmap *tmp;
0378
0379 list_for_each_entry_safe(p, tmp, meta_list, fmr_list) {
0380 if (!prev) {
0381 prev = p;
0382 continue;
0383 }
0384
0385 if (prev->fmr_owner == p->fmr_owner &&
0386 prev->fmr_physical + prev->fmr_length == p->fmr_physical) {
0387 prev->fmr_length += p->fmr_length;
0388 list_del(&p->fmr_list);
0389 kfree(p);
0390 } else
0391 prev = p;
0392 }
0393 }
0394
0395
0396 static void ext4_getfsmap_free_fixed_metadata(struct list_head *meta_list)
0397 {
0398 struct ext4_fsmap *p;
0399 struct ext4_fsmap *tmp;
0400
0401 list_for_each_entry_safe(p, tmp, meta_list, fmr_list) {
0402 list_del(&p->fmr_list);
0403 kfree(p);
0404 }
0405 }
0406
0407
0408 static int ext4_getfsmap_find_fixed_metadata(struct super_block *sb,
0409 struct list_head *meta_list)
0410 {
0411 struct ext4_group_desc *gdp;
0412 ext4_group_t agno;
0413 int error;
0414
0415 INIT_LIST_HEAD(meta_list);
0416
0417
0418 for (agno = 0; agno < EXT4_SB(sb)->s_groups_count; agno++) {
0419 gdp = ext4_get_group_desc(sb, agno, NULL);
0420 if (!gdp) {
0421 error = -EFSCORRUPTED;
0422 goto err;
0423 }
0424
0425
0426 error = ext4_getfsmap_find_sb(sb, agno, meta_list);
0427 if (error)
0428 goto err;
0429
0430
0431 error = ext4_getfsmap_fill(meta_list,
0432 ext4_block_bitmap(sb, gdp), 1,
0433 EXT4_FMR_OWN_BLKBM);
0434 if (error)
0435 goto err;
0436
0437
0438 error = ext4_getfsmap_fill(meta_list,
0439 ext4_inode_bitmap(sb, gdp), 1,
0440 EXT4_FMR_OWN_INOBM);
0441 if (error)
0442 goto err;
0443
0444
0445 error = ext4_getfsmap_fill(meta_list,
0446 ext4_inode_table(sb, gdp),
0447 EXT4_SB(sb)->s_itb_per_group,
0448 EXT4_FMR_OWN_INODES);
0449 if (error)
0450 goto err;
0451 }
0452
0453
0454 list_sort(NULL, meta_list, ext4_getfsmap_compare);
0455
0456
0457 ext4_getfsmap_merge_fixed_metadata(meta_list);
0458
0459 return 0;
0460 err:
0461 ext4_getfsmap_free_fixed_metadata(meta_list);
0462 return error;
0463 }
0464
0465
0466 static int ext4_getfsmap_datadev(struct super_block *sb,
0467 struct ext4_fsmap *keys,
0468 struct ext4_getfsmap_info *info)
0469 {
0470 struct ext4_sb_info *sbi = EXT4_SB(sb);
0471 ext4_fsblk_t start_fsb;
0472 ext4_fsblk_t end_fsb;
0473 ext4_fsblk_t bofs;
0474 ext4_fsblk_t eofs;
0475 ext4_group_t start_ag;
0476 ext4_group_t end_ag;
0477 ext4_grpblk_t first_cluster;
0478 ext4_grpblk_t last_cluster;
0479 int error = 0;
0480
0481 bofs = le32_to_cpu(sbi->s_es->s_first_data_block);
0482 eofs = ext4_blocks_count(sbi->s_es);
0483 if (keys[0].fmr_physical >= eofs)
0484 return 0;
0485 else if (keys[0].fmr_physical < bofs)
0486 keys[0].fmr_physical = bofs;
0487 if (keys[1].fmr_physical >= eofs)
0488 keys[1].fmr_physical = eofs - 1;
0489 start_fsb = keys[0].fmr_physical;
0490 end_fsb = keys[1].fmr_physical;
0491
0492
0493 ext4_get_group_no_and_offset(sb, start_fsb, &start_ag, &first_cluster);
0494 ext4_get_group_no_and_offset(sb, end_fsb, &end_ag, &last_cluster);
0495
0496
0497
0498
0499
0500
0501 info->gfi_low = keys[0];
0502 info->gfi_low.fmr_physical = EXT4_C2B(sbi, first_cluster);
0503 info->gfi_low.fmr_length = 0;
0504
0505 memset(&info->gfi_high, 0xFF, sizeof(info->gfi_high));
0506
0507
0508 error = ext4_getfsmap_find_fixed_metadata(sb, &info->gfi_meta_list);
0509 if (error)
0510 goto err;
0511
0512
0513 for (info->gfi_agno = start_ag;
0514 info->gfi_agno <= end_ag;
0515 info->gfi_agno++) {
0516
0517
0518
0519
0520 if (info->gfi_agno == end_ag) {
0521 info->gfi_high = keys[1];
0522 info->gfi_high.fmr_physical = EXT4_C2B(sbi,
0523 last_cluster);
0524 info->gfi_high.fmr_length = 0;
0525 }
0526
0527 trace_ext4_fsmap_low_key(sb, info->gfi_dev, info->gfi_agno,
0528 info->gfi_low.fmr_physical,
0529 info->gfi_low.fmr_length,
0530 info->gfi_low.fmr_owner);
0531
0532 trace_ext4_fsmap_high_key(sb, info->gfi_dev, info->gfi_agno,
0533 info->gfi_high.fmr_physical,
0534 info->gfi_high.fmr_length,
0535 info->gfi_high.fmr_owner);
0536
0537 error = ext4_mballoc_query_range(sb, info->gfi_agno,
0538 EXT4_B2C(sbi, info->gfi_low.fmr_physical),
0539 EXT4_B2C(sbi, info->gfi_high.fmr_physical),
0540 ext4_getfsmap_datadev_helper, info);
0541 if (error)
0542 goto err;
0543
0544
0545
0546
0547
0548 if (info->gfi_agno == start_ag)
0549 memset(&info->gfi_low, 0, sizeof(info->gfi_low));
0550 }
0551
0552
0553 if (info->gfi_lastfree.fmr_owner) {
0554 error = ext4_getfsmap_helper(sb, info, &info->gfi_lastfree);
0555 if (error)
0556 goto err;
0557 }
0558
0559
0560 info->gfi_last = true;
0561 error = ext4_getfsmap_datadev_helper(sb, end_ag, last_cluster, 0, info);
0562 if (error)
0563 goto err;
0564
0565 err:
0566 ext4_getfsmap_free_fixed_metadata(&info->gfi_meta_list);
0567 return error;
0568 }
0569
0570
0571 static bool ext4_getfsmap_is_valid_device(struct super_block *sb,
0572 struct ext4_fsmap *fm)
0573 {
0574 if (fm->fmr_device == 0 || fm->fmr_device == UINT_MAX ||
0575 fm->fmr_device == new_encode_dev(sb->s_bdev->bd_dev))
0576 return true;
0577 if (EXT4_SB(sb)->s_journal_bdev &&
0578 fm->fmr_device == new_encode_dev(EXT4_SB(sb)->s_journal_bdev->bd_dev))
0579 return true;
0580 return false;
0581 }
0582
0583
0584 static bool ext4_getfsmap_check_keys(struct ext4_fsmap *low_key,
0585 struct ext4_fsmap *high_key)
0586 {
0587 if (low_key->fmr_device > high_key->fmr_device)
0588 return false;
0589 if (low_key->fmr_device < high_key->fmr_device)
0590 return true;
0591
0592 if (low_key->fmr_physical > high_key->fmr_physical)
0593 return false;
0594 if (low_key->fmr_physical < high_key->fmr_physical)
0595 return true;
0596
0597 if (low_key->fmr_owner > high_key->fmr_owner)
0598 return false;
0599 if (low_key->fmr_owner < high_key->fmr_owner)
0600 return true;
0601
0602 return false;
0603 }
0604
0605 #define EXT4_GETFSMAP_DEVS 2
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627 int ext4_getfsmap(struct super_block *sb, struct ext4_fsmap_head *head,
0628 ext4_fsmap_format_t formatter, void *arg)
0629 {
0630 struct ext4_fsmap dkeys[2];
0631 struct ext4_getfsmap_dev handlers[EXT4_GETFSMAP_DEVS];
0632 struct ext4_getfsmap_info info = { NULL };
0633 int i;
0634 int error = 0;
0635
0636 if (head->fmh_iflags & ~FMH_IF_VALID)
0637 return -EINVAL;
0638 if (!ext4_getfsmap_is_valid_device(sb, &head->fmh_keys[0]) ||
0639 !ext4_getfsmap_is_valid_device(sb, &head->fmh_keys[1]))
0640 return -EINVAL;
0641
0642 head->fmh_entries = 0;
0643
0644
0645 memset(handlers, 0, sizeof(handlers));
0646 handlers[0].gfd_dev = new_encode_dev(sb->s_bdev->bd_dev);
0647 handlers[0].gfd_fn = ext4_getfsmap_datadev;
0648 if (EXT4_SB(sb)->s_journal_bdev) {
0649 handlers[1].gfd_dev = new_encode_dev(
0650 EXT4_SB(sb)->s_journal_bdev->bd_dev);
0651 handlers[1].gfd_fn = ext4_getfsmap_logdev;
0652 }
0653
0654 sort(handlers, EXT4_GETFSMAP_DEVS, sizeof(struct ext4_getfsmap_dev),
0655 ext4_getfsmap_dev_compare, NULL);
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668 dkeys[0] = head->fmh_keys[0];
0669 dkeys[0].fmr_physical += dkeys[0].fmr_length;
0670 dkeys[0].fmr_owner = 0;
0671 dkeys[0].fmr_length = 0;
0672 memset(&dkeys[1], 0xFF, sizeof(struct ext4_fsmap));
0673
0674 if (!ext4_getfsmap_check_keys(dkeys, &head->fmh_keys[1]))
0675 return -EINVAL;
0676
0677 info.gfi_next_fsblk = head->fmh_keys[0].fmr_physical +
0678 head->fmh_keys[0].fmr_length;
0679 info.gfi_formatter = formatter;
0680 info.gfi_format_arg = arg;
0681 info.gfi_head = head;
0682
0683
0684 for (i = 0; i < EXT4_GETFSMAP_DEVS; i++) {
0685
0686 if (!handlers[i].gfd_fn)
0687 continue;
0688 if (head->fmh_keys[0].fmr_device > handlers[i].gfd_dev)
0689 continue;
0690 if (head->fmh_keys[1].fmr_device < handlers[i].gfd_dev)
0691 break;
0692
0693
0694
0695
0696
0697
0698
0699
0700 if (handlers[i].gfd_dev == head->fmh_keys[1].fmr_device)
0701 dkeys[1] = head->fmh_keys[1];
0702 if (handlers[i].gfd_dev > head->fmh_keys[0].fmr_device)
0703 memset(&dkeys[0], 0, sizeof(struct ext4_fsmap));
0704
0705 info.gfi_dev = handlers[i].gfd_dev;
0706 info.gfi_last = false;
0707 info.gfi_agno = -1;
0708 error = handlers[i].gfd_fn(sb, dkeys, &info);
0709 if (error)
0710 break;
0711 info.gfi_next_fsblk = 0;
0712 }
0713
0714 head->fmh_oflags = FMH_OF_DEV_T;
0715 return error;
0716 }