Whamcloud - gitweb
LU-6215 llite: handle removal of ki_nbytes in struct kiocb
[fs/lustre-release.git] / lustre / llite / file.c
index 6653783..8b54068 100644 (file)
 #include <linux/pagemap.h>
 #include <linux/file.h>
 #include <linux/sched.h>
+#include <linux/user_namespace.h>
+#ifdef HAVE_UIDGID_HEADER
+# include <linux/uidgid.h>
+#endif
 #include <lustre/ll_fiemap.h>
 #include <lustre_ioctl.h>
 
@@ -95,7 +99,6 @@ void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data,
        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;
@@ -125,39 +128,63 @@ out:
         EXIT;
 }
 
+/**
+ * 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 obd_export *md_exp,
-                                    struct inode *inode,
                                     struct obd_client_handle *och,
-                                    const __u64 *data_version)
+                                    struct inode *inode,
+                                    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       *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;
 
-        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 (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);
+       }
 
-        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);
+       if (op_data == NULL)
+               /* XXX We leak openhandle and request here. */
+               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;
+
+       default:
+               LASSERT(data == NULL);
+               break;
        }
 
         rc = md_close(md_exp, op_data, och->och_mod, &req);
@@ -177,15 +204,17 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp,
                spin_unlock(&lli->lli_lock);
        }
 
-       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);
@@ -234,7 +263,7 @@ int ll_md_real_close(struct inode *inode, fmode_t fmode)
                /* 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);
+                                              och, inode, 0, NULL);
        }
 
        RETURN(rc);
@@ -243,10 +272,16 @@ int ll_md_real_close(struct inode *inode, fmode_t fmode)
 static int ll_md_close(struct obd_export *md_exp, 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;
+       ldlm_policy_data_t 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;
+       int lockmode;
+       int rc = 0;
+       ENTRY;
 
        /* clear group lock, if present */
        if (unlikely(fd->fd_flags & LL_FILE_GROUP_LOCKED))
@@ -265,52 +300,37 @@ 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(md_exp, fd->fd_och, inode, 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(md_exp, 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);
 }
@@ -345,7 +365,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);
@@ -355,7 +375,7 @@ 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) {
+       if (inode->i_sb->s_root == file->f_path.dentry) {
                 LUSTRE_FPRIVATE(file) = NULL;
                 ll_file_data_put(fd);
                 RETURN(0);
@@ -378,7 +398,7 @@ int ll_file_release(struct inode *inode, struct file *file)
 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;
@@ -459,7 +479,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));
@@ -523,7 +543,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);
         }
@@ -581,7 +601,7 @@ restart:
                                 GOTO(out_openerr, rc);
                         }
 
-                        ll_release_openhandle(file->f_dentry, it);
+                       ll_release_openhandle(file->f_path.dentry, it);
                 }
                 (*och_usecount)++;
 
@@ -651,8 +671,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);
 
@@ -830,7 +848,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(sbi->ll_md_exp, och, inode, 0, NULL);
        if (rc2 < 0)
                CERROR("%s: error closing file "DFID": %d\n",
                       ll_get_fsname(inode->i_sb, NULL, 0),
@@ -845,6 +863,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(ll_i2sbi(inode)->ll_md_exp, och, inode,
+                                      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.
  */
@@ -872,8 +952,9 @@ 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(ll_i2sbi(inode)->ll_md_exp, och, inode,
+                                      0, NULL);
+
        RETURN(rc);
 }
 
@@ -962,7 +1043,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) {
@@ -988,37 +1069,25 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
                   struct file *file, enum cl_io_type iot,
                   loff_t *ppos, size_t count)
 {
-       struct inode *inode = file->f_dentry->d_inode;
-       struct ll_inode_info *lli = ll_i2info(inode);
-       loff_t               end;
-       struct ll_file_data  *fd  = LUSTRE_FPRIVATE(file);
-       struct cl_io         *io;
-       ssize_t               result;
-       struct range_lock     range;
+       struct vvp_io           *vio = vvp_env_io(env);
+       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;
+       ssize_t                 result = 0;
+       int                     rc = 0;
+       struct range_lock       range;
+
        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);
-        ll_io_init(io, file, iot == CIT_WRITE);
-
-       /* The maximum Lustre file size is variable, based on the
-        * OST maximum object size and number of stripes.  This
-        * needs another check in addition to the VFS checks earlier. */
-       end = (io->u.ci_wr.wr_append ? i_size_read(inode) : *ppos) + count;
-       if (end > ll_file_maxbytes(inode)) {
-               result = -EFBIG;
-               CDEBUG(D_INODE, "%s: file "DFID" offset %llu > maxbytes "LPU64
-                      ": rc = %zd\n", ll_get_fsname(inode->i_sb, NULL, 0),
-                      PFID(&lli->lli_fid), end, ll_file_maxbytes(inode),
-                      result);
-               RETURN(result);
-       }
-
-        if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) {
-               struct vvp_io *vio = vvp_env_io(env);
+       ll_io_init(io, file, iot == CIT_WRITE);
+
+       if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) {
                bool range_locked = false;
 
                if (file->f_flags & O_APPEND)
@@ -1035,18 +1104,20 @@ restart:
                        vio->vui_nrsegs = args->u.normal.via_nrsegs;
                        vio->vui_tot_nrsegs = vio->vui_nrsegs;
                        vio->vui_iocb = args->u.normal.via_iocb;
-                       if ((iot == CIT_WRITE) &&
+                       /* 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 "RL_FMT"\n",
                                       RL_PARA(&range));
-                               result = range_lock(&lli->lli_write_tree,
-                                                   &range);
-                               if (result < 0)
-                                       GOTO(out, result);
+                               rc = range_lock(&lli->lli_write_tree, &range);
+                               if (rc < 0)
+                                       GOTO(out, rc);
 
                                range_locked = true;
                        }
-                       down_read(&lli->lli_trunc_sem);
                        break;
                case IO_SPLICE:
                        vio->u.splice.vui_pipe = args->u.splice.via_pipe;
@@ -1058,57 +1129,62 @@ restart:
                }
 
                ll_cl_add(file, env, io);
-                result = cl_io_loop(env, io);
+               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));
                        range_unlock(&lli->lli_write_tree, &range);
                }
-        } else {
-                /* cl_io_rw_init() handled IO */
-                result = io->ci_result;
-        }
+       } else {
+               /* cl_io_rw_init() handled IO */
+               rc = io->ci_result;
+       }
 
-        if (io->ci_nob > 0) {
-                result = io->ci_nob;
-                *ppos = io->u.ci_wr.wr.crw_pos;
-        }
-        GOTO(out, result);
+       if (io->ci_nob > 0) {
+               result += io->ci_nob;
+               count -= io->ci_nob;
+               *ppos = io->u.ci_wr.wr.crw_pos; /* for splice */
+
+               /* 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;
+               }
+       }
+       GOTO(out, rc);
 out:
-        cl_io_fini(env, io);
-       /* If any bit been read/written (result != 0), we just return
-        * short read/write instead of restart io. */
-       if ((result == 0 || result == -ENODATA) && io->ci_need_restart) {
-               CDEBUG(D_VFSTRACE, "Restart %s on %s from %lld, count:%zu\n",
+       cl_io_fini(env, io);
+
+       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_path.dentry->d_name.name,
                       iot == CIT_READ ? "read" : "write",
-                      file->f_dentry->d_name.name, *ppos, count);
-               LASSERTF(io->ci_nob == 0, "%zd\n", io->ci_nob);
+                      *ppos, count, result);
                goto restart;
        }
 
-        if (iot == CIT_READ) {
-                if (result >= 0)
-                        ll_stats_ops_tally(ll_i2sbi(file->f_dentry->d_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),
-                                           LPROC_LL_WRITE_BYTES, result);
+       if (iot == CIT_READ) {
+               if (result > 0)
+                       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(inode),
+                                          LPROC_LL_WRITE_BYTES, result);
                        fd->fd_write_failed = false;
-               } else if (result != -ERESTARTSYS) {
+               } else if (rc != -ERESTARTSYS) {
                        fd->fd_write_failed = true;
                }
        }
+
        CDEBUG(D_VFSTRACE, "iot: %d, result: %zd\n", iot, result);
 
-       return result;
+       return result > 0 ? result : rc;
 }
 
-
 /*
  * XXX: exact copy from kernel code (__generic_file_aio_write_nolock)
  */
@@ -1141,10 +1217,11 @@ static int ll_file_get_iov_count(const struct iovec *iov,
 }
 
 static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
-                                unsigned long nr_segs, loff_t pos)
+                               unsigned long nr_segs, loff_t pos)
 {
-        struct lu_env      *env;
-        struct vvp_io_args *args;
+       struct lu_env      *env;
+       struct vvp_io_args *args;
+       struct iovec       *local_iov;
         size_t              count;
         ssize_t             result;
         int                 refcheck;
@@ -1158,22 +1235,40 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
         if (IS_ERR(env))
                 RETURN(PTR_ERR(env));
 
+       if (nr_segs == 1) {
+               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);
+                       RETURN(-ENOMEM);
+               }
+
+               memcpy(local_iov, iov, sizeof(*iov) * nr_segs);
+       }
+
        args = ll_env_args(env, IO_NORMAL);
-        args->u.normal.via_iov = (struct iovec *)iov;
-        args->u.normal.via_nrsegs = nr_segs;
-        args->u.normal.via_iocb = iocb;
+       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);
-        cl_env_put(env, &refcheck);
-        RETURN(result);
+       result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ,
+                                   &iocb->ki_pos, count);
+
+       cl_env_put(env, &refcheck);
+
+       if (nr_segs > 1)
+               OBD_FREE(local_iov, sizeof(*iov) * nr_segs);
+
+       RETURN(result);
 }
 
 static ssize_t ll_file_read(struct file *file, char __user *buf, size_t count,
-                            loff_t *ppos)
+                           loff_t *ppos)
 {
-        struct lu_env *env;
-        struct iovec  *local_iov;
+       struct lu_env *env;
+       struct iovec   iov = { .iov_base = buf, .iov_len = count };
         struct kiocb  *kiocb;
         ssize_t        result;
         int            refcheck;
@@ -1183,23 +1278,20 @@ static ssize_t ll_file_read(struct file *file, char __user *buf, size_t count,
         if (IS_ERR(env))
                 RETURN(PTR_ERR(env));
 
-       local_iov = &ll_env_info(env)->lti_local_iov;
        kiocb = &ll_env_info(env)->lti_kiocb;
-        local_iov->iov_base = (void __user *)buf;
-        local_iov->iov_len = 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, local_iov, 1, kiocb->ki_pos);
-        *ppos = kiocb->ki_pos;
+       result = ll_file_aio_read(kiocb, &iov, 1, kiocb->ki_pos);
+       *ppos = kiocb->ki_pos;
 
-        cl_env_put(env, &refcheck);
-        RETURN(result);
+       cl_env_put(env, &refcheck);
+       RETURN(result);
 }
 
 /*
@@ -1207,10 +1299,11 @@ static ssize_t ll_file_read(struct file *file, char __user *buf, size_t count,
  * AIO stuff
  */
 static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
-                                 unsigned long nr_segs, loff_t pos)
+                                unsigned long nr_segs, loff_t pos)
 {
-        struct lu_env      *env;
-        struct vvp_io_args *args;
+       struct lu_env      *env;
+       struct vvp_io_args *args;
+       struct iovec       *local_iov;
         size_t              count;
         ssize_t             result;
         int                 refcheck;
@@ -1224,22 +1317,40 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
         if (IS_ERR(env))
                 RETURN(PTR_ERR(env));
 
+       if (nr_segs == 1) {
+               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);
+                       RETURN(-ENOMEM);
+               }
+
+               memcpy(local_iov, iov, sizeof(*iov) * nr_segs);
+       }
+
        args = ll_env_args(env, IO_NORMAL);
-        args->u.normal.via_iov = (struct iovec *)iov;
-        args->u.normal.via_nrsegs = nr_segs;
-        args->u.normal.via_iocb = iocb;
+       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_WRITE,
-                                  &iocb->ki_pos, count);
-        cl_env_put(env, &refcheck);
-        RETURN(result);
+       result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_WRITE,
+                                 &iocb->ki_pos, count);
+       cl_env_put(env, &refcheck);
+
+       if (nr_segs > 1)
+               OBD_FREE(local_iov, sizeof(*iov) * nr_segs);
+
+       RETURN(result);
 }
 
 static ssize_t ll_file_write(struct file *file, const char __user *buf,
                             size_t count, loff_t *ppos)
 {
-        struct lu_env *env;
-        struct iovec  *local_iov;
+       struct lu_env *env;
+       struct iovec   iov = { .iov_base = (void __user *)buf,
+                              .iov_len = count };
         struct kiocb  *kiocb;
         ssize_t        result;
         int            refcheck;
@@ -1249,23 +1360,20 @@ static ssize_t ll_file_write(struct file *file, const char __user *buf,
         if (IS_ERR(env))
                 RETURN(PTR_ERR(env));
 
-       local_iov = &ll_env_info(env)->lti_local_iov;
        kiocb = &ll_env_info(env)->lti_kiocb;
-        local_iov->iov_base = (void __user *)buf;
-        local_iov->iov_len = 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_write(kiocb, local_iov, 1, kiocb->ki_pos);
-        *ppos = kiocb->ki_pos;
+       result = ll_file_aio_write(kiocb, &iov, 1, kiocb->ki_pos);
+       *ppos = kiocb->ki_pos;
 
-        cl_env_put(env, &refcheck);
-        RETURN(result);
+       cl_env_put(env, &refcheck);
+       RETURN(result);
 }
 
 /*
@@ -1310,7 +1418,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);
@@ -1595,7 +1703,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);
+                                      och, inode, 0, NULL);
 out:
        /* this one is in place of ll_file_open */
        if (it_disposition(it, DISP_ENQ_OPEN_REF)) {
@@ -1617,7 +1725,7 @@ static int ll_do_fiemap(struct inode *inode, struct fiemap *fiemap,
        struct lu_env                   *env;
        int                             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 */
@@ -1643,17 +1751,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);
@@ -1705,61 +1813,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.
  *
@@ -1773,13 +1826,16 @@ error:
  */
 int ll_data_version(struct inode *inode, __u64 *data_version, int flags)
 {
-       struct lu_env   *env;
-       int             refcheck;
-       int             rc;
+       struct cl_object *obj = ll_i2info(inode)->lli_clob;
+       struct lu_env *env;
+       struct cl_io *io;
+       int refcheck;
+       int result;
+
        ENTRY;
 
        /* If no file object initialized, we consider its version is 0. */
-       if (ll_i2info(inode)->lli_clob == NULL) {
+       if (obj == NULL) {
                *data_version = 0;
                RETURN(0);
        }
@@ -1788,10 +1844,27 @@ int ll_data_version(struct inode *inode, __u64 *data_version, int flags)
        if (IS_ERR(env))
                RETURN(PTR_ERR(env));
 
-       rc = cl_object_data_version(env, ll_i2info(inode)->lli_clob,
-                                   data_version, flags);
+       io = vvp_env_thread_io(env);
+       io->ci_obj = obj;
+       io->u.ci_data_version.dv_data_version = 0;
+       io->u.ci_data_version.dv_flags = flags;
+
+restart:
+       if (cl_io_init(env, io, CIT_DATA_VERSION, io->ci_obj) == 0)
+               result = cl_io_loop(env, io);
+       else
+               result = io->ci_result;
+
+       *data_version = io->u.ci_data_version.dv_data_version;
+
+       cl_io_fini(env, io);
+
+       if (unlikely(io->ci_need_restart))
+               goto restart;
+
        cl_env_put(env, &refcheck);
-       RETURN(rc);
+
+       RETURN(result);
 }
 
 /*
@@ -1829,8 +1902,8 @@ 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,
-                                      &data_version);
+       rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, och, inode,
+                                      MDS_HSM_RELEASE, &data_version);
        och = NULL;
 
        EXIT;
@@ -1842,10 +1915,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,
@@ -1862,18 +1937,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)
@@ -1888,7 +1957,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);
@@ -1910,18 +1979,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) {
@@ -1956,45 +2013,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);
@@ -2080,7 +2107,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;
 
@@ -2105,7 +2132,7 @@ static inline long ll_lease_type_from_fmode(fmode_t fmode)
 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;
@@ -2156,24 +2183,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));
@@ -2445,7 +2494,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:
@@ -2494,7 +2543,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;
@@ -2519,7 +2568,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;
@@ -2555,7 +2604,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;
@@ -2568,15 +2616,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);
@@ -2592,25 +2637,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
@@ -2622,7 +2665,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;
 
@@ -2651,10 +2693,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)
@@ -2681,7 +2720,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,
@@ -2868,7 +2907,7 @@ 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) {
                        child_inode = igrab(dchild->d_inode);
@@ -3096,9 +3135,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) {
@@ -3210,35 +3246,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;
 }
@@ -3596,7 +3634,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;
@@ -3609,7 +3646,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
@@ -3617,13 +3654,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);
 
@@ -3645,13 +3680,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:
@@ -3669,7 +3708,6 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode,
        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;
@@ -3701,38 +3739,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;