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
Kirill Smelkov
linux
Commits
af81e654
Commit
af81e654
authored
Nov 10, 2004
by
Anton Altaparmakov
Browse files
Options
Browse Files
Download
Plain Diff
Merge
ssh://linux-ntfs@bkbits.net/ntfs-2.6-devel
into cantab.net:/home/src/ntfs-2.6-devel
parents
aae109de
d586a8d9
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
68 additions
and
76 deletions
+68
-76
Documentation/filesystems/ntfs.txt
Documentation/filesystems/ntfs.txt
+3
-0
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+4
-1
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/aops.c
fs/ntfs/aops.c
+60
-74
No files found.
Documentation/filesystems/ntfs.txt
View file @
af81e654
...
@@ -432,6 +432,9 @@ ChangeLog
...
@@ -432,6 +432,9 @@ 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.22:
- Improve handling of ntfs volumes with errors.
- Fix various bugs and race conditions.
2.1.21:
2.1.21:
- Fix several race conditions and various other bugs.
- Fix several race conditions and various other bugs.
- Many internal cleanups, code reorganization, optimizations, and mft
- Many internal cleanups, code reorganization, optimizations, and mft
...
...
fs/ntfs/ChangeLog
View file @
af81e654
...
@@ -25,7 +25,7 @@ ToDo/Notes:
...
@@ -25,7 +25,7 @@ ToDo/Notes:
- Enable the code for setting the NT4 compatibility flag when we start
- Enable the code for setting the NT4 compatibility flag when we start
making NTFS 1.2 specific modifications.
making NTFS 1.2 specific modifications.
2.1.22
-WIP
2.1.22
- Many bug and race fixes and error handling improvements.
- Improve error handling in fs/ntfs/inode.c::ntfs_truncate().
- Improve error handling in fs/ntfs/inode.c::ntfs_truncate().
- Change fs/ntfs/inode.c::ntfs_truncate() to return an error code
- Change fs/ntfs/inode.c::ntfs_truncate() to return an error code
...
@@ -85,6 +85,9 @@ ToDo/Notes:
...
@@ -85,6 +85,9 @@ ToDo/Notes:
complete runlist for the mft mirror is always mapped into memory.
complete runlist for the mft mirror is always mapped into memory.
- Add creation of buffers to fs/ntfs/mft.c::ntfs_sync_mft_mirror().
- Add creation of buffers to fs/ntfs/mft.c::ntfs_sync_mft_mirror().
- Improve error handling in fs/ntfs/aops.c::ntfs_{read,write}_block().
- Improve error handling in fs/ntfs/aops.c::ntfs_{read,write}_block().
- Cleanup fs/ntfs/aops.c::ntfs_{read,write}page() since we know that a
resident attribute will be smaller than a page which makes the code
simpler. Also make the code more tolerant to concurrent ->truncate.
2.1.21 - Fix some races and bugs, rewrite mft write code, add mft allocator.
2.1.21 - Fix some races and bugs, rewrite mft write code, add mft allocator.
...
...
fs/ntfs/Makefile
View file @
af81e654
...
@@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
...
@@ -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
\
index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o
\
unistr.o upcase.o
unistr.o upcase.o
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.1.22
-WIP
\"
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.1.22
\"
ifeq
($(CONFIG_NTFS_DEBUG),y)
ifeq
($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS
+=
-DDEBUG
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/aops.c
View file @
af81e654
...
@@ -341,7 +341,7 @@ static int ntfs_read_block(struct page *page)
...
@@ -341,7 +341,7 @@ static int ntfs_read_block(struct page *page)
*/
*/
static
int
ntfs_readpage
(
struct
file
*
file
,
struct
page
*
page
)
static
int
ntfs_readpage
(
struct
file
*
file
,
struct
page
*
page
)
{
{
s64
attr_pos
;
loff_t
i_size
;
ntfs_inode
*
ni
,
*
base_ni
;
ntfs_inode
*
ni
,
*
base_ni
;
u8
*
kaddr
;
u8
*
kaddr
;
ntfs_attr_search_ctx
*
ctx
;
ntfs_attr_search_ctx
*
ctx
;
...
@@ -350,7 +350,6 @@ static int ntfs_readpage(struct file *file, struct page *page)
...
@@ -350,7 +350,6 @@ static int ntfs_readpage(struct file *file, struct page *page)
int
err
=
0
;
int
err
=
0
;
BUG_ON
(
!
PageLocked
(
page
));
BUG_ON
(
!
PageLocked
(
page
));
/*
/*
* This can potentially happen because we clear PageUptodate() during
* This can potentially happen because we clear PageUptodate() during
* ntfs_writepage() of MstProtected() attributes.
* ntfs_writepage() of MstProtected() attributes.
...
@@ -359,7 +358,6 @@ static int ntfs_readpage(struct file *file, struct page *page)
...
@@ -359,7 +358,6 @@ static int ntfs_readpage(struct file *file, struct page *page)
unlock_page
(
page
);
unlock_page
(
page
);
return
0
;
return
0
;
}
}
ni
=
NTFS_I
(
page
->
mapping
->
host
);
ni
=
NTFS_I
(
page
->
mapping
->
host
);
/* NInoNonResident() == NInoIndexAllocPresent() */
/* NInoNonResident() == NInoIndexAllocPresent() */
...
@@ -381,12 +379,23 @@ static int ntfs_readpage(struct file *file, struct page *page)
...
@@ -381,12 +379,23 @@ static int ntfs_readpage(struct file *file, struct page *page)
/* Normal data stream. */
/* Normal data stream. */
return
ntfs_read_block
(
page
);
return
ntfs_read_block
(
page
);
}
}
/* Attribute is resident, implying it is not compressed or encrypted. */
/*
* Attribute is resident, implying it is not compressed or encrypted.
* This also means the attribute is smaller than an mft record and
* hence smaller than a page, so can simply zero out any pages with
* index above 0. We can also do this if the file size is 0.
*/
if
(
unlikely
(
page
->
index
>
0
||
!
i_size_read
(
VFS_I
(
ni
))))
{
kaddr
=
kmap_atomic
(
page
,
KM_USER0
);
memset
(
kaddr
,
0
,
PAGE_CACHE_SIZE
);
flush_dcache_page
(
page
);
kunmap_atomic
(
kaddr
,
KM_USER0
);
goto
done
;
}
if
(
!
NInoAttr
(
ni
))
if
(
!
NInoAttr
(
ni
))
base_ni
=
ni
;
base_ni
=
ni
;
else
else
base_ni
=
ni
->
ext
.
base_ntfs_ino
;
base_ni
=
ni
->
ext
.
base_ntfs_ino
;
/* Map, pin, and lock the mft record. */
/* Map, pin, and lock the mft record. */
mrec
=
map_mft_record
(
base_ni
);
mrec
=
map_mft_record
(
base_ni
);
if
(
IS_ERR
(
mrec
))
{
if
(
IS_ERR
(
mrec
))
{
...
@@ -402,35 +411,25 @@ static int ntfs_readpage(struct file *file, struct page *page)
...
@@ -402,35 +411,25 @@ static int ntfs_readpage(struct file *file, struct page *page)
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
);
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
);
if
(
unlikely
(
err
))
if
(
unlikely
(
err
))
goto
put_unm_err_out
;
goto
put_unm_err_out
;
/* Starting position of the page within the attribute value. */
attr_pos
=
page
->
index
<<
PAGE_CACHE_SHIFT
;
/* The total length of the attribute value. */
attr_len
=
le32_to_cpu
(
ctx
->
attr
->
data
.
resident
.
value_length
);
attr_len
=
le32_to_cpu
(
ctx
->
attr
->
data
.
resident
.
value_length
);
i_size
=
i_size_read
(
VFS_I
(
ni
));
if
(
unlikely
(
attr_len
>
i_size
))
attr_len
=
i_size
;
kaddr
=
kmap_atomic
(
page
,
KM_USER0
);
kaddr
=
kmap_atomic
(
page
,
KM_USER0
);
/* Copy over in bounds data, zeroing the remainder of the page. */
/* Copy the data to the page. */
if
(
attr_pos
<
attr_len
)
{
memcpy
(
kaddr
,
(
u8
*
)
ctx
->
attr
+
u32
bytes
=
attr_len
-
attr_pos
;
le16_to_cpu
(
ctx
->
attr
->
data
.
resident
.
value_offset
),
if
(
bytes
>
PAGE_CACHE_SIZE
)
attr_len
);
bytes
=
PAGE_CACHE_SIZE
;
/* Zero the remainder of the page. */
else
if
(
bytes
<
PAGE_CACHE_SIZE
)
memset
(
kaddr
+
attr_len
,
0
,
PAGE_CACHE_SIZE
-
attr_len
);
memset
(
kaddr
+
bytes
,
0
,
PAGE_CACHE_SIZE
-
bytes
);
/* Copy the data to the page. */
memcpy
(
kaddr
,
attr_pos
+
(
char
*
)
ctx
->
attr
+
le16_to_cpu
(
ctx
->
attr
->
data
.
resident
.
value_offset
),
bytes
);
}
else
memset
(
kaddr
,
0
,
PAGE_CACHE_SIZE
);
flush_dcache_page
(
page
);
flush_dcache_page
(
page
);
kunmap_atomic
(
kaddr
,
KM_USER0
);
kunmap_atomic
(
kaddr
,
KM_USER0
);
SetPageUptodate
(
page
);
put_unm_err_out:
put_unm_err_out:
ntfs_attr_put_search_ctx
(
ctx
);
ntfs_attr_put_search_ctx
(
ctx
);
unm_err_out:
unm_err_out:
unmap_mft_record
(
base_ni
);
unmap_mft_record
(
base_ni
);
done:
SetPageUptodate
(
page
);
err_out:
err_out:
unlock_page
(
page
);
unlock_page
(
page
);
return
err
;
return
err
;
...
@@ -1223,21 +1222,22 @@ static int ntfs_write_mst_block(struct page *page,
...
@@ -1223,21 +1222,22 @@ static int ntfs_write_mst_block(struct page *page,
*/
*/
static
int
ntfs_writepage
(
struct
page
*
page
,
struct
writeback_control
*
wbc
)
static
int
ntfs_writepage
(
struct
page
*
page
,
struct
writeback_control
*
wbc
)
{
{
s64
attr_pos
;
loff_t
i_size
;
struct
inode
*
vi
;
struct
inode
*
vi
;
ntfs_inode
*
ni
,
*
base_ni
;
ntfs_inode
*
ni
,
*
base_ni
;
char
*
kaddr
;
char
*
kaddr
;
ntfs_attr_search_ctx
*
ctx
;
ntfs_attr_search_ctx
*
ctx
;
MFT_RECORD
*
m
;
MFT_RECORD
*
m
;
u32
attr_len
,
bytes
;
u32
attr_len
;
int
err
;
int
err
;
BUG_ON
(
!
PageLocked
(
page
));
BUG_ON
(
!
PageLocked
(
page
));
vi
=
page
->
mapping
->
host
;
vi
=
page
->
mapping
->
host
;
i_size
=
i_size_read
(
vi
);
/* Is the page fully outside i_size? (truncate in progress) */
/* Is the page fully outside i_size? (truncate in progress) */
if
(
unlikely
(
page
->
index
>=
(
vi
->
i_size
+
PAGE_CACHE_SIZE
-
1
)
>>
if
(
unlikely
(
page
->
index
>=
(
i_size
+
PAGE_CACHE_SIZE
-
1
)
>>
PAGE_CACHE_SHIFT
))
{
PAGE_CACHE_SHIFT
))
{
/*
/*
* The page may have dirty, unmapped buffers. Make them
* The page may have dirty, unmapped buffers. Make them
...
@@ -1248,7 +1248,6 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
...
@@ -1248,7 +1248,6 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
ntfs_debug
(
"Write outside i_size - truncated?"
);
ntfs_debug
(
"Write outside i_size - truncated?"
);
return
0
;
return
0
;
}
}
ni
=
NTFS_I
(
vi
);
ni
=
NTFS_I
(
vi
);
/* NInoNonResident() == NInoIndexAllocPresent() */
/* NInoNonResident() == NInoIndexAllocPresent() */
...
@@ -1284,9 +1283,9 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
...
@@ -1284,9 +1283,9 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
}
}
}
}
/* We have to zero every time due to mmap-at-end-of-file. */
/* We have to zero every time due to mmap-at-end-of-file. */
if
(
page
->
index
>=
(
vi
->
i_size
>>
PAGE_CACHE_SHIFT
))
{
if
(
page
->
index
>=
(
i_size
>>
PAGE_CACHE_SHIFT
))
{
/* The page straddles i_size. */
/* The page straddles i_size. */
unsigned
int
ofs
=
vi
->
i_size
&
~
PAGE_CACHE_MASK
;
unsigned
int
ofs
=
i_size
&
~
PAGE_CACHE_MASK
;
kaddr
=
kmap_atomic
(
page
,
KM_USER0
);
kaddr
=
kmap_atomic
(
page
,
KM_USER0
);
memset
(
kaddr
+
ofs
,
0
,
PAGE_CACHE_SIZE
-
ofs
);
memset
(
kaddr
+
ofs
,
0
,
PAGE_CACHE_SIZE
-
ofs
);
flush_dcache_page
(
page
);
flush_dcache_page
(
page
);
...
@@ -1300,16 +1299,25 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
...
@@ -1300,16 +1299,25 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
}
}
/*
/*
* Attribute is resident, implying it is not compressed, encrypted,
* Attribute is resident, implying it is not compressed, encrypted,
* sparse, or mst protected.
* sparse, or mst protected. This also means the attribute is smaller
* than an mft record and hence smaller than a page, so can simply
* return error on any pages with index above 0.
*/
*/
BUG_ON
(
page_has_buffers
(
page
));
BUG_ON
(
page_has_buffers
(
page
));
BUG_ON
(
!
PageUptodate
(
page
));
BUG_ON
(
!
PageUptodate
(
page
));
if
(
unlikely
(
page
->
index
>
0
))
{
ntfs_error
(
vi
->
i_sb
,
"BUG()! page->index (0x%lx) > 0. "
"Aborting write."
,
page
->
index
);
BUG_ON
(
PageWriteback
(
page
));
set_page_writeback
(
page
);
unlock_page
(
page
);
end_page_writeback
(
page
);
return
-
EIO
;
}
if
(
!
NInoAttr
(
ni
))
if
(
!
NInoAttr
(
ni
))
base_ni
=
ni
;
base_ni
=
ni
;
else
else
base_ni
=
ni
->
ext
.
base_ntfs_ino
;
base_ni
=
ni
->
ext
.
base_ntfs_ino
;
/* Map, pin, and lock the mft record. */
/* Map, pin, and lock the mft record. */
m
=
map_mft_record
(
base_ni
);
m
=
map_mft_record
(
base_ni
);
if
(
IS_ERR
(
m
))
{
if
(
IS_ERR
(
m
))
{
...
@@ -1327,32 +1335,6 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
...
@@ -1327,32 +1335,6 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
);
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
);
if
(
unlikely
(
err
))
if
(
unlikely
(
err
))
goto
err_out
;
goto
err_out
;
/* Starting position of the page within the attribute value. */
attr_pos
=
page
->
index
<<
PAGE_CACHE_SHIFT
;
/* The total length of the attribute value. */
attr_len
=
le32_to_cpu
(
ctx
->
attr
->
data
.
resident
.
value_length
);
if
(
unlikely
(
vi
->
i_size
!=
attr_len
))
{
ntfs_error
(
vi
->
i_sb
,
"BUG()! i_size (0x%llx) doesn't match "
"attr_len (0x%x). Aborting write."
,
vi
->
i_size
,
attr_len
);
err
=
-
EIO
;
goto
err_out
;
}
if
(
unlikely
(
attr_pos
>=
attr_len
))
{
ntfs_error
(
vi
->
i_sb
,
"BUG()! attr_pos (0x%llx) > attr_len "
"(0x%x). Aborting write."
,
(
unsigned
long
long
)
attr_pos
,
attr_len
);
err
=
-
EIO
;
goto
err_out
;
}
bytes
=
attr_len
-
attr_pos
;
if
(
unlikely
(
bytes
>
PAGE_CACHE_SIZE
))
bytes
=
PAGE_CACHE_SIZE
;
/*
/*
* Keep the VM happy. This must be done otherwise the radix-tree tag
* Keep the VM happy. This must be done otherwise the radix-tree tag
* PAGECACHE_TAG_DIRTY remains set even though the page is clean.
* PAGECACHE_TAG_DIRTY remains set even though the page is clean.
...
@@ -1384,26 +1366,30 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
...
@@ -1384,26 +1366,30 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
* TODO: ntfs_truncate(), others?
* TODO: ntfs_truncate(), others?
*/
*/
attr_len
=
le32_to_cpu
(
ctx
->
attr
->
data
.
resident
.
value_length
);
i_size
=
i_size_read
(
VFS_I
(
ni
));
kaddr
=
kmap_atomic
(
page
,
KM_USER0
);
kaddr
=
kmap_atomic
(
page
,
KM_USER0
);
if
(
unlikely
(
attr_len
>
i_size
))
{
/* Zero out of bounds area in the mft record. */
memset
((
u8
*
)
ctx
->
attr
+
le16_to_cpu
(
ctx
->
attr
->
data
.
resident
.
value_offset
)
+
i_size
,
0
,
attr_len
-
i_size
);
attr_len
=
i_size
;
}
/* Copy the data from the page to the mft record. */
/* Copy the data from the page to the mft record. */
memcpy
((
u8
*
)
ctx
->
attr
+
le16_to_cpu
(
memcpy
((
u8
*
)
ctx
->
attr
+
ctx
->
attr
->
data
.
resident
.
value_offset
)
+
attr_pos
,
le16_to_cpu
(
ctx
->
attr
->
data
.
resident
.
value_offset
)
,
kaddr
,
bytes
);
kaddr
,
attr_len
);
flush_dcache_mft_record_page
(
ctx
->
ntfs_ino
);
flush_dcache_mft_record_page
(
ctx
->
ntfs_ino
);
#if 0
/* Zero out of bounds area in the page cache page. */
/* Zero out of bounds area. */
memset
(
kaddr
+
attr_len
,
0
,
PAGE_CACHE_SIZE
-
attr_len
);
if (likely(bytes < PAGE_CACHE_SIZE)) {
flush_dcache_page
(
page
);
memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
flush_dcache_page(page);
}
#endif
kunmap_atomic
(
kaddr
,
KM_USER0
);
kunmap_atomic
(
kaddr
,
KM_USER0
);
end_page_writeback
(
page
);
end_page_writeback
(
page
);
/* Mark the mft record dirty, so it gets written back. */
/* Mark the mft record dirty, so it gets written back. */
mark_mft_record_dirty
(
ctx
->
ntfs_ino
);
mark_mft_record_dirty
(
ctx
->
ntfs_ino
);
ntfs_attr_put_search_ctx
(
ctx
);
ntfs_attr_put_search_ctx
(
ctx
);
unmap_mft_record
(
base_ni
);
unmap_mft_record
(
base_ni
);
return
0
;
return
0
;
...
@@ -1413,13 +1399,13 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
...
@@ -1413,13 +1399,13 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
"page so we try again later."
);
"page so we try again later."
);
/*
/*
* Put the page back on mapping->dirty_pages, but leave its
* Put the page back on mapping->dirty_pages, but leave its
* buffer
's
dirty state as-is.
* buffer
s'
dirty state as-is.
*/
*/
redirty_page_for_writepage
(
wbc
,
page
);
redirty_page_for_writepage
(
wbc
,
page
);
err
=
0
;
err
=
0
;
}
else
{
}
else
{
ntfs_error
(
vi
->
i_sb
,
"Resident attribute write failed with "
ntfs_error
(
vi
->
i_sb
,
"Resident attribute write failed with "
"error %i.
Setting page error flag."
,
-
err
);
"error %i.
Setting page error flag."
,
err
);
SetPageError
(
page
);
SetPageError
(
page
);
}
}
unlock_page
(
page
);
unlock_page
(
page
);
...
...
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