Whamcloud - gitweb
LU-12355 llite: MS_* flags and SB_* flags split
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_handler.c
index a93f4f6..6ae6a64 100644 (file)
@@ -423,7 +423,7 @@ struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
         */
         /* LASSERT(current->journal_info == NULL); */
 
-       inode = ldiskfs_iget(osd_sb(dev), id->oii_ino);
+       inode = osd_ldiskfs_iget(osd_sb(dev), id->oii_ino);
        if (IS_ERR(inode)) {
                CDEBUG(D_INODE, "no inode: ino = %u, rc = %ld\n",
                       id->oii_ino, PTR_ERR(inode));
@@ -559,7 +559,7 @@ static struct inode *osd_iget_check(struct osd_thread_info *info,
         */
 
 again:
-       inode = ldiskfs_iget(osd_sb(dev), id->oii_ino);
+       inode = osd_ldiskfs_iget(osd_sb(dev), id->oii_ino);
        if (IS_ERR(inode)) {
                rc = PTR_ERR(inode);
                if (!trusted && (rc == -ENOENT || rc == -ESTALE))
@@ -706,29 +706,30 @@ put:
 }
 
 /**
- * \retval +v: new filter_fid, does not contain self-fid
- * \retval 0:  filter_fid_old, contains self-fid
+ * \retval +v: new filter_fid does not contain self-fid
+ * \retval 0:  filter_fid_18_23, contains self-fid
  * \retval -v: other failure cases
  */
 int osd_get_idif(struct osd_thread_info *info, struct inode *inode,
                 struct dentry *dentry, struct lu_fid *fid)
 {
-       struct filter_fid_old *ff = &info->oti_ff;
+       struct filter_fid *ff = &info->oti_ff;
        struct ost_id *ostid = &info->oti_ostid;
        int rc;
 
        rc = __osd_xattr_get(inode, dentry, XATTR_NAME_FID, ff, sizeof(*ff));
-       if (rc == sizeof(*ff)) {
-               rc = 0;
-               ostid_set_seq(ostid, le64_to_cpu(ff->ff_seq));
-               rc = ostid_set_id(ostid, le64_to_cpu(ff->ff_objid));
+       if (rc == sizeof(struct filter_fid_18_23)) {
+               struct filter_fid_18_23 *ff_old = (void *)ff;
+
+               ostid_set_seq(ostid, le64_to_cpu(ff_old->ff_seq));
+               rc = ostid_set_id(ostid, le64_to_cpu(ff_old->ff_objid));
                /*
                 * XXX: use 0 as the index for compatibility, the caller will
                 * handle index related issues when necessary.
                 */
                if (!rc)
                        ostid_to_fid(fid, ostid, 0);
-       } else if (rc == sizeof(struct filter_fid)) {
+       } else if (rc >= (int)sizeof(struct filter_fid_24_29)) {
                rc = 1;
        } else if (rc >= 0) {
                rc = -EINVAL;
@@ -782,7 +783,7 @@ static int osd_check_lma(const struct lu_env *env, struct osd_object *obj)
        if (rc == -ENODATA && !fid_is_igif(rfid) && osd->od_check_ff) {
                fid = &lma->lma_self_fid;
                rc = osd_get_idif(info, inode, dentry, fid);
-               if ((rc > 0) || (rc == -ENODATA && osd->od_index_in_idif)) {
+               if (rc > 0 || (rc == -ENODATA && osd->od_index_in_idif)) {
                        /*
                         * For the given OST-object, if it has neither LMA nor
                         * FID in XATTR_NAME_FID, then the given FID (which is
@@ -1127,6 +1128,12 @@ static int osd_fid_lookup(const struct lu_env *env, struct osd_object *obj,
                goto trigger;
        }
 
+       /* -ESTALE is returned if inode of OST object doesn't exist */
+       if (result == -ESTALE &&
+           fid_is_on_ost(info, dev, fid, OI_CHECK_FLD)) {
+               GOTO(out, result = 0);
+       }
+
        if (result)
                GOTO(out, result);
 
@@ -1289,6 +1296,19 @@ check_lma:
 
        LASSERT(!updated);
 
+       /*
+        * if two OST objects map to the same inode, and inode mode is
+        * (S_IFREG | S_ISUID | S_ISGID | S_ISVTX | 0666), which means it's
+        * reserved by precreate, and not written yet, in this case, don't
+        * set inode for the object whose FID mismatch, so that it can create
+        * inode and not block precreate.
+        */
+       if (fid_is_on_ost(info, dev, fid, OI_CHECK_FLD) &&
+           inode->i_mode == (S_IFREG | S_ISUID | S_ISGID | S_ISVTX | 0666)) {
+               obj->oo_inode = NULL;
+               GOTO(out, result = 0);
+       }
+
        result = osd_oi_lookup(info, dev, fid, id, OI_CHECK_FLD);
        /*
         * "result == -ENOENT" means the cached OI mapping has been removed
@@ -1706,8 +1726,7 @@ static void osd_trans_commit_cb(struct super_block *sb,
        if (error)
                CERROR("transaction @0x%p commit error: %d\n", th, error);
 
-       dt_txn_hook_commit(th);
-
+       OBD_FAIL_TIMEOUT(OBD_FAIL_OST_DELAY_TRANS, 40);
        /* call per-transaction callbacks if any */
        list_for_each_entry_safe(dcb, tmp, &oh->ot_commit_dcb_list,
                                 dcb_linkage) {
@@ -1864,7 +1883,7 @@ static int osd_trans_start(const struct lu_env *env, struct dt_device *d,
                 */
                if (last_credits != oh->ot_credits &&
                    time_after(jiffies, last_printed +
-                              msecs_to_jiffies(60 * MSEC_PER_SEC)) &&
+                              cfs_time_seconds(60)) &&
                    osd_transaction_size(dev) > 512) {
                        CWARN("%s: credits %u > trans_max %u\n", osd_name(dev),
                              oh->ot_credits, osd_transaction_size(dev));
@@ -1894,6 +1913,9 @@ static int osd_trans_start(const struct lu_env *env, struct dt_device *d,
                        oh->ot_credits = osd_transaction_size(dev);
        }
 
+       if (OBD_FAIL_CHECK(OBD_FAIL_OSD_TXN_START))
+               GOTO(out, rc = -EIO);
+
        /*
         * XXX temporary stuff. Some abstraction layer should
         * be used.
@@ -1965,7 +1987,7 @@ static int osd_trans_stop(const struct lu_env *env, struct dt_device *dt,
        struct osd_thandle *oh;
        struct osd_iobuf *iobuf = &oti->oti_iobuf;
        struct osd_device *osd = osd_dt_dev(th->th_dev);
-       struct qsd_instance *qsd = osd->od_quota_slave;
+       struct qsd_instance *qsd = osd_def_qsd(osd);
        struct lquota_trans *qtrans;
        struct list_head truncates = LIST_HEAD_INIT(truncates);
        int rc = 0, remove_agents = 0;
@@ -2080,7 +2102,11 @@ static int osd_trans_cb_add(struct thandle *th, struct dt_txn_commit_cb *dcb)
 static void osd_object_delete(const struct lu_env *env, struct lu_object *l)
 {
        struct osd_object *obj = osd_obj(l);
+       struct qsd_instance *qsd = osd_def_qsd(osd_obj2dev(obj));
        struct inode *inode = obj->oo_inode;
+       __u64 projid;
+       qid_t uid;
+       qid_t gid;
 
        LINVRNT(osd_invariant(obj));
 
@@ -2089,27 +2115,36 @@ static void osd_object_delete(const struct lu_env *env, struct lu_object *l)
         */
 
        osd_index_fini(obj);
-       if (inode != NULL) {
-               struct qsd_instance     *qsd = osd_obj2dev(obj)->od_quota_slave;
-               qid_t                    uid = i_uid_read(inode);
-               qid_t                    gid = i_gid_read(inode);
 
-               obj->oo_inode = NULL;
-               iput(inode);
-               if (!obj->oo_header && qsd) {
-                       struct osd_thread_info *info = osd_oti_get(env);
-                       struct lquota_id_info *qi = &info->oti_qi;
+       if (!inode)
+               return;
+
+       uid = i_uid_read(inode);
+       gid = i_gid_read(inode);
+       projid = i_projid_read(inode);
 
-                       /* Release granted quota to master if necessary */
-                       qi->lqi_id.qid_uid = uid;
-                       qsd_op_adjust(env, qsd, &qi->lqi_id, USRQUOTA);
+       obj->oo_inode = NULL;
+       iput(inode);
+
+       /* do not rebalance quota if the caller needs to release memory
+        * otherwise qsd_refresh_usage() may went into a new ldiskfs
+        * transaction and risk to deadlock - LU-12178 */
+       if (current->flags & (PF_MEMALLOC | PF_KSWAPD))
+               return;
 
-                       qi->lqi_id.qid_uid = gid;
-                       qsd_op_adjust(env, qsd, &qi->lqi_id, GRPQUOTA);
+       if (!obj->oo_header && qsd) {
+               struct osd_thread_info *info = osd_oti_get(env);
+               struct lquota_id_info *qi = &info->oti_qi;
 
-                       qi->lqi_id.qid_uid = i_projid_read(inode);
-                       qsd_op_adjust(env, qsd, &qi->lqi_id, PRJQUOTA);
-               }
+               /* Release granted quota to master if necessary */
+               qi->lqi_id.qid_uid = uid;
+               qsd_op_adjust(env, qsd, &qi->lqi_id, USRQUOTA);
+
+               qi->lqi_id.qid_uid = gid;
+               qsd_op_adjust(env, qsd, &qi->lqi_id, GRPQUOTA);
+
+               qi->lqi_id.qid_uid = projid;
+               qsd_op_adjust(env, qsd, &qi->lqi_id, PRJQUOTA);
        }
 }
 
@@ -2155,7 +2190,7 @@ static int osd_object_print(const struct lu_env *env, void *cookie,
  * Concurrency: shouldn't matter.
  */
 int osd_statfs(const struct lu_env *env, struct dt_device *d,
-               struct obd_statfs *sfs)
+               struct obd_statfs *sfs, struct obd_statfs_info *info)
 {
        struct osd_device *osd = osd_dt_dev(d);
        struct super_block *sb = osd_sb(osd);
@@ -2180,8 +2215,11 @@ int osd_statfs(const struct lu_env *env, struct dt_device *d,
                goto out;
 
        statfs_pack(sfs, ksfs);
-       if (unlikely(sb->s_flags & MS_RDONLY))
+       if (unlikely(sb->s_flags & SB_RDONLY))
                sfs->os_state |= OS_STATE_READONLY;
+
+       sfs->os_state |= osd->od_nonrotational ? OS_STATE_NONROT : 0;
+
        if (ldiskfs_has_feature_extents(sb))
                sfs->os_maxbytes = sb->s_maxbytes;
        else
@@ -2251,12 +2289,12 @@ static void osd_conf_get(const struct lu_env *env,
         */
        param->ddp_inodespace     = PER_OBJ_USAGE;
        /*
-        * EXT_INIT_MAX_LEN is the theoretical maximum extent size  (32k blocks
-        * = 128MB) which is unlikely to be hit in real life. Report a smaller
-        * maximum length to not under count the actual number of extents
-        * needed for writing a file.
+        * EXT_INIT_MAX_LEN is the theoretical maximum extent size (32k blocks
+        * is 128MB) which is unlikely to be hit in real life. Report a smaller
+        * maximum length to not under-count the actual number of extents
+        * needed for writing a file if there are sub-optimal block allocations.
         */
-       param->ddp_max_extent_blks = EXT_INIT_MAX_LEN >> 2;
+       param->ddp_max_extent_blks = EXT_INIT_MAX_LEN >> 1;
        /* worst-case extent insertion metadata overhead */
        param->ddp_extent_tax = 6 * LDISKFS_BLOCK_SIZE(sb);
        param->ddp_mntopts = 0;
@@ -2281,8 +2319,8 @@ static void osd_conf_get(const struct lu_env *env,
 #endif
                param->ddp_max_ea_size = sb->s_blocksize - ea_overhead;
 
-       if (param->ddp_max_ea_size > OSD_MAX_EA_SIZE)
-               param->ddp_max_ea_size = OSD_MAX_EA_SIZE;
+       if (param->ddp_max_ea_size > OBD_MAX_EA_SIZE)
+               param->ddp_max_ea_size = OBD_MAX_EA_SIZE;
 
        /*
         * Preferred RPC size for efficient disk IO.  4MB shows good
@@ -2311,22 +2349,32 @@ static void osd_conf_get(const struct lu_env *env,
                            sizeof("T10-DIF-TYPE") - 1) == 0) {
                        /* also skip "1/3-" at end */
                        const int type_off = sizeof("T10-DIF-TYPE.");
+                       char type_number = name[type_off - 2];
 
-                       if (interval != 512 && interval != 4096)
+                       if (interval != 512 && interval != 4096) {
                                CERROR("%s: unsupported T10PI sector size %u\n",
                                       d->od_svname, interval);
-                       else if (strcmp(name + type_off, "CRC") == 0)
+                       } else if (type_number != '1' && type_number != '3') {
+                               CERROR("%s: unsupported T10PI type %s\n",
+                                      d->od_svname, name);
+                       } else if (strcmp(name + type_off, "CRC") == 0) {
+                               d->od_t10_type = type_number == '1' ?
+                                       OSD_T10_TYPE1_CRC : OSD_T10_TYPE3_CRC;
                                param->ddp_t10_cksum_type = interval == 512 ?
                                        OBD_CKSUM_T10CRC512 :
                                        OBD_CKSUM_T10CRC4K;
-                       else if (strcmp(name + type_off, "IP") == 0)
+                       } else if (strcmp(name + type_off, "IP") == 0) {
+                               d->od_t10_type = type_number == '1' ?
+                                       OSD_T10_TYPE1_IP : OSD_T10_TYPE3_IP;
                                param->ddp_t10_cksum_type = interval == 512 ?
                                        OBD_CKSUM_T10IP512 :
                                        OBD_CKSUM_T10IP4K;
-                       else
+                       } else {
                                CERROR("%s: unsupported checksum type of "
                                       "T10PI type '%s'",
                                       d->od_svname, name);
+                       }
+
                } else {
                        CERROR("%s: unsupported T10PI type '%s'",
                               d->od_svname, name);
@@ -2334,6 +2382,11 @@ static void osd_conf_get(const struct lu_env *env,
        }
 }
 
+static struct super_block *osd_mnt_sb_get(const struct dt_device *d)
+{
+       return osd_sb(osd_dt_dev(d));
+}
+
 /*
  * Concurrency: shouldn't matter.
  */
@@ -2496,6 +2549,7 @@ static const struct dt_device_operations osd_dt_ops = {
        .dt_trans_stop     = osd_trans_stop,
        .dt_trans_cb_add   = osd_trans_cb_add,
        .dt_conf_get       = osd_conf_get,
+       .dt_mnt_sb_get     = osd_mnt_sb_get,
        .dt_sync           = osd_sync,
        .dt_ro             = osd_ro,
        .dt_commit_async   = osd_commit_async,
@@ -2567,18 +2621,6 @@ static int osd_write_locked(const struct lu_env *env, struct dt_object *dt)
        return obj->oo_owner == env;
 }
 
-static struct timespec *osd_inode_time(const struct lu_env *env,
-                                      struct inode *inode, __u64 seconds)
-{
-       struct osd_thread_info *oti = osd_oti_get(env);
-       struct timespec *t = &oti->oti_time;
-
-       t->tv_sec = seconds;
-       t->tv_nsec = 0;
-       *t = timespec_trunc(*t, inode->i_sb->s_time_gran);
-       return t;
-}
-
 static void osd_inode_getattr(const struct lu_env *env,
                              struct inode *inode, struct lu_attr *attr)
 {
@@ -2587,9 +2629,9 @@ static void osd_inode_getattr(const struct lu_env *env,
                           LA_PROJID | LA_FLAGS | LA_NLINK | LA_RDEV |
                           LA_BLKSIZE | LA_TYPE;
 
-       attr->la_atime   = LTIME_S(inode->i_atime);
-       attr->la_mtime   = LTIME_S(inode->i_mtime);
-       attr->la_ctime   = LTIME_S(inode->i_ctime);
+       attr->la_atime = inode->i_atime.tv_sec;
+       attr->la_mtime = inode->i_mtime.tv_sec;
+       attr->la_ctime = inode->i_ctime.tv_sec;
        attr->la_mode    = inode->i_mode;
        attr->la_size    = i_size_read(inode);
        attr->la_blocks  = inode->i_blocks;
@@ -2610,8 +2652,7 @@ static void osd_inode_getattr(const struct lu_env *env,
                attr->la_flags |= LUSTRE_PROJINHERIT_FL;
 }
 
-static int osd_attr_get(const struct lu_env *env,
-                       struct dt_object *dt,
+static int osd_attr_get(const struct lu_env *env, struct dt_object *dt,
                        struct lu_attr *attr)
 {
        struct osd_object *obj = osd_dt_obj(dt);
@@ -2626,8 +2667,10 @@ static int osd_attr_get(const struct lu_env *env,
 
        spin_lock(&obj->oo_guard);
        osd_inode_getattr(env, obj->oo_inode, attr);
-       if (obj->oo_lma_flags & LUSTRE_ORPHAN_FL)
+       if (obj->oo_lma_flags & LUSTRE_ORPHAN_FL) {
+               attr->la_valid |= LA_FLAGS;
                attr->la_flags |= LUSTRE_ORPHAN_FL;
+       }
        spin_unlock(&obj->oo_guard);
 
        return 0;
@@ -2793,11 +2836,11 @@ static int osd_inode_setattr(const struct lu_env *env,
                return 0;
 
        if (bits & LA_ATIME)
-               inode->i_atime  = *osd_inode_time(env, inode, attr->la_atime);
+               inode->i_atime = osd_inode_time(inode, attr->la_atime);
        if (bits & LA_CTIME)
-               inode->i_ctime  = *osd_inode_time(env, inode, attr->la_ctime);
+               inode->i_ctime = osd_inode_time(inode, attr->la_ctime);
        if (bits & LA_MTIME)
-               inode->i_mtime  = *osd_inode_time(env, inode, attr->la_mtime);
+               inode->i_mtime = osd_inode_time(inode, attr->la_mtime);
        if (bits & LA_SIZE) {
                spin_lock(&inode->i_lock);
                LDISKFS_I(inode)->i_disksize = attr->la_size;
@@ -3042,13 +3085,19 @@ static struct dentry *osd_child_dentry_get(const struct lu_env *env,
 
 static int osd_mkfile(struct osd_thread_info *info, struct osd_object *obj,
                      umode_t mode, struct dt_allocation_hint *hint,
-                     struct thandle *th)
+                     struct thandle *th, struct lu_attr *attr)
 {
        int result;
        struct osd_device *osd = osd_obj2dev(obj);
        struct osd_thandle *oth;
        struct dt_object *parent = NULL;
        struct inode *inode;
+       uid_t owner[2] = {0, 0};
+
+       if (attr->la_valid & LA_UID)
+               owner[0] = attr->la_uid;
+       if (attr->la_valid & LA_GID)
+               owner[1] = attr->la_gid;
 
        LINVRNT(osd_invariant(obj));
        LASSERT(obj->oo_inode == NULL);
@@ -3071,7 +3120,7 @@ static int osd_mkfile(struct osd_thread_info *info, struct osd_object *obj,
        inode = ldiskfs_create_inode(oth->ot_handle,
                                     parent ? osd_dt_obj(parent)->oo_inode :
                                              osd_sb(osd)->s_root->d_inode,
-                                    mode);
+                                    mode, owner);
        if (!IS_ERR(inode)) {
                /* Do not update file c/mtime in ldiskfs. */
                inode->i_flags |= S_NOCMTIME;
@@ -3113,7 +3162,7 @@ static int osd_mkdir(struct osd_thread_info *info, struct osd_object *obj,
 
        oth = container_of(th, struct osd_thandle, ot_super);
        LASSERT(oth->ot_handle->h_transaction != NULL);
-       result = osd_mkfile(info, obj, mode, hint, th);
+       result = osd_mkfile(info, obj, mode, hint, th, attr);
 
        return result;
 }
@@ -3135,7 +3184,7 @@ static int osd_mk_index(struct osd_thread_info *info, struct osd_object *obj,
        oth = container_of(th, struct osd_thandle, ot_super);
        LASSERT(oth->ot_handle->h_transaction != NULL);
 
-       result = osd_mkfile(info, obj, mode, hint, th);
+       result = osd_mkfile(info, obj, mode, hint, th, attr);
        if (result == 0) {
                LASSERT(obj->oo_inode != NULL);
                if (feat->dif_flags & DT_IND_VARKEY)
@@ -3162,7 +3211,8 @@ static int osd_mkreg(struct osd_thread_info *info, struct osd_object *obj,
 {
        LASSERT(S_ISREG(attr->la_mode));
        return osd_mkfile(info, obj, (attr->la_mode &
-                        (S_IFMT | S_IALLUGO | S_ISVTX)), hint, th);
+                        (S_IFMT | S_IALLUGO | S_ISVTX)), hint, th,
+                         attr);
 }
 
 static int osd_mksym(struct osd_thread_info *info, struct osd_object *obj,
@@ -3173,7 +3223,8 @@ static int osd_mksym(struct osd_thread_info *info, struct osd_object *obj,
 {
        LASSERT(S_ISLNK(attr->la_mode));
        return osd_mkfile(info, obj, (attr->la_mode &
-                        (S_IFMT | S_IALLUGO | S_ISVTX)), hint, th);
+                        (S_IFMT | S_IALLUGO | S_ISVTX)), hint, th,
+                         attr);
 }
 
 static int osd_mknod(struct osd_thread_info *info, struct osd_object *obj,
@@ -3190,7 +3241,7 @@ static int osd_mknod(struct osd_thread_info *info, struct osd_object *obj,
        LASSERT(S_ISCHR(mode) || S_ISBLK(mode) ||
                S_ISFIFO(mode) || S_ISSOCK(mode));
 
-       result = osd_mkfile(info, obj, mode, hint, th);
+       result = osd_mkfile(info, obj, mode, hint, th, attr);
        if (result == 0) {
                LASSERT(obj->oo_inode != NULL);
                /*
@@ -3267,11 +3318,11 @@ static void osd_attr_init(struct osd_thread_info *info, struct osd_object *obj,
 
        if (dof->dof_type != DFT_NODE)
                attr->la_valid &= ~LA_RDEV;
-       if ((valid & LA_ATIME) && (attr->la_atime == LTIME_S(inode->i_atime)))
+       if ((valid & LA_ATIME) && (attr->la_atime == inode->i_atime.tv_sec))
                attr->la_valid &= ~LA_ATIME;
-       if ((valid & LA_CTIME) && (attr->la_ctime == LTIME_S(inode->i_ctime)))
+       if ((valid & LA_CTIME) && (attr->la_ctime == inode->i_ctime.tv_sec))
                attr->la_valid &= ~LA_CTIME;
-       if ((valid & LA_MTIME) && (attr->la_mtime == LTIME_S(inode->i_mtime)))
+       if ((valid & LA_MTIME) && (attr->la_mtime == inode->i_mtime.tv_sec))
                attr->la_valid &= ~LA_MTIME;
 
        result = osd_quota_transfer(inode, attr);
@@ -3360,6 +3411,19 @@ static int __osd_oi_insert(const struct lu_env *env, struct osd_object *obj,
        osd_id_gen(id, obj->oo_inode->i_ino, obj->oo_inode->i_generation);
        rc = osd_oi_insert(info, osd, fid, id, oh->ot_handle,
                           OI_CHECK_FLD, NULL);
+       if (CFS_FAIL_CHECK(OBD_FAIL_OSD_DUPLICATE_MAP) && osd->od_is_ost) {
+               struct lu_fid next_fid = *fid;
+
+               /* insert next object in advance, and map to the same inode */
+               next_fid.f_oid++;
+               if (next_fid.f_oid != 0) {
+                       osd_trans_exec_op(env, th, OSD_OT_INSERT);
+                       osd_oi_insert(info, osd, &next_fid, id, oh->ot_handle,
+                                     OI_CHECK_FLD, NULL);
+                       osd_trans_exec_check(env, th, OSD_OT_INSERT);
+               }
+       }
+
        osd_trans_exec_check(env, th, OSD_OT_INSERT);
 
        return rc;
@@ -3424,6 +3488,9 @@ static int osd_declare_create(const struct lu_env *env, struct dt_object *dt,
         */
        osd_trans_declare_op(env, oh, OSD_OT_INSERT,
                             osd_dto_credits_noquota[DTO_INDEX_INSERT] + 1);
+       if (CFS_FAIL_CHECK(OBD_FAIL_OSD_DUPLICATE_MAP))
+               osd_trans_declare_op(env, oh, OSD_OT_INSERT,
+                            osd_dto_credits_noquota[DTO_INDEX_INSERT] + 1);
 
        /* will help to find FID->ino mapping at dt_insert() */
        rc = osd_idc_find_and_init(env, osd_obj2dev(osd_dt_obj(dt)),
@@ -3741,7 +3808,8 @@ static struct inode *osd_create_local_agent_inode(const struct lu_env *env,
        oh = container_of(th, struct osd_thandle, ot_super);
        LASSERT(oh->ot_handle->h_transaction != NULL);
 
-       local = ldiskfs_create_inode(oh->ot_handle, pobj->oo_inode, type);
+       local = ldiskfs_create_inode(oh->ot_handle, pobj->oo_inode, type,
+                                    NULL);
        if (IS_ERR(local)) {
                CERROR("%s: create local error %d\n", osd_name(osd),
                       (int)PTR_ERR(local));
@@ -3754,6 +3822,19 @@ static struct inode *osd_create_local_agent_inode(const struct lu_env *env,
         */
        local->i_gid = current_fsgid();
        ldiskfs_set_inode_state(local, LDISKFS_STATE_LUSTRE_NOSCRUB);
+
+       /* e2fsck doesn't like empty symlinks.  Store remote FID as symlink.
+        * That gives e2fsck something to look at and be happy, and allows
+        * debugging if we need to determine where this symlink came from.
+        */
+       if (S_ISLNK(type)) {
+               CLASSERT(LDISKFS_N_BLOCKS * 4 >= FID_LEN + 1);
+               rc = snprintf((char *)LDISKFS_I(local)->i_data,
+                             LDISKFS_N_BLOCKS * 4, DFID, PFID(fid));
+
+               i_size_write(local, rc);
+               LDISKFS_I(local)->i_disksize = rc;
+       }
        unlock_new_inode(local);
 
        /* Agent inode should not have project ID */
@@ -4695,7 +4776,7 @@ static int osd_object_sync(const struct lu_env *env, struct dt_object *dt,
        file->f_op = inode->i_fop;
        set_file_inode(file, inode);
 
-       rc = ll_vfs_fsync_range(file, start, end, 0);
+       rc = vfs_fsync_range(file, start, end, 0);
 
        RETURN(rc);
 }
@@ -5261,8 +5342,7 @@ static int osd_index_declare_iam_insert(const struct lu_env *env,
  */
 static int osd_index_iam_insert(const struct lu_env *env, struct dt_object *dt,
                                const struct dt_rec *rec,
-                               const struct dt_key *key, struct thandle *th,
-                               int ignore_quota)
+                               const struct dt_key *key, struct thandle *th)
 {
        struct osd_object *obj = osd_dt_obj(dt);
        struct iam_path_descr *ipd;
@@ -5952,8 +6032,7 @@ static int osd_index_declare_ea_insert(const struct lu_env *env,
  */
 static int osd_index_ea_insert(const struct lu_env *env, struct dt_object *dt,
                               const struct dt_rec *rec,
-                              const struct dt_key *key, struct thandle *th,
-                              int ignore_quota)
+                              const struct dt_key *key, struct thandle *th)
 {
        struct osd_object *obj = osd_dt_obj(dt);
        struct osd_device *osd = osd_dev(dt->do_lu.lo_dev);
@@ -7310,6 +7389,16 @@ static void osd_key_fini(const struct lu_context *ctx,
        struct ldiskfs_inode_info *lli = LDISKFS_I(info->oti_inode);
        struct osd_idmap_cache *idc = info->oti_ins_cache;
 
+       if (info->oti_dio_pages) {
+               int i;
+               for (i = 0; i < PTLRPC_MAX_BRW_PAGES; i++) {
+                       if (info->oti_dio_pages[i])
+                               __free_page(info->oti_dio_pages[i]);
+               }
+               OBD_FREE(info->oti_dio_pages,
+                        sizeof(struct page *) * PTLRPC_MAX_BRW_PAGES);
+       }
+
        if (info->oti_inode != NULL)
                OBD_FREE_PTR(lli);
        if (info->oti_hlock != NULL)
@@ -7317,6 +7406,7 @@ static void osd_key_fini(const struct lu_context *ctx,
        OBD_FREE(info->oti_it_ea_buf, OSD_IT_EA_BUFSIZE);
        lu_buf_free(&info->oti_iobuf.dr_pg_buf);
        lu_buf_free(&info->oti_iobuf.dr_bl_buf);
+       lu_buf_free(&info->oti_iobuf.dr_lnb_buf);
        lu_buf_free(&info->oti_big_buf);
        if (idc != NULL) {
                LASSERT(info->oti_ins_cache_size > 0);
@@ -7412,10 +7502,17 @@ static int osd_shutdown(const struct lu_env *env, struct osd_device *o)
        ENTRY;
 
        /* shutdown quota slave instance associated with the device */
-       if (o->od_quota_slave != NULL) {
-               struct qsd_instance *qsd = o->od_quota_slave;
+       if (o->od_quota_slave_md != NULL) {
+               struct qsd_instance *qsd = o->od_quota_slave_md;
 
-               o->od_quota_slave = NULL;
+               o->od_quota_slave_md = NULL;
+               qsd_fini(env, qsd);
+       }
+
+       if (o->od_quota_slave_dt != NULL) {
+               struct qsd_instance *qsd = o->od_quota_slave_dt;
+
+               o->od_quota_slave_dt = NULL;
                qsd_fini(env, qsd);
        }
 
@@ -7521,7 +7618,7 @@ static int osd_mount(const struct lu_env *env,
                        "force_over_512tb",
                        NULL
                };
-               strcat(options, opts);
+               strncat(options, opts, PAGE_SIZE);
                for (rc = 0, str = options; sout[rc]; ) {
                        char *op = strstr(str, sout[rc]);
 
@@ -7541,13 +7638,13 @@ static int osd_mount(const struct lu_env *env,
                                ;
                }
        } else {
-               strncat(options, "user_xattr,acl", 14);
+               strncat(options, "user_xattr,acl", PAGE_SIZE);
        }
 
        /* Glom up mount options */
        if (*options != '\0')
-               strcat(options, ",");
-       strlcat(options, "no_mbcache,nodelalloc", PAGE_SIZE);
+               strncat(options, ",", PAGE_SIZE);
+       strncat(options, "no_mbcache,nodelalloc", PAGE_SIZE);
 
        type = get_fs_type("ldiskfs");
        if (!type) {
@@ -7620,6 +7717,12 @@ static int osd_mount(const struct lu_env *env,
        if (lmd_flags & LMD_FLG_NOSCRUB)
                o->od_auto_scrub_interval = AS_NEVER;
 
+       if (blk_queue_nonrot(bdev_get_queue(osd_sb(o)->s_bdev))) {
+               /* do not use pagecache with flash-backed storage */
+               o->od_writethrough_cache = 0;
+               o->od_read_cache = 0;
+       }
+
        GOTO(out, rc = 0);
 
 out_mnt:
@@ -7675,10 +7778,12 @@ static int osd_device_init0(const struct lu_env *env,
        INIT_LIST_HEAD(&o->od_index_restore_list);
        spin_lock_init(&o->od_lock);
        o->od_index_backup_policy = LIBP_NONE;
+       o->od_t10_type = 0;
 
        o->od_read_cache = 1;
        o->od_writethrough_cache = 1;
        o->od_readcache_max_filesize = OSD_MAX_CACHE_SIZE;
+
        o->od_auto_scrub_interval = AS_DEFAULT;
 
        cplen = strlcpy(o->od_svname, lustre_cfg_string(cfg, 4),
@@ -7700,6 +7805,10 @@ static int osd_device_init0(const struct lu_env *env,
        if (rc != 0)
                GOTO(out, rc);
 
+       /* Can only check block device after mount */
+       o->od_nonrotational =
+               blk_queue_nonrot(bdev_get_queue(osd_sb(o)->s_bdev));
+
        rc = osd_obj_map_init(env, o);
        if (rc != 0)
                GOTO(out_mnt, rc);
@@ -7732,11 +7841,29 @@ static int osd_device_init0(const struct lu_env *env,
        LASSERT(l->ld_site->ls_linkage.prev != NULL);
 
        /* initialize quota slave instance */
-       o->od_quota_slave = qsd_init(env, o->od_svname, &o->od_dt_dev,
-                                    o->od_proc_entry);
-       if (IS_ERR(o->od_quota_slave)) {
-               rc = PTR_ERR(o->od_quota_slave);
-               o->od_quota_slave = NULL;
+       /* currently it's no need to prepare qsd_instance_md for OST */
+       if (!o->od_is_ost) {
+               o->od_quota_slave_md = qsd_init(env, o->od_svname,
+                                               &o->od_dt_dev,
+                                               o->od_proc_entry, true);
+               if (IS_ERR(o->od_quota_slave_md)) {
+                       rc = PTR_ERR(o->od_quota_slave_md);
+                       o->od_quota_slave_md = NULL;
+                       GOTO(out_procfs, rc);
+               }
+       }
+
+       o->od_quota_slave_dt = qsd_init(env, o->od_svname, &o->od_dt_dev,
+                                       o->od_proc_entry, false);
+
+       if (IS_ERR(o->od_quota_slave_dt)) {
+               if (o->od_quota_slave_md != NULL) {
+                       qsd_fini(env, o->od_quota_slave_md);
+                       o->od_quota_slave_md = NULL;
+               }
+
+               rc = PTR_ERR(o->od_quota_slave_dt);
+               o->od_quota_slave_dt = NULL;
                GOTO(out_procfs, rc);
        }
 
@@ -7809,6 +7936,7 @@ static int osd_process_config(const struct lu_env *env,
                              struct lu_device *d, struct lustre_cfg *cfg)
 {
        struct osd_device *o = osd_dev(d);
+       ssize_t count;
        int rc;
 
        ENTRY;
@@ -7828,15 +7956,12 @@ static int osd_process_config(const struct lu_env *env,
                break;
        case LCFG_PARAM:
                LASSERT(&o->od_dt_dev);
-               rc = class_process_proc_param(PARAM_OSD, lprocfs_osd_obd_vars,
-                                             cfg, &o->od_dt_dev);
-               if (rc > 0 || rc == -ENOSYS) {
-                       rc = class_process_proc_param(PARAM_OST,
-                                                     lprocfs_osd_obd_vars,
-                                                     cfg, &o->od_dt_dev);
-                       if (rc > 0)
-                               rc = 0;
-               }
+               count  = class_modify_config(cfg, PARAM_OSD,
+                                            &o->od_dt_dev.dd_kobj);
+               if (count < 0)
+                       count = class_modify_config(cfg, PARAM_OST,
+                                                   &o->od_dt_dev.dd_kobj);
+               rc = count > 0 ? 0 : count;
                break;
        case LCFG_PRE_CLEANUP:
                osd_scrub_stop(o);
@@ -7859,14 +7984,17 @@ static int osd_recovery_complete(const struct lu_env *env,
 
        ENTRY;
 
-       if (osd->od_quota_slave == NULL)
+       if (osd->od_quota_slave_md == NULL && osd->od_quota_slave_dt == NULL)
                RETURN(0);
 
        /*
         * start qsd instance on recovery completion, this notifies the quota
         * slave code that we are about to process new requests now
         */
-       rc = qsd_start(env, osd->od_quota_slave);
+       rc = qsd_start(env, osd->od_quota_slave_dt);
+       if (rc == 0 && osd->od_quota_slave_md != NULL)
+               rc = qsd_start(env, osd->od_quota_slave_md);
+
        RETURN(rc);
 }
 
@@ -7934,13 +8062,21 @@ static int osd_prepare(const struct lu_env *env, struct lu_device *pdev,
 
        ENTRY;
 
-       if (osd->od_quota_slave != NULL) {
-               /* set up quota slave objects */
-               result = qsd_prepare(env, osd->od_quota_slave);
+       if (osd->od_quota_slave_md != NULL) {
+               /* set up quota slave objects for inode */
+               result = qsd_prepare(env, osd->od_quota_slave_md);
                if (result != 0)
                        RETURN(result);
        }
 
+       if (osd->od_quota_slave_dt != NULL) {
+               /* set up quota slave objects for block */
+               result = qsd_prepare(env, osd->od_quota_slave_dt);
+               if (result != 0)
+                       RETURN(result);
+       }
+
+
        if (lsd->lsd_feature_incompat & OBD_COMPAT_OST) {
 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 52, 0)
                if (lsd->lsd_feature_rocompat & OBD_ROCOMPAT_IDX_IN_IDIF) {
@@ -8011,7 +8147,7 @@ static int osd_health_check(const struct lu_env *env, struct obd_device *obd)
        struct osd_device *osd = osd_dev(obd->obd_lu_dev);
        struct super_block *sb = osd_sb(osd);
 
-       return (osd->od_mnt == NULL || sb->s_flags & MS_RDONLY);
+       return (osd->od_mnt == NULL || sb->s_flags & SB_RDONLY);
 }
 
 /*
@@ -8025,8 +8161,33 @@ static struct obd_ops osd_obd_device_ops = {
        .o_health_check = osd_health_check,
 };
 
+static ssize_t track_declares_assert_show(struct kobject *kobj,
+                                  struct attribute *attr,
+                                  char *buf)
+{
+       return sprintf(buf, "%d\n", ldiskfs_track_declares_assert);
+}
+
+static ssize_t track_declares_assert_store(struct kobject *kobj,
+                                          struct attribute *attr,
+                                          const char *buffer, size_t count)
+{
+       bool track_declares_assert;
+       int rc;
+
+       rc = kstrtobool(buffer, &track_declares_assert);
+       if (rc)
+               return rc;
+
+       ldiskfs_track_declares_assert = track_declares_assert;
+
+       return count;
+}
+LUSTRE_RW_ATTR(track_declares_assert);
+
 static int __init osd_init(void)
 {
+       struct kobject *kobj;
        int rc;
 
        CLASSERT(BH_DXLock < sizeof(((struct buffer_head *)0)->b_state) * 8);
@@ -8047,16 +8208,36 @@ static int __init osd_init(void)
                (void *)kallsyms_lookup_name("dev_check_rdonly");
 #endif
 
-       rc = class_register_type(&osd_obd_device_ops, NULL, true,
-                                lprocfs_osd_module_vars,
+       rc = class_register_type(&osd_obd_device_ops, NULL, true, NULL,
                                 LUSTRE_OSD_LDISKFS_NAME, &osd_device_type);
-       if (rc)
+       if (rc) {
                lu_kmem_fini(ldiskfs_caches);
+               return rc;
+       }
+
+       kobj = kset_find_obj(lustre_kset, LUSTRE_OSD_LDISKFS_NAME);
+       if (kobj) {
+               rc = sysfs_create_file(kobj,
+                                      &lustre_attr_track_declares_assert.attr);
+               kobject_put(kobj);
+               if (rc) {
+                       CWARN("osd-ldiskfs: track_declares_assert failed to register with sysfs\n");
+                       rc = 0;
+               }
+       }
        return rc;
 }
 
 static void __exit osd_exit(void)
 {
+       struct kobject *kobj;
+
+       kobj = kset_find_obj(lustre_kset, LUSTRE_OSD_LDISKFS_NAME);
+       if (kobj) {
+               sysfs_remove_file(kobj,
+                                 &lustre_attr_track_declares_assert.attr);
+               kobject_put(kobj);
+       }
        class_unregister_type(LUSTRE_OSD_LDISKFS_NAME);
        lu_kmem_fini(ldiskfs_caches);
 }