Commit eeb382a1 authored by Anton Altaparmakov's avatar Anton Altaparmakov

NTFS 2.0.3: Small bug fixes, cleanups, and performance improvements.

- Remove some dead code from mft.c.
- Optimize readpage and read_block functions throughout aops.c so that
  only initialized blocks are read. Non-initialized ones have their
  buffer head mapped, zeroed, and set up to date, without scheduling
  any i/o. Thanks to Al Viro for advice on how to avoid the device i/o.
Thanks go to Andrew Morton for spotting the below:
- Fix buglet in allocate_compression_buffers() error code path.
- Call flush_dcache_page() after modifying page cache page contents in
  ntfs_file_readpage().
- Check for existence of page buffers throughout aops.c before calling
  create_empty_buffers(). This happens when an I/O error occurs and the
  read is retried. (It also happens once writing is implemented so that
  needed doing anyway but I had left it for later...)
- Don't BUG_ON() uptodate and/or mapped buffers throughout aops.c in
  readpage and read_block functions. Reasoning same as above (i.e. I/O
  error retries and future write code paths.)
parent 43b706e9
......@@ -168,6 +168,8 @@ ChangeLog
Note that a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.3:
- Small bug fixes, cleanups, and performance improvements.
2.0.2:
- Use default fmask of 0177 so that files are no executable by default.
If you want owner executable files, just use fmask=0077.
......@@ -177,7 +179,6 @@ Note that a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.1:
- Minor updates, primarily set the executable bit by default on files
so they can be executed.
2.0.0:
- Started ChangeLog.
......@@ -27,6 +27,25 @@ ToDo:
quite big. Modularising them a bit, e.g. a-la get_block(), will make
them cleaner and make code reuse easier.
2.0.3 - Small bug fixes, cleanups, and performance improvements.
- Remove some dead code from mft.c.
- Optimize readpage and read_block functions throughout aops.c so that
only initialized blocks are read. Non-initialized ones have their
buffer head mapped, zeroed, and set up to date, without scheduling
any i/o. Thanks to Al Viro for advice on how to avoid the device i/o.
Thanks go to Andrew Morton for spotting the below:
- Fix buglet in allocate_compression_buffers() error code path.
- Call flush_dcache_page() after modifying page cache page contents in
ntfs_file_readpage().
- Check for existence of page buffers throughout aops.c before calling
create_empty_buffers(). This happens when an I/O error occurs and the
read is retried. (It also happens once writing is implemented so that
needed doing anyway but I had left it for later...)
- Don't BUG_ON() uptodate and/or mapped buffers throughout aops.c in
readpage and read_block functions. Reasoning same as above (i.e. I/O
error retries and future write code paths.)
2.0.2 - Minor updates and cleanups.
- Cleanup: rename mst.c::__post_read_mst_fixup to post_write_mst_fixup
......
......@@ -7,7 +7,7 @@ obj-y := time.o unistr.o inode.o file.o mft.o super.o debug.o aops.o \
obj-m := $(O_TARGET)
EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.2\"
EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.3\"
ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
......
This diff is collapsed.
......@@ -69,7 +69,7 @@ int allocate_compression_buffers(void)
BUG_ON(ntfs_compression_buffers);
ntfs_compression_buffers = (u8**)kmalloc(smp_num_cpus * sizeof(u8 *),
ntfs_compression_buffers = (u8**)kmalloc(smp_num_cpus * sizeof(u8*),
GFP_KERNEL);
if (!ntfs_compression_buffers)
return -ENOMEM;
......@@ -81,7 +81,7 @@ int allocate_compression_buffers(void)
if (i == smp_num_cpus)
return 0;
/* Allocation failed, cleanup and return error. */
for (j = 0; i < j; j++)
for (j = 0; j < i; j++)
vfree(ntfs_compression_buffers[j]);
kfree(ntfs_compression_buffers);
return -ENOMEM;
......
......@@ -69,44 +69,6 @@ static void __format_mft_record(MFT_RECORD *m, const int size,
a->length = cpu_to_le32(0);
}
/**
* format_mft_record2 - initialize an empty mft record
* @vfs_sb: vfs super block of volume
* @inum: mft record number / inode number to format
* @mft_rec: mapped, pinned and locked mft record (optional)
*
* Initialize an empty mft record. This is used when extending the MFT.
*
* If @mft_rec is NULL, we call map_mft_record() to obtain the record and we
* unmap it again when finished.
*
* We return 0 on success or -errno on error.
*/
#if 0
// Can't do this as iget_map_mft_record no longer exists...
int format_mft_record2(struct super_block *vfs_sb, const unsigned long inum,
MFT_RECORD *mft_rec)
{
MFT_RECORD *m;
ntfs_inode *ni;
if (mft_rec)
m = mft_rec;
else {
m = iget_map_mft_record(WRITE, vfs_sb, inum, &ni);
if (IS_ERR(m))
return PTR_ERR(m);
}
__format_mft_record(m, NTFS_SB(vfs_sb)->mft_record_size, inum);
if (!mft_rec) {
// TODO: dirty mft record
unmap_mft_record(WRITE, ni);
// TODO: Do stuff to get rid of the ntfs_inode
}
return 0;
}
#endif
/**
* format_mft_record - initialize an empty mft record
* @ni: ntfs inode of mft record
......@@ -340,71 +302,6 @@ MFT_RECORD *map_mft_record(const int rw, ntfs_inode *ni)
return m;
}
/**
* iget_map_mft_record - iget, map, pin, lock an mft record
* @rw: map for read (rw = READ) or write (rw = WRITE)
* @vfs_sb: vfs super block of mounted volume
* @inum: inode number / MFT record number whose mft record to map
* @vfs_ino: output parameter which we set to the inode on successful return
*
* Does the same as map_mft_record(), except that it starts out only with the
* knowledge of the super block (@vfs_sb) and the mft record number which is of
* course the same as the inode number (@inum).
*
* On success, *@vfs_ino will contain a pointer to the inode structure of the
* mft record on return. On error return, *@vfs_ino is undefined.
*
* See map_mft_record() description for details and for a description of how
* errors are returned and what error codes are defined.
*
* IMPROTANT: The caller is responsible for calling iput(@vfs_ino) when
* finished with the inode, i.e. after unmap_mft_record() has been called. If
* that is omitted you will get busy inodes upon umount...
*/
#if 0
// this is no longer possible. iget() cannot be called as we may be loading
// an ntfs inode which will never have a corresponding vfs inode counter part.
// this is not going to be pretty. )-:
// we need our own hash for ntfs inodes now, ugh. )-:
// not having vfs inodes associated with all ntfs inodes is a bad mistake I am
// getting the impression. this will in the end turn out uglier than just
// having iget_no_wait().
// my only hope is that we can get away without this functionality in the driver
// altogether. we are ok for extent inodes already because we only handle them
// via map_extent_mft_record().
// if we really need it, we could have a list or hash of "pure ntfs inodes"
// to cope with this situation, so the lookup would be:
// look for the inode and if not present look for pure ntfs inode and if not
// present add a new pure ntfs inode. under this scheme extent inodes have to
// also be added to the list/hash of pure inodes.
MFT_RECORD *iget_map_mft_record(const int rw, struct super_block *vfs_sb,
const unsigned long inum, struct inode **vfs_ino)
{
struct inode *inode;
MFT_RECORD *mrec;
/*
* The corresponding iput() happens when clear_inode() is called on the
* base mft record of this extent mft record.
* When used on base mft records, caller has to perform the iput().
*/
inode = iget(vfs_sb, inum);
if (inode && !is_bad_inode(inode)) {
mrec = map_mft_record(rw, inode);
if (!IS_ERR(mrec)) {
ntfs_debug("Success for i_ino 0x%lx.", inum);
*vfs_ino = inode;
return mrec;
}
} else
mrec = ERR_PTR(-EIO);
if (inode)
iput(inode);
ntfs_debug("Failed for i_ino 0x%lx.", inum);
return mrec;
}
#endif
/**
* unmap_mft_record - release a mapped mft record
* @rw: unmap from read (@rw = READ) or write (@rw = WRITE)
......
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