diff options
author | Anton Altaparmakov <aia21@cantab.net> | 2006-02-24 05:32:33 -0500 |
---|---|---|
committer | Anton Altaparmakov <aia21@cantab.net> | 2006-02-24 05:32:33 -0500 |
commit | 78af34f03d33d2ba179c9d35685860170b94a285 (patch) | |
tree | dc41d99f07193a581e7dd3734671c3854aa185eb /fs | |
parent | 7b875affd49fbc8978a1a898a0a80ebfff11f8c6 (diff) |
NTFS: Implement support for sector sizes above 512 bytes (up to the maximum
supported by NTFS which is 4096 bytes).
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ntfs/ChangeLog | 6 | ||||
-rw-r--r-- | fs/ntfs/aops.c | 18 | ||||
-rw-r--r-- | fs/ntfs/file.c | 8 | ||||
-rw-r--r-- | fs/ntfs/mft.c | 8 | ||||
-rw-r--r-- | fs/ntfs/super.c | 151 |
5 files changed, 121 insertions, 70 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 4a62201e8441..e66b4ac2fade 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -21,8 +21,14 @@ ToDo/Notes: | |||
21 | 21 | ||
22 | 2.1.26 - Minor bug fixes and updates. | 22 | 2.1.26 - Minor bug fixes and updates. |
23 | 23 | ||
24 | - Fix a potential overflow in file.c where a cast to s64 was missing in | ||
25 | a left shift of a page index. | ||
26 | - The struct inode has had its i_sem semaphore changed to a mutex named | ||
27 | i_mutex. | ||
24 | - We have struct kmem_cache now so use it instead of the typedef | 28 | - We have struct kmem_cache now so use it instead of the typedef |
25 | kmem_cache_t. (Pekka Enberg) | 29 | kmem_cache_t. (Pekka Enberg) |
30 | - Implement support for sector sizes above 512 bytes (up to the maximum | ||
31 | supported by NTFS which is 4096 bytes). | ||
26 | - Miscellaneous updates to layout.h. | 32 | - Miscellaneous updates to layout.h. |
27 | - Cope with attribute list attribute having invalid flags. Windows | 33 | - Cope with attribute list attribute having invalid flags. Windows |
28 | copes with this and even chkdsk does not detect or fix this so we | 34 | copes with this and even chkdsk does not detect or fix this so we |
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 1c0a4315876a..7e361da770b3 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * aops.c - NTFS kernel address space operations and page cache handling. | 2 | * aops.c - NTFS kernel address space operations and page cache handling. |
3 | * Part of the Linux-NTFS project. | 3 | * Part of the Linux-NTFS project. |
4 | * | 4 | * |
5 | * Copyright (c) 2001-2005 Anton Altaparmakov | 5 | * Copyright (c) 2001-2006 Anton Altaparmakov |
6 | * Copyright (c) 2002 Richard Russon | 6 | * Copyright (c) 2002 Richard Russon |
7 | * | 7 | * |
8 | * This program/include file is free software; you can redistribute it and/or | 8 | * This program/include file is free software; you can redistribute it and/or |
@@ -200,8 +200,8 @@ static int ntfs_read_block(struct page *page) | |||
200 | /* $MFT/$DATA must have its complete runlist in memory at all times. */ | 200 | /* $MFT/$DATA must have its complete runlist in memory at all times. */ |
201 | BUG_ON(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni)); | 201 | BUG_ON(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni)); |
202 | 202 | ||
203 | blocksize_bits = VFS_I(ni)->i_blkbits; | 203 | blocksize = vol->sb->s_blocksize; |
204 | blocksize = 1 << blocksize_bits; | 204 | blocksize_bits = vol->sb->s_blocksize_bits; |
205 | 205 | ||
206 | if (!page_has_buffers(page)) { | 206 | if (!page_has_buffers(page)) { |
207 | create_empty_buffers(page, blocksize, 0); | 207 | create_empty_buffers(page, blocksize, 0); |
@@ -569,10 +569,8 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc) | |||
569 | 569 | ||
570 | BUG_ON(!NInoNonResident(ni)); | 570 | BUG_ON(!NInoNonResident(ni)); |
571 | BUG_ON(NInoMstProtected(ni)); | 571 | BUG_ON(NInoMstProtected(ni)); |
572 | 572 | blocksize = vol->sb->s_blocksize; | |
573 | blocksize_bits = vi->i_blkbits; | 573 | blocksize_bits = vol->sb->s_blocksize_bits; |
574 | blocksize = 1 << blocksize_bits; | ||
575 | |||
576 | if (!page_has_buffers(page)) { | 574 | if (!page_has_buffers(page)) { |
577 | BUG_ON(!PageUptodate(page)); | 575 | BUG_ON(!PageUptodate(page)); |
578 | create_empty_buffers(page, blocksize, | 576 | create_empty_buffers(page, blocksize, |
@@ -949,8 +947,8 @@ static int ntfs_write_mst_block(struct page *page, | |||
949 | */ | 947 | */ |
950 | BUG_ON(!(is_mft || S_ISDIR(vi->i_mode) || | 948 | BUG_ON(!(is_mft || S_ISDIR(vi->i_mode) || |
951 | (NInoAttr(ni) && ni->type == AT_INDEX_ALLOCATION))); | 949 | (NInoAttr(ni) && ni->type == AT_INDEX_ALLOCATION))); |
952 | bh_size_bits = vi->i_blkbits; | 950 | bh_size = vol->sb->s_blocksize; |
953 | bh_size = 1 << bh_size_bits; | 951 | bh_size_bits = vol->sb->s_blocksize_bits; |
954 | max_bhs = PAGE_CACHE_SIZE / bh_size; | 952 | max_bhs = PAGE_CACHE_SIZE / bh_size; |
955 | BUG_ON(!max_bhs); | 953 | BUG_ON(!max_bhs); |
956 | BUG_ON(max_bhs > MAX_BUF_PER_PAGE); | 954 | BUG_ON(max_bhs > MAX_BUF_PER_PAGE); |
@@ -1596,7 +1594,7 @@ void mark_ntfs_record_dirty(struct page *page, const unsigned int ofs) { | |||
1596 | 1594 | ||
1597 | BUG_ON(!PageUptodate(page)); | 1595 | BUG_ON(!PageUptodate(page)); |
1598 | end = ofs + ni->itype.index.block_size; | 1596 | end = ofs + ni->itype.index.block_size; |
1599 | bh_size = 1 << VFS_I(ni)->i_blkbits; | 1597 | bh_size = VFS_I(ni)->i_sb->s_blocksize; |
1600 | spin_lock(&mapping->private_lock); | 1598 | spin_lock(&mapping->private_lock); |
1601 | if (unlikely(!page_has_buffers(page))) { | 1599 | if (unlikely(!page_has_buffers(page))) { |
1602 | spin_unlock(&mapping->private_lock); | 1600 | spin_unlock(&mapping->private_lock); |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 3a119a87686a..5027d3d1b3fe 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * file.c - NTFS kernel file operations. Part of the Linux-NTFS project. | 2 | * file.c - NTFS kernel file operations. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2005 Anton Altaparmakov | 4 | * Copyright (c) 2001-2006 Anton Altaparmakov |
5 | * | 5 | * |
6 | * This program/include file is free software; you can redistribute it and/or | 6 | * This program/include file is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as published | 7 | * modify it under the terms of the GNU General Public License as published |
@@ -529,8 +529,8 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages, | |||
529 | "index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%zx.", | 529 | "index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%zx.", |
530 | vi->i_ino, ni->type, pages[0]->index, nr_pages, | 530 | vi->i_ino, ni->type, pages[0]->index, nr_pages, |
531 | (long long)pos, bytes); | 531 | (long long)pos, bytes); |
532 | blocksize_bits = vi->i_blkbits; | 532 | blocksize = vol->sb->s_blocksize; |
533 | blocksize = 1 << blocksize_bits; | 533 | blocksize_bits = vol->sb->s_blocksize_bits; |
534 | u = 0; | 534 | u = 0; |
535 | do { | 535 | do { |
536 | struct page *page = pages[u]; | 536 | struct page *page = pages[u]; |
@@ -1525,7 +1525,7 @@ static inline int ntfs_commit_pages_after_non_resident_write( | |||
1525 | 1525 | ||
1526 | vi = pages[0]->mapping->host; | 1526 | vi = pages[0]->mapping->host; |
1527 | ni = NTFS_I(vi); | 1527 | ni = NTFS_I(vi); |
1528 | blocksize = 1 << vi->i_blkbits; | 1528 | blocksize = vi->i_sb->s_blocksize; |
1529 | end = pos + bytes; | 1529 | end = pos + bytes; |
1530 | u = 0; | 1530 | u = 0; |
1531 | do { | 1531 | do { |
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 0c65cbb8c5cf..6499aafc2258 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-2005 Anton Altaparmakov | 4 | * Copyright (c) 2001-2006 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 |
@@ -473,7 +473,7 @@ int ntfs_sync_mft_mirror(ntfs_volume *vol, const unsigned long mft_no, | |||
473 | runlist_element *rl; | 473 | runlist_element *rl; |
474 | unsigned int block_start, block_end, m_start, m_end, page_ofs; | 474 | unsigned int block_start, block_end, m_start, m_end, page_ofs; |
475 | int i_bhs, nr_bhs, err = 0; | 475 | int i_bhs, nr_bhs, err = 0; |
476 | unsigned char blocksize_bits = vol->mftmirr_ino->i_blkbits; | 476 | unsigned char blocksize_bits = vol->sb->s_blocksize_bits; |
477 | 477 | ||
478 | ntfs_debug("Entering for inode 0x%lx.", mft_no); | 478 | ntfs_debug("Entering for inode 0x%lx.", mft_no); |
479 | BUG_ON(!max_bhs); | 479 | BUG_ON(!max_bhs); |
@@ -672,8 +672,8 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync) | |||
672 | { | 672 | { |
673 | ntfs_volume *vol = ni->vol; | 673 | ntfs_volume *vol = ni->vol; |
674 | struct page *page = ni->page; | 674 | struct page *page = ni->page; |
675 | unsigned char blocksize_bits = vol->mft_ino->i_blkbits; | 675 | unsigned int blocksize = vol->sb->s_blocksize; |
676 | unsigned int blocksize = 1 << blocksize_bits; | 676 | unsigned char blocksize_bits = vol->sb->s_blocksize_bits; |
677 | int max_bhs = vol->mft_record_size / blocksize; | 677 | int max_bhs = vol->mft_record_size / blocksize; |
678 | struct buffer_head *bhs[max_bhs]; | 678 | struct buffer_head *bhs[max_bhs]; |
679 | struct buffer_head *bh, *head; | 679 | struct buffer_head *bh, *head; |
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index e9c0d80dfab1..489f7049146b 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * super.c - NTFS kernel super block handling. Part of the Linux-NTFS project. | 2 | * super.c - NTFS kernel super block handling. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2005 Anton Altaparmakov | 4 | * Copyright (c) 2001-2006 Anton Altaparmakov |
5 | * Copyright (c) 2001,2002 Richard Russon | 5 | * Copyright (c) 2001,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 |
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/stddef.h> | 23 | #include <linux/stddef.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/slab.h> | ||
25 | #include <linux/string.h> | 26 | #include <linux/string.h> |
26 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
27 | #include <linux/blkdev.h> /* For bdev_hardsect_size(). */ | 28 | #include <linux/blkdev.h> /* For bdev_hardsect_size(). */ |
@@ -641,7 +642,7 @@ static struct buffer_head *read_ntfs_boot_sector(struct super_block *sb, | |||
641 | { | 642 | { |
642 | const char *read_err_str = "Unable to read %s boot sector."; | 643 | const char *read_err_str = "Unable to read %s boot sector."; |
643 | struct buffer_head *bh_primary, *bh_backup; | 644 | struct buffer_head *bh_primary, *bh_backup; |
644 | long nr_blocks = NTFS_SB(sb)->nr_blocks; | 645 | sector_t nr_blocks = NTFS_SB(sb)->nr_blocks; |
645 | 646 | ||
646 | /* Try to read primary boot sector. */ | 647 | /* Try to read primary boot sector. */ |
647 | if ((bh_primary = sb_bread(sb, 0))) { | 648 | if ((bh_primary = sb_bread(sb, 0))) { |
@@ -688,13 +689,18 @@ hotfix_primary_boot_sector: | |||
688 | /* | 689 | /* |
689 | * If we managed to read sector zero and the volume is not | 690 | * If we managed to read sector zero and the volume is not |
690 | * read-only, copy the found, valid backup boot sector to the | 691 | * read-only, copy the found, valid backup boot sector to the |
691 | * primary boot sector. | 692 | * primary boot sector. Note we only copy the actual boot |
693 | * sector structure, not the actual whole device sector as that | ||
694 | * may be bigger and would potentially damage the $Boot system | ||
695 | * file (FIXME: Would be nice to know if the backup boot sector | ||
696 | * on a large sector device contains the whole boot loader or | ||
697 | * just the first 512 bytes). | ||
692 | */ | 698 | */ |
693 | if (!(sb->s_flags & MS_RDONLY)) { | 699 | if (!(sb->s_flags & MS_RDONLY)) { |
694 | ntfs_warning(sb, "Hot-fix: Recovering invalid primary " | 700 | ntfs_warning(sb, "Hot-fix: Recovering invalid primary " |
695 | "boot sector from backup copy."); | 701 | "boot sector from backup copy."); |
696 | memcpy(bh_primary->b_data, bh_backup->b_data, | 702 | memcpy(bh_primary->b_data, bh_backup->b_data, |
697 | sb->s_blocksize); | 703 | NTFS_BLOCK_SIZE); |
698 | mark_buffer_dirty(bh_primary); | 704 | mark_buffer_dirty(bh_primary); |
699 | sync_dirty_buffer(bh_primary); | 705 | sync_dirty_buffer(bh_primary); |
700 | if (buffer_uptodate(bh_primary)) { | 706 | if (buffer_uptodate(bh_primary)) { |
@@ -733,9 +739,13 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b) | |||
733 | vol->sector_size); | 739 | vol->sector_size); |
734 | ntfs_debug("vol->sector_size_bits = %i (0x%x)", vol->sector_size_bits, | 740 | ntfs_debug("vol->sector_size_bits = %i (0x%x)", vol->sector_size_bits, |
735 | vol->sector_size_bits); | 741 | vol->sector_size_bits); |
736 | if (vol->sector_size != vol->sb->s_blocksize) | 742 | if (vol->sector_size < vol->sb->s_blocksize) { |
737 | ntfs_warning(vol->sb, "The boot sector indicates a sector size " | 743 | ntfs_error(vol->sb, "Sector size (%i) is smaller than the " |
738 | "different from the device sector size."); | 744 | "device block size (%lu). This is not " |
745 | "supported. Sorry.", vol->sector_size, | ||
746 | vol->sb->s_blocksize); | ||
747 | return FALSE; | ||
748 | } | ||
739 | ntfs_debug("sectors_per_cluster = 0x%x", b->bpb.sectors_per_cluster); | 749 | ntfs_debug("sectors_per_cluster = 0x%x", b->bpb.sectors_per_cluster); |
740 | sectors_per_cluster_bits = ffs(b->bpb.sectors_per_cluster) - 1; | 750 | sectors_per_cluster_bits = ffs(b->bpb.sectors_per_cluster) - 1; |
741 | ntfs_debug("sectors_per_cluster_bits = 0x%x", | 751 | ntfs_debug("sectors_per_cluster_bits = 0x%x", |
@@ -748,16 +758,11 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b) | |||
748 | ntfs_debug("vol->cluster_size = %i (0x%x)", vol->cluster_size, | 758 | ntfs_debug("vol->cluster_size = %i (0x%x)", vol->cluster_size, |
749 | vol->cluster_size); | 759 | vol->cluster_size); |
750 | ntfs_debug("vol->cluster_size_mask = 0x%x", vol->cluster_size_mask); | 760 | ntfs_debug("vol->cluster_size_mask = 0x%x", vol->cluster_size_mask); |
751 | ntfs_debug("vol->cluster_size_bits = %i (0x%x)", | 761 | ntfs_debug("vol->cluster_size_bits = %i", vol->cluster_size_bits); |
752 | vol->cluster_size_bits, vol->cluster_size_bits); | 762 | if (vol->cluster_size < vol->sector_size) { |
753 | if (vol->sector_size > vol->cluster_size) { | 763 | ntfs_error(vol->sb, "Cluster size (%i) is smaller than the " |
754 | ntfs_error(vol->sb, "Sector sizes above the cluster size are " | 764 | "sector size (%i). This is not supported. " |
755 | "not supported. Sorry."); | 765 | "Sorry.", vol->cluster_size, vol->sector_size); |
756 | return FALSE; | ||
757 | } | ||
758 | if (vol->sb->s_blocksize > vol->cluster_size) { | ||
759 | ntfs_error(vol->sb, "Cluster sizes smaller than the device " | ||
760 | "sector size are not supported. Sorry."); | ||
761 | return FALSE; | 766 | return FALSE; |
762 | } | 767 | } |
763 | clusters_per_mft_record = b->clusters_per_mft_record; | 768 | clusters_per_mft_record = b->clusters_per_mft_record; |
@@ -786,11 +791,18 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b) | |||
786 | * we store $MFT/$DATA, the table of mft records in the page cache. | 791 | * we store $MFT/$DATA, the table of mft records in the page cache. |
787 | */ | 792 | */ |
788 | if (vol->mft_record_size > PAGE_CACHE_SIZE) { | 793 | if (vol->mft_record_size > PAGE_CACHE_SIZE) { |
789 | ntfs_error(vol->sb, "Mft record size %i (0x%x) exceeds the " | 794 | ntfs_error(vol->sb, "Mft record size (%i) exceeds the " |
790 | "page cache size on your system %lu (0x%lx). " | 795 | "PAGE_CACHE_SIZE on your system (%lu). " |
791 | "This is not supported. Sorry.", | 796 | "This is not supported. Sorry.", |
792 | vol->mft_record_size, vol->mft_record_size, | 797 | vol->mft_record_size, PAGE_CACHE_SIZE); |
793 | PAGE_CACHE_SIZE, PAGE_CACHE_SIZE); | 798 | return FALSE; |
799 | } | ||
800 | /* We cannot support mft record sizes below the sector size. */ | ||
801 | if (vol->mft_record_size < vol->sector_size) { | ||
802 | ntfs_error(vol->sb, "Mft record size (%i) is smaller than the " | ||
803 | "sector size (%i). This is not supported. " | ||
804 | "Sorry.", vol->mft_record_size, | ||
805 | vol->sector_size); | ||
794 | return FALSE; | 806 | return FALSE; |
795 | } | 807 | } |
796 | clusters_per_index_record = b->clusters_per_index_record; | 808 | clusters_per_index_record = b->clusters_per_index_record; |
@@ -816,6 +828,14 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b) | |||
816 | ntfs_debug("vol->index_record_size_bits = %i (0x%x)", | 828 | ntfs_debug("vol->index_record_size_bits = %i (0x%x)", |
817 | vol->index_record_size_bits, | 829 | vol->index_record_size_bits, |
818 | vol->index_record_size_bits); | 830 | vol->index_record_size_bits); |
831 | /* We cannot support index record sizes below the sector size. */ | ||
832 | if (vol->index_record_size < vol->sector_size) { | ||
833 | ntfs_error(vol->sb, "Index record size (%i) is smaller than " | ||
834 | "the sector size (%i). This is not " | ||
835 | "supported. Sorry.", vol->index_record_size, | ||
836 | vol->sector_size); | ||
837 | return FALSE; | ||
838 | } | ||
819 | /* | 839 | /* |
820 | * Get the size of the volume in clusters and check for 64-bit-ness. | 840 | * Get the size of the volume in clusters and check for 64-bit-ness. |
821 | * Windows currently only uses 32 bits to save the clusters so we do | 841 | * Windows currently only uses 32 bits to save the clusters so we do |
@@ -845,15 +865,18 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b) | |||
845 | } | 865 | } |
846 | ll = sle64_to_cpu(b->mft_lcn); | 866 | ll = sle64_to_cpu(b->mft_lcn); |
847 | if (ll >= vol->nr_clusters) { | 867 | if (ll >= vol->nr_clusters) { |
848 | ntfs_error(vol->sb, "MFT LCN is beyond end of volume. Weird."); | 868 | ntfs_error(vol->sb, "MFT LCN (%lli, 0x%llx) is beyond end of " |
869 | "volume. Weird.", (unsigned long long)ll, | ||
870 | (unsigned long long)ll); | ||
849 | return FALSE; | 871 | return FALSE; |
850 | } | 872 | } |
851 | vol->mft_lcn = ll; | 873 | vol->mft_lcn = ll; |
852 | ntfs_debug("vol->mft_lcn = 0x%llx", (long long)vol->mft_lcn); | 874 | ntfs_debug("vol->mft_lcn = 0x%llx", (long long)vol->mft_lcn); |
853 | ll = sle64_to_cpu(b->mftmirr_lcn); | 875 | ll = sle64_to_cpu(b->mftmirr_lcn); |
854 | if (ll >= vol->nr_clusters) { | 876 | if (ll >= vol->nr_clusters) { |
855 | ntfs_error(vol->sb, "MFTMirr LCN is beyond end of volume. " | 877 | ntfs_error(vol->sb, "MFTMirr LCN (%lli, 0x%llx) is beyond end " |
856 | "Weird."); | 878 | "of volume. Weird.", (unsigned long long)ll, |
879 | (unsigned long long)ll); | ||
857 | return FALSE; | 880 | return FALSE; |
858 | } | 881 | } |
859 | vol->mftmirr_lcn = ll; | 882 | vol->mftmirr_lcn = ll; |
@@ -2685,7 +2708,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2685 | ntfs_volume *vol; | 2708 | ntfs_volume *vol; |
2686 | struct buffer_head *bh; | 2709 | struct buffer_head *bh; |
2687 | struct inode *tmp_ino; | 2710 | struct inode *tmp_ino; |
2688 | int result; | 2711 | int blocksize, result; |
2689 | 2712 | ||
2690 | ntfs_debug("Entering."); | 2713 | ntfs_debug("Entering."); |
2691 | #ifndef NTFS_RW | 2714 | #ifndef NTFS_RW |
@@ -2724,60 +2747,85 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2724 | if (!parse_options(vol, (char*)opt)) | 2747 | if (!parse_options(vol, (char*)opt)) |
2725 | goto err_out_now; | 2748 | goto err_out_now; |
2726 | 2749 | ||
2750 | /* We support sector sizes up to the PAGE_CACHE_SIZE. */ | ||
2751 | if (bdev_hardsect_size(sb->s_bdev) > PAGE_CACHE_SIZE) { | ||
2752 | if (!silent) | ||
2753 | ntfs_error(sb, "Device has unsupported sector size " | ||
2754 | "(%i). The maximum supported sector " | ||
2755 | "size on this architecture is %lu " | ||
2756 | "bytes.", | ||
2757 | bdev_hardsect_size(sb->s_bdev), | ||
2758 | PAGE_CACHE_SIZE); | ||
2759 | goto err_out_now; | ||
2760 | } | ||
2727 | /* | 2761 | /* |
2728 | * TODO: Fail safety check. In the future we should really be able to | 2762 | * Setup the device access block size to NTFS_BLOCK_SIZE or the hard |
2729 | * cope with this being the case, but for now just bail out. | 2763 | * sector size, whichever is bigger. |
2730 | */ | 2764 | */ |
2731 | if (bdev_hardsect_size(sb->s_bdev) > NTFS_BLOCK_SIZE) { | 2765 | blocksize = sb_min_blocksize(sb, NTFS_BLOCK_SIZE); |
2766 | if (blocksize < NTFS_BLOCK_SIZE) { | ||
2732 | if (!silent) | 2767 | if (!silent) |
2733 | ntfs_error(sb, "Device has unsupported hardsect_size."); | 2768 | ntfs_error(sb, "Unable to set device block size."); |
2734 | goto err_out_now; | 2769 | goto err_out_now; |
2735 | } | 2770 | } |
2736 | 2771 | BUG_ON(blocksize != sb->s_blocksize); | |
2737 | /* Setup the device access block size to NTFS_BLOCK_SIZE. */ | 2772 | ntfs_debug("Set device block size to %i bytes (block size bits %i).", |
2738 | if (sb_set_blocksize(sb, NTFS_BLOCK_SIZE) != NTFS_BLOCK_SIZE) { | 2773 | blocksize, sb->s_blocksize_bits); |
2774 | /* Determine the size of the device in units of block_size bytes. */ | ||
2775 | if (!i_size_read(sb->s_bdev->bd_inode)) { | ||
2739 | if (!silent) | 2776 | if (!silent) |
2740 | ntfs_error(sb, "Unable to set block size."); | 2777 | ntfs_error(sb, "Unable to determine device size."); |
2741 | goto err_out_now; | 2778 | goto err_out_now; |
2742 | } | 2779 | } |
2743 | |||
2744 | /* Get the size of the device in units of NTFS_BLOCK_SIZE bytes. */ | ||
2745 | vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >> | 2780 | vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >> |
2746 | NTFS_BLOCK_SIZE_BITS; | 2781 | sb->s_blocksize_bits; |
2747 | |||
2748 | /* Read the boot sector and return unlocked buffer head to it. */ | 2782 | /* Read the boot sector and return unlocked buffer head to it. */ |
2749 | if (!(bh = read_ntfs_boot_sector(sb, silent))) { | 2783 | if (!(bh = read_ntfs_boot_sector(sb, silent))) { |
2750 | if (!silent) | 2784 | if (!silent) |
2751 | ntfs_error(sb, "Not an NTFS volume."); | 2785 | ntfs_error(sb, "Not an NTFS volume."); |
2752 | goto err_out_now; | 2786 | goto err_out_now; |
2753 | } | 2787 | } |
2754 | |||
2755 | /* | 2788 | /* |
2756 | * Extract the data from the boot sector and setup the ntfs super block | 2789 | * Extract the data from the boot sector and setup the ntfs volume |
2757 | * using it. | 2790 | * using it. |
2758 | */ | 2791 | */ |
2759 | result = parse_ntfs_boot_sector(vol, (NTFS_BOOT_SECTOR*)bh->b_data); | 2792 | result = parse_ntfs_boot_sector(vol, (NTFS_BOOT_SECTOR*)bh->b_data); |
2760 | |||
2761 | /* Initialize the cluster and mft allocators. */ | ||
2762 | ntfs_setup_allocators(vol); | ||
2763 | |||
2764 | brelse(bh); | 2793 | brelse(bh); |
2765 | |||
2766 | if (!result) { | 2794 | if (!result) { |
2767 | if (!silent) | 2795 | if (!silent) |
2768 | ntfs_error(sb, "Unsupported NTFS filesystem."); | 2796 | ntfs_error(sb, "Unsupported NTFS filesystem."); |
2769 | goto err_out_now; | 2797 | goto err_out_now; |
2770 | } | 2798 | } |
2771 | |||
2772 | /* | 2799 | /* |
2773 | * TODO: When we start coping with sector sizes different from | 2800 | * If the boot sector indicates a sector size bigger than the current |
2774 | * NTFS_BLOCK_SIZE, we now probably need to set the blocksize of the | 2801 | * device block size, switch the device block size to the sector size. |
2775 | * device (probably to NTFS_BLOCK_SIZE). | 2802 | * TODO: It may be possible to support this case even when the set |
2803 | * below fails, we would just be breaking up the i/o for each sector | ||
2804 | * into multiple blocks for i/o purposes but otherwise it should just | ||
2805 | * work. However it is safer to leave disabled until someone hits this | ||
2806 | * error message and then we can get them to try it without the setting | ||
2807 | * so we know for sure that it works. | ||
2776 | */ | 2808 | */ |
2777 | 2809 | if (vol->sector_size > blocksize) { | |
2810 | blocksize = sb_set_blocksize(sb, vol->sector_size); | ||
2811 | if (blocksize != vol->sector_size) { | ||
2812 | if (!silent) | ||
2813 | ntfs_error(sb, "Unable to set device block " | ||
2814 | "size to sector size (%i).", | ||
2815 | vol->sector_size); | ||
2816 | goto err_out_now; | ||
2817 | } | ||
2818 | BUG_ON(blocksize != sb->s_blocksize); | ||
2819 | vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >> | ||
2820 | sb->s_blocksize_bits; | ||
2821 | ntfs_debug("Changed device block size to %i bytes (block size " | ||
2822 | "bits %i) to match volume sector size.", | ||
2823 | blocksize, sb->s_blocksize_bits); | ||
2824 | } | ||
2825 | /* Initialize the cluster and mft allocators. */ | ||
2826 | ntfs_setup_allocators(vol); | ||
2778 | /* Setup remaining fields in the super block. */ | 2827 | /* Setup remaining fields in the super block. */ |
2779 | sb->s_magic = NTFS_SB_MAGIC; | 2828 | sb->s_magic = NTFS_SB_MAGIC; |
2780 | |||
2781 | /* | 2829 | /* |
2782 | * Ntfs allows 63 bits for the file size, i.e. correct would be: | 2830 | * Ntfs allows 63 bits for the file size, i.e. correct would be: |
2783 | * sb->s_maxbytes = ~0ULL >> 1; | 2831 | * sb->s_maxbytes = ~0ULL >> 1; |
@@ -2787,9 +2835,8 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2787 | * without overflowing the index or to 2^63 - 1, whichever is smaller. | 2835 | * without overflowing the index or to 2^63 - 1, whichever is smaller. |
2788 | */ | 2836 | */ |
2789 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 2837 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
2790 | 2838 | /* Ntfs measures time in 100ns intervals. */ | |
2791 | sb->s_time_gran = 100; | 2839 | sb->s_time_gran = 100; |
2792 | |||
2793 | /* | 2840 | /* |
2794 | * Now load the metadata required for the page cache and our address | 2841 | * Now load the metadata required for the page cache and our address |
2795 | * space operations to function. We do this by setting up a specialised | 2842 | * space operations to function. We do this by setting up a specialised |