Commit 70d3a085 authored by Anton Altaparmakov's avatar Anton Altaparmakov

NTFS: Release 2.0.6 - Major bugfix to make compatible with other kernel changes.

- Initialize the mftbmp address space properly now that there are more
fields in the struct address_space. This was leading to hangs and
oopses on umount since 2.5.12 because of changes to other parts of
the kernel. We probably want a kernel generic init_address_space()
function...
- Drop BKL from ntfs_readdir() after consultation with Al Viro. The
only caller of ->readdir() is vfs_readdir() which holds i_sem during
the call, and i_sem is sufficient protection against changes in the
directory inode (including ->i_size).
- Use generic_file_llseek() for directories (as opposed to
default_llseek()) as this downs i_sem instead of the BKL which is
what we now need for exclusion against ->f_pos changes considering we
no longer take the BKL in ntfs_readdir().
parent 0501bce1
...@@ -262,6 +262,13 @@ ChangeLog ...@@ -262,6 +262,13 @@ ChangeLog
Note that a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. Note that a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.6:
- Major bugfix to make compatible with other kernel changes. This fixes
the hangs/oopses on umount.
- Locking cleanup in directory operations (remove BKL usage).
2.0.5:
- Major buffer overflow bug fix.
- Minor cleanups and updates for kernel 2.5.12.
2.0.4: 2.0.4:
- Cleanups and updates for kernel 2.5.11. - Cleanups and updates for kernel 2.5.11.
2.0.3: 2.0.3:
......
...@@ -14,11 +14,6 @@ ToDo: ...@@ -14,11 +14,6 @@ ToDo:
strictly a speed optimization. Obviously need to keep the ->run_list strictly a speed optimization. Obviously need to keep the ->run_list
locked or RACE. load_attribute_list() already performs such an locked or RACE. load_attribute_list() already performs such an
optimization so use the same optimization where desired. optimization so use the same optimization where desired.
- Optimize all our readpage functions to not do i/o on buffer heads
beyond initialized_size, just zero the buffer heads instead.
Question: How to setup the buffer heads so they point to the on disk
location correctly (after all they are allocated) but are not read
from disk?
- Consider if ntfs_file_read_compressed_block() shouldn't be coping - Consider if ntfs_file_read_compressed_block() shouldn't be coping
with initialized_size < data_size. I don't think it can happen but with initialized_size < data_size. I don't think it can happen but
it requires more careful consideration. it requires more careful consideration.
...@@ -26,6 +21,24 @@ ToDo: ...@@ -26,6 +21,24 @@ ToDo:
several copies of almost identicall functions and the functions are several copies of almost identicall functions and the functions are
quite big. Modularising them a bit, e.g. a-la get_block(), will make quite big. Modularising them a bit, e.g. a-la get_block(), will make
them cleaner and make code reuse easier. them cleaner and make code reuse easier.
- Want to use dummy inodes for address space i/o. We need some VFS
changes first, which are currently under discussion.
2.0.6 - Major bugfix to make compatible with other kernel changes.
- Initialize the mftbmp address space properly now that there are more
fields in the struct address_space. This was leading to hangs and
oopses on umount since 2.5.12 because of changes to other parts of
the kernel. We probably want a kernel generic init_address_space()
function...
- Drop BKL from ntfs_readdir() after consultation with Al Viro. The
only caller of ->readdir() is vfs_readdir() which holds i_sem during
the call, and i_sem is sufficient protection against changes in the
directory inode (including ->i_size).
- Use generic_file_llseek() for directories (as opposed to
default_llseek()) as this downs i_sem instead of the BKL which is
what we now need for exclusion against ->f_pos changes considering we
no longer take the BKL in ntfs_readdir().
2.0.5 - Major bugfix. Buffer overflow in extent inode handling. 2.0.5 - Major bugfix. Buffer overflow in extent inode handling.
......
...@@ -7,7 +7,7 @@ obj-y := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \ ...@@ -7,7 +7,7 @@ obj-y := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \
obj-m := $(O_TARGET) obj-m := $(O_TARGET)
EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.5\" EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.6\"
ifeq ($(CONFIG_NTFS_DEBUG),y) ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
......
...@@ -763,9 +763,10 @@ int ntfs_file_read_compressed_block(struct page *page) ...@@ -763,9 +763,10 @@ int ntfs_file_read_compressed_block(struct page *page)
* ntfs_decompess. * ntfs_decompess.
*/ */
if (err) { if (err) {
ntfs_error(vol->sb, "ntfs_decompress() failed with " ntfs_error(vol->sb, "ntfs_decompress() failed in inode "
"error code %i. Skipping this " "0x%Lx with error code %i. Skipping "
"compression block.\n", -err); "this compression block.\n",
(unsigned long long)ni->mft_no, -err);
/* Release the unfinished pages. */ /* Release the unfinished pages. */
for (; prev_cur_page < cur_page; prev_cur_page++) { for (; prev_cur_page < cur_page; prev_cur_page++) {
page = pages[prev_cur_page]; page = pages[prev_cur_page];
......
...@@ -500,7 +500,12 @@ static inline int ntfs_filldir(ntfs_volume *vol, struct file *filp, ...@@ -500,7 +500,12 @@ static inline int ntfs_filldir(ntfs_volume *vol, struct file *filp,
} }
/* /*
* VFS calls readdir with BKL held so no possible RACE conditions. * VFS calls readdir without BKL but with i_sem held. This protects the VFS
* parts (e.g. ->f_pos and ->i_size, and it also protects against directory
* modifications). Together with the rw semaphore taken by the call to
* map_mft_record(), the directory is truly locked down so we have a race free
* ntfs_readdir() without the BKL. (-:
*
* We use the same basic approach as the old NTFS driver, i.e. we parse the * We use the same basic approach as the old NTFS driver, i.e. we parse the
* index root entries and then the index allocation entries that are marked * index root entries and then the index allocation entries that are marked
* as in use in the index bitmap. * as in use in the index bitmap.
...@@ -525,7 +530,6 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -525,7 +530,6 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
u8 *kaddr, *bmp, *index_end; u8 *kaddr, *bmp, *index_end;
attr_search_context *ctx; attr_search_context *ctx;
lock_kernel();
ntfs_debug("Entering for inode 0x%Lx, f_pos 0x%Lx.", ntfs_debug("Entering for inode 0x%Lx, f_pos 0x%Lx.",
(unsigned long long)ndir->mft_no, filp->f_pos); (unsigned long long)ndir->mft_no, filp->f_pos);
rc = err = 0; rc = err = 0;
...@@ -794,7 +798,6 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -794,7 +798,6 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
ntfs_debug("filldir returned %i, f_pos 0x%Lx, returning 0.", ntfs_debug("filldir returned %i, f_pos 0x%Lx, returning 0.",
rc, filp->f_pos); rc, filp->f_pos);
#endif #endif
unlock_kernel();
return 0; return 0;
map_page_err_out: map_page_err_out:
ntfs_error(sb, "Reading index allocation data failed."); ntfs_error(sb, "Reading index allocation data failed.");
...@@ -817,7 +820,8 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -817,7 +820,8 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
} }
struct file_operations ntfs_dir_ops = { struct file_operations ntfs_dir_ops = {
read: generic_read_dir, /* Return -EISDIR. */ llseek: generic_file_llseek, /* Seek inside directory. */
readdir: ntfs_readdir, /* Read directory. */ read: generic_read_dir, /* Return -EISDIR. */
readdir: ntfs_readdir, /* Read directory contents. */
}; };
...@@ -1126,8 +1126,7 @@ void ntfs_put_super(struct super_block *vfs_sb) ...@@ -1126,8 +1126,7 @@ void ntfs_put_super(struct super_block *vfs_sb)
down_write(&vol->mftbmp_lock); down_write(&vol->mftbmp_lock);
/* /*
* Clean up mft bitmap address space. Ignore the _inode_ bit in the * Clean up mft bitmap address space. Ignore the _inode_ bit in the
* name of the function... FIXME: What does this do with dirty pages? * name of the function... FIXME: This destroys dirty pages!!! (AIA)
* (ask Al Viro)
*/ */
truncate_inode_pages(&vol->mftbmp_mapping, 0); truncate_inode_pages(&vol->mftbmp_mapping, 0);
vol->mftbmp_mapping.a_ops = NULL; vol->mftbmp_mapping.a_ops = NULL;
...@@ -1493,22 +1492,6 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) ...@@ -1493,22 +1492,6 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
vol->sb = sb; vol->sb = sb;
vol->upcase = NULL; vol->upcase = NULL;
vol->mft_ino = NULL; vol->mft_ino = NULL;
init_rwsem(&vol->mftbmp_lock);
INIT_LIST_HEAD(&vol->mftbmp_mapping.clean_pages);
INIT_LIST_HEAD(&vol->mftbmp_mapping.dirty_pages);
INIT_LIST_HEAD(&vol->mftbmp_mapping.locked_pages);
vol->mftbmp_mapping.a_ops = NULL;
vol->mftbmp_mapping.host = NULL;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,6)
vol->mftbmp_mapping.i_mmap = NULL;
vol->mftbmp_mapping.i_mmap_shared = NULL;
#else
INIT_LIST_HEAD(&vol->mftbmp_mapping.i_mmap);
INIT_LIST_HEAD(&vol->mftbmp_mapping.i_mmap_shared);
#endif
spin_lock_init(&vol->mftbmp_mapping.i_shared_lock);
init_run_list(&vol->mftbmp_rl);
vol->mftmirr_ino = NULL; vol->mftmirr_ino = NULL;
vol->lcnbmp_ino = NULL; vol->lcnbmp_ino = NULL;
init_rwsem(&vol->lcnbmp_lock); init_rwsem(&vol->lcnbmp_lock);
...@@ -1519,6 +1502,26 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) ...@@ -1519,6 +1502,26 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
vol->on_errors = 0; vol->on_errors = 0;
vol->mft_zone_multiplier = 0; vol->mft_zone_multiplier = 0;
vol->nls_map = NULL; vol->nls_map = NULL;
init_rwsem(&vol->mftbmp_lock);
init_run_list(&vol->mftbmp_rl);
/* Initialize the mftbmp address space mapping. */
INIT_RADIX_TREE(&vol->mftbmp_mapping.page_tree, GFP_ATOMIC);
rwlock_init(&vol->mftbmp_mapping.page_lock);
INIT_LIST_HEAD(&vol->mftbmp_mapping.clean_pages);
INIT_LIST_HEAD(&vol->mftbmp_mapping.dirty_pages);
INIT_LIST_HEAD(&vol->mftbmp_mapping.locked_pages);
INIT_LIST_HEAD(&vol->mftbmp_mapping.io_pages);
vol->mftbmp_mapping.nrpages = 0;
vol->mftbmp_mapping.a_ops = NULL;
vol->mftbmp_mapping.host = NULL;
INIT_LIST_HEAD(&vol->mftbmp_mapping.i_mmap);
INIT_LIST_HEAD(&vol->mftbmp_mapping.i_mmap_shared);
spin_lock_init(&vol->mftbmp_mapping.i_shared_lock);
vol->mftbmp_mapping.dirtied_when = 0;
vol->mftbmp_mapping.gfp_mask = GFP_HIGHUSER;
vol->mftbmp_mapping.ra_pages =
sb->s_bdev->bd_inode->i_mapping->ra_pages;
/* /*
* Default is group and other don't have any access to files or * Default is group and other don't have any access to files or
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment