+ struct ll_inode_info *lli = ll_i2info(inode);
+
+ LASSERT(S_ISDIR(inode->i_mode));
+
+ if (lli->lli_lsm_md != NULL) {
+ lmv_free_memmd(lli->lli_lsm_md);
+ lli->lli_lsm_md = NULL;
+ }
+}
+
+static struct inode *ll_iget_anon_dir(struct super_block *sb,
+ const struct lu_fid *fid,
+ struct lustre_md *md)
+{
+ struct ll_sb_info *sbi = ll_s2sbi(sb);
+ struct mdt_body *body = md->body;
+ struct inode *inode;
+ ino_t ino;
+ ENTRY;
+
+ ino = cl_fid_build_ino(fid, sbi->ll_flags & LL_SBI_32BIT_API);
+ inode = iget_locked(sb, ino);
+ if (inode == NULL) {
+ CERROR("%s: failed get simple inode "DFID": rc = -ENOENT\n",
+ ll_get_fsname(sb, NULL, 0), PFID(fid));
+ RETURN(ERR_PTR(-ENOENT));
+ }
+
+ if (inode->i_state & I_NEW) {
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct lmv_stripe_md *lsm = md->lmv;
+
+ inode->i_mode = (inode->i_mode & ~S_IFMT) |
+ (body->mbo_mode & S_IFMT);
+ LASSERTF(S_ISDIR(inode->i_mode), "Not slave inode "DFID"\n",
+ PFID(fid));
+
+ LTIME_S(inode->i_mtime) = 0;
+ LTIME_S(inode->i_atime) = 0;
+ LTIME_S(inode->i_ctime) = 0;
+ inode->i_rdev = 0;
+
+ /* initializing backing dev info. */
+ inode->i_mapping->backing_dev_info =
+ &s2lsi(inode->i_sb)->lsi_bdi;
+ inode->i_op = &ll_dir_inode_operations;
+ inode->i_fop = &ll_dir_operations;
+ lli->lli_fid = *fid;
+ ll_lli_init(lli);
+
+ LASSERT(lsm != NULL);
+ /* master object FID */
+ lli->lli_pfid = body->mbo_fid1;
+ CDEBUG(D_INODE, "lli %p slave "DFID" master "DFID"\n",
+ lli, PFID(fid), PFID(&lli->lli_pfid));
+ unlock_new_inode(inode);
+ }
+
+ RETURN(inode);
+}
+
+static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md)
+{
+ struct lu_fid *fid;
+ struct lmv_stripe_md *lsm = md->lmv;
+ int i;
+
+ LASSERT(lsm != NULL);
+ /* XXX sigh, this lsm_root initialization should be in
+ * LMV layer, but it needs ll_iget right now, so we
+ * put this here right now. */
+ for (i = 0; i < lsm->lsm_md_stripe_count; i++) {
+ fid = &lsm->lsm_md_oinfo[i].lmo_fid;
+ LASSERT(lsm->lsm_md_oinfo[i].lmo_root == NULL);
+ /* Unfortunately ll_iget will call ll_update_inode,
+ * where the initialization of slave inode is slightly
+ * different, so it reset lsm_md to NULL to avoid
+ * initializing lsm for slave inode. */
+ /* For migrating inode, master stripe and master object will
+ * be same, so we only need assign this inode */
+ if (lsm->lsm_md_hash_type & LMV_HASH_FLAG_MIGRATION && i == 0)
+ lsm->lsm_md_oinfo[i].lmo_root = inode;
+ else
+ lsm->lsm_md_oinfo[i].lmo_root =
+ ll_iget_anon_dir(inode->i_sb, fid, md);
+
+ if (IS_ERR(lsm->lsm_md_oinfo[i].lmo_root)) {
+ int rc = PTR_ERR(lsm->lsm_md_oinfo[i].lmo_root);
+
+ lsm->lsm_md_oinfo[i].lmo_root = NULL;
+ return rc;
+ }
+ }
+
+ /* Here is where the lsm is being initialized(fill lmo_info) after
+ * client retrieve MD stripe information from MDT. */
+ return md_update_lsm_md(ll_i2mdexp(inode), lsm, md->body,
+ ll_md_blocking_ast);
+}
+
+static inline int lli_lsm_md_eq(const struct lmv_stripe_md *lsm_md1,
+ const struct lmv_stripe_md *lsm_md2)
+{
+ return lsm_md1->lsm_md_magic == lsm_md2->lsm_md_magic &&
+ lsm_md1->lsm_md_stripe_count == lsm_md2->lsm_md_stripe_count &&
+ lsm_md1->lsm_md_master_mdt_index ==
+ lsm_md2->lsm_md_master_mdt_index &&
+ lsm_md1->lsm_md_hash_type == lsm_md2->lsm_md_hash_type &&
+ lsm_md1->lsm_md_layout_version ==
+ lsm_md2->lsm_md_layout_version &&
+ strcmp(lsm_md1->lsm_md_pool_name,
+ lsm_md2->lsm_md_pool_name) == 0;
+}
+
+static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md)
+{
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct lmv_stripe_md *lsm = md->lmv;
+ int rc;
+ ENTRY;
+
+ LASSERT(S_ISDIR(inode->i_mode));
+ CDEBUG(D_INODE, "update lsm %p of "DFID"\n", lli->lli_lsm_md,
+ PFID(ll_inode2fid(inode)));
+
+ /* no striped information from request. */
+ if (lsm == NULL) {
+ if (lli->lli_lsm_md == NULL) {
+ RETURN(0);
+ } else if (lli->lli_lsm_md->lsm_md_hash_type &
+ LMV_HASH_FLAG_MIGRATION) {
+ /* migration is done, the temporay MIGRATE layout has
+ * been removed */
+ CDEBUG(D_INODE, DFID" finish migration.\n",
+ PFID(ll_inode2fid(inode)));
+ lmv_free_memmd(lli->lli_lsm_md);
+ lli->lli_lsm_md = NULL;
+ RETURN(0);
+ } else {
+ /* The lustre_md from req does not include stripeEA,
+ * see ll_md_setattr */
+ RETURN(0);
+ }
+ }
+
+ /* set the directory layout */
+ if (lli->lli_lsm_md == NULL) {
+
+ rc = ll_init_lsm_md(inode, md);
+ if (rc != 0)
+ RETURN(rc);
+
+ lli->lli_lsm_md = lsm;
+ /* set lsm_md to NULL, so the following free lustre_md
+ * will not free this lsm */
+ md->lmv = NULL;
+ CDEBUG(D_INODE, "Set lsm %p magic %x to "DFID"\n", lsm,
+ lsm->lsm_md_magic, PFID(ll_inode2fid(inode)));
+ RETURN(0);
+ }
+
+ /* Compare the old and new stripe information */
+ if (!lsm_md_eq(lli->lli_lsm_md, lsm)) {
+ struct lmv_stripe_md *old_lsm = lli->lli_lsm_md;
+ int idx;
+
+ CERROR("%s: inode "DFID"(%p)'s lmv layout mismatch (%p)/(%p)"
+ "magic:0x%x/0x%x stripe count: %d/%d master_mdt: %d/%d"
+ "hash_type:0x%x/0x%x layout: 0x%x/0x%x pool:%s/%s\n",
+ ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid),
+ inode, lsm, old_lsm,
+ lsm->lsm_md_magic, old_lsm->lsm_md_magic,
+ lsm->lsm_md_stripe_count,
+ old_lsm->lsm_md_stripe_count,
+ lsm->lsm_md_master_mdt_index,
+ old_lsm->lsm_md_master_mdt_index,
+ lsm->lsm_md_hash_type, old_lsm->lsm_md_hash_type,
+ lsm->lsm_md_layout_version,
+ old_lsm->lsm_md_layout_version,
+ lsm->lsm_md_pool_name,
+ old_lsm->lsm_md_pool_name);
+
+ for (idx = 0; idx < old_lsm->lsm_md_stripe_count; idx++) {
+ CERROR("%s: sub FIDs in old lsm idx %d, old: "DFID"\n",
+ ll_get_fsname(inode->i_sb, NULL, 0), idx,
+ PFID(&old_lsm->lsm_md_oinfo[idx].lmo_fid));
+ }
+
+ for (idx = 0; idx < lsm->lsm_md_stripe_count; idx++) {
+ CERROR("%s: sub FIDs in new lsm idx %d, new: "DFID"\n",
+ ll_get_fsname(inode->i_sb, NULL, 0), idx,
+ PFID(&lsm->lsm_md_oinfo[idx].lmo_fid));
+ }
+
+ RETURN(-EIO);
+ }
+
+ rc = md_update_lsm_md(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md,
+ md->body, ll_md_blocking_ast);
+
+ RETURN(rc);