linux/fs/btrfs/file-item.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2007 Oracle.  All rights reserved.
   4 */
   5
   6#include <linux/bio.h>
   7#include <linux/slab.h>
   8#include <linux/pagemap.h>
   9#include <linux/highmem.h>
  10#include "ctree.h"
  11#include "disk-io.h"
  12#include "transaction.h"
  13#include "volumes.h"
  14#include "print-tree.h"
  15#include "compression.h"
  16
  17#define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \
  18                                   sizeof(struct btrfs_item) * 2) / \
  19                                  size) - 1))
  20
  21#define MAX_CSUM_ITEMS(r, size) (min_t(u32, __MAX_CSUM_ITEMS(r, size), \
  22                                       PAGE_SIZE))
  23
  24#define MAX_ORDERED_SUM_BYTES(fs_info) ((PAGE_SIZE - \
  25                                   sizeof(struct btrfs_ordered_sum)) / \
  26                                   sizeof(u32) * (fs_info)->sectorsize)
  27
  28int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
  29                             struct btrfs_root *root,
  30                             u64 objectid, u64 pos,
  31                             u64 disk_offset, u64 disk_num_bytes,
  32                             u64 num_bytes, u64 offset, u64 ram_bytes,
  33                             u8 compression, u8 encryption, u16 other_encoding)
  34{
  35        int ret = 0;
  36        struct btrfs_file_extent_item *item;
  37        struct btrfs_key file_key;
  38        struct btrfs_path *path;
  39        struct extent_buffer *leaf;
  40
  41        path = btrfs_alloc_path();
  42        if (!path)
  43                return -ENOMEM;
  44        file_key.objectid = objectid;
  45        file_key.offset = pos;
  46        file_key.type = BTRFS_EXTENT_DATA_KEY;
  47
  48        path->leave_spinning = 1;
  49        ret = btrfs_insert_empty_item(trans, root, path, &file_key,
  50                                      sizeof(*item));
  51        if (ret < 0)
  52                goto out;
  53        BUG_ON(ret); /* Can't happen */
  54        leaf = path->nodes[0];
  55        item = btrfs_item_ptr(leaf, path->slots[0],
  56                              struct btrfs_file_extent_item);
  57        btrfs_set_file_extent_disk_bytenr(leaf, item, disk_offset);
  58        btrfs_set_file_extent_disk_num_bytes(leaf, item, disk_num_bytes);
  59        btrfs_set_file_extent_offset(leaf, item, offset);
  60        btrfs_set_file_extent_num_bytes(leaf, item, num_bytes);
  61        btrfs_set_file_extent_ram_bytes(leaf, item, ram_bytes);
  62        btrfs_set_file_extent_generation(leaf, item, trans->transid);
  63        btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG);
  64        btrfs_set_file_extent_compression(leaf, item, compression);
  65        btrfs_set_file_extent_encryption(leaf, item, encryption);
  66        btrfs_set_file_extent_other_encoding(leaf, item, other_encoding);
  67
  68        btrfs_mark_buffer_dirty(leaf);
  69out:
  70        btrfs_free_path(path);
  71        return ret;
  72}
  73
  74static struct btrfs_csum_item *
  75btrfs_lookup_csum(struct btrfs_trans_handle *trans,
  76                  struct btrfs_root *root,
  77                  struct btrfs_path *path,
  78                  u64 bytenr, int cow)
  79{
  80        struct btrfs_fs_info *fs_info = root->fs_info;
  81        int ret;
  82        struct btrfs_key file_key;
  83        struct btrfs_key found_key;
  84        struct btrfs_csum_item *item;
  85        struct extent_buffer *leaf;
  86        u64 csum_offset = 0;
  87        u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
  88        int csums_in_item;
  89
  90        file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
  91        file_key.offset = bytenr;
  92        file_key.type = BTRFS_EXTENT_CSUM_KEY;
  93        ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
  94        if (ret < 0)
  95                goto fail;
  96        leaf = path->nodes[0];
  97        if (ret > 0) {
  98                ret = 1;
  99                if (path->slots[0] == 0)
 100                        goto fail;
 101                path->slots[0]--;
 102                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 103                if (found_key.type != BTRFS_EXTENT_CSUM_KEY)
 104                        goto fail;
 105
 106                csum_offset = (bytenr - found_key.offset) >>
 107                                fs_info->sb->s_blocksize_bits;
 108                csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]);
 109                csums_in_item /= csum_size;
 110
 111                if (csum_offset == csums_in_item) {
 112                        ret = -EFBIG;
 113                        goto fail;
 114                } else if (csum_offset > csums_in_item) {
 115                        goto fail;
 116                }
 117        }
 118        item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
 119        item = (struct btrfs_csum_item *)((unsigned char *)item +
 120                                          csum_offset * csum_size);
 121        return item;
 122fail:
 123        if (ret > 0)
 124                ret = -ENOENT;
 125        return ERR_PTR(ret);
 126}
 127
 128int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
 129                             struct btrfs_root *root,
 130                             struct btrfs_path *path, u64 objectid,
 131                             u64 offset, int mod)
 132{
 133        int ret;
 134        struct btrfs_key file_key;
 135        int ins_len = mod < 0 ? -1 : 0;
 136        int cow = mod != 0;
 137
 138        file_key.objectid = objectid;
 139        file_key.offset = offset;
 140        file_key.type = BTRFS_EXTENT_DATA_KEY;
 141        ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
 142        return ret;
 143}
 144
 145static void btrfs_io_bio_endio_readpage(struct btrfs_io_bio *bio, int err)
 146{
 147        kfree(bio->csum_allocated);
 148}
 149
 150static blk_status_t __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
 151                                   u64 logical_offset, u32 *dst, int dio)
 152{
 153        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
 154        struct bio_vec bvec;
 155        struct bvec_iter iter;
 156        struct btrfs_io_bio *btrfs_bio = btrfs_io_bio(bio);
 157        struct btrfs_csum_item *item = NULL;
 158        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
 159        struct btrfs_path *path;
 160        u8 *csum;
 161        u64 offset = 0;
 162        u64 item_start_offset = 0;
 163        u64 item_last_offset = 0;
 164        u64 disk_bytenr;
 165        u64 page_bytes_left;
 166        u32 diff;
 167        int nblocks;
 168        int count = 0;
 169        u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
 170
 171        path = btrfs_alloc_path();
 172        if (!path)
 173                return BLK_STS_RESOURCE;
 174
 175        nblocks = bio->bi_iter.bi_size >> inode->i_sb->s_blocksize_bits;
 176        if (!dst) {
 177                if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
 178                        btrfs_bio->csum_allocated = kmalloc_array(nblocks,
 179                                        csum_size, GFP_NOFS);
 180                        if (!btrfs_bio->csum_allocated) {
 181                                btrfs_free_path(path);
 182                                return BLK_STS_RESOURCE;
 183                        }
 184                        btrfs_bio->csum = btrfs_bio->csum_allocated;
 185                        btrfs_bio->end_io = btrfs_io_bio_endio_readpage;
 186                } else {
 187                        btrfs_bio->csum = btrfs_bio->csum_inline;
 188                }
 189                csum = btrfs_bio->csum;
 190        } else {
 191                csum = (u8 *)dst;
 192        }
 193
 194        if (bio->bi_iter.bi_size > PAGE_SIZE * 8)
 195                path->reada = READA_FORWARD;
 196
 197        /*
 198         * the free space stuff is only read when it hasn't been
 199         * updated in the current transaction.  So, we can safely
 200         * read from the commit root and sidestep a nasty deadlock
 201         * between reading the free space cache and updating the csum tree.
 202         */
 203        if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
 204                path->search_commit_root = 1;
 205                path->skip_locking = 1;
 206        }
 207
 208        disk_bytenr = (u64)bio->bi_iter.bi_sector << 9;
 209        if (dio)
 210                offset = logical_offset;
 211
 212        bio_for_each_segment(bvec, bio, iter) {
 213                page_bytes_left = bvec.bv_len;
 214                if (count)
 215                        goto next;
 216
 217                if (!dio)
 218                        offset = page_offset(bvec.bv_page) + bvec.bv_offset;
 219                count = btrfs_find_ordered_sum(inode, offset, disk_bytenr,
 220                                               (u32 *)csum, nblocks);
 221                if (count)
 222                        goto found;
 223
 224                if (!item || disk_bytenr < item_start_offset ||
 225                    disk_bytenr >= item_last_offset) {
 226                        struct btrfs_key found_key;
 227                        u32 item_size;
 228
 229                        if (item)
 230                                btrfs_release_path(path);
 231                        item = btrfs_lookup_csum(NULL, fs_info->csum_root,
 232                                                 path, disk_bytenr, 0);
 233                        if (IS_ERR(item)) {
 234                                count = 1;
 235                                memset(csum, 0, csum_size);
 236                                if (BTRFS_I(inode)->root->root_key.objectid ==
 237                                    BTRFS_DATA_RELOC_TREE_OBJECTID) {
 238                                        set_extent_bits(io_tree, offset,
 239                                                offset + fs_info->sectorsize - 1,
 240                                                EXTENT_NODATASUM);
 241                                } else {
 242                                        btrfs_info_rl(fs_info,
 243                                                   "no csum found for inode %llu start %llu",
 244                                               btrfs_ino(BTRFS_I(inode)), offset);
 245                                }
 246                                item = NULL;
 247                                btrfs_release_path(path);
 248                                goto found;
 249                        }
 250                        btrfs_item_key_to_cpu(path->nodes[0], &found_key,
 251                                              path->slots[0]);
 252
 253                        item_start_offset = found_key.offset;
 254                        item_size = btrfs_item_size_nr(path->nodes[0],
 255                                                       path->slots[0]);
 256                        item_last_offset = item_start_offset +
 257                                (item_size / csum_size) *
 258                                fs_info->sectorsize;
 259                        item = btrfs_item_ptr(path->nodes[0], path->slots[0],
 260                                              struct btrfs_csum_item);
 261                }
 262                /*
 263                 * this byte range must be able to fit inside
 264                 * a single leaf so it will also fit inside a u32
 265                 */
 266                diff = disk_bytenr - item_start_offset;
 267                diff = diff / fs_info->sectorsize;
 268                diff = diff * csum_size;
 269                count = min_t(int, nblocks, (item_last_offset - disk_bytenr) >>
 270                                            inode->i_sb->s_blocksize_bits);
 271                read_extent_buffer(path->nodes[0], csum,
 272                                   ((unsigned long)item) + diff,
 273                                   csum_size * count);
 274found:
 275                csum += count * csum_size;
 276                nblocks -= count;
 277next:
 278                while (count--) {
 279                        disk_bytenr += fs_info->sectorsize;
 280                        offset += fs_info->sectorsize;
 281                        page_bytes_left -= fs_info->sectorsize;
 282                        if (!page_bytes_left)
 283                                break; /* move to next bio */
 284                }
 285        }
 286
 287        WARN_ON_ONCE(count);
 288        btrfs_free_path(path);
 289        return 0;
 290}
 291
 292blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u32 *dst)
 293{
 294        return __btrfs_lookup_bio_sums(inode, bio, 0, dst, 0);
 295}
 296
 297blk_status_t btrfs_lookup_bio_sums_dio(struct inode *inode, struct bio *bio, u64 offset)
 298{
 299        return __btrfs_lookup_bio_sums(inode, bio, offset, NULL, 1);
 300}
 301
 302int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
 303                             struct list_head *list, int search_commit)
 304{
 305        struct btrfs_fs_info *fs_info = root->fs_info;
 306        struct btrfs_key key;
 307        struct btrfs_path *path;
 308        struct extent_buffer *leaf;
 309        struct btrfs_ordered_sum *sums;
 310        struct btrfs_csum_item *item;
 311        LIST_HEAD(tmplist);
 312        unsigned long offset;
 313        int ret;
 314        size_t size;
 315        u64 csum_end;
 316        u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
 317
 318        ASSERT(IS_ALIGNED(start, fs_info->sectorsize) &&
 319               IS_ALIGNED(end + 1, fs_info->sectorsize));
 320
 321        path = btrfs_alloc_path();
 322        if (!path)
 323                return -ENOMEM;
 324
 325        if (search_commit) {
 326                path->skip_locking = 1;
 327                path->reada = READA_FORWARD;
 328                path->search_commit_root = 1;
 329        }
 330
 331        key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
 332        key.offset = start;
 333        key.type = BTRFS_EXTENT_CSUM_KEY;
 334
 335        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 336        if (ret < 0)
 337                goto fail;
 338        if (ret > 0 && path->slots[0] > 0) {
 339                leaf = path->nodes[0];
 340                btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
 341                if (key.objectid == BTRFS_EXTENT_CSUM_OBJECTID &&
 342                    key.type == BTRFS_EXTENT_CSUM_KEY) {
 343                        offset = (start - key.offset) >>
 344                                 fs_info->sb->s_blocksize_bits;
 345                        if (offset * csum_size <
 346                            btrfs_item_size_nr(leaf, path->slots[0] - 1))
 347                                path->slots[0]--;
 348                }
 349        }
 350
 351        while (start <= end) {
 352                leaf = path->nodes[0];
 353                if (path->slots[0] >= btrfs_header_nritems(leaf)) {
 354                        ret = btrfs_next_leaf(root, path);
 355                        if (ret < 0)
 356                                goto fail;
 357                        if (ret > 0)
 358                                break;
 359                        leaf = path->nodes[0];
 360                }
 361
 362                btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
 363                if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
 364                    key.type != BTRFS_EXTENT_CSUM_KEY ||
 365                    key.offset > end)
 366                        break;
 367
 368                if (key.offset > start)
 369                        start = key.offset;
 370
 371                size = btrfs_item_size_nr(leaf, path->slots[0]);
 372                csum_end = key.offset + (size / csum_size) * fs_info->sectorsize;
 373                if (csum_end <= start) {
 374                        path->slots[0]++;
 375                        continue;
 376                }
 377
 378                csum_end = min(csum_end, end + 1);
 379                item = btrfs_item_ptr(path->nodes[0], path->slots[0],
 380                                      struct btrfs_csum_item);
 381                while (start < csum_end) {
 382                        size = min_t(size_t, csum_end - start,
 383                                     MAX_ORDERED_SUM_BYTES(fs_info));
 384                        sums = kzalloc(btrfs_ordered_sum_size(fs_info, size),
 385                                       GFP_NOFS);
 386                        if (!sums) {
 387                                ret = -ENOMEM;
 388                                goto fail;
 389                        }
 390
 391                        sums->bytenr = start;
 392                        sums->len = (int)size;
 393
 394                        offset = (start - key.offset) >>
 395                                fs_info->sb->s_blocksize_bits;
 396                        offset *= csum_size;
 397                        size >>= fs_info->sb->s_blocksize_bits;
 398
 399                        read_extent_buffer(path->nodes[0],
 400                                           sums->sums,
 401                                           ((unsigned long)item) + offset,
 402                                           csum_size * size);
 403
 404                        start += fs_info->sectorsize * size;
 405                        list_add_tail(&sums->list, &tmplist);
 406                }
 407                path->slots[0]++;
 408        }
 409        ret = 0;
 410fail:
 411        while (ret < 0 && !list_empty(&tmplist)) {
 412                sums = list_entry(tmplist.next, struct btrfs_ordered_sum, list);
 413                list_del(&sums->list);
 414                kfree(sums);
 415        }
 416        list_splice_tail(&tmplist, list);
 417
 418        btrfs_free_path(path);
 419        return ret;
 420}
 421
 422blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
 423                       u64 file_start, int contig)
 424{
 425        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
 426        struct btrfs_ordered_sum *sums;
 427        struct btrfs_ordered_extent *ordered = NULL;
 428        char *data;
 429        struct bvec_iter iter;
 430        struct bio_vec bvec;
 431        int index;
 432        int nr_sectors;
 433        unsigned long total_bytes = 0;
 434        unsigned long this_sum_bytes = 0;
 435        int i;
 436        u64 offset;
 437
 438        sums = kzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size),
 439                       GFP_NOFS);
 440        if (!sums)
 441                return BLK_STS_RESOURCE;
 442
 443        sums->len = bio->bi_iter.bi_size;
 444        INIT_LIST_HEAD(&sums->list);
 445
 446        if (contig)
 447                offset = file_start;
 448        else
 449                offset = 0; /* shut up gcc */
 450
 451        sums->bytenr = (u64)bio->bi_iter.bi_sector << 9;
 452        index = 0;
 453
 454        bio_for_each_segment(bvec, bio, iter) {
 455                if (!contig)
 456                        offset = page_offset(bvec.bv_page) + bvec.bv_offset;
 457
 458                if (!ordered) {
 459                        ordered = btrfs_lookup_ordered_extent(inode, offset);
 460                        BUG_ON(!ordered); /* Logic error */
 461                }
 462
 463                data = kmap_atomic(bvec.bv_page);
 464
 465                nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info,
 466                                                 bvec.bv_len + fs_info->sectorsize
 467                                                 - 1);
 468
 469                for (i = 0; i < nr_sectors; i++) {
 470                        if (offset >= ordered->file_offset + ordered->len ||
 471                                offset < ordered->file_offset) {
 472                                unsigned long bytes_left;
 473
 474                                kunmap_atomic(data);
 475                                sums->len = this_sum_bytes;
 476                                this_sum_bytes = 0;
 477                                btrfs_add_ordered_sum(inode, ordered, sums);
 478                                btrfs_put_ordered_extent(ordered);
 479
 480                                bytes_left = bio->bi_iter.bi_size - total_bytes;
 481
 482                                sums = kzalloc(btrfs_ordered_sum_size(fs_info, bytes_left),
 483                                               GFP_NOFS);
 484                                BUG_ON(!sums); /* -ENOMEM */
 485                                sums->len = bytes_left;
 486                                ordered = btrfs_lookup_ordered_extent(inode,
 487                                                                offset);
 488                                ASSERT(ordered); /* Logic error */
 489                                sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9)
 490                                        + total_bytes;
 491                                index = 0;
 492
 493                                data = kmap_atomic(bvec.bv_page);
 494                        }
 495
 496                        sums->sums[index] = ~(u32)0;
 497                        sums->sums[index]
 498                                = btrfs_csum_data(data + bvec.bv_offset
 499                                                + (i * fs_info->sectorsize),
 500                                                sums->sums[index],
 501                                                fs_info->sectorsize);
 502                        btrfs_csum_final(sums->sums[index],
 503                                        (char *)(sums->sums + index));
 504                        index++;
 505                        offset += fs_info->sectorsize;
 506                        this_sum_bytes += fs_info->sectorsize;
 507                        total_bytes += fs_info->sectorsize;
 508                }
 509
 510                kunmap_atomic(data);
 511        }
 512        this_sum_bytes = 0;
 513        btrfs_add_ordered_sum(inode, ordered, sums);
 514        btrfs_put_ordered_extent(ordered);
 515        return 0;
 516}
 517
 518/*
 519 * helper function for csum removal, this expects the
 520 * key to describe the csum pointed to by the path, and it expects
 521 * the csum to overlap the range [bytenr, len]
 522 *
 523 * The csum should not be entirely contained in the range and the
 524 * range should not be entirely contained in the csum.
 525 *
 526 * This calls btrfs_truncate_item with the correct args based on the
 527 * overlap, and fixes up the key as required.
 528 */
 529static noinline void truncate_one_csum(struct btrfs_fs_info *fs_info,
 530                                       struct btrfs_path *path,
 531                                       struct btrfs_key *key,
 532                                       u64 bytenr, u64 len)
 533{
 534        struct extent_buffer *leaf;
 535        u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
 536        u64 csum_end;
 537        u64 end_byte = bytenr + len;
 538        u32 blocksize_bits = fs_info->sb->s_blocksize_bits;
 539
 540        leaf = path->nodes[0];
 541        csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
 542        csum_end <<= fs_info->sb->s_blocksize_bits;
 543        csum_end += key->offset;
 544
 545        if (key->offset < bytenr && csum_end <= end_byte) {
 546                /*
 547                 *         [ bytenr - len ]
 548                 *         [   ]
 549                 *   [csum     ]
 550                 *   A simple truncate off the end of the item
 551                 */
 552                u32 new_size = (bytenr - key->offset) >> blocksize_bits;
 553                new_size *= csum_size;
 554                btrfs_truncate_item(fs_info, path, new_size, 1);
 555        } else if (key->offset >= bytenr && csum_end > end_byte &&
 556                   end_byte > key->offset) {
 557                /*
 558                 *         [ bytenr - len ]
 559                 *                 [ ]
 560                 *                 [csum     ]
 561                 * we need to truncate from the beginning of the csum
 562                 */
 563                u32 new_size = (csum_end - end_byte) >> blocksize_bits;
 564                new_size *= csum_size;
 565
 566                btrfs_truncate_item(fs_info, path, new_size, 0);
 567
 568                key->offset = end_byte;
 569                btrfs_set_item_key_safe(fs_info, path, key);
 570        } else {
 571                BUG();
 572        }
 573}
 574
 575/*
 576 * deletes the csum items from the csum tree for a given
 577 * range of bytes.
 578 */
 579int btrfs_del_csums(struct btrfs_trans_handle *trans,
 580                    struct btrfs_fs_info *fs_info, u64 bytenr, u64 len)
 581{
 582        struct btrfs_root *root = fs_info->csum_root;
 583        struct btrfs_path *path;
 584        struct btrfs_key key;
 585        u64 end_byte = bytenr + len;
 586        u64 csum_end;
 587        struct extent_buffer *leaf;
 588        int ret;
 589        u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
 590        int blocksize_bits = fs_info->sb->s_blocksize_bits;
 591
 592        path = btrfs_alloc_path();
 593        if (!path)
 594                return -ENOMEM;
 595
 596        while (1) {
 597                key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
 598                key.offset = end_byte - 1;
 599                key.type = BTRFS_EXTENT_CSUM_KEY;
 600
 601                path->leave_spinning = 1;
 602                ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
 603                if (ret > 0) {
 604                        if (path->slots[0] == 0)
 605                                break;
 606                        path->slots[0]--;
 607                } else if (ret < 0) {
 608                        break;
 609                }
 610
 611                leaf = path->nodes[0];
 612                btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
 613
 614                if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
 615                    key.type != BTRFS_EXTENT_CSUM_KEY) {
 616                        break;
 617                }
 618
 619                if (key.offset >= end_byte)
 620                        break;
 621
 622                csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
 623                csum_end <<= blocksize_bits;
 624                csum_end += key.offset;
 625
 626                /* this csum ends before we start, we're done */
 627                if (csum_end <= bytenr)
 628                        break;
 629
 630                /* delete the entire item, it is inside our range */
 631                if (key.offset >= bytenr && csum_end <= end_byte) {
 632                        int del_nr = 1;
 633
 634                        /*
 635                         * Check how many csum items preceding this one in this
 636                         * leaf correspond to our range and then delete them all
 637                         * at once.
 638                         */
 639                        if (key.offset > bytenr && path->slots[0] > 0) {
 640                                int slot = path->slots[0] - 1;
 641
 642                                while (slot >= 0) {
 643                                        struct btrfs_key pk;
 644
 645                                        btrfs_item_key_to_cpu(leaf, &pk, slot);
 646                                        if (pk.offset < bytenr ||
 647                                            pk.type != BTRFS_EXTENT_CSUM_KEY ||
 648                                            pk.objectid !=
 649                                            BTRFS_EXTENT_CSUM_OBJECTID)
 650                                                break;
 651                                        path->slots[0] = slot;
 652                                        del_nr++;
 653                                        key.offset = pk.offset;
 654                                        slot--;
 655                                }
 656                        }
 657                        ret = btrfs_del_items(trans, root, path,
 658                                              path->slots[0], del_nr);
 659                        if (ret)
 660                                goto out;
 661                        if (key.offset == bytenr)
 662                                break;
 663                } else if (key.offset < bytenr && csum_end > end_byte) {
 664                        unsigned long offset;
 665                        unsigned long shift_len;
 666                        unsigned long item_offset;
 667                        /*
 668                         *        [ bytenr - len ]
 669                         *     [csum                ]
 670                         *
 671                         * Our bytes are in the middle of the csum,
 672                         * we need to split this item and insert a new one.
 673                         *
 674                         * But we can't drop the path because the
 675                         * csum could change, get removed, extended etc.
 676                         *
 677                         * The trick here is the max size of a csum item leaves
 678                         * enough room in the tree block for a single
 679                         * item header.  So, we split the item in place,
 680                         * adding a new header pointing to the existing
 681                         * bytes.  Then we loop around again and we have
 682                         * a nicely formed csum item that we can neatly
 683                         * truncate.
 684                         */
 685                        offset = (bytenr - key.offset) >> blocksize_bits;
 686                        offset *= csum_size;
 687
 688                        shift_len = (len >> blocksize_bits) * csum_size;
 689
 690                        item_offset = btrfs_item_ptr_offset(leaf,
 691                                                            path->slots[0]);
 692
 693                        memzero_extent_buffer(leaf, item_offset + offset,
 694                                             shift_len);
 695                        key.offset = bytenr;
 696
 697                        /*
 698                         * btrfs_split_item returns -EAGAIN when the
 699                         * item changed size or key
 700                         */
 701                        ret = btrfs_split_item(trans, root, path, &key, offset);
 702                        if (ret && ret != -EAGAIN) {
 703                                btrfs_abort_transaction(trans, ret);
 704                                goto out;
 705                        }
 706
 707                        key.offset = end_byte - 1;
 708                } else {
 709                        truncate_one_csum(fs_info, path, &key, bytenr, len);
 710                        if (key.offset < bytenr)
 711                                break;
 712                }
 713                btrfs_release_path(path);
 714        }
 715        ret = 0;
 716out:
 717        btrfs_free_path(path);
 718        return ret;
 719}
 720
 721int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
 722                           struct btrfs_root *root,
 723                           struct btrfs_ordered_sum *sums)
 724{
 725        struct btrfs_fs_info *fs_info = root->fs_info;
 726        struct btrfs_key file_key;
 727        struct btrfs_key found_key;
 728        struct btrfs_path *path;
 729        struct btrfs_csum_item *item;
 730        struct btrfs_csum_item *item_end;
 731        struct extent_buffer *leaf = NULL;
 732        u64 next_offset;
 733        u64 total_bytes = 0;
 734        u64 csum_offset;
 735        u64 bytenr;
 736        u32 nritems;
 737        u32 ins_size;
 738        int index = 0;
 739        int found_next;
 740        int ret;
 741        u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
 742
 743        path = btrfs_alloc_path();
 744        if (!path)
 745                return -ENOMEM;
 746again:
 747        next_offset = (u64)-1;
 748        found_next = 0;
 749        bytenr = sums->bytenr + total_bytes;
 750        file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
 751        file_key.offset = bytenr;
 752        file_key.type = BTRFS_EXTENT_CSUM_KEY;
 753
 754        item = btrfs_lookup_csum(trans, root, path, bytenr, 1);
 755        if (!IS_ERR(item)) {
 756                ret = 0;
 757                leaf = path->nodes[0];
 758                item_end = btrfs_item_ptr(leaf, path->slots[0],
 759                                          struct btrfs_csum_item);
 760                item_end = (struct btrfs_csum_item *)((char *)item_end +
 761                           btrfs_item_size_nr(leaf, path->slots[0]));
 762                goto found;
 763        }
 764        ret = PTR_ERR(item);
 765        if (ret != -EFBIG && ret != -ENOENT)
 766                goto fail_unlock;
 767
 768        if (ret == -EFBIG) {
 769                u32 item_size;
 770                /* we found one, but it isn't big enough yet */
 771                leaf = path->nodes[0];
 772                item_size = btrfs_item_size_nr(leaf, path->slots[0]);
 773                if ((item_size / csum_size) >=
 774                    MAX_CSUM_ITEMS(fs_info, csum_size)) {
 775                        /* already at max size, make a new one */
 776                        goto insert;
 777                }
 778        } else {
 779                int slot = path->slots[0] + 1;
 780                /* we didn't find a csum item, insert one */
 781                nritems = btrfs_header_nritems(path->nodes[0]);
 782                if (!nritems || (path->slots[0] >= nritems - 1)) {
 783                        ret = btrfs_next_leaf(root, path);
 784                        if (ret == 1)
 785                                found_next = 1;
 786                        if (ret != 0)
 787                                goto insert;
 788                        slot = path->slots[0];
 789                }
 790                btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot);
 791                if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
 792                    found_key.type != BTRFS_EXTENT_CSUM_KEY) {
 793                        found_next = 1;
 794                        goto insert;
 795                }
 796                next_offset = found_key.offset;
 797                found_next = 1;
 798                goto insert;
 799        }
 800
 801        /*
 802         * at this point, we know the tree has an item, but it isn't big
 803         * enough yet to put our csum in.  Grow it
 804         */
 805        btrfs_release_path(path);
 806        ret = btrfs_search_slot(trans, root, &file_key, path,
 807                                csum_size, 1);
 808        if (ret < 0)
 809                goto fail_unlock;
 810
 811        if (ret > 0) {
 812                if (path->slots[0] == 0)
 813                        goto insert;
 814                path->slots[0]--;
 815        }
 816
 817        leaf = path->nodes[0];
 818        btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 819        csum_offset = (bytenr - found_key.offset) >>
 820                        fs_info->sb->s_blocksize_bits;
 821
 822        if (found_key.type != BTRFS_EXTENT_CSUM_KEY ||
 823            found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
 824            csum_offset >= MAX_CSUM_ITEMS(fs_info, csum_size)) {
 825                goto insert;
 826        }
 827
 828        if (csum_offset == btrfs_item_size_nr(leaf, path->slots[0]) /
 829            csum_size) {
 830                int extend_nr;
 831                u64 tmp;
 832                u32 diff;
 833                u32 free_space;
 834
 835                if (btrfs_leaf_free_space(fs_info, leaf) <
 836                                 sizeof(struct btrfs_item) + csum_size * 2)
 837                        goto insert;
 838
 839                free_space = btrfs_leaf_free_space(fs_info, leaf) -
 840                                         sizeof(struct btrfs_item) - csum_size;
 841                tmp = sums->len - total_bytes;
 842                tmp >>= fs_info->sb->s_blocksize_bits;
 843                WARN_ON(tmp < 1);
 844
 845                extend_nr = max_t(int, 1, (int)tmp);
 846                diff = (csum_offset + extend_nr) * csum_size;
 847                diff = min(diff,
 848                           MAX_CSUM_ITEMS(fs_info, csum_size) * csum_size);
 849
 850                diff = diff - btrfs_item_size_nr(leaf, path->slots[0]);
 851                diff = min(free_space, diff);
 852                diff /= csum_size;
 853                diff *= csum_size;
 854
 855                btrfs_extend_item(fs_info, path, diff);
 856                ret = 0;
 857                goto csum;
 858        }
 859
 860insert:
 861        btrfs_release_path(path);
 862        csum_offset = 0;
 863        if (found_next) {
 864                u64 tmp;
 865
 866                tmp = sums->len - total_bytes;
 867                tmp >>= fs_info->sb->s_blocksize_bits;
 868                tmp = min(tmp, (next_offset - file_key.offset) >>
 869                                         fs_info->sb->s_blocksize_bits);
 870
 871                tmp = max_t(u64, 1, tmp);
 872                tmp = min_t(u64, tmp, MAX_CSUM_ITEMS(fs_info, csum_size));
 873                ins_size = csum_size * tmp;
 874        } else {
 875                ins_size = csum_size;
 876        }
 877        path->leave_spinning = 1;
 878        ret = btrfs_insert_empty_item(trans, root, path, &file_key,
 879                                      ins_size);
 880        path->leave_spinning = 0;
 881        if (ret < 0)
 882                goto fail_unlock;
 883        if (WARN_ON(ret != 0))
 884                goto fail_unlock;
 885        leaf = path->nodes[0];
 886csum:
 887        item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
 888        item_end = (struct btrfs_csum_item *)((unsigned char *)item +
 889                                      btrfs_item_size_nr(leaf, path->slots[0]));
 890        item = (struct btrfs_csum_item *)((unsigned char *)item +
 891                                          csum_offset * csum_size);
 892found:
 893        ins_size = (u32)(sums->len - total_bytes) >>
 894                   fs_info->sb->s_blocksize_bits;
 895        ins_size *= csum_size;
 896        ins_size = min_t(u32, (unsigned long)item_end - (unsigned long)item,
 897                              ins_size);
 898        write_extent_buffer(leaf, sums->sums + index, (unsigned long)item,
 899                            ins_size);
 900
 901        ins_size /= csum_size;
 902        total_bytes += ins_size * fs_info->sectorsize;
 903        index += ins_size;
 904
 905        btrfs_mark_buffer_dirty(path->nodes[0]);
 906        if (total_bytes < sums->len) {
 907                btrfs_release_path(path);
 908                cond_resched();
 909                goto again;
 910        }
 911out:
 912        btrfs_free_path(path);
 913        return ret;
 914
 915fail_unlock:
 916        goto out;
 917}
 918
 919void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode,
 920                                     const struct btrfs_path *path,
 921                                     struct btrfs_file_extent_item *fi,
 922                                     const bool new_inline,
 923                                     struct extent_map *em)
 924{
 925        struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
 926        struct btrfs_root *root = inode->root;
 927        struct extent_buffer *leaf = path->nodes[0];
 928        const int slot = path->slots[0];
 929        struct btrfs_key key;
 930        u64 extent_start, extent_end;
 931        u64 bytenr;
 932        u8 type = btrfs_file_extent_type(leaf, fi);
 933        int compress_type = btrfs_file_extent_compression(leaf, fi);
 934
 935        em->bdev = fs_info->fs_devices->latest_bdev;
 936        btrfs_item_key_to_cpu(leaf, &key, slot);
 937        extent_start = key.offset;
 938
 939        if (type == BTRFS_FILE_EXTENT_REG ||
 940            type == BTRFS_FILE_EXTENT_PREALLOC) {
 941                extent_end = extent_start +
 942                        btrfs_file_extent_num_bytes(leaf, fi);
 943        } else if (type == BTRFS_FILE_EXTENT_INLINE) {
 944                size_t size;
 945                size = btrfs_file_extent_inline_len(leaf, slot, fi);
 946                extent_end = ALIGN(extent_start + size,
 947                                   fs_info->sectorsize);
 948        }
 949
 950        em->ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
 951        if (type == BTRFS_FILE_EXTENT_REG ||
 952            type == BTRFS_FILE_EXTENT_PREALLOC) {
 953                em->start = extent_start;
 954                em->len = extent_end - extent_start;
 955                em->orig_start = extent_start -
 956                        btrfs_file_extent_offset(leaf, fi);
 957                em->orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi);
 958                bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
 959                if (bytenr == 0) {
 960                        em->block_start = EXTENT_MAP_HOLE;
 961                        return;
 962                }
 963                if (compress_type != BTRFS_COMPRESS_NONE) {
 964                        set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
 965                        em->compress_type = compress_type;
 966                        em->block_start = bytenr;
 967                        em->block_len = em->orig_block_len;
 968                } else {
 969                        bytenr += btrfs_file_extent_offset(leaf, fi);
 970                        em->block_start = bytenr;
 971                        em->block_len = em->len;
 972                        if (type == BTRFS_FILE_EXTENT_PREALLOC)
 973                                set_bit(EXTENT_FLAG_PREALLOC, &em->flags);
 974                }
 975        } else if (type == BTRFS_FILE_EXTENT_INLINE) {
 976                em->block_start = EXTENT_MAP_INLINE;
 977                em->start = extent_start;
 978                em->len = extent_end - extent_start;
 979                /*
 980                 * Initialize orig_start and block_len with the same values
 981                 * as in inode.c:btrfs_get_extent().
 982                 */
 983                em->orig_start = EXTENT_MAP_HOLE;
 984                em->block_len = (u64)-1;
 985                if (!new_inline && compress_type != BTRFS_COMPRESS_NONE) {
 986                        set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
 987                        em->compress_type = compress_type;
 988                }
 989        } else {
 990                btrfs_err(fs_info,
 991                          "unknown file extent item type %d, inode %llu, offset %llu, "
 992                          "root %llu", type, btrfs_ino(inode), extent_start,
 993                          root->root_key.objectid);
 994        }
 995}
 996