LCOV - code coverage report
Current view: top level - fs/btrfs - file-item.c (source / functions) Hit Total Coverage
Test: btrfstest.info Lines: 406 426 95.3 %
Date: 2014-11-28 Functions: 12 13 92.3 %

          Line data    Source code
       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             : 
      40        5044 : int 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        5044 :         path = btrfs_alloc_path();
      54        5044 :         if (!path)
      55             :                 return -ENOMEM;
      56        5044 :         file_key.objectid = objectid;
      57        5044 :         file_key.offset = pos;
      58             :         btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
      59             : 
      60        5044 :         path->leave_spinning = 1;
      61             :         ret = btrfs_insert_empty_item(trans, root, path, &file_key,
      62             :                                       sizeof(*item));
      63        5045 :         if (ret < 0)
      64             :                 goto out;
      65        5045 :         BUG_ON(ret); /* Can't happen */
      66        5045 :         leaf = path->nodes[0];
      67       10090 :         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        5045 :         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        5045 :         btrfs_mark_buffer_dirty(leaf);
      81             : out:
      82        5045 :         btrfs_free_path(path);
      83        5045 :         return ret;
      84             : }
      85             : 
      86             : static struct btrfs_csum_item *
      87      121427 : btrfs_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      242854 :         u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
      99             :         int csums_in_item;
     100             : 
     101      121427 :         file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
     102      121427 :         file_key.offset = bytenr;
     103             :         btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY);
     104      121427 :         ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
     105      121428 :         if (ret < 0)
     106             :                 goto fail;
     107      121428 :         leaf = path->nodes[0];
     108      121428 :         if (ret > 0) {
     109             :                 ret = 1;
     110      120555 :                 if (path->slots[0] == 0)
     111             :                         goto fail;
     112      120468 :                 path->slots[0]--;
     113      120468 :                 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
     114      120468 :                 if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY)
     115             :                         goto fail;
     116             : 
     117      240524 :                 csum_offset = (bytenr - found_key.offset) >>
     118      120262 :                                 root->fs_info->sb->s_blocksize_bits;
     119      240524 :                 csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]);
     120      120262 :                 csums_in_item /= csum_size;
     121             : 
     122      120262 :                 if (csum_offset == csums_in_item) {
     123             :                         ret = -EFBIG;
     124             :                         goto fail;
     125       38230 :                 } else if (csum_offset > csums_in_item) {
     126             :                         goto fail;
     127             :                 }
     128             :         }
     129       54838 :         item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
     130       27419 :         item = (struct btrfs_csum_item *)((unsigned char *)item +
     131             :                                           csum_offset * csum_size);
     132       27419 :         return item;
     133             : fail:
     134       94009 :         if (ret > 0)
     135             :                 ret = -ENOENT;
     136      188018 :         return ERR_PTR(ret);
     137             : }
     138             : 
     139      120872 : int 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      120872 :         int ins_len = mod < 0 ? -1 : 0;
     147      120872 :         int cow = mod != 0;
     148             : 
     149      120872 :         file_key.objectid = objectid;
     150      120872 :         file_key.offset = offset;
     151             :         btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
     152      120872 :         ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
     153      120896 :         return ret;
     154             : }
     155             : 
     156         375 : static void btrfs_io_bio_endio_readpage(struct btrfs_io_bio *bio, int err)
     157             : {
     158         375 :         kfree(bio->csum_allocated);
     159         375 : }
     160             : 
     161       26095 : static 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       26095 :         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       26095 :         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       52190 :         u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
     180             : 
     181       26095 :         path = btrfs_alloc_path();
     182       26095 :         if (!path)
     183             :                 return -ENOMEM;
     184             : 
     185       26095 :         nblocks = bio->bi_iter.bi_size >> inode->i_sb->s_blocksize_bits;
     186       26095 :         if (!dst) {
     187       26053 :                 if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
     188         750 :                         btrfs_bio->csum_allocated = kmalloc(nblocks * csum_size,
     189             :                                                             GFP_NOFS);
     190         375 :                         if (!btrfs_bio->csum_allocated) {
     191           0 :                                 btrfs_free_path(path);
     192             :                                 return -ENOMEM;
     193             :                         }
     194         375 :                         btrfs_bio->csum = btrfs_bio->csum_allocated;
     195         375 :                         btrfs_bio->end_io = btrfs_io_bio_endio_readpage;
     196             :                 } else {
     197       25678 :                         btrfs_bio->csum = btrfs_bio->csum_inline;
     198             :                 }
     199       26053 :                 csum = btrfs_bio->csum;
     200             :         } else {
     201             :                 csum = (u8 *)dst;
     202             :         }
     203             : 
     204       26095 :         if (bio->bi_iter.bi_size > PAGE_CACHE_SIZE * 8)
     205         508 :                 path->reada = 2;
     206             : 
     207       26095 :         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       26095 :         if (btrfs_is_free_space_inode(inode)) {
     216           0 :                 path->search_commit_root = 1;
     217           0 :                 path->skip_locking = 1;
     218             :         }
     219             : 
     220       26095 :         disk_bytenr = (u64)bio->bi_iter.bi_sector << 9;
     221       26095 :         if (dio)
     222             :                 offset = logical_offset;
     223       52684 :         while (bio_index < bio->bi_vcnt) {
     224       26589 :                 if (!dio)
     225       53178 :                         offset = page_offset(bvec->bv_page) + bvec->bv_offset;
     226       26589 :                 count = btrfs_find_ordered_sum(inode, offset, disk_bytenr,
     227             :                                                (u32 *)csum, nblocks);
     228       26589 :                 if (count)
     229             :                         goto found;
     230             : 
     231       26589 :                 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       26589 :                         if (item)
     237         243 :                                 btrfs_release_path(path);
     238       26589 :                         item = btrfs_lookup_csum(NULL, root->fs_info->csum_root,
     239             :                                                  path, disk_bytenr, 0);
     240       26589 :                         if (IS_ERR(item)) {
     241             :                                 count = 1;
     242         254 :                                 memset(csum, 0, csum_size);
     243         254 :                                 if (BTRFS_I(inode)->root->root_key.objectid ==
     244             :                                     BTRFS_DATA_RELOC_TREE_OBJECTID) {
     245         254 :                                         set_extent_bits(io_tree, offset,
     246         254 :                                                 offset + bvec->bv_len - 1,
     247             :                                                 EXTENT_NODATASUM, GFP_NOFS);
     248             :                                 } else {
     249           0 :                                         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         254 :                                 btrfs_release_path(path);
     255         254 :                                 goto found;
     256             :                         }
     257       26335 :                         btrfs_item_key_to_cpu(path->nodes[0], &found_key,
     258             :                                               path->slots[0]);
     259             : 
     260       26335 :                         item_start_offset = found_key.offset;
     261       26335 :                         item_size = btrfs_item_size_nr(path->nodes[0],
     262             :                                                        path->slots[0]);
     263       26335 :                         item_last_offset = item_start_offset +
     264       52670 :                                 (item_size / csum_size) *
     265       26335 :                                 root->sectorsize;
     266       52670 :                         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       26335 :                 diff = disk_bytenr - item_start_offset;
     274       26335 :                 diff = diff / root->sectorsize;
     275       26335 :                 diff = diff * csum_size;
     276       26335 :                 count = min_t(int, nblocks, (item_last_offset - disk_bytenr) >>
     277             :                                             inode->i_sb->s_blocksize_bits);
     278       52670 :                 read_extent_buffer(path->nodes[0], csum,
     279       26335 :                                    ((unsigned long)item) + diff,
     280       26335 :                                    csum_size * count);
     281             : found:
     282       26589 :                 csum += count * csum_size;
     283       26589 :                 nblocks -= count;
     284       26589 :                 bio_index += count;
     285       88672 :                 while (count--) {
     286       62083 :                         disk_bytenr += bvec->bv_len;
     287       62083 :                         offset += bvec->bv_len;
     288       62083 :                         bvec++;
     289             :                 }
     290             :         }
     291       26095 :         btrfs_free_path(path);
     292             :         return 0;
     293             : }
     294             : 
     295       26095 : int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
     296             :                           struct bio *bio, u32 *dst)
     297             : {
     298       26095 :         return __btrfs_lookup_bio_sums(root, inode, bio, 0, dst, 0);
     299             : }
     300             : 
     301           0 : int 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           0 :         int len = (bio->bi_iter.bi_sector << 9) - dip->disk_bytenr;
     306           0 :         u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
     307             :         int ret;
     308             : 
     309           0 :         len >>= inode->i_sb->s_blocksize_bits;
     310           0 :         len *= csum_size;
     311             : 
     312           0 :         ret = __btrfs_lookup_bio_sums(root, inode, bio, offset,
     313           0 :                                       (u32 *)(dip->csum + len), 1);
     314           0 :         return ret;
     315             : }
     316             : 
     317      298804 : int 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      332312 :         struct extent_buffer *leaf;
     323             :         struct btrfs_ordered_sum *sums;
     324             :         struct btrfs_csum_item *item;
     325      298804 :         LIST_HEAD(tmplist);
     326             :         unsigned long offset;
     327             :         int ret;
     328             :         size_t size;
     329             :         u64 csum_end;
     330      597608 :         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      298804 :         path = btrfs_alloc_path();
     336      298817 :         if (!path)
     337             :                 return -ENOMEM;
     338             : 
     339      298818 :         if (search_commit) {
     340      290477 :                 path->skip_locking = 1;
     341      290477 :                 path->reada = 2;
     342      290477 :                 path->search_commit_root = 1;
     343             :         }
     344             : 
     345      298818 :         key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
     346      298818 :         key.offset = start;
     347      298818 :         key.type = BTRFS_EXTENT_CSUM_KEY;
     348             : 
     349      298818 :         ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
     350      298752 :         if (ret < 0)
     351             :                 goto fail;
     352      298759 :         if (ret > 0 && path->slots[0] > 0) {
     353      265409 :                 leaf = path->nodes[0];
     354      265409 :                 btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
     355      530919 :                 if (key.objectid == BTRFS_EXTENT_CSUM_OBJECTID &&
     356      265461 :                     key.type == BTRFS_EXTENT_CSUM_KEY) {
     357      530916 :                         offset = (start - key.offset) >>
     358      265458 :                                  root->fs_info->sb->s_blocksize_bits;
     359      530905 :                         if (offset * csum_size <
     360      265458 :                             btrfs_item_size_nr(leaf, path->slots[0] - 1))
     361      253980 :                                 path->slots[0]--;
     362             :                 }
     363             :         }
     364             : 
     365      615503 :         while (start <= end) {
     366      332312 :                 leaf = path->nodes[0];
     367      664624 :                 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
     368        4401 :                         ret = btrfs_next_leaf(root, path);
     369        4401 :                         if (ret < 0)
     370             :                                 goto fail;
     371        4401 :                         if (ret > 0)
     372             :                                 break;
     373        1095 :                         leaf = path->nodes[0];
     374             :                 }
     375             : 
     376      329006 :                 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
     377      658112 :                 if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
     378      658114 :                     key.type != BTRFS_EXTENT_CSUM_KEY ||
     379      329057 :                     key.offset > end)
     380             :                         break;
     381             : 
     382      316729 :                 if (key.offset > start)
     383             :                         start = key.offset;
     384             : 
     385      633456 :                 size = btrfs_item_size_nr(leaf, path->slots[0]);
     386      316727 :                 csum_end = key.offset + (size / csum_size) * root->sectorsize;
     387      316727 :                 if (csum_end <= start) {
     388           6 :                         path->slots[0]++;
     389           6 :                         continue;
     390             :                 }
     391             : 
     392      316721 :                 csum_end = min(csum_end, end + 1);
     393      633409 :                 item = btrfs_item_ptr(path->nodes[0], path->slots[0],
     394             :                                       struct btrfs_csum_item);
     395      950072 :                 while (start < csum_end) {
     396      316684 :                         size = min_t(size_t, csum_end - start,
     397             :                                      MAX_ORDERED_SUM_BYTES(root));
     398      316684 :                         sums = kzalloc(btrfs_ordered_sum_size(root, size),
     399             :                                        GFP_NOFS);
     400      316694 :                         if (!sums) {
     401             :                                 ret = -ENOMEM;
     402             :                                 goto fail;
     403             :                         }
     404             : 
     405      316694 :                         sums->bytenr = start;
     406      316694 :                         sums->len = (int)size;
     407             : 
     408      633388 :                         offset = (start - key.offset) >>
     409      316694 :                                 root->fs_info->sb->s_blocksize_bits;
     410      316694 :                         offset *= csum_size;
     411      316694 :                         size >>= root->fs_info->sb->s_blocksize_bits;
     412             : 
     413      633388 :                         read_extent_buffer(path->nodes[0],
     414      316694 :                                            sums->sums,
     415             :                                            ((unsigned long)item) + offset,
     416             :                                            csum_size * size);
     417             : 
     418      316698 :                         start += root->sectorsize * size;
     419      316698 :                         list_add_tail(&sums->list, &tmplist);
     420             :                 }
     421      316700 :                 path->slots[0]++;
     422             :         }
     423             :         ret = 0;
     424             : fail:
     425      298770 :         while (ret < 0 && !list_empty(&tmplist)) {
     426             :                 sums = list_entry(&tmplist, struct btrfs_ordered_sum, list);
     427           0 :                 list_del(&sums->list);
     428           0 :                 kfree(sums);
     429             :         }
     430             :         list_splice_tail(&tmplist, list);
     431             : 
     432      298770 :         btrfs_free_path(path);
     433      298793 :         return ret;
     434             : }
     435             : 
     436      176401 : int 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       86553 :         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       86553 :         WARN_ON(bio->bi_vcnt <= 0);
     450      173106 :         sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_iter.bi_size),
     451             :                        GFP_NOFS);
     452       86511 :         if (!sums)
     453             :                 return -ENOMEM;
     454             : 
     455       86516 :         sums->len = bio->bi_iter.bi_size;
     456       86516 :         INIT_LIST_HEAD(&sums->list);
     457             : 
     458       86516 :         if (contig)
     459             :                 offset = file_start;
     460             :         else
     461     1221531 :                 offset = page_offset(bvec->bv_page) + bvec->bv_offset;
     462             : 
     463       86516 :         ordered = btrfs_lookup_ordered_extent(inode, offset);
     464       86325 :         BUG_ON(!ordered); /* Logic error */
     465       86325 :         sums->bytenr = (u64)bio->bi_iter.bi_sector << 9;
     466             :         index = 0;
     467             : 
     468     1297758 :         while (bio_index < bio->bi_vcnt) {
     469     1124902 :                 if (!contig)
     470     2198522 :                         offset = page_offset(bvec->bv_page) + bvec->bv_offset;
     471             : 
     472     1124902 :                 if (offset >= ordered->file_offset + ordered->len ||
     473             :                     offset < ordered->file_offset) {
     474             :                         unsigned long bytes_left;
     475        3352 :                         sums->len = this_sum_bytes;
     476             :                         this_sum_bytes = 0;
     477        3352 :                         btrfs_add_ordered_sum(inode, ordered, sums);
     478        3295 :                         btrfs_put_ordered_extent(ordered);
     479             : 
     480        3295 :                         bytes_left = bio->bi_iter.bi_size - total_bytes;
     481             : 
     482        3295 :                         sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left),
     483             :                                        GFP_NOFS);
     484        3294 :                         BUG_ON(!sums); /* -ENOMEM */
     485        3294 :                         sums->len = bytes_left;
     486        3294 :                         ordered = btrfs_lookup_ordered_extent(inode, offset);
     487        3295 :                         BUG_ON(!ordered); /* Logic error */
     488        3295 :                         sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9) +
     489             :                                        total_bytes;
     490             :                         index = 0;
     491             :                 }
     492             : 
     493     1124845 :                 data = kmap_atomic(bvec->bv_page);
     494     1122062 :                 sums->sums[index] = ~(u32)0;
     495     1122062 :                 sums->sums[index] = btrfs_csum_data(data + bvec->bv_offset,
     496             :                                                     sums->sums[index],
     497     1122062 :                                                     bvec->bv_len);
     498             :                 kunmap_atomic(data);
     499     1130189 :                 btrfs_csum_final(sums->sums[index],
     500     1130189 :                                  (char *)(sums->sums + index));
     501             : 
     502     1125108 :                 bio_index++;
     503     1125108 :                 index++;
     504     1125108 :                 total_bytes += bvec->bv_len;
     505     1125108 :                 this_sum_bytes += bvec->bv_len;
     506     1125108 :                 offset += bvec->bv_len;
     507     1125108 :                 bvec++;
     508             :         }
     509             :         this_sum_bytes = 0;
     510       86531 :         btrfs_add_ordered_sum(inode, ordered, sums);
     511       86559 :         btrfs_put_ordered_extent(ordered);
     512       86556 :         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             :  */
     526        8455 : static 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        8455 :         u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
     533             :         u64 csum_end;
     534        8455 :         u64 end_byte = bytenr + len;
     535        8455 :         u32 blocksize_bits = root->fs_info->sb->s_blocksize_bits;
     536             : 
     537        8455 :         leaf = path->nodes[0];
     538       16910 :         csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
     539        8455 :         csum_end <<= root->fs_info->sb->s_blocksize_bits;
     540        8455 :         csum_end += key->offset;
     541             : 
     542       11705 :         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        3250 :                 u32 new_size = (bytenr - key->offset) >> blocksize_bits;
     550        3250 :                 new_size *= csum_size;
     551        3250 :                 btrfs_truncate_item(root, path, new_size, 1);
     552        5205 :         } else if (key->offset >= bytenr && csum_end > end_byte &&
     553        5205 :                    end_byte > key->offset) {
     554             :                 /*
     555             :                  *         [ bytenr - len ]
     556             :                  *                 [ ]
     557             :                  *                 [csum     ]
     558             :                  * we need to truncate from the beginning of the csum
     559             :                  */
     560        5205 :                 u32 new_size = (csum_end - end_byte) >> blocksize_bits;
     561        5205 :                 new_size *= csum_size;
     562             : 
     563        5205 :                 btrfs_truncate_item(root, path, new_size, 0);
     564             : 
     565        5205 :                 key->offset = end_byte;
     566        5205 :                 btrfs_set_item_key_safe(root, path, key);
     567             :         } else {
     568           0 :                 BUG();
     569             :         }
     570        8455 : }
     571             : 
     572             : /*
     573             :  * deletes the csum items from the csum tree for a given
     574             :  * range of bytes.
     575             :  */
     576       16268 : int 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       16268 :         u64 end_byte = bytenr + len;
     582             :         u64 csum_end;
     583             :         struct extent_buffer *leaf;
     584             :         int ret;
     585       32536 :         u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
     586       16268 :         int blocksize_bits = root->fs_info->sb->s_blocksize_bits;
     587             : 
     588       16268 :         root = root->fs_info->csum_root;
     589             : 
     590       16268 :         path = btrfs_alloc_path();
     591       16268 :         if (!path)
     592             :                 return -ENOMEM;
     593             : 
     594             :         while (1) {
     595       23314 :                 key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
     596       23314 :                 key.offset = end_byte - 1;
     597       23314 :                 key.type = BTRFS_EXTENT_CSUM_KEY;
     598             : 
     599       23314 :                 path->leave_spinning = 1;
     600       23314 :                 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
     601       23314 :                 if (ret > 0) {
     602       23314 :                         if (path->slots[0] == 0)
     603             :                                 break;
     604       20700 :                         path->slots[0]--;
     605           0 :                 } else if (ret < 0) {
     606             :                         break;
     607             :                 }
     608             : 
     609       20700 :                 leaf = path->nodes[0];
     610       20700 :                 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
     611             : 
     612       41400 :                 if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
     613       20700 :                     key.type != BTRFS_EXTENT_CSUM_KEY) {
     614             :                         break;
     615             :                 }
     616             : 
     617       20700 :                 if (key.offset >= end_byte)
     618             :                         break;
     619             : 
     620       41400 :                 csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
     621       20700 :                 csum_end <<= blocksize_bits;
     622       20700 :                 csum_end += key.offset;
     623             : 
     624             :                 /* this csum ends before we start, we're done */
     625       20700 :                 if (csum_end <= bytenr)
     626             :                         break;
     627             : 
     628             :                 /* delete the entire item, it is inside our range */
     629       13043 :                 if (key.offset >= bytenr && csum_end <= end_byte) {
     630             :                         ret = btrfs_del_item(trans, root, path);
     631        3405 :                         if (ret)
     632             :                                 goto out;
     633        3405 :                         if (key.offset == bytenr)
     634             :                                 break;
     635       10821 :                 } 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        1183 :                         offset = (bytenr - key.offset) >> blocksize_bits;
     658        1183 :                         offset *= csum_size;
     659             : 
     660        1183 :                         shift_len = (len >> blocksize_bits) * csum_size;
     661             : 
     662        2366 :                         item_offset = btrfs_item_ptr_offset(leaf,
     663             :                                                             path->slots[0]);
     664             : 
     665        1183 :                         memset_extent_buffer(leaf, 0, item_offset + offset,
     666             :                                              shift_len);
     667        1183 :                         key.offset = bytenr;
     668             : 
     669             :                         /*
     670             :                          * btrfs_split_item returns -EAGAIN when the
     671             :                          * item changed size or key
     672             :                          */
     673        1183 :                         ret = btrfs_split_item(trans, root, path, &key, offset);
     674        1183 :                         if (ret && ret != -EAGAIN) {
     675           0 :                                 btrfs_abort_transaction(trans, root, ret);
     676           0 :                                 goto out;
     677             :                         }
     678             : 
     679        1183 :                         key.offset = end_byte - 1;
     680             :                 } else {
     681        8455 :                         truncate_one_csum(root, path, &key, bytenr, len);
     682        8455 :                         if (key.offset < bytenr)
     683             :                                 break;
     684             :                 }
     685        7046 :                 btrfs_release_path(path);
     686        7046 :         }
     687             :         ret = 0;
     688             : out:
     689       16268 :         btrfs_free_path(path);
     690       16268 :         return ret;
     691             : }
     692             : 
     693       93666 : int 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      187332 :         u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
     713             : 
     714       93666 :         path = btrfs_alloc_path();
     715       93674 :         if (!path)
     716             :                 return -ENOMEM;
     717             : again:
     718             :         next_offset = (u64)-1;
     719             :         found_next = 0;
     720       94836 :         bytenr = sums->bytenr + total_bytes;
     721       94836 :         file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
     722       94836 :         file_key.offset = bytenr;
     723             :         btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY);
     724             : 
     725       94836 :         item = btrfs_lookup_csum(trans, root, path, bytenr, 1);
     726       94839 :         if (!IS_ERR(item)) {
     727             :                 ret = 0;
     728        1084 :                 leaf = path->nodes[0];
     729        2168 :                 item_end = btrfs_item_ptr(leaf, path->slots[0],
     730             :                                           struct btrfs_csum_item);
     731        1084 :                 item_end = (struct btrfs_csum_item *)((char *)item_end +
     732        1084 :                            btrfs_item_size_nr(leaf, path->slots[0]));
     733        1084 :                 goto found;
     734             :         }
     735       93755 :         ret = PTR_ERR(item);
     736       93755 :         if (ret != -EFBIG && ret != -ENOENT)
     737             :                 goto fail_unlock;
     738             : 
     739       93755 :         if (ret == -EFBIG) {
     740             :                 u32 item_size;
     741             :                 /* we found one, but it isn't big enough yet */
     742       82031 :                 leaf = path->nodes[0];
     743       82031 :                 item_size = btrfs_item_size_nr(leaf, path->slots[0]);
     744      164060 :                 if ((item_size / csum_size) >=
     745       82030 :                     MAX_CSUM_ITEMS(root, csum_size)) {
     746             :                         /* already at max size, make a new one */
     747             :                         goto insert;
     748             :                 }
     749             :         } else {
     750       11724 :                 int slot = path->slots[0] + 1;
     751             :                 /* we didn't find a csum item, insert one */
     752       11724 :                 nritems = btrfs_header_nritems(path->nodes[0]);
     753       11724 :                 if (!nritems || (path->slots[0] >= nritems - 1)) {
     754        7149 :                         ret = btrfs_next_leaf(root, path);
     755        7148 :                         if (ret == 1)
     756             :                                 found_next = 1;
     757        7148 :                         if (ret != 0)
     758             :                                 goto insert;
     759          95 :                         slot = path->slots[0];
     760             :                 }
     761        4670 :                 btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot);
     762        9340 :                 if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
     763        4670 :                     found_key.type != BTRFS_EXTENT_CSUM_KEY) {
     764             :                         found_next = 1;
     765             :                         goto insert;
     766             :                 }
     767        4670 :                 next_offset = found_key.offset;
     768             :                 found_next = 1;
     769        4670 :                 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       82029 :         btrfs_release_path(path);
     777       82027 :         ret = btrfs_search_slot(trans, root, &file_key, path,
     778             :                                 csum_size, 1);
     779       82031 :         if (ret < 0)
     780             :                 goto fail_unlock;
     781             : 
     782       82031 :         if (ret > 0) {
     783       82031 :                 if (path->slots[0] == 0)
     784             :                         goto insert;
     785       82005 :                 path->slots[0]--;
     786             :         }
     787             : 
     788       82005 :         leaf = path->nodes[0];
     789       82005 :         btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
     790      164010 :         csum_offset = (bytenr - found_key.offset) >>
     791       82005 :                         root->fs_info->sb->s_blocksize_bits;
     792             : 
     793      164010 :         if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY ||
     794      164010 :             found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
     795       82005 :             csum_offset >= MAX_CSUM_ITEMS(root, csum_size)) {
     796             :                 goto insert;
     797             :         }
     798             : 
     799      164010 :         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      164010 :                 if (btrfs_leaf_free_space(root, leaf) <
     807       82005 :                                  sizeof(struct btrfs_item) + csum_size * 2)
     808             :                         goto insert;
     809             : 
     810       81370 :                 free_space = btrfs_leaf_free_space(root, leaf) -
     811             :                                          sizeof(struct btrfs_item) - csum_size;
     812       81370 :                 tmp = sums->len - total_bytes;
     813       81370 :                 tmp >>= root->fs_info->sb->s_blocksize_bits;
     814       81370 :                 WARN_ON(tmp < 1);
     815             : 
     816       81370 :                 extend_nr = max_t(int, 1, (int)tmp);
     817       81370 :                 diff = (csum_offset + extend_nr) * csum_size;
     818       81370 :                 diff = min(diff, MAX_CSUM_ITEMS(root, csum_size) * csum_size);
     819             : 
     820      162740 :                 diff = diff - btrfs_item_size_nr(leaf, path->slots[0]);
     821       81370 :                 diff = min(free_space, diff);
     822       81370 :                 diff /= csum_size;
     823       81370 :                 diff *= csum_size;
     824             : 
     825       81370 :                 btrfs_extend_item(root, path, diff);
     826             :                 ret = 0;
     827       81368 :                 goto csum;
     828             :         }
     829             : 
     830             : insert:
     831       12385 :         btrfs_release_path(path);
     832             :         csum_offset = 0;
     833       12383 :         if (found_next) {
     834             :                 u64 tmp;
     835             : 
     836       11721 :                 tmp = sums->len - total_bytes;
     837       11721 :                 tmp >>= root->fs_info->sb->s_blocksize_bits;
     838       11721 :                 tmp = min(tmp, (next_offset - file_key.offset) >>
     839             :                                          root->fs_info->sb->s_blocksize_bits);
     840             : 
     841       11721 :                 tmp = max((u64)1, tmp);
     842       11721 :                 tmp = min(tmp, (u64)MAX_CSUM_ITEMS(root, csum_size));
     843       11721 :                 ins_size = csum_size * tmp;
     844             :         } else {
     845         662 :                 ins_size = csum_size;
     846             :         }
     847       12383 :         path->leave_spinning = 1;
     848             :         ret = btrfs_insert_empty_item(trans, root, path, &file_key,
     849             :                                       ins_size);
     850       12386 :         path->leave_spinning = 0;
     851       12386 :         if (ret < 0)
     852             :                 goto fail_unlock;
     853       12386 :         if (WARN_ON(ret != 0))
     854             :                 goto fail_unlock;
     855       12386 :         leaf = path->nodes[0];
     856             : csum:
     857      187507 :         item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
     858       93753 :         item_end = (struct btrfs_csum_item *)((unsigned char *)item +
     859       93753 :                                       btrfs_item_size_nr(leaf, path->slots[0]));
     860       93753 :         item = (struct btrfs_csum_item *)((unsigned char *)item +
     861             :                                           csum_offset * csum_size);
     862             : found:
     863      189674 :         ins_size = (u32)(sums->len - total_bytes) >>
     864       94837 :                    root->fs_info->sb->s_blocksize_bits;
     865       94837 :         ins_size *= csum_size;
     866       94837 :         ins_size = min_t(u32, (unsigned long)item_end - (unsigned long)item,
     867             :                               ins_size);
     868       94837 :         write_extent_buffer(leaf, sums->sums + index, (unsigned long)item,
     869             :                             ins_size);
     870             : 
     871       94837 :         ins_size /= csum_size;
     872       94837 :         total_bytes += ins_size * root->sectorsize;
     873       94837 :         index += ins_size;
     874             : 
     875       94837 :         btrfs_mark_buffer_dirty(path->nodes[0]);
     876       94840 :         if (total_bytes < sums->len) {
     877        1162 :                 btrfs_release_path(path);
     878        1162 :                 cond_resched();
     879        1162 :                 goto again;
     880             :         }
     881             : out:
     882       93678 :         btrfs_free_path(path);
     883       93677 :         return ret;
     884             : 
     885             : fail_unlock:
     886             :         goto out;
     887             : }
     888             : 
     889       30816 : void 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       30816 :         struct btrfs_root *root = BTRFS_I(inode)->root;
     896       30816 :         struct extent_buffer *leaf = path->nodes[0];
     897       30816 :         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       30816 :         int compress_type = btrfs_file_extent_compression(leaf, fi);
     903             : 
     904       30816 :         em->bdev = root->fs_info->fs_devices->latest_bdev;
     905       30816 :         btrfs_item_key_to_cpu(leaf, &key, slot);
     906       30816 :         extent_start = key.offset;
     907             : 
     908       30816 :         if (type == BTRFS_FILE_EXTENT_REG ||
     909             :             type == BTRFS_FILE_EXTENT_PREALLOC) {
     910       30319 :                 extent_end = extent_start +
     911             :                         btrfs_file_extent_num_bytes(leaf, fi);
     912         497 :         } else if (type == BTRFS_FILE_EXTENT_INLINE) {
     913             :                 size_t size;
     914         497 :                 size = btrfs_file_extent_inline_len(leaf, slot, fi);
     915         497 :                 extent_end = ALIGN(extent_start + size, root->sectorsize);
     916             :         }
     917             : 
     918       30816 :         em->ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
     919       30816 :         if (type == BTRFS_FILE_EXTENT_REG ||
     920             :             type == BTRFS_FILE_EXTENT_PREALLOC) {
     921       30319 :                 em->start = extent_start;
     922       30319 :                 em->len = extent_end - extent_start;
     923       30319 :                 em->orig_start = extent_start -
     924             :                         btrfs_file_extent_offset(leaf, fi);
     925       30319 :                 em->orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi);
     926             :                 bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
     927       30319 :                 if (bytenr == 0) {
     928         942 :                         em->block_start = EXTENT_MAP_HOLE;
     929       31758 :                         return;
     930             :                 }
     931       29377 :                 if (compress_type != BTRFS_COMPRESS_NONE) {
     932             :                         set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
     933          42 :                         em->compress_type = compress_type;
     934          42 :                         em->block_start = bytenr;
     935          42 :                         em->block_len = em->orig_block_len;
     936             :                 } else {
     937       29335 :                         bytenr += btrfs_file_extent_offset(leaf, fi);
     938       29335 :                         em->block_start = bytenr;
     939       29335 :                         em->block_len = em->len;
     940       29335 :                         if (type == BTRFS_FILE_EXTENT_PREALLOC)
     941             :                                 set_bit(EXTENT_FLAG_PREALLOC, &em->flags);
     942             :                 }
     943         497 :         } else if (type == BTRFS_FILE_EXTENT_INLINE) {
     944         497 :                 em->block_start = EXTENT_MAP_INLINE;
     945         497 :                 em->start = extent_start;
     946         497 :                 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         497 :                 em->orig_start = EXTENT_MAP_HOLE;
     952         497 :                 em->block_len = (u64)-1;
     953         497 :                 if (!new_inline && compress_type != BTRFS_COMPRESS_NONE) {
     954             :                         set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
     955           0 :                         em->compress_type = compress_type;
     956             :                 }
     957             :         } else {
     958           0 :                 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             : }

Generated by: LCOV version 1.10