diff options
| author | Andrew Morton <akpm@zip.com.au> | 2002-04-29 23:53:20 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-04-29 23:53:20 -0700 |
| commit | 7d513234c45c6428985e77a5fd6d1382b8fa205b (patch) | |
| tree | c53addf52a1f3c8207006c2ea433c271a6a262a9 | |
| parent | df6867ef84a7d9ee4d44f451751a3f4128de10f9 (diff) | |
[PATCH] remove i_dirty_data_buffers
Removes inode.i_dirty_data_buffers. It's no longer used - all dirty
buffers have their pages marked dirty and filemap_fdatasync() /
filemap_fdatawait() catches it all.
Updates all callers.
This required a change in JFS - it has "metapages" which
are a container around a page which holds metadata. They
were holding these pages locked and were relying on fsync_inode_data_buffers
for writing them out. So fdatasync() deadlocked.
I've changed JFS to not lock those pages. Change was acked
by Dave Kleikamp <shaggy@austin.ibm.com> as the right
thing to do, but may not be complete. Probably igrab()
against ->host is needed to pin the address_space down.
| -rw-r--r-- | fs/buffer.c | 17 | ||||
| -rw-r--r-- | fs/ext2/fsync.c | 1 | ||||
| -rw-r--r-- | fs/ext3/fsync.c | 2 | ||||
| -rw-r--r-- | fs/inode.c | 1 | ||||
| -rw-r--r-- | fs/jfs/file.c | 2 | ||||
| -rw-r--r-- | fs/jfs/jfs_dmap.c | 3 | ||||
| -rw-r--r-- | fs/jfs/jfs_imap.c | 6 | ||||
| -rw-r--r-- | fs/jfs/jfs_logmgr.c | 9 | ||||
| -rw-r--r-- | fs/jfs/jfs_metapage.c | 14 | ||||
| -rw-r--r-- | fs/jfs/jfs_txnmgr.c | 6 | ||||
| -rw-r--r-- | fs/jfs/super.c | 6 | ||||
| -rw-r--r-- | fs/minix/file.c | 1 | ||||
| -rw-r--r-- | fs/reiserfs/file.c | 1 | ||||
| -rw-r--r-- | fs/sysv/file.c | 1 | ||||
| -rw-r--r-- | fs/udf/fsync.c | 1 | ||||
| -rw-r--r-- | include/linux/fs.h | 13 | ||||
| -rw-r--r-- | mm/filemap.c | 2 |
17 files changed, 32 insertions, 54 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 88bb9b9f297d..fc575fd54f01 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -428,8 +428,7 @@ int inode_has_buffers(struct inode *inode) int ret; spin_lock(&inode->i_bufferlist_lock); - ret = !list_empty(&inode->i_dirty_buffers) || - !list_empty(&inode->i_dirty_data_buffers); + ret = !list_empty(&inode->i_dirty_buffers); spin_unlock(&inode->i_bufferlist_lock); return ret; @@ -694,9 +693,6 @@ void invalidate_inode_buffers(struct inode *inode) while ((entry = inode->i_dirty_buffers.next) != &inode->i_dirty_buffers) __remove_inode_queue(BH_ENTRY(entry)); - while ((entry = inode->i_dirty_data_buffers.next) != - &inode->i_dirty_data_buffers) - __remove_inode_queue(BH_ENTRY(entry)); spin_unlock(&inode->i_bufferlist_lock); } @@ -954,10 +950,6 @@ __getblk(struct block_device *bdev, sector_t block, int size) * block_read_full_page() against that page will discover all the uptodate * buffers, will set the page uptodate and will perform no I/O. */ -static inline void __mark_dirty(struct buffer_head *bh) -{ - __set_page_dirty_nobuffers(bh->b_page); -} /** * mark_buffer_dirty - mark a buffer_head as needing writeout @@ -973,7 +965,7 @@ static inline void __mark_dirty(struct buffer_head *bh) void mark_buffer_dirty(struct buffer_head *bh) { if (!atomic_set_buffer_dirty(bh)) - __mark_dirty(bh); + __set_page_dirty_nobuffers(bh->b_page); } /* @@ -1498,10 +1490,7 @@ static int __block_commit_write(struct inode *inode, struct page *page, partial = 1; } else { mark_buffer_uptodate(bh, 1); - if (!atomic_set_buffer_dirty(bh)) { - __mark_dirty(bh); - buffer_insert_inode_data_queue(bh, inode); - } + mark_buffer_dirty(bh); } } diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c index 17caa2fee050..71ac1701a3a4 100644 --- a/fs/ext2/fsync.c +++ b/fs/ext2/fsync.c @@ -38,7 +38,6 @@ int ext2_sync_file(struct file * file, struct dentry *dentry, int datasync) int err; err = fsync_inode_buffers(inode); - err |= fsync_inode_data_buffers(inode); if (!(inode->i_state & I_DIRTY)) return err; if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c index e474547eb3e2..8266f2408664 100644 --- a/fs/ext3/fsync.c +++ b/fs/ext3/fsync.c @@ -62,8 +62,6 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) * we'll end up waiting on them in commit. */ ret = fsync_inode_buffers(inode); - ret |= fsync_inode_data_buffers(inode); - ext3_force_commit(inode->i_sb); return ret; diff --git a/fs/inode.c b/fs/inode.c index 3cc5dd6abbc3..61e3f6678737 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -140,7 +140,6 @@ void inode_init_once(struct inode *inode) INIT_LIST_HEAD(&inode->i_data.io_pages); INIT_LIST_HEAD(&inode->i_dentry); INIT_LIST_HEAD(&inode->i_dirty_buffers); - INIT_LIST_HEAD(&inode->i_dirty_data_buffers); INIT_LIST_HEAD(&inode->i_devices); sema_init(&inode->i_sem, 1); INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC); diff --git a/fs/jfs/file.c b/fs/jfs/file.c index 0c0fa3e29bcd..b926fb7ffacd 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c @@ -33,8 +33,6 @@ int jfs_fsync(struct file *file, struct dentry *dentry, int datasync) struct inode *inode = dentry->d_inode; int rc = 0; - rc = fsync_inode_data_buffers(inode); - if (!(inode->i_state & I_DIRTY)) return rc; if (datasync || !(inode->i_state & I_DIRTY_DATASYNC)) diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 49ef167944d8..644ec9efb321 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -325,7 +325,8 @@ int dbSync(struct inode *ipbmap) /* * write out dirty pages of bmap */ - fsync_inode_data_buffers(ipbmap); + filemap_fdatasync(ipbmap->i_mapping); + filemap_fdatawait(ipbmap->i_mapping); ipbmap->i_state |= I_DIRTY; diWriteSpecial(ipbmap); diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index bc5cfd0bfd27..88f8c02513ca 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -282,7 +282,8 @@ int diSync(struct inode *ipimap) /* * write out dirty pages of imap */ - fsync_inode_data_buffers(ipimap); + filemap_fdatasync(ipimap->i_mapping); + filemap_fdatawait(ipimap->i_mapping); diWriteSpecial(ipimap); @@ -607,7 +608,8 @@ void diFreeSpecial(struct inode *ip) jERROR(1, ("diFreeSpecial called with NULL ip!\n")); return; } - fsync_inode_data_buffers(ip); + filemap_fdatasync(ip->i_mapping); + filemap_fdatawait(ip->i_mapping); truncate_inode_pages(ip->i_mapping, 0); iput(ip); } diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index b774b32760bf..ee3abdc2ffde 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -966,9 +966,12 @@ int lmLogSync(log_t * log, int nosyncwait) * We need to make sure all of the "written" metapages * actually make it to disk */ - fsync_inode_data_buffers(sbi->ipbmap); - fsync_inode_data_buffers(sbi->ipimap); - fsync_inode_data_buffers(sbi->direct_inode); + filemap_fdatasync(sbi->ipbmap->i_mapping); + filemap_fdatasync(sbi->ipimap->i_mapping); + filemap_fdatasync(sbi->direct_inode->i_mapping); + filemap_fdatawait(sbi->ipbmap->i_mapping); + filemap_fdatawait(sbi->ipimap->i_mapping); + filemap_fdatawait(sbi->direct_inode->i_mapping); lrd.logtid = 0; lrd.backchain = 0; diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 2ed5a1e3f86a..131f9e4c14fd 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -349,7 +349,7 @@ metapage_t *__get_metapage(struct inode *inode, page_index = lblock >> l2BlocksPerPage; page_offset = (lblock - (page_index << l2BlocksPerPage)) << l2bsize; - if ((page_offset + size) > PAGE_SIZE) { + if ((page_offset + size) > PAGE_CACHE_SIZE) { spin_unlock(&meta_lock); jERROR(1, ("MetaData crosses page boundary!!\n")); return NULL; @@ -394,8 +394,10 @@ metapage_t *__get_metapage(struct inode *inode, __free_metapage(mp); spin_unlock(&meta_lock); return NULL; - } else + } else { INCREMENT(mpStat.pagealloc); + unlock_page(mp->page); + } } else { jFYI(1, ("__get_metapage: Calling read_cache_page\n")); @@ -412,7 +414,6 @@ metapage_t *__get_metapage(struct inode *inode, return NULL; } else INCREMENT(mpStat.pagealloc); - lock_page(mp->page); } mp->data = (void *) (kmap(mp->page) + page_offset); } @@ -459,6 +460,7 @@ static void __write_metapage(metapage_t * mp) page_offset = (mp->index - (page_index << l2BlocksPerPage)) << l2bsize; + lock_page(mp->page); rc = mp->mapping->a_ops->prepare_write(NULL, mp->page, page_offset, page_offset + mp->logical_size); @@ -466,6 +468,7 @@ static void __write_metapage(metapage_t * mp) jERROR(1, ("prepare_write return %d!\n", rc)); ClearPageUptodate(mp->page); kunmap(mp->page); + unlock_page(mp->page); clear_bit(META_dirty, &mp->flag); return; } @@ -476,6 +479,7 @@ static void __write_metapage(metapage_t * mp) jERROR(1, ("commit_write returned %d\n", rc)); } + unlock_page(mp->page); clear_bit(META_dirty, &mp->flag); jFYI(1, ("__write_metapage done\n")); @@ -525,7 +529,6 @@ void release_metapage(metapage_t * mp) mp->data = 0; if (test_bit(META_dirty, &mp->flag)) __write_metapage(mp); - unlock_page(mp->page); if (test_bit(META_sync, &mp->flag)) { sync_metapage(mp); clear_bit(META_sync, &mp->flag); @@ -585,7 +588,9 @@ void invalidate_metapages(struct inode *ip, unsigned long addr, /* * If in the metapage cache, we've got the page locked */ + lock_page(mp->page); block_flushpage(mp->page, 0); + unlock_page(mp->page); } else { spin_unlock(&meta_lock); page = find_lock_page(mapping, lblock>>l2BlocksPerPage); @@ -608,7 +613,6 @@ void invalidate_inode_metapages(struct inode *inode) clear_bit(META_dirty, &mp->flag); set_bit(META_discard, &mp->flag); kunmap(mp->page); - unlock_page(mp->page); page_cache_release(mp->page); INCREMENT(mpStat.pagefree); mp->data = 0; diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 8c475afc414a..fafc77ba1c7d 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -1163,8 +1163,10 @@ int txCommit(tid_t tid, /* transaction identifier */ * committing transactions and use i_sem instead. */ if ((!S_ISDIR(ip->i_mode)) - && (tblk->flag & COMMIT_DELETE) == 0) - fsync_inode_data_buffers(ip); + && (tblk->flag & COMMIT_DELETE) == 0) { + filemap_fdatasync(ip->i_mapping); + filemap_fdatawait(ip->i_mapping); + } /* * Mark inode as not dirty. It will still be on the dirty diff --git a/fs/jfs/super.c b/fs/jfs/super.c index a03e9aba5752..eeda6fc33d6c 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -151,7 +151,8 @@ static void jfs_put_super(struct super_block *sb) * We need to clean out the direct_inode pages since this inode * is not in the inode hash. */ - fsync_inode_data_buffers(sbi->direct_inode); + filemap_fdatasync(sbi->direct_inode->i_mapping); + filemap_fdatawait(sbi->direct_inode->i_mapping); truncate_inode_pages(sbi->direct_mapping, 0); iput(sbi->direct_inode); sbi->direct_inode = NULL; @@ -337,7 +338,8 @@ out_no_rw: jERROR(1, ("jfs_umount failed with return code %d\n", rc)); } out_mount_failed: - fsync_inode_data_buffers(sbi->direct_inode); + filemap_fdatasync(sbi->direct_inode->i_mapping); + filemap_fdatawait(sbi->direct_inode->i_mapping); truncate_inode_pages(sbi->direct_mapping, 0); make_bad_inode(sbi->direct_inode); iput(sbi->direct_inode); diff --git a/fs/minix/file.c b/fs/minix/file.c index 63352bb8cc3e..870b602d0c39 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c @@ -32,7 +32,6 @@ int minix_sync_file(struct file * file, struct dentry *dentry, int datasync) int err; err = fsync_inode_buffers(inode); - err |= fsync_inode_data_buffers(inode); if (!(inode->i_state & I_DIRTY)) return err; if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 75d41a57c538..f6aa41b82360 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -86,7 +86,6 @@ static int reiserfs_sync_file( BUG (); n_err = fsync_inode_buffers(p_s_inode) ; - n_err |= fsync_inode_data_buffers(p_s_inode); reiserfs_commit_for_inode(p_s_inode) ; unlock_kernel() ; return ( n_err < 0 ) ? -EIO : 0; diff --git a/fs/sysv/file.c b/fs/sysv/file.c index ee1ec8bf62e3..20ebed377040 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c @@ -38,7 +38,6 @@ int sysv_sync_file(struct file * file, struct dentry *dentry, int datasync) int err; err = fsync_inode_buffers(inode); - err |= fsync_inode_data_buffers(inode); if (!(inode->i_state & I_DIRTY)) return err; if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) diff --git a/fs/udf/fsync.c b/fs/udf/fsync.c index 00d4c207f4fe..c48ddf0d0408 100644 --- a/fs/udf/fsync.c +++ b/fs/udf/fsync.c @@ -45,7 +45,6 @@ int udf_fsync_inode(struct inode *inode, int datasync) int err; err = fsync_inode_buffers(inode); - err |= fsync_inode_data_buffers(inode); if (!(inode->i_state & I_DIRTY)) return err; if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) diff --git a/include/linux/fs.h b/include/linux/fs.h index 16c8dc3de35b..4027b4573cd7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -435,7 +435,6 @@ struct inode { struct list_head i_dentry; struct list_head i_dirty_buffers; /* uses i_bufferlist_lock */ - struct list_head i_dirty_data_buffers; spinlock_t i_bufferlist_lock; unsigned long i_ino; @@ -1266,13 +1265,6 @@ buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode) bh, &inode->i_dirty_buffers); } -static inline void -buffer_insert_inode_data_queue(struct buffer_head *bh, struct inode *inode) -{ - buffer_insert_list(&inode->i_bufferlist_lock, - bh, &inode->i_dirty_data_buffers); -} - #define atomic_set_buffer_dirty(bh) test_and_set_bit(BH_Dirty, &(bh)->b_state) static inline void mark_buffer_async(struct buffer_head * bh, int on) @@ -1341,11 +1333,6 @@ static inline int fsync_inode_buffers(struct inode *inode) return fsync_buffers_list(&inode->i_bufferlist_lock, &inode->i_dirty_buffers); } -static inline int fsync_inode_data_buffers(struct inode *inode) -{ - return fsync_buffers_list(&inode->i_bufferlist_lock, - &inode->i_dirty_data_buffers); -} extern int inode_has_buffers(struct inode *); extern int filemap_fdatasync(struct address_space *); extern int filemap_fdatawait(struct address_space *); diff --git a/mm/filemap.c b/mm/filemap.c index 9e2c70f075af..795993c00699 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1084,8 +1084,6 @@ static ssize_t generic_file_direct_IO(int rw, struct file * filp, char * buf, si */ retval = filemap_fdatasync(mapping); if (retval == 0) - retval = fsync_inode_data_buffers(inode); - if (retval == 0) retval = filemap_fdatawait(mapping); if (retval < 0) goto out_free; |
