]> 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 3b327c8cfb166156bd12ef342fe47a467b894bbc..2315039356529fac0315a57733a035d86a00b3b1 100644 (file)
@@ -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 +
@@ -4404,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
@@ -4599,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);
 
@@ -6710,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;
 }
@@ -8895,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;
@@ -8931,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) {
@@ -9414,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);
@@ -10509,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,
@@ -10551,6 +10570,7 @@ static const struct extent_io_ops btrfs_extent_io_ops = {
        .submit_bio_hook = btrfs_submit_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,