Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
78af34f0
Commit
78af34f0
authored
Feb 24, 2006
by
Anton Altaparmakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
NTFS: Implement support for sector sizes above 512 bytes (up to the maximum
supported by NTFS which is 4096 bytes).
parent
7b875aff
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
121 additions
and
70 deletions
+121
-70
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+6
-0
fs/ntfs/aops.c
fs/ntfs/aops.c
+8
-10
fs/ntfs/file.c
fs/ntfs/file.c
+4
-4
fs/ntfs/mft.c
fs/ntfs/mft.c
+4
-4
fs/ntfs/super.c
fs/ntfs/super.c
+99
-52
No files found.
fs/ntfs/ChangeLog
View file @
78af34f0
...
...
@@ -21,8 +21,14 @@ ToDo/Notes:
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
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.
- Cope with attribute list attribute having invalid flags. Windows
copes with this and even chkdsk does not detect or fix this so we
...
...
fs/ntfs/aops.c
View file @
78af34f0
...
...
@@ -2,7 +2,7 @@
* aops.c - NTFS kernel address space operations and page cache handling.
* Part of the Linux-NTFS project.
*
* Copyright (c) 2001-200
5
Anton Altaparmakov
* Copyright (c) 2001-200
6
Anton Altaparmakov
* Copyright (c) 2002 Richard Russon
*
* 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. */
BUG_ON
(
!
ni
->
runlist
.
rl
&&
!
ni
->
mft_no
&&
!
NInoAttr
(
ni
));
blocksize
_bits
=
VFS_I
(
ni
)
->
i_blkbits
;
blocksize
=
1
<<
blocksize_bits
;
blocksize
=
vol
->
sb
->
s_blocksize
;
blocksize
_bits
=
vol
->
sb
->
s_
blocksize_bits
;
if
(
!
page_has_buffers
(
page
))
{
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
(
NInoMstProtected
(
ni
));
blocksize_bits
=
vi
->
i_blkbits
;
blocksize
=
1
<<
blocksize_bits
;
blocksize
=
vol
->
sb
->
s_blocksize
;
blocksize_bits
=
vol
->
sb
->
s_blocksize_bits
;
if
(
!
page_has_buffers
(
page
))
{
BUG_ON
(
!
PageUptodate
(
page
));
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
)
||
(
NInoAttr
(
ni
)
&&
ni
->
type
==
AT_INDEX_ALLOCATION
)));
bh_size
_bits
=
vi
->
i_blkbits
;
bh_size
=
1
<<
bh_
size_bits
;
bh_size
=
vol
->
sb
->
s_blocksize
;
bh_size
_bits
=
vol
->
sb
->
s_block
size_bits
;
max_bhs
=
PAGE_CACHE_SIZE
/
bh_size
;
BUG_ON
(
!
max_bhs
);
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
));
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
);
if
(
unlikely
(
!
page_has_buffers
(
page
)))
{
spin_unlock
(
&
mapping
->
private_lock
);
...
...
fs/ntfs/file.c
View file @
78af34f0
/*
* file.c - NTFS kernel file operations. Part of the Linux-NTFS project.
*
* Copyright (c) 2001-200
5
Anton Altaparmakov
* Copyright (c) 2001-200
6
Anton Altaparmakov
*
* 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
...
...
@@ -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."
,
vi
->
i_ino
,
ni
->
type
,
pages
[
0
]
->
index
,
nr_pages
,
(
long
long
)
pos
,
bytes
);
blocksize
_bits
=
vi
->
i_blkbits
;
blocksize
=
1
<<
blocksize_bits
;
blocksize
=
vol
->
sb
->
s_blocksize
;
blocksize
_bits
=
vol
->
sb
->
s_
blocksize_bits
;
u
=
0
;
do
{
struct
page
*
page
=
pages
[
u
];
...
...
@@ -1525,7 +1525,7 @@ static inline int ntfs_commit_pages_after_non_resident_write(
vi
=
pages
[
0
]
->
mapping
->
host
;
ni
=
NTFS_I
(
vi
);
blocksize
=
1
<<
vi
->
i_blkbits
;
blocksize
=
vi
->
i_sb
->
s_blocksize
;
end
=
pos
+
bytes
;
u
=
0
;
do
{
...
...
fs/ntfs/mft.c
View file @
78af34f0
/**
* mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project.
*
* Copyright (c) 2001-200
5
Anton Altaparmakov
* Copyright (c) 2001-200
6
Anton Altaparmakov
* Copyright (c) 2002 Richard Russon
*
* 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
;
unsigned
int
block_start
,
block_end
,
m_start
,
m_end
,
page_ofs
;
int
i_bhs
,
nr_bhs
,
err
=
0
;
unsigned
char
blocksize_bits
=
vol
->
mftmirr_ino
->
i_blk
bits
;
unsigned
char
blocksize_bits
=
vol
->
sb
->
s_blocksize_
bits
;
ntfs_debug
(
"Entering for inode 0x%lx."
,
mft_no
);
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
;
struct
page
*
page
=
ni
->
page
;
unsigned
char
blocksize_bits
=
vol
->
mft_ino
->
i_blkbits
;
unsigned
int
blocksize
=
1
<<
blocksize_bits
;
unsigned
int
blocksize
=
vol
->
sb
->
s_blocksize
;
unsigned
char
blocksize_bits
=
vol
->
sb
->
s_
blocksize_bits
;
int
max_bhs
=
vol
->
mft_record_size
/
blocksize
;
struct
buffer_head
*
bhs
[
max_bhs
];
struct
buffer_head
*
bh
,
*
head
;
...
...
fs/ntfs/super.c
View file @
78af34f0
/*
* super.c - NTFS kernel super block handling. Part of the Linux-NTFS project.
*
* Copyright (c) 2001-200
5
Anton Altaparmakov
* Copyright (c) 2001-200
6
Anton Altaparmakov
* Copyright (c) 2001,2002 Richard Russon
*
* This program/include file is free software; you can redistribute it and/or
...
...
@@ -22,6 +22,7 @@
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#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."
;
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. */
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
* 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
))
{
ntfs_warning
(
sb
,
"Hot-fix: Recovering invalid primary "
"boot sector from backup copy."
);
memcpy
(
bh_primary
->
b_data
,
bh_backup
->
b_data
,
sb
->
s_blocksize
);
NTFS_BLOCK_SIZE
);
mark_buffer_dirty
(
bh_primary
);
sync_dirty_buffer
(
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
);
ntfs_debug
(
"vol->sector_size_bits = %i (0x%x)"
,
vol
->
sector_size_bits
,
vol
->
sector_size_bits
);
if
(
vol
->
sector_size
!=
vol
->
sb
->
s_blocksize
)
ntfs_warning
(
vol
->
sb
,
"The boot sector indicates a sector size "
"different from the device sector size."
);
if
(
vol
->
sector_size
<
vol
->
sb
->
s_blocksize
)
{
ntfs_error
(
vol
->
sb
,
"Sector size (%i) is smaller than the "
"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
);
sectors_per_cluster_bits
=
ffs
(
b
->
bpb
.
sectors_per_cluster
)
-
1
;
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
,
vol
->
cluster_size
);
ntfs_debug
(
"vol->cluster_size_mask = 0x%x"
,
vol
->
cluster_size_mask
);
ntfs_debug
(
"vol->cluster_size_bits = %i (0x%x)"
,
vol
->
cluster_size_bits
,
vol
->
cluster_size_bits
);
if
(
vol
->
sector_size
>
vol
->
cluster_size
)
{
ntfs_error
(
vol
->
sb
,
"Sector sizes above the cluster size are "
"not supported. Sorry."
);
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."
);
ntfs_debug
(
"vol->cluster_size_bits = %i"
,
vol
->
cluster_size_bits
);
if
(
vol
->
cluster_size
<
vol
->
sector_size
)
{
ntfs_error
(
vol
->
sb
,
"Cluster size (%i) is smaller than the "
"sector size (%i). This is not supported. "
"Sorry."
,
vol
->
cluster_size
,
vol
->
sector_size
);
return
FALSE
;
}
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.
*/
if
(
vol
->
mft_record_size
>
PAGE_CACHE_SIZE
)
{
ntfs_error
(
vol
->
sb
,
"Mft record size
%i (0x%x
) exceeds the "
"
page cache size on your system %lu (0x%lx
). "
ntfs_error
(
vol
->
sb
,
"Mft record size
(%i
) exceeds the "
"
PAGE_CACHE_SIZE on your system (%lu
). "
"This is not supported. Sorry."
,
vol
->
mft_record_size
,
vol
->
mft_record_size
,
PAGE_CACHE_SIZE
,
PAGE_CACHE_SIZE
);
vol
->
mft_record_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
;
}
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)"
,
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.
* 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
);
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
;
}
vol
->
mft_lcn
=
ll
;
ntfs_debug
(
"vol->mft_lcn = 0x%llx"
,
(
long
long
)
vol
->
mft_lcn
);
ll
=
sle64_to_cpu
(
b
->
mftmirr_lcn
);
if
(
ll
>=
vol
->
nr_clusters
)
{
ntfs_error
(
vol
->
sb
,
"MFTMirr LCN is beyond end of volume. "
"Weird."
);
ntfs_error
(
vol
->
sb
,
"MFTMirr LCN (%lli, 0x%llx) is beyond end "
"of volume. Weird."
,
(
unsigned
long
long
)
ll
,
(
unsigned
long
long
)
ll
);
return
FALSE
;
}
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
;
struct
buffer_head
*
bh
;
struct
inode
*
tmp_ino
;
int
result
;
int
blocksize
,
result
;
ntfs_debug
(
"Entering."
);
#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
))
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
*
cope with this being the case, but for now just bail out
.
*
Setup the device access block size to NTFS_BLOCK_SIZE or the hard
*
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
)
ntfs_error
(
sb
,
"
Device has unsupported hardsect_
size."
);
ntfs_error
(
sb
,
"
Unable to set device block
size."
);
goto
err_out_now
;
}
/* Setup the device access block size to NTFS_BLOCK_SIZE. */
if
(
sb_set_blocksize
(
sb
,
NTFS_BLOCK_SIZE
)
!=
NTFS_BLOCK_SIZE
)
{
BUG_ON
(
blocksize
!=
sb
->
s_blocksize
);
ntfs_debug
(
"Set device block size to %i bytes (block size bits %i)."
,
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
)
ntfs_error
(
sb
,
"Unable to
set block
size."
);
ntfs_error
(
sb
,
"Unable to
determine device
size."
);
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
)
>>
NTFS_BLOCK_SIZE_BITS
;
sb
->
s_blocksize_bits
;
/* Read the boot sector and return unlocked buffer head to it. */
if
(
!
(
bh
=
read_ntfs_boot_sector
(
sb
,
silent
)))
{
if
(
!
silent
)
ntfs_error
(
sb
,
"Not an NTFS volume."
);
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.
*/
result
=
parse_ntfs_boot_sector
(
vol
,
(
NTFS_BOOT_SECTOR
*
)
bh
->
b_data
);
/* Initialize the cluster and mft allocators. */
ntfs_setup_allocators
(
vol
);
brelse
(
bh
);
if
(
!
result
)
{
if
(
!
silent
)
ntfs_error
(
sb
,
"Unsupported NTFS filesystem."
);
goto
err_out_now
;
}
/*
* TODO: When we start coping with sector sizes different from
* NTFS_BLOCK_SIZE, we now probably need to set the blocksize of the
* device (probably to NTFS_BLOCK_SIZE).
*/
* If the boot sector indicates a sector size bigger than the current
* device block size, switch the device block size to the sector 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. */
sb
->
s_magic
=
NTFS_SB_MAGIC
;
/*
* Ntfs allows 63 bits for the file size, i.e. correct would be:
* 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.
*/
sb
->
s_maxbytes
=
MAX_LFS_FILESIZE
;
/* Ntfs measures time in 100ns intervals. */
sb
->
s_time_gran
=
100
;
/*
* Now load the metadata required for the page cache and our address
* space operations to function. We do this by setting up a specialised
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment