]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 9 Feb 2014 19:12:26 +0000 (11:12 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 9 Feb 2014 19:12:26 +0000 (11:12 -0800)
Pull btrfs fixes from Chris Mason:
 "This is a small collection of fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: fix data corruption when reading/updating compressed extents
  Btrfs: don't loop forever if we can't run because of the tree mod log
  btrfs: reserve no transaction units in btrfs_ioctl_set_features
  btrfs: commit transaction after setting label and features
  Btrfs: fix assert screwup for the pending move stuff

1  2 
fs/btrfs/compression.c
fs/btrfs/ioctl.c

diff --combined fs/btrfs/compression.c
index e2600cdb6c257e366b873445c396a917249e76f3,ed1ff1cb101771c1b8c52abec38905cb68c3f107..b01fb6c527e32e7443cc5d461138222d5b538b9d
@@@ -171,8 -171,7 +171,8 @@@ static void end_compressed_bio_read(str
                goto out;
  
        inode = cb->inode;
 -      ret = check_compressed_csum(inode, cb, (u64)bio->bi_sector << 9);
 +      ret = check_compressed_csum(inode, cb,
 +                                  (u64)bio->bi_iter.bi_sector << 9);
        if (ret)
                goto csum_failed;
  
@@@ -201,16 -200,18 +201,16 @@@ csum_failed
        if (cb->errors) {
                bio_io_error(cb->orig_bio);
        } else {
 -              int bio_index = 0;
 -              struct bio_vec *bvec = cb->orig_bio->bi_io_vec;
 +              int i;
 +              struct bio_vec *bvec;
  
                /*
                 * we have verified the checksum already, set page
                 * checked so the end_io handlers know about it
                 */
 -              while (bio_index < cb->orig_bio->bi_vcnt) {
 +              bio_for_each_segment_all(bvec, cb->orig_bio, i)
                        SetPageChecked(bvec->bv_page);
 -                      bvec++;
 -                      bio_index++;
 -              }
 +
                bio_endio(cb->orig_bio, 0);
        }
  
@@@ -370,7 -371,7 +370,7 @@@ int btrfs_submit_compressed_write(struc
        for (pg_index = 0; pg_index < cb->nr_pages; pg_index++) {
                page = compressed_pages[pg_index];
                page->mapping = inode->i_mapping;
 -              if (bio->bi_size)
 +              if (bio->bi_iter.bi_size)
                        ret = io_tree->ops->merge_bio_hook(WRITE, page, 0,
                                                           PAGE_CACHE_SIZE,
                                                           bio, 0);
@@@ -505,7 -506,7 +505,7 @@@ static noinline int add_ra_bio_pages(st
  
                if (!em || last_offset < em->start ||
                    (last_offset + PAGE_CACHE_SIZE > extent_map_end(em)) ||
 -                  (em->block_start >> 9) != cb->orig_bio->bi_sector) {
 +                  (em->block_start >> 9) != cb->orig_bio->bi_iter.bi_sector) {
                        free_extent_map(em);
                        unlock_extent(tree, last_offset, end);
                        unlock_page(page);
@@@ -551,7 -552,7 +551,7 @@@ next
   * in it.  We don't actually do IO on those pages but allocate new ones
   * to hold the compressed pages on disk.
   *
 - * bio->bi_sector points to the compressed extent on disk
 + * bio->bi_iter.bi_sector points to the compressed extent on disk
   * bio->bi_io_vec points to all of the inode pages
   * bio->bi_vcnt is a count of pages
   *
@@@ -572,7 -573,7 +572,7 @@@ int btrfs_submit_compressed_read(struc
        struct page *page;
        struct block_device *bdev;
        struct bio *comp_bio;
 -      u64 cur_disk_byte = (u64)bio->bi_sector << 9;
 +      u64 cur_disk_byte = (u64)bio->bi_iter.bi_sector << 9;
        u64 em_len;
        u64 em_start;
        struct extent_map *em;
                page->mapping = inode->i_mapping;
                page->index = em_start >> PAGE_CACHE_SHIFT;
  
 -              if (comp_bio->bi_size)
 +              if (comp_bio->bi_iter.bi_size)
                        ret = tree->ops->merge_bio_hook(READ, page, 0,
                                                        PAGE_CACHE_SIZE,
                                                        comp_bio, 0);
                                                        comp_bio, sums);
                                BUG_ON(ret); /* -ENOMEM */
                        }
 -                      sums += (comp_bio->bi_size + root->sectorsize - 1) /
 -                              root->sectorsize;
 +                      sums += (comp_bio->bi_iter.bi_size +
 +                               root->sectorsize - 1) / root->sectorsize;
  
                        ret = btrfs_map_bio(root, READ, comp_bio,
                                            mirror_num, 0);
@@@ -1010,6 -1011,8 +1010,8 @@@ int btrfs_decompress_buf2page(char *buf
                bytes = min(bytes, working_bytes);
                kaddr = kmap_atomic(page_out);
                memcpy(kaddr + *pg_offset, buf + buf_offset, bytes);
+               if (*pg_index == (vcnt - 1) && *pg_offset == 0)
+                       memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
                kunmap_atomic(kaddr);
                flush_dcache_page(page_out);
  
diff --combined fs/btrfs/ioctl.c
index b0134892dc70cdf69be04ad44e3e52183a86fcb0,ebdd866d4cfd0de8b67c426d9b2b6d0c79745778..383ab455bfa7ce421f0f0c380224a10820e3801e
@@@ -2735,11 -2735,14 +2735,11 @@@ out_unlock
  #define BTRFS_MAX_DEDUPE_LEN  (16 * 1024 * 1024)
  
  static long btrfs_ioctl_file_extent_same(struct file *file,
 -                                       void __user *argp)
 +                      struct btrfs_ioctl_same_args __user *argp)
  {
 -      struct btrfs_ioctl_same_args tmp;
        struct btrfs_ioctl_same_args *same;
        struct btrfs_ioctl_same_extent_info *info;
 -      struct inode *src = file->f_dentry->d_inode;
 -      struct file *dst_file = NULL;
 -      struct inode *dst;
 +      struct inode *src = file_inode(file);
        u64 off;
        u64 len;
        int i;
        unsigned long size;
        u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;
        bool is_admin = capable(CAP_SYS_ADMIN);
 +      u16 count;
  
        if (!(file->f_mode & FMODE_READ))
                return -EINVAL;
        if (ret)
                return ret;
  
 -      if (copy_from_user(&tmp,
 -                         (struct btrfs_ioctl_same_args __user *)argp,
 -                         sizeof(tmp))) {
 +      if (get_user(count, &argp->dest_count)) {
                ret = -EFAULT;
                goto out;
        }
  
 -      size = sizeof(tmp) +
 -              tmp.dest_count * sizeof(struct btrfs_ioctl_same_extent_info);
 +      size = offsetof(struct btrfs_ioctl_same_args __user, info[count]);
  
 -      same = memdup_user((struct btrfs_ioctl_same_args __user *)argp, size);
 +      same = memdup_user(argp, size);
  
        if (IS_ERR(same)) {
                ret = PTR_ERR(same);
                goto out;
  
        /* pre-format output fields to sane values */
 -      for (i = 0; i < same->dest_count; i++) {
 +      for (i = 0; i < count; i++) {
                same->info[i].bytes_deduped = 0ULL;
                same->info[i].status = 0;
        }
  
 -      ret = 0;
 -      for (i = 0; i < same->dest_count; i++) {
 -              info = &same->info[i];
 -
 -              dst_file = fget(info->fd);
 -              if (!dst_file) {
 +      for (i = 0, info = same->info; i < count; i++, info++) {
 +              struct inode *dst;
 +              struct fd dst_file = fdget(info->fd);
 +              if (!dst_file.file) {
                        info->status = -EBADF;
 -                      goto next;
 +                      continue;
                }
 +              dst = file_inode(dst_file.file);
  
 -              if (!(is_admin || (dst_file->f_mode & FMODE_WRITE))) {
 +              if (!(is_admin || (dst_file.file->f_mode & FMODE_WRITE))) {
                        info->status = -EINVAL;
 -                      goto next;
 -              }
 -
 -              info->status = -EXDEV;
 -              if (file->f_path.mnt != dst_file->f_path.mnt)
 -                      goto next;
 -
 -              dst = dst_file->f_dentry->d_inode;
 -              if (src->i_sb != dst->i_sb)
 -                      goto next;
 -
 -              if (S_ISDIR(dst->i_mode)) {
 +              } else if (file->f_path.mnt != dst_file.file->f_path.mnt) {
 +                      info->status = -EXDEV;
 +              } else if (S_ISDIR(dst->i_mode)) {
                        info->status = -EISDIR;
 -                      goto next;
 -              }
 -
 -              if (!S_ISREG(dst->i_mode)) {
 +              } else if (!S_ISREG(dst->i_mode)) {
                        info->status = -EACCES;
 -                      goto next;
 +              } else {
 +                      info->status = btrfs_extent_same(src, off, len, dst,
 +                                                      info->logical_offset);
 +                      if (info->status == 0)
 +                              info->bytes_deduped += len;
                }
 -
 -              info->status = btrfs_extent_same(src, off, len, dst,
 -                                              info->logical_offset);
 -              if (info->status == 0)
 -                      info->bytes_deduped += len;
 -
 -next:
 -              if (dst_file)
 -                      fput(dst_file);
 +              fdput(dst_file);
        }
  
        ret = copy_to_user(argp, same, size);
@@@ -4525,7 -4547,7 +4525,7 @@@ static int btrfs_ioctl_set_fslabel(stru
        spin_lock(&root->fs_info->super_lock);
        strcpy(super_block->label, label);
        spin_unlock(&root->fs_info->super_lock);
-       ret = btrfs_end_transaction(trans, root);
+       ret = btrfs_commit_transaction(trans, root);
  
  out_unlock:
        mnt_drop_write_file(file);
@@@ -4668,7 -4690,7 +4668,7 @@@ static int btrfs_ioctl_set_features(str
        if (ret)
                return ret;
  
-       trans = btrfs_start_transaction(root, 1);
+       trans = btrfs_start_transaction(root, 0);
        if (IS_ERR(trans))
                return PTR_ERR(trans);
  
        btrfs_set_super_incompat_flags(super_block, newflags);
        spin_unlock(&root->fs_info->super_lock);
  
-       return btrfs_end_transaction(trans, root);
+       return btrfs_commit_transaction(trans, root);
  }
  
  long btrfs_ioctl(struct file *file, unsigned int