diff options
-rw-r--r-- | fs/ntfs/ChangeLog | 4 | ||||
-rw-r--r-- | fs/ntfs/attrib.c | 53 |
2 files changed, 40 insertions, 17 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 1d1dcab3902c..b0cc43bd2974 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -66,6 +66,10 @@ ToDo/Notes: | |||
66 | return LCN_ENOENT when there is no runlist and the allocated size is | 66 | return LCN_ENOENT when there is no runlist and the allocated size is |
67 | zero. | 67 | zero. |
68 | - Fix load_attribute_list() to handle the case of a NULL runlist. | 68 | - Fix load_attribute_list() to handle the case of a NULL runlist. |
69 | - Fix handling of sparse attributes in ntfs_attr_make_non_resident(). | ||
70 | - Add BUG() checks to ntfs_attr_make_non_resident() and ntfs_attr_set() | ||
71 | to ensure that these functions are never called for compressed or | ||
72 | encrypted attributes. | ||
69 | 73 | ||
70 | 2.1.23 - Implement extension of resident files and make writing safe as well as | 74 | 2.1.23 - Implement extension of resident files and make writing safe as well as |
71 | many bug fixes, cleanups, and enhancements... | 75 | many bug fixes, cleanups, and enhancements... |
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 98b5b96e8397..3f9a4ff42ee5 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -1372,6 +1372,12 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni) | |||
1372 | return err; | 1372 | return err; |
1373 | } | 1373 | } |
1374 | /* | 1374 | /* |
1375 | * FIXME: Compressed and encrypted attributes are not supported when | ||
1376 | * writing and we should never have gotten here for them. | ||
1377 | */ | ||
1378 | BUG_ON(NInoCompressed(ni)); | ||
1379 | BUG_ON(NInoEncrypted(ni)); | ||
1380 | /* | ||
1375 | * The size needs to be aligned to a cluster boundary for allocation | 1381 | * The size needs to be aligned to a cluster boundary for allocation |
1376 | * purposes. | 1382 | * purposes. |
1377 | */ | 1383 | */ |
@@ -1447,10 +1453,15 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni) | |||
1447 | BUG_ON(a->non_resident); | 1453 | BUG_ON(a->non_resident); |
1448 | /* | 1454 | /* |
1449 | * Calculate new offsets for the name and the mapping pairs array. | 1455 | * Calculate new offsets for the name and the mapping pairs array. |
1450 | * We assume the attribute is not compressed or sparse. | ||
1451 | */ | 1456 | */ |
1452 | name_ofs = (offsetof(ATTR_REC, | 1457 | if (NInoSparse(ni) || NInoCompressed(ni)) |
1453 | data.non_resident.compressed_size) + 7) & ~7; | 1458 | name_ofs = (offsetof(ATTR_REC, |
1459 | data.non_resident.compressed_size) + | ||
1460 | sizeof(a->data.non_resident.compressed_size) + | ||
1461 | 7) & ~7; | ||
1462 | else | ||
1463 | name_ofs = (offsetof(ATTR_REC, | ||
1464 | data.non_resident.compressed_size) + 7) & ~7; | ||
1454 | mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7; | 1465 | mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7; |
1455 | /* | 1466 | /* |
1456 | * Determine the size of the resident part of the now non-resident | 1467 | * Determine the size of the resident part of the now non-resident |
@@ -1489,24 +1500,23 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni) | |||
1489 | memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset), | 1500 | memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset), |
1490 | a->name_length * sizeof(ntfschar)); | 1501 | a->name_length * sizeof(ntfschar)); |
1491 | a->name_offset = cpu_to_le16(name_ofs); | 1502 | a->name_offset = cpu_to_le16(name_ofs); |
1492 | /* | ||
1493 | * FIXME: For now just clear all of these as we do not support them | ||
1494 | * when writing. | ||
1495 | */ | ||
1496 | a->flags &= cpu_to_le16(0xffff & ~le16_to_cpu(ATTR_IS_SPARSE | | ||
1497 | ATTR_IS_ENCRYPTED | ATTR_COMPRESSION_MASK)); | ||
1498 | /* Setup the fields specific to non-resident attributes. */ | 1503 | /* Setup the fields specific to non-resident attributes. */ |
1499 | a->data.non_resident.lowest_vcn = 0; | 1504 | a->data.non_resident.lowest_vcn = 0; |
1500 | a->data.non_resident.highest_vcn = cpu_to_sle64((new_size - 1) >> | 1505 | a->data.non_resident.highest_vcn = cpu_to_sle64((new_size - 1) >> |
1501 | vol->cluster_size_bits); | 1506 | vol->cluster_size_bits); |
1502 | a->data.non_resident.mapping_pairs_offset = cpu_to_le16(mp_ofs); | 1507 | a->data.non_resident.mapping_pairs_offset = cpu_to_le16(mp_ofs); |
1503 | a->data.non_resident.compression_unit = 0; | ||
1504 | memset(&a->data.non_resident.reserved, 0, | 1508 | memset(&a->data.non_resident.reserved, 0, |
1505 | sizeof(a->data.non_resident.reserved)); | 1509 | sizeof(a->data.non_resident.reserved)); |
1506 | a->data.non_resident.allocated_size = cpu_to_sle64(new_size); | 1510 | a->data.non_resident.allocated_size = cpu_to_sle64(new_size); |
1507 | a->data.non_resident.data_size = | 1511 | a->data.non_resident.data_size = |
1508 | a->data.non_resident.initialized_size = | 1512 | a->data.non_resident.initialized_size = |
1509 | cpu_to_sle64(attr_size); | 1513 | cpu_to_sle64(attr_size); |
1514 | if (NInoSparse(ni) || NInoCompressed(ni)) { | ||
1515 | a->data.non_resident.compression_unit = 4; | ||
1516 | a->data.non_resident.compressed_size = | ||
1517 | a->data.non_resident.allocated_size; | ||
1518 | } else | ||
1519 | a->data.non_resident.compression_unit = 0; | ||
1510 | /* Generate the mapping pairs array into the attribute record. */ | 1520 | /* Generate the mapping pairs array into the attribute record. */ |
1511 | err = ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs, | 1521 | err = ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs, |
1512 | arec_size - mp_ofs, rl, 0, -1, NULL); | 1522 | arec_size - mp_ofs, rl, 0, -1, NULL); |
@@ -1516,16 +1526,19 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni) | |||
1516 | goto undo_err_out; | 1526 | goto undo_err_out; |
1517 | } | 1527 | } |
1518 | /* Setup the in-memory attribute structure to be non-resident. */ | 1528 | /* Setup the in-memory attribute structure to be non-resident. */ |
1519 | /* | ||
1520 | * FIXME: For now just clear all of these as we do not support them | ||
1521 | * when writing. | ||
1522 | */ | ||
1523 | NInoClearSparse(ni); | ||
1524 | NInoClearEncrypted(ni); | ||
1525 | NInoClearCompressed(ni); | ||
1526 | ni->runlist.rl = rl; | 1529 | ni->runlist.rl = rl; |
1527 | write_lock_irqsave(&ni->size_lock, flags); | 1530 | write_lock_irqsave(&ni->size_lock, flags); |
1528 | ni->allocated_size = new_size; | 1531 | ni->allocated_size = new_size; |
1532 | if (NInoSparse(ni) || NInoCompressed(ni)) { | ||
1533 | ni->itype.compressed.size = ni->allocated_size; | ||
1534 | ni->itype.compressed.block_size = 1U << | ||
1535 | (a->data.non_resident.compression_unit + | ||
1536 | vol->cluster_size_bits); | ||
1537 | ni->itype.compressed.block_size_bits = | ||
1538 | ffs(ni->itype.compressed.block_size) - 1; | ||
1539 | ni->itype.compressed.block_clusters = 1U << | ||
1540 | a->data.non_resident.compression_unit; | ||
1541 | } | ||
1529 | write_unlock_irqrestore(&ni->size_lock, flags); | 1542 | write_unlock_irqrestore(&ni->size_lock, flags); |
1530 | /* | 1543 | /* |
1531 | * This needs to be last since the address space operations ->readpage | 1544 | * This needs to be last since the address space operations ->readpage |
@@ -1673,6 +1686,12 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val) | |||
1673 | BUG_ON(cnt < 0); | 1686 | BUG_ON(cnt < 0); |
1674 | if (!cnt) | 1687 | if (!cnt) |
1675 | goto done; | 1688 | goto done; |
1689 | /* | ||
1690 | * FIXME: Compressed and encrypted attributes are not supported when | ||
1691 | * writing and we should never have gotten here for them. | ||
1692 | */ | ||
1693 | BUG_ON(NInoCompressed(ni)); | ||
1694 | BUG_ON(NInoEncrypted(ni)); | ||
1676 | mapping = VFS_I(ni)->i_mapping; | 1695 | mapping = VFS_I(ni)->i_mapping; |
1677 | /* Work out the starting index and page offset. */ | 1696 | /* Work out the starting index and page offset. */ |
1678 | idx = ofs >> PAGE_CACHE_SHIFT; | 1697 | idx = ofs >> PAGE_CACHE_SHIFT; |