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 /fs/ntfs/aops.c | |
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>
Diffstat (limited to 'fs/ntfs/aops.c')
-rw-r--r-- | fs/ntfs/aops.c | 56 |
1 files changed, 41 insertions, 15 deletions
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); |