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
b425c8c5
Commit
b425c8c5
authored
Mar 23, 2006
by
Anton Altaparmakov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://imp.csi.cam.ac.uk/home/src/ntfs-2.6-devel/
parents
a05ba456
92fe7b9e
Changes
17
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
291 additions
and
211 deletions
+291
-211
Documentation/filesystems/ntfs.txt
Documentation/filesystems/ntfs.txt
+5
-0
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+28
-2
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/aops.c
fs/ntfs/aops.c
+10
-4
fs/ntfs/attrib.c
fs/ntfs/attrib.c
+19
-16
fs/ntfs/compress.c
fs/ntfs/compress.c
+2
-2
fs/ntfs/file.c
fs/ntfs/file.c
+1
-12
fs/ntfs/inode.c
fs/ntfs/inode.c
+66
-45
fs/ntfs/inode.h
fs/ntfs/inode.h
+7
-6
fs/ntfs/layout.h
fs/ntfs/layout.h
+24
-20
fs/ntfs/mft.c
fs/ntfs/mft.c
+33
-35
fs/ntfs/mft.h
fs/ntfs/mft.h
+1
-4
fs/ntfs/namei.c
fs/ntfs/namei.c
+5
-4
fs/ntfs/ntfs.h
fs/ntfs/ntfs.h
+1
-1
fs/ntfs/runlist.c
fs/ntfs/runlist.c
+8
-4
fs/ntfs/super.c
fs/ntfs/super.c
+48
-36
fs/ntfs/unistr.c
fs/ntfs/unistr.c
+32
-19
No files found.
Documentation/filesystems/ntfs.txt
View file @
b425c8c5
...
...
@@ -457,6 +457,11 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.1.27:
- Implement page migration support so the kernel can move memory used
by NTFS files and directories around for management purposes.
- Add support for writing to sparse files created with Windows XP SP2.
- Many minor improvements and bug fixes.
2.1.26:
- Implement support for sector sizes above 512 bytes (up to the maximum
supported by NTFS which is 4096 bytes).
...
...
fs/ntfs/ChangeLog
View file @
b425c8c5
...
...
@@ -16,8 +16,34 @@ ToDo/Notes:
inode having been discarded already. Whether this can actually ever
happen is unclear however so it is worth waiting until someone hits
the problem.
- Enable the code for setting the NT4 compatibility flag when we start
making NTFS 1.2 specific modifications.
2.1.27 - Various bug fixes and cleanups.
- Fix two compiler warnings on Alpha. Thanks to Andrew Morton for
reporting them.
- Fix an (innocent) off-by-one error in the runlist code.
- Fix a buggette in an "should be impossible" case handling where we
continued the attribute lookup loop instead of aborting it.
- Use buffer_migrate_page() for the ->migratepage function of all ntfs
address space operations.
- Fix comparison of $MFT and $MFTMirr to not bail out when there are
unused, invalid mft records which are the same in both $MFT and
$MFTMirr.
- Add support for sparse files which have a compression unit of 0.
- Remove all the make_bad_inode() calls. This should only be called
from read inode and new inode code paths.
- Limit name length in fs/ntfs/unistr.c::ntfs_nlstoucs() to maximum
allowed by NTFS, i.e. 255 Unicode characters, not including the
terminating NULL (which is not stored on disk).
- Improve comments on file attribute flags in fs/ntfs/layout.h.
- Fix a bug in fs/ntfs/inode.c::ntfs_read_locked_index_inode() where we
forgot to update a temporary variable so loading index inodes which
have an index allocation attribute failed.
- Add a missing call to flush_dcache_mft_record_page() in
fs/ntfs/inode.c::ntfs_write_inode().
- Handle the recently introduced -ENAMETOOLONG return value from
fs/ntfs/unistr.c::ntfs_nlstoucs() in fs/ntfs/namei.c::ntfs_lookup().
- Semaphore to mutex conversion. (Ingo Molnar)
2.1.26 - Minor bug fixes and updates.
...
...
fs/ntfs/Makefile
View file @
b425c8c5
...
...
@@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o
\
unistr.o upcase.o
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.1.2
6
\"
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.1.2
7
\"
ifeq
($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/aops.c
View file @
b425c8c5
...
...
@@ -22,6 +22,7 @@
*/
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
...
...
@@ -1277,18 +1278,18 @@ unm_done:
tni
=
locked_nis
[
nr_locked_nis
];
/* Get the base inode. */
down
(
&
tni
->
extent_lock
);
mutex_lock
(
&
tni
->
extent_lock
);
if
(
tni
->
nr_extents
>=
0
)
base_tni
=
tni
;
else
{
base_tni
=
tni
->
ext
.
base_ntfs_ino
;
BUG_ON
(
!
base_tni
);
}
up
(
&
tni
->
extent_lock
);
mutex_unlock
(
&
tni
->
extent_lock
);
ntfs_debug
(
"Unlocking %s inode 0x%lx."
,
tni
==
base_tni
?
"base"
:
"extent"
,
tni
->
mft_no
);
up
(
&
tni
->
mrec_lock
);
mutex_unlock
(
&
tni
->
mrec_lock
);
atomic_dec
(
&
tni
->
count
);
iput
(
VFS_I
(
base_tni
));
}
...
...
@@ -1529,7 +1530,6 @@ err_out:
"error %i."
,
err
);
SetPageError
(
page
);
NVolSetErrors
(
ni
->
vol
);
make_bad_inode
(
vi
);
}
unlock_page
(
page
);
if
(
ctx
)
...
...
@@ -1551,6 +1551,9 @@ struct address_space_operations ntfs_aops = {
#ifdef NTFS_RW
.
writepage
=
ntfs_writepage
,
/* Write dirty page to disk. */
#endif
/* NTFS_RW */
.
migratepage
=
buffer_migrate_page
,
/* Move a page cache page from
one physical page to an
other. */
};
/**
...
...
@@ -1567,6 +1570,9 @@ struct address_space_operations ntfs_mst_aops = {
without touching the buffers
belonging to the page. */
#endif
/* NTFS_RW */
.
migratepage
=
buffer_migrate_page
,
/* Move a page cache page from
one physical page to an
other. */
};
#ifdef NTFS_RW
...
...
fs/ntfs/attrib.c
View file @
b425c8c5
/**
* attrib.c - NTFS attribute 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
...
...
@@ -1048,7 +1048,7 @@ do_next_attr_loop:
le32_to_cpu
(
ctx
->
mrec
->
bytes_allocated
))
break
;
if
(
a
->
type
==
AT_END
)
continue
;
break
;
if
(
!
a
->
length
)
break
;
if
(
al_entry
->
instance
!=
a
->
instance
)
...
...
@@ -1695,6 +1695,8 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
a
->
data
.
non_resident
.
initialized_size
=
cpu_to_sle64
(
attr_size
);
if
(
NInoSparse
(
ni
)
||
NInoCompressed
(
ni
))
{
a
->
data
.
non_resident
.
compression_unit
=
0
;
if
(
NInoCompressed
(
ni
)
||
vol
->
major_ver
<
3
)
a
->
data
.
non_resident
.
compression_unit
=
4
;
a
->
data
.
non_resident
.
compressed_size
=
a
->
data
.
non_resident
.
allocated_size
;
...
...
@@ -1714,13 +1716,20 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
ni
->
allocated_size
=
new_size
;
if
(
NInoSparse
(
ni
)
||
NInoCompressed
(
ni
))
{
ni
->
itype
.
compressed
.
size
=
ni
->
allocated_size
;
ni
->
itype
.
compressed
.
block_size
=
1U
<<
(
a
->
data
.
non_resident
.
compression_unit
+
if
(
a
->
data
.
non_resident
.
compression_unit
)
{
ni
->
itype
.
compressed
.
block_size
=
1U
<<
(
a
->
data
.
non_resident
.
compression_unit
+
vol
->
cluster_size_bits
);
ni
->
itype
.
compressed
.
block_size_bits
=
ffs
(
ni
->
itype
.
compressed
.
block_size
)
-
1
;
ffs
(
ni
->
itype
.
compressed
.
block_size
)
-
1
;
ni
->
itype
.
compressed
.
block_clusters
=
1U
<<
a
->
data
.
non_resident
.
compression_unit
;
}
else
{
ni
->
itype
.
compressed
.
block_size
=
0
;
ni
->
itype
.
compressed
.
block_size_bits
=
0
;
ni
->
itype
.
compressed
.
block_clusters
=
0
;
}
vi
->
i_blocks
=
ni
->
itype
.
compressed
.
size
>>
9
;
}
else
vi
->
i_blocks
=
ni
->
allocated_size
>>
9
;
...
...
@@ -2429,16 +2438,12 @@ undo_alloc:
"chkdsk to recover."
,
IS_ERR
(
m
)
?
"restore attribute search context"
:
"truncate attribute runlist"
);
make_bad_inode
(
vi
);
make_bad_inode
(
VFS_I
(
base_ni
));
NVolSetErrors
(
vol
);
}
else
if
(
mp_rebuilt
)
{
if
(
ntfs_attr_record_resize
(
m
,
a
,
attr_len
))
{
ntfs_error
(
vol
->
sb
,
"Failed to restore attribute "
"record in error code path. Run "
"chkdsk to recover."
);
make_bad_inode
(
vi
);
make_bad_inode
(
VFS_I
(
base_ni
));
NVolSetErrors
(
vol
);
}
else
/* if (success) */
{
if
(
ntfs_mapping_pairs_build
(
vol
,
(
u8
*
)
a
+
le16_to_cpu
(
...
...
@@ -2451,8 +2456,6 @@ undo_alloc:
"mapping pairs array in error "
"code path. Run chkdsk to "
"recover."
);
make_bad_inode
(
vi
);
make_bad_inode
(
VFS_I
(
base_ni
));
NVolSetErrors
(
vol
);
}
flush_dcache_mft_record_page
(
ctx
->
ntfs_ino
);
...
...
fs/ntfs/compress.c
View file @
b425c8c5
...
...
@@ -67,7 +67,7 @@ static DEFINE_SPINLOCK(ntfs_cb_lock);
/**
* allocate_compression_buffers - allocate the decompression buffers
*
* Caller has to hold the ntfs_lock
semaphore
.
* Caller has to hold the ntfs_lock
mutex
.
*
* Return 0 on success or -ENOMEM if the allocations failed.
*/
...
...
@@ -84,7 +84,7 @@ int allocate_compression_buffers(void)
/**
* free_compression_buffers - free the decompression buffers
*
* Caller has to hold the ntfs_lock
semaphore
.
* Caller has to hold the ntfs_lock
mutex
.
*/
void
free_compression_buffers
(
void
)
{
...
...
fs/ntfs/file.c
View file @
b425c8c5
...
...
@@ -1207,8 +1207,6 @@ rl_not_mapped_enoent:
"attribute runlist in error code "
"path. Run chkdsk to recover the "
"lost cluster."
);
make_bad_inode
(
vi
);
make_bad_inode
(
VFS_I
(
base_ni
));
NVolSetErrors
(
vol
);
}
else
/* if (success) */
{
status
.
runlist_merged
=
0
;
...
...
@@ -1239,8 +1237,6 @@ rl_not_mapped_enoent:
ntfs_error
(
vol
->
sb
,
"Failed to restore attribute "
"record in error code path. Run "
"chkdsk to recover."
);
make_bad_inode
(
vi
);
make_bad_inode
(
VFS_I
(
base_ni
));
NVolSetErrors
(
vol
);
}
else
/* if (success) */
{
if
(
ntfs_mapping_pairs_build
(
vol
,
(
u8
*
)
a
+
...
...
@@ -1253,8 +1249,6 @@ rl_not_mapped_enoent:
"mapping pairs array in error "
"code path. Run chkdsk to "
"recover."
);
make_bad_inode
(
vi
);
make_bad_inode
(
VFS_I
(
base_ni
));
NVolSetErrors
(
vol
);
}
flush_dcache_mft_record_page
(
ctx
->
ntfs_ino
);
...
...
@@ -1623,11 +1617,8 @@ err_out:
unmap_mft_record
(
base_ni
);
ntfs_error
(
vi
->
i_sb
,
"Failed to update initialized_size/i_size (error "
"code %i)."
,
err
);
if
(
err
!=
-
ENOMEM
)
{
if
(
err
!=
-
ENOMEM
)
NVolSetErrors
(
ni
->
vol
);
make_bad_inode
(
VFS_I
(
base_ni
));
make_bad_inode
(
vi
);
}
return
err
;
}
...
...
@@ -1802,8 +1793,6 @@ err_out:
ntfs_error
(
vi
->
i_sb
,
"Resident attribute commit write failed "
"with error %i."
,
err
);
NVolSetErrors
(
ni
->
vol
);
make_bad_inode
(
VFS_I
(
base_ni
));
make_bad_inode
(
vi
);
}
if
(
ctx
)
ntfs_attr_put_search_ctx
(
ctx
);
...
...
fs/ntfs/inode.c
View file @
b425c8c5
/**
* inode.c - NTFS kernel inode handling. 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
...
...
@@ -19,13 +19,19 @@
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/
smp_lock
.h>
#include <linux/
quotaops
.h>
#include <linux/
fs
.h>
#include <linux/
mm
.h>
#include <linux/mount.h>
#include <linux/mutex.h>
#include <linux/pagemap.h>
#include <linux/quotaops.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include "aops.h"
#include "attrib.h"
#include "bitmap.h"
#include "dir.h"
#include "debug.h"
#include "inode.h"
...
...
@@ -382,7 +388,7 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
atomic_set
(
&
ni
->
count
,
1
);
ni
->
vol
=
NTFS_SB
(
sb
);
ntfs_init_runlist
(
&
ni
->
runlist
);
init_MUTEX
(
&
ni
->
mrec_lock
);
mutex_init
(
&
ni
->
mrec_lock
);
ni
->
page
=
NULL
;
ni
->
page_ofs
=
0
;
ni
->
attr_list_size
=
0
;
...
...
@@ -394,7 +400,7 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
ni
->
itype
.
index
.
collation_rule
=
0
;
ni
->
itype
.
index
.
block_size_bits
=
0
;
ni
->
itype
.
index
.
vcn_size_bits
=
0
;
init_MUTEX
(
&
ni
->
extent_lock
);
mutex_init
(
&
ni
->
extent_lock
);
ni
->
nr_extents
=
0
;
ni
->
ext
.
base_ntfs_ino
=
NULL
;
}
...
...
@@ -1064,10 +1070,10 @@ skip_large_dir_stuff:
if
(
a
->
non_resident
)
{
NInoSetNonResident
(
ni
);
if
(
NInoCompressed
(
ni
)
||
NInoSparse
(
ni
))
{
if
(
a
->
data
.
non_resident
.
compression_unit
!=
4
)
{
if
(
NInoCompressed
(
ni
)
&&
a
->
data
.
non_resident
.
compression_unit
!=
4
)
{
ntfs_error
(
vi
->
i_sb
,
"Found "
"nonstandard "
"non
-
standard "
"compression unit (%u "
"instead of 4). "
"Cannot handle this."
,
...
...
@@ -1076,16 +1082,26 @@ skip_large_dir_stuff:
err
=
-
EOPNOTSUPP
;
goto
unm_err_out
;
}
ni
->
itype
.
compressed
.
block_clusters
=
1U
<<
a
->
data
.
non_resident
.
compression_unit
;
ni
->
itype
.
compressed
.
block_size
=
1U
<<
(
a
->
data
.
non_resident
.
if
(
a
->
data
.
non_resident
.
compression_unit
)
{
ni
->
itype
.
compressed
.
block_size
=
1U
<<
(
a
->
data
.
non_resident
.
compression_unit
+
vol
->
cluster_size_bits
);
ni
->
itype
.
compressed
.
block_size_bits
=
ffs
(
ni
->
itype
.
compressed
.
ni
->
itype
.
compressed
.
block_size_bits
=
ffs
(
ni
->
itype
.
compressed
.
block_size
)
-
1
;
ni
->
itype
.
compressed
.
block_clusters
=
1U
<<
a
->
data
.
non_resident
.
compression_unit
;
}
else
{
ni
->
itype
.
compressed
.
block_size
=
0
;
ni
->
itype
.
compressed
.
block_size_bits
=
0
;
ni
->
itype
.
compressed
.
block_clusters
=
0
;
}
ni
->
itype
.
compressed
.
size
=
sle64_to_cpu
(
a
->
data
.
non_resident
.
compressed_size
);
...
...
@@ -1338,8 +1354,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
goto
unm_err_out
;
}
if
(
NInoCompressed
(
ni
)
||
NInoSparse
(
ni
))
{
if
(
a
->
data
.
non_resident
.
compression_unit
!=
4
)
{
ntfs_error
(
vi
->
i_sb
,
"Found nonstandard "
if
(
NInoCompressed
(
ni
)
&&
a
->
data
.
non_resident
.
compression_unit
!=
4
)
{
ntfs_error
(
vi
->
i_sb
,
"Found non-standard "
"compression unit (%u instead "
"of 4). Cannot handle this."
,
a
->
data
.
non_resident
.
...
...
@@ -1347,13 +1364,22 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
err
=
-
EOPNOTSUPP
;
goto
unm_err_out
;
}
ni
->
itype
.
compressed
.
block_clusters
=
1U
<<
a
->
data
.
non_resident
.
compression_unit
;
ni
->
itype
.
compressed
.
block_size
=
1U
<<
(
a
->
data
.
non_resident
.
compression_unit
+
if
(
a
->
data
.
non_resident
.
compression_unit
)
{
ni
->
itype
.
compressed
.
block_size
=
1U
<<
(
a
->
data
.
non_resident
.
compression_unit
+
vol
->
cluster_size_bits
);
ni
->
itype
.
compressed
.
block_size_bits
=
ffs
(
ni
->
itype
.
compressed
.
block_size
)
-
1
;
ni
->
itype
.
compressed
.
block_size_bits
=
ffs
(
ni
->
itype
.
compressed
.
block_size
)
-
1
;
ni
->
itype
.
compressed
.
block_clusters
=
1U
<<
a
->
data
.
non_resident
.
compression_unit
;
}
else
{
ni
->
itype
.
compressed
.
block_size
=
0
;
ni
->
itype
.
compressed
.
block_size_bits
=
0
;
ni
->
itype
.
compressed
.
block_clusters
=
0
;
}
ni
->
itype
.
compressed
.
size
=
sle64_to_cpu
(
a
->
data
.
non_resident
.
compressed_size
);
}
...
...
@@ -1406,7 +1432,6 @@ err_out:
"Run chkdsk."
,
err
,
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
,
base_vi
->
i_ino
);
make_bad_inode
(
vi
);
make_bad_inode
(
base_vi
);
if
(
err
!=
-
ENOMEM
)
NVolSetErrors
(
vol
);
return
err
;
...
...
@@ -1591,6 +1616,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
"$INDEX_ALLOCATION attribute."
);
goto
unm_err_out
;
}
a
=
ctx
->
attr
;
if
(
!
a
->
non_resident
)
{
ntfs_error
(
vi
->
i_sb
,
"$INDEX_ALLOCATION attribute is "
"resident."
);
...
...
@@ -2823,11 +2849,8 @@ done:
old_bad_out:
old_size
=
-
1
;
bad_out:
if
(
err
!=
-
ENOMEM
&&
err
!=
-
EOPNOTSUPP
)
{
make_bad_inode
(
vi
);
make_bad_inode
(
VFS_I
(
base_ni
));
if
(
err
!=
-
ENOMEM
&&
err
!=
-
EOPNOTSUPP
)
NVolSetErrors
(
vol
);
}
if
(
err
!=
-
EOPNOTSUPP
)
NInoSetTruncateFailed
(
ni
);
else
if
(
old_size
>=
0
)
...
...
@@ -2842,11 +2865,8 @@ out:
ntfs_debug
(
"Failed. Returning error code %i."
,
err
);
return
err
;
conv_err_out:
if
(
err
!=
-
ENOMEM
&&
err
!=
-
EOPNOTSUPP
)
{
make_bad_inode
(
vi
);
make_bad_inode
(
VFS_I
(
base_ni
));
if
(
err
!=
-
ENOMEM
&&
err
!=
-
EOPNOTSUPP
)
NVolSetErrors
(
vol
);
}
if
(
err
!=
-
EOPNOTSUPP
)
NInoSetTruncateFailed
(
ni
);
else
...
...
@@ -3044,15 +3064,18 @@ int ntfs_write_inode(struct inode *vi, int sync)
* record will be cleaned and written out to disk below, i.e. before
* this function returns.
*/
if
(
modified
&&
!
NInoTestSetDirty
(
ctx
->
ntfs_ino
))
if
(
modified
)
{
flush_dcache_mft_record_page
(
ctx
->
ntfs_ino
);
if
(
!
NInoTestSetDirty
(
ctx
->
ntfs_ino
))
mark_ntfs_record_dirty
(
ctx
->
ntfs_ino
->
page
,
ctx
->
ntfs_ino
->
page_ofs
);
}
ntfs_attr_put_search_ctx
(
ctx
);
/* Now the access times are updated, write the base mft record. */
if
(
NInoDirty
(
ni
))
err
=
write_mft_record
(
ni
,
m
,
sync
);
/* Write all attached extent mft records. */
down
(
&
ni
->
extent_lock
);
mutex_lock
(
&
ni
->
extent_lock
);
if
(
ni
->
nr_extents
>
0
)
{
ntfs_inode
**
extent_nis
=
ni
->
ext
.
extent_ntfs_inos
;
int
i
;
...
...
@@ -3079,7 +3102,7 @@ int ntfs_write_inode(struct inode *vi, int sync)
}
}
}
up
(
&
ni
->
extent_lock
);
mutex_unlock
(
&
ni
->
extent_lock
);
unmap_mft_record
(
ni
);
if
(
unlikely
(
err
))
goto
err_out
;
...
...
@@ -3094,9 +3117,7 @@ err_out:
"retries later."
);
mark_inode_dirty
(
vi
);
}
else
{
ntfs_error
(
vi
->
i_sb
,
"Failed (error code %i): Marking inode "
"as bad. You should run chkdsk."
,
-
err
);
make_bad_inode
(
vi
);
ntfs_error
(
vi
->
i_sb
,
"Failed (error %i): Run chkdsk."
,
-
err
);
NVolSetErrors
(
ni
->
vol
);
}
return
err
;
...
...
fs/ntfs/inode.h
View file @
b425c8c5
...
...
@@ -24,12 +24,13 @@
#ifndef _LINUX_NTFS_INODE_H
#define _LINUX_NTFS_INODE_H
#include <linux/mm.h>
#include <asm/atomic.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/list.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include <linux/mm.h>
#include <linux/mutex.h>
#include <linux/seq_file.h>
#include "layout.h"
#include "volume.h"
...
...
@@ -81,7 +82,7 @@ struct _ntfs_inode {
* The following fields are only valid for real inodes and extent
* inodes.
*/
struct
semaphore
mrec_lock
;
/* Lock for serializing access to the
struct
mutex
mrec_lock
;
/* Lock for serializing access to the
mft record belonging to this inode. */
struct
page
*
page
;
/* The page containing the mft record of the
inode. This should only be touched by the
...
...
@@ -119,7 +120,7 @@ struct _ntfs_inode {
u8
block_clusters
;
/* Number of clusters per cb. */
}
compressed
;
}
itype
;
struct
semaphore
extent_lock
;
/* Lock for accessing/modifying the
struct
mutex
extent_lock
;
/* Lock for accessing/modifying the
below . */
s32
nr_extents
;
/* For a base mft record, the number of attached extent
inodes (0 if none), for extent records and for fake
...
...
fs/ntfs/layout.h
View file @
b425c8c5
...
...
@@ -769,7 +769,7 @@ typedef struct {
compressed. (This effectively limits the
compression unit size to be a power of two
clusters.) WinNT4 only uses a value of 4.
Sparse files
also have this set to 4
. */
Sparse files
have this set to 0 on XPSP2
. */
/* 35*/
u8
reserved
[
5
];
/* Align to 8-byte boundary. */
/* The sizes below are only used when lowest_vcn is zero, as otherwise it would
be difficult to keep them up-to-date.*/
...
...
@@ -801,13 +801,16 @@ typedef struct {
typedef
ATTR_RECORD
ATTR_REC
;
/*
* File attribute flags (32-bit).
* File attribute flags (32-bit) appearing in the file_attributes fields of the
* STANDARD_INFORMATION attribute of MFT_RECORDs and the FILENAME_ATTR
* attributes of MFT_RECORDs and directory index entries.
*
* All of the below flags appear in the directory index entries but only some
* appear in the STANDARD_INFORMATION attribute whilst only some others appear
* in the FILENAME_ATTR attribute of MFT_RECORDs. Unless otherwise stated the
* flags appear in all of the above.
*/
enum
{
/*
* The following flags are only present in the STANDARD_INFORMATION
* attribute (in the field file_attributes).
*/
FILE_ATTR_READONLY
=
const_cpu_to_le32
(
0x00000001
),
FILE_ATTR_HIDDEN
=
const_cpu_to_le32
(
0x00000002
),
FILE_ATTR_SYSTEM
=
const_cpu_to_le32
(
0x00000004
),
...
...
@@ -839,18 +842,14 @@ enum {
F_A_COMPRESSED, and F_A_ENCRYPTED and preserves the rest. This mask
is used to to obtain all flags that are valid for setting. */
/*
* The following flag is only present in the FILE_NAME attribute (in
* the field file_attributes).
* The flag FILE_ATTR_DUP_FILENAME_INDEX_PRESENT is present in all
* FILENAME_ATTR attributes but not in the STANDARD_INFORMATION
* attribute of an mft record.
*/
FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT
=
const_cpu_to_le32
(
0x10000000
),
/* Note, this is a copy of the corresponding bit from the mft record,
telling us whether this is a directory or not, i.e. whether it has
an index root attribute or not. */
/*
* The following flag is present both in the STANDARD_INFORMATION
* attribute and in the FILE_NAME attribute (in the field
* file_attributes).
*/
FILE_ATTR_DUP_VIEW_INDEX_PRESENT
=
const_cpu_to_le32
(
0x20000000
),
/* Note, this is a copy of the corresponding bit from the mft record,
telling us whether this file has a view index present (eg. object id
...
...
@@ -891,7 +890,7 @@ typedef struct {
Windows this is only updated when
accessed if some time delta has
passed since the last update. Also,
last access time
s
updates can be
last access time updates can be
disabled altogether for speed. */
/* 32*/
FILE_ATTR_FLAGS
file_attributes
;
/* Flags describing the file. */
/* 36*/
union
{
...
...
@@ -1076,16 +1075,21 @@ typedef struct {
/* 20*/
sle64
last_access_time
;
/* Time this mft record was last
accessed. */
/* 28*/
sle64
allocated_size
;
/* Byte size of on-disk allocated space
for the
data attribute. So for
normal $DATA, this is the
for the
unnamed data attribute. So
for
normal $DATA, this is the
allocated_size from the unnamed
$DATA attribute and for compressed
and/or sparse $DATA, this is the
compressed_size from the unnamed
$DATA attribute. NOTE: This is a
multiple of the cluster size. */
/* 30*/
sle64
data_size
;
/* Byte size of actual data in data
attribute. */
$DATA attribute. For a directory or
other inode without an unnamed $DATA
attribute, this is always 0. NOTE:
This is a multiple of the cluster
size. */
/* 30*/
sle64
data_size
;
/* Byte size of actual data in unnamed
data attribute. For a directory or
other inode without an unnamed $DATA
attribute, this is always 0. */
/* 38*/
FILE_ATTR_FLAGS
file_attributes
;
/* Flags describing the file. */
/* 3c*/
union
{
/* 3c*/
struct
{
...
...
fs/ntfs/mft.c
View file @
b425c8c5
...
...
@@ -93,6 +93,7 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
"Run chkdsk."
,
ni
->
mft_no
);
ntfs_unmap_page
(
page
);
page
=
ERR_PTR
(
-
EIO
);
NVolSetErrors
(
vol
);
}
err_out:
ni
->
page
=
NULL
;
...
...
@@ -104,8 +105,8 @@ err_out:
* map_mft_record - map, pin and lock an mft record
* @ni: ntfs inode whose MFT record to map
*
* First, take the mrec_lock
semaphore.
We might now be sleeping, while waiting
* for the
semaphore
if it was already locked by someone else.
* First, take the mrec_lock
mutex.
We might now be sleeping, while waiting
* for the
mutex
if it was already locked by someone else.
*
* The page of the record is mapped using map_mft_record_page() before being
* returned to the caller.
...
...
@@ -135,9 +136,9 @@ err_out:
* So that code will end up having to own the mrec_lock of all mft
* records/inodes present in the page before I/O can proceed. In that case we
* wouldn't need to bother with PG_locked and PG_uptodate as nobody will be
* accessing anything without owning the mrec_lock
semaphore. But we do need
*
to use them because of the read_cache_page() invocation and the code becomes
*
so
much simpler this way that it is well worth it.
* accessing anything without owning the mrec_lock
mutex. But we do need to
*
use them because of the read_cache_page() invocation and the code becomes so
* much simpler this way that it is well worth it.
*
* 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
...
...
@@ -160,13 +161,13 @@ MFT_RECORD *map_mft_record(ntfs_inode *ni)
atomic_inc
(
&
ni
->
count
);
/* Serialize access to this mft record. */
down
(
&
ni
->
mrec_lock
);
mutex_lock
(
&
ni
->
mrec_lock
);
m
=
map_mft_record_page
(
ni
);
if
(
likely
(
!
IS_ERR
(
m
)))
return
m
;
up
(
&
ni
->
mrec_lock
);
mutex_unlock
(
&
ni
->
mrec_lock
);
atomic_dec
(
&
ni
->
count
);
ntfs_error
(
ni
->
vol
->
sb
,
"Failed with error code %lu."
,
-
PTR_ERR
(
m
));
return
m
;
...
...
@@ -217,7 +218,7 @@ void unmap_mft_record(ntfs_inode *ni)
ntfs_debug
(
"Entering for mft_no 0x%lx."
,
ni
->
mft_no
);
unmap_mft_record_page
(
ni
);
up
(
&
ni
->
mrec_lock
);
mutex_unlock
(
&
ni
->
mrec_lock
);
atomic_dec
(
&
ni
->
count
);
/*
* If pure ntfs_inode, i.e. no vfs inode attached, we leave it to
...
...
@@ -261,7 +262,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
* in which case just return it. If not found, add it to the base
* inode before returning it.
*/
down
(
&
base_ni
->
extent_lock
);
mutex_lock
(
&
base_ni
->
extent_lock
);
if
(
base_ni
->
nr_extents
>
0
)
{
extent_nis
=
base_ni
->
ext
.
extent_ntfs_inos
;
for
(
i
=
0
;
i
<
base_ni
->
nr_extents
;
i
++
)
{
...
...
@@ -274,7 +275,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
}
}
if
(
likely
(
ni
!=
NULL
))
{
up
(
&
base_ni
->
extent_lock
);
mutex_unlock
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
/* We found the record; just have to map and return it. */
m
=
map_mft_record
(
ni
);
...
...
@@ -301,7 +302,7 @@ map_err_out:
/* Record wasn't there. Get a new ntfs inode and initialize it. */
ni
=
ntfs_new_extent_inode
(
base_ni
->
vol
->
sb
,
mft_no
);
if
(
unlikely
(
!
ni
))
{
up
(
&
base_ni
->
extent_lock
);
mutex_unlock
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
return
ERR_PTR
(
-
ENOMEM
);
}
...
...
@@ -312,7 +313,7 @@ map_err_out:
/* Now map the record. */
m
=
map_mft_record
(
ni
);
if
(
IS_ERR
(
m
))
{
up
(
&
base_ni
->
extent_lock
);
mutex_unlock
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
ntfs_clear_extent_inode
(
ni
);
goto
map_err_out
;
...
...
@@ -347,14 +348,14 @@ map_err_out:
base_ni
->
ext
.
extent_ntfs_inos
=
tmp
;
}
base_ni
->
ext
.
extent_ntfs_inos
[
base_ni
->
nr_extents
++
]
=
ni
;
up
(
&
base_ni
->
extent_lock
);
mutex_unlock
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
ntfs_debug
(
"Done 2."
);
*
ntfs_ino
=
ni
;
return
m
;
unm_err_out:
unmap_mft_record
(
ni
);
up
(
&
base_ni
->
extent_lock
);
mutex_unlock
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
/*
* If the extent inode was not attached to the base inode we need to
...
...
@@ -399,12 +400,12 @@ void __mark_mft_record_dirty(ntfs_inode *ni)
BUG_ON
(
NInoAttr
(
ni
));
mark_ntfs_record_dirty
(
ni
->
page
,
ni
->
page_ofs
);
/* Determine the base vfs inode and mark it dirty, too. */
down
(
&
ni
->
extent_lock
);
mutex_lock
(
&
ni
->
extent_lock
);
if
(
likely
(
ni
->
nr_extents
>=
0
))
base_ni
=
ni
;
else
base_ni
=
ni
->
ext
.
base_ntfs_ino
;
up
(
&
ni
->
extent_lock
);
mutex_unlock
(
&
ni
->
extent_lock
);
__mark_inode_dirty
(
VFS_I
(
base_ni
),
I_DIRTY_SYNC
|
I_DIRTY_DATASYNC
);
}
...
...
@@ -650,10 +651,7 @@ err_out:
* fs/ntfs/aops.c::mark_ntfs_record_dirty().
*
* On success, clean the mft record and return 0. On error, leave the mft
* record dirty and return -errno. The caller should call make_bad_inode() on
* the base inode to ensure no more access happens to this inode. We do not do
* it here as the caller may want to finish writing other extent mft records
* first to minimize on-disk metadata inconsistencies.
* record dirty and return -errno.
*
* NOTE: We always perform synchronous i/o and ignore the @sync parameter.
* However, if the mft record has a counterpart in the mft mirror and @sync is
...
...
@@ -983,7 +981,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
}
ntfs_debug
(
"Inode 0x%lx is not dirty."
,
mft_no
);
/* The inode is not dirty, try to take the mft record lock. */
if
(
unlikely
(
down
_trylock
(
&
ni
->
mrec_lock
)))
{
if
(
unlikely
(
!
mutex
_trylock
(
&
ni
->
mrec_lock
)))
{
ntfs_debug
(
"Mft record 0x%lx is already locked, do "
"not write it."
,
mft_no
);
atomic_dec
(
&
ni
->
count
);
...
...
@@ -1043,13 +1041,13 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
* corresponding to this extent mft record attached.
*/
ni
=
NTFS_I
(
vi
);
down
(
&
ni
->
extent_lock
);
mutex_lock
(
&
ni
->
extent_lock
);
if
(
ni
->
nr_extents
<=
0
)
{
/*
* The base inode has no attached extent inodes, write this
* extent mft record.
*/
up
(
&
ni
->
extent_lock
);
mutex_unlock
(
&
ni
->
extent_lock
);
iput
(
vi
);
ntfs_debug
(
"Base inode 0x%lx has no attached extent inodes, "
"write the extent record."
,
na
.
mft_no
);
...
...
@@ -1072,7 +1070,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
* extent mft record.
*/
if
(
!
eni
)
{
up
(
&
ni
->
extent_lock
);
mutex_unlock
(
&
ni
->
extent_lock
);
iput
(
vi
);
ntfs_debug
(
"Extent inode 0x%lx is not attached to its base "
"inode 0x%lx, write the extent record."
,
...
...
@@ -1083,12 +1081,12 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no,
mft_no
,
na
.
mft_no
);
/* Take a reference to the extent ntfs inode. */
atomic_inc
(
&
eni
->
count
);
up
(
&
ni
->
extent_lock
);
mutex_unlock
(
&
ni
->
extent_lock
);
/*
* Found the extent inode coresponding to this extent mft record.
* Try to take the mft record lock.
*/
if
(
unlikely
(
down
_trylock
(
&
eni
->
mrec_lock
)))
{
if
(
unlikely
(
!
mutex
_trylock
(
&
eni
->
mrec_lock
)))
{
atomic_dec
(
&
eni
->
count
);
iput
(
vi
);
ntfs_debug
(
"Extent mft record 0x%lx is already locked, do "
...
...
@@ -2711,7 +2709,7 @@ mft_rec_already_initialized:
* have its page mapped and it is very easy to do.
*/
atomic_inc
(
&
ni
->
count
);
down
(
&
ni
->
mrec_lock
);
mutex_lock
(
&
ni
->
mrec_lock
);
ni
->
page
=
page
;
ni
->
page_ofs
=
ofs
;
/*
...
...
@@ -2798,22 +2796,22 @@ int ntfs_extent_mft_record_free(ntfs_inode *ni, MFT_RECORD *m)
BUG_ON
(
NInoAttr
(
ni
));
BUG_ON
(
ni
->
nr_extents
!=
-
1
);
down
(
&
ni
->
extent_lock
);
mutex_lock
(
&
ni
->
extent_lock
);
base_ni
=
ni
->
ext
.
base_ntfs_ino
;
up
(
&
ni
->
extent_lock
);
mutex_unlock
(
&
ni
->
extent_lock
);
BUG_ON
(
base_ni
->
nr_extents
<=
0
);
ntfs_debug
(
"Entering for extent inode 0x%lx, base inode 0x%lx.
\n
"
,
mft_no
,
base_ni
->
mft_no
);
down
(
&
base_ni
->
extent_lock
);
mutex_lock
(
&
base_ni
->
extent_lock
);
/* Make sure we are holding the only reference to the extent inode. */
if
(
atomic_read
(
&
ni
->
count
)
>
2
)
{
ntfs_error
(
vol
->
sb
,
"Tried to free busy extent inode 0x%lx, "
"not freeing."
,
base_ni
->
mft_no
);
up
(
&
base_ni
->
extent_lock
);
mutex_unlock
(
&
base_ni
->
extent_lock
);
return
-
EBUSY
;
}
...
...
@@ -2831,7 +2829,7 @@ int ntfs_extent_mft_record_free(ntfs_inode *ni, MFT_RECORD *m)
break
;
}
up
(
&
base_ni
->
extent_lock
);
mutex_unlock
(
&
base_ni
->
extent_lock
);
if
(
unlikely
(
err
))
{
ntfs_error
(
vol
->
sb
,
"Extent inode 0x%lx is not attached to "
...
...
@@ -2890,7 +2888,7 @@ rollback_error:
return
0
;
rollback:
/* Rollback what we did... */
down
(
&
base_ni
->
extent_lock
);
mutex_lock
(
&
base_ni
->
extent_lock
);
extent_nis
=
base_ni
->
ext
.
extent_ntfs_inos
;
if
(
!
(
base_ni
->
nr_extents
&
3
))
{
int
new_size
=
(
base_ni
->
nr_extents
+
4
)
*
sizeof
(
ntfs_inode
*
);
...
...
@@ -2899,7 +2897,7 @@ rollback:
if
(
unlikely
(
!
extent_nis
))
{
ntfs_error
(
vol
->
sb
,
"Failed to allocate internal "
"buffer during rollback.%s"
,
es
);
up
(
&
base_ni
->
extent_lock
);
mutex_unlock
(
&
base_ni
->
extent_lock
);
NVolSetErrors
(
vol
);
goto
rollback_error
;
}
...
...
@@ -2914,7 +2912,7 @@ rollback:
m
->
flags
|=
MFT_RECORD_IN_USE
;
m
->
sequence_number
=
old_seq_no
;
extent_nis
[
base_ni
->
nr_extents
++
]
=
ni
;
up
(
&
base_ni
->
extent_lock
);
mutex_unlock
(
&
base_ni
->
extent_lock
);
mark_mft_record_dirty
(
ni
);
return
err
;
}
...
...
fs/ntfs/mft.h
View file @
b425c8c5
...
...
@@ -97,10 +97,7 @@ extern int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync);
* uptodate.
*
* On success, clean the mft record and return 0. On error, leave the mft
* record dirty and return -errno. The caller should call make_bad_inode() on
* the base inode to ensure no more access happens to this inode. We do not do
* it here as the caller may want to finish writing other extent mft records
* first to minimize on-disk metadata inconsistencies.
* record dirty and return -errno.
*/
static
inline
int
write_mft_record
(
ntfs_inode
*
ni
,
MFT_RECORD
*
m
,
int
sync
)
{
...
...
fs/ntfs/namei.c
View file @
b425c8c5
...
...
@@ -2,7 +2,7 @@
* namei.c - NTFS kernel directory inode operations. Part of the Linux-NTFS
* project.
*
* Copyright (c) 2001-200
4
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
...
...
@@ -115,7 +115,9 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
uname_len
=
ntfs_nlstoucs
(
vol
,
dent
->
d_name
.
name
,
dent
->
d_name
.
len
,
&
uname
);
if
(
uname_len
<
0
)
{
ntfs_error
(
vol
->
sb
,
"Failed to convert name to Unicode."
);
if
(
uname_len
!=
-
ENAMETOOLONG
)
ntfs_error
(
vol
->
sb
,
"Failed to convert name to "
"Unicode."
);
return
ERR_PTR
(
uname_len
);
}
mref
=
ntfs_lookup_inode_by_name
(
NTFS_I
(
dir_ino
),
uname
,
uname_len
,
...
...
@@ -157,7 +159,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
/* Return the error code. */
return
(
struct
dentry
*
)
dent_inode
;
}
/* It is guaranteed that name is no longer allocated at this point. */
/* It is guaranteed that
@
name is no longer allocated at this point. */
if
(
MREF_ERR
(
mref
)
==
-
ENOENT
)
{
ntfs_debug
(
"Entry was not found, adding negative dentry."
);
/* The dcache will handle negative entries. */
...
...
@@ -168,7 +170,6 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
ntfs_error
(
vol
->
sb
,
"ntfs_lookup_ino_by_name() failed with error "
"code %i."
,
-
MREF_ERR
(
mref
));
return
ERR_PTR
(
MREF_ERR
(
mref
));
// TODO: Consider moving this lot to a separate function! (AIA)
handle_name:
{
...
...
fs/ntfs/ntfs.h
View file @
b425c8c5
...
...
@@ -91,7 +91,7 @@ extern void free_compression_buffers(void);
/* From fs/ntfs/super.c */
#define default_upcase_len 0x10000
extern
struct
semaphore
ntfs_lock
;
extern
struct
mutex
ntfs_lock
;
typedef
struct
{
int
val
;
...
...
fs/ntfs/runlist.c
View file @
b425c8c5
...
...
@@ -381,6 +381,7 @@ static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
static
inline
runlist_element
*
ntfs_rl_replace
(
runlist_element
*
dst
,
int
dsize
,
runlist_element
*
src
,
int
ssize
,
int
loc
)
{
signed
delta
;
BOOL
left
=
FALSE
;
/* Left end of @src needs merging. */
BOOL
right
=
FALSE
;
/* Right end of @src needs merging. */
int
tail
;
/* Start of tail of @dst. */
...
...
@@ -396,11 +397,14 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
left
=
ntfs_are_rl_mergeable
(
dst
+
loc
-
1
,
src
);
/*
* Allocate some space. We will need less if the left, right, or both
* ends get merged.
* ends get merged.
The -1 accounts for the run being replaced.
*/
dst
=
ntfs_rl_realloc
(
dst
,
dsize
,
dsize
+
ssize
-
left
-
right
);
delta
=
ssize
-
1
-
left
-
right
;
if
(
delta
>
0
)
{
dst
=
ntfs_rl_realloc
(
dst
,
dsize
,
dsize
+
delta
);
if
(
IS_ERR
(
dst
))
return
dst
;
}
/*
* We are guaranteed to succeed from here so can start modifying the
* original runlists.
...
...
fs/ntfs/super.c
View file @
b425c8c5
...
...
@@ -1099,26 +1099,38 @@ static BOOL check_mft_mirror(ntfs_volume *vol)
kmirr
=
page_address
(
mirr_page
);
++
index
;
}
/* Do not check the record if it is not in use. */
if
(((
MFT_RECORD
*
)
kmft
)
->
flags
&
MFT_RECORD_IN_USE
)
{
/* Make sure the record is ok. */
if
(
ntfs_is_baad_recordp
((
le32
*
)
kmft
))
{
ntfs_error
(
sb
,
"Incomplete multi sector transfer "
"detected in mft record %i."
,
i
);
ntfs_error
(
sb
,
"Incomplete multi sector "
"transfer detected in mft "
"record %i."
,
i
);
mm_unmap_out:
ntfs_unmap_page
(
mirr_page
);
mft_unmap_out:
ntfs_unmap_page
(
mft_page
);
return
FALSE
;
}
}
/* Do not check the mirror record if it is not in use. */
if
(((
MFT_RECORD
*
)
kmirr
)
->
flags
&
MFT_RECORD_IN_USE
)
{
if
(
ntfs_is_baad_recordp
((
le32
*
)
kmirr
))
{
ntfs_error
(
sb
,
"Incomplete multi sector transfer "
"detected in mft mirror record %i."
,
i
);
ntfs_error
(
sb
,
"Incomplete multi sector "
"transfer detected in mft "
"mirror record %i."
,
i
);
goto
mm_unmap_out
;
}
}
/* Get the amount of data in the current record. */
bytes
=
le32_to_cpu
(((
MFT_RECORD
*
)
kmft
)
->
bytes_in_use
);
if
(
!
bytes
||
bytes
>
vol
->
mft_record_size
)
{
if
(
bytes
<
sizeof
(
MFT_RECORD_OLD
)
||
bytes
>
vol
->
mft_record_size
||
ntfs_is_baad_recordp
((
le32
*
)
kmft
))
{
bytes
=
le32_to_cpu
(((
MFT_RECORD
*
)
kmirr
)
->
bytes_in_use
);
if
(
!
bytes
||
bytes
>
vol
->
mft_record_size
)
if
(
bytes
<
sizeof
(
MFT_RECORD_OLD
)
||
bytes
>
vol
->
mft_record_size
||
ntfs_is_baad_recordp
((
le32
*
)
kmirr
))
bytes
=
vol
->
mft_record_size
;
}
/* Compare the two records. */
...
...
@@ -1665,11 +1677,11 @@ read_partial_upcase_page:
ntfs_debug
(
"Read %llu bytes from $UpCase (expected %zu bytes)."
,
i_size
,
64
*
1024
*
sizeof
(
ntfschar
));
iput
(
ino
);
down
(
&
ntfs_lock
);
mutex_lock
(
&
ntfs_lock
);
if
(
!
default_upcase
)
{
ntfs_debug
(
"Using volume specified $UpCase since default is "
"not present."
);
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
return
TRUE
;
}
max
=
default_upcase_len
;
...
...
@@ -1683,12 +1695,12 @@ read_partial_upcase_page:
vol
->
upcase
=
default_upcase
;
vol
->
upcase_len
=
max
;
ntfs_nr_upcase_users
++
;
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
ntfs_debug
(
"Volume specified $UpCase matches default. Using "
"default."
);
return
TRUE
;
}
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
ntfs_debug
(
"Using volume specified $UpCase since it does not match "
"the default."
);
return
TRUE
;
...
...
@@ -1697,17 +1709,17 @@ iput_upcase_failed:
ntfs_free
(
vol
->
upcase
);
vol
->
upcase
=
NULL
;
upcase_failed:
down
(
&
ntfs_lock
);
mutex_lock
(
&
ntfs_lock
);
if
(
default_upcase
)
{
vol
->
upcase
=
default_upcase
;
vol
->
upcase_len
=
default_upcase_len
;
ntfs_nr_upcase_users
++
;
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
ntfs_error
(
sb
,
"Failed to load $UpCase from the volume. Using "
"default."
);
return
TRUE
;
}
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
ntfs_error
(
sb
,
"Failed to initialize upcase table."
);
return
FALSE
;
}
...
...
@@ -2183,12 +2195,12 @@ iput_attrdef_err_out:
iput_upcase_err_out:
#endif
/* NTFS_RW */
vol
->
upcase_len
=
0
;
down
(
&
ntfs_lock
);
mutex_lock
(
&
ntfs_lock
);
if
(
vol
->
upcase
==
default_upcase
)
{
ntfs_nr_upcase_users
--
;
vol
->
upcase
=
NULL
;
}
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
if
(
vol
->
upcase
)
{
ntfs_free
(
vol
->
upcase
);
vol
->
upcase
=
NULL
;
...
...
@@ -2393,7 +2405,7 @@ static void ntfs_put_super(struct super_block *sb)
* Destroy the global default upcase table if necessary. Also decrease
* the number of upcase users if we are a user.
*/
down
(
&
ntfs_lock
);
mutex_lock
(
&
ntfs_lock
);
if
(
vol
->
upcase
==
default_upcase
)
{
ntfs_nr_upcase_users
--
;
vol
->
upcase
=
NULL
;
...
...
@@ -2404,7 +2416,7 @@ static void ntfs_put_super(struct super_block *sb)
}
if
(
vol
->
cluster_size
<=
4096
&&
!--
ntfs_nr_compression_users
)
free_compression_buffers
();
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
if
(
vol
->
upcase
)
{
ntfs_free
(
vol
->
upcase
);
vol
->
upcase
=
NULL
;
...
...
@@ -2878,7 +2890,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
ntfs_error
(
sb
,
"Failed to load essential metadata."
);
goto
iput_tmp_ino_err_out_now
;
}
down
(
&
ntfs_lock
);
mutex_lock
(
&
ntfs_lock
);
/*
* The current mount is a compression user if the cluster size is
* less than or equal 4kiB.
...
...
@@ -2889,7 +2901,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
ntfs_error
(
NULL
,
"Failed to allocate buffers "
"for compression engine."
);
ntfs_nr_compression_users
--
;
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
goto
iput_tmp_ino_err_out_now
;
}
}
...
...
@@ -2901,7 +2913,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
if
(
!
default_upcase
)
default_upcase
=
generate_default_upcase
();
ntfs_nr_upcase_users
++
;
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
/*
* From now on, ignore @silent parameter. If we fail below this line,
* it will be due to a corrupt fs or a system error, so we report it.
...
...
@@ -2919,12 +2931,12 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
atomic_inc
(
&
vol
->
root_ino
->
i_count
);
ntfs_debug
(
"Exiting, status successful."
);
/* Release the default upcase if it has no users. */
down
(
&
ntfs_lock
);
mutex_lock
(
&
ntfs_lock
);
if
(
!--
ntfs_nr_upcase_users
&&
default_upcase
)
{
ntfs_free
(
default_upcase
);
default_upcase
=
NULL
;
}
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
sb
->
s_export_op
=
&
ntfs_export_ops
;
lock_kernel
();
return
0
;
...
...
@@ -2992,12 +3004,12 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
vol
->
attrdef
=
NULL
;
}
vol
->
upcase_len
=
0
;
down
(
&
ntfs_lock
);
mutex_lock
(
&
ntfs_lock
);
if
(
vol
->
upcase
==
default_upcase
)
{
ntfs_nr_upcase_users
--
;
vol
->
upcase
=
NULL
;
}
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
if
(
vol
->
upcase
)
{
ntfs_free
(
vol
->
upcase
);
vol
->
upcase
=
NULL
;
...
...
@@ -3012,14 +3024,14 @@ unl_upcase_iput_tmp_ino_err_out_now:
* Decrease the number of upcase users and destroy the global default
* upcase table if necessary.
*/
down
(
&
ntfs_lock
);
mutex_lock
(
&
ntfs_lock
);
if
(
!--
ntfs_nr_upcase_users
&&
default_upcase
)
{
ntfs_free
(
default_upcase
);
default_upcase
=
NULL
;
}
if
(
vol
->
cluster_size
<=
4096
&&
!--
ntfs_nr_compression_users
)
free_compression_buffers
();
up
(
&
ntfs_lock
);
mutex_unlock
(
&
ntfs_lock
);
iput_tmp_ino_err_out_now:
iput
(
tmp_ino
);
if
(
vol
->
mft_ino
&&
vol
->
mft_ino
!=
tmp_ino
)
...
...
@@ -3078,8 +3090,8 @@ static void ntfs_big_inode_init_once(void *foo, struct kmem_cache *cachep,
struct
kmem_cache
*
ntfs_attr_ctx_cache
;
struct
kmem_cache
*
ntfs_index_ctx_cache
;
/* Driver wide
semaphore
. */
DE
CLAR
E_MUTEX
(
ntfs_lock
);
/* Driver wide
mutex
. */
DE
FIN
E_MUTEX
(
ntfs_lock
);
static
struct
super_block
*
ntfs_get_sb
(
struct
file_system_type
*
fs_type
,
int
flags
,
const
char
*
dev_name
,
void
*
data
)
...
...
@@ -3234,7 +3246,7 @@ static void __exit exit_ntfs_fs(void)
}
MODULE_AUTHOR
(
"Anton Altaparmakov <aia21@cantab.net>"
);
MODULE_DESCRIPTION
(
"NTFS 1.2/3.x driver - Copyright (c) 2001-200
5
Anton Altaparmakov"
);
MODULE_DESCRIPTION
(
"NTFS 1.2/3.x driver - Copyright (c) 2001-200
6
Anton Altaparmakov"
);
MODULE_VERSION
(
NTFS_VERSION
);
MODULE_LICENSE
(
"GPL"
);
#ifdef DEBUG
...
...
fs/ntfs/unistr.c
View file @
b425c8c5
/*
* unistr.c - NTFS Unicode string handling. 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
...
...
@@ -19,6 +19,8 @@
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/slab.h>
#include "types.h"
#include "debug.h"
#include "ntfs.h"
...
...
@@ -242,7 +244,7 @@ int ntfs_file_compare_values(FILE_NAME_ATTR *file_name_attr1,
* map dictates, into a little endian, 2-byte Unicode string.
*
* This function allocates the string and the caller is responsible for
* calling kmem_cache_free(ntfs_name_cache, @outs); when finished with it.
* calling kmem_cache_free(ntfs_name_cache,
*
@outs); when finished with it.
*
* On success the function returns the number of Unicode characters written to
* the output string *@outs (>= 0), not counting the terminating Unicode NULL
...
...
@@ -262,37 +264,48 @@ int ntfs_nlstoucs(const ntfs_volume *vol, const char *ins,
wchar_t
wc
;
int
i
,
o
,
wc_len
;
/* We do
n'
t trust outside sources. */
if
(
ins
)
{
/* We do
no
t trust outside sources. */
if
(
likely
(
ins
)
)
{
ucs
=
kmem_cache_alloc
(
ntfs_name_cache
,
SLAB_NOFS
);
if
(
ucs
)
{
if
(
likely
(
ucs
)
)
{
for
(
i
=
o
=
0
;
i
<
ins_len
;
i
+=
wc_len
)
{
wc_len
=
nls
->
char2uni
(
ins
+
i
,
ins_len
-
i
,
&
wc
);
if
(
wc_len
>=
0
)
{
if
(
wc
)
{
if
(
likely
(
wc_len
>=
0
&&
o
<
NTFS_MAX_NAME_LEN
))
{
if
(
likely
(
wc
))
{
ucs
[
o
++
]
=
cpu_to_le16
(
wc
);
continue
;
}
/* else (!wc) */
}
/* else
if
(!wc) */
break
;
}
/* else (wc_len < 0) */
goto
conversion_err
;
}
/* else if (wc_len < 0 ||
o >= NTFS_MAX_NAME_LEN) */
goto
name_err
;
}
ucs
[
o
]
=
0
;
*
outs
=
ucs
;
return
o
;
}
/* else (!ucs) */
ntfs_error
(
vol
->
sb
,
"Failed to allocate
name from
"
"n
tfs_name_cache!
"
);
}
/* else
if
(!ucs) */
ntfs_error
(
vol
->
sb
,
"Failed to allocate
buffer for converted
"
"n
ame from ntfs_name_cache.
"
);
return
-
ENOMEM
;
}
/* else (!ins) */
ntfs_error
(
NULL
,
"Received NULL pointer."
);
}
/* else
if
(!ins) */
ntfs_error
(
vol
->
sb
,
"Received NULL pointer."
);
return
-
EINVAL
;
conversion_err:
ntfs_error
(
vol
->
sb
,
"Name using character set %s contains characters "
"that cannot be converted to Unicode."
,
nls
->
charset
);
name_err:
kmem_cache_free
(
ntfs_name_cache
,
ucs
);
return
-
EILSEQ
;
if
(
wc_len
<
0
)
{
ntfs_error
(
vol
->
sb
,
"Name using character set %s contains "
"characters that cannot be converted to "
"Unicode."
,
nls
->
charset
);
i
=
-
EILSEQ
;
}
else
/* if (o >= NTFS_MAX_NAME_LEN) */
{
ntfs_error
(
vol
->
sb
,
"Name is too long (maximum length for a "
"name on NTFS is %d Unicode characters."
,
NTFS_MAX_NAME_LEN
);
i
=
-
ENAMETOOLONG
;
}
return
i
;
}
/**
...
...
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