diff options
Diffstat (limited to 'fs/nilfs2/alloc.c')
-rw-r--r-- | fs/nilfs2/alloc.c | 111 |
1 files changed, 87 insertions, 24 deletions
diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c index d69e6ae59251..7cfb87e692da 100644 --- a/fs/nilfs2/alloc.c +++ b/fs/nilfs2/alloc.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/buffer_head.h> | 26 | #include <linux/buffer_head.h> |
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include <linux/slab.h> | ||
29 | #include "mdt.h" | 30 | #include "mdt.h" |
30 | #include "alloc.h" | 31 | #include "alloc.h" |
31 | 32 | ||
@@ -142,29 +143,75 @@ static void nilfs_palloc_desc_block_init(struct inode *inode, | |||
142 | } | 143 | } |
143 | } | 144 | } |
144 | 145 | ||
146 | static int nilfs_palloc_get_block(struct inode *inode, unsigned long blkoff, | ||
147 | int create, | ||
148 | void (*init_block)(struct inode *, | ||
149 | struct buffer_head *, | ||
150 | void *), | ||
151 | struct buffer_head **bhp, | ||
152 | struct nilfs_bh_assoc *prev, | ||
153 | spinlock_t *lock) | ||
154 | { | ||
155 | int ret; | ||
156 | |||
157 | spin_lock(lock); | ||
158 | if (prev->bh && blkoff == prev->blkoff) { | ||
159 | get_bh(prev->bh); | ||
160 | *bhp = prev->bh; | ||
161 | spin_unlock(lock); | ||
162 | return 0; | ||
163 | } | ||
164 | spin_unlock(lock); | ||
165 | |||
166 | ret = nilfs_mdt_get_block(inode, blkoff, create, init_block, bhp); | ||
167 | if (!ret) { | ||
168 | spin_lock(lock); | ||
169 | /* | ||
170 | * The following code must be safe for change of the | ||
171 | * cache contents during the get block call. | ||
172 | */ | ||
173 | brelse(prev->bh); | ||
174 | get_bh(*bhp); | ||
175 | prev->bh = *bhp; | ||
176 | prev->blkoff = blkoff; | ||
177 | spin_unlock(lock); | ||
178 | } | ||
179 | return ret; | ||
180 | } | ||
181 | |||
145 | static int nilfs_palloc_get_desc_block(struct inode *inode, | 182 | static int nilfs_palloc_get_desc_block(struct inode *inode, |
146 | unsigned long group, | 183 | unsigned long group, |
147 | int create, struct buffer_head **bhp) | 184 | int create, struct buffer_head **bhp) |
148 | { | 185 | { |
149 | return nilfs_mdt_get_block(inode, | 186 | struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache; |
150 | nilfs_palloc_desc_blkoff(inode, group), | 187 | |
151 | create, nilfs_palloc_desc_block_init, bhp); | 188 | return nilfs_palloc_get_block(inode, |
189 | nilfs_palloc_desc_blkoff(inode, group), | ||
190 | create, nilfs_palloc_desc_block_init, | ||
191 | bhp, &cache->prev_desc, &cache->lock); | ||
152 | } | 192 | } |
153 | 193 | ||
154 | static int nilfs_palloc_get_bitmap_block(struct inode *inode, | 194 | static int nilfs_palloc_get_bitmap_block(struct inode *inode, |
155 | unsigned long group, | 195 | unsigned long group, |
156 | int create, struct buffer_head **bhp) | 196 | int create, struct buffer_head **bhp) |
157 | { | 197 | { |
158 | return nilfs_mdt_get_block(inode, | 198 | struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache; |
159 | nilfs_palloc_bitmap_blkoff(inode, group), | 199 | |
160 | create, NULL, bhp); | 200 | return nilfs_palloc_get_block(inode, |
201 | nilfs_palloc_bitmap_blkoff(inode, group), | ||
202 | create, NULL, bhp, | ||
203 | &cache->prev_bitmap, &cache->lock); | ||
161 | } | 204 | } |
162 | 205 | ||
163 | int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr, | 206 | int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr, |
164 | int create, struct buffer_head **bhp) | 207 | int create, struct buffer_head **bhp) |
165 | { | 208 | { |
166 | return nilfs_mdt_get_block(inode, nilfs_palloc_entry_blkoff(inode, nr), | 209 | struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache; |
167 | create, NULL, bhp); | 210 | |
211 | return nilfs_palloc_get_block(inode, | ||
212 | nilfs_palloc_entry_blkoff(inode, nr), | ||
213 | create, NULL, bhp, | ||
214 | &cache->prev_entry, &cache->lock); | ||
168 | } | 215 | } |
169 | 216 | ||
170 | static struct nilfs_palloc_group_desc * | 217 | static struct nilfs_palloc_group_desc * |
@@ -176,13 +223,6 @@ nilfs_palloc_block_get_group_desc(const struct inode *inode, | |||
176 | group % nilfs_palloc_groups_per_desc_block(inode); | 223 | group % nilfs_palloc_groups_per_desc_block(inode); |
177 | } | 224 | } |
178 | 225 | ||
179 | static unsigned char * | ||
180 | nilfs_palloc_block_get_bitmap(const struct inode *inode, | ||
181 | const struct buffer_head *bh, void *kaddr) | ||
182 | { | ||
183 | return (unsigned char *)(kaddr + bh_offset(bh)); | ||
184 | } | ||
185 | |||
186 | void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr, | 226 | void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr, |
187 | const struct buffer_head *bh, void *kaddr) | 227 | const struct buffer_head *bh, void *kaddr) |
188 | { | 228 | { |
@@ -289,8 +329,7 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode, | |||
289 | if (ret < 0) | 329 | if (ret < 0) |
290 | goto out_desc; | 330 | goto out_desc; |
291 | bitmap_kaddr = kmap(bitmap_bh->b_page); | 331 | bitmap_kaddr = kmap(bitmap_bh->b_page); |
292 | bitmap = nilfs_palloc_block_get_bitmap( | 332 | bitmap = bitmap_kaddr + bh_offset(bitmap_bh); |
293 | inode, bitmap_bh, bitmap_kaddr); | ||
294 | pos = nilfs_palloc_find_available_slot( | 333 | pos = nilfs_palloc_find_available_slot( |
295 | inode, group, group_offset, bitmap, | 334 | inode, group, group_offset, bitmap, |
296 | entries_per_group); | 335 | entries_per_group); |
@@ -351,8 +390,7 @@ void nilfs_palloc_commit_free_entry(struct inode *inode, | |||
351 | desc = nilfs_palloc_block_get_group_desc(inode, group, | 390 | desc = nilfs_palloc_block_get_group_desc(inode, group, |
352 | req->pr_desc_bh, desc_kaddr); | 391 | req->pr_desc_bh, desc_kaddr); |
353 | bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page); | 392 | bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page); |
354 | bitmap = nilfs_palloc_block_get_bitmap(inode, req->pr_bitmap_bh, | 393 | bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh); |
355 | bitmap_kaddr); | ||
356 | 394 | ||
357 | if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group), | 395 | if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group), |
358 | group_offset, bitmap)) | 396 | group_offset, bitmap)) |
@@ -385,11 +423,10 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode, | |||
385 | desc = nilfs_palloc_block_get_group_desc(inode, group, | 423 | desc = nilfs_palloc_block_get_group_desc(inode, group, |
386 | req->pr_desc_bh, desc_kaddr); | 424 | req->pr_desc_bh, desc_kaddr); |
387 | bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page); | 425 | bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page); |
388 | bitmap = nilfs_palloc_block_get_bitmap(inode, req->pr_bitmap_bh, | 426 | bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh); |
389 | bitmap_kaddr); | ||
390 | if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group), | 427 | if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group), |
391 | group_offset, bitmap)) | 428 | group_offset, bitmap)) |
392 | printk(KERN_WARNING "%s: entry numer %llu already freed\n", | 429 | printk(KERN_WARNING "%s: entry number %llu already freed\n", |
393 | __func__, (unsigned long long)req->pr_entry_nr); | 430 | __func__, (unsigned long long)req->pr_entry_nr); |
394 | 431 | ||
395 | nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); | 432 | nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); |
@@ -472,8 +509,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) | |||
472 | desc = nilfs_palloc_block_get_group_desc( | 509 | desc = nilfs_palloc_block_get_group_desc( |
473 | inode, group, desc_bh, desc_kaddr); | 510 | inode, group, desc_bh, desc_kaddr); |
474 | bitmap_kaddr = kmap(bitmap_bh->b_page); | 511 | bitmap_kaddr = kmap(bitmap_bh->b_page); |
475 | bitmap = nilfs_palloc_block_get_bitmap( | 512 | bitmap = bitmap_kaddr + bh_offset(bitmap_bh); |
476 | inode, bitmap_bh, bitmap_kaddr); | ||
477 | for (j = i, n = 0; | 513 | for (j = i, n = 0; |
478 | (j < nitems) && nilfs_palloc_group_is_in(inode, group, | 514 | (j < nitems) && nilfs_palloc_group_is_in(inode, group, |
479 | entry_nrs[j]); | 515 | entry_nrs[j]); |
@@ -502,3 +538,30 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) | |||
502 | } | 538 | } |
503 | return 0; | 539 | return 0; |
504 | } | 540 | } |
541 | |||
542 | void nilfs_palloc_setup_cache(struct inode *inode, | ||
543 | struct nilfs_palloc_cache *cache) | ||
544 | { | ||
545 | NILFS_MDT(inode)->mi_palloc_cache = cache; | ||
546 | spin_lock_init(&cache->lock); | ||
547 | } | ||
548 | |||
549 | void nilfs_palloc_clear_cache(struct inode *inode) | ||
550 | { | ||
551 | struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache; | ||
552 | |||
553 | spin_lock(&cache->lock); | ||
554 | brelse(cache->prev_desc.bh); | ||
555 | brelse(cache->prev_bitmap.bh); | ||
556 | brelse(cache->prev_entry.bh); | ||
557 | cache->prev_desc.bh = NULL; | ||
558 | cache->prev_bitmap.bh = NULL; | ||
559 | cache->prev_entry.bh = NULL; | ||
560 | spin_unlock(&cache->lock); | ||
561 | } | ||
562 | |||
563 | void nilfs_palloc_destroy_cache(struct inode *inode) | ||
564 | { | ||
565 | nilfs_palloc_clear_cache(inode); | ||
566 | NILFS_MDT(inode)->mi_palloc_cache = NULL; | ||
567 | } | ||