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 "print-tree.h"
  27
  28#define MAX_CSUM_ITEMS(r, size) ((((BTRFS_LEAF_DATA_SIZE(r) - \
  29                                   sizeof(struct btrfs_item) * 2) / \
  30                                  size) - 1))
  31
  32#define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \
  33                                   sizeof(struct btrfs_ordered_sum)) / \
  34                                   sizeof(struct btrfs_sector_sum) * \
  35                                   (r)->sectorsize - (r)->sectorsize)
  36
  37int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
  38                             struct btrfs_root *root,
  39                             u64 objectid, u64 pos,
  40                             u64 disk_offset, u64 disk_num_bytes,
  41                             u64 num_bytes, u64 offset, u64 ram_bytes,
  42                             u8 compression, u8 encryption, u16 other_encoding)
  43{
  44        int ret = 0;
  45        struct btrfs_file_extent_item *item;
  46        struct btrfs_key file_key;
  47        struct btrfs_path *path;
  48        struct extent_buffer *leaf;
  49
  50        path = btrfs_alloc_path();
  51        if (!path)
  52                return -ENOMEM;
  53        file_key.objectid = objectid;
  54        file_key.offset = pos;
  55        btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
  56
  57        path->leave_spinning = 1;
  58        ret = btrfs_insert_empty_item(trans, root, path, &file_key,
  59                                      sizeof(*item));
  60        if (ret < 0)
  61                goto out;
  62        BUG_ON(ret);
  63        leaf = path->nodes[0];
  64        item = btrfs_item_ptr(leaf, path->slots[0],
  65                              struct btrfs_file_extent_item);
  66        btrfs_set_file_extent_disk_bytenr(leaf, item, disk_offset);
  67        btrfs_set_file_extent_disk_num_bytes(leaf, item, disk_num_bytes);
  68        btrfs_set_file_extent_offset(leaf, item, offset);
  69        btrfs_set_file_extent_num_bytes(leaf, item, num_bytes);
  70        btrfs_set_file_extent_ram_bytes(leaf, item, ram_bytes);
  71        btrfs_set_file_extent_generation(leaf, item, trans->transid);
  72        btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG);
  73        btrfs_set_file_extent_compression(leaf, item, compression);
  74        btrfs_set_file_extent_encryption(leaf, item, encryption);
  75        btrfs_set_file_extent_other_encoding(leaf, item, other_encoding);
  76
  77        btrfs_mark_buffer_dirty(leaf);
  78out:
  79        btrfs_free_path(path);
  80        return ret;
  81}
  82
  83struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
  84                                          struct btrfs_root *root,
  85                                          struct btrfs_path *path,
  86                                          u64 bytenr, int cow)
  87{
  88        int ret;
  89        struct btrfs_key file_key;
  90        struct btrfs_key found_key;
  91        struct btrfs_csum_item *item;
  92        struct extent_buffer *leaf;
  93        u64 csum_offset = 0;
  94        u16 csum_size =
  95                btrfs_super_csum_size(&root->fs_info->super_copy);
  96        int csums_in_item;
  97
  98        file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
  99        file_key.offset = bytenr;
 100        btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY);
 101        ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
 102        if (ret < 0)
 103                goto fail;
 104        leaf = path->nodes[0];
 105        if (ret > 0) {
 106                ret = 1;
 107                if (path->slots[0] == 0)
 108                        goto fail;
 109                path->slots[0]--;
 110                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 111                if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY)
 112                        goto fail;
 113
 114                csum_offset = (bytenr - found_key.offset) >>
 115                                root->fs_info->sb->s_blocksize_bits;
 116                csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]);
 117                csums_in_item /= csum_size;
 118
 119                if (csum_offset >= csums_in_item) {
 120                        ret = -EFBIG;
 121                        goto fail;
 122                }
 123        }
 124        item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
 125        item = (struct btrfs_csum_item *)((unsigned char *)item +
 126                                          csum_offset * csum_size);
 127        return item;
 128fail:
 129        if (ret > 0)
 130                ret = -ENOENT;
 131        return ERR_PTR(ret);
 132}
 133
 134
 135int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
 136                             struct btrfs_root *root,
 137                             struct btrfs_path *path, u64 objectid,
 138                             u64 offset, int mod)
 139{
 140        int ret;
 141        struct btrfs_key file_key;
 142        int ins_len = mod < 0 ? -1 : 0;
 143        int cow = mod != 0;
 144
 145        file_key.objectid = objectid;
 146        file_key.offset = offset;
 147        btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
 148        ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
 149        return ret;
 150}
 151
 152
 153static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
 154                                   struct inode *inode, struct bio *bio,
 155                                   u64 logical_offset, u32 *dst, int dio)
 156{
 157        u32 sum;
 158        struct bio_vec *bvec = bio->bi_io_vec;
 159        int bio_index = 0;
 160        u64 offset = 0;
 161        u64 item_start_offset = 0;
 162        u64 item_last_offset = 0;
 163        u64 disk_bytenr;
 164        u32 diff;
 165        u16 csum_size =
 166                btrfs_super_csum_size(&root->fs_info->super_copy);
 167        int ret;
 168        struct btrfs_path *path;
 169        struct btrfs_csum_item *item = NULL;
 170        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
 171
 172        path = btrfs_alloc_path();
 173        if (!path)
 174                return -ENOMEM;
 175        if (bio->bi_size > PAGE_CACHE_SIZE * 8)
 176                path->reada = 2;
 177
 178        WARN_ON(bio->bi_vcnt <= 0);
 179
 180        disk_bytenr = (u64)bio->bi_sector << 9;
 181        if (dio)
 182                offset = logical_offset;
 183        while (bio_index < bio->bi_vcnt) {
 184                if (!dio)
 185                        offset = page_offset(bvec->bv_page) + bvec->bv_offset;
 186                ret = btrfs_find_ordered_sum(inode, offset, disk_bytenr, &sum);
 187                if (ret == 0)
 188                        goto found;
 189
 190                if (!item || disk_bytenr < item_start_offset ||
 191                    disk_bytenr >= item_last_offset) {
 192                        struct btrfs_key found_key;
 193                        u32 item_size;
 194
 195                        if (item)
 196                                btrfs_release_path(root, path);
 197                        item = btrfs_lookup_csum(NULL, root->fs_info->csum_root,
 198                                                 path, disk_bytenr, 0);
 199                        if (IS_ERR(item)) {
 200                                ret = PTR_ERR(item);
 201                                if (ret == -ENOENT || ret == -EFBIG)
 202                                        ret = 0;
 203                                sum = 0;
 204                                if (BTRFS_I(inode)->root->root_key.objectid ==
 205                                    BTRFS_DATA_RELOC_TREE_OBJECTID) {
 206                                        set_extent_bits(io_tree, offset,
 207                                                offset + bvec->bv_len - 1,
 208                                                EXTENT_NODATASUM, GFP_NOFS);
 209                                } else {
 210                                        printk(KERN_INFO "btrfs no csum found "
 211                                               "for inode %lu start %llu\n",
 212                                               inode->i_ino,
 213                                               (unsigned long long)offset);
 214                                }
 215                                item = NULL;
 216                                btrfs_release_path(root, path);
 217                                goto found;
 218                        }
 219                        btrfs_item_key_to_cpu(path->nodes[0], &found_key,
 220                                              path->slots[0]);
 221
 222                        item_start_offset = found_key.offset;
 223                        item_size = btrfs_item_size_nr(path->nodes[0],
 224                                                       path->slots[0]);
 225                        item_last_offset = item_start_offset +
 226                                (item_size / csum_size) *
 227                                root->sectorsize;
 228                        item = btrfs_item_ptr(path->nodes[0], path->slots[0],
 229                                              struct btrfs_csum_item);
 230                }
 231                /*
 232                 * this byte range must be able to fit inside
 233                 * a single leaf so it will also fit inside a u32
 234                 */
 235                diff = disk_bytenr - item_start_offset;
 236                diff = diff / root->sectorsize;
 237                diff = diff * csum_size;
 238
 239                read_extent_buffer(path->nodes[0], &sum,
 240                                   ((unsigned long)item) + diff,
 241                                   csum_size);
 242found:
 243                if (dst)
 244                        *dst++ = sum;
 245                else
 246                        set_state_private(io_tree, offset, sum);
 247                disk_bytenr += bvec->bv_len;
 248                offset += bvec->bv_len;
 249                bio_index++;
 250                bvec++;
 251        }
 252        btrfs_free_path(path);
 253        return 0;
 254}
 255
 256int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
 257                          struct bio *bio, u32 *dst)
 258{
 259        return __btrfs_lookup_bio_sums(root, inode, bio, 0, dst, 0);
 260}
 261
 262int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
 263                              struct bio *bio, u64 offset, u32 *dst)
 264{
 265        return __btrfs_lookup_bio_sums(root, inode, bio, offset, dst, 1);
 266}
 267
 268int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
 269                             struct list_head *list)
 270{
 271        struct btrfs_key key;
 272        struct btrfs_path *path;
 273        struct extent_buffer *leaf;
 274        struct btrfs_ordered_sum *sums;
 275        struct btrfs_sector_sum *sector_sum;
 276        struct btrfs_csum_item *item;
 277        unsigned long offset;
 278        int ret;
 279        size_t size;
 280        u64 csum_end;
 281        u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy);
 282
 283        path = btrfs_alloc_path();
 284        BUG_ON(!path);
 285
 286        key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
 287        key.offset = start;
 288        key.type = BTRFS_EXTENT_CSUM_KEY;
 289
 290        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 291        if (ret < 0)
 292                goto fail;
 293        if (ret > 0 && path->slots[0] > 0) {
 294                leaf = path->nodes[0];
 295                btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
 296                if (key.objectid == BTRFS_EXTENT_CSUM_OBJECTID &&
 297                    key.type == BTRFS_EXTENT_CSUM_KEY) {
 298                        offset = (start - key.offset) >>
 299                                 root->fs_info->sb->s_blocksize_bits;
 300                        if (offset * csum_size <
 301                            btrfs_item_size_nr(leaf, path->slots[0] - 1))
 302                                path->slots[0]--;
 303                }
 304        }
 305
 306        while (start <= end) {
 307                leaf = path->nodes[0];
 308                if (path->slots[0] >= btrfs_header_nritems(leaf)) {
 309                        ret = btrfs_next_leaf(root, path);
 310                        if (ret < 0)
 311                                goto fail;
 312                        if (ret > 0)
 313                                break;
 314                        leaf = path->nodes[0];
 315                }
 316
 317                btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
 318                if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
 319                    key.type != BTRFS_EXTENT_CSUM_KEY)
 320                        break;
 321
 322                btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
 323                if (key.offset > end)
 324                        break;
 325
 326                if (key.offset > start)
 327                        start = key.offset;
 328
 329                size = btrfs_item_size_nr(leaf, path->slots[0]);
 330                csum_end = key.offset + (size / csum_size) * root->sectorsize;
 331                if (csum_end <= start) {
 332                        path->slots[0]++;
 333                        continue;
 334                }
 335
 336                csum_end = min(csum_end, end + 1);
 337                item = btrfs_item_ptr(path->nodes[0], path->slots[0],
 338                                      struct btrfs_csum_item);
 339                while (start < csum_end) {
 340                        size = min_t(size_t, csum_end - start,
 341                                        MAX_ORDERED_SUM_BYTES(root));
 342                        sums = kzalloc(btrfs_ordered_sum_size(root, size),
 343                                        GFP_NOFS);
 344                        BUG_ON(!sums);
 345
 346                        sector_sum = sums->sums;
 347                        sums->bytenr = start;
 348                        sums->len = size;
 349
 350                        offset = (start - key.offset) >>
 351                                root->fs_info->sb->s_blocksize_bits;
 352                        offset *= csum_size;
 353
 354                        while (size > 0) {
 355                                read_extent_buffer(path->nodes[0],
 356                                                &sector_sum->sum,
 357                                                ((unsigned long)item) +
 358                                                offset, csum_size);
 359                                sector_sum->bytenr = start;
 360
 361                                size -= root->sectorsize;
 362                                start += root->sectorsize;
 363                                offset += csum_size;
 364                                sector_sum++;
 365                        }
 366                        list_add_tail(&sums->list, list);
 367                }
 368                path->slots[0]++;
 369        }
 370        ret = 0;
 371fail:
 372        btrfs_free_path(path);
 373        return ret;
 374}
 375
 376int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
 377                       struct bio *bio, u64 file_start, int contig)
 378{
 379        struct btrfs_ordered_sum *sums;
 380        struct btrfs_sector_sum *sector_sum;
 381        struct btrfs_ordered_extent *ordered;
 382        char *data;
 383        struct bio_vec *bvec = bio->bi_io_vec;
 384        int bio_index = 0;
 385        unsigned long total_bytes = 0;
 386        unsigned long this_sum_bytes = 0;
 387        u64 offset;
 388        u64 disk_bytenr;
 389
 390        WARN_ON(bio->bi_vcnt <= 0);
 391        sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS);
 392        if (!sums)
 393                return -ENOMEM;
 394
 395        sector_sum = sums->sums;
 396        disk_bytenr = (u64)bio->bi_sector << 9;
 397        sums->len = bio->bi_size;
 398        INIT_LIST_HEAD(&sums->list);
 399
 400        if (contig)
 401                offset = file_start;
 402        else
 403                offset = page_offset(bvec->bv_page) + bvec->bv_offset;
 404
 405        ordered = btrfs_lookup_ordered_extent(inode, offset);
 406        BUG_ON(!ordered);
 407        sums->bytenr = ordered->start;
 408
 409        while (bio_index < bio->bi_vcnt) {
 410                if (!contig)
 411                        offset = page_offset(bvec->bv_page) + bvec->bv_offset;
 412
 413                if (!contig && (offset >= ordered->file_offset + ordered->len ||
 414                    offset < ordered->file_offset)) {
 415                        unsigned long bytes_left;
 416                        sums->len = this_sum_bytes;
 417                        this_sum_bytes = 0;
 418                        btrfs_add_ordered_sum(inode, ordered, sums);
 419                        btrfs_put_ordered_extent(ordered);
 420
 421                        bytes_left = bio->bi_size - total_bytes;
 422
 423                        sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left),
 424                                       GFP_NOFS);
 425                        BUG_ON(!sums);
 426                        sector_sum = sums->sums;
 427                        sums->len = bytes_left;
 428                        ordered = btrfs_lookup_ordered_extent(inode, offset);
 429                        BUG_ON(!ordered);
 430                        sums->bytenr = ordered->start;
 431                }
 432
 433                data = kmap_atomic(bvec->bv_page, KM_USER0);
 434                sector_sum->sum = ~(u32)0;
 435                sector_sum->sum = btrfs_csum_data(root,
 436                                                  data + bvec->bv_offset,
 437                                                  sector_sum->sum,
 438                                                  bvec->bv_len);
 439                kunmap_atomic(data, KM_USER0);
 440                btrfs_csum_final(sector_sum->sum,
 441                                 (char *)&sector_sum->sum);
 442                sector_sum->bytenr = disk_bytenr;
 443
 444                sector_sum++;
 445                bio_index++;
 446                total_bytes += bvec->bv_len;
 447                this_sum_bytes += bvec->bv_len;
 448                disk_bytenr += bvec->bv_len;
 449                offset += bvec->bv_len;
 450                bvec++;
 451        }
 452        this_sum_bytes = 0;
 453        btrfs_add_ordered_sum(inode, ordered, sums);
 454        btrfs_put_ordered_extent(ordered);
 455        return 0;
 456}
 457
 458/*
 459 * helper function for csum removal, this expects the
 460 * key to describe the csum pointed to by the path, and it expects
 461 * the csum to overlap the range [bytenr, len]
 462 *
 463 * The csum should not be entirely contained in the range and the
 464 * range should not be entirely contained in the csum.
 465 *
 466 * This calls btrfs_truncate_item with the correct args based on the
 467 * overlap, and fixes up the key as required.
 468 */
 469static noinline int truncate_one_csum(struct btrfs_trans_handle *trans,
 470                                      struct btrfs_root *root,
 471                                      struct btrfs_path *path,
 472                                      struct btrfs_key *key,
 473                                      u64 bytenr, u64 len)
 474{
 475        struct extent_buffer *leaf;
 476        u16 csum_size =
 477                btrfs_super_csum_size(&root->fs_info->super_copy);
 478        u64 csum_end;
 479        u64 end_byte = bytenr + len;
 480        u32 blocksize_bits = root->fs_info->sb->s_blocksize_bits;
 481        int ret;
 482
 483        leaf = path->nodes[0];
 484        csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
 485        csum_end <<= root->fs_info->sb->s_blocksize_bits;
 486        csum_end += key->offset;
 487
 488        if (key->offset < bytenr && csum_end <= end_byte) {
 489                /*
 490                 *         [ bytenr - len ]
 491                 *         [   ]
 492                 *   [csum     ]
 493                 *   A simple truncate off the end of the item
 494                 */
 495                u32 new_size = (bytenr - key->offset) >> blocksize_bits;
 496                new_size *= csum_size;
 497                ret = btrfs_truncate_item(trans, root, path, new_size, 1);
 498                BUG_ON(ret);
 499        } else if (key->offset >= bytenr && csum_end > end_byte &&
 500                   end_byte > key->offset) {
 501                /*
 502                 *         [ bytenr - len ]
 503                 *                 [ ]
 504                 *                 [csum     ]
 505                 * we need to truncate from the beginning of the csum
 506                 */
 507                u32 new_size = (csum_end - end_byte) >> blocksize_bits;
 508                new_size *= csum_size;
 509
 510                ret = btrfs_truncate_item(trans, root, path, new_size, 0);
 511                BUG_ON(ret);
 512
 513                key->offset = end_byte;
 514                ret = btrfs_set_item_key_safe(trans, root, path, key);
 515                BUG_ON(ret);
 516        } else {
 517                BUG();
 518        }
 519        return 0;
 520}
 521
 522/*
 523 * deletes the csum items from the csum tree for a given
 524 * range of bytes.
 525 */
 526int btrfs_del_csums(struct btrfs_trans_handle *trans,
 527                    struct btrfs_root *root, u64 bytenr, u64 len)
 528{
 529        struct btrfs_path *path;
 530        struct btrfs_key key;
 531        u64 end_byte = bytenr + len;
 532        u64 csum_end;
 533        struct extent_buffer *leaf;
 534        int ret;
 535        u16 csum_size =
 536                btrfs_super_csum_size(&root->fs_info->super_copy);
 537        int blocksize_bits = root->fs_info->sb->s_blocksize_bits;
 538
 539        root = root->fs_info->csum_root;
 540
 541        path = btrfs_alloc_path();
 542        if (!path)
 543                return -ENOMEM;
 544
 545        while (1) {
 546                key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
 547                key.offset = end_byte - 1;
 548                key.type = BTRFS_EXTENT_CSUM_KEY;
 549
 550                path->leave_spinning = 1;
 551                ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
 552                if (ret > 0) {
 553                        if (path->slots[0] == 0)
 554                                goto out;
 555                        path->slots[0]--;
 556                } else if (ret < 0) {
 557                        goto out;
 558                }
 559
 560                leaf = path->nodes[0];
 561                btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
 562
 563                if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
 564                    key.type != BTRFS_EXTENT_CSUM_KEY) {
 565                        break;
 566                }
 567
 568                if (key.offset >= end_byte)
 569                        break;
 570
 571                csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
 572                csum_end <<= blocksize_bits;
 573                csum_end += key.offset;
 574
 575                /* this csum ends before we start, we're done */
 576                if (csum_end <= bytenr)
 577                        break;
 578
 579                /* delete the entire item, it is inside our range */
 580                if (key.offset >= bytenr && csum_end <= end_byte) {
 581                        ret = btrfs_del_item(trans, root, path);
 582                        BUG_ON(ret);
 583                        if (key.offset == bytenr)
 584                                break;
 585                } else if (key.offset < bytenr && csum_end > end_byte) {
 586                        unsigned long offset;
 587                        unsigned long shift_len;
 588                        unsigned long item_offset;
 589                        /*
 590                         *        [ bytenr - len ]
 591                         *     [csum                ]
 592                         *
 593                         * Our bytes are in the middle of the csum,
 594                         * we need to split this item and insert a new one.
 595                         *
 596                         * But we can't drop the path because the
 597                         * csum could change, get removed, extended etc.
 598                         *
 599                         * The trick here is the max size of a csum item leaves
 600                         * enough room in the tree block for a single
 601                         * item header.  So, we split the item in place,
 602                         * adding a new header pointing to the existing
 603                         * bytes.  Then we loop around again and we have
 604                         * a nicely formed csum item that we can neatly
 605                         * truncate.
 606                         */
 607                        offset = (bytenr - key.offset) >> blocksize_bits;
 608                        offset *= csum_size;
 609
 610                        shift_len = (len >> blocksize_bits) * csum_size;
 611
 612                        item_offset = btrfs_item_ptr_offset(leaf,
 613                                                            path->slots[0]);
 614
 615                        memset_extent_buffer(leaf, 0, item_offset + offset,
 616                                             shift_len);
 617                        key.offset = bytenr;
 618
 619                        /*
 620                         * btrfs_split_item returns -EAGAIN when the
 621                         * item changed size or key
 622                         */
 623                        ret = btrfs_split_item(trans, root, path, &key, offset);
 624                        BUG_ON(ret && ret != -EAGAIN);
 625
 626                        key.offset = end_byte - 1;
 627                } else {
 628                        ret = truncate_one_csum(trans, root, path,
 629                                                &key, bytenr, len);
 630                        BUG_ON(ret);
 631                        if (key.offset < bytenr)
 632                                break;
 633                }
 634                btrfs_release_path(root, path);
 635        }
 636out:
 637        btrfs_free_path(path);
 638        return 0;
 639}
 640
 641int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
 642                           struct btrfs_root *root,
 643                           struct btrfs_ordered_sum *sums)
 644{
 645        u64 bytenr;
 646        int ret;
 647        struct btrfs_key file_key;
 648        struct btrfs_key found_key;
 649        u64 next_offset;
 650        u64 total_bytes = 0;
 651        int found_next;
 652        struct btrfs_path *path;
 653        struct btrfs_csum_item *item;
 654        struct btrfs_csum_item *item_end;
 655        struct extent_buffer *leaf = NULL;
 656        u64 csum_offset;
 657        struct btrfs_sector_sum *sector_sum;
 658        u32 nritems;
 659        u32 ins_size;
 660        char *eb_map;
 661        char *eb_token;
 662        unsigned long map_len;
 663        unsigned long map_start;
 664        u16 csum_size =
 665                btrfs_super_csum_size(&root->fs_info->super_copy);
 666
 667        path = btrfs_alloc_path();
 668        BUG_ON(!path);
 669        sector_sum = sums->sums;
 670again:
 671        next_offset = (u64)-1;
 672        found_next = 0;
 673        file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
 674        file_key.offset = sector_sum->bytenr;
 675        bytenr = sector_sum->bytenr;
 676        btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY);
 677
 678        item = btrfs_lookup_csum(trans, root, path, sector_sum->bytenr, 1);
 679        if (!IS_ERR(item)) {
 680                leaf = path->nodes[0];
 681                ret = 0;
 682                goto found;
 683        }
 684        ret = PTR_ERR(item);
 685        if (ret != -EFBIG && ret != -ENOENT)
 686                goto fail_unlock;
 687
 688        if (ret == -EFBIG) {
 689                u32 item_size;
 690                /* we found one, but it isn't big enough yet */
 691                leaf = path->nodes[0];
 692                item_size = btrfs_item_size_nr(leaf, path->slots[0]);
 693                if ((item_size / csum_size) >=
 694                    MAX_CSUM_ITEMS(root, csum_size)) {
 695                        /* already at max size, make a new one */
 696                        goto insert;
 697                }
 698        } else {
 699                int slot = path->slots[0] + 1;
 700                /* we didn't find a csum item, insert one */
 701                nritems = btrfs_header_nritems(path->nodes[0]);
 702                if (path->slots[0] >= nritems - 1) {
 703                        ret = btrfs_next_leaf(root, path);
 704                        if (ret == 1)
 705                                found_next = 1;
 706                        if (ret != 0)
 707                                goto insert;
 708                        slot = 0;
 709                }
 710                btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot);
 711                if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
 712                    found_key.type != BTRFS_EXTENT_CSUM_KEY) {
 713                        found_next = 1;
 714                        goto insert;
 715                }
 716                next_offset = found_key.offset;
 717                found_next = 1;
 718                goto insert;
 719        }
 720
 721        /*
 722         * at this point, we know the tree has an item, but it isn't big
 723         * enough yet to put our csum in.  Grow it
 724         */
 725        btrfs_release_path(root, path);
 726        ret = btrfs_search_slot(trans, root, &file_key, path,
 727                                csum_size, 1);
 728        if (ret < 0)
 729                goto fail_unlock;
 730
 731        if (ret > 0) {
 732                if (path->slots[0] == 0)
 733                        goto insert;
 734                path->slots[0]--;
 735        }
 736
 737        leaf = path->nodes[0];
 738        btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 739        csum_offset = (bytenr - found_key.offset) >>
 740                        root->fs_info->sb->s_blocksize_bits;
 741
 742        if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY ||
 743            found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
 744            csum_offset >= MAX_CSUM_ITEMS(root, csum_size)) {
 745                goto insert;
 746        }
 747
 748        if (csum_offset >= btrfs_item_size_nr(leaf, path->slots[0]) /
 749            csum_size) {
 750                u32 diff = (csum_offset + 1) * csum_size;
 751
 752                /*
 753                 * is the item big enough already?  we dropped our lock
 754                 * before and need to recheck
 755                 */
 756                if (diff < btrfs_item_size_nr(leaf, path->slots[0]))
 757                        goto csum;
 758
 759                diff = diff - btrfs_item_size_nr(leaf, path->slots[0]);
 760                if (diff != csum_size)
 761                        goto insert;
 762
 763                ret = btrfs_extend_item(trans, root, path, diff);
 764                BUG_ON(ret);
 765                goto csum;
 766        }
 767
 768insert:
 769        btrfs_release_path(root, path);
 770        csum_offset = 0;
 771        if (found_next) {
 772                u64 tmp = total_bytes + root->sectorsize;
 773                u64 next_sector = sector_sum->bytenr;
 774                struct btrfs_sector_sum *next = sector_sum + 1;
 775
 776                while (tmp < sums->len) {
 777                        if (next_sector + root->sectorsize != next->bytenr)
 778                                break;
 779                        tmp += root->sectorsize;
 780                        next_sector = next->bytenr;
 781                        next++;
 782                }
 783                tmp = min(tmp, next_offset - file_key.offset);
 784                tmp >>= root->fs_info->sb->s_blocksize_bits;
 785                tmp = max((u64)1, tmp);
 786                tmp = min(tmp, (u64)MAX_CSUM_ITEMS(root, csum_size));
 787                ins_size = csum_size * tmp;
 788        } else {
 789                ins_size = csum_size;
 790        }
 791        path->leave_spinning = 1;
 792        ret = btrfs_insert_empty_item(trans, root, path, &file_key,
 793                                      ins_size);
 794        path->leave_spinning = 0;
 795        if (ret < 0)
 796                goto fail_unlock;
 797        if (ret != 0) {
 798                WARN_ON(1);
 799                goto fail_unlock;
 800        }
 801csum:
 802        leaf = path->nodes[0];
 803        item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
 804        ret = 0;
 805        item = (struct btrfs_csum_item *)((unsigned char *)item +
 806                                          csum_offset * csum_size);
 807found:
 808        item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
 809        item_end = (struct btrfs_csum_item *)((unsigned char *)item_end +
 810                                      btrfs_item_size_nr(leaf, path->slots[0]));
 811        eb_token = NULL;
 812next_sector:
 813
 814        if (!eb_token ||
 815           (unsigned long)item + csum_size >= map_start + map_len) {
 816                int err;
 817
 818                if (eb_token)
 819                        unmap_extent_buffer(leaf, eb_token, KM_USER1);
 820                eb_token = NULL;
 821                err = map_private_extent_buffer(leaf, (unsigned long)item,
 822                                                csum_size,
 823                                                &eb_token, &eb_map,
 824                                                &map_start, &map_len, KM_USER1);
 825                if (err)
 826                        eb_token = NULL;
 827        }
 828        if (eb_token) {
 829                memcpy(eb_token + ((unsigned long)item & (PAGE_CACHE_SIZE - 1)),
 830                       &sector_sum->sum, csum_size);
 831        } else {
 832                write_extent_buffer(leaf, &sector_sum->sum,
 833                                    (unsigned long)item, csum_size);
 834        }
 835
 836        total_bytes += root->sectorsize;
 837        sector_sum++;
 838        if (total_bytes < sums->len) {
 839                item = (struct btrfs_csum_item *)((char *)item +
 840                                                  csum_size);
 841                if (item < item_end && bytenr + PAGE_CACHE_SIZE ==
 842                    sector_sum->bytenr) {
 843                        bytenr = sector_sum->bytenr;
 844                        goto next_sector;
 845                }
 846        }
 847        if (eb_token) {
 848                unmap_extent_buffer(leaf, eb_token, KM_USER1);
 849                eb_token = NULL;
 850        }
 851        btrfs_mark_buffer_dirty(path->nodes[0]);
 852        if (total_bytes < sums->len) {
 853                btrfs_release_path(root, path);
 854                cond_resched();
 855                goto again;
 856        }
 857out:
 858        btrfs_free_path(path);
 859        return ret;
 860
 861fail_unlock:
 862        goto out;
 863}
 864