linux/fs/nilfs2/bmap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * bmap.c - 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}
 581