Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
579cc8b7
Commit
579cc8b7
authored
Jun 19, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linux-ntfs.bkbits.net/ntfs-tng-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
ed0f878e
eab71b80
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
154 additions
and
144 deletions
+154
-144
Documentation/filesystems/ntfs.txt
Documentation/filesystems/ntfs.txt
+10
-0
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+22
-0
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/attrib.c
fs/ntfs/attrib.c
+1
-2
fs/ntfs/compress.c
fs/ntfs/compress.c
+14
-11
fs/ntfs/dir.c
fs/ntfs/dir.c
+59
-80
fs/ntfs/dir.h
fs/ntfs/dir.h
+2
-2
fs/ntfs/inode.c
fs/ntfs/inode.c
+19
-12
fs/ntfs/inode.h
fs/ntfs/inode.h
+1
-1
fs/ntfs/layout.h
fs/ntfs/layout.h
+3
-4
fs/ntfs/mft.c
fs/ntfs/mft.c
+6
-10
fs/ntfs/namei.c
fs/ntfs/namei.c
+9
-10
fs/ntfs/super.c
fs/ntfs/super.c
+5
-9
fs/ntfs/volume.h
fs/ntfs/volume.h
+2
-2
No files found.
Documentation/filesystems/ntfs.txt
View file @
579cc8b7
...
...
@@ -247,6 +247,16 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.10:
- Microsoft says that the maximum number of inodes is 2^32 - 1. Update
the driver accordingly to only use 32-bits to store inode numbers on
32-bit architectures. This improves the speed of the driver a little.
2.0.9:
- Change decompression engine to use a single buffer. This should not
affect performance except perhaps on the most heavy i/o on SMP
systems when accessing multiple compressed files from multiple
devices simultaneously.
- Minor updates and cleanups.
2.0.8:
- Remove now obsolete show_inodes and posix mount option(s).
- Restore show_sys_files mount option.
...
...
fs/ntfs/ChangeLog
View file @
579cc8b7
...
...
@@ -23,6 +23,28 @@ ToDo:
them cleaner and make code reuse easier.
- Want to use dummy inodes for address space i/o.
2.0.10 - There can only be 2^32 - 1 inodes on an NTFS volume.
- Add check at mount time to verify that the number of inodes on the
volume does not exceed 2^32 - 1, which is the maximum allowed for
NTFS according to Microsoft.
- Change mft_no member of ntfs_inode structure to be unsigned long.
Update all users. This makes ntfs_inode->mft_no just a copy of struct
inode->i_ino. But we can't just always use struct inode->i_ino and
remove mft_no because extent inodes do not have an attached struct
inode.
2.0.9 - Decompression engine now uses a single buffer and other cleanups.
- Change decompression engine to use a single buffer protected by a
spin lock instead of per-CPU buffers. (Rusty Russell)
- Switch to using the new KM_BIO_SRC_IRQ for atomic kmaps. (Andrew
Morton)
- Change buffer size in ntfs_readdir()/ntfs_filldir() to use
NLS_MAX_CHARSET_SIZE which makes the buffers almost 1kiB each but
it also makes everything safer so it is a good thing.
- Miscellaneous minor cleanups to comments.
2.0.8 - Major updates for handling of case sensitivity and dcache aliasing.
Big thanks go to Al Viro and other inhabitants of #kernel for investing
...
...
fs/ntfs/Makefile
View file @
579cc8b7
...
...
@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
ntfs-objs
:=
aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o
\
mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.0.
8
\"
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.0.
10
\"
ifeq
($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/attrib.c
View file @
579cc8b7
...
...
@@ -1243,8 +1243,7 @@ static BOOL find_external_attr(const ATTR_TYPES type, const uchar_t *name,
ni
=
ctx
->
ntfs_ino
;
base_ni
=
ctx
->
base_ntfs_ino
;
ntfs_debug
(
"Entering for inode 0x%Lx, type 0x%x."
,
(
unsigned
long
long
)
ni
->
mft_no
,
type
);
ntfs_debug
(
"Entering for inode 0x%lx, type 0x%x."
,
ni
->
mft_no
,
type
);
if
(
!
base_ni
)
{
/* First call happens with the base mft record. */
base_ni
=
ctx
->
base_ntfs_ino
=
ctx
->
ntfs_ino
;
...
...
fs/ntfs/compress.c
View file @
579cc8b7
...
...
@@ -50,11 +50,13 @@ typedef enum {
}
ntfs_compression_constants
;
/**
* ntfs_compression_buffer - one buffer for the decompression engine
.
* ntfs_compression_buffer - one buffer for the decompression engine
*/
static
u8
*
ntfs_compression_buffer
=
NULL
;
/* This spinlock which protects it */
/**
* ntfs_cb_lock - spinlock which protects ntfs_compression_buffer
*/
static
spinlock_t
ntfs_cb_lock
=
SPIN_LOCK_UNLOCKED
;
/**
...
...
@@ -66,8 +68,6 @@ static spinlock_t ntfs_cb_lock = SPIN_LOCK_UNLOCKED;
*/
int
allocate_compression_buffers
(
void
)
{
int
i
,
j
;
BUG_ON
(
ntfs_compression_buffer
);
ntfs_compression_buffer
=
vmalloc
(
NTFS_MAX_CB_SIZE
);
...
...
@@ -83,8 +83,6 @@ int allocate_compression_buffers(void)
*/
void
free_compression_buffers
(
void
)
{
int
i
;
BUG_ON
(
!
ntfs_compression_buffer
);
vfree
(
ntfs_compression_buffer
);
ntfs_compression_buffer
=
NULL
;
...
...
@@ -592,7 +590,8 @@ int ntfs_file_read_compressed_block(struct page *page)
/*
* Get the compression buffer. We must not sleep any more
* until we are finished with it. */
* until we are finished with it.
*/
spin_lock
(
&
ntfs_cb_lock
);
cb
=
ntfs_compression_buffer
;
...
...
@@ -668,7 +667,10 @@ int ntfs_file_read_compressed_block(struct page *page)
if
(
page
)
memset
(
page_address
(
page
)
+
cur_ofs
,
0
,
cb_max_ofs
-
cur_ofs
);
cb_pos
+=
cb_max_ofs
-
cur_ofs
;
/*
* No need to update cb_pos at this stage:
* cb_pos += cb_max_ofs - cur_ofs;
*/
cur_ofs
=
cb_max_ofs
;
}
}
else
if
(
vcn
==
start_vcn
)
{
...
...
@@ -742,12 +744,13 @@ int ntfs_file_read_compressed_block(struct page *page)
cb_pos
,
cb_size
-
(
cb_pos
-
cb
));
/*
* We can sleep from now on, lock already dropped by
* ntfs_decompress. */
* ntfs_decompress().
*/
if
(
err
)
{
ntfs_error
(
vol
->
sb
,
"ntfs_decompress() failed in inode "
"0x%
L
x with error code %i. Skipping "
"0x%
l
x with error code %i. Skipping "
"this compression block.
\n
"
,
(
unsigned
long
long
)
ni
->
mft_no
,
-
err
);
ni
->
mft_no
,
-
err
);
/* Release the unfinished pages. */
for
(;
prev_cur_page
<
cur_page
;
prev_cur_page
++
)
{
page
=
pages
[
prev_cur_page
];
...
...
fs/ntfs/dir.c
View file @
579cc8b7
...
...
@@ -64,7 +64,7 @@ const uchar_t I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'),
* work but we don't care for how quickly one can access them. This also fixes
* the dcache aliasing issues.
*/
u64
ntfs_lookup_inode_by_name
(
ntfs_inode
*
dir_ni
,
const
uchar_t
*
uname
,
MFT_REF
ntfs_lookup_inode_by_name
(
ntfs_inode
*
dir_ni
,
const
uchar_t
*
uname
,
const
int
uname_len
,
ntfs_name
**
res
)
{
ntfs_volume
*
vol
=
dir_ni
->
vol
;
...
...
@@ -98,8 +98,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if
(
!
lookup_attr
(
AT_INDEX_ROOT
,
I30
,
4
,
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
))
{
ntfs_error
(
sb
,
"Index root attribute missing in directory "
"inode 0x%Lx."
,
(
unsigned
long
long
)
dir_ni
->
mft_no
);
"inode 0x%lx."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
put_unm_err_out
;
}
...
...
@@ -278,9 +277,8 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
/* Consistency check: Verify that an index allocation exists. */
if
(
!
NInoIndexAllocPresent
(
dir_ni
))
{
ntfs_error
(
sb
,
"No index allocation attribute but index entry "
"requires one. Directory inode 0x%Lx is "
"corrupt or driver bug."
,
(
unsigned
long
long
)
dir_ni
->
mft_no
);
"requires one. Directory inode 0x%lx is "
"corrupt or driver bug."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
put_unm_err_out
;
}
...
...
@@ -308,30 +306,27 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
/* Bounds checks. */
if
((
u8
*
)
ia
<
kaddr
||
(
u8
*
)
ia
>
kaddr
+
PAGE_CACHE_SIZE
)
{
ntfs_error
(
sb
,
"Out of bounds check failed. Corrupt directory "
"inode 0x%Lx or driver bug."
,
(
unsigned
long
long
)
dir_ni
->
mft_no
);
"inode 0x%lx or driver bug."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_unm_err_out
;
}
if
(
sle64_to_cpu
(
ia
->
index_block_vcn
)
!=
vcn
)
{
ntfs_error
(
sb
,
"Actual VCN (0x%Lx) of index buffer is "
"different from expected VCN (0x%Lx). "
"Directory inode 0x%
L
x is corrupt or driver "
"Directory inode 0x%
l
x is corrupt or driver "
"bug."
,
(
long
long
)
sle64_to_cpu
(
ia
->
index_block_vcn
),
(
long
long
)
vcn
,
(
unsigned
long
long
)
dir_ni
->
mft_no
);
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_unm_err_out
;
}
if
(
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
!=
dir_ni
->
_IDM
(
index_block_size
))
{
ntfs_error
(
sb
,
"Index buffer (VCN 0x%Lx) of directory inode "
"0x%
L
x has a size (%u) differing from the "
"0x%
l
x has a size (%u) differing from the "
"directory specified size (%u). Directory "
"inode is corrupt or driver bug."
,
(
long
long
)
vcn
,
(
unsigned
long
long
)
dir_ni
->
mft_no
,
(
long
long
)
vcn
,
dir_ni
->
mft_no
,
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
,
dir_ni
->
_IDM
(
index_block_size
));
err
=
-
EIO
;
...
...
@@ -340,19 +335,17 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
index_end
=
(
u8
*
)
ia
+
dir_ni
->
_IDM
(
index_block_size
);
if
(
index_end
>
kaddr
+
PAGE_CACHE_SIZE
)
{
ntfs_error
(
sb
,
"Index buffer (VCN 0x%Lx) of directory inode "
"0x%
L
x crosses page boundary. Impossible! "
"0x%
l
x crosses page boundary. Impossible! "
"Cannot access! This is probably a bug in the "
"driver."
,
(
long
long
)
vcn
,
(
unsigned
long
long
)
dir_ni
->
mft_no
);
"driver."
,
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_unm_err_out
;
}
index_end
=
(
u8
*
)
&
ia
->
index
+
le32_to_cpu
(
ia
->
index
.
index_length
);
if
(
index_end
>
(
u8
*
)
ia
+
dir_ni
->
_IDM
(
index_block_size
))
{
ntfs_error
(
sb
,
"Size of index buffer (VCN 0x%Lx) of directory "
"inode 0x%Lx exceeds maximum size."
,
(
long
long
)
vcn
,
(
unsigned
long
long
)
dir_ni
->
mft_no
);
"inode 0x%lx exceeds maximum size."
,
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_unm_err_out
;
}
...
...
@@ -371,8 +364,8 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
(
u8
*
)
ie
+
le16_to_cpu
(
ie
->
_IEH
(
key_length
))
>
index_end
)
{
ntfs_error
(
sb
,
"Index entry out of bounds in "
"directory inode 0x%
L
x."
,
(
unsigned
long
long
)
dir_ni
->
mft_no
);
"directory inode 0x%
l
x."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_unm_err_out
;
}
...
...
@@ -523,8 +516,8 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if
(
ie
->
_IEH
(
flags
)
&
INDEX_ENTRY_NODE
)
{
if
((
ia
->
index
.
flags
&
NODE_MASK
)
==
LEAF_NODE
)
{
ntfs_error
(
sb
,
"Index entry with child node found in "
"a leaf node in directory inode 0x%
L
x."
,
(
unsigned
long
long
)
dir_ni
->
mft_no
);
"a leaf node in directory inode 0x%
l
x."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_unm_err_out
;
}
...
...
@@ -544,7 +537,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
goto
descend_into_child_node
;
}
ntfs_error
(
sb
,
"Negative child node vcn in directory inode "
"0x%
Lx."
,
(
unsigned
long
long
)
dir_ni
->
mft_no
);
"0x%
lx."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
goto
unm_unm_err_out
;
}
...
...
@@ -643,8 +636,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if (!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 0,
ctx)) {
ntfs_error(sb, "Index root attribute missing in directory "
"inode 0x%Lx.",
(unsigned long long)dir_ni->mft_no);
"inode 0x%lx.", dir_ni->mft_no);
err = -EIO;
goto put_unm_err_out;
}
...
...
@@ -750,9 +742,8 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
/* Consistency check: Verify that an index allocation exists. */
if (!NInoIndexAllocPresent(dir_ni)) {
ntfs_error(sb, "No index allocation attribute but index entry "
"requires one. Directory inode 0x%Lx is "
"corrupt or driver bug.",
(unsigned long long)dir_ni->mft_no);
"requires one. Directory inode 0x%lx is "
"corrupt or driver bug.", dir_ni->mft_no);
err = -EIO;
goto put_unm_err_out;
}
...
...
@@ -780,30 +771,27 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
/* Bounds checks. */
if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) {
ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
"inode 0x%Lx or driver bug.",
(unsigned long long)dir_ni->mft_no);
"inode 0x%lx or driver bug.", dir_ni->mft_no);
err = -EIO;
goto unm_unm_err_out;
}
if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
ntfs_error(sb, "Actual VCN (0x%Lx) of index buffer is "
"different from expected VCN (0x%Lx). "
"Directory inode 0x%
L
x is corrupt or driver "
"Directory inode 0x%
l
x is corrupt or driver "
"bug.",
(long long)sle64_to_cpu(ia->index_block_vcn),
(long long)vcn,
(unsigned long long)dir_ni->mft_no);
(long long)vcn, dir_ni->mft_no);
err = -EIO;
goto unm_unm_err_out;
}
if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
dir_ni->_IDM(index_block_size)) {
ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode "
"0x%
L
x has a size (%u) differing from the "
"0x%
l
x has a size (%u) differing from the "
"directory specified size (%u). Directory "
"inode is corrupt or driver bug.",
(long long)vcn,
(unsigned long long)dir_ni->mft_no,
(long long)vcn, dir_ni->mft_no,
le32_to_cpu(ia->index.allocated_size) + 0x18,
dir_ni->_IDM(index_block_size));
err = -EIO;
...
...
@@ -812,19 +800,17 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
index_end = (u8*)ia + dir_ni->_IDM(index_block_size);
if (index_end > kaddr + PAGE_CACHE_SIZE) {
ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode "
"0x%
L
x crosses page boundary. Impossible! "
"0x%
l
x crosses page boundary. Impossible! "
"Cannot access! This is probably a bug in the "
"driver.", (long long)vcn,
(unsigned long long)dir_ni->mft_no);
"driver.", (long long)vcn, dir_ni->mft_no);
err = -EIO;
goto unm_unm_err_out;
}
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
if (index_end > (u8*)ia + dir_ni->_IDM(index_block_size)) {
ntfs_error(sb, "Size of index buffer (VCN 0x%Lx) of directory "
"inode 0x%Lx exceeds maximum size.",
(long long)vcn,
(unsigned long long)dir_ni->mft_no);
"inode 0x%lx exceeds maximum size.",
(long long)vcn, dir_ni->mft_no);
err = -EIO;
goto unm_unm_err_out;
}
...
...
@@ -843,8 +829,8 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
(u8*)ie + le16_to_cpu(ie->_IEH(key_length)) >
index_end) {
ntfs_error(sb, "Index entry out of bounds in "
"directory inode 0x%
L
x.",
(unsigned long long)
dir_ni->mft_no);
"directory inode 0x%
l
x.",
dir_ni->mft_no);
err = -EIO;
goto unm_unm_err_out;
}
...
...
@@ -928,8 +914,8 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if (ie->_IEH(flags) & INDEX_ENTRY_NODE) {
if ((ia->index.flags & NODE_MASK) == LEAF_NODE) {
ntfs_error(sb, "Index entry with child node found in "
"a leaf node in directory inode 0x%
L
x.",
(unsigned long long)
dir_ni->mft_no);
"a leaf node in directory inode 0x%
l
x.",
dir_ni->mft_no);
err = -EIO;
goto unm_unm_err_out;
}
...
...
@@ -949,7 +935,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
goto descend_into_child_node;
}
ntfs_error(sb, "Negative child node vcn in directory inode "
"0x%
Lx.", (unsigned long long)
dir_ni->mft_no);
"0x%
lx.",
dir_ni->mft_no);
err = -EIO;
goto unm_unm_err_out;
}
...
...
@@ -995,10 +981,10 @@ typedef enum {
* @ie: current index entry
* @name: buffer to use for the converted name
* @dirent: vfs filldir callback context
* filldir: vfs filldir callback
*
@
filldir: vfs filldir callback
*
* Convert the Unicode
name to the loaded NLS and pass it to
*
the filldir
callback.
* Convert the Unicode
@name to the loaded NLS and pass it to the @filldir
* callback.
*/
static
inline
int
ntfs_filldir
(
ntfs_volume
*
vol
,
struct
file
*
filp
,
ntfs_inode
*
ndir
,
const
INDEX_TYPE
index_type
,
...
...
@@ -1033,7 +1019,7 @@ static inline int ntfs_filldir(ntfs_volume *vol, struct file *filp,
}
name_len
=
ntfs_ucstonls
(
vol
,
(
uchar_t
*
)
&
ie
->
key
.
file_name
.
file_name
,
ie
->
key
.
file_name
.
file_name_length
,
&
name
,
NTFS_MAX_NAME_LEN
*
3
+
1
);
NTFS_MAX_NAME_LEN
*
NLS_MAX_CHARSET_SIZE
+
1
);
if
(
name_len
<=
0
)
{
ntfs_debug
(
"Skipping unrepresentable file."
);
return
0
;
...
...
@@ -1044,12 +1030,11 @@ static inline int ntfs_filldir(ntfs_volume *vol, struct file *filp,
else
dt_type
=
DT_REG
;
ntfs_debug
(
"Calling filldir for %s with len %i, f_pos 0x%Lx, inode "
"0x%
L
x, DT_%s."
,
name
,
name_len
,
filp
->
f_pos
,
(
unsigned
long
long
)
MREF_LE
(
ie
->
_IIF
(
indexed_file
)),
"0x%
l
x, DT_%s."
,
name
,
name_len
,
filp
->
f_pos
,
MREF_LE
(
ie
->
_IIF
(
indexed_file
)),
dt_type
==
DT_DIR
?
"DIR"
:
"REG"
);
return
filldir
(
dirent
,
name
,
name_len
,
filp
->
f_pos
,
(
unsigned
long
)
MREF_LE
(
ie
->
_IIF
(
indexed_file
)),
dt_type
);
MREF_LE
(
ie
->
_IIF
(
indexed_file
)),
dt_type
);
}
/*
...
...
@@ -1083,8 +1068,8 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
u8
*
kaddr
,
*
bmp
,
*
index_end
;
attr_search_context
*
ctx
;
ntfs_debug
(
"Entering for inode 0x%
L
x, f_pos 0x%Lx."
,
(
unsigned
long
long
)
ndir
->
mft_
no
,
filp
->
f_pos
);
ntfs_debug
(
"Entering for inode 0x%
l
x, f_pos 0x%Lx."
,
vdir
->
i_i
no
,
filp
->
f_pos
);
rc
=
err
=
0
;
/* Are we at end of dir yet? */
if
(
filp
->
f_pos
>=
vdir
->
i_size
+
vol
->
mft_record_size
)
...
...
@@ -1092,8 +1077,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Emulate . and .. for all directories. */
if
(
!
filp
->
f_pos
)
{
ntfs_debug
(
"Calling filldir for . with len 1, f_pos 0x0, "
"inode 0x%Lx, DT_DIR."
,
(
unsigned
long
long
)
ndir
->
mft_no
);
"inode 0x%lx, DT_DIR."
,
vdir
->
i_ino
);
rc
=
filldir
(
dirent
,
"."
,
1
,
filp
->
f_pos
,
vdir
->
i_ino
,
DT_DIR
);
if
(
rc
)
goto
done
;
...
...
@@ -1126,7 +1110,8 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
* Allocate a buffer to store the current name being processed
* converted to format determined by current NLS.
*/
name
=
(
u8
*
)
kmalloc
(
NTFS_MAX_NAME_LEN
*
3
+
1
,
GFP_NOFS
);
name
=
(
u8
*
)
kmalloc
(
NTFS_MAX_NAME_LEN
*
NLS_MAX_CHARSET_SIZE
+
1
,
GFP_NOFS
);
if
(
!
name
)
{
err
=
-
ENOMEM
;
goto
put_unm_err_out
;
...
...
@@ -1140,8 +1125,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if
(
!
lookup_attr
(
AT_INDEX_ROOT
,
I30
,
4
,
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
))
{
ntfs_error
(
sb
,
"Index root attribute missing in directory "
"inode 0x%Lx."
,
(
unsigned
long
long
)
ndir
->
mft_no
);
"inode 0x%lx."
,
vdir
->
i_ino
);
err
=
-
EIO
;
goto
kf_unm_err_out
;
}
...
...
@@ -1200,8 +1184,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if
(
!
lookup_attr
(
AT_BITMAP
,
I30
,
4
,
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
))
{
ntfs_error
(
sb
,
"Index bitmap attribute missing in "
"directory inode 0x%Lx."
,
(
unsigned
long
long
)
ndir
->
mft_no
);
"directory inode 0x%lx."
,
vdir
->
i_ino
);
err
=
-
EIO
;
goto
kf_unm_err_out
;
}
...
...
@@ -1250,8 +1233,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Bounds checks. */
if
((
u8
*
)
ia
<
kaddr
||
(
u8
*
)
ia
>
kaddr
+
PAGE_CACHE_SIZE
)
{
ntfs_error
(
sb
,
"Out of bounds check failed. Corrupt directory "
"inode 0x%Lx or driver bug."
,
(
unsigned
long
long
)
ndir
->
mft_no
);
"inode 0x%lx or driver bug."
,
vdir
->
i_ino
);
err
=
-
EIO
;
goto
unm_dir_err_out
;
}
...
...
@@ -1260,23 +1242,22 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
ndir
->
_IDM
(
index_vcn_size_bits
))
{
ntfs_error
(
sb
,
"Actual VCN (0x%Lx) of index buffer is "
"different from expected VCN (0x%Lx). "
"Directory inode 0x%
L
x is corrupt or driver "
"Directory inode 0x%
l
x is corrupt or driver "
"bug. "
,
(
long
long
)
sle64_to_cpu
(
ia
->
index_block_vcn
),
(
long
long
)
ia_pos
>>
ndir
->
_IDM
(
index_vcn_size_bits
),
(
unsigned
long
long
)
ndir
->
mft_no
);
ndir
->
_IDM
(
index_vcn_size_bits
),
vdir
->
i_ino
);
err
=
-
EIO
;
goto
unm_dir_err_out
;
}
if
(
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
!=
ndir
->
_IDM
(
index_block_size
))
{
ntfs_error
(
sb
,
"Index buffer (VCN 0x%Lx) of directory inode "
"0x%
L
x has a size (%u) differing from the "
"0x%
l
x has a size (%u) differing from the "
"directory specified size (%u). Directory "
"inode is corrupt or driver bug."
,
(
long
long
)
ia_pos
>>
ndir
->
_IDM
(
index_vcn_size_bits
),
(
unsigned
long
long
)
ndir
->
mft_
no
,
(
long
long
)
ia_pos
>>
ndir
->
_IDM
(
index_vcn_size_bits
),
vdir
->
i_i
no
,
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
,
ndir
->
_IDM
(
index_block_size
));
err
=
-
EIO
;
...
...
@@ -1285,11 +1266,10 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
index_end
=
(
u8
*
)
ia
+
ndir
->
_IDM
(
index_block_size
);
if
(
index_end
>
kaddr
+
PAGE_CACHE_SIZE
)
{
ntfs_error
(
sb
,
"Index buffer (VCN 0x%Lx) of directory inode "
"0x%
L
x crosses page boundary. Impossible! "
"0x%
l
x crosses page boundary. Impossible! "
"Cannot access! This is probably a bug in the "
"driver."
,
(
long
long
)
ia_pos
>>
ndir
->
_IDM
(
index_vcn_size_bits
),
(
unsigned
long
long
)
ndir
->
mft_no
);
ndir
->
_IDM
(
index_vcn_size_bits
),
vdir
->
i_ino
);
err
=
-
EIO
;
goto
unm_dir_err_out
;
}
...
...
@@ -1297,10 +1277,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
index_end
=
(
u8
*
)
&
ia
->
index
+
le32_to_cpu
(
ia
->
index
.
index_length
);
if
(
index_end
>
(
u8
*
)
ia
+
ndir
->
_IDM
(
index_block_size
))
{
ntfs_error
(
sb
,
"Size of index buffer (VCN 0x%Lx) of directory "
"inode 0x%
L
x exceeds maximum size."
,
"inode 0x%
l
x exceeds maximum size."
,
(
long
long
)
ia_pos
>>
ndir
->
_IDM
(
index_vcn_size_bits
),
(
unsigned
long
long
)
ndir
->
mft_no
);
ndir
->
_IDM
(
index_vcn_size_bits
),
vdir
->
i_ino
);
err
=
-
EIO
;
goto
unm_dir_err_out
;
}
...
...
fs/ntfs/dir.h
View file @
579cc8b7
...
...
@@ -40,8 +40,8 @@ typedef struct {
/* The little endian Unicode string $I30 as a global constant. */
extern
const
uchar_t
I30
[
5
];
extern
u64
ntfs_lookup_inode_by_name
(
ntfs_inode
*
dir_ni
,
const
uchar_t
*
uname
,
const
int
uname_len
,
ntfs_name
**
res
);
extern
MFT_REF
ntfs_lookup_inode_by_name
(
ntfs_inode
*
dir_ni
,
const
uchar_t
*
uname
,
const
int
uname_len
,
ntfs_name
**
res
);
#endif
/* _LINUX_NTFS_FS_DIR_H */
fs/ntfs/inode.c
View file @
579cc8b7
...
...
@@ -357,8 +357,7 @@ void ntfs_read_inode(struct inode *vi)
if
(
lookup_attr
(
AT_ATTRIBUTE_LIST
,
NULL
,
0
,
0
,
0
,
NULL
,
0
,
ctx
))
{
if
(
vi
->
i_ino
==
FILE_MFT
)
goto
skip_attr_list_load
;
ntfs_debug
(
"Attribute list found in inode %li (0x%lx)."
,
vi
->
i_ino
,
vi
->
i_ino
);
ntfs_debug
(
"Attribute list found in inode 0x%lx."
,
vi
->
i_ino
);
ni
->
state
|=
1
<<
NI_AttrList
;
if
(
ctx
->
attr
->
flags
&
ATTR_IS_ENCRYPTED
||
ctx
->
attr
->
flags
&
ATTR_COMPRESSION_MASK
)
{
...
...
@@ -805,8 +804,8 @@ void ntfs_read_inode(struct inode *vi)
ec_unm_err_out:
unmap_mft_record
(
READ
,
ni
);
err_out:
ntfs_error
(
vi
->
i_sb
,
"Failed with error code %i. Marking inode "
"
%li (0x%lx) as bad."
,
-
err
,
vi
->
i_ino
,
vi
->
i_ino
);
ntfs_error
(
vi
->
i_sb
,
"Failed with error code %i. Marking inode
0x%lx
"
"
as bad."
,
-
err
,
vi
->
i_ino
);
make_bad_inode
(
vi
);
return
;
}
...
...
@@ -857,7 +856,7 @@ void ntfs_read_inode_mount(struct inode *vi)
ntfs_init_big_inode
(
vi
);
ni
=
NTFS_I
(
vi
);
if
(
vi
->
i_ino
!=
FILE_MFT
)
{
ntfs_error
(
sb
,
"Called for inode
%ld
but only inode %d "
ntfs_error
(
sb
,
"Called for inode
0x%lx
but only inode %d "
"allowed."
,
vi
->
i_ino
,
FILE_MFT
);
goto
err_out
;
}
...
...
@@ -1034,7 +1033,7 @@ void ntfs_read_inode_mount(struct inode *vi)
if
(
al_entry
->
lowest_vcn
)
goto
em_put_err_out
;
/* First entry has to be in the base mft record. */
if
(
MREF_LE
(
al_entry
->
mft_reference
)
!=
ni
->
mft_
no
)
{
if
(
MREF_LE
(
al_entry
->
mft_reference
)
!=
vi
->
i_i
no
)
{
/* MFT references do not match, logic fails. */
ntfs_error
(
sb
,
"BUG: The first $DATA extent "
"of $MFT is not in the base "
...
...
@@ -1096,6 +1095,8 @@ void ntfs_read_inode_mount(struct inode *vi)
/* Are we in the first extent? */
if
(
!
next_vcn
)
{
u64
ll
;
if
(
attr
->
_ANR
(
lowest_vcn
))
{
ntfs_error
(
sb
,
"First extent of $DATA "
"attribute has non zero "
...
...
@@ -1113,8 +1114,16 @@ void ntfs_read_inode_mount(struct inode *vi)
ni
->
allocated_size
=
sle64_to_cpu
(
attr
->
_ANR
(
allocated_size
));
/* Set the number of mft records. */
vol
->
_VMM
(
nr_mft_records
)
=
vi
->
i_size
>>
vol
->
mft_record_size_bits
;
ll
=
vi
->
i_size
>>
vol
->
mft_record_size_bits
;
/*
* Verify the number of mft records does not exceed
* 2^32 - 1.
*/
if
(
ll
>=
(
1ULL
<<
32
))
{
ntfs_error
(
sb
,
"$MFT is too big! Aborting."
);
goto
put_err_out
;
}
vol
->
_VMM
(
nr_mft_records
)
=
ll
;
/*
* We have got the first extent of the run_list for
* $MFT which means it is now relatively safe to call
...
...
@@ -1255,8 +1264,7 @@ void ntfs_dirty_inode(struct inode *vi)
*/
int
ntfs_commit_inode
(
ntfs_inode
*
ni
)
{
ntfs_debug
(
"Entering for inode 0x%Lx."
,
(
unsigned
long
long
)
ni
->
mft_no
);
ntfs_debug
(
"Entering for inode 0x%lx."
,
ni
->
mft_no
);
NInoClearDirty
(
ni
);
return
0
;
}
...
...
@@ -1265,8 +1273,7 @@ void __ntfs_clear_inode(ntfs_inode *ni)
{
int
err
;
ntfs_debug
(
"Entering for inode 0x%Lx."
,
(
unsigned
long
long
)
ni
->
mft_no
);
ntfs_debug
(
"Entering for inode 0x%lx."
,
ni
->
mft_no
);
if
(
NInoDirty
(
ni
))
{
err
=
ntfs_commit_inode
(
ni
);
if
(
err
)
{
...
...
fs/ntfs/inode.h
View file @
579cc8b7
...
...
@@ -39,7 +39,7 @@ struct _ntfs_inode {
s64
allocated_size
;
/* Copy from $DATA/$INDEX_ALLOCATION. */
unsigned
long
state
;
/* NTFS specific flags describing this inode.
See fs/ntfs/ntfs.h:ntfs_inode_state_bits. */
u
64
mft_no
;
/* Mft record number (inode number)
. */
u
nsigned
long
mft_no
;
/* Number of the mft record / inode
. */
u16
seq_no
;
/* Sequence number of the mft record. */
atomic_t
count
;
/* Inode reference count for book keeping. */
ntfs_volume
*
vol
;
/* Pointer to the ntfs volume of this inode. */
...
...
fs/ntfs/layout.h
View file @
579cc8b7
...
...
@@ -278,9 +278,9 @@ typedef enum {
typedef
u64
MFT_REF
;
#define MREF(x) ((u
64
)((x) & MFT_REF_MASK_CPU))
#define MREF(x) ((u
nsigned long
)((x) & MFT_REF_MASK_CPU))
#define MSEQNO(x) ((u16)(((x) >> 48) & 0xffff))
#define MREF_LE(x) ((u
64
)(le64_to_cpu(x) & MFT_REF_MASK_CPU))
#define MREF_LE(x) ((u
nsigned long
)(le64_to_cpu(x) & MFT_REF_MASK_CPU))
#define MSEQNO_LE(x) ((u16)((le64_to_cpu(x) >> 48) & 0xffff))
#define IS_ERR_MREF(x) (((x) & 0x0000800000000000ULL) ? 1 : 0)
...
...
@@ -948,8 +948,7 @@ typedef struct {
data attribute. NOTE: Is a multiple
of the cluster size. */
/* 30*/
s64
data_size
;
/* Byte size of actual data in data
attribute. NOTE: Only present when
lowest_vcn is 0. */
attribute. */
/* 38*/
FILE_ATTR_FLAGS
file_attributes
;
/* Flags describing the file. */
/* 3c*/
union
{
/* 3c*/
struct
{
...
...
fs/ntfs/mft.c
View file @
579cc8b7
...
...
@@ -240,8 +240,7 @@ static inline void unmap_mft_record_page(ntfs_inode *ni)
*
* The mft record is now ours and we return a pointer to it. You need to check
* the returned pointer with IS_ERR() and if that is true, PTR_ERR() will return
* the error code. The following error codes are defined:
* TODO: Fill in the possible error codes.
* the error code.
*
* NOTE: Caller is responsible for setting the mft record dirty before calling
* unmap_mft_record(). This is obviously only necessary if the caller really
...
...
@@ -254,8 +253,7 @@ MFT_RECORD *map_mft_record(const int rw, ntfs_inode *ni)
{
MFT_RECORD
*
m
;
ntfs_debug
(
"Entering for i_ino 0x%Lx, mapping for %s."
,
(
unsigned
long
long
)
ni
->
mft_no
,
ntfs_debug
(
"Entering for mft_no 0x%lx, mapping for %s."
,
ni
->
mft_no
,
rw
==
READ
?
"READ"
:
"WRITE"
);
/* Make sure the ntfs inode doesn't go away. */
...
...
@@ -318,8 +316,7 @@ void unmap_mft_record(const int rw, ntfs_inode *ni)
BUG_ON
(
!
atomic_read
(
&
ni
->
mft_count
)
||
!
page
);
ntfs_debug
(
"Entering for mft_no 0x%Lx, unmapping from %s."
,
(
unsigned
long
long
)
ni
->
mft_no
,
ntfs_debug
(
"Entering for mft_no 0x%lx, unmapping from %s."
,
ni
->
mft_no
,
rw
==
READ
?
"READ"
:
"WRITE"
);
/* Only release the actual page mapping if this is the last one. */
...
...
@@ -369,13 +366,12 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
ntfs_inode
*
ni
=
NULL
;
ntfs_inode
**
extent_nis
=
NULL
;
int
i
;
u
64
mft_no
=
MREF_LE
(
mref
);
u
nsigned
long
mft_no
=
MREF_LE
(
mref
);
u16
seq_no
=
MSEQNO_LE
(
mref
);
BOOL
destroy_ni
=
FALSE
;
ntfs_debug
(
"Mapping extent mft record 0x%Lx (base mft record 0x%Lx)."
,
(
unsigned
long
long
)
mft_no
,
(
unsigned
long
long
)
base_ni
->
mft_no
);
ntfs_debug
(
"Mapping extent mft record 0x%lx (base mft record 0x%lx)."
,
mft_no
,
base_ni
->
mft_no
);
/* Make sure the base ntfs inode doesn't go away. */
atomic_inc
(
&
base_ni
->
count
);
/*
...
...
fs/ntfs/namei.c
View file @
579cc8b7
...
...
@@ -93,7 +93,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
struct
inode
*
dent_inode
;
uchar_t
*
uname
;
ntfs_name
*
name
=
NULL
;
u64
mref
;
MFT_REF
mref
;
unsigned
long
dent_ino
;
int
uname_len
;
...
...
@@ -110,7 +110,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
&
name
);
kmem_cache_free
(
ntfs_name_cache
,
uname
);
if
(
!
IS_ERR_MREF
(
mref
))
{
dent_ino
=
(
unsigned
long
)
MREF
(
mref
);
dent_ino
=
MREF
(
mref
);
ntfs_debug
(
"Found inode 0x%lx. Calling iget."
,
dent_ino
);
dent_inode
=
iget
(
vol
->
sb
,
dent_ino
);
if
(
dent_inode
)
{
...
...
@@ -130,17 +130,15 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
goto
handle_name
;
}
ntfs_error
(
vol
->
sb
,
"Found stale reference to inode "
"0x%
L
x (reference sequence number = "
"0x%
l
x (reference sequence number = "
"0x%x, inode sequence number = 0x%x, "
"returning -EACCES. Run chkdsk."
,
(
unsigned
long
long
)
MREF
(
mref
),
MSEQNO
(
mref
),
dent_ino
,
MSEQNO
(
mref
),
NTFS_I
(
dent_inode
)
->
seq_no
);
iput
(
dent_inode
);
}
else
ntfs_error
(
vol
->
sb
,
"iget(0x%Lx) failed, returning "
"-EACCES."
,
(
unsigned
long
long
)
MREF
(
mref
));
ntfs_error
(
vol
->
sb
,
"iget(0x%lx) failed, returning "
"-EACCES."
,
dent_ino
);
if
(
name
)
kfree
(
name
);
return
ERR_PTR
(
-
EACCES
);
...
...
@@ -235,8 +233,9 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
}
nls_name
.
hash
=
full_name_hash
(
nls_name
.
name
,
nls_name
.
len
);
// FIXME: Do we need dcache_lock or dparent_lock here or is the
// fact that i_sem is held on the parent inode sufficient? (AIA)
/*
* Note: No need for dparent_lock as i_sem is held on the parent inode.
*/
/* Does a dentry matching the nls_name exist already? */
real_dent
=
d_lookup
(
dent
->
d_parent
,
&
nls_name
);
...
...
fs/ntfs/super.c
View file @
579cc8b7
...
...
@@ -1236,14 +1236,13 @@ s64 get_nr_free_clusters(ntfs_volume *vol)
* Errors are ignored and we just return the number of free inodes we have
* found. This means we return an underestimate on error.
*/
s64
get_nr_free_mft_records
(
ntfs_volume
*
vol
)
unsigned
long
get_nr_free_mft_records
(
ntfs_volume
*
vol
)
{
struct
address_space
*
mapping
;
filler_t
*
readpage
;
struct
page
*
page
;
unsigned
long
index
,
max_index
;
unsigned
long
index
,
max_index
,
nr_free
=
0
;
unsigned
int
max_size
,
i
;
s64
nr_free
=
0LL
;
u32
*
b
;
ntfs_debug
(
"Entering."
);
...
...
@@ -1285,7 +1284,7 @@ s64 get_nr_free_mft_records(ntfs_volume *vol)
b
=
(
u32
*
)
kmap
(
page
);
/* For each 4 bytes, add up the number of zero bits. */
for
(
i
=
0
;
i
<
max_size
;
i
++
)
nr_free
+=
(
s64
)(
32
-
hweight32
(
b
[
i
])
);
nr_free
+=
32
-
hweight32
(
b
[
i
]
);
kunmap
(
page
);
page_cache_release
(
page
);
}
...
...
@@ -1300,7 +1299,7 @@ s64 get_nr_free_mft_records(ntfs_volume *vol)
if
(
max_size
)
{
/* Compensate for out of bounds zero bits. */
if
((
i
=
vol
->
_VMM
(
nr_mft_records
)
&
31
))
nr_free
-=
(
s64
)(
32
-
i
)
;
nr_free
-=
32
-
i
;
ntfs_debug
(
"Handling partial page, max_size = 0x%x"
,
max_size
);
goto
handle_partial_page
;
...
...
@@ -1358,10 +1357,7 @@ int ntfs_statfs(struct super_block *sb, struct statfs *sfs)
/* Total file nodes in file system (at this moment in time). */
sfs
->
f_files
=
vol
->
mft_ino
->
i_size
>>
vol
->
mft_record_size_bits
;
/* Free file nodes in fs (based on current total count). */
size
=
get_nr_free_mft_records
(
vol
);
if
(
size
<
0LL
)
size
=
0LL
;
sfs
->
f_ffree
=
size
;
sfs
->
f_ffree
=
get_nr_free_mft_records
(
vol
);
/*
* File system id. This is extremely *nix flavour dependent and even
* within Linux itself all fs do their own thing. I interpret this to
...
...
fs/ntfs/volume.h
View file @
579cc8b7
...
...
@@ -105,8 +105,8 @@ typedef struct {
struct
rw_semaphore
mftbmp_lock
;
/* Lock for serializing accesses to the
mft record bitmap ($MFT/$BITMAP). */
union
{
s64
nr_mft_records
;
/* Number of records in the mft
. */
s64
nr_mft_bits
;
/* Number of bits in mft bitmap. */
unsigned
long
nr_mft_records
;
/* Number of mft records
. */
unsigned
long
nr_mft_bits
;
/* Number of bits in mft bitmap. */
}
SN
(
vmm
);
struct
address_space
mftbmp_mapping
;
/* Page cache for $MFT/$BITMAP. */
run_list
mftbmp_rl
;
/* Run list for $MFT/$BITMAP. */
...
...
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