diff options
Diffstat (limited to 'fs/ntfs/mft.c')
| -rw-r--r-- | fs/ntfs/mft.c | 227 |
1 files changed, 155 insertions, 72 deletions
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index dfa85ac2f8ba..ac9ff39aa834 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project. | 2 | * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project. |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2001-2004 Anton Altaparmakov | 4 | * Copyright (c) 2001-2005 Anton Altaparmakov |
| 5 | * Copyright (c) 2002 Richard Russon | 5 | * Copyright (c) 2002 Richard Russon |
| 6 | * | 6 | * |
| 7 | * This program/include file is free software; you can redistribute it and/or | 7 | * This program/include file is free software; you can redistribute it and/or |
| @@ -45,6 +45,7 @@ | |||
| 45 | */ | 45 | */ |
| 46 | static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni) | 46 | static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni) |
| 47 | { | 47 | { |
| 48 | loff_t i_size; | ||
| 48 | ntfs_volume *vol = ni->vol; | 49 | ntfs_volume *vol = ni->vol; |
| 49 | struct inode *mft_vi = vol->mft_ino; | 50 | struct inode *mft_vi = vol->mft_ino; |
| 50 | struct page *page; | 51 | struct page *page; |
| @@ -60,13 +61,14 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni) | |||
| 60 | index = ni->mft_no << vol->mft_record_size_bits >> PAGE_CACHE_SHIFT; | 61 | index = ni->mft_no << vol->mft_record_size_bits >> PAGE_CACHE_SHIFT; |
| 61 | ofs = (ni->mft_no << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK; | 62 | ofs = (ni->mft_no << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK; |
| 62 | 63 | ||
| 64 | i_size = i_size_read(mft_vi); | ||
| 63 | /* The maximum valid index into the page cache for $MFT's data. */ | 65 | /* The maximum valid index into the page cache for $MFT's data. */ |
| 64 | end_index = mft_vi->i_size >> PAGE_CACHE_SHIFT; | 66 | end_index = i_size >> PAGE_CACHE_SHIFT; |
| 65 | 67 | ||
| 66 | /* If the wanted index is out of bounds the mft record doesn't exist. */ | 68 | /* If the wanted index is out of bounds the mft record doesn't exist. */ |
| 67 | if (unlikely(index >= end_index)) { | 69 | if (unlikely(index >= end_index)) { |
| 68 | if (index > end_index || (mft_vi->i_size & ~PAGE_CACHE_MASK) < | 70 | if (index > end_index || (i_size & ~PAGE_CACHE_MASK) < ofs + |
| 69 | ofs + vol->mft_record_size) { | 71 | vol->mft_record_size) { |
| 70 | page = ERR_PTR(-ENOENT); | 72 | page = ERR_PTR(-ENOENT); |
| 71 | ntfs_error(vol->sb, "Attemt to read mft record 0x%lx, " | 73 | ntfs_error(vol->sb, "Attemt to read mft record 0x%lx, " |
| 72 | "which is beyond the end of the mft. " | 74 | "which is beyond the end of the mft. " |
| @@ -285,7 +287,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref, | |||
| 285 | } | 287 | } |
| 286 | unmap_mft_record(ni); | 288 | unmap_mft_record(ni); |
| 287 | ntfs_error(base_ni->vol->sb, "Found stale extent mft " | 289 | ntfs_error(base_ni->vol->sb, "Found stale extent mft " |
| 288 | "reference! Corrupt file system. " | 290 | "reference! Corrupt filesystem. " |
| 289 | "Run chkdsk."); | 291 | "Run chkdsk."); |
| 290 | return ERR_PTR(-EIO); | 292 | return ERR_PTR(-EIO); |
| 291 | } | 293 | } |
| @@ -316,7 +318,7 @@ map_err_out: | |||
| 316 | /* Verify the sequence number if it is present. */ | 318 | /* Verify the sequence number if it is present. */ |
| 317 | if (seq_no && (le16_to_cpu(m->sequence_number) != seq_no)) { | 319 | if (seq_no && (le16_to_cpu(m->sequence_number) != seq_no)) { |
| 318 | ntfs_error(base_ni->vol->sb, "Found stale extent mft " | 320 | ntfs_error(base_ni->vol->sb, "Found stale extent mft " |
| 319 | "reference! Corrupt file system. Run chkdsk."); | 321 | "reference! Corrupt filesystem. Run chkdsk."); |
| 320 | destroy_ni = TRUE; | 322 | destroy_ni = TRUE; |
| 321 | m = ERR_PTR(-EIO); | 323 | m = ERR_PTR(-EIO); |
| 322 | goto unm_err_out; | 324 | goto unm_err_out; |
| @@ -946,20 +948,23 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no, | |||
| 946 | na.name_len = 0; | 948 | na.name_len = 0; |
| 947 | na.type = AT_UNUSED; | 949 | na.type = AT_UNUSED; |
| 948 | /* | 950 | /* |
| 949 | * For inode 0, i.e. $MFT itself, we cannot use ilookup5() from here or | 951 | * Optimize inode 0, i.e. $MFT itself, since we have it in memory and |
| 950 | * we deadlock because the inode is already locked by the kernel | 952 | * we get here for it rather often. |
| 951 | * (fs/fs-writeback.c::__sync_single_inode()) and ilookup5() waits | ||
| 952 | * until the inode is unlocked before returning it and it never gets | ||
| 953 | * unlocked because ntfs_should_write_mft_record() never returns. )-: | ||
| 954 | * Fortunately, we have inode 0 pinned in icache for the duration of | ||
| 955 | * the mount so we can access it directly. | ||
| 956 | */ | 953 | */ |
| 957 | if (!mft_no) { | 954 | if (!mft_no) { |
| 958 | /* Balance the below iput(). */ | 955 | /* Balance the below iput(). */ |
| 959 | vi = igrab(mft_vi); | 956 | vi = igrab(mft_vi); |
| 960 | BUG_ON(vi != mft_vi); | 957 | BUG_ON(vi != mft_vi); |
| 961 | } else | 958 | } else { |
| 962 | vi = ilookup5(sb, mft_no, (test_t)ntfs_test_inode, &na); | 959 | /* |
| 960 | * Have to use ilookup5_nowait() since ilookup5() waits for the | ||
| 961 | * inode lock which causes ntfs to deadlock when a concurrent | ||
| 962 | * inode write via the inode dirty code paths and the page | ||
| 963 | * dirty code path of the inode dirty code path when writing | ||
| 964 | * $MFT occurs. | ||
| 965 | */ | ||
| 966 | vi = ilookup5_nowait(sb, mft_no, (test_t)ntfs_test_inode, &na); | ||
| 967 | } | ||
| 963 | if (vi) { | 968 | if (vi) { |
| 964 | ntfs_debug("Base inode 0x%lx is in icache.", mft_no); | 969 | ntfs_debug("Base inode 0x%lx is in icache.", mft_no); |
| 965 | /* The inode is in icache. */ | 970 | /* The inode is in icache. */ |
| @@ -1014,7 +1019,13 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no, | |||
| 1014 | na.mft_no = MREF_LE(m->base_mft_record); | 1019 | na.mft_no = MREF_LE(m->base_mft_record); |
| 1015 | ntfs_debug("Mft record 0x%lx is an extent record. Looking for base " | 1020 | ntfs_debug("Mft record 0x%lx is an extent record. Looking for base " |
| 1016 | "inode 0x%lx in icache.", mft_no, na.mft_no); | 1021 | "inode 0x%lx in icache.", mft_no, na.mft_no); |
| 1017 | vi = ilookup5(sb, na.mft_no, (test_t)ntfs_test_inode, &na); | 1022 | if (!na.mft_no) { |
| 1023 | /* Balance the below iput(). */ | ||
| 1024 | vi = igrab(mft_vi); | ||
| 1025 | BUG_ON(vi != mft_vi); | ||
| 1026 | } else | ||
| 1027 | vi = ilookup5_nowait(sb, na.mft_no, (test_t)ntfs_test_inode, | ||
| 1028 | &na); | ||
| 1018 | if (!vi) { | 1029 | if (!vi) { |
| 1019 | /* | 1030 | /* |
| 1020 | * The base inode is not in icache, write this extent mft | 1031 | * The base inode is not in icache, write this extent mft |
| @@ -1121,6 +1132,7 @@ static int ntfs_mft_bitmap_find_and_alloc_free_rec_nolock(ntfs_volume *vol, | |||
| 1121 | ntfs_inode *base_ni) | 1132 | ntfs_inode *base_ni) |
| 1122 | { | 1133 | { |
| 1123 | s64 pass_end, ll, data_pos, pass_start, ofs, bit; | 1134 | s64 pass_end, ll, data_pos, pass_start, ofs, bit; |
| 1135 | unsigned long flags; | ||
| 1124 | struct address_space *mftbmp_mapping; | 1136 | struct address_space *mftbmp_mapping; |
| 1125 | u8 *buf, *byte; | 1137 | u8 *buf, *byte; |
| 1126 | struct page *page; | 1138 | struct page *page; |
| @@ -1134,9 +1146,13 @@ static int ntfs_mft_bitmap_find_and_alloc_free_rec_nolock(ntfs_volume *vol, | |||
| 1134 | * Set the end of the pass making sure we do not overflow the mft | 1146 | * Set the end of the pass making sure we do not overflow the mft |
| 1135 | * bitmap. | 1147 | * bitmap. |
| 1136 | */ | 1148 | */ |
| 1149 | read_lock_irqsave(&NTFS_I(vol->mft_ino)->size_lock, flags); | ||
| 1137 | pass_end = NTFS_I(vol->mft_ino)->allocated_size >> | 1150 | pass_end = NTFS_I(vol->mft_ino)->allocated_size >> |
| 1138 | vol->mft_record_size_bits; | 1151 | vol->mft_record_size_bits; |
| 1152 | read_unlock_irqrestore(&NTFS_I(vol->mft_ino)->size_lock, flags); | ||
| 1153 | read_lock_irqsave(&NTFS_I(vol->mftbmp_ino)->size_lock, flags); | ||
| 1139 | ll = NTFS_I(vol->mftbmp_ino)->initialized_size << 3; | 1154 | ll = NTFS_I(vol->mftbmp_ino)->initialized_size << 3; |
| 1155 | read_unlock_irqrestore(&NTFS_I(vol->mftbmp_ino)->size_lock, flags); | ||
| 1140 | if (pass_end > ll) | 1156 | if (pass_end > ll) |
| 1141 | pass_end = ll; | 1157 | pass_end = ll; |
| 1142 | pass = 1; | 1158 | pass = 1; |
| @@ -1263,6 +1279,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1263 | { | 1279 | { |
| 1264 | LCN lcn; | 1280 | LCN lcn; |
| 1265 | s64 ll; | 1281 | s64 ll; |
| 1282 | unsigned long flags; | ||
| 1266 | struct page *page; | 1283 | struct page *page; |
| 1267 | ntfs_inode *mft_ni, *mftbmp_ni; | 1284 | ntfs_inode *mft_ni, *mftbmp_ni; |
| 1268 | runlist_element *rl, *rl2 = NULL; | 1285 | runlist_element *rl, *rl2 = NULL; |
| @@ -1284,17 +1301,20 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1284 | /* | 1301 | /* |
| 1285 | * Determine the last lcn of the mft bitmap. The allocated size of the | 1302 | * Determine the last lcn of the mft bitmap. The allocated size of the |
| 1286 | * mft bitmap cannot be zero so we are ok to do this. | 1303 | * mft bitmap cannot be zero so we are ok to do this. |
| 1287 | * ntfs_find_vcn() returns the runlist locked on success. | ||
| 1288 | */ | 1304 | */ |
| 1289 | rl = ntfs_find_vcn(mftbmp_ni, (mftbmp_ni->allocated_size - 1) >> | 1305 | down_write(&mftbmp_ni->runlist.lock); |
| 1290 | vol->cluster_size_bits, TRUE); | 1306 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); |
| 1307 | ll = mftbmp_ni->allocated_size; | ||
| 1308 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1309 | rl = ntfs_attr_find_vcn_nolock(mftbmp_ni, | ||
| 1310 | (ll - 1) >> vol->cluster_size_bits, TRUE); | ||
| 1291 | if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { | 1311 | if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { |
| 1312 | up_write(&mftbmp_ni->runlist.lock); | ||
| 1292 | ntfs_error(vol->sb, "Failed to determine last allocated " | 1313 | ntfs_error(vol->sb, "Failed to determine last allocated " |
| 1293 | "cluster of mft bitmap attribute."); | 1314 | "cluster of mft bitmap attribute."); |
| 1294 | if (!IS_ERR(rl)) { | 1315 | if (!IS_ERR(rl)) |
| 1295 | up_write(&mftbmp_ni->runlist.lock); | ||
| 1296 | ret = -EIO; | 1316 | ret = -EIO; |
| 1297 | } else | 1317 | else |
| 1298 | ret = PTR_ERR(rl); | 1318 | ret = PTR_ERR(rl); |
| 1299 | return ret; | 1319 | return ret; |
| 1300 | } | 1320 | } |
| @@ -1396,7 +1416,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1396 | BUG_ON(ll < rl2->vcn); | 1416 | BUG_ON(ll < rl2->vcn); |
| 1397 | BUG_ON(ll >= rl2->vcn + rl2->length); | 1417 | BUG_ON(ll >= rl2->vcn + rl2->length); |
| 1398 | /* Get the size for the new mapping pairs array for this extent. */ | 1418 | /* Get the size for the new mapping pairs array for this extent. */ |
| 1399 | mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll); | 1419 | mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, -1); |
| 1400 | if (unlikely(mp_size <= 0)) { | 1420 | if (unlikely(mp_size <= 0)) { |
| 1401 | ntfs_error(vol->sb, "Get size for mapping pairs failed for " | 1421 | ntfs_error(vol->sb, "Get size for mapping pairs failed for " |
| 1402 | "mft bitmap attribute extent."); | 1422 | "mft bitmap attribute extent."); |
| @@ -1418,6 +1438,8 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1418 | // TODO: Deal with this by moving this extent to a new mft | 1438 | // TODO: Deal with this by moving this extent to a new mft |
| 1419 | // record or by starting a new extent in a new mft record or by | 1439 | // record or by starting a new extent in a new mft record or by |
| 1420 | // moving other attributes out of this mft record. | 1440 | // moving other attributes out of this mft record. |
| 1441 | // Note: It will need to be a special mft record and if none of | ||
| 1442 | // those are available it gets rather complicated... | ||
| 1421 | ntfs_error(vol->sb, "Not enough space in this mft record to " | 1443 | ntfs_error(vol->sb, "Not enough space in this mft record to " |
| 1422 | "accomodate extended mft bitmap attribute " | 1444 | "accomodate extended mft bitmap attribute " |
| 1423 | "extent. Cannot handle this yet."); | 1445 | "extent. Cannot handle this yet."); |
| @@ -1428,7 +1450,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1428 | /* Generate the mapping pairs array directly into the attr record. */ | 1450 | /* Generate the mapping pairs array directly into the attr record. */ |
| 1429 | ret = ntfs_mapping_pairs_build(vol, (u8*)a + | 1451 | ret = ntfs_mapping_pairs_build(vol, (u8*)a + |
| 1430 | le16_to_cpu(a->data.non_resident.mapping_pairs_offset), | 1452 | le16_to_cpu(a->data.non_resident.mapping_pairs_offset), |
| 1431 | mp_size, rl2, ll, NULL); | 1453 | mp_size, rl2, ll, -1, NULL); |
| 1432 | if (unlikely(ret)) { | 1454 | if (unlikely(ret)) { |
| 1433 | ntfs_error(vol->sb, "Failed to build mapping pairs array for " | 1455 | ntfs_error(vol->sb, "Failed to build mapping pairs array for " |
| 1434 | "mft bitmap attribute."); | 1456 | "mft bitmap attribute."); |
| @@ -1458,9 +1480,11 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1458 | } | 1480 | } |
| 1459 | a = ctx->attr; | 1481 | a = ctx->attr; |
| 1460 | } | 1482 | } |
| 1483 | write_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 1461 | mftbmp_ni->allocated_size += vol->cluster_size; | 1484 | mftbmp_ni->allocated_size += vol->cluster_size; |
| 1462 | a->data.non_resident.allocated_size = | 1485 | a->data.non_resident.allocated_size = |
| 1463 | cpu_to_sle64(mftbmp_ni->allocated_size); | 1486 | cpu_to_sle64(mftbmp_ni->allocated_size); |
| 1487 | write_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1464 | /* Ensure the changes make it to disk. */ | 1488 | /* Ensure the changes make it to disk. */ |
| 1465 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 1489 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
| 1466 | mark_mft_record_dirty(ctx->ntfs_ino); | 1490 | mark_mft_record_dirty(ctx->ntfs_ino); |
| @@ -1476,7 +1500,9 @@ restore_undo_alloc: | |||
| 1476 | 0, ctx)) { | 1500 | 0, ctx)) { |
| 1477 | ntfs_error(vol->sb, "Failed to find last attribute extent of " | 1501 | ntfs_error(vol->sb, "Failed to find last attribute extent of " |
| 1478 | "mft bitmap attribute.%s", es); | 1502 | "mft bitmap attribute.%s", es); |
| 1503 | write_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 1479 | mftbmp_ni->allocated_size += vol->cluster_size; | 1504 | mftbmp_ni->allocated_size += vol->cluster_size; |
| 1505 | write_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1480 | ntfs_attr_put_search_ctx(ctx); | 1506 | ntfs_attr_put_search_ctx(ctx); |
| 1481 | unmap_mft_record(mft_ni); | 1507 | unmap_mft_record(mft_ni); |
| 1482 | up_write(&mftbmp_ni->runlist.lock); | 1508 | up_write(&mftbmp_ni->runlist.lock); |
| @@ -1512,7 +1538,7 @@ undo_alloc: | |||
| 1512 | a->data.non_resident.mapping_pairs_offset), | 1538 | a->data.non_resident.mapping_pairs_offset), |
| 1513 | old_alen - le16_to_cpu( | 1539 | old_alen - le16_to_cpu( |
| 1514 | a->data.non_resident.mapping_pairs_offset), | 1540 | a->data.non_resident.mapping_pairs_offset), |
| 1515 | rl2, ll, NULL)) { | 1541 | rl2, ll, -1, NULL)) { |
| 1516 | ntfs_error(vol->sb, "Failed to restore mapping pairs " | 1542 | ntfs_error(vol->sb, "Failed to restore mapping pairs " |
| 1517 | "array.%s", es); | 1543 | "array.%s", es); |
| 1518 | NVolSetErrors(vol); | 1544 | NVolSetErrors(vol); |
| @@ -1550,6 +1576,7 @@ undo_alloc: | |||
| 1550 | static int ntfs_mft_bitmap_extend_initialized_nolock(ntfs_volume *vol) | 1576 | static int ntfs_mft_bitmap_extend_initialized_nolock(ntfs_volume *vol) |
| 1551 | { | 1577 | { |
| 1552 | s64 old_data_size, old_initialized_size; | 1578 | s64 old_data_size, old_initialized_size; |
| 1579 | unsigned long flags; | ||
| 1553 | struct inode *mftbmp_vi; | 1580 | struct inode *mftbmp_vi; |
| 1554 | ntfs_inode *mft_ni, *mftbmp_ni; | 1581 | ntfs_inode *mft_ni, *mftbmp_ni; |
| 1555 | ntfs_attr_search_ctx *ctx; | 1582 | ntfs_attr_search_ctx *ctx; |
| @@ -1583,7 +1610,8 @@ static int ntfs_mft_bitmap_extend_initialized_nolock(ntfs_volume *vol) | |||
| 1583 | goto put_err_out; | 1610 | goto put_err_out; |
| 1584 | } | 1611 | } |
| 1585 | a = ctx->attr; | 1612 | a = ctx->attr; |
| 1586 | old_data_size = mftbmp_vi->i_size; | 1613 | write_lock_irqsave(&mftbmp_ni->size_lock, flags); |
| 1614 | old_data_size = i_size_read(mftbmp_vi); | ||
| 1587 | old_initialized_size = mftbmp_ni->initialized_size; | 1615 | old_initialized_size = mftbmp_ni->initialized_size; |
| 1588 | /* | 1616 | /* |
| 1589 | * We can simply update the initialized_size before filling the space | 1617 | * We can simply update the initialized_size before filling the space |
| @@ -1593,11 +1621,12 @@ static int ntfs_mft_bitmap_extend_initialized_nolock(ntfs_volume *vol) | |||
| 1593 | mftbmp_ni->initialized_size += 8; | 1621 | mftbmp_ni->initialized_size += 8; |
| 1594 | a->data.non_resident.initialized_size = | 1622 | a->data.non_resident.initialized_size = |
| 1595 | cpu_to_sle64(mftbmp_ni->initialized_size); | 1623 | cpu_to_sle64(mftbmp_ni->initialized_size); |
| 1596 | if (mftbmp_ni->initialized_size > mftbmp_vi->i_size) { | 1624 | if (mftbmp_ni->initialized_size > old_data_size) { |
| 1597 | mftbmp_vi->i_size = mftbmp_ni->initialized_size; | 1625 | i_size_write(mftbmp_vi, mftbmp_ni->initialized_size); |
| 1598 | a->data.non_resident.data_size = | 1626 | a->data.non_resident.data_size = |
| 1599 | cpu_to_sle64(mftbmp_vi->i_size); | 1627 | cpu_to_sle64(mftbmp_ni->initialized_size); |
| 1600 | } | 1628 | } |
| 1629 | write_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1601 | /* Ensure the changes make it to disk. */ | 1630 | /* Ensure the changes make it to disk. */ |
| 1602 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 1631 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
| 1603 | mark_mft_record_dirty(ctx->ntfs_ino); | 1632 | mark_mft_record_dirty(ctx->ntfs_ino); |
| @@ -1636,22 +1665,28 @@ unm_err_out: | |||
| 1636 | goto err_out; | 1665 | goto err_out; |
| 1637 | } | 1666 | } |
| 1638 | a = ctx->attr; | 1667 | a = ctx->attr; |
| 1668 | write_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 1639 | mftbmp_ni->initialized_size = old_initialized_size; | 1669 | mftbmp_ni->initialized_size = old_initialized_size; |
| 1640 | a->data.non_resident.initialized_size = | 1670 | a->data.non_resident.initialized_size = |
| 1641 | cpu_to_sle64(old_initialized_size); | 1671 | cpu_to_sle64(old_initialized_size); |
| 1642 | if (mftbmp_vi->i_size != old_data_size) { | 1672 | if (i_size_read(mftbmp_vi) != old_data_size) { |
| 1643 | mftbmp_vi->i_size = old_data_size; | 1673 | i_size_write(mftbmp_vi, old_data_size); |
| 1644 | a->data.non_resident.data_size = cpu_to_sle64(old_data_size); | 1674 | a->data.non_resident.data_size = cpu_to_sle64(old_data_size); |
| 1645 | } | 1675 | } |
| 1676 | write_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1646 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 1677 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
| 1647 | mark_mft_record_dirty(ctx->ntfs_ino); | 1678 | mark_mft_record_dirty(ctx->ntfs_ino); |
| 1648 | ntfs_attr_put_search_ctx(ctx); | 1679 | ntfs_attr_put_search_ctx(ctx); |
| 1649 | unmap_mft_record(mft_ni); | 1680 | unmap_mft_record(mft_ni); |
| 1681 | #ifdef DEBUG | ||
| 1682 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 1650 | ntfs_debug("Restored status of mftbmp: allocated_size 0x%llx, " | 1683 | ntfs_debug("Restored status of mftbmp: allocated_size 0x%llx, " |
| 1651 | "data_size 0x%llx, initialized_size 0x%llx.", | 1684 | "data_size 0x%llx, initialized_size 0x%llx.", |
| 1652 | (long long)mftbmp_ni->allocated_size, | 1685 | (long long)mftbmp_ni->allocated_size, |
| 1653 | (long long)mftbmp_vi->i_size, | 1686 | (long long)i_size_read(mftbmp_vi), |
| 1654 | (long long)mftbmp_ni->initialized_size); | 1687 | (long long)mftbmp_ni->initialized_size); |
| 1688 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1689 | #endif /* DEBUG */ | ||
| 1655 | err_out: | 1690 | err_out: |
| 1656 | return ret; | 1691 | return ret; |
| 1657 | } | 1692 | } |
| @@ -1679,7 +1714,8 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1679 | { | 1714 | { |
| 1680 | LCN lcn; | 1715 | LCN lcn; |
| 1681 | VCN old_last_vcn; | 1716 | VCN old_last_vcn; |
| 1682 | s64 min_nr, nr, ll = 0; | 1717 | s64 min_nr, nr, ll; |
| 1718 | unsigned long flags; | ||
| 1683 | ntfs_inode *mft_ni; | 1719 | ntfs_inode *mft_ni; |
| 1684 | runlist_element *rl, *rl2; | 1720 | runlist_element *rl, *rl2; |
| 1685 | ntfs_attr_search_ctx *ctx = NULL; | 1721 | ntfs_attr_search_ctx *ctx = NULL; |
| @@ -1695,23 +1731,25 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1695 | * Determine the preferred allocation location, i.e. the last lcn of | 1731 | * Determine the preferred allocation location, i.e. the last lcn of |
| 1696 | * the mft data attribute. The allocated size of the mft data | 1732 | * the mft data attribute. The allocated size of the mft data |
| 1697 | * attribute cannot be zero so we are ok to do this. | 1733 | * attribute cannot be zero so we are ok to do this. |
| 1698 | * ntfs_find_vcn() returns the runlist locked on success. | ||
| 1699 | */ | 1734 | */ |
| 1700 | rl = ntfs_find_vcn(mft_ni, (mft_ni->allocated_size - 1) >> | 1735 | down_write(&mft_ni->runlist.lock); |
| 1701 | vol->cluster_size_bits, TRUE); | 1736 | read_lock_irqsave(&mft_ni->size_lock, flags); |
| 1737 | ll = mft_ni->allocated_size; | ||
| 1738 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 1739 | rl = ntfs_attr_find_vcn_nolock(mft_ni, | ||
| 1740 | (ll - 1) >> vol->cluster_size_bits, TRUE); | ||
| 1702 | if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { | 1741 | if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { |
| 1742 | up_write(&mft_ni->runlist.lock); | ||
| 1703 | ntfs_error(vol->sb, "Failed to determine last allocated " | 1743 | ntfs_error(vol->sb, "Failed to determine last allocated " |
| 1704 | "cluster of mft data attribute."); | 1744 | "cluster of mft data attribute."); |
| 1705 | if (!IS_ERR(rl)) { | 1745 | if (!IS_ERR(rl)) |
| 1706 | up_write(&mft_ni->runlist.lock); | ||
| 1707 | ret = -EIO; | 1746 | ret = -EIO; |
| 1708 | } else | 1747 | else |
| 1709 | ret = PTR_ERR(rl); | 1748 | ret = PTR_ERR(rl); |
| 1710 | return ret; | 1749 | return ret; |
| 1711 | } | 1750 | } |
| 1712 | lcn = rl->lcn + rl->length; | 1751 | lcn = rl->lcn + rl->length; |
| 1713 | ntfs_debug("Last lcn of mft data attribute is 0x%llx.", | 1752 | ntfs_debug("Last lcn of mft data attribute is 0x%llx.", (long long)lcn); |
| 1714 | (long long)lcn); | ||
| 1715 | /* Minimum allocation is one mft record worth of clusters. */ | 1753 | /* Minimum allocation is one mft record worth of clusters. */ |
| 1716 | min_nr = vol->mft_record_size >> vol->cluster_size_bits; | 1754 | min_nr = vol->mft_record_size >> vol->cluster_size_bits; |
| 1717 | if (!min_nr) | 1755 | if (!min_nr) |
| @@ -1721,12 +1759,13 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1721 | if (!nr) | 1759 | if (!nr) |
| 1722 | nr = min_nr; | 1760 | nr = min_nr; |
| 1723 | /* Ensure we do not go above 2^32-1 mft records. */ | 1761 | /* Ensure we do not go above 2^32-1 mft records. */ |
| 1724 | if (unlikely((mft_ni->allocated_size + | 1762 | read_lock_irqsave(&mft_ni->size_lock, flags); |
| 1725 | (nr << vol->cluster_size_bits)) >> | 1763 | ll = mft_ni->allocated_size; |
| 1764 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 1765 | if (unlikely((ll + (nr << vol->cluster_size_bits)) >> | ||
| 1726 | vol->mft_record_size_bits >= (1ll << 32))) { | 1766 | vol->mft_record_size_bits >= (1ll << 32))) { |
| 1727 | nr = min_nr; | 1767 | nr = min_nr; |
| 1728 | if (unlikely((mft_ni->allocated_size + | 1768 | if (unlikely((ll + (nr << vol->cluster_size_bits)) >> |
| 1729 | (nr << vol->cluster_size_bits)) >> | ||
| 1730 | vol->mft_record_size_bits >= (1ll << 32))) { | 1769 | vol->mft_record_size_bits >= (1ll << 32))) { |
| 1731 | ntfs_warning(vol->sb, "Cannot allocate mft record " | 1770 | ntfs_warning(vol->sb, "Cannot allocate mft record " |
| 1732 | "because the maximum number of inodes " | 1771 | "because the maximum number of inodes " |
| @@ -1772,7 +1811,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1772 | return PTR_ERR(rl); | 1811 | return PTR_ERR(rl); |
| 1773 | } | 1812 | } |
| 1774 | mft_ni->runlist.rl = rl; | 1813 | mft_ni->runlist.rl = rl; |
| 1775 | ntfs_debug("Allocated %lli clusters.", nr); | 1814 | ntfs_debug("Allocated %lli clusters.", (long long)nr); |
| 1776 | /* Find the last run in the new runlist. */ | 1815 | /* Find the last run in the new runlist. */ |
| 1777 | for (; rl[1].length; rl++) | 1816 | for (; rl[1].length; rl++) |
| 1778 | ; | 1817 | ; |
| @@ -1808,7 +1847,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1808 | BUG_ON(ll < rl2->vcn); | 1847 | BUG_ON(ll < rl2->vcn); |
| 1809 | BUG_ON(ll >= rl2->vcn + rl2->length); | 1848 | BUG_ON(ll >= rl2->vcn + rl2->length); |
| 1810 | /* Get the size for the new mapping pairs array for this extent. */ | 1849 | /* Get the size for the new mapping pairs array for this extent. */ |
| 1811 | mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll); | 1850 | mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, -1); |
| 1812 | if (unlikely(mp_size <= 0)) { | 1851 | if (unlikely(mp_size <= 0)) { |
| 1813 | ntfs_error(vol->sb, "Get size for mapping pairs failed for " | 1852 | ntfs_error(vol->sb, "Get size for mapping pairs failed for " |
| 1814 | "mft data attribute extent."); | 1853 | "mft data attribute extent."); |
| @@ -1832,7 +1871,11 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1832 | // moving other attributes out of this mft record. | 1871 | // moving other attributes out of this mft record. |
| 1833 | // Note: Use the special reserved mft records and ensure that | 1872 | // Note: Use the special reserved mft records and ensure that |
| 1834 | // this extent is not required to find the mft record in | 1873 | // this extent is not required to find the mft record in |
| 1835 | // question. | 1874 | // question. If no free special records left we would need to |
| 1875 | // move an existing record away, insert ours in its place, and | ||
| 1876 | // then place the moved record into the newly allocated space | ||
| 1877 | // and we would then need to update all references to this mft | ||
| 1878 | // record appropriately. This is rather complicated... | ||
| 1836 | ntfs_error(vol->sb, "Not enough space in this mft record to " | 1879 | ntfs_error(vol->sb, "Not enough space in this mft record to " |
| 1837 | "accomodate extended mft data attribute " | 1880 | "accomodate extended mft data attribute " |
| 1838 | "extent. Cannot handle this yet."); | 1881 | "extent. Cannot handle this yet."); |
| @@ -1843,7 +1886,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1843 | /* Generate the mapping pairs array directly into the attr record. */ | 1886 | /* Generate the mapping pairs array directly into the attr record. */ |
| 1844 | ret = ntfs_mapping_pairs_build(vol, (u8*)a + | 1887 | ret = ntfs_mapping_pairs_build(vol, (u8*)a + |
| 1845 | le16_to_cpu(a->data.non_resident.mapping_pairs_offset), | 1888 | le16_to_cpu(a->data.non_resident.mapping_pairs_offset), |
| 1846 | mp_size, rl2, ll, NULL); | 1889 | mp_size, rl2, ll, -1, NULL); |
| 1847 | if (unlikely(ret)) { | 1890 | if (unlikely(ret)) { |
| 1848 | ntfs_error(vol->sb, "Failed to build mapping pairs array of " | 1891 | ntfs_error(vol->sb, "Failed to build mapping pairs array of " |
| 1849 | "mft data attribute."); | 1892 | "mft data attribute."); |
| @@ -1875,9 +1918,11 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1875 | } | 1918 | } |
| 1876 | a = ctx->attr; | 1919 | a = ctx->attr; |
| 1877 | } | 1920 | } |
| 1921 | write_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 1878 | mft_ni->allocated_size += nr << vol->cluster_size_bits; | 1922 | mft_ni->allocated_size += nr << vol->cluster_size_bits; |
| 1879 | a->data.non_resident.allocated_size = | 1923 | a->data.non_resident.allocated_size = |
| 1880 | cpu_to_sle64(mft_ni->allocated_size); | 1924 | cpu_to_sle64(mft_ni->allocated_size); |
| 1925 | write_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 1881 | /* Ensure the changes make it to disk. */ | 1926 | /* Ensure the changes make it to disk. */ |
| 1882 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 1927 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
| 1883 | mark_mft_record_dirty(ctx->ntfs_ino); | 1928 | mark_mft_record_dirty(ctx->ntfs_ino); |
| @@ -1892,7 +1937,9 @@ restore_undo_alloc: | |||
| 1892 | CASE_SENSITIVE, rl[1].vcn, NULL, 0, ctx)) { | 1937 | CASE_SENSITIVE, rl[1].vcn, NULL, 0, ctx)) { |
| 1893 | ntfs_error(vol->sb, "Failed to find last attribute extent of " | 1938 | ntfs_error(vol->sb, "Failed to find last attribute extent of " |
| 1894 | "mft data attribute.%s", es); | 1939 | "mft data attribute.%s", es); |
| 1940 | write_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 1895 | mft_ni->allocated_size += nr << vol->cluster_size_bits; | 1941 | mft_ni->allocated_size += nr << vol->cluster_size_bits; |
| 1942 | write_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 1896 | ntfs_attr_put_search_ctx(ctx); | 1943 | ntfs_attr_put_search_ctx(ctx); |
| 1897 | unmap_mft_record(mft_ni); | 1944 | unmap_mft_record(mft_ni); |
| 1898 | up_write(&mft_ni->runlist.lock); | 1945 | up_write(&mft_ni->runlist.lock); |
| @@ -1921,7 +1968,7 @@ undo_alloc: | |||
| 1921 | a->data.non_resident.mapping_pairs_offset), | 1968 | a->data.non_resident.mapping_pairs_offset), |
| 1922 | old_alen - le16_to_cpu( | 1969 | old_alen - le16_to_cpu( |
| 1923 | a->data.non_resident.mapping_pairs_offset), | 1970 | a->data.non_resident.mapping_pairs_offset), |
| 1924 | rl2, ll, NULL)) { | 1971 | rl2, ll, -1, NULL)) { |
| 1925 | ntfs_error(vol->sb, "Failed to restore mapping pairs " | 1972 | ntfs_error(vol->sb, "Failed to restore mapping pairs " |
| 1926 | "array.%s", es); | 1973 | "array.%s", es); |
| 1927 | NVolSetErrors(vol); | 1974 | NVolSetErrors(vol); |
| @@ -1991,7 +2038,7 @@ static int ntfs_mft_record_layout(const ntfs_volume *vol, const s64 mft_no, | |||
| 1991 | "reports this as corruption, please email " | 2038 | "reports this as corruption, please email " |
| 1992 | "linux-ntfs-dev@lists.sourceforge.net stating " | 2039 | "linux-ntfs-dev@lists.sourceforge.net stating " |
| 1993 | "that you saw this message and that the " | 2040 | "that you saw this message and that the " |
| 1994 | "modified file system created was corrupt. " | 2041 | "modified filesystem created was corrupt. " |
| 1995 | "Thank you."); | 2042 | "Thank you."); |
| 1996 | } | 2043 | } |
| 1997 | /* Set the update sequence number to 1. */ | 2044 | /* Set the update sequence number to 1. */ |
| @@ -2036,6 +2083,7 @@ static int ntfs_mft_record_layout(const ntfs_volume *vol, const s64 mft_no, | |||
| 2036 | */ | 2083 | */ |
| 2037 | static int ntfs_mft_record_format(const ntfs_volume *vol, const s64 mft_no) | 2084 | static int ntfs_mft_record_format(const ntfs_volume *vol, const s64 mft_no) |
| 2038 | { | 2085 | { |
| 2086 | loff_t i_size; | ||
| 2039 | struct inode *mft_vi = vol->mft_ino; | 2087 | struct inode *mft_vi = vol->mft_ino; |
| 2040 | struct page *page; | 2088 | struct page *page; |
| 2041 | MFT_RECORD *m; | 2089 | MFT_RECORD *m; |
| @@ -2051,10 +2099,11 @@ static int ntfs_mft_record_format(const ntfs_volume *vol, const s64 mft_no) | |||
| 2051 | index = mft_no << vol->mft_record_size_bits >> PAGE_CACHE_SHIFT; | 2099 | index = mft_no << vol->mft_record_size_bits >> PAGE_CACHE_SHIFT; |
| 2052 | ofs = (mft_no << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK; | 2100 | ofs = (mft_no << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK; |
| 2053 | /* The maximum valid index into the page cache for $MFT's data. */ | 2101 | /* The maximum valid index into the page cache for $MFT's data. */ |
| 2054 | end_index = mft_vi->i_size >> PAGE_CACHE_SHIFT; | 2102 | i_size = i_size_read(mft_vi); |
| 2103 | end_index = i_size >> PAGE_CACHE_SHIFT; | ||
| 2055 | if (unlikely(index >= end_index)) { | 2104 | if (unlikely(index >= end_index)) { |
| 2056 | if (unlikely(index > end_index || ofs + vol->mft_record_size >= | 2105 | if (unlikely(index > end_index || ofs + vol->mft_record_size >= |
| 2057 | (mft_vi->i_size & ~PAGE_CACHE_MASK))) { | 2106 | (i_size & ~PAGE_CACHE_MASK))) { |
| 2058 | ntfs_error(vol->sb, "Tried to format non-existing mft " | 2107 | ntfs_error(vol->sb, "Tried to format non-existing mft " |
| 2059 | "record 0x%llx.", (long long)mft_no); | 2108 | "record 0x%llx.", (long long)mft_no); |
| 2060 | return -ENOENT; | 2109 | return -ENOENT; |
| @@ -2188,6 +2237,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, | |||
| 2188 | ntfs_inode *base_ni, MFT_RECORD **mrec) | 2237 | ntfs_inode *base_ni, MFT_RECORD **mrec) |
| 2189 | { | 2238 | { |
| 2190 | s64 ll, bit, old_data_initialized, old_data_size; | 2239 | s64 ll, bit, old_data_initialized, old_data_size; |
| 2240 | unsigned long flags; | ||
| 2191 | struct inode *vi; | 2241 | struct inode *vi; |
| 2192 | struct page *page; | 2242 | struct page *page; |
| 2193 | ntfs_inode *mft_ni, *mftbmp_ni, *ni; | 2243 | ntfs_inode *mft_ni, *mftbmp_ni, *ni; |
| @@ -2237,9 +2287,13 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, | |||
| 2237 | * the first 24 mft records as they are special and whilst they may not | 2287 | * the first 24 mft records as they are special and whilst they may not |
| 2238 | * be in use, we do not allocate from them. | 2288 | * be in use, we do not allocate from them. |
| 2239 | */ | 2289 | */ |
| 2290 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2240 | ll = mft_ni->initialized_size >> vol->mft_record_size_bits; | 2291 | ll = mft_ni->initialized_size >> vol->mft_record_size_bits; |
| 2241 | if (mftbmp_ni->initialized_size << 3 > ll && | 2292 | read_unlock_irqrestore(&mft_ni->size_lock, flags); |
| 2242 | mftbmp_ni->initialized_size > 3) { | 2293 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); |
| 2294 | old_data_initialized = mftbmp_ni->initialized_size; | ||
| 2295 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 2296 | if (old_data_initialized << 3 > ll && old_data_initialized > 3) { | ||
| 2243 | bit = ll; | 2297 | bit = ll; |
| 2244 | if (bit < 24) | 2298 | if (bit < 24) |
| 2245 | bit = 24; | 2299 | bit = 24; |
| @@ -2254,15 +2308,18 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, | |||
| 2254 | * mft record that we can allocate. | 2308 | * mft record that we can allocate. |
| 2255 | * Note: The smallest mft record we allocate is mft record 24. | 2309 | * Note: The smallest mft record we allocate is mft record 24. |
| 2256 | */ | 2310 | */ |
| 2257 | bit = mftbmp_ni->initialized_size << 3; | 2311 | bit = old_data_initialized << 3; |
| 2258 | if (unlikely(bit >= (1ll << 32))) | 2312 | if (unlikely(bit >= (1ll << 32))) |
| 2259 | goto max_err_out; | 2313 | goto max_err_out; |
| 2314 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 2315 | old_data_size = mftbmp_ni->allocated_size; | ||
| 2260 | ntfs_debug("Status of mftbmp before extension: allocated_size 0x%llx, " | 2316 | ntfs_debug("Status of mftbmp before extension: allocated_size 0x%llx, " |
| 2261 | "data_size 0x%llx, initialized_size 0x%llx.", | 2317 | "data_size 0x%llx, initialized_size 0x%llx.", |
| 2262 | (long long)mftbmp_ni->allocated_size, | 2318 | (long long)old_data_size, |
| 2263 | (long long)vol->mftbmp_ino->i_size, | 2319 | (long long)i_size_read(vol->mftbmp_ino), |
| 2264 | (long long)mftbmp_ni->initialized_size); | 2320 | (long long)old_data_initialized); |
| 2265 | if (mftbmp_ni->initialized_size + 8 > mftbmp_ni->allocated_size) { | 2321 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); |
| 2322 | if (old_data_initialized + 8 > old_data_size) { | ||
| 2266 | /* Need to extend bitmap by one more cluster. */ | 2323 | /* Need to extend bitmap by one more cluster. */ |
| 2267 | ntfs_debug("mftbmp: initialized_size + 8 > allocated_size."); | 2324 | ntfs_debug("mftbmp: initialized_size + 8 > allocated_size."); |
| 2268 | err = ntfs_mft_bitmap_extend_allocation_nolock(vol); | 2325 | err = ntfs_mft_bitmap_extend_allocation_nolock(vol); |
| @@ -2270,12 +2327,16 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, | |||
| 2270 | up_write(&vol->mftbmp_lock); | 2327 | up_write(&vol->mftbmp_lock); |
| 2271 | goto err_out; | 2328 | goto err_out; |
| 2272 | } | 2329 | } |
| 2330 | #ifdef DEBUG | ||
| 2331 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 2273 | ntfs_debug("Status of mftbmp after allocation extension: " | 2332 | ntfs_debug("Status of mftbmp after allocation extension: " |
| 2274 | "allocated_size 0x%llx, data_size 0x%llx, " | 2333 | "allocated_size 0x%llx, data_size 0x%llx, " |
| 2275 | "initialized_size 0x%llx.", | 2334 | "initialized_size 0x%llx.", |
| 2276 | (long long)mftbmp_ni->allocated_size, | 2335 | (long long)mftbmp_ni->allocated_size, |
| 2277 | (long long)vol->mftbmp_ino->i_size, | 2336 | (long long)i_size_read(vol->mftbmp_ino), |
| 2278 | (long long)mftbmp_ni->initialized_size); | 2337 | (long long)mftbmp_ni->initialized_size); |
| 2338 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 2339 | #endif /* DEBUG */ | ||
| 2279 | } | 2340 | } |
| 2280 | /* | 2341 | /* |
| 2281 | * We now have sufficient allocated space, extend the initialized_size | 2342 | * We now have sufficient allocated space, extend the initialized_size |
| @@ -2287,12 +2348,16 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, | |||
| 2287 | up_write(&vol->mftbmp_lock); | 2348 | up_write(&vol->mftbmp_lock); |
| 2288 | goto err_out; | 2349 | goto err_out; |
| 2289 | } | 2350 | } |
| 2351 | #ifdef DEBUG | ||
| 2352 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 2290 | ntfs_debug("Status of mftbmp after initialized extention: " | 2353 | ntfs_debug("Status of mftbmp after initialized extention: " |
| 2291 | "allocated_size 0x%llx, data_size 0x%llx, " | 2354 | "allocated_size 0x%llx, data_size 0x%llx, " |
| 2292 | "initialized_size 0x%llx.", | 2355 | "initialized_size 0x%llx.", |
| 2293 | (long long)mftbmp_ni->allocated_size, | 2356 | (long long)mftbmp_ni->allocated_size, |
| 2294 | (long long)vol->mftbmp_ino->i_size, | 2357 | (long long)i_size_read(vol->mftbmp_ino), |
| 2295 | (long long)mftbmp_ni->initialized_size); | 2358 | (long long)mftbmp_ni->initialized_size); |
| 2359 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 2360 | #endif /* DEBUG */ | ||
| 2296 | ntfs_debug("Found free record (#3), bit 0x%llx.", (long long)bit); | 2361 | ntfs_debug("Found free record (#3), bit 0x%llx.", (long long)bit); |
| 2297 | found_free_rec: | 2362 | found_free_rec: |
| 2298 | /* @bit is the found free mft record, allocate it in the mft bitmap. */ | 2363 | /* @bit is the found free mft record, allocate it in the mft bitmap. */ |
| @@ -2314,7 +2379,10 @@ have_alloc_rec: | |||
| 2314 | * parallel allocation could allocate the same mft record as this one. | 2379 | * parallel allocation could allocate the same mft record as this one. |
| 2315 | */ | 2380 | */ |
| 2316 | ll = (bit + 1) << vol->mft_record_size_bits; | 2381 | ll = (bit + 1) << vol->mft_record_size_bits; |
| 2317 | if (ll <= mft_ni->initialized_size) { | 2382 | read_lock_irqsave(&mft_ni->size_lock, flags); |
| 2383 | old_data_initialized = mft_ni->initialized_size; | ||
| 2384 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2385 | if (ll <= old_data_initialized) { | ||
| 2318 | ntfs_debug("Allocated mft record already initialized."); | 2386 | ntfs_debug("Allocated mft record already initialized."); |
| 2319 | goto mft_rec_already_initialized; | 2387 | goto mft_rec_already_initialized; |
| 2320 | } | 2388 | } |
| @@ -2325,26 +2393,30 @@ have_alloc_rec: | |||
| 2325 | * actually traversed more than once when a freshly formatted volume is | 2393 | * actually traversed more than once when a freshly formatted volume is |
| 2326 | * first written to so it optimizes away nicely in the common case. | 2394 | * first written to so it optimizes away nicely in the common case. |
| 2327 | */ | 2395 | */ |
| 2396 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2328 | ntfs_debug("Status of mft data before extension: " | 2397 | ntfs_debug("Status of mft data before extension: " |
| 2329 | "allocated_size 0x%llx, data_size 0x%llx, " | 2398 | "allocated_size 0x%llx, data_size 0x%llx, " |
| 2330 | "initialized_size 0x%llx.", | 2399 | "initialized_size 0x%llx.", |
| 2331 | (long long)mft_ni->allocated_size, | 2400 | (long long)mft_ni->allocated_size, |
| 2332 | (long long)vol->mft_ino->i_size, | 2401 | (long long)i_size_read(vol->mft_ino), |
| 2333 | (long long)mft_ni->initialized_size); | 2402 | (long long)mft_ni->initialized_size); |
| 2334 | while (ll > mft_ni->allocated_size) { | 2403 | while (ll > mft_ni->allocated_size) { |
| 2404 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2335 | err = ntfs_mft_data_extend_allocation_nolock(vol); | 2405 | err = ntfs_mft_data_extend_allocation_nolock(vol); |
| 2336 | if (unlikely(err)) { | 2406 | if (unlikely(err)) { |
| 2337 | ntfs_error(vol->sb, "Failed to extend mft data " | 2407 | ntfs_error(vol->sb, "Failed to extend mft data " |
| 2338 | "allocation."); | 2408 | "allocation."); |
| 2339 | goto undo_mftbmp_alloc_nolock; | 2409 | goto undo_mftbmp_alloc_nolock; |
| 2340 | } | 2410 | } |
| 2411 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2341 | ntfs_debug("Status of mft data after allocation extension: " | 2412 | ntfs_debug("Status of mft data after allocation extension: " |
| 2342 | "allocated_size 0x%llx, data_size 0x%llx, " | 2413 | "allocated_size 0x%llx, data_size 0x%llx, " |
| 2343 | "initialized_size 0x%llx.", | 2414 | "initialized_size 0x%llx.", |
| 2344 | (long long)mft_ni->allocated_size, | 2415 | (long long)mft_ni->allocated_size, |
| 2345 | (long long)vol->mft_ino->i_size, | 2416 | (long long)i_size_read(vol->mft_ino), |
| 2346 | (long long)mft_ni->initialized_size); | 2417 | (long long)mft_ni->initialized_size); |
| 2347 | } | 2418 | } |
| 2419 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2348 | /* | 2420 | /* |
| 2349 | * Extend mft data initialized size (and data size of course) to reach | 2421 | * Extend mft data initialized size (and data size of course) to reach |
| 2350 | * the allocated mft record, formatting the mft records allong the way. | 2422 | * the allocated mft record, formatting the mft records allong the way. |
| @@ -2352,6 +2424,7 @@ have_alloc_rec: | |||
| 2352 | * needed by ntfs_mft_record_format(). We will update the attribute | 2424 | * needed by ntfs_mft_record_format(). We will update the attribute |
| 2353 | * record itself in one fell swoop later on. | 2425 | * record itself in one fell swoop later on. |
| 2354 | */ | 2426 | */ |
| 2427 | write_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2355 | old_data_initialized = mft_ni->initialized_size; | 2428 | old_data_initialized = mft_ni->initialized_size; |
| 2356 | old_data_size = vol->mft_ino->i_size; | 2429 | old_data_size = vol->mft_ino->i_size; |
| 2357 | while (ll > mft_ni->initialized_size) { | 2430 | while (ll > mft_ni->initialized_size) { |
| @@ -2360,8 +2433,9 @@ have_alloc_rec: | |||
| 2360 | new_initialized_size = mft_ni->initialized_size + | 2433 | new_initialized_size = mft_ni->initialized_size + |
| 2361 | vol->mft_record_size; | 2434 | vol->mft_record_size; |
| 2362 | mft_no = mft_ni->initialized_size >> vol->mft_record_size_bits; | 2435 | mft_no = mft_ni->initialized_size >> vol->mft_record_size_bits; |
| 2363 | if (new_initialized_size > vol->mft_ino->i_size) | 2436 | if (new_initialized_size > i_size_read(vol->mft_ino)) |
| 2364 | vol->mft_ino->i_size = new_initialized_size; | 2437 | i_size_write(vol->mft_ino, new_initialized_size); |
| 2438 | write_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2365 | ntfs_debug("Initializing mft record 0x%llx.", | 2439 | ntfs_debug("Initializing mft record 0x%llx.", |
| 2366 | (long long)mft_no); | 2440 | (long long)mft_no); |
| 2367 | err = ntfs_mft_record_format(vol, mft_no); | 2441 | err = ntfs_mft_record_format(vol, mft_no); |
| @@ -2369,8 +2443,10 @@ have_alloc_rec: | |||
| 2369 | ntfs_error(vol->sb, "Failed to format mft record."); | 2443 | ntfs_error(vol->sb, "Failed to format mft record."); |
| 2370 | goto undo_data_init; | 2444 | goto undo_data_init; |
| 2371 | } | 2445 | } |
| 2446 | write_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2372 | mft_ni->initialized_size = new_initialized_size; | 2447 | mft_ni->initialized_size = new_initialized_size; |
| 2373 | } | 2448 | } |
| 2449 | write_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2374 | record_formatted = TRUE; | 2450 | record_formatted = TRUE; |
| 2375 | /* Update the mft data attribute record to reflect the new sizes. */ | 2451 | /* Update the mft data attribute record to reflect the new sizes. */ |
| 2376 | m = map_mft_record(mft_ni); | 2452 | m = map_mft_record(mft_ni); |
| @@ -2396,22 +2472,27 @@ have_alloc_rec: | |||
| 2396 | goto undo_data_init; | 2472 | goto undo_data_init; |
| 2397 | } | 2473 | } |
| 2398 | a = ctx->attr; | 2474 | a = ctx->attr; |
| 2475 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2399 | a->data.non_resident.initialized_size = | 2476 | a->data.non_resident.initialized_size = |
| 2400 | cpu_to_sle64(mft_ni->initialized_size); | 2477 | cpu_to_sle64(mft_ni->initialized_size); |
| 2401 | a->data.non_resident.data_size = cpu_to_sle64(vol->mft_ino->i_size); | 2478 | a->data.non_resident.data_size = |
| 2479 | cpu_to_sle64(i_size_read(vol->mft_ino)); | ||
| 2480 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2402 | /* Ensure the changes make it to disk. */ | 2481 | /* Ensure the changes make it to disk. */ |
| 2403 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 2482 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
| 2404 | mark_mft_record_dirty(ctx->ntfs_ino); | 2483 | mark_mft_record_dirty(ctx->ntfs_ino); |
| 2405 | ntfs_attr_put_search_ctx(ctx); | 2484 | ntfs_attr_put_search_ctx(ctx); |
| 2406 | unmap_mft_record(mft_ni); | 2485 | unmap_mft_record(mft_ni); |
| 2486 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2407 | ntfs_debug("Status of mft data after mft record initialization: " | 2487 | ntfs_debug("Status of mft data after mft record initialization: " |
| 2408 | "allocated_size 0x%llx, data_size 0x%llx, " | 2488 | "allocated_size 0x%llx, data_size 0x%llx, " |
| 2409 | "initialized_size 0x%llx.", | 2489 | "initialized_size 0x%llx.", |
| 2410 | (long long)mft_ni->allocated_size, | 2490 | (long long)mft_ni->allocated_size, |
| 2411 | (long long)vol->mft_ino->i_size, | 2491 | (long long)i_size_read(vol->mft_ino), |
| 2412 | (long long)mft_ni->initialized_size); | 2492 | (long long)mft_ni->initialized_size); |
| 2413 | BUG_ON(vol->mft_ino->i_size > mft_ni->allocated_size); | 2493 | BUG_ON(i_size_read(vol->mft_ino) > mft_ni->allocated_size); |
| 2414 | BUG_ON(mft_ni->initialized_size > vol->mft_ino->i_size); | 2494 | BUG_ON(mft_ni->initialized_size > i_size_read(vol->mft_ino)); |
| 2495 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2415 | mft_rec_already_initialized: | 2496 | mft_rec_already_initialized: |
| 2416 | /* | 2497 | /* |
| 2417 | * We can finally drop the mft bitmap lock as the mft data attribute | 2498 | * We can finally drop the mft bitmap lock as the mft data attribute |
| @@ -2652,8 +2733,10 @@ mft_rec_already_initialized: | |||
| 2652 | *mrec = m; | 2733 | *mrec = m; |
| 2653 | return ni; | 2734 | return ni; |
| 2654 | undo_data_init: | 2735 | undo_data_init: |
| 2736 | write_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2655 | mft_ni->initialized_size = old_data_initialized; | 2737 | mft_ni->initialized_size = old_data_initialized; |
| 2656 | vol->mft_ino->i_size = old_data_size; | 2738 | i_size_write(vol->mft_ino, old_data_size); |
| 2739 | write_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2657 | goto undo_mftbmp_alloc_nolock; | 2740 | goto undo_mftbmp_alloc_nolock; |
| 2658 | undo_mftbmp_alloc: | 2741 | undo_mftbmp_alloc: |
| 2659 | down_write(&vol->mftbmp_lock); | 2742 | down_write(&vol->mftbmp_lock); |
