aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/btnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nilfs2/btnode.c')
-rw-r--r--fs/nilfs2/btnode.c77
1 files changed, 35 insertions, 42 deletions
diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c
index 84c25382f8e3..447ce47a3306 100644
--- a/fs/nilfs2/btnode.c
+++ b/fs/nilfs2/btnode.c
@@ -27,6 +27,7 @@
27#include <linux/buffer_head.h> 27#include <linux/buffer_head.h>
28#include <linux/mm.h> 28#include <linux/mm.h>
29#include <linux/backing-dev.h> 29#include <linux/backing-dev.h>
30#include <linux/gfp.h>
30#include "nilfs.h" 31#include "nilfs.h"
31#include "mdt.h" 32#include "mdt.h"
32#include "dat.h" 33#include "dat.h"
@@ -68,9 +69,34 @@ void nilfs_btnode_cache_clear(struct address_space *btnc)
68 truncate_inode_pages(btnc, 0); 69 truncate_inode_pages(btnc, 0);
69} 70}
70 71
72struct buffer_head *
73nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr)
74{
75 struct inode *inode = NILFS_BTNC_I(btnc);
76 struct buffer_head *bh;
77
78 bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node);
79 if (unlikely(!bh))
80 return NULL;
81
82 if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
83 buffer_dirty(bh))) {
84 brelse(bh);
85 BUG();
86 }
87 memset(bh->b_data, 0, 1 << inode->i_blkbits);
88 bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev;
89 bh->b_blocknr = blocknr;
90 set_buffer_mapped(bh);
91 set_buffer_uptodate(bh);
92
93 unlock_page(bh->b_page);
94 page_cache_release(bh->b_page);
95 return bh;
96}
97
71int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, 98int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
72 sector_t pblocknr, struct buffer_head **pbh, 99 sector_t pblocknr, struct buffer_head **pbh)
73 int newblk)
74{ 100{
75 struct buffer_head *bh; 101 struct buffer_head *bh;
76 struct inode *inode = NILFS_BTNC_I(btnc); 102 struct inode *inode = NILFS_BTNC_I(btnc);
@@ -81,19 +107,6 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
81 return -ENOMEM; 107 return -ENOMEM;
82 108
83 err = -EEXIST; /* internal code */ 109 err = -EEXIST; /* internal code */
84 if (newblk) {
85 if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
86 buffer_dirty(bh))) {
87 brelse(bh);
88 BUG();
89 }
90 memset(bh->b_data, 0, 1 << inode->i_blkbits);
91 bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev;
92 bh->b_blocknr = blocknr;
93 set_buffer_mapped(bh);
94 set_buffer_uptodate(bh);
95 goto found;
96 }
97 110
98 if (buffer_uptodate(bh) || buffer_dirty(bh)) 111 if (buffer_uptodate(bh) || buffer_dirty(bh))
99 goto found; 112 goto found;
@@ -135,27 +148,6 @@ out_locked:
135 return err; 148 return err;
136} 149}
137 150
138int nilfs_btnode_get(struct address_space *btnc, __u64 blocknr,
139 sector_t pblocknr, struct buffer_head **pbh, int newblk)
140{
141 struct buffer_head *bh;
142 int err;
143
144 err = nilfs_btnode_submit_block(btnc, blocknr, pblocknr, pbh, newblk);
145 if (err == -EEXIST) /* internal code (cache hit) */
146 return 0;
147 if (unlikely(err))
148 return err;
149
150 bh = *pbh;
151 wait_on_buffer(bh);
152 if (!buffer_uptodate(bh)) {
153 brelse(bh);
154 return -EIO;
155 }
156 return 0;
157}
158
159/** 151/**
160 * nilfs_btnode_delete - delete B-tree node buffer 152 * nilfs_btnode_delete - delete B-tree node buffer
161 * @bh: buffer to be deleted 153 * @bh: buffer to be deleted
@@ -244,12 +236,13 @@ retry:
244 unlock_page(obh->b_page); 236 unlock_page(obh->b_page);
245 } 237 }
246 238
247 err = nilfs_btnode_get(btnc, newkey, 0, &nbh, 1); 239 nbh = nilfs_btnode_create_block(btnc, newkey);
248 if (likely(!err)) { 240 if (!nbh)
249 BUG_ON(nbh == obh); 241 return -ENOMEM;
250 ctxt->newbh = nbh; 242
251 } 243 BUG_ON(nbh == obh);
252 return err; 244 ctxt->newbh = nbh;
245 return 0;
253 246
254 failed_unlock: 247 failed_unlock:
255 unlock_page(obh->b_page); 248 unlock_page(obh->b_page);