Merge remote-tracking branch 'jk/vfs' into work.misc
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 8 Oct 2016 15:06:08 +0000 (11:06 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 8 Oct 2016 15:06:08 +0000 (11:06 -0400)
17 files changed:
1  2 
fs/attr.c
fs/btrfs/inode.c
fs/cifs/inode.c
fs/ext4/inode.c
fs/f2fs/file.c
fs/fuse/file.c
fs/ocfs2/file.c
fs/orangefs/inode.c
fs/overlayfs/inode.c
fs/posix_acl.c
fs/proc/base.c
fs/utimes.c
fs/xfs/xfs_file.c
fs/xfs/xfs_iops.c
include/linux/fs.h
include/linux/posix_acl.h
mm/shmem.c

diff --combined fs/attr.c
+++ b/fs/attr.c
  #include <linux/ima.h>
  
  /**
-  * inode_change_ok - check if attribute changes to an inode are allowed
-  * @inode:    inode to check
+  * setattr_prepare - check if attribute changes to a dentry are allowed
+  * @dentry:   dentry to check
   * @attr:     attributes to change
   *
   * Check if we are allowed to change the attributes contained in @attr
-  * in the given inode.  This includes the normal unix access permission
-  * checks, as well as checks for rlimits and others.
+  * in the given dentry.  This includes the normal unix access permission
+  * checks, as well as checks for rlimits and others. The function also clears
+  * SGID bit from mode if user is not allowed to set it. Also file capabilities
+  * and IMA extended attributes are cleared if ATTR_KILL_PRIV is set.
   *
   * Should be called as the first thing in ->setattr implementations,
   * possibly after taking additional locks.
   */
- int inode_change_ok(const struct inode *inode, struct iattr *attr)
+ int setattr_prepare(struct dentry *dentry, struct iattr *attr)
  {
+       struct inode *inode = d_inode(dentry);
        unsigned int ia_valid = attr->ia_valid;
  
        /*
@@@ -44,7 -47,7 +47,7 @@@
  
        /* If force is set do it anyway. */
        if (ia_valid & ATTR_FORCE)
-               return 0;
+               goto kill_priv;
  
        /* Make sure a caller can chown. */
        if ((ia_valid & ATTR_UID) &&
                        return -EPERM;
        }
  
+ kill_priv:
+       /* User has permission for the change */
+       if (ia_valid & ATTR_KILL_PRIV) {
+               int error;
+               error = security_inode_killpriv(dentry);
+               if (error)
+                       return error;
+       }
        return 0;
  }
- EXPORT_SYMBOL(inode_change_ok);
+ EXPORT_SYMBOL(setattr_prepare);
  
  /**
   * inode_newsize_ok - may this inode be truncated to a given size
@@@ -202,21 -215,6 +215,21 @@@ int notify_change(struct dentry * dentr
                        return -EPERM;
        }
  
 +      /*
 +       * If utimes(2) and friends are called with times == NULL (or both
 +       * times are UTIME_NOW), then we need to check for write permission
 +       */
 +      if (ia_valid & ATTR_TOUCH) {
 +              if (IS_IMMUTABLE(inode))
 +                      return -EPERM;
 +
 +              if (!inode_owner_or_capable(inode)) {
 +                      error = inode_permission(inode, MAY_WRITE);
 +                      if (error)
 +                              return error;
 +              }
 +      }
 +
        if ((ia_valid & ATTR_MODE)) {
                umode_t amode = attr->ia_mode;
                /* Flag setting protected by i_mutex */
        if (!(ia_valid & ATTR_MTIME_SET))
                attr->ia_mtime = now;
        if (ia_valid & ATTR_KILL_PRIV) {
-               attr->ia_valid &= ~ATTR_KILL_PRIV;
-               ia_valid &= ~ATTR_KILL_PRIV;
                error = security_inode_need_killpriv(dentry);
-               if (error > 0)
-                       error = security_inode_killpriv(dentry);
-               if (error)
+               if (error < 0)
                        return error;
+               if (error == 0)
+                       ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV;
        }
  
        /*
diff --combined fs/btrfs/inode.c
@@@ -566,8 -566,6 +566,8 @@@ cont
                                                     PAGE_SET_WRITEBACK |
                                                     page_error_op |
                                                     PAGE_END_WRITEBACK);
 +                      btrfs_free_reserved_data_space_noquota(inode, start,
 +                                              end - start + 1);
                        goto free_pages_out;
                }
        }
@@@ -744,7 -742,7 +744,7 @@@ retry
                lock_extent(io_tree, async_extent->start,
                            async_extent->start + async_extent->ram_size - 1);
  
 -              ret = btrfs_reserve_extent(root,
 +              ret = btrfs_reserve_extent(root, async_extent->ram_size,
                                           async_extent->compressed_size,
                                           async_extent->compressed_size,
                                           0, alloc_hint, &ins, 1, 1);
@@@ -971,8 -969,7 +971,8 @@@ static noinline int cow_file_range(stru
                                     EXTENT_DEFRAG, PAGE_UNLOCK |
                                     PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK |
                                     PAGE_END_WRITEBACK);
 -
 +                      btrfs_free_reserved_data_space_noquota(inode, start,
 +                                              end - start + 1);
                        *nr_written = *nr_written +
                             (end - start + PAGE_SIZE) / PAGE_SIZE;
                        *page_started = 1;
                unsigned long op;
  
                cur_alloc_size = disk_num_bytes;
 -              ret = btrfs_reserve_extent(root, cur_alloc_size,
 +              ret = btrfs_reserve_extent(root, cur_alloc_size, cur_alloc_size,
                                           root->sectorsize, 0, alloc_hint,
                                           &ins, 1, 1);
                if (ret < 0)
@@@ -1492,10 -1489,8 +1492,10 @@@ out_check
                extent_clear_unlock_delalloc(inode, cur_offset,
                                             cur_offset + num_bytes - 1,
                                             locked_page, EXTENT_LOCKED |
 -                                           EXTENT_DELALLOC, PAGE_UNLOCK |
 -                                           PAGE_SET_PRIVATE2);
 +                                           EXTENT_DELALLOC |
 +                                           EXTENT_CLEAR_DATA_RESV,
 +                                           PAGE_UNLOCK | PAGE_SET_PRIVATE2);
 +
                if (!nolock && nocow)
                        btrfs_end_write_no_snapshoting(root);
                cur_offset = extent_end;
@@@ -1812,9 -1807,7 +1812,9 @@@ static void btrfs_clear_bit_hook(struc
                        return;
  
                if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID
 -                  && do_list && !(state->state & EXTENT_NORESERVE))
 +                  && do_list && !(state->state & EXTENT_NORESERVE)
 +                  && (*bits & (EXTENT_DO_ACCOUNTING |
 +                  EXTENT_CLEAR_DATA_RESV)))
                        btrfs_free_reserved_data_space_noquota(inode,
                                        state->start, len);
  
@@@ -3442,10 -3435,10 +3442,10 @@@ int btrfs_orphan_cleanup(struct btrfs_r
                found_key.offset = 0;
                inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
                ret = PTR_ERR_OR_ZERO(inode);
 -              if (ret && ret != -ESTALE)
 +              if (ret && ret != -ENOENT)
                        goto out;
  
 -              if (ret == -ESTALE && root == root->fs_info->tree_root) {
 +              if (ret == -ENOENT && root == root->fs_info->tree_root) {
                        struct btrfs_root *dead_root;
                        struct btrfs_fs_info *fs_info = root->fs_info;
                        int is_dead_root = 0;
                 * Inode is already gone but the orphan item is still there,
                 * kill the orphan item.
                 */
 -              if (ret == -ESTALE) {
 +              if (ret == -ENOENT) {
                        trans = btrfs_start_transaction(root, 1);
                        if (IS_ERR(trans)) {
                                ret = PTR_ERR(trans);
@@@ -3640,7 -3633,7 +3640,7 @@@ static noinline int acls_after_inode_it
  /*
   * read an inode from the btree into the in-memory inode
   */
 -static void btrfs_read_locked_inode(struct inode *inode)
 +static int btrfs_read_locked_inode(struct inode *inode)
  {
        struct btrfs_path *path;
        struct extent_buffer *leaf;
                filled = true;
  
        path = btrfs_alloc_path();
 -      if (!path)
 +      if (!path) {
 +              ret = -ENOMEM;
                goto make_bad;
 +      }
  
        memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
  
        ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
 -      if (ret)
 +      if (ret) {
 +              if (ret > 0)
 +                      ret = -ENOENT;
                goto make_bad;
 +      }
  
        leaf = path->nodes[0];
  
@@@ -3824,12 -3812,11 +3824,12 @@@ cache_acl
        }
  
        btrfs_update_iflags(inode);
 -      return;
 +      return 0;
  
  make_bad:
        btrfs_free_path(path);
        make_bad_inode(inode);
 +      return ret;
  }
  
  /*
@@@ -4217,7 -4204,6 +4217,7 @@@ static int btrfs_rmdir(struct inode *di
        int err = 0;
        struct btrfs_root *root = BTRFS_I(dir)->root;
        struct btrfs_trans_handle *trans;
 +      u64 last_unlink_trans;
  
        if (inode->i_size > BTRFS_EMPTY_DIR_SIZE)
                return -ENOTEMPTY;
        if (err)
                goto out;
  
 +      last_unlink_trans = BTRFS_I(inode)->last_unlink_trans;
 +
        /* now the directory is empty */
        err = btrfs_unlink_inode(trans, root, dir, d_inode(dentry),
                                 dentry->d_name.name, dentry->d_name.len);
 -      if (!err)
 +      if (!err) {
                btrfs_i_size_write(inode, 0);
 +              /*
 +               * Propagate the last_unlink_trans value of the deleted dir to
 +               * its parent directory. This is to prevent an unrecoverable
 +               * log tree in the case we do something like this:
 +               * 1) create dir foo
 +               * 2) create snapshot under dir foo
 +               * 3) delete the snapshot
 +               * 4) rmdir foo
 +               * 5) mkdir foo
 +               * 6) fsync foo or some file inside foo
 +               */
 +              if (last_unlink_trans >= trans->transid)
 +                      BTRFS_I(dir)->last_unlink_trans = last_unlink_trans;
 +      }
  out:
        btrfs_end_transaction(trans, root);
        btrfs_btree_balance_dirty(root);
@@@ -5072,7 -5042,7 +5072,7 @@@ static int btrfs_setattr(struct dentry 
        if (btrfs_root_readonly(root))
                return -EROFS;
  
-       err = inode_change_ok(inode, attr);
+       err = setattr_prepare(dentry, attr);
        if (err)
                return err;
  
@@@ -5636,9 -5606,7 +5636,9 @@@ struct inode *btrfs_iget(struct super_b
                return ERR_PTR(-ENOMEM);
  
        if (inode->i_state & I_NEW) {
 -              btrfs_read_locked_inode(inode);
 +              int ret;
 +
 +              ret = btrfs_read_locked_inode(inode);
                if (!is_bad_inode(inode)) {
                        inode_tree_add(inode);
                        unlock_new_inode(inode);
                } else {
                        unlock_new_inode(inode);
                        iput(inode);
 -                      inode = ERR_PTR(-ESTALE);
 +                      ASSERT(ret < 0);
 +                      inode = ERR_PTR(ret < 0 ? ret : -ESTALE);
                }
        }
  
@@@ -7258,7 -7225,7 +7258,7 @@@ static struct extent_map *btrfs_new_ext
        int ret;
  
        alloc_hint = get_extent_allocation_hint(inode, start, len);
 -      ret = btrfs_reserve_extent(root, len, root->sectorsize, 0,
 +      ret = btrfs_reserve_extent(root, len, len, root->sectorsize, 0,
                                   alloc_hint, &ins, 1, 1);
        if (ret)
                return ERR_PTR(ret);
@@@ -7758,13 -7725,6 +7758,13 @@@ static int btrfs_get_blocks_direct(stru
                                ret = PTR_ERR(em2);
                                goto unlock_err;
                        }
 +                      /*
 +                       * For inode marked NODATACOW or extent marked PREALLOC,
 +                       * use the existing or preallocated extent, so does not
 +                       * need to adjust btrfs_space_info's bytes_may_use.
 +                       */
 +                      btrfs_free_reserved_data_space_noquota(inode,
 +                                      start, len);
                        goto unlock;
                }
        }
@@@ -7799,6 -7759,7 +7799,6 @@@ unlock
                        i_size_write(inode, start + len);
  
                adjust_dio_outstanding_extents(inode, dio_data, len);
 -              btrfs_free_reserved_data_space(inode, start, len);
                WARN_ON(dio_data->reserve < len);
                dio_data->reserve -= len;
                dio_data->unsubmitted_oe_range_end = start + len;
@@@ -10319,7 -10280,6 +10319,7 @@@ static int __btrfs_prealloc_file_range(
        u64 last_alloc = (u64)-1;
        int ret = 0;
        bool own_trans = true;
 +      u64 end = start + num_bytes - 1;
  
        if (trans)
                own_trans = false;
                 * sized chunks.
                 */
                cur_bytes = min(cur_bytes, last_alloc);
 -              ret = btrfs_reserve_extent(root, cur_bytes, min_size, 0,
 -                                         *alloc_hint, &ins, 1, 0);
 +              ret = btrfs_reserve_extent(root, cur_bytes, cur_bytes,
 +                              min_size, 0, *alloc_hint, &ins, 1, 0);
                if (ret) {
                        if (own_trans)
                                btrfs_end_transaction(trans, root);
@@@ -10428,9 -10388,6 +10428,9 @@@ next
                if (own_trans)
                        btrfs_end_transaction(trans, root);
        }
 +      if (cur_offset < end)
 +              btrfs_free_reserved_data_space(inode, cur_offset,
 +                      end - cur_offset + 1);
        return ret;
  }
  
@@@ -10543,6 -10500,21 +10543,6 @@@ out_inode
  
  }
  
 -/* Inspired by filemap_check_errors() */
 -int btrfs_inode_check_errors(struct inode *inode)
 -{
 -      int ret = 0;
 -
 -      if (test_bit(AS_ENOSPC, &inode->i_mapping->flags) &&
 -          test_and_clear_bit(AS_ENOSPC, &inode->i_mapping->flags))
 -              ret = -ENOSPC;
 -      if (test_bit(AS_EIO, &inode->i_mapping->flags) &&
 -          test_and_clear_bit(AS_EIO, &inode->i_mapping->flags))
 -              ret = -EIO;
 -
 -      return ret;
 -}
 -
  static const struct inode_operations btrfs_dir_inode_operations = {
        .getattr        = btrfs_getattr,
        .lookup         = btrfs_lookup,
diff --combined fs/cifs/inode.c
@@@ -1951,7 -1951,7 +1951,7 @@@ int cifs_revalidate_dentry_attr(struct 
  
        cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
                 full_path, inode, inode->i_count.counter,
 -               dentry, dentry->d_time, jiffies);
 +               dentry, cifs_get_time(dentry), jiffies);
  
        if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
                rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
@@@ -2154,7 -2154,7 +2154,7 @@@ cifs_setattr_unix(struct dentry *dirent
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
                attrs->ia_valid |= ATTR_FORCE;
  
-       rc = inode_change_ok(inode, attrs);
+       rc = setattr_prepare(direntry, attrs);
        if (rc < 0)
                goto out;
  
@@@ -2294,7 -2294,7 +2294,7 @@@ cifs_setattr_nounix(struct dentry *dire
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
                attrs->ia_valid |= ATTR_FORCE;
  
-       rc = inode_change_ok(inode, attrs);
+       rc = setattr_prepare(direntry, attrs);
        if (rc < 0) {
                free_xid(xid);
                return rc;
diff --combined fs/ext4/inode.c
@@@ -5073,7 -5073,7 +5073,7 @@@ int ext4_setattr(struct dentry *dentry
        int orphan = 0;
        const unsigned int ia_valid = attr->ia_valid;
  
-       error = inode_change_ok(inode, attr);
+       error = setattr_prepare(dentry, attr);
        if (error)
                return error;
  
@@@ -5466,6 -5466,8 +5466,6 @@@ int ext4_mark_inode_dirty(handle_t *han
                                                      sbi->s_want_extra_isize,
                                                      iloc, handle);
                        if (ret) {
 -                              ext4_set_inode_state(inode,
 -                                                   EXT4_STATE_NO_EXPAND);
                                if (mnt_count !=
                                        le16_to_cpu(sbi->s_es->s_mnt_count)) {
                                        ext4_warning(inode->i_sb,
diff --combined fs/f2fs/file.c
@@@ -680,7 -680,7 +680,7 @@@ int f2fs_setattr(struct dentry *dentry
        struct inode *inode = d_inode(dentry);
        int err;
  
-       err = inode_change_ok(inode, attr);
+       err = setattr_prepare(dentry, attr);
        if (err)
                return err;
  
@@@ -1757,14 -1757,21 +1757,14 @@@ static int f2fs_ioc_set_encryption_poli
  {
        struct fscrypt_policy policy;
        struct inode *inode = file_inode(filp);
 -      int ret;
  
        if (copy_from_user(&policy, (struct fscrypt_policy __user *)arg,
                                                        sizeof(policy)))
                return -EFAULT;
  
 -      ret = mnt_want_write_file(filp);
 -      if (ret)
 -              return ret;
 -
        f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
 -      ret = fscrypt_process_policy(inode, &policy);
  
 -      mnt_drop_write_file(filp);
 -      return ret;
 +      return fscrypt_process_policy(filp, &policy);
  }
  
  static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg)
@@@ -2079,19 -2086,15 +2079,19 @@@ static int f2fs_move_file_range(struct 
        if (unlikely(f2fs_readonly(src->i_sb)))
                return -EROFS;
  
 -      if (S_ISDIR(src->i_mode) || S_ISDIR(dst->i_mode))
 -              return -EISDIR;
 +      if (!S_ISREG(src->i_mode) || !S_ISREG(dst->i_mode))
 +              return -EINVAL;
  
        if (f2fs_encrypted_inode(src) || f2fs_encrypted_inode(dst))
                return -EOPNOTSUPP;
  
        inode_lock(src);
 -      if (src != dst)
 -              inode_lock(dst);
 +      if (src != dst) {
 +              if (!inode_trylock(dst)) {
 +                      ret = -EBUSY;
 +                      goto out;
 +              }
 +      }
  
        ret = -EINVAL;
        if (pos_in + len > src->i_size || pos_in + len < pos_in)
  out_unlock:
        if (src != dst)
                inode_unlock(dst);
 +out:
        inode_unlock(src);
        return ret;
  }
diff --combined fs/fuse/file.c
@@@ -530,13 -530,13 +530,13 @@@ void fuse_read_fill(struct fuse_req *re
        req->out.args[0].size = count;
  }
  
 -static void fuse_release_user_pages(struct fuse_req *req, int write)
 +static void fuse_release_user_pages(struct fuse_req *req, bool should_dirty)
  {
        unsigned i;
  
        for (i = 0; i < req->num_pages; i++) {
                struct page *page = req->pages[i];
 -              if (write)
 +              if (should_dirty)
                        set_page_dirty_lock(page);
                put_page(page);
        }
@@@ -1320,7 -1320,6 +1320,7 @@@ ssize_t fuse_direct_io(struct fuse_io_p
                       loff_t *ppos, int flags)
  {
        int write = flags & FUSE_DIO_WRITE;
 +      bool should_dirty = !write && iter_is_iovec(iter);
        int cuse = flags & FUSE_DIO_CUSE;
        struct file *file = io->file;
        struct inode *inode = file->f_mapping->host;
                        nres = fuse_send_read(req, io, pos, nbytes, owner);
  
                if (!io->async)
 -                      fuse_release_user_pages(req, !write);
 +                      fuse_release_user_pages(req, should_dirty);
                if (req->out.h.error) {
                        err = req->out.h.error;
                        break;
@@@ -2842,7 -2841,7 +2842,7 @@@ static void fuse_do_truncate(struct fil
        attr.ia_file = file;
        attr.ia_valid |= ATTR_FILE;
  
-       fuse_do_setattr(inode, &attr, file);
+       fuse_do_setattr(file_dentry(file), &attr, file);
  }
  
  static inline loff_t fuse_round_up(loff_t off)
diff --combined fs/ocfs2/file.c
@@@ -1155,7 -1155,7 +1155,7 @@@ int ocfs2_setattr(struct dentry *dentry
        if (!(attr->ia_valid & OCFS2_VALID_ATTRS))
                return 0;
  
-       status = inode_change_ok(inode, attr);
+       status = setattr_prepare(dentry, attr);
        if (status)
                return status;
  
@@@ -1506,8 -1506,7 +1506,8 @@@ static int ocfs2_zero_partial_clusters(
                                       u64 start, u64 len)
  {
        int ret = 0;
 -      u64 tmpend, end = start + len;
 +      u64 tmpend = 0;
 +      u64 end = start + len;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        unsigned int csize = osb->s_clustersize;
        handle_t *handle;
        }
  
        /*
 -       * We want to get the byte offset of the end of the 1st cluster.
 +       * If start is on a cluster boundary and end is somewhere in another
 +       * cluster, we have not COWed the cluster starting at start, unless
 +       * end is also within the same cluster. So, in this case, we skip this
 +       * first call to ocfs2_zero_range_for_truncate() truncate and move on
 +       * to the next one.
         */
 -      tmpend = (u64)osb->s_clustersize + (start & ~(osb->s_clustersize - 1));
 -      if (tmpend > end)
 -              tmpend = end;
 +      if ((start & (csize - 1)) != 0) {
 +              /*
 +               * We want to get the byte offset of the end of the 1st
 +               * cluster.
 +               */
 +              tmpend = (u64)osb->s_clustersize +
 +                      (start & ~(osb->s_clustersize - 1));
 +              if (tmpend > end)
 +                      tmpend = end;
  
 -      trace_ocfs2_zero_partial_clusters_range1((unsigned long long)start,
 -                                               (unsigned long long)tmpend);
 +              trace_ocfs2_zero_partial_clusters_range1(
 +                      (unsigned long long)start,
 +                      (unsigned long long)tmpend);
  
 -      ret = ocfs2_zero_range_for_truncate(inode, handle, start, tmpend);
 -      if (ret)
 -              mlog_errno(ret);
 +              ret = ocfs2_zero_range_for_truncate(inode, handle, start,
 +                                                  tmpend);
 +              if (ret)
 +                      mlog_errno(ret);
 +      }
  
        if (tmpend < end) {
                /*
diff --combined fs/orangefs/inode.c
@@@ -129,8 -129,8 +129,8 @@@ static ssize_t orangefs_direct_IO(struc
                                  struct iov_iter *iter)
  {
        gossip_debug(GOSSIP_INODE_DEBUG,
 -                   "orangefs_direct_IO: %s\n",
 -                   iocb->ki_filp->f_path.dentry->d_name.name);
 +                   "orangefs_direct_IO: %pD\n",
 +                   iocb->ki_filp);
  
        return -EINVAL;
  }
@@@ -216,10 -216,10 +216,10 @@@ int orangefs_setattr(struct dentry *den
        struct inode *inode = dentry->d_inode;
  
        gossip_debug(GOSSIP_INODE_DEBUG,
 -                   "orangefs_setattr: called on %s\n",
 -                   dentry->d_name.name);
 +                   "orangefs_setattr: called on %pd\n",
 +                   dentry);
  
-       ret = inode_change_ok(inode, iattr);
+       ret = setattr_prepare(dentry, iattr);
        if (ret)
                goto out;
  
@@@ -259,8 -259,8 +259,8 @@@ int orangefs_getattr(struct vfsmount *m
        struct orangefs_inode_s *orangefs_inode = NULL;
  
        gossip_debug(GOSSIP_INODE_DEBUG,
 -                   "orangefs_getattr: called on %s\n",
 -                   dentry->d_name.name);
 +                   "orangefs_getattr: called on %pd\n",
 +                   dentry);
  
        ret = orangefs_inode_getattr(inode, 0, 0);
        if (ret == 0) {
diff --combined fs/overlayfs/inode.c
@@@ -10,7 -10,6 +10,7 @@@
  #include <linux/fs.h>
  #include <linux/slab.h>
  #include <linux/xattr.h>
 +#include <linux/posix_acl.h>
  #include "overlayfs.h"
  
  static int ovl_copy_up_truncate(struct dentry *dentry)
@@@ -53,7 -52,7 +53,7 @@@ int ovl_setattr(struct dentry *dentry, 
         * inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not
         * check for a swapfile (which this won't be anyway).
         */
-       err = inode_change_ok(dentry->d_inode, attr);
+       err = setattr_prepare(dentry, attr);
        if (err)
                return err;
  
@@@ -192,44 -191,32 +192,44 @@@ static int ovl_readlink(struct dentry *
        return err;
  }
  
 -static bool ovl_is_private_xattr(const char *name)
 +bool ovl_is_private_xattr(const char *name)
  {
 -#define OVL_XATTR_PRE_NAME OVL_XATTR_PREFIX "."
 -      return strncmp(name, OVL_XATTR_PRE_NAME,
 -                     sizeof(OVL_XATTR_PRE_NAME) - 1) == 0;
 +      return strncmp(name, OVL_XATTR_PREFIX,
 +                     sizeof(OVL_XATTR_PREFIX) - 1) == 0;
  }
  
 -int ovl_setxattr(struct dentry *dentry, struct inode *inode,
 -               const char *name, const void *value,
 -               size_t size, int flags)
 +int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value,
 +                size_t size, int flags)
  {
        int err;
 -      struct dentry *upperdentry;
 +      struct path realpath;
 +      enum ovl_path_type type = ovl_path_real(dentry, &realpath);
        const struct cred *old_cred;
  
        err = ovl_want_write(dentry);
        if (err)
                goto out;
  
 +      if (!value && !OVL_TYPE_UPPER(type)) {
 +              err = vfs_getxattr(realpath.dentry, name, NULL, 0);
 +              if (err < 0)
 +                      goto out_drop_write;
 +      }
 +
        err = ovl_copy_up(dentry);
        if (err)
                goto out_drop_write;
  
 -      upperdentry = ovl_dentry_upper(dentry);
 +      if (!OVL_TYPE_UPPER(type))
 +              ovl_path_upper(dentry, &realpath);
 +
        old_cred = ovl_override_creds(dentry->d_sb);
 -      err = vfs_setxattr(upperdentry, name, value, size, flags);
 +      if (value)
 +              err = vfs_setxattr(realpath.dentry, name, value, size, flags);
 +      else {
 +              WARN_ON(flags != XATTR_REPLACE);
 +              err = vfs_removexattr(realpath.dentry, name);
 +      }
        revert_creds(old_cred);
  
  out_drop_write:
@@@ -238,13 -225,16 +238,13 @@@ out
        return err;
  }
  
 -ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
 -                   const char *name, void *value, size_t size)
 +int ovl_xattr_get(struct dentry *dentry, const char *name,
 +                void *value, size_t size)
  {
        struct dentry *realdentry = ovl_dentry_real(dentry);
        ssize_t res;
        const struct cred *old_cred;
  
 -      if (ovl_is_private_xattr(name))
 -              return -ENODATA;
 -
        old_cred = ovl_override_creds(dentry->d_sb);
        res = vfs_getxattr(realdentry, name, value, size);
        revert_creds(old_cred);
@@@ -255,8 -245,7 +255,8 @@@ ssize_t ovl_listxattr(struct dentry *de
  {
        struct dentry *realdentry = ovl_dentry_real(dentry);
        ssize_t res;
 -      int off;
 +      size_t len;
 +      char *s;
        const struct cred *old_cred;
  
        old_cred = ovl_override_creds(dentry->d_sb);
                return res;
  
        /* filter out private xattrs */
 -      for (off = 0; off < res;) {
 -              char *s = list + off;
 -              size_t slen = strlen(s) + 1;
 +      for (s = list, len = res; len;) {
 +              size_t slen = strnlen(s, len) + 1;
  
 -              BUG_ON(off + slen > res);
 +              /* underlying fs providing us with an broken xattr list? */
 +              if (WARN_ON(slen > len))
 +                      return -EIO;
  
 +              len -= slen;
                if (ovl_is_private_xattr(s)) {
                        res -= slen;
 -                      memmove(s, s + slen, res - off);
 +                      memmove(s, s + slen, len);
                } else {
 -                      off += slen;
 +                      s += slen;
                }
        }
  
        return res;
  }
  
 -int ovl_removexattr(struct dentry *dentry, const char *name)
 -{
 -      int err;
 -      struct path realpath;
 -      enum ovl_path_type type = ovl_path_real(dentry, &realpath);
 -      const struct cred *old_cred;
 -
 -      err = ovl_want_write(dentry);
 -      if (err)
 -              goto out;
 -
 -      err = -ENODATA;
 -      if (ovl_is_private_xattr(name))
 -              goto out_drop_write;
 -
 -      if (!OVL_TYPE_UPPER(type)) {
 -              err = vfs_getxattr(realpath.dentry, name, NULL, 0);
 -              if (err < 0)
 -                      goto out_drop_write;
 -
 -              err = ovl_copy_up(dentry);
 -              if (err)
 -                      goto out_drop_write;
 -
 -              ovl_path_upper(dentry, &realpath);
 -      }
 -
 -      old_cred = ovl_override_creds(dentry->d_sb);
 -      err = vfs_removexattr(realpath.dentry, name);
 -      revert_creds(old_cred);
 -out_drop_write:
 -      ovl_drop_write(dentry);
 -out:
 -      return err;
 -}
 -
  struct posix_acl *ovl_get_acl(struct inode *inode, int type)
  {
        struct inode *realinode = ovl_inode_real(inode, NULL);
        const struct cred *old_cred;
        struct posix_acl *acl;
  
 -      if (!IS_POSIXACL(realinode))
 +      if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode))
                return NULL;
  
        if (!realinode->i_op->get_acl)
                return NULL;
  
        old_cred = ovl_override_creds(inode->i_sb);
 -      acl = realinode->i_op->get_acl(realinode, type);
 +      acl = get_acl(realinode, type);
        revert_creds(old_cred);
  
        return acl;
@@@ -368,9 -391,9 +368,9 @@@ static const struct inode_operations ov
        .permission     = ovl_permission,
        .getattr        = ovl_getattr,
        .setxattr       = generic_setxattr,
 -      .getxattr       = ovl_getxattr,
 +      .getxattr       = generic_getxattr,
        .listxattr      = ovl_listxattr,
 -      .removexattr    = ovl_removexattr,
 +      .removexattr    = generic_removexattr,
        .get_acl        = ovl_get_acl,
        .update_time    = ovl_update_time,
  };
@@@ -381,9 -404,9 +381,9 @@@ static const struct inode_operations ov
        .readlink       = ovl_readlink,
        .getattr        = ovl_getattr,
        .setxattr       = generic_setxattr,
 -      .getxattr       = ovl_getxattr,
 +      .getxattr       = generic_getxattr,
        .listxattr      = ovl_listxattr,
 -      .removexattr    = ovl_removexattr,
 +      .removexattr    = generic_removexattr,
        .update_time    = ovl_update_time,
  };
  
@@@ -392,9 -415,6 +392,9 @@@ static void ovl_fill_inode(struct inod
        inode->i_ino = get_next_ino();
        inode->i_mode = mode;
        inode->i_flags |= S_NOCMTIME;
 +#ifdef CONFIG_FS_POSIX_ACL
 +      inode->i_acl = inode->i_default_acl = ACL_DONT_CACHE;
 +#endif
  
        mode &= S_IFMT;
        switch (mode) {
diff --combined fs/posix_acl.c
@@@ -598,14 -598,13 +598,14 @@@ posix_acl_create(struct inode *dir, umo
        if (IS_ERR(p))
                return PTR_ERR(p);
  
 +      ret = -ENOMEM;
        clone = posix_acl_clone(p, GFP_NOFS);
        if (!clone)
 -              goto no_mem;
 +              goto err_release;
  
        ret = posix_acl_create_masq(clone, mode);
        if (ret < 0)
 -              goto no_mem_clone;
 +              goto err_release_clone;
  
        if (ret == 0)
                posix_acl_release(clone);
  
        return 0;
  
 -no_mem_clone:
 +err_release_clone:
        posix_acl_release(clone);
 -no_mem:
 +err_release:
        posix_acl_release(p);
 -      return -ENOMEM;
 +      return ret;
  }
  EXPORT_SYMBOL_GPL(posix_acl_create);
  
+ /**
+  * posix_acl_update_mode  -  update mode in set_acl
+  *
+  * Update the file mode when setting an ACL: compute the new file permission
+  * bits based on the ACL.  In addition, if the ACL is equivalent to the new
+  * file mode, set *acl to NULL to indicate that no ACL should be set.
+  *
+  * As with chmod, clear the setgit bit if the caller is not in the owning group
+  * or capable of CAP_FSETID (see inode_change_ok).
+  *
+  * Called from set_acl inode operations.
+  */
+ int posix_acl_update_mode(struct inode *inode, umode_t *mode_p,
+                         struct posix_acl **acl)
+ {
+       umode_t mode = inode->i_mode;
+       int error;
+       error = posix_acl_equiv_mode(*acl, &mode);
+       if (error < 0)
+               return error;
+       if (error == 0)
+               *acl = NULL;
+       if (!in_group_p(inode->i_gid) &&
+           !capable_wrt_inode_uidgid(inode, CAP_FSETID))
+               mode &= ~S_ISGID;
+       *mode_p = mode;
+       return 0;
+ }
+ EXPORT_SYMBOL(posix_acl_update_mode);
  /*
   * Fix up the uids and gids in posix acl extended attributes in place.
   */
@@@ -634,15 -664,15 +665,15 @@@ static void posix_acl_fix_xattr_userns
        struct user_namespace *to, struct user_namespace *from,
        void *value, size_t size)
  {
 -      posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
 -      posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
 +      struct posix_acl_xattr_header *header = value;
 +      struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
        int count;
        kuid_t uid;
        kgid_t gid;
  
        if (!value)
                return;
 -      if (size < sizeof(posix_acl_xattr_header))
 +      if (size < sizeof(struct posix_acl_xattr_header))
                return;
        if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
                return;
@@@ -692,15 -722,15 +723,15 @@@ struct posix_acl 
  posix_acl_from_xattr(struct user_namespace *user_ns,
                     const void *value, size_t size)
  {
 -      posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
 -      posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
 +      const struct posix_acl_xattr_header *header = value;
 +      const struct posix_acl_xattr_entry *entry = (const void *)(header + 1), *end;
        int count;
        struct posix_acl *acl;
        struct posix_acl_entry *acl_e;
  
        if (!value)
                return NULL;
 -      if (size < sizeof(posix_acl_xattr_header))
 +      if (size < sizeof(struct posix_acl_xattr_header))
                 return ERR_PTR(-EINVAL);
        if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
                return ERR_PTR(-EOPNOTSUPP);
@@@ -761,8 -791,8 +792,8 @@@ in
  posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
                   void *buffer, size_t size)
  {
 -      posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
 -      posix_acl_xattr_entry *ext_entry;
 +      struct posix_acl_xattr_header *ext_acl = buffer;
 +      struct posix_acl_xattr_entry *ext_entry;
        int real_size, n;
  
        real_size = posix_acl_xattr_size(acl->a_count);
        if (real_size > size)
                return -ERANGE;
  
 -      ext_entry = ext_acl->a_entries;
 +      ext_entry = (void *)(ext_acl + 1);
        ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
  
        for (n=0; n < acl->a_count; n++, ext_entry++) {
diff --combined fs/proc/base.c
@@@ -400,6 -400,23 +400,6 @@@ static const struct file_operations pro
        .llseek = generic_file_llseek,
  };
  
 -static int proc_pid_auxv(struct seq_file *m, struct pid_namespace *ns,
 -                       struct pid *pid, struct task_struct *task)
 -{
 -      struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
 -      if (mm && !IS_ERR(mm)) {
 -              unsigned int nwords = 0;
 -              do {
 -                      nwords += 2;
 -              } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
 -              seq_write(m, mm->saved_auxv, nwords * sizeof(mm->saved_auxv[0]));
 -              mmput(mm);
 -              return 0;
 -      } else
 -              return PTR_ERR(mm);
 -}
 -
 -
  #ifdef CONFIG_KALLSYMS
  /*
   * Provides a wchan file via kallsyms in a proper one-value-per-file format.
@@@ -692,7 -709,7 +692,7 @@@ int proc_setattr(struct dentry *dentry
        if (attr->ia_valid & ATTR_MODE)
                return -EPERM;
  
-       error = inode_change_ok(inode, attr);
+       error = setattr_prepare(dentry, attr);
        if (error)
                return error;
  
@@@ -997,30 -1014,6 +997,30 @@@ static const struct file_operations pro
        .release        = mem_release,
  };
  
 +static int auxv_open(struct inode *inode, struct file *file)
 +{
 +      return __mem_open(inode, file, PTRACE_MODE_READ_FSCREDS);
 +}
 +
 +static ssize_t auxv_read(struct file *file, char __user *buf,
 +                      size_t count, loff_t *ppos)
 +{
 +      struct mm_struct *mm = file->private_data;
 +      unsigned int nwords = 0;
 +      do {
 +              nwords += 2;
 +      } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
 +      return simple_read_from_buffer(buf, count, ppos, mm->saved_auxv,
 +                                     nwords * sizeof(mm->saved_auxv[0]));
 +}
 +
 +static const struct file_operations proc_auxv_operations = {
 +      .open           = auxv_open,
 +      .read           = auxv_read,
 +      .llseek         = generic_file_llseek,
 +      .release        = mem_release,
 +};
 +
  static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
                            loff_t *ppos)
  {
@@@ -1563,13 -1556,18 +1563,13 @@@ static const struct file_operations pro
  static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
  {
        struct task_struct *task;
 -      struct mm_struct *mm;
        struct file *exe_file;
  
        task = get_proc_task(d_inode(dentry));
        if (!task)
                return -ENOENT;
 -      mm = get_task_mm(task);
 +      exe_file = get_task_exe_file(task);
        put_task_struct(task);
 -      if (!mm)
 -              return -ENOENT;
 -      exe_file = get_mm_exe_file(mm);
 -      mmput(mm);
        if (exe_file) {
                *exe_path = exe_file->f_path;
                path_get(&exe_file->f_path);
@@@ -2829,7 -2827,7 +2829,7 @@@ static const struct pid_entry tgid_base
        DIR("net",        S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
  #endif
        REG("environ",    S_IRUSR, proc_environ_operations),
 -      ONE("auxv",       S_IRUSR, proc_pid_auxv),
 +      REG("auxv",       S_IRUSR, proc_auxv_operations),
        ONE("status",     S_IRUGO, proc_pid_status),
        ONE("personality", S_IRUSR, proc_pid_personality),
        ONE("limits",     S_IRUGO, proc_pid_limits),
@@@ -3217,7 -3215,7 +3217,7 @@@ static const struct pid_entry tid_base_
        DIR("net",        S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
  #endif
        REG("environ",   S_IRUSR, proc_environ_operations),
 -      ONE("auxv",      S_IRUSR, proc_pid_auxv),
 +      REG("auxv",      S_IRUSR, proc_auxv_operations),
        ONE("status",    S_IRUGO, proc_pid_status),
        ONE("personality", S_IRUSR, proc_pid_personality),
        ONE("limits",    S_IRUGO, proc_pid_limits),
diff --combined fs/utimes.c
@@@ -81,13 -81,27 +81,13 @@@ static int utimes_common(struct path *p
                        newattrs.ia_valid |= ATTR_MTIME_SET;
                }
                /*
-                * Tell inode_change_ok(), that this is an explicit time
+                * Tell setattr_prepare(), that this is an explicit time
                 * update, even if neither ATTR_ATIME_SET nor ATTR_MTIME_SET
                 * were used.
                 */
                newattrs.ia_valid |= ATTR_TIMES_SET;
        } else {
 -              /*
 -               * If times is NULL (or both times are UTIME_NOW),
 -               * then we need to check permissions, because
 -               * setattr_prepare() won't do it.
 -               */
 -              error = -EPERM;
 -                if (IS_IMMUTABLE(inode))
 -                      goto mnt_drop_write_and_out;
 -
 -              error = -EACCES;
 -              if (!inode_owner_or_capable(inode)) {
 -                      error = inode_permission(inode, MAY_WRITE);
 -                      if (error)
 -                              goto mnt_drop_write_and_out;
 -              }
 +              newattrs.ia_valid |= ATTR_TOUCH;
        }
  retry_deleg:
        inode_lock(inode);
                        goto retry_deleg;
        }
  
 -mnt_drop_write_and_out:
        mnt_drop_write(path->mnt);
  out:
        return error;
diff --combined fs/xfs/xfs_file.c
@@@ -741,20 -741,9 +741,20 @@@ xfs_file_dax_write
         * page is inserted into the pagecache when we have to serve a write
         * fault on a hole.  It should never be dirtied and can simply be
         * dropped from the pagecache once we get real data for the page.
 +       *
 +       * XXX: This is racy against mmap, and there's nothing we can do about
 +       * it. dax_do_io() should really do this invalidation internally as
 +       * it will know if we've allocated over a holei for this specific IO and
 +       * if so it needs to update the mapping tree and invalidate existing
 +       * PTEs over the newly allocated range. Remove this invalidation when
 +       * dax_do_io() is fixed up.
         */
        if (mapping->nrpages) {
 -              ret = invalidate_inode_pages2(mapping);
 +              loff_t end = iocb->ki_pos + iov_iter_count(from) - 1;
 +
 +              ret = invalidate_inode_pages2_range(mapping,
 +                                                  iocb->ki_pos >> PAGE_SHIFT,
 +                                                  end >> PAGE_SHIFT);
                WARN_ON_ONCE(ret);
        }
  
@@@ -984,7 -973,7 +984,7 @@@ xfs_file_fallocate
  
                iattr.ia_valid = ATTR_SIZE;
                iattr.ia_size = new_size;
-               error = xfs_setattr_size(ip, &iattr);
+               error = xfs_vn_setattr_size(file_dentry(file), &iattr);
                if (error)
                        goto out_unlock;
        }
diff --combined fs/xfs/xfs_iops.c
@@@ -542,6 -542,28 +542,28 @@@ xfs_setattr_time
                inode->i_mtime = iattr->ia_mtime;
  }
  
+ static int
+ xfs_vn_change_ok(
+       struct dentry   *dentry,
+       struct iattr    *iattr)
+ {
+       struct xfs_mount        *mp = XFS_I(d_inode(dentry))->i_mount;
+       if (mp->m_flags & XFS_MOUNT_RDONLY)
+               return -EROFS;
+       if (XFS_FORCED_SHUTDOWN(mp))
+               return -EIO;
+       return setattr_prepare(dentry, iattr);
+ }
+ /*
+  * Set non-size attributes of an inode.
+  *
+  * Caution: The caller of this function is responsible for calling
+  * setattr_prepare() or otherwise verifying the change is fine.
+  */
  int
  xfs_setattr_nonsize(
        struct xfs_inode        *ip,
        struct xfs_dquot        *udqp = NULL, *gdqp = NULL;
        struct xfs_dquot        *olddquot1 = NULL, *olddquot2 = NULL;
  
-       trace_xfs_setattr(ip);
-       /* If acls are being inherited, we already have this checked */
-       if (!(flags & XFS_ATTR_NOACL)) {
-               if (mp->m_flags & XFS_MOUNT_RDONLY)
-                       return -EROFS;
-               if (XFS_FORCED_SHUTDOWN(mp))
-                       return -EIO;
-               error = inode_change_ok(inode, iattr);
-               if (error)
-                       return error;
-       }
        ASSERT((mask & ATTR_SIZE) == 0);
  
        /*
@@@ -743,8 -750,27 +750,27 @@@ out_dqrele
        return error;
  }
  
+ int
+ xfs_vn_setattr_nonsize(
+       struct dentry           *dentry,
+       struct iattr            *iattr)
+ {
+       struct xfs_inode        *ip = XFS_I(d_inode(dentry));
+       int error;
+       trace_xfs_setattr(ip);
+       error = xfs_vn_change_ok(dentry, iattr);
+       if (error)
+               return error;
+       return xfs_setattr_nonsize(ip, iattr, 0);
+ }
  /*
   * Truncate file.  Must have write permission and not be a directory.
+  *
+  * Caution: The caller of this function is responsible for calling
+  * setattr_prepare() or otherwise verifying the change is fine.
   */
  int
  xfs_setattr_size(
        uint                    lock_flags = 0;
        bool                    did_zeroing = false;
  
-       trace_xfs_setattr(ip);
-       if (mp->m_flags & XFS_MOUNT_RDONLY)
-               return -EROFS;
-       if (XFS_FORCED_SHUTDOWN(mp))
-               return -EIO;
-       error = inode_change_ok(inode, iattr);
-       if (error)
-               return error;
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
        ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL));
        ASSERT(S_ISREG(inode->i_mode));
@@@ -942,16 -956,32 +956,32 @@@ out_trans_cancel
        goto out_unlock;
  }
  
+ int
+ xfs_vn_setattr_size(
+       struct dentry           *dentry,
+       struct iattr            *iattr)
+ {
+       struct xfs_inode        *ip = XFS_I(d_inode(dentry));
+       int error;
+       trace_xfs_setattr(ip);
+       error = xfs_vn_change_ok(dentry, iattr);
+       if (error)
+               return error;
+       return xfs_setattr_size(ip, iattr);
+ }
  STATIC int
  xfs_vn_setattr(
        struct dentry           *dentry,
        struct iattr            *iattr)
  {
-       struct xfs_inode        *ip = XFS_I(d_inode(dentry));
        int                     error;
  
        if (iattr->ia_valid & ATTR_SIZE) {
-               uint            iolock = XFS_IOLOCK_EXCL;
+               struct xfs_inode        *ip = XFS_I(d_inode(dentry));
+               uint                    iolock = XFS_IOLOCK_EXCL;
  
                xfs_ilock(ip, iolock);
                error = xfs_break_layouts(d_inode(dentry), &iolock, true);
                        xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
                        iolock |= XFS_MMAPLOCK_EXCL;
  
-                       error = xfs_setattr_size(ip, iattr);
+                       error = xfs_vn_setattr_size(dentry, iattr);
                }
                xfs_iunlock(ip, iolock);
        } else {
-               error = xfs_setattr_nonsize(ip, iattr, 0);
+               error = xfs_vn_setattr_nonsize(dentry, iattr);
        }
  
        return error;
@@@ -1009,14 -1039,7 +1039,14 @@@ xfs_vn_fiemap
        int                     error;
  
        xfs_ilock(XFS_I(inode), XFS_IOLOCK_SHARED);
 -      error = iomap_fiemap(inode, fieinfo, start, length, &xfs_iomap_ops);
 +      if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
 +              fieinfo->fi_flags &= ~FIEMAP_FLAG_XATTR;
 +              error = iomap_fiemap(inode, fieinfo, start, length,
 +                              &xfs_xattr_iomap_ops);
 +      } else {
 +              error = iomap_fiemap(inode, fieinfo, start, length,
 +                              &xfs_iomap_ops);
 +      }
        xfs_iunlock(XFS_I(inode), XFS_IOLOCK_SHARED);
  
        return error;
diff --combined include/linux/fs.h
@@@ -63,7 -63,7 +63,7 @@@ extern void __init files_maxfiles_init(
  
  extern struct files_stat_struct files_stat;
  extern unsigned long get_max_files(void);
 -extern int sysctl_nr_open;
 +extern unsigned int sysctl_nr_open;
  extern struct inodes_stat_t inodes_stat;
  extern int leases_enable, lease_break_time;
  extern int sysctl_protected_symlinks;
@@@ -224,7 -224,6 +224,7 @@@ typedef int (dio_iodone_t)(struct kioc
  #define ATTR_KILL_PRIV        (1 << 14)
  #define ATTR_OPEN     (1 << 15) /* Truncating from open(O_TRUNC) */
  #define ATTR_TIMES_SET        (1 << 16)
 +#define ATTR_TOUCH    (1 << 17)
  
  /*
   * Whiteout is represented by a char device.  The following constants define the
@@@ -575,7 -574,6 +575,7 @@@ static inline void mapping_allow_writab
  
  struct posix_acl;
  #define ACL_NOT_CACHED ((void *)(-1))
 +#define ACL_DONT_CACHE ((void *)(-3))
  
  static inline struct posix_acl *
  uncached_acl_sentinel(struct task_struct *task)
@@@ -1065,18 -1063,6 +1065,18 @@@ struct file_lock_context 
  
  extern void send_sigio(struct fown_struct *fown, int fd, int band);
  
 +/*
 + * Return the inode to use for locking
 + *
 + * For overlayfs this should be the overlay inode, not the real inode returned
 + * by file_inode().  For any other fs file_inode(filp) and locks_inode(filp) are
 + * equal.
 + */
 +static inline struct inode *locks_inode(const struct file *f)
 +{
 +      return f->f_path.dentry->d_inode;
 +}
 +
  #ifdef CONFIG_FILE_LOCKING
  extern int fcntl_getlk(struct file *, unsigned int, struct flock __user *);
  extern int fcntl_setlk(unsigned int, struct file *, unsigned int,
@@@ -1264,7 -1250,7 +1264,7 @@@ static inline struct dentry *file_dentr
  
  static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl)
  {
 -      return locks_lock_inode_wait(file_inode(filp), fl);
 +      return locks_lock_inode_wait(locks_inode(filp), fl);
  }
  
  struct fasync_struct {
@@@ -2019,6 -2005,7 +2019,6 @@@ enum file_time_flags 
        S_VERSION = 8,
  };
  
 -extern bool atime_needs_update(const struct path *, struct inode *);
  extern void touch_atime(const struct path *);
  static inline void file_accessed(struct file *file)
  {
@@@ -2167,7 -2154,7 +2167,7 @@@ static inline int mandatory_lock(struc
  
  static inline int locks_verify_locked(struct file *file)
  {
 -      if (mandatory_lock(file_inode(file)))
 +      if (mandatory_lock(locks_inode(file)))
                return locks_mandatory_locked(file);
        return 0;
  }
@@@ -3007,7 -2994,7 +3007,7 @@@ extern int buffer_migrate_page(struct a
  #define buffer_migrate_page NULL
  #endif
  
- extern int inode_change_ok(const struct inode *, struct iattr *);
+ extern int setattr_prepare(struct dentry *, struct iattr *);
  extern int inode_newsize_ok(const struct inode *, loff_t offset);
  extern void setattr_copy(struct inode *inode, const struct iattr *attr);
  
  #include <linux/bug.h>
  #include <linux/slab.h>
  #include <linux/rcupdate.h>
 -
 -#define ACL_UNDEFINED_ID      (-1)
 -
 -/* a_type field in acl_user_posix_entry_t */
 -#define ACL_TYPE_ACCESS               (0x8000)
 -#define ACL_TYPE_DEFAULT      (0x4000)
 -
 -/* e_tag entry in struct posix_acl_entry */
 -#define ACL_USER_OBJ          (0x01)
 -#define ACL_USER              (0x02)
 -#define ACL_GROUP_OBJ         (0x04)
 -#define ACL_GROUP             (0x08)
 -#define ACL_MASK              (0x10)
 -#define ACL_OTHER             (0x20)
 -
 -/* permissions in the e_perm field */
 -#define ACL_READ              (0x04)
 -#define ACL_WRITE             (0x02)
 -#define ACL_EXECUTE           (0x01)
 -//#define ACL_ADD             (0x08)
 -//#define ACL_DELETE          (0x10)
 +#include <uapi/linux/posix_acl.h>
  
  struct posix_acl_entry {
        short                   e_tag;
@@@ -73,6 -93,7 +73,7 @@@ extern int set_posix_acl(struct inode *
  extern int posix_acl_chmod(struct inode *, umode_t);
  extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **,
                struct posix_acl **);
+ extern int posix_acl_update_mode(struct inode *, umode_t *, struct posix_acl **);
  
  extern int simple_set_acl(struct inode *, struct posix_acl *, int);
  extern int simple_acl_create(struct inode *, struct inode *);
diff --combined mm/shmem.c
@@@ -270,7 -270,7 +270,7 @@@ bool shmem_charge(struct inode *inode, 
                info->alloced -= pages;
                shmem_recalc_inode(inode);
                spin_unlock_irqrestore(&info->lock, flags);
 -
 +              shmem_unacct_blocks(info->flags, pages);
                return false;
        }
        percpu_counter_add(&sbinfo->used_blocks, pages);
@@@ -291,7 -291,6 +291,7 @@@ void shmem_uncharge(struct inode *inode
  
        if (sbinfo->max_blocks)
                percpu_counter_sub(&sbinfo->used_blocks, pages);
 +      shmem_unacct_blocks(info->flags, pages);
  }
  
  /*
@@@ -960,7 -959,7 +960,7 @@@ static int shmem_setattr(struct dentry 
        struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
        int error;
  
-       error = inode_change_ok(inode, attr);
+       error = setattr_prepare(dentry, attr);
        if (error)
                return error;
  
@@@ -1981,7 -1980,7 +1981,7 @@@ unsigned long shmem_get_unmapped_area(s
                                return addr;
                        sb = shm_mnt->mnt_sb;
                }
 -              if (SHMEM_SB(sb)->huge != SHMEM_HUGE_NEVER)
 +              if (SHMEM_SB(sb)->huge == SHMEM_HUGE_NEVER)
                        return addr;
        }
  
@@@ -3976,9 -3975,7 +3976,9 @@@ static ssize_t shmem_enabled_store(stru
  
  struct kobj_attribute shmem_enabled_attr =
        __ATTR(shmem_enabled, 0644, shmem_enabled_show, shmem_enabled_store);
 +#endif /* CONFIG_TRANSPARENT_HUGE_PAGECACHE && CONFIG_SYSFS */
  
 +#ifdef CONFIG_TRANSPARENT_HUGE_PAGECACHE
  bool shmem_huge_enabled(struct vm_area_struct *vma)
  {
        struct inode *inode = file_inode(vma->vm_file);
                        return false;
        }
  }
 -#endif /* CONFIG_TRANSPARENT_HUGE_PAGECACHE && CONFIG_SYSFS */
 +#endif /* CONFIG_TRANSPARENT_HUGE_PAGECACHE */
  
  #else /* !CONFIG_SHMEM */