aboutsummaryrefslogtreecommitdiff
path: root/fs/buffer.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/buffer.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'fs/buffer.c')
-rw-r--r--fs/buffer.c3152
1 files changed, 3152 insertions, 0 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
new file mode 100644
index 00000000000..f961605a904
--- /dev/null
+++ b/fs/buffer.c
@@ -0,0 +1,3152 @@
+/*
+ * linux/fs/buffer.c
+ *
+ * Copyright (C) 1991, 1992, 2002 Linus Torvalds
+ */
+
+/*
+ * Start bdflush() with kernel_thread not syscall - Paul Gortmaker, 12/95
+ *
+ * Removed a lot of unnecessary code and simplified things now that
+ * the buffer cache isn't our primary cache - Andrew Tridgell 12/96
+ *
+ * Speed up hash, lru, and free list operations. Use gfp() for allocating
+ * hash table, use SLAB cache for buffer heads. SMP threading. -DaveM
+ *
+ * Added 32k buffer block sizes - these are required older ARM systems. - RMK
+ *
+ * async buffer flushing, 1999 Andrea Arcangeli <andrea@suse.de>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/syscalls.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/blkdev.h>
+#include <linux/file.h>
+#include <linux/quotaops.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+#include <linux/writeback.h>
+#include <linux/hash.h>
+#include <linux/suspend.h>
+#include <linux/buffer_head.h>
+#include <linux/bio.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/bitops.h>
+#include <linux/mpage.h>
+
+static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
+static void invalidate_bh_lrus(void);
+
+#define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
+
+inline void
+init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private)
+{
+ bh->b_end_io = handler;
+ bh->b_private = private;
+}
+
+static int sync_buffer(void *word)
+{
+ struct block_device *bd;
+ struct buffer_head *bh
+ = container_of(word, struct buffer_head, b_state);
+
+ smp_mb();
+ bd = bh->b_bdev;
+ if (bd)
+ blk_run_address_space(bd->bd_inode->i_mapping);
+ io_schedule();
+ return 0;
+}
+
+void fastcall __lock_buffer(struct buffer_head *bh)
+{
+ wait_on_bit_lock(&bh->b_state, BH_Lock, sync_buffer,
+ TASK_UNINTERRUPTIBLE);
+}
+EXPORT_SYMBOL(__lock_buffer);
+
+void fastcall unlock_buffer(struct buffer_head *bh)
+{
+ clear_buffer_locked(bh);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&bh->b_state, BH_Lock);
+}
+
+/*
+ * Block until a buffer comes unlocked. This doesn't stop it
+ * from becoming locked again - you have to lock it yourself
+ * if you want to preserve its state.
+ */
+void __wait_on_buffer(struct buffer_head * bh)
+{
+ wait_on_bit(&bh->b_state, BH_Lock, sync_buffer, TASK_UNINTERRUPTIBLE);
+}
+
+static void
+__clear_page_buffers(struct page *page)
+{
+ ClearPagePrivate(page);
+ page->private = 0;
+ page_cache_release(page);
+}
+
+static void buffer_io_error(struct buffer_head *bh)
+{
+ char b[BDEVNAME_SIZE];
+
+ printk(KERN_ERR "Buffer I/O error on device %s, logical block %Lu\n",
+ bdevname(bh->b_bdev, b),
+ (unsigned long long)bh->b_blocknr);
+}
+
+/*
+ * Default synchronous end-of-IO handler.. Just mark it up-to-date and
+ * unlock the buffer. This is what ll_rw_block uses too.
+ */
+void end_buffer_read_sync(struct buffer_head *bh, int uptodate)
+{
+ if (uptodate) {
+ set_buffer_uptodate(bh);
+ } else {
+ /* This happens, due to failed READA attempts. */
+ clear_buffer_uptodate(bh);
+ }
+ unlock_buffer(bh);
+ put_bh(bh);
+}
+
+void end_buffer_write_sync(struct buffer_head *bh, int uptodate)
+{
+ char b[BDEVNAME_SIZE];
+
+ if (uptodate) {
+ set_buffer_uptodate(bh);
+ } else {
+ if (!buffer_eopnotsupp(bh) && printk_ratelimit()) {
+ buffer_io_error(bh);
+ printk(KERN_WARNING "lost page write due to "
+ "I/O error on %s\n",
+ bdevname(bh->b_bdev, b));
+ }
+ set_buffer_write_io_error(bh);
+ clear_buffer_uptodate(bh);
+ }
+ unlock_buffer(bh);
+ put_bh(bh);
+}
+
+/*
+ * Write out and wait upon all the dirty data associated with a block
+ * device via its mapping. Does not take the superblock lock.
+ */
+int sync_blockdev(struct block_device *bdev)
+{
+ int ret = 0;
+
+ if (bdev) {
+ int err;
+
+ ret = filemap_fdatawrite(bdev->bd_inode->i_mapping);
+ err = filemap_fdatawait(bdev->bd_inode->i_mapping);
+ if (!ret)
+ ret = err;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(sync_blockdev);
+
+/*
+ * Write out and wait upon all dirty data associated with this
+ * superblock. Filesystem data as well as the underlying block
+ * device. Takes the superblock lock.
+ */
+int fsync_super(struct super_block *sb)
+{
+ sync_inodes_sb(sb, 0);
+ DQUOT_SYNC(sb);
+ lock_super(sb);
+ if (sb->s_dirt && sb->s_op->write_super)
+ sb->s_op->write_super(sb);
+ unlock_super(sb);
+ if (sb->s_op->sync_fs)
+ sb->s_op->sync_fs(sb, 1);
+ sync_blockdev(sb->s_bdev);
+ sync_inodes_sb(sb, 1);
+
+ return sync_blockdev(sb->s_bdev);
+}
+
+/*
+ * Write out and wait upon all dirty data associated with this
+ * device. Filesystem data as well as the underlying block
+ * device. Takes the superblock lock.
+ */
+int fsync_bdev(struct block_device *bdev)
+{
+ struct super_block *sb = get_super(bdev);
+ if (sb) {
+ int res = fsync_super(sb);
+ drop_super(sb);
+ return res;
+ }
+ return sync_blockdev(bdev);
+}
+
+/**
+ * freeze_bdev -- lock a filesystem and force it into a consistent state
+ * @bdev: blockdevice to lock
+ *
+ * This takes the block device bd_mount_sem to make sure no new mounts
+ * happen on bdev until thaw_bdev() is called.
+ * If a superblock is found on this device, we take the s_umount semaphore
+ * on it to make sure nobody unmounts until the snapshot creation is done.
+ */
+struct super_block *freeze_bdev(struct block_device *bdev)
+{
+ struct super_block *sb;
+
+ down(&bdev->bd_mount_sem);
+ sb = get_super(bdev);
+ if (sb && !(sb->s_flags & MS_RDONLY)) {
+ sb->s_frozen = SB_FREEZE_WRITE;
+ wmb();
+
+ sync_inodes_sb(sb, 0);
+ DQUOT_SYNC(sb);
+
+ lock_super(sb);
+ if (sb->s_dirt && sb->s_op->write_super)
+ sb->s_op->write_super(sb);
+ unlock_super(sb);
+
+ if (sb->s_op->sync_fs)
+ sb->s_op->sync_fs(sb, 1);
+
+ sync_blockdev(sb->s_bdev);
+ sync_inodes_sb(sb, 1);
+
+ sb->s_frozen = SB_FREEZE_TRANS;
+ wmb();
+
+ sync_blockdev(sb->s_bdev);
+
+ if (sb->s_op->write_super_lockfs)
+ sb->s_op->write_super_lockfs(sb);
+ }
+
+ sync_blockdev(bdev);
+ return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */
+}
+EXPORT_SYMBOL(freeze_bdev);
+
+/**
+ * thaw_bdev -- unlock filesystem
+ * @bdev: blockdevice to unlock
+ * @sb: associated superblock
+ *
+ * Unlocks the filesystem and marks it writeable again after freeze_bdev().
+ */
+void thaw_bdev(struct block_device *bdev, struct super_block *sb)
+{
+ if (sb) {
+ BUG_ON(sb->s_bdev != bdev);
+
+ if (sb->s_op->unlockfs)
+ sb->s_op->unlockfs(sb);
+ sb->s_frozen = SB_UNFROZEN;
+ wmb();
+ wake_up(&sb->s_wait_unfrozen);
+ drop_super(sb);
+ }
+
+ up(&bdev->bd_mount_sem);
+}
+EXPORT_SYMBOL(thaw_bdev);
+
+/*
+ * sync everything. Start out by waking pdflush, because that writes back
+ * all queues in parallel.
+ */
+static void do_sync(unsigned long wait)
+{
+ wakeup_bdflush(0);
+ sync_inodes(0); /* All mappings, inodes and their blockdevs */
+ DQUOT_SYNC(NULL);
+ sync_supers(); /* Write the superblocks */
+ sync_filesystems(0); /* Start syncing the filesystems */
+ sync_filesystems(wait); /* Waitingly sync the filesystems */
+ sync_inodes(wait); /* Mappings, inodes and blockdevs, again. */
+ if (!wait)
+ printk("Emergency Sync complete\n");
+ if (unlikely(laptop_mode))
+ laptop_sync_completion();
+}
+
+asmlinkage long sys_sync(void)
+{
+ do_sync(1);
+ return 0;
+}
+
+void emergency_sync(void)
+{
+ pdflush_operation(do_sync, 0);
+}
+
+/*
+ * Generic function to fsync a file.
+ *
+ * filp may be NULL if called via the msync of a vma.
+ */
+
+int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
+{
+ struct inode * inode = dentry->d_inode;
+ struct super_block * sb;
+ int ret, err;
+
+ /* sync the inode to buffers */
+ ret = write_inode_now(inode, 0);
+
+ /* sync the superblock to buffers */
+ sb = inode->i_sb;
+ lock_super(sb);
+ if (sb->s_op->write_super)
+ sb->s_op->write_super(sb);
+ unlock_super(sb);
+
+ /* .. finally sync the buffers to disk */
+ err = sync_blockdev(sb->s_bdev);
+ if (!ret)
+ ret = err;
+ return ret;
+}
+
+asmlinkage long sys_fsync(unsigned int fd)
+{
+ struct file * file;
+ struct address_space *mapping;
+ int ret, err;
+
+ ret = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ mapping = file->f_mapping;
+
+ ret = -EINVAL;
+ if (!file->f_op || !file->f_op->fsync) {
+ /* Why? We can still call filemap_fdatawrite */
+ goto out_putf;
+ }
+
+ current->flags |= PF_SYNCWRITE;
+ ret = filemap_fdatawrite(mapping);
+
+ /*
+ * We need to protect against concurrent writers,
+ * which could cause livelocks in fsync_buffers_list
+ */
+ down(&mapping->host->i_sem);
+ err = file->f_op->fsync(file, file->f_dentry, 0);
+ if (!ret)
+ ret = err;
+ up(&mapping->host->i_sem);
+ err = filemap_fdatawait(mapping);
+ if (!ret)
+ ret = err;
+ current->flags &= ~PF_SYNCWRITE;
+
+out_putf:
+ fput(file);
+out:
+ return ret;
+}
+
+asmlinkage long sys_fdatasync(unsigned int fd)
+{
+ struct file * file;
+ struct address_space *mapping;
+ int ret, err;
+
+ ret = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ ret = -EINVAL;
+ if (!file->f_op || !file->f_op->fsync)
+ goto out_putf;
+
+ mapping = file->f_mapping;
+
+ current->flags |= PF_SYNCWRITE;
+ ret = filemap_fdatawrite(mapping);
+ down(&mapping->host->i_sem);
+ err = file->f_op->fsync(file, file->f_dentry, 1);
+ if (!ret)
+ ret = err;
+ up(&mapping->host->i_sem);
+ err = filemap_fdatawait(mapping);
+ if (!ret)
+ ret = err;
+ current->flags &= ~PF_SYNCWRITE;
+
+out_putf:
+ fput(file);
+out:
+ return ret;
+}
+
+/*
+ * Various filesystems appear to want __find_get_block to be non-blocking.
+ * But it's the page lock which protects the buffers. To get around this,
+ * we get exclusion from try_to_free_buffers with the blockdev mapping's
+ * private_lock.
+ *
+ * Hack idea: for the blockdev mapping, i_bufferlist_lock contention
+ * may be quite high. This code could TryLock the page, and if that
+ * succeeds, there is no need to take private_lock. (But if
+ * private_lock is contended then so is mapping->tree_lock).
+ */
+static struct buffer_head *
+__find_get_block_slow(struct block_device *bdev, sector_t block, int unused)
+{
+ struct inode *bd_inode = bdev->bd_inode;
+ struct address_space *bd_mapping = bd_inode->i_mapping;
+ struct buffer_head *ret = NULL;
+ pgoff_t index;
+ struct buffer_head *bh;
+ struct buffer_head *head;
+ struct page *page;
+ int all_mapped = 1;
+
+ index = block >> (PAGE_CACHE_SHIFT - bd_inode->i_blkbits);
+ page = find_get_page(bd_mapping, index);
+ if (!page)
+ goto out;
+
+ spin_lock(&bd_mapping->private_lock);
+ if (!page_has_buffers(page))
+ goto out_unlock;
+ head = page_buffers(page);
+ bh = head;
+ do {
+ if (bh->b_blocknr == block) {
+ ret = bh;
+ get_bh(bh);
+ goto out_unlock;
+ }
+ if (!buffer_mapped(bh))
+ all_mapped = 0;
+ bh = bh->b_this_page;
+ } while (bh != head);
+
+ /* we might be here because some of the buffers on this page are
+ * not mapped. This is due to various races between
+ * file io on the block device and getblk. It gets dealt with
+ * elsewhere, don't buffer_error if we had some unmapped buffers
+ */
+ if (all_mapped) {
+ printk("__find_get_block_slow() failed. "
+ "block=%llu, b_blocknr=%llu\n",
+ (unsigned long long)block, (unsigned long long)bh->b_blocknr);
+ printk("b_state=0x%08lx, b_size=%u\n", bh->b_state, bh->b_size);
+ printk("device blocksize: %d\n", 1 << bd_inode->i_blkbits);
+ }
+out_unlock:
+ spin_unlock(&bd_mapping->private_lock);
+ page_cache_release(page);
+out:
+ return ret;
+}
+
+/* If invalidate_buffers() will trash dirty buffers, it means some kind
+ of fs corruption is going on. Trashing dirty data always imply losing
+ information that was supposed to be just stored on the physical layer
+ by the user.
+
+ Thus invalidate_buffers in general usage is not allwowed to trash
+ dirty buffers. For example ioctl(FLSBLKBUF) expects dirty data to
+ be preserved. These buffers are simply skipped.
+
+ We also skip buffers which are still in use. For example this can
+ happen if a userspace program is reading the block device.
+
+ NOTE: In the case where the user removed a removable-media-disk even if
+ there's still dirty data not synced on disk (due a bug in the device driver
+ or due an error of the user), by not destroying the dirty buffers we could
+ generate corruption also on the next media inserted, thus a parameter is
+ necessary to handle this case in the most safe way possible (trying
+ to not corrupt also the new disk inserted with the data belonging to
+ the old now corrupted disk). Also for the ramdisk the natural thing
+ to do in order to release the ramdisk memory is to destroy dirty buffers.
+
+ These are two special cases. Normal usage imply the device driver
+ to issue a sync on the device (without waiting I/O completion) and
+ then an invalidate_buffers call that doesn't trash dirty buffers.
+
+ For handling cache coherency with the blkdev pagecache the 'update' case
+ is been introduced. It is needed to re-read from disk any pinned
+ buffer. NOTE: re-reading from disk is destructive so we can do it only
+ when we assume nobody is changing the buffercache under our I/O and when
+ we think the disk contains more recent information than the buffercache.
+ The update == 1 pass marks the buffers we need to update, the update == 2
+ pass does the actual I/O. */
+void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers)
+{
+ invalidate_bh_lrus();
+ /*
+ * FIXME: what about destroy_dirty_buffers?
+ * We really want to use invalidate_inode_pages2() for
+ * that, but not until that's cleaned up.
+ */
+ invalidate_inode_pages(bdev->bd_inode->i_mapping);
+}
+
+/*
+ * Kick pdflush then try to free up some ZONE_NORMAL memory.
+ */
+static void free_more_memory(void)
+{
+ struct zone **zones;
+ pg_data_t *pgdat;
+
+ wakeup_bdflush(1024);
+ yield();
+
+ for_each_pgdat(pgdat) {
+ zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones;
+ if (*zones)
+ try_to_free_pages(zones, GFP_NOFS, 0);
+ }
+}
+
+/*
+ * I/O completion handler for block_read_full_page() - pages
+ * which come unlocked at the end of I/O.
+ */
+static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
+{
+ static DEFINE_SPINLOCK(page_uptodate_lock);
+ unsigned long flags;
+ struct buffer_head *tmp;
+ struct page *page;
+ int page_uptodate = 1;
+
+ BUG_ON(!buffer_async_read(bh));
+
+ page = bh->b_page;
+ if (uptodate) {
+ set_buffer_uptodate(bh);
+ } else {
+ clear_buffer_uptodate(bh);
+ if (printk_ratelimit())
+ buffer_io_error(bh);
+ SetPageError(page);
+ }
+
+ /*
+ * Be _very_ careful from here on. Bad things can happen if
+ * two buffer heads end IO at almost the same time and both
+ * decide that the page is now completely done.
+ */
+ spin_lock_irqsave(&page_uptodate_lock, flags);
+ clear_buffer_async_read(bh);
+ unlock_buffer(bh);
+ tmp = bh;
+ do {
+ if (!buffer_uptodate(tmp))
+ page_uptodate = 0;
+ if (buffer_async_read(tmp)) {
+ BUG_ON(!buffer_locked(tmp));
+ goto still_busy;
+ }
+ tmp = tmp->b_this_page;
+ } while (tmp != bh);
+ spin_unlock_irqrestore(&page_uptodate_lock, flags);
+
+ /*
+ * If none of the buffers had errors and they are all
+ * uptodate then we can set the page uptodate.
+ */
+ if (page_uptodate && !PageError(page))
+ SetPageUptodate(page);
+ unlock_page(page);
+ return;
+
+still_busy:
+ spin_unlock_irqrestore(&page_uptodate_lock, flags);
+ return;
+}
+
+/*
+ * Completion handler for block_write_full_page() - pages which are unlocked
+ * during I/O, and which have PageWriteback cleared upon I/O completion.
+ */
+void end_buffer_async_write(struct buffer_head *bh, int uptodate)
+{
+ char b[BDEVNAME_SIZE];
+ static DEFINE_SPINLOCK(page_uptodate_lock);
+ unsigned long flags;
+ struct buffer_head *tmp;
+ struct page *page;
+
+ BUG_ON(!buffer_async_write(bh));
+
+ page = bh->b_page;
+ if (uptodate) {
+ set_buffer_uptodate(bh);
+ } else {
+ if (printk_ratelimit()) {
+ buffer_io_error(bh);
+ printk(KERN_WARNING "lost page write due to "
+ "I/O error on %s\n",
+ bdevname(bh->b_bdev, b));
+ }
+ set_bit(AS_EIO, &page->mapping->flags);
+ clear_buffer_uptodate(bh);
+ SetPageError(page);
+ }
+
+ spin_lock_irqsave(&page_uptodate_lock, flags);
+ clear_buffer_async_write(bh);
+ unlock_buffer(bh);
+ tmp = bh->b_this_page;
+ while (tmp != bh) {
+ if (buffer_async_write(tmp)) {
+ BUG_ON(!buffer_locked(tmp));
+ goto still_busy;
+ }
+ tmp = tmp->b_this_page;
+ }
+ spin_unlock_irqrestore(&page_uptodate_lock, flags);
+ end_page_writeback(page);
+ return;
+
+still_busy:
+ spin_unlock_irqrestore(&page_uptodate_lock, flags);
+ return;
+}
+
+/*
+ * If a page's buffers are under async readin (end_buffer_async_read
+ * completion) then there is a possibility that another thread of
+ * control could lock one of the buffers after it has completed
+ * but while some of the other buffers have not completed. This
+ * locked buffer would confuse end_buffer_async_read() into not unlocking
+ * the page. So the absence of BH_Async_Read tells end_buffer_async_read()
+ * that this buffer is not under async I/O.
+ *
+ * The page comes unlocked when it has no locked buffer_async buffers
+ * left.
+ *
+ * PageLocked prevents anyone starting new async I/O reads any of
+ * the buffers.
+ *
+ * PageWriteback is used to prevent simultaneous writeout of the same
+ * page.
+ *
+ * PageLocked prevents anyone from starting writeback of a page which is
+ * under read I/O (PageWriteback is only ever set against a locked page).
+ */
+static void mark_buffer_async_read(struct buffer_head *bh)
+{
+ bh->b_end_io = end_buffer_async_read;
+ set_buffer_async_read(bh);
+}
+
+void mark_buffer_async_write(struct buffer_head *bh)
+{
+ bh->b_end_io = end_buffer_async_write;
+ set_buffer_async_write(bh);
+}
+EXPORT_SYMBOL(mark_buffer_async_write);
+
+
+/*
+ * fs/buffer.c contains helper functions for buffer-backed address space's
+ * fsync functions. A common requirement for buffer-based filesystems is
+ * that certain data from the backing blockdev needs to be written out for
+ * a successful fsync(). For example, ext2 indirect blocks need to be
+ * written back and waited upon before fsync() returns.
+ *
+ * The functions mark_buffer_inode_dirty(), fsync_inode_buffers(),
+ * inode_has_buffers() and invalidate_inode_buffers() are provided for the
+ * management of a list of dependent buffers at ->i_mapping->private_list.
+ *
+ * Locking is a little subtle: try_to_free_buffers() will remove buffers
+ * from their controlling inode's queue when they are being freed. But
+ * try_to_free_buffers() will be operating against the *blockdev* mapping
+ * at the time, not against the S_ISREG file which depends on those buffers.
+ * So the locking for private_list is via the private_lock in the address_space
+ * which backs the buffers. Which is different from the address_space
+ * against which the buffers are listed. So for a particular address_space,
+ * mapping->private_lock does *not* protect mapping->private_list! In fact,
+ * mapping->private_list will always be protected by the backing blockdev's
+ * ->private_lock.
+ *
+ * Which introduces a requirement: all buffers on an address_space's
+ * ->private_list must be from the same address_space: the blockdev's.
+ *
+ * address_spaces which do not place buffers at ->private_list via these
+ * utility functions are free to use private_lock and private_list for
+ * whatever they want. The only requirement is that list_empty(private_list)
+ * be true at clear_inode() time.
+ *
+ * FIXME: clear_inode should not call invalidate_inode_buffers(). The
+ * filesystems should do that. invalidate_inode_buffers() should just go
+ * BUG_ON(!list_empty).
+ *
+ * FIXME: mark_buffer_dirty_inode() is a data-plane operation. It should
+ * take an address_space, not an inode. And it should be called
+ * mark_buffer_dirty_fsync() to clearly define why those buffers are being
+ * queued up.
+ *
+ * FIXME: mark_buffer_dirty_inode() doesn't need to add the buffer to the
+ * list if it is already on a list. Because if the buffer is on a list,
+ * it *must* already be on the right one. If not, the filesystem is being
+ * silly. This will save a ton of locking. But first we have to ensure
+ * that buffers are taken *off* the old inode's list when they are freed
+ * (presumably in truncate). That requires careful auditing of all
+ * filesystems (do it inside bforget()). It could also be done by bringing
+ * b_inode back.
+ */
+
+/*
+ * The buffer's backing address_space's private_lock must be held
+ */
+static inline void __remove_assoc_queue(struct buffer_head *bh)
+{
+ list_del_init(&bh->b_assoc_buffers);
+}
+
+int inode_has_buffers(struct inode *inode)
+{
+ return !list_empty(&inode->i_data.private_list);
+}
+
+/*
+ * osync is designed to support O_SYNC io. It waits synchronously for
+ * all already-submitted IO to complete, but does not queue any new
+ * writes to the disk.
+ *
+ * To do O_SYNC writes, just queue the buffer writes with ll_rw_block as
+ * you dirty the buffers, and then use osync_inode_buffers to wait for
+ * completion. Any other dirty buffers which are not yet queued for
+ * write will not be flushed to disk by the osync.
+ */
+static int osync_buffers_list(spinlock_t *lock, struct list_head *list)
+{
+ struct buffer_head *bh;
+ struct list_head *p;
+ int err = 0;
+
+ spin_lock(lock);
+repeat:
+ list_for_each_prev(p, list) {
+ bh = BH_ENTRY(p);
+ if (buffer_locked(bh)) {
+ get_bh(bh);
+ spin_unlock(lock);
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh))
+ err = -EIO;
+ brelse(bh);
+ spin_lock(lock);
+ goto repeat;
+ }
+ }
+ spin_unlock(lock);
+ return err;
+}
+
+/**
+ * sync_mapping_buffers - write out and wait upon a mapping's "associated"
+ * buffers
+ * @buffer_mapping - the mapping which backs the buffers' data
+ * @mapping - the mapping which wants those buffers written
+ *
+ * Starts I/O against the buffers at mapping->private_list, and waits upon
+ * that I/O.
+ *
+ * Basically, this is a convenience function for fsync(). @buffer_mapping is
+ * the blockdev which "owns" the buffers and @mapping is a file or directory
+ * which needs those buffers to be written for a successful fsync().
+ */
+int sync_mapping_buffers(struct address_space *mapping)
+{
+ struct address_space *buffer_mapping = mapping->assoc_mapping;
+
+ if (buffer_mapping == NULL || list_empty(&mapping->private_list))
+ return 0;
+
+ return fsync_buffers_list(&buffer_mapping->private_lock,
+ &mapping->private_list);
+}
+EXPORT_SYMBOL(sync_mapping_buffers);
+
+/*
+ * Called when we've recently written block `bblock', and it is known that
+ * `bblock' was for a buffer_boundary() buffer. This means that the block at
+ * `bblock + 1' is probably a dirty indirect block. Hunt it down and, if it's
+ * dirty, schedule it for IO. So that indirects merge nicely with their data.
+ */
+void write_boundary_block(struct block_device *bdev,
+ sector_t bblock, unsigned blocksize)
+{
+ struct buffer_head *bh = __find_get_block(bdev, bblock + 1, blocksize);
+ if (bh) {
+ if (buffer_dirty(bh))
+ ll_rw_block(WRITE, 1, &bh);
+ put_bh(bh);
+ }
+}
+
+void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
+{
+ struct address_space *mapping = inode->i_mapping;
+ struct address_space *buffer_mapping = bh->b_page->mapping;
+
+ mark_buffer_dirty(bh);
+ if (!mapping->assoc_mapping) {
+ mapping->assoc_mapping = buffer_mapping;
+ } else {
+ if (mapping->assoc_mapping != buffer_mapping)
+ BUG();
+ }
+ if (list_empty(&bh->b_assoc_buffers)) {
+ spin_lock(&buffer_mapping->private_lock);
+ list_move_tail(&bh->b_assoc_buffers,
+ &mapping->private_list);
+ spin_unlock(&buffer_mapping->private_lock);
+ }
+}
+EXPORT_SYMBOL(mark_buffer_dirty_inode);
+
+/*
+ * Add a page to the dirty page list.
+ *
+ * It is a sad fact of life that this function is called from several places
+ * deeply under spinlocking. It may not sleep.
+ *
+ * If the page has buffers, the uptodate buffers are set dirty, to preserve
+ * dirty-state coherency between the page and the buffers. It the page does
+ * not have buffers then when they are later attached they will all be set
+ * dirty.
+ *
+ * The buffers are dirtied before the page is dirtied. There's a small race
+ * window in which a writepage caller may see the page cleanness but not the
+ * buffer dirtiness. That's fine. If this code were to set the page dirty
+ * before the buffers, a concurrent writepage caller could clear the page dirty
+ * bit, see a bunch of clean buffers and we'd end up with dirty buffers/clean
+ * page on the dirty page list.
+ *
+ * We use private_lock to lock against try_to_free_buffers while using the
+ * page's buffer list. Also use this to protect against clean buffers being
+ * added to the page after it was set dirty.
+ *
+ * FIXME: may need to call ->reservepage here as well. That's rather up to the
+ * address_space though.
+ */
+int __set_page_dirty_buffers(struct page *page)
+{
+ struct address_space * const mapping = page->mapping;
+
+ spin_lock(&mapping->private_lock);
+ if (page_has_buffers(page)) {
+ struct buffer_head *head = page_buffers(page);
+ struct buffer_head *bh = head;
+
+ do {
+ set_buffer_dirty(bh);
+ bh = bh->b_this_page;
+ } while (bh != head);
+ }
+ spin_unlock(&mapping->private_lock);
+
+ if (!TestSetPageDirty(page)) {
+ write_lock_irq(&mapping->tree_lock);
+ if (page->mapping) { /* Race with truncate? */
+ if (mapping_cap_account_dirty(mapping))
+ inc_page_state(nr_dirty);
+ radix_tree_tag_set(&mapping->page_tree,
+ page_index(page),
+ PAGECACHE_TAG_DIRTY);
+ }
+ write_unlock_irq(&mapping->tree_lock);
+ __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(__set_page_dirty_buffers);
+
+/*
+ * Write out and wait upon a list of buffers.
+ *
+ * We have conflicting pressures: we want to make sure that all
+ * initially dirty buffers get waited on, but that any subsequently
+ * dirtied buffers don't. After all, we don't want fsync to last
+ * forever if somebody is actively writing to the file.
+ *
+ * Do this in two main stages: first we copy dirty buffers to a
+ * temporary inode list, queueing the writes as we go. Then we clean
+ * up, waiting for those writes to complete.
+ *
+ * During this second stage, any subsequent updates to the file may end
+ * up refiling the buffer on the original inode's dirty list again, so
+ * there is a chance we will end up with a buffer queued for write but
+ * not yet completed on that list. So, as a final cleanup we go through
+ * the osync code to catch these locked, dirty buffers without requeuing
+ * any newly dirty buffers for write.
+ */
+static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
+{
+ struct buffer_head *bh;
+ struct list_head tmp;
+ int err = 0, err2;
+
+ INIT_LIST_HEAD(&tmp);
+
+ spin_lock(lock);
+ while (!list_empty(list)) {
+ bh = BH_ENTRY(list->next);
+ list_del_init(&bh->b_assoc_buffers);
+ if (buffer_dirty(bh) || buffer_locked(bh)) {
+ list_add(&bh->b_assoc_buffers, &tmp);
+ if (buffer_dirty(bh)) {
+ get_bh(bh);
+ spin_unlock(lock);
+ /*
+ * Ensure any pending I/O completes so that
+ * ll_rw_block() actually writes the current
+ * contents - it is a noop if I/O is still in
+ * flight on potentially older contents.
+ */
+ wait_on_buffer(bh);
+ ll_rw_block(WRITE, 1, &bh);
+ brelse(bh);
+ spin_lock(lock);
+ }
+ }
+ }
+
+ while (!list_empty(&tmp)) {
+ bh = BH_ENTRY(tmp.prev);
+ __remove_assoc_queue(bh);
+ get_bh(bh);
+ spin_unlock(lock);
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh))
+ err = -EIO;
+ brelse(bh);
+ spin_lock(lock);
+ }
+
+ spin_unlock(lock);
+ err2 = osync_buffers_list(lock, list);
+ if (err)
+ return err;
+ else
+ return err2;
+}
+
+/*
+ * Invalidate any and all dirty buffers on a given inode. We are
+ * probably unmounting the fs, but that doesn't mean we have already
+ * done a sync(). Just drop the buffers from the inode list.
+ *
+ * NOTE: we take the inode's blockdev's mapping's private_lock. Which
+ * assumes that all the buffers are against the blockdev. Not true
+ * for reiserfs.
+ */
+void invalidate_inode_buffers(struct inode *inode)
+{
+ if (inode_has_buffers(inode)) {
+ struct address_space *mapping = &inode->i_data;
+ struct list_head *list = &mapping->private_list;
+ struct address_space *buffer_mapping = mapping->assoc_mapping;
+
+ spin_lock(&buffer_mapping->private_lock);
+ while (!list_empty(list))
+ __remove_assoc_queue(BH_ENTRY(list->next));
+ spin_unlock(&buffer_mapping->private_lock);
+ }
+}
+
+/*
+ * Remove any clean buffers from the inode's buffer list. This is called
+ * when we're trying to free the inode itself. Those buffers can pin it.
+ *
+ * Returns true if all buffers were removed.
+ */
+int remove_inode_buffers(struct inode *inode)
+{
+ int ret = 1;
+
+ if (inode_has_buffers(inode)) {
+ struct address_space *mapping = &inode->i_data;
+ struct list_head *list = &mapping->private_list;
+ struct address_space *buffer_mapping = mapping->assoc_mapping;
+
+ spin_lock(&buffer_mapping->private_lock);
+ while (!list_empty(list)) {
+ struct buffer_head *bh = BH_ENTRY(list->next);
+ if (buffer_dirty(bh)) {
+ ret = 0;
+ break;
+ }
+ __remove_assoc_queue(bh);
+ }
+ spin_unlock(&buffer_mapping->private_lock);
+ }
+ return ret;
+}
+
+/*
+ * Create the appropriate buffers when given a page for data area and
+ * the size of each buffer.. Use the bh->b_this_page linked list to
+ * follow the buffers created. Return NULL if unable to create more
+ * buffers.
+ *
+ * The retry flag is used to differentiate async IO (paging, swapping)
+ * which may not fail from ordinary buffer allocations.
+ */
+struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
+ int retry)
+{
+ struct buffer_head *bh, *head;
+ long offset;
+
+try_again:
+ head = NULL;
+ offset = PAGE_SIZE;
+ while ((offset -= size) >= 0) {
+ bh = alloc_buffer_head(GFP_NOFS);
+ if (!bh)
+ goto no_grow;
+
+ bh->b_bdev = NULL;
+ bh->b_this_page = head;
+ bh->b_blocknr = -1;
+ head = bh;
+
+ bh->b_state = 0;
+ atomic_set(&bh->b_count, 0);
+ bh->b_size = size;
+
+ /* Link the buffer to its page */
+ set_bh_page(bh, page, offset);
+
+ bh->b_end_io = NULL;
+ }
+ return head;
+/*
+ * In case anything failed, we just free everything we got.
+ */
+no_grow:
+ if (head) {
+ do {
+ bh = head;
+ head = head->b_this_page;
+ free_buffer_head(bh);
+ } while (head);
+ }
+
+ /*
+ * Return failure for non-async IO requests. Async IO requests
+ * are not allowed to fail, so we have to wait until buffer heads
+ * become available. But we don't want tasks sleeping with
+ * partially complete buffers, so all were released above.
+ */
+ if (!retry)
+ return NULL;
+
+ /* We're _really_ low on memory. Now we just
+ * wait for old buffer heads to become free due to
+ * finishing IO. Since this is an async request and
+ * the reserve list is empty, we're sure there are
+ * async buffer heads in use.
+ */
+ free_more_memory();
+ goto try_again;
+}
+EXPORT_SYMBOL_GPL(alloc_page_buffers);
+
+static inline void
+link_dev_buffers(struct page *page, struct buffer_head *head)
+{
+ struct buffer_head *bh, *tail;
+
+ bh = head;
+ do {
+ tail = bh;
+ bh = bh->b_this_page;
+ } while (bh);
+ tail->b_this_page = head;
+ attach_page_buffers(page, head);
+}
+
+/*
+ * Initialise the state of a blockdev page's buffers.
+ */
+static void
+init_page_buffers(struct page *page, struct block_device *bdev,
+ sector_t block, int size)
+{
+ struct buffer_head *head = page_buffers(page);
+ struct buffer_head *bh = head;
+ int uptodate = PageUptodate(page);
+
+ do {
+ if (!buffer_mapped(bh)) {
+ init_buffer(bh, NULL, NULL);
+ bh->b_bdev = bdev;
+ bh->b_blocknr = block;
+ if (uptodate)
+ set_buffer_uptodate(bh);
+ set_buffer_mapped(bh);
+ }
+ block++;
+ bh = bh->b_this_page;
+ } while (bh != head);
+}
+
+/*
+ * Create the page-cache page that contains the requested block.
+ *
+ * This is user purely for blockdev mappings.
+ */
+static struct page *
+grow_dev_page(struct block_device *bdev, sector_t block,
+ pgoff_t index, int size)
+{
+ struct inode *inode = bdev->bd_inode;
+ struct page *page;
+ struct buffer_head *bh;
+
+ page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
+ if (!page)
+ return NULL;
+
+ if (!PageLocked(page))
+ BUG();
+
+ if (pag