+ struct lu_device *d)
+{
+ struct osd_device *o = osd_dev(d);
+ int rc;
+
+ ENTRY;
+ osd_index_backup(env, o, false);
+ if (o->od_os) {
+ osd_objset_unregister_callbacks(o);
+ if (!o->od_dt_dev.dd_rdonly) {
+ osd_sync(env, lu2dt_dev(d));
+ txg_wait_callbacks(
+ spa_get_dsl(dmu_objset_spa(o->od_os)));
+ }
+ }
+
+ /* now with all the callbacks completed we can cleanup the remainings */
+ osd_shutdown(env, o);
+ osd_scrub_cleanup(env, o);
+
+ rc = osd_procfs_fini(o);
+ if (rc) {
+ CERROR("proc fini error %d\n", rc);
+ RETURN(ERR_PTR(rc));
+ }
+
+ if (o->od_os)
+ osd_umount(env, o);
+
+ RETURN(NULL);
+}
+
+
+static struct lu_device *osd_device_free(const struct lu_env *env,
+ struct lu_device *d)
+{
+ struct osd_device *o = osd_dev(d);
+
+ ENTRY;
+ /* XXX: make osd top device in order to release reference */
+ if (d->ld_site) {
+ d->ld_site->ls_top_dev = d;
+ lu_site_purge(env, d->ld_site, -1);
+ lu_site_print(env, d->ld_site, &d->ld_site->ls_obj_hash.nelems,
+ D_ERROR, lu_cdebug_printer);
+ }
+ if (o->od_site.ls_bottom_dev)
+ lu_site_fini(&o->od_site);
+ dt_device_fini(&o->od_dt_dev);
+ OBD_FREE_PTR(o);
+
+ RETURN(NULL);
+}