Commit 7d513234 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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.
parent df6867ef
...@@ -428,8 +428,7 @@ int inode_has_buffers(struct inode *inode) ...@@ -428,8 +428,7 @@ int inode_has_buffers(struct inode *inode)
int ret; int ret;
spin_lock(&inode->i_bufferlist_lock); spin_lock(&inode->i_bufferlist_lock);
ret = !list_empty(&inode->i_dirty_buffers) || ret = !list_empty(&inode->i_dirty_buffers);
!list_empty(&inode->i_dirty_data_buffers);
spin_unlock(&inode->i_bufferlist_lock); spin_unlock(&inode->i_bufferlist_lock);
return ret; return ret;
...@@ -694,9 +693,6 @@ void invalidate_inode_buffers(struct inode *inode) ...@@ -694,9 +693,6 @@ void invalidate_inode_buffers(struct inode *inode)
while ((entry = inode->i_dirty_buffers.next) != while ((entry = inode->i_dirty_buffers.next) !=
&inode->i_dirty_buffers) &inode->i_dirty_buffers)
__remove_inode_queue(BH_ENTRY(entry)); __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); spin_unlock(&inode->i_bufferlist_lock);
} }
...@@ -954,10 +950,6 @@ __getblk(struct block_device *bdev, sector_t block, int size) ...@@ -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 * block_read_full_page() against that page will discover all the uptodate
* buffers, will set the page uptodate and will perform no I/O. * 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 * mark_buffer_dirty - mark a buffer_head as needing writeout
...@@ -973,7 +965,7 @@ static inline void __mark_dirty(struct buffer_head *bh) ...@@ -973,7 +965,7 @@ static inline void __mark_dirty(struct buffer_head *bh)
void mark_buffer_dirty(struct buffer_head *bh) void mark_buffer_dirty(struct buffer_head *bh)
{ {
if (!atomic_set_buffer_dirty(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, ...@@ -1498,10 +1490,7 @@ static int __block_commit_write(struct inode *inode, struct page *page,
partial = 1; partial = 1;
} else { } else {
mark_buffer_uptodate(bh, 1); mark_buffer_uptodate(bh, 1);
if (!atomic_set_buffer_dirty(bh)) { mark_buffer_dirty(bh);
__mark_dirty(bh);
buffer_insert_inode_data_queue(bh, inode);
}
} }
} }
......
...@@ -38,7 +38,6 @@ int ext2_sync_file(struct file * file, struct dentry *dentry, int datasync) ...@@ -38,7 +38,6 @@ int ext2_sync_file(struct file * file, struct dentry *dentry, int datasync)
int err; int err;
err = fsync_inode_buffers(inode); err = fsync_inode_buffers(inode);
err |= fsync_inode_data_buffers(inode);
if (!(inode->i_state & I_DIRTY)) if (!(inode->i_state & I_DIRTY))
return err; return err;
if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
......
...@@ -62,8 +62,6 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) ...@@ -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. * we'll end up waiting on them in commit.
*/ */
ret = fsync_inode_buffers(inode); ret = fsync_inode_buffers(inode);
ret |= fsync_inode_data_buffers(inode);
ext3_force_commit(inode->i_sb); ext3_force_commit(inode->i_sb);
return ret; return ret;
......
...@@ -140,7 +140,6 @@ void inode_init_once(struct inode *inode) ...@@ -140,7 +140,6 @@ void inode_init_once(struct inode *inode)
INIT_LIST_HEAD(&inode->i_data.io_pages); INIT_LIST_HEAD(&inode->i_data.io_pages);
INIT_LIST_HEAD(&inode->i_dentry); INIT_LIST_HEAD(&inode->i_dentry);
INIT_LIST_HEAD(&inode->i_dirty_buffers); INIT_LIST_HEAD(&inode->i_dirty_buffers);
INIT_LIST_HEAD(&inode->i_dirty_data_buffers);
INIT_LIST_HEAD(&inode->i_devices); INIT_LIST_HEAD(&inode->i_devices);
sema_init(&inode->i_sem, 1); sema_init(&inode->i_sem, 1);
INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC); INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
......
...@@ -33,8 +33,6 @@ int jfs_fsync(struct file *file, struct dentry *dentry, int datasync) ...@@ -33,8 +33,6 @@ int jfs_fsync(struct file *file, struct dentry *dentry, int datasync)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int rc = 0; int rc = 0;
rc = fsync_inode_data_buffers(inode);
if (!(inode->i_state & I_DIRTY)) if (!(inode->i_state & I_DIRTY))
return rc; return rc;
if (datasync || !(inode->i_state & I_DIRTY_DATASYNC)) if (datasync || !(inode->i_state & I_DIRTY_DATASYNC))
......
...@@ -325,7 +325,8 @@ int dbSync(struct inode *ipbmap) ...@@ -325,7 +325,8 @@ int dbSync(struct inode *ipbmap)
/* /*
* write out dirty pages of bmap * 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; ipbmap->i_state |= I_DIRTY;
diWriteSpecial(ipbmap); diWriteSpecial(ipbmap);
......
...@@ -282,7 +282,8 @@ int diSync(struct inode *ipimap) ...@@ -282,7 +282,8 @@ int diSync(struct inode *ipimap)
/* /*
* write out dirty pages of imap * write out dirty pages of imap
*/ */
fsync_inode_data_buffers(ipimap); filemap_fdatasync(ipimap->i_mapping);
filemap_fdatawait(ipimap->i_mapping);
diWriteSpecial(ipimap); diWriteSpecial(ipimap);
...@@ -607,7 +608,8 @@ void diFreeSpecial(struct inode *ip) ...@@ -607,7 +608,8 @@ void diFreeSpecial(struct inode *ip)
jERROR(1, ("diFreeSpecial called with NULL ip!\n")); jERROR(1, ("diFreeSpecial called with NULL ip!\n"));
return; return;
} }
fsync_inode_data_buffers(ip); filemap_fdatasync(ip->i_mapping);
filemap_fdatawait(ip->i_mapping);
truncate_inode_pages(ip->i_mapping, 0); truncate_inode_pages(ip->i_mapping, 0);
iput(ip); iput(ip);
} }
......
...@@ -966,9 +966,12 @@ int lmLogSync(log_t * log, int nosyncwait) ...@@ -966,9 +966,12 @@ int lmLogSync(log_t * log, int nosyncwait)
* We need to make sure all of the "written" metapages * We need to make sure all of the "written" metapages
* actually make it to disk * actually make it to disk
*/ */
fsync_inode_data_buffers(sbi->ipbmap); filemap_fdatasync(sbi->ipbmap->i_mapping);
fsync_inode_data_buffers(sbi->ipimap); filemap_fdatasync(sbi->ipimap->i_mapping);
fsync_inode_data_buffers(sbi->direct_inode); 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.logtid = 0;
lrd.backchain = 0; lrd.backchain = 0;
......
...@@ -349,7 +349,7 @@ metapage_t *__get_metapage(struct inode *inode, ...@@ -349,7 +349,7 @@ metapage_t *__get_metapage(struct inode *inode,
page_index = lblock >> l2BlocksPerPage; page_index = lblock >> l2BlocksPerPage;
page_offset = (lblock - (page_index << l2BlocksPerPage)) << page_offset = (lblock - (page_index << l2BlocksPerPage)) <<
l2bsize; l2bsize;
if ((page_offset + size) > PAGE_SIZE) { if ((page_offset + size) > PAGE_CACHE_SIZE) {
spin_unlock(&meta_lock); spin_unlock(&meta_lock);
jERROR(1, ("MetaData crosses page boundary!!\n")); jERROR(1, ("MetaData crosses page boundary!!\n"));
return NULL; return NULL;
...@@ -394,8 +394,10 @@ metapage_t *__get_metapage(struct inode *inode, ...@@ -394,8 +394,10 @@ metapage_t *__get_metapage(struct inode *inode,
__free_metapage(mp); __free_metapage(mp);
spin_unlock(&meta_lock); spin_unlock(&meta_lock);
return NULL; return NULL;
} else } else {
INCREMENT(mpStat.pagealloc); INCREMENT(mpStat.pagealloc);
unlock_page(mp->page);
}
} else { } else {
jFYI(1, jFYI(1,
("__get_metapage: Calling read_cache_page\n")); ("__get_metapage: Calling read_cache_page\n"));
...@@ -412,7 +414,6 @@ metapage_t *__get_metapage(struct inode *inode, ...@@ -412,7 +414,6 @@ metapage_t *__get_metapage(struct inode *inode,
return NULL; return NULL;
} else } else
INCREMENT(mpStat.pagealloc); INCREMENT(mpStat.pagealloc);
lock_page(mp->page);
} }
mp->data = (void *) (kmap(mp->page) + page_offset); mp->data = (void *) (kmap(mp->page) + page_offset);
} }
...@@ -459,6 +460,7 @@ static void __write_metapage(metapage_t * mp) ...@@ -459,6 +460,7 @@ static void __write_metapage(metapage_t * mp)
page_offset = page_offset =
(mp->index - (page_index << l2BlocksPerPage)) << l2bsize; (mp->index - (page_index << l2BlocksPerPage)) << l2bsize;
lock_page(mp->page);
rc = mp->mapping->a_ops->prepare_write(NULL, mp->page, page_offset, rc = mp->mapping->a_ops->prepare_write(NULL, mp->page, page_offset,
page_offset + page_offset +
mp->logical_size); mp->logical_size);
...@@ -466,6 +468,7 @@ static void __write_metapage(metapage_t * mp) ...@@ -466,6 +468,7 @@ static void __write_metapage(metapage_t * mp)
jERROR(1, ("prepare_write return %d!\n", rc)); jERROR(1, ("prepare_write return %d!\n", rc));
ClearPageUptodate(mp->page); ClearPageUptodate(mp->page);
kunmap(mp->page); kunmap(mp->page);
unlock_page(mp->page);
clear_bit(META_dirty, &mp->flag); clear_bit(META_dirty, &mp->flag);
return; return;
} }
...@@ -476,6 +479,7 @@ static void __write_metapage(metapage_t * mp) ...@@ -476,6 +479,7 @@ static void __write_metapage(metapage_t * mp)
jERROR(1, ("commit_write returned %d\n", rc)); jERROR(1, ("commit_write returned %d\n", rc));
} }
unlock_page(mp->page);
clear_bit(META_dirty, &mp->flag); clear_bit(META_dirty, &mp->flag);
jFYI(1, ("__write_metapage done\n")); jFYI(1, ("__write_metapage done\n"));
...@@ -525,7 +529,6 @@ void release_metapage(metapage_t * mp) ...@@ -525,7 +529,6 @@ void release_metapage(metapage_t * mp)
mp->data = 0; mp->data = 0;
if (test_bit(META_dirty, &mp->flag)) if (test_bit(META_dirty, &mp->flag))
__write_metapage(mp); __write_metapage(mp);
unlock_page(mp->page);
if (test_bit(META_sync, &mp->flag)) { if (test_bit(META_sync, &mp->flag)) {
sync_metapage(mp); sync_metapage(mp);
clear_bit(META_sync, &mp->flag); clear_bit(META_sync, &mp->flag);
...@@ -585,7 +588,9 @@ void invalidate_metapages(struct inode *ip, unsigned long addr, ...@@ -585,7 +588,9 @@ void invalidate_metapages(struct inode *ip, unsigned long addr,
/* /*
* If in the metapage cache, we've got the page locked * If in the metapage cache, we've got the page locked
*/ */
lock_page(mp->page);
block_flushpage(mp->page, 0); block_flushpage(mp->page, 0);
unlock_page(mp->page);
} else { } else {
spin_unlock(&meta_lock); spin_unlock(&meta_lock);
page = find_lock_page(mapping, lblock>>l2BlocksPerPage); page = find_lock_page(mapping, lblock>>l2BlocksPerPage);
...@@ -608,7 +613,6 @@ void invalidate_inode_metapages(struct inode *inode) ...@@ -608,7 +613,6 @@ void invalidate_inode_metapages(struct inode *inode)
clear_bit(META_dirty, &mp->flag); clear_bit(META_dirty, &mp->flag);
set_bit(META_discard, &mp->flag); set_bit(META_discard, &mp->flag);
kunmap(mp->page); kunmap(mp->page);
unlock_page(mp->page);
page_cache_release(mp->page); page_cache_release(mp->page);
INCREMENT(mpStat.pagefree); INCREMENT(mpStat.pagefree);
mp->data = 0; mp->data = 0;
......
...@@ -1163,8 +1163,10 @@ int txCommit(tid_t tid, /* transaction identifier */ ...@@ -1163,8 +1163,10 @@ int txCommit(tid_t tid, /* transaction identifier */
* committing transactions and use i_sem instead. * committing transactions and use i_sem instead.
*/ */
if ((!S_ISDIR(ip->i_mode)) if ((!S_ISDIR(ip->i_mode))
&& (tblk->flag & COMMIT_DELETE) == 0) && (tblk->flag & COMMIT_DELETE) == 0) {
fsync_inode_data_buffers(ip); filemap_fdatasync(ip->i_mapping);
filemap_fdatawait(ip->i_mapping);
}
/* /*
* Mark inode as not dirty. It will still be on the dirty * Mark inode as not dirty. It will still be on the dirty
......
...@@ -151,7 +151,8 @@ static void jfs_put_super(struct super_block *sb) ...@@ -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 * We need to clean out the direct_inode pages since this inode
* is not in the inode hash. * 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); truncate_inode_pages(sbi->direct_mapping, 0);
iput(sbi->direct_inode); iput(sbi->direct_inode);
sbi->direct_inode = NULL; sbi->direct_inode = NULL;
...@@ -337,7 +338,8 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -337,7 +338,8 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
jERROR(1, ("jfs_umount failed with return code %d\n", rc)); jERROR(1, ("jfs_umount failed with return code %d\n", rc));
} }
out_mount_failed: 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); truncate_inode_pages(sbi->direct_mapping, 0);
make_bad_inode(sbi->direct_inode); make_bad_inode(sbi->direct_inode);
iput(sbi->direct_inode); iput(sbi->direct_inode);
......
...@@ -32,7 +32,6 @@ int minix_sync_file(struct file * file, struct dentry *dentry, int datasync) ...@@ -32,7 +32,6 @@ int minix_sync_file(struct file * file, struct dentry *dentry, int datasync)
int err; int err;
err = fsync_inode_buffers(inode); err = fsync_inode_buffers(inode);
err |= fsync_inode_data_buffers(inode);
if (!(inode->i_state & I_DIRTY)) if (!(inode->i_state & I_DIRTY))
return err; return err;
if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
......
...@@ -86,7 +86,6 @@ static int reiserfs_sync_file( ...@@ -86,7 +86,6 @@ static int reiserfs_sync_file(
BUG (); BUG ();
n_err = fsync_inode_buffers(p_s_inode) ; n_err = fsync_inode_buffers(p_s_inode) ;
n_err |= fsync_inode_data_buffers(p_s_inode);
reiserfs_commit_for_inode(p_s_inode) ; reiserfs_commit_for_inode(p_s_inode) ;
unlock_kernel() ; unlock_kernel() ;
return ( n_err < 0 ) ? -EIO : 0; return ( n_err < 0 ) ? -EIO : 0;
......
...@@ -38,7 +38,6 @@ int sysv_sync_file(struct file * file, struct dentry *dentry, int datasync) ...@@ -38,7 +38,6 @@ int sysv_sync_file(struct file * file, struct dentry *dentry, int datasync)
int err; int err;
err = fsync_inode_buffers(inode); err = fsync_inode_buffers(inode);
err |= fsync_inode_data_buffers(inode);
if (!(inode->i_state & I_DIRTY)) if (!(inode->i_state & I_DIRTY))
return err; return err;
if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
......
...@@ -45,7 +45,6 @@ int udf_fsync_inode(struct inode *inode, int datasync) ...@@ -45,7 +45,6 @@ int udf_fsync_inode(struct inode *inode, int datasync)
int err; int err;
err = fsync_inode_buffers(inode); err = fsync_inode_buffers(inode);
err |= fsync_inode_data_buffers(inode);
if (!(inode->i_state & I_DIRTY)) if (!(inode->i_state & I_DIRTY))
return err; return err;
if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
......
...@@ -435,7 +435,6 @@ struct inode { ...@@ -435,7 +435,6 @@ struct inode {
struct list_head i_dentry; struct list_head i_dentry;
struct list_head i_dirty_buffers; /* uses i_bufferlist_lock */ struct list_head i_dirty_buffers; /* uses i_bufferlist_lock */
struct list_head i_dirty_data_buffers;
spinlock_t i_bufferlist_lock; spinlock_t i_bufferlist_lock;
unsigned long i_ino; unsigned long i_ino;
...@@ -1266,13 +1265,6 @@ buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode) ...@@ -1266,13 +1265,6 @@ buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode)
bh, &inode->i_dirty_buffers); 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) #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) 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) ...@@ -1341,11 +1333,6 @@ static inline int fsync_inode_buffers(struct inode *inode)
return fsync_buffers_list(&inode->i_bufferlist_lock, return fsync_buffers_list(&inode->i_bufferlist_lock,
&inode->i_dirty_buffers); &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 inode_has_buffers(struct inode *);
extern int filemap_fdatasync(struct address_space *); extern int filemap_fdatasync(struct address_space *);
extern int filemap_fdatawait(struct address_space *); extern int filemap_fdatawait(struct address_space *);
......
...@@ -1083,8 +1083,6 @@ static ssize_t generic_file_direct_IO(int rw, struct file * filp, char * buf, si ...@@ -1083,8 +1083,6 @@ static ssize_t generic_file_direct_IO(int rw, struct file * filp, char * buf, si
* completly asynchronous or performance will go to /dev/null. * completly asynchronous or performance will go to /dev/null.
*/ */
retval = filemap_fdatasync(mapping); retval = filemap_fdatasync(mapping);
if (retval == 0)
retval = fsync_inode_data_buffers(inode);
if (retval == 0) if (retval == 0)
retval = filemap_fdatawait(mapping); retval = filemap_fdatawait(mapping);
if (retval < 0) if (retval < 0)
......
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