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
6ba24a9c
Commit
6ba24a9c
authored
Jul 14, 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
3afddb10
a5ea1066
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
189 additions
and
170 deletions
+189
-170
Documentation/filesystems/ntfs.txt
Documentation/filesystems/ntfs.txt
+6
-0
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+12
-2
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/dir.c
fs/ntfs/dir.c
+116
-97
fs/ntfs/inode.c
fs/ntfs/inode.c
+48
-59
fs/ntfs/inode.h
fs/ntfs/inode.h
+4
-7
fs/ntfs/super.c
fs/ntfs/super.c
+2
-4
No files found.
Documentation/filesystems/ntfs.txt
View file @
6ba24a9c
...
...
@@ -247,6 +247,12 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.20:
- Support non-resident directory index bitmaps. This means we now cope
with huge directories without problems.
- Fix a page leak that manifested itself in some cases when reading
directory contents.
- Internal cleanups.
2.0.19:
- Fix race condition and improvements in block i/o interface.
- Optimization when reading compressed files.
...
...
fs/ntfs/ChangeLog
View file @
6ba24a9c
...
...
@@ -7,10 +7,20 @@ ToDo:
truncate the visible i_size? Will the user just get -E2BIG (or
whatever) on open()? Or will (s)he be able to open() but lseek() and
read() will fail when s_maxbytes is reached? -> Investigate this.
- Implement/allow non-resident index bitmaps in dir.c::ntfs_readdir()
and then also consider initialized_size w.r.t. the bitmaps, etc.
- Enable NFS exporting of NTFS.
2.0.20 - Support non-resident directory index bitmaps, fix page leak in readdir.
- Move the directory index bitmap to use an attribute inode instead of
having special fields for it inside the ntfs inode structure. This
means that the index bitmaps now use the page cache for i/o, too,
and also as a side effect we get support for non-resident index
bitmaps for free.
- Simplify/cleanup error handling in fs/ntfs/dir.c::ntfs_readdir() and
fix a page leak that manifested itself in some cases.
- Add fs/ntfs/inode.c::ntfs_put_inode(), which we need to release the
index bitmap inode on the final iput().
2.0.19 - Fix race condition, improvements, and optimizations in i/o interface.
- Apply block optimization added to fs/ntfs/aops.c::ntfs_read_block()
...
...
fs/ntfs/Makefile
View file @
6ba24a9c
...
...
@@ -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.
19
\"
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.0.
20
\"
ifeq
($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/dir.c
View file @
6ba24a9c
...
...
@@ -2,7 +2,7 @@
* dir.c - NTFS kernel directory operations. Part of the Linux-NTFS project.
*
* Copyright (c) 2001,2002 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
* modify it under the terms of the GNU General Public License as published
...
...
@@ -1052,8 +1052,8 @@ static inline int ntfs_filldir(ntfs_volume *vol, struct file *filp,
*/
static
int
ntfs_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
{
s64
ia_pos
,
ia_start
,
prev_ia_pos
;
struct
inode
*
vdir
=
filp
->
f_dentry
->
d_inode
;
s64
ia_pos
,
ia_start
,
prev_ia_pos
,
bmp_pos
;
struct
inode
*
bmp_vi
,
*
vdir
=
filp
->
f_dentry
->
d_inode
;
struct
super_block
*
sb
=
vdir
->
i_sb
;
ntfs_inode
*
ndir
=
NTFS_I
(
vdir
);
ntfs_volume
*
vol
=
NTFS_SB
(
sb
);
...
...
@@ -1061,10 +1061,10 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
INDEX_ROOT
*
ir
;
INDEX_ENTRY
*
ie
;
INDEX_ALLOCATION
*
ia
;
u8
*
name
;
int
rc
,
err
,
ir_pos
,
bmp_pos
;
struct
address_space
*
ia_mapping
;
struct
page
*
page
;
u8
*
name
=
NULL
;
int
rc
,
err
,
ir_pos
,
cur_
bmp_pos
;
struct
address_space
*
ia_mapping
,
*
bmp_mapping
;
struct
page
*
bmp_page
=
NULL
,
*
ia_page
=
NULL
;
u8
*
kaddr
,
*
bmp
,
*
index_end
;
attr_search_context
*
ctx
;
...
...
@@ -1093,17 +1093,20 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto
done
;
filp
->
f_pos
++
;
}
/* Get hold of the mft record for the directory. */
m
=
map_mft_record
(
READ
,
ndir
);
if
(
IS_ERR
(
m
))
{
if
(
unlikely
(
IS_ERR
(
m
)
))
{
err
=
PTR_ERR
(
m
);
m
=
NULL
;
ctx
=
NULL
;
goto
err_out
;
}
ctx
=
get_attr_search_ctx
(
ndir
,
m
);
if
(
!
ctx
)
{
if
(
unlikely
(
!
ctx
)
)
{
err
=
-
ENOMEM
;
goto
unm_
err_out
;
goto
err_out
;
}
/*
...
...
@@ -1112,9 +1115,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
*/
name
=
(
u8
*
)
kmalloc
(
NTFS_MAX_NAME_LEN
*
NLS_MAX_CHARSET_SIZE
+
1
,
GFP_NOFS
);
if
(
!
name
)
{
if
(
unlikely
(
!
name
)
)
{
err
=
-
ENOMEM
;
goto
put_unm_
err_out
;
goto
err_out
;
}
/* Are we jumping straight into the index allocation attribute? */
if
(
filp
->
f_pos
>=
vol
->
mft_record_size
)
...
...
@@ -1122,12 +1125,11 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Get the offset into the index root attribute. */
ir_pos
=
(
s64
)
filp
->
f_pos
;
/* Find the index root attribute in the mft record. */
if
(
!
lookup_attr
(
AT_INDEX_ROOT
,
I30
,
4
,
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
))
{
if
(
unlikely
(
!
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."
,
vdir
->
i_ino
);
err
=
-
EIO
;
goto
kf_unm_err_out
;
goto
err_out
;
}
/* Get to the index root value (it's been verified in read_inode). */
ir
=
(
INDEX_ROOT
*
)((
u8
*
)
ctx
->
attr
+
...
...
@@ -1144,11 +1146,11 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
for
(;;
ie
=
(
INDEX_ENTRY
*
)((
u8
*
)
ie
+
le16_to_cpu
(
ie
->
_IEH
(
length
))))
{
ntfs_debug
(
"In index root, offset 0x%x."
,
(
u8
*
)
ie
-
(
u8
*
)
ir
);
/* Bounds checks. */
if
((
u8
*
)
ie
<
(
u8
*
)
ctx
->
mrec
||
(
u8
*
)
ie
+
if
(
unlikely
(
(
u8
*
)
ie
<
(
u8
*
)
ctx
->
mrec
||
(
u8
*
)
ie
+
sizeof
(
INDEX_ENTRY_HEADER
)
>
index_end
||
(
u8
*
)
ie
+
le16_to_cpu
(
ie
->
_IEH
(
key_length
))
>
index_end
)
goto
dir_
err_out
;
index_end
)
)
goto
err_out
;
/* The last entry cannot contain a name. */
if
(
ie
->
_IEH
(
flags
)
&
INDEX_ENTRY_END
)
break
;
...
...
@@ -1166,80 +1168,99 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto
EOD
;
/* Advance f_pos to the beginning of the index allocation. */
filp
->
f_pos
=
vol
->
mft_record_size
;
/* Reinitialize the search context. */
reinit_attr_search_ctx
(
ctx
);
skip_index_root:
if
(
NInoBmpNonResident
(
ndir
))
{
/*
* Read the page of the bitmap that contains the current index
* block.
*/
// TODO: FIXME: Implement this!
ntfs_error
(
sb
,
"Index bitmap is non-resident, which is not "
"supported yet. Pretending that end of "
"directory has been reached.
\n
"
);
goto
EOD
;
}
else
{
/* Find the index bitmap attribute in the mft record. */
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."
,
vdir
->
i_ino
);
err
=
-
EIO
;
goto
kf_unm_err_out
;
}
bmp
=
(
u8
*
)
ctx
->
attr
+
le16_to_cpu
(
ctx
->
attr
->
_ARA
(
value_offset
));
}
kaddr
=
NULL
;
prev_ia_pos
=
-
1LL
;
/* Get the offset into the index allocation attribute. */
ia_pos
=
(
s64
)
filp
->
f_pos
-
vol
->
mft_record_size
;
ia_mapping
=
vdir
->
i_mapping
;
/* If the index block is not in use find the next one that is. */
bmp_vi
=
ndir
->
_IDM
(
bmp_ino
);
if
(
unlikely
(
!
bmp_vi
))
{
ntfs_debug
(
"Inode %lu, regetting index bitmap."
,
vdir
->
i_ino
);
bmp_vi
=
ntfs_attr_iget
(
vdir
,
AT_BITMAP
,
I30
,
4
);
if
(
unlikely
(
IS_ERR
(
bmp_vi
)))
{
ntfs_error
(
sb
,
"Failed to get bitmap attribute."
);
err
=
PTR_ERR
(
bmp_vi
);
goto
err_out
;
}
ndir
->
_IDM
(
bmp_ino
)
=
bmp_vi
;
}
bmp_mapping
=
bmp_vi
->
i_mapping
;
/* Get the starting bitmap bit position and sanity check it. */
bmp_pos
=
ia_pos
>>
ndir
->
_IDM
(
index_block_size_bits
);
page
=
NULL
;
kaddr
=
NULL
;
prev_ia_pos
=
-
1LL
;
if
(
bmp_pos
>>
3
>=
ndir
->
_IDM
(
bmp_size
))
{
if
(
unlikely
(
bmp_pos
>>
3
>=
bmp_vi
->
i_size
))
{
ntfs_error
(
sb
,
"Current index allocation position exceeds "
"index bitmap size."
);
goto
kf_unm_err_out
;
goto
err_out
;
}
/* Get the starting bit position in the current bitmap page. */
cur_bmp_pos
=
bmp_pos
&
((
PAGE_CACHE_SIZE
*
8
)
-
1
);
bmp_pos
&=
~
((
PAGE_CACHE_SIZE
*
8
)
-
1
);
get_next_bmp_page:
ntfs_debug
(
"Reading bitmap with page index 0x%Lx, bit ofs 0x%Lx"
,
(
long
long
)
bmp_pos
>>
(
3
+
PAGE_CACHE_SHIFT
),
(
long
long
)
bmp_pos
&
((
PAGE_CACHE_SIZE
*
8
)
-
1
));
bmp_page
=
ntfs_map_page
(
bmp_mapping
,
bmp_pos
>>
(
3
+
PAGE_CACHE_SHIFT
));
if
(
unlikely
(
IS_ERR
(
bmp_page
)))
{
ntfs_error
(
sb
,
"Reading index bitmap failed."
);
err
=
PTR_ERR
(
bmp_page
);
bmp_page
=
NULL
;
goto
err_out
;
}
while
(
!
(
bmp
[
bmp_pos
>>
3
]
&
(
1
<<
(
bmp_pos
&
7
))))
{
bmp
=
(
u8
*
)
page_address
(
bmp_page
);
/* Find next index block in use. */
while
(
!
(
bmp
[
cur_bmp_pos
>>
3
]
&
(
1
<<
(
cur_bmp_pos
&
7
))))
{
find_next_index_buffer:
bmp_pos
++
;
cur_bmp_pos
++
;
/*
* If we have reached the end of the bitmap page, get the next
* page, and put away the old one.
*/
if
(
unlikely
((
cur_bmp_pos
>>
3
)
>=
PAGE_CACHE_SIZE
))
{
ntfs_unmap_page
(
bmp_page
);
bmp_pos
+=
PAGE_CACHE_SIZE
*
8
;
cur_bmp_pos
=
0
;
goto
get_next_bmp_page
;
}
/* If we have reached the end of the bitmap, we are done. */
if
(
bmp_pos
>>
3
>=
ndir
->
_IDM
(
bmp_size
))
goto
EOD
;
ia_pos
=
(
s64
)
bmp_pos
<<
ndir
->
_IDM
(
index_block_size_bits
);
if
(
unlikely
(((
bmp_pos
+
cur_bmp_pos
)
>>
3
)
>=
vdir
->
i_size
))
goto
unm_EOD
;
ia_pos
=
(
bmp_pos
+
cur_bmp_pos
)
<<
ndir
->
_IDM
(
index_block_size_bits
);
}
ntfs_debug
(
"Handling index buffer 0x%x."
,
bmp_pos
);
ntfs_debug
(
"Handling index buffer 0x%Lx."
,
(
long
long
)
bmp_pos
+
cur_bmp_pos
);
/* If the current index buffer is in the same page we reuse the page. */
if
((
prev_ia_pos
&
PAGE_CACHE_MASK
)
!=
(
ia_pos
&
PAGE_CACHE_MASK
))
{
prev_ia_pos
=
ia_pos
;
if
(
page
)
ntfs_unmap_page
(
page
);
if
(
likely
(
ia_page
!=
NULL
)
)
ntfs_unmap_page
(
ia_
page
);
/*
* Map the page cache page containing the current ia_pos,
* reading it from disk if necessary.
*/
page
=
ntfs_map_page
(
ia_mapping
,
ia_pos
>>
PAGE_CACHE_SHIFT
);
if
(
IS_ERR
(
page
))
goto
map_page_err_out
;
kaddr
=
(
u8
*
)
page_address
(
page
);
ia_page
=
ntfs_map_page
(
ia_mapping
,
ia_pos
>>
PAGE_CACHE_SHIFT
);
if
(
unlikely
(
IS_ERR
(
ia_page
)))
{
ntfs_error
(
sb
,
"Reading index allocation data failed."
);
err
=
PTR_ERR
(
ia_page
);
ia_page
=
NULL
;
goto
err_out
;
}
kaddr
=
(
u8
*
)
page_address
(
ia_page
);
}
/* Get the current index buffer. */
ia
=
(
INDEX_ALLOCATION
*
)(
kaddr
+
(
ia_pos
&
~
PAGE_CACHE_MASK
&
~
(
s64
)(
ndir
->
_IDM
(
index_block_size
)
-
1
)));
/* Bounds checks. */
if
(
(
u8
*
)
ia
<
kaddr
||
(
u8
*
)
ia
>
kaddr
+
PAGE_CACHE_SIZE
)
{
if
(
unlikely
((
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."
,
vdir
->
i_ino
);
err
=
-
EIO
;
goto
unm_dir_err_out
;
goto
err_out
;
}
if
(
sle64_to_cpu
(
ia
->
index_block_vcn
)
!=
(
ia_pos
&
if
(
unlikely
(
sle64_to_cpu
(
ia
->
index_block_vcn
)
!=
(
ia_pos
&
~
(
s64
)(
ndir
->
_IDM
(
index_block_size
)
-
1
))
>>
ndir
->
_IDM
(
index_vcn_size_bits
))
{
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%lx is corrupt or driver "
...
...
@@ -1247,11 +1268,10 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
(
long
long
)
sle64_to_cpu
(
ia
->
index_block_vcn
),
(
long
long
)
ia_pos
>>
ndir
->
_IDM
(
index_vcn_size_bits
),
vdir
->
i_ino
);
err
=
-
EIO
;
goto
unm_dir_err_out
;
goto
err_out
;
}
if
(
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
!=
ndir
->
_IDM
(
index_block_size
))
{
if
(
unlikely
(
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%lx has a size (%u) differing from the "
"directory specified size (%u). Directory "
...
...
@@ -1260,28 +1280,25 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
ndir
->
_IDM
(
index_vcn_size_bits
),
vdir
->
i_ino
,
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
,
ndir
->
_IDM
(
index_block_size
));
err
=
-
EIO
;
goto
unm_dir_err_out
;
goto
err_out
;
}
index_end
=
(
u8
*
)
ia
+
ndir
->
_IDM
(
index_block_size
);
if
(
index_end
>
kaddr
+
PAGE_CACHE_SIZE
)
{
if
(
unlikely
(
index_end
>
kaddr
+
PAGE_CACHE_SIZE
)
)
{
ntfs_error
(
sb
,
"Index buffer (VCN 0x%Lx) of directory inode "
"0x%lx crosses page boundary. Impossible! "
"Cannot access! This is probably a bug in the "
"driver."
,
(
long
long
)
ia_pos
>>
ndir
->
_IDM
(
index_vcn_size_bits
),
vdir
->
i_ino
);
err
=
-
EIO
;
goto
unm_dir_err_out
;
goto
err_out
;
}
ia_start
=
ia_pos
&
~
(
s64
)(
ndir
->
_IDM
(
index_block_size
)
-
1
);
index_end
=
(
u8
*
)
&
ia
->
index
+
le32_to_cpu
(
ia
->
index
.
index_length
);
if
(
index_end
>
(
u8
*
)
ia
+
ndir
->
_IDM
(
index_block_size
))
{
if
(
unlikely
(
index_end
>
(
u8
*
)
ia
+
ndir
->
_IDM
(
index_block_size
)
))
{
ntfs_error
(
sb
,
"Size of index buffer (VCN 0x%Lx) of directory "
"inode 0x%lx exceeds maximum size."
,
(
long
long
)
ia_pos
>>
ndir
->
_IDM
(
index_vcn_size_bits
),
vdir
->
i_ino
);
err
=
-
EIO
;
goto
unm_dir_err_out
;
goto
err_out
;
}
/* The first index entry in this index buffer. */
ie
=
(
INDEX_ENTRY
*
)((
u8
*
)
&
ia
->
index
+
...
...
@@ -1295,11 +1312,11 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
ntfs_debug
(
"In index allocation, offset 0x%Lx."
,
(
long
long
)
ia_start
+
((
u8
*
)
ie
-
(
u8
*
)
ia
));
/* Bounds checks. */
if
((
u8
*
)
ie
<
(
u8
*
)
ia
||
(
u8
*
)
ie
+
if
(
unlikely
(
(
u8
*
)
ie
<
(
u8
*
)
ia
||
(
u8
*
)
ie
+
sizeof
(
INDEX_ENTRY_HEADER
)
>
index_end
||
(
u8
*
)
ie
+
le16_to_cpu
(
ie
->
_IEH
(
key_length
))
>
index_end
)
goto
unm_dir_
err_out
;
index_end
)
)
goto
err_out
;
/* The last entry cannot contain a name. */
if
(
ie
->
_IEH
(
flags
)
&
INDEX_ENTRY_END
)
break
;
...
...
@@ -1310,11 +1327,16 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
rc
=
ntfs_filldir
(
vol
,
filp
,
ndir
,
INDEX_TYPE_ALLOCATION
,
ia
,
ie
,
name
,
dirent
,
filldir
);
if
(
rc
)
{
ntfs_unmap_page
(
page
);
ntfs_unmap_page
(
ia_page
);
ntfs_unmap_page
(
bmp_page
);
goto
abort
;
}
}
goto
find_next_index_buffer
;
unm_EOD:
if
(
ia_page
)
ntfs_unmap_page
(
ia_page
);
ntfs_unmap_page
(
bmp_page
);
EOD:
/* We are finished, set f_pos to EOD. */
filp
->
f_pos
=
vdir
->
i_size
+
vol
->
mft_record_size
;
...
...
@@ -1331,24 +1353,21 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
rc
,
filp
->
f_pos
);
#endif
return
0
;
map_page_err_out:
ntfs_error
(
sb
,
"Reading index allocation data failed."
);
err
=
PTR_ERR
(
page
);
kf_unm_err_out:
err_out:
if
(
bmp_page
)
ntfs_unmap_page
(
bmp_page
);
if
(
ia_page
)
ntfs_unmap_page
(
ia_page
);
if
(
name
)
kfree
(
name
);
put_unm_err_out:
if
(
ctx
)
put_attr_search_ctx
(
ctx
);
unm_err_out:
if
(
m
)
unmap_mft_record
(
READ
,
ndir
);
err_out:
if
(
!
err
)
err
=
-
EIO
;
ntfs_debug
(
"Failed. Returning error code %i."
,
-
err
);
return
err
;
unm_dir_err_out:
ntfs_unmap_page
(
page
);
dir_err_out:
ntfs_error
(
sb
,
"Corrupt directory. Aborting. You should run chkdsk."
);
err
=
-
EIO
;
goto
kf_unm_err_out
;
}
struct
file_operations
ntfs_dir_ops
=
{
...
...
fs/ntfs/inode.c
View file @
6ba24a9c
...
...
@@ -329,12 +329,9 @@ static void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
ni
->
attr_list_size
=
0
;
ni
->
attr_list
=
NULL
;
init_run_list
(
&
ni
->
attr_list_rl
);
ni
->
_IDM
(
bmp_ino
)
=
NULL
;
ni
->
_IDM
(
index_block_size
)
=
0
;
ni
->
_IDM
(
index_vcn_size
)
=
0
;
ni
->
_IDM
(
bmp_size
)
=
0
;
ni
->
_IDM
(
bmp_initialized_size
)
=
0
;
ni
->
_IDM
(
bmp_allocated_size
)
=
0
;
init_run_list
(
&
ni
->
_IDM
(
bmp_rl
));
ni
->
_IDM
(
index_block_size_bits
)
=
0
;
ni
->
_IDM
(
index_vcn_size_bits
)
=
0
;
init_MUTEX
(
&
ni
->
extent_lock
);
...
...
@@ -680,6 +677,8 @@ static int ntfs_read_locked_inode(struct inode *vi)
* in ntfs_ino->attr_list and it is ntfs_ino->attr_list_size bytes.
*/
if
(
S_ISDIR
(
vi
->
i_mode
))
{
struct
inode
*
bvi
;
ntfs_inode
*
bni
;
INDEX_ROOT
*
ir
;
char
*
ir_end
,
*
index_end
;
...
...
@@ -787,7 +786,8 @@ static int ntfs_read_locked_inode(struct inode *vi)
if
(
!
(
ir
->
index
.
flags
&
LARGE_INDEX
))
{
/* No index allocation. */
vi
->
i_size
=
ni
->
initialized_size
=
0
;
vi
->
i_size
=
ni
->
initialized_size
=
ni
->
allocated_size
=
0
;
goto
skip_large_dir_stuff
;
}
/* LARGE_INDEX: Index allocation present. Setup state. */
NInoSetIndexAllocPresent
(
ni
);
...
...
@@ -832,63 +832,31 @@ static int ntfs_read_locked_inode(struct inode *vi)
ctx
->
attr
->
_ANR
(
initialized_size
));
ni
->
allocated_size
=
sle64_to_cpu
(
ctx
->
attr
->
_ANR
(
allocated_size
));
/* Find bitmap attribute. */
reinit_attr_search_ctx
(
ctx
);
if
(
!
lookup_attr
(
AT_BITMAP
,
I30
,
4
,
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
))
{
ntfs_error
(
vi
->
i_sb
,
"
$BITMAP attribute is not "
"present but it must be."
);
/* Get the index bitmap attribute inode. */
bvi
=
ntfs_attr_iget
(
vi
,
AT_BITMAP
,
I30
,
4
);
if
(
unlikely
(
IS_ERR
(
bvi
)
))
{
ntfs_error
(
vi
->
i_sb
,
"
Failed to get bitmap attribute."
);
err
=
PTR_ERR
(
bvi
);
goto
unm_err_out
;
}
if
(
ctx
->
attr
->
flags
&
(
ATTR_COMPRESSION_MASK
|
ATTR_IS_ENCRYPTED
|
ATTR_IS_SPARSE
))
{
ni
->
_IDM
(
bmp_ino
)
=
bvi
;
bni
=
NTFS_I
(
bvi
);
if
(
NInoCompressed
(
bni
)
||
NInoEncrypted
(
bni
)
||
NInoSparse
(
bni
))
{
ntfs_error
(
vi
->
i_sb
,
"$BITMAP attribute is compressed "
"and/or encrypted and/or sparse."
);
goto
unm_err_out
;
}
if
(
ctx
->
attr
->
non_resident
)
{
NInoSetBmpNonResident
(
ni
);
if
(
ctx
->
attr
->
_ANR
(
lowest_vcn
))
{
ntfs_error
(
vi
->
i_sb
,
"First extent of $BITMAP "
"attribute has non zero "
"lowest_vcn. Inode is corrupt. "
"You should run chkdsk."
);
goto
unm_err_out
;
}
ni
->
_IDM
(
bmp_size
)
=
sle64_to_cpu
(
ctx
->
attr
->
_ANR
(
data_size
));
ni
->
_IDM
(
bmp_initialized_size
)
=
sle64_to_cpu
(
ctx
->
attr
->
_ANR
(
initialized_size
));
ni
->
_IDM
(
bmp_allocated_size
)
=
sle64_to_cpu
(
ctx
->
attr
->
_ANR
(
allocated_size
));
/*
* Setup the run list. No need for locking as we have
* exclusive access to the inode at this time.
*/
ni
->
_IDM
(
bmp_rl
).
rl
=
decompress_mapping_pairs
(
vol
,
ctx
->
attr
,
NULL
);
if
(
IS_ERR
(
ni
->
_IDM
(
bmp_rl
).
rl
))
{
err
=
PTR_ERR
(
ni
->
_IDM
(
bmp_rl
).
rl
);
ni
->
_IDM
(
bmp_rl
).
rl
=
NULL
;
ntfs_error
(
vi
->
i_sb
,
"Mapping pairs "
"decompression failed with "
"error code %i."
,
-
err
);
goto
unm_err_out
;
}
}
else
ni
->
_IDM
(
bmp_size
)
=
ni
->
_IDM
(
bmp_initialized_size
)
=
ni
->
_IDM
(
bmp_allocated_size
)
=
le32_to_cpu
(
ctx
->
attr
->
_ARA
(
value_length
));
/* Consistency check bitmap size vs. index allocation size. */
if
(
ni
->
_IDM
(
bmp_size
)
<<
3
<
vi
->
i_size
>>
ni
->
_IDM
(
index_block_size_bits
))
{
ntfs_error
(
vi
->
i_sb
,
"
$I30
bitmap too small (0x%Lx) "
if
(
(
bvi
->
i_size
<<
3
)
<
(
vi
->
i_size
>>
ni
->
_IDM
(
index_block_size_bits
))
)
{
ntfs_error
(
vi
->
i_sb
,
"
Index
bitmap too small (0x%Lx) "
"for index allocation (0x%Lx)."
,
(
long
long
)
ni
->
_IDM
(
bmp_size
)
<<
3
,
vi
->
i_size
);
bvi
->
i_size
<<
3
,
vi
->
i_size
);
goto
unm_err_out
;
}
skip_large_dir_stuff:
/* Everyone gets read and scan permissions. */
vi
->
i_mode
|=
S_IRUGO
|
S_IXUGO
;
...
...
@@ -1271,7 +1239,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"will probably cause problems "
"when trying to access the "
"file. Please notify "
"linux-ntfs-dev@
lists.sf.net "
"linux-ntfs-dev@lists.sf.net "
"that you saw this message."
);
}
}
...
...
@@ -1785,6 +1753,32 @@ int ntfs_commit_inode(ntfs_inode *ni)
return
0
;
}
/**
* ntfs_put_inode - handler for when the inode reference count is decremented
* @vi: vfs inode
*
* The VFS calls ntfs_put_inode() every time the inode reference count (i_count)
* is about to be decremented (but before the decrement itself.
*
* If the inode @vi is a directory with a single reference, we need to put the
* attribute inode for the directory index bitmap, if it is present, otherwise
* the directory inode would remain pinned for ever (or rather until umount()
* time.
*/
void
ntfs_put_inode
(
struct
inode
*
vi
)
{
if
(
S_ISDIR
(
vi
->
i_mode
)
&&
(
atomic_read
(
&
vi
->
i_count
)
==
2
))
{
ntfs_inode
*
ni
;
ni
=
NTFS_I
(
vi
);
if
(
NInoIndexAllocPresent
(
ni
)
&&
ni
->
_IDM
(
bmp_ino
))
{
iput
(
ni
->
_IDM
(
bmp_ino
));
ni
->
_IDM
(
bmp_ino
)
=
NULL
;
}
}
return
;
}
void
__ntfs_clear_inode
(
ntfs_inode
*
ni
)
{
int
err
;
...
...
@@ -1866,12 +1860,7 @@ void ntfs_clear_big_inode(struct inode *vi)
__ntfs_clear_inode
(
ni
);
if
(
S_ISDIR
(
vi
->
i_mode
))
{
down_write
(
&
ni
->
_IDM
(
bmp_rl
).
lock
);
if
(
ni
->
_IDM
(
bmp_rl
).
rl
)
ntfs_free
(
ni
->
_IDM
(
bmp_rl
).
rl
);
up_write
(
&
ni
->
_IDM
(
bmp_rl
).
lock
);
}
else
if
(
NInoAttr
(
ni
))
{
if
(
NInoAttr
(
ni
))
{
/* Release the base inode if we are holding it. */
if
(
ni
->
nr_extents
==
-
1
)
{
iput
(
VFS_I
(
ni
->
_INE
(
base_ntfs_ino
)));
...
...
fs/ntfs/inode.h
View file @
6ba24a9c
...
...
@@ -92,14 +92,11 @@ struct _ntfs_inode {
run_list
attr_list_rl
;
/* Run list for the attribute list value. */
union
{
struct
{
/* It is a directory or $MFT. */
struct
inode
*
bmp_ino
;
/* Attribute inode for the
directory index $BITMAP. */
u32
index_block_size
;
/* Size of an index block. */
u32
index_vcn_size
;
/* Size of a vcn in this
directory index. */
s64
bmp_size
;
/* Size of the $I30 bitmap. */
s64
bmp_initialized_size
;
/* Copy from $I30 bitmap. */
s64
bmp_allocated_size
;
/* Copy from $I30 bitmap. */
run_list
bmp_rl
;
/* Run list for the $I30 bitmap
if it is non-resident. */
u8
index_block_size_bits
;
/* Log2 of the above. */
u8
index_vcn_size_bits
;
/* Log2 of the above. */
}
SN
(
idm
);
...
...
@@ -165,7 +162,6 @@ typedef enum {
NI_Sparse
,
/* 1: Unnamed data attr is sparse (f).
1: Create sparse files by default (d).
1: Attribute is sparse (a). */
NI_BmpNonResident
,
/* 1: $I30 bitmap attr is non resident (d). */
}
ntfs_inode_state_bits
;
/*
...
...
@@ -203,7 +199,6 @@ NINO_FNS(IndexAllocPresent)
NINO_FNS
(
Compressed
)
NINO_FNS
(
Encrypted
)
NINO_FNS
(
Sparse
)
NINO_FNS
(
BmpNonResident
)
/*
* The full structure containing a ntfs_inode and a vfs struct inode. Used for
...
...
@@ -247,6 +242,8 @@ extern void ntfs_read_inode_mount(struct inode *vi);
extern
void
ntfs_dirty_inode
(
struct
inode
*
vi
);
extern
void
ntfs_put_inode
(
struct
inode
*
vi
);
extern
int
ntfs_show_options
(
struct
seq_file
*
sf
,
struct
vfsmount
*
mnt
);
#endif
/* _LINUX_NTFS_FS_INODE_H */
...
...
fs/ntfs/super.c
View file @
6ba24a9c
...
...
@@ -1263,10 +1263,8 @@ struct super_operations ntfs_sops = {
dirty_inode:
ntfs_dirty_inode
,
/* VFS: Called from
__mark_inode_dirty(). */
//write_inode: NULL, /* VFS: Write dirty inode to disk. */
//put_inode: NULL, /* VFS: Called whenever the reference
// count (i_count) of the inode is
// going to be decreased but before the
// actual decrease. */
put_inode:
ntfs_put_inode
,
/* VFS: Called just before the inode
reference count is decreased. */
//delete_inode: NULL, /* VFS: Delete inode from disk. Called
// when i_count becomes 0 and i_nlink is
// also 0. */
...
...
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