mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-10 15:58:47 +00:00
NTFS: Implement support for sector sizes above 512 bytes (up to the maximum
supported by NTFS which is 4096 bytes).
This commit is contained in:
parent
7b875affd4
commit
78af34f03d
@ -21,8 +21,14 @@ ToDo/Notes:
|
|||||||
|
|
||||||
2.1.26 - Minor bug fixes and updates.
|
2.1.26 - Minor bug fixes and updates.
|
||||||
|
|
||||||
|
- Fix a potential overflow in file.c where a cast to s64 was missing in
|
||||||
|
a left shift of a page index.
|
||||||
|
- The struct inode has had its i_sem semaphore changed to a mutex named
|
||||||
|
i_mutex.
|
||||||
- We have struct kmem_cache now so use it instead of the typedef
|
- We have struct kmem_cache now so use it instead of the typedef
|
||||||
kmem_cache_t. (Pekka Enberg)
|
kmem_cache_t. (Pekka Enberg)
|
||||||
|
- Implement support for sector sizes above 512 bytes (up to the maximum
|
||||||
|
supported by NTFS which is 4096 bytes).
|
||||||
- Miscellaneous updates to layout.h.
|
- Miscellaneous updates to layout.h.
|
||||||
- Cope with attribute list attribute having invalid flags. Windows
|
- Cope with attribute list attribute having invalid flags. Windows
|
||||||
copes with this and even chkdsk does not detect or fix this so we
|
copes with this and even chkdsk does not detect or fix this so we
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* aops.c - NTFS kernel address space operations and page cache handling.
|
* aops.c - NTFS kernel address space operations and page cache handling.
|
||||||
* Part of the Linux-NTFS project.
|
* Part of the Linux-NTFS project.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2001-2005 Anton Altaparmakov
|
* Copyright (c) 2001-2006 Anton Altaparmakov
|
||||||
* Copyright (c) 2002 Richard Russon
|
* Copyright (c) 2002 Richard Russon
|
||||||
*
|
*
|
||||||
* This program/include file is free software; you can redistribute it and/or
|
* 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)
|
|||||||
/* $MFT/$DATA must have its complete runlist in memory at all times. */
|
/* $MFT/$DATA must have its complete runlist in memory at all times. */
|
||||||
BUG_ON(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni));
|
BUG_ON(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni));
|
||||||
|
|
||||||
blocksize_bits = VFS_I(ni)->i_blkbits;
|
blocksize = vol->sb->s_blocksize;
|
||||||
blocksize = 1 << blocksize_bits;
|
blocksize_bits = vol->sb->s_blocksize_bits;
|
||||||
|
|
||||||
if (!page_has_buffers(page)) {
|
if (!page_has_buffers(page)) {
|
||||||
create_empty_buffers(page, blocksize, 0);
|
create_empty_buffers(page, blocksize, 0);
|
||||||
@ -569,10 +569,8 @@ static int ntfs_write_block(struct page *page, struct writeback_control *wbc)
|
|||||||
|
|
||||||
BUG_ON(!NInoNonResident(ni));
|
BUG_ON(!NInoNonResident(ni));
|
||||||
BUG_ON(NInoMstProtected(ni));
|
BUG_ON(NInoMstProtected(ni));
|
||||||
|
blocksize = vol->sb->s_blocksize;
|
||||||
blocksize_bits = vi->i_blkbits;
|
blocksize_bits = vol->sb->s_blocksize_bits;
|
||||||
blocksize = 1 << blocksize_bits;
|
|
||||||
|
|
||||||
if (!page_has_buffers(page)) {
|
if (!page_has_buffers(page)) {
|
||||||
BUG_ON(!PageUptodate(page));
|
BUG_ON(!PageUptodate(page));
|
||||||
create_empty_buffers(page, blocksize,
|
create_empty_buffers(page, blocksize,
|
||||||
@ -949,8 +947,8 @@ static int ntfs_write_mst_block(struct page *page,
|
|||||||
*/
|
*/
|
||||||
BUG_ON(!(is_mft || S_ISDIR(vi->i_mode) ||
|
BUG_ON(!(is_mft || S_ISDIR(vi->i_mode) ||
|
||||||
(NInoAttr(ni) && ni->type == AT_INDEX_ALLOCATION)));
|
(NInoAttr(ni) && ni->type == AT_INDEX_ALLOCATION)));
|
||||||
bh_size_bits = vi->i_blkbits;
|
bh_size = vol->sb->s_blocksize;
|
||||||
bh_size = 1 << bh_size_bits;
|
bh_size_bits = vol->sb->s_blocksize_bits;
|
||||||
max_bhs = PAGE_CACHE_SIZE / bh_size;
|
max_bhs = PAGE_CACHE_SIZE / bh_size;
|
||||||
BUG_ON(!max_bhs);
|
BUG_ON(!max_bhs);
|
||||||
BUG_ON(max_bhs > MAX_BUF_PER_PAGE);
|
BUG_ON(max_bhs > MAX_BUF_PER_PAGE);
|
||||||
@ -1596,7 +1594,7 @@ void mark_ntfs_record_dirty(struct page *page, const unsigned int ofs) {
|
|||||||
|
|
||||||
BUG_ON(!PageUptodate(page));
|
BUG_ON(!PageUptodate(page));
|
||||||
end = ofs + ni->itype.index.block_size;
|
end = ofs + ni->itype.index.block_size;
|
||||||
bh_size = 1 << VFS_I(ni)->i_blkbits;
|
bh_size = VFS_I(ni)->i_sb->s_blocksize;
|
||||||
spin_lock(&mapping->private_lock);
|
spin_lock(&mapping->private_lock);
|
||||||
if (unlikely(!page_has_buffers(page))) {
|
if (unlikely(!page_has_buffers(page))) {
|
||||||
spin_unlock(&mapping->private_lock);
|
spin_unlock(&mapping->private_lock);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* file.c - NTFS kernel file operations. Part of the Linux-NTFS project.
|
* file.c - NTFS kernel file operations. Part of the Linux-NTFS project.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2001-2005 Anton Altaparmakov
|
* Copyright (c) 2001-2006 Anton Altaparmakov
|
||||||
*
|
*
|
||||||
* This program/include file is free software; you can redistribute it and/or
|
* This program/include file is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as published
|
* 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,
|
|||||||
"index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%zx.",
|
"index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%zx.",
|
||||||
vi->i_ino, ni->type, pages[0]->index, nr_pages,
|
vi->i_ino, ni->type, pages[0]->index, nr_pages,
|
||||||
(long long)pos, bytes);
|
(long long)pos, bytes);
|
||||||
blocksize_bits = vi->i_blkbits;
|
blocksize = vol->sb->s_blocksize;
|
||||||
blocksize = 1 << blocksize_bits;
|
blocksize_bits = vol->sb->s_blocksize_bits;
|
||||||
u = 0;
|
u = 0;
|
||||||
do {
|
do {
|
||||||
struct page *page = pages[u];
|
struct page *page = pages[u];
|
||||||
@ -1525,7 +1525,7 @@ static inline int ntfs_commit_pages_after_non_resident_write(
|
|||||||
|
|
||||||
vi = pages[0]->mapping->host;
|
vi = pages[0]->mapping->host;
|
||||||
ni = NTFS_I(vi);
|
ni = NTFS_I(vi);
|
||||||
blocksize = 1 << vi->i_blkbits;
|
blocksize = vi->i_sb->s_blocksize;
|
||||||
end = pos + bytes;
|
end = pos + bytes;
|
||||||
u = 0;
|
u = 0;
|
||||||
do {
|
do {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project.
|
* mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2001-2005 Anton Altaparmakov
|
* Copyright (c) 2001-2006 Anton Altaparmakov
|
||||||
* Copyright (c) 2002 Richard Russon
|
* Copyright (c) 2002 Richard Russon
|
||||||
*
|
*
|
||||||
* This program/include file is free software; you can redistribute it and/or
|
* 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,
|
|||||||
runlist_element *rl;
|
runlist_element *rl;
|
||||||
unsigned int block_start, block_end, m_start, m_end, page_ofs;
|
unsigned int block_start, block_end, m_start, m_end, page_ofs;
|
||||||
int i_bhs, nr_bhs, err = 0;
|
int i_bhs, nr_bhs, err = 0;
|
||||||
unsigned char blocksize_bits = vol->mftmirr_ino->i_blkbits;
|
unsigned char blocksize_bits = vol->sb->s_blocksize_bits;
|
||||||
|
|
||||||
ntfs_debug("Entering for inode 0x%lx.", mft_no);
|
ntfs_debug("Entering for inode 0x%lx.", mft_no);
|
||||||
BUG_ON(!max_bhs);
|
BUG_ON(!max_bhs);
|
||||||
@ -672,8 +672,8 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync)
|
|||||||
{
|
{
|
||||||
ntfs_volume *vol = ni->vol;
|
ntfs_volume *vol = ni->vol;
|
||||||
struct page *page = ni->page;
|
struct page *page = ni->page;
|
||||||
unsigned char blocksize_bits = vol->mft_ino->i_blkbits;
|
unsigned int blocksize = vol->sb->s_blocksize;
|
||||||
unsigned int blocksize = 1 << blocksize_bits;
|
unsigned char blocksize_bits = vol->sb->s_blocksize_bits;
|
||||||
int max_bhs = vol->mft_record_size / blocksize;
|
int max_bhs = vol->mft_record_size / blocksize;
|
||||||
struct buffer_head *bhs[max_bhs];
|
struct buffer_head *bhs[max_bhs];
|
||||||
struct buffer_head *bh, *head;
|
struct buffer_head *bh, *head;
|
||||||
|
151
fs/ntfs/super.c
151
fs/ntfs/super.c
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* super.c - NTFS kernel super block handling. Part of the Linux-NTFS project.
|
* super.c - NTFS kernel super block handling. Part of the Linux-NTFS project.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2001-2005 Anton Altaparmakov
|
* Copyright (c) 2001-2006 Anton Altaparmakov
|
||||||
* Copyright (c) 2001,2002 Richard Russon
|
* Copyright (c) 2001,2002 Richard Russon
|
||||||
*
|
*
|
||||||
* This program/include file is free software; you can redistribute it and/or
|
* This program/include file is free software; you can redistribute it and/or
|
||||||
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <linux/stddef.h>
|
#include <linux/stddef.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/blkdev.h> /* For bdev_hardsect_size(). */
|
#include <linux/blkdev.h> /* For bdev_hardsect_size(). */
|
||||||
@ -641,7 +642,7 @@ static struct buffer_head *read_ntfs_boot_sector(struct super_block *sb,
|
|||||||
{
|
{
|
||||||
const char *read_err_str = "Unable to read %s boot sector.";
|
const char *read_err_str = "Unable to read %s boot sector.";
|
||||||
struct buffer_head *bh_primary, *bh_backup;
|
struct buffer_head *bh_primary, *bh_backup;
|
||||||
long nr_blocks = NTFS_SB(sb)->nr_blocks;
|
sector_t nr_blocks = NTFS_SB(sb)->nr_blocks;
|
||||||
|
|
||||||
/* Try to read primary boot sector. */
|
/* Try to read primary boot sector. */
|
||||||
if ((bh_primary = sb_bread(sb, 0))) {
|
if ((bh_primary = sb_bread(sb, 0))) {
|
||||||
@ -688,13 +689,18 @@ hotfix_primary_boot_sector:
|
|||||||
/*
|
/*
|
||||||
* If we managed to read sector zero and the volume is not
|
* If we managed to read sector zero and the volume is not
|
||||||
* read-only, copy the found, valid backup boot sector to the
|
* read-only, copy the found, valid backup boot sector to the
|
||||||
* primary boot sector.
|
* primary boot sector. Note we only copy the actual boot
|
||||||
|
* sector structure, not the actual whole device sector as that
|
||||||
|
* may be bigger and would potentially damage the $Boot system
|
||||||
|
* file (FIXME: Would be nice to know if the backup boot sector
|
||||||
|
* on a large sector device contains the whole boot loader or
|
||||||
|
* just the first 512 bytes).
|
||||||
*/
|
*/
|
||||||
if (!(sb->s_flags & MS_RDONLY)) {
|
if (!(sb->s_flags & MS_RDONLY)) {
|
||||||
ntfs_warning(sb, "Hot-fix: Recovering invalid primary "
|
ntfs_warning(sb, "Hot-fix: Recovering invalid primary "
|
||||||
"boot sector from backup copy.");
|
"boot sector from backup copy.");
|
||||||
memcpy(bh_primary->b_data, bh_backup->b_data,
|
memcpy(bh_primary->b_data, bh_backup->b_data,
|
||||||
sb->s_blocksize);
|
NTFS_BLOCK_SIZE);
|
||||||
mark_buffer_dirty(bh_primary);
|
mark_buffer_dirty(bh_primary);
|
||||||
sync_dirty_buffer(bh_primary);
|
sync_dirty_buffer(bh_primary);
|
||||||
if (buffer_uptodate(bh_primary)) {
|
if (buffer_uptodate(bh_primary)) {
|
||||||
@ -733,9 +739,13 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
|
|||||||
vol->sector_size);
|
vol->sector_size);
|
||||||
ntfs_debug("vol->sector_size_bits = %i (0x%x)", vol->sector_size_bits,
|
ntfs_debug("vol->sector_size_bits = %i (0x%x)", vol->sector_size_bits,
|
||||||
vol->sector_size_bits);
|
vol->sector_size_bits);
|
||||||
if (vol->sector_size != vol->sb->s_blocksize)
|
if (vol->sector_size < vol->sb->s_blocksize) {
|
||||||
ntfs_warning(vol->sb, "The boot sector indicates a sector size "
|
ntfs_error(vol->sb, "Sector size (%i) is smaller than the "
|
||||||
"different from the device sector size.");
|
"device block size (%lu). This is not "
|
||||||
|
"supported. Sorry.", vol->sector_size,
|
||||||
|
vol->sb->s_blocksize);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
ntfs_debug("sectors_per_cluster = 0x%x", b->bpb.sectors_per_cluster);
|
ntfs_debug("sectors_per_cluster = 0x%x", b->bpb.sectors_per_cluster);
|
||||||
sectors_per_cluster_bits = ffs(b->bpb.sectors_per_cluster) - 1;
|
sectors_per_cluster_bits = ffs(b->bpb.sectors_per_cluster) - 1;
|
||||||
ntfs_debug("sectors_per_cluster_bits = 0x%x",
|
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)
|
|||||||
ntfs_debug("vol->cluster_size = %i (0x%x)", vol->cluster_size,
|
ntfs_debug("vol->cluster_size = %i (0x%x)", vol->cluster_size,
|
||||||
vol->cluster_size);
|
vol->cluster_size);
|
||||||
ntfs_debug("vol->cluster_size_mask = 0x%x", vol->cluster_size_mask);
|
ntfs_debug("vol->cluster_size_mask = 0x%x", vol->cluster_size_mask);
|
||||||
ntfs_debug("vol->cluster_size_bits = %i (0x%x)",
|
ntfs_debug("vol->cluster_size_bits = %i", vol->cluster_size_bits);
|
||||||
vol->cluster_size_bits, vol->cluster_size_bits);
|
if (vol->cluster_size < vol->sector_size) {
|
||||||
if (vol->sector_size > vol->cluster_size) {
|
ntfs_error(vol->sb, "Cluster size (%i) is smaller than the "
|
||||||
ntfs_error(vol->sb, "Sector sizes above the cluster size are "
|
"sector size (%i). This is not supported. "
|
||||||
"not supported. Sorry.");
|
"Sorry.", vol->cluster_size, vol->sector_size);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (vol->sb->s_blocksize > vol->cluster_size) {
|
|
||||||
ntfs_error(vol->sb, "Cluster sizes smaller than the device "
|
|
||||||
"sector size are not supported. Sorry.");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
clusters_per_mft_record = b->clusters_per_mft_record;
|
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)
|
|||||||
* we store $MFT/$DATA, the table of mft records in the page cache.
|
* we store $MFT/$DATA, the table of mft records in the page cache.
|
||||||
*/
|
*/
|
||||||
if (vol->mft_record_size > PAGE_CACHE_SIZE) {
|
if (vol->mft_record_size > PAGE_CACHE_SIZE) {
|
||||||
ntfs_error(vol->sb, "Mft record size %i (0x%x) exceeds the "
|
ntfs_error(vol->sb, "Mft record size (%i) exceeds the "
|
||||||
"page cache size on your system %lu (0x%lx). "
|
"PAGE_CACHE_SIZE on your system (%lu). "
|
||||||
"This is not supported. Sorry.",
|
"This is not supported. Sorry.",
|
||||||
vol->mft_record_size, vol->mft_record_size,
|
vol->mft_record_size, PAGE_CACHE_SIZE);
|
||||||
PAGE_CACHE_SIZE, PAGE_CACHE_SIZE);
|
return FALSE;
|
||||||
|
}
|
||||||
|
/* We cannot support mft record sizes below the sector size. */
|
||||||
|
if (vol->mft_record_size < vol->sector_size) {
|
||||||
|
ntfs_error(vol->sb, "Mft record size (%i) is smaller than the "
|
||||||
|
"sector size (%i). This is not supported. "
|
||||||
|
"Sorry.", vol->mft_record_size,
|
||||||
|
vol->sector_size);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
clusters_per_index_record = b->clusters_per_index_record;
|
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)
|
|||||||
ntfs_debug("vol->index_record_size_bits = %i (0x%x)",
|
ntfs_debug("vol->index_record_size_bits = %i (0x%x)",
|
||||||
vol->index_record_size_bits,
|
vol->index_record_size_bits,
|
||||||
vol->index_record_size_bits);
|
vol->index_record_size_bits);
|
||||||
|
/* We cannot support index record sizes below the sector size. */
|
||||||
|
if (vol->index_record_size < vol->sector_size) {
|
||||||
|
ntfs_error(vol->sb, "Index record size (%i) is smaller than "
|
||||||
|
"the sector size (%i). This is not "
|
||||||
|
"supported. Sorry.", vol->index_record_size,
|
||||||
|
vol->sector_size);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Get the size of the volume in clusters and check for 64-bit-ness.
|
* Get the size of the volume in clusters and check for 64-bit-ness.
|
||||||
* Windows currently only uses 32 bits to save the clusters so we do
|
* 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)
|
|||||||
}
|
}
|
||||||
ll = sle64_to_cpu(b->mft_lcn);
|
ll = sle64_to_cpu(b->mft_lcn);
|
||||||
if (ll >= vol->nr_clusters) {
|
if (ll >= vol->nr_clusters) {
|
||||||
ntfs_error(vol->sb, "MFT LCN is beyond end of volume. Weird.");
|
ntfs_error(vol->sb, "MFT LCN (%lli, 0x%llx) is beyond end of "
|
||||||
|
"volume. Weird.", (unsigned long long)ll,
|
||||||
|
(unsigned long long)ll);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
vol->mft_lcn = ll;
|
vol->mft_lcn = ll;
|
||||||
ntfs_debug("vol->mft_lcn = 0x%llx", (long long)vol->mft_lcn);
|
ntfs_debug("vol->mft_lcn = 0x%llx", (long long)vol->mft_lcn);
|
||||||
ll = sle64_to_cpu(b->mftmirr_lcn);
|
ll = sle64_to_cpu(b->mftmirr_lcn);
|
||||||
if (ll >= vol->nr_clusters) {
|
if (ll >= vol->nr_clusters) {
|
||||||
ntfs_error(vol->sb, "MFTMirr LCN is beyond end of volume. "
|
ntfs_error(vol->sb, "MFTMirr LCN (%lli, 0x%llx) is beyond end "
|
||||||
"Weird.");
|
"of volume. Weird.", (unsigned long long)ll,
|
||||||
|
(unsigned long long)ll);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
vol->mftmirr_lcn = ll;
|
vol->mftmirr_lcn = ll;
|
||||||
@ -2685,7 +2708,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
|
|||||||
ntfs_volume *vol;
|
ntfs_volume *vol;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct inode *tmp_ino;
|
struct inode *tmp_ino;
|
||||||
int result;
|
int blocksize, result;
|
||||||
|
|
||||||
ntfs_debug("Entering.");
|
ntfs_debug("Entering.");
|
||||||
#ifndef NTFS_RW
|
#ifndef NTFS_RW
|
||||||
@ -2724,60 +2747,85 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
|
|||||||
if (!parse_options(vol, (char*)opt))
|
if (!parse_options(vol, (char*)opt))
|
||||||
goto err_out_now;
|
goto err_out_now;
|
||||||
|
|
||||||
|
/* We support sector sizes up to the PAGE_CACHE_SIZE. */
|
||||||
|
if (bdev_hardsect_size(sb->s_bdev) > PAGE_CACHE_SIZE) {
|
||||||
|
if (!silent)
|
||||||
|
ntfs_error(sb, "Device has unsupported sector size "
|
||||||
|
"(%i). The maximum supported sector "
|
||||||
|
"size on this architecture is %lu "
|
||||||
|
"bytes.",
|
||||||
|
bdev_hardsect_size(sb->s_bdev),
|
||||||
|
PAGE_CACHE_SIZE);
|
||||||
|
goto err_out_now;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* TODO: Fail safety check. In the future we should really be able to
|
* Setup the device access block size to NTFS_BLOCK_SIZE or the hard
|
||||||
* cope with this being the case, but for now just bail out.
|
* sector size, whichever is bigger.
|
||||||
*/
|
*/
|
||||||
if (bdev_hardsect_size(sb->s_bdev) > NTFS_BLOCK_SIZE) {
|
blocksize = sb_min_blocksize(sb, NTFS_BLOCK_SIZE);
|
||||||
|
if (blocksize < NTFS_BLOCK_SIZE) {
|
||||||
if (!silent)
|
if (!silent)
|
||||||
ntfs_error(sb, "Device has unsupported hardsect_size.");
|
ntfs_error(sb, "Unable to set device block size.");
|
||||||
goto err_out_now;
|
goto err_out_now;
|
||||||
}
|
}
|
||||||
|
BUG_ON(blocksize != sb->s_blocksize);
|
||||||
/* Setup the device access block size to NTFS_BLOCK_SIZE. */
|
ntfs_debug("Set device block size to %i bytes (block size bits %i).",
|
||||||
if (sb_set_blocksize(sb, NTFS_BLOCK_SIZE) != NTFS_BLOCK_SIZE) {
|
blocksize, sb->s_blocksize_bits);
|
||||||
|
/* Determine the size of the device in units of block_size bytes. */
|
||||||
|
if (!i_size_read(sb->s_bdev->bd_inode)) {
|
||||||
if (!silent)
|
if (!silent)
|
||||||
ntfs_error(sb, "Unable to set block size.");
|
ntfs_error(sb, "Unable to determine device size.");
|
||||||
goto err_out_now;
|
goto err_out_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the size of the device in units of NTFS_BLOCK_SIZE bytes. */
|
|
||||||
vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >>
|
vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >>
|
||||||
NTFS_BLOCK_SIZE_BITS;
|
sb->s_blocksize_bits;
|
||||||
|
|
||||||
/* Read the boot sector and return unlocked buffer head to it. */
|
/* Read the boot sector and return unlocked buffer head to it. */
|
||||||
if (!(bh = read_ntfs_boot_sector(sb, silent))) {
|
if (!(bh = read_ntfs_boot_sector(sb, silent))) {
|
||||||
if (!silent)
|
if (!silent)
|
||||||
ntfs_error(sb, "Not an NTFS volume.");
|
ntfs_error(sb, "Not an NTFS volume.");
|
||||||
goto err_out_now;
|
goto err_out_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract the data from the boot sector and setup the ntfs super block
|
* Extract the data from the boot sector and setup the ntfs volume
|
||||||
* using it.
|
* using it.
|
||||||
*/
|
*/
|
||||||
result = parse_ntfs_boot_sector(vol, (NTFS_BOOT_SECTOR*)bh->b_data);
|
result = parse_ntfs_boot_sector(vol, (NTFS_BOOT_SECTOR*)bh->b_data);
|
||||||
|
|
||||||
/* Initialize the cluster and mft allocators. */
|
|
||||||
ntfs_setup_allocators(vol);
|
|
||||||
|
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
if (!silent)
|
if (!silent)
|
||||||
ntfs_error(sb, "Unsupported NTFS filesystem.");
|
ntfs_error(sb, "Unsupported NTFS filesystem.");
|
||||||
goto err_out_now;
|
goto err_out_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: When we start coping with sector sizes different from
|
* If the boot sector indicates a sector size bigger than the current
|
||||||
* NTFS_BLOCK_SIZE, we now probably need to set the blocksize of the
|
* device block size, switch the device block size to the sector size.
|
||||||
* device (probably to NTFS_BLOCK_SIZE).
|
* TODO: It may be possible to support this case even when the set
|
||||||
|
* below fails, we would just be breaking up the i/o for each sector
|
||||||
|
* into multiple blocks for i/o purposes but otherwise it should just
|
||||||
|
* work. However it is safer to leave disabled until someone hits this
|
||||||
|
* error message and then we can get them to try it without the setting
|
||||||
|
* so we know for sure that it works.
|
||||||
*/
|
*/
|
||||||
|
if (vol->sector_size > blocksize) {
|
||||||
|
blocksize = sb_set_blocksize(sb, vol->sector_size);
|
||||||
|
if (blocksize != vol->sector_size) {
|
||||||
|
if (!silent)
|
||||||
|
ntfs_error(sb, "Unable to set device block "
|
||||||
|
"size to sector size (%i).",
|
||||||
|
vol->sector_size);
|
||||||
|
goto err_out_now;
|
||||||
|
}
|
||||||
|
BUG_ON(blocksize != sb->s_blocksize);
|
||||||
|
vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >>
|
||||||
|
sb->s_blocksize_bits;
|
||||||
|
ntfs_debug("Changed device block size to %i bytes (block size "
|
||||||
|
"bits %i) to match volume sector size.",
|
||||||
|
blocksize, sb->s_blocksize_bits);
|
||||||
|
}
|
||||||
|
/* Initialize the cluster and mft allocators. */
|
||||||
|
ntfs_setup_allocators(vol);
|
||||||
/* Setup remaining fields in the super block. */
|
/* Setup remaining fields in the super block. */
|
||||||
sb->s_magic = NTFS_SB_MAGIC;
|
sb->s_magic = NTFS_SB_MAGIC;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ntfs allows 63 bits for the file size, i.e. correct would be:
|
* Ntfs allows 63 bits for the file size, i.e. correct would be:
|
||||||
* sb->s_maxbytes = ~0ULL >> 1;
|
* sb->s_maxbytes = ~0ULL >> 1;
|
||||||
@ -2787,9 +2835,8 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
|
|||||||
* without overflowing the index or to 2^63 - 1, whichever is smaller.
|
* without overflowing the index or to 2^63 - 1, whichever is smaller.
|
||||||
*/
|
*/
|
||||||
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
||||||
|
/* Ntfs measures time in 100ns intervals. */
|
||||||
sb->s_time_gran = 100;
|
sb->s_time_gran = 100;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now load the metadata required for the page cache and our address
|
* Now load the metadata required for the page cache and our address
|
||||||
* space operations to function. We do this by setting up a specialised
|
* space operations to function. We do this by setting up a specialised
|
||||||
|
Loading…
x
Reference in New Issue
Block a user