]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/inode.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[karo-tx-linux.git] / fs / btrfs / inode.c
index 77fb24b94a9ebaf1ed75719ab9f15eebaee8134a..2315039356529fac0315a57733a035d86a00b3b1 100644 (file)
@@ -432,8 +432,6 @@ static noinline void compress_file_range(struct inode *inode,
        unsigned long nr_pages;
        unsigned long total_compressed = 0;
        unsigned long total_in = 0;
-       unsigned long max_compressed = SZ_128K;
-       unsigned long max_uncompressed = SZ_128K;
        int i;
        int will_compress;
        int compress_type = fs_info->compress_type;
@@ -446,7 +444,9 @@ static noinline void compress_file_range(struct inode *inode,
 again:
        will_compress = 0;
        nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
-       nr_pages = min_t(unsigned long, nr_pages, SZ_128K / PAGE_SIZE);
+       BUILD_BUG_ON((BTRFS_MAX_COMPRESSED % PAGE_SIZE) != 0);
+       nr_pages = min_t(unsigned long, nr_pages,
+                       BTRFS_MAX_COMPRESSED / PAGE_SIZE);
 
        /*
         * we don't want to send crud past the end of i_size through
@@ -471,7 +471,8 @@ again:
           (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size))
                goto cleanup_and_bail_uncompressed;
 
-       total_compressed = min(total_compressed, max_uncompressed);
+       total_compressed = min_t(unsigned long, total_compressed,
+                       BTRFS_MAX_UNCOMPRESSED);
        num_bytes = ALIGN(end - start + 1, blocksize);
        num_bytes = max(blocksize,  num_bytes);
        total_in = 0;
@@ -509,8 +510,7 @@ again:
                                           pages,
                                           &nr_pages,
                                           &total_in,
-                                          &total_compressed,
-                                          max_compressed);
+                                          &total_compressed);
 
                if (!ret) {
                        unsigned long offset = total_compressed &
@@ -1323,10 +1323,16 @@ next_slot:
                         * either valid or do not exist.
                         */
                        if (csum_exist_in_range(fs_info, disk_bytenr,
-                                               num_bytes))
+                                               num_bytes)) {
+                               if (!nolock)
+                                       btrfs_end_write_no_snapshoting(root);
                                goto out_check;
-                       if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr))
+                       }
+                       if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr)) {
+                               if (!nolock)
+                                       btrfs_end_write_no_snapshoting(root);
                                goto out_check;
+                       }
                        nocow = 1;
                } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                        extent_end = found_key.offset +
@@ -2972,7 +2978,7 @@ static void finish_ordered_fn(struct btrfs_work *work)
        btrfs_finish_ordered_io(ordered_extent);
 }
 
-static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
+static void btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
                                struct extent_state *state, int uptodate)
 {
        struct inode *inode = page->mapping->host;
@@ -2986,7 +2992,7 @@ static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
        ClearPagePrivate2(page);
        if (!btrfs_dec_test_ordered_pending(inode, &ordered_extent, start,
                                            end - start + 1, uptodate))
-               return 0;
+               return;
 
        if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
                wq = fs_info->endio_freespace_worker;
@@ -2999,8 +3005,6 @@ static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
        btrfs_init_work(&ordered_extent->work, func, finish_ordered_fn, NULL,
                        NULL);
        btrfs_queue_work(wq, &ordered_extent->work);
-
-       return 0;
 }
 
 static int __readpage_endio_check(struct inode *inode,
@@ -4406,19 +4410,8 @@ search_again:
                if (found_type > min_type) {
                        del_item = 1;
                } else {
-                       if (item_end < new_size) {
-                               /*
-                                * With NO_HOLES mode, for the following mapping
-                                *
-                                * [0-4k][hole][8k-12k]
-                                *
-                                * if truncating isize down to 6k, it ends up
-                                * isize being 8k.
-                                */
-                               if (btrfs_fs_incompat(root->fs_info, NO_HOLES))
-                                       last_size = new_size;
+                       if (item_end < new_size)
                                break;
-                       }
                        if (found_key.offset >= new_size)
                                del_item = 1;
                        else
@@ -4601,8 +4594,12 @@ out:
                        btrfs_abort_transaction(trans, ret);
        }
 error:
-       if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
+       if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
+               ASSERT(last_size >= new_size);
+               if (!err && last_size > new_size)
+                       last_size = new_size;
                btrfs_ordered_update_i_size(inode, last_size, NULL);
+       }
 
        btrfs_free_path(path);
 
@@ -6712,6 +6709,20 @@ static noinline int uncompress_inline(struct btrfs_path *path,
        max_size = min_t(unsigned long, PAGE_SIZE, max_size);
        ret = btrfs_decompress(compress_type, tmp, page,
                               extent_offset, inline_size, max_size);
+
+       /*
+        * decompression code contains a memset to fill in any space between the end
+        * of the uncompressed data and the end of max_size in case the decompressed
+        * data ends up shorter than ram_bytes.  That doesn't cover the hole between
+        * the end of an inline extent and the beginning of the next block, so we
+        * cover that region here.
+        */
+
+       if (max_size + pg_offset < PAGE_SIZE) {
+               char *map = kmap(page);
+               memset(map + pg_offset + max_size, 0, PAGE_SIZE - max_size - pg_offset);
+               kunmap(page);
+       }
        kfree(tmp);
        return ret;
 }
@@ -8897,10 +8908,10 @@ again:
  * beyond EOF, then the page is guaranteed safe against truncation until we
  * unlock the page.
  */
-int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+int btrfs_page_mkwrite(struct vm_fault *vmf)
 {
        struct page *page = vmf->page;
-       struct inode *inode = file_inode(vma->vm_file);
+       struct inode *inode = file_inode(vmf->vma->vm_file);
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
        struct btrfs_ordered_extent *ordered;
@@ -8933,7 +8944,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        ret = btrfs_delalloc_reserve_space(inode, page_start,
                                           reserved_space);
        if (!ret) {
-               ret = file_update_time(vma->vm_file);
+               ret = file_update_time(vmf->vma->vm_file);
                reserved = 1;
        }
        if (ret) {
@@ -9416,11 +9427,11 @@ fail:
        return -ENOMEM;
 }
 
-static int btrfs_getattr(struct vfsmount *mnt,
-                        struct dentry *dentry, struct kstat *stat)
+static int btrfs_getattr(const struct path *path, struct kstat *stat,
+                        u32 request_mask, unsigned int flags)
 {
        u64 delalloc_bytes;
-       struct inode *inode = d_inode(dentry);
+       struct inode *inode = d_inode(path->dentry);
        u32 blocksize = inode->i_sb->s_blocksize;
 
        generic_fillattr(inode, stat);
@@ -10511,6 +10522,12 @@ out_inode:
 
 }
 
+__attribute__((const))
+static int dummy_readpage_io_failed_hook(struct page *page, int failed_mirror)
+{
+       return 0;
+}
+
 static const struct inode_operations btrfs_dir_inode_operations = {
        .getattr        = btrfs_getattr,
        .lookup         = btrfs_lookup,
@@ -10549,10 +10566,14 @@ static const struct file_operations btrfs_dir_file_operations = {
 };
 
 static const struct extent_io_ops btrfs_extent_io_ops = {
-       .fill_delalloc = run_delalloc_range,
+       /* mandatory callbacks */
        .submit_bio_hook = btrfs_submit_bio_hook,
-       .merge_bio_hook = btrfs_merge_bio_hook,
        .readpage_end_io_hook = btrfs_readpage_end_io_hook,
+       .merge_bio_hook = btrfs_merge_bio_hook,
+       .readpage_io_failed_hook = dummy_readpage_io_failed_hook,
+
+       /* optional callbacks */
+       .fill_delalloc = run_delalloc_range,
        .writepage_end_io_hook = btrfs_writepage_end_io_hook,
        .writepage_start_hook = btrfs_writepage_start_hook,
        .set_bit_hook = btrfs_set_bit_hook,