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