Merge branch 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 11 Oct 2016 00:11:50 +0000 (17:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 11 Oct 2016 00:11:50 +0000 (17:11 -0700)
Pull vfs xattr updates from Al Viro:
 "xattr stuff from Andreas

  This completes the switch to xattr_handler ->get()/->set() from
  ->getxattr/->setxattr/->removexattr"

* 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  vfs: Remove {get,set,remove}xattr inode operations
  xattr: Stop calling {get,set,remove}xattr inode operations
  vfs: Check for the IOP_XATTR flag in listxattr
  xattr: Add __vfs_{get,set,remove}xattr helpers
  libfs: Use IOP_XATTR flag for empty directory handling
  vfs: Use IOP_XATTR flag for bad-inode handling
  vfs: Add IOP_XATTR inode operations flag
  vfs: Move xattr_resolve_name to the front of fs/xattr.c
  ecryptfs: Switch to generic xattr handlers
  sockfs: Get rid of getxattr iop
  sockfs: getxattr: Fail with -EOPNOTSUPP for invalid attribute names
  kernfs: Switch to generic xattr handlers
  hfs: Switch to generic xattr handlers
  jffs2: Remove jffs2_{get,set,remove}xattr macros
  xattr: Remove unnecessary NULL attribute name check

37 files changed:
1  2 
Documentation/filesystems/vfs.txt
drivers/staging/lustre/lustre/llite/file.c
drivers/staging/lustre/lustre/llite/namei.c
drivers/staging/lustre/lustre/llite/symlink.c
fs/9p/vfs_inode_dotl.c
fs/btrfs/inode.c
fs/cachefiles/namei.c
fs/ceph/inode.c
fs/ecryptfs/inode.c
fs/ext2/file.c
fs/ext4/file.c
fs/ext4/namei.c
fs/ext4/symlink.c
fs/f2fs/file.c
fs/f2fs/namei.c
fs/fuse/dir.c
fs/gfs2/inode.c
fs/hfs/inode.c
fs/hfsplus/inode.c
fs/inode.c
fs/jfs/file.c
fs/kernfs/inode.c
fs/libfs.c
fs/ocfs2/file.c
fs/orangefs/inode.c
fs/orangefs/namei.c
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/inode.c
fs/overlayfs/super.c
fs/ubifs/file.c
fs/xfs/xfs_iops.c
include/linux/fs.h
mm/shmem.c
security/integrity/ima/ima_appraise.c
security/selinux/hooks.c
security/smack/smack_lsm.c

@@@ -323,6 -323,35 +323,35 @@@ Whoever sets up the inode is responsibl
  is a pointer to a "struct inode_operations" which describes the methods that
  can be performed on individual inodes.
  
+ struct xattr_handlers
+ ---------------------
+ On filesystems that support extended attributes (xattrs), the s_xattr
+ superblock field points to a NULL-terminated array of xattr handlers.  Extended
+ attributes are name:value pairs.
+   name: Indicates that the handler matches attributes with the specified name
+       (such as "system.posix_acl_access"); the prefix field must be NULL.
+   prefix: Indicates that the handler matches all attributes with the specified
+       name prefix (such as "user."); the name field must be NULL.
+   list: Determine if attributes matching this xattr handler should be listed
+       for a particular dentry.  Used by some listxattr implementations like
+       generic_listxattr.
+   get: Called by the VFS to get the value of a particular extended attribute.
+       This method is called by the getxattr(2) system call.
+   set: Called by the VFS to set the value of a particular extended attribute.
+       When the new value is NULL, called to remove a particular extended
+       attribute.  This method is called by the the setxattr(2) and
+       removexattr(2) system calls.
+ When none of the xattr handlers of a filesystem match the specified attribute
+ name or when a filesystem doesn't support extended attributes, the various
+ *xattr(2) system calls return -EOPNOTSUPP.
  
  The Inode Object
  ================
@@@ -356,10 -385,7 +385,7 @@@ struct inode_operations 
        int (*get_acl)(struct inode *, int);
        int (*setattr) (struct dentry *, struct iattr *);
        int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
-       int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
-       ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
-       int (*removexattr) (struct dentry *, const char *);
        void (*update_time)(struct inode *, struct timespec *, int);
        int (*atomic_open)(struct inode *, struct dentry *, struct file *,
                        unsigned open_flag, umode_t create_mode, int *opened);
@@@ -463,19 -489,8 +489,8 @@@ otherwise noted
    getattr: called by the VFS to get attributes of a file. This method
        is called by stat(2) and related system calls.
  
-   setxattr: called by the VFS to set an extended attribute for a file.
-       Extended attribute is a name:value pair associated with an
-       inode. This method is called by setxattr(2) system call.
-   getxattr: called by the VFS to retrieve the value of an extended
-       attribute name. This method is called by getxattr(2) function
-       call.
    listxattr: called by the VFS to list all extended attributes for a
-       given file. This method is called by listxattr(2) system call.
-   removexattr: called by the VFS to remove an extended attribute from
-       a file. This method is called by removexattr(2) system call.
+       given file. This method is called by the listxattr(2) system call.
  
    update_time: called by the VFS to update a specific time or the i_version of
        an inode.  If this is not defined the VFS will update the inode itself
@@@ -722,7 -737,7 +737,7 @@@ struct address_space_operations 
  
        The second case is when a request has been made to invalidate
          some or all pages in an address_space.  This can happen
 -        through the fadvice(POSIX_FADV_DONTNEED) system call or by the
 +        through the fadvise(POSIX_FADV_DONTNEED) system call or by the
          filesystem explicitly requesting it as nfs and 9fs do (when
          they believe the cache may be out of date with storage) by
          calling invalidate_inode_pages2().
  
  #define DEBUG_SUBSYSTEM S_LLITE
  #include "../include/lustre_dlm.h"
 -#include "../include/lustre_lite.h"
  #include <linux/pagemap.h>
  #include <linux/file.h>
 +#include <linux/sched.h>
  #include <linux/mount.h>
 -#include "llite_internal.h"
  #include "../include/lustre/ll_fiemap.h"
 +#include "../include/lustre/lustre_ioctl.h"
  
  #include "../include/cl_object.h"
 +#include "llite_internal.h"
  
  static int
  ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg);
@@@ -189,11 -188,17 +189,11 @@@ static int ll_close_inode_openhandle(st
                spin_unlock(&lli->lli_lock);
        }
  
 -      if (rc == 0) {
 -              rc = ll_objects_destroy(req, inode);
 -              if (rc)
 -                      CERROR("inode %lu ll_objects destroy: rc = %d\n",
 -                             inode->i_ino, rc);
 -      }
        if (rc == 0 && op_data->op_bias & MDS_HSM_RELEASE) {
                struct mdt_body *body;
  
                body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
 -              if (!(body->valid & OBD_MD_FLRELEASED))
 +              if (!(body->mbo_valid & OBD_MD_FLRELEASED))
                        rc = -EBUSY;
        }
  
@@@ -344,11 -349,13 +344,11 @@@ int ll_file_release(struct inode *inode
        fd = LUSTRE_FPRIVATE(file);
        LASSERT(fd);
  
 -      /* The last ref on @file, maybe not be the owner pid of statahead.
 -       * Different processes can open the same dir, "ll_opendir_key" means:
 -       * it is me that should stop the statahead thread.
 +      /* The last ref on @file, maybe not be the owner pid of statahead,
 +       * because parent and child process can share the same file handle.
         */
 -      if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd &&
 -          lli->lli_opendir_pid != 0)
 -              ll_stop_statahead(inode, lli->lli_opendir_key);
 +      if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd)
 +              ll_deauthorize_statahead(inode, fd);
  
        if (is_root_inode(inode)) {
                LUSTRE_FPRIVATE(file) = NULL;
        }
  
        if (!S_ISDIR(inode->i_mode)) {
 -              lov_read_and_clear_async_rc(lli->lli_clob);
 +              if (lli->lli_clob)
 +                      lov_read_and_clear_async_rc(lli->lli_clob);
                lli->lli_async_rc = 0;
        }
  
        return rc;
  }
  
 -static int ll_intent_file_open(struct dentry *dentry, void *lmm,
 -                             int lmmsize, struct lookup_intent *itp)
 +static int ll_intent_file_open(struct dentry *de, void *lmm, int lmmsize,
 +                             struct lookup_intent *itp)
  {
 -      struct inode *inode = d_inode(dentry);
 +      struct inode *inode = d_inode(de);
        struct ll_sb_info *sbi = ll_i2sbi(inode);
 -      struct dentry *parent = dentry->d_parent;
 -      const char *name = dentry->d_name.name;
 -      const int len = dentry->d_name.len;
 +      struct dentry *parent = de->d_parent;
 +      const char *name = NULL;
        struct md_op_data *op_data;
 -      struct ptlrpc_request *req;
 -      __u32 opc = LUSTRE_OPC_ANY;
 -      int rc;
 +      struct ptlrpc_request *req = NULL;
 +      int len = 0, rc;
  
 -      /* Usually we come here only for NFSD, and we want open lock. */
 -      /* We can also get here if there was cached open handle in revalidate_it
 -       * but it disappeared while we were getting from there to ll_file_open.
 -       * But this means this file was closed and immediately opened which
 -       * makes a good candidate for using OPEN lock
 -       */
 -      /* If lmmsize & lmm are not 0, we are just setting stripe info
 -       * parameters. No need for the open lock
 +      LASSERT(parent);
 +      LASSERT(itp->it_flags & MDS_OPEN_BY_FID);
 +
 +      /*
 +       * if server supports open-by-fid, or file name is invalid, don't pack
 +       * name in open request
         */
 -      if (!lmm && lmmsize == 0) {
 -              struct ll_dentry_data *ldd = ll_d2d(dentry);
 -              /*
 -               * If we came via ll_iget_for_nfs, then we need to request
 -               * struct ll_dentry_data *ldd = ll_d2d(file->f_dentry);
 -               *
 -               * NB: when ldd is NULL, it must have come via normal
 -               * lookup path only, since ll_iget_for_nfs always calls
 -               * ll_d_init().
 -               */
 -              if (ldd && ldd->lld_nfs_dentry) {
 -                      ldd->lld_nfs_dentry = 0;
 -                      itp->it_flags |= MDS_OPEN_LOCK;
 -              }
 -              if (itp->it_flags & FMODE_WRITE)
 -                      opc = LUSTRE_OPC_CREATE;
 +      if (!(exp_connect_flags(sbi->ll_md_exp) & OBD_CONNECT_OPEN_BY_FID) &&
 +          lu_name_is_valid_2(de->d_name.name, de->d_name.len)) {
 +              name = de->d_name.name;
 +              len = de->d_name.len;
        }
  
 -      op_data  = ll_prep_md_op_data(NULL, d_inode(parent),
 -                                    inode, name, len,
 -                                    O_RDWR, opc, NULL);
 +      op_data  = ll_prep_md_op_data(NULL, d_inode(parent), inode, name, len,
 +                                    O_RDWR, LUSTRE_OPC_ANY, NULL);
        if (IS_ERR(op_data))
                return PTR_ERR(op_data);
 +      op_data->op_data = lmm;
 +      op_data->op_data_size = lmmsize;
  
 -      itp->it_flags |= MDS_OPEN_BY_FID;
 -      rc = md_intent_lock(sbi->ll_md_exp, op_data, lmm, lmmsize, itp,
 -                          0 /*unused */, &req, ll_md_blocking_ast, 0);
 +      rc = md_intent_lock(sbi->ll_md_exp, op_data, itp, &req,
 +                          &ll_md_blocking_ast, 0);
        ll_finish_md_op_data(op_data);
        if (rc == -ESTALE) {
                /* reason for keep own exit path - don`t flood log
@@@ -457,8 -479,8 +457,8 @@@ static int ll_och_fill(struct obd_expor
        struct mdt_body *body;
  
        body = req_capsule_server_get(&it->it_request->rq_pill, &RMF_MDT_BODY);
 -      och->och_fh = body->handle;
 -      och->och_fid = body->fid1;
 +      och->och_fh = body->mbo_handle;
 +      och->och_fid = body->mbo_fid1;
        och->och_lease_handle.cookie = it->it_lock_handle;
        och->och_magic = OBD_CLIENT_HANDLE_MAGIC;
        och->och_flags = it->it_flags;
@@@ -486,7 -508,7 +486,7 @@@ static int ll_local_open(struct file *f
  
                body = req_capsule_server_get(&it->it_request->rq_pill,
                                              &RMF_MDT_BODY);
 -              ll_ioepoch_open(lli, body->ioepoch);
 +              ll_ioepoch_open(lli, body->mbo_ioepoch);
        }
  
        LUSTRE_FPRIVATE(file) = fd;
@@@ -521,7 -543,7 +521,7 @@@ int ll_file_open(struct inode *inode, s
        struct obd_client_handle **och_p = NULL;
        __u64 *och_usecount = NULL;
        struct ll_file_data *fd;
 -      int rc = 0, opendir_set = 0;
 +      int rc = 0;
  
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), flags %o\n",
               PFID(ll_inode2fid(inode)), inode, file->f_flags);
        }
  
        fd->fd_file = file;
 -      if (S_ISDIR(inode->i_mode)) {
 -              spin_lock(&lli->lli_sa_lock);
 -              if (!lli->lli_opendir_key && !lli->lli_sai &&
 -                  lli->lli_opendir_pid == 0) {
 -                      lli->lli_opendir_key = fd;
 -                      lli->lli_opendir_pid = current_pid();
 -                      opendir_set = 1;
 -              }
 -              spin_unlock(&lli->lli_sa_lock);
 -      }
 +      if (S_ISDIR(inode->i_mode))
 +              ll_authorize_statahead(inode, fd);
  
        if (is_root_inode(inode)) {
                LUSTRE_FPRIVATE(file) = fd;
@@@ -585,7 -615,7 +585,7 @@@ restart
        } else if (it->it_flags & FMODE_EXEC) {
                och_p = &lli->lli_mds_exec_och;
                och_usecount = &lli->lli_open_fd_exec_count;
 -       } else {
 +      } else {
                och_p = &lli->lli_mds_read_och;
                och_usecount = &lli->lli_open_fd_read_count;
        }
                         * result in a deadlock
                         */
                        mutex_unlock(&lli->lli_och_mutex);
 -                      it->it_create_mode |= M_CHECK_STALE;
 +                      /*
 +                       * Normally called under two situations:
 +                       * 1. NFS export.
 +                       * 2. revalidate with IT_OPEN (revalidate doesn't
 +                       *    execute this intent any more).
 +                       *
 +                       * Always fetch MDS_OPEN_LOCK if this is not setstripe.
 +                       *
 +                       * Always specify MDS_OPEN_BY_FID because we don't want
 +                       * to get file with different fid.
 +                       */
 +                      it->it_flags |= MDS_OPEN_LOCK | MDS_OPEN_BY_FID;
                        rc = ll_intent_file_open(file->f_path.dentry, NULL, 0, it);
 -                      it->it_create_mode &= ~M_CHECK_STALE;
                        if (rc)
                                goto out_openerr;
  
@@@ -696,10 -716,9 +696,10 @@@ out_och_free
                mutex_unlock(&lli->lli_och_mutex);
  
  out_openerr:
 -              if (opendir_set != 0)
 -                      ll_stop_statahead(inode, lli->lli_opendir_key);
 -              ll_file_data_put(fd);
 +              if (lli->lli_opendir_key == fd)
 +                      ll_deauthorize_statahead(inode, fd);
 +              if (fd)
 +                      ll_file_data_put(fd);
        } else {
                ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_OPEN, 1);
        }
@@@ -745,7 -764,7 +745,7 @@@ ll_lease_open(struct inode *inode, stru
        struct lookup_intent it = { .it_op = IT_OPEN };
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct md_op_data *op_data;
 -      struct ptlrpc_request *req;
 +      struct ptlrpc_request *req = NULL;
        struct lustre_handle old_handle = { 0 };
        struct obd_client_handle *och = NULL;
        int rc;
  
        it.it_flags = fmode | open_flags;
        it.it_flags |= MDS_OPEN_LOCK | MDS_OPEN_BY_FID | MDS_OPEN_LEASE;
 -      rc = md_intent_lock(sbi->ll_md_exp, op_data, NULL, 0, &it, 0, &req,
 -                          ll_md_blocking_lease_ast,
 +      rc = md_intent_lock(sbi->ll_md_exp, op_data, &it, &req,
 +                          &ll_md_blocking_lease_ast,
        /* LDLM_FL_NO_LRU: To not put the lease lock into LRU list, otherwise
         * it can be cancelled which may mislead applications that the lease is
         * broken;
         * open in ll_md_blocking_ast(). Otherwise as ll_md_blocking_lease_ast
         * doesn't deal with openhandle, so normal openhandle will be leaked.
         */
 -                              LDLM_FL_NO_LRU | LDLM_FL_EXCL);
 +                          LDLM_FL_NO_LRU | LDLM_FL_EXCL);
        ll_finish_md_op_data(op_data);
        ptlrpc_req_finished(req);
        if (rc < 0)
@@@ -889,6 -908,7 +889,6 @@@ static int ll_lease_close(struct obd_cl
  {
        struct ldlm_lock *lock;
        bool cancelled = true;
 -      int rc;
  
        lock = ldlm_handle2lock(&och->och_lease_handle);
        if (lock) {
        if (lease_broken)
                *lease_broken = cancelled;
  
 -      rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, inode, och,
 -                                     NULL);
 -      return rc;
 +      return ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp,
 +                                       inode, och, NULL);
  }
  
  /* Fills the obdo with the attributes for the lsm */
@@@ -1117,12 -1138,11 +1117,12 @@@ ll_file_io_generic(const struct lu_env 
  {
        struct ll_inode_info *lli = ll_i2info(file_inode(file));
        struct ll_file_data  *fd  = LUSTRE_FPRIVATE(file);
 +      struct range_lock range;
        struct cl_io     *io;
        ssize_t        result;
  
 -      CDEBUG(D_VFSTRACE, "file: %s, type: %d ppos: %llu, count: %zd\n",
 -             file->f_path.dentry->d_name.name, iot, *ppos, count);
 +      CDEBUG(D_VFSTRACE, "file: %pD, type: %d ppos: %llu, count: %zu\n",
 +             file, iot, *ppos, count);
  
  restart:
        io = vvp_env_thread_io(env);
  
        if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) {
                struct vvp_io *vio = vvp_env_io(env);
 -              int write_mutex_locked = 0;
 +              bool range_locked = false;
 +
 +              if (file->f_flags & O_APPEND)
 +                      range_lock_init(&range, 0, LUSTRE_EOF);
 +              else
 +                      range_lock_init(&range, *ppos, *ppos + count - 1);
  
                vio->vui_fd  = LUSTRE_FPRIVATE(file);
 -              vio->vui_io_subtype = args->via_io_subtype;
 -
 -              switch (vio->vui_io_subtype) {
 -              case IO_NORMAL:
 -                      vio->vui_iter = args->u.normal.via_iter;
 -                      vio->vui_iocb = args->u.normal.via_iocb;
 -                      if ((iot == CIT_WRITE) &&
 -                          !(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
 -                              if (mutex_lock_interruptible(&lli->
 -                                                             lli_write_mutex)) {
 -                                      result = -ERESTARTSYS;
 -                                      goto out;
 -                              }
 -                              write_mutex_locked = 1;
 -                      }
 -                      down_read(&lli->lli_trunc_sem);
 -                      break;
 -              case IO_SPLICE:
 -                      vio->u.splice.vui_pipe = args->u.splice.via_pipe;
 -                      vio->u.splice.vui_flags = args->u.splice.via_flags;
 -                      break;
 -              default:
 -                      CERROR("Unknown IO type - %u\n", vio->vui_io_subtype);
 -                      LBUG();
 +              vio->vui_iter = args->u.normal.via_iter;
 +              vio->vui_iocb = args->u.normal.via_iocb;
 +              /*
 +               * Direct IO reads must also take range lock,
 +               * or multiple reads will try to work on the same pages
 +               * See LU-6227 for details.
 +               */
 +              if (((iot == CIT_WRITE) ||
 +                   (iot == CIT_READ && (file->f_flags & O_DIRECT))) &&
 +                  !(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
 +                      CDEBUG(D_VFSTRACE, "Range lock [%llu, %llu]\n",
 +                             range.rl_node.in_extent.start,
 +                             range.rl_node.in_extent.end);
 +                      result = range_lock(&lli->lli_write_tree,
 +                                          &range);
 +                      if (result < 0)
 +                              goto out;
 +
 +                      range_locked = true;
                }
 +              down_read(&lli->lli_trunc_sem);
                ll_cl_add(file, env, io);
                result = cl_io_loop(env, io);
                ll_cl_remove(file, env);
 -              if (args->via_io_subtype == IO_NORMAL)
 -                      up_read(&lli->lli_trunc_sem);
 -              if (write_mutex_locked)
 -                      mutex_unlock(&lli->lli_write_mutex);
 +              up_read(&lli->lli_trunc_sem);
 +              if (range_locked) {
 +                      CDEBUG(D_VFSTRACE, "Range unlock [%llu, %llu]\n",
 +                             range.rl_node.in_extent.start,
 +                             range.rl_node.in_extent.end);
 +                      range_unlock(&lli->lli_write_tree, &range);
 +              }
        } else {
                /* cl_io_rw_init() handled IO */
                result = io->ci_result;
@@@ -1185,7 -1201,7 +1185,7 @@@ out
         * short read/write instead of restart io.
         */
        if ((result == 0 || result == -ENODATA) && io->ci_need_restart) {
 -              CDEBUG(D_VFSTRACE, "Restart %s on %pD from %lld, count:%zd\n",
 +              CDEBUG(D_VFSTRACE, "Restart %s on %pD from %lld, count:%zu\n",
                       iot == CIT_READ ? "read" : "write",
                       file, *ppos, count);
                LASSERTF(io->ci_nob == 0, "%zd\n", io->ci_nob);
@@@ -1221,7 -1237,7 +1221,7 @@@ static ssize_t ll_file_read_iter(struc
        if (IS_ERR(env))
                return PTR_ERR(env);
  
 -      args = ll_env_args(env, IO_NORMAL);
 +      args = ll_env_args(env);
        args->u.normal.via_iter = to;
        args->u.normal.via_iocb = iocb;
  
@@@ -1245,7 -1261,7 +1245,7 @@@ static ssize_t ll_file_write_iter(struc
        if (IS_ERR(env))
                return PTR_ERR(env);
  
 -      args = ll_env_args(env, IO_NORMAL);
 +      args = ll_env_args(env);
        args->u.normal.via_iter = from;
        args->u.normal.via_iocb = iocb;
  
        return result;
  }
  
 -/*
 - * Send file content (through pagecache) somewhere with helper
 - */
 -static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos,
 -                                 struct pipe_inode_info *pipe, size_t count,
 -                                 unsigned int flags)
 -{
 -      struct lu_env      *env;
 -      struct vvp_io_args *args;
 -      ssize_t      result;
 -      int              refcheck;
 -
 -      env = cl_env_get(&refcheck);
 -      if (IS_ERR(env))
 -              return PTR_ERR(env);
 -
 -      args = ll_env_args(env, IO_SPLICE);
 -      args->u.splice.via_pipe = pipe;
 -      args->u.splice.via_flags = flags;
 -
 -      result = ll_file_io_generic(env, args, in_file, CIT_READ, ppos, count);
 -      cl_env_put(env, &refcheck);
 -      return result;
 -}
 -
 -static int ll_lov_recreate(struct inode *inode, struct ost_id *oi, u32 ost_idx)
 -{
 -      struct obd_export *exp = ll_i2dtexp(inode);
 -      struct obd_trans_info oti = { 0 };
 -      struct obdo *oa = NULL;
 -      int lsm_size;
 -      int rc = 0;
 -      struct lov_stripe_md *lsm = NULL, *lsm2;
 -
 -      oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS);
 -      if (!oa)
 -              return -ENOMEM;
 -
 -      lsm = ccc_inode_lsm_get(inode);
 -      if (!lsm_has_objects(lsm)) {
 -              rc = -ENOENT;
 -              goto out;
 -      }
 -
 -      lsm_size = sizeof(*lsm) + (sizeof(struct lov_oinfo) *
 -                 (lsm->lsm_stripe_count));
 -
 -      lsm2 = libcfs_kvzalloc(lsm_size, GFP_NOFS);
 -      if (!lsm2) {
 -              rc = -ENOMEM;
 -              goto out;
 -      }
 -
 -      oa->o_oi = *oi;
 -      oa->o_nlink = ost_idx;
 -      oa->o_flags |= OBD_FL_RECREATE_OBJS;
 -      oa->o_valid = OBD_MD_FLID | OBD_MD_FLFLAGS | OBD_MD_FLGROUP;
 -      obdo_from_inode(oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME |
 -                                 OBD_MD_FLMTIME | OBD_MD_FLCTIME);
 -      obdo_set_parent_fid(oa, &ll_i2info(inode)->lli_fid);
 -      memcpy(lsm2, lsm, lsm_size);
 -      ll_inode_size_lock(inode);
 -      rc = obd_create(NULL, exp, oa, &lsm2, &oti);
 -      ll_inode_size_unlock(inode);
 -
 -      kvfree(lsm2);
 -      goto out;
 -out:
 -      ccc_inode_lsm_put(inode, lsm);
 -      kmem_cache_free(obdo_cachep, oa);
 -      return rc;
 -}
 -
 -static int ll_lov_recreate_obj(struct inode *inode, unsigned long arg)
 -{
 -      struct ll_recreate_obj ucreat;
 -      struct ost_id           oi;
 -
 -      if (!capable(CFS_CAP_SYS_ADMIN))
 -              return -EPERM;
 -
 -      if (copy_from_user(&ucreat, (struct ll_recreate_obj __user *)arg,
 -                         sizeof(ucreat)))
 -              return -EFAULT;
 -
 -      ostid_set_seq_mdt0(&oi);
 -      ostid_set_id(&oi, ucreat.lrc_id);
 -      return ll_lov_recreate(inode, &oi, ucreat.lrc_ost_idx);
 -}
 -
 -static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg)
 -{
 -      struct lu_fid   fid;
 -      struct ost_id   oi;
 -      u32             ost_idx;
 -
 -      if (!capable(CFS_CAP_SYS_ADMIN))
 -              return -EPERM;
 -
 -      if (copy_from_user(&fid, (struct lu_fid __user *)arg, sizeof(fid)))
 -              return -EFAULT;
 -
 -      fid_to_ostid(&fid, &oi);
 -      ost_idx = (fid_seq(&fid) >> 16) & 0xffff;
 -      return ll_lov_recreate(inode, &oi, ost_idx);
 -}
 -
  int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry,
                             __u64 flags, struct lov_user_md *lum,
                             int lum_size)
  {
        struct lov_stripe_md *lsm = NULL;
 -      struct lookup_intent oit = {.it_op = IT_OPEN, .it_flags = flags};
 +      struct lookup_intent oit = {
 +              .it_op = IT_OPEN,
 +              .it_flags = flags | MDS_OPEN_BY_FID,
 +      };
        int rc = 0;
  
        lsm = ccc_inode_lsm_get(inode);
  
        ll_inode_size_lock(inode);
        rc = ll_intent_file_open(dentry, lum, lum_size, &oit);
 -      if (rc)
 +      if (rc < 0)
                goto out_unlock;
        rc = oit.it_status;
        if (rc < 0)
 -              goto out_req_free;
 +              goto out_unlock;
  
        ll_release_openhandle(inode, &oit);
  
@@@ -1291,6 -1411,9 +1291,6 @@@ out_unlock
        ccc_inode_lsm_put(inode, lsm);
  out:
        return rc;
 -out_req_free:
 -      ptlrpc_req_finished((struct ptlrpc_request *)oit.it_request);
 -      goto out;
  }
  
  int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
  
        body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
  
 -      lmmsize = body->eadatasize;
 +      lmmsize = body->mbo_eadatasize;
  
 -      if (!(body->valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) ||
 +      if (!(body->mbo_valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) ||
            lmmsize == 0) {
                rc = -ENODATA;
                goto out;
                 */
                if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) {
                        lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lmm);
 -                      if (S_ISREG(body->mode))
 +                      if (S_ISREG(body->mbo_mode))
                                lustre_swab_lov_user_md_objects(
                                 ((struct lov_user_md_v1 *)lmm)->lmm_objects,
                                 stripe_count);
                } else if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) {
                        lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm);
 -                      if (S_ISREG(body->mode))
 +                      if (S_ISREG(body->mbo_mode))
                                lustre_swab_lov_user_md_objects(
                                 ((struct lov_user_md_v3 *)lmm)->lmm_objects,
                                 stripe_count);
@@@ -1407,48 -1530,55 +1407,48 @@@ static int ll_lov_setea(struct inode *i
        return rc;
  }
  
 +static int ll_file_getstripe(struct inode *inode,
 +                           struct lov_user_md __user *lum)
 +{
 +      struct lu_env *env;
 +      int refcheck;
 +      int rc;
 +
 +      env = cl_env_get(&refcheck);
 +      if (IS_ERR(env))
 +              return PTR_ERR(env);
 +
 +      rc = cl_object_getstripe(env, ll_i2info(inode)->lli_clob, lum);
 +      cl_env_put(env, &refcheck);
 +      return rc;
 +}
 +
  static int ll_lov_setstripe(struct inode *inode, struct file *file,
                            unsigned long arg)
  {
 -      struct lov_user_md_v3 lumv3;
 -      struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3;
 -      struct lov_user_md_v1 __user *lumv1p = (void __user *)arg;
 -      struct lov_user_md_v3 __user *lumv3p = (void __user *)arg;
 +      struct lov_user_md __user *lum = (struct lov_user_md __user *)arg;
 +      struct lov_user_md *klum;
        int lum_size, rc;
        __u64 flags = FMODE_WRITE;
  
 -      /* first try with v1 which is smaller than v3 */
 -      lum_size = sizeof(struct lov_user_md_v1);
 -      if (copy_from_user(lumv1, lumv1p, lum_size))
 -              return -EFAULT;
 -
 -      if (lumv1->lmm_magic == LOV_USER_MAGIC_V3) {
 -              lum_size = sizeof(struct lov_user_md_v3);
 -              if (copy_from_user(&lumv3, lumv3p, lum_size))
 -                      return -EFAULT;
 -      }
 +      rc = ll_copy_user_md(lum, &klum);
 +      if (rc < 0)
 +              return rc;
  
 -      rc = ll_lov_setstripe_ea_info(inode, file->f_path.dentry, flags, lumv1,
 +      lum_size = rc;
 +      rc = ll_lov_setstripe_ea_info(inode, file->f_path.dentry, flags, klum,
                                      lum_size);
        cl_lov_delay_create_clear(&file->f_flags);
        if (rc == 0) {
 -              struct lov_stripe_md *lsm;
                __u32 gen;
  
 -              put_user(0, &lumv1p->lmm_stripe_count);
 +              put_user(0, &lum->lmm_stripe_count);
  
                ll_layout_refresh(inode, &gen);
 -              lsm = ccc_inode_lsm_get(inode);
 -              rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode),
 -                                 0, lsm, (void __user *)arg);
 -              ccc_inode_lsm_put(inode, lsm);
 +              rc = ll_file_getstripe(inode, (struct lov_user_md __user *)arg);
        }
 -      return rc;
 -}
  
 -static int ll_lov_getstripe(struct inode *inode, unsigned long arg)
 -{
 -      struct lov_stripe_md *lsm;
 -      int rc = -ENODATA;
 -
 -      lsm = ccc_inode_lsm_get(inode);
 -      if (lsm)
 -              rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), 0,
 -                                 lsm, (void __user *)arg);
 -      ccc_inode_lsm_put(inode, lsm);
 +      kfree(klum);
        return rc;
  }
  
@@@ -2117,12 -2247,6 +2117,12 @@@ free_hss
        return rc;
  }
  
 +static inline long ll_lease_type_from_fmode(fmode_t fmode)
 +{
 +      return ((fmode & FMODE_READ) ? LL_LEASE_RDLCK : 0) |
 +             ((fmode & FMODE_WRITE) ? LL_LEASE_WRLCK : 0);
 +}
 +
  static long
  ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
                return rc;
        }
        case LL_IOC_LOV_GETSTRIPE:
 -              return ll_lov_getstripe(inode, arg);
 -      case LL_IOC_RECREATE_OBJ:
 -              return ll_lov_recreate_obj(inode, arg);
 -      case LL_IOC_RECREATE_FID:
 -              return ll_lov_recreate_fid(inode, arg);
 +              return ll_file_getstripe(inode,
 +                                       (struct lov_user_md __user *)arg);
        case FSFILT_IOC_FIEMAP:
                return ll_ioctl_fiemap(inode, arg);
        case FSFILT_IOC_GETFLAGS:
  
                return 0;
        }
 +      case LL_IOC_GETPARENT:
 +              return ll_getparent(file, (struct getparent __user *)arg);
        case OBD_IOC_FID2PATH:
                return ll_fid2path(inode, (void __user *)arg);
        case LL_IOC_DATA_VERSION: {
                struct ll_inode_info *lli = ll_i2info(inode);
                struct obd_client_handle *och = NULL;
                bool lease_broken;
 -              fmode_t mode = 0;
 +              fmode_t fmode;
  
                switch (arg) {
 -              case F_WRLCK:
 +              case LL_LEASE_WRLCK:
                        if (!(file->f_mode & FMODE_WRITE))
                                return -EPERM;
 -                      mode = FMODE_WRITE;
 +                      fmode = FMODE_WRITE;
                        break;
 -              case F_RDLCK:
 +              case LL_LEASE_RDLCK:
                        if (!(file->f_mode & FMODE_READ))
                                return -EPERM;
 -                      mode = FMODE_READ;
 +                      fmode = FMODE_READ;
                        break;
 -              case F_UNLCK:
 +              case LL_LEASE_UNLCK:
                        mutex_lock(&lli->lli_och_mutex);
                        if (fd->fd_lease_och) {
                                och = fd->fd_lease_och;
                        }
                        mutex_unlock(&lli->lli_och_mutex);
  
 -                      if (och) {
 -                              mode = och->och_flags &
 -                                     (FMODE_READ|FMODE_WRITE);
 -                              rc = ll_lease_close(och, inode, &lease_broken);
 -                              if (rc == 0 && lease_broken)
 -                                      mode = 0;
 -                      } else {
 -                              rc = -ENOLCK;
 -                      }
 +                      if (!och)
 +                              return -ENOLCK;
 +
 +                      fmode = och->och_flags;
 +                      rc = ll_lease_close(och, inode, &lease_broken);
 +                      if (rc < 0)
 +                              return rc;
 +
 +                      if (lease_broken)
 +                              fmode = 0;
  
 -                      /* return the type of lease or error */
 -                      return rc < 0 ? rc : (int)mode;
 +                      return ll_lease_type_from_fmode(fmode);
                default:
                        return -EINVAL;
                }
  
 -              CDEBUG(D_INODE, "Set lease with mode %d\n", mode);
 +              CDEBUG(D_INODE, "Set lease with mode %u\n", fmode);
  
                /* apply for lease */
 -              och = ll_lease_open(inode, file, mode, 0);
 +              och = ll_lease_open(inode, file, fmode, 0);
                if (IS_ERR(och))
                        return PTR_ERR(och);
  
        case LL_IOC_GET_LEASE: {
                struct ll_inode_info *lli = ll_i2info(inode);
                struct ldlm_lock *lock = NULL;
 +              fmode_t fmode = 0;
  
 -              rc = 0;
                mutex_lock(&lli->lli_och_mutex);
                if (fd->fd_lease_och) {
                        struct obd_client_handle *och = fd->fd_lease_och;
                        if (lock) {
                                lock_res_and_lock(lock);
                                if (!ldlm_is_cancel(lock))
 -                                      rc = och->och_flags &
 -                                              (FMODE_READ | FMODE_WRITE);
 +                                      fmode = och->och_flags;
                                unlock_res_and_lock(lock);
                                LDLM_LOCK_PUT(lock);
                        }
                }
                mutex_unlock(&lli->lli_och_mutex);
 -              return rc;
 +              return ll_lease_type_from_fmode(fmode);
        }
        case LL_IOC_HSM_IMPORT: {
                struct hsm_user_import *hui;
@@@ -2448,8 -2574,9 +2448,8 @@@ static loff_t ll_file_seek(struct file 
                eof = i_size_read(inode);
        }
  
 -      retval = generic_file_llseek_size(file, offset, origin,
 -                                        ll_file_maxbytes(inode), eof);
 -      return retval;
 +      return generic_file_llseek_size(file, offset, origin,
 +                                      ll_file_maxbytes(inode), eof);
  }
  
  static int ll_flush(struct file *file, fl_owner_t id)
         */
        rc = lli->lli_async_rc;
        lli->lli_async_rc = 0;
 -      err = lov_read_and_clear_async_rc(lli->lli_clob);
 -      if (rc == 0)
 -              rc = err;
 +      if (lli->lli_clob) {
 +              err = lov_read_and_clear_async_rc(lli->lli_clob);
 +              if (!rc)
 +                      rc = err;
 +      }
  
        /* The application has been told about write failure already.
         * Do not report failure again.
@@@ -2589,7 -2714,6 +2589,7 @@@ ll_file_flock(struct file *file, int cm
        struct md_op_data *op_data;
        struct lustre_handle lockh = {0};
        ldlm_policy_data_t flock = { {0} };
 +      int fl_type = file_lock->fl_type;
        __u64 flags = 0;
        int rc;
        int rc2 = 0;
        if (file_lock->fl_lmops && file_lock->fl_lmops->lm_compare_owner)
                flock.l_flock.owner = (unsigned long)file_lock->fl_pid;
  
 -      switch (file_lock->fl_type) {
 +      switch (fl_type) {
        case F_RDLCK:
                einfo.ei_mode = LCK_PR;
                break;
                einfo.ei_mode = LCK_PW;
                break;
        default:
 -              CDEBUG(D_INFO, "Unknown fcntl lock type: %d\n",
 -                     file_lock->fl_type);
 +              CDEBUG(D_INFO, "Unknown fcntl lock type: %d\n", fl_type);
                return -ENOTSUPP;
        }
  
        case F_GETLK64:
  #endif
                flags = LDLM_FL_TEST_LOCK;
 -              /* Save the old mode so that if the mode in the lock changes we
 -               * can decrement the appropriate reader or writer refcount.
 -               */
 -              file_lock->fl_type = einfo.ei_mode;
                break;
        default:
                CERROR("unknown fcntl lock command: %d\n", cmd);
                return -EINVAL;
        }
  
 +      /*
 +       * Save the old mode so that if the mode in the lock changes we
 +       * can decrement the appropriate reader or writer refcount.
 +       */
 +      file_lock->fl_type = einfo.ei_mode;
 +
        op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
                                     LUSTRE_OPC_ANY, NULL);
        if (IS_ERR(op_data))
               PFID(ll_inode2fid(inode)), flock.l_flock.pid, flags,
               einfo.ei_mode, flock.l_flock.start, flock.l_flock.end);
  
 -      rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL,
 -                      op_data, &lockh, &flock, 0, NULL /* req */, flags);
 +      rc = md_enqueue(sbi->ll_md_exp, &einfo, &flock, NULL, op_data, &lockh,
 +                      flags);
 +
 +      /* Restore the file lock type if not TEST lock. */
 +      if (!(flags & LDLM_FL_TEST_LOCK))
 +              file_lock->fl_type = fl_type;
  
        if ((rc == 0 || file_lock->fl_type == F_UNLCK) &&
            !(flags & LDLM_FL_TEST_LOCK))
  
        if (rc2 && file_lock->fl_type != F_UNLCK) {
                einfo.ei_mode = LCK_NL;
 -              md_enqueue(sbi->ll_md_exp, &einfo, NULL,
 -                         op_data, &lockh, &flock, 0, NULL /* req */, flags);
 +              md_enqueue(sbi->ll_md_exp, &einfo, &flock, NULL, op_data,
 +                         &lockh, flags);
                rc = rc2;
        }
  
        return rc;
  }
  
 +int ll_get_fid_by_name(struct inode *parent, const char *name,
 +                     int namelen, struct lu_fid *fid)
 +{
 +      struct md_op_data *op_data = NULL;
 +      struct ptlrpc_request *req;
 +      struct mdt_body *body;
 +      int rc;
 +
 +      op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen, 0,
 +                                   LUSTRE_OPC_ANY, NULL);
 +      if (IS_ERR(op_data))
 +              return PTR_ERR(op_data);
 +
 +      op_data->op_valid = OBD_MD_FLID;
 +      rc = md_getattr_name(ll_i2sbi(parent)->ll_md_exp, op_data, &req);
 +      ll_finish_md_op_data(op_data);
 +      if (rc < 0)
 +              return rc;
 +
 +      body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
 +      if (!body) {
 +              rc = -EFAULT;
 +              goto out_req;
 +      }
 +      if (fid)
 +              *fid = body->mbo_fid1;
 +out_req:
 +      ptlrpc_req_finished(req);
 +      return rc;
 +}
 +
 +int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
 +             const char *name, int namelen)
 +{
 +      struct ptlrpc_request *request = NULL;
 +      struct inode *child_inode = NULL;
 +      struct dentry *dchild = NULL;
 +      struct md_op_data *op_data;
 +      struct qstr qstr;
 +      int rc;
 +
 +      CDEBUG(D_VFSTRACE, "migrate %s under "DFID" to MDT%d\n",
 +             name, PFID(ll_inode2fid(parent)), mdtidx);
 +
 +      op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen,
 +                                   0, LUSTRE_OPC_ANY, NULL);
 +      if (IS_ERR(op_data))
 +              return PTR_ERR(op_data);
 +
 +      /* Get child FID first */
 +      qstr.hash = full_name_hash(parent, name, namelen);
 +      qstr.name = name;
 +      qstr.len = namelen;
 +      dchild = d_lookup(file_dentry(file), &qstr);
 +      if (dchild) {
 +              op_data->op_fid3 = *ll_inode2fid(dchild->d_inode);
 +              if (dchild->d_inode) {
 +                      child_inode = igrab(dchild->d_inode);
 +                      if (child_inode) {
 +                              inode_lock(child_inode);
 +                              op_data->op_fid3 = *ll_inode2fid(child_inode);
 +                              ll_invalidate_aliases(child_inode);
 +                      }
 +              }
 +              dput(dchild);
 +      } else {
 +              rc = ll_get_fid_by_name(parent, name, namelen,
 +                                      &op_data->op_fid3);
 +              if (rc)
 +                      goto out_free;
 +      }
 +
 +      if (!fid_is_sane(&op_data->op_fid3)) {
 +              CERROR("%s: migrate %s, but fid "DFID" is insane\n",
 +                     ll_get_fsname(parent->i_sb, NULL, 0), name,
 +                     PFID(&op_data->op_fid3));
 +              rc = -EINVAL;
 +              goto out_free;
 +      }
 +
 +      rc = ll_get_mdt_idx_by_fid(ll_i2sbi(parent), &op_data->op_fid3);
 +      if (rc < 0)
 +              goto out_free;
 +
 +      if (rc == mdtidx) {
 +              CDEBUG(D_INFO, "%s:"DFID" is already on MDT%d.\n", name,
 +                     PFID(&op_data->op_fid3), mdtidx);
 +              rc = 0;
 +              goto out_free;
 +      }
 +
 +      op_data->op_mds = mdtidx;
 +      op_data->op_cli_flags = CLI_MIGRATE;
 +      rc = md_rename(ll_i2sbi(parent)->ll_md_exp, op_data, name,
 +                     namelen, name, namelen, &request);
 +      if (!rc)
 +              ll_update_times(request, parent);
 +
 +      ptlrpc_req_finished(request);
 +
 +out_free:
 +      if (child_inode) {
 +              clear_nlink(child_inode);
 +              inode_unlock(child_inode);
 +              iput(child_inode);
 +      }
 +
 +      ll_finish_md_op_data(op_data);
 +      return rc;
 +}
 +
  static int
  ll_file_noflock(struct file *file, int cmd, struct file_lock *file_lock)
  {
@@@ -2839,7 -2847,7 +2839,7 @@@ int ll_have_md_lock(struct inode *inode
        struct lustre_handle lockh;
        ldlm_policy_data_t policy;
        enum ldlm_mode mode = (l_req_mode == LCK_MINMODE) ?
 -                              (LCK_CR|LCK_CW|LCK_PR|LCK_PW) : l_req_mode;
 +                            (LCK_CR | LCK_CW | LCK_PR | LCK_PW) : l_req_mode;
        struct lu_fid *fid;
        __u64 flags;
        int i;
@@@ -2880,12 -2888,15 +2880,12 @@@ enum ldlm_mode ll_take_md_lock(struct i
  {
        ldlm_policy_data_t policy = { .l_inodebits = {bits} };
        struct lu_fid *fid;
 -      enum ldlm_mode rc;
  
        fid = &ll_i2info(inode)->lli_fid;
        CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
  
 -      rc = md_lock_match(ll_i2mdexp(inode), flags | LDLM_FL_BLOCK_GRANTED,
 -                         fid, LDLM_IBITS, &policy, mode, lockh);
 -
 -      return rc;
 +      return md_lock_match(ll_i2mdexp(inode), flags | LDLM_FL_BLOCK_GRANTED,
 +                           fid, LDLM_IBITS, &policy, mode, lockh);
  }
  
  static int ll_inode_revalidate_fini(struct inode *inode, int rc)
@@@ -2938,9 -2949,15 +2938,9 @@@ static int __ll_inode_revalidate(struc
                if (IS_ERR(op_data))
                        return PTR_ERR(op_data);
  
 -              oit.it_create_mode |= M_CHECK_STALE;
 -              rc = md_intent_lock(exp, op_data, NULL, 0,
 -                                  /* we are not interested in name
 -                                   * based lookup
 -                                   */
 -                                  &oit, 0, &req,
 -                                  ll_md_blocking_ast, 0);
 +              rc = md_intent_lock(exp, op_data, &oit, &req,
 +                                  &ll_md_blocking_ast, 0);
                ll_finish_md_op_data(op_data);
 -              oit.it_create_mode &= ~M_CHECK_STALE;
                if (rc < 0) {
                        rc = ll_inode_revalidate_fini(inode, rc);
                        goto out;
                op_data->op_valid = valid;
                rc = md_getattr(sbi->ll_md_exp, op_data, &req);
                ll_finish_md_op_data(op_data);
 -              if (rc) {
 -                      rc = ll_inode_revalidate_fini(inode, rc);
 -                      return rc;
 -              }
 +              if (rc)
 +                      return ll_inode_revalidate_fini(inode, rc);
  
                rc = ll_prep_inode(&inode, req, NULL, NULL);
        }
        return rc;
  }
  
 +static int ll_merge_md_attr(struct inode *inode)
 +{
 +      struct cl_attr attr = { 0 };
 +      int rc;
 +
 +      LASSERT(ll_i2info(inode)->lli_lsm_md);
 +      rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md,
 +                         &attr, ll_md_blocking_ast);
 +      if (rc)
 +              return rc;
 +
 +      set_nlink(inode, attr.cat_nlink);
 +      inode->i_blocks = attr.cat_blocks;
 +      i_size_write(inode, attr.cat_size);
 +
 +      ll_i2info(inode)->lli_atime = attr.cat_atime;
 +      ll_i2info(inode)->lli_mtime = attr.cat_mtime;
 +      ll_i2info(inode)->lli_ctime = attr.cat_ctime;
 +
 +      return 0;
 +}
 +
  static int ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
  {
        struct inode *inode = d_inode(dentry);
  
        /* if object isn't regular file, don't validate size */
        if (!S_ISREG(inode->i_mode)) {
 +              if (S_ISDIR(inode->i_mode) &&
 +                  ll_i2info(inode)->lli_lsm_md) {
 +                      rc = ll_merge_md_attr(inode);
 +                      if (rc)
 +                              return rc;
 +              }
 +
                LTIME_S(inode->i_atime) = ll_i2info(inode)->lli_atime;
                LTIME_S(inode->i_mtime) = ll_i2info(inode)->lli_mtime;
                LTIME_S(inode->i_ctime) = ll_i2info(inode)->lli_ctime;
@@@ -3067,14 -3057,13 +3067,14 @@@ int ll_getattr(struct vfsmount *mnt, st
        if (res)
                return res;
  
 +      OBD_FAIL_TIMEOUT(OBD_FAIL_GETATTR_DELAY, 30);
 +
        stat->dev = inode->i_sb->s_dev;
        if (ll_need_32bit_api(sbi))
                stat->ino = cl_fid_build_ino(&lli->lli_fid, 1);
        else
                stat->ino = inode->i_ino;
        stat->mode = inode->i_mode;
 -      stat->nlink = inode->i_nlink;
        stat->uid = inode->i_uid;
        stat->gid = inode->i_gid;
        stat->rdev = inode->i_rdev;
        stat->ctime = inode->i_ctime;
        stat->blksize = 1 << inode->i_blkbits;
  
 +      stat->nlink = inode->i_nlink;
        stat->size = i_size_read(inode);
        stat->blocks = inode->i_blocks;
  
@@@ -3151,12 -3139,6 +3151,12 @@@ struct posix_acl *ll_get_acl(struct ino
  
  int ll_inode_permission(struct inode *inode, int mask)
  {
 +      struct ll_sb_info *sbi;
 +      struct root_squash_info *squash;
 +      const struct cred *old_cred = NULL;
 +      struct cred *cred = NULL;
 +      bool squash_id = false;
 +      cfs_cap_t cap;
        int rc = 0;
  
        if (mask & MAY_NOT_BLOCK)
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), inode mode %x mask %o\n",
               PFID(ll_inode2fid(inode)), inode, inode->i_mode, mask);
  
 +      /* squash fsuid/fsgid if needed */
 +      sbi = ll_i2sbi(inode);
 +      squash = &sbi->ll_squash;
 +      if (unlikely(squash->rsi_uid &&
 +                   uid_eq(current_fsuid(), GLOBAL_ROOT_UID) &&
 +                   !(sbi->ll_flags & LL_SBI_NOROOTSQUASH))) {
 +              squash_id = true;
 +      }
 +
 +      if (squash_id) {
 +              CDEBUG(D_OTHER, "squash creds (%d:%d)=>(%d:%d)\n",
 +                     __kuid_val(current_fsuid()), __kgid_val(current_fsgid()),
 +                     squash->rsi_uid, squash->rsi_gid);
 +
 +              /*
 +               * update current process's credentials
 +               * and FS capability
 +               */
 +              cred = prepare_creds();
 +              if (!cred)
 +                      return -ENOMEM;
 +
 +              cred->fsuid = make_kuid(&init_user_ns, squash->rsi_uid);
 +              cred->fsgid = make_kgid(&init_user_ns, squash->rsi_gid);
 +              for (cap = 0; cap < sizeof(cfs_cap_t) * 8; cap++) {
 +                      if ((1 << cap) & CFS_CAP_FS_MASK)
 +                              cap_lower(cred->cap_effective, cap);
 +              }
 +              old_cred = override_creds(cred);
 +      }
 +
        ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_INODE_PERM, 1);
        rc = generic_permission(inode, mask);
  
 +      /* restore current process's credentials and FS capability */
 +      if (squash_id) {
 +              revert_creds(old_cred);
 +              put_cred(cred);
 +      }
 +
        return rc;
  }
  
@@@ -3228,7 -3173,7 +3228,7 @@@ struct file_operations ll_file_operatio
        .release        = ll_file_release,
        .mmap      = ll_file_mmap,
        .llseek  = ll_file_seek,
 -      .splice_read    = ll_file_splice_read,
 +      .splice_read    = generic_file_splice_read,
        .fsync    = ll_fsync,
        .flush    = ll_flush
  };
@@@ -3241,7 -3186,7 +3241,7 @@@ struct file_operations ll_file_operatio
        .release        = ll_file_release,
        .mmap      = ll_file_mmap,
        .llseek  = ll_file_seek,
 -      .splice_read    = ll_file_splice_read,
 +      .splice_read    = generic_file_splice_read,
        .fsync    = ll_fsync,
        .flush    = ll_flush,
        .flock    = ll_file_flock,
@@@ -3257,7 -3202,7 +3257,7 @@@ struct file_operations ll_file_operatio
        .release        = ll_file_release,
        .mmap      = ll_file_mmap,
        .llseek  = ll_file_seek,
 -      .splice_read    = ll_file_splice_read,
 +      .splice_read    = generic_file_splice_read,
        .fsync    = ll_fsync,
        .flush    = ll_flush,
        .flock    = ll_file_noflock,
@@@ -3268,10 -3213,7 +3268,7 @@@ const struct inode_operations ll_file_i
        .setattr        = ll_setattr,
        .getattr        = ll_getattr,
        .permission     = ll_inode_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ll_listxattr,
-       .removexattr    = generic_removexattr,
        .fiemap         = ll_fiemap,
        .get_acl        = ll_get_acl,
  };
@@@ -3306,6 -3248,7 +3303,6 @@@ void *ll_iocontrol_register(llioc_callb
        if (!in_data)
                return NULL;
  
 -      memset(in_data, 0, sizeof(*in_data));
        in_data->iocd_size = size;
        in_data->iocd_cb = cb;
        in_data->iocd_count = count;
@@@ -3443,7 -3386,7 +3440,7 @@@ static int ll_layout_fetch(struct inod
                goto out;
        }
  
 -      lmmsize = body->eadatasize;
 +      lmmsize = body->mbo_eadatasize;
        if (lmmsize == 0) /* empty layout */ {
                rc = 0;
                goto out;
@@@ -3501,7 -3444,7 +3498,7 @@@ static int ll_layout_lock_set(struct lu
                   PFID(&lli->lli_fid), inode, reconf);
  
        /* in case this is a caching lock and reinstate with new inode */
 -      md_set_lock_data(sbi->ll_md_exp, &lockh->cookie, inode, NULL);
 +      md_set_lock_data(sbi->ll_md_exp, lockh, inode, NULL);
  
        lock_res_and_lock(lock);
        lvb_ready = ldlm_is_lvb_ready(lock);
@@@ -3611,8 -3554,8 +3608,8 @@@ int ll_layout_refresh(struct inode *ino
        struct ldlm_enqueue_info einfo = {
                .ei_type = LDLM_IBITS,
                .ei_mode = LCK_CR,
 -              .ei_cb_bl = ll_md_blocking_ast,
 -              .ei_cb_cp = ldlm_completion_ast,
 +              .ei_cb_bl = &ll_md_blocking_ast,
 +              .ei_cb_cp = &ldlm_completion_ast,
        };
        int rc;
  
@@@ -3658,7 -3601,8 +3655,7 @@@ again
                          ll_get_fsname(inode->i_sb, NULL, 0),
                          PFID(&lli->lli_fid), inode);
  
 -      rc = md_enqueue(sbi->ll_md_exp, &einfo, &it, op_data, &lockh,
 -                      NULL, 0, NULL, 0);
 +      rc = md_enqueue(sbi->ll_md_exp, &einfo, NULL, &it, op_data, &lockh, 0);
        ptlrpc_req_finished(it.it_request);
        it.it_request = NULL;
  
  
  #include "../include/obd_support.h"
  #include "../include/lustre_fid.h"
 -#include "../include/lustre_lite.h"
  #include "../include/lustre_dlm.h"
  #include "../include/lustre_ver.h"
  #include "llite_internal.h"
  
 -static int ll_create_it(struct inode *, struct dentry *,
 -                      int, struct lookup_intent *);
 +static int ll_create_it(struct inode *dir, struct dentry *dentry,
 +                      struct lookup_intent *it);
  
  /* called from iget5_locked->find_inode() under inode_hash_lock spinlock */
  static int ll_test_inode(struct inode *inode, void *opaque)
        struct ll_inode_info *lli = ll_i2info(inode);
        struct lustre_md     *md = opaque;
  
 -      if (unlikely(!(md->body->valid & OBD_MD_FLID))) {
 +      if (unlikely(!(md->body->mbo_valid & OBD_MD_FLID))) {
                CERROR("MDS body missing FID\n");
                return 0;
        }
  
 -      if (!lu_fid_eq(&lli->lli_fid, &md->body->fid1))
 +      if (!lu_fid_eq(&lli->lli_fid, &md->body->mbo_fid1))
                return 0;
  
        return 1;
@@@ -71,20 -72,20 +71,20 @@@ static int ll_set_inode(struct inode *i
        struct ll_inode_info *lli = ll_i2info(inode);
        struct mdt_body *body = ((struct lustre_md *)opaque)->body;
  
 -      if (unlikely(!(body->valid & OBD_MD_FLID))) {
 +      if (unlikely(!(body->mbo_valid & OBD_MD_FLID))) {
                CERROR("MDS body missing FID\n");
                return -EINVAL;
        }
  
 -      lli->lli_fid = body->fid1;
 -      if (unlikely(!(body->valid & OBD_MD_FLTYPE))) {
 +      lli->lli_fid = body->mbo_fid1;
 +      if (unlikely(!(body->mbo_valid & OBD_MD_FLTYPE))) {
                CERROR("Can not initialize inode " DFID
                       " without object type: valid = %#llx\n",
 -                     PFID(&lli->lli_fid), body->valid);
 +                     PFID(&lli->lli_fid), body->mbo_valid);
                return -EINVAL;
        }
  
 -      inode->i_mode = (inode->i_mode & ~S_IFMT) | (body->mode & S_IFMT);
 +      inode->i_mode = (inode->i_mode & ~S_IFMT) | (body->mbo_mode & S_IFMT);
        if (unlikely(inode->i_mode == 0)) {
                CERROR("Invalid inode "DFID" type\n", PFID(&lli->lli_fid));
                return -EINVAL;
        return 0;
  }
  
 -/*
 - * Get an inode by inode number (already instantiated by the intent lookup).
 - * Returns inode or NULL
 +/**
 + * Get an inode by inode number(@hash), which is already instantiated by
 + * the intent lookup).
   */
  struct inode *ll_iget(struct super_block *sb, ino_t hash,
                      struct lustre_md *md)
  {
        struct inode     *inode;
 +      int rc = 0;
  
        LASSERT(hash != 0);
        inode = iget5_locked(sb, hash, ll_test_inode, ll_set_inode, md);
 -
 -      if (inode) {
 -              if (inode->i_state & I_NEW) {
 -                      int rc = 0;
 -
 -                      ll_read_inode2(inode, md);
 -                      if (S_ISREG(inode->i_mode) &&
 -                          !ll_i2info(inode)->lli_clob) {
 -                              CDEBUG(D_INODE,
 -                                     "%s: apply lsm %p to inode " DFID ".\n",
 -                                     ll_get_fsname(sb, NULL, 0), md->lsm,
 -                                     PFID(ll_inode2fid(inode)));
 -                              rc = cl_file_inode_init(inode, md);
 -                      }
 -                      if (rc != 0) {
 -                              iget_failed(inode);
 -                              inode = NULL;
 -                      } else {
 -                              unlock_new_inode(inode);
 -                      }
 -              } else if (!(inode->i_state & (I_FREEING | I_CLEAR))) {
 -                      ll_update_inode(inode, md);
 -                      CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p)\n",
 -                             PFID(&md->body->fid1), inode);
 +      if (!inode)
 +              return ERR_PTR(-ENOMEM);
 +
 +      if (inode->i_state & I_NEW) {
 +              rc = ll_read_inode2(inode, md);
 +              if (!rc && S_ISREG(inode->i_mode) &&
 +                  !ll_i2info(inode)->lli_clob) {
 +                      CDEBUG(D_INODE, "%s: apply lsm %p to inode "DFID"\n",
 +                             ll_get_fsname(sb, NULL, 0), md->lsm,
 +                             PFID(ll_inode2fid(inode)));
 +                      rc = cl_file_inode_init(inode, md);
 +              }
 +              if (rc) {
 +                      make_bad_inode(inode);
 +                      unlock_new_inode(inode);
 +                      iput(inode);
 +                      inode = ERR_PTR(rc);
 +              } else {
 +                      unlock_new_inode(inode);
 +              }
 +      } else if (!(inode->i_state & (I_FREEING | I_CLEAR))) {
 +              rc = ll_update_inode(inode, md);
 +              CDEBUG(D_VFSTRACE, "got inode: "DFID"(%p): rc = %d\n",
 +                     PFID(&md->body->mbo_fid1), inode, rc);
 +              if (rc) {
 +                      iput(inode);
 +                      inode = ERR_PTR(rc);
                }
        }
        return inode;
@@@ -161,11 -158,6 +161,11 @@@ static void ll_invalidate_negative_chil
        spin_unlock(&dir->i_lock);
  }
  
 +int ll_test_inode_by_fid(struct inode *inode, void *opaque)
 +{
 +      return lu_fid_eq(&ll_i2info(inode)->lli_fid, opaque);
 +}
 +
  int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
                       void *data, int flag)
  {
                }
  
                if (bits & MDS_INODELOCK_XATTR) {
 +                      if (S_ISDIR(inode->i_mode))
 +                              ll_i2info(inode)->lli_def_stripe_offset = -1;
                        ll_xattr_cache_destroy(inode);
                        bits &= ~MDS_INODELOCK_XATTR;
                }
                }
  
                if ((bits & MDS_INODELOCK_UPDATE) && S_ISDIR(inode->i_mode)) {
 -                      CDEBUG(D_INODE, "invalidating inode "DFID"\n",
 -                             PFID(ll_inode2fid(inode)));
 +                      struct ll_inode_info *lli = ll_i2info(inode);
 +
 +                      CDEBUG(D_INODE, "invalidating inode "DFID" lli = %p, pfid  = "DFID"\n",
 +                             PFID(ll_inode2fid(inode)), lli,
 +                             PFID(&lli->lli_pfid));
 +
                        truncate_inode_pages(inode->i_mapping, 0);
 -                      ll_invalidate_negative_children(inode);
 +
 +                      if (unlikely(!fid_is_zero(&lli->lli_pfid))) {
 +                              struct inode *master_inode = NULL;
 +                              unsigned long hash;
 +
 +                              /*
 +                               * This is slave inode, since all of the child
 +                               * dentry is connected on the master inode, so
 +                               * we have to invalidate the negative children
 +                               * on master inode
 +                               */
 +                              CDEBUG(D_INODE, "Invalidate s"DFID" m"DFID"\n",
 +                                     PFID(ll_inode2fid(inode)),
 +                                     PFID(&lli->lli_pfid));
 +
 +                              hash = cl_fid_build_ino(&lli->lli_pfid,
 +                                                      ll_need_32bit_api(ll_i2sbi(inode)));
 +
 +                              master_inode = ilookup5(inode->i_sb, hash,
 +                                                      ll_test_inode_by_fid,
 +                                                      (void *)&lli->lli_pfid);
 +                              if (master_inode && !IS_ERR(master_inode)) {
 +                                      ll_invalidate_negative_children(master_inode);
 +                                      iput(master_inode);
 +                              }
 +                      } else {
 +                              ll_invalidate_negative_children(inode);
 +                      }
                }
  
                if ((bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)) &&
@@@ -363,8 -322,7 +363,8 @@@ static struct dentry *ll_find_alias(str
                LASSERT(alias != dentry);
  
                spin_lock(&alias->d_lock);
 -              if (alias->d_flags & DCACHE_DISCONNECTED)
 +              if ((alias->d_flags & DCACHE_DISCONNECTED) &&
 +                  S_ISDIR(inode->i_mode))
                        /* LASSERT(last_discon == NULL); LU-405, bz 20055 */
                        discon_alias = alias;
                else if (alias->d_parent == dentry->d_parent         &&
@@@ -475,20 -433,9 +475,20 @@@ static int ll_lookup_it_finish(struct p
                struct lookup_intent parent_it = {
                                        .it_op = IT_GETATTR,
                                        .it_lock_handle = 0 };
 +              struct lu_fid fid = ll_i2info(parent)->lli_fid;
 +
 +              /* If it is striped directory, get the real stripe parent */
 +              if (unlikely(ll_i2info(parent)->lli_lsm_md)) {
 +                      rc = md_get_fid_from_lsm(ll_i2mdexp(parent),
 +                                               ll_i2info(parent)->lli_lsm_md,
 +                                               (*de)->d_name.name,
 +                                               (*de)->d_name.len, &fid);
 +                      if (rc)
 +                              return rc;
 +              }
  
 -              if (md_revalidate_lock(ll_i2mdexp(parent), &parent_it,
 -                                     &ll_i2info(parent)->lli_fid, NULL)) {
 +              if (md_revalidate_lock(ll_i2mdexp(parent), &parent_it, &fid,
 +                                     NULL)) {
                        d_lustre_revalidate(*de);
                        ll_intent_release(&parent_it);
                }
@@@ -502,13 -449,13 +502,13 @@@ out
  }
  
  static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
 -                                 struct lookup_intent *it, int lookup_flags)
 +                                 struct lookup_intent *it)
  {
        struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
        struct dentry *save = dentry, *retval;
        struct ptlrpc_request *req = NULL;
 +      struct md_op_data *op_data = NULL;
        struct inode *inode;
 -      struct md_op_data *op_data;
        __u32 opc;
        int rc;
  
        if (!it || it->it_op == IT_GETXATTR)
                it = &lookup_it;
  
 -      if (it->it_op == IT_GETATTR) {
 -              rc = ll_statahead_enter(parent, &dentry, 0);
 +      if (it->it_op == IT_GETATTR && dentry_may_statahead(parent, dentry)) {
 +              rc = ll_statahead(parent, &dentry, 0);
                if (rc == 1) {
                        if (dentry == save)
                                retval = NULL;
                opc = LUSTRE_OPC_ANY;
  
        op_data = ll_prep_md_op_data(NULL, parent, NULL, dentry->d_name.name,
 -                                   dentry->d_name.len, lookup_flags, opc,
 -                                   NULL);
 +                                   dentry->d_name.len, 0, opc, NULL);
        if (IS_ERR(op_data))
                return (void *)op_data;
  
        if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent)))
                it->it_create_mode &= ~current_umask();
  
 -      rc = md_intent_lock(ll_i2mdexp(parent), op_data, NULL, 0, it,
 -                          lookup_flags, &req, ll_md_blocking_ast, 0);
 -      ll_finish_md_op_data(op_data);
 +      rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req,
 +                          &ll_md_blocking_ast, 0);
 +      /*
 +       * If the MDS allows the client to chgrp (CFS_SETGRP_PERM), but the
 +       * client does not know which suppgid should be sent to the MDS, or
 +       * some other(s) changed the target file's GID after this RPC sent
 +       * to the MDS with the suppgid as the original GID, then we should
 +       * try again with right suppgid.
 +       */
 +      if (rc == -EACCES && it->it_op & IT_OPEN &&
 +          it_disposition(it, DISP_OPEN_DENY)) {
 +              struct mdt_body *body;
 +
 +              LASSERT(req);
 +
 +              body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
 +              if (op_data->op_suppgids[0] == body->mbo_gid ||
 +                  op_data->op_suppgids[1] == body->mbo_gid ||
 +                  !in_group_p(make_kgid(&init_user_ns, body->mbo_gid))) {
 +                      retval = ERR_PTR(-EACCES);
 +                      goto out;
 +              }
 +
 +              fid_zero(&op_data->op_fid2);
 +              op_data->op_suppgids[1] = body->mbo_gid;
 +              ptlrpc_req_finished(req);
 +              req = NULL;
 +              ll_intent_release(it);
 +              rc = md_intent_lock(ll_i2mdexp(parent), op_data, it, &req,
 +                                  ll_md_blocking_ast, 0);
 +      }
 +
        if (rc < 0) {
                retval = ERR_PTR(rc);
                goto out;
                retval = NULL;
        else
                retval = dentry;
 - out:
 -      if (req)
 -              ptlrpc_req_finished(req);
 -      if (it->it_op == IT_GETATTR && (!retval || retval == dentry))
 -              ll_statahead_mark(parent, dentry);
 +out:
 +      if (op_data && !IS_ERR(op_data))
 +              ll_finish_md_op_data(op_data);
 +
 +      ptlrpc_req_finished(req);
        return retval;
  }
  
@@@ -622,19 -541,15 +622,19 @@@ static struct dentry *ll_lookup_nd(stru
        CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),flags=%u\n",
               dentry, PFID(ll_inode2fid(parent)), parent, flags);
  
 -      /* Optimize away (CREATE && !OPEN). Let .create handle the race. */
 -      if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN))
 +      /* Optimize away (CREATE && !OPEN). Let .create handle the race.
 +       * but only if we have write permissions there, otherwise we need
 +       * to proceed with lookup. LU-4185
 +       */
 +      if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN) &&
 +          (inode_permission(parent, MAY_WRITE | MAY_EXEC) == 0))
                return NULL;
  
 -      if (flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE))
 +      if (flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE))
                itp = NULL;
        else
                itp = &it;
 -      de = ll_lookup_it(parent, dentry, itp, 0);
 +      de = ll_lookup_it(parent, dentry, itp);
  
        if (itp)
                ll_intent_release(itp);
@@@ -652,6 -567,7 +652,6 @@@ static int ll_atomic_open(struct inode 
  {
        struct lookup_intent *it;
        struct dentry *de;
 -      long long lookup_flags = LOOKUP_OPEN;
        int rc = 0;
  
        CDEBUG(D_VFSTRACE, "VFS Op:name=%pd, dir="DFID"(%p),file %p,open_flags %x,mode %x opened %d\n",
                return -ENOMEM;
  
        it->it_op = IT_OPEN;
 -      if (open_flags & O_CREAT) {
 +      if (open_flags & O_CREAT)
                it->it_op |= IT_CREAT;
 -              lookup_flags |= LOOKUP_CREATE;
 -      }
        it->it_create_mode = (mode & S_IALLUGO) | S_IFREG;
        it->it_flags = (open_flags & ~O_ACCMODE) | OPEN_FMODE(open_flags);
 +      it->it_flags &= ~MDS_OPEN_FL_INTERNAL;
  
        /* Dentry added to dcache tree in ll_lookup_it */
 -      de = ll_lookup_it(dir, dentry, it, lookup_flags);
 +      de = ll_lookup_it(dir, dentry, it);
        if (IS_ERR(de))
                rc = PTR_ERR(de);
        else if (de)
        if (!rc) {
                if (it_disposition(it, DISP_OPEN_CREATE)) {
                        /* Dentry instantiated in ll_create_it. */
 -                      rc = ll_create_it(dir, dentry, mode, it);
 +                      rc = ll_create_it(dir, dentry, it);
                        if (rc) {
                                /* We dget in ll_splice_alias. */
                                if (de)
@@@ -783,7 -700,7 +783,7 @@@ static struct inode *ll_create_node(str
   * If the create succeeds, we fill in the inode information
   * with d_instantiate().
   */
 -static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode,
 +static int ll_create_it(struct inode *dir, struct dentry *dentry,
                        struct lookup_intent *it)
  {
        struct inode *inode;
        return 0;
  }
  
 -static void ll_update_times(struct ptlrpc_request *request,
 -                          struct inode *inode)
 +void ll_update_times(struct ptlrpc_request *request, struct inode *inode)
  {
        struct mdt_body *body = req_capsule_server_get(&request->rq_pill,
                                                       &RMF_MDT_BODY);
  
        LASSERT(body);
 -      if (body->valid & OBD_MD_FLMTIME &&
 -          body->mtime > LTIME_S(inode->i_mtime)) {
 +      if (body->mbo_valid & OBD_MD_FLMTIME &&
 +          body->mbo_mtime > LTIME_S(inode->i_mtime)) {
                CDEBUG(D_INODE, "setting fid "DFID" mtime from %lu to %llu\n",
                       PFID(ll_inode2fid(inode)), LTIME_S(inode->i_mtime),
 -                     body->mtime);
 -              LTIME_S(inode->i_mtime) = body->mtime;
 +                     body->mbo_mtime);
 +              LTIME_S(inode->i_mtime) = body->mbo_mtime;
        }
 -      if (body->valid & OBD_MD_FLCTIME &&
 -          body->ctime > LTIME_S(inode->i_ctime))
 -              LTIME_S(inode->i_ctime) = body->ctime;
 +      if (body->mbo_valid & OBD_MD_FLCTIME &&
 +          body->mbo_ctime > LTIME_S(inode->i_ctime))
 +              LTIME_S(inode->i_ctime) = body->mbo_ctime;
  }
  
  static int ll_new_node(struct inode *dir, struct dentry *dentry,
 -                     const char *tgt, int mode, int rdev,
 +                     const char *tgt, umode_t mode, int rdev,
                       __u32 opc)
  {
        struct ptlrpc_request *request = NULL;
  
        if (unlikely(tgt))
                tgt_len = strlen(tgt) + 1;
 -
 +again:
        op_data = ll_prep_md_op_data(NULL, dir, NULL,
                                     dentry->d_name.name,
                                     dentry->d_name.len,
                        from_kgid(&init_user_ns, current_fsgid()),
                        cfs_curproc_cap_pack(), rdev, &request);
        ll_finish_md_op_data(op_data);
 -      if (err)
 +      if (err < 0 && err != -EREMOTE)
                goto err_exit;
  
 +      /*
 +       * If the client doesn't know where to create a subdirectory (or
 +       * in case of a race that sends the RPC to the wrong MDS), the
 +       * MDS will return -EREMOTE and the client will fetch the layout
 +       * of the directory, then create the directory on the right MDT.
 +       */
 +      if (unlikely(err == -EREMOTE)) {
 +              struct ll_inode_info *lli = ll_i2info(dir);
 +              struct lmv_user_md *lum;
 +              int lumsize, err2;
 +
 +              ptlrpc_req_finished(request);
 +              request = NULL;
 +
 +              err2 = ll_dir_getstripe(dir, (void **)&lum, &lumsize, &request,
 +                                      OBD_MD_DEFAULT_MEA);
 +              if (!err2) {
 +                      /* Update stripe_offset and retry */
 +                      lli->lli_def_stripe_offset = lum->lum_stripe_offset;
 +              } else if (err2 == -ENODATA &&
 +                         lli->lli_def_stripe_offset != -1) {
 +                      /*
 +                       * If there are no default stripe EA on the MDT, but the
 +                       * client has default stripe, then it probably means
 +                       * default stripe EA has just been deleted.
 +                       */
 +                      lli->lli_def_stripe_offset = -1;
 +              } else {
 +                      goto err_exit;
 +              }
 +
 +              ptlrpc_req_finished(request);
 +              request = NULL;
 +              goto again;
 +      }
 +
        ll_update_times(request, dir);
  
        err = ll_prep_inode(&inode, request, dir->i_sb, NULL);
  
        d_instantiate(dentry, inode);
  err_exit:
 -      ptlrpc_req_finished(request);
 +      if (request)
 +              ptlrpc_req_finished(request);
  
        return err;
  }
@@@ -961,6 -842,77 +961,6 @@@ static int ll_create_nd(struct inode *d
        return rc;
  }
  
 -int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir)
 -{
 -      struct mdt_body *body;
 -      struct lov_mds_md *eadata;
 -      struct lov_stripe_md *lsm = NULL;
 -      struct obd_trans_info oti = { 0 };
 -      struct obdo *oa;
 -      int rc;
 -
 -      /* req is swabbed so this is safe */
 -      body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY);
 -      if (!(body->valid & OBD_MD_FLEASIZE))
 -              return 0;
 -
 -      if (body->eadatasize == 0) {
 -              CERROR("OBD_MD_FLEASIZE set but eadatasize zero\n");
 -              rc = -EPROTO;
 -              goto out;
 -      }
 -
 -      /* The MDS sent back the EA because we unlinked the last reference
 -       * to this file. Use this EA to unlink the objects on the OST.
 -       * It's opaque so we don't swab here; we leave it to obd_unpackmd() to
 -       * check it is complete and sensible.
 -       */
 -      eadata = req_capsule_server_sized_get(&request->rq_pill, &RMF_MDT_MD,
 -                                            body->eadatasize);
 -      LASSERT(eadata);
 -
 -      rc = obd_unpackmd(ll_i2dtexp(dir), &lsm, eadata, body->eadatasize);
 -      if (rc < 0) {
 -              CERROR("obd_unpackmd: %d\n", rc);
 -              goto out;
 -      }
 -      LASSERT(rc >= sizeof(*lsm));
 -
 -      oa = kmem_cache_zalloc(obdo_cachep, GFP_NOFS);
 -      if (!oa) {
 -              rc = -ENOMEM;
 -              goto out_free_memmd;
 -      }
 -
 -      oa->o_oi = lsm->lsm_oi;
 -      oa->o_mode = body->mode & S_IFMT;
 -      oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLGROUP;
 -
 -      if (body->valid & OBD_MD_FLCOOKIE) {
 -              oa->o_valid |= OBD_MD_FLCOOKIE;
 -              oti.oti_logcookies =
 -                      req_capsule_server_sized_get(&request->rq_pill,
 -                                                   &RMF_LOGCOOKIES,
 -                                                 sizeof(struct llog_cookie) *
 -                                                   lsm->lsm_stripe_count);
 -              if (!oti.oti_logcookies) {
 -                      oa->o_valid &= ~OBD_MD_FLCOOKIE;
 -                      body->valid &= ~OBD_MD_FLCOOKIE;
 -              }
 -      }
 -
 -      rc = obd_destroy(NULL, ll_i2dtexp(dir), oa, lsm, &oti,
 -                       ll_i2mdexp(dir));
 -      if (rc)
 -              CERROR("obd destroy objid "DOSTID" error %d\n",
 -                     POSTID(&lsm->lsm_oi), rc);
 -out_free_memmd:
 -      obd_free_memmd(ll_i2dtexp(dir), &lsm);
 -      kmem_cache_free(obdo_cachep, oa);
 -out:
 -      return rc;
 -}
 -
  /* ll_unlink() doesn't update the inode with the new link count.
   * Instead, ll_ddelete() and ll_d_iput() will update it based upon if there
   * is any lock existing. They will recycle dentries and inodes based upon locks
@@@ -982,7 -934,7 +982,7 @@@ static int ll_unlink(struct inode *dir
        if (IS_ERR(op_data))
                return PTR_ERR(op_data);
  
 -      if (dchild && dchild->d_inode)
 +      if (dchild->d_inode)
                op_data->op_fid3 = *ll_inode2fid(dchild->d_inode);
  
        op_data->op_fid2 = op_data->op_fid3;
        ll_update_times(request, dir);
        ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_UNLINK, 1);
  
 -      rc = ll_objects_destroy(request, dir);
   out:
        ptlrpc_req_finished(request);
        return rc;
@@@ -1008,9 -961,9 +1008,9 @@@ static int ll_mkdir(struct inode *dir, 
  
        if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir)))
                mode &= ~current_umask();
 -      mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR;
 -      err = ll_new_node(dir, dentry, NULL, mode, 0, LUSTRE_OPC_MKDIR);
 +      mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
  
 +      err = ll_new_node(dir, dentry, NULL, mode, 0, LUSTRE_OPC_MKDIR);
        if (!err)
                ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_MKDIR, 1);
  
@@@ -1033,7 -986,7 +1033,7 @@@ static int ll_rmdir(struct inode *dir, 
        if (IS_ERR(op_data))
                return PTR_ERR(op_data);
  
 -      if (dchild && dchild->d_inode)
 +      if (dchild->d_inode)
                op_data->op_fid3 = *ll_inode2fid(dchild->d_inode);
  
        op_data->op_fid2 = op_data->op_fid3;
@@@ -1114,9 -1067,9 +1114,9 @@@ static int ll_rename(struct inode *src
        if (IS_ERR(op_data))
                return PTR_ERR(op_data);
  
 -      if (src_dchild && src_dchild->d_inode)
 +      if (src_dchild->d_inode)
                op_data->op_fid3 = *ll_inode2fid(src_dchild->d_inode);
 -      if (tgt_dchild && tgt_dchild->d_inode)
 +      if (tgt_dchild->d_inode)
                op_data->op_fid4 = *ll_inode2fid(tgt_dchild->d_inode);
  
        err = md_rename(sbi->ll_md_exp, op_data,
                ll_update_times(request, src);
                ll_update_times(request, tgt);
                ll_stats_ops_tally(sbi, LPROC_LL_RENAME, 1);
 -              err = ll_objects_destroy(request, src);
        }
  
        ptlrpc_req_finished(request);
@@@ -1152,10 -1106,7 +1152,7 @@@ const struct inode_operations ll_dir_in
        .setattr            = ll_setattr,
        .getattr            = ll_getattr,
        .permission      = ll_inode_permission,
-       .setxattr          = generic_setxattr,
-       .getxattr          = generic_getxattr,
        .listxattr        = ll_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl            = ll_get_acl,
  };
  
@@@ -1163,9 -1114,6 +1160,6 @@@ const struct inode_operations ll_specia
        .setattr        = ll_setattr,
        .getattr        = ll_getattr,
        .permission     = ll_inode_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ll_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl            = ll_get_acl,
  };
@@@ -35,6 -35,7 +35,6 @@@
  #include <linux/stat.h>
  #define DEBUG_SUBSYSTEM S_LLITE
  
 -#include "../include/lustre_lite.h"
  #include "llite_internal.h"
  
  static int ll_readlink_internal(struct inode *inode,
        }
  
        body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY);
 -      if ((body->valid & OBD_MD_LINKNAME) == 0) {
 +      if ((body->mbo_valid & OBD_MD_LINKNAME) == 0) {
                CERROR("OBD_MD_LINKNAME not set on reply\n");
                rc = -EPROTO;
                goto failed;
        }
  
        LASSERT(symlen != 0);
 -      if (body->eadatasize != symlen) {
 +      if (body->mbo_eadatasize != symlen) {
                CERROR("%s: inode "DFID": symlink length %d not expected %d\n",
                       ll_get_fsname(inode->i_sb, NULL, 0),
 -                     PFID(ll_inode2fid(inode)), body->eadatasize - 1,
 +                     PFID(ll_inode2fid(inode)), body->mbo_eadatasize - 1,
                       symlen - 1);
                rc = -EPROTO;
                goto failed;
@@@ -154,8 -155,5 +154,5 @@@ const struct inode_operations ll_fast_s
        .get_link       = ll_get_link,
        .getattr        = ll_getattr,
        .permission     = ll_inode_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ll_listxattr,
-       .removexattr    = generic_removexattr,
  };
diff --combined fs/9p/vfs_inode_dotl.c
@@@ -558,7 -558,7 +558,7 @@@ int v9fs_vfs_setattr_dotl(struct dentr
  
        p9_debug(P9_DEBUG_VFS, "\n");
  
 -      retval = inode_change_ok(inode, iattr);
 +      retval = setattr_prepare(dentry, iattr);
        if (retval)
                return retval;
  
@@@ -967,9 -967,6 +967,6 @@@ const struct inode_operations v9fs_dir_
        .rename = v9fs_vfs_rename,
        .getattr = v9fs_vfs_getattr_dotl,
        .setattr = v9fs_vfs_setattr_dotl,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
-       .removexattr = generic_removexattr,
        .listxattr = v9fs_listxattr,
        .get_acl = v9fs_iop_get_acl,
  };
  const struct inode_operations v9fs_file_inode_operations_dotl = {
        .getattr = v9fs_vfs_getattr_dotl,
        .setattr = v9fs_vfs_setattr_dotl,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
-       .removexattr = generic_removexattr,
        .listxattr = v9fs_listxattr,
        .get_acl = v9fs_iop_get_acl,
  };
@@@ -989,8 -983,5 +983,5 @@@ const struct inode_operations v9fs_syml
        .get_link = v9fs_vfs_get_link_dotl,
        .getattr = v9fs_vfs_getattr_dotl,
        .setattr = v9fs_vfs_setattr_dotl,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
-       .removexattr = generic_removexattr,
        .listxattr = v9fs_listxattr,
  };
diff --combined fs/btrfs/inode.c
@@@ -5072,7 -5072,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;
  
@@@ -8412,7 -8412,7 +8412,7 @@@ static int btrfs_submit_direct_hook(str
        if (!bio)
                return -ENOMEM;
  
 -      bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_opf);
 +      bio_set_op_attrs(bio, bio_op(orig_bio), bio_flags(orig_bio));
        bio->bi_private = dip;
        bio->bi_end_io = btrfs_end_dio_bio;
        btrfs_io_bio(bio)->logical = file_offset;
@@@ -8450,8 -8450,7 +8450,8 @@@ next_block
                                                  start_sector, GFP_NOFS);
                        if (!bio)
                                goto out_err;
 -                      bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_opf);
 +                      bio_set_op_attrs(bio, bio_op(orig_bio),
 +                                       bio_flags(orig_bio));
                        bio->bi_private = dip;
                        bio->bi_end_io = btrfs_end_dio_bio;
                        btrfs_io_bio(bio)->logical = file_offset;
@@@ -8619,7 -8618,7 +8619,7 @@@ static ssize_t check_direct_IO(struct b
                goto out;
  
        /* If this is a write we don't need to check anymore */
 -      if (iov_iter_rw(iter) == WRITE)
 +      if (iov_iter_rw(iter) != READ || !iter_is_iovec(iter))
                return 0;
        /*
         * Check to make sure we don't have duplicate iov_base's in this
@@@ -10544,6 -10543,21 +10544,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,
        .symlink        = btrfs_symlink,
        .setattr        = btrfs_setattr,
        .mknod          = btrfs_mknod,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = generic_removexattr,
        .permission     = btrfs_permission,
        .get_acl        = btrfs_get_acl,
        .set_acl        = btrfs_set_acl,
@@@ -10633,10 -10644,7 +10630,7 @@@ static const struct address_space_opera
  static const struct inode_operations btrfs_file_inode_operations = {
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = generic_removexattr,
        .permission     = btrfs_permission,
        .fiemap         = btrfs_fiemap,
        .get_acl        = btrfs_get_acl,
@@@ -10647,10 -10655,7 +10641,7 @@@ static const struct inode_operations bt
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
        .permission     = btrfs_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = btrfs_get_acl,
        .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
@@@ -10661,10 -10666,7 +10652,7 @@@ static const struct inode_operations bt
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
        .permission     = btrfs_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = generic_removexattr,
        .update_time    = btrfs_update_time,
  };
  
diff --combined fs/cachefiles/namei.c
@@@ -20,6 -20,7 +20,7 @@@
  #include <linux/namei.h>
  #include <linux/security.h>
  #include <linux/slab.h>
+ #include <linux/xattr.h>
  #include "internal.h"
  
  #define CACHEFILES_KEYBUF_SIZE 512
@@@ -261,9 -262,10 +262,9 @@@ requeue
   * Mark an object as being inactive.
   */
  void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
 -                                   struct cachefiles_object *object)
 +                                   struct cachefiles_object *object,
 +                                   blkcnt_t i_blocks)
  {
 -      blkcnt_t i_blocks = d_backing_inode(object->dentry)->i_blocks;
 -
        write_lock(&cache->active_lock);
        rb_erase(&object->active_node, &cache->active_nodes);
        clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
@@@ -706,8 -708,7 +707,8 @@@ mark_active_timed_out
  
  check_error:
        _debug("check error %d", ret);
 -      cachefiles_mark_object_inactive(cache, object);
 +      cachefiles_mark_object_inactive(
 +              cache, object, d_backing_inode(object->dentry)->i_blocks);
  release_dentry:
        dput(object->dentry);
        object->dentry = NULL;
@@@ -799,8 -800,7 +800,7 @@@ struct dentry *cachefiles_get_directory
        }
  
        ret = -EPERM;
-       if (!d_backing_inode(subdir)->i_op->setxattr ||
-           !d_backing_inode(subdir)->i_op->getxattr ||
+       if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
            !d_backing_inode(subdir)->i_op->lookup ||
            !d_backing_inode(subdir)->i_op->mkdir ||
            !d_backing_inode(subdir)->i_op->create ||
diff --combined fs/ceph/inode.c
@@@ -94,10 -94,7 +94,7 @@@ const struct inode_operations ceph_file
        .permission = ceph_permission,
        .setattr = ceph_setattr,
        .getattr = ceph_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = ceph_listxattr,
-       .removexattr = generic_removexattr,
        .get_acl = ceph_get_acl,
        .set_acl = ceph_set_acl,
  };
@@@ -1885,10 -1882,7 +1882,7 @@@ static const struct inode_operations ce
        .get_link = simple_get_link,
        .setattr = ceph_setattr,
        .getattr = ceph_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = ceph_listxattr,
-       .removexattr = generic_removexattr,
  };
  
  int __ceph_setattr(struct inode *inode, struct iattr *attr)
        int inode_dirty_flags = 0;
        bool lock_snap_rwsem = false;
  
 -      if (ceph_snap(inode) != CEPH_NOSNAP)
 -              return -EROFS;
 -
 -      err = inode_change_ok(inode, attr);
 -      if (err != 0)
 -              return err;
 -
        prealloc_cf = ceph_alloc_cap_flush();
        if (!prealloc_cf)
                return -ENOMEM;
@@@ -2117,17 -2118,7 +2111,17 @@@ out_put
   */
  int ceph_setattr(struct dentry *dentry, struct iattr *attr)
  {
 -      return __ceph_setattr(d_inode(dentry), attr);
 +      struct inode *inode = d_inode(dentry);
 +      int err;
 +
 +      if (ceph_snap(inode) != CEPH_NOSNAP)
 +              return -EROFS;
 +
 +      err = setattr_prepare(dentry, attr);
 +      if (err != 0)
 +              return err;
 +
 +      return __ceph_setattr(inode, attr);
  }
  
  /*
diff --combined fs/ecryptfs/inode.c
@@@ -927,7 -927,7 +927,7 @@@ static int ecryptfs_setattr(struct dent
        }
        mutex_unlock(&crypt_stat->cs_mutex);
  
 -      rc = inode_change_ok(inode, ia);
 +      rc = setattr_prepare(dentry, ia);
        if (rc)
                goto out;
        if (ia->ia_valid & ATTR_SIZE) {
@@@ -1005,15 -1005,14 +1005,14 @@@ ecryptfs_setxattr(struct dentry *dentry
                  const char *name, const void *value,
                  size_t size, int flags)
  {
-       int rc = 0;
+       int rc;
        struct dentry *lower_dentry;
  
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       if (!d_inode(lower_dentry)->i_op->setxattr) {
+       if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
                rc = -EOPNOTSUPP;
                goto out;
        }
        rc = vfs_setxattr(lower_dentry, name, value, size, flags);
        if (!rc && inode)
                fsstack_copy_attr_all(inode, d_inode(lower_dentry));
@@@ -1025,15 -1024,14 +1024,14 @@@ ssize_
  ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
                        const char *name, void *value, size_t size)
  {
-       int rc = 0;
+       int rc;
  
-       if (!lower_inode->i_op->getxattr) {
+       if (!(lower_inode->i_opflags & IOP_XATTR)) {
                rc = -EOPNOTSUPP;
                goto out;
        }
        inode_lock(lower_inode);
-       rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
-                                        name, value, size);
+       rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
        inode_unlock(lower_inode);
  out:
        return rc;
        return rc;
  }
  
- static int ecryptfs_removexattr(struct dentry *dentry, const char *name)
+ static int ecryptfs_removexattr(struct dentry *dentry, struct inode *inode,
+                               const char *name)
  {
-       int rc = 0;
+       int rc;
        struct dentry *lower_dentry;
+       struct inode *lower_inode;
  
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       if (!d_inode(lower_dentry)->i_op->removexattr) {
+       lower_inode = ecryptfs_inode_to_lower(inode);
+       if (!(lower_inode->i_opflags & IOP_XATTR)) {
                rc = -EOPNOTSUPP;
                goto out;
        }
-       inode_lock(d_inode(lower_dentry));
-       rc = d_inode(lower_dentry)->i_op->removexattr(lower_dentry, name);
-       inode_unlock(d_inode(lower_dentry));
+       inode_lock(lower_inode);
+       rc = __vfs_removexattr(lower_dentry, name);
+       inode_unlock(lower_inode);
  out:
        return rc;
  }
@@@ -1089,10 -1090,7 +1090,7 @@@ const struct inode_operations ecryptfs_
        .permission = ecryptfs_permission,
        .setattr = ecryptfs_setattr,
        .getattr = ecryptfs_getattr_link,
-       .setxattr = ecryptfs_setxattr,
-       .getxattr = ecryptfs_getxattr,
        .listxattr = ecryptfs_listxattr,
-       .removexattr = ecryptfs_removexattr
  };
  
  const struct inode_operations ecryptfs_dir_iops = {
        .rename = ecryptfs_rename,
        .permission = ecryptfs_permission,
        .setattr = ecryptfs_setattr,
-       .setxattr = ecryptfs_setxattr,
-       .getxattr = ecryptfs_getxattr,
        .listxattr = ecryptfs_listxattr,
-       .removexattr = ecryptfs_removexattr
  };
  
  const struct inode_operations ecryptfs_main_iops = {
        .permission = ecryptfs_permission,
        .setattr = ecryptfs_setattr,
        .getattr = ecryptfs_getattr,
-       .setxattr = ecryptfs_setxattr,
-       .getxattr = ecryptfs_getxattr,
        .listxattr = ecryptfs_listxattr,
-       .removexattr = ecryptfs_removexattr
+ };
+ static int ecryptfs_xattr_get(const struct xattr_handler *handler,
+                             struct dentry *dentry, struct inode *inode,
+                             const char *name, void *buffer, size_t size)
+ {
+       return ecryptfs_getxattr(dentry, inode, name, buffer, size);
+ }
+ static int ecryptfs_xattr_set(const struct xattr_handler *handler,
+                             struct dentry *dentry, struct inode *inode,
+                             const char *name, const void *value, size_t size,
+                             int flags)
+ {
+       if (value)
+               return ecryptfs_setxattr(dentry, inode, name, value, size, flags);
+       else {
+               BUG_ON(flags != XATTR_REPLACE);
+               return ecryptfs_removexattr(dentry, inode, name);
+       }
+ }
+ const struct xattr_handler ecryptfs_xattr_handler = {
+       .prefix = "",  /* match anything */
+       .get = ecryptfs_xattr_get,
+       .set = ecryptfs_xattr_set,
+ };
+ const struct xattr_handler *ecryptfs_xattr_handlers[] = {
+       &ecryptfs_xattr_handler,
+       NULL
  };
diff --combined fs/ext2/file.c
  #include <linux/pagemap.h>
  #include <linux/dax.h>
  #include <linux/quotaops.h>
 +#include <linux/iomap.h>
 +#include <linux/uio.h>
  #include "ext2.h"
  #include "xattr.h"
  #include "acl.h"
  
  #ifdef CONFIG_FS_DAX
 +static ssize_t ext2_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
 +{
 +      struct inode *inode = iocb->ki_filp->f_mapping->host;
 +      ssize_t ret;
 +
 +      if (!iov_iter_count(to))
 +              return 0; /* skip atime */
 +
 +      inode_lock_shared(inode);
 +      ret = iomap_dax_rw(iocb, to, &ext2_iomap_ops);
 +      inode_unlock_shared(inode);
 +
 +      file_accessed(iocb->ki_filp);
 +      return ret;
 +}
 +
 +static ssize_t ext2_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
 +{
 +      struct file *file = iocb->ki_filp;
 +      struct inode *inode = file->f_mapping->host;
 +      ssize_t ret;
 +
 +      inode_lock(inode);
 +      ret = generic_write_checks(iocb, from);
 +      if (ret <= 0)
 +              goto out_unlock;
 +      ret = file_remove_privs(file);
 +      if (ret)
 +              goto out_unlock;
 +      ret = file_update_time(file);
 +      if (ret)
 +              goto out_unlock;
 +
 +      ret = iomap_dax_rw(iocb, from, &ext2_iomap_ops);
 +      if (ret > 0 && iocb->ki_pos > i_size_read(inode)) {
 +              i_size_write(inode, iocb->ki_pos);
 +              mark_inode_dirty(inode);
 +      }
 +
 +out_unlock:
 +      inode_unlock(inode);
 +      if (ret > 0)
 +              ret = generic_write_sync(iocb, ret);
 +      return ret;
 +}
 +
  /*
   * The lock ordering for ext2 DAX fault paths is:
   *
@@@ -99,7 -51,7 +99,7 @@@ static int ext2_dax_fault(struct vm_are
        }
        down_read(&ei->dax_sem);
  
 -      ret = dax_fault(vma, vmf, ext2_get_block);
 +      ret = iomap_dax_fault(vma, vmf, &ext2_iomap_ops);
  
        up_read(&ei->dax_sem);
        if (vmf->flags & FAULT_FLAG_WRITE)
@@@ -204,28 -156,14 +204,28 @@@ int ext2_fsync(struct file *file, loff_
        return ret;
  }
  
 -/*
 - * We have mostly NULL's here: the current defaults are ok for
 - * the ext2 filesystem.
 - */
 +static ssize_t ext2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
 +{
 +#ifdef CONFIG_FS_DAX
 +      if (IS_DAX(iocb->ki_filp->f_mapping->host))
 +              return ext2_dax_read_iter(iocb, to);
 +#endif
 +      return generic_file_read_iter(iocb, to);
 +}
 +
 +static ssize_t ext2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 +{
 +#ifdef CONFIG_FS_DAX
 +      if (IS_DAX(iocb->ki_filp->f_mapping->host))
 +              return ext2_dax_write_iter(iocb, from);
 +#endif
 +      return generic_file_write_iter(iocb, from);
 +}
 +
  const struct file_operations ext2_file_operations = {
        .llseek         = generic_file_llseek,
 -      .read_iter      = generic_file_read_iter,
 -      .write_iter     = generic_file_write_iter,
 +      .read_iter      = ext2_file_read_iter,
 +      .write_iter     = ext2_file_write_iter,
        .unlocked_ioctl = ext2_ioctl,
  #ifdef CONFIG_COMPAT
        .compat_ioctl   = ext2_compat_ioctl,
        .open           = dquot_file_open,
        .release        = ext2_release_file,
        .fsync          = ext2_fsync,
 +      .get_unmapped_area = thp_get_unmapped_area,
        .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
  };
  
  const struct inode_operations ext2_file_inode_operations = {
  #ifdef CONFIG_EXT2_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext2_listxattr,
-       .removexattr    = generic_removexattr,
  #endif
        .setattr        = ext2_setattr,
        .get_acl        = ext2_get_acl,
diff --combined fs/ext4/file.c
@@@ -91,7 -91,9 +91,7 @@@ ext4_unaligned_aio(struct inode *inode
  static ssize_t
  ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
  {
 -      struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(iocb->ki_filp);
 -      struct blk_plug plug;
        int o_direct = iocb->ki_flags & IOCB_DIRECT;
        int unaligned_aio = 0;
        int overwrite = 0;
        if (o_direct) {
                size_t length = iov_iter_count(from);
                loff_t pos = iocb->ki_pos;
 -              blk_start_plug(&plug);
  
                /* check whether we do a DIO overwrite or not */
                if (ext4_should_dioread_nolock(inode) && !unaligned_aio &&
 -                  !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
 +                  pos + length <= i_size_read(inode)) {
                        struct ext4_map_blocks map;
                        unsigned int blkbits = inode->i_blkbits;
                        int err, len;
  
                        map.m_lblk = pos >> blkbits;
 -                      map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >> blkbits)
 -                              - map.m_lblk;
 +                      map.m_len = EXT4_MAX_BLOCKS(length, pos, blkbits);
                        len = map.m_len;
  
                        err = ext4_map_blocks(NULL, inode, &map, 0);
  
        if (ret > 0)
                ret = generic_write_sync(iocb, ret);
 -      if (o_direct)
 -              blk_finish_plug(&plug);
  
        return ret;
  
@@@ -697,7 -703,6 +697,7 @@@ const struct file_operations ext4_file_
        .open           = ext4_file_open,
        .release        = ext4_release_file,
        .fsync          = ext4_sync_file,
 +      .get_unmapped_area = thp_get_unmapped_area,
        .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
        .fallocate      = ext4_fallocate,
  const struct inode_operations ext4_file_inode_operations = {
        .setattr        = ext4_setattr,
        .getattr        = ext4_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = ext4_get_acl,
        .set_acl        = ext4_set_acl,
        .fiemap         = ext4_fiemap,
diff --combined fs/ext4/namei.c
@@@ -639,7 -639,7 +639,7 @@@ static struct stats dx_show_leaf(struc
                                        res = fscrypt_fname_alloc_buffer(
                                                dir, len,
                                                &fname_crypto_str);
 -                                      if (res < 0)
 +                                      if (res)
                                                printk(KERN_WARNING "Error "
                                                        "allocating crypto "
                                                        "buffer--skipping "
                                        res = fscrypt_fname_disk_to_usr(dir,
                                                0, 0, &de_name,
                                                &fname_crypto_str);
 -                                      if (res < 0) {
 +                                      if (res) {
                                                printk(KERN_WARNING "Error "
                                                        "converting filename "
                                                        "from disk to usr"
@@@ -1011,7 -1011,7 +1011,7 @@@ static int htree_dirblock_to_tree(struc
                        err = fscrypt_fname_disk_to_usr(dir, hinfo->hash,
                                        hinfo->minor_hash, &de_name,
                                        &fname_crypto_str);
 -                      if (err < 0) {
 +                      if (err) {
                                count = err;
                                goto errout;
                        }
@@@ -2044,31 -2044,33 +2044,31 @@@ static int make_indexed_dir(handle_t *h
        frame->entries = entries;
        frame->at = entries;
        frame->bh = bh;
 -      bh = bh2;
  
        retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
        if (retval)
                goto out_frames;        
 -      retval = ext4_handle_dirty_dirent_node(handle, dir, bh);
 +      retval = ext4_handle_dirty_dirent_node(handle, dir, bh2);
        if (retval)
                goto out_frames;        
  
 -      de = do_split(handle,dir, &bh, frame, &fname->hinfo);
 +      de = do_split(handle,dir, &bh2, frame, &fname->hinfo);
        if (IS_ERR(de)) {
                retval = PTR_ERR(de);
                goto out_frames;
        }
 -      dx_release(frames);
  
 -      retval = add_dirent_to_buf(handle, fname, dir, inode, de, bh);
 -      brelse(bh);
 -      return retval;
 +      retval = add_dirent_to_buf(handle, fname, dir, inode, de, bh2);
  out_frames:
        /*
         * Even if the block split failed, we have to properly write
         * out all the changes we did so far. Otherwise we can end up
         * with corrupted filesystem.
         */
 -      ext4_mark_inode_dirty(handle, dir);
 +      if (retval)
 +              ext4_mark_inode_dirty(handle, dir);
        dx_release(frames);
 +      brelse(bh2);
        return retval;
  }
  
@@@ -3142,7 -3144,7 +3142,7 @@@ static int ext4_symlink(struct inode *d
                istr.name = (const unsigned char *) symname;
                istr.len = len;
                err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
 -              if (err < 0)
 +              if (err)
                        goto err_drop_inode;
                sd->len = cpu_to_le16(ostr.len);
                disk_link.name = (char *) sd;
@@@ -3880,10 -3882,7 +3880,7 @@@ const struct inode_operations ext4_dir_
        .tmpfile        = ext4_tmpfile,
        .rename2        = ext4_rename2,
        .setattr        = ext4_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = ext4_get_acl,
        .set_acl        = ext4_set_acl,
        .fiemap         = ext4_fiemap,
  
  const struct inode_operations ext4_special_inode_operations = {
        .setattr        = ext4_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = ext4_get_acl,
        .set_acl        = ext4_set_acl,
  };
diff --combined fs/ext4/symlink.c
@@@ -30,6 -30,7 +30,6 @@@ static const char *ext4_encrypted_get_l
        char *caddr, *paddr = NULL;
        struct fscrypt_str cstr, pstr;
        struct fscrypt_symlink_data *sd;
 -      loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
        int res;
        u32 max_size = inode->i_sb->s_blocksize;
  
@@@ -48,6 -49,7 +48,6 @@@
                if (IS_ERR(cpage))
                        return ERR_CAST(cpage);
                caddr = page_address(cpage);
 -              caddr[size] = 0;
        }
  
        /* Symlink is encrypted */
        res = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
        if (res)
                goto errout;
 +      paddr = pstr.name;
  
        res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
 -      if (res < 0)
 +      if (res)
                goto errout;
  
 -      paddr = pstr.name;
 -
        /* Null-terminate the name */
 -      if (res <= pstr.len)
 -              paddr[res] = '\0';
 +      paddr[pstr.len] = '\0';
        if (cpage)
                put_page(cpage);
        set_delayed_call(done, kfree_link, paddr);
@@@ -86,28 -90,19 +86,19 @@@ const struct inode_operations ext4_encr
        .readlink       = generic_readlink,
        .get_link       = ext4_encrypted_get_link,
        .setattr        = ext4_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
  };
  
  const struct inode_operations ext4_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .get_link       = page_get_link,
        .setattr        = ext4_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
  };
  
  const struct inode_operations ext4_fast_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .get_link       = simple_get_link,
        .setattr        = ext4_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ext4_listxattr,
-       .removexattr    = generic_removexattr,
  };
diff --combined fs/f2fs/file.c
@@@ -135,7 -135,7 +135,7 @@@ static inline bool need_do_checkpoint(s
  
        if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
                need_cp = true;
 -      else if (file_enc_name(inode) && need_dentry_mark(sbi, inode->i_ino))
 +      else if (is_sbi_flag_set(sbi, SBI_NEED_CP))
                need_cp = true;
        else if (file_wrong_pino(inode))
                need_cp = true;
@@@ -523,7 -523,7 +523,7 @@@ static int truncate_partial_data_page(s
                return 0;
  
        if (cache_only) {
 -              page = f2fs_grab_cache_page(mapping, index, false);
 +              page = find_lock_page(mapping, index);
                if (page && PageUptodate(page))
                        goto truncate_out;
                f2fs_put_page(page, 1);
@@@ -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;
  
@@@ -732,10 -732,7 +732,7 @@@ const struct inode_operations f2fs_file
        .get_acl        = f2fs_get_acl,
        .set_acl        = f2fs_set_acl,
  #ifdef CONFIG_F2FS_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = f2fs_listxattr,
-       .removexattr    = generic_removexattr,
  #endif
        .fiemap         = f2fs_fiemap,
  };
@@@ -1454,7 -1451,7 +1451,7 @@@ static int f2fs_ioc_setflags(struct fil
  {
        struct inode *inode = file_inode(filp);
        struct f2fs_inode_info *fi = F2FS_I(inode);
 -      unsigned int flags = fi->i_flags & FS_FL_USER_VISIBLE;
 +      unsigned int flags;
        unsigned int oldflags;
        int ret;
  
@@@ -1954,7 -1951,7 +1951,7 @@@ static int f2fs_defragment_range(struc
         * avoid defragment running in SSR mode when free section are allocated
         * intensively
         */
 -      if (has_not_enough_free_secs(sbi, sec_num)) {
 +      if (has_not_enough_free_secs(sbi, 0, sec_num)) {
                err = -EAGAIN;
                goto out;
        }
@@@ -2085,13 -2082,6 +2082,13 @@@ static int f2fs_move_file_range(struct 
        if (f2fs_encrypted_inode(src) || f2fs_encrypted_inode(dst))
                return -EOPNOTSUPP;
  
 +      if (src == dst) {
 +              if (pos_in == pos_out)
 +                      return 0;
 +              if (pos_out > pos_in && pos_out < pos_in + len)
 +                      return -EINVAL;
 +      }
 +
        inode_lock(src);
        if (src != dst) {
                if (!inode_trylock(dst)) {
  
        f2fs_balance_fs(sbi, true);
        f2fs_lock_op(sbi);
 -      ret = __exchange_data_block(src, dst, pos_in,
 -                              pos_out, len >> F2FS_BLKSIZE_BITS, false);
 +      ret = __exchange_data_block(src, dst, pos_in >> F2FS_BLKSIZE_BITS,
 +                              pos_out >> F2FS_BLKSIZE_BITS,
 +                              len >> F2FS_BLKSIZE_BITS, false);
  
        if (!ret) {
                if (dst_max_i_size)
diff --combined fs/f2fs/namei.c
@@@ -91,23 -91,18 +91,23 @@@ static int is_multimedia_file(const uns
  {
        size_t slen = strlen(s);
        size_t sublen = strlen(sub);
 +      int i;
  
        /*
         * filename format of multimedia file should be defined as:
 -       * "filename + '.' + extension".
 +       * "filename + '.' + extension + (optional: '.' + temp extension)".
         */
        if (slen < sublen + 2)
                return 0;
  
 -      if (s[slen - sublen - 1] != '.')
 -              return 0;
 +      for (i = 1; i < slen - sublen; i++) {
 +              if (s[i] != '.')
 +                      continue;
 +              if (!strncasecmp(s + i + 1, sub, sublen))
 +                      return 1;
 +      }
  
 -      return !strncasecmp(s + slen - sublen, sub, sublen);
 +      return 0;
  }
  
  /*
@@@ -454,7 -449,7 +454,7 @@@ static int f2fs_symlink(struct inode *d
                ostr.name = sd->encrypted_path;
                ostr.len = disk_link.len;
                err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr);
 -              if (err < 0)
 +              if (err)
                        goto err_out;
  
                sd->len = cpu_to_le16(ostr.len);
@@@ -1015,6 -1010,7 +1015,6 @@@ static const char *f2fs_encrypted_get_l
        struct fscrypt_str cstr = FSTR_INIT(NULL, 0);
        struct fscrypt_str pstr = FSTR_INIT(NULL, 0);
        struct fscrypt_symlink_data *sd;
 -      loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
        u32 max_size = inode->i_sb->s_blocksize;
        int res;
  
        if (IS_ERR(cpage))
                return ERR_CAST(cpage);
        caddr = page_address(cpage);
 -      caddr[size] = 0;
  
        /* Symlink is encrypted */
        sd = (struct fscrypt_symlink_data *)caddr;
                goto errout;
  
        res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
 -      if (res < 0)
 +      if (res)
                goto errout;
  
        /* this is broken symlink case */
        paddr = pstr.name;
  
        /* Null-terminate the name */
 -      paddr[res] = '\0';
 +      paddr[pstr.len] = '\0';
  
        put_page(cpage);
        set_delayed_call(done, kfree_link, paddr);
@@@ -1080,10 -1077,7 +1080,7 @@@ const struct inode_operations f2fs_encr
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
  #ifdef CONFIG_F2FS_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = f2fs_listxattr,
-       .removexattr    = generic_removexattr,
  #endif
  };
  
@@@ -1103,10 -1097,7 +1100,7 @@@ const struct inode_operations f2fs_dir_
        .get_acl        = f2fs_get_acl,
        .set_acl        = f2fs_set_acl,
  #ifdef CONFIG_F2FS_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = f2fs_listxattr,
-       .removexattr    = generic_removexattr,
  #endif
  };
  
@@@ -1116,10 -1107,7 +1110,7 @@@ const struct inode_operations f2fs_syml
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
  #ifdef CONFIG_F2FS_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = f2fs_listxattr,
-       .removexattr    = generic_removexattr,
  #endif
  };
  
@@@ -1129,9 -1117,6 +1120,6 @@@ const struct inode_operations f2fs_spec
        .get_acl        = f2fs_get_acl,
        .set_acl        = f2fs_set_acl,
  #ifdef CONFIG_F2FS_FS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = f2fs_listxattr,
-       .removexattr    = generic_removexattr,
  #endif
  };
diff --combined fs/fuse/dir.c
@@@ -14,7 -14,6 +14,7 @@@
  #include <linux/namei.h>
  #include <linux/slab.h>
  #include <linux/xattr.h>
 +#include <linux/posix_acl.h>
  
  static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
  {
@@@ -39,39 -38,47 +39,39 @@@ static void fuse_advise_use_readdirplus
        set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
  }
  
 -#if BITS_PER_LONG >= 64
 +union fuse_dentry {
 +      u64 time;
 +      struct rcu_head rcu;
 +};
 +
  static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
  {
 -      entry->d_time = time;
 +      ((union fuse_dentry *) entry->d_fsdata)->time = time;
  }
  
  static inline u64 fuse_dentry_time(struct dentry *entry)
  {
 -      return entry->d_time;
 -}
 -#else
 -/*
 - * On 32 bit archs store the high 32 bits of time in d_fsdata
 - */
 -static void fuse_dentry_settime(struct dentry *entry, u64 time)
 -{
 -      entry->d_time = time;
 -      entry->d_fsdata = (void *) (unsigned long) (time >> 32);
 -}
 -
 -static u64 fuse_dentry_time(struct dentry *entry)
 -{
 -      return (u64) entry->d_time +
 -              ((u64) (unsigned long) entry->d_fsdata << 32);
 +      return ((union fuse_dentry *) entry->d_fsdata)->time;
  }
 -#endif
  
  /*
   * FUSE caches dentries and attributes with separate timeout.  The
   * time in jiffies until the dentry/attributes are valid is stored in
 - * dentry->d_time and fuse_inode->i_time respectively.
 + * dentry->d_fsdata and fuse_inode->i_time respectively.
   */
  
  /*
   * Calculate the time in jiffies until a dentry/attributes are valid
   */
 -static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
 +static u64 time_to_jiffies(u64 sec, u32 nsec)
  {
        if (sec || nsec) {
 -              struct timespec ts = {sec, nsec};
 -              return get_jiffies_64() + timespec_to_jiffies(&ts);
 +              struct timespec64 ts = {
 +                      sec,
 +                      max_t(u32, nsec, NSEC_PER_SEC - 1)
 +              };
 +
 +              return get_jiffies_64() + timespec64_to_jiffies(&ts);
        } else
                return 0;
  }
@@@ -237,7 -244,6 +237,7 @@@ static int fuse_dentry_revalidate(struc
                if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
                        goto invalid;
  
 +              forget_all_cached_acls(inode);
                fuse_change_attributes(inode, &outarg.attr,
                                       entry_attr_timeout(&outarg),
                                       attr_version);
@@@ -267,23 -273,8 +267,23 @@@ static int invalid_nodeid(u64 nodeid
        return !nodeid || nodeid == FUSE_ROOT_ID;
  }
  
 +static int fuse_dentry_init(struct dentry *dentry)
 +{
 +      dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), GFP_KERNEL);
 +
 +      return dentry->d_fsdata ? 0 : -ENOMEM;
 +}
 +static void fuse_dentry_release(struct dentry *dentry)
 +{
 +      union fuse_dentry *fd = dentry->d_fsdata;
 +
 +      kfree_rcu(fd, rcu);
 +}
 +
  const struct dentry_operations fuse_dentry_operations = {
        .d_revalidate   = fuse_dentry_revalidate,
 +      .d_init         = fuse_dentry_init,
 +      .d_release      = fuse_dentry_release,
  };
  
  int fuse_valid_type(int m)
@@@ -927,7 -918,6 +927,7 @@@ int fuse_update_attributes(struct inod
  
        if (time_before64(fi->i_time, get_jiffies_64())) {
                r = true;
 +              forget_all_cached_acls(inode);
                err = fuse_do_getattr(inode, stat, file);
        } else {
                r = false;
@@@ -1028,7 -1018,7 +1028,7 @@@ int fuse_allow_current_process(struct f
  {
        const struct cred *cred;
  
 -      if (fc->flags & FUSE_ALLOW_OTHER)
 +      if (fc->allow_other)
                return 1;
  
        cred = current_cred();
@@@ -1075,7 -1065,6 +1075,7 @@@ static int fuse_perm_getattr(struct ino
        if (mask & MAY_NOT_BLOCK)
                return -ECHILD;
  
 +      forget_all_cached_acls(inode);
        return fuse_do_getattr(inode, NULL, NULL);
  }
  
@@@ -1104,7 -1093,7 +1104,7 @@@ static int fuse_permission(struct inod
        /*
         * If attributes are needed, refresh them before proceeding
         */
 -      if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
 +      if (fc->default_permissions ||
            ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
                struct fuse_inode *fi = get_fuse_inode(inode);
  
                }
        }
  
 -      if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
 +      if (fc->default_permissions) {
                err = generic_permission(inode, mask);
  
                /* If permission is denied, try to refresh file
@@@ -1245,7 -1234,6 +1245,7 @@@ retry
                fi->nlookup++;
                spin_unlock(&fc->lock);
  
 +              forget_all_cached_acls(inode);
                fuse_change_attributes(inode, &o->attr,
                                       entry_attr_timeout(o),
                                       attr_version);
@@@ -1604,10 -1592,9 +1604,10 @@@ int fuse_flush_times(struct inode *inod
   * vmtruncate() doesn't allow for this case, so do the rlimit checking
   * and the actual truncation by hand.
   */
 -int fuse_do_setattr(struct inode *inode, struct iattr *attr,
 +int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
                    struct file *file)
  {
 +      struct inode *inode = d_inode(dentry);
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_inode *fi = get_fuse_inode(inode);
        FUSE_ARGS(args);
        int err;
        bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
  
 -      if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
 +      if (!fc->default_permissions)
                attr->ia_valid |= ATTR_FORCE;
  
 -      err = inode_change_ok(inode, attr);
 +      err = setattr_prepare(dentry, attr);
        if (err)
                return err;
  
@@@ -1716,63 -1703,14 +1716,63 @@@ error
  static int fuse_setattr(struct dentry *entry, struct iattr *attr)
  {
        struct inode *inode = d_inode(entry);
 +      struct fuse_conn *fc = get_fuse_conn(inode);
 +      struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
 +      int ret;
  
        if (!fuse_allow_current_process(get_fuse_conn(inode)))
                return -EACCES;
  
 -      if (attr->ia_valid & ATTR_FILE)
 -              return fuse_do_setattr(inode, attr, attr->ia_file);
 -      else
 -              return fuse_do_setattr(inode, attr, NULL);
 +      if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
 +              attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
 +                                  ATTR_MODE);
 +
 +              /*
 +               * The only sane way to reliably kill suid/sgid is to do it in
 +               * the userspace filesystem
 +               *
 +               * This should be done on write(), truncate() and chown().
 +               */
 +              if (!fc->handle_killpriv) {
 +                      int kill;
 +
 +                      /*
 +                       * ia_mode calculation may have used stale i_mode.
 +                       * Refresh and recalculate.
 +                       */
 +                      ret = fuse_do_getattr(inode, NULL, file);
 +                      if (ret)
 +                              return ret;
 +
 +                      attr->ia_mode = inode->i_mode;
 +                      kill = should_remove_suid(entry);
 +                      if (kill & ATTR_KILL_SUID) {
 +                              attr->ia_valid |= ATTR_MODE;
 +                              attr->ia_mode &= ~S_ISUID;
 +                      }
 +                      if (kill & ATTR_KILL_SGID) {
 +                              attr->ia_valid |= ATTR_MODE;
 +                              attr->ia_mode &= ~S_ISGID;
 +                      }
 +              }
 +      }
 +      if (!attr->ia_valid)
 +              return 0;
 +
 +      ret = fuse_do_setattr(entry, attr, file);
 +      if (!ret) {
 +              /*
 +               * If filesystem supports acls it may have updated acl xattrs in
 +               * the filesystem, so forget cached acls for the inode.
 +               */
 +              if (fc->posix_acl)
 +                      forget_all_cached_acls(inode);
 +
 +              /* Directory mode changed, may need to revalidate access */
 +              if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
 +                      fuse_invalidate_entry_cache(entry);
 +      }
 +      return ret;
  }
  
  static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
@@@ -1801,12 -1739,7 +1801,9 @@@ static const struct inode_operations fu
        .mknod          = fuse_mknod,
        .permission     = fuse_permission,
        .getattr        = fuse_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = fuse_listxattr,
-       .removexattr    = generic_removexattr,
 +      .get_acl        = fuse_get_acl,
 +      .set_acl        = fuse_set_acl,
  };
  
  static const struct file_operations fuse_dir_operations = {
@@@ -1824,12 -1757,7 +1821,9 @@@ static const struct inode_operations fu
        .setattr        = fuse_setattr,
        .permission     = fuse_permission,
        .getattr        = fuse_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = fuse_listxattr,
-       .removexattr    = generic_removexattr,
 +      .get_acl        = fuse_get_acl,
 +      .set_acl        = fuse_set_acl,
  };
  
  static const struct inode_operations fuse_symlink_inode_operations = {
        .get_link       = fuse_get_link,
        .readlink       = generic_readlink,
        .getattr        = fuse_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = fuse_listxattr,
-       .removexattr    = generic_removexattr,
  };
  
  void fuse_init_common(struct inode *inode)
diff --combined fs/gfs2/inode.c
@@@ -187,10 -187,6 +187,10 @@@ struct inode *gfs2_inode_lookup(struct 
                }
  
                gfs2_set_iop(inode);
 +
 +              inode->i_atime.tv_sec = 0;
 +              inode->i_atime.tv_nsec = 0;
 +
                unlock_new_inode(inode);
        }
  
@@@ -1936,7 -1932,7 +1936,7 @@@ static int gfs2_setattr(struct dentry *
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
                goto out;
  
 -      error = inode_change_ok(inode, attr);
 +      error = setattr_prepare(dentry, attr);
        if (error)
                goto out;
  
@@@ -2040,10 -2036,7 +2040,7 @@@ const struct inode_operations gfs2_file
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = gfs2_listxattr,
-       .removexattr = generic_removexattr,
        .fiemap = gfs2_fiemap,
        .get_acl = gfs2_get_acl,
        .set_acl = gfs2_set_acl,
@@@ -2062,10 -2055,7 +2059,7 @@@ const struct inode_operations gfs2_dir_
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = gfs2_listxattr,
-       .removexattr = generic_removexattr,
        .fiemap = gfs2_fiemap,
        .get_acl = gfs2_get_acl,
        .set_acl = gfs2_set_acl,
@@@ -2078,10 -2068,7 +2072,7 @@@ const struct inode_operations gfs2_syml
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = gfs2_listxattr,
-       .removexattr = generic_removexattr,
        .fiemap = gfs2_fiemap,
  };
  
diff --combined fs/hfs/inode.c
@@@ -15,6 -15,7 +15,7 @@@
  #include <linux/mpage.h>
  #include <linux/sched.h>
  #include <linux/uio.h>
+ #include <linux/xattr.h>
  
  #include "hfs_fs.h"
  #include "btree.h"
@@@ -605,7 -606,7 +606,7 @@@ int hfs_inode_setattr(struct dentry *de
        struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
        int error;
  
 -      error = inode_change_ok(inode, attr); /* basic permission checks */
 +      error = setattr_prepare(dentry, attr); /* basic permission checks */
        if (error)
                return error;
  
@@@ -687,7 -688,5 +688,5 @@@ static const struct file_operations hfs
  static const struct inode_operations hfs_file_inode_operations = {
        .lookup         = hfs_file_lookup,
        .setattr        = hfs_inode_setattr,
-       .setxattr       = hfs_setxattr,
-       .getxattr       = hfs_getxattr,
-       .listxattr      = hfs_listxattr,
+       .listxattr      = generic_listxattr,
  };
diff --combined fs/hfsplus/inode.c
@@@ -245,7 -245,7 +245,7 @@@ static int hfsplus_setattr(struct dentr
        struct inode *inode = d_inode(dentry);
        int error;
  
 -      error = inode_change_ok(inode, attr);
 +      error = setattr_prepare(dentry, attr);
        if (error)
                return error;
  
@@@ -333,10 -333,7 +333,7 @@@ int hfsplus_file_fsync(struct file *fil
  
  static const struct inode_operations hfsplus_file_inode_operations = {
        .setattr        = hfsplus_setattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = hfsplus_listxattr,
-       .removexattr    = generic_removexattr,
  #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
        .get_acl        = hfsplus_get_posix_acl,
        .set_acl        = hfsplus_set_posix_acl,
diff --combined fs/inode.c
@@@ -140,6 -140,8 +140,8 @@@ int inode_init_always(struct super_bloc
        inode->i_fop = &no_open_fops;
        inode->__i_nlink = 1;
        inode->i_opflags = 0;
+       if (sb->s_xattr)
+               inode->i_opflags |= IOP_XATTR;
        i_uid_write(inode, 0);
        i_gid_write(inode, 0);
        atomic_set(&inode->i_writecount, 0);
@@@ -1021,17 -1023,13 +1023,17 @@@ struct inode *iget5_locked(struct super
  {
        struct hlist_head *head = inode_hashtable + hash(sb, hashval);
        struct inode *inode;
 -
 +again:
        spin_lock(&inode_hash_lock);
        inode = find_inode(sb, head, test, data);
        spin_unlock(&inode_hash_lock);
  
        if (inode) {
                wait_on_inode(inode);
 +              if (unlikely(inode_unhashed(inode))) {
 +                      iput(inode);
 +                      goto again;
 +              }
                return inode;
        }
  
                destroy_inode(inode);
                inode = old;
                wait_on_inode(inode);
 +              if (unlikely(inode_unhashed(inode))) {
 +                      iput(inode);
 +                      goto again;
 +              }
        }
        return inode;
  
@@@ -1099,16 -1093,12 +1101,16 @@@ struct inode *iget_locked(struct super_
  {
        struct hlist_head *head = inode_hashtable + hash(sb, ino);
        struct inode *inode;
 -
 +again:
        spin_lock(&inode_hash_lock);
        inode = find_inode_fast(sb, head, ino);
        spin_unlock(&inode_hash_lock);
        if (inode) {
                wait_on_inode(inode);
 +              if (unlikely(inode_unhashed(inode))) {
 +                      iput(inode);
 +                      goto again;
 +              }
                return inode;
        }
  
                destroy_inode(inode);
                inode = old;
                wait_on_inode(inode);
 +              if (unlikely(inode_unhashed(inode))) {
 +                      iput(inode);
 +                      goto again;
 +              }
        }
        return inode;
  }
@@@ -1282,16 -1268,10 +1284,16 @@@ EXPORT_SYMBOL(ilookup5_nowait)
  struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
                int (*test)(struct inode *, void *), void *data)
  {
 -      struct inode *inode = ilookup5_nowait(sb, hashval, test, data);
 -
 -      if (inode)
 +      struct inode *inode;
 +again:
 +      inode = ilookup5_nowait(sb, hashval, test, data);
 +      if (inode) {
                wait_on_inode(inode);
 +              if (unlikely(inode_unhashed(inode))) {
 +                      iput(inode);
 +                      goto again;
 +              }
 +      }
        return inode;
  }
  EXPORT_SYMBOL(ilookup5);
@@@ -1308,18 -1288,13 +1310,18 @@@ struct inode *ilookup(struct super_bloc
  {
        struct hlist_head *head = inode_hashtable + hash(sb, ino);
        struct inode *inode;
 -
 +again:
        spin_lock(&inode_hash_lock);
        inode = find_inode_fast(sb, head, ino);
        spin_unlock(&inode_hash_lock);
  
 -      if (inode)
 +      if (inode) {
                wait_on_inode(inode);
 +              if (unlikely(inode_unhashed(inode))) {
 +                      iput(inode);
 +                      goto again;
 +              }
 +      }
        return inode;
  }
  EXPORT_SYMBOL(ilookup);
@@@ -1562,37 -1537,17 +1564,37 @@@ sector_t bmap(struct inode *inode, sect
  }
  EXPORT_SYMBOL(bmap);
  
 +/*
 + * Update times in overlayed inode from underlying real inode
 + */
 +static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode,
 +                             bool rcu)
 +{
 +      if (!rcu) {
 +              struct inode *realinode = d_real_inode(dentry);
 +
 +              if (unlikely(inode != realinode) &&
 +                  (!timespec_equal(&inode->i_mtime, &realinode->i_mtime) ||
 +                   !timespec_equal(&inode->i_ctime, &realinode->i_ctime))) {
 +                      inode->i_mtime = realinode->i_mtime;
 +                      inode->i_ctime = realinode->i_ctime;
 +              }
 +      }
 +}
 +
  /*
   * With relative atime, only update atime if the previous atime is
   * earlier than either the ctime or mtime or if at least a day has
   * passed since the last atime update.
   */
 -static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
 -                           struct timespec now)
 +static int relatime_need_update(const struct path *path, struct inode *inode,
 +                              struct timespec now, bool rcu)
  {
  
 -      if (!(mnt->mnt_flags & MNT_RELATIME))
 +      if (!(path->mnt->mnt_flags & MNT_RELATIME))
                return 1;
 +
 +      update_ovl_inode_times(path->dentry, inode, rcu);
        /*
         * Is mtime younger than atime? If yes, update atime:
         */
@@@ -1659,8 -1614,7 +1661,8 @@@ static int update_time(struct inode *in
   *    This function automatically handles read only file systems and media,
   *    as well as the "noatime" flag and inode specific "noatime" markers.
   */
 -bool atime_needs_update(const struct path *path, struct inode *inode)
 +bool __atime_needs_update(const struct path *path, struct inode *inode,
 +                        bool rcu)
  {
        struct vfsmount *mnt = path->mnt;
        struct timespec now;
  
        now = current_fs_time(inode->i_sb);
  
 -      if (!relatime_need_update(mnt, inode, now))
 +      if (!relatime_need_update(path, inode, now, rcu))
                return false;
  
        if (timespec_equal(&inode->i_atime, &now))
@@@ -1701,7 -1655,7 +1703,7 @@@ void touch_atime(const struct path *pat
        struct inode *inode = d_inode(path->dentry);
        struct timespec now;
  
 -      if (!atime_needs_update(path, inode))
 +      if (!__atime_needs_update(path, inode, false))
                return;
  
        if (!sb_start_write_trylock(inode->i_sb))
diff --combined fs/jfs/file.c
@@@ -103,7 -103,7 +103,7 @@@ int jfs_setattr(struct dentry *dentry, 
        struct inode *inode = d_inode(dentry);
        int rc;
  
 -      rc = inode_change_ok(inode, iattr);
 +      rc = setattr_prepare(dentry, iattr);
        if (rc)
                return rc;
  
  }
  
  const struct inode_operations jfs_file_inode_operations = {
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = jfs_listxattr,
-       .removexattr    = generic_removexattr,
        .setattr        = jfs_setattr,
  #ifdef CONFIG_JFS_POSIX_ACL
        .get_acl        = jfs_get_acl,
diff --combined fs/kernfs/inode.c
@@@ -28,9 -28,6 +28,6 @@@ static const struct inode_operations ke
        .permission     = kernfs_iop_permission,
        .setattr        = kernfs_iop_setattr,
        .getattr        = kernfs_iop_getattr,
-       .setxattr       = kernfs_iop_setxattr,
-       .removexattr    = kernfs_iop_removexattr,
-       .getxattr       = kernfs_iop_getxattr,
        .listxattr      = kernfs_iop_listxattr,
  };
  
@@@ -122,7 -119,7 +119,7 @@@ int kernfs_iop_setattr(struct dentry *d
                return -EINVAL;
  
        mutex_lock(&kernfs_mutex);
 -      error = inode_change_ok(inode, iattr);
 +      error = setattr_prepare(dentry, iattr);
        if (error)
                goto out;
  
@@@ -138,17 -135,12 +135,12 @@@ out
        return error;
  }
  
- static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
+ static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
                                  u32 *secdata_len)
  {
-       struct kernfs_iattrs *attrs;
        void *old_secdata;
        size_t old_secdata_len;
  
-       attrs = kernfs_iattrs(kn);
-       if (!attrs)
-               return -ENOMEM;
        old_secdata = attrs->ia_secdata;
        old_secdata_len = attrs->ia_secdata_len;
  
        return 0;
  }
  
- int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode,
-                       const char *name, const void *value,
-                       size_t size, int flags)
- {
-       struct kernfs_node *kn = inode->i_private;
-       struct kernfs_iattrs *attrs;
-       void *secdata;
-       int error;
-       u32 secdata_len = 0;
-       attrs = kernfs_iattrs(kn);
-       if (!attrs)
-               return -ENOMEM;
-       if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
-               const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
-               error = security_inode_setsecurity(inode, suffix,
-                                               value, size, flags);
-               if (error)
-                       return error;
-               error = security_inode_getsecctx(inode,
-                                               &secdata, &secdata_len);
-               if (error)
-                       return error;
-               mutex_lock(&kernfs_mutex);
-               error = kernfs_node_setsecdata(kn, &secdata, &secdata_len);
-               mutex_unlock(&kernfs_mutex);
-               if (secdata)
-                       security_release_secctx(secdata, secdata_len);
-               return error;
-       } else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
-               return simple_xattr_set(&attrs->xattrs, name, value, size,
-                                       flags);
-       }
-       return -EINVAL;
- }
- int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
- {
-       struct kernfs_node *kn = dentry->d_fsdata;
-       struct kernfs_iattrs *attrs;
-       attrs = kernfs_iattrs(kn);
-       if (!attrs)
-               return -ENOMEM;
-       return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);
- }
- ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode,
-                           const char *name, void *buf, size_t size)
- {
-       struct kernfs_node *kn = inode->i_private;
-       struct kernfs_iattrs *attrs;
-       attrs = kernfs_iattrs(kn);
-       if (!attrs)
-               return -ENOMEM;
-       return simple_xattr_get(&attrs->xattrs, name, buf, size);
- }
  ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
  {
        struct kernfs_node *kn = dentry->d_fsdata;
@@@ -376,3 -303,83 +303,83 @@@ int kernfs_iop_permission(struct inode 
  
        return generic_permission(inode, mask);
  }
+ static int kernfs_xattr_get(const struct xattr_handler *handler,
+                           struct dentry *unused, struct inode *inode,
+                           const char *suffix, void *value, size_t size)
+ {
+       const char *name = xattr_full_name(handler, suffix);
+       struct kernfs_node *kn = inode->i_private;
+       struct kernfs_iattrs *attrs;
+       attrs = kernfs_iattrs(kn);
+       if (!attrs)
+               return -ENOMEM;
+       return simple_xattr_get(&attrs->xattrs, name, value, size);
+ }
+ static int kernfs_xattr_set(const struct xattr_handler *handler,
+                           struct dentry *unused, struct inode *inode,
+                           const char *suffix, const void *value,
+                           size_t size, int flags)
+ {
+       const char *name = xattr_full_name(handler, suffix);
+       struct kernfs_node *kn = inode->i_private;
+       struct kernfs_iattrs *attrs;
+       attrs = kernfs_iattrs(kn);
+       if (!attrs)
+               return -ENOMEM;
+       return simple_xattr_set(&attrs->xattrs, name, value, size, flags);
+ }
+ const struct xattr_handler kernfs_trusted_xattr_handler = {
+       .prefix = XATTR_TRUSTED_PREFIX,
+       .get = kernfs_xattr_get,
+       .set = kernfs_xattr_set,
+ };
+ static int kernfs_security_xattr_set(const struct xattr_handler *handler,
+                                    struct dentry *unused, struct inode *inode,
+                                    const char *suffix, const void *value,
+                                    size_t size, int flags)
+ {
+       struct kernfs_node *kn = inode->i_private;
+       struct kernfs_iattrs *attrs;
+       void *secdata;
+       u32 secdata_len = 0;
+       int error;
+       attrs = kernfs_iattrs(kn);
+       if (!attrs)
+               return -ENOMEM;
+       error = security_inode_setsecurity(inode, suffix, value, size, flags);
+       if (error)
+               return error;
+       error = security_inode_getsecctx(inode, &secdata, &secdata_len);
+       if (error)
+               return error;
+       mutex_lock(&kernfs_mutex);
+       error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
+       mutex_unlock(&kernfs_mutex);
+       if (secdata)
+               security_release_secctx(secdata, secdata_len);
+       return error;
+ }
+ const struct xattr_handler kernfs_security_xattr_handler = {
+       .prefix = XATTR_SECURITY_PREFIX,
+       .get = kernfs_xattr_get,
+       .set = kernfs_security_xattr_set,
+ };
+ const struct xattr_handler *kernfs_xattr_handlers[] = {
+       &kernfs_trusted_xattr_handler,
+       &kernfs_security_xattr_handler,
+       NULL
+ };
diff --combined fs/libfs.c
@@@ -236,8 -236,8 +236,8 @@@ static const struct super_operations si
   * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
   * will never be mountable)
   */
- struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
-       const struct super_operations *ops,
+ struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, char *name,
+       const struct super_operations *ops, const struct xattr_handler **xattr,
        const struct dentry_operations *dops, unsigned long magic)
  {
        struct super_block *s;
        s->s_blocksize_bits = PAGE_SHIFT;
        s->s_magic = magic;
        s->s_op = ops ? ops : &simple_super_operations;
+       s->s_xattr = xattr;
        s->s_time_gran = 1;
        root = new_inode(s);
        if (!root)
@@@ -281,7 -282,7 +282,7 @@@ Enomem
        deactivate_locked_super(s);
        return ERR_PTR(-ENOMEM);
  }
- EXPORT_SYMBOL(mount_pseudo);
+ EXPORT_SYMBOL(mount_pseudo_xattr);
  
  int simple_open(struct inode *inode, struct file *file)
  {
@@@ -394,7 -395,7 +395,7 @@@ int simple_setattr(struct dentry *dentr
        struct inode *inode = d_inode(dentry);
        int error;
  
 -      error = inode_change_ok(inode, iattr);
 +      error = setattr_prepare(dentry, iattr);
        if (error)
                return error;
  
@@@ -1149,24 -1150,6 +1150,6 @@@ static int empty_dir_setattr(struct den
        return -EPERM;
  }
  
- static int empty_dir_setxattr(struct dentry *dentry, struct inode *inode,
-                             const char *name, const void *value,
-                             size_t size, int flags)
- {
-       return -EOPNOTSUPP;
- }
- static ssize_t empty_dir_getxattr(struct dentry *dentry, struct inode *inode,
-                                 const char *name, void *value, size_t size)
- {
-       return -EOPNOTSUPP;
- }
- static int empty_dir_removexattr(struct dentry *dentry, const char *name)
- {
-       return -EOPNOTSUPP;
- }
  static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size)
  {
        return -EOPNOTSUPP;
@@@ -1177,9 -1160,6 +1160,6 @@@ static const struct inode_operations em
        .permission     = generic_permission,
        .setattr        = empty_dir_setattr,
        .getattr        = empty_dir_getattr,
-       .setxattr       = empty_dir_setxattr,
-       .getxattr       = empty_dir_getxattr,
-       .removexattr    = empty_dir_removexattr,
        .listxattr      = empty_dir_listxattr,
  };
  
@@@ -1215,6 -1195,7 +1195,7 @@@ void make_empty_dir_inode(struct inode 
        inode->i_blocks = 0;
  
        inode->i_op = &empty_dir_inode_operations;
+       inode->i_opflags &= ~IOP_XATTR;
        inode->i_fop = &empty_dir_operations;
  }
  
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;
  
@@@ -2321,6 -2321,36 +2321,6 @@@ out_mutex
        return ret;
  }
  
 -static ssize_t ocfs2_file_splice_read(struct file *in,
 -                                    loff_t *ppos,
 -                                    struct pipe_inode_info *pipe,
 -                                    size_t len,
 -                                    unsigned int flags)
 -{
 -      int ret = 0, lock_level = 0;
 -      struct inode *inode = file_inode(in);
 -
 -      trace_ocfs2_file_splice_read(inode, in, in->f_path.dentry,
 -                      (unsigned long long)OCFS2_I(inode)->ip_blkno,
 -                      in->f_path.dentry->d_name.len,
 -                      in->f_path.dentry->d_name.name, len);
 -
 -      /*
 -       * See the comment in ocfs2_file_read_iter()
 -       */
 -      ret = ocfs2_inode_lock_atime(inode, in->f_path.mnt, &lock_level);
 -      if (ret < 0) {
 -              mlog_errno(ret);
 -              goto bail;
 -      }
 -      ocfs2_inode_unlock(inode, lock_level);
 -
 -      ret = generic_file_splice_read(in, ppos, pipe, len, flags);
 -
 -bail:
 -      return ret;
 -}
 -
  static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
                                   struct iov_iter *to)
  {
@@@ -2444,10 -2474,7 +2444,7 @@@ const struct inode_operations ocfs2_fil
        .setattr        = ocfs2_setattr,
        .getattr        = ocfs2_getattr,
        .permission     = ocfs2_permission,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ocfs2_listxattr,
-       .removexattr    = generic_removexattr,
        .fiemap         = ocfs2_fiemap,
        .get_acl        = ocfs2_iop_get_acl,
        .set_acl        = ocfs2_iop_set_acl,
@@@ -2479,7 -2506,7 +2476,7 @@@ const struct file_operations ocfs2_fop
  #endif
        .lock           = ocfs2_lock,
        .flock          = ocfs2_flock,
 -      .splice_read    = ocfs2_file_splice_read,
 +      .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
        .fallocate      = ocfs2_fallocate,
  };
@@@ -2524,7 -2551,7 +2521,7 @@@ const struct file_operations ocfs2_fops
        .compat_ioctl   = ocfs2_compat_ioctl,
  #endif
        .flock          = ocfs2_flock,
 -      .splice_read    = ocfs2_file_splice_read,
 +      .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
        .fallocate      = ocfs2_fallocate,
  };
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) {
@@@ -296,10 -296,7 +296,7 @@@ const struct inode_operations orangefs_
        .set_acl = orangefs_set_acl,
        .setattr = orangefs_setattr,
        .getattr = orangefs_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
        .listxattr = orangefs_listxattr,
-       .removexattr = generic_removexattr,
        .permission = orangefs_permission,
  };
  
diff --combined fs/orangefs/namei.c
@@@ -24,9 -24,9 +24,9 @@@ static int orangefs_create(struct inod
        struct inode *inode;
        int ret;
  
 -      gossip_debug(GOSSIP_NAME_DEBUG, "%s: %s\n",
 +      gossip_debug(GOSSIP_NAME_DEBUG, "%s: %pd\n",
                     __func__,
 -                   dentry->d_name.name);
 +                   dentry);
  
        new_op = op_alloc(ORANGEFS_VFS_OP_CREATE);
        if (!new_op)
@@@ -43,9 -43,9 +43,9 @@@
        ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
  
        gossip_debug(GOSSIP_NAME_DEBUG,
 -                   "%s: %s: handle:%pU: fsid:%d: new_op:%p: ret:%d:\n",
 +                   "%s: %pd: handle:%pU: fsid:%d: new_op:%p: ret:%d:\n",
                     __func__,
 -                   dentry->d_name.name,
 +                   dentry,
                     &new_op->downcall.resp.create.refn.khandle,
                     new_op->downcall.resp.create.refn.fs_id,
                     new_op,
        inode = orangefs_new_inode(dir->i_sb, dir, S_IFREG | mode, 0,
                                &new_op->downcall.resp.create.refn);
        if (IS_ERR(inode)) {
 -              gossip_err("%s: Failed to allocate inode for file :%s:\n",
 +              gossip_err("%s: Failed to allocate inode for file :%pd:\n",
                           __func__,
 -                         dentry->d_name.name);
 +                         dentry);
                ret = PTR_ERR(inode);
                goto out;
        }
  
        gossip_debug(GOSSIP_NAME_DEBUG,
 -                   "%s: Assigned inode :%pU: for file :%s:\n",
 +                   "%s: Assigned inode :%pU: for file :%pd:\n",
                     __func__,
                     get_khandle_from_ino(inode),
 -                   dentry->d_name.name);
 +                   dentry);
  
        d_instantiate(dentry, inode);
        unlock_new_inode(inode);
 -      dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000;
 +      dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;
        ORANGEFS_I(inode)->getattr_time = jiffies - 1;
  
        gossip_debug(GOSSIP_NAME_DEBUG,
 -                   "%s: dentry instantiated for %s\n",
 +                   "%s: dentry instantiated for %pd\n",
                     __func__,
 -                   dentry->d_name.name);
 +                   dentry);
  
        SetMtimeFlag(parent);
        dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
@@@ -87,9 -87,9 +87,9 @@@
  out:
        op_release(new_op);
        gossip_debug(GOSSIP_NAME_DEBUG,
 -                   "%s: %s: returning %d\n",
 +                   "%s: %pd: returning %d\n",
                     __func__,
 -                   dentry->d_name.name,
 +                   dentry,
                     ret);
        return ret;
  }
@@@ -115,8 -115,8 +115,8 @@@ static struct dentry *orangefs_lookup(s
         * -EEXIST on O_EXCL opens, which is broken if we skip this lookup
         * in the create path)
         */
 -      gossip_debug(GOSSIP_NAME_DEBUG, "%s called on %s\n",
 -                   __func__, dentry->d_name.name);
 +      gossip_debug(GOSSIP_NAME_DEBUG, "%s called on %pd\n",
 +                   __func__, dentry);
  
        if (dentry->d_name.len > (ORANGEFS_NAME_MAX - 1))
                return ERR_PTR(-ENAMETOOLONG);
  
                        gossip_debug(GOSSIP_NAME_DEBUG,
                                     "orangefs_lookup: Adding *negative* dentry "
 -                                   "%p for %s\n",
 +                                   "%p for %pd\n",
                                     dentry,
 -                                   dentry->d_name.name);
 +                                   dentry);
  
                        d_add(dentry, NULL);
                        res = NULL;
                goto out;
        }
  
 -      dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000;
 +      dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;
  
        inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn);
        if (IS_ERR(inode)) {
@@@ -224,10 -224,10 +224,10 @@@ static int orangefs_unlink(struct inod
        int ret;
  
        gossip_debug(GOSSIP_NAME_DEBUG,
 -                   "%s: called on %s\n"
 +                   "%s: called on %pd\n"
                     "  (inode %pU): Parent is %pU | fs_id %d\n",
                     __func__,
 -                   dentry->d_name.name,
 +                   dentry,
                     get_khandle_from_ino(inode),
                     &parent->refn.khandle,
                     parent->refn.fs_id);
@@@ -322,13 -322,13 +322,13 @@@ static int orangefs_symlink(struct inod
  
        d_instantiate(dentry, inode);
        unlock_new_inode(inode);
 -      dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000;
 +      dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;
        ORANGEFS_I(inode)->getattr_time = jiffies - 1;
  
        gossip_debug(GOSSIP_NAME_DEBUG,
 -                   "Inode (Symlink) %pU -> %s\n",
 +                   "Inode (Symlink) %pU -> %pd\n",
                     get_khandle_from_ino(inode),
 -                   dentry->d_name.name);
 +                   dentry);
  
        SetMtimeFlag(parent);
        dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
@@@ -386,13 -386,13 +386,13 @@@ static int orangefs_mkdir(struct inode 
  
        d_instantiate(dentry, inode);
        unlock_new_inode(inode);
 -      dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000;
 +      dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;
        ORANGEFS_I(inode)->getattr_time = jiffies - 1;
  
        gossip_debug(GOSSIP_NAME_DEBUG,
 -                   "Inode (Directory) %pU -> %s\n",
 +                   "Inode (Directory) %pU -> %pd\n",
                     get_khandle_from_ino(inode),
 -                   dentry->d_name.name);
 +                   dentry);
  
        /*
         * NOTE: we have no good way to keep nlink consistent for directories
@@@ -462,9 -462,6 +462,6 @@@ const struct inode_operations orangefs_
        .rename = orangefs_rename,
        .setattr = orangefs_setattr,
        .getattr = orangefs_getattr,
-       .setxattr = generic_setxattr,
-       .getxattr = generic_getxattr,
-       .removexattr = generic_removexattr,
        .listxattr = orangefs_listxattr,
        .permission = orangefs_permission,
  };
diff --combined fs/overlayfs/copy_up.c
@@@ -58,8 -58,8 +58,8 @@@ int ovl_copy_xattr(struct dentry *old, 
        char *buf, *name, *value = NULL;
        int uninitialized_var(error);
  
-       if (!old->d_inode->i_op->getxattr ||
-           !new->d_inode->i_op->getxattr)
+       if (!(old->d_inode->i_opflags & IOP_XATTR) ||
+           !(new->d_inode->i_opflags & IOP_XATTR))
                return 0;
  
        list_size = vfs_listxattr(old, NULL, 0);
@@@ -105,13 -105,6 +105,13 @@@ retry
                        goto retry;
                }
  
 +              error = security_inode_copy_up_xattr(name);
 +              if (error < 0 && error != -EOPNOTSUPP)
 +                      break;
 +              if (error == 1) {
 +                      error = 0;
 +                      continue; /* Discard */
 +              }
                error = vfs_setxattr(new, name, value, size, 0);
                if (error)
                        break;
@@@ -255,8 -248,6 +255,8 @@@ static int ovl_copy_up_locked(struct de
        struct dentry *upper = NULL;
        umode_t mode = stat->mode;
        int err;
 +      const struct cred *old_creds = NULL;
 +      struct cred *new_creds = NULL;
  
        newdentry = ovl_lookup_temp(workdir, dentry);
        err = PTR_ERR(newdentry);
        if (IS_ERR(upper))
                goto out1;
  
 +      err = security_inode_copy_up(dentry, &new_creds);
 +      if (err < 0)
 +              goto out2;
 +
 +      if (new_creds)
 +              old_creds = override_creds(new_creds);
 +
        /* Can't properly set mode on creation because of the umask */
        stat->mode &= S_IFMT;
        err = ovl_create_real(wdir, newdentry, stat, link, NULL, true);
        stat->mode = mode;
 +
 +      if (new_creds) {
 +              revert_creds(old_creds);
 +              put_cred(new_creds);
 +      }
 +
        if (err)
                goto out2;
  
diff --combined fs/overlayfs/dir.c
@@@ -489,15 -489,6 +489,15 @@@ static int ovl_create_or_link(struct de
        if (override_cred) {
                override_cred->fsuid = inode->i_uid;
                override_cred->fsgid = inode->i_gid;
 +              if (!hardlink) {
 +                      err = security_dentry_create_files_as(dentry,
 +                                      stat->mode, &dentry->d_name, old_cred,
 +                                      override_cred);
 +                      if (err) {
 +                              put_cred(override_cred);
 +                              goto out_revert_creds;
 +                      }
 +              }
                put_cred(override_creds(override_cred));
                put_cred(override_cred);
  
                        err = ovl_create_over_whiteout(dentry, inode, stat,
                                                        link, hardlink);
        }
 +out_revert_creds:
        revert_creds(old_cred);
        if (!err) {
                struct inode *realinode = d_inode(ovl_dentry_upper(dentry));
@@@ -1013,10 -1003,7 +1013,7 @@@ const struct inode_operations ovl_dir_i
        .mknod          = ovl_mknod,
        .permission     = ovl_permission,
        .getattr        = ovl_dir_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ovl_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = ovl_get_acl,
        .update_time    = ovl_update_time,
  };
diff --combined fs/overlayfs/inode.c
@@@ -53,7 -53,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;
  
@@@ -367,10 -367,7 +367,7 @@@ static const struct inode_operations ov
        .setattr        = ovl_setattr,
        .permission     = ovl_permission,
        .getattr        = ovl_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ovl_listxattr,
-       .removexattr    = generic_removexattr,
        .get_acl        = ovl_get_acl,
        .update_time    = ovl_update_time,
  };
@@@ -380,10 -377,7 +377,7 @@@ static const struct inode_operations ov
        .get_link       = ovl_get_link,
        .readlink       = ovl_readlink,
        .getattr        = ovl_getattr,
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = ovl_listxattr,
-       .removexattr    = generic_removexattr,
        .update_time    = ovl_update_time,
  };
  
diff --combined fs/overlayfs/super.c
@@@ -275,10 -275,10 +275,10 @@@ static bool ovl_is_opaquedir(struct den
        char val;
        struct inode *inode = dentry->d_inode;
  
-       if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr)
+       if (!S_ISDIR(inode->i_mode) || !(inode->i_opflags & IOP_XATTR))
                return false;
  
-       res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
+       res = __vfs_getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
        if (res == 1 && val == 'y')
                return true;
  
@@@ -1320,7 -1320,7 +1320,7 @@@ static int ovl_fill_super(struct super_
        sb->s_xattr = ovl_xattr_handlers;
        sb->s_root = root_dentry;
        sb->s_fs_info = ufs;
 -      sb->s_flags |= MS_POSIXACL;
 +      sb->s_flags |= MS_POSIXACL | MS_NOREMOTELOCK;
  
        return 0;
  
diff --combined fs/ubifs/file.c
@@@ -1262,7 -1262,7 +1262,7 @@@ int ubifs_setattr(struct dentry *dentry
  
        dbg_gen("ino %lu, mode %#x, ia_valid %#x",
                inode->i_ino, inode->i_mode, attr->ia_valid);
 -      err = inode_change_ok(inode, attr);
 +      err = setattr_prepare(dentry, attr);
        if (err)
                return err;
  
@@@ -1621,10 -1621,7 +1621,7 @@@ const struct address_space_operations u
  const struct inode_operations ubifs_file_inode_operations = {
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
-       .setxattr    = generic_setxattr,
-       .getxattr    = generic_getxattr,
        .listxattr   = ubifs_listxattr,
-       .removexattr = generic_removexattr,
  #ifdef CONFIG_UBIFS_ATIME_SUPPORT
        .update_time = ubifs_update_time,
  #endif
@@@ -1635,10 -1632,7 +1632,7 @@@ const struct inode_operations ubifs_sym
        .get_link    = simple_get_link,
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
-       .setxattr    = generic_setxattr,
-       .getxattr    = generic_getxattr,
        .listxattr   = ubifs_listxattr,
-       .removexattr = generic_removexattr,
  #ifdef CONFIG_UBIFS_ATIME_SUPPORT
        .update_time = ubifs_update_time,
  #endif
diff --combined fs/xfs/xfs_iops.c
@@@ -542,28 -542,6 +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);
  
        /*
@@@ -750,27 -743,8 +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));
@@@ -956,32 -942,16 +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;
@@@ -1066,9 -1036,6 +1066,6 @@@ static const struct inode_operations xf
        .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
-       .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
        .fiemap                 = xfs_vn_fiemap,
        .update_time            = xfs_vn_update_time,
@@@ -1094,9 -1061,6 +1091,6 @@@ static const struct inode_operations xf
        .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
-       .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
        .update_time            = xfs_vn_update_time,
        .tmpfile                = xfs_vn_tmpfile,
@@@ -1122,9 -1086,6 +1116,6 @@@ static const struct inode_operations xf
        .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
-       .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
        .update_time            = xfs_vn_update_time,
        .tmpfile                = xfs_vn_tmpfile,
@@@ -1135,9 -1096,6 +1126,6 @@@ static const struct inode_operations xf
        .get_link               = xfs_vn_get_link,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
-       .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
        .update_time            = xfs_vn_update_time,
  };
@@@ -1147,9 -1105,6 +1135,6 @@@ static const struct inode_operations xf
        .get_link               = xfs_vn_get_link_inline,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
-       .setxattr               = generic_setxattr,
-       .getxattr               = generic_getxattr,
-       .removexattr            = generic_removexattr,
        .listxattr              = xfs_vn_listxattr,
        .update_time            = xfs_vn_update_time,
  };
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
@@@ -592,6 -591,7 +592,7 @@@ is_uncached_acl(struct posix_acl *acl
  #define IOP_FASTPERM  0x0001
  #define IOP_LOOKUP    0x0002
  #define IOP_NOFOLLOW  0x0004
+ #define IOP_XATTR     0x0008
  
  /*
   * Keep mostly read-only and often accessed (especially for
@@@ -1065,18 -1065,6 +1066,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 -1252,7 +1265,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 {
@@@ -1751,12 -1739,7 +1752,7 @@@ struct inode_operations 
                        struct inode *, struct dentry *, unsigned int);
        int (*setattr) (struct dentry *, struct iattr *);
        int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
-       int (*setxattr) (struct dentry *, struct inode *,
-                        const char *, const void *, size_t, int);
-       ssize_t (*getxattr) (struct dentry *, struct inode *,
-                            const char *, void *, size_t);
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
-       int (*removexattr) (struct dentry *, const char *);
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
                      u64 len);
        int (*update_time)(struct inode *, struct timespec *, int);
@@@ -2019,6 -2002,7 +2015,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)
  {
@@@ -2087,10 -2071,19 +2083,19 @@@ struct super_block *sget(struct file_sy
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),
                        int flags, void *data);
- extern struct dentry *mount_pseudo(struct file_system_type *, char *,
-       const struct super_operations *ops,
-       const struct dentry_operations *dops,
-       unsigned long);
+ extern struct dentry *mount_pseudo_xattr(struct file_system_type *, char *,
+                                        const struct super_operations *ops,
+                                        const struct xattr_handler **xattr,
+                                        const struct dentry_operations *dops,
+                                        unsigned long);
+ static inline struct dentry *
+ mount_pseudo(struct file_system_type *fs_type, char *name,
+            const struct super_operations *ops,
+            const struct dentry_operations *dops, unsigned long magic)
+ {
+       return mount_pseudo_xattr(fs_type, name, ops, NULL, dops, magic);
+ }
  
  /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
  #define fops_get(fops) \
@@@ -2167,7 -2160,7 +2172,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;
  }
@@@ -2806,6 -2799,8 +2811,6 @@@ extern void block_sync_page(struct pag
  /* fs/splice.c */
  extern ssize_t generic_file_splice_read(struct file *, loff_t *,
                struct pipe_inode_info *, size_t, unsigned int);
 -extern ssize_t default_file_splice_read(struct file *, loff_t *,
 -              struct pipe_inode_info *, size_t, unsigned int);
  extern ssize_t iter_file_splice_write(struct pipe_inode_info *,
                struct file *, loff_t *, size_t, unsigned int);
  extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
@@@ -3005,7 -3000,7 +3010,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);
  
diff --combined mm/shmem.c
@@@ -960,7 -960,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;
  
@@@ -2311,6 -2311,119 +2311,6 @@@ static ssize_t shmem_file_read_iter(str
        return retval ? retval : error;
  }
  
 -static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
 -                              struct pipe_inode_info *pipe, size_t len,
 -                              unsigned int flags)
 -{
 -      struct address_space *mapping = in->f_mapping;
 -      struct inode *inode = mapping->host;
 -      unsigned int loff, nr_pages, req_pages;
 -      struct page *pages[PIPE_DEF_BUFFERS];
 -      struct partial_page partial[PIPE_DEF_BUFFERS];
 -      struct page *page;
 -      pgoff_t index, end_index;
 -      loff_t isize, left;
 -      int error, page_nr;
 -      struct splice_pipe_desc spd = {
 -              .pages = pages,
 -              .partial = partial,
 -              .nr_pages_max = PIPE_DEF_BUFFERS,
 -              .flags = flags,
 -              .ops = &page_cache_pipe_buf_ops,
 -              .spd_release = spd_release_page,
 -      };
 -
 -      isize = i_size_read(inode);
 -      if (unlikely(*ppos >= isize))
 -              return 0;
 -
 -      left = isize - *ppos;
 -      if (unlikely(left < len))
 -              len = left;
 -
 -      if (splice_grow_spd(pipe, &spd))
 -              return -ENOMEM;
 -
 -      index = *ppos >> PAGE_SHIFT;
 -      loff = *ppos & ~PAGE_MASK;
 -      req_pages = (len + loff + PAGE_SIZE - 1) >> PAGE_SHIFT;
 -      nr_pages = min(req_pages, spd.nr_pages_max);
 -
 -      spd.nr_pages = find_get_pages_contig(mapping, index,
 -                                              nr_pages, spd.pages);
 -      index += spd.nr_pages;
 -      error = 0;
 -
 -      while (spd.nr_pages < nr_pages) {
 -              error = shmem_getpage(inode, index, &page, SGP_CACHE);
 -              if (error)
 -                      break;
 -              unlock_page(page);
 -              spd.pages[spd.nr_pages++] = page;
 -              index++;
 -      }
 -
 -      index = *ppos >> PAGE_SHIFT;
 -      nr_pages = spd.nr_pages;
 -      spd.nr_pages = 0;
 -
 -      for (page_nr = 0; page_nr < nr_pages; page_nr++) {
 -              unsigned int this_len;
 -
 -              if (!len)
 -                      break;
 -
 -              this_len = min_t(unsigned long, len, PAGE_SIZE - loff);
 -              page = spd.pages[page_nr];
 -
 -              if (!PageUptodate(page) || page->mapping != mapping) {
 -                      error = shmem_getpage(inode, index, &page, SGP_CACHE);
 -                      if (error)
 -                              break;
 -                      unlock_page(page);
 -                      put_page(spd.pages[page_nr]);
 -                      spd.pages[page_nr] = page;
 -              }
 -
 -              isize = i_size_read(inode);
 -              end_index = (isize - 1) >> PAGE_SHIFT;
 -              if (unlikely(!isize || index > end_index))
 -                      break;
 -
 -              if (end_index == index) {
 -                      unsigned int plen;
 -
 -                      plen = ((isize - 1) & ~PAGE_MASK) + 1;
 -                      if (plen <= loff)
 -                              break;
 -
 -                      this_len = min(this_len, plen - loff);
 -                      len = this_len;
 -              }
 -
 -              spd.partial[page_nr].offset = loff;
 -              spd.partial[page_nr].len = this_len;
 -              len -= this_len;
 -              loff = 0;
 -              spd.nr_pages++;
 -              index++;
 -      }
 -
 -      while (page_nr < nr_pages)
 -              put_page(spd.pages[page_nr++]);
 -
 -      if (spd.nr_pages)
 -              error = splice_to_pipe(pipe, &spd);
 -
 -      splice_shrink_spd(&spd);
 -
 -      if (error > 0) {
 -              *ppos += error;
 -              file_accessed(in);
 -      }
 -      return error;
 -}
 -
  /*
   * llseek SEEK_DATA or SEEK_HOLE through the radix_tree.
   */
@@@ -3175,10 -3288,7 +3175,7 @@@ static const struct inode_operations sh
        .readlink       = generic_readlink,
        .get_link       = simple_get_link,
  #ifdef CONFIG_TMPFS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = shmem_listxattr,
-       .removexattr    = generic_removexattr,
  #endif
  };
  
@@@ -3186,10 -3296,7 +3183,7 @@@ static const struct inode_operations sh
        .readlink       = generic_readlink,
        .get_link       = shmem_get_link,
  #ifdef CONFIG_TMPFS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = shmem_listxattr,
-       .removexattr    = generic_removexattr,
  #endif
  };
  
@@@ -3673,7 -3780,7 +3667,7 @@@ static const struct file_operations shm
        .read_iter      = shmem_file_read_iter,
        .write_iter     = generic_file_write_iter,
        .fsync          = noop_fsync,
 -      .splice_read    = shmem_file_splice_read,
 +      .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
        .fallocate      = shmem_fallocate,
  #endif
@@@ -3683,10 -3790,7 +3677,7 @@@ static const struct inode_operations sh
        .getattr        = shmem_getattr,
        .setattr        = shmem_setattr,
  #ifdef CONFIG_TMPFS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = shmem_listxattr,
-       .removexattr    = generic_removexattr,
        .set_acl        = simple_set_acl,
  #endif
  };
@@@ -3705,10 -3809,7 +3696,7 @@@ static const struct inode_operations sh
        .tmpfile        = shmem_tmpfile,
  #endif
  #ifdef CONFIG_TMPFS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = shmem_listxattr,
-       .removexattr    = generic_removexattr,
  #endif
  #ifdef CONFIG_TMPFS_POSIX_ACL
        .setattr        = shmem_setattr,
  
  static const struct inode_operations shmem_special_inode_operations = {
  #ifdef CONFIG_TMPFS_XATTR
-       .setxattr       = generic_setxattr,
-       .getxattr       = generic_getxattr,
        .listxattr      = shmem_listxattr,
-       .removexattr    = generic_removexattr,
  #endif
  #ifdef CONFIG_TMPFS_POSIX_ACL
        .setattr        = shmem_setattr,
@@@ -3965,7 -4063,7 +3950,7 @@@ EXPORT_SYMBOL_GPL(shmem_truncate_range)
  
  /* common code */
  
 -static struct dentry_operations anon_ops = {
 +static const struct dentry_operations anon_ops = {
        .d_dname = simple_dname
  };
  
@@@ -165,13 -165,13 +165,13 @@@ enum hash_algo ima_get_hash_algo(struc
  int ima_read_xattr(struct dentry *dentry,
                   struct evm_ima_xattr_data **xattr_value)
  {
-       struct inode *inode = d_backing_inode(dentry);
-       if (!inode->i_op->getxattr)
-               return 0;
+       ssize_t ret;
  
-       return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
-                                 0, GFP_NOFS);
+       ret = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
+                                0, GFP_NOFS);
+       if (ret == -EOPNOTSUPP)
+               ret = 0;
+       return ret;
  }
  
  /*
@@@ -190,12 -190,12 +190,12 @@@ int ima_appraise_measurement(enum ima_h
  {
        static const char op[] = "appraise_data";
        char *cause = "unknown";
 -      struct dentry *dentry = file->f_path.dentry;
 +      struct dentry *dentry = file_dentry(file);
        struct inode *inode = d_backing_inode(dentry);
        enum integrity_status status = INTEGRITY_UNKNOWN;
        int rc = xattr_len, hash_start = 0;
  
-       if (!inode->i_op->getxattr)
+       if (!(inode->i_opflags & IOP_XATTR))
                return INTEGRITY_UNKNOWN;
  
        if (rc <= 0) {
@@@ -295,7 -295,7 +295,7 @@@ out
   */
  void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
  {
 -      struct dentry *dentry = file->f_path.dentry;
 +      struct dentry *dentry = file_dentry(file);
        int rc = 0;
  
        /* do not collect and update hash for digital signatures */
@@@ -322,10 -322,10 +322,10 @@@ void ima_inode_post_setattr(struct dent
  {
        struct inode *inode = d_backing_inode(dentry);
        struct integrity_iint_cache *iint;
-       int must_appraise, rc;
+       int must_appraise;
  
        if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
-           || !inode->i_op->removexattr)
+           || !(inode->i_opflags & IOP_XATTR))
                return;
  
        must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
                        iint->flags |= IMA_APPRAISE;
        }
        if (!must_appraise)
-               rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA);
-       return;
+               __vfs_removexattr(dentry, XATTR_NAME_IMA);
  }
  
  /*
diff --combined security/selinux/hooks.c
@@@ -507,14 -507,14 +507,14 @@@ static int sb_finish_set_opts(struct su
                   the root directory.  -ENODATA is ok, as this may be
                   the first boot of the SELinux kernel before we have
                   assigned xattr values to the filesystem. */
-               if (!root_inode->i_op->getxattr) {
+               if (!(root_inode->i_opflags & IOP_XATTR)) {
                        printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
                               "xattr support\n", sb->s_id, sb->s_type->name);
                        rc = -EOPNOTSUPP;
                        goto out;
                }
-               rc = root_inode->i_op->getxattr(root, root_inode,
-                                               XATTR_NAME_SELINUX, NULL, 0);
+               rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
                if (rc < 0 && rc != -ENODATA) {
                        if (rc == -EOPNOTSUPP)
                                printk(KERN_WARNING "SELinux: (dev %s, type "
@@@ -1410,11 -1410,10 +1410,10 @@@ static int inode_doinit_with_dentry(str
        case SECURITY_FS_USE_NATIVE:
                break;
        case SECURITY_FS_USE_XATTR:
-               if (!inode->i_op->getxattr) {
+               if (!(inode->i_opflags & IOP_XATTR)) {
                        isec->sid = sbsec->def_sid;
                        break;
                }
                /* Need a dentry, since the xattr API requires one.
                   Life would be simpler if we could just pass the inode. */
                if (opt_dentry) {
                        goto out_unlock;
                }
                context[len] = '\0';
-               rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
-                                          context, len);
+               rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
                if (rc == -ERANGE) {
                        kfree(context);
  
                        /* Need a larger buffer.  Query for the right size. */
-                       rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
-                                                  NULL, 0);
+                       rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
                        if (rc < 0) {
                                dput(dentry);
                                goto out_unlock;
                                goto out_unlock;
                        }
                        context[len] = '\0';
-                       rc = inode->i_op->getxattr(dentry, inode,
-                                                  XATTR_NAME_SELINUX,
-                                                  context, len);
+                       rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
                }
                dput(dentry);
                if (rc < 0) {
@@@ -1761,8 -1756,8 +1756,8 @@@ static inline int file_path_has_perm(co
  {
        struct common_audit_data ad;
  
 -      ad.type = LSM_AUDIT_DATA_PATH;
 -      ad.u.path = file->f_path;
 +      ad.type = LSM_AUDIT_DATA_FILE;
 +      ad.u.file = file;
        return inode_has_perm(cred, file_inode(file), av, &ad);
  }
  
@@@ -1784,8 -1779,8 +1779,8 @@@ static int file_has_perm(const struct c
        u32 sid = cred_sid(cred);
        int rc;
  
 -      ad.type = LSM_AUDIT_DATA_PATH;
 -      ad.u.path = file->f_path;
 +      ad.type = LSM_AUDIT_DATA_FILE;
 +      ad.u.file = file;
  
        if (sid != fsec->sid) {
                rc = avc_has_perm(sid, fsec->sid,
  /*
   * Determine the label for an inode that might be unioned.
   */
 -static int selinux_determine_inode_label(struct inode *dir,
 -                                       const struct qstr *name,
 -                                       u16 tclass,
 -                                       u32 *_new_isid)
 +static int
 +selinux_determine_inode_label(const struct task_security_struct *tsec,
 +                               struct inode *dir,
 +                               const struct qstr *name, u16 tclass,
 +                               u32 *_new_isid)
  {
        const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
 -      const struct task_security_struct *tsec = current_security();
  
        if ((sbsec->flags & SE_SBINITIALIZED) &&
            (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
@@@ -1857,8 -1852,8 +1852,8 @@@ static int may_create(struct inode *dir
        if (rc)
                return rc;
  
 -      rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass,
 -                                         &newsid);
 +      rc = selinux_determine_inode_label(current_security(), dir,
 +                                         &dentry->d_name, tclass, &newsid);
        if (rc)
                return rc;
  
@@@ -2365,8 -2360,8 +2360,8 @@@ static int selinux_bprm_set_creds(struc
                        new_tsec->sid = old_tsec->sid;
        }
  
 -      ad.type = LSM_AUDIT_DATA_PATH;
 -      ad.u.path = bprm->file->f_path;
 +      ad.type = LSM_AUDIT_DATA_FILE;
 +      ad.u.file = bprm->file;
  
        if (new_tsec->sid == old_tsec->sid) {
                rc = avc_has_perm(old_tsec->sid, isec->sid,
@@@ -2838,8 -2833,7 +2833,8 @@@ static int selinux_dentry_init_security
        u32 newsid;
        int rc;
  
 -      rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name,
 +      rc = selinux_determine_inode_label(current_security(),
 +                                         d_inode(dentry->d_parent), name,
                                           inode_mode_to_security_class(mode),
                                           &newsid);
        if (rc)
        return security_sid_to_context(newsid, (char **)ctx, ctxlen);
  }
  
 +static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
 +                                        struct qstr *name,
 +                                        const struct cred *old,
 +                                        struct cred *new)
 +{
 +      u32 newsid;
 +      int rc;
 +      struct task_security_struct *tsec;
 +
 +      rc = selinux_determine_inode_label(old->security,
 +                                         d_inode(dentry->d_parent), name,
 +                                         inode_mode_to_security_class(mode),
 +                                         &newsid);
 +      if (rc)
 +              return rc;
 +
 +      tsec = new->security;
 +      tsec->create_sid = newsid;
 +      return 0;
 +}
 +
  static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
                                       const struct qstr *qstr,
                                       const char **name,
        sid = tsec->sid;
        newsid = tsec->create_sid;
  
 -      rc = selinux_determine_inode_label(
 +      rc = selinux_determine_inode_label(current_security(),
                dir, qstr,
                inode_mode_to_security_class(inode->i_mode),
                &newsid);
@@@ -3315,41 -3288,6 +3310,41 @@@ static void selinux_inode_getsecid(stru
        *secid = isec->sid;
  }
  
 +static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
 +{
 +      u32 sid;
 +      struct task_security_struct *tsec;
 +      struct cred *new_creds = *new;
 +
 +      if (new_creds == NULL) {
 +              new_creds = prepare_creds();
 +              if (!new_creds)
 +                      return -ENOMEM;
 +      }
 +
 +      tsec = new_creds->security;
 +      /* Get label from overlay inode and set it in create_sid */
 +      selinux_inode_getsecid(d_inode(src), &sid);
 +      tsec->create_sid = sid;
 +      *new = new_creds;
 +      return 0;
 +}
 +
 +static int selinux_inode_copy_up_xattr(const char *name)
 +{
 +      /* The copy_up hook above sets the initial context on an inode, but we
 +       * don't then want to overwrite it by blindly copying all the lower
 +       * xattrs up.  Instead, we have to filter out SELinux-related xattrs.
 +       */
 +      if (strcmp(name, XATTR_NAME_SELINUX) == 0)
 +              return 1; /* Discard */
 +      /*
 +       * Any other attribute apart from SELINUX is not claimed, supported
 +       * by selinux.
 +       */
 +      return -EOPNOTSUPP;
 +}
 +
  /* file security operations */
  
  static int selinux_revalidate_file_permission(struct file *file, int mask)
@@@ -3833,8 -3771,8 +3828,8 @@@ static int selinux_kernel_module_from_f
  
        /* finit_module */
  
 -      ad.type = LSM_AUDIT_DATA_PATH;
 -      ad.u.path = file->f_path;
 +      ad.type = LSM_AUDIT_DATA_FILE;
 +      ad.u.file = file;
  
        fsec = file->f_security;
        if (sid != fsec->sid) {
@@@ -4041,7 -3979,7 +4036,7 @@@ out
        return ret;
  }
  
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 +#if IS_ENABLED(CONFIG_IPV6)
  
  /* Returns error only if unable to parse addresses */
  static int selinux_parse_skb_ipv6(struct sk_buff *skb,
@@@ -4132,7 -4070,7 +4127,7 @@@ static int selinux_parse_skb(struct sk_
                                       &ad->u.net->v4info.daddr);
                goto okay;
  
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 +#if IS_ENABLED(CONFIG_IPV6)
        case PF_INET6:
                ret = selinux_parse_skb_ipv6(skb, ad, proto);
                if (ret)
@@@ -5086,7 -5024,7 +5081,7 @@@ static unsigned int selinux_ipv4_forwar
        return selinux_ip_forward(skb, state->in, PF_INET);
  }
  
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 +#if IS_ENABLED(CONFIG_IPV6)
  static unsigned int selinux_ipv6_forward(void *priv,
                                         struct sk_buff *skb,
                                         const struct nf_hook_state *state)
@@@ -5144,7 -5082,7 +5139,7 @@@ static unsigned int selinux_ipv4_output
        return selinux_ip_output(skb, PF_INET);
  }
  
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 +#if IS_ENABLED(CONFIG_IPV6)
  static unsigned int selinux_ipv6_output(void *priv,
                                        struct sk_buff *skb,
                                        const struct nf_hook_state *state)
@@@ -5330,7 -5268,7 +5325,7 @@@ static unsigned int selinux_ipv4_postro
        return selinux_ip_postroute(skb, state->out, PF_INET);
  }
  
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 +#if IS_ENABLED(CONFIG_IPV6)
  static unsigned int selinux_ipv6_postroute(void *priv,
                                           struct sk_buff *skb,
                                           const struct nf_hook_state *state)
@@@ -6119,7 -6057,6 +6114,7 @@@ static struct security_hook_list selinu
        LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
  
        LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
 +      LSM_HOOK_INIT(dentry_create_files_as, selinux_dentry_create_files_as),
  
        LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
        LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
        LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
        LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
        LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
 +      LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),
 +      LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr),
  
        LSM_HOOK_INIT(file_permission, selinux_file_permission),
        LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
@@@ -6377,7 -6312,7 +6372,7 @@@ static struct nf_hook_ops selinux_nf_op
                .hooknum =      NF_INET_LOCAL_OUT,
                .priority =     NF_IP_PRI_SELINUX_FIRST,
        },
 -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 +#if IS_ENABLED(CONFIG_IPV6)
        {
                .hook =         selinux_ipv6_postroute,
                .pf =           NFPROTO_IPV6,
@@@ -265,14 -265,14 +265,14 @@@ static struct smack_known *smk_fetch(co
        char *buffer;
        struct smack_known *skp = NULL;
  
-       if (ip->i_op->getxattr == NULL)
+       if (!(ip->i_opflags & IOP_XATTR))
                return ERR_PTR(-EOPNOTSUPP);
  
        buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
        if (buffer == NULL)
                return ERR_PTR(-ENOMEM);
  
-       rc = ip->i_op->getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
+       rc = __vfs_getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
        if (rc < 0)
                skp = ERR_PTR(rc);
        else if (rc == 0)
@@@ -1857,14 -1857,14 +1857,14 @@@ static int smack_file_send_sigiotask(st
  
        /* we don't log here as rc can be overriden */
        skp = file->f_security;
 -      rc = smk_access(skp, tkp, MAY_WRITE, NULL);
 -      rc = smk_bu_note("sigiotask", skp, tkp, MAY_WRITE, rc);
 +      rc = smk_access(skp, tkp, MAY_DELIVER, NULL);
 +      rc = smk_bu_note("sigiotask", skp, tkp, MAY_DELIVER, rc);
        if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
                rc = 0;
  
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
        smk_ad_setfield_u_tsk(&ad, tsk);
 -      smack_log(skp->smk_known, tkp->smk_known, MAY_WRITE, rc, &ad);
 +      smack_log(skp->smk_known, tkp->smk_known, MAY_DELIVER, rc, &ad);
        return rc;
  }
  
@@@ -2265,8 -2265,8 +2265,8 @@@ static int smack_task_kill(struct task_
         * can write the receiver.
         */
        if (secid == 0) {
 -              rc = smk_curacc(tkp, MAY_WRITE, &ad);
 -              rc = smk_bu_task(p, MAY_WRITE, rc);
 +              rc = smk_curacc(tkp, MAY_DELIVER, &ad);
 +              rc = smk_bu_task(p, MAY_DELIVER, rc);
                return rc;
        }
        /*
         * we can't take privilege into account.
         */
        skp = smack_from_secid(secid);
 -      rc = smk_access(skp, tkp, MAY_WRITE, &ad);
 -      rc = smk_bu_note("USB signal", skp, tkp, MAY_WRITE, rc);
 +      rc = smk_access(skp, tkp, MAY_DELIVER, &ad);
 +      rc = smk_bu_note("USB signal", skp, tkp, MAY_DELIVER, rc);
        return rc;
  }
  
@@@ -3520,8 -3520,8 +3520,8 @@@ static void smack_d_instantiate(struct 
                 * It would be curious if the label of the task
                 * does not match that assigned.
                 */
-               if (inode->i_op->getxattr == NULL)
-                       break;
+               if (!(inode->i_opflags & IOP_XATTR))
+                       break;
                /*
                 * Get the dentry for xattr.
                 */
                         */
                        if (isp->smk_flags & SMK_INODE_CHANGED) {
                                isp->smk_flags &= ~SMK_INODE_CHANGED;
-                               rc = inode->i_op->setxattr(dp, inode,
+                               rc = __vfs_setxattr(dp, inode,
                                        XATTR_NAME_SMACKTRANSMUTE,
                                        TRANS_TRUE, TRANS_TRUE_SIZE,
                                        0);
                        } else {
-                               rc = inode->i_op->getxattr(dp, inode,
+                               rc = __vfs_getxattr(dp, inode,
                                        XATTR_NAME_SMACKTRANSMUTE, trattr,
                                        TRANS_TRUE_SIZE);
                                if (rc >= 0 && strncmp(trattr, TRANS_TRUE,