]> 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, 27 Apr 2014 20:26:28 +0000 (13:26 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Apr 2014 20:26:28 +0000 (13:26 -0700)
Pull btrfs fixes from Chris Mason.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: limit the path size in send to PATH_MAX
  Btrfs: correctly set profile flags on seqlock retry
  Btrfs: use correct key when repeating search for extent item
  Btrfs: fix inode caching vs tree log
  Btrfs: fix possible memory leaks in open_ctree()
  Btrfs: avoid triggering bug_on() when we fail to start inode caching task
  Btrfs: move btrfs_{set,clear}_and_info() to ctree.h
  btrfs: replace error code from btrfs_drop_extents
  btrfs: Change the hole range to a more accurate value.
  btrfs: fix use-after-free in mount_subvol()

1  2 
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/file.c
fs/btrfs/ioctl.c
fs/btrfs/super.c

diff --combined fs/btrfs/ctree.h
index 4c48df572bd65d74636df643c77acda204af5418,e7c9e1c540f441e4135940d6a8cf5b0c02a2f12d..ba6b88528dc7eb28b9fe282cc2370f43fa7ea7d4
@@@ -2058,6 -2058,20 +2058,20 @@@ struct btrfs_ioctl_defrag_range_args 
  #define btrfs_raw_test_opt(o, opt)    ((o) & BTRFS_MOUNT_##opt)
  #define btrfs_test_opt(root, opt)     ((root)->fs_info->mount_opt & \
                                         BTRFS_MOUNT_##opt)
+ #define btrfs_set_and_info(root, opt, fmt, args...)                   \
+ {                                                                     \
+       if (!btrfs_test_opt(root, opt))                                 \
+               btrfs_info(root->fs_info, fmt, ##args);                 \
+       btrfs_set_opt(root->fs_info->mount_opt, opt);                   \
+ }
+ #define btrfs_clear_and_info(root, opt, fmt, args...)                 \
+ {                                                                     \
+       if (btrfs_test_opt(root, opt))                                  \
+               btrfs_info(root->fs_info, fmt, ##args);                 \
+       btrfs_clear_opt(root->fs_info->mount_opt, opt);                 \
+ }
  /*
   * Inode flags
   */
@@@ -3992,17 -4006,20 +4006,17 @@@ do {                                                                 
  /* acl.c */
  #ifdef CONFIG_BTRFS_FS_POSIX_ACL
  struct posix_acl *btrfs_get_acl(struct inode *inode, int type);
 +int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
  int btrfs_init_acl(struct btrfs_trans_handle *trans,
                   struct inode *inode, struct inode *dir);
 -int btrfs_acl_chmod(struct inode *inode);
  #else
  #define btrfs_get_acl NULL
 +#define btrfs_set_acl NULL
  static inline int btrfs_init_acl(struct btrfs_trans_handle *trans,
                                 struct inode *inode, struct inode *dir)
  {
        return 0;
  }
 -static inline int btrfs_acl_chmod(struct inode *inode)
 -{
 -      return 0;
 -}
  #endif
  
  /* relocation.c */
diff --combined fs/btrfs/disk-io.c
index 029d46c2e17048a20a02e7cb34955d22ff80e752,0e4fb4a5c7f0a40a7152e6f6883a8672737b4ff7..983314932af3cc51260753b8acf807a98ce0988a
@@@ -854,17 -854,20 +854,17 @@@ int btrfs_wq_submit_bio(struct btrfs_fs
  
  static int btree_csum_one_bio(struct bio *bio)
  {
 -      struct bio_vec *bvec = bio->bi_io_vec;
 -      int bio_index = 0;
 +      struct bio_vec *bvec;
        struct btrfs_root *root;
 -      int ret = 0;
 +      int i, ret = 0;
  
 -      WARN_ON(bio->bi_vcnt <= 0);
 -      while (bio_index < bio->bi_vcnt) {
 +      bio_for_each_segment_all(bvec, bio, i) {
                root = BTRFS_I(bvec->bv_page->mapping->host)->root;
                ret = csum_dirty_buffer(root, bvec->bv_page);
                if (ret)
                        break;
 -              bio_index++;
 -              bvec++;
        }
 +
        return ret;
  }
  
@@@ -1735,7 -1738,7 +1735,7 @@@ static void end_workqueue_fn(struct btr
        bio->bi_private = end_io_wq->private;
        bio->bi_end_io = end_io_wq->end_io;
        kfree(end_io_wq);
 -      bio_endio(bio, error);
 +      bio_endio_nodec(bio, error);
  }
  
  static int cleaner_kthread(void *arg)
@@@ -2861,7 -2864,7 +2861,7 @@@ retry_root_backup
                        printk(KERN_ERR "BTRFS: failed to read log tree\n");
                        free_extent_buffer(log_tree_root->node);
                        kfree(log_tree_root);
-                       goto fail_trans_kthread;
+                       goto fail_qgroup;
                }
                /* returns with log_tree_root freed on success */
                ret = btrfs_recover_log_trees(log_tree_root);
                                    "Failed to recover log tree");
                        free_extent_buffer(log_tree_root->node);
                        kfree(log_tree_root);
-                       goto fail_trans_kthread;
+                       goto fail_qgroup;
                }
  
                if (sb->s_flags & MS_RDONLY) {
                        ret = btrfs_commit_super(tree_root);
                        if (ret)
-                               goto fail_trans_kthread;
+                               goto fail_qgroup;
                }
        }
  
        ret = btrfs_find_orphan_roots(tree_root);
        if (ret)
-               goto fail_trans_kthread;
+               goto fail_qgroup;
  
        if (!(sb->s_flags & MS_RDONLY)) {
                ret = btrfs_cleanup_fs_roots(fs_info);
                if (ret)
-                       goto fail_trans_kthread;
+                       goto fail_qgroup;
  
                ret = btrfs_recover_relocation(tree_root);
                if (ret < 0) {
diff --combined fs/btrfs/file.c
index eb742c07e7a41aacdb595b0252a12b3584bbee83,1eee3f79d75fe319ae8f6fdc4a1c8b4b07d170fe..ae6af072b635e195e26f3199c3aabd427964881f
@@@ -425,8 -425,13 +425,8 @@@ static noinline int btrfs_copy_from_use
                struct page *page = prepared_pages[pg];
                /*
                 * Copy data from userspace to the current page
 -               *
 -               * Disable pagefault to avoid recursive lock since
 -               * the pages are already locked
                 */
 -              pagefault_disable();
                copied = iov_iter_copy_from_user_atomic(page, i, offset, count);
 -              pagefault_enable();
  
                /* Flush processor's dcache for this page */
                flush_dcache_page(page);
@@@ -800,7 -805,7 +800,7 @@@ next_slot
                if (start > key.offset && end < extent_end) {
                        BUG_ON(del_nr > 0);
                        if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
-                               ret = -EINVAL;
+                               ret = -EOPNOTSUPP;
                                break;
                        }
  
                 */
                if (start <= key.offset && end < extent_end) {
                        if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
-                               ret = -EINVAL;
+                               ret = -EOPNOTSUPP;
                                break;
                        }
  
                if (start > key.offset && end >= extent_end) {
                        BUG_ON(del_nr > 0);
                        if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
-                               ret = -EINVAL;
+                               ret = -EOPNOTSUPP;
                                break;
                        }
  
@@@ -1660,7 -1665,7 +1660,7 @@@ again
  static ssize_t __btrfs_direct_write(struct kiocb *iocb,
                                    const struct iovec *iov,
                                    unsigned long nr_segs, loff_t pos,
 -                                  loff_t *ppos, size_t count, size_t ocount)
 +                                  size_t count, size_t ocount)
  {
        struct file *file = iocb->ki_filp;
        struct iov_iter i;
        loff_t endbyte;
        int err;
  
 -      written = generic_file_direct_write(iocb, iov, &nr_segs, pos, ppos,
 +      written = generic_file_direct_write(iocb, iov, &nr_segs, pos,
                                            count, ocount);
  
        if (written < 0 || written == count)
        if (err)
                goto out;
        written += written_buffered;
 -      *ppos = pos + written_buffered;
 +      iocb->ki_pos = pos + written_buffered;
        invalidate_mapping_pages(file->f_mapping, pos >> PAGE_CACHE_SHIFT,
                                 endbyte >> PAGE_CACHE_SHIFT);
  out:
@@@ -1720,6 -1725,7 +1720,6 @@@ static ssize_t btrfs_file_aio_write(str
        struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
        struct btrfs_root *root = BTRFS_I(inode)->root;
 -      loff_t *ppos = &iocb->ki_pos;
        u64 start_pos;
        u64 end_pos;
        ssize_t num_written = 0;
        start_pos = round_down(pos, root->sectorsize);
        if (start_pos > i_size_read(inode)) {
                /* Expand hole size to cover write data, preventing empty gap */
-               end_pos = round_up(pos + iov->iov_len, root->sectorsize);
+               end_pos = round_up(pos + count, root->sectorsize);
                err = btrfs_cont_expand(inode, i_size_read(inode), end_pos);
                if (err) {
                        mutex_unlock(&inode->i_mutex);
  
        if (unlikely(file->f_flags & O_DIRECT)) {
                num_written = __btrfs_direct_write(iocb, iov, nr_segs,
 -                                                 pos, ppos, count, ocount);
 +                                                 pos, count, ocount);
        } else {
                struct iov_iter i;
  
  
                num_written = __btrfs_buffered_write(file, &i, pos);
                if (num_written > 0)
 -                      *ppos = pos + num_written;
 +                      iocb->ki_pos = pos + num_written;
        }
  
        mutex_unlock(&inode->i_mutex);
        BTRFS_I(inode)->last_sub_trans = root->log_transid;
        if (num_written > 0) {
                err = generic_write_sync(file, pos, num_written);
 -              if (err < 0 && num_written > 0)
 +              if (err < 0)
                        num_written = err;
        }
  
@@@ -2022,7 -2028,6 +2022,7 @@@ out
  
  static const struct vm_operations_struct btrfs_file_vm_ops = {
        .fault          = filemap_fault,
 +      .map_pages      = filemap_map_pages,
        .page_mkwrite   = btrfs_page_mkwrite,
        .remap_pages    = generic_file_remap_pages,
  };
diff --combined fs/btrfs/ioctl.c
index e79ff6b90cb71bb131426b97838c369ae0e6f48c,7b001abc73c7437f7a71bd23138ef10dbe04f44b..2ad7de94efef71e58af4e747cd05d3cb3aeeba40
@@@ -2807,11 -2807,14 +2807,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);
@@@ -3066,7 -3088,7 +3066,7 @@@ process_slot
                                                         new_key.offset + datal,
                                                         1);
                                if (ret) {
-                                       if (ret != -EINVAL)
+                                       if (ret != -EOPNOTSUPP)
                                                btrfs_abort_transaction(trans,
                                                                root, ret);
                                        btrfs_end_transaction(trans, root);
                                                         new_key.offset + datal,
                                                         1);
                                if (ret) {
-                                       if (ret != -EINVAL)
+                                       if (ret != -EOPNOTSUPP)
                                                btrfs_abort_transaction(trans,
                                                        root, ret);
                                        btrfs_end_transaction(trans, root);
diff --combined fs/btrfs/super.c
index 5011aadacab8e4cf1ac291f061f3c6ada24f8b9a,363404b9713f8a2a3b104d1ec4ac748844763560..9601d25a46075eaa44c0151ba890213efae8ec29
@@@ -385,20 -385,6 +385,6 @@@ static match_table_t tokens = 
        {Opt_err, NULL},
  };
  
- #define btrfs_set_and_info(root, opt, fmt, args...)                   \
- {                                                                     \
-       if (!btrfs_test_opt(root, opt))                                 \
-               btrfs_info(root->fs_info, fmt, ##args);                 \
-       btrfs_set_opt(root->fs_info->mount_opt, opt);                   \
- }
- #define btrfs_clear_and_info(root, opt, fmt, args...)                 \
- {                                                                     \
-       if (btrfs_test_opt(root, opt))                                  \
-               btrfs_info(root->fs_info, fmt, ##args);                 \
-       btrfs_clear_opt(root->fs_info->mount_opt, opt);                 \
- }
  /*
   * Regular mount options parser.  Everything that is needed only when
   * reading in a new superblock is parsed here.
@@@ -1186,7 -1172,6 +1172,6 @@@ static struct dentry *mount_subvol(cons
                return ERR_PTR(-ENOMEM);
        mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name,
                             newargs);
-       kfree(newargs);
  
        if (PTR_RET(mnt) == -EBUSY) {
                if (flags & MS_RDONLY) {
                        int r;
                        mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY, device_name,
                                             newargs);
-                       if (IS_ERR(mnt))
+                       if (IS_ERR(mnt)) {
+                               kfree(newargs);
                                return ERR_CAST(mnt);
+                       }
  
                        r = btrfs_remount(mnt->mnt_sb, &flags, NULL);
                        if (r < 0) {
                                /* FIXME: release vfsmount mnt ??*/
+                               kfree(newargs);
                                return ERR_PTR(r);
                        }
                }
        }
  
+       kfree(newargs);
        if (IS_ERR(mnt))
                return ERR_CAST(mnt);
  
@@@ -1402,7 -1392,6 +1392,7 @@@ static int btrfs_remount(struct super_b
        unsigned int old_metadata_ratio = fs_info->metadata_ratio;
        int ret;
  
 +      sync_filesystem(sb);
        btrfs_remount_prepare(fs_info);
  
        ret = btrfs_parse_options(root, data);