+ CFS_FREE_BITMAP(mds->mds_lov_page_dirty);
+ EXIT;
+}
+
+/**
+ * currently exist two ways for know about ost count and max ost index.
+ * first - after ost is connected to mds and sync process finished
+ * second - get from lmm in recovery process, in case when mds not have configs,
+ * and ost isn't registered in mgs.
+ *
+ * \param mds pointer to mds structure
+ * \param index maxium ost index
+ *
+ * \retval -ENOMEM is not hame memory for new page
+ * \retval 0 is update passed
+ */
+static int mds_lov_update_max_ost(struct mds_obd *mds, obd_id index)
+{
+ __u32 page = index / OBJID_PER_PAGE();
+ __u32 off = index % OBJID_PER_PAGE();
+ obd_id *data = mds->mds_lov_page_array[page];
+
+ if (data == NULL) {
+ OBD_ALLOC(data, MDS_LOV_ALLOC_SIZE);
+ if (data == NULL)
+ RETURN(-ENOMEM);
+
+ mds->mds_lov_page_array[page] = data;
+ }
+
+ if (index > mds->mds_lov_objid_max_index) {
+ mds->mds_lov_objid_lastpage = page;
+ mds->mds_lov_objid_lastidx = off;
+ mds->mds_lov_objid_max_index = index;
+ }
+
+ /* workaround - New target not in objids file; increase mdsize */
+ /* ld_tgt_count is used as the max index everywhere, despite its name. */
+ if (data[off] == 0) {
+ __u32 stripes;
+
+ data[off] = 1;
+ mds->mds_lov_objid_count++;
+ stripes = min_t(__u32, LOV_MAX_STRIPE_COUNT,
+ mds->mds_lov_objid_count);
+
+ mds->mds_max_mdsize = lov_mds_md_size(stripes, LOV_MAGIC_V3);
+ mds->mds_max_cookiesize = stripes * sizeof(struct llog_cookie);
+
+ CDEBUG(D_CONFIG, "updated max_mdsize/max_cookiesize for %d"
+ " stripes: %d/%d\n", stripes, mds->mds_max_mdsize,
+ mds->mds_max_cookiesize);
+ }
+
+ EXIT;
+ return 0;
+}
+
+static int mds_lov_objinit(struct mds_obd *mds, __u32 index)
+{
+ __u32 page = index / OBJID_PER_PAGE();
+ __u32 off = index % OBJID_PER_PAGE();
+ obd_id *data = mds->mds_lov_page_array[page];
+
+ return (data[off] > 0);
+}
+
+int mds_lov_prepare_objids(struct obd_device *obd, struct lov_mds_md *lmm)
+{
+ struct lov_ost_data_v1 *data;
+ __u32 count;
+ int rc = 0;
+ __u32 j;
+
+ /* if we create file without objects - lmm is NULL */
+ if (lmm == NULL)
+ return 0;
+
+ switch (le32_to_cpu(lmm->lmm_magic)) {
+ case LOV_MAGIC_V1:
+ count = le32_to_cpu(((struct lov_mds_md_v1*)lmm)->lmm_stripe_count);
+ data = &(((struct lov_mds_md_v1*)lmm)->lmm_objects[0]);
+ break;
+ case LOV_MAGIC_V3:
+ count = le32_to_cpu(((struct lov_mds_md_v3*)lmm)->lmm_stripe_count);
+ data = &(((struct lov_mds_md_v3*)lmm)->lmm_objects[0]);
+ break;
+ default:
+ CERROR("Unknow lmm type %X!\n", le32_to_cpu(lmm->lmm_magic));
+ RETURN(-EINVAL);
+ }
+
+
+ cfs_mutex_down(&obd->obd_dev_sem);
+ for (j = 0; j < count; j++) {
+ __u32 i = le32_to_cpu(data[j].l_ost_idx);
+ if (mds_lov_update_max_ost(&obd->u.mds, i)) {
+ rc = -ENOMEM;
+ break;
+ }
+ }
+ cfs_mutex_up(&obd->obd_dev_sem);
+
+ RETURN(rc);
+}
+EXPORT_SYMBOL(mds_lov_prepare_objids);
+
+/*
+ * write llog orphan record about lost ost object,
+ * Special lsm is allocated with single stripe, caller should deallocated it
+ * after use
+ */
+static int mds_log_lost_precreated(struct obd_device *obd,
+ struct lov_stripe_md **lsmp, int *stripes,
+ obd_id id, obd_count count, int idx)
+{
+ struct lov_stripe_md *lsm = *lsmp;
+ int rc;
+ ENTRY;
+
+ if (*lsmp == NULL) {
+ rc = obd_alloc_memmd(obd->u.mds.mds_lov_exp, &lsm);
+ if (rc < 0)
+ RETURN(rc);
+ /* need only one stripe, save old value */
+ *stripes = lsm->lsm_stripe_count;
+ lsm->lsm_stripe_count = 1;
+ *lsmp = lsm;
+ }
+
+ lsm->lsm_oinfo[0]->loi_id = id;
+ lsm->lsm_oinfo[0]->loi_seq = mdt_to_obd_objseq(obd->u.mds.mds_id);
+ lsm->lsm_oinfo[0]->loi_ost_idx = idx;
+
+ rc = mds_log_op_orphan(obd, lsm, count);
+ RETURN(rc);
+}
+
+void mds_lov_update_objids(struct obd_device *obd, struct lov_mds_md *lmm)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ int j;
+ struct lov_ost_data_v1 *obj;
+ struct lov_stripe_md *lsm = NULL;
+ int stripes = 0;
+ int count;
+ ENTRY;
+
+ /* if we create file without objects - lmm is NULL */
+ if (lmm == NULL)
+ return;
+
+ switch (le32_to_cpu(lmm->lmm_magic)) {
+ case LOV_MAGIC_V1:
+ count = le32_to_cpu(((struct lov_mds_md_v1*)lmm)->lmm_stripe_count);
+ obj = ((struct lov_mds_md_v1*)lmm)->lmm_objects;
+ break;
+ case LOV_MAGIC_V3:
+ count = le32_to_cpu(((struct lov_mds_md_v3*)lmm)->lmm_stripe_count);
+ obj = ((struct lov_mds_md_v3*)lmm)->lmm_objects;
+ break;
+ default:
+ CERROR("Unknow lmm type %X !\n",
+ le32_to_cpu(lmm->lmm_magic));
+ return;
+ }
+
+ for (j = 0; j < count; j++) {
+ __u32 i = le32_to_cpu(obj[j].l_ost_idx);
+ obd_id id = le64_to_cpu(obj[j].l_object_id);
+ __u32 page = i / OBJID_PER_PAGE();
+ __u32 idx = i % OBJID_PER_PAGE();
+ obd_id *data;
+
+ data = mds->mds_lov_page_array[page];
+
+ CDEBUG(D_INODE,"update last object for ost %u"
+ " - new "LPU64" old "LPU64"\n", i, id, data[idx]);
+ if (id > data[idx]) {
+ int lost = id - data[idx] - 1;
+ /* we might have lost precreated objects due to VBR */
+ if (lost > 0 && obd->obd_recovering) {
+ CDEBUG(D_HA, "Gap in objids is %u\n", lost);
+ if (!obd->obd_version_recov)
+ CERROR("Unexpected gap in objids\n");
+ /* lsm is allocated if NULL */
+ mds_log_lost_precreated(obd, &lsm, &stripes,
+ data[idx]+1, lost, i);
+ }
+ data[idx] = id;
+ cfs_bitmap_set(mds->mds_lov_page_dirty, page);
+ }
+ }
+ if (lsm) {
+ /* restore stripes number */
+ lsm->lsm_stripe_count = stripes;
+ obd_free_memmd(mds->mds_lov_exp, &lsm);
+ }
+ EXIT;
+ return;
+}
+EXPORT_SYMBOL(mds_lov_update_objids);
+
+static int mds_lov_update_from_read(struct mds_obd *mds, obd_id *data,
+ __u32 count)
+{
+ __u32 i;
+ __u32 stripes;
+
+ for (i = 0; i < count; i++) {
+ if (data[i] == 0)
+ continue;
+
+ mds->mds_lov_objid_count++;
+ }
+
+ stripes = min_t(__u32, LOV_MAX_STRIPE_COUNT,
+ mds->mds_lov_objid_count);
+
+ mds->mds_max_mdsize = lov_mds_md_size(stripes, LOV_MAGIC_V3);
+ mds->mds_max_cookiesize = stripes * sizeof(struct llog_cookie);
+
+ CDEBUG(D_CONFIG, "updated max_mdsize/max_cookiesize for %d stripes: "
+ "%d/%d\n", stripes, mds->mds_max_mdsize,
+ mds->mds_max_cookiesize);
+