Whamcloud - gitweb
LU-11838 lustre: discard LTIME_S macro
[fs/lustre-release.git] / lustre / llite / llite_lib.c
index 94b9a29..b4cbe57 100644 (file)
@@ -23,7 +23,7 @@
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2016, Intel Corporation.
+ * Copyright (c) 2011, 2017, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
 #endif
 #include <linux/security.h>
 
-#include <lustre_ioctl.h>
+#include <uapi/linux/lustre/lustre_ioctl.h>
 #include <lustre_ha.h>
 #include <lustre_dlm.h>
 #include <lprocfs_status.h>
 #include <lustre_disk.h>
-#include <lustre_param.h>
+#include <uapi/linux/lustre/lustre_param.h>
 #include <lustre_log.h>
 #include <cl_object.h>
 #include <obd_cksum.h>
@@ -99,8 +99,7 @@ static struct ll_sb_info *ll_init_sbi(void)
        sbi->ll_ra_info.ra_max_pages_per_file = min(pages / 32,
                                           SBI_DEFAULT_READAHEAD_MAX);
        sbi->ll_ra_info.ra_max_pages = sbi->ll_ra_info.ra_max_pages_per_file;
-       sbi->ll_ra_info.ra_max_read_ahead_whole_pages =
-                                          SBI_DEFAULT_READAHEAD_WHOLE_MAX;
+       sbi->ll_ra_info.ra_max_read_ahead_whole_pages = -1;
 
         ll_generate_random_uuid(uuid);
         class_uuid_unparse(uuid, &sbi->ll_sb_uuid);
@@ -124,6 +123,7 @@ static struct ll_sb_info *ll_init_sbi(void)
         }
 
        /* metadata statahead is enabled by default */
+       sbi->ll_sa_running_max = LL_SA_RUNNING_DEF;
        sbi->ll_sa_max = LL_SA_RPC_DEF;
        atomic_set(&sbi->ll_sa_total, 0);
        atomic_set(&sbi->ll_sa_wrong, 0);
@@ -131,6 +131,7 @@ static struct ll_sb_info *ll_init_sbi(void)
        atomic_set(&sbi->ll_agl_total, 0);
        sbi->ll_flags |= LL_SBI_AGL_ENABLED;
        sbi->ll_flags |= LL_SBI_FAST_READ;
+       sbi->ll_flags |= LL_SBI_TINY_WRITE;
 
        /* root squash */
        sbi->ll_squash.rsi_uid = 0;
@@ -158,30 +159,23 @@ static void ll_free_sbi(struct super_block *sb)
        EXIT;
 }
 
-static inline int obd_connect_has_secctx(struct obd_connect_data *data)
-{
-       return data->ocd_connect_flags & OBD_CONNECT_FLAGS2 &&
-              data->ocd_connect_flags2 & OBD_CONNECT2_FILE_SECCTX;
-}
-
 static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                                     struct vfsmount *mnt)
 {
        struct inode *root = NULL;
-        struct ll_sb_info *sbi = ll_s2sbi(sb);
-        struct obd_device *obd;
-        struct obd_statfs *osfs = NULL;
-        struct ptlrpc_request *request = NULL;
-        struct obd_connect_data *data = NULL;
-        struct obd_uuid *uuid;
-        struct md_op_data *op_data;
-        struct lustre_md lmd;
+       struct ll_sb_info *sbi = ll_s2sbi(sb);
+       struct obd_statfs *osfs = NULL;
+       struct ptlrpc_request *request = NULL;
+       struct obd_connect_data *data = NULL;
+       struct obd_uuid *uuid;
+       struct md_op_data *op_data;
+       struct lustre_md lmd;
        u64 valid;
-        int size, err, checksum;
-        ENTRY;
+       int size, err, checksum;
 
-        obd = class_name2obd(md);
-        if (!obd) {
+       ENTRY;
+       sbi->ll_md_obd = class_name2obd(md);
+       if (!sbi->ll_md_obd) {
                 CERROR("MD %s: not setup or attached\n", md);
                 RETURN(-EINVAL);
         }
@@ -196,13 +190,18 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                 RETURN(-ENOMEM);
         }
 
-        /* indicate the features supported by this client */
-        data->ocd_connect_flags = OBD_CONNECT_IBITS    | OBD_CONNECT_NODEVOH  |
-                                  OBD_CONNECT_ATTRFID  |
-                                  OBD_CONNECT_VERSION  | OBD_CONNECT_BRW_SIZE |
-                                  OBD_CONNECT_MDS_CAPA | OBD_CONNECT_OSS_CAPA |
-                                  OBD_CONNECT_CANCELSET | OBD_CONNECT_FID     |
-                                  OBD_CONNECT_AT       | OBD_CONNECT_LOV_V3   |
+       /* pass client page size via ocd_grant_blkbits, the server should report
+        * back its backend blocksize for grant calculation purpose */
+       data->ocd_grant_blkbits = PAGE_SHIFT;
+
+       /* indicate MDT features supported by this client */
+       data->ocd_connect_flags = OBD_CONNECT_IBITS    | OBD_CONNECT_NODEVOH  |
+                                 OBD_CONNECT_ATTRFID  | OBD_CONNECT_GRANT |
+                                 OBD_CONNECT_VERSION  | OBD_CONNECT_BRW_SIZE |
+                                 OBD_CONNECT_SRVLOCK  | OBD_CONNECT_TRUNCLOCK|
+                                 OBD_CONNECT_MDS_CAPA | OBD_CONNECT_OSS_CAPA |
+                                 OBD_CONNECT_CANCELSET | OBD_CONNECT_FID     |
+                                 OBD_CONNECT_AT       | OBD_CONNECT_LOV_V3   |
                                  OBD_CONNECT_VBR | OBD_CONNECT_FULL20 |
                                  OBD_CONNECT_64BITHASH |
                                  OBD_CONNECT_EINPROGRESS |
@@ -213,20 +212,29 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                                  OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK |
                                  OBD_CONNECT_OPEN_BY_FID |
                                  OBD_CONNECT_DIR_STRIPE |
-                                 OBD_CONNECT_BULK_MBITS |
+                                 OBD_CONNECT_BULK_MBITS | OBD_CONNECT_CKSUM |
                                  OBD_CONNECT_SUBTREE |
-                                 OBD_CONNECT_FLAGS2;
+                                 OBD_CONNECT_MULTIMODRPCS |
+                                 OBD_CONNECT_GRANT_PARAM |
+                                 OBD_CONNECT_SHORTIO | OBD_CONNECT_FLAGS2;
 
-       data->ocd_connect_flags2 = 0;
+       data->ocd_connect_flags2 = OBD_CONNECT2_FLR |
+                                  OBD_CONNECT2_LOCK_CONVERT |
+                                  OBD_CONNECT2_DIR_MIGRATE |
+                                  OBD_CONNECT2_SUM_STATFS |
+                                  OBD_CONNECT2_ARCHIVE_ID_ARRAY;
 
 #ifdef HAVE_LRU_RESIZE_SUPPORT
         if (sbi->ll_flags & LL_SBI_LRU_RESIZE)
                 data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE;
 #endif
 #ifdef CONFIG_FS_POSIX_ACL
-        data->ocd_connect_flags |= OBD_CONNECT_ACL | OBD_CONNECT_UMASK;
+       data->ocd_connect_flags |= OBD_CONNECT_ACL | OBD_CONNECT_UMASK |
+                                  OBD_CONNECT_LARGE_ACL;
 #endif
 
+       data->ocd_cksum_types = obd_cksum_types_supported_client();
+
        if (OBD_FAIL_CHECK(OBD_FAIL_MDC_LIGHTWEIGHT))
                /* flag mdc connection as lightweight, only used for test
                 * purpose, use with care */
@@ -240,6 +248,13 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
         if (sbi->ll_flags & LL_SBI_USER_XATTR)
                 data->ocd_connect_flags |= OBD_CONNECT_XATTR;
 
+#ifdef MS_NOSEC
+       /* Setting this indicates we correctly support S_NOSEC (See kernel
+        * commit 9e1f1de02c2275d7172e18dc4e7c2065777611bf)
+        */
+       sb->s_flags |= MS_NOSEC;
+#endif
+
         if (sbi->ll_flags & LL_SBI_FLOCK)
                 sbi->ll_fop = &ll_file_operations_flock;
         else if (sbi->ll_flags & LL_SBI_LOCALFLOCK)
@@ -251,13 +266,12 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
        if (sbi->ll_flags & LL_SBI_ALWAYS_PING)
                data->ocd_connect_flags &= ~OBD_CONNECT_PINGLESS;
 
-#ifdef HAVE_SECURITY_DENTRY_INIT_SECURITY
-       data->ocd_connect_flags2 |= OBD_CONNECT2_FILE_SECCTX;
-#endif /* HAVE_SECURITY_DENTRY_INIT_SECURITY */
+       obd_connect_set_secctx(data);
 
        data->ocd_brw_size = MD_MAX_BRW_SIZE;
 
-        err = obd_connect(NULL, &sbi->ll_md_exp, obd, &sbi->ll_sb_uuid, data, NULL);
+       err = obd_connect(NULL, &sbi->ll_md_exp, sbi->ll_md_obd,
+                         &sbi->ll_sb_uuid, data, NULL);
         if (err == -EBUSY) {
                 LCONSOLE_ERROR_MSG(0x14f, "An MDT (md %s) is performing "
                                    "recovery, of which this client is not a "
@@ -283,7 +297,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
         * 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),
+                       ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
                        OBD_STATFS_FOR_MDT0);
        if (err)
                GOTO(out_md_fid, err);
@@ -352,11 +366,6 @@ 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_pages = data->ocd_brw_size >> PAGE_SHIFT;
-       else
-               sbi->ll_md_brw_pages = 1;
-
        if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK)
                sbi->ll_flags |= LL_SBI_LAYOUT_LOCK;
 
@@ -367,14 +376,16 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                if (!(data->ocd_connect_flags & OBD_CONNECT_MAX_EASIZE)) {
                        LCONSOLE_INFO("%s: disabling xattr cache due to "
                                      "unknown maximum xattr size.\n", dt);
-               } else {
+               } else if (!sbi->ll_xattr_cache_set) {
+                       /* If xattr_cache is already set (no matter 0 or 1)
+                        * during processing llog, it won't be enabled here. */
                        sbi->ll_flags |= LL_SBI_XATTR_CACHE;
                        sbi->ll_xattr_cache_enabled = 1;
                }
        }
 
-       obd = class_name2obd(dt);
-       if (!obd) {
+       sbi->ll_dt_obd = class_name2obd(dt);
+       if (!sbi->ll_dt_obd) {
                CERROR("DT %s: not setup or attached\n", dt);
                GOTO(out_md_fid, err = -ENODEV);
        }
@@ -383,6 +394,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
         * back its backend blocksize for grant calculation purpose */
        data->ocd_grant_blkbits = PAGE_SHIFT;
 
+       /* indicate OST features supported by this client */
        data->ocd_connect_flags = OBD_CONNECT_GRANT | OBD_CONNECT_VERSION |
                                  OBD_CONNECT_REQPORTAL | OBD_CONNECT_BRW_SIZE |
                                  OBD_CONNECT_CANCELSET | OBD_CONNECT_FID |
@@ -394,25 +406,41 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                                  OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE |
                                  OBD_CONNECT_LAYOUTLOCK |
                                  OBD_CONNECT_PINGLESS | OBD_CONNECT_LFSCK |
-                                 OBD_CONNECT_BULK_MBITS;
+                                 OBD_CONNECT_BULK_MBITS | OBD_CONNECT_SHORTIO |
+                                 OBD_CONNECT_FLAGS2 | OBD_CONNECT_GRANT_SHRINK;
+
+/* The client currently advertises support for OBD_CONNECT_LOCKAHEAD_OLD so it
+ * can interoperate with an older version of lockahead which was released prior
+ * to landing in master. This support will be dropped when 2.13 development
+ * starts.  At the point, we should not just drop the connect flag (below), we
+ * should also remove the support in the code.
+ *
+ * Removing it means a few things:
+ * 1. Remove this section here
+ * 2. Remove CEF_NONBLOCK in ll_file_lockahead()
+ * 3. Remove function exp_connect_lockahead_old
+ * 4. Remove LDLM_FL_LOCKAHEAD_OLD_RESERVED in lustre_dlm_flags.h
+ * */
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 12, 50, 0)
+       data->ocd_connect_flags |= OBD_CONNECT_LOCKAHEAD_OLD;
+#endif
 
-       data->ocd_connect_flags2 = 0;
+       data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD;
 
        if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_GRANT_PARAM))
                data->ocd_connect_flags |= OBD_CONNECT_GRANT_PARAM;
 
-       if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_CKSUM)) {
-               /* OBD_CONNECT_CKSUM should always be set, even if checksums are
-                * disabled by default, because it can still be enabled on the
-                * fly via /proc. As a consequence, we still need to come to an
-                * agreement on the supported algorithms at connect time */
-               data->ocd_connect_flags |= OBD_CONNECT_CKSUM;
+       /* OBD_CONNECT_CKSUM should always be set, even if checksums are
+        * disabled by default, because it can still be enabled on the
+        * fly via /sys. As a consequence, we still need to come to an
+        * agreement on the supported algorithms at connect time
+        */
+       data->ocd_connect_flags |= OBD_CONNECT_CKSUM;
 
-               if (OBD_FAIL_CHECK(OBD_FAIL_OSC_CKSUM_ADLER_ONLY))
-                       data->ocd_cksum_types = OBD_CKSUM_ADLER;
-               else
-                       data->ocd_cksum_types = cksum_types_supported_client();
-       }
+       if (OBD_FAIL_CHECK(OBD_FAIL_OSC_CKSUM_ADLER_ONLY))
+               data->ocd_cksum_types = OBD_CKSUM_ADLER;
+       else
+               data->ocd_cksum_types = obd_cksum_types_supported_client();
 
 #ifdef HAVE_LRU_RESIZE_SUPPORT
        data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE;
@@ -425,13 +453,13 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
               "ocd_grant: %d\n", data->ocd_connect_flags,
               data->ocd_version, data->ocd_grant);
 
-       obd->obd_upcall.onu_owner = &sbi->ll_lco;
-       obd->obd_upcall.onu_upcall = cl_ocd_update;
+       sbi->ll_dt_obd->obd_upcall.onu_owner = &sbi->ll_lco;
+       sbi->ll_dt_obd->obd_upcall.onu_upcall = cl_ocd_update;
 
        data->ocd_brw_size = DT_MAX_BRW_SIZE;
 
-       err = obd_connect(NULL, &sbi->ll_dt_exp, obd, &sbi->ll_sb_uuid, data,
-                         NULL);
+       err = obd_connect(NULL, &sbi->ll_dt_exp, sbi->ll_dt_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 "
@@ -446,6 +474,12 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
 
        sbi->ll_dt_exp->exp_connect_data = *data;
 
+       /* Don't change value if it was specified in the config log */
+       if (sbi->ll_ra_info.ra_max_read_ahead_whole_pages == -1)
+               sbi->ll_ra_info.ra_max_read_ahead_whole_pages =
+                       max_t(unsigned long, SBI_DEFAULT_READAHEAD_WHOLE_MAX,
+                             (data->ocd_brw_size >> PAGE_SHIFT));
+
        err = obd_fid_init(sbi->ll_dt_exp->exp_obd, sbi->ll_dt_exp,
                           LUSTRE_SEQ_METADATA);
        if (err) {
@@ -476,6 +510,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
        CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid));
 
        sb->s_op = &lustre_super_operations;
+#ifdef HAVE_XATTR_HANDLER_FLAGS
+       sb->s_xattr = ll_xattr_handlers;
+#endif
 #if THREAD_SIZE >= 8192 /*b=17630*/
        sb->s_export_op = &lustre_export_operations;
 #endif
@@ -532,13 +569,15 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
        }
 
        checksum = sbi->ll_flags & LL_SBI_CHECKSUM;
-       err = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM),
-                                KEY_CHECKSUM, sizeof(checksum), &checksum,
-                                NULL);
-       if (err) {
-               CERROR("%s: Set checksum failed: rc = %d\n",
-                      sbi->ll_dt_exp->exp_obd->obd_name, err);
-               GOTO(out_root, err);
+       if (sbi->ll_checksum_set) {
+               err = obd_set_info_async(NULL, sbi->ll_dt_exp,
+                                        sizeof(KEY_CHECKSUM), KEY_CHECKSUM,
+                                        sizeof(checksum), &checksum, NULL);
+               if (err) {
+                       CERROR("%s: Set checksum failed: rc = %d\n",
+                              sbi->ll_dt_exp->exp_obd->obd_name, err);
+                       GOTO(out_root, err);
+               }
        }
        cl_sb_init(sb);
 
@@ -576,12 +615,25 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                OBD_FREE_PTR(data);
        if (osfs != NULL)
                OBD_FREE_PTR(osfs);
-       if (proc_lustre_fs_root != NULL) {
-               err = lprocfs_register_mountpoint(proc_lustre_fs_root, sb,
-                                                 dt, md);
+
+       if (sbi->ll_dt_obd) {
+               err = sysfs_create_link(&sbi->ll_kset.kobj,
+                                       &sbi->ll_dt_obd->obd_kset.kobj,
+                                       sbi->ll_dt_obd->obd_type->typ_name);
+               if (err < 0) {
+                       CERROR("%s: could not register %s in llite: rc = %d\n",
+                              dt, ll_get_fsname(sb, NULL, 0), err);
+                       err = 0;
+               }
+       }
+
+       if (sbi->ll_md_obd) {
+               err = sysfs_create_link(&sbi->ll_kset.kobj,
+                                       &sbi->ll_md_obd->obd_kset.kobj,
+                                       sbi->ll_md_obd->obd_type->typ_name);
                if (err < 0) {
-                       CERROR("%s: could not register mount in lprocfs: "
-                              "rc = %d\n", ll_get_fsname(sb, NULL, 0), err);
+                       CERROR("%s: could not register %s in llite: rc = %d\n",
+                              md, ll_get_fsname(sb, NULL, 0), err);
                        err = 0;
                }
        }
@@ -595,11 +647,13 @@ out_lock_cn_cb:
 out_dt:
        obd_disconnect(sbi->ll_dt_exp);
        sbi->ll_dt_exp = NULL;
+       sbi->ll_dt_obd = NULL;
 out_md_fid:
        obd_fid_fini(sbi->ll_md_exp->exp_obd);
 out_md:
        obd_disconnect(sbi->ll_md_exp);
        sbi->ll_md_exp = NULL;
+       sbi->ll_md_obd = NULL;
 out:
        if (data != NULL)
                OBD_FREE_PTR(data);
@@ -680,69 +734,24 @@ int ll_set_default_mdsize(struct ll_sb_info *sbi, int lmmsize)
        RETURN(rc);
 }
 
-static void ll_dump_inode(struct inode *inode)
-{
-       struct ll_d_hlist_node *tmp;
-       int dentry_count = 0;
-
-       LASSERT(inode != NULL);
-
-       ll_d_hlist_for_each(tmp, &inode->i_dentry)
-               dentry_count++;
-
-       CERROR("%s: inode %p dump: dev=%s fid="DFID
-              " mode=%o count=%u, %d dentries\n",
-              ll_get_fsname(inode->i_sb, NULL, 0), inode,
-              ll_i2mdexp(inode)->exp_obd->obd_name, PFID(ll_inode2fid(inode)),
-              inode->i_mode, atomic_read(&inode->i_count), dentry_count);
-}
-
-void lustre_dump_dentry(struct dentry *dentry, int recur)
-{
-        struct list_head *tmp;
-        int subdirs = 0;
-
-        LASSERT(dentry != NULL);
-
-        list_for_each(tmp, &dentry->d_subdirs)
-                subdirs++;
-
-        CERROR("dentry %p dump: name=%.*s parent=%.*s (%p), inode=%p, count=%u,"
-               " flags=0x%x, fsdata=%p, %d subdirs\n", dentry,
-               dentry->d_name.len, dentry->d_name.name,
-               dentry->d_parent->d_name.len, dentry->d_parent->d_name.name,
-              dentry->d_parent, dentry->d_inode, ll_d_count(dentry),
-               dentry->d_flags, dentry->d_fsdata, subdirs);
-        if (dentry->d_inode != NULL)
-                ll_dump_inode(dentry->d_inode);
-
-        if (recur == 0)
-                return;
-
-       list_for_each(tmp, &dentry->d_subdirs) {
-               struct dentry *d = list_entry(tmp, struct dentry, d_child);
-               lustre_dump_dentry(d, recur - 1);
-       }
-}
-
 static void client_common_put_super(struct super_block *sb)
 {
-        struct ll_sb_info *sbi = ll_s2sbi(sb);
-        ENTRY;
+       struct ll_sb_info *sbi = ll_s2sbi(sb);
+       ENTRY;
 
-        cl_sb_fini(sb);
+       cl_sb_fini(sb);
 
        obd_fid_fini(sbi->ll_dt_exp->exp_obd);
-        obd_disconnect(sbi->ll_dt_exp);
-        sbi->ll_dt_exp = NULL;
+       obd_disconnect(sbi->ll_dt_exp);
+       sbi->ll_dt_exp = NULL;
 
-        lprocfs_unregister_mountpoint(sbi);
+       ll_debugfs_unregister_super(sb);
 
        obd_fid_fini(sbi->ll_md_exp->exp_obd);
-        obd_disconnect(sbi->ll_md_exp);
-        sbi->ll_md_exp = NULL;
+       obd_disconnect(sbi->ll_md_exp);
+       sbi->ll_md_exp = NULL;
 
-        EXIT;
+       EXIT;
 }
 
 void ll_kill_super(struct super_block *sb)
@@ -774,23 +783,24 @@ void ll_kill_super(struct super_block *sb)
 
 static inline int ll_set_opt(const char *opt, char *data, int fl)
 {
-        if (strncmp(opt, data, strlen(opt)) != 0)
-                return(0);
-        else
-                return(fl);
+       if (strncmp(opt, data, strlen(opt)) != 0)
+               return 0;
+       else
+               return fl;
 }
 
 /* non-client-specific mount options are parsed in lmd_parse */
-static int ll_options(char *options, int *flags)
+static int ll_options(char *options, struct ll_sb_info *sbi)
 {
-        int tmp;
-        char *s1 = options, *s2;
-        ENTRY;
+       int tmp;
+       char *s1 = options, *s2;
+       int *flags = &sbi->ll_flags;
+       ENTRY;
 
-        if (!options)
-                RETURN(0);
+       if (!options)
+               RETURN(0);
 
-        CDEBUG(D_CONFIG, "Parsing opts %s\n", options);
+       CDEBUG(D_CONFIG, "Parsing opts %s\n", options);
 
         while (*s1) {
                 CDEBUG(D_SUPER, "next opt=%s\n", s1);
@@ -847,16 +857,18 @@ static int ll_options(char *options, int *flags)
                        goto next;
                }
 
-                tmp = ll_set_opt("checksum", s1, LL_SBI_CHECKSUM);
-                if (tmp) {
-                        *flags |= tmp;
-                        goto next;
-                }
-                tmp = ll_set_opt("nochecksum", s1, LL_SBI_CHECKSUM);
-                if (tmp) {
-                        *flags &= ~tmp;
-                        goto next;
-                }
+               tmp = ll_set_opt("checksum", s1, LL_SBI_CHECKSUM);
+               if (tmp) {
+                       *flags |= tmp;
+                       sbi->ll_checksum_set = 1;
+                       goto next;
+               }
+               tmp = ll_set_opt("nochecksum", s1, LL_SBI_CHECKSUM);
+               if (tmp) {
+                       *flags &= ~tmp;
+                       sbi->ll_checksum_set = 1;
+                       goto next;
+               }
                 tmp = ll_set_opt("lruresize", s1, LL_SBI_LRU_RESIZE);
                 if (tmp) {
                         *flags |= tmp;
@@ -943,155 +955,212 @@ void ll_lli_init(struct ll_inode_info *lli)
                lli->lli_opendir_pid = 0;
                lli->lli_sa_enabled = 0;
                lli->lli_def_stripe_offset = -1;
+               init_rwsem(&lli->lli_lsm_sem);
        } else {
                mutex_init(&lli->lli_size_mutex);
                lli->lli_symlink_name = NULL;
                init_rwsem(&lli->lli_trunc_sem);
                range_lock_tree_init(&lli->lli_write_tree);
                init_rwsem(&lli->lli_glimpse_sem);
-               lli->lli_glimpse_time = 0;
+               lli->lli_glimpse_time = ktime_set(0, 0);
                INIT_LIST_HEAD(&lli->lli_agl_list);
                lli->lli_agl_index = 0;
                lli->lli_async_rc = 0;
        }
        mutex_init(&lli->lli_layout_mutex);
-       memset(lli->lli_jobid, 0, LUSTRE_JOBID_SIZE);
+       memset(lli->lli_jobid, 0, sizeof(lli->lli_jobid));
 }
 
-static inline int ll_bdi_register(struct backing_dev_info *bdi)
+#define MAX_STRING_SIZE 128
+
+#ifndef HAVE_SUPER_SETUP_BDI_NAME
+
+#define LSI_BDI_INITIALIZED    0x00400000
+
+#ifndef HAVE_BDI_CAP_MAP_COPY
+# define BDI_CAP_MAP_COPY      0
+#endif
+
+static int super_setup_bdi_name(struct super_block *sb, char *fmt, ...)
 {
-       static atomic_t ll_bdi_num = ATOMIC_INIT(0);
+       struct  lustre_sb_info *lsi = s2lsi(sb);
+       char buf[MAX_STRING_SIZE];
+       va_list args;
+       int err;
+
+       err = bdi_init(&lsi->lsi_bdi);
+       if (err)
+               return err;
 
-       bdi->name = "lustre";
-       return bdi_register(bdi, NULL, "lustre-%d",
-                           atomic_inc_return(&ll_bdi_num));
+       lsi->lsi_flags |= LSI_BDI_INITIALIZED;
+       lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY;
+       lsi->lsi_bdi.name = "lustre";
+       va_start(args, fmt);
+       vsnprintf(buf, MAX_STRING_SIZE, fmt, args);
+       va_end(args);
+       err = bdi_register(&lsi->lsi_bdi, NULL, "%s", buf);
+       va_end(args);
+       if (!err)
+               sb->s_bdi = &lsi->lsi_bdi;
+
+       return err;
 }
+#endif /* !HAVE_SUPER_SETUP_BDI_NAME */
 
 int ll_fill_super(struct super_block *sb, struct vfsmount *mnt)
 {
-        struct lustre_profile *lprof = NULL;
-        struct lustre_sb_info *lsi = s2lsi(sb);
-        struct ll_sb_info *sbi;
-        char  *dt = NULL, *md = NULL;
-        char  *profilenm = get_profile_name(sb);
-        struct config_llog_instance *cfg;
-        /* %p for void* in printf needs 16+2 characters: 0xffffffffffffffff */
-        const int instlen = sizeof(cfg->cfg_instance) * 2 + 2;
-        int    err;
-        ENTRY;
-
-        CDEBUG(D_VFSTRACE, "VFS Op: sb %p\n", sb);
+       struct  lustre_profile *lprof = NULL;
+       struct  lustre_sb_info *lsi = s2lsi(sb);
+       struct  ll_sb_info *sbi = NULL;
+       char    *dt = NULL, *md = NULL;
+       char    *profilenm = get_profile_name(sb);
+       struct config_llog_instance *cfg;
+       /* %p for void* in printf needs 16+2 characters: 0xffffffffffffffff */
+       const int instlen = 16 + 2;
+       unsigned long cfg_instance = ll_get_cfg_instance(sb);
+       char name[MAX_STRING_SIZE];
+       int md_len = 0;
+       int dt_len = 0;
+       char *ptr;
+       int len;
+       int err;
 
-        OBD_ALLOC_PTR(cfg);
-        if (cfg == NULL)
-                RETURN(-ENOMEM);
+       ENTRY;
+       /* for ASLR, to map between cfg_instance and hashed ptr */
+       CDEBUG(D_VFSTRACE, "VFS Op: cfg_instance %s-%016lx (sb %p)\n",
+              profilenm, cfg_instance, sb);
 
        try_module_get(THIS_MODULE);
 
+       OBD_ALLOC_PTR(cfg);
+       if (cfg == NULL)
+               GOTO(out_free_cfg, err = -ENOMEM);
+
        /* client additional sb info */
        lsi->lsi_llsbi = sbi = ll_init_sbi();
-       if (!sbi) {
-               module_put(THIS_MODULE);
-               OBD_FREE_PTR(cfg);
-               RETURN(-ENOMEM);
-       }
+       if (!sbi)
+               GOTO(out_free_cfg, err = -ENOMEM);
 
-        err = ll_options(lsi->lsi_lmd->lmd_opts, &sbi->ll_flags);
-        if (err)
-                GOTO(out_free, err);
-
-       err = bdi_init(&lsi->lsi_bdi);
+       err = ll_options(lsi->lsi_lmd->lmd_opts, sbi);
        if (err)
-               GOTO(out_free, err);
-       lsi->lsi_flags |= LSI_BDI_INITIALIZED;
-#ifdef HAVE_BDI_CAP_MAP_COPY
-       lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY;
-#else
-       lsi->lsi_bdi.capabilities = 0;
-#endif
-       err = ll_bdi_register(&lsi->lsi_bdi);
+               GOTO(out_free_cfg, err);
+
+       err = super_setup_bdi_name(sb, "lustre-%016lx", cfg_instance);
        if (err)
-               GOTO(out_free, err);
+               GOTO(out_free_cfg, err);
 
-        sb->s_bdi = &lsi->lsi_bdi;
 #ifndef HAVE_DCACHE_LOCK
        /* kernel >= 2.6.38 store dentry operations in sb->s_d_op. */
        sb->s_d_op = &ll_d_ops;
 #endif
+       /* Get fsname */
+       len = strlen(profilenm);
+       ptr = strrchr(profilenm, '-');
+       if (ptr && (strcmp(ptr, "-client") == 0))
+               len -= 7;
+
+       /* Mount info */
+       snprintf(name, MAX_STRING_SIZE, "%.*s-%016lx", len,
+                profilenm, cfg_instance);
 
-        /* Generate a string unique to this super, in case some joker tries
-           to mount the same fs at two mount points.
-           Use the address of the super itself.*/
-        cfg->cfg_instance = sb;
-        cfg->cfg_uuid = lsi->lsi_llsbi->ll_sb_uuid;
+       /* Call ll_debugfs_register_super() before lustre_process_log()
+        * so that "llite.*.*" params can be processed correctly.
+        */
+       err = ll_debugfs_register_super(sb, name);
+       if (err < 0) {
+               CERROR("%s: could not register mountpoint in llite: rc = %d\n",
+                      ll_get_fsname(sb, NULL, 0), err);
+               err = 0;
+       }
+
+       /* The cfg_instance is a value unique to this super, in case some
+        * joker tries to mount the same fs at two mount points.
+        */
+       cfg->cfg_instance = cfg_instance;
+       cfg->cfg_uuid = lsi->lsi_llsbi->ll_sb_uuid;
        cfg->cfg_callback = class_config_llog_handler;
        cfg->cfg_sub_clds = CONFIG_SUB_CLIENT;
-        /* set up client obds */
-        err = lustre_process_log(sb, profilenm, cfg);
+       /* set up client obds */
+       err = lustre_process_log(sb, profilenm, cfg);
        if (err < 0)
-               GOTO(out_free, err);
-
-        /* Profile set with LCFG_MOUNTOPT so we can find our mdc and osc obds */
-        lprof = class_get_profile(profilenm);
-        if (lprof == NULL) {
-                LCONSOLE_ERROR_MSG(0x156, "The client profile '%s' could not be"
-                                   " read from the MGS.  Does that filesystem "
-                                   "exist?\n", profilenm);
-                GOTO(out_free, err = -EINVAL);
-        }
-        CDEBUG(D_CONFIG, "Found profile %s: mdc=%s osc=%s\n", profilenm,
-               lprof->lp_md, lprof->lp_dt);
-
-        OBD_ALLOC(dt, strlen(lprof->lp_dt) + instlen + 2);
-        if (!dt)
-                GOTO(out_free, err = -ENOMEM);
-        sprintf(dt, "%s-%p", lprof->lp_dt, cfg->cfg_instance);
-
-        OBD_ALLOC(md, strlen(lprof->lp_md) + instlen + 2);
-        if (!md)
-                GOTO(out_free, err = -ENOMEM);
-        sprintf(md, "%s-%p", lprof->lp_md, cfg->cfg_instance);
-
-        /* connections, registrations, sb setup */
-        err = client_common_fill_super(sb, md, dt, mnt);
+               GOTO(out_debugfs, err);
+
+       /* Profile set with LCFG_MOUNTOPT so we can find our mdc and osc obds */
+       lprof = class_get_profile(profilenm);
+       if (lprof == NULL) {
+               LCONSOLE_ERROR_MSG(0x156, "The client profile '%s' could not be"
+                                  " read from the MGS.  Does that filesystem "
+                                  "exist?\n", profilenm);
+               GOTO(out_debugfs, err = -EINVAL);
+       }
+       CDEBUG(D_CONFIG, "Found profile %s: mdc=%s osc=%s\n", profilenm,
+              lprof->lp_md, lprof->lp_dt);
+
+       dt_len = strlen(lprof->lp_dt) + instlen + 2;
+       OBD_ALLOC(dt, dt_len);
+       if (!dt)
+               GOTO(out_profile, err = -ENOMEM);
+       snprintf(dt, dt_len - 1, "%s-%016lx", lprof->lp_dt, cfg_instance);
+
+       md_len = strlen(lprof->lp_md) + instlen + 2;
+       OBD_ALLOC(md, md_len);
+       if (!md)
+               GOTO(out_free_dt, err = -ENOMEM);
+       snprintf(md, md_len - 1, "%s-%016lx", lprof->lp_md, cfg_instance);
+
+       /* connections, registrations, sb setup */
+       err = client_common_fill_super(sb, md, dt, mnt);
        if (err < 0)
-               GOTO(out_free, err);
+               GOTO(out_free_md, err);
 
        sbi->ll_client_common_fill_super_succeeded = 1;
 
-out_free:
+out_free_md:
        if (md)
-               OBD_FREE(md, strlen(lprof->lp_md) + instlen + 2);
+               OBD_FREE(md, md_len);
+out_free_dt:
        if (dt)
-               OBD_FREE(dt, strlen(lprof->lp_dt) + instlen + 2);
-       if (lprof != NULL)
+               OBD_FREE(dt, dt_len);
+out_profile:
+       if (lprof)
                class_put_profile(lprof);
+out_debugfs:
+       if (err < 0)
+               ll_debugfs_unregister_super(sb);
+out_free_cfg:
+       if (cfg)
+               OBD_FREE_PTR(cfg);
+
        if (err)
                ll_put_super(sb);
        else if (sbi->ll_flags & LL_SBI_VERBOSE)
                LCONSOLE_WARN("Mounted %s\n", profilenm);
-
-       OBD_FREE_PTR(cfg);
        RETURN(err);
 } /* ll_fill_super */
 
 void ll_put_super(struct super_block *sb)
 {
        struct config_llog_instance cfg, params_cfg;
-        struct obd_device *obd;
-        struct lustre_sb_info *lsi = s2lsi(sb);
-        struct ll_sb_info *sbi = ll_s2sbi(sb);
-        char *profilenm = get_profile_name(sb);
+       struct obd_device *obd;
+       struct lustre_sb_info *lsi = s2lsi(sb);
+       struct ll_sb_info *sbi = ll_s2sbi(sb);
+       char *profilenm = get_profile_name(sb);
+       unsigned long cfg_instance = ll_get_cfg_instance(sb);
        long ccc_count;
        int next, force = 1, rc = 0;
-        ENTRY;
+       ENTRY;
+
+       if (!sbi)
+               GOTO(out_no_sbi, 0);
 
-        CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm);
+       /* Should replace instance_id with something better for ASLR */
+       CDEBUG(D_VFSTRACE, "VFS Op: cfg_instance %s-%016lx (sb %p)\n",
+              profilenm, cfg_instance, sb);
 
-        cfg.cfg_instance = sb;
-        lustre_end_log(sb, profilenm, &cfg);
+       cfg.cfg_instance = cfg_instance;
+       lustre_end_log(sb, profilenm, &cfg);
 
-       params_cfg.cfg_instance = sb;
+       params_cfg.cfg_instance = cfg_instance;
        lustre_end_log(sb, PARAMS_FILENAME, &params_cfg);
 
         if (sbi->ll_md_exp) {
@@ -1112,7 +1181,6 @@ void ll_put_super(struct super_block *sb)
        if (force == 0 && rc != -EINTR)
                LASSERTF(ccc_count == 0, "count: %li\n", ccc_count);
 
-
         /* We need to set force before the lov_disconnect in
            lustre_common_put_super, since l_d cleans up osc's as well. */
         if (force) {
@@ -1139,14 +1207,16 @@ void ll_put_super(struct super_block *sb)
         if (profilenm)
                 class_del_profile(profilenm);
 
+#ifndef HAVE_SUPER_SETUP_BDI_NAME
        if (lsi->lsi_flags & LSI_BDI_INITIALIZED) {
                bdi_destroy(&lsi->lsi_bdi);
                lsi->lsi_flags &= ~LSI_BDI_INITIALIZED;
        }
+#endif
 
         ll_free_sbi(sb);
         lsi->lsi_llsbi = NULL;
-
+out_no_sbi:
        lustre_common_put_super(sb);
 
        cl_env_cache_purge(~0);
@@ -1220,9 +1290,9 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb,
                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_mtime.tv_sec = 0;
+               inode->i_atime.tv_sec = 0;
+               inode->i_ctime.tv_sec = 0;
                inode->i_rdev = 0;
 
 #ifdef HAVE_BACKING_DEV_INFO
@@ -1250,9 +1320,16 @@ static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md)
 {
        struct lu_fid *fid;
        struct lmv_stripe_md *lsm = md->lmv;
+       struct ll_inode_info *lli = ll_i2info(inode);
        int i;
 
        LASSERT(lsm != NULL);
+
+       CDEBUG(D_INODE, "%s: "DFID" set dir layout:\n",
+               ll_get_fsname(inode->i_sb, NULL, 0),
+               PFID(&lli->lli_fid));
+       lsm_md_dump(D_INODE, lsm);
+
        /* 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. */
@@ -1263,93 +1340,103 @@ static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md)
                 * 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 =
+               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;
+                       while (i-- > 0) {
+                               iput(lsm->lsm_md_oinfo[i].lmo_root);
+                               lsm->lsm_md_oinfo[i].lmo_root = NULL;
+                       }
                        return rc;
                }
        }
 
-       return 0;
-}
+       lli->lli_lsm_md = lsm;
 
-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;
+       return 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;
+       int rc = 0;
+
        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);
+       /*
+        * no striped information from request, lustre_md from req does not
+        * include stripeEA, see ll_md_setattr()
+        */
+       if (!lsm)
+               RETURN(0);
+
+       /*
+        * normally dir layout doesn't change, only take read lock to check
+        * that to avoid blocking other MD operations.
+        */
+       if (lli->lli_lsm_md)
+               down_read(&lli->lli_lsm_sem);
+       else
+               down_write(&lli->lli_lsm_sem);
+
+       /*
+        * if dir layout mismatch, check whether version is increased, which
+        * means layout is changed, this happens in dir migration and lfsck.
+        */
+       if (lli->lli_lsm_md && !lsm_md_eq(lli->lli_lsm_md, lsm)) {
+               if (lsm->lsm_md_layout_version <=
+                   lli->lli_lsm_md->lsm_md_layout_version) {
+                       CERROR("%s: "DFID" dir layout mismatch:\n",
+                               ll_get_fsname(inode->i_sb, NULL, 0),
+                               PFID(&lli->lli_fid));
+                       lsm_md_dump(D_ERROR, lli->lli_lsm_md);
+                       lsm_md_dump(D_ERROR, lsm);
+                       GOTO(unlock, rc = -EINVAL);
                }
+
+               /* layout changed, switch to write lock */
+               up_read(&lli->lli_lsm_sem);
+               down_write(&lli->lli_lsm_sem);
+               ll_dir_clear_lsm_md(inode);
        }
 
-       /* set the directory layout */
-       if (lli->lli_lsm_md == NULL) {
+       /* set directory layout */
+       if (!lli->lli_lsm_md) {
                struct cl_attr  *attr;
 
                rc = ll_init_lsm_md(inode, md);
+               up_write(&lli->lli_lsm_sem);
                if (rc != 0)
                        RETURN(rc);
 
                /* set md->lmv to NULL, so the following free lustre_md
                 * will not free this lsm */
                md->lmv = NULL;
-               lli->lli_lsm_md = lsm;
+
+               /*
+                * md_merge_attr() may take long, since lsm is already set,
+                * switch to read lock.
+                */
+               down_read(&lli->lli_lsm_sem);
 
                OBD_ALLOC_PTR(attr);
                if (attr == NULL)
-                       RETURN(-ENOMEM);
+                       GOTO(unlock, rc = -ENOMEM);
 
                /* validate the lsm */
                rc = md_merge_attr(ll_i2mdexp(inode), lsm, attr,
                                   ll_md_blocking_ast);
                if (rc != 0) {
                        OBD_FREE_PTR(attr);
-                       RETURN(rc);
+                       GOTO(unlock, rc);
                }
 
                if (md->body->mbo_valid & OBD_MD_FLNLINK)
@@ -1364,49 +1451,11 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md)
                        md->body->mbo_mtime = attr->cat_mtime;
 
                OBD_FREE_PTR(attr);
-
-               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);
        }
+unlock:
+       up_read(&lli->lli_lsm_sem);
 
-       RETURN(0);
+       RETURN(rc);
 }
 
 void ll_clear_inode(struct inode *inode)
@@ -1447,6 +1496,7 @@ void ll_clear_inode(struct inode *inode)
        ll_xattr_cache_destroy(inode);
 
 #ifdef CONFIG_FS_POSIX_ACL
+       forget_all_cached_acls(inode);
        if (lli->lli_posix_acl) {
                LASSERT(atomic_read(&lli->lli_posix_acl->a_refcount) == 1);
                posix_acl_release(lli->lli_posix_acl);
@@ -1542,7 +1592,8 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data)
  *
  * In case of HSMimport, we only set attr on MDS.
  */
-int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
+int ll_setattr_raw(struct dentry *dentry, struct iattr *attr,
+                  enum op_xvalid xvalid, bool hsm_import)
 {
         struct inode *inode = dentry->d_inode;
         struct ll_inode_info *lli = ll_i2info(inode);
@@ -1582,27 +1633,27 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
                        RETURN(-EPERM);
        }
 
-        /* We mark all of the fields "set" so MDS/OST does not re-set them */
-       if (!(attr->ia_valid & ATTR_CTIME_SET) &&
-           (attr->ia_valid & ATTR_CTIME)) {
-               attr->ia_ctime = CURRENT_TIME;
-                attr->ia_valid |= ATTR_CTIME_SET;
-        }
+       /* We mark all of the fields "set" so MDS/OST does not re-set them */
+       if (!(xvalid & OP_XVALID_CTIME_SET) &&
+            (attr->ia_valid & ATTR_CTIME)) {
+               attr->ia_ctime = current_time(inode);
+               xvalid |= OP_XVALID_CTIME_SET;
+       }
        if (!(attr->ia_valid & ATTR_ATIME_SET) &&
            (attr->ia_valid & ATTR_ATIME)) {
-               attr->ia_atime = CURRENT_TIME;
+               attr->ia_atime = current_time(inode);
                 attr->ia_valid |= ATTR_ATIME_SET;
         }
        if (!(attr->ia_valid & ATTR_MTIME_SET) &&
            (attr->ia_valid & ATTR_MTIME)) {
-               attr->ia_mtime = CURRENT_TIME;
+               attr->ia_mtime = current_time(inode);
                 attr->ia_valid |= ATTR_MTIME_SET;
         }
 
         if (attr->ia_valid & (ATTR_MTIME | ATTR_CTIME))
-                CDEBUG(D_INODE, "setting mtime %lu, ctime %lu, now = %lu\n",
-                       LTIME_S(attr->ia_mtime), LTIME_S(attr->ia_ctime),
-                       cfs_time_current_sec());
+               CDEBUG(D_INODE, "setting mtime %lld, ctime %lld, now = %lld\n",
+                      (s64)attr->ia_mtime.tv_sec, (s64)attr->ia_ctime.tv_sec,
+                      ktime_get_real_seconds());
 
        if (S_ISREG(inode->i_mode)) {
                if (attr->ia_valid & ATTR_SIZE)
@@ -1619,13 +1670,22 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
 
        if (!hsm_import && attr->ia_valid & ATTR_SIZE) {
                /* If we are changing file size, file content is
-                * modified, flag it. */
-               attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE;
+                * modified, flag it.
+                */
+               xvalid |= OP_XVALID_OWNEROVERRIDE;
                op_data->op_bias |= MDS_DATA_MODIFIED;
                ll_file_clear_flag(lli, LLIF_DATA_MODIFIED);
        }
 
+       if (attr->ia_valid & ATTR_FILE) {
+               struct ll_file_data *fd = LUSTRE_FPRIVATE(attr->ia_file);
+
+               if (fd->fd_lease_och)
+                       op_data->op_bias |= MDS_TRUNC_KEEP_LEASE;
+       }
+
        op_data->op_attr = *attr;
+       op_data->op_xvalid = xvalid;
 
        rc = ll_md_setattr(dentry, op_data);
        if (rc)
@@ -1634,17 +1694,17 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
        if (!S_ISREG(inode->i_mode) || hsm_import)
                GOTO(out, rc = 0);
 
-       if (attr->ia_valid & (ATTR_SIZE |
-                             ATTR_ATIME | ATTR_ATIME_SET |
-                             ATTR_MTIME | ATTR_MTIME_SET |
-                             ATTR_CTIME | ATTR_CTIME_SET)) {
+       if (attr->ia_valid & (ATTR_SIZE | ATTR_ATIME | ATTR_ATIME_SET |
+                             ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME) ||
+           xvalid & OP_XVALID_CTIME_SET) {
                /* For truncate and utimes sending attributes to OSTs, setting
                 * mtime/atime to the past will be performed under PW [0:EOF]
                 * extent lock (new_size:EOF for truncate).  It may seem
                 * excessive to send mtime/atime updates to OSTs when not
                 * setting times to past, but it is necessary due to possible
-                * time de-synchronization between MDT inode and OST objects */
-               rc = cl_setattr_ost(lli->lli_clob, attr, 0);
+                * time de-synchronization between MDT inode and OST objects
+                */
+               rc = cl_setattr_ost(lli->lli_clob, attr, xvalid, 0);
        }
 
        /* If the file was restored, it needs to set dirty flag.
@@ -1687,6 +1747,12 @@ out:
                inode_lock(inode);
                if ((attr->ia_valid & ATTR_SIZE) && !hsm_import)
                        inode_dio_wait(inode);
+               /* Once we've got the i_mutex, it's safe to set the S_NOSEC
+                * flag.  ll_update_inode (called from ll_md_setattr), clears
+                * inode flags, so there is a gap where S_NOSEC is not set.
+                * This can cause a writer to take the i_mutex unnecessarily,
+                * but this is safe to do and should be rare. */
+               inode_has_no_xattr(inode);
        }
 
        ll_stats_ops_tally(ll_i2sbi(inode), (attr->ia_valid & ATTR_SIZE) ?
@@ -1698,10 +1764,11 @@ out:
 int ll_setattr(struct dentry *de, struct iattr *attr)
 {
        int mode = de->d_inode->i_mode;
+       enum op_xvalid xvalid = 0;
 
        if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) ==
                              (ATTR_CTIME|ATTR_SIZE|ATTR_MODE))
-               attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE;
+               xvalid |= OP_XVALID_OWNEROVERRIDE;
 
        if (((attr->ia_valid & (ATTR_MODE|ATTR_FORCE|ATTR_SIZE)) ==
                               (ATTR_SIZE|ATTR_MODE)) &&
@@ -1722,16 +1789,18 @@ int ll_setattr(struct dentry *de, struct iattr *attr)
            !(attr->ia_valid & ATTR_KILL_SGID))
                attr->ia_valid |= ATTR_KILL_SGID;
 
-       return ll_setattr_raw(de, attr, false);
+       return ll_setattr_raw(de, attr, xvalid, false);
 }
 
-int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
-                       __u64 max_age, __u32 flags)
+int ll_statfs_internal(struct ll_sb_info *sbi, struct obd_statfs *osfs,
+                      u32 flags)
 {
-        struct ll_sb_info *sbi = ll_s2sbi(sb);
-        struct obd_statfs obd_osfs;
-        int rc;
-        ENTRY;
+       struct obd_statfs obd_osfs;
+       time64_t max_age;
+       int rc;
+
+       ENTRY;
+       max_age = ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS;
 
         rc = obd_statfs(NULL, sbi->ll_md_exp, osfs, max_age, flags);
         if (rc) {
@@ -1739,15 +1808,18 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
                 RETURN(rc);
         }
 
-        osfs->os_type = sb->s_magic;
+       osfs->os_type = LL_SUPER_MAGIC;
 
        CDEBUG(D_SUPER, "MDC blocks %llu/%llu objects %llu/%llu\n",
                osfs->os_bavail, osfs->os_blocks, osfs->os_ffree,osfs->os_files);
 
+       if (osfs->os_state & OS_STATE_SUM)
+               GOTO(out, rc);
+
         if (sbi->ll_flags & LL_SBI_LAZYSTATFS)
                 flags |= OBD_STATFS_NODELAY;
 
-        rc = obd_statfs_rqset(sbi->ll_dt_exp, &obd_osfs, max_age, flags);
+       rc = obd_statfs(NULL, sbi->ll_dt_exp, &obd_osfs, max_age, flags);
         if (rc) {
                 CERROR("obd_statfs fails: rc = %d\n", rc);
                 RETURN(rc);
@@ -1772,6 +1844,7 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
                 osfs->os_ffree = obd_osfs.os_ffree;
         }
 
+out:
         RETURN(rc);
 }
 int ll_statfs(struct dentry *de, struct kstatfs *sfs)
@@ -1784,12 +1857,10 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs)
        CDEBUG(D_VFSTRACE, "VFS Op: at %llu jiffies\n", get_jiffies_64());
         ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_STAFS, 1);
 
-        /* Some amount of caching on the client is allowed */
-        rc = ll_statfs_internal(sb, &osfs,
-                                cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
-                                0);
-        if (rc)
-                return rc;
+       /* Some amount of caching on the client is allowed */
+       rc = ll_statfs_internal(ll_s2sbi(sb), &osfs, OBD_STATFS_SUM);
+       if (rc)
+               return rc;
 
         statfs_unpack(sfs, &osfs);
 
@@ -1833,18 +1904,29 @@ void ll_inode_size_unlock(struct inode *inode)
        mutex_unlock(&lli->lli_size_mutex);
 }
 
+void ll_update_inode_flags(struct inode *inode, int ext_flags)
+{
+       inode->i_flags = ll_ext_to_inode_flags(ext_flags);
+       if (ext_flags & LUSTRE_PROJINHERIT_FL)
+               ll_file_set_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT);
+       else
+               ll_file_clear_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT);
+}
+
 int ll_update_inode(struct inode *inode, struct lustre_md *md)
 {
        struct ll_inode_info *lli = ll_i2info(inode);
        struct mdt_body *body = md->body;
        struct ll_sb_info *sbi = ll_i2sbi(inode);
+       int rc = 0;
 
-       if (body->mbo_valid & OBD_MD_FLEASIZE)
-               cl_file_inode_init(inode, md);
+       if (body->mbo_valid & OBD_MD_FLEASIZE) {
+               rc = cl_file_inode_init(inode, md);
+               if (rc)
+                       return rc;
+       }
 
        if (S_ISDIR(inode->i_mode)) {
-               int     rc;
-
                rc = ll_update_lsm_md(inode, md);
                if (rc != 0)
                        return rc;
@@ -1864,27 +1946,31 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md)
        inode->i_generation = cl_fid_build_gen(&body->mbo_fid1);
 
        if (body->mbo_valid & OBD_MD_FLATIME) {
-               if (body->mbo_atime > LTIME_S(inode->i_atime))
-                       LTIME_S(inode->i_atime) = body->mbo_atime;
+               if (body->mbo_atime > inode->i_atime.tv_sec)
+                       inode->i_atime.tv_sec = body->mbo_atime;
                lli->lli_atime = body->mbo_atime;
        }
 
        if (body->mbo_valid & OBD_MD_FLMTIME) {
-               if (body->mbo_mtime > LTIME_S(inode->i_mtime)) {
-                       CDEBUG(D_INODE, "setting ino %lu mtime from %lu "
-                              "to %llu\n", inode->i_ino,
-                              LTIME_S(inode->i_mtime), body->mbo_mtime);
-                       LTIME_S(inode->i_mtime) = body->mbo_mtime;
+               if (body->mbo_mtime > inode->i_mtime.tv_sec) {
+                       CDEBUG(D_INODE,
+                              "setting ino %lu mtime from %lld to %llu\n",
+                              inode->i_ino, (s64)inode->i_mtime.tv_sec,
+                              body->mbo_mtime);
+                       inode->i_mtime.tv_sec = body->mbo_mtime;
                }
                lli->lli_mtime = body->mbo_mtime;
        }
 
        if (body->mbo_valid & OBD_MD_FLCTIME) {
-               if (body->mbo_ctime > LTIME_S(inode->i_ctime))
-                       LTIME_S(inode->i_ctime) = body->mbo_ctime;
+               if (body->mbo_ctime > inode->i_ctime.tv_sec)
+                       inode->i_ctime.tv_sec = body->mbo_ctime;
                lli->lli_ctime = body->mbo_ctime;
        }
 
+       /* Clear i_flags to remove S_NOSEC before permissions are updated */
+       if (body->mbo_valid & OBD_MD_FLFLAGS)
+               ll_update_inode_flags(inode, body->mbo_flags);
        if (body->mbo_valid & OBD_MD_FLMODE)
                inode->i_mode = (inode->i_mode & S_IFMT) |
                                (body->mbo_mode & ~S_IFMT);
@@ -1904,8 +1990,8 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md)
                inode->i_uid = make_kuid(&init_user_ns, body->mbo_uid);
        if (body->mbo_valid & OBD_MD_FLGID)
                inode->i_gid = make_kgid(&init_user_ns, body->mbo_gid);
-       if (body->mbo_valid & OBD_MD_FLFLAGS)
-               inode->i_flags = ll_ext_to_inode_flags(body->mbo_flags);
+       if (body->mbo_valid & OBD_MD_FLPROJID)
+               lli->lli_projid = body->mbo_projid;
        if (body->mbo_valid & OBD_MD_FLNLINK)
                set_nlink(inode, body->mbo_nlink);
        if (body->mbo_valid & OBD_MD_FLRDEV)
@@ -1964,11 +2050,12 @@ int ll_read_inode2(struct inode *inode, void *opaque)
         /* Core attributes from the MDS first.  This is a new inode, and
          * the VFS doesn't zero times in the core inode so we have to do
          * it ourselves.  They will be overwritten by either MDS or OST
-         * attributes - we just need to make sure they aren't newer. */
-        LTIME_S(inode->i_mtime) = 0;
-        LTIME_S(inode->i_atime) = 0;
-        LTIME_S(inode->i_ctime) = 0;
-        inode->i_rdev = 0;
+        * attributes - we just need to make sure they aren't newer.
+        */
+       inode->i_mtime.tv_sec = 0;
+       inode->i_atime.tv_sec = 0;
+       inode->i_ctime.tv_sec = 0;
+       inode->i_rdev = 0;
        rc = ll_update_inode(inode, md);
        if (rc != 0)
                RETURN(rc);
@@ -2007,6 +2094,8 @@ int ll_read_inode2(struct inode *inode, void *opaque)
 void ll_delete_inode(struct inode *inode)
 {
        struct ll_inode_info *lli = ll_i2info(inode);
+       struct address_space *mapping = &inode->i_data;
+       unsigned long nrpages;
        ENTRY;
 
        if (S_ISREG(inode->i_mode) && lli->lli_clob != NULL)
@@ -2014,11 +2103,26 @@ void ll_delete_inode(struct inode *inode)
                 * otherwise we may lose data while umount */
                cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, CL_FSYNC_LOCAL, 1);
 
-       truncate_inode_pages_final(&inode->i_data);
+       truncate_inode_pages_final(mapping);
 
-       LASSERTF(inode->i_data.nrpages == 0, "inode="DFID"(%p) nrpages=%lu, "
-                "see https://jira.hpdd.intel.com/browse/LU-118\n",
-                PFID(ll_inode2fid(inode)), inode, inode->i_data.nrpages);
+       /* Workaround for LU-118: Note nrpages may not be totally updated when
+        * truncate_inode_pages() returns, as there can be a page in the process
+        * of deletion (inside __delete_from_page_cache()) in the specified
+        * range. Thus mapping->nrpages can be non-zero when this function
+        * returns even after truncation of the whole mapping.  Only do this if
+        * npages isn't already zero.
+        */
+       nrpages = mapping->nrpages;
+       if (nrpages) {
+               spin_lock_irq(&mapping->tree_lock);
+               nrpages = mapping->nrpages;
+               spin_unlock_irq(&mapping->tree_lock);
+       } /* Workaround end */
+
+       LASSERTF(nrpages == 0, "%s: inode="DFID"(%p) nrpages=%lu, "
+                "see https://jira.whamcloud.com/browse/LU-118\n",
+                ll_get_fsname(inode->i_sb, NULL, 0),
+                PFID(ll_inode2fid(inode)), inode, nrpages);
 
 #ifdef HAVE_SBOPS_EVICT_INODE
        ll_clear_inode(inode);
@@ -2031,13 +2135,13 @@ void ll_delete_inode(struct inode *inode)
 int ll_iocontrol(struct inode *inode, struct file *file,
                  unsigned int cmd, unsigned long arg)
 {
-        struct ll_sb_info *sbi = ll_i2sbi(inode);
-        struct ptlrpc_request *req = NULL;
-        int rc, flags = 0;
-        ENTRY;
+       struct ll_sb_info *sbi = ll_i2sbi(inode);
+       struct ptlrpc_request *req = NULL;
+       int rc, flags = 0;
+       ENTRY;
 
-        switch(cmd) {
-        case FSFILT_IOC_GETFLAGS: {
+       switch (cmd) {
+       case FS_IOC_GETFLAGS: {
                 struct mdt_body *body;
                 struct md_op_data *op_data;
 
@@ -2061,32 +2165,41 @@ int ll_iocontrol(struct inode *inode, struct file *file,
 
                flags = body->mbo_flags;
 
-                ptlrpc_req_finished(req);
+               ptlrpc_req_finished(req);
 
                RETURN(put_user(flags, (int __user *)arg));
-        }
-        case FSFILT_IOC_SETFLAGS: {
+       }
+       case FS_IOC_SETFLAGS: {
                struct iattr *attr;
                struct md_op_data *op_data;
                struct cl_object *obj;
+               struct fsxattr fa = { 0 };
 
                if (get_user(flags, (int __user *)arg))
                        RETURN(-EFAULT);
 
-                op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
-                                             LUSTRE_OPC_ANY, NULL);
-                if (IS_ERR(op_data))
-                        RETURN(PTR_ERR(op_data));
+               fa.fsx_projid = ll_i2info(inode)->lli_projid;
+               if (flags & LUSTRE_PROJINHERIT_FL)
+                       fa.fsx_xflags = FS_XFLAG_PROJINHERIT;
+
+               rc = ll_ioctl_check_project(inode, &fa);
+               if (rc)
+                       RETURN(rc);
+
+               op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
+                                            LUSTRE_OPC_ANY, NULL);
+               if (IS_ERR(op_data))
+                       RETURN(PTR_ERR(op_data));
 
                op_data->op_attr_flags = flags;
-                op_data->op_attr.ia_valid |= ATTR_ATTR_FLAG;
+               op_data->op_xvalid |= OP_XVALID_FLAGS;
                rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, &req);
                 ll_finish_md_op_data(op_data);
                 ptlrpc_req_finished(req);
                if (rc)
                        RETURN(rc);
 
-               inode->i_flags = ll_ext_to_inode_flags(flags);
+               ll_update_inode_flags(inode, flags);
 
                obj = ll_i2info(inode)->lli_clob;
                if (obj == NULL)
@@ -2096,8 +2209,7 @@ int ll_iocontrol(struct inode *inode, struct file *file,
                if (attr == NULL)
                        RETURN(-ENOMEM);
 
-               attr->ia_valid = ATTR_ATTR_FLAG;
-               rc = cl_setattr_ost(obj, attr, flags);
+               rc = cl_setattr_ost(obj, attr, OP_XVALID_FLAGS, flags);
 
                OBD_FREE_PTR(attr);
                RETURN(rc);
@@ -2245,7 +2357,7 @@ void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req)
        }
 
        op_data->op_fid1 = body->mbo_fid1;
-       op_data->op_handle = body->mbo_handle;
+       op_data->op_open_handle = body->mbo_open_handle;
        op_data->op_mod_time = ktime_get_real_seconds();
        md_close(exp, op_data, NULL, &close_req);
        ptlrpc_req_finished(close_req);
@@ -2383,35 +2495,25 @@ int ll_obd_statfs(struct inode *inode, void __user *arg)
         if (rc)
                 GOTO(out_statfs, rc);
 out_statfs:
-        if (buf)
-                obd_ioctl_freedata(buf, len);
-        return rc;
+       OBD_FREE_LARGE(buf, len);
+       return rc;
 }
 
-int ll_process_config(struct lustre_cfg *lcfg)
+/*
+ * this is normally called in ll_fini_md_op_data(), but sometimes it needs to
+ * be called early to avoid deadlock.
+ */
+void ll_unlock_md_op_lsm(struct md_op_data *op_data)
 {
-       struct super_block *sb;
-       unsigned long x;
-       int rc = 0;
-       char *ptr;
+       if (op_data->op_mea2_sem) {
+               up_read(op_data->op_mea2_sem);
+               op_data->op_mea2_sem = NULL;
+       }
 
-       /* The instance name contains the sb: lustre-client-aacfe000 */
-       ptr = strrchr(lustre_cfg_string(lcfg, 0), '-');
-       if (!ptr || !*(++ptr))
-               return -EINVAL;
-       if (sscanf(ptr, "%lx", &x) != 1)
-               return -EINVAL;
-       sb = (struct super_block *)x;
-       /* This better be a real Lustre superblock! */
-       LASSERT(s2lsi(sb)->lsi_lmd->lmd_magic == LMD_MAGIC);
-
-       /* Note we have not called client_common_fill_super yet, so
-          proc fns must be able to handle that! */
-       rc = class_process_proc_param(PARAM_LLITE, lprocfs_llite_obd_vars,
-                                     lcfg, sb);
-       if (rc > 0)
-               rc = 0;
-       return rc;
+       if (op_data->op_mea1_sem) {
+               up_read(op_data->op_mea1_sem);
+               op_data->op_mea1_sem = NULL;
+       }
 }
 
 /* this function prepares md_op_data hint for passing it down to MD stack. */
@@ -2443,7 +2545,10 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
        ll_i2gids(op_data->op_suppgids, i1, i2);
        op_data->op_fid1 = *ll_inode2fid(i1);
        op_data->op_default_stripe_offset = -1;
+
        if (S_ISDIR(i1->i_mode)) {
+               down_read(&ll_i2info(i1)->lli_lsm_sem);
+               op_data->op_mea1_sem = &ll_i2info(i1)->lli_lsm_sem;
                op_data->op_mea1 = ll_i2info(i1)->lli_lsm_md;
                if (opc == LUSTRE_OPC_MKDIR)
                        op_data->op_default_stripe_offset =
@@ -2452,8 +2557,14 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
 
        if (i2) {
                op_data->op_fid2 = *ll_inode2fid(i2);
-               if (S_ISDIR(i2->i_mode))
+               if (S_ISDIR(i2->i_mode)) {
+                       if (i2 != i1) {
+                               down_read(&ll_i2info(i2)->lli_lsm_sem);
+                               op_data->op_mea2_sem =
+                                               &ll_i2info(i2)->lli_lsm_sem;
+                       }
                        op_data->op_mea2 = ll_i2info(i2)->lli_lsm_md;
+               }
        } else {
                fid_zero(&op_data->op_fid2);
        }
@@ -2467,15 +2578,14 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_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_mod_time = ktime_get_real_seconds();
        op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid());
        op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid());
        op_data->op_cap = cfs_curproc_cap_pack();
+       op_data->op_mds = 0;
        if ((opc == LUSTRE_OPC_CREATE) && (name != NULL) &&
             filename_is_volatile(name, namelen, &op_data->op_mds)) {
                op_data->op_bias |= MDS_CREATE_VOLATILE;
-       } else {
-               op_data->op_mds = 0;
        }
        op_data->op_data = data;
 
@@ -2484,6 +2594,7 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
 
 void ll_finish_md_op_data(struct md_op_data *op_data)
 {
+       ll_unlock_md_op_lsm(op_data);
        security_release_secctx(op_data->op_file_secctx,
                                op_data->op_file_secctx_size);
         OBD_FREE_PTR(op_data);
@@ -2749,7 +2860,6 @@ static int ll_linkea_decode(struct linkea_data *ldata, unsigned int linkno,
  */
 int ll_getparent(struct file *file, struct getparent __user *arg)
 {
-       struct dentry           *dentry = file_dentry(file);
        struct inode            *inode = file_inode(file);
        struct linkea_data      *ldata;
        struct lu_buf            buf = LU_BUF_NULL;
@@ -2782,7 +2892,13 @@ int ll_getparent(struct file *file, struct getparent __user *arg)
        if (rc < 0)
                GOTO(ldata_free, rc);
 
-       rc = ll_getxattr(dentry, XATTR_NAME_LINK, buf.lb_buf, buf.lb_len);
+#ifdef HAVE_XATTR_HANDLER_FLAGS
+       rc = ll_xattr_list(inode, XATTR_NAME_LINK, XATTR_TRUSTED_T, buf.lb_buf,
+                          buf.lb_len, OBD_MD_FLXATTR);
+#else
+       rc = ll_getxattr(file_dentry(file), XATTR_NAME_LINK, buf.lb_buf,
+                        buf.lb_len);
+#endif /* HAVE_XATTR_HANDLER_FLAGS */
        if (rc < 0)
                GOTO(lb_free, rc);