Merge tag 'for-5.12-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 5 Mar 2021 20:21:14 +0000 (12:21 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 5 Mar 2021 20:21:14 +0000 (12:21 -0800)
Pull btrfs fixes from David Sterba:
 "More regression fixes and stabilization.

  Regressions:

   - zoned mode
      - count zone sizes in wider int types
      - fix space accounting for read-only block groups

   - subpage: fix page tail zeroing

  Fixes:

   - fix spurious warning when remounting with free space tree

   - fix warning when creating a directory with smack enabled

   - ioctl checks for qgroup inheritance when creating a snapshot

   - qgroup
      - fix missing unlock on error path in zero range
      - fix amount of released reservation on error
      - fix flushing from unsafe context with open transaction,
        potentially deadlocking

   - minor build warning fixes"

* tag 'for-5.12-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: zoned: do not account freed region of read-only block group as zone_unusable
  btrfs: zoned: use sector_t for zone sectors
  btrfs: subpage: fix the false data csum mismatch error
  btrfs: fix warning when creating a directory with smack enabled
  btrfs: don't flush from btrfs_delayed_inode_reserve_metadata
  btrfs: export and rename qgroup_reserve_meta
  btrfs: free correct amount of space in btrfs_delayed_inode_reserve_metadata
  btrfs: fix spurious free_space_tree remount warning
  btrfs: validate qgroup inherit for SNAP_CREATE_V2 ioctl
  btrfs: unlock extents in btrfs_zero_range in case of quota reservation errors
  btrfs: ref-verify: use 'inline void' keyword ordering

1  2 
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/xattr.c
fs/btrfs/zoned.c

diff --combined fs/btrfs/file.c
@@@ -1942,8 -1942,8 +1942,8 @@@ relock
                goto buffered;
        }
  
 -      dio = __iomap_dio_rw(iocb, from, &btrfs_dio_iomap_ops,
 -                           &btrfs_dio_ops, is_sync_kiocb(iocb));
 +      dio = __iomap_dio_rw(iocb, from, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
 +                           0);
  
        btrfs_inode_unlock(inode, ilock_flags);
  
@@@ -3260,8 -3260,11 +3260,11 @@@ reserve_space
                        goto out;
                ret = btrfs_qgroup_reserve_data(BTRFS_I(inode), &data_reserved,
                                                alloc_start, bytes_to_reserve);
-               if (ret)
+               if (ret) {
+                       unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart,
+                                            lockend, &cached_state);
                        goto out;
+               }
                ret = btrfs_prealloc_file_range(inode, mode, alloc_start,
                                                alloc_end - alloc_start,
                                                i_blocksize(inode),
@@@ -3618,7 -3621,8 +3621,7 @@@ static ssize_t btrfs_direct_read(struc
                return 0;
  
        btrfs_inode_lock(inode, BTRFS_ILOCK_SHARED);
 -      ret = iomap_dio_rw(iocb, to, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
 -                         is_sync_kiocb(iocb));
 +      ret = iomap_dio_rw(iocb, to, &btrfs_dio_iomap_ops, &btrfs_dio_ops, 0);
        btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
        return ret;
  }
@@@ -3634,7 -3638,7 +3637,7 @@@ static ssize_t btrfs_file_read_iter(str
                        return ret;
        }
  
 -      return generic_file_buffered_read(iocb, to, ret);
 +      return filemap_read(iocb, to, ret);
  }
  
  const struct file_operations btrfs_file_operations = {
diff --combined fs/btrfs/inode.c
@@@ -5210,8 -5210,7 +5210,8 @@@ static int btrfs_setsize(struct inode *
        return ret;
  }
  
 -static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
 +static int btrfs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
 +                       struct iattr *attr)
  {
        struct inode *inode = d_inode(dentry);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        if (btrfs_root_readonly(root))
                return -EROFS;
  
 -      err = setattr_prepare(dentry, attr);
 +      err = setattr_prepare(&init_user_ns, dentry, attr);
        if (err)
                return err;
  
        }
  
        if (attr->ia_valid) {
 -              setattr_copy(inode, attr);
 +              setattr_copy(&init_user_ns, inode, attr);
                inode_inc_iversion(inode);
                err = btrfs_dirty_inode(inode);
  
                if (!err && attr->ia_valid & ATTR_MODE)
 -                      err = posix_acl_chmod(inode, inode->i_mode);
 +                      err = posix_acl_chmod(&init_user_ns, inode,
 +                                            inode->i_mode);
        }
  
        return err;
@@@ -6083,7 -6081,7 +6083,7 @@@ static int btrfs_dirty_inode(struct ino
                return PTR_ERR(trans);
  
        ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
-       if (ret && ret == -ENOSPC) {
+       if (ret && (ret == -ENOSPC || ret == -EDQUOT)) {
                /* whoops, lets try again with the full transaction */
                btrfs_end_transaction(trans);
                trans = btrfs_start_transaction(root, 1);
@@@ -6357,7 -6355,7 +6357,7 @@@ static struct inode *btrfs_new_inode(st
        if (ret != 0)
                goto fail_unlock;
  
 -      inode_init_owner(inode, dir, mode);
 +      inode_init_owner(&init_user_ns, inode, dir, mode);
        inode_set_bytes(inode, 0);
  
        inode->i_mtime = current_time(inode);
@@@ -6518,8 -6516,8 +6518,8 @@@ static int btrfs_add_nondir(struct btrf
        return err;
  }
  
 -static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
 -                      umode_t mode, dev_t rdev)
 +static int btrfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
 +                     struct dentry *dentry, umode_t mode, dev_t rdev)
  {
        struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
        struct btrfs_trans_handle *trans;
@@@ -6582,8 -6580,8 +6582,8 @@@ out_unlock
        return err;
  }
  
 -static int btrfs_create(struct inode *dir, struct dentry *dentry,
 -                      umode_t mode, bool excl)
 +static int btrfs_create(struct user_namespace *mnt_userns, struct inode *dir,
 +                      struct dentry *dentry, umode_t mode, bool excl)
  {
        struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
        struct btrfs_trans_handle *trans;
@@@ -6727,8 -6725,7 +6727,8 @@@ fail
        return err;
  }
  
 -static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 +static int btrfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
 +                     struct dentry *dentry, umode_t mode)
  {
        struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
        struct inode *inode = NULL;
@@@ -9018,8 -9015,7 +9018,8 @@@ fail
        return -ENOMEM;
  }
  
 -static int btrfs_getattr(const struct path *path, struct kstat *stat,
 +static int btrfs_getattr(struct user_namespace *mnt_userns,
 +                       const struct path *path, struct kstat *stat,
                         u32 request_mask, unsigned int flags)
  {
        u64 delalloc_bytes;
                                  STATX_ATTR_IMMUTABLE |
                                  STATX_ATTR_NODUMP);
  
 -      generic_fillattr(inode, stat);
 +      generic_fillattr(&init_user_ns, inode, stat);
        stat->dev = BTRFS_I(inode)->root->anon_dev;
  
        spin_lock(&BTRFS_I(inode)->lock);
@@@ -9536,9 -9532,9 +9536,9 @@@ out_notrans
        return ret;
  }
  
 -static int btrfs_rename2(struct inode *old_dir, struct dentry *old_dentry,
 -                       struct inode *new_dir, struct dentry *new_dentry,
 -                       unsigned int flags)
 +static int btrfs_rename2(struct user_namespace *mnt_userns, struct inode *old_dir,
 +                       struct dentry *old_dentry, struct inode *new_dir,
 +                       struct dentry *new_dentry, unsigned int flags)
  {
        if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
                return -EINVAL;
@@@ -9746,8 -9742,8 +9746,8 @@@ out
        return ret;
  }
  
 -static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
 -                       const char *symname)
 +static int btrfs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
 +                       struct dentry *dentry, const char *symname)
  {
        struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
        struct btrfs_trans_handle *trans;
@@@ -10081,8 -10077,7 +10081,8 @@@ static int btrfs_set_page_dirty(struct 
        return __set_page_dirty_nobuffers(page);
  }
  
 -static int btrfs_permission(struct inode *inode, int mask)
 +static int btrfs_permission(struct user_namespace *mnt_userns,
 +                          struct inode *inode, int mask)
  {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        umode_t mode = inode->i_mode;
                if (BTRFS_I(inode)->flags & BTRFS_INODE_READONLY)
                        return -EACCES;
        }
 -      return generic_permission(inode, mask);
 +      return generic_permission(&init_user_ns, inode, mask);
  }
  
 -static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
 +static int btrfs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
 +                       struct dentry *dentry, umode_t mode)
  {
        struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
        struct btrfs_trans_handle *trans;
diff --combined fs/btrfs/ioctl.c
@@@ -213,7 -213,7 +213,7 @@@ static int btrfs_ioctl_setflags(struct 
        const char *comp = NULL;
        u32 binode_flags;
  
 -      if (!inode_owner_or_capable(inode))
 +      if (!inode_owner_or_capable(&init_user_ns, inode))
                return -EPERM;
  
        if (btrfs_root_readonly(root))
@@@ -429,7 -429,7 +429,7 @@@ static int btrfs_ioctl_fssetxattr(struc
        unsigned old_i_flags;
        int ret = 0;
  
 -      if (!inode_owner_or_capable(inode))
 +      if (!inode_owner_or_capable(&init_user_ns, inode))
                return -EPERM;
  
        if (btrfs_root_readonly(root))
@@@ -925,14 -925,13 +925,14 @@@ static int btrfs_may_delete(struct inod
        BUG_ON(d_inode(victim->d_parent) != dir);
        audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
  
 -      error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
 +      error = inode_permission(&init_user_ns, dir, MAY_WRITE | MAY_EXEC);
        if (error)
                return error;
        if (IS_APPEND(dir))
                return -EPERM;
 -      if (check_sticky(dir, d_inode(victim)) || IS_APPEND(d_inode(victim)) ||
 -          IS_IMMUTABLE(d_inode(victim)) || IS_SWAPFILE(d_inode(victim)))
 +      if (check_sticky(&init_user_ns, dir, d_inode(victim)) ||
 +          IS_APPEND(d_inode(victim)) || IS_IMMUTABLE(d_inode(victim)) ||
 +          IS_SWAPFILE(d_inode(victim)))
                return -EPERM;
        if (isdir) {
                if (!d_is_dir(victim))
@@@ -955,7 -954,7 +955,7 @@@ static inline int btrfs_may_create(stru
                return -EEXIST;
        if (IS_DEADDIR(dir))
                return -ENOENT;
 -      return inode_permission(dir, MAY_WRITE | MAY_EXEC);
 +      return inode_permission(&init_user_ns, dir, MAY_WRITE | MAY_EXEC);
  }
  
  /*
@@@ -1872,7 -1871,7 +1872,7 @@@ static noinline int __btrfs_ioctl_snap_
                        btrfs_info(BTRFS_I(file_inode(file))->root->fs_info,
                                   "Snapshot src from another FS");
                        ret = -EXDEV;
 -              } else if (!inode_owner_or_capable(src_inode)) {
 +              } else if (!inode_owner_or_capable(&init_user_ns, src_inode)) {
                        /*
                         * Subvolume creation is not restricted, but snapshots
                         * are limited to own subvolumes only
@@@ -1936,7 -1935,10 +1936,10 @@@ static noinline int btrfs_ioctl_snap_cr
        if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
                readonly = true;
        if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
-               if (vol_args->size > PAGE_SIZE) {
+               u64 nums;
+               if (vol_args->size < sizeof(*inherit) ||
+                   vol_args->size > PAGE_SIZE) {
                        ret = -EINVAL;
                        goto free_args;
                }
                        ret = PTR_ERR(inherit);
                        goto free_args;
                }
+               if (inherit->num_qgroups > PAGE_SIZE ||
+                   inherit->num_ref_copies > PAGE_SIZE ||
+                   inherit->num_excl_copies > PAGE_SIZE) {
+                       ret = -EINVAL;
+                       goto free_inherit;
+               }
+               nums = inherit->num_qgroups + 2 * inherit->num_ref_copies +
+                      2 * inherit->num_excl_copies;
+               if (vol_args->size != struct_size(inherit, qgroups, nums)) {
+                       ret = -EINVAL;
+                       goto free_inherit;
+               }
        }
  
        ret = __btrfs_ioctl_snap_create(file, vol_args->name, vol_args->fd,
@@@ -1992,7 -2008,7 +2009,7 @@@ static noinline int btrfs_ioctl_subvol_
        u64 flags;
        int ret = 0;
  
 -      if (!inode_owner_or_capable(inode))
 +      if (!inode_owner_or_capable(&init_user_ns, inode))
                return -EPERM;
  
        ret = mnt_want_write_file(file);
@@@ -2548,8 -2564,7 +2565,8 @@@ static int btrfs_search_path_in_tree_us
                                ret = PTR_ERR(temp_inode);
                                goto out_put;
                        }
 -                      ret = inode_permission(temp_inode, MAY_READ | MAY_EXEC);
 +                      ret = inode_permission(&init_user_ns, temp_inode,
 +                                             MAY_READ | MAY_EXEC);
                        iput(temp_inode);
                        if (ret) {
                                ret = -EACCES;
@@@ -3079,8 -3094,7 +3096,8 @@@ static noinline int btrfs_ioctl_snap_de
                if (root == dest)
                        goto out_dput;
  
 -              err = inode_permission(inode, MAY_WRITE | MAY_EXEC);
 +              err = inode_permission(&init_user_ns, inode,
 +                                     MAY_WRITE | MAY_EXEC);
                if (err)
                        goto out_dput;
        }
@@@ -3151,7 -3165,7 +3168,7 @@@ static int btrfs_ioctl_defrag(struct fi
                 * running and allows defrag on files open in read-only mode.
                 */
                if (!capable(CAP_SYS_ADMIN) &&
 -                  inode_permission(inode, MAY_WRITE)) {
 +                  inode_permission(&init_user_ns, inode, MAY_WRITE)) {
                        ret = -EPERM;
                        goto out;
                }
@@@ -4463,7 -4477,7 +4480,7 @@@ static long _btrfs_ioctl_set_received_s
        int ret = 0;
        int received_uuid_changed;
  
 -      if (!inode_owner_or_capable(inode))
 +      if (!inode_owner_or_capable(&init_user_ns, inode))
                return -EPERM;
  
        ret = mnt_want_write_file(file);
diff --combined fs/btrfs/xattr.c
@@@ -229,11 -229,33 +229,33 @@@ int btrfs_setxattr_trans(struct inode *
  {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_trans_handle *trans;
+       const bool start_trans = (current->journal_info == NULL);
        int ret;
  
-       trans = btrfs_start_transaction(root, 2);
-       if (IS_ERR(trans))
-               return PTR_ERR(trans);
+       if (start_trans) {
+               /*
+                * 1 unit for inserting/updating/deleting the xattr
+                * 1 unit for the inode item update
+                */
+               trans = btrfs_start_transaction(root, 2);
+               if (IS_ERR(trans))
+                       return PTR_ERR(trans);
+       } else {
+               /*
+                * This can happen when smack is enabled and a directory is being
+                * created. It happens through d_instantiate_new(), which calls
+                * smack_d_instantiate(), which in turn calls __vfs_setxattr() to
+                * set the transmute xattr (XATTR_NAME_SMACKTRANSMUTE) on the
+                * inode. We have already reserved space for the xattr and inode
+                * update at btrfs_mkdir(), so just use the transaction handle.
+                * We don't join or start a transaction, as that will reset the
+                * block_rsv of the handle and trigger a warning for the start
+                * case.
+                */
+               ASSERT(strncmp(name, XATTR_SECURITY_PREFIX,
+                              XATTR_SECURITY_PREFIX_LEN) == 0);
+               trans = current->journal_info;
+       }
  
        ret = btrfs_setxattr(trans, inode, name, value, size, flags);
        if (ret)
        ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
        BUG_ON(ret);
  out:
-       btrfs_end_transaction(trans);
+       if (start_trans)
+               btrfs_end_transaction(trans);
        return ret;
  }
  
@@@ -362,7 -385,6 +385,7 @@@ static int btrfs_xattr_handler_get(cons
  }
  
  static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
 +                                 struct user_namespace *mnt_userns,
                                   struct dentry *unused, struct inode *inode,
                                   const char *name, const void *buffer,
                                   size_t size, int flags)
  }
  
  static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
 +                                      struct user_namespace *mnt_userns,
                                        struct dentry *unused, struct inode *inode,
                                        const char *name, const void *value,
                                        size_t size, int flags)
diff --combined fs/btrfs/zoned.c
@@@ -269,7 -269,7 +269,7 @@@ int btrfs_get_dev_zone_info(struct btrf
        sector_t sector = 0;
        struct blk_zone *zones = NULL;
        unsigned int i, nreported = 0, nr_zones;
-       unsigned int zone_sectors;
+       sector_t zone_sectors;
        char *model, *emulated;
        int ret;
  
@@@ -658,7 -658,7 +658,7 @@@ int btrfs_sb_log_location_bdev(struct b
                               u64 *bytenr_ret)
  {
        struct blk_zone zones[BTRFS_NR_SB_LOG_ZONES];
-       unsigned int zone_sectors;
+       sector_t zone_sectors;
        u32 sb_zone;
        int ret;
        u8 zone_sectors_shift;
@@@ -1275,8 -1275,8 +1275,8 @@@ void btrfs_record_physical_zoned(struc
                return;
  
        ordered->physical = physical;
 -      ordered->disk = bio->bi_disk;
 -      ordered->partno = bio->bi_partno;
 +      ordered->disk = bio->bi_bdev->bd_disk;
 +      ordered->partno = bio->bi_bdev->bd_partno;
  
        btrfs_put_ordered_extent(ordered);
  }