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 | } | ||