- return rc;
-}
-
-/* update the LOV-OSC knowledge of the last used object id's */
-int mdd_lov_set_nextid(struct mdd_device *mdd)
-{
- struct mdd_lov_info *lov_info = &mdd->mdd_lov_info;
- int rc;
- ENTRY;
-
- LASSERT(lov_info->mdd_lov_objids != NULL);
-
- rc = obd_set_info_async(lov_info->mdd_lov_obd->obd_self_export,
- strlen(KEY_NEXT_ID), KEY_NEXT_ID,
- lov_info->mdd_lov_desc.ld_tgt_count,
- lov_info->mdd_lov_objids, NULL);
-
- if (rc)
- CERROR ("mdd_lov_set_nextid failed (%d)\n", rc);
-
- RETURN(rc);
-}
-
-struct mdd_lov_sync_info {
- struct lu_context *mlsi_ctxt;
- struct lu_device *mlsi_ld; /* the lov device to sync */
- struct obd_device *mlsi_watched; /* target osc */
- __u32 mlsi_index; /* index of target */
-};
-
-#define MDSLOV_NO_INDEX -1
-
-/* Inform MDS about new/updated target */
-static int mdd_lov_update_mds(struct lu_context *ctxt,
- struct lu_device *ld,
- struct obd_device *watched,
- __u32 idx)
-{
- struct mdd_device *mdd = lu2mdd_dev(ld);
- struct mdd_lov_info *lov_info = &mdd->mdd_lov_info;
- int old_count;
- int rc = 0;
- ENTRY;
-
- old_count = lov_info->mdd_lov_desc.ld_tgt_count;
- rc = mdd_lov_update_desc(ctxt, mdd);
- if (rc)
- RETURN(rc);
-
- /*
- * idx is set as data from lov_notify.
- * XXX did not consider recovery here
- */
- if (idx != MDSLOV_NO_INDEX) {
- if (idx >= lov_info->mdd_lov_desc.ld_tgt_count) {
- CERROR("index %d > count %d!\n", idx,
- lov_info->mdd_lov_desc.ld_tgt_count);
- RETURN(-EINVAL);
- }
-
- if (idx >= lov_info->mdd_lov_objids_in_file) {
- /* We never read this lastid; ask the osc */
- obd_id lastid;
- __u32 size = sizeof(lastid);
- rc = obd_get_info(watched->obd_self_export,
- strlen("last_id"),
- "last_id", &size, &lastid);
- if (rc)
- RETURN(rc);
- lov_info->mdd_lov_objids[idx] = lastid;
- lov_info->mdd_lov_objids_dirty = 1;
- mdd_lov_write_objids(ctxt, lov_info);
- } else {
- /* We have read this lastid from disk; tell the osc.
- Don't call this during recovery. */
- rc = mdd_lov_set_nextid(mdd);
- }
-
- CDEBUG(D_CONFIG, "last object "LPU64" from OST %d\n",
- lov_info->mdd_lov_objids[idx], idx);
- }
-
- RETURN(rc);
-}
-
-static int mdd_lov_clear_orphans(struct mdd_lov_info *mli,
- struct obd_uuid *ost_uuid)
-{
- int rc;
- struct obdo oa;
- struct obd_trans_info oti = {0};
- struct lov_stripe_md *empty_ea = NULL;
- ENTRY;
-
- LASSERT(mli->mdd_lov_objids != NULL);
-
- /* This create will in fact either create or destroy: If the OST is
- * missing objects below this ID, they will be created. If it finds
- * objects above this ID, they will be removed. */
- memset(&oa, 0, sizeof(oa));
- oa.o_valid = OBD_MD_FLFLAGS;
- oa.o_flags = OBD_FL_DELORPHAN;
- if (ost_uuid != NULL) {
- memcpy(&oa.o_inline, ost_uuid, sizeof(*ost_uuid));
- oa.o_valid |= OBD_MD_FLINLINE;
- }
- rc = obd_create(mli->mdd_lov_obd->obd_self_export, &oa,
- &empty_ea, &oti);
-
- RETURN(rc);
-}
-
-/* We only sync one osc at a time, so that we don't have to hold
- any kind of lock on the whole mds_lov_desc, which may change
- (grow) as a result of mds_lov_add_ost. This also avoids any
- kind of mismatch between the lov_desc and the mds_lov_desc,
- which are not in lock-step during lov_add_obd */
-static int __mdd_lov_synchronize(void *data)
-{
- struct mdd_lov_sync_info *mlsi = data;
- struct lu_device *ld = mlsi->mlsi_ld;
- struct obd_device *watched = mlsi->mlsi_watched;
- struct lu_context *ctxt = mlsi->mlsi_ctxt;
- struct mdd_device *mdd = lu2mdd_dev(ld);
- struct obd_uuid *uuid;
- __u32 idx = mlsi->mlsi_index;
- int rc = 0;
- ENTRY;
-
- OBD_FREE(mlsi, sizeof(*mlsi));
-
- LASSERT(ld);
- LASSERT(watched);
- uuid = &watched->u.cli.cl_target_uuid;
- LASSERT(uuid);
-
- rc = mdd_lov_update_mds(ctxt, ld, watched, idx);
- if (rc != 0)
- GOTO(out, rc);
-
- rc = obd_set_info_async(mdd->mdd_lov_info.mdd_lov_obd->obd_self_export,
- strlen(KEY_MDS_CONN), KEY_MDS_CONN, 0, uuid,
- NULL);
- if (rc != 0) {
- CERROR("failed at obd_set_info_async: %d\n", rc);
- GOTO(out, rc);
- }
-
- rc = mdd_lov_clear_orphans(&mdd->mdd_lov_info, uuid);
- if (rc != 0) {
- CERROR("failed at mds_lov_clear_orphans: %d\n", rc);
- GOTO(out, rc);
- }
-out:
- EXIT;
- lu_device_put(ld);
- return rc;
-}
-
-int mdd_lov_synchronize(void *data)
-{
- struct mdd_lov_sync_info *mlsi = data;
- char name[20];
-
- sprintf(name, "ll_mlov_sync_%02u", mlsi->mlsi_index);
- ptlrpc_daemonize(name);
-
- RETURN(__mdd_lov_synchronize(data));
-}
-
-int mdd_lov_start_synchronize(const struct lu_context *ctxt,
- struct lu_device *ld,
- struct obd_device *watched,
- void *data, int nonblock)
-{
- struct mdd_lov_sync_info *mlsi;
- int rc;
-
- ENTRY;
-
- LASSERT(watched);
-
- OBD_ALLOC(mlsi, sizeof(*mlsi));
- if (mlsi == NULL)
- RETURN(-ENOMEM);
-
- mlsi->mlsi_ctxt = (struct lu_context *)ctxt;
- mlsi->mlsi_ld = ld;
- mlsi->mlsi_watched = watched;
- if (data)
- mlsi->mlsi_index = *(__u32 *)data;
- else
- mlsi->mlsi_index = MDSLOV_NO_INDEX;
-
- /* Although class_export_get(obd->obd_self_export) would lock
- the MDS in place, since it's only a self-export
- it doesn't lock the LOV in place. The LOV can be disconnected
- during MDS precleanup, leaving nothing for __mdd_lov_synchronize.
- Simply taking an export ref on the LOV doesn't help, because it's
- still disconnected. Taking an obd reference insures that we don't
- disconnect the LOV. This of course means a cleanup won't
- finish for as long as the sync is blocking. */
- lu_device_get(ld);
-#if 0
- if (nonblock) {
- /* Synchronize in the background */
- rc = cfs_kernel_thread(mdd_lov_synchronize, mlsi,
- CLONE_VM | CLONE_FILES);
- if (rc < 0) {
- CERROR("error starting mdd_lov_synchronize: %d\n", rc);
- lu_device_put(ld);
- } else {
- CDEBUG(D_HA, "mdd_lov_synchronize idx=%d thread=%d\n",
- mlsi->mlsi_index, rc);
- rc = 0;
- }
- } else {
- rc = __mdd_lov_synchronize((void *)mlsi);
- }
-#else
- /*FIXME: Did not implement the nonblock lov sync here. because ctxt can not
- * be shared, maybe we need ref_count for ctxt */
- rc = __mdd_lov_synchronize((void *)mlsi);
-#endif