Commit 565e162d authored by Anton Altaparmakov's avatar Anton Altaparmakov

NTFS: Modify fs/ntfs/mft.c::write_mft_record_nolock() so that it only

      writes the mft record if the buffers belonging to it are dirty.
      Otherwise we assume that it was written out by other means already.
Signed-off-by: default avatarAnton Altaparmakov <aia21@cantab.net>
parent 96471b7a
...@@ -73,6 +73,9 @@ ToDo/Notes: ...@@ -73,6 +73,9 @@ ToDo/Notes:
- Add fs/ntfs/mft.c::try_map_mft_record() which fails with -EALREADY if - Add fs/ntfs/mft.c::try_map_mft_record() which fails with -EALREADY if
the mft record is already locked and otherwise behaves the same way the mft record is already locked and otherwise behaves the same way
as fs/ntfs/mft.c::map_mft_record(). as fs/ntfs/mft.c::map_mft_record().
- Modify fs/ntfs/mft.c::write_mft_record_nolock() so that it only
writes the mft record if the buffers belonging to it are dirty.
Otherwise we assume that it was written out by other means already.
2.1.20 - Fix two stupid bugs introduced in 2.1.18 release. 2.1.20 - Fix two stupid bugs introduced in 2.1.18 release.
......
...@@ -678,6 +678,9 @@ static int sync_mft_mirror(ntfs_inode *ni, MFT_RECORD *m, int sync) ...@@ -678,6 +678,9 @@ static int sync_mft_mirror(ntfs_inode *ni, MFT_RECORD *m, int sync)
* ntfs inode @ni to backing store. If the mft record @m has a counterpart in * ntfs inode @ni to backing store. If the mft record @m has a counterpart in
* the mft mirror, that is also updated. * the mft mirror, that is also updated.
* *
* We only write the mft record if the ntfs inode @ni is dirty and the buffers
* belonging to its mft record are dirty, too.
*
* On success, clean the mft record and return 0. On error, leave the mft * On success, clean the mft record and return 0. On error, leave the mft
* record dirty and return -errno. The caller should call make_bad_inode() on * record dirty and return -errno. The caller should call make_bad_inode() on
* the base inode to ensure no more access happens to this inode. We do not do * the base inode to ensure no more access happens to this inode. We do not do
...@@ -707,6 +710,7 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync) ...@@ -707,6 +710,7 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync)
struct buffer_head *bh, *head; struct buffer_head *bh, *head;
unsigned int block_start, block_end, m_start, m_end; unsigned int block_start, block_end, m_start, m_end;
int i_bhs, nr_bhs, err = 0; int i_bhs, nr_bhs, err = 0;
BOOL rec_is_dirty = TRUE;
ntfs_debug("Entering for inode 0x%lx.", ni->mft_no); ntfs_debug("Entering for inode 0x%lx.", ni->mft_no);
BUG_ON(NInoAttr(ni)); BUG_ON(NInoAttr(ni));
...@@ -739,29 +743,34 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync) ...@@ -739,29 +743,34 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync)
do { do {
block_end = block_start + blocksize; block_end = block_start + blocksize;
/* If the buffer is outside the mft record, skip it. */ /* If the buffer is outside the mft record, skip it. */
if ((block_end <= m_start) || (block_start >= m_end)) if (block_end <= m_start)
continue; continue;
if (!buffer_mapped(bh)) { if (unlikely(block_start >= m_end))
ntfs_error(vol->sb, "Writing mft records without " break;
"existing mapped buffers is not " /*
"implemented yet. %s", * If the buffer is clean and it is the first buffer of the mft
ntfs_please_email); * record, it was written out by other means already so we are
err = -EOPNOTSUPP; * done. For safety we make sure all the other buffers are
continue; * clean also. If it is clean but not the first buffer and the
} * first buffer was dirty it is a bug.
if (!buffer_uptodate(bh)) { */
ntfs_error(vol->sb, "Writing mft records without " if (!buffer_dirty(bh)) {
"existing uptodate buffers is not " if (block_start == m_start)
"implemented yet. %s", rec_is_dirty = FALSE;
ntfs_please_email); else
err = -EOPNOTSUPP; BUG_ON(rec_is_dirty);
continue; continue;
} }
BUG_ON(!rec_is_dirty);
BUG_ON(!buffer_mapped(bh));
BUG_ON(!buffer_uptodate(bh));
BUG_ON(!nr_bhs && (m_start != block_start)); BUG_ON(!nr_bhs && (m_start != block_start));
BUG_ON(nr_bhs >= max_bhs); BUG_ON(nr_bhs >= max_bhs);
bhs[nr_bhs++] = bh; bhs[nr_bhs++] = bh;
BUG_ON((nr_bhs >= max_bhs) && (m_end != block_end)); BUG_ON((nr_bhs >= max_bhs) && (m_end != block_end));
} while (block_start = block_end, (bh = bh->b_this_page) != head); } while (block_start = block_end, (bh = bh->b_this_page) != head);
if (!rec_is_dirty)
goto done;
if (unlikely(err)) if (unlikely(err))
goto cleanup_out; goto cleanup_out;
/* Apply the mst protection fixups. */ /* Apply the mst protection fixups. */
...@@ -778,8 +787,7 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync) ...@@ -778,8 +787,7 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync)
if (unlikely(test_set_buffer_locked(tbh))) if (unlikely(test_set_buffer_locked(tbh)))
BUG(); BUG();
BUG_ON(!buffer_uptodate(tbh)); BUG_ON(!buffer_uptodate(tbh));
if (buffer_dirty(tbh)) clear_buffer_dirty(tbh);
clear_buffer_dirty(tbh);
get_bh(tbh); get_bh(tbh);
tbh->b_end_io = end_buffer_write_sync; tbh->b_end_io = end_buffer_write_sync;
submit_bh(WRITE, tbh); submit_bh(WRITE, tbh);
...@@ -795,8 +803,8 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync) ...@@ -795,8 +803,8 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync)
if (unlikely(!buffer_uptodate(tbh))) { if (unlikely(!buffer_uptodate(tbh))) {
err = -EIO; err = -EIO;
/* /*
* Set the buffer uptodate so the page & buffer states * Set the buffer uptodate so the page and buffer
* don't become out of sync. * states do not become out of sync.
*/ */
if (PageUptodate(page)) if (PageUptodate(page))
set_buffer_uptodate(tbh); set_buffer_uptodate(tbh);
......
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