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