diff options
| author | Anton Altaparmakov <aia21@cantab.net> | 2004-07-02 12:18:27 +0100 |
|---|---|---|
| committer | Anton Altaparmakov <aia21@cantab.net> | 2004-07-02 12:18:27 +0100 |
| commit | a97689d27e01ad9fa189fbf90fd1762baaf535a7 (patch) | |
| tree | 3a44e8039c1216c24febf74b397d850fe908124f | |
| parent | c4b0642b6f9b55957f9e5f8a8c494dcfd6293826 (diff) | |
NTFS: Add fs/ntfs/index.c::__ntfs_index_entry_mark_dirty() which sets all
buffers that are inside the ntfs record in the page dirty after which
it sets the page dirty. This allows ->writepage to only write the
dirty index records rather than having to write all the records in
the page. Modify fs/ntfs/index.h::ntfs_index_entry_mark_dirty() to
use this rather than __set_page_dirty_nobuffers().
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
| -rw-r--r-- | fs/ntfs/ChangeLog | 6 | ||||
| -rw-r--r-- | fs/ntfs/index.c | 60 | ||||
| -rw-r--r-- | fs/ntfs/index.h | 27 |
3 files changed, 76 insertions, 17 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 30aa30ac9bc6..863b078a4e4a 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -83,6 +83,12 @@ ToDo/Notes: It is simply set to __set_page_dirty_nobuffers() to make sure that running set_page_dirty() on a page containing mft/ntfs records will not affect the dirty state of the page buffers. + - Add fs/ntfs/index.c::__ntfs_index_entry_mark_dirty() which sets all + buffers that are inside the ntfs record in the page dirty after which + it sets the page dirty. This allows ->writepage to only write the + dirty index records rather than having to write all the records in + the page. Modify fs/ntfs/index.h::ntfs_index_entry_mark_dirty() to + use this rather than __set_page_dirty_nobuffers(). 2.1.14 - Fix an NFSd caused deadlock reported by several users. diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c index 06e81aff1a3d..41bfe847ac44 100644 --- a/fs/ntfs/index.c +++ b/fs/ntfs/index.c @@ -457,3 +457,63 @@ idx_err_out: err = -EIO; goto err_out; } + +#ifdef NTFS_RW + +/** + * __ntfs_index_entry_mark_dirty - mark an index allocation entry dirty + * @ictx: ntfs index context describing the index entry + * + * NOTE: You want to use fs/ntfs/index.h::ntfs_index_entry_mark_dirty() instead! + * + * Mark the index allocation entry described by the index entry context @ictx + * dirty. + * + * The index entry must be in an index block belonging to the index allocation + * attribute. Mark the buffers belonging to the index record as well as the + * page cache page the index block is in dirty. This automatically marks the + * VFS inode of the ntfs index inode to which the index entry belongs dirty, + * too (I_DIRTY_PAGES) and this in turn ensures the page buffers, and hence the + * dirty index block, will be written out to disk later. + */ +void __ntfs_index_entry_mark_dirty(ntfs_index_context *ictx) +{ + struct address_space *mapping; + struct page *page; + ntfs_inode *ni; + + BUG_ON(ictx->is_in_root); + ni = ictx->idx_ni; + page = ictx->page; + /* + * If the index block is the same size as the page cache page, set all + * the buffers in the page, as well as the page itself, dirty. + */ + if (ni->itype.index.block_size == PAGE_CACHE_SIZE) { + __set_page_dirty_buffers(page); + return; + } + /* Set only the buffers in which the index block is located dirty. */ + mapping = page->mapping; + if (page_has_buffers(page)) { + struct buffer_head *bh, *head; + unsigned int bh_start, bh_end, rec_start, rec_end; + unsigned int bh_size = ni->vol->sb->s_blocksize; + + bh = head = page_buffers(page); + bh_start = 0; + rec_start = (unsigned int)((u8*)ictx->ia - + (u8*)page_address(page)); + rec_end = rec_start + ni->itype.index.block_size; + do { + bh_end = bh_start + bh_size; + if ((bh_start >= rec_start) && (bh_end <= rec_end)) + set_buffer_dirty(bh); + bh_start = bh_end; + } while ((bh = bh->b_this_page) != head); + } + /* Finally, set the page itself dirty, too. */ + __set_page_dirty_nobuffers(page); +} + +#endif /* NTFS_RW */ diff --git a/fs/ntfs/index.h b/fs/ntfs/index.h index e43bedc4519f..8ed943655a1d 100644 --- a/fs/ntfs/index.h +++ b/fs/ntfs/index.h @@ -54,8 +54,8 @@ * @page are NULL in this case. * * If @is_in_root is FALSE, @entry is in the index allocation attribute and @ia - * and @page point to the index allocation block and the locked page it is in, - * respectively. @ir, @actx and @base_ni are NULL in this case. + * and @page point to the index allocation block and the mapped, locked page it + * is in, respectively. @ir, @actx and @base_ni are NULL in this case. * * To obtain a context call ntfs_index_ctx_get(). * @@ -115,6 +115,8 @@ static inline void ntfs_index_entry_flush_dcache_page(ntfs_index_context *ictx) flush_dcache_page(ictx->page); } +extern void __ntfs_index_entry_mark_dirty(ntfs_index_context *ictx); + /** * ntfs_index_entry_mark_dirty - mark an index entry dirty * @ictx: ntfs index context describing the index entry @@ -127,27 +129,18 @@ static inline void ntfs_index_entry_flush_dcache_page(ntfs_index_context *ictx) * later. * * If the index entry is in an index block belonging to the index allocation - * attribute, simply mark the page cache page the index block is in dirty. - * This automatically marks the VFS inode of the ntfs index inode to which the - * index entry belongs dirty, too (I_DIRTY_PAGES) and this in turn ensures the - * page, and hence the dirty index block, will be written out to disk later. - * - * Note, that if an index block is smaller than PAGE_CACHE_SIZE, i.e. if there - * are multiple index blocks in each page cache page, dirtying an index entry - * in one index block will cause all index blocks located in the same page - * cache page to be written out, too but this is a small price to pay - * considering how much more complicated the code would have to be to keep - * track of which index block inside a page is dirty and which is not. And - * anyway, on ia32 architectures index blocks are usually 4kiB in size which is - * the PAGE_CACHE_SIZE and hence this problem does not exist in the majority of - * cases. + * attribute, mark the buffers belonging to the index record as well as the + * page cache page the index block is in dirty. This automatically marks the + * VFS inode of the ntfs index inode to which the index entry belongs dirty, + * too (I_DIRTY_PAGES) and this in turn ensures the page buffers, and hence the + * dirty index block, will be written out to disk later. */ static inline void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx) { if (ictx->is_in_root) mark_mft_record_dirty(ictx->actx->ntfs_ino); else - __set_page_dirty_nobuffers(ictx->page); + __ntfs_index_entry_mark_dirty(ictx); } #endif /* NTFS_RW */ |
