+static int osd_oi_destroy(const struct lu_env *env, struct osd_device *o,
+ const char *name)
+{
+ struct osd_oi oi;
+ dmu_tx_t *tx;
+ dnode_t *rootdn;
+ uint64_t oid;
+ int rc;
+
+ ENTRY;
+
+ if (o->od_dt_dev.dd_rdonly)
+ RETURN(-EROFS);
+
+ rc = osd_oi_lookup(env, o, o->od_rootid, name, &oi);
+ if (rc == -ENOENT)
+ RETURN(0);
+ if (rc)
+ RETURN(rc);
+
+ oid = oi.oi_zapid;
+
+ rc = __osd_obj2dnode(o->od_os, o->od_rootid, &rootdn);
+ if (rc)
+ RETURN(rc);
+
+ tx = dmu_tx_create(o->od_os);
+ dmu_tx_mark_netfree(tx);
+ dmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END);
+ osd_tx_hold_zap(tx, oid, rootdn, FALSE, NULL);
+ rc = -dmu_tx_assign(tx, TXG_WAIT);
+ if (rc) {
+ dmu_tx_abort(tx);
+ GOTO(out, rc);
+ }
+
+ rc = -dmu_object_free(o->od_os, oid, tx);
+ if (rc) {
+ CERROR("%s: failed to free %s %llu: rc = %d\n",
+ o->od_svname, name, oid, rc);
+ GOTO(commit, rc);
+ }
+
+ rc = osd_zap_remove(o, o->od_rootid, rootdn, name, tx);
+ if (rc) {
+ CERROR("%s: zap_remove %s failed: rc = %d\n",
+ o->od_svname, name, rc);
+ GOTO(commit, rc);
+ }
+
+ EXIT;
+commit:
+ dmu_tx_commit(tx);
+out:
+ osd_dnode_rele(rootdn);
+
+ return rc;
+}
+