}
EXPORT_SYMBOL(sync_mapping_buffers);
-/**
- * write_mapping_buffers - Start writeout of a mapping's "associated" buffers.
- * @mapping - the mapping which wants those buffers written.
- *
- * Starts I/O against dirty buffers which are on @mapping->private_list.
- * Those buffers must be backed by @mapping->assoc_mapping.
- *
- * The private_list buffers generally contain filesystem indirect blocks.
- * The idea is that the filesystem can start I/O against the indirects at
- * the same time as running generic_writepages(), so the indirect's
- * I/O will be merged with the data.
- *
- * We sneakliy write the buffers in probable tail-to-head order. This is
- * because generic_writepages() writes in probable head-to-tail
- * order. If the file is so huge that the data or the indirects overflow
- * the request queue we will at least get some merging this way.
- *
- * Any clean+unlocked buffers are de-listed. clean/locked buffers must be
- * left on the list for an fsync() to wait on.
- *
- * Couldn't think of a smart way of avoiding livelock, so chose the dumb
- * way instead.
- *
- * FIXME: duplicates fsync_inode_buffers() functionality a bit.
- */
-int write_mapping_buffers(struct address_space *mapping)
-{
- spinlock_t *lock;
- struct address_space *buffer_mapping;
- unsigned nr_to_write; /* livelock avoidance */
- struct list_head *lh;
- int ret = 0;
-
- if (list_empty(&mapping->private_list))
- goto out;
-
- buffer_mapping = mapping->assoc_mapping;
- lock = &buffer_mapping->private_lock;
- spin_lock(lock);
- nr_to_write = 0;
- lh = mapping->private_list.next;
- while (lh != &mapping->private_list) {
- lh = lh->next;
- nr_to_write++;
- }
- nr_to_write *= 2; /* Allow for some late additions */
-
- while (nr_to_write-- && !list_empty(&mapping->private_list)) {
- struct buffer_head *bh;
-
- bh = BH_ENTRY(mapping->private_list.prev);
- list_del_init(&bh->b_assoc_buffers);
- if (!buffer_dirty(bh) && !buffer_locked(bh))
- continue;
- /* Stick it on the far end of the list. Order is preserved. */
- list_add(&bh->b_assoc_buffers, &mapping->private_list);
- if (test_set_buffer_locked(bh))
- continue;
- get_bh(bh);
- spin_unlock(lock);
- if (test_clear_buffer_dirty(bh)) {
- bh->b_end_io = end_buffer_io_sync;
- submit_bh(WRITE, bh);
- } else {
- unlock_buffer(bh);
- put_bh(bh);
- }
- spin_lock(lock);
- }
- spin_unlock(lock);
-out:
- return ret;
-}
-EXPORT_SYMBOL(write_mapping_buffers);
-
void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
{
struct address_space *mapping = inode->i_mapping;
void buffer_insert_list(spinlock_t *lock,
struct buffer_head *, struct list_head *);
void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode);
-int write_mapping_buffers(struct address_space *mapping);
int inode_has_buffers(struct inode *);
void invalidate_inode_buffers(struct inode *);
int fsync_buffers_list(spinlock_t *lock, struct list_head *);