+static int mdt_export_cleanup(struct obd_export *exp)
+{
+ struct mdt_export_data *med = &exp->exp_mdt_data;
+ struct obd_device *obd = exp->exp_obd;
+ struct mdt_device *mdt;
+ struct mdt_thread_info *info;
+ struct lu_env env;
+ CFS_LIST_HEAD(closing_list);
+ struct mdt_file_data *mfd, *n;
+ int rc = 0;
+ ENTRY;
+
+ cfs_spin_lock(&med->med_open_lock);
+ while (!cfs_list_empty(&med->med_open_head)) {
+ cfs_list_t *tmp = med->med_open_head.next;
+ mfd = cfs_list_entry(tmp, struct mdt_file_data, mfd_list);
+
+ /* Remove mfd handle so it can't be found again.
+ * We are consuming the mfd_list reference here. */
+ class_handle_unhash(&mfd->mfd_handle);
+ cfs_list_move_tail(&mfd->mfd_list, &closing_list);
+ }
+ cfs_spin_unlock(&med->med_open_lock);
+ mdt = mdt_dev(obd->obd_lu_dev);
+ LASSERT(mdt != NULL);
+
+ rc = lu_env_init(&env, LCT_MD_THREAD);
+ if (rc)
+ RETURN(rc);
+
+ info = lu_context_key_get(&env.le_ctx, &mdt_thread_key);
+ LASSERT(info != NULL);
+ memset(info, 0, sizeof *info);
+ info->mti_env = &env;
+ info->mti_mdt = mdt;
+ info->mti_exp = exp;
+
+ if (!cfs_list_empty(&closing_list)) {
+ struct md_attr *ma = &info->mti_attr;
+ int lmm_size;
+ int cookie_size;
+
+ lmm_size = mdt->mdt_max_mdsize;
+ OBD_ALLOC(ma->ma_lmm, lmm_size);
+ if (ma->ma_lmm == NULL)
+ GOTO(out_lmm, rc = -ENOMEM);
+
+ cookie_size = mdt->mdt_max_cookiesize;
+ OBD_ALLOC(ma->ma_cookie, cookie_size);
+ if (ma->ma_cookie == NULL)
+ GOTO(out_cookie, rc = -ENOMEM);
+
+ /* Close any open files (which may also cause orphan unlinking). */
+ cfs_list_for_each_entry_safe(mfd, n, &closing_list, mfd_list) {
+ cfs_list_del_init(&mfd->mfd_list);
+ memset(&ma->ma_attr, 0, sizeof(ma->ma_attr));
+ ma->ma_lmm_size = lmm_size;
+ ma->ma_cookie_size = cookie_size;
+ ma->ma_need = 0;
+ /* It is not for setattr, just tell MDD to send
+ * DESTROY RPC to OSS if needed */
+ ma->ma_attr_flags = MDS_CLOSE_CLEANUP;
+ ma->ma_valid = MA_FLAGS;
+ mdt_mfd_close(info, mfd);
+ }
+ OBD_FREE(ma->ma_cookie, cookie_size);
+ ma->ma_cookie = NULL;
+out_cookie:
+ OBD_FREE(ma->ma_lmm, lmm_size);
+ ma->ma_lmm = NULL;
+ }
+out_lmm:
+ info->mti_mdt = NULL;
+ /* cleanup client slot early */
+ mdt_client_del(&env, mdt);
+ lu_env_fini(&env);
+
+ RETURN(rc);
+}