Whamcloud - gitweb
LU-3254 llite: Update layout_gen only if layout change succeed
[fs/lustre-release.git] / lustre / llite / file.c
index e2eb565..e0019c3 100644 (file)
 
 #include "cl_object.h"
 
-struct ll_file_data *ll_file_data_get(void)
+static int
+ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg);
+
+static int ll_lease_close(struct obd_client_handle *och, struct inode *inode,
+                         bool *lease_broken);
+
+static enum llioc_iter
+ll_iocontrol_call(struct inode *inode, struct file *file,
+                 unsigned int cmd, unsigned long arg, int *rcp);
+
+static struct ll_file_data *ll_file_data_get(void)
 {
        struct ll_file_data *fd;
 
-       OBD_SLAB_ALLOC_PTR_GFP(fd, ll_file_data_slab, __GFP_IO);
+       OBD_SLAB_ALLOC_PTR_GFP(fd, ll_file_data_slab, GFP_NOFS);
        if (fd == NULL)
                return NULL;
 
@@ -218,48 +228,51 @@ out:
         return rc;
 }
 
-int ll_md_real_close(struct inode *inode, int flags)
+int ll_md_real_close(struct inode *inode, fmode_t fmode)
 {
-        struct ll_inode_info *lli = ll_i2info(inode);
-        struct obd_client_handle **och_p;
-        struct obd_client_handle *och;
-        __u64 *och_usecount;
-        int rc = 0;
-        ENTRY;
+       struct ll_inode_info *lli = ll_i2info(inode);
+       struct obd_client_handle **och_p;
+       struct obd_client_handle *och;
+       __u64 *och_usecount;
+       int rc = 0;
+       ENTRY;
 
-        if (flags & FMODE_WRITE) {
-                och_p = &lli->lli_mds_write_och;
-                och_usecount = &lli->lli_open_fd_write_count;
-        } else if (flags & FMODE_EXEC) {
-                och_p = &lli->lli_mds_exec_och;
-                och_usecount = &lli->lli_open_fd_exec_count;
-        } else {
-                LASSERT(flags & FMODE_READ);
-                och_p = &lli->lli_mds_read_och;
-                och_usecount = &lli->lli_open_fd_read_count;
-        }
+       if (fmode & FMODE_WRITE) {
+               och_p = &lli->lli_mds_write_och;
+               och_usecount = &lli->lli_open_fd_write_count;
+       } else if (fmode & FMODE_EXEC) {
+               och_p = &lli->lli_mds_exec_och;
+               och_usecount = &lli->lli_open_fd_exec_count;
+       } else {
+               LASSERT(fmode & FMODE_READ);
+               och_p = &lli->lli_mds_read_och;
+               och_usecount = &lli->lli_open_fd_read_count;
+       }
 
        mutex_lock(&lli->lli_och_mutex);
-        if (*och_usecount) { /* There are still users of this handle, so
-                                skip freeing it. */
+       if (*och_usecount > 0) {
+               /* There are still users of this handle, so skip
+                * freeing it. */
                mutex_unlock(&lli->lli_och_mutex);
-                RETURN(0);
-        }
-        och=*och_p;
-        *och_p = NULL;
+               RETURN(0);
+       }
+
+       och = *och_p;
+       *och_p = NULL;
        mutex_unlock(&lli->lli_och_mutex);
 
-        if (och) { /* There might be a race and somebody have freed this och
-                      already */
-                rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp,
+       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);
-        }
+       }
 
-        RETURN(rc);
+       RETURN(rc);
 }
 
-int ll_md_close(struct obd_export *md_exp, struct inode *inode,
-                struct file *file)
+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);
@@ -381,7 +394,8 @@ int ll_file_release(struct inode *inode, struct file *file)
         }
 
         if (!S_ISDIR(inode->i_mode)) {
-               lov_read_and_clear_async_rc(lli->lli_clob);
+               if (lli->lli_clob != NULL)
+                       lov_read_and_clear_async_rc(lli->lli_clob);
                 lli->lli_async_rc = 0;
         }
 
@@ -496,8 +510,8 @@ static int ll_och_fill(struct obd_export *md_exp, struct lookup_intent *it,
        return md_set_open_replay_data(md_exp, och, it);
 }
 
-int ll_local_open(struct file *file, struct lookup_intent *it,
-                  struct ll_file_data *fd, struct obd_client_handle *och)
+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 ll_inode_info *lli = ll_i2info(inode);
@@ -669,16 +683,18 @@ restart:
                  * (bug 3430) */
                 /* XXX (green): Should not we bail out on any error here, not
                  * just open error? */
-                rc = it_open_error(DISP_OPEN_OPEN, it);
-                if (rc)
-                        GOTO(out_och_free, rc);
+               rc = it_open_error(DISP_OPEN_OPEN, it);
+               if (rc != 0)
+                       GOTO(out_och_free, rc);
 
-                LASSERT(it_disposition(it, DISP_ENQ_OPEN_REF));
+               LASSERTF(it_disposition(it, DISP_ENQ_OPEN_REF),
+                        "inode %p: disposition %x, status %d\n", inode,
+                        it_disposition(it, ~0), it->d.lustre.it_status);
 
-                rc = ll_local_open(file, it, fd, *och_p);
-                if (rc)
-                        GOTO(out_och_free, rc);
-        }
+               rc = ll_local_open(file, it, fd, *och_p);
+               if (rc)
+                       GOTO(out_och_free, rc);
+       }
        mutex_unlock(&lli->lli_och_mutex);
         fd = NULL;
 
@@ -690,15 +706,14 @@ restart:
 
         ll_capa_open(inode);
 
-       if (!lli->lli_has_smd) {
-                if (file->f_flags & O_LOV_DELAY_CREATE ||
-                    !(file->f_mode & FMODE_WRITE)) {
-                        CDEBUG(D_INODE, "object creation was delayed\n");
-                        GOTO(out_och_free, rc);
-                }
-        }
-        file->f_flags &= ~O_LOV_DELAY_CREATE;
-        GOTO(out_och_free, rc);
+       if (!lli->lli_has_smd &&
+           (cl_is_lov_delay_create(file->f_flags) ||
+            (file->f_mode & FMODE_WRITE) == 0)) {
+               CDEBUG(D_INODE, "object creation was delayed\n");
+               GOTO(out_och_free, rc);
+       }
+       cl_lov_delay_create_clear(&file->f_flags);
+       GOTO(out_och_free, rc);
 
 out_och_free:
         if (rc) {
@@ -752,8 +767,9 @@ static int ll_md_blocking_lease_ast(struct ldlm_lock *lock,
 /**
  * Acquire a lease and open the file.
  */
-struct obd_client_handle *ll_lease_open(struct inode *inode, struct file *file,
-                                       fmode_t fmode, __u64 open_flags)
+static struct obd_client_handle *
+ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode,
+             __u64 open_flags)
 {
        struct lookup_intent it = { .it_op = IT_OPEN };
        struct ll_sb_info *sbi = ll_i2sbi(inode);
@@ -886,14 +902,13 @@ out:
                OBD_FREE_PTR(och);
        RETURN(ERR_PTR(rc));
 }
-EXPORT_SYMBOL(ll_lease_open);
 
 /**
  * Release lease and close the file.
  * It will check if the lease has ever broken.
  */
-int ll_lease_close(struct obd_client_handle *och, struct inode *inode,
-                       bool *lease_broken)
+static int ll_lease_close(struct obd_client_handle *och, struct inode *inode,
+                         bool *lease_broken)
 {
        struct ldlm_lock *lock;
        bool cancelled = true;
@@ -920,7 +935,6 @@ int ll_lease_close(struct obd_client_handle *och, struct inode *inode,
                                       NULL);
        RETURN(rc);
 }
-EXPORT_SYMBOL(ll_lease_close);
 
 /* Fills the obdo with the attributes for the lsm */
 static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp,
@@ -1095,7 +1109,7 @@ static bool file_is_noatime(const struct file *file)
        return false;
 }
 
-void ll_io_init(struct cl_io *io, const struct file *file, int write)
+static void ll_io_init(struct cl_io *io, const struct file *file, int write)
 {
         struct inode *inode = file->f_dentry->d_inode;
 
@@ -1125,9 +1139,12 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
 {
        struct ll_inode_info *lli = ll_i2info(file->f_dentry->d_inode);
        struct ll_file_data  *fd  = LUSTRE_FPRIVATE(file);
-        struct cl_io         *io;
-        ssize_t               result;
-        ENTRY;
+       struct cl_io         *io;
+       ssize_t               result;
+       ENTRY;
+
+       CDEBUG(D_VFSTRACE, "file: %s, type: %d ppos: "LPU64", count: %zd\n",
+               file->f_dentry->d_name.name, iot, *ppos, count);
 
 restart:
         io = ccc_env_thread_io(env);
@@ -1150,16 +1167,11 @@ restart:
                         if ((iot == CIT_WRITE) &&
                             !(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
                                if (mutex_lock_interruptible(&lli->
-                                                               lli_write_mutex))
-                                        GOTO(out, result = -ERESTARTSYS);
-                                write_mutex_locked = 1;
-                        } else if (iot == CIT_READ) {
-                               down_read(&lli->lli_trunc_sem);
-                        }
-                        break;
-                case IO_SENDFILE:
-                        vio->u.sendfile.cui_actor = args->u.sendfile.via_actor;
-                        vio->u.sendfile.cui_target = args->u.sendfile.via_target;
+                                                       lli_write_mutex))
+                                       GOTO(out, result = -ERESTARTSYS);
+                               write_mutex_locked = 1;
+                       }
+                       down_read(&lli->lli_trunc_sem);
                         break;
                 case IO_SPLICE:
                         vio->u.splice.cui_pipe = args->u.splice.via_pipe;
@@ -1170,10 +1182,10 @@ restart:
                         LBUG();
                 }
                 result = cl_io_loop(env, io);
-                if (write_mutex_locked)
-                       mutex_unlock(&lli->lli_write_mutex);
-                else if (args->via_io_subtype == IO_NORMAL && iot == CIT_READ)
+               if (args->via_io_subtype == IO_NORMAL)
                        up_read(&lli->lli_trunc_sem);
+               if (write_mutex_locked)
+                       mutex_unlock(&lli->lli_write_mutex);
         } else {
                 /* cl_io_rw_init() handled IO */
                 result = io->ci_result;
@@ -1209,6 +1221,7 @@ out:
                        fd->fd_write_failed = true;
                }
        }
+       CDEBUG(D_VFSTRACE, "iot: %d, result: %zd\n", iot, result);
 
        return result;
 }
@@ -1294,7 +1307,11 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
         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;
+#endif
 
         result = ll_file_aio_read(kiocb, local_iov, 1, kiocb->ki_pos);
         *ppos = kiocb->ki_pos;
@@ -1356,7 +1373,11 @@ static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
         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;
+#endif
 
         result = ll_file_aio_write(kiocb, local_iov, 1, kiocb->ki_pos);
         *ppos = kiocb->ki_pos;
@@ -1487,23 +1508,25 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file,
                ccc_inode_lsm_put(inode, lsm);
                CDEBUG(D_IOCTL, "stripe already exists for inode "DFID"\n",
                       PFID(ll_inode2fid(inode)));
-               RETURN(-EEXIST);
+               GOTO(out, rc = -EEXIST);
        }
 
        ll_inode_size_lock(inode);
-        rc = ll_intent_file_open(file, lum, lum_size, &oit);
-        if (rc)
-                GOTO(out, rc);
-        rc = oit.d.lustre.it_status;
-        if (rc < 0)
-                GOTO(out_req_free, rc);
+       rc = ll_intent_file_open(file, lum, lum_size, &oit);
+       if (rc)
+               GOTO(out_unlock, rc);
+       rc = oit.d.lustre.it_status;
+       if (rc < 0)
+               GOTO(out_req_free, rc);
 
-        ll_release_openhandle(file->f_dentry, &oit);
+       ll_release_openhandle(file->f_dentry, &oit);
 
- out:
+out_unlock:
        ll_inode_size_unlock(inode);
        ll_intent_release(&oit);
        ccc_inode_lsm_put(inode, lsm);
+out:
+       cl_lov_delay_create_clear(&file->f_flags);
        RETURN(rc);
 out_req_free:
        ptlrpc_req_finished((struct ptlrpc_request *) oit.d.lustre.it_data);
@@ -1521,9 +1544,9 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
         struct md_op_data *op_data;
         int rc, lmmsize;
 
-        rc = ll_get_max_mdsize(sbi, &lmmsize);
-        if (rc)
-                RETURN(rc);
+       rc = ll_get_default_mdsize(sbi, &lmmsize);
+       if (rc)
+               RETURN(rc);
 
         op_data = ll_prep_md_op_data(NULL, inode, NULL, filename,
                                      strlen(filename), lmmsize,
@@ -1674,7 +1697,8 @@ static int ll_lov_getstripe(struct inode *inode, unsigned long arg)
        RETURN(rc);
 }
 
-int ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg)
+static int
+ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg)
 {
         struct ll_inode_info   *lli = ll_i2info(inode);
         struct ll_file_data    *fd = LUSTRE_FPRIVATE(file);
@@ -1797,8 +1821,8 @@ out:
  * Get size for inode for which FIEMAP mapping is requested.
  * Make the FIEMAP get_info call and returns the result.
  */
-int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap,
-              int num_bytes)
+static int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap,
+                       int num_bytes)
 {
        struct obd_export *exp = ll_i2dtexp(inode);
        struct lov_stripe_md *lsm = NULL;
@@ -2255,8 +2279,8 @@ static int ll_hsm_import(struct inode *inode, struct file *file,
 
        attr->ia_mode = hui->hui_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
        attr->ia_mode |= S_IFREG;
-       attr->ia_uid = hui->hui_uid;
-       attr->ia_gid = hui->hui_gid;
+       attr->ia_uid = make_kuid(&init_user_ns, hui->hui_uid);
+       attr->ia_gid = make_kgid(&init_user_ns, hui->hui_gid);
        attr->ia_size = hui->hui_size;
        attr->ia_mtime.tv_sec = hui->hui_mtime;
        attr->ia_mtime.tv_nsec = hui->hui_mtime_ns;
@@ -2282,7 +2306,8 @@ out:
        RETURN(rc);
 }
 
-long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long
+ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct inode            *inode = file->f_dentry->d_inode;
        struct ll_file_data     *fd = LUSTRE_FPRIVATE(file);
@@ -2587,6 +2612,7 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                OBD_FREE_PTR(hui);
                RETURN(rc);
        }
+
        default: {
                int err;
 
@@ -2667,7 +2693,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int origin,
 }
 #endif
 
-loff_t ll_file_seek(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;
        loff_t retval, eof = 0;
@@ -2692,7 +2718,7 @@ loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
        RETURN(retval);
 }
 
-int ll_flush(struct file *file, fl_owner_t id)
+static int ll_flush(struct file *file, fl_owner_t id)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ll_inode_info *lli = ll_i2info(inode);
@@ -2705,9 +2731,11 @@ int ll_flush(struct file *file, fl_owner_t id)
         * failed for pages in this mapping. */
        rc = lli->lli_async_rc;
        lli->lli_async_rc = 0;
-       err = lov_read_and_clear_async_rc(lli->lli_clob);
-       if (rc == 0)
-               rc = err;
+       if (lli->lli_clob != NULL) {
+               err = lov_read_and_clear_async_rc(lli->lli_clob);
+               if (rc == 0)
+                       rc = err;
+       }
 
        /* The application has been told write failure already.
         * Do not report failure again. */
@@ -2788,48 +2816,48 @@ int ll_fsync(struct file *file, int datasync)
 int ll_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
 #endif
-        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;
+       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;
 
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n",
               PFID(ll_inode2fid(inode)), inode);
-        ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FSYNC, 1);
+       ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FSYNC, 1);
 
 #ifdef HAVE_FILE_FSYNC_4ARGS
        rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
        mutex_lock(&inode->i_mutex);
 #else
-        /* fsync's caller has already called _fdata{sync,write}, we want
-         * that IO to finish before calling the osc and mdc sync methods */
-        rc = filemap_fdatawait(inode->i_mapping);
+       /* fsync's caller has already called _fdata{sync,write}, we want
+        * that IO to finish before calling the osc and mdc sync methods */
+       rc = filemap_fdatawait(inode->i_mapping);
 #endif
 
-        /* catch async errors that were recorded back when async writeback
-         * failed for pages in this mapping. */
-        if (!S_ISDIR(inode->i_mode)) {
-                err = lli->lli_async_rc;
-                lli->lli_async_rc = 0;
-                if (rc == 0)
-                        rc = err;
+       /* catch async errors that were recorded back when async writeback
+        * failed for pages in this mapping. */
+       if (!S_ISDIR(inode->i_mode)) {
+               err = lli->lli_async_rc;
+               lli->lli_async_rc = 0;
+               if (rc == 0)
+                       rc = err;
                err = lov_read_and_clear_async_rc(lli->lli_clob);
                if (rc == 0)
                        rc = err;
-        }
+       }
 
-        oc = ll_mdscapa_get(inode);
+       oc = ll_mdscapa_get(inode);
        err = md_fsync(ll_i2sbi(inode)->ll_md_exp, ll_inode2fid(inode), oc,
                       &req);
-        capa_put(oc);
-        if (!rc)
-                rc = err;
-        if (!err)
-                ptlrpc_req_finished(req);
+       capa_put(oc);
+       if (!rc)
+               rc = err;
+       if (!err)
+               ptlrpc_req_finished(req);
 
-       if (datasync && S_ISREG(inode->i_mode)) {
+       if (S_ISREG(inode->i_mode)) {
                struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
 
                err = cl_sync_file_range(inode, 0, OBD_OBJECT_EOF,
@@ -2848,7 +2876,8 @@ int ll_fsync(struct file *file, struct dentry *dentry, int datasync)
        RETURN(rc);
 }
 
-int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
+static int
+ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ll_sb_info *sbi = ll_i2sbi(inode);
@@ -2979,7 +3008,114 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
         RETURN(rc);
 }
 
-int ll_file_noflock(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)
+{
+       struct md_op_data       *op_data = NULL;
+       struct mdt_body         *body;
+       struct ptlrpc_request   *req;
+       int                     rc;
+       ENTRY;
+
+       op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen, 0,
+                                    LUSTRE_OPC_ANY, NULL);
+       if (IS_ERR(op_data))
+               RETURN(PTR_ERR(op_data));
+
+       op_data->op_valid = OBD_MD_FLID;
+       rc = md_getattr_name(ll_i2sbi(parent)->ll_md_exp, op_data, &req);
+       ll_finish_md_op_data(op_data);
+       if (rc < 0)
+               RETURN(rc);
+
+       body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
+       if (body == NULL)
+               GOTO(out_req, rc = -EFAULT);
+       if (fid != NULL)
+               *fid = body->fid1;
+out_req:
+       ptlrpc_req_finished(req);
+       RETURN(rc);
+}
+
+int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
+              const char *name, int namelen)
+{
+       struct dentry         *dchild = NULL;
+       struct inode          *child_inode = NULL;
+       struct md_op_data     *op_data;
+       struct ptlrpc_request *request = NULL;
+       struct qstr           qstr;
+       int                    rc;
+       ENTRY;
+
+       CDEBUG(D_VFSTRACE, "migrate %s under "DFID" to MDT%04x\n",
+              name, PFID(ll_inode2fid(parent)), mdtidx);
+
+       op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen,
+                                    0, LUSTRE_OPC_ANY, NULL);
+       if (IS_ERR(op_data))
+               RETURN(PTR_ERR(op_data));
+
+       /* Get child FID first */
+       qstr.hash = full_name_hash(name, namelen);
+       qstr.name = name;
+       qstr.len = namelen;
+       dchild = d_lookup(file->f_dentry, &qstr);
+       if (dchild != NULL && dchild->d_inode != NULL) {
+               op_data->op_fid3 = *ll_inode2fid(dchild->d_inode);
+               if (dchild->d_inode != NULL) {
+                       child_inode = igrab(dchild->d_inode);
+                       ll_invalidate_aliases(child_inode);
+               }
+               dput(dchild);
+       } else {
+               rc = ll_get_fid_by_name(parent, name, namelen,
+                                       &op_data->op_fid3);
+               if (rc != 0)
+                       GOTO(out_free, rc);
+       }
+
+       if (!fid_is_sane(&op_data->op_fid3)) {
+               CERROR("%s: migrate %s , but fid "DFID" is insane\n",
+                      ll_get_fsname(parent->i_sb, NULL, 0), name,
+                      PFID(&op_data->op_fid3));
+               GOTO(out_free, rc = -EINVAL);
+       }
+
+       rc = ll_get_mdt_idx_by_fid(ll_i2sbi(parent), &op_data->op_fid3);
+       if (rc < 0)
+               GOTO(out_free, rc);
+
+       if (rc == mdtidx) {
+               CDEBUG(D_INFO, "%s:"DFID" is already on MDT%d.\n", name,
+                      PFID(&op_data->op_fid3), mdtidx);
+               GOTO(out_free, rc = 0);
+       }
+
+       op_data->op_mds = mdtidx;
+       op_data->op_cli_flags = CLI_MIGRATE;
+       rc = md_rename(ll_i2sbi(parent)->ll_md_exp, op_data, name,
+                      namelen, name, namelen, &request);
+       if (rc == 0)
+               ll_update_times(request, parent);
+
+       ptlrpc_req_finished(request);
+       if (rc != 0)
+               GOTO(out_free, rc);
+
+out_free:
+       if (child_inode != NULL) {
+               clear_nlink(child_inode);
+               iput(child_inode);
+       }
+
+       ll_finish_md_op_data(op_data);
+       RETURN(rc);
+}
+
+static int
+ll_file_noflock(struct file *file, int cmd, struct file_lock *file_lock)
 {
         ENTRY;
 
@@ -3066,16 +3202,16 @@ static int ll_inode_revalidate_fini(struct inode *inode, int rc)
                if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
                        return 0;
        } else if (rc != 0) {
-               CERROR("%s: revalidate FID "DFID" error: rc = %d\n",
-                      ll_get_fsname(inode->i_sb, NULL, 0),
-                      PFID(ll_inode2fid(inode)), rc);
+               CDEBUG_LIMIT((rc == -EACCES || rc == -EIDRM) ? D_INFO : D_ERROR,
+                            "%s: revalidate FID "DFID" error: rc = %d\n",
+                            ll_get_fsname(inode->i_sb, NULL, 0),
+                            PFID(ll_inode2fid(inode)), rc);
        }
 
        return rc;
 }
 
-int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
-                             __u64 ibits)
+static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
 {
         struct inode *inode = dentry->d_inode;
         struct ptlrpc_request *req = NULL;
@@ -3140,12 +3276,12 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
                 struct md_op_data *op_data;
                 int ealen = 0;
 
-                if (S_ISREG(inode->i_mode)) {
-                        rc = ll_get_max_mdsize(sbi, &ealen);
-                        if (rc)
-                                RETURN(rc);
-                        valid |= OBD_MD_FLEASIZE | OBD_MD_FLMODEASIZE;
-                }
+               if (S_ISREG(inode->i_mode)) {
+                       rc = ll_get_default_mdsize(sbi, &ealen);
+                       if (rc)
+                               RETURN(rc);
+                       valid |= OBD_MD_FLEASIZE | OBD_MD_FLMODEASIZE;
+               }
 
                 op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL,
                                              0, ealen, LUSTRE_OPC_ANY,
@@ -3171,19 +3307,47 @@ out:
         return rc;
 }
 
-int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
-                          __u64 ibits)
+static int ll_merge_md_attr(struct inode *inode)
+{
+       struct cl_attr attr = { 0 };
+       int rc;
+
+       LASSERT(ll_i2info(inode)->lli_lsm_md != NULL);
+       rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md,
+                          &attr);
+       if (rc != 0)
+               RETURN(rc);
+
+       ll_i2info(inode)->lli_stripe_dir_size = attr.cat_size;
+       ll_i2info(inode)->lli_stripe_dir_nlink = attr.cat_nlink;
+
+       ll_i2info(inode)->lli_lvb.lvb_atime = attr.cat_atime;
+       ll_i2info(inode)->lli_lvb.lvb_mtime = attr.cat_mtime;
+       ll_i2info(inode)->lli_lvb.lvb_ctime = attr.cat_ctime;
+
+       RETURN(0);
+}
+
+static int
+ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
 {
        struct inode    *inode = dentry->d_inode;
        int              rc;
        ENTRY;
 
-       rc = __ll_inode_revalidate_it(dentry, it, ibits);
+       rc = __ll_inode_revalidate(dentry, ibits);
        if (rc != 0)
                RETURN(rc);
 
        /* if object isn't regular file, don't validate size */
        if (!S_ISREG(inode->i_mode)) {
+               if (S_ISDIR(inode->i_mode) &&
+                   ll_i2info(inode)->lli_lsm_md != NULL) {
+                       rc = ll_merge_md_attr(inode);
+                       if (rc != 0)
+                               RETURN(rc);
+               }
+
                LTIME_S(inode->i_atime) = ll_i2info(inode)->lli_lvb.lvb_atime;
                LTIME_S(inode->i_mtime) = ll_i2info(inode)->lli_lvb.lvb_mtime;
                LTIME_S(inode->i_ctime) = ll_i2info(inode)->lli_lvb.lvb_ctime;
@@ -3201,50 +3365,49 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
        RETURN(rc);
 }
 
-int ll_getattr_it(struct vfsmount *mnt, struct dentry *de,
-                  struct lookup_intent *it, struct kstat *stat)
+int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat)
 {
         struct inode *inode = de->d_inode;
         struct ll_sb_info *sbi = ll_i2sbi(inode);
         struct ll_inode_info *lli = ll_i2info(inode);
         int res = 0;
 
-        res = ll_inode_revalidate_it(de, it, MDS_INODELOCK_UPDATE |
-                                             MDS_INODELOCK_LOOKUP);
+       res = ll_inode_revalidate(de, MDS_INODELOCK_UPDATE |
+                                     MDS_INODELOCK_LOOKUP);
         ll_stats_ops_tally(sbi, LPROC_LL_GETATTR, 1);
 
         if (res)
                 return res;
 
-        stat->dev = inode->i_sb->s_dev;
-        if (ll_need_32bit_api(sbi))
-                stat->ino = cl_fid_build_ino(&lli->lli_fid, 1);
-        else
-                stat->ino = inode->i_ino;
-        stat->mode = inode->i_mode;
-        stat->nlink = inode->i_nlink;
-        stat->uid = inode->i_uid;
-        stat->gid = inode->i_gid;
+       stat->dev = inode->i_sb->s_dev;
+       if (ll_need_32bit_api(sbi))
+               stat->ino = cl_fid_build_ino(&lli->lli_fid, 1);
+       else
+               stat->ino = inode->i_ino;
+       stat->mode = inode->i_mode;
+       stat->uid = inode->i_uid;
+       stat->gid = inode->i_gid;
        stat->rdev = inode->i_rdev;
-        stat->atime = inode->i_atime;
-        stat->mtime = inode->i_mtime;
-        stat->ctime = inode->i_ctime;
+       stat->atime = inode->i_atime;
+       stat->mtime = inode->i_mtime;
+       stat->ctime = inode->i_ctime;
        stat->blksize = 1 << inode->i_blkbits;
+       stat->blocks = inode->i_blocks;
 
-        stat->size = i_size_read(inode);
-        stat->blocks = inode->i_blocks;
+       if (S_ISDIR(inode->i_mode) &&
+               ll_i2info(inode)->lli_lsm_md != NULL) {
+               stat->nlink = lli->lli_stripe_dir_nlink;
+               stat->size = lli->lli_stripe_dir_size;
+       } else {
+               stat->nlink = inode->i_nlink;
+               stat->size = i_size_read(inode);
+       }
 
         return 0;
 }
-int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat)
-{
-        struct lookup_intent it = { .it_op = IT_GETATTR };
 
-        return ll_getattr_it(mnt, de, &it, stat);
-}
-
-int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
-                __u64 start, __u64 len)
+static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+                    __u64 start, __u64 len)
 {
         int rc;
         size_t num_bytes;
@@ -3276,7 +3439,7 @@ int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
         return rc;
 }
 
-struct posix_acl * ll_get_acl(struct inode *inode, int type)
+struct posix_acl *ll_get_acl(struct inode *inode, int type)
 {
        struct ll_inode_info *lli = ll_i2info(inode);
        struct posix_acl *acl = NULL;
@@ -3347,10 +3510,8 @@ int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
         * need to do it before permission check. */
 
         if (inode == inode->i_sb->s_root->d_inode) {
-                struct lookup_intent it = { .it_op = IT_LOOKUP };
-
-                rc = __ll_inode_revalidate_it(inode->i_sb->s_root, &it,
-                                              MDS_INODELOCK_LOOKUP);
+               rc = __ll_inode_revalidate(inode->i_sb->s_root,
+                                          MDS_INODELOCK_LOOKUP);
                 if (rc)
                         RETURN(rc);
         }
@@ -3505,8 +3666,9 @@ void ll_iocontrol_unregister(void *magic)
 EXPORT_SYMBOL(ll_iocontrol_register);
 EXPORT_SYMBOL(ll_iocontrol_unregister);
 
-enum llioc_iter ll_iocontrol_call(struct inode *inode, struct file *file,
-                        unsigned int cmd, unsigned long arg, int *rcp)
+static enum llioc_iter
+ll_iocontrol_call(struct inode *inode, struct file *file,
+                 unsigned int cmd, unsigned long arg, int *rcp)
 {
         enum llioc_iter ret = LLIOC_CONT;
         struct llioc_data *data;
@@ -3556,11 +3718,24 @@ int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf)
                LASSERT(lock != NULL);
                LASSERT(ldlm_has_layout(lock));
                if (result == 0) {
+                       struct lustre_md *md = conf->u.coc_md;
+                       __u32 gen = LL_LAYOUT_GEN_EMPTY;
+
                        /* it can only be allowed to match after layout is
                         * applied to inode otherwise false layout would be
                         * seen. Applying layout shoud happen before dropping
                         * the intent lock. */
                        ldlm_lock_allow_match(lock);
+
+                       lli->lli_has_smd = lsm_has_objects(md->lsm);
+                       if (md->lsm != NULL)
+                               gen = md->lsm->lsm_layout_gen;
+
+                       CDEBUG(D_VFSTRACE,
+                              DFID ": layout version change: %u -> %u\n",
+                              PFID(&lli->lli_fid), ll_layout_version_get(lli),
+                              gen);
+                       ll_layout_version_set(lli, gen);
                }
        }
        RETURN(result);
@@ -3593,7 +3768,7 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock)
         * 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_max_mdsize(sbi, &lmmsize);
+       rc = ll_get_default_mdsize(sbi, &lmmsize);
        if (rc == 0)
                rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
                                OBD_MD_FLXATTR, XATTR_NAME_LOV, NULL, 0,
@@ -3603,7 +3778,7 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock)
                RETURN(rc);
 
        body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
-       if (body == NULL || body->eadatasize > lmmsize)
+       if (body == NULL)
                GOTO(out, rc = -EPROTO);
 
        lmmsize = body->eadatasize;
@@ -3674,7 +3849,7 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode,
                if (lvb_ready) {
                        /* layout_gen must be valid if layout lock is not
                         * cancelled and stripe has already set */
-                       *gen = lli->lli_layout_gen;
+                       *gen = ll_layout_version_get(lli);
                        rc = 0;
                }
                GOTO(out, rc);
@@ -3775,32 +3950,20 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen)
        int rc;
        ENTRY;
 
-       *gen = lli->lli_layout_gen;
-       if (!(sbi->ll_flags & LL_SBI_LAYOUT_LOCK))
+       *gen = ll_layout_version_get(lli);
+       if (!(sbi->ll_flags & LL_SBI_LAYOUT_LOCK) || *gen != LL_LAYOUT_GEN_NONE)
                RETURN(0);
 
        /* sanity checks */
        LASSERT(fid_is_sane(ll_inode2fid(inode)));
        LASSERT(S_ISREG(inode->i_mode));
 
-       /* mostly layout lock is caching on the local side, so try to match
-        * it before grabbing layout lock mutex. */
-       mode = ll_take_md_lock(inode, MDS_INODELOCK_LAYOUT, &lockh, 0,
-                              LCK_CR | LCK_CW | LCK_PR | LCK_PW);
-       if (mode != 0) { /* hit cached lock */
-               rc = ll_layout_lock_set(&lockh, mode, inode, gen, false);
-               if (rc == 0)
-                       RETURN(0);
-
-               /* better hold lli_layout_mutex to try again otherwise
-                * it will have starvation problem. */
-       }
-
        /* take layout lock mutex to enqueue layout lock exclusively. */
        mutex_lock(&lli->lli_layout_mutex);
 
 again:
-       /* try again. Maybe somebody else has done this. */
+       /* mostly layout lock is caching on the local side, so try to match
+        * it before grabbing layout lock mutex. */
        mode = ll_take_md_lock(inode, MDS_INODELOCK_LAYOUT, &lockh, 0,
                               LCK_CR | LCK_CW | LCK_PR | LCK_PW);
        if (mode != 0) { /* hit cached lock */
@@ -3813,7 +3976,7 @@ again:
        }
 
        op_data = ll_prep_md_op_data(NULL, inode, inode, NULL,
-                       0, 0, LUSTRE_OPC_ANY, NULL);
+                                    0, 0, LUSTRE_OPC_ANY, NULL);
        if (IS_ERR(op_data)) {
                mutex_unlock(&lli->lli_layout_mutex);
                RETURN(PTR_ERR(op_data));