]> err.no Git - linux-2.6/blobdiff - fs/buffer.c
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6] / fs / buffer.c
index bc75f2e7b274e09f395417124fdc7958b1d162f6..13e5938a64f6338072e06c16ad8b73e366cad024 100644 (file)
@@ -331,7 +331,7 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
        return ret;
 }
 
-asmlinkage long sys_fsync(unsigned int fd)
+static long do_fsync(unsigned int fd, int datasync)
 {
        struct file * file;
        struct address_space *mapping;
@@ -342,14 +342,14 @@ asmlinkage long sys_fsync(unsigned int 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;
        }
 
+       mapping = file->f_mapping;
+
        current->flags |= PF_SYNCWRITE;
        ret = filemap_fdatawrite(mapping);
 
@@ -358,7 +358,7 @@ asmlinkage long sys_fsync(unsigned int fd)
         * which could cause livelocks in fsync_buffers_list
         */
        down(&mapping->host->i_sem);
-       err = file->f_op->fsync(file, file->f_dentry, 0);
+       err = file->f_op->fsync(file, file->f_dentry, datasync);
        if (!ret)
                ret = err;
        up(&mapping->host->i_sem);
@@ -373,39 +373,14 @@ out:
        return ret;
 }
 
-asmlinkage long sys_fdatasync(unsigned int fd)
+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;
-
-       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;
+       return do_fsync(fd, 0);
+}
 
-out_putf:
-       fput(file);
-out:
-       return ret;
+asmlinkage long sys_fdatasync(unsigned int fd)
+{
+       return do_fsync(fd, 1);
 }
 
 /*
@@ -528,7 +503,7 @@ static void free_more_memory(void)
        for_each_pgdat(pgdat) {
                zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones;
                if (*zones)
-                       try_to_free_pages(zones, GFP_NOFS, 0);
+                       try_to_free_pages(zones, GFP_NOFS);
        }
 }
 
@@ -1210,7 +1185,7 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
        return 1;
 }
 
-struct buffer_head *
+static struct buffer_head *
 __getblk_slow(struct block_device *bdev, sector_t block, int size)
 {
        /* Size must be multiple of hard sectorsize */
@@ -1751,7 +1726,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
        int err;
        sector_t block;
        sector_t last_block;
-       struct buffer_head *bh, *head, *last_bh = NULL;
+       struct buffer_head *bh, *head;
        int nr_underway = 0;
 
        BUG_ON(!PageLocked(page));
@@ -1826,8 +1801,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
                }
                if (test_clear_buffer_dirty(bh)) {
                        mark_buffer_async_write(bh);
-                       get_bh(bh);
-                       last_bh = bh;
                } else {
                        unlock_buffer(bh);
                }
@@ -1839,20 +1812,16 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
         */
        BUG_ON(PageWriteback(page));
        set_page_writeback(page);
-       unlock_page(page);
 
        do {
                struct buffer_head *next = bh->b_this_page;
                if (buffer_async_write(bh)) {
                        submit_bh(WRITE, bh);
                        nr_underway++;
-                       put_bh(bh);
-                       if (bh == last_bh)
-                               break;
                }
                bh = next;
        } while (bh != head);
-       bh = head;
+       unlock_page(page);
 
        err = 0;
 done:
@@ -1894,8 +1863,6 @@ recover:
                if (buffer_mapped(bh) && buffer_dirty(bh)) {
                        lock_buffer(bh);
                        mark_buffer_async_write(bh);
-                       get_bh(bh);
-                       last_bh = bh;
                } else {
                        /*
                         * The buffer may have been set dirty during
@@ -1914,13 +1881,9 @@ recover:
                        clear_buffer_dirty(bh);
                        submit_bh(WRITE, bh);
                        nr_underway++;
-                       put_bh(bh);
-                       if (bh == last_bh)
-                               break;
                }
                bh = next;
        } while (bh != head);
-       bh = head;
        goto done;
 }
 
@@ -1963,7 +1926,6 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
                        if (err)
                                break;
                        if (buffer_new(bh)) {
-                               clear_buffer_new(bh);
                                unmap_underlying_metadata(bh->b_bdev,
                                                        bh->b_blocknr);
                                if (PageUptodate(page)) {
@@ -2005,9 +1967,14 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
                if (!buffer_uptodate(*wait_bh))
                        err = -EIO;
        }
-       if (!err)
-               return err;
-
+       if (!err) {
+               bh = head;
+               do {
+                       if (buffer_new(bh))
+                               clear_buffer_new(bh);
+               } while ((bh = bh->b_this_page) != head);
+               return 0;
+       }
        /* Error case: */
        /*
         * Zero out any newly allocated blocks to avoid exposing stale
@@ -2106,9 +2073,12 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
                        continue;
 
                if (!buffer_mapped(bh)) {
+                       int err = 0;
+
                        fully_mapped = 0;
                        if (iblock < lblock) {
-                               if (get_block(inode, iblock, bh, 0))
+                               err = get_block(inode, iblock, bh, 0);
+                               if (err)
                                        SetPageError(page);
                        }
                        if (!buffer_mapped(bh)) {
@@ -2116,7 +2086,8 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
                                memset(kaddr + i * blocksize, 0, blocksize);
                                flush_dcache_page(page);
                                kunmap_atomic(kaddr, KM_USER0);
-                               set_buffer_uptodate(bh);
+                               if (!err)
+                                       set_buffer_uptodate(bh);
                                continue;
                        }
                        /*