Whamcloud - gitweb
LU-9678 osd-zfs: register arc_prune_func() after site init
[fs/lustre-release.git] / lustre / osd-zfs / osd_handler.c
index fa04e09..bcb8705 100644 (file)
@@ -47,7 +47,7 @@
 #include <obd_class.h>
 #include <lustre_disk.h>
 #include <lustre_fid.h>
-#include <lustre_param.h>
+#include <uapi/linux/lustre_param.h>
 #include <md_object.h>
 
 #include "osd_internal.h"
@@ -96,6 +96,8 @@ static void arc_prune_func(int64_t bytes, void *private)
        struct lu_env      env;
        int rc;
 
+       LASSERT(site->ls_obj_hash);
+
        rc = lu_env_init(&env, LCT_SHRINKER);
        if (rc) {
                CERROR("%s: can't initialize shrinker env: rc = %d\n",
@@ -147,8 +149,13 @@ static void osd_trans_commit_cb(void *cb_data, int error)
        dt_txn_hook_commit(th);
 
        /* call per-transaction callbacks if any */
-       list_for_each_entry_safe(dcb, tmp, &oh->ot_dcb_list, dcb_linkage)
+       list_for_each_entry_safe(dcb, tmp, &oh->ot_dcb_list, dcb_linkage) {
+               LASSERTF(dcb->dcb_magic == TRANS_COMMIT_CB_MAGIC,
+                        "commit callback entry: magic=%x name='%s'\n",
+                        dcb->dcb_magic, dcb->dcb_name);
+               list_del_init(&dcb->dcb_linkage);
                dcb->dcb_func(NULL, th, dcb, error);
+       }
 
        /* Unlike ldiskfs, zfs updates space accounting at commit time.
         * As a consequence, op_end is called only now to inform the quota slave
@@ -227,9 +234,8 @@ static int osd_trans_start(const struct lu_env *env, struct dt_device *d,
        RETURN(rc);
 }
 
-static int osd_unlinked_object_free(struct osd_device *osd, uint64_t oid);
-
-static void osd_unlinked_list_emptify(struct osd_device *osd,
+static void osd_unlinked_list_emptify(const struct lu_env *env,
+                                     struct osd_device *osd,
                                      struct list_head *list, bool free)
 {
        struct osd_object *obj;
@@ -243,7 +249,7 @@ static void osd_unlinked_list_emptify(struct osd_device *osd,
 
                list_del_init(&obj->oo_unlinked_linkage);
                if (free)
-                       (void)osd_unlinked_object_free(osd, oid);
+                       (void)osd_unlinked_object_free(env, osd, oid);
        }
 }
 
@@ -287,7 +293,7 @@ static int osd_trans_stop(const struct lu_env *env, struct dt_device *dt,
                LASSERT(oh->ot_tx);
                dmu_tx_abort(oh->ot_tx);
                osd_object_sa_dirty_rele(oh);
-               osd_unlinked_list_emptify(osd, &unlinked, false);
+               osd_unlinked_list_emptify(env, osd, &unlinked, false);
                /* there won't be any commit, release reserved quota space now,
                 * if any */
                qsd_op_end(env, osd->od_quota_slave, &oh->ot_quota_trans);
@@ -310,7 +316,7 @@ static int osd_trans_stop(const struct lu_env *env, struct dt_device *dt,
         * by osd_trans_commit_cb already. */
        dmu_tx_commit(oh->ot_tx);
 
-       osd_unlinked_list_emptify(osd, &unlinked, true);
+       osd_unlinked_list_emptify(env, osd, &unlinked, true);
 
        if (sync)
                txg_wait_synced(dmu_objset_pool(osd->od_os), txg);
@@ -741,6 +747,9 @@ static int osd_shutdown(const struct lu_env *env, struct osd_device *o)
 
        /* shutdown quota slave instance associated with the device */
        if (o->od_quota_slave != NULL) {
+               /* complete all in-flight callbacks */
+               osd_sync(env, &o->od_dt_dev);
+               txg_wait_callbacks(spa_get_dsl(dmu_objset_spa(o->od_os)));
                qsd_fini(env, o->od_quota_slave);
                o->od_quota_slave = NULL;
        }
@@ -838,7 +847,7 @@ err:
 static int osd_objset_open(struct osd_device *o)
 {
        uint64_t        version = ZPL_VERSION;
-       uint64_t        sa_obj;
+       uint64_t        sa_obj, unlink_obj;
        int             rc;
        ENTRY;
 
@@ -883,7 +892,7 @@ static int osd_objset_open(struct osd_device *o)
        }
 
        rc = -zap_lookup(o->od_os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET,
-                        8, 1, &o->od_unlinkedid);
+                        8, 1, &unlink_obj);
        if (rc) {
                CERROR("%s: lookup for %s failed: rc = %d\n",
                       o->od_svname, ZFS_UNLINKED_SET, rc);
@@ -899,6 +908,13 @@ static int osd_objset_open(struct osd_device *o)
                GOTO(out, rc = -ENOTSUPP);
        }
 
+       rc = __osd_obj2dnode(o->od_os, unlink_obj, &o->od_unlinked);
+       if (rc) {
+               CERROR("%s: can't get dnode for unlinked: rc = %d\n",
+                      o->od_svname, rc);
+               GOTO(out, rc);
+       }
+
 out:
        if (rc != 0 && o->od_os != NULL) {
                dmu_objset_disown(o->od_os, o);
@@ -908,9 +924,10 @@ out:
        RETURN(rc);
 }
 
-static int
-osd_unlinked_object_free(struct osd_device *osd, uint64_t oid)
+int osd_unlinked_object_free(const struct lu_env *env, struct osd_device *osd,
+                        uint64_t oid)
 {
+       char *key = osd_oti_get(env)->oti_str;
        int       rc;
        dmu_tx_t *tx;
 
@@ -931,7 +948,8 @@ osd_unlinked_object_free(struct osd_device *osd, uint64_t oid)
 
        tx = dmu_tx_create(osd->od_os);
        dmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END);
-       dmu_tx_hold_zap(tx, osd->od_unlinkedid, FALSE, NULL);
+       osd_tx_hold_zap(tx, osd->od_unlinked->dn_object, osd->od_unlinked,
+                       FALSE, NULL);
        rc = -dmu_tx_assign(tx, TXG_WAIT);
        if (rc != 0) {
                CWARN("%s: Cannot assign tx for %llu: rc = %d\n",
@@ -939,7 +957,9 @@ osd_unlinked_object_free(struct osd_device *osd, uint64_t oid)
                goto failed;
        }
 
-       rc = -zap_remove_int(osd->od_os, osd->od_unlinkedid, oid, tx);
+       snprintf(key, sizeof(osd_oti_get(env)->oti_str), "%llx", oid);
+       rc = osd_zap_remove(osd, osd->od_unlinked->dn_object,
+                           osd->od_unlinked, key, tx);
        if (rc != 0) {
                CWARN("%s: Cannot remove %llu from unlinked set: rc = %d\n",
                      osd->od_svname, oid, rc);
@@ -969,13 +989,13 @@ osd_unlinked_drain(const struct lu_env *env, struct osd_device *osd)
        zap_cursor_t     zc;
        zap_attribute_t *za = &osd_oti_get(env)->oti_za;
 
-       zap_cursor_init(&zc, osd->od_os, osd->od_unlinkedid);
+       zap_cursor_init(&zc, osd->od_os, osd->od_unlinked->dn_object);
 
        while (zap_cursor_retrieve(&zc, za) == 0) {
                /* If cannot free the object, leave it in the unlinked set,
                 * until the OSD is mounted again when obd_unlinked_drain()
                 * will be called. */
-               if (osd_unlinked_object_free(osd, za->za_first_integer) != 0)
+               if (osd_unlinked_object_free(env, osd, za->za_first_integer))
                        break;
                zap_cursor_advance(&zc);
        }
@@ -1033,16 +1053,21 @@ static int osd_mount(const struct lu_env *env,
        o->od_xattr_in_sa = B_TRUE;
        o->od_max_blksz = osd_spa_maxblocksize(o->od_os->os_spa);
 
-       rc = osd_objset_register_callbacks(o);
+       rc = __osd_obj2dnode(o->od_os, o->od_rootid, &rootdn);
        if (rc)
                GOTO(err, rc);
+       o->od_root = rootdn->dn_object;
+       osd_dnode_rele(rootdn);
 
-       rc = __osd_obj2dnode(env, o->od_os, o->od_rootid, &rootdn);
+       rc = __osd_obj2dnode(o->od_os, DMU_USERUSED_OBJECT,
+                            &o->od_userused_dn);
        if (rc)
                GOTO(err, rc);
 
-       o->od_root = rootdn->dn_object;
-       osd_dnode_rele(rootdn);
+       rc = __osd_obj2dnode(o->od_os, DMU_GROUPUSED_OBJECT,
+                            &o->od_groupused_dn);
+       if (rc)
+               GOTO(err, rc);
 
        /* 1. initialize oi before any file create or file open */
        rc = osd_oi_init(env, o);
@@ -1058,6 +1083,10 @@ static int osd_mount(const struct lu_env *env,
        if (rc)
                GOTO(err, rc);
 
+       rc = osd_objset_register_callbacks(o);
+       if (rc)
+               GOTO(err, rc);
+
        rc = osd_procfs_init(o, o->od_svname);
        if (rc)
                GOTO(err, rc);
@@ -1100,6 +1129,19 @@ static void osd_umount(const struct lu_env *env, struct osd_device *o)
                CERROR("%s: lost %d pinned dbuf(s)\n", o->od_svname,
                       atomic_read(&o->od_zerocopy_pin));
 
+       if (o->od_unlinked) {
+               osd_dnode_rele(o->od_unlinked);
+               o->od_unlinked = NULL;
+       }
+       if (o->od_userused_dn) {
+               osd_dnode_rele(o->od_userused_dn);
+               o->od_userused_dn = NULL;
+       }
+       if (o->od_groupused_dn) {
+               osd_dnode_rele(o->od_groupused_dn);
+               o->od_groupused_dn = NULL;
+       }
+
        if (o->od_os != NULL) {
                if (!o->od_dt_dev.dd_rdonly)
                        /* force a txg sync to get all commit callbacks */
@@ -1199,9 +1241,6 @@ static struct lu_device *osd_device_fini(const struct lu_env *env,
        ENTRY;
 
 
-       osd_shutdown(env, o);
-       osd_oi_fini(env, o);
-
        if (o->od_os) {
                osd_objset_unregister_callbacks(o);
                if (!o->od_dt_dev.dd_rdonly) {
@@ -1211,6 +1250,10 @@ static struct lu_device *osd_device_fini(const struct lu_env *env,
                }
        }
 
+       /* now with all the callbacks completed we can cleanup the remainings */
+       osd_shutdown(env, o);
+       osd_oi_fini(env, o);
+
        rc = osd_procfs_fini(o);
        if (rc) {
                CERROR("proc fini error %d\n", rc);