Whamcloud - gitweb
LU-7382 llite: Fix iovec references accounting in ll_file_aio_read/write
[fs/lustre-release.git] / lustre / llite / file.c
index 5d7f902..b4f3779 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2014, Intel Corporation.
+ * Copyright (c) 2011, 2015, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -86,119 +86,117 @@ static void ll_file_data_put(struct ll_file_data *fd)
                 OBD_SLAB_FREE_PTR(fd, ll_file_data_slab);
 }
 
-void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data,
-                          struct lustre_handle *fh)
-{
-        op_data->op_fid1 = ll_i2info(inode)->lli_fid;
-        op_data->op_attr.ia_mode = inode->i_mode;
-        op_data->op_attr.ia_atime = inode->i_atime;
-        op_data->op_attr.ia_mtime = inode->i_mtime;
-        op_data->op_attr.ia_ctime = inode->i_ctime;
-        op_data->op_attr.ia_size = i_size_read(inode);
-        op_data->op_attr_blocks = inode->i_blocks;
-       op_data->op_attr_flags = ll_inode_to_ext_flags(inode->i_flags);
-        if (fh)
-                op_data->op_handle = *fh;
-        op_data->op_capa1 = ll_mdscapa_get(inode);
-
-       if (LLIF_DATA_MODIFIED & ll_i2info(inode)->lli_flags)
-               op_data->op_bias |= MDS_DATA_MODIFIED;
-}
-
 /**
  * Packs all the attributes into @op_data for the CLOSE rpc.
  */
 static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data,
                              struct obd_client_handle *och)
 {
-        ENTRY;
-
-       op_data->op_attr.ia_valid = ATTR_MODE | ATTR_ATIME | ATTR_ATIME_SET |
-                                       ATTR_MTIME | ATTR_MTIME_SET |
-                                       ATTR_CTIME | ATTR_CTIME_SET;
+       ENTRY;
 
-        if (!(och->och_flags & FMODE_WRITE))
-                goto out;
+       ll_prep_md_op_data(op_data, inode, NULL, NULL,
+                          0, 0, LUSTRE_OPC_ANY, NULL);
+
+       op_data->op_attr.ia_mode = inode->i_mode;
+       op_data->op_attr.ia_atime = inode->i_atime;
+       op_data->op_attr.ia_mtime = inode->i_mtime;
+       op_data->op_attr.ia_ctime = inode->i_ctime;
+       op_data->op_attr.ia_size = i_size_read(inode);
+       op_data->op_attr.ia_valid |= ATTR_MODE | ATTR_ATIME | ATTR_ATIME_SET |
+                                    ATTR_MTIME | ATTR_MTIME_SET |
+                                    ATTR_CTIME | ATTR_CTIME_SET;
+       op_data->op_attr_blocks = inode->i_blocks;
+       op_data->op_attr_flags = ll_inode_to_ext_flags(inode->i_flags);
+       op_data->op_handle = och->och_fh;
 
-       op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS;
+       if (och->och_flags & FMODE_WRITE &&
+           ll_file_test_and_clear_flag(ll_i2info(inode), LLIF_DATA_MODIFIED))
+               /* For HSM: if inode data has been modified, pack it so that
+                * MDT can set data dirty flag in the archive. */
+               op_data->op_bias |= MDS_DATA_MODIFIED;
 
-out:
-        ll_pack_inode2opdata(inode, op_data, &och->och_fh);
-        ll_prep_md_op_data(op_data, inode, NULL, NULL,
-                           0, 0, LUSTRE_OPC_ANY, NULL);
-        EXIT;
+       EXIT;
 }
 
-static int ll_close_inode_openhandle(struct obd_export *md_exp,
-                                    struct inode *inode,
+/**
+ * Perform a close, possibly with a bias.
+ * The meaning of "data" depends on the value of "bias".
+ *
+ * If \a bias is MDS_HSM_RELEASE then \a data is a pointer to the data version.
+ * If \a bias is MDS_CLOSE_LAYOUT_SWAP then \a data is a pointer to the inode to
+ * swap layouts with.
+ */
+static int ll_close_inode_openhandle(struct inode *inode,
                                     struct obd_client_handle *och,
-                                    const __u64 *data_version)
+                                    enum mds_op_bias bias, void *data)
 {
-        struct obd_export *exp = ll_i2mdexp(inode);
-        struct md_op_data *op_data;
-        struct ptlrpc_request *req = NULL;
-        struct obd_device *obd = class_exp2obd(exp);
-        int rc;
-        ENTRY;
+       struct obd_export *md_exp = ll_i2mdexp(inode);
+       const struct ll_inode_info *lli = ll_i2info(inode);
+       struct md_op_data *op_data;
+       struct ptlrpc_request *req = NULL;
+       int rc;
+       ENTRY;
 
-        if (obd == NULL) {
-                /*
-                 * XXX: in case of LMV, is this correct to access
-                 * ->exp_handle?
-                 */
-                CERROR("Invalid MDC connection handle "LPX64"\n",
-                       ll_i2mdexp(inode)->exp_handle.h_cookie);
-                GOTO(out, rc = 0);
-        }
+       if (class_exp2obd(md_exp) == NULL) {
+               CERROR("%s: invalid MDC connection handle closing "DFID"\n",
+                      ll_get_fsname(inode->i_sb, NULL, 0),
+                      PFID(&lli->lli_fid));
+               GOTO(out, rc = 0);
+       }
 
-        OBD_ALLOC_PTR(op_data);
-        if (op_data == NULL)
-                GOTO(out, rc = -ENOMEM); // XXX We leak openhandle and request here.
+       OBD_ALLOC_PTR(op_data);
+       /* We leak openhandle and request here on error, but not much to be
+        * done in OOM case since app won't retry close on error either. */
+       if (op_data == NULL)
+               GOTO(out, rc = -ENOMEM);
 
        ll_prepare_close(inode, op_data, och);
-       if (data_version != NULL) {
-               /* Pass in data_version implies release. */
+       switch (bias) {
+       case MDS_CLOSE_LAYOUT_SWAP:
+               LASSERT(data != NULL);
+               op_data->op_bias |= MDS_CLOSE_LAYOUT_SWAP;
+               op_data->op_data_version = 0;
+               op_data->op_lease_handle = och->och_lease_handle;
+               op_data->op_fid2 = *ll_inode2fid(data);
+               break;
+
+       case MDS_HSM_RELEASE:
+               LASSERT(data != NULL);
                op_data->op_bias |= MDS_HSM_RELEASE;
-               op_data->op_data_version = *data_version;
+               op_data->op_data_version = *(__u64 *)data;
                op_data->op_lease_handle = och->och_lease_handle;
                op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS;
-       }
+               break;
 
-        rc = md_close(md_exp, op_data, och->och_mod, &req);
-       if (rc) {
-               CERROR("%s: inode "DFID" mdc close failed: rc = %d\n",
-                      ll_i2mdexp(inode)->exp_obd->obd_name,
-                      PFID(ll_inode2fid(inode)), rc);
+       default:
+               LASSERT(data == NULL);
+               break;
        }
 
-       /* DATA_MODIFIED flag was successfully sent on close, cancel data
-        * modification flag. */
-       if (rc == 0 && (op_data->op_bias & MDS_DATA_MODIFIED)) {
-               struct ll_inode_info *lli = ll_i2info(inode);
-
-               spin_lock(&lli->lli_lock);
-               lli->lli_flags &= ~LLIF_DATA_MODIFIED;
-               spin_unlock(&lli->lli_lock);
-       }
+       rc = md_close(md_exp, op_data, och->och_mod, &req);
+       if (rc != 0 && rc != -EINTR)
+               CERROR("%s: inode "DFID" mdc close failed: rc = %d\n",
+                      md_exp->exp_obd->obd_name, PFID(&lli->lli_fid), rc);
 
-       if (rc == 0 && op_data->op_bias & MDS_HSM_RELEASE) {
+       if (rc == 0 &&
+           op_data->op_bias & (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP)) {
                struct mdt_body *body;
+
                body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
-               if (!(body->mbo_valid & OBD_MD_FLRELEASED))
+               if (!(body->mbo_valid & OBD_MD_CLOSE_INTENT_EXECED))
                        rc = -EBUSY;
        }
 
-        ll_finish_md_op_data(op_data);
-        EXIT;
+       ll_finish_md_op_data(op_data);
+       EXIT;
 out:
 
        md_clear_open_replay_data(md_exp, och);
        och->och_fh.cookie = DEAD_HANDLE_MAGIC;
        OBD_FREE_PTR(och);
 
-        if (req) /* This is close request */
-                ptlrpc_req_finished(req);
-        return rc;
+       ptlrpc_req_finished(req);       /* This is close request */
+       return rc;
 }
 
 int ll_md_real_close(struct inode *inode, fmode_t fmode)
@@ -237,20 +235,24 @@ int ll_md_real_close(struct inode *inode, fmode_t fmode)
        if (och != NULL) {
                /* There might be a race and this handle may already
                 * be closed. */
-               rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp,
-                                              inode, och, NULL);
+               rc = ll_close_inode_openhandle(inode, och, 0, NULL);
        }
 
        RETURN(rc);
 }
 
-static int ll_md_close(struct obd_export *md_exp, struct inode *inode,
-                      struct file *file)
+static int ll_md_close(struct inode *inode, struct file *file)
 {
-        struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
-        struct ll_inode_info *lli = ll_i2info(inode);
-        int rc = 0;
-        ENTRY;
+       union ldlm_policy_data policy = {
+               .l_inodebits    = { MDS_INODELOCK_OPEN },
+       };
+       __u64 flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK;
+       struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+       struct ll_inode_info *lli = ll_i2info(inode);
+       struct lustre_handle lockh;
+       enum ldlm_mode lockmode;
+       int rc = 0;
+       ENTRY;
 
        /* clear group lock, if present */
        if (unlikely(fd->fd_flags & LL_FILE_GROUP_LOCKED))
@@ -269,52 +271,36 @@ static int ll_md_close(struct obd_export *md_exp, struct inode *inode,
        }
 
        if (fd->fd_och != NULL) {
-               rc = ll_close_inode_openhandle(md_exp, inode, fd->fd_och, NULL);
+               rc = ll_close_inode_openhandle(inode, fd->fd_och, 0, NULL);
                fd->fd_och = NULL;
                GOTO(out, rc);
        }
 
         /* Let's see if we have good enough OPEN lock on the file and if
            we can skip talking to MDS */
-        if (file->f_dentry->d_inode) { /* Can this ever be false? */
-                int lockmode;
-               __u64 flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK;
-                struct lustre_handle lockh;
-                struct inode *inode = file->f_dentry->d_inode;
-                ldlm_policy_data_t policy = {.l_inodebits={MDS_INODELOCK_OPEN}};
-
-               mutex_lock(&lli->lli_och_mutex);
-                if (fd->fd_omode & FMODE_WRITE) {
-                        lockmode = LCK_CW;
-                        LASSERT(lli->lli_open_fd_write_count);
-                        lli->lli_open_fd_write_count--;
-                } else if (fd->fd_omode & FMODE_EXEC) {
-                        lockmode = LCK_PR;
-                        LASSERT(lli->lli_open_fd_exec_count);
-                        lli->lli_open_fd_exec_count--;
-                } else {
-                        lockmode = LCK_CR;
-                        LASSERT(lli->lli_open_fd_read_count);
-                        lli->lli_open_fd_read_count--;
-                }
-               mutex_unlock(&lli->lli_och_mutex);
-
-                if (!md_lock_match(md_exp, flags, ll_inode2fid(inode),
-                                   LDLM_IBITS, &policy, lockmode,
-                                   &lockh)) {
-                        rc = ll_md_real_close(file->f_dentry->d_inode,
-                                              fd->fd_omode);
-                }
+       mutex_lock(&lli->lli_och_mutex);
+       if (fd->fd_omode & FMODE_WRITE) {
+               lockmode = LCK_CW;
+               LASSERT(lli->lli_open_fd_write_count);
+               lli->lli_open_fd_write_count--;
+       } else if (fd->fd_omode & FMODE_EXEC) {
+               lockmode = LCK_PR;
+               LASSERT(lli->lli_open_fd_exec_count);
+               lli->lli_open_fd_exec_count--;
        } else {
-               CERROR("released file has negative dentry: file = %p, "
-                      "dentry = %p, name = %s\n",
-                      file, file->f_dentry, file->f_dentry->d_name.name);
+               lockmode = LCK_CR;
+               LASSERT(lli->lli_open_fd_read_count);
+               lli->lli_open_fd_read_count--;
        }
+       mutex_unlock(&lli->lli_och_mutex);
+
+       if (!md_lock_match(ll_i2mdexp(inode), flags, ll_inode2fid(inode),
+                          LDLM_IBITS, &policy, lockmode, &lockh))
+               rc = ll_md_real_close(inode, fd->fd_omode);
 
 out:
        LUSTRE_FPRIVATE(file) = NULL;
        ll_file_data_put(fd);
-       ll_capa_close(inode);
 
        RETURN(rc);
 }
@@ -349,7 +335,7 @@ int ll_file_release(struct inode *inode, struct file *file)
        }
 #endif
 
-        if (inode->i_sb->s_root != file->f_dentry)
+       if (inode->i_sb->s_root != file->f_path.dentry)
                 ll_stats_ops_tally(sbi, LPROC_LL_RELEASE, 1);
         fd = LUSTRE_FPRIVATE(file);
         LASSERT(fd != NULL);
@@ -359,30 +345,30 @@ int ll_file_release(struct inode *inode, struct file *file)
        if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd)
                ll_deauthorize_statahead(inode, fd);
 
-        if (inode->i_sb->s_root == file->f_dentry) {
-                LUSTRE_FPRIVATE(file) = NULL;
-                ll_file_data_put(fd);
-                RETURN(0);
-        }
+       if (inode->i_sb->s_root == file->f_path.dentry) {
+               LUSTRE_FPRIVATE(file) = NULL;
+               ll_file_data_put(fd);
+               RETURN(0);
+       }
 
-        if (!S_ISDIR(inode->i_mode)) {
+       if (!S_ISDIR(inode->i_mode)) {
                if (lli->lli_clob != NULL)
                        lov_read_and_clear_async_rc(lli->lli_clob);
-                lli->lli_async_rc = 0;
-        }
+               lli->lli_async_rc = 0;
+       }
 
-        rc = ll_md_close(sbi->ll_md_exp, inode, file);
+       rc = ll_md_close(inode, file);
 
-        if (CFS_FAIL_TIMEOUT_MS(OBD_FAIL_PTLRPC_DUMP_LOG, cfs_fail_val))
-                libcfs_debug_dumplog();
+       if (CFS_FAIL_TIMEOUT_MS(OBD_FAIL_PTLRPC_DUMP_LOG, cfs_fail_val))
+               libcfs_debug_dumplog();
 
-        RETURN(rc);
+       RETURN(rc);
 }
 
 static int ll_intent_file_open(struct file *file, void *lmm, int lmmsize,
                                struct lookup_intent *itp)
 {
-       struct dentry *de = file->f_dentry;
+       struct dentry *de = file->f_path.dentry;
        struct ll_sb_info *sbi = ll_i2sbi(de->d_inode);
        struct dentry *parent = de->d_parent;
        const char *name = NULL;
@@ -463,7 +449,7 @@ static int ll_och_fill(struct obd_export *md_exp, struct lookup_intent *it,
 static int ll_local_open(struct file *file, struct lookup_intent *it,
                         struct ll_file_data *fd, struct obd_client_handle *och)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        ENTRY;
 
        LASSERT(!LUSTRE_FPRIVATE(file));
@@ -527,7 +513,7 @@ int ll_file_open(struct inode *inode, struct file *file)
        if (S_ISDIR(inode->i_mode))
                ll_authorize_statahead(inode, fd);
 
-        if (inode->i_sb->s_root == file->f_dentry) {
+       if (inode->i_sb->s_root == file->f_path.dentry) {
                 LUSTRE_FPRIVATE(file) = fd;
                 RETURN(0);
         }
@@ -585,7 +571,7 @@ restart:
                                 GOTO(out_openerr, rc);
                         }
 
-                        ll_release_openhandle(file->f_dentry, it);
+                       ll_release_openhandle(file->f_path.dentry, it);
                 }
                 (*och_usecount)++;
 
@@ -655,8 +641,6 @@ restart:
         if (!S_ISREG(inode->i_mode))
                 GOTO(out_och_free, rc);
 
-        ll_capa_open(inode);
-
        cl_lov_delay_create_clear(&file->f_flags);
        GOTO(out_och_free, rc);
 
@@ -834,7 +818,7 @@ out_close:
                it.d.lustre.it_lock_mode = 0;
                och->och_lease_handle.cookie = 0ULL;
        }
-       rc2 = ll_close_inode_openhandle(sbi->ll_md_exp, inode, och, NULL);
+       rc2 = ll_close_inode_openhandle(inode, och, 0, NULL);
        if (rc2 < 0)
                CERROR("%s: error closing file "DFID": %d\n",
                       ll_get_fsname(inode->i_sb, NULL, 0),
@@ -849,6 +833,68 @@ out:
 }
 
 /**
+ * Check whether a layout swap can be done between two inodes.
+ *
+ * \param[in] inode1  First inode to check
+ * \param[in] inode2  Second inode to check
+ *
+ * \retval 0 on success, layout swap can be performed between both inodes
+ * \retval negative error code if requirements are not met
+ */
+static int ll_check_swap_layouts_validity(struct inode *inode1,
+                                         struct inode *inode2)
+{
+       if (!S_ISREG(inode1->i_mode) || !S_ISREG(inode2->i_mode))
+               return -EINVAL;
+
+       if (inode_permission(inode1, MAY_WRITE) ||
+           inode_permission(inode2, MAY_WRITE))
+               return -EPERM;
+
+       if (inode1->i_sb != inode2->i_sb)
+               return -EXDEV;
+
+       return 0;
+}
+
+static int ll_swap_layouts_close(struct obd_client_handle *och,
+                                struct inode *inode, struct inode *inode2)
+{
+       const struct lu_fid     *fid1 = ll_inode2fid(inode);
+       const struct lu_fid     *fid2;
+       int                      rc;
+       ENTRY;
+
+       CDEBUG(D_INODE, "%s: biased close of file "DFID"\n",
+              ll_get_fsname(inode->i_sb, NULL, 0), PFID(fid1));
+
+       rc = ll_check_swap_layouts_validity(inode, inode2);
+       if (rc < 0)
+               GOTO(out_free_och, rc);
+
+       /* We now know that inode2 is a lustre inode */
+       fid2 = ll_inode2fid(inode2);
+
+       rc = lu_fid_cmp(fid1, fid2);
+       if (rc == 0)
+               GOTO(out_free_och, rc = -EINVAL);
+
+       /* Close the file and swap layouts between inode & inode2.
+        * NB: lease lock handle is released in mdc_close_layout_swap_pack()
+        * because we still need it to pack l_remote_handle to MDT. */
+       rc = ll_close_inode_openhandle(inode, och, MDS_CLOSE_LAYOUT_SWAP,
+                                      inode2);
+
+       och = NULL; /* freed in ll_close_inode_openhandle() */
+
+out_free_och:
+       if (och != NULL)
+               OBD_FREE_PTR(och);
+
+       RETURN(rc);
+}
+
+/**
  * Release lease and close the file.
  * It will check if the lease has ever broken.
  */
@@ -876,8 +922,7 @@ static int ll_lease_close(struct obd_client_handle *och, struct inode *inode,
        if (lease_broken != NULL)
                *lease_broken = cancelled;
 
-       rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, inode, och,
-                                      NULL);
+       rc = ll_close_inode_openhandle(inode, och, 0, NULL);
        RETURN(rc);
 }
 
@@ -966,7 +1011,7 @@ static bool file_is_noatime(const struct file *file)
 
 static void ll_io_init(struct cl_io *io, const struct file *file, int write)
 {
-        struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
 
         io->u.ci_rw.crw_nonblock = file->f_flags & O_NONBLOCK;
        if (write) {
@@ -993,7 +1038,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
                   loff_t *ppos, size_t count)
 {
        struct vvp_io           *vio = vvp_env_io(env);
-       struct inode            *inode = file->f_dentry->d_inode;
+       struct inode            *inode = file->f_path.dentry->d_inode;
        struct ll_inode_info    *lli = ll_i2info(inode);
        struct ll_file_data     *fd  = LUSTRE_FPRIVATE(file);
        struct cl_io            *io;
@@ -1004,7 +1049,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
        ENTRY;
 
        CDEBUG(D_VFSTRACE, "file: %s, type: %d ppos: "LPU64", count: %zu\n",
-               file->f_dentry->d_name.name, iot, *ppos, count);
+               file->f_path.dentry->d_name.name, iot, *ppos, count);
 
 restart:
        io = vvp_env_thread_io(env);
@@ -1023,9 +1068,10 @@ restart:
 
                switch (vio->vui_io_subtype) {
                case IO_NORMAL:
-                       vio->vui_iov = args->u.normal.via_iov;
-                       vio->vui_nrsegs = args->u.normal.via_nrsegs;
-                       vio->vui_tot_nrsegs = vio->vui_nrsegs;
+                       vio->vui_iter = args->u.normal.via_iter;
+#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+                       vio->vui_tot_nrsegs = vio->vui_iter->nr_segs;
+#endif /* !HAVE_FILE_OPERATIONS_READ_WRITE_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
@@ -1041,7 +1087,6 @@ restart:
 
                                range_locked = true;
                        }
-                       down_read(&lli->lli_trunc_sem);
                        break;
                case IO_SPLICE:
                        vio->u.splice.vui_pipe = args->u.splice.via_pipe;
@@ -1056,8 +1101,6 @@ restart:
                rc = cl_io_loop(env, io);
                ll_cl_remove(file, env);
 
-               if (args->via_io_subtype == IO_NORMAL)
-                       up_read(&lli->lli_trunc_sem);
                if (range_locked) {
                        CDEBUG(D_VFSTRACE, "Range unlock "RL_FMT"\n",
                               RL_PARA(&range));
@@ -1075,8 +1118,10 @@ restart:
 
                /* prepare IO restart */
                if (count > 0 && args->via_io_subtype == IO_NORMAL) {
-                       args->u.normal.via_iov = vio->vui_iov;
-                       args->u.normal.via_nrsegs = vio->vui_tot_nrsegs;
+                       args->u.normal.via_iter = vio->vui_iter;
+#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+                       args->u.normal.via_iter->nr_segs = vio->vui_tot_nrsegs;
+#endif /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
                }
        }
        GOTO(out, rc);
@@ -1086,7 +1131,7 @@ out:
        if ((rc == 0 || rc == -ENODATA) && count > 0 && io->ci_need_restart) {
                CDEBUG(D_VFSTRACE,
                       "%s: restart %s from %lld, count:%zu, result: %zd\n",
-                      file->f_dentry->d_name.name,
+                      file->f_path.dentry->d_name.name,
                       iot == CIT_READ ? "read" : "write",
                       *ppos, count, result);
                goto restart;
@@ -1094,13 +1139,19 @@ out:
 
        if (iot == CIT_READ) {
                if (result > 0)
-                       ll_stats_ops_tally(ll_i2sbi(file->f_dentry->d_inode),
+                       ll_stats_ops_tally(ll_i2sbi(inode),
                                           LPROC_LL_READ_BYTES, result);
        } else if (iot == CIT_WRITE) {
                if (result > 0) {
-                       ll_stats_ops_tally(ll_i2sbi(file->f_dentry->d_inode),
+                       ll_stats_ops_tally(ll_i2sbi(inode),
                                           LPROC_LL_WRITE_BYTES, result);
                        fd->fd_write_failed = false;
+               } else if (result == 0 && rc == 0) {
+                       rc = io->ci_result;
+                       if (rc < 0)
+                               fd->fd_write_failed = true;
+                       else
+                               fd->fd_write_failed = false;
                } else if (rc != -ERESTARTSYS) {
                        fd->fd_write_failed = true;
                }
@@ -1112,79 +1163,135 @@ out:
 }
 
 /*
+ * Read from a file (through the page cache).
+ */
+static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+       struct vvp_io_args *args;
+       struct lu_env *env;
+       ssize_t result;
+       __u16 refcheck;
+
+       env = cl_env_get(&refcheck);
+       if (IS_ERR(env))
+               return PTR_ERR(env);
+
+       args = ll_env_args(env, IO_NORMAL);
+       args->u.normal.via_iter = to;
+       args->u.normal.via_iocb = iocb;
+
+       result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ,
+                                   &iocb->ki_pos, iov_iter_count(to));
+       cl_env_put(env, &refcheck);
+       return result;
+}
+
+/*
+ * Write to a file (through the page cache).
+ */
+static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+       struct vvp_io_args *args;
+       struct lu_env *env;
+       ssize_t result;
+       __u16 refcheck;
+
+       env = cl_env_get(&refcheck);
+       if (IS_ERR(env))
+               return PTR_ERR(env);
+
+       args = ll_env_args(env, IO_NORMAL);
+       args->u.normal.via_iter = from;
+       args->u.normal.via_iocb = iocb;
+
+       result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_WRITE,
+                                   &iocb->ki_pos, iov_iter_count(from));
+       cl_env_put(env, &refcheck);
+       return result;
+}
+
+#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+/*
  * XXX: exact copy from kernel code (__generic_file_aio_write_nolock)
  */
 static int ll_file_get_iov_count(const struct iovec *iov,
-                                 unsigned long *nr_segs, size_t *count)
+                                unsigned long *nr_segs, size_t *count)
 {
-        size_t cnt = 0;
-        unsigned long seg;
+       size_t cnt = 0;
+       unsigned long seg;
 
-        for (seg = 0; seg < *nr_segs; seg++) {
-                const struct iovec *iv = &iov[seg];
+       for (seg = 0; seg < *nr_segs; seg++) {
+               const struct iovec *iv = &iov[seg];
 
-                /*
-                 * If any segment has a negative length, or the cumulative
-                 * length ever wraps negative then return -EINVAL.
-                 */
-                cnt += iv->iov_len;
-                if (unlikely((ssize_t)(cnt|iv->iov_len) < 0))
-                        return -EINVAL;
-                if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
-                        continue;
-                if (seg == 0)
-                        return -EFAULT;
-                *nr_segs = seg;
-                cnt -= iv->iov_len;   /* This segment is no good */
-                break;
-        }
-        *count = cnt;
-        return 0;
+               /*
+                * If any segment has a negative length, or the cumulative
+                * length ever wraps negative then return -EINVAL.
+                */
+               cnt += iv->iov_len;
+               if (unlikely((ssize_t)(cnt|iv->iov_len) < 0))
+                       return -EINVAL;
+               if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
+                       continue;
+               if (seg == 0)
+                       return -EFAULT;
+               *nr_segs = seg;
+               cnt -= iv->iov_len;     /* This segment is no good */
+               break;
+       }
+       *count = cnt;
+       return 0;
 }
 
 static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos)
 {
-       struct lu_env      *env;
-       struct vvp_io_args *args;
-       struct iovec       *local_iov;
-        size_t              count;
-        ssize_t             result;
-        int                 refcheck;
-        ENTRY;
+       struct iovec *local_iov;
+       struct iov_iter *to;
+       size_t iov_count;
+       ssize_t result;
+       struct lu_env *env = NULL;
+       __u16 refcheck;
+       ENTRY;
 
-        result = ll_file_get_iov_count(iov, &nr_segs, &count);
-        if (result)
-                RETURN(result);
-
-        env = cl_env_get(&refcheck);
-        if (IS_ERR(env))
-                RETURN(PTR_ERR(env));
+       result = ll_file_get_iov_count(iov, &nr_segs, &iov_count);
+       if (result)
+               RETURN(result);
 
        if (nr_segs == 1) {
+
+               env = cl_env_get(&refcheck);
+               if (IS_ERR(env))
+                       RETURN(PTR_ERR(env));
+
                local_iov = &ll_env_info(env)->lti_local_iov;
                *local_iov = *iov;
+
        } else {
                OBD_ALLOC(local_iov, sizeof(*iov) * nr_segs);
-               if (local_iov == NULL) {
-                       cl_env_put(env, &refcheck);
+               if (local_iov == NULL)
                        RETURN(-ENOMEM);
-               }
 
                memcpy(local_iov, iov, sizeof(*iov) * nr_segs);
        }
 
-       args = ll_env_args(env, IO_NORMAL);
-       args->u.normal.via_iov = local_iov;
-       args->u.normal.via_nrsegs = nr_segs;
-       args->u.normal.via_iocb = iocb;
-
-       result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ,
-                                   &iocb->ki_pos, count);
+       OBD_ALLOC_PTR(to);
+       if (to == NULL) {
+               result = -ENOMEM;
+               goto out;
+       }
+# ifdef HAVE_IOV_ITER_INIT_DIRECTION
+       iov_iter_init(to, READ, local_iov, nr_segs, iov_count);
+# else /* !HAVE_IOV_ITER_INIT_DIRECTION */
+       iov_iter_init(to, local_iov, nr_segs, iov_count, 0);
+# endif /* HAVE_IOV_ITER_INIT_DIRECTION */
 
-       cl_env_put(env, &refcheck);
+       result = ll_file_read_iter(iocb, to);
 
-       if (nr_segs > 1)
+       OBD_FREE_PTR(to);
+out:
+       if (nr_segs == 1)
+               cl_env_put(env, &refcheck);
+       else
                OBD_FREE(local_iov, sizeof(*iov) * nr_segs);
 
        RETURN(result);
@@ -1197,7 +1304,7 @@ static ssize_t ll_file_read(struct file *file, char __user *buf, size_t count,
        struct iovec   iov = { .iov_base = buf, .iov_len = count };
         struct kiocb  *kiocb;
         ssize_t        result;
-        int            refcheck;
+       __u16          refcheck;
         ENTRY;
 
         env = cl_env_get(&refcheck);
@@ -1208,9 +1315,9 @@ static ssize_t ll_file_read(struct file *file, char __user *buf, size_t count,
         init_sync_kiocb(kiocb, file);
         kiocb->ki_pos = *ppos;
 #ifdef HAVE_KIOCB_KI_LEFT
-        kiocb->ki_left = count;
-#else
-        kiocb->ki_nbytes = count;
+       kiocb->ki_left = count;
+#elif defined(HAVE_KI_NBYTES)
+       kiocb->ki_nbytes = count;
 #endif
 
        result = ll_file_aio_read(kiocb, &iov, 1, kiocb->ki_pos);
@@ -1227,45 +1334,51 @@ static ssize_t ll_file_read(struct file *file, char __user *buf, size_t count,
 static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                                 unsigned long nr_segs, loff_t pos)
 {
-       struct lu_env      *env;
-       struct vvp_io_args *args;
-       struct iovec       *local_iov;
-        size_t              count;
-        ssize_t             result;
-        int                 refcheck;
-        ENTRY;
+       struct iovec *local_iov;
+       struct iov_iter *from;
+       size_t iov_count;
+       ssize_t result;
+       struct lu_env *env = NULL;
+       __u16 refcheck;
+       ENTRY;
 
-        result = ll_file_get_iov_count(iov, &nr_segs, &count);
-        if (result)
-                RETURN(result);
-
-        env = cl_env_get(&refcheck);
-        if (IS_ERR(env))
-                RETURN(PTR_ERR(env));
+       result = ll_file_get_iov_count(iov, &nr_segs, &iov_count);
+       if (result)
+               RETURN(result);
 
        if (nr_segs == 1) {
+               env = cl_env_get(&refcheck);
+               if (IS_ERR(env))
+                       RETURN(PTR_ERR(env));
+
                local_iov = &ll_env_info(env)->lti_local_iov;
                *local_iov = *iov;
        } else {
                OBD_ALLOC(local_iov, sizeof(*iov) * nr_segs);
-               if (local_iov == NULL) {
-                       cl_env_put(env, &refcheck);
+               if (local_iov == NULL)
                        RETURN(-ENOMEM);
-               }
 
                memcpy(local_iov, iov, sizeof(*iov) * nr_segs);
        }
 
-       args = ll_env_args(env, IO_NORMAL);
-       args->u.normal.via_iov = local_iov;
-       args->u.normal.via_nrsegs = nr_segs;
-       args->u.normal.via_iocb = iocb;
+       OBD_ALLOC_PTR(from);
+       if (from == NULL) {
+               result = -ENOMEM;
+               goto out;
+       }
+# ifdef HAVE_IOV_ITER_INIT_DIRECTION
+       iov_iter_init(from, WRITE, local_iov, nr_segs, iov_count);
+# else /* !HAVE_IOV_ITER_INIT_DIRECTION */
+       iov_iter_init(from, local_iov, nr_segs, iov_count, 0);
+# endif /* HAVE_IOV_ITER_INIT_DIRECTION */
 
-       result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_WRITE,
-                                 &iocb->ki_pos, count);
-       cl_env_put(env, &refcheck);
+       result = ll_file_write_iter(iocb, from);
 
-       if (nr_segs > 1)
+       OBD_FREE_PTR(from);
+out:
+       if (nr_segs == 1)
+               cl_env_put(env, &refcheck);
+       else
                OBD_FREE(local_iov, sizeof(*iov) * nr_segs);
 
        RETURN(result);
@@ -1279,7 +1392,7 @@ static ssize_t ll_file_write(struct file *file, const char __user *buf,
                               .iov_len = count };
         struct kiocb  *kiocb;
         ssize_t        result;
-        int            refcheck;
+       __u16          refcheck;
         ENTRY;
 
         env = cl_env_get(&refcheck);
@@ -1290,9 +1403,9 @@ static ssize_t ll_file_write(struct file *file, const char __user *buf,
         init_sync_kiocb(kiocb, file);
         kiocb->ki_pos = *ppos;
 #ifdef HAVE_KIOCB_KI_LEFT
-        kiocb->ki_left = count;
-#else
-        kiocb->ki_nbytes = count;
+       kiocb->ki_left = count;
+#elif defined(HAVE_KI_NBYTES)
+       kiocb->ki_nbytes = count;
 #endif
 
        result = ll_file_aio_write(kiocb, &iov, 1, kiocb->ki_pos);
@@ -1301,6 +1414,7 @@ static ssize_t ll_file_write(struct file *file, const char __user *buf,
        cl_env_put(env, &refcheck);
        RETURN(result);
 }
+#endif /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
 
 /*
  * Send file content (through pagecache) somewhere with helper
@@ -1312,7 +1426,7 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos,
         struct lu_env      *env;
         struct vvp_io_args *args;
         ssize_t             result;
-        int                 refcheck;
+       __u16               refcheck;
         ENTRY;
 
         env = cl_env_get(&refcheck);
@@ -1344,7 +1458,7 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file,
        if (rc < 0)
                GOTO(out_unlock, rc);
 
-       ll_release_openhandle(file->f_dentry, &oit);
+       ll_release_openhandle(file->f_path.dentry, &oit);
 
 out_unlock:
        ll_inode_size_unlock(inode);
@@ -1471,7 +1585,7 @@ static int ll_file_getstripe(struct inode *inode,
                             struct lov_user_md __user *lum)
 {
        struct lu_env   *env;
-       int             refcheck;
+       __u16           refcheck;
        int             rc;
        ENTRY;
 
@@ -1628,8 +1742,7 @@ int ll_release_openhandle(struct dentry *dentry, struct lookup_intent *it)
 
        ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och);
 
-        rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp,
-                                      inode, och, NULL);
+       rc = ll_close_inode_openhandle(inode, och, 0, NULL);
 out:
        /* this one is in place of ll_file_open */
        if (it_disposition(it, DISP_ENQ_OPEN_REF)) {
@@ -1649,9 +1762,9 @@ static int ll_do_fiemap(struct inode *inode, struct fiemap *fiemap,
                        size_t num_bytes)
 {
        struct lu_env                   *env;
-       int                             refcheck;
+       __u16                           refcheck;
        int                             rc = 0;
-       struct ll_fiemap_info_key       fmkey = { .name = KEY_FIEMAP, };
+       struct ll_fiemap_info_key       fmkey = { .lfik_name = KEY_FIEMAP, };
        ENTRY;
 
        /* Checks for fiemap flags */
@@ -1677,17 +1790,17 @@ static int ll_do_fiemap(struct inode *inode, struct fiemap *fiemap,
                        GOTO(out, rc);
        }
 
-       fmkey.oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
-       obdo_from_inode(&fmkey.oa, inode, OBD_MD_FLSIZE);
-       obdo_set_parent_fid(&fmkey.oa, &ll_i2info(inode)->lli_fid);
+       fmkey.lfik_oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
+       obdo_from_inode(&fmkey.lfik_oa, inode, OBD_MD_FLSIZE);
+       obdo_set_parent_fid(&fmkey.lfik_oa, &ll_i2info(inode)->lli_fid);
 
        /* If filesize is 0, then there would be no objects for mapping */
-       if (fmkey.oa.o_size == 0) {
+       if (fmkey.lfik_oa.o_size == 0) {
                fiemap->fm_mapped_extents = 0;
                GOTO(out, rc = 0);
        }
 
-       fmkey.fiemap = *fiemap;
+       fmkey.lfik_fiemap = *fiemap;
 
        rc = cl_object_fiemap(env, ll_i2info(inode)->lli_clob,
                              &fmkey, fiemap, &num_bytes);
@@ -1739,61 +1852,6 @@ gf_free:
        RETURN(rc);
 }
 
-static int ll_ioctl_fiemap(struct inode *inode, struct fiemap __user *arg)
-{
-       struct fiemap   *fiemap;
-       size_t          num_bytes;
-       size_t          ret_bytes;
-       __u32           extent_count;
-       int             rc = 0;
-
-       /* Get the extent count so we can calculate the size of
-        * required fiemap buffer */
-       if (get_user(extent_count, &arg->fm_extent_count))
-               RETURN(-EFAULT);
-
-       if (extent_count >=
-           (SIZE_MAX - sizeof(*fiemap)) / sizeof(struct ll_fiemap_extent))
-               RETURN(-EINVAL);
-       num_bytes = sizeof(*fiemap) + (extent_count *
-                                      sizeof(struct ll_fiemap_extent));
-
-       OBD_ALLOC_LARGE(fiemap, num_bytes);
-       if (fiemap == NULL)
-               RETURN(-ENOMEM);
-
-       /* get the fiemap value */
-       if (copy_from_user(fiemap, arg, sizeof(*fiemap)))
-               GOTO(error, rc = -EFAULT);
-
-       /* If fm_extent_count is non-zero, read the first extent since
-        * it is used to calculate end_offset and device from previous
-        * fiemap call. */
-       if (extent_count != 0) {
-               if (copy_from_user(&fiemap->fm_extents[0],
-                                  (char __user *)arg + sizeof(*fiemap),
-                                  sizeof(struct ll_fiemap_extent)))
-                       GOTO(error, rc = -EFAULT);
-       }
-
-       rc = ll_do_fiemap(inode, fiemap, num_bytes);
-       if (rc)
-               GOTO(error, rc);
-
-       ret_bytes = sizeof(struct fiemap);
-
-       if (extent_count != 0)
-               ret_bytes += (fiemap->fm_mapped_extents *
-                                sizeof(struct ll_fiemap_extent));
-
-       if (copy_to_user((void __user *)arg, fiemap, ret_bytes))
-               rc = -EFAULT;
-
-error:
-       OBD_FREE_LARGE(fiemap, num_bytes);
-       RETURN(rc);
-}
-
 /*
  * Read the data_version for inode.
  *
@@ -1810,7 +1868,7 @@ int ll_data_version(struct inode *inode, __u64 *data_version, int flags)
        struct cl_object *obj = ll_i2info(inode)->lli_clob;
        struct lu_env *env;
        struct cl_io *io;
-       int refcheck;
+       __u16  refcheck;
        int result;
 
        ENTRY;
@@ -1883,7 +1941,7 @@ int ll_hsm_release(struct inode *inode)
        /* Release the file.
         * NB: lease lock handle is released in mdc_hsm_release_pack() because
         * we still need it to pack l_remote_handle to MDT. */
-       rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, inode, och,
+       rc = ll_close_inode_openhandle(inode, och, MDS_HSM_RELEASE,
                                       &data_version);
        och = NULL;
 
@@ -1896,10 +1954,12 @@ out:
 }
 
 struct ll_swap_stack {
-       struct iattr             ia1, ia2;
-       __u64                    dv1, dv2;
-       struct inode            *inode1, *inode2;
-       bool                     check_dv1, check_dv2;
+       __u64                    dv1;
+       __u64                    dv2;
+       struct inode            *inode1;
+       struct inode            *inode2;
+       bool                     check_dv1;
+       bool                     check_dv2;
 };
 
 static int ll_swap_layouts(struct file *file1, struct file *file2,
@@ -1916,18 +1976,12 @@ static int ll_swap_layouts(struct file *file1, struct file *file2,
        if (llss == NULL)
                RETURN(-ENOMEM);
 
-       llss->inode1 = file1->f_dentry->d_inode;
-       llss->inode2 = file2->f_dentry->d_inode;
+       llss->inode1 = file1->f_path.dentry->d_inode;
+       llss->inode2 = file2->f_path.dentry->d_inode;
 
-       if (!S_ISREG(llss->inode2->i_mode))
-               GOTO(free, rc = -EINVAL);
-
-       if (inode_permission(llss->inode1, MAY_WRITE) ||
-           inode_permission(llss->inode2, MAY_WRITE))
-               GOTO(free, rc = -EPERM);
-
-       if (llss->inode2->i_sb != llss->inode1->i_sb)
-               GOTO(free, rc = -EXDEV);
+       rc = ll_check_swap_layouts_validity(llss->inode1, llss->inode2);
+       if (rc < 0)
+               GOTO(free, rc);
 
        /* we use 2 bool because it is easier to swap than 2 bits */
        if (lsl->sl_flags & SWAP_LAYOUTS_CHECK_DV1)
@@ -1942,7 +1996,7 @@ static int ll_swap_layouts(struct file *file1, struct file *file2,
 
        rc = lu_fid_cmp(ll_inode2fid(llss->inode1), ll_inode2fid(llss->inode2));
        if (rc == 0) /* same file, done! */
-               GOTO(free, rc = 0);
+               GOTO(free, rc);
 
        if (rc < 0) { /* sequentialize it */
                swap(llss->inode1, llss->inode2);
@@ -1964,18 +2018,6 @@ static int ll_swap_layouts(struct file *file1, struct file *file2,
                }
        }
 
-       /* to be able to restore mtime and atime after swap
-        * we need to first save them */
-       if (lsl->sl_flags &
-           (SWAP_LAYOUTS_KEEP_MTIME | SWAP_LAYOUTS_KEEP_ATIME)) {
-               llss->ia1.ia_mtime = llss->inode1->i_mtime;
-               llss->ia1.ia_atime = llss->inode1->i_atime;
-               llss->ia1.ia_valid = ATTR_MTIME | ATTR_ATIME;
-               llss->ia2.ia_mtime = llss->inode2->i_mtime;
-               llss->ia2.ia_atime = llss->inode2->i_atime;
-               llss->ia2.ia_valid = ATTR_MTIME | ATTR_ATIME;
-       }
-
        /* ultimate check, before swaping the layouts we check if
         * dataversion has changed (if requested) */
        if (llss->check_dv1) {
@@ -2010,45 +2052,15 @@ static int ll_swap_layouts(struct file *file1, struct file *file2,
                           sizeof(*op_data), op_data, NULL);
        ll_finish_md_op_data(op_data);
 
+       if (rc < 0)
+               GOTO(putgl, rc);
+
 putgl:
        if (gid != 0) {
                ll_put_grouplock(llss->inode2, file2, gid);
                ll_put_grouplock(llss->inode1, file1, gid);
        }
 
-       /* rc can be set from obd_iocontrol() or from a GOTO(putgl, ...) */
-       if (rc != 0)
-               GOTO(free, rc);
-
-       /* clear useless flags */
-       if (!(lsl->sl_flags & SWAP_LAYOUTS_KEEP_MTIME)) {
-               llss->ia1.ia_valid &= ~ATTR_MTIME;
-               llss->ia2.ia_valid &= ~ATTR_MTIME;
-       }
-
-       if (!(lsl->sl_flags & SWAP_LAYOUTS_KEEP_ATIME)) {
-               llss->ia1.ia_valid &= ~ATTR_ATIME;
-               llss->ia2.ia_valid &= ~ATTR_ATIME;
-       }
-
-       /* update time if requested */
-       rc = 0;
-       if (llss->ia2.ia_valid != 0) {
-               mutex_lock(&llss->inode1->i_mutex);
-               rc = ll_setattr(file1->f_dentry, &llss->ia2);
-               mutex_unlock(&llss->inode1->i_mutex);
-       }
-
-       if (llss->ia1.ia_valid != 0) {
-               int rc1;
-
-               mutex_lock(&llss->inode2->i_mutex);
-               rc1 = ll_setattr(file2->f_dentry, &llss->ia1);
-               mutex_unlock(&llss->inode2->i_mutex);
-               if (rc == 0)
-                       rc = rc1;
-       }
-
 free:
        if (llss != NULL)
                OBD_FREE_PTR(llss);
@@ -2056,7 +2068,7 @@ free:
        RETURN(rc);
 }
 
-static int ll_hsm_state_set(struct inode *inode, struct hsm_state_set *hss)
+int ll_hsm_state_set(struct inode *inode, struct hsm_state_set *hss)
 {
        struct md_op_data       *op_data;
        int                      rc;
@@ -2134,7 +2146,7 @@ static int ll_hsm_import(struct inode *inode, struct file *file,
 
        mutex_lock(&inode->i_mutex);
 
-       rc = ll_setattr_raw(file->f_dentry, attr, true);
+       rc = ll_setattr_raw(file->f_path.dentry, attr, true);
        if (rc == -ENODATA)
                rc = 0;
 
@@ -2156,10 +2168,46 @@ static inline long ll_lease_type_from_fmode(fmode_t fmode)
               ((fmode & FMODE_WRITE) ? LL_LEASE_WRLCK : 0);
 }
 
+static int ll_file_futimes_3(struct file *file, const struct ll_futimes_3 *lfu)
+{
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct iattr ia = {
+               .ia_valid = ATTR_ATIME | ATTR_ATIME_SET |
+                           ATTR_MTIME | ATTR_MTIME_SET |
+                           ATTR_CTIME | ATTR_CTIME_SET,
+               .ia_atime = {
+                       .tv_sec = lfu->lfu_atime_sec,
+                       .tv_nsec = lfu->lfu_atime_nsec,
+               },
+               .ia_mtime = {
+                       .tv_sec = lfu->lfu_mtime_sec,
+                       .tv_nsec = lfu->lfu_mtime_nsec,
+               },
+               .ia_ctime = {
+                       .tv_sec = lfu->lfu_ctime_sec,
+                       .tv_nsec = lfu->lfu_ctime_nsec,
+               },
+       };
+       int rc;
+       ENTRY;
+
+       if (!capable(CAP_SYS_ADMIN))
+               RETURN(-EPERM);
+
+       if (!S_ISREG(inode->i_mode))
+               RETURN(-EINVAL);
+
+       mutex_lock(&inode->i_mutex);
+       rc = ll_setattr_raw(file->f_path.dentry, &ia, false);
+       mutex_unlock(&inode->i_mutex);
+
+       RETURN(rc);
+}
+
 static long
 ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct inode            *inode = file->f_dentry->d_inode;
+       struct inode            *inode = file->f_path.dentry->d_inode;
        struct ll_file_data     *fd = LUSTRE_FPRIVATE(file);
        int                      flags, rc;
        ENTRY;
@@ -2210,24 +2258,46 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                       sizeof(struct lustre_swap_layouts)))
                        RETURN(-EFAULT);
 
-               if ((file->f_flags & O_ACCMODE) == 0) /* O_RDONLY */
+               if ((file->f_flags & O_ACCMODE) == O_RDONLY)
                        RETURN(-EPERM);
 
                file2 = fget(lsl.sl_fd);
                if (file2 == NULL)
                        RETURN(-EBADF);
 
-               rc = -EPERM;
-               if ((file2->f_flags & O_ACCMODE) != 0) /* O_WRONLY or O_RDWR */
+               /* O_WRONLY or O_RDWR */
+               if ((file2->f_flags & O_ACCMODE) == O_RDONLY)
+                       GOTO(out, rc = -EPERM);
+
+               if (lsl.sl_flags & SWAP_LAYOUTS_CLOSE) {
+                       struct inode                    *inode2;
+                       struct ll_inode_info            *lli;
+                       struct obd_client_handle        *och = NULL;
+
+                       if (lsl.sl_flags != SWAP_LAYOUTS_CLOSE)
+                               GOTO(out, rc = -EINVAL);
+
+                       lli = ll_i2info(inode);
+                       mutex_lock(&lli->lli_och_mutex);
+                       if (fd->fd_lease_och != NULL) {
+                               och = fd->fd_lease_och;
+                               fd->fd_lease_och = NULL;
+                       }
+                       mutex_unlock(&lli->lli_och_mutex);
+                       if (och == NULL)
+                               GOTO(out, rc = -ENOLCK);
+                       inode2 = file2->f_path.dentry->d_inode;
+                       rc = ll_swap_layouts_close(och, inode, inode2);
+               } else {
                        rc = ll_swap_layouts(file, file2, &lsl);
+               }
+out:
                fput(file2);
                RETURN(rc);
        }
        case LL_IOC_LOV_GETSTRIPE:
                RETURN(ll_file_getstripe(inode,
                                         (struct lov_user_md __user *)arg));
-       case FSFILT_IOC_FIEMAP:
-               RETURN(ll_ioctl_fiemap(inode, (struct fiemap __user *)arg));
         case FSFILT_IOC_GETFLAGS:
         case FSFILT_IOC_SETFLAGS:
                 RETURN(ll_iocontrol(inode, file, cmd, arg));
@@ -2465,7 +2535,16 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                OBD_FREE_PTR(hui);
                RETURN(rc);
        }
+       case LL_IOC_FUTIMES_3: {
+               struct ll_futimes_3 lfu;
 
+               if (copy_from_user(&lfu,
+                                  (const struct ll_futimes_3 __user *)arg,
+                                  sizeof(lfu)))
+                       RETURN(-EFAULT);
+
+               RETURN(ll_file_futimes_3(file, &lfu));
+       }
        default: {
                int err;
 
@@ -2499,7 +2578,7 @@ static loff_t
 generic_file_llseek_size(struct file *file, loff_t offset, int origin,
                 loff_t maxsize, loff_t eof)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
 
        switch (origin) {
        case SEEK_END:
@@ -2548,7 +2627,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int origin,
 
 static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        loff_t retval, eof = 0;
 
        ENTRY;
@@ -2573,7 +2652,7 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
 
 static int ll_flush(struct file *file, fl_owner_t id)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct ll_inode_info *lli = ll_i2info(inode);
        struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
        int rc, err;
@@ -2609,7 +2688,6 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end,
        struct cl_env_nest nest;
        struct lu_env *env;
        struct cl_io *io;
-       struct obd_capa *capa = NULL;
        struct cl_fsync_io *fio;
        int result;
        ENTRY;
@@ -2622,15 +2700,12 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end,
        if (IS_ERR(env))
                RETURN(PTR_ERR(env));
 
-       capa = ll_osscapa_get(inode, CAPA_OPC_OSS_WRITE);
-
        io = vvp_env_thread_io(env);
        io->ci_obj = ll_i2info(inode)->lli_clob;
        io->ci_ignore_layout = ignore_layout;
 
        /* initialize parameters for sync */
        fio = &io->u.ci_fsync;
-       fio->fi_capa = capa;
        fio->fi_start = start;
        fio->fi_end = end;
        fio->fi_fid = ll_inode2fid(inode);
@@ -2646,25 +2721,23 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end,
        cl_io_fini(env, io);
        cl_env_nested_put(&nest, env);
 
-       capa_put(capa);
-
        RETURN(result);
 }
 
 /*
- * When dentry is provided (the 'else' case), *file->f_dentry may be
+ * When dentry is provided (the 'else' case), *file->f_path.dentry may be
  * null and dentry must be used directly rather than pulled from
- * *file->f_dentry as is done otherwise.
+ * *file->f_path.dentry as is done otherwise.
  */
 
 #ifdef HAVE_FILE_FSYNC_4ARGS
 int ll_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
 #elif defined(HAVE_FILE_FSYNC_2ARGS)
 int ll_fsync(struct file *file, int datasync)
 {
-       struct dentry *dentry = file->f_dentry;
+       struct dentry *dentry = file->f_path.dentry;
        loff_t start = 0;
        loff_t end = LLONG_MAX;
 #else
@@ -2676,7 +2749,6 @@ int ll_fsync(struct file *file, struct dentry *dentry, int datasync)
        struct inode *inode = dentry->d_inode;
        struct ll_inode_info *lli = ll_i2info(inode);
        struct ptlrpc_request *req;
-       struct obd_capa *oc;
        int rc, err;
        ENTRY;
 
@@ -2705,10 +2777,7 @@ int ll_fsync(struct file *file, struct dentry *dentry, int datasync)
                        rc = err;
        }
 
-       oc = ll_mdscapa_get(inode);
-       err = md_fsync(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode), oc,
-                      &req);
-       capa_put(oc);
+       err = md_fsync(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode), &req);
        if (!rc)
                rc = err;
        if (!err)
@@ -2735,7 +2804,7 @@ int ll_fsync(struct file *file, struct dentry *dentry, int datasync)
 static int
 ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct ldlm_enqueue_info einfo = {
                .ei_type        = LDLM_FLOCK,
@@ -2743,8 +2812,8 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
                .ei_cbdata      = file_lock,
        };
        struct md_op_data *op_data;
-       struct lustre_handle lockh = {0};
-       ldlm_policy_data_t flock = {{0}};
+       struct lustre_handle lockh = { 0 };
+       union ldlm_policy_data flock = { { 0 } };
        int fl_type = file_lock->fl_type;
        __u64 flags = 0;
        int rc;
@@ -2870,7 +2939,8 @@ ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 }
 
 int ll_get_fid_by_name(struct inode *parent, const char *name,
-                      int namelen, struct lu_fid *fid)
+                      int namelen, struct lu_fid *fid,
+                      struct inode **inode)
 {
        struct md_op_data       *op_data = NULL;
        struct mdt_body         *body;
@@ -2883,7 +2953,7 @@ int ll_get_fid_by_name(struct inode *parent, const char *name,
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));
 
-       op_data->op_valid = OBD_MD_FLID;
+       op_data->op_valid = OBD_MD_FLID | OBD_MD_FLTYPE;
        rc = md_getattr_name(ll_i2sbi(parent)->ll_md_exp, op_data, &req);
        ll_finish_md_op_data(op_data);
        if (rc < 0)
@@ -2894,6 +2964,9 @@ int ll_get_fid_by_name(struct inode *parent, const char *name,
                GOTO(out_req, rc = -EFAULT);
        if (fid != NULL)
                *fid = body->mbo_fid1;
+
+       if (inode != NULL)
+               rc = ll_prep_inode(inode, req, parent->i_sb, NULL);
 out_req:
        ptlrpc_req_finished(req);
        RETURN(rc);
@@ -2906,8 +2979,11 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
        struct inode          *child_inode = NULL;
        struct md_op_data     *op_data;
        struct ptlrpc_request *request = NULL;
+       struct obd_client_handle *och = NULL;
        struct qstr           qstr;
+       struct mdt_body         *body;
        int                    rc;
+       __u64                   data_version = 0;
        ENTRY;
 
        CDEBUG(D_VFSTRACE, "migrate %s under "DFID" to MDT%04x\n",
@@ -2922,39 +2998,60 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
        qstr.hash = full_name_hash(name, namelen);
        qstr.name = name;
        qstr.len = namelen;
-       dchild = d_lookup(file->f_dentry, &qstr);
+       dchild = d_lookup(file->f_path.dentry, &qstr);
        if (dchild != NULL) {
-               if (dchild->d_inode != NULL) {
+               if (dchild->d_inode != NULL)
                        child_inode = igrab(dchild->d_inode);
-                       if (child_inode != NULL) {
-                               mutex_lock(&child_inode->i_mutex);
-                               op_data->op_fid3 = *ll_inode2fid(child_inode);
-                               ll_invalidate_aliases(child_inode);
-                       }
-               }
                dput(dchild);
-       } else {
+       }
+
+       if (child_inode == NULL) {
                rc = ll_get_fid_by_name(parent, name, namelen,
-                                       &op_data->op_fid3);
+                                       &op_data->op_fid3, &child_inode);
                if (rc != 0)
                        GOTO(out_free, rc);
        }
 
+       if (child_inode == NULL)
+               GOTO(out_free, rc = -EINVAL);
+
+       mutex_lock(&child_inode->i_mutex);
+       op_data->op_fid3 = *ll_inode2fid(child_inode);
        if (!fid_is_sane(&op_data->op_fid3)) {
-               CERROR("%s: migrate %s , but fid "DFID" is insane\n",
+               CERROR("%s: migrate %s, but FID "DFID" is insane\n",
                       ll_get_fsname(parent->i_sb, NULL, 0), name,
                       PFID(&op_data->op_fid3));
-               GOTO(out_free, rc = -EINVAL);
+               GOTO(out_unlock, rc = -EINVAL);
        }
 
        rc = ll_get_mdt_idx_by_fid(ll_i2sbi(parent), &op_data->op_fid3);
        if (rc < 0)
-               GOTO(out_free, rc);
+               GOTO(out_unlock, rc);
 
        if (rc == mdtidx) {
-               CDEBUG(D_INFO, "%s:"DFID" is already on MDT%d.\n", name,
+               CDEBUG(D_INFO, "%s: "DFID" is already on MDT%04x\n", name,
                       PFID(&op_data->op_fid3), mdtidx);
-               GOTO(out_free, rc = 0);
+               GOTO(out_unlock, rc = 0);
+       }
+again:
+       if (S_ISREG(child_inode->i_mode)) {
+               och = ll_lease_open(child_inode, NULL, FMODE_WRITE, 0);
+               if (IS_ERR(och)) {
+                       rc = PTR_ERR(och);
+                       och = NULL;
+                       GOTO(out_unlock, rc);
+               }
+
+               rc = ll_data_version(child_inode, &data_version,
+                                    LL_DV_WR_FLUSH);
+               if (rc != 0)
+                       GOTO(out_close, rc);
+
+               op_data->op_handle = och->och_fh;
+               op_data->op_data = och->och_mod;
+               op_data->op_data_version = data_version;
+               op_data->op_lease_handle = och->och_lease_handle;
+               op_data->op_bias |= MDS_RENAME_MIGRATE;
        }
 
        op_data->op_mds = mdtidx;
@@ -2964,17 +3061,41 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
        if (rc == 0)
                ll_update_times(request, parent);
 
-       ptlrpc_req_finished(request);
-       if (rc != 0)
-               GOTO(out_free, rc);
+       if (request != NULL) {
+               body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY);
+               if (body == NULL) {
+                       ptlrpc_req_finished(request);
+                       GOTO(out_close, rc = -EPROTO);
+               }
 
-out_free:
-       if (child_inode != NULL) {
-               clear_nlink(child_inode);
-               mutex_unlock(&child_inode->i_mutex);
-               iput(child_inode);
+               /* If the server does release layout lock, then we cleanup
+                * the client och here, otherwise release it in out_close: */
+               if (och != NULL &&
+                   body->mbo_valid & OBD_MD_CLOSE_INTENT_EXECED) {
+                       obd_mod_put(och->och_mod);
+                       md_clear_open_replay_data(ll_i2sbi(parent)->ll_md_exp,
+                                                 och);
+                       och->och_fh.cookie = DEAD_HANDLE_MAGIC;
+                       OBD_FREE_PTR(och);
+                       och = NULL;
+               }
+               ptlrpc_req_finished(request);
        }
 
+       /* Try again if the file layout has changed. */
+       if (rc == -EAGAIN && S_ISREG(child_inode->i_mode)) {
+               request = NULL;
+               goto again;
+       }
+out_close:
+       if (och != NULL) /* close the file */
+               ll_lease_close(och, child_inode, NULL);
+       if (rc == 0)
+               clear_nlink(child_inode);
+out_unlock:
+       mutex_unlock(&child_inode->i_mutex);
+       iput(child_inode);
+out_free:
        ll_finish_md_op_data(op_data);
        RETURN(rc);
 }
@@ -2997,16 +3118,16 @@ ll_file_noflock(struct file *file, int cmd, struct file_lock *file_lock)
  * \param l_req_mode [IN] searched lock mode
  * \retval boolean, true iff all bits are found
  */
-int ll_have_md_lock(struct inode *inode, __u64 *bits,  ldlm_mode_t l_req_mode)
+int ll_have_md_lock(struct inode *inode, __u64 *bits, enum ldlm_mode l_req_mode)
 {
-        struct lustre_handle lockh;
-        ldlm_policy_data_t policy;
-        ldlm_mode_t mode = (l_req_mode == LCK_MINMODE) ?
-                                (LCK_CR|LCK_CW|LCK_PR|LCK_PW) : l_req_mode;
-        struct lu_fid *fid;
+       struct lustre_handle lockh;
+       union ldlm_policy_data policy;
+       enum ldlm_mode mode = (l_req_mode == LCK_MINMODE) ?
+                             (LCK_CR | LCK_CW | LCK_PR | LCK_PW) : l_req_mode;
+       struct lu_fid *fid;
        __u64 flags;
-        int i;
-        ENTRY;
+       int i;
+       ENTRY;
 
         if (!inode)
                RETURN(0);
@@ -3038,17 +3159,17 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits,  ldlm_mode_t l_req_mode)
         RETURN(*bits == 0);
 }
 
-ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits,
-                           struct lustre_handle *lockh, __u64 flags,
-                           ldlm_mode_t mode)
+enum ldlm_mode ll_take_md_lock(struct inode *inode, __u64 bits,
+                              struct lustre_handle *lockh, __u64 flags,
+                              enum ldlm_mode mode)
 {
-        ldlm_policy_data_t policy = { .l_inodebits = {bits}};
-        struct lu_fid *fid;
-        ldlm_mode_t rc;
-        ENTRY;
+       union ldlm_policy_data policy = { .l_inodebits = { bits } };
+       struct lu_fid *fid;
+       enum ldlm_mode rc;
+       ENTRY;
 
-        fid = &ll_i2info(inode)->lli_fid;
-        CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
+       fid = &ll_i2info(inode)->lli_fid;
+       CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
 
        rc = md_lock_match(ll_i2mdexp(inode), LDLM_FL_BLOCK_GRANTED|flags,
                           fid, LDLM_IBITS, &policy, mode, lockh);
@@ -3061,6 +3182,13 @@ static int ll_inode_revalidate_fini(struct inode *inode, int rc)
        /* Already unlinked. Just update nlink and return success */
        if (rc == -ENOENT) {
                clear_nlink(inode);
+               /* If it is striped directory, and there is bad stripe
+                * Let's revalidate the dentry again, instead of returning
+                * error */
+               if (S_ISDIR(inode->i_mode) &&
+                   ll_i2info(inode)->lli_lsm_md != NULL)
+                       return 0;
+
                /* This path cannot be hit for regular files unless in
                 * case of obscure races, so no need to to validate
                 * size. */
@@ -3150,9 +3278,6 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
                         RETURN(PTR_ERR(op_data));
 
                 op_data->op_valid = valid;
-                /* Once OBD_CONNECT_ATTRFID is not supported, we can't find one
-                 * capa for this inode. Because we only keep capas of dirs
-                 * fresh. */
                 rc = md_getattr(sbi->ll_md_exp, op_data, &req);
                 ll_finish_md_op_data(op_data);
                 if (rc) {
@@ -3220,7 +3345,7 @@ ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
                 * restore the MDT holds the layout lock so the glimpse will
                 * block up to the end of restore (getattr will block)
                 */
-               if (!(ll_i2info(inode)->lli_flags & LLIF_FILE_RESTORING))
+               if (!ll_file_test_flag(ll_i2info(inode), LLIF_FILE_RESTORING))
                        rc = ll_glimpse_size(inode);
        }
        RETURN(rc);
@@ -3264,35 +3389,37 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat)
 static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                     __u64 start, __u64 len)
 {
-        int rc;
-        size_t num_bytes;
-        struct ll_user_fiemap *fiemap;
-        unsigned int extent_count = fieinfo->fi_extents_max;
+       int             rc;
+       size_t          num_bytes;
+       struct fiemap   *fiemap;
+       unsigned int    extent_count = fieinfo->fi_extents_max;
 
-        num_bytes = sizeof(*fiemap) + (extent_count *
-                                       sizeof(struct ll_fiemap_extent));
-        OBD_ALLOC_LARGE(fiemap, num_bytes);
+       num_bytes = sizeof(*fiemap) + (extent_count *
+                                      sizeof(struct fiemap_extent));
+       OBD_ALLOC_LARGE(fiemap, num_bytes);
 
-        if (fiemap == NULL)
-                RETURN(-ENOMEM);
+       if (fiemap == NULL)
+               RETURN(-ENOMEM);
 
-        fiemap->fm_flags = fieinfo->fi_flags;
-        fiemap->fm_extent_count = fieinfo->fi_extents_max;
-        fiemap->fm_start = start;
-        fiemap->fm_length = len;
-       if (extent_count > 0)
-               memcpy(&fiemap->fm_extents[0], fieinfo->fi_extents_start,
-                      sizeof(struct ll_fiemap_extent));
+       fiemap->fm_flags = fieinfo->fi_flags;
+       fiemap->fm_extent_count = fieinfo->fi_extents_max;
+       fiemap->fm_start = start;
+       fiemap->fm_length = len;
+       if (extent_count > 0 &&
+           copy_from_user(&fiemap->fm_extents[0], fieinfo->fi_extents_start,
+                          sizeof(struct fiemap_extent)) != 0)
+               GOTO(out, rc = -EFAULT);
 
        rc = ll_do_fiemap(inode, fiemap, num_bytes);
 
        fieinfo->fi_flags = fiemap->fm_flags;
        fieinfo->fi_extents_mapped = fiemap->fm_mapped_extents;
-       if (extent_count > 0)
-               memcpy(fieinfo->fi_extents_start, &fiemap->fm_extents[0],
-                      fiemap->fm_mapped_extents *
-                      sizeof(struct ll_fiemap_extent));
-
+       if (extent_count > 0 &&
+           copy_to_user(fieinfo->fi_extents_start, &fiemap->fm_extents[0],
+                        fiemap->fm_mapped_extents *
+                        sizeof(struct fiemap_extent)) != 0)
+               GOTO(out, rc = -EFAULT);
+out:
        OBD_FREE_LARGE(fiemap, num_bytes);
        return rc;
 }
@@ -3429,53 +3556,80 @@ int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
 
 /* -o localflock - only provides locally consistent flock locks */
 struct file_operations ll_file_operations = {
-        .read           = ll_file_read,
-       .aio_read    = ll_file_aio_read,
-        .write          = ll_file_write,
-       .aio_write   = ll_file_aio_write,
-        .unlocked_ioctl = ll_file_ioctl,
-        .open           = ll_file_open,
-        .release        = ll_file_release,
-        .mmap           = ll_file_mmap,
-        .llseek         = ll_file_seek,
-        .splice_read    = ll_file_splice_read,
-        .fsync          = ll_fsync,
-        .flush          = ll_flush
+#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+# ifdef HAVE_SYNC_READ_WRITE
+       .read           = new_sync_read,
+       .write          = new_sync_write,
+# endif
+       .read_iter      = ll_file_read_iter,
+       .write_iter     = ll_file_write_iter,
+#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
+       .read           = ll_file_read,
+       .aio_read       = ll_file_aio_read,
+       .write          = ll_file_write,
+       .aio_write      = ll_file_aio_write,
+#endif /* HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
+       .unlocked_ioctl = ll_file_ioctl,
+       .open           = ll_file_open,
+       .release        = ll_file_release,
+       .mmap           = ll_file_mmap,
+       .llseek         = ll_file_seek,
+       .splice_read    = ll_file_splice_read,
+       .fsync          = ll_fsync,
+       .flush          = ll_flush
 };
 
 struct file_operations ll_file_operations_flock = {
-        .read           = ll_file_read,
-       .aio_read    = ll_file_aio_read,
-        .write          = ll_file_write,
-       .aio_write   = ll_file_aio_write,
-        .unlocked_ioctl = ll_file_ioctl,
-        .open           = ll_file_open,
-        .release        = ll_file_release,
-        .mmap           = ll_file_mmap,
-        .llseek         = ll_file_seek,
-        .splice_read    = ll_file_splice_read,
-        .fsync          = ll_fsync,
-        .flush          = ll_flush,
-        .flock          = ll_file_flock,
-        .lock           = ll_file_flock
+#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+# ifdef HAVE_SYNC_READ_WRITE
+       .read           = new_sync_read,
+       .write          = new_sync_write,
+# endif /* HAVE_SYNC_READ_WRITE */
+       .read_iter      = ll_file_read_iter,
+       .write_iter     = ll_file_write_iter,
+#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
+       .read           = ll_file_read,
+       .aio_read       = ll_file_aio_read,
+       .write          = ll_file_write,
+       .aio_write      = ll_file_aio_write,
+#endif /* HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
+       .unlocked_ioctl = ll_file_ioctl,
+       .open           = ll_file_open,
+       .release        = ll_file_release,
+       .mmap           = ll_file_mmap,
+       .llseek         = ll_file_seek,
+       .splice_read    = ll_file_splice_read,
+       .fsync          = ll_fsync,
+       .flush          = ll_flush,
+       .flock          = ll_file_flock,
+       .lock           = ll_file_flock
 };
 
 /* These are for -o noflock - to return ENOSYS on flock calls */
 struct file_operations ll_file_operations_noflock = {
-        .read           = ll_file_read,
-       .aio_read    = ll_file_aio_read,
-        .write          = ll_file_write,
-       .aio_write   = ll_file_aio_write,
-        .unlocked_ioctl = ll_file_ioctl,
-        .open           = ll_file_open,
-        .release        = ll_file_release,
-        .mmap           = ll_file_mmap,
-        .llseek         = ll_file_seek,
-        .splice_read    = ll_file_splice_read,
-        .fsync          = ll_fsync,
-        .flush          = ll_flush,
-        .flock          = ll_file_noflock,
-        .lock           = ll_file_noflock
+#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+# ifdef HAVE_SYNC_READ_WRITE
+       .read           = new_sync_read,
+       .write          = new_sync_write,
+# endif /* HAVE_SYNC_READ_WRITE */
+       .read_iter      = ll_file_read_iter,
+       .write_iter     = ll_file_write_iter,
+#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
+       .read           = ll_file_read,
+       .aio_read       = ll_file_aio_read,
+       .write          = ll_file_write,
+       .aio_write      = ll_file_aio_write,
+#endif /* HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
+       .unlocked_ioctl = ll_file_ioctl,
+       .open           = ll_file_open,
+       .release        = ll_file_release,
+       .mmap           = ll_file_mmap,
+       .llseek         = ll_file_seek,
+       .splice_read    = ll_file_splice_read,
+       .fsync          = ll_fsync,
+       .flush          = ll_flush,
+       .flock          = ll_file_noflock,
+       .lock           = ll_file_noflock
 };
 
 struct inode_operations ll_file_inode_operations = {
@@ -3650,7 +3804,6 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock)
 
 {
        struct ll_sb_info *sbi = ll_i2sbi(inode);
-       struct obd_capa *oc;
        struct ptlrpc_request *req;
        struct mdt_body *body;
        void *lvbdata;
@@ -3663,7 +3816,7 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock)
               PFID(ll_inode2fid(inode)), ldlm_is_lvb_ready(lock),
               lock->l_lvb_data, lock->l_lvb_len);
 
-       if ((lock->l_lvb_data != NULL) && ldlm_is_lvb_ready(lock))
+       if (lock->l_lvb_data != NULL)
                RETURN(0);
 
        /* if layout lock was granted right away, the layout is returned
@@ -3671,13 +3824,11 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock)
         * blocked and then granted via completion ast, we have to fetch
         * layout here. Please note that we can't use the LVB buffer in
         * completion AST because it doesn't have a large enough buffer */
-       oc = ll_mdscapa_get(inode);
        rc = ll_get_default_mdsize(sbi, &lmmsize);
        if (rc == 0)
-               rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
+               rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode),
                                OBD_MD_FLXATTR, XATTR_NAME_LOV, NULL, 0,
                                lmmsize, 0, &req);
-       capa_put(oc);
        if (rc < 0)
                RETURN(rc);
 
@@ -3699,13 +3850,17 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock)
 
        memcpy(lvbdata, lmm, lmmsize);
        lock_res_and_lock(lock);
-       if (lock->l_lvb_data != NULL)
-               OBD_FREE_LARGE(lock->l_lvb_data, lock->l_lvb_len);
-
-       lock->l_lvb_data = lvbdata;
-       lock->l_lvb_len = lmmsize;
+       if (unlikely(lock->l_lvb_data == NULL)) {
+               lock->l_lvb_type = LVB_T_LAYOUT;
+               lock->l_lvb_data = lvbdata;
+               lock->l_lvb_len = lmmsize;
+               lvbdata = NULL;
+       }
        unlock_res_and_lock(lock);
 
+       if (lvbdata != NULL)
+               OBD_FREE_LARGE(lvbdata, lmmsize);
+
        EXIT;
 
 out:
@@ -3717,13 +3872,12 @@ out:
  * Apply the layout to the inode. Layout lock is held and will be released
  * in this function.
  */
-static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode,
+static int ll_layout_lock_set(struct lustre_handle *lockh, enum ldlm_mode mode,
                              struct inode *inode)
 {
        struct ll_inode_info *lli = ll_i2info(inode);
        struct ll_sb_info    *sbi = ll_i2sbi(inode);
        struct ldlm_lock *lock;
-       struct lustre_md md = { NULL };
        struct cl_object_conf conf;
        int rc = 0;
        bool lvb_ready;
@@ -3755,38 +3909,20 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode,
        if (rc < 0)
                GOTO(out, rc);
 
-       /* for layout lock, lmm is returned in lock's lvb.
+       /* for layout lock, lmm is stored in lock's lvb.
         * lvb_data is immutable if the lock is held so it's safe to access it
-        * without res lock. See the description in ldlm_lock_decref_internal()
-        * for the condition to free lvb_data of layout lock */
-       if (lock->l_lvb_data != NULL) {
-               rc = obd_unpackmd(sbi->ll_dt_exp, &md.lsm,
-                                 lock->l_lvb_data, lock->l_lvb_len);
-               if (rc < 0) {
-                       CERROR("%s: file "DFID" unpackmd error: %d\n",
-                               ll_get_fsname(inode->i_sb, NULL, 0),
-                               PFID(&lli->lli_fid), rc);
-                       GOTO(out, rc);
-               }
-
-               LASSERTF(md.lsm != NULL, "lvb_data = %p, lvb_len = %u\n",
-                        lock->l_lvb_data, lock->l_lvb_len);
-
-               rc = 0;
-       }
-
-       /* set layout to file. Unlikely this will fail as old layout was
+        * without res lock.
+        *
+        * set layout to file. Unlikely this will fail as old layout was
         * surely eliminated */
        memset(&conf, 0, sizeof conf);
        conf.coc_opc = OBJECT_CONF_SET;
        conf.coc_inode = inode;
        conf.coc_lock = lock;
-       conf.u.coc_md = &md;
+       conf.u.coc_layout.lb_buf = lock->l_lvb_data;
+       conf.u.coc_layout.lb_len = lock->l_lvb_len;
        rc = ll_layout_conf(inode, &conf);
 
-       if (md.lsm != NULL)
-               obd_free_memmd(sbi->ll_dt_exp, &md.lsm);
-
        /* refresh layout failed, need to wait */
        wait_layout = rc == -EBUSY;
        EXIT;
@@ -3820,9 +3956,9 @@ static int ll_layout_refresh_locked(struct inode *inode)
        struct ll_inode_info  *lli = ll_i2info(inode);
        struct ll_sb_info     *sbi = ll_i2sbi(inode);
        struct md_op_data     *op_data;
-       struct lookup_intent   it;
-       struct lustre_handle   lockh;
-       ldlm_mode_t            mode;
+       struct lookup_intent    it;
+       struct lustre_handle    lockh;
+       enum ldlm_mode          mode;
        struct ldlm_enqueue_info einfo = {
                .ei_type = LDLM_IBITS,
                .ei_mode = LCK_CR,