1 // SPDX-License-Identifier: GPL-2.0+
5 * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
7 * Written by Koji Sato.
11 #include <linux/string.h>
12 #include <linux/errno.h>
22 struct inode
*nilfs_bmap_get_dat(const struct nilfs_bmap
*bmap
)
24 struct the_nilfs
*nilfs
= bmap
->b_inode
->i_sb
->s_fs_info
;
29 static int nilfs_bmap_convert_error(struct nilfs_bmap
*bmap
,
30 const char *fname
, int err
)
32 struct inode
*inode
= bmap
->b_inode
;
35 __nilfs_error(inode
->i_sb
, fname
,
36 "broken bmap (inode number=%lu)", inode
->i_ino
);
43 * nilfs_bmap_lookup_at_level - find a data block or node block
47 * @ptrp: place to store the value associated to @key
49 * Description: nilfs_bmap_lookup_at_level() finds a record whose key
50 * matches @key in the block at @level of the bmap.
52 * Return Value: On success, 0 is returned and the record associated with @key
53 * is stored in the place pointed by @ptrp. On error, one of the following
54 * negative error codes is returned.
58 * %-ENOMEM - Insufficient amount of memory available.
60 * %-ENOENT - A record associated with @key does not exist.
62 int nilfs_bmap_lookup_at_level(struct nilfs_bmap
*bmap
, __u64 key
, int level
,
68 down_read(&bmap
->b_sem
);
69 ret
= bmap
->b_ops
->bop_lookup(bmap
, key
, level
, ptrp
);
73 if (NILFS_BMAP_USE_VBN(bmap
)) {
74 ret
= nilfs_dat_translate(nilfs_bmap_get_dat(bmap
), *ptrp
,
78 else if (ret
== -ENOENT
) {
80 * If there was no valid entry in DAT for the block
81 * address obtained by b_ops->bop_lookup, then pass
82 * internal code -EINVAL to nilfs_bmap_convert_error
83 * to treat it as metadata corruption.
90 up_read(&bmap
->b_sem
);
91 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
94 int nilfs_bmap_lookup_contig(struct nilfs_bmap
*bmap
, __u64 key
, __u64
*ptrp
,
95 unsigned int maxblocks
)
99 down_read(&bmap
->b_sem
);
100 ret
= bmap
->b_ops
->bop_lookup_contig(bmap
, key
, ptrp
, maxblocks
);
101 up_read(&bmap
->b_sem
);
103 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
106 static int nilfs_bmap_do_insert(struct nilfs_bmap
*bmap
, __u64 key
, __u64 ptr
)
108 __u64 keys
[NILFS_BMAP_SMALL_HIGH
+ 1];
109 __u64 ptrs
[NILFS_BMAP_SMALL_HIGH
+ 1];
112 if (bmap
->b_ops
->bop_check_insert
!= NULL
) {
113 ret
= bmap
->b_ops
->bop_check_insert(bmap
, key
);
115 n
= bmap
->b_ops
->bop_gather_data(
116 bmap
, keys
, ptrs
, NILFS_BMAP_SMALL_HIGH
+ 1);
119 ret
= nilfs_btree_convert_and_insert(
120 bmap
, key
, ptr
, keys
, ptrs
, n
);
122 bmap
->b_u
.u_flags
|= NILFS_BMAP_LARGE
;
129 return bmap
->b_ops
->bop_insert(bmap
, key
, ptr
);
133 * nilfs_bmap_insert - insert a new key-record pair into a bmap
138 * Description: nilfs_bmap_insert() inserts the new key-record pair specified
139 * by @key and @rec into @bmap.
141 * Return Value: On success, 0 is returned. On error, one of the following
142 * negative error codes is returned.
146 * %-ENOMEM - Insufficient amount of memory available.
148 * %-EEXIST - A record associated with @key already exist.
150 int nilfs_bmap_insert(struct nilfs_bmap
*bmap
, __u64 key
, unsigned long rec
)
154 down_write(&bmap
->b_sem
);
155 ret
= nilfs_bmap_do_insert(bmap
, key
, rec
);
156 up_write(&bmap
->b_sem
);
158 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
161 static int nilfs_bmap_do_delete(struct nilfs_bmap
*bmap
, __u64 key
)
163 __u64 keys
[NILFS_BMAP_LARGE_LOW
+ 1];
164 __u64 ptrs
[NILFS_BMAP_LARGE_LOW
+ 1];
167 if (bmap
->b_ops
->bop_check_delete
!= NULL
) {
168 ret
= bmap
->b_ops
->bop_check_delete(bmap
, key
);
170 n
= bmap
->b_ops
->bop_gather_data(
171 bmap
, keys
, ptrs
, NILFS_BMAP_LARGE_LOW
+ 1);
174 ret
= nilfs_direct_delete_and_convert(
175 bmap
, key
, keys
, ptrs
, n
);
177 bmap
->b_u
.u_flags
&= ~NILFS_BMAP_LARGE
;
184 return bmap
->b_ops
->bop_delete(bmap
, key
);
188 * nilfs_bmap_seek_key - seek a valid entry and return its key
190 * @start: start key number
191 * @keyp: place to store valid key
193 * Description: nilfs_bmap_seek_key() seeks a valid key on @bmap
194 * starting from @start, and stores it to @keyp if found.
196 * Return Value: On success, 0 is returned. On error, one of the following
197 * negative error codes is returned.
201 * %-ENOMEM - Insufficient amount of memory available.
203 * %-ENOENT - No valid entry was found
205 int nilfs_bmap_seek_key(struct nilfs_bmap
*bmap
, __u64 start
, __u64
*keyp
)
209 down_read(&bmap
->b_sem
);
210 ret
= bmap
->b_ops
->bop_seek_key(bmap
, start
, keyp
);
211 up_read(&bmap
->b_sem
);
214 ret
= nilfs_bmap_convert_error(bmap
, __func__
, ret
);
218 int nilfs_bmap_last_key(struct nilfs_bmap
*bmap
, __u64
*keyp
)
222 down_read(&bmap
->b_sem
);
223 ret
= bmap
->b_ops
->bop_last_key(bmap
, keyp
);
224 up_read(&bmap
->b_sem
);
227 ret
= nilfs_bmap_convert_error(bmap
, __func__
, ret
);
232 * nilfs_bmap_delete - delete a key-record pair from a bmap
236 * Description: nilfs_bmap_delete() deletes the key-record pair specified by
239 * Return Value: On success, 0 is returned. On error, one of the following
240 * negative error codes is returned.
244 * %-ENOMEM - Insufficient amount of memory available.
246 * %-ENOENT - A record associated with @key does not exist.
248 int nilfs_bmap_delete(struct nilfs_bmap
*bmap
, __u64 key
)
252 down_write(&bmap
->b_sem
);
253 ret
= nilfs_bmap_do_delete(bmap
, key
);
254 up_write(&bmap
->b_sem
);
256 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
259 static int nilfs_bmap_do_truncate(struct nilfs_bmap
*bmap
, __u64 key
)
264 ret
= bmap
->b_ops
->bop_last_key(bmap
, &lastkey
);
271 while (key
<= lastkey
) {
272 ret
= nilfs_bmap_do_delete(bmap
, lastkey
);
275 ret
= bmap
->b_ops
->bop_last_key(bmap
, &lastkey
);
286 * nilfs_bmap_truncate - truncate a bmap to a specified key
290 * Description: nilfs_bmap_truncate() removes key-record pairs whose keys are
291 * greater than or equal to @key from @bmap.
293 * Return Value: On success, 0 is returned. On error, one of the following
294 * negative error codes is returned.
298 * %-ENOMEM - Insufficient amount of memory available.
300 int nilfs_bmap_truncate(struct nilfs_bmap
*bmap
, __u64 key
)
304 down_write(&bmap
->b_sem
);
305 ret
= nilfs_bmap_do_truncate(bmap
, key
);
306 up_write(&bmap
->b_sem
);
308 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
312 * nilfs_bmap_clear - free resources a bmap holds
315 * Description: nilfs_bmap_clear() frees resources associated with @bmap.
317 void nilfs_bmap_clear(struct nilfs_bmap
*bmap
)
319 down_write(&bmap
->b_sem
);
320 if (bmap
->b_ops
->bop_clear
!= NULL
)
321 bmap
->b_ops
->bop_clear(bmap
);
322 up_write(&bmap
->b_sem
);
326 * nilfs_bmap_propagate - propagate dirty state
330 * Description: nilfs_bmap_propagate() marks the buffers that directly or
331 * indirectly refer to the block specified by @bh dirty.
333 * Return Value: On success, 0 is returned. On error, one of the following
334 * negative error codes is returned.
338 * %-ENOMEM - Insufficient amount of memory available.
340 int nilfs_bmap_propagate(struct nilfs_bmap
*bmap
, struct buffer_head
*bh
)
344 down_write(&bmap
->b_sem
);
345 ret
= bmap
->b_ops
->bop_propagate(bmap
, bh
);
346 up_write(&bmap
->b_sem
);
348 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
352 * nilfs_bmap_lookup_dirty_buffers - collect dirty block buffers
354 * @listp: pointer to buffer head list
356 void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap
*bmap
,
357 struct list_head
*listp
)
359 if (bmap
->b_ops
->bop_lookup_dirty_buffers
!= NULL
)
360 bmap
->b_ops
->bop_lookup_dirty_buffers(bmap
, listp
);
364 * nilfs_bmap_assign - assign a new block number to a block
366 * @bh: pointer to buffer head
367 * @blocknr: block number
368 * @binfo: block information
370 * Description: nilfs_bmap_assign() assigns the block number @blocknr to the
371 * buffer specified by @bh.
373 * Return Value: On success, 0 is returned and the buffer head of a newly
374 * create buffer and the block information associated with the buffer are
375 * stored in the place pointed by @bh and @binfo, respectively. On error, one
376 * of the following negative error codes is returned.
380 * %-ENOMEM - Insufficient amount of memory available.
382 int nilfs_bmap_assign(struct nilfs_bmap
*bmap
,
383 struct buffer_head
**bh
,
384 unsigned long blocknr
,
385 union nilfs_binfo
*binfo
)
389 down_write(&bmap
->b_sem
);
390 ret
= bmap
->b_ops
->bop_assign(bmap
, bh
, blocknr
, binfo
);
391 up_write(&bmap
->b_sem
);
393 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
397 * nilfs_bmap_mark - mark block dirty
402 * Description: nilfs_bmap_mark() marks the block specified by @key and @level
405 * Return Value: On success, 0 is returned. On error, one of the following
406 * negative error codes is returned.
410 * %-ENOMEM - Insufficient amount of memory available.
412 int nilfs_bmap_mark(struct nilfs_bmap
*bmap
, __u64 key
, int level
)
416 if (bmap
->b_ops
->bop_mark
== NULL
)
419 down_write(&bmap
->b_sem
);
420 ret
= bmap
->b_ops
->bop_mark(bmap
, key
, level
);
421 up_write(&bmap
->b_sem
);
423 return nilfs_bmap_convert_error(bmap
, __func__
, ret
);
427 * nilfs_bmap_test_and_clear_dirty - test and clear a bmap dirty state
430 * Description: nilfs_test_and_clear() is the atomic operation to test and
431 * clear the dirty state of @bmap.
433 * Return Value: 1 is returned if @bmap is dirty, or 0 if clear.
435 int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap
*bmap
)
439 down_write(&bmap
->b_sem
);
440 ret
= nilfs_bmap_dirty(bmap
);
441 nilfs_bmap_clear_dirty(bmap
);
442 up_write(&bmap
->b_sem
);
450 __u64
nilfs_bmap_data_get_key(const struct nilfs_bmap
*bmap
,
451 const struct buffer_head
*bh
)
453 loff_t pos
= folio_pos(bh
->b_folio
) + bh_offset(bh
);
455 return pos
>> bmap
->b_inode
->i_blkbits
;
458 __u64
nilfs_bmap_find_target_seq(const struct nilfs_bmap
*bmap
, __u64 key
)
462 diff
= key
- bmap
->b_last_allocated_key
;
463 if ((nilfs_bmap_keydiff_abs(diff
) < NILFS_INODE_BMAP_SIZE
) &&
464 (bmap
->b_last_allocated_ptr
!= NILFS_BMAP_INVALID_PTR
) &&
465 (bmap
->b_last_allocated_ptr
+ diff
> 0))
466 return bmap
->b_last_allocated_ptr
+ diff
;
468 return NILFS_BMAP_INVALID_PTR
;
471 #define NILFS_BMAP_GROUP_DIV 8
472 __u64
nilfs_bmap_find_target_in_group(const struct nilfs_bmap
*bmap
)
474 struct inode
*dat
= nilfs_bmap_get_dat(bmap
);
475 unsigned long entries_per_group
= nilfs_palloc_entries_per_group(dat
);
476 unsigned long group
= bmap
->b_inode
->i_ino
/ entries_per_group
;
478 return group
* entries_per_group
+
479 (bmap
->b_inode
->i_ino
% NILFS_BMAP_GROUP_DIV
) *
480 (entries_per_group
/ NILFS_BMAP_GROUP_DIV
);
483 static struct lock_class_key nilfs_bmap_dat_lock_key
;
484 static struct lock_class_key nilfs_bmap_mdt_lock_key
;
487 * nilfs_bmap_read - read a bmap from an inode
489 * @raw_inode: on-disk inode
491 * Description: nilfs_bmap_read() initializes the bmap @bmap.
493 * Return Value: On success, 0 is returned. On error, the following negative
494 * error code is returned.
496 * %-ENOMEM - Insufficient amount of memory available.
498 int nilfs_bmap_read(struct nilfs_bmap
*bmap
, struct nilfs_inode
*raw_inode
)
500 if (raw_inode
== NULL
)
501 memset(bmap
->b_u
.u_data
, 0, NILFS_BMAP_SIZE
);
503 memcpy(bmap
->b_u
.u_data
, raw_inode
->i_bmap
, NILFS_BMAP_SIZE
);
505 init_rwsem(&bmap
->b_sem
);
507 bmap
->b_inode
= &NILFS_BMAP_I(bmap
)->vfs_inode
;
508 switch (bmap
->b_inode
->i_ino
) {
510 bmap
->b_ptr_type
= NILFS_BMAP_PTR_P
;
511 bmap
->b_last_allocated_key
= 0;
512 bmap
->b_last_allocated_ptr
= NILFS_BMAP_NEW_PTR_INIT
;
513 lockdep_set_class(&bmap
->b_sem
, &nilfs_bmap_dat_lock_key
);
515 case NILFS_CPFILE_INO
:
516 case NILFS_SUFILE_INO
:
517 bmap
->b_ptr_type
= NILFS_BMAP_PTR_VS
;
518 bmap
->b_last_allocated_key
= 0;
519 bmap
->b_last_allocated_ptr
= NILFS_BMAP_INVALID_PTR
;
520 lockdep_set_class(&bmap
->b_sem
, &nilfs_bmap_mdt_lock_key
);
522 case NILFS_IFILE_INO
:
523 lockdep_set_class(&bmap
->b_sem
, &nilfs_bmap_mdt_lock_key
);
526 bmap
->b_ptr_type
= NILFS_BMAP_PTR_VM
;
527 bmap
->b_last_allocated_key
= 0;
528 bmap
->b_last_allocated_ptr
= NILFS_BMAP_INVALID_PTR
;
532 return (bmap
->b_u
.u_flags
& NILFS_BMAP_LARGE
) ?
533 nilfs_btree_init(bmap
) : nilfs_direct_init(bmap
);
537 * nilfs_bmap_write - write back a bmap to an inode
539 * @raw_inode: on-disk inode
541 * Description: nilfs_bmap_write() stores @bmap in @raw_inode.
543 void nilfs_bmap_write(struct nilfs_bmap
*bmap
, struct nilfs_inode
*raw_inode
)
545 memcpy(raw_inode
->i_bmap
, bmap
->b_u
.u_data
,
546 NILFS_INODE_BMAP_SIZE
* sizeof(__le64
));
547 if (bmap
->b_inode
->i_ino
== NILFS_DAT_INO
)
548 bmap
->b_last_allocated_ptr
= NILFS_BMAP_NEW_PTR_INIT
;
551 void nilfs_bmap_init_gc(struct nilfs_bmap
*bmap
)
553 memset(&bmap
->b_u
, 0, NILFS_BMAP_SIZE
);
554 init_rwsem(&bmap
->b_sem
);
555 bmap
->b_inode
= &NILFS_BMAP_I(bmap
)->vfs_inode
;
556 bmap
->b_ptr_type
= NILFS_BMAP_PTR_U
;
557 bmap
->b_last_allocated_key
= 0;
558 bmap
->b_last_allocated_ptr
= NILFS_BMAP_INVALID_PTR
;
560 nilfs_btree_init_gc(bmap
);
563 void nilfs_bmap_save(const struct nilfs_bmap
*bmap
,
564 struct nilfs_bmap_store
*store
)
566 memcpy(store
->data
, bmap
->b_u
.u_data
, sizeof(store
->data
));
567 store
->last_allocated_key
= bmap
->b_last_allocated_key
;
568 store
->last_allocated_ptr
= bmap
->b_last_allocated_ptr
;
569 store
->state
= bmap
->b_state
;
572 void nilfs_bmap_restore(struct nilfs_bmap
*bmap
,
573 const struct nilfs_bmap_store
*store
)
575 memcpy(bmap
->b_u
.u_data
, store
->data
, sizeof(store
->data
));
576 bmap
->b_last_allocated_key
= store
->last_allocated_key
;
577 bmap
->b_last_allocated_ptr
= store
->last_allocated_ptr
;
578 bmap
->b_state
= store
->state
;