Commit 32e5fcaa authored by Anton Altaparmakov's avatar Anton Altaparmakov

NTFS: 2.1.13 - Enable overwriting of resident files and housekeeping of system files.

- Mark the volume dirty when (re)mounting read-write and mark it clean
  when unmounting or remounting read-only.  If any volume errors are
  found, the volume is left marked dirty to force chkdsk to run.
- Add code to set the NT4 compatibility flag when (re)mounting
  read-write for newer NTFS versions but leave it commented out for now
  since we do not make any modifications that are NTFS 1.2 specific yet
  and since setting this flag breaks Captive-NTFS which is not nice.
  This code must be enabled once we start writing NTFS 1.2 specific
  changes otherwise Windows NTFS driver might crash / cause corruption.
- Fix a silly bug that caused a deadlock in ntfs_mft_writepage().
  For inode 0, i.e. $MFT itself, we cannot use ilookup5() from
  there because the inode is already locked by the kernel
  (fs/fs-writeback.c::__sync_single_inode()) and ilookup5() waits
  until the inode is unlocked before returning it and it never gets
  unlocked because ntfs_mft_writepage() never returns.  )-:
  Fortunately, we have inode 0 pinned in icache for the duration
  of the mount so we can access it directly.
Signed-off-by: default avatarAnton Altaparmakov <aia21@cantab.net>
parent ec479b03
......@@ -273,6 +273,19 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.1.13:
- Implement writing of inodes (access time updates are not implemented
yet so mounting with -o noatime,nodiratime is enforced).
- Enable writing out of resident files so you can now overwrite any
uncompressed, unencrypted, nonsparse file as long as you do not
change the file size.
- Add housekeeping of ntfs system files so that ntfsfix no longer needs
to be run after writing to an NTFS volume.
NOTE: This still leaves quota tracking and user space journalling on
the side but they should not cause data corruption. In the worst
case the charged quotas will be out of date ($Quota) and some
userspace applications might get confused due to the out of date
userspace journal ($UsnJrnl).
2.1.12:
- Fix the second fix to the decompression engine from the 2.1.9 release
and some further internals cleanups.
......
ToDo:
ToDo/Notes:
- Find and fix bugs.
- Either invalidate quotas or update the quota charges on NTFS 3.x
volumes with quota tracking enabled ($Quota).
......@@ -32,8 +32,10 @@ ToDo:
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.13 - WIP.
2.1.13 - Enable overwriting of resident files and housekeeping of system files.
- Implement writing of mft records (fs/ntfs/mft.[hc]), which includes
keeping the mft mirror in sync with the mft when mirrored mft records
......@@ -70,6 +72,15 @@ ToDo:
are present and ask the user to email us if they see this happening.
- Add functions ntfs_{clear,set}_volume_flags(), to modify the volume
information flags (fs/ntfs/super.c).
- Mark the volume dirty when (re)mounting read-write and mark it clean
when unmounting or remounting read-only. If any volume errors are
found, the volume is left marked dirty to force chkdsk to run.
- Add code to set the NT4 compatibility flag when (re)mounting
read-write for newer NTFS versions but leave it commented out for now
since we do not make any modifications that are NTFS 1.2 specific yet
and since setting this flag breaks Captive-NTFS which is not nice.
This code must be enabled once we start writing NTFS 1.2 specific
changes otherwise Windows NTFS driver might crash / cause corruption.
2.1.12 - Fix the second fix to the decompression engine and some cleanups.
......
......@@ -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 unistr.o upcase.o
EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.13-WIP\"
EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.13\"
ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
......
......@@ -933,44 +933,77 @@ static int ntfs_mft_writepage(struct page *page, struct writeback_control *wbc)
na.name = NULL;
na.name_len = 0;
na.type = AT_UNUSED;
/*
* Check if the inode corresponding to this mft record is in
* the VFS inode cache and obtain a reference to it if it is.
*/
vi = ilookup5(sb, mft_no, (test_t)ntfs_test_inode, &na);
ntfs_debug("Looking for inode 0x%lx in icache.", mft_no);
/*
* For inode 0, i.e. $MFT itself, we cannot use ilookup5() from
* here or we deadlock because the inode is already locked by
* the kernel (fs/fs-writeback.c::__sync_single_inode()) and
* ilookup5() waits until the inode is unlocked before
* returning it and it never gets unlocked because
* ntfs_mft_writepage() never returns. )-: Fortunately, we
* have inode 0 pinned in icache for the duration of the mount
* so we can access it directly.
*/
if (!mft_no) {
/* Balance the below iput(). */
vi = igrab(mft_vi);
BUG_ON(vi != mft_vi);
} else
vi = ilookup5(sb, mft_no, (test_t)ntfs_test_inode, &na);
if (vi) {
ntfs_debug("Inode 0x%lx is in icache.", mft_no);
/* The inode is in icache. Check if it is dirty. */
ni = NTFS_I(vi);
if (!NInoDirty(ni)) {
/* The inode is not dirty, skip this record. */
ntfs_debug("Inode 0x%lx is not dirty, "
"continuing search.", mft_no);
iput(vi);
continue;
}
ntfs_debug("Inode 0x%lx is dirty, aborting search.",
mft_no);
/* The inode is dirty, no need to search further. */
iput(vi);
is_dirty = TRUE;
break;
}
ntfs_debug("Inode 0x%lx is not in icache.", mft_no);
/* The inode is not in icache. */
/* Skip the record if it is not a mft record (type "FILE"). */
if (!ntfs_is_mft_recordp(maddr))
if (!ntfs_is_mft_recordp(maddr)) {
ntfs_debug("Mft record 0x%lx is not a FILE record, "
"continuing search.", mft_no);
continue;
}
m = (MFT_RECORD*)maddr;
/*
* Skip the mft record if it is not in use. FIXME: What about
* deleted/deallocated (extent) inodes? (AIA)
*/
if (!(m->flags & MFT_RECORD_IN_USE))
if (!(m->flags & MFT_RECORD_IN_USE)) {
ntfs_debug("Mft record 0x%lx is not in use, "
"continuing search.", mft_no);
continue;
}
/* Skip the mft record if it is a base inode. */
if (!m->base_mft_record)
if (!m->base_mft_record) {
ntfs_debug("Mft record 0x%lx is a base record, "
"continuing search.", mft_no);
continue;
}
/*
* This is an extent mft record. Check if the inode
* corresponding to its base mft record is in icache.
*/
na.mft_no = MREF_LE(m->base_mft_record);
ntfs_debug("Mft record 0x%lx is an extent record. Looking "
"for base inode 0x%lx in icache.", mft_no,
na.mft_no);
vi = ilookup5(sb, na.mft_no, (test_t)ntfs_test_inode,
&na);
if (!vi) {
......@@ -978,8 +1011,11 @@ static int ntfs_mft_writepage(struct page *page, struct writeback_control *wbc)
* The base inode is not in icache. Skip this extent
* mft record.
*/
ntfs_debug("Base inode 0x%lx is not in icache, "
"continuing search.", na.mft_no);
continue;
}
ntfs_debug("Base inode 0x%lx is in icache.", na.mft_no);
/*
* The base inode is in icache. Check if it has the extent
* inode corresponding to this extent mft record attached.
......
This diff is collapsed.
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