2 * bmap.c - NILFS block mapping.
4 * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Written by Koji Sato <koji@osrg.net>.
24 #include <linux/string.h>
25 #include <linux/errno.h>
36 struct inode
*nilfs_bmap_get_dat(const struct nilfs_bmap
*bmap
)
38 return NILFS_I_NILFS(bmap
->b_inode
)->ns_dat
;
41 static int nilfs_bmap_convert_error(struct nilfs_bmap
*bmap
,
42 const char *fname
, int err
)
44 struct inode
*inode
= bmap
->b_inode
;
47 nilfs_error(inode
->i_sb
, fname
,
48 "broken bmap (inode number=%lu)\n", inode
->i_ino
);
55 * nilfs_bmap_lookup_at_level - find a data block or node block
59 * @ptrp: place to store the value associated to @key
61 * Description: nilfs_bmap_lookup_at_level() finds a record whose key
62 * matches @key in the block at @level of the bmap.
64 * Return Value: On success, 0 is returned and the record associated with @key
65 * is stored in the place pointed by @ptrp. On error, one of the following
66 * negative error codes is returned.
70 * %-ENOMEM - Insufficient amount of memory available.
72 * %-ENOENT - A record associated with @key does not exist.
74 int nilfs_bmap_lookup_at_level(struct nilfs_bmap
*bmap
, __u64 key
, int level
,
80 down_read(&bmap
->b_sem
);
81 ret
= bmap
->b_ops
->bop_lookup(bmap
, key
, level
, ptrp
);
83 ret
= nilfs_bmap_convert_error(bmap
, __func__
, ret
);
86 if (NILFS_BMAP_USE_VBN(bmap
)) {
87 ret
= nilfs_dat_translate(nilfs_bmap_get_dat(bmap
), *ptrp
,
94 up_read(&bmap
->b_sem
);
98 int nilfs_bmap_lookup_contig(struct nilfs_bmap
*bmap
, __u64 key
, __u64
*ptrp
,
103 down_read(&bmap
->b_sem
);
104 ret
= bmap
->b_ops
->bop_lookup_contig(bmap
, key
, ptrp
, maxblocks
);
105 up_read(&bmap
->b_sem
);
107 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
110 static int nilfs_bmap_do_insert(struct nilfs_bmap
*bmap
, __u64 key
, __u64 ptr
)
112 __u64 keys
[NILFS_BMAP_SMALL_HIGH
+ 1];
113 __u64 ptrs
[NILFS_BMAP_SMALL_HIGH
+ 1];
116 if (bmap
->b_ops
->bop_check_insert
!= NULL
) {
117 ret
= bmap
->b_ops
->bop_check_insert(bmap
, key
);
119 n
= bmap
->b_ops
->bop_gather_data(
120 bmap
, keys
, ptrs
, NILFS_BMAP_SMALL_HIGH
+ 1);
123 ret
= nilfs_btree_convert_and_insert(
124 bmap
, key
, ptr
, keys
, ptrs
, n
);
126 bmap
->b_u
.u_flags
|= NILFS_BMAP_LARGE
;
133 return bmap
->b_ops
->bop_insert(bmap
, key
, ptr
);
137 * nilfs_bmap_insert - insert a new key-record pair into a bmap
142 * Description: nilfs_bmap_insert() inserts the new key-record pair specified
143 * by @key and @rec into @bmap.
145 * Return Value: On success, 0 is returned. On error, one of the following
146 * negative error codes is returned.
150 * %-ENOMEM - Insufficient amount of memory available.
152 * %-EEXIST - A record associated with @key already exist.
154 int nilfs_bmap_insert(struct nilfs_bmap
*bmap
,
160 down_write(&bmap
->b_sem
);
161 ret
= nilfs_bmap_do_insert(bmap
, key
, rec
);
162 up_write(&bmap
->b_sem
);
164 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
167 static int nilfs_bmap_do_delete(struct nilfs_bmap
*bmap
, __u64 key
)
169 __u64 keys
[NILFS_BMAP_LARGE_LOW
+ 1];
170 __u64 ptrs
[NILFS_BMAP_LARGE_LOW
+ 1];
173 if (bmap
->b_ops
->bop_check_delete
!= NULL
) {
174 ret
= bmap
->b_ops
->bop_check_delete(bmap
, key
);
176 n
= bmap
->b_ops
->bop_gather_data(
177 bmap
, keys
, ptrs
, NILFS_BMAP_LARGE_LOW
+ 1);
180 ret
= nilfs_direct_delete_and_convert(
181 bmap
, key
, keys
, ptrs
, n
);
183 bmap
->b_u
.u_flags
&= ~NILFS_BMAP_LARGE
;
190 return bmap
->b_ops
->bop_delete(bmap
, key
);
193 int nilfs_bmap_last_key(struct nilfs_bmap
*bmap
, unsigned long *key
)
198 down_read(&bmap
->b_sem
);
199 ret
= bmap
->b_ops
->bop_last_key(bmap
, &lastkey
);
200 up_read(&bmap
->b_sem
);
203 ret
= nilfs_bmap_convert_error(bmap
, __func__
, ret
);
210 * nilfs_bmap_delete - delete a key-record pair from a bmap
214 * Description: nilfs_bmap_delete() deletes the key-record pair specified by
217 * Return Value: On success, 0 is returned. On error, one of the following
218 * negative error codes is returned.
222 * %-ENOMEM - Insufficient amount of memory available.
224 * %-ENOENT - A record associated with @key does not exist.
226 int nilfs_bmap_delete(struct nilfs_bmap
*bmap
, unsigned long key
)
230 down_write(&bmap
->b_sem
);
231 ret
= nilfs_bmap_do_delete(bmap
, key
);
232 up_write(&bmap
->b_sem
);
234 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
237 static int nilfs_bmap_do_truncate(struct nilfs_bmap
*bmap
, unsigned long key
)
242 ret
= bmap
->b_ops
->bop_last_key(bmap
, &lastkey
);
249 while (key
<= lastkey
) {
250 ret
= nilfs_bmap_do_delete(bmap
, lastkey
);
253 ret
= bmap
->b_ops
->bop_last_key(bmap
, &lastkey
);
264 * nilfs_bmap_truncate - truncate a bmap to a specified key
268 * Description: nilfs_bmap_truncate() removes key-record pairs whose keys are
269 * greater than or equal to @key from @bmap.
271 * Return Value: On success, 0 is returned. On error, one of the following
272 * negative error codes is returned.
276 * %-ENOMEM - Insufficient amount of memory available.
278 int nilfs_bmap_truncate(struct nilfs_bmap
*bmap
, unsigned long key
)
282 down_write(&bmap
->b_sem
);
283 ret
= nilfs_bmap_do_truncate(bmap
, key
);
284 up_write(&bmap
->b_sem
);
286 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
290 * nilfs_bmap_clear - free resources a bmap holds
293 * Description: nilfs_bmap_clear() frees resources associated with @bmap.
295 void nilfs_bmap_clear(struct nilfs_bmap
*bmap
)
297 down_write(&bmap
->b_sem
);
298 if (bmap
->b_ops
->bop_clear
!= NULL
)
299 bmap
->b_ops
->bop_clear(bmap
);
300 up_write(&bmap
->b_sem
);
304 * nilfs_bmap_propagate - propagate dirty state
308 * Description: nilfs_bmap_propagate() marks the buffers that directly or
309 * indirectly refer to the block specified by @bh dirty.
311 * Return Value: On success, 0 is returned. On error, one of the following
312 * negative error codes is returned.
316 * %-ENOMEM - Insufficient amount of memory available.
318 int nilfs_bmap_propagate(struct nilfs_bmap
*bmap
, struct buffer_head
*bh
)
322 down_write(&bmap
->b_sem
);
323 ret
= bmap
->b_ops
->bop_propagate(bmap
, bh
);
324 up_write(&bmap
->b_sem
);
326 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
330 * nilfs_bmap_lookup_dirty_buffers -
332 * @listp: pointer to buffer head list
334 void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap
*bmap
,
335 struct list_head
*listp
)
337 if (bmap
->b_ops
->bop_lookup_dirty_buffers
!= NULL
)
338 bmap
->b_ops
->bop_lookup_dirty_buffers(bmap
, listp
);
342 * nilfs_bmap_assign - assign a new block number to a block
344 * @bhp: pointer to buffer head
345 * @blocknr: block number
346 * @binfo: block information
348 * Description: nilfs_bmap_assign() assigns the block number @blocknr to the
349 * buffer specified by @bh.
351 * Return Value: On success, 0 is returned and the buffer head of a newly
352 * create buffer and the block information associated with the buffer are
353 * stored in the place pointed by @bh and @binfo, respectively. On error, one
354 * of the following negative error codes is returned.
358 * %-ENOMEM - Insufficient amount of memory available.
360 int nilfs_bmap_assign(struct nilfs_bmap
*bmap
,
361 struct buffer_head
**bh
,
362 unsigned long blocknr
,
363 union nilfs_binfo
*binfo
)
367 down_write(&bmap
->b_sem
);
368 ret
= bmap
->b_ops
->bop_assign(bmap
, bh
, blocknr
, binfo
);
369 up_write(&bmap
->b_sem
);
371 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
375 * nilfs_bmap_mark - mark block dirty
380 * Description: nilfs_bmap_mark() marks the block specified by @key and @level
383 * Return Value: On success, 0 is returned. On error, one of the following
384 * negative error codes is returned.
388 * %-ENOMEM - Insufficient amount of memory available.
390 int nilfs_bmap_mark(struct nilfs_bmap
*bmap
, __u64 key
, int level
)
394 if (bmap
->b_ops
->bop_mark
== NULL
)
397 down_write(&bmap
->b_sem
);
398 ret
= bmap
->b_ops
->bop_mark(bmap
, key
, level
);
399 up_write(&bmap
->b_sem
);
401 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
405 * nilfs_bmap_test_and_clear_dirty - test and clear a bmap dirty state
408 * Description: nilfs_test_and_clear() is the atomic operation to test and
409 * clear the dirty state of @bmap.
411 * Return Value: 1 is returned if @bmap is dirty, or 0 if clear.
413 int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap
*bmap
)
417 down_write(&bmap
->b_sem
);
418 ret
= nilfs_bmap_dirty(bmap
);
419 nilfs_bmap_clear_dirty(bmap
);
420 up_write(&bmap
->b_sem
);
429 void nilfs_bmap_add_blocks(const struct nilfs_bmap
*bmap
, int n
)
431 inode_add_bytes(bmap
->b_inode
, (1 << bmap
->b_inode
->i_blkbits
) * n
);
434 void nilfs_bmap_sub_blocks(const struct nilfs_bmap
*bmap
, int n
)
436 inode_sub_bytes(bmap
->b_inode
, (1 << bmap
->b_inode
->i_blkbits
) * n
);
439 __u64
nilfs_bmap_data_get_key(const struct nilfs_bmap
*bmap
,
440 const struct buffer_head
*bh
)
442 struct buffer_head
*pbh
;
445 key
= page_index(bh
->b_page
) << (PAGE_CACHE_SHIFT
-
446 bmap
->b_inode
->i_blkbits
);
447 for (pbh
= page_buffers(bh
->b_page
); pbh
!= bh
; pbh
= pbh
->b_this_page
)
453 __u64
nilfs_bmap_find_target_seq(const struct nilfs_bmap
*bmap
, __u64 key
)
457 diff
= key
- bmap
->b_last_allocated_key
;
458 if ((nilfs_bmap_keydiff_abs(diff
) < NILFS_INODE_BMAP_SIZE
) &&
459 (bmap
->b_last_allocated_ptr
!= NILFS_BMAP_INVALID_PTR
) &&
460 (bmap
->b_last_allocated_ptr
+ diff
> 0))
461 return bmap
->b_last_allocated_ptr
+ diff
;
463 return NILFS_BMAP_INVALID_PTR
;
466 #define NILFS_BMAP_GROUP_DIV 8
467 __u64
nilfs_bmap_find_target_in_group(const struct nilfs_bmap
*bmap
)
469 struct inode
*dat
= nilfs_bmap_get_dat(bmap
);
470 unsigned long entries_per_group
= nilfs_palloc_entries_per_group(dat
);
471 unsigned long group
= bmap
->b_inode
->i_ino
/ entries_per_group
;
473 return group
* entries_per_group
+
474 (bmap
->b_inode
->i_ino
% NILFS_BMAP_GROUP_DIV
) *
475 (entries_per_group
/ NILFS_BMAP_GROUP_DIV
);
478 static struct lock_class_key nilfs_bmap_dat_lock_key
;
479 static struct lock_class_key nilfs_bmap_mdt_lock_key
;
482 * nilfs_bmap_read - read a bmap from an inode
484 * @raw_inode: on-disk inode
486 * Description: nilfs_bmap_read() initializes the bmap @bmap.
488 * Return Value: On success, 0 is returned. On error, the following negative
489 * error code is returned.
491 * %-ENOMEM - Insufficient amount of memory available.
493 int nilfs_bmap_read(struct nilfs_bmap
*bmap
, struct nilfs_inode
*raw_inode
)
495 if (raw_inode
== NULL
)
496 memset(bmap
->b_u
.u_data
, 0, NILFS_BMAP_SIZE
);
498 memcpy(bmap
->b_u
.u_data
, raw_inode
->i_bmap
, NILFS_BMAP_SIZE
);
500 init_rwsem(&bmap
->b_sem
);
502 bmap
->b_inode
= &NILFS_BMAP_I(bmap
)->vfs_inode
;
503 switch (bmap
->b_inode
->i_ino
) {
505 bmap
->b_ptr_type
= NILFS_BMAP_PTR_P
;
506 bmap
->b_last_allocated_key
= 0;
507 bmap
->b_last_allocated_ptr
= NILFS_BMAP_NEW_PTR_INIT
;
508 lockdep_set_class(&bmap
->b_sem
, &nilfs_bmap_dat_lock_key
);
510 case NILFS_CPFILE_INO
:
511 case NILFS_SUFILE_INO
:
512 bmap
->b_ptr_type
= NILFS_BMAP_PTR_VS
;
513 bmap
->b_last_allocated_key
= 0;
514 bmap
->b_last_allocated_ptr
= NILFS_BMAP_INVALID_PTR
;
515 lockdep_set_class(&bmap
->b_sem
, &nilfs_bmap_mdt_lock_key
);
517 case NILFS_IFILE_INO
:
518 lockdep_set_class(&bmap
->b_sem
, &nilfs_bmap_mdt_lock_key
);
521 bmap
->b_ptr_type
= NILFS_BMAP_PTR_VM
;
522 bmap
->b_last_allocated_key
= 0;
523 bmap
->b_last_allocated_ptr
= NILFS_BMAP_INVALID_PTR
;
527 return (bmap
->b_u
.u_flags
& NILFS_BMAP_LARGE
) ?
528 nilfs_btree_init(bmap
) : nilfs_direct_init(bmap
);
532 * nilfs_bmap_write - write back a bmap to an inode
534 * @raw_inode: on-disk inode
536 * Description: nilfs_bmap_write() stores @bmap in @raw_inode.
538 void nilfs_bmap_write(struct nilfs_bmap
*bmap
, struct nilfs_inode
*raw_inode
)
540 down_write(&bmap
->b_sem
);
541 memcpy(raw_inode
->i_bmap
, bmap
->b_u
.u_data
,
542 NILFS_INODE_BMAP_SIZE
* sizeof(__le64
));
543 if (bmap
->b_inode
->i_ino
== NILFS_DAT_INO
)
544 bmap
->b_last_allocated_ptr
= NILFS_BMAP_NEW_PTR_INIT
;
546 up_write(&bmap
->b_sem
);
549 void nilfs_bmap_init_gc(struct nilfs_bmap
*bmap
)
551 memset(&bmap
->b_u
, 0, NILFS_BMAP_SIZE
);
552 init_rwsem(&bmap
->b_sem
);
553 bmap
->b_inode
= &NILFS_BMAP_I(bmap
)->vfs_inode
;
554 bmap
->b_ptr_type
= NILFS_BMAP_PTR_U
;
555 bmap
->b_last_allocated_key
= 0;
556 bmap
->b_last_allocated_ptr
= NILFS_BMAP_INVALID_PTR
;
558 nilfs_btree_init_gc(bmap
);
561 void nilfs_bmap_save(const struct nilfs_bmap
*bmap
,
562 struct nilfs_bmap_store
*store
)
564 memcpy(store
->data
, bmap
->b_u
.u_data
, sizeof(store
->data
));
565 store
->last_allocated_key
= bmap
->b_last_allocated_key
;
566 store
->last_allocated_ptr
= bmap
->b_last_allocated_ptr
;
567 store
->state
= bmap
->b_state
;
570 void nilfs_bmap_restore(struct nilfs_bmap
*bmap
,
571 const struct nilfs_bmap_store
*store
)
573 memcpy(bmap
->b_u
.u_data
, store
->data
, sizeof(store
->data
));
574 bmap
->b_last_allocated_key
= store
->last_allocated_key
;
575 bmap
->b_last_allocated_ptr
= store
->last_allocated_ptr
;
576 bmap
->b_state
= store
->state
;