Whamcloud - gitweb
LU-2689 interop: use stripe md in ll_update_inode()
[fs/lustre-release.git] / lustre / llite / llite_lib.c
index acdec48..6e91365 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2012, Whamcloud, Inc.
+ * Copyright (c) 2011, 2012, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -94,11 +94,7 @@ static struct ll_sb_info *ll_init_sbi(void)
         si_meminfo(&si);
         pages = si.totalram - si.totalhigh;
         if (pages >> (20 - CFS_PAGE_SHIFT) < 512) {
-#ifdef HAVE_BGL_SUPPORT
-               lru_page_max = pages / 4;
-#else
                lru_page_max = pages / 2;
-#endif
        } else {
                lru_page_max = (pages / 4) * 3;
        }
@@ -221,7 +217,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                                   OBD_CONNECT_RMT_CLIENT | OBD_CONNECT_VBR    |
                                   OBD_CONNECT_FULL20   | OBD_CONNECT_64BITHASH|
                                  OBD_CONNECT_EINPROGRESS |
-                                 OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE;
+                                 OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE |
+                                 OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS;
 
         if (sbi->ll_flags & LL_SBI_SOM_PREVIEW)
                 data->ocd_connect_flags |= OBD_CONNECT_SOM;
@@ -267,7 +264,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
         if (sbi->ll_flags & LL_SBI_RMT_CLIENT)
                 data->ocd_connect_flags |= OBD_CONNECT_RMT_CLIENT_FORCE;
 
-        data->ocd_brw_size = PTLRPC_MAX_BRW_SIZE;
+       data->ocd_brw_size = MD_MAX_BRW_SIZE;
 
         err = obd_connect(NULL, &sbi->ll_md_exp, obd, &sbi->ll_sb_uuid, data, NULL);
         if (err == -EBUSY) {
@@ -281,51 +278,51 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                 GOTO(out, err);
         }
 
-        err = obd_fid_init(sbi->ll_md_exp);
-        if (err) {
-                CERROR("Can't init metadata layer FID infrastructure, "
-                       "rc %d\n", err);
-                GOTO(out_md, err);
-        }
+       sbi->ll_md_exp->exp_connect_data = *data;
+
+       /* For mount, we only need fs info from MDT0, and also in DNE, it
+        * can make sure the client can be mounted as long as MDT0 is
+        * avaible */
+       err = obd_statfs(NULL, sbi->ll_md_exp, osfs,
+                       cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
+                       OBD_STATFS_FOR_MDT0);
+       if (err)
+               GOTO(out_md, err);
+
+       /* This needs to be after statfs to ensure connect has finished.
+        * Note that "data" does NOT contain the valid connect reply.
+        * If connecting to a 1.8 server there will be no LMV device, so
+        * we can access the MDC export directly and exp_connect_flags will
+        * be non-zero, but if accessing an upgraded 2.1 server it will
+        * have the correct flags filled in.
+        * XXX: fill in the LMV exp_connect_flags from MDC(s). */
+       valid = exp_connect_flags(sbi->ll_md_exp) & CLIENT_CONNECT_MDT_REQD;
+       if (exp_connect_flags(sbi->ll_md_exp) != 0 &&
+           valid != CLIENT_CONNECT_MDT_REQD) {
+               char *buf;
+
+               OBD_ALLOC_WAIT(buf, CFS_PAGE_SIZE);
+               obd_connect_flags2str(buf, CFS_PAGE_SIZE,
+                                     valid ^ CLIENT_CONNECT_MDT_REQD, ",");
+               LCONSOLE_ERROR_MSG(0x170, "Server %s does not support "
+                                  "feature(s) needed for correct operation "
+                                  "of this client (%s). Please upgrade "
+                                  "server or downgrade client.\n",
+                                  sbi->ll_md_exp->exp_obd->obd_name, buf);
+               OBD_FREE(buf, CFS_PAGE_SIZE);
+               GOTO(out_md, err = -EPROTO);
+       }
 
-        err = obd_statfs(NULL, sbi->ll_md_exp, osfs,
-                         cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), 0);
-        if (err)
-                GOTO(out_md_fid, err);
-
-        /* This needs to be after statfs to ensure connect has finished.
-         * Note that "data" does NOT contain the valid connect reply.
-         * If connecting to a 1.8 server there will be no LMV device, so
-         * we can access the MDC export directly and exp_connect_flags will
-         * be non-zero, but if accessing an upgraded 2.1 server it will
-         * have the correct flags filled in.
-         * XXX: fill in the LMV exp_connect_flags from MDC(s). */
-        valid = sbi->ll_md_exp->exp_connect_flags & CLIENT_CONNECT_MDT_REQD;
-        if (sbi->ll_md_exp->exp_connect_flags != 0 &&
-            valid != CLIENT_CONNECT_MDT_REQD) {
-                char *buf;
-
-                OBD_ALLOC_WAIT(buf, CFS_PAGE_SIZE);
-                obd_connect_flags2str(buf, CFS_PAGE_SIZE,
-                                      valid ^ CLIENT_CONNECT_MDT_REQD, ",");
-                LCONSOLE_ERROR_MSG(0x170, "Server %s does not support "
-                                   "feature(s) needed for correct operation "
-                                   "of this client (%s). Please upgrade "
-                                   "server or downgrade client.\n",
-                                   sbi->ll_md_exp->exp_obd->obd_name, buf);
-                OBD_FREE(buf, CFS_PAGE_SIZE);
-                GOTO(out_md, err = -EPROTO);
-        }
-
-        size = sizeof(*data);
-        err = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_CONN_DATA),
-                           KEY_CONN_DATA,  &size, data, NULL);
-        if (err) {
-                CERROR("Get connect data failed: %d \n", err);
-                GOTO(out_md, err);
-        }
+       size = sizeof(*data);
+       err = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_CONN_DATA),
+                          KEY_CONN_DATA,  &size, data, NULL);
+       if (err) {
+               CERROR("%s: Get connect data failed: rc = %d\n",
+                      sbi->ll_md_exp->exp_obd->obd_name, err);
+               GOTO(out_md, err);
+       }
 
-        LASSERT(osfs->os_bsize);
+       LASSERT(osfs->os_bsize);
         sb->s_blocksize = osfs->os_bsize;
         sb->s_blocksize_bits = log2(osfs->os_bsize);
         sb->s_magic = LL_SUPER_MAGIC;
@@ -379,21 +376,21 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
         if (data->ocd_connect_flags & OBD_CONNECT_64BITHASH)
                 sbi->ll_flags |= LL_SBI_64BIT_HASH;
 
-        if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE)
-                sbi->ll_md_brw_size = data->ocd_brw_size;
-        else
-                sbi->ll_md_brw_size = CFS_PAGE_SIZE;
+       if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE)
+               sbi->ll_md_brw_size = data->ocd_brw_size;
+       else
+               sbi->ll_md_brw_size = CFS_PAGE_SIZE;
 
        if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) {
                LCONSOLE_INFO("Layout lock feature supported.\n");
                sbi->ll_flags |= LL_SBI_LAYOUT_LOCK;
        }
 
-        obd = class_name2obd(dt);
-        if (!obd) {
-                CERROR("DT %s: not setup or attached\n", dt);
-                GOTO(out_md_fid, err = -ENODEV);
-        }
+       obd = class_name2obd(dt);
+       if (!obd) {
+               CERROR("DT %s: not setup or attached\n", dt);
+               GOTO(out_md, err = -ENODEV);
+       }
 
         data->ocd_connect_flags = OBD_CONNECT_GRANT     | OBD_CONNECT_VERSION  |
                                   OBD_CONNECT_REQPORTAL | OBD_CONNECT_BRW_SIZE |
@@ -404,7 +401,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                                   OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH |
                                   OBD_CONNECT_MAXBYTES |
                                  OBD_CONNECT_EINPROGRESS |
-                                 OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE;
+                                 OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE |
+                                 OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS;
 
         if (sbi->ll_flags & LL_SBI_SOM_PREVIEW)
                 data->ocd_connect_flags |= OBD_CONNECT_SOM;
@@ -435,82 +433,83 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
         obd->obd_upcall.onu_owner = &sbi->ll_lco;
         obd->obd_upcall.onu_upcall = cl_ocd_update;
 
-        data->ocd_brw_size = PTLRPC_MAX_BRW_SIZE;
-
-        err = obd_connect(NULL, &sbi->ll_dt_exp, obd, &sbi->ll_sb_uuid, data, NULL);
-        if (err == -EBUSY) {
-                LCONSOLE_ERROR_MSG(0x150, "An OST (dt %s) is performing "
-                                   "recovery, of which this client is not a "
-                                   "part.  Please wait for recovery to "
-                                   "complete, abort, or time out.\n", dt);
-                GOTO(out_md_fid, err);
-        } else if (err) {
-                CERROR("Cannot connect to %s: rc = %d\n", dt, err);
-                GOTO(out_md_fid, err);
-        }
+       data->ocd_brw_size = DT_MAX_BRW_SIZE;
+
+       err = obd_connect(NULL, &sbi->ll_dt_exp, obd, &sbi->ll_sb_uuid, data,
+                         NULL);
+       if (err == -EBUSY) {
+               LCONSOLE_ERROR_MSG(0x150, "An OST (dt %s) is performing "
+                                  "recovery, of which this client is not a "
+                                  "part.  Please wait for recovery to "
+                                  "complete, abort, or time out.\n", dt);
+               GOTO(out_md, err);
+       } else if (err) {
+               CERROR("%s: Cannot connect to %s: rc = %d\n",
+                      sbi->ll_dt_exp->exp_obd->obd_name, dt, err);
+               GOTO(out_md, err);
+       }
 
-        err = obd_fid_init(sbi->ll_dt_exp);
-        if (err) {
-                CERROR("Can't init data layer FID infrastructure, "
-                       "rc %d\n", err);
-                GOTO(out_dt, err);
-        }
+       sbi->ll_dt_exp->exp_connect_data = *data;
 
        mutex_lock(&sbi->ll_lco.lco_lock);
-        sbi->ll_lco.lco_flags = data->ocd_connect_flags;
-        sbi->ll_lco.lco_md_exp = sbi->ll_md_exp;
-        sbi->ll_lco.lco_dt_exp = sbi->ll_dt_exp;
+       sbi->ll_lco.lco_flags = data->ocd_connect_flags;
+       sbi->ll_lco.lco_md_exp = sbi->ll_md_exp;
+       sbi->ll_lco.lco_dt_exp = sbi->ll_dt_exp;
        mutex_unlock(&sbi->ll_lco.lco_lock);
 
-        fid_zero(&sbi->ll_root_fid);
-        err = md_getstatus(sbi->ll_md_exp, &sbi->ll_root_fid, &oc);
-        if (err) {
-                CERROR("cannot mds_connect: rc = %d\n", err);
-                GOTO(out_lock_cn_cb, err);
-        }
-        if (!fid_is_sane(&sbi->ll_root_fid)) {
-                CERROR("Invalid root fid during mount\n");
-                GOTO(out_lock_cn_cb, err = -EINVAL);
-        }
-        CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid));
+       fid_zero(&sbi->ll_root_fid);
+       err = md_getstatus(sbi->ll_md_exp, &sbi->ll_root_fid, &oc);
+       if (err) {
+               CERROR("cannot mds_connect: rc = %d\n", err);
+               GOTO(out_dt, err);
+       }
+       if (!fid_is_sane(&sbi->ll_root_fid)) {
+               CERROR("%s: Invalid root fid "DFID" during mount\n",
+                      sbi->ll_md_exp->exp_obd->obd_name,
+                      PFID(&sbi->ll_root_fid));
+               GOTO(out_dt, err = -EINVAL);
+       }
+       CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid));
 
-        sb->s_op = &lustre_super_operations;
+       sb->s_op = &lustre_super_operations;
 #if THREAD_SIZE >= 8192 /*b=17630*/
         sb->s_export_op = &lustre_export_operations;
 #endif
 
-        /* make root inode
-         * XXX: move this to after cbd setup? */
-        valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMDSCAPA;
-        if (sbi->ll_flags & LL_SBI_RMT_CLIENT)
-                valid |= OBD_MD_FLRMTPERM;
-        else if (sbi->ll_flags & LL_SBI_ACL)
-                valid |= OBD_MD_FLACL;
-
-        OBD_ALLOC_PTR(op_data);
-        if (op_data == NULL)
-                GOTO(out_lock_cn_cb, err = -ENOMEM);
-
-        op_data->op_fid1 = sbi->ll_root_fid;
-        op_data->op_mode = 0;
-        op_data->op_capa1 = oc;
-        op_data->op_valid = valid;
+       /* make root inode
+        * XXX: move this to after cbd setup? */
+       valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMDSCAPA;
+       if (sbi->ll_flags & LL_SBI_RMT_CLIENT)
+               valid |= OBD_MD_FLRMTPERM;
+       else if (sbi->ll_flags & LL_SBI_ACL)
+               valid |= OBD_MD_FLACL;
+
+       OBD_ALLOC_PTR(op_data);
+       if (op_data == NULL)
+               GOTO(out_dt, err = -ENOMEM);
+
+       op_data->op_fid1 = sbi->ll_root_fid;
+       op_data->op_mode = 0;
+       op_data->op_capa1 = oc;
+       op_data->op_valid = valid;
+
+       err = md_getattr(sbi->ll_md_exp, op_data, &request);
+       if (oc)
+               capa_put(oc);
+       OBD_FREE_PTR(op_data);
+       if (err) {
+               CERROR("%s: md_getattr failed for root: rc = %d\n",
+                      sbi->ll_md_exp->exp_obd->obd_name, err);
+               GOTO(out_dt, err);
+       }
 
-        err = md_getattr(sbi->ll_md_exp, op_data, &request);
-        if (oc)
-                capa_put(oc);
-        OBD_FREE_PTR(op_data);
-        if (err) {
-                CERROR("md_getattr failed for root: rc = %d\n", err);
-                GOTO(out_lock_cn_cb, err);
-        }
-        err = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp,
-                               sbi->ll_md_exp, &lmd);
-        if (err) {
-                CERROR("failed to understand root inode md: rc = %d\n", err);
-                ptlrpc_req_finished (request);
-                GOTO(out_lock_cn_cb, err);
-        }
+       err = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp,
+                              sbi->ll_md_exp, &lmd);
+       if (err) {
+               CERROR("failed to understand root inode md: rc = %d\n", err);
+               ptlrpc_req_finished(request);
+               GOTO(out_dt, err);
+       }
 
         LASSERT(fid_is_sane(&sbi->ll_root_fid));
         root = ll_iget(sb, cl_fid_build_ino(&sbi->ll_root_fid, 0), &lmd);
@@ -559,7 +558,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
        if (sb->s_root == NULL) {
                CERROR("%s: can't make root dentry\n",
                        ll_get_fsname(sb, NULL, 0));
-               GOTO(out_lock_cn_cb, err = -ENOMEM);
+               GOTO(out_root, err = -ENOMEM);
        }
 
 #ifdef HAVE_DCACHE_LOCK
@@ -590,13 +589,11 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
 out_root:
         if (root)
                 iput(root);
-out_lock_cn_cb:
-        obd_fid_fini(sbi->ll_dt_exp);
 out_dt:
         obd_disconnect(sbi->ll_dt_exp);
         sbi->ll_dt_exp = NULL;
-out_md_fid:
-        obd_fid_fini(sbi->ll_md_exp);
+       /* Make sure all OScs are gone, since cl_cache is accessing sbi. */
+       obd_zombie_barrier();
 out_md:
         obd_disconnect(sbi->ll_md_exp);
         sbi->ll_md_exp = NULL;
@@ -625,17 +622,17 @@ int ll_get_max_mdsize(struct ll_sb_info *sbi, int *lmmsize)
 
 void ll_dump_inode(struct inode *inode)
 {
-        struct list_head *tmp;
-        int dentry_count = 0;
+       struct ll_d_hlist_node *tmp;
+       int dentry_count = 0;
 
-        LASSERT(inode != NULL);
+       LASSERT(inode != NULL);
 
-        list_for_each(tmp, &inode->i_dentry)
-                dentry_count++;
+       ll_d_hlist_for_each(tmp, &inode->i_dentry)
+               dentry_count++;
 
-        CERROR("inode %p dump: dev=%s ino=%lu mode=%o count=%u, %d dentries\n",
-               inode, ll_i2mdexp(inode)->exp_obd->obd_name, inode->i_ino,
-               inode->i_mode, atomic_read(&inode->i_count), dentry_count);
+       CERROR("inode %p dump: dev=%s ino=%lu mode=%o count=%u, %d dentries\n",
+              inode, ll_i2mdexp(inode)->exp_obd->obd_name, inode->i_ino,
+              inode->i_mode, atomic_read(&inode->i_count), dentry_count);
 }
 
 void lustre_dump_dentry(struct dentry *dentry, int recur)
@@ -684,13 +681,14 @@ void client_common_put_super(struct super_block *sb)
 
         cfs_list_del(&sbi->ll_conn_chain);
 
-        obd_fid_fini(sbi->ll_dt_exp);
         obd_disconnect(sbi->ll_dt_exp);
         sbi->ll_dt_exp = NULL;
+       /* wait till all OSCs are gone, since cl_cache is accessing sbi.
+        * see LU-2543. */
+       obd_zombie_barrier();
 
         lprocfs_unregister_mountpoint(sbi);
 
-        obd_fid_fini(sbi->ll_md_exp);
         obd_disconnect(sbi->ll_md_exp);
         sbi->ll_md_exp = NULL;
 
@@ -918,6 +916,7 @@ void ll_lli_init(struct ll_inode_info *lli)
        mutex_init(&lli->lli_och_mutex);
        spin_lock_init(&lli->lli_agl_lock);
        lli->lli_has_smd = false;
+       lli->lli_layout_gen = LL_LAYOUT_GEN_NONE;
        lli->lli_clob = NULL;
 
        LASSERT(lli->lli_vfs_inode.i_mode != 0);
@@ -939,6 +938,7 @@ void ll_lli_init(struct ll_inode_info *lli)
                CFS_INIT_LIST_HEAD(&lli->lli_agl_list);
                lli->lli_agl_index = 0;
                lli->lli_async_rc = 0;
+               lli->lli_volatile = false;
        }
        mutex_init(&lli->lli_layout_mutex);
 }
@@ -991,14 +991,14 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
         if (err)
                 GOTO(out_free, err);
 
-        err = ll_bdi_init(&lsi->lsi_bdi);
-        if (err)
-                GOTO(out_free, err);
-        lsi->lsi_flags |= LSI_BDI_INITIALIZED;
-        lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY;
-        err = ll_bdi_register(&lsi->lsi_bdi);
-        if (err)
-                GOTO(out_free, err);
+       err = bdi_init(&lsi->lsi_bdi);
+       if (err)
+               GOTO(out_free, err);
+       lsi->lsi_flags |= LSI_BDI_INITIALIZED;
+       lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY;
+       err = ll_bdi_register(&lsi->lsi_bdi);
+       if (err)
+               GOTO(out_free, err);
 
 #ifdef HAVE_SB_BDI
         sb->s_bdi = &lsi->lsi_bdi;
@@ -1107,10 +1107,10 @@ void ll_put_super(struct super_block *sb)
         if (profilenm)
                 class_del_profile(profilenm);
 
-        if (lsi->lsi_flags & LSI_BDI_INITIALIZED) {
-                ll_bdi_destroy(&lsi->lsi_bdi);
-                lsi->lsi_flags &= ~LSI_BDI_INITIALIZED;
-        }
+       if (lsi->lsi_flags & LSI_BDI_INITIALIZED) {
+               bdi_destroy(&lsi->lsi_bdi);
+               lsi->lsi_flags &= ~LSI_BDI_INITIALIZED;
+       }
 
         ll_free_sbi(sb);
         lsi->lsi_llsbi = NULL;
@@ -1460,6 +1460,13 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
                        LTIME_S(attr->ia_mtime), LTIME_S(attr->ia_ctime),
                        cfs_time_current_sec());
 
+       /* If we are changing file size, file content is modified, flag it. */
+       if (attr->ia_valid & ATTR_SIZE) {
+               spin_lock(&lli->lli_lock);
+               lli->lli_flags |= LLIF_DATA_MODIFIED;
+               spin_unlock(&lli->lli_lock);
+       }
+
         /* We always do an MDS RPC, even if we're only changing the size;
          * only the MDS knows whether truncate() should fail with -ETXTBUSY */
 
@@ -1472,9 +1479,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
                        inode_dio_write_done(inode);
                mutex_unlock(&inode->i_mutex);
                down_write(&lli->lli_trunc_sem);
-               mutex_lock(&inode->i_mutex);
-               if (ia_valid & ATTR_SIZE)
-                       inode_dio_wait(inode);
        }
 
        /* We need a steady stripe configuration for setattr to avoid
@@ -1499,6 +1503,13 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
         if (rc)
                 GOTO(out, rc);
 
+       /* RPC to MDT is sent, cancel data modification flag */
+       if (rc == 0 && (op_data->op_bias & MDS_DATA_MODIFIED)) {
+               spin_lock(&lli->lli_lock);
+               lli->lli_flags &= ~LLIF_DATA_MODIFIED;
+               spin_unlock(&lli->lli_lock);
+       }
+
         ll_ioepoch_open(lli, op_data->op_ioepoch);
        if (!S_ISREG(inode->i_mode))
                 GOTO(out, rc = 0);
@@ -1525,13 +1536,17 @@ out:
                 }
                 ll_finish_md_op_data(op_data);
         }
-        if (!S_ISDIR(inode->i_mode))
+       if (!S_ISDIR(inode->i_mode)) {
                up_write(&lli->lli_trunc_sem);
+               mutex_lock(&inode->i_mutex);
+               if (ia_valid & ATTR_SIZE)
+                       inode_dio_wait(inode);
+       }
 
-        ll_stats_ops_tally(ll_i2sbi(inode), (ia_valid & ATTR_SIZE) ?
-                           LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1);
+       ll_stats_ops_tally(ll_i2sbi(inode), (ia_valid & ATTR_SIZE) ?
+                       LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1);
 
-        return rc;
+       return rc;
 }
 
 int ll_setattr(struct dentry *de, struct iattr *attr)
@@ -1682,21 +1697,13 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md)
 
        LASSERT ((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0));
        if (lsm != NULL) {
-               LASSERT(S_ISREG(inode->i_mode));
-               CDEBUG(D_INODE, "adding lsm %p to inode %lu/%u(%p)\n",
-                               lsm, inode->i_ino, inode->i_generation, inode);
-               /* cl_file_inode_init must go before lli_has_smd or a race
-                * is possible where client thinks the file has stripes,
-                * but lov raid0 is not setup yet and parallel e.g.
-                * glimpse would try to use uninitialized lov */
-               if (cl_file_inode_init(inode, md) == 0)
-                       lli->lli_has_smd = true;
+               if (!lli->lli_has_smd &&
+                   !(sbi->ll_flags & LL_SBI_LAYOUT_LOCK))
+                       cl_file_inode_init(inode, md);
 
                lli->lli_maxbytes = lsm->lsm_maxbytes;
                if (lli->lli_maxbytes > MAX_LFS_FILESIZE)
                        lli->lli_maxbytes = MAX_LFS_FILESIZE;
-               if (md->lsm != NULL)
-                       obd_free_memmd(ll_i2dtexp(inode), &md->lsm);
        }
 
         if (sbi->ll_flags & LL_SBI_RMT_CLIENT) {
@@ -2115,13 +2122,11 @@ int ll_remount_fs(struct super_block *sb, int *flags, char *data)
         return 0;
 }
 
-int ll_prep_inode(struct inode **inode,
-                  struct ptlrpc_request *req,
-                  struct super_block *sb)
+int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
+                 struct super_block *sb, struct lookup_intent *it)
 {
        struct ll_sb_info *sbi = NULL;
        struct lustre_md md;
-       __u64 ibits;
         int rc;
         ENTRY;
 
@@ -2145,8 +2150,6 @@ int ll_prep_inode(struct inode **inode,
 
                 *inode = ll_iget(sb, cl_fid_build_ino(&md.body->fid1, 0), &md);
                 if (*inode == NULL || IS_ERR(*inode)) {
-                        if (md.lsm)
-                                obd_free_memmd(sbi->ll_dt_exp, &md.lsm);
 #ifdef CONFIG_FS_POSIX_ACL
                         if (md.posix_acl) {
                                 posix_acl_release(md.posix_acl);
@@ -2160,16 +2163,37 @@ int ll_prep_inode(struct inode **inode,
                 }
         }
 
-       /* sanity check for LAYOUT lock. */
-       ibits = MDS_INODELOCK_LAYOUT;
-       if (S_ISREG(md.body->mode) && sbi->ll_flags & LL_SBI_LAYOUT_LOCK &&
-           md.lsm != NULL && !ll_have_md_lock(*inode, &ibits, LCK_MINMODE)) {
-               CERROR("%s: inode "DFID" (%p) layout lock not granted.\n",
-                       ll_get_fsname(sb, NULL, 0),
-                       PFID(ll_inode2fid(*inode)), *inode);
+       /* Handling piggyback layout lock.
+        * Layout lock can be piggybacked by getattr and open request.
+        * The lsm can be applied to inode only if it comes with a layout lock
+        * otherwise correct layout may be overwritten, for example:
+        * 1. proc1: mdt returns a lsm but not granting layout
+        * 2. layout was changed by another client
+        * 3. proc2: refresh layout and layout lock granted
+        * 4. proc1: to apply a stale layout */
+       if (it != NULL && it->d.lustre.it_lock_mode != 0) {
+               struct lustre_handle lockh;
+               struct ldlm_lock *lock;
+
+               lockh.cookie = it->d.lustre.it_lock_handle;
+               lock = ldlm_handle2lock(&lockh);
+               LASSERT(lock != NULL);
+               if (ldlm_has_layout(lock)) {
+                       struct cl_object_conf conf;
+
+                       memset(&conf, 0, sizeof(conf));
+                       conf.coc_opc = OBJECT_CONF_SET;
+                       conf.coc_inode = *inode;
+                       conf.coc_lock = lock;
+                       conf.u.coc_md = &md;
+                       (void)ll_layout_conf(*inode, &conf);
+               }
+               LDLM_LOCK_PUT(lock);
        }
 
 out:
+       if (md.lsm != NULL)
+               obd_free_memmd(sbi->ll_dt_exp, &md.lsm);
        md_free_lustre_md(sbi->ll_md_exp, &md);
        RETURN(rc);
 }
@@ -2278,17 +2302,21 @@ struct md_op_data * ll_prep_md_op_data(struct md_op_data *op_data,
                 op_data->op_capa2 = NULL;
         }
 
-        op_data->op_name = name;
-        op_data->op_namelen = namelen;
-        op_data->op_mode = mode;
-        op_data->op_mod_time = cfs_time_current_sec();
-        op_data->op_fsuid = cfs_curproc_fsuid();
-        op_data->op_fsgid = cfs_curproc_fsgid();
-        op_data->op_cap = cfs_curproc_cap_pack();
-        op_data->op_bias = MDS_CHECK_SPLIT;
-        op_data->op_opc = opc;
-        op_data->op_mds = 0;
-        op_data->op_data = data;
+       op_data->op_name = name;
+       op_data->op_namelen = namelen;
+       op_data->op_mode = mode;
+       op_data->op_mod_time = cfs_time_current_sec();
+       op_data->op_fsuid = cfs_curproc_fsuid();
+       op_data->op_fsgid = cfs_curproc_fsgid();
+       op_data->op_cap = cfs_curproc_cap_pack();
+       op_data->op_bias = 0;
+       op_data->op_cli_flags = 0;
+       if ((opc == LUSTRE_OPC_CREATE) && (name != NULL) &&
+            filename_is_volatile(name, namelen, NULL))
+               op_data->op_bias |= MDS_CREATE_VOLATILE;
+       op_data->op_opc = opc;
+       op_data->op_mds = 0;
+       op_data->op_data = data;
 
         /* If the file is being opened after mknod() (normally due to NFS)
          * try to use the default stripe data from parent directory for
@@ -2304,6 +2332,10 @@ struct md_op_data * ll_prep_md_op_data(struct md_op_data *op_data,
                /** We ignore parent's capability temporary. */
        }
 
+       /* When called by ll_setattr_raw, file is i1. */
+       if (LLIF_DATA_MODIFIED & ll_i2info(i1)->lli_flags)
+               op_data->op_bias |= MDS_DATA_MODIFIED;
+
        return op_data;
 }
 
@@ -2435,7 +2467,8 @@ void ll_dirty_page_discard_warn(cfs_page_t *page, int ioret)
        struct dentry *dentry = NULL;
        struct ccc_object *obj = cl_inode2ccc(page->mapping->host);
 
-       buf = (char *)__get_free_page(GFP_KERNEL);
+       /* this can be called inside spin lock so use GFP_ATOMIC. */
+       buf = (char *)__get_free_page(GFP_ATOMIC);
        if (buf != NULL) {
                dentry = d_find_alias(page->mapping->host);
                if (dentry != NULL)