bmap.c (14749B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * NILFS block mapping. 4 * 5 * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation. 6 * 7 * Written by Koji Sato. 8 */ 9 10#include <linux/fs.h> 11#include <linux/string.h> 12#include <linux/errno.h> 13#include "nilfs.h" 14#include "bmap.h" 15#include "btree.h" 16#include "direct.h" 17#include "btnode.h" 18#include "mdt.h" 19#include "dat.h" 20#include "alloc.h" 21 22struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap) 23{ 24 struct the_nilfs *nilfs = bmap->b_inode->i_sb->s_fs_info; 25 26 return nilfs->ns_dat; 27} 28 29static int nilfs_bmap_convert_error(struct nilfs_bmap *bmap, 30 const char *fname, int err) 31{ 32 struct inode *inode = bmap->b_inode; 33 34 if (err == -EINVAL) { 35 __nilfs_error(inode->i_sb, fname, 36 "broken bmap (inode number=%lu)", inode->i_ino); 37 err = -EIO; 38 } 39 return err; 40} 41 42/** 43 * nilfs_bmap_lookup_at_level - find a data block or node block 44 * @bmap: bmap 45 * @key: key 46 * @level: level 47 * @ptrp: place to store the value associated to @key 48 * 49 * Description: nilfs_bmap_lookup_at_level() finds a record whose key 50 * matches @key in the block at @level of the bmap. 51 * 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. 55 * 56 * %-EIO - I/O error. 57 * 58 * %-ENOMEM - Insufficient amount of memory available. 59 * 60 * %-ENOENT - A record associated with @key does not exist. 61 */ 62int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level, 63 __u64 *ptrp) 64{ 65 sector_t blocknr; 66 int ret; 67 68 down_read(&bmap->b_sem); 69 ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp); 70 if (ret < 0) { 71 ret = nilfs_bmap_convert_error(bmap, __func__, ret); 72 goto out; 73 } 74 if (NILFS_BMAP_USE_VBN(bmap)) { 75 ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp, 76 &blocknr); 77 if (!ret) 78 *ptrp = blocknr; 79 } 80 81 out: 82 up_read(&bmap->b_sem); 83 return ret; 84} 85 86int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp, 87 unsigned int maxblocks) 88{ 89 int ret; 90 91 down_read(&bmap->b_sem); 92 ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks); 93 up_read(&bmap->b_sem); 94 95 return nilfs_bmap_convert_error(bmap, __func__, ret); 96} 97 98static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) 99{ 100 __u64 keys[NILFS_BMAP_SMALL_HIGH + 1]; 101 __u64 ptrs[NILFS_BMAP_SMALL_HIGH + 1]; 102 int ret, n; 103 104 if (bmap->b_ops->bop_check_insert != NULL) { 105 ret = bmap->b_ops->bop_check_insert(bmap, key); 106 if (ret > 0) { 107 n = bmap->b_ops->bop_gather_data( 108 bmap, keys, ptrs, NILFS_BMAP_SMALL_HIGH + 1); 109 if (n < 0) 110 return n; 111 ret = nilfs_btree_convert_and_insert( 112 bmap, key, ptr, keys, ptrs, n); 113 if (ret == 0) 114 bmap->b_u.u_flags |= NILFS_BMAP_LARGE; 115 116 return ret; 117 } else if (ret < 0) 118 return ret; 119 } 120 121 return bmap->b_ops->bop_insert(bmap, key, ptr); 122} 123 124/** 125 * nilfs_bmap_insert - insert a new key-record pair into a bmap 126 * @bmap: bmap 127 * @key: key 128 * @rec: record 129 * 130 * Description: nilfs_bmap_insert() inserts the new key-record pair specified 131 * by @key and @rec into @bmap. 132 * 133 * Return Value: On success, 0 is returned. On error, one of the following 134 * negative error codes is returned. 135 * 136 * %-EIO - I/O error. 137 * 138 * %-ENOMEM - Insufficient amount of memory available. 139 * 140 * %-EEXIST - A record associated with @key already exist. 141 */ 142int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec) 143{ 144 int ret; 145 146 down_write(&bmap->b_sem); 147 ret = nilfs_bmap_do_insert(bmap, key, rec); 148 up_write(&bmap->b_sem); 149 150 return nilfs_bmap_convert_error(bmap, __func__, ret); 151} 152 153static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key) 154{ 155 __u64 keys[NILFS_BMAP_LARGE_LOW + 1]; 156 __u64 ptrs[NILFS_BMAP_LARGE_LOW + 1]; 157 int ret, n; 158 159 if (bmap->b_ops->bop_check_delete != NULL) { 160 ret = bmap->b_ops->bop_check_delete(bmap, key); 161 if (ret > 0) { 162 n = bmap->b_ops->bop_gather_data( 163 bmap, keys, ptrs, NILFS_BMAP_LARGE_LOW + 1); 164 if (n < 0) 165 return n; 166 ret = nilfs_direct_delete_and_convert( 167 bmap, key, keys, ptrs, n); 168 if (ret == 0) 169 bmap->b_u.u_flags &= ~NILFS_BMAP_LARGE; 170 171 return ret; 172 } else if (ret < 0) 173 return ret; 174 } 175 176 return bmap->b_ops->bop_delete(bmap, key); 177} 178 179/** 180 * nilfs_bmap_seek_key - seek a valid entry and return its key 181 * @bmap: bmap struct 182 * @start: start key number 183 * @keyp: place to store valid key 184 * 185 * Description: nilfs_bmap_seek_key() seeks a valid key on @bmap 186 * starting from @start, and stores it to @keyp if found. 187 * 188 * Return Value: On success, 0 is returned. On error, one of the following 189 * negative error codes is returned. 190 * 191 * %-EIO - I/O error. 192 * 193 * %-ENOMEM - Insufficient amount of memory available. 194 * 195 * %-ENOENT - No valid entry was found 196 */ 197int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp) 198{ 199 int ret; 200 201 down_read(&bmap->b_sem); 202 ret = bmap->b_ops->bop_seek_key(bmap, start, keyp); 203 up_read(&bmap->b_sem); 204 205 if (ret < 0) 206 ret = nilfs_bmap_convert_error(bmap, __func__, ret); 207 return ret; 208} 209 210int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp) 211{ 212 int ret; 213 214 down_read(&bmap->b_sem); 215 ret = bmap->b_ops->bop_last_key(bmap, keyp); 216 up_read(&bmap->b_sem); 217 218 if (ret < 0) 219 ret = nilfs_bmap_convert_error(bmap, __func__, ret); 220 return ret; 221} 222 223/** 224 * nilfs_bmap_delete - delete a key-record pair from a bmap 225 * @bmap: bmap 226 * @key: key 227 * 228 * Description: nilfs_bmap_delete() deletes the key-record pair specified by 229 * @key from @bmap. 230 * 231 * Return Value: On success, 0 is returned. On error, one of the following 232 * negative error codes is returned. 233 * 234 * %-EIO - I/O error. 235 * 236 * %-ENOMEM - Insufficient amount of memory available. 237 * 238 * %-ENOENT - A record associated with @key does not exist. 239 */ 240int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key) 241{ 242 int ret; 243 244 down_write(&bmap->b_sem); 245 ret = nilfs_bmap_do_delete(bmap, key); 246 up_write(&bmap->b_sem); 247 248 return nilfs_bmap_convert_error(bmap, __func__, ret); 249} 250 251static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, __u64 key) 252{ 253 __u64 lastkey; 254 int ret; 255 256 ret = bmap->b_ops->bop_last_key(bmap, &lastkey); 257 if (ret < 0) { 258 if (ret == -ENOENT) 259 ret = 0; 260 return ret; 261 } 262 263 while (key <= lastkey) { 264 ret = nilfs_bmap_do_delete(bmap, lastkey); 265 if (ret < 0) 266 return ret; 267 ret = bmap->b_ops->bop_last_key(bmap, &lastkey); 268 if (ret < 0) { 269 if (ret == -ENOENT) 270 ret = 0; 271 return ret; 272 } 273 } 274 return 0; 275} 276 277/** 278 * nilfs_bmap_truncate - truncate a bmap to a specified key 279 * @bmap: bmap 280 * @key: key 281 * 282 * Description: nilfs_bmap_truncate() removes key-record pairs whose keys are 283 * greater than or equal to @key from @bmap. 284 * 285 * Return Value: On success, 0 is returned. On error, one of the following 286 * negative error codes is returned. 287 * 288 * %-EIO - I/O error. 289 * 290 * %-ENOMEM - Insufficient amount of memory available. 291 */ 292int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key) 293{ 294 int ret; 295 296 down_write(&bmap->b_sem); 297 ret = nilfs_bmap_do_truncate(bmap, key); 298 up_write(&bmap->b_sem); 299 300 return nilfs_bmap_convert_error(bmap, __func__, ret); 301} 302 303/** 304 * nilfs_bmap_clear - free resources a bmap holds 305 * @bmap: bmap 306 * 307 * Description: nilfs_bmap_clear() frees resources associated with @bmap. 308 */ 309void nilfs_bmap_clear(struct nilfs_bmap *bmap) 310{ 311 down_write(&bmap->b_sem); 312 if (bmap->b_ops->bop_clear != NULL) 313 bmap->b_ops->bop_clear(bmap); 314 up_write(&bmap->b_sem); 315} 316 317/** 318 * nilfs_bmap_propagate - propagate dirty state 319 * @bmap: bmap 320 * @bh: buffer head 321 * 322 * Description: nilfs_bmap_propagate() marks the buffers that directly or 323 * indirectly refer to the block specified by @bh dirty. 324 * 325 * Return Value: On success, 0 is returned. On error, one of the following 326 * negative error codes is returned. 327 * 328 * %-EIO - I/O error. 329 * 330 * %-ENOMEM - Insufficient amount of memory available. 331 */ 332int nilfs_bmap_propagate(struct nilfs_bmap *bmap, struct buffer_head *bh) 333{ 334 int ret; 335 336 down_write(&bmap->b_sem); 337 ret = bmap->b_ops->bop_propagate(bmap, bh); 338 up_write(&bmap->b_sem); 339 340 return nilfs_bmap_convert_error(bmap, __func__, ret); 341} 342 343/** 344 * nilfs_bmap_lookup_dirty_buffers - 345 * @bmap: bmap 346 * @listp: pointer to buffer head list 347 */ 348void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *bmap, 349 struct list_head *listp) 350{ 351 if (bmap->b_ops->bop_lookup_dirty_buffers != NULL) 352 bmap->b_ops->bop_lookup_dirty_buffers(bmap, listp); 353} 354 355/** 356 * nilfs_bmap_assign - assign a new block number to a block 357 * @bmap: bmap 358 * @bh: pointer to buffer head 359 * @blocknr: block number 360 * @binfo: block information 361 * 362 * Description: nilfs_bmap_assign() assigns the block number @blocknr to the 363 * buffer specified by @bh. 364 * 365 * Return Value: On success, 0 is returned and the buffer head of a newly 366 * create buffer and the block information associated with the buffer are 367 * stored in the place pointed by @bh and @binfo, respectively. On error, one 368 * of the following negative error codes is returned. 369 * 370 * %-EIO - I/O error. 371 * 372 * %-ENOMEM - Insufficient amount of memory available. 373 */ 374int nilfs_bmap_assign(struct nilfs_bmap *bmap, 375 struct buffer_head **bh, 376 unsigned long blocknr, 377 union nilfs_binfo *binfo) 378{ 379 int ret; 380 381 down_write(&bmap->b_sem); 382 ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo); 383 up_write(&bmap->b_sem); 384 385 return nilfs_bmap_convert_error(bmap, __func__, ret); 386} 387 388/** 389 * nilfs_bmap_mark - mark block dirty 390 * @bmap: bmap 391 * @key: key 392 * @level: level 393 * 394 * Description: nilfs_bmap_mark() marks the block specified by @key and @level 395 * as dirty. 396 * 397 * Return Value: On success, 0 is returned. On error, one of the following 398 * negative error codes is returned. 399 * 400 * %-EIO - I/O error. 401 * 402 * %-ENOMEM - Insufficient amount of memory available. 403 */ 404int nilfs_bmap_mark(struct nilfs_bmap *bmap, __u64 key, int level) 405{ 406 int ret; 407 408 if (bmap->b_ops->bop_mark == NULL) 409 return 0; 410 411 down_write(&bmap->b_sem); 412 ret = bmap->b_ops->bop_mark(bmap, key, level); 413 up_write(&bmap->b_sem); 414 415 return nilfs_bmap_convert_error(bmap, __func__, ret); 416} 417 418/** 419 * nilfs_bmap_test_and_clear_dirty - test and clear a bmap dirty state 420 * @bmap: bmap 421 * 422 * Description: nilfs_test_and_clear() is the atomic operation to test and 423 * clear the dirty state of @bmap. 424 * 425 * Return Value: 1 is returned if @bmap is dirty, or 0 if clear. 426 */ 427int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap) 428{ 429 int ret; 430 431 down_write(&bmap->b_sem); 432 ret = nilfs_bmap_dirty(bmap); 433 nilfs_bmap_clear_dirty(bmap); 434 up_write(&bmap->b_sem); 435 return ret; 436} 437 438 439/* 440 * Internal use only 441 */ 442__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap, 443 const struct buffer_head *bh) 444{ 445 struct buffer_head *pbh; 446 __u64 key; 447 448 key = page_index(bh->b_page) << (PAGE_SHIFT - 449 bmap->b_inode->i_blkbits); 450 for (pbh = page_buffers(bh->b_page); pbh != bh; pbh = pbh->b_this_page) 451 key++; 452 453 return key; 454} 455 456__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *bmap, __u64 key) 457{ 458 __s64 diff; 459 460 diff = key - bmap->b_last_allocated_key; 461 if ((nilfs_bmap_keydiff_abs(diff) < NILFS_INODE_BMAP_SIZE) && 462 (bmap->b_last_allocated_ptr != NILFS_BMAP_INVALID_PTR) && 463 (bmap->b_last_allocated_ptr + diff > 0)) 464 return bmap->b_last_allocated_ptr + diff; 465 else 466 return NILFS_BMAP_INVALID_PTR; 467} 468 469#define NILFS_BMAP_GROUP_DIV 8 470__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap) 471{ 472 struct inode *dat = nilfs_bmap_get_dat(bmap); 473 unsigned long entries_per_group = nilfs_palloc_entries_per_group(dat); 474 unsigned long group = bmap->b_inode->i_ino / entries_per_group; 475 476 return group * entries_per_group + 477 (bmap->b_inode->i_ino % NILFS_BMAP_GROUP_DIV) * 478 (entries_per_group / NILFS_BMAP_GROUP_DIV); 479} 480 481static struct lock_class_key nilfs_bmap_dat_lock_key; 482static struct lock_class_key nilfs_bmap_mdt_lock_key; 483 484/** 485 * nilfs_bmap_read - read a bmap from an inode 486 * @bmap: bmap 487 * @raw_inode: on-disk inode 488 * 489 * Description: nilfs_bmap_read() initializes the bmap @bmap. 490 * 491 * Return Value: On success, 0 is returned. On error, the following negative 492 * error code is returned. 493 * 494 * %-ENOMEM - Insufficient amount of memory available. 495 */ 496int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode) 497{ 498 if (raw_inode == NULL) 499 memset(bmap->b_u.u_data, 0, NILFS_BMAP_SIZE); 500 else 501 memcpy(bmap->b_u.u_data, raw_inode->i_bmap, NILFS_BMAP_SIZE); 502 503 init_rwsem(&bmap->b_sem); 504 bmap->b_state = 0; 505 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; 506 switch (bmap->b_inode->i_ino) { 507 case NILFS_DAT_INO: 508 bmap->b_ptr_type = NILFS_BMAP_PTR_P; 509 bmap->b_last_allocated_key = 0; 510 bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT; 511 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); 512 break; 513 case NILFS_CPFILE_INO: 514 case NILFS_SUFILE_INO: 515 bmap->b_ptr_type = NILFS_BMAP_PTR_VS; 516 bmap->b_last_allocated_key = 0; 517 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR; 518 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key); 519 break; 520 case NILFS_IFILE_INO: 521 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key); 522 fallthrough; 523 default: 524 bmap->b_ptr_type = NILFS_BMAP_PTR_VM; 525 bmap->b_last_allocated_key = 0; 526 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR; 527 break; 528 } 529 530 return (bmap->b_u.u_flags & NILFS_BMAP_LARGE) ? 531 nilfs_btree_init(bmap) : nilfs_direct_init(bmap); 532} 533 534/** 535 * nilfs_bmap_write - write back a bmap to an inode 536 * @bmap: bmap 537 * @raw_inode: on-disk inode 538 * 539 * Description: nilfs_bmap_write() stores @bmap in @raw_inode. 540 */ 541void nilfs_bmap_write(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode) 542{ 543 down_write(&bmap->b_sem); 544 memcpy(raw_inode->i_bmap, bmap->b_u.u_data, 545 NILFS_INODE_BMAP_SIZE * sizeof(__le64)); 546 if (bmap->b_inode->i_ino == NILFS_DAT_INO) 547 bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT; 548 549 up_write(&bmap->b_sem); 550} 551 552void nilfs_bmap_init_gc(struct nilfs_bmap *bmap) 553{ 554 memset(&bmap->b_u, 0, NILFS_BMAP_SIZE); 555 init_rwsem(&bmap->b_sem); 556 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; 557 bmap->b_ptr_type = NILFS_BMAP_PTR_U; 558 bmap->b_last_allocated_key = 0; 559 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR; 560 bmap->b_state = 0; 561 nilfs_btree_init_gc(bmap); 562} 563 564void nilfs_bmap_save(const struct nilfs_bmap *bmap, 565 struct nilfs_bmap_store *store) 566{ 567 memcpy(store->data, bmap->b_u.u_data, sizeof(store->data)); 568 store->last_allocated_key = bmap->b_last_allocated_key; 569 store->last_allocated_ptr = bmap->b_last_allocated_ptr; 570 store->state = bmap->b_state; 571} 572 573void nilfs_bmap_restore(struct nilfs_bmap *bmap, 574 const struct nilfs_bmap_store *store) 575{ 576 memcpy(bmap->b_u.u_data, store->data, sizeof(store->data)); 577 bmap->b_last_allocated_key = store->last_allocated_key; 578 bmap->b_last_allocated_ptr = store->last_allocated_ptr; 579 bmap->b_state = store->state; 580}