diff options
| author | Anton Altaparmakov <aia21@cantab.net> | 2005-01-12 08:08:26 -0500 |
|---|---|---|
| committer | Anton Altaparmakov <aia21@cantab.net> | 2005-05-05 05:39:08 -0400 |
| commit | 07a4e2da7dd3c9345f84b2552872f9d38c257451 (patch) | |
| tree | 8fbd4c3e11196752ae8ff7944ccb26b93cafbb1c | |
| parent | f50f3ac51983025405a71b70b033cc6bcb0d1fc1 (diff) | |
NTFS: Use i_size_{read,write}() in fs/ntfs/{aops.c,mft.c} and protect
access to the i_size and other size fields using the size_lock.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
| -rw-r--r-- | fs/ntfs/ChangeLog | 2 | ||||
| -rw-r--r-- | fs/ntfs/aops.c | 56 | ||||
| -rw-r--r-- | fs/ntfs/mft.c | 157 |
3 files changed, 156 insertions, 59 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 445d421e961d..051c6818aad8 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
| @@ -49,6 +49,8 @@ ToDo/Notes: | |||
| 49 | - Minor optimization to fs/ntfs/super.c::ntfs_statfs() and its helpers. | 49 | - Minor optimization to fs/ntfs/super.c::ntfs_statfs() and its helpers. |
| 50 | - Use i_size_read() in fs/ntfs/inode.c once and then use the cached | 50 | - Use i_size_read() in fs/ntfs/inode.c once and then use the cached |
| 51 | value afterwards when reading the size of the bitmap inode. | 51 | value afterwards when reading the size of the bitmap inode. |
| 52 | - Use i_size_{read,write}() in fs/ntfs/{aops.c,mft.c} and protect | ||
| 53 | access to the i_size and other size fields using the size_lock. | ||
| 52 | 54 | ||
| 53 | 2.1.22 - Many bug and race fixes and error handling improvements. | 55 | 2.1.22 - Many bug and race fixes and error handling improvements. |
| 54 | 56 | ||
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 45d56e41ed98..a53212793809 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c | |||
| @@ -66,19 +66,22 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
| 66 | ni = NTFS_I(page->mapping->host); | 66 | ni = NTFS_I(page->mapping->host); |
| 67 | 67 | ||
| 68 | if (likely(uptodate)) { | 68 | if (likely(uptodate)) { |
| 69 | s64 file_ofs; | 69 | s64 file_ofs, initialized_size; |
| 70 | 70 | ||
| 71 | set_buffer_uptodate(bh); | 71 | set_buffer_uptodate(bh); |
| 72 | 72 | ||
| 73 | file_ofs = ((s64)page->index << PAGE_CACHE_SHIFT) + | 73 | file_ofs = ((s64)page->index << PAGE_CACHE_SHIFT) + |
| 74 | bh_offset(bh); | 74 | bh_offset(bh); |
| 75 | read_lock_irqsave(&ni->size_lock, flags); | ||
| 76 | initialized_size = ni->initialized_size; | ||
| 77 | read_unlock_irqrestore(&ni->size_lock, flags); | ||
| 75 | /* Check for the current buffer head overflowing. */ | 78 | /* Check for the current buffer head overflowing. */ |
| 76 | if (file_ofs + bh->b_size > ni->initialized_size) { | 79 | if (file_ofs + bh->b_size > initialized_size) { |
| 77 | char *addr; | 80 | char *addr; |
| 78 | int ofs = 0; | 81 | int ofs = 0; |
| 79 | 82 | ||
| 80 | if (file_ofs < ni->initialized_size) | 83 | if (file_ofs < initialized_size) |
| 81 | ofs = ni->initialized_size - file_ofs; | 84 | ofs = initialized_size - file_ofs; |
| 82 | addr = kmap_atomic(page, KM_BIO_SRC_IRQ); | 85 | addr = kmap_atomic(page, KM_BIO_SRC_IRQ); |
| 83 | memset(addr + bh_offset(bh) + ofs, 0, bh->b_size - ofs); | 86 | memset(addr + bh_offset(bh) + ofs, 0, bh->b_size - ofs); |
| 84 | flush_dcache_page(page); | 87 | flush_dcache_page(page); |
| @@ -168,6 +171,7 @@ static int ntfs_read_block(struct page *page) | |||
| 168 | runlist_element *rl; | 171 | runlist_element *rl; |
| 169 | struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE]; | 172 | struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE]; |
| 170 | sector_t iblock, lblock, zblock; | 173 | sector_t iblock, lblock, zblock; |
| 174 | unsigned long flags; | ||
| 171 | unsigned int blocksize, vcn_ofs; | 175 | unsigned int blocksize, vcn_ofs; |
| 172 | int i, nr; | 176 | int i, nr; |
| 173 | unsigned char blocksize_bits; | 177 | unsigned char blocksize_bits; |
| @@ -190,8 +194,10 @@ static int ntfs_read_block(struct page *page) | |||
| 190 | } | 194 | } |
| 191 | 195 | ||
| 192 | iblock = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits); | 196 | iblock = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits); |
| 197 | read_lock_irqsave(&ni->size_lock, flags); | ||
| 193 | lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits; | 198 | lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits; |
| 194 | zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits; | 199 | zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits; |
| 200 | read_unlock_irqrestore(&ni->size_lock, flags); | ||
| 195 | 201 | ||
| 196 | /* Loop through all the buffers in the page. */ | 202 | /* Loop through all the buffers in the page. */ |
| 197 | rl = NULL; | 203 | rl = NULL; |
| @@ -463,12 +469,15 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc) | |||
| 463 | { | 469 | { |
| 464 | VCN vcn; | 470 | VCN vcn; |
| 465 | LCN lcn; | 471 | LCN lcn; |
| 472 | s64 initialized_size; | ||
| 473 | loff_t i_size; | ||
| 466 | sector_t block, dblock, iblock; | 474 | sector_t block, dblock, iblock; |
| 467 | struct inode *vi; | 475 | struct inode *vi; |
| 468 | ntfs_inode *ni; | 476 | ntfs_inode *ni; |
| 469 | ntfs_volume *vol; | 477 | ntfs_volume *vol; |
| 470 | runlist_element *rl; | 478 | runlist_element *rl; |
| 471 | struct buffer_head *bh, *head; | 479 | struct buffer_head *bh, *head; |
| 480 | unsigned long flags; | ||
| 472 | unsigned int blocksize, vcn_ofs; | 481 | unsigned int blocksize, vcn_ofs; |
| 473 | int err; | 482 | int err; |
| 474 | BOOL need_end_writeback; | 483 | BOOL need_end_writeback; |
| @@ -510,11 +519,16 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc) | |||
| 510 | /* The first block in the page. */ | 519 | /* The first block in the page. */ |
| 511 | block = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits); | 520 | block = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits); |
| 512 | 521 | ||
| 522 | read_lock_irqsave(&ni->size_lock, flags); | ||
| 523 | i_size = i_size_read(vi); | ||
| 524 | initialized_size = ni->initialized_size; | ||
| 525 | read_unlock_irqrestore(&ni->size_lock, flags); | ||
| 526 | |||
| 513 | /* The first out of bounds block for the data size. */ | 527 | /* The first out of bounds block for the data size. */ |
| 514 | dblock = (vi->i_size + blocksize - 1) >> blocksize_bits; | 528 | dblock = (i_size + blocksize - 1) >> blocksize_bits; |
| 515 | 529 | ||
| 516 | /* The last (fully or partially) initialized block. */ | 530 | /* The last (fully or partially) initialized block. */ |
| 517 | iblock = ni->initialized_size >> blocksize_bits; | 531 | iblock = initialized_size >> blocksize_bits; |
| 518 | 532 | ||
| 519 | /* | 533 | /* |
| 520 | * Be very careful. We have no exclusion from __set_page_dirty_buffers | 534 | * Be very careful. We have no exclusion from __set_page_dirty_buffers |
| @@ -559,7 +573,7 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc) | |||
| 559 | 573 | ||
| 560 | /* Make sure we have enough initialized size. */ | 574 | /* Make sure we have enough initialized size. */ |
| 561 | if (unlikely((block >= iblock) && | 575 | if (unlikely((block >= iblock) && |
| 562 | (ni->initialized_size < vi->i_size))) { | 576 | (initialized_size < i_size))) { |
| 563 | /* | 577 | /* |
| 564 | * If this page is fully outside initialized size, zero | 578 | * If this page is fully outside initialized size, zero |
| 565 | * out all pages between the current initialized size | 579 | * out all pages between the current initialized size |
| @@ -846,7 +860,7 @@ static int ntfs_write_mst_block(struct page *page, | |||
| 846 | (PAGE_CACHE_SHIFT - bh_size_bits); | 860 | (PAGE_CACHE_SHIFT - bh_size_bits); |
| 847 | 861 | ||
| 848 | /* The first out of bounds block for the data size. */ | 862 | /* The first out of bounds block for the data size. */ |
| 849 | dblock = (vi->i_size + bh_size - 1) >> bh_size_bits; | 863 | dblock = (i_size_read(vi) + bh_size - 1) >> bh_size_bits; |
| 850 | 864 | ||
| 851 | rl = NULL; | 865 | rl = NULL; |
| 852 | err = err2 = nr_bhs = nr_recs = nr_locked_nis = 0; | 866 | err = err2 = nr_bhs = nr_recs = nr_locked_nis = 0; |
| @@ -1367,7 +1381,7 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) | |||
| 1367 | */ | 1381 | */ |
| 1368 | 1382 | ||
| 1369 | attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); | 1383 | attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); |
| 1370 | i_size = i_size_read(VFS_I(ni)); | 1384 | i_size = i_size_read(vi); |
| 1371 | kaddr = kmap_atomic(page, KM_USER0); | 1385 | kaddr = kmap_atomic(page, KM_USER0); |
| 1372 | if (unlikely(attr_len > i_size)) { | 1386 | if (unlikely(attr_len > i_size)) { |
| 1373 | /* Zero out of bounds area in the mft record. */ | 1387 | /* Zero out of bounds area in the mft record. */ |
| @@ -1425,12 +1439,15 @@ static int ntfs_prepare_nonresident_write(struct page *page, | |||
| 1425 | { | 1439 | { |
| 1426 | VCN vcn; | 1440 | VCN vcn; |
| 1427 | LCN lcn; | 1441 | LCN lcn; |
| 1442 | s64 initialized_size; | ||
| 1443 | loff_t i_size; | ||
| 1428 | sector_t block, ablock, iblock; | 1444 | sector_t block, ablock, iblock; |
| 1429 | struct inode *vi; | 1445 | struct inode *vi; |
| 1430 | ntfs_inode *ni; | 1446 | ntfs_inode *ni; |
| 1431 | ntfs_volume *vol; | 1447 | ntfs_volume *vol; |
| 1432 | runlist_element *rl; | 1448 | runlist_element *rl; |
| 1433 | struct buffer_head *bh, *head, *wait[2], **wait_bh = wait; | 1449 | struct buffer_head *bh, *head, *wait[2], **wait_bh = wait; |
| 1450 | unsigned long flags; | ||
| 1434 | unsigned int vcn_ofs, block_start, block_end, blocksize; | 1451 | unsigned int vcn_ofs, block_start, block_end, blocksize; |
| 1435 | int err; | 1452 | int err; |
| 1436 | BOOL is_retry; | 1453 | BOOL is_retry; |
| @@ -1462,6 +1479,7 @@ static int ntfs_prepare_nonresident_write(struct page *page, | |||
| 1462 | /* The first block in the page. */ | 1479 | /* The first block in the page. */ |
| 1463 | block = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits); | 1480 | block = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits); |
| 1464 | 1481 | ||
| 1482 | read_lock_irqsave(&ni->size_lock, flags); | ||
| 1465 | /* | 1483 | /* |
| 1466 | * The first out of bounds block for the allocated size. No need to | 1484 | * The first out of bounds block for the allocated size. No need to |
| 1467 | * round up as allocated_size is in multiples of cluster size and the | 1485 | * round up as allocated_size is in multiples of cluster size and the |
| @@ -1470,8 +1488,12 @@ static int ntfs_prepare_nonresident_write(struct page *page, | |||
| 1470 | */ | 1488 | */ |
| 1471 | ablock = ni->allocated_size >> blocksize_bits; | 1489 | ablock = ni->allocated_size >> blocksize_bits; |
| 1472 | 1490 | ||
| 1491 | i_size = i_size_read(vi); | ||
| 1492 | initialized_size = ni->initialized_size; | ||
| 1493 | read_unlock_irqrestore(&ni->size_lock, flags); | ||
| 1494 | |||
| 1473 | /* The last (fully or partially) initialized block. */ | 1495 | /* The last (fully or partially) initialized block. */ |
| 1474 | iblock = ni->initialized_size >> blocksize_bits; | 1496 | iblock = initialized_size >> blocksize_bits; |
| 1475 | 1497 | ||
| 1476 | /* Loop through all the buffers in the page. */ | 1498 | /* Loop through all the buffers in the page. */ |
| 1477 | block_start = 0; | 1499 | block_start = 0; |
| @@ -1518,7 +1540,7 @@ static int ntfs_prepare_nonresident_write(struct page *page, | |||
| 1518 | * request, i.e. block < ablock is true. | 1540 | * request, i.e. block < ablock is true. |
| 1519 | */ | 1541 | */ |
| 1520 | if (unlikely((block >= iblock) && | 1542 | if (unlikely((block >= iblock) && |
| 1521 | (ni->initialized_size < vi->i_size))) { | 1543 | (initialized_size < i_size))) { |
| 1522 | /* | 1544 | /* |
| 1523 | * If this page is fully outside initialized size, zero | 1545 | * If this page is fully outside initialized size, zero |
| 1524 | * out all pages between the current initialized size | 1546 | * out all pages between the current initialized size |
| @@ -1868,7 +1890,7 @@ static int ntfs_prepare_write(struct file *file, struct page *page, | |||
| 1868 | BUG_ON(page_has_buffers(page)); | 1890 | BUG_ON(page_has_buffers(page)); |
| 1869 | new_size = ((s64)page->index << PAGE_CACHE_SHIFT) + to; | 1891 | new_size = ((s64)page->index << PAGE_CACHE_SHIFT) + to; |
| 1870 | /* If we do not need to resize the attribute allocation we are done. */ | 1892 | /* If we do not need to resize the attribute allocation we are done. */ |
| 1871 | if (new_size <= vi->i_size) | 1893 | if (new_size <= i_size_read(vi)) |
| 1872 | goto done; | 1894 | goto done; |
| 1873 | 1895 | ||
| 1874 | // FIXME: We abort for now as this code is not safe. | 1896 | // FIXME: We abort for now as this code is not safe. |
| @@ -1904,7 +1926,7 @@ static int ntfs_prepare_write(struct file *file, struct page *page, | |||
| 1904 | a = ctx->attr; | 1926 | a = ctx->attr; |
| 1905 | /* The total length of the attribute value. */ | 1927 | /* The total length of the attribute value. */ |
| 1906 | attr_len = le32_to_cpu(a->data.resident.value_length); | 1928 | attr_len = le32_to_cpu(a->data.resident.value_length); |
| 1907 | BUG_ON(vi->i_size != attr_len); | 1929 | BUG_ON(i_size_read(vi) != attr_len); |
| 1908 | /* Check if new size is allowed in $AttrDef. */ | 1930 | /* Check if new size is allowed in $AttrDef. */ |
| 1909 | err = ntfs_attr_size_bounds_check(vol, ni->type, new_size); | 1931 | err = ntfs_attr_size_bounds_check(vol, ni->type, new_size); |
| 1910 | if (unlikely(err)) { | 1932 | if (unlikely(err)) { |
| @@ -2047,7 +2069,7 @@ static int ntfs_commit_nonresident_write(struct page *page, | |||
| 2047 | * now we know ntfs_prepare_write() would have failed in the write | 2069 | * now we know ntfs_prepare_write() would have failed in the write |
| 2048 | * exceeds i_size case, so this will never trigger which is fine. | 2070 | * exceeds i_size case, so this will never trigger which is fine. |
| 2049 | */ | 2071 | */ |
| 2050 | if (pos > vi->i_size) { | 2072 | if (pos > i_size_read(vi)) { |
| 2051 | ntfs_error(vi->i_sb, "Writing beyond the existing file size is " | 2073 | ntfs_error(vi->i_sb, "Writing beyond the existing file size is " |
| 2052 | "not supported yet. Sorry."); | 2074 | "not supported yet. Sorry."); |
| 2053 | return -EOPNOTSUPP; | 2075 | return -EOPNOTSUPP; |
| @@ -2183,9 +2205,13 @@ static int ntfs_commit_write(struct file *file, struct page *page, | |||
| 2183 | } | 2205 | } |
| 2184 | kunmap_atomic(kaddr, KM_USER0); | 2206 | kunmap_atomic(kaddr, KM_USER0); |
| 2185 | /* Update i_size if necessary. */ | 2207 | /* Update i_size if necessary. */ |
| 2186 | if (vi->i_size < attr_len) { | 2208 | if (i_size_read(vi) < attr_len) { |
| 2209 | unsigned long flags; | ||
| 2210 | |||
| 2211 | write_lock_irqsave(&ni->size_lock, flags); | ||
| 2187 | ni->allocated_size = ni->initialized_size = attr_len; | 2212 | ni->allocated_size = ni->initialized_size = attr_len; |
| 2188 | i_size_write(vi, attr_len); | 2213 | i_size_write(vi, attr_len); |
| 2214 | write_unlock_irqrestore(&ni->size_lock, flags); | ||
| 2189 | } | 2215 | } |
| 2190 | /* Mark the mft record dirty, so it gets written back. */ | 2216 | /* Mark the mft record dirty, so it gets written back. */ |
| 2191 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 2217 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index dfa85ac2f8ba..20011e02f5b6 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c | |||
| @@ -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. " |
| @@ -1121,6 +1123,7 @@ static int ntfs_mft_bitmap_find_and_alloc_free_rec_nolock(ntfs_volume *vol, | |||
| 1121 | ntfs_inode *base_ni) | 1123 | ntfs_inode *base_ni) |
| 1122 | { | 1124 | { |
| 1123 | s64 pass_end, ll, data_pos, pass_start, ofs, bit; | 1125 | s64 pass_end, ll, data_pos, pass_start, ofs, bit; |
| 1126 | unsigned long flags; | ||
| 1124 | struct address_space *mftbmp_mapping; | 1127 | struct address_space *mftbmp_mapping; |
| 1125 | u8 *buf, *byte; | 1128 | u8 *buf, *byte; |
| 1126 | struct page *page; | 1129 | struct page *page; |
| @@ -1134,9 +1137,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 | 1137 | * Set the end of the pass making sure we do not overflow the mft |
| 1135 | * bitmap. | 1138 | * bitmap. |
| 1136 | */ | 1139 | */ |
| 1140 | read_lock_irqsave(&NTFS_I(vol->mft_ino)->size_lock, flags); | ||
| 1137 | pass_end = NTFS_I(vol->mft_ino)->allocated_size >> | 1141 | pass_end = NTFS_I(vol->mft_ino)->allocated_size >> |
| 1138 | vol->mft_record_size_bits; | 1142 | vol->mft_record_size_bits; |
| 1143 | read_unlock_irqrestore(&NTFS_I(vol->mft_ino)->size_lock, flags); | ||
| 1144 | read_lock_irqsave(&NTFS_I(vol->mftbmp_ino)->size_lock, flags); | ||
| 1139 | ll = NTFS_I(vol->mftbmp_ino)->initialized_size << 3; | 1145 | ll = NTFS_I(vol->mftbmp_ino)->initialized_size << 3; |
| 1146 | read_unlock_irqrestore(&NTFS_I(vol->mftbmp_ino)->size_lock, flags); | ||
| 1140 | if (pass_end > ll) | 1147 | if (pass_end > ll) |
| 1141 | pass_end = ll; | 1148 | pass_end = ll; |
| 1142 | pass = 1; | 1149 | pass = 1; |
| @@ -1263,6 +1270,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1263 | { | 1270 | { |
| 1264 | LCN lcn; | 1271 | LCN lcn; |
| 1265 | s64 ll; | 1272 | s64 ll; |
| 1273 | unsigned long flags; | ||
| 1266 | struct page *page; | 1274 | struct page *page; |
| 1267 | ntfs_inode *mft_ni, *mftbmp_ni; | 1275 | ntfs_inode *mft_ni, *mftbmp_ni; |
| 1268 | runlist_element *rl, *rl2 = NULL; | 1276 | runlist_element *rl, *rl2 = NULL; |
| @@ -1286,8 +1294,10 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1286 | * mft bitmap cannot be zero so we are ok to do this. | 1294 | * mft bitmap cannot be zero so we are ok to do this. |
| 1287 | * ntfs_find_vcn() returns the runlist locked on success. | 1295 | * ntfs_find_vcn() returns the runlist locked on success. |
| 1288 | */ | 1296 | */ |
| 1289 | rl = ntfs_find_vcn(mftbmp_ni, (mftbmp_ni->allocated_size - 1) >> | 1297 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); |
| 1290 | vol->cluster_size_bits, TRUE); | 1298 | ll = mftbmp_ni->allocated_size; |
| 1299 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1300 | rl = ntfs_find_vcn(mftbmp_ni, (ll - 1) >> vol->cluster_size_bits, TRUE); | ||
| 1291 | if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { | 1301 | if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { |
| 1292 | ntfs_error(vol->sb, "Failed to determine last allocated " | 1302 | ntfs_error(vol->sb, "Failed to determine last allocated " |
| 1293 | "cluster of mft bitmap attribute."); | 1303 | "cluster of mft bitmap attribute."); |
| @@ -1458,9 +1468,11 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1458 | } | 1468 | } |
| 1459 | a = ctx->attr; | 1469 | a = ctx->attr; |
| 1460 | } | 1470 | } |
| 1471 | write_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 1461 | mftbmp_ni->allocated_size += vol->cluster_size; | 1472 | mftbmp_ni->allocated_size += vol->cluster_size; |
| 1462 | a->data.non_resident.allocated_size = | 1473 | a->data.non_resident.allocated_size = |
| 1463 | cpu_to_sle64(mftbmp_ni->allocated_size); | 1474 | cpu_to_sle64(mftbmp_ni->allocated_size); |
| 1475 | write_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1464 | /* Ensure the changes make it to disk. */ | 1476 | /* Ensure the changes make it to disk. */ |
| 1465 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 1477 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
| 1466 | mark_mft_record_dirty(ctx->ntfs_ino); | 1478 | mark_mft_record_dirty(ctx->ntfs_ino); |
| @@ -1476,7 +1488,9 @@ restore_undo_alloc: | |||
| 1476 | 0, ctx)) { | 1488 | 0, ctx)) { |
| 1477 | ntfs_error(vol->sb, "Failed to find last attribute extent of " | 1489 | ntfs_error(vol->sb, "Failed to find last attribute extent of " |
| 1478 | "mft bitmap attribute.%s", es); | 1490 | "mft bitmap attribute.%s", es); |
| 1491 | write_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 1479 | mftbmp_ni->allocated_size += vol->cluster_size; | 1492 | mftbmp_ni->allocated_size += vol->cluster_size; |
| 1493 | write_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1480 | ntfs_attr_put_search_ctx(ctx); | 1494 | ntfs_attr_put_search_ctx(ctx); |
| 1481 | unmap_mft_record(mft_ni); | 1495 | unmap_mft_record(mft_ni); |
| 1482 | up_write(&mftbmp_ni->runlist.lock); | 1496 | up_write(&mftbmp_ni->runlist.lock); |
| @@ -1550,6 +1564,7 @@ undo_alloc: | |||
| 1550 | static int ntfs_mft_bitmap_extend_initialized_nolock(ntfs_volume *vol) | 1564 | static int ntfs_mft_bitmap_extend_initialized_nolock(ntfs_volume *vol) |
| 1551 | { | 1565 | { |
| 1552 | s64 old_data_size, old_initialized_size; | 1566 | s64 old_data_size, old_initialized_size; |
| 1567 | unsigned long flags; | ||
| 1553 | struct inode *mftbmp_vi; | 1568 | struct inode *mftbmp_vi; |
| 1554 | ntfs_inode *mft_ni, *mftbmp_ni; | 1569 | ntfs_inode *mft_ni, *mftbmp_ni; |
| 1555 | ntfs_attr_search_ctx *ctx; | 1570 | ntfs_attr_search_ctx *ctx; |
| @@ -1583,7 +1598,8 @@ static int ntfs_mft_bitmap_extend_initialized_nolock(ntfs_volume *vol) | |||
| 1583 | goto put_err_out; | 1598 | goto put_err_out; |
| 1584 | } | 1599 | } |
| 1585 | a = ctx->attr; | 1600 | a = ctx->attr; |
| 1586 | old_data_size = mftbmp_vi->i_size; | 1601 | write_lock_irqsave(&mftbmp_ni->size_lock, flags); |
| 1602 | old_data_size = i_size_read(mftbmp_vi); | ||
| 1587 | old_initialized_size = mftbmp_ni->initialized_size; | 1603 | old_initialized_size = mftbmp_ni->initialized_size; |
| 1588 | /* | 1604 | /* |
| 1589 | * We can simply update the initialized_size before filling the space | 1605 | * We can simply update the initialized_size before filling the space |
| @@ -1593,11 +1609,12 @@ static int ntfs_mft_bitmap_extend_initialized_nolock(ntfs_volume *vol) | |||
| 1593 | mftbmp_ni->initialized_size += 8; | 1609 | mftbmp_ni->initialized_size += 8; |
| 1594 | a->data.non_resident.initialized_size = | 1610 | a->data.non_resident.initialized_size = |
| 1595 | cpu_to_sle64(mftbmp_ni->initialized_size); | 1611 | cpu_to_sle64(mftbmp_ni->initialized_size); |
| 1596 | if (mftbmp_ni->initialized_size > mftbmp_vi->i_size) { | 1612 | if (mftbmp_ni->initialized_size > old_data_size) { |
| 1597 | mftbmp_vi->i_size = mftbmp_ni->initialized_size; | 1613 | i_size_write(mftbmp_vi, mftbmp_ni->initialized_size); |
| 1598 | a->data.non_resident.data_size = | 1614 | a->data.non_resident.data_size = |
| 1599 | cpu_to_sle64(mftbmp_vi->i_size); | 1615 | cpu_to_sle64(mftbmp_ni->initialized_size); |
| 1600 | } | 1616 | } |
| 1617 | write_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1601 | /* Ensure the changes make it to disk. */ | 1618 | /* Ensure the changes make it to disk. */ |
| 1602 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 1619 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
| 1603 | mark_mft_record_dirty(ctx->ntfs_ino); | 1620 | mark_mft_record_dirty(ctx->ntfs_ino); |
| @@ -1636,22 +1653,28 @@ unm_err_out: | |||
| 1636 | goto err_out; | 1653 | goto err_out; |
| 1637 | } | 1654 | } |
| 1638 | a = ctx->attr; | 1655 | a = ctx->attr; |
| 1656 | write_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 1639 | mftbmp_ni->initialized_size = old_initialized_size; | 1657 | mftbmp_ni->initialized_size = old_initialized_size; |
| 1640 | a->data.non_resident.initialized_size = | 1658 | a->data.non_resident.initialized_size = |
| 1641 | cpu_to_sle64(old_initialized_size); | 1659 | cpu_to_sle64(old_initialized_size); |
| 1642 | if (mftbmp_vi->i_size != old_data_size) { | 1660 | if (i_size_read(mftbmp_vi) != old_data_size) { |
| 1643 | mftbmp_vi->i_size = old_data_size; | 1661 | i_size_write(mftbmp_vi, old_data_size); |
| 1644 | a->data.non_resident.data_size = cpu_to_sle64(old_data_size); | 1662 | a->data.non_resident.data_size = cpu_to_sle64(old_data_size); |
| 1645 | } | 1663 | } |
| 1664 | write_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1646 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 1665 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
| 1647 | mark_mft_record_dirty(ctx->ntfs_ino); | 1666 | mark_mft_record_dirty(ctx->ntfs_ino); |
| 1648 | ntfs_attr_put_search_ctx(ctx); | 1667 | ntfs_attr_put_search_ctx(ctx); |
| 1649 | unmap_mft_record(mft_ni); | 1668 | unmap_mft_record(mft_ni); |
| 1669 | #ifdef DEBUG | ||
| 1670 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 1650 | ntfs_debug("Restored status of mftbmp: allocated_size 0x%llx, " | 1671 | ntfs_debug("Restored status of mftbmp: allocated_size 0x%llx, " |
| 1651 | "data_size 0x%llx, initialized_size 0x%llx.", | 1672 | "data_size 0x%llx, initialized_size 0x%llx.", |
| 1652 | (long long)mftbmp_ni->allocated_size, | 1673 | (long long)mftbmp_ni->allocated_size, |
| 1653 | (long long)mftbmp_vi->i_size, | 1674 | (long long)i_size_read(mftbmp_vi), |
| 1654 | (long long)mftbmp_ni->initialized_size); | 1675 | (long long)mftbmp_ni->initialized_size); |
| 1676 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 1677 | #endif /* DEBUG */ | ||
| 1655 | err_out: | 1678 | err_out: |
| 1656 | return ret; | 1679 | return ret; |
| 1657 | } | 1680 | } |
| @@ -1679,7 +1702,8 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1679 | { | 1702 | { |
| 1680 | LCN lcn; | 1703 | LCN lcn; |
| 1681 | VCN old_last_vcn; | 1704 | VCN old_last_vcn; |
| 1682 | s64 min_nr, nr, ll = 0; | 1705 | s64 min_nr, nr, ll; |
| 1706 | unsigned long flags; | ||
| 1683 | ntfs_inode *mft_ni; | 1707 | ntfs_inode *mft_ni; |
| 1684 | runlist_element *rl, *rl2; | 1708 | runlist_element *rl, *rl2; |
| 1685 | ntfs_attr_search_ctx *ctx = NULL; | 1709 | ntfs_attr_search_ctx *ctx = NULL; |
| @@ -1697,8 +1721,10 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1697 | * attribute cannot be zero so we are ok to do this. | 1721 | * attribute cannot be zero so we are ok to do this. |
| 1698 | * ntfs_find_vcn() returns the runlist locked on success. | 1722 | * ntfs_find_vcn() returns the runlist locked on success. |
| 1699 | */ | 1723 | */ |
| 1700 | rl = ntfs_find_vcn(mft_ni, (mft_ni->allocated_size - 1) >> | 1724 | read_lock_irqsave(&mft_ni->size_lock, flags); |
| 1701 | vol->cluster_size_bits, TRUE); | 1725 | ll = mft_ni->allocated_size; |
| 1726 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 1727 | rl = ntfs_find_vcn(mft_ni, (ll - 1) >> vol->cluster_size_bits, TRUE); | ||
| 1702 | if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { | 1728 | if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { |
| 1703 | ntfs_error(vol->sb, "Failed to determine last allocated " | 1729 | ntfs_error(vol->sb, "Failed to determine last allocated " |
| 1704 | "cluster of mft data attribute."); | 1730 | "cluster of mft data attribute."); |
| @@ -1710,8 +1736,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1710 | return ret; | 1736 | return ret; |
| 1711 | } | 1737 | } |
| 1712 | lcn = rl->lcn + rl->length; | 1738 | lcn = rl->lcn + rl->length; |
| 1713 | ntfs_debug("Last lcn of mft data attribute is 0x%llx.", | 1739 | 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. */ | 1740 | /* Minimum allocation is one mft record worth of clusters. */ |
| 1716 | min_nr = vol->mft_record_size >> vol->cluster_size_bits; | 1741 | min_nr = vol->mft_record_size >> vol->cluster_size_bits; |
| 1717 | if (!min_nr) | 1742 | if (!min_nr) |
| @@ -1721,12 +1746,13 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1721 | if (!nr) | 1746 | if (!nr) |
| 1722 | nr = min_nr; | 1747 | nr = min_nr; |
| 1723 | /* Ensure we do not go above 2^32-1 mft records. */ | 1748 | /* Ensure we do not go above 2^32-1 mft records. */ |
| 1724 | if (unlikely((mft_ni->allocated_size + | 1749 | read_lock_irqsave(&mft_ni->size_lock, flags); |
| 1725 | (nr << vol->cluster_size_bits)) >> | 1750 | ll = mft_ni->allocated_size; |
| 1751 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 1752 | if (unlikely((ll + (nr << vol->cluster_size_bits)) >> | ||
| 1726 | vol->mft_record_size_bits >= (1ll << 32))) { | 1753 | vol->mft_record_size_bits >= (1ll << 32))) { |
| 1727 | nr = min_nr; | 1754 | nr = min_nr; |
| 1728 | if (unlikely((mft_ni->allocated_size + | 1755 | if (unlikely((ll + (nr << vol->cluster_size_bits)) >> |
| 1729 | (nr << vol->cluster_size_bits)) >> | ||
| 1730 | vol->mft_record_size_bits >= (1ll << 32))) { | 1756 | vol->mft_record_size_bits >= (1ll << 32))) { |
| 1731 | ntfs_warning(vol->sb, "Cannot allocate mft record " | 1757 | ntfs_warning(vol->sb, "Cannot allocate mft record " |
| 1732 | "because the maximum number of inodes " | 1758 | "because the maximum number of inodes " |
| @@ -1875,9 +1901,11 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) | |||
| 1875 | } | 1901 | } |
| 1876 | a = ctx->attr; | 1902 | a = ctx->attr; |
| 1877 | } | 1903 | } |
| 1904 | write_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 1878 | mft_ni->allocated_size += nr << vol->cluster_size_bits; | 1905 | mft_ni->allocated_size += nr << vol->cluster_size_bits; |
| 1879 | a->data.non_resident.allocated_size = | 1906 | a->data.non_resident.allocated_size = |
| 1880 | cpu_to_sle64(mft_ni->allocated_size); | 1907 | cpu_to_sle64(mft_ni->allocated_size); |
| 1908 | write_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 1881 | /* Ensure the changes make it to disk. */ | 1909 | /* Ensure the changes make it to disk. */ |
| 1882 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 1910 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
| 1883 | mark_mft_record_dirty(ctx->ntfs_ino); | 1911 | mark_mft_record_dirty(ctx->ntfs_ino); |
| @@ -1892,7 +1920,9 @@ restore_undo_alloc: | |||
| 1892 | CASE_SENSITIVE, rl[1].vcn, NULL, 0, ctx)) { | 1920 | CASE_SENSITIVE, rl[1].vcn, NULL, 0, ctx)) { |
| 1893 | ntfs_error(vol->sb, "Failed to find last attribute extent of " | 1921 | ntfs_error(vol->sb, "Failed to find last attribute extent of " |
| 1894 | "mft data attribute.%s", es); | 1922 | "mft data attribute.%s", es); |
| 1923 | write_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 1895 | mft_ni->allocated_size += nr << vol->cluster_size_bits; | 1924 | mft_ni->allocated_size += nr << vol->cluster_size_bits; |
| 1925 | write_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 1896 | ntfs_attr_put_search_ctx(ctx); | 1926 | ntfs_attr_put_search_ctx(ctx); |
| 1897 | unmap_mft_record(mft_ni); | 1927 | unmap_mft_record(mft_ni); |
| 1898 | up_write(&mft_ni->runlist.lock); | 1928 | up_write(&mft_ni->runlist.lock); |
| @@ -2036,6 +2066,7 @@ static int ntfs_mft_record_layout(const ntfs_volume *vol, const s64 mft_no, | |||
| 2036 | */ | 2066 | */ |
| 2037 | static int ntfs_mft_record_format(const ntfs_volume *vol, const s64 mft_no) | 2067 | static int ntfs_mft_record_format(const ntfs_volume *vol, const s64 mft_no) |
| 2038 | { | 2068 | { |
| 2069 | loff_t i_size; | ||
| 2039 | struct inode *mft_vi = vol->mft_ino; | 2070 | struct inode *mft_vi = vol->mft_ino; |
| 2040 | struct page *page; | 2071 | struct page *page; |
| 2041 | MFT_RECORD *m; | 2072 | MFT_RECORD *m; |
| @@ -2051,10 +2082,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; | 2082 | index = mft_no << vol->mft_record_size_bits >> PAGE_CACHE_SHIFT; |
| 2052 | ofs = (mft_no << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK; | 2083 | ofs = (mft_no << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK; |
| 2053 | /* The maximum valid index into the page cache for $MFT's data. */ | 2084 | /* The maximum valid index into the page cache for $MFT's data. */ |
| 2054 | end_index = mft_vi->i_size >> PAGE_CACHE_SHIFT; | 2085 | i_size = i_size_read(mft_vi); |
| 2086 | end_index = i_size >> PAGE_CACHE_SHIFT; | ||
| 2055 | if (unlikely(index >= end_index)) { | 2087 | if (unlikely(index >= end_index)) { |
| 2056 | if (unlikely(index > end_index || ofs + vol->mft_record_size >= | 2088 | if (unlikely(index > end_index || ofs + vol->mft_record_size >= |
| 2057 | (mft_vi->i_size & ~PAGE_CACHE_MASK))) { | 2089 | (i_size & ~PAGE_CACHE_MASK))) { |
| 2058 | ntfs_error(vol->sb, "Tried to format non-existing mft " | 2090 | ntfs_error(vol->sb, "Tried to format non-existing mft " |
| 2059 | "record 0x%llx.", (long long)mft_no); | 2091 | "record 0x%llx.", (long long)mft_no); |
| 2060 | return -ENOENT; | 2092 | return -ENOENT; |
| @@ -2188,6 +2220,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, | |||
| 2188 | ntfs_inode *base_ni, MFT_RECORD **mrec) | 2220 | ntfs_inode *base_ni, MFT_RECORD **mrec) |
| 2189 | { | 2221 | { |
| 2190 | s64 ll, bit, old_data_initialized, old_data_size; | 2222 | s64 ll, bit, old_data_initialized, old_data_size; |
| 2223 | unsigned long flags; | ||
| 2191 | struct inode *vi; | 2224 | struct inode *vi; |
| 2192 | struct page *page; | 2225 | struct page *page; |
| 2193 | ntfs_inode *mft_ni, *mftbmp_ni, *ni; | 2226 | ntfs_inode *mft_ni, *mftbmp_ni, *ni; |
| @@ -2237,9 +2270,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 | 2270 | * the first 24 mft records as they are special and whilst they may not |
| 2238 | * be in use, we do not allocate from them. | 2271 | * be in use, we do not allocate from them. |
| 2239 | */ | 2272 | */ |
| 2273 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2240 | ll = mft_ni->initialized_size >> vol->mft_record_size_bits; | 2274 | ll = mft_ni->initialized_size >> vol->mft_record_size_bits; |
| 2241 | if (mftbmp_ni->initialized_size << 3 > ll && | 2275 | read_unlock_irqrestore(&mft_ni->size_lock, flags); |
| 2242 | mftbmp_ni->initialized_size > 3) { | 2276 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); |
| 2277 | old_data_initialized = mftbmp_ni->initialized_size; | ||
| 2278 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 2279 | if (old_data_initialized << 3 > ll && old_data_initialized > 3) { | ||
| 2243 | bit = ll; | 2280 | bit = ll; |
| 2244 | if (bit < 24) | 2281 | if (bit < 24) |
| 2245 | bit = 24; | 2282 | bit = 24; |
| @@ -2254,15 +2291,18 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, | |||
| 2254 | * mft record that we can allocate. | 2291 | * mft record that we can allocate. |
| 2255 | * Note: The smallest mft record we allocate is mft record 24. | 2292 | * Note: The smallest mft record we allocate is mft record 24. |
| 2256 | */ | 2293 | */ |
| 2257 | bit = mftbmp_ni->initialized_size << 3; | 2294 | bit = old_data_initialized << 3; |
| 2258 | if (unlikely(bit >= (1ll << 32))) | 2295 | if (unlikely(bit >= (1ll << 32))) |
| 2259 | goto max_err_out; | 2296 | goto max_err_out; |
| 2297 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 2298 | old_data_size = mftbmp_ni->allocated_size; | ||
| 2260 | ntfs_debug("Status of mftbmp before extension: allocated_size 0x%llx, " | 2299 | ntfs_debug("Status of mftbmp before extension: allocated_size 0x%llx, " |
| 2261 | "data_size 0x%llx, initialized_size 0x%llx.", | 2300 | "data_size 0x%llx, initialized_size 0x%llx.", |
| 2262 | (long long)mftbmp_ni->allocated_size, | 2301 | (long long)old_data_size, |
| 2263 | (long long)vol->mftbmp_ino->i_size, | 2302 | (long long)i_size_read(vol->mftbmp_ino), |
| 2264 | (long long)mftbmp_ni->initialized_size); | 2303 | (long long)old_data_initialized); |
| 2265 | if (mftbmp_ni->initialized_size + 8 > mftbmp_ni->allocated_size) { | 2304 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); |
| 2305 | if (old_data_initialized + 8 > old_data_size) { | ||
| 2266 | /* Need to extend bitmap by one more cluster. */ | 2306 | /* Need to extend bitmap by one more cluster. */ |
| 2267 | ntfs_debug("mftbmp: initialized_size + 8 > allocated_size."); | 2307 | ntfs_debug("mftbmp: initialized_size + 8 > allocated_size."); |
| 2268 | err = ntfs_mft_bitmap_extend_allocation_nolock(vol); | 2308 | err = ntfs_mft_bitmap_extend_allocation_nolock(vol); |
| @@ -2270,12 +2310,16 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, | |||
| 2270 | up_write(&vol->mftbmp_lock); | 2310 | up_write(&vol->mftbmp_lock); |
| 2271 | goto err_out; | 2311 | goto err_out; |
| 2272 | } | 2312 | } |
| 2313 | #ifdef DEBUG | ||
| 2314 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 2273 | ntfs_debug("Status of mftbmp after allocation extension: " | 2315 | ntfs_debug("Status of mftbmp after allocation extension: " |
| 2274 | "allocated_size 0x%llx, data_size 0x%llx, " | 2316 | "allocated_size 0x%llx, data_size 0x%llx, " |
| 2275 | "initialized_size 0x%llx.", | 2317 | "initialized_size 0x%llx.", |
| 2276 | (long long)mftbmp_ni->allocated_size, | 2318 | (long long)mftbmp_ni->allocated_size, |
| 2277 | (long long)vol->mftbmp_ino->i_size, | 2319 | (long long)i_size_read(vol->mftbmp_ino), |
| 2278 | (long long)mftbmp_ni->initialized_size); | 2320 | (long long)mftbmp_ni->initialized_size); |
| 2321 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 2322 | #endif /* DEBUG */ | ||
| 2279 | } | 2323 | } |
| 2280 | /* | 2324 | /* |
| 2281 | * We now have sufficient allocated space, extend the initialized_size | 2325 | * We now have sufficient allocated space, extend the initialized_size |
| @@ -2287,12 +2331,16 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, const int mode, | |||
| 2287 | up_write(&vol->mftbmp_lock); | 2331 | up_write(&vol->mftbmp_lock); |
| 2288 | goto err_out; | 2332 | goto err_out; |
| 2289 | } | 2333 | } |
| 2334 | #ifdef DEBUG | ||
| 2335 | read_lock_irqsave(&mftbmp_ni->size_lock, flags); | ||
| 2290 | ntfs_debug("Status of mftbmp after initialized extention: " | 2336 | ntfs_debug("Status of mftbmp after initialized extention: " |
| 2291 | "allocated_size 0x%llx, data_size 0x%llx, " | 2337 | "allocated_size 0x%llx, data_size 0x%llx, " |
| 2292 | "initialized_size 0x%llx.", | 2338 | "initialized_size 0x%llx.", |
| 2293 | (long long)mftbmp_ni->allocated_size, | 2339 | (long long)mftbmp_ni->allocated_size, |
| 2294 | (long long)vol->mftbmp_ino->i_size, | 2340 | (long long)i_size_read(vol->mftbmp_ino), |
| 2295 | (long long)mftbmp_ni->initialized_size); | 2341 | (long long)mftbmp_ni->initialized_size); |
| 2342 | read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); | ||
| 2343 | #endif /* DEBUG */ | ||
| 2296 | ntfs_debug("Found free record (#3), bit 0x%llx.", (long long)bit); | 2344 | ntfs_debug("Found free record (#3), bit 0x%llx.", (long long)bit); |
| 2297 | found_free_rec: | 2345 | found_free_rec: |
| 2298 | /* @bit is the found free mft record, allocate it in the mft bitmap. */ | 2346 | /* @bit is the found free mft record, allocate it in the mft bitmap. */ |
| @@ -2314,7 +2362,10 @@ have_alloc_rec: | |||
| 2314 | * parallel allocation could allocate the same mft record as this one. | 2362 | * parallel allocation could allocate the same mft record as this one. |
| 2315 | */ | 2363 | */ |
| 2316 | ll = (bit + 1) << vol->mft_record_size_bits; | 2364 | ll = (bit + 1) << vol->mft_record_size_bits; |
| 2317 | if (ll <= mft_ni->initialized_size) { | 2365 | read_lock_irqsave(&mft_ni->size_lock, flags); |
| 2366 | old_data_initialized = mft_ni->initialized_size; | ||
| 2367 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2368 | if (ll <= old_data_initialized) { | ||
| 2318 | ntfs_debug("Allocated mft record already initialized."); | 2369 | ntfs_debug("Allocated mft record already initialized."); |
| 2319 | goto mft_rec_already_initialized; | 2370 | goto mft_rec_already_initialized; |
| 2320 | } | 2371 | } |
| @@ -2325,25 +2376,32 @@ have_alloc_rec: | |||
| 2325 | * actually traversed more than once when a freshly formatted volume is | 2376 | * actually traversed more than once when a freshly formatted volume is |
| 2326 | * first written to so it optimizes away nicely in the common case. | 2377 | * first written to so it optimizes away nicely in the common case. |
| 2327 | */ | 2378 | */ |
| 2379 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2380 | old_data_size = mft_ni->allocated_size; | ||
| 2328 | ntfs_debug("Status of mft data before extension: " | 2381 | ntfs_debug("Status of mft data before extension: " |
| 2329 | "allocated_size 0x%llx, data_size 0x%llx, " | 2382 | "allocated_size 0x%llx, data_size 0x%llx, " |
| 2330 | "initialized_size 0x%llx.", | 2383 | "initialized_size 0x%llx.", |
| 2331 | (long long)mft_ni->allocated_size, | 2384 | (long long)old_data_size, |
| 2332 | (long long)vol->mft_ino->i_size, | 2385 | (long long)i_size_read(vol->mft_ino), |
| 2333 | (long long)mft_ni->initialized_size); | 2386 | (long long)mft_ni->initialized_size); |
| 2334 | while (ll > mft_ni->allocated_size) { | 2387 | read_unlock_irqrestore(&mft_ni->size_lock, flags); |
| 2388 | while (ll > old_data_size) { | ||
| 2335 | err = ntfs_mft_data_extend_allocation_nolock(vol); | 2389 | err = ntfs_mft_data_extend_allocation_nolock(vol); |
| 2336 | if (unlikely(err)) { | 2390 | if (unlikely(err)) { |
| 2337 | ntfs_error(vol->sb, "Failed to extend mft data " | 2391 | ntfs_error(vol->sb, "Failed to extend mft data " |
| 2338 | "allocation."); | 2392 | "allocation."); |
| 2339 | goto undo_mftbmp_alloc_nolock; | 2393 | goto undo_mftbmp_alloc_nolock; |
| 2340 | } | 2394 | } |
| 2395 | #ifdef DEBUG | ||
| 2396 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2341 | ntfs_debug("Status of mft data after allocation extension: " | 2397 | ntfs_debug("Status of mft data after allocation extension: " |
| 2342 | "allocated_size 0x%llx, data_size 0x%llx, " | 2398 | "allocated_size 0x%llx, data_size 0x%llx, " |
| 2343 | "initialized_size 0x%llx.", | 2399 | "initialized_size 0x%llx.", |
| 2344 | (long long)mft_ni->allocated_size, | 2400 | (long long)mft_ni->allocated_size, |
| 2345 | (long long)vol->mft_ino->i_size, | 2401 | (long long)i_size_read(vol->mft_ino), |
| 2346 | (long long)mft_ni->initialized_size); | 2402 | (long long)mft_ni->initialized_size); |
| 2403 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2404 | #endif /* DEBUG */ | ||
| 2347 | } | 2405 | } |
| 2348 | /* | 2406 | /* |
| 2349 | * Extend mft data initialized size (and data size of course) to reach | 2407 | * Extend mft data initialized size (and data size of course) to reach |
| @@ -2352,6 +2410,7 @@ have_alloc_rec: | |||
| 2352 | * needed by ntfs_mft_record_format(). We will update the attribute | 2410 | * needed by ntfs_mft_record_format(). We will update the attribute |
| 2353 | * record itself in one fell swoop later on. | 2411 | * record itself in one fell swoop later on. |
| 2354 | */ | 2412 | */ |
| 2413 | write_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2355 | old_data_initialized = mft_ni->initialized_size; | 2414 | old_data_initialized = mft_ni->initialized_size; |
| 2356 | old_data_size = vol->mft_ino->i_size; | 2415 | old_data_size = vol->mft_ino->i_size; |
| 2357 | while (ll > mft_ni->initialized_size) { | 2416 | while (ll > mft_ni->initialized_size) { |
| @@ -2360,8 +2419,9 @@ have_alloc_rec: | |||
| 2360 | new_initialized_size = mft_ni->initialized_size + | 2419 | new_initialized_size = mft_ni->initialized_size + |
| 2361 | vol->mft_record_size; | 2420 | vol->mft_record_size; |
| 2362 | mft_no = mft_ni->initialized_size >> vol->mft_record_size_bits; | 2421 | mft_no = mft_ni->initialized_size >> vol->mft_record_size_bits; |
| 2363 | if (new_initialized_size > vol->mft_ino->i_size) | 2422 | if (new_initialized_size > i_size_read(vol->mft_ino)) |
| 2364 | vol->mft_ino->i_size = new_initialized_size; | 2423 | i_size_write(vol->mft_ino, new_initialized_size); |
| 2424 | write_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2365 | ntfs_debug("Initializing mft record 0x%llx.", | 2425 | ntfs_debug("Initializing mft record 0x%llx.", |
| 2366 | (long long)mft_no); | 2426 | (long long)mft_no); |
| 2367 | err = ntfs_mft_record_format(vol, mft_no); | 2427 | err = ntfs_mft_record_format(vol, mft_no); |
| @@ -2369,8 +2429,10 @@ have_alloc_rec: | |||
| 2369 | ntfs_error(vol->sb, "Failed to format mft record."); | 2429 | ntfs_error(vol->sb, "Failed to format mft record."); |
| 2370 | goto undo_data_init; | 2430 | goto undo_data_init; |
| 2371 | } | 2431 | } |
| 2432 | write_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2372 | mft_ni->initialized_size = new_initialized_size; | 2433 | mft_ni->initialized_size = new_initialized_size; |
| 2373 | } | 2434 | } |
| 2435 | write_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2374 | record_formatted = TRUE; | 2436 | record_formatted = TRUE; |
| 2375 | /* Update the mft data attribute record to reflect the new sizes. */ | 2437 | /* Update the mft data attribute record to reflect the new sizes. */ |
| 2376 | m = map_mft_record(mft_ni); | 2438 | m = map_mft_record(mft_ni); |
| @@ -2396,22 +2458,27 @@ have_alloc_rec: | |||
| 2396 | goto undo_data_init; | 2458 | goto undo_data_init; |
| 2397 | } | 2459 | } |
| 2398 | a = ctx->attr; | 2460 | a = ctx->attr; |
| 2461 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2399 | a->data.non_resident.initialized_size = | 2462 | a->data.non_resident.initialized_size = |
| 2400 | cpu_to_sle64(mft_ni->initialized_size); | 2463 | cpu_to_sle64(mft_ni->initialized_size); |
| 2401 | a->data.non_resident.data_size = cpu_to_sle64(vol->mft_ino->i_size); | 2464 | a->data.non_resident.data_size = |
| 2465 | cpu_to_sle64(i_size_read(vol->mft_ino)); | ||
| 2466 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2402 | /* Ensure the changes make it to disk. */ | 2467 | /* Ensure the changes make it to disk. */ |
| 2403 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 2468 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
| 2404 | mark_mft_record_dirty(ctx->ntfs_ino); | 2469 | mark_mft_record_dirty(ctx->ntfs_ino); |
| 2405 | ntfs_attr_put_search_ctx(ctx); | 2470 | ntfs_attr_put_search_ctx(ctx); |
| 2406 | unmap_mft_record(mft_ni); | 2471 | unmap_mft_record(mft_ni); |
| 2472 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2407 | ntfs_debug("Status of mft data after mft record initialization: " | 2473 | ntfs_debug("Status of mft data after mft record initialization: " |
| 2408 | "allocated_size 0x%llx, data_size 0x%llx, " | 2474 | "allocated_size 0x%llx, data_size 0x%llx, " |
| 2409 | "initialized_size 0x%llx.", | 2475 | "initialized_size 0x%llx.", |
| 2410 | (long long)mft_ni->allocated_size, | 2476 | (long long)mft_ni->allocated_size, |
| 2411 | (long long)vol->mft_ino->i_size, | 2477 | (long long)i_size_read(vol->mft_ino), |
| 2412 | (long long)mft_ni->initialized_size); | 2478 | (long long)mft_ni->initialized_size); |
| 2413 | BUG_ON(vol->mft_ino->i_size > mft_ni->allocated_size); | 2479 | BUG_ON(i_size_read(vol->mft_ino) > mft_ni->allocated_size); |
| 2414 | BUG_ON(mft_ni->initialized_size > vol->mft_ino->i_size); | 2480 | BUG_ON(mft_ni->initialized_size > i_size_read(vol->mft_ino)); |
| 2481 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2415 | mft_rec_already_initialized: | 2482 | mft_rec_already_initialized: |
| 2416 | /* | 2483 | /* |
| 2417 | * We can finally drop the mft bitmap lock as the mft data attribute | 2484 | * We can finally drop the mft bitmap lock as the mft data attribute |
| @@ -2652,8 +2719,10 @@ mft_rec_already_initialized: | |||
| 2652 | *mrec = m; | 2719 | *mrec = m; |
| 2653 | return ni; | 2720 | return ni; |
| 2654 | undo_data_init: | 2721 | undo_data_init: |
| 2722 | write_lock_irqsave(&mft_ni->size_lock, flags); | ||
| 2655 | mft_ni->initialized_size = old_data_initialized; | 2723 | mft_ni->initialized_size = old_data_initialized; |
| 2656 | vol->mft_ino->i_size = old_data_size; | 2724 | i_size_write(vol->mft_ino, old_data_size); |
| 2725 | write_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
| 2657 | goto undo_mftbmp_alloc_nolock; | 2726 | goto undo_mftbmp_alloc_nolock; |
| 2658 | undo_mftbmp_alloc: | 2727 | undo_mftbmp_alloc: |
| 2659 | down_write(&vol->mftbmp_lock); | 2728 | down_write(&vol->mftbmp_lock); |
