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