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