]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - fs/nilfs2/btnode.c
CIFS: Fix too big maxBuf size for SMB3 mounts
[linux-3.10.git] / fs / nilfs2 / btnode.c
index 4cc07b2c30e0c893e9baf4df3f26c305f2f9c805..a35ae35e69320f711454125f9a600586869bb980 100644 (file)
 #include <linux/buffer_head.h>
 #include <linux/mm.h>
 #include <linux/backing-dev.h>
+#include <linux/gfp.h>
 #include "nilfs.h"
 #include "mdt.h"
 #include "dat.h"
 #include "page.h"
 #include "btnode.h"
 
-
-void nilfs_btnode_cache_init_once(struct address_space *btnc)
+void nilfs_btnode_cache_clear(struct address_space *btnc)
 {
-       INIT_RADIX_TREE(&btnc->page_tree, GFP_ATOMIC);
-       spin_lock_init(&btnc->tree_lock);
-       INIT_LIST_HEAD(&btnc->private_list);
-       spin_lock_init(&btnc->private_lock);
-
-       spin_lock_init(&btnc->i_mmap_lock);
-       INIT_RAW_PRIO_TREE_ROOT(&btnc->i_mmap);
-       INIT_LIST_HEAD(&btnc->i_mmap_nonlinear);
+       invalidate_mapping_pages(btnc, 0, -1);
+       truncate_inode_pages(btnc, 0);
 }
 
-static struct address_space_operations def_btnode_aops;
-
-void nilfs_btnode_cache_init(struct address_space *btnc)
+struct buffer_head *
+nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr)
 {
-       btnc->host = NULL;  /* can safely set to host inode ? */
-       btnc->flags = 0;
-       mapping_set_gfp_mask(btnc, GFP_NOFS);
-       btnc->assoc_mapping = NULL;
-       btnc->backing_dev_info = &default_backing_dev_info;
-       btnc->a_ops = &def_btnode_aops;
-}
+       struct inode *inode = NILFS_BTNC_I(btnc);
+       struct buffer_head *bh;
 
-void nilfs_btnode_cache_clear(struct address_space *btnc)
-{
-       invalidate_mapping_pages(btnc, 0, -1);
-       truncate_inode_pages(btnc, 0);
+       bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node);
+       if (unlikely(!bh))
+               return NULL;
+
+       if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
+                    buffer_dirty(bh))) {
+               brelse(bh);
+               BUG();
+       }
+       memset(bh->b_data, 0, 1 << inode->i_blkbits);
+       bh->b_bdev = inode->i_sb->s_bdev;
+       bh->b_blocknr = blocknr;
+       set_buffer_mapped(bh);
+       set_buffer_uptodate(bh);
+
+       unlock_page(bh->b_page);
+       page_cache_release(bh->b_page);
+       return bh;
 }
 
 int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
-                             sector_t pblocknr, struct buffer_head **pbh,
-                             int newblk)
+                             sector_t pblocknr, int mode,
+                             struct buffer_head **pbh, sector_t *submit_ptr)
 {
        struct buffer_head *bh;
        struct inode *inode = NILFS_BTNC_I(btnc);
+       struct page *page;
        int err;
 
        bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node);
@@ -77,18 +80,7 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
                return -ENOMEM;
 
        err = -EEXIST; /* internal code */
-       if (newblk) {
-               if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
-                            buffer_dirty(bh))) {
-                       brelse(bh);
-                       BUG();
-               }
-               bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev;
-               bh->b_blocknr = blocknr;
-               set_buffer_mapped(bh);
-               set_buffer_uptodate(bh);
-               goto found;
-       }
+       page = bh->b_page;
 
        if (buffer_uptodate(bh) || buffer_dirty(bh))
                goto found;
@@ -96,61 +88,50 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
        if (pblocknr == 0) {
                pblocknr = blocknr;
                if (inode->i_ino != NILFS_DAT_INO) {
-                       struct inode *dat =
-                               nilfs_dat_inode(NILFS_I_NILFS(inode));
+                       struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 
                        /* blocknr is a virtual block number */
-                       err = nilfs_dat_translate(dat, blocknr, &pblocknr);
+                       err = nilfs_dat_translate(nilfs->ns_dat, blocknr,
+                                                 &pblocknr);
                        if (unlikely(err)) {
                                brelse(bh);
                                goto out_locked;
                        }
                }
        }
-       lock_buffer(bh);
+
+       if (mode == READA) {
+               if (pblocknr != *submit_ptr + 1 || !trylock_buffer(bh)) {
+                       err = -EBUSY; /* internal code */
+                       brelse(bh);
+                       goto out_locked;
+               }
+       } else { /* mode == READ */
+               lock_buffer(bh);
+       }
        if (buffer_uptodate(bh)) {
                unlock_buffer(bh);
                err = -EEXIST; /* internal code */
                goto found;
        }
        set_buffer_mapped(bh);
-       bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev;
+       bh->b_bdev = inode->i_sb->s_bdev;
        bh->b_blocknr = pblocknr; /* set block address for read */
        bh->b_end_io = end_buffer_read_sync;
        get_bh(bh);
-       submit_bh(READ, bh);
+       submit_bh(mode, bh);
        bh->b_blocknr = blocknr; /* set back to the given block address */
+       *submit_ptr = pblocknr;
        err = 0;
 found:
        *pbh = bh;
 
 out_locked:
-       unlock_page(bh->b_page);
-       page_cache_release(bh->b_page);
+       unlock_page(page);
+       page_cache_release(page);
        return err;
 }
 
-int nilfs_btnode_get(struct address_space *btnc, __u64 blocknr,
-                    sector_t pblocknr, struct buffer_head **pbh, int newblk)
-{
-       struct buffer_head *bh;
-       int err;
-
-       err = nilfs_btnode_submit_block(btnc, blocknr, pblocknr, pbh, newblk);
-       if (err == -EEXIST) /* internal code (cache hit) */
-               return 0;
-       if (unlikely(err))
-               return err;
-
-       bh = *pbh;
-       wait_on_buffer(bh);
-       if (!buffer_uptodate(bh)) {
-               brelse(bh);
-               return -EIO;
-       }
-       return 0;
-}
-
 /**
  * nilfs_btnode_delete - delete B-tree node buffer
  * @bh: buffer to be deleted
@@ -206,6 +187,7 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc,
                 * We cannot call radix_tree_preload for the kernels older
                 * than 2.6.23, because it is not exported for modules.
                 */
+retry:
                err = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
                if (err)
                        goto failed_unlock;
@@ -216,7 +198,6 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc,
                                       (unsigned long long)oldkey,
                                       (unsigned long long)newkey);
 
-retry:
                spin_lock_irq(&btnc->tree_lock);
                err = radix_tree_insert(&btnc->page_tree, newkey, obh->b_page);
                spin_unlock_irq(&btnc->tree_lock);
@@ -239,12 +220,13 @@ retry:
                unlock_page(obh->b_page);
        }
 
-       err = nilfs_btnode_get(btnc, newkey, 0, &nbh, 1);
-       if (likely(!err)) {
-               BUG_ON(nbh == obh);
-               ctxt->newbh = nbh;
-       }
-       return err;
+       nbh = nilfs_btnode_create_block(btnc, newkey);
+       if (!nbh)
+               return -ENOMEM;
+
+       BUG_ON(nbh == obh);
+       ctxt->newbh = nbh;
+       return 0;
 
  failed_unlock:
        unlock_page(obh->b_page);
@@ -272,8 +254,7 @@ void nilfs_btnode_commit_change_key(struct address_space *btnc,
                                       "invalid oldkey %lld (newkey=%lld)",
                                       (unsigned long long)oldkey,
                                       (unsigned long long)newkey);
-               if (!test_set_buffer_dirty(obh) && TestSetPageDirty(opage))
-                       BUG();
+               mark_buffer_dirty(obh);
 
                spin_lock_irq(&btnc->tree_lock);
                radix_tree_delete(&btnc->page_tree, oldkey);
@@ -285,7 +266,7 @@ void nilfs_btnode_commit_change_key(struct address_space *btnc,
                unlock_page(opage);
        } else {
                nilfs_copy_buffer(nbh, obh);
-               nilfs_btnode_mark_dirty(nbh);
+               mark_buffer_dirty(nbh);
 
                nbh->b_blocknr = newkey;
                ctxt->bh = nbh;