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
0f9ee687
Commit
0f9ee687
authored
Apr 30, 2003
by
Anton Altaparmakov
Browse files
Options
Browse Files
Download
Plain Diff
Merge cantab.net:/home/aia21/bklinux-2.5
into cantab.net:/home/aia21/ntfs-2.5
parents
d1f880ab
d73e26f5
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
231 additions
and
128 deletions
+231
-128
Documentation/filesystems/ntfs.txt
Documentation/filesystems/ntfs.txt
+10
-0
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+19
-0
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/attrib.c
fs/ntfs/attrib.c
+12
-11
fs/ntfs/compress.c
fs/ntfs/compress.c
+70
-20
fs/ntfs/inode.c
fs/ntfs/inode.c
+1
-11
fs/ntfs/super.c
fs/ntfs/super.c
+108
-77
fs/ntfs/unistr.c
fs/ntfs/unistr.c
+5
-3
fs/ntfs/upcase.c
fs/ntfs/upcase.c
+5
-5
No files found.
Documentation/filesystems/ntfs.txt
View file @
0f9ee687
...
@@ -247,6 +247,16 @@ ChangeLog
...
@@ -247,6 +247,16 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.1.3:
- Major bug fixes for reading files and volumes in corner cases which
were being hit by Windows 2k/XP users.
2.1.2:
- Major bug fixes aleviating the hangs in statfs experienced by some
users.
2.1.1:
- Update handling of compressed files so people no longer get the
frequently reported warning messages about initialized_size !=
data_size.
2.1.0:
2.1.0:
- Add configuration option for developmental write support.
- Add configuration option for developmental write support.
- Initial implementation of file overwriting. (Writes to resident files
- Initial implementation of file overwriting. (Writes to resident files
...
...
fs/ntfs/ChangeLog
View file @
0f9ee687
...
@@ -20,6 +20,25 @@ ToDo:
...
@@ -20,6 +20,25 @@ ToDo:
sufficient for synchronisation here. We then just need to make sure
sufficient for synchronisation here. We then just need to make sure
ntfs_readpage/writepage/truncate interoperate properly with us.
ntfs_readpage/writepage/truncate interoperate properly with us.
2.1.3 - Important bug fixes in corner cases.
- super.c::parse_ntfs_boot_sector(): Correct the check for 64-bit
clusters. (Philipp Thomas)
- attrib.c::load_attribute_list(): Fix bug when initialized_size is a
multiple of the block_size but not the cluster size. (Szabolcs
Szakacsits <szaka@sienet.hu>)
2.1.2 - Important bug fixes aleviating the hangs in statfs.
- Fix buggy free cluster and free inode determination logic.
2.1.1 - Minor updates.
- Add handling for initialized_size != data_size in compressed files.
- Reduce function local stack usage from 0x3d4 bytes to just noise in
fs/ntfs/upcase.c. (Randy Dunlap <rddunlap@osdl.ord>)
- Remove compiler warnings for newer gcc.
2.1.0 - First steps towards write support: implement file overwrite.
2.1.0 - First steps towards write support: implement file overwrite.
- Add configuration option for developmental write support with an
- Add configuration option for developmental write support with an
...
...
fs/ntfs/Makefile
View file @
0f9ee687
...
@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
...
@@ -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
\
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
mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.1.
0
\"
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.1.
3
\"
ifeq
($(CONFIG_NTFS_DEBUG),y)
ifeq
($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS
+=
-DDEBUG
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/attrib.c
View file @
0f9ee687
/**
/**
* attrib.c - NTFS attribute operations. Part of the Linux-NTFS project.
* attrib.c - NTFS attribute operations. Part of the Linux-NTFS project.
*
*
* Copyright (c) 2001
,2002 Anton Altaparmakov.
* Copyright (c) 2001
-2003 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
* 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
...
@@ -1180,12 +1180,15 @@ BOOL find_attr(const ATTR_TYPES type, const uchar_t *name, const u32 name_len,
...
@@ -1180,12 +1180,15 @@ BOOL find_attr(const ATTR_TYPES type, const uchar_t *name, const u32 name_len,
return
TRUE
;
return
TRUE
;
/* @val is present; compare values. */
/* @val is present; compare values. */
else
{
else
{
u32
vl
;
register
int
rc
;
register
int
rc
;
vl
=
le32_to_cpu
(
a
->
_ARA
(
value_length
));
if
(
vl
>
val_len
)
vl
=
val_len
;
rc
=
memcmp
(
val
,
(
u8
*
)
a
+
le16_to_cpu
(
rc
=
memcmp
(
val
,
(
u8
*
)
a
+
le16_to_cpu
(
a
->
_ARA
(
value_offset
)),
a
->
_ARA
(
value_offset
)),
vl
);
min_t
(
const
u32
,
val_len
,
le32_to_cpu
(
a
->
_ARA
(
value_length
))));
/*
/*
* If @val collates before the current attribute's
* If @val collates before the current attribute's
* value, there is no matching attribute.
* value, there is no matching attribute.
...
@@ -1235,11 +1238,9 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al,
...
@@ -1235,11 +1238,9 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al,
unsigned
char
block_size_bits
=
sb
->
s_blocksize_bits
;
unsigned
char
block_size_bits
=
sb
->
s_blocksize_bits
;
ntfs_debug
(
"Entering."
);
ntfs_debug
(
"Entering."
);
#ifdef DEBUG
if
(
!
vol
||
!
run_list
||
!
al
||
size
<=
0
||
initialized_size
<
0
||
if
(
!
vol
||
!
run_list
||
!
al
||
size
<=
0
||
initialized_size
<
0
||
initialized_size
>
size
)
initialized_size
>
size
)
return
-
EINVAL
;
return
-
EINVAL
;
#endif
if
(
!
initialized_size
)
{
if
(
!
initialized_size
)
{
memset
(
al
,
0
,
size
);
memset
(
al
,
0
,
size
);
return
0
;
return
0
;
...
@@ -1270,8 +1271,8 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al,
...
@@ -1270,8 +1271,8 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al,
"read attribute list."
);
"read attribute list."
);
goto
err_out
;
goto
err_out
;
}
}
if
(
al
+
block_size
>
al_end
)
if
(
al
+
block_size
>
=
al_end
)
goto
do_
parti
al
;
goto
do_
fin
al
;
memcpy
(
al
,
bh
->
b_data
,
block_size
);
memcpy
(
al
,
bh
->
b_data
,
block_size
);
brelse
(
bh
);
brelse
(
bh
);
al
+=
block_size
;
al
+=
block_size
;
...
@@ -1285,7 +1286,7 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al,
...
@@ -1285,7 +1286,7 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al,
done:
done:
up_read
(
&
run_list
->
lock
);
up_read
(
&
run_list
->
lock
);
return
err
;
return
err
;
do_
parti
al:
do_
fin
al:
if
(
al
<
al_end
)
{
if
(
al
<
al_end
)
{
/* Partial block. */
/* Partial block. */
memcpy
(
al
,
bh
->
b_data
,
al_end
-
al
);
memcpy
(
al
,
bh
->
b_data
,
al_end
-
al
);
...
...
fs/ntfs/compress.c
View file @
0f9ee687
...
@@ -2,8 +2,8 @@
...
@@ -2,8 +2,8 @@
* compress.c - NTFS kernel compressed attributes handling.
* compress.c - NTFS kernel compressed attributes handling.
* Part of the Linux-NTFS project.
* Part of the Linux-NTFS project.
*
*
* Copyright (c) 2001
,2002 Anton Altaparmakov.
* Copyright (c) 2001
-2003 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
* 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
...
@@ -44,7 +44,7 @@ typedef enum {
...
@@ -44,7 +44,7 @@ typedef enum {
* The maximum compression block size is by definition 16 * the cluster
* The maximum compression block size is by definition 16 * the cluster
* size, with the maximum supported cluster size being 4kiB. Thus the
* size, with the maximum supported cluster size being 4kiB. Thus the
* maximum compression buffer size is 64kiB, so we use this when
* maximum compression buffer size is 64kiB, so we use this when
* initializing the
per-CPU buffers
.
* initializing the
compression buffer
.
*/
*/
NTFS_MAX_CB_SIZE
=
64
*
1024
,
NTFS_MAX_CB_SIZE
=
64
*
1024
,
}
ntfs_compression_constants
;
}
ntfs_compression_constants
;
...
@@ -88,6 +88,40 @@ void free_compression_buffers(void)
...
@@ -88,6 +88,40 @@ void free_compression_buffers(void)
ntfs_compression_buffer
=
NULL
;
ntfs_compression_buffer
=
NULL
;
}
}
/**
* zero_partial_compressed_page - zero out of bounds compressed page region
*/
static
void
zero_partial_compressed_page
(
ntfs_inode
*
ni
,
struct
page
*
page
)
{
u8
*
kp
=
page_address
(
page
);
unsigned
int
kp_ofs
;
ntfs_debug
(
"Zeroing page region outside initialized size."
);
if
(((
s64
)
page
->
index
<<
PAGE_CACHE_SHIFT
)
>=
ni
->
initialized_size
)
{
/*
* FIXME: Using clear_page() will become wrong when we get
* PAGE_CACHE_SIZE != PAGE_SIZE but for now there is no problem.
*/
clear_page
(
kp
);
return
;
}
kp_ofs
=
ni
->
initialized_size
&
~
PAGE_CACHE_MASK
;
memset
(
kp
+
kp_ofs
,
0
,
PAGE_CACHE_SIZE
-
kp_ofs
);
return
;
}
/**
* handle_bounds_compressed_page - test for&handle out of bounds compressed page
*/
static
inline
void
handle_bounds_compressed_page
(
ntfs_inode
*
ni
,
struct
page
*
page
)
{
if
((
page
->
index
>=
(
ni
->
initialized_size
>>
PAGE_CACHE_SHIFT
))
&&
(
ni
->
initialized_size
<
VFS_I
(
ni
)
->
i_size
))
zero_partial_compressed_page
(
ni
,
page
);
return
;
}
/**
/**
* ntfs_decompress - decompress a compression block into an array of pages
* ntfs_decompress - decompress a compression block into an array of pages
* @dest_pages: destination array of pages
* @dest_pages: destination array of pages
...
@@ -164,7 +198,7 @@ static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
...
@@ -164,7 +198,7 @@ static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
cb
-
cb_start
);
cb
-
cb_start
);
/* Have we reached the end of the compression block? */
/* Have we reached the end of the compression block? */
if
(
cb
==
cb_end
||
!
le16_to_cpup
(
cb
))
{
if
(
cb
==
cb_end
||
!
le16_to_cpup
(
(
u16
*
)
cb
))
{
int
i
;
int
i
;
ntfs_debug
(
"Completed. Returning success (0)."
);
ntfs_debug
(
"Completed. Returning success (0)."
);
...
@@ -173,19 +207,29 @@ static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
...
@@ -173,19 +207,29 @@ static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
/* We can sleep from now on, so we drop lock. */
/* We can sleep from now on, so we drop lock. */
spin_unlock
(
&
ntfs_cb_lock
);
spin_unlock
(
&
ntfs_cb_lock
);
/* Second stage: finalize completed pages. */
/* Second stage: finalize completed pages. */
for
(
i
=
0
;
i
<
nr_completed_pages
;
i
++
)
{
if
(
nr_completed_pages
>
0
)
{
int
di
=
completed_pages
[
i
];
struct
page
*
page
=
dest_pages
[
completed_pages
[
0
]];
ntfs_inode
*
ni
=
NTFS_I
(
page
->
mapping
->
host
);
dp
=
dest_pages
[
di
];
flush_dcache_page
(
dp
);
for
(
i
=
0
;
i
<
nr_completed_pages
;
i
++
)
{
kunmap
(
dp
);
int
di
=
completed_pages
[
i
];
SetPageUptodate
(
dp
);
unlock_page
(
dp
);
dp
=
dest_pages
[
di
];
if
(
di
==
xpage
)
/*
*
xpage_done
=
1
;
* If we are outside the initialized size, zero
else
* the out of bounds page range.
page_cache_release
(
dp
);
*/
dest_pages
[
di
]
=
NULL
;
handle_bounds_compressed_page
(
ni
,
dp
);
flush_dcache_page
(
dp
);
kunmap
(
dp
);
SetPageUptodate
(
dp
);
unlock_page
(
dp
);
if
(
di
==
xpage
)
*
xpage_done
=
1
;
else
page_cache_release
(
dp
);
dest_pages
[
di
]
=
NULL
;
}
}
}
return
err
;
return
err
;
}
}
...
@@ -204,7 +248,8 @@ static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
...
@@ -204,7 +248,8 @@ static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
/* Setup the current sub-block source pointers and validate range. */
/* Setup the current sub-block source pointers and validate range. */
cb_sb_start
=
cb
;
cb_sb_start
=
cb
;
cb_sb_end
=
cb_sb_start
+
(
le16_to_cpup
(
cb
)
&
NTFS_SB_SIZE_MASK
)
+
3
;
cb_sb_end
=
cb_sb_start
+
(
le16_to_cpup
((
u16
*
)
cb
)
&
NTFS_SB_SIZE_MASK
)
+
3
;
if
(
cb_sb_end
>
cb_end
)
if
(
cb_sb_end
>
cb_end
)
goto
return_overflow
;
goto
return_overflow
;
...
@@ -225,7 +270,7 @@ static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
...
@@ -225,7 +270,7 @@ static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
dp_addr
=
(
u8
*
)
page_address
(
dp
)
+
do_sb_start
;
dp_addr
=
(
u8
*
)
page_address
(
dp
)
+
do_sb_start
;
/* Now, we are ready to process the current sub-block (sb). */
/* Now, we are ready to process the current sub-block (sb). */
if
(
!
(
le16_to_cpup
(
cb
)
&
NTFS_SB_IS_COMPRESSED
))
{
if
(
!
(
le16_to_cpup
(
(
u16
*
)
cb
)
&
NTFS_SB_IS_COMPRESSED
))
{
ntfs_debug
(
"Found uncompressed sub-block."
);
ntfs_debug
(
"Found uncompressed sub-block."
);
/* This sb is not compressed, just copy it into destination. */
/* This sb is not compressed, just copy it into destination. */
...
@@ -330,7 +375,7 @@ static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
...
@@ -330,7 +375,7 @@ static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
lg
++
;
lg
++
;
/* Get the phrase token into i. */
/* Get the phrase token into i. */
pt
=
le16_to_cpup
(
cb
);
pt
=
le16_to_cpup
(
(
u16
*
)
cb
);
/*
/*
* Calculate starting position of the byte sequence in
* Calculate starting position of the byte sequence in
...
@@ -763,6 +808,11 @@ int ntfs_read_compressed_block(struct page *page)
...
@@ -763,6 +808,11 @@ int ntfs_read_compressed_block(struct page *page)
for
(;
cur2_page
<
cb_max_page
;
cur2_page
++
)
{
for
(;
cur2_page
<
cb_max_page
;
cur2_page
++
)
{
page
=
pages
[
cur2_page
];
page
=
pages
[
cur2_page
];
if
(
page
)
{
if
(
page
)
{
/*
* If we are outside the initialized size, zero
* the out of bounds page range.
*/
handle_bounds_compressed_page
(
ni
,
page
);
flush_dcache_page
(
page
);
flush_dcache_page
(
page
);
kunmap
(
page
);
kunmap
(
page
);
SetPageUptodate
(
page
);
SetPageUptodate
(
page
);
...
...
fs/ntfs/inode.c
View file @
0f9ee687
/**
/**
* inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project.
* inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project.
*
*
* Copyright (c) 2001
,2002 Anton Altaparmakov.
* Copyright (c) 2001
-2003 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
...
@@ -996,16 +996,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
...
@@ -996,16 +996,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
if
(
NInoCompressed
(
ni
))
{
if
(
NInoCompressed
(
ni
))
{
ni
->
_ICF
(
compressed_size
)
=
sle64_to_cpu
(
ni
->
_ICF
(
compressed_size
)
=
sle64_to_cpu
(
ctx
->
attr
->
_ANR
(
compressed_size
));
ctx
->
attr
->
_ANR
(
compressed_size
));
if
(
vi
->
i_size
!=
ni
->
initialized_size
)
ntfs_warning
(
vi
->
i_sb
,
"BUG: Found "
"compressed file with "
"data_size not equal to "
"initialized_size. This will "
"probably cause problems when "
"trying to access the file. "
"Please notify linux-ntfs-dev@"
"lists.sf.net that you saw "
"this message. Thanks!"
);
}
}
}
else
{
/* Resident attribute. */
}
else
{
/* Resident attribute. */
/*
/*
...
...
fs/ntfs/super.c
View file @
0f9ee687
/*
/*
* 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
,2002 Anton Altaparmakov.
* Copyright (c) 2001
-2003 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
* 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
...
@@ -619,9 +619,8 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
...
@@ -619,9 +619,8 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
* the same as it is much faster on 32-bit CPUs.
* the same as it is much faster on 32-bit CPUs.
*/
*/
ll
=
sle64_to_cpu
(
b
->
number_of_sectors
)
>>
sectors_per_cluster_bits
;
ll
=
sle64_to_cpu
(
b
->
number_of_sectors
)
>>
sectors_per_cluster_bits
;
if
((
u64
)
ll
>=
1ULL
<<
(
sizeof
(
unsigned
long
)
*
8
))
{
if
((
u64
)
ll
>=
1ULL
<<
32
)
{
ntfs_error
(
vol
->
sb
,
"Cannot handle %i-bit clusters. Sorry."
,
ntfs_error
(
vol
->
sb
,
"Cannot handle 64-bit clusters. Sorry."
);
sizeof
(
unsigned
long
)
*
4
);
return
FALSE
;
return
FALSE
;
}
}
vol
->
nr_clusters
=
ll
;
vol
->
nr_clusters
=
ll
;
...
@@ -1060,78 +1059,93 @@ static void ntfs_put_super(struct super_block *vfs_sb)
...
@@ -1060,78 +1059,93 @@ static void ntfs_put_super(struct super_block *vfs_sb)
* get_nr_free_clusters - return the number of free clusters on a volume
* get_nr_free_clusters - return the number of free clusters on a volume
* @vol: ntfs volume for which to obtain free cluster count
* @vol: ntfs volume for which to obtain free cluster count
*
*
* Calculate the number of free clusters on the mounted NTFS volume @vol.
* Calculate the number of free clusters on the mounted NTFS volume @vol. We
* actually calculate the number of clusters in use instead because this
* allows us to not care about partial pages as these will be just zero filled
* and hence not be counted as allocated clusters.
*
*
* Errors are ignored and we just return the number of free clusters we have
* The only particularity is that clusters beyond the end of the logical ntfs
* found. This means we return an underestimate on error.
* volume will be marked as allocated to prevent errors which means we have to
* discount those at the end. This is important as the cluster bitmap always
* has a size in multiples of 8 bytes, i.e. up to 63 clusters could be outside
* the logical volume and marked in use when they are not as they do not exist.
*
* If any pages cannot be read we assume all clusters in the erroring pages are
* in use. This means we return an underestimate on errors which is better than
* an overestimate.
*/
*/
static
s64
get_nr_free_clusters
(
ntfs_volume
*
vol
)
static
s64
get_nr_free_clusters
(
ntfs_volume
*
vol
)
{
{
s64
nr_free
=
vol
->
nr_clusters
;
u32
*
kaddr
;
struct
address_space
*
mapping
=
vol
->
lcnbmp_ino
->
i_mapping
;
struct
address_space
*
mapping
=
vol
->
lcnbmp_ino
->
i_mapping
;
filler_t
*
readpage
=
(
filler_t
*
)
mapping
->
a_ops
->
readpage
;
filler_t
*
readpage
=
(
filler_t
*
)
mapping
->
a_ops
->
readpage
;
struct
page
*
page
;
struct
page
*
page
;
unsigned
long
index
,
max_index
;
unsigned
long
index
,
max_index
;
unsigned
int
max_size
,
i
;
unsigned
int
max_size
;
s64
nr_free
=
0LL
;
u32
*
b
;
ntfs_debug
(
"Entering."
);
ntfs_debug
(
"Entering."
);
/* Serialize accesses to the cluster bitmap. */
/* Serialize accesses to the cluster bitmap. */
down_read
(
&
vol
->
lcnbmp_lock
);
down_read
(
&
vol
->
lcnbmp_lock
);
/*
/*
* Convert the number of bits into bytes rounded up, then convert into
* Convert the number of bits into bytes rounded up, then convert into
* multiples of PAGE_CACHE_SIZE.
* multiples of PAGE_CACHE_SIZE, rounding up so that if we have one
* full and one partial page max_index = 2.
*/
*/
max_index
=
(
vol
->
nr_clusters
+
7
)
>>
(
3
+
PAGE_CACHE_SHIFT
);
max_index
=
(((
vol
->
nr_clusters
+
7
)
>>
3
)
+
PAGE_CACHE_SIZE
-
1
)
>>
PAGE_CACHE_SHIFT
;
/* Use multiples of 4 bytes. */
/* Use multiples of 4 bytes. */
max_size
=
PAGE_CACHE_SIZE
>>
2
;
max_size
=
PAGE_CACHE_SIZE
>>
2
;
ntfs_debug
(
"Reading $B
ITMAP
, max_index = 0x%lx, max_size = 0x%x."
,
ntfs_debug
(
"Reading $B
itmap
, max_index = 0x%lx, max_size = 0x%x."
,
max_index
,
max_size
);
max_index
,
max_size
);
for
(
index
=
0UL
;
index
<
max_index
;)
{
for
(
index
=
0UL
;
index
<
max_index
;
index
++
)
{
handle_partial_page:
unsigned
int
i
;
/*
/*
* Read the page from page cache, getting it from backing store
* Read the page from page cache, getting it from backing store
* if necessary, and increment the use count.
* if necessary, and increment the use count.
*/
*/
page
=
read_cache_page
(
mapping
,
index
++
,
(
filler_t
*
)
readpage
,
page
=
read_cache_page
(
mapping
,
index
,
(
filler_t
*
)
readpage
,
NULL
);
NULL
);
/* Ignore pages which errored synchronously. */
/* Ignore pages which errored synchronously. */
if
(
IS_ERR
(
page
))
{
if
(
IS_ERR
(
page
))
{
ntfs_debug
(
"Sync read_cache_page() error. Skipping "
ntfs_debug
(
"Sync read_cache_page() error. Skipping "
"page (index 0x%lx)."
,
index
-
1
);
"page (index 0x%lx)."
,
index
);
nr_free
-=
PAGE_CACHE_SIZE
*
8
;
continue
;
continue
;
}
}
wait_on_page_locked
(
page
);
wait_on_page_locked
(
page
);
/* Ignore pages which errored asynchronously. */
if
(
!
PageUptodate
(
page
))
{
if
(
!
PageUptodate
(
page
))
{
ntfs_debug
(
"Async read_cache_page() error. Skipping "
ntfs_debug
(
"Async read_cache_page() error. Skipping "
"page (index 0x%lx)."
,
index
-
1
);
"page (index 0x%lx)."
,
index
);
/* Ignore pages which errored asynchronously. */
page_cache_release
(
page
);
page_cache_release
(
page
);
nr_free
-=
PAGE_CACHE_SIZE
*
8
;
continue
;
continue
;
}
}
b
=
(
u32
*
)
kmap
(
page
);
kaddr
=
(
u32
*
)
kmap_atomic
(
page
,
KM_USER0
);
/* For each 4 bytes, add up the number zero bits. */
for
(
i
=
0
;
i
<
max_size
;
i
++
)
nr_free
+=
(
s64
)(
32
-
hweight32
(
b
[
i
]));
kunmap
(
page
);
page_cache_release
(
page
);
}
if
(
max_size
==
PAGE_CACHE_SIZE
>>
2
)
{
/*
/*
* Get the multiples of 4 bytes in use in the final partial
* For each 4 bytes, subtract the number of set bits. If this
* page.
* is the last page and it is partial we don't really care as
* it just means we do a little extra work but it won't affect
* the result as all out of range bytes are set to zero by
* ntfs_readpage().
*/
*/
max_size
=
((((
vol
->
nr_clusters
+
7
)
>>
3
)
&
~
PAGE_CACHE_MASK
)
for
(
i
=
0
;
i
<
max_size
;
i
++
)
+
3
)
>>
2
;
nr_free
-=
(
s64
)
hweight32
(
kaddr
[
i
]);
/* If there is a partial page go back and do it. */
kunmap_atomic
(
kaddr
,
KM_USER0
);
if
(
max_size
)
{
page_cache_release
(
page
);
ntfs_debug
(
"Handling partial page, max_size = 0x%x."
,
max_size
);
goto
handle_partial_page
;
}
}
}
ntfs_debug
(
"Finished reading $BITMAP, last index = 0x%lx"
,
index
-
1
);
ntfs_debug
(
"Finished reading $Bitmap, last index = 0x%lx."
,
index
-
1
);
/*
* Fixup for eventual bits outside logical ntfs volume (see function
* description above).
*/
if
(
vol
->
nr_clusters
&
63
)
nr_free
+=
64
-
(
vol
->
nr_clusters
&
63
);
up_read
(
&
vol
->
lcnbmp_lock
);
up_read
(
&
vol
->
lcnbmp_lock
);
/* If errors occured we may well have gone below zero, fix this. */
if
(
nr_free
<
0
)
nr_free
=
0
;
ntfs_debug
(
"Exiting."
);
ntfs_debug
(
"Exiting."
);
return
nr_free
;
return
nr_free
;
}
}
...
@@ -1141,64 +1155,81 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
...
@@ -1141,64 +1155,81 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
* @vol: ntfs volume for which to obtain free inode count
* @vol: ntfs volume for which to obtain free inode count
*
*
* Calculate the number of free mft records (inodes) on the mounted NTFS
* Calculate the number of free mft records (inodes) on the mounted NTFS
* volume @vol.
* volume @vol. We actually calculate the number of mft records in use instead
* because this allows us to not care about partial pages as these will be just
* zero filled and hence not be counted as allocated mft record.
*
*
* Errors are ignored and we just return the number of free inodes we have
* If any pages cannot be read we assume all mft records in the erroring pages
* found. This means we return an underestimate on error.
* are in use. This means we return an underestimate on errors which is better
* than an overestimate.
*
*
* NOTE: Caller must hold mftbmp_lock rw_semaphore for reading or writing.
* NOTE: Caller must hold mftbmp_lock rw_semaphore for reading or writing.
*/
*/
static
unsigned
long
__get_nr_free_mft_records
(
ntfs_volume
*
vol
)
static
unsigned
long
__get_nr_free_mft_records
(
ntfs_volume
*
vol
)
{
{
struct
address_space
*
mapping
;
s64
nr_free
=
vol
->
nr_mft_records
;
u32
*
kaddr
;
struct
address_space
*
mapping
=
vol
->
mftbmp_ino
->
i_mapping
;
filler_t
*
readpage
=
(
filler_t
*
)
mapping
->
a_ops
->
readpage
;
struct
page
*
page
;
struct
page
*
page
;
unsigned
long
index
,
max_index
,
nr_free
=
0
;
unsigned
long
index
,
max_index
;
unsigned
int
max_size
,
i
;
unsigned
int
max_size
;
u32
*
b
;
mapping
=
vol
->
mftbmp_ino
->
i_mapping
;
ntfs_debug
(
"Entering."
)
;
/*
/*
* Convert the number of bits into bytes rounded up to a multiple of 8
* Convert the number of bits into bytes rounded up, then convert into
* bytes, then convert into multiples of PAGE_CACHE_SIZE.
* multiples of PAGE_CACHE_SIZE, rounding up so that if we have one
* full and one partial page max_index = 2.
*/
*/
max_index
=
(((
vol
->
nr_mft_records
+
7
)
>>
3
)
+
7
)
>>
PAGE_CACHE_SHIFT
;
max_index
=
(((
vol
->
nr_mft_records
+
7
)
>>
3
)
+
PAGE_CACHE_SIZE
-
1
)
>>
PAGE_CACHE_SHIFT
;
/* Use multiples of 4 bytes. */
/* Use multiples of 4 bytes. */
max_size
=
PAGE_CACHE_SIZE
>>
2
;
max_size
=
PAGE_CACHE_SIZE
>>
2
;
ntfs_debug
(
"Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = "
ntfs_debug
(
"Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = "
"0x%x."
,
max_index
,
max_size
);
"0x%x."
,
max_index
,
max_size
);
for
(
index
=
0UL
;
index
<
max_index
;)
{
for
(
index
=
0UL
;
index
<
max_index
;
index
++
)
{
handle_partial_page:
unsigned
int
i
;
page
=
ntfs_map_page
(
mapping
,
index
++
);
/*
* Read the page from page cache, getting it from backing store
* if necessary, and increment the use count.
*/
page
=
read_cache_page
(
mapping
,
index
,
(
filler_t
*
)
readpage
,
NULL
);
/* Ignore pages which errored synchronously. */
if
(
IS_ERR
(
page
))
{
if
(
IS_ERR
(
page
))
{
ntfs_debug
(
"ntfs_map_page() error. Skipping page "
ntfs_debug
(
"Sync read_cache_page() error. Skipping "
"(index 0x%lx)."
,
index
-
1
);
"page (index 0x%lx)."
,
index
);
nr_free
-=
PAGE_CACHE_SIZE
*
8
;
continue
;
continue
;
}
}
b
=
(
u32
*
)
page_address
(
page
);
wait_on_page_locked
(
page
);
/* For each 4 bytes, add up the number of zero bits. */
/* Ignore pages which errored asynchronously. */
for
(
i
=
0
;
i
<
max_size
;
i
++
)
if
(
!
PageUptodate
(
page
))
{
nr_free
+=
32
-
hweight32
(
b
[
i
]);
ntfs_debug
(
"Async read_cache_page() error. Skipping "
ntfs_unmap_page
(
page
);
"page (index 0x%lx)."
,
index
);
}
page_cache_release
(
page
);
if
(
index
==
max_index
)
{
nr_free
-=
PAGE_CACHE_SIZE
*
8
;
continue
;
}
kaddr
=
(
u32
*
)
kmap_atomic
(
page
,
KM_USER0
);
/*
/*
* Get the multiples of 4 bytes in use in the final partial
* For each 4 bytes, subtract the number of set bits. If this
* page.
* is the last page and it is partial we don't really care as
* it just means we do a little extra work but it won't affect
* the result as all out of range bytes are set to zero by
* ntfs_readpage().
*/
*/
max_size
=
((((((
vol
->
nr_mft_records
+
7
)
>>
3
)
+
7
)
&
~
7
)
&
for
(
i
=
0
;
i
<
max_size
;
i
++
)
~
PAGE_CACHE_MASK
)
+
3
)
>>
2
;
nr_free
-=
(
s64
)
hweight32
(
kaddr
[
i
]);
/* If there is a partial page go back and do it. */
kunmap_atomic
(
kaddr
,
KM_USER0
);
if
(
max_size
)
{
page_cache_release
(
page
);
/* Compensate for out of bounds zero bits. */
if
((
i
=
vol
->
nr_mft_records
&
31
))
nr_free
-=
32
-
i
;
ntfs_debug
(
"Handling partial page, max_size = 0x%x"
,
max_size
);
goto
handle_partial_page
;
}
}
}
ntfs_debug
(
"Finished reading $MFT/$BITMAP, last index = 0x%lx"
,
ntfs_debug
(
"Finished reading $MFT/$BITMAP, last index = 0x%lx
.
"
,
index
-
1
);
index
-
1
);
/* If errors occured we may well have gone below zero, fix this. */
if
(
nr_free
<
0
)
nr_free
=
0
;
ntfs_debug
(
"Exiting."
);
return
nr_free
;
return
nr_free
;
}
}
...
@@ -1761,7 +1792,7 @@ static void __exit exit_ntfs_fs(void)
...
@@ -1761,7 +1792,7 @@ static void __exit exit_ntfs_fs(void)
}
}
MODULE_AUTHOR
(
"Anton Altaparmakov <aia21@cantab.net>"
);
MODULE_AUTHOR
(
"Anton Altaparmakov <aia21@cantab.net>"
);
MODULE_DESCRIPTION
(
"NTFS 1.2/3.x driver - Copyright (c) 2001-200
2
Anton Altaparmakov"
);
MODULE_DESCRIPTION
(
"NTFS 1.2/3.x driver - Copyright (c) 2001-200
3
Anton Altaparmakov"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
#ifdef DEBUG
#ifdef DEBUG
MODULE_PARM
(
debug_msgs
,
"i"
);
MODULE_PARM
(
debug_msgs
,
"i"
);
...
...
fs/ntfs/unistr.c
View file @
0f9ee687
/*
/*
* unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project.
* unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project.
*
*
* Copyright (c) 2001
Anton Altaparmakov.
* Copyright (c) 2001
-2003 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
...
@@ -96,10 +96,12 @@ int ntfs_collate_names(const uchar_t *name1, const u32 name1_len,
...
@@ -96,10 +96,12 @@ int ntfs_collate_names(const uchar_t *name1, const u32 name1_len,
const
int
err_val
,
const
IGNORE_CASE_BOOL
ic
,
const
int
err_val
,
const
IGNORE_CASE_BOOL
ic
,
const
uchar_t
*
upcase
,
const
u32
upcase_len
)
const
uchar_t
*
upcase
,
const
u32
upcase_len
)
{
{
u32
cnt
;
u32
cnt
,
min_len
;
const
u32
min_len
=
min_t
(
const
u32
,
name1_len
,
name2_len
);
uchar_t
c1
,
c2
;
uchar_t
c1
,
c2
;
min_len
=
name1_len
;
if
(
name1_len
>
name2_len
)
min_len
=
name2_len
;
for
(
cnt
=
0
;
cnt
<
min_len
;
++
cnt
)
{
for
(
cnt
=
0
;
cnt
<
min_len
;
++
cnt
)
{
c1
=
le16_to_cpu
(
*
name1
++
);
c1
=
le16_to_cpu
(
*
name1
++
);
c2
=
le16_to_cpu
(
*
name2
++
);
c2
=
le16_to_cpu
(
*
name2
++
);
...
...
fs/ntfs/upcase.c
View file @
0f9ee687
...
@@ -2,8 +2,8 @@
...
@@ -2,8 +2,8 @@
* upcase.c - Generate the full NTFS Unicode upcase table in little endian.
* upcase.c - Generate the full NTFS Unicode upcase table in little endian.
* Part of the Linux-NTFS project.
* Part of the Linux-NTFS project.
*
*
* Copyright (
C
) 2001 Richard Russon <ntfs@flatcap.org>
* Copyright (
c
) 2001 Richard Russon <ntfs@flatcap.org>
* Copyright (c) 2001
,2002
Anton Altaparmakov
* Copyright (c) 2001
-2003
Anton Altaparmakov
*
*
* Modified for mkntfs inclusion 9 June 2001 by Anton Altaparmakov.
* Modified for mkntfs inclusion 9 June 2001 by Anton Altaparmakov.
* Modified for kernel inclusion 10 September 2001 by Anton Altparmakov.
* Modified for kernel inclusion 10 September 2001 by Anton Altparmakov.
...
@@ -28,7 +28,7 @@
...
@@ -28,7 +28,7 @@
uchar_t
*
generate_default_upcase
(
void
)
uchar_t
*
generate_default_upcase
(
void
)
{
{
const
int
uc_run_table
[][
3
]
=
{
/* Start, End, Add */
static
const
int
uc_run_table
[][
3
]
=
{
/* Start, End, Add */
{
0x0061
,
0x007B
,
-
32
},
{
0x0451
,
0x045D
,
-
80
},
{
0x1F70
,
0x1F72
,
74
},
{
0x0061
,
0x007B
,
-
32
},
{
0x0451
,
0x045D
,
-
80
},
{
0x1F70
,
0x1F72
,
74
},
{
0x00E0
,
0x00F7
,
-
32
},
{
0x045E
,
0x0460
,
-
80
},
{
0x1F72
,
0x1F76
,
86
},
{
0x00E0
,
0x00F7
,
-
32
},
{
0x045E
,
0x0460
,
-
80
},
{
0x1F72
,
0x1F76
,
86
},
{
0x00F8
,
0x00FF
,
-
32
},
{
0x0561
,
0x0587
,
-
48
},
{
0x1F76
,
0x1F78
,
100
},
{
0x00F8
,
0x00FF
,
-
32
},
{
0x0561
,
0x0587
,
-
48
},
{
0x1F76
,
0x1F78
,
100
},
...
@@ -45,7 +45,7 @@ uchar_t *generate_default_upcase(void)
...
@@ -45,7 +45,7 @@ uchar_t *generate_default_upcase(void)
{
0
}
{
0
}
};
};
const
int
uc_dup_table
[][
2
]
=
{
/* Start, End */
static
const
int
uc_dup_table
[][
2
]
=
{
/* Start, End */
{
0x0100
,
0x012F
},
{
0x01A0
,
0x01A6
},
{
0x03E2
,
0x03EF
},
{
0x04CB
,
0x04CC
},
{
0x0100
,
0x012F
},
{
0x01A0
,
0x01A6
},
{
0x03E2
,
0x03EF
},
{
0x04CB
,
0x04CC
},
{
0x0132
,
0x0137
},
{
0x01B3
,
0x01B7
},
{
0x0460
,
0x0481
},
{
0x04D0
,
0x04EB
},
{
0x0132
,
0x0137
},
{
0x01B3
,
0x01B7
},
{
0x0460
,
0x0481
},
{
0x04D0
,
0x04EB
},
{
0x0139
,
0x0149
},
{
0x01CD
,
0x01DD
},
{
0x0490
,
0x04BF
},
{
0x04EE
,
0x04F5
},
{
0x0139
,
0x0149
},
{
0x01CD
,
0x01DD
},
{
0x0490
,
0x04BF
},
{
0x04EE
,
0x04F5
},
...
@@ -55,7 +55,7 @@ uchar_t *generate_default_upcase(void)
...
@@ -55,7 +55,7 @@ uchar_t *generate_default_upcase(void)
{
0
}
{
0
}
};
};
const
int
uc_word_table
[][
2
]
=
{
/* Offset, Value */
static
const
int
uc_word_table
[][
2
]
=
{
/* Offset, Value */
{
0x00FF
,
0x0178
},
{
0x01AD
,
0x01AC
},
{
0x01F3
,
0x01F1
},
{
0x0269
,
0x0196
},
{
0x00FF
,
0x0178
},
{
0x01AD
,
0x01AC
},
{
0x01F3
,
0x01F1
},
{
0x0269
,
0x0196
},
{
0x0183
,
0x0182
},
{
0x01B0
,
0x01AF
},
{
0x0253
,
0x0181
},
{
0x026F
,
0x019C
},
{
0x0183
,
0x0182
},
{
0x01B0
,
0x01AF
},
{
0x0253
,
0x0181
},
{
0x026F
,
0x019C
},
{
0x0185
,
0x0184
},
{
0x01B9
,
0x01B8
},
{
0x0254
,
0x0186
},
{
0x0272
,
0x019D
},
{
0x0185
,
0x0184
},
{
0x01B9
,
0x01B8
},
{
0x0254
,
0x0186
},
{
0x0272
,
0x019D
},
...
...
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