replmd: Try to add forward-link for unknown cross-partition links
authorTim Beale <timbeale@catalyst.net.nz>
Mon, 24 Jul 2017 04:20:58 +0000 (16:20 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 18 Aug 2017 04:07:12 +0000 (06:07 +0200)
Previously Samba would just drop cross-partition links where the link
target object is unknown. Instead, what we want to do is try to add the
forward link for the GUID specified. We can't add the backlink because
we don't know the target, however, dbcheck should be able to fix any
missing backlinks.

The new behaviour should now mean dbcheck will detect the problem and be
able to fix it. It's still not ideal, but it's better than dropping the
link completely.

I've updated the log so that it has higher severity and tells the user
what they need to do to fix it.

These changes now mean that the selftests now detect an error - instead
of completely dropping the serverReference, we now have a missing
backlink. I've updated the selftests to fix up any missing
serverReference backlinks before running dbcheck.

Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12972

source4/dsdb/samdb/ldb_modules/repl_meta_data.c
testprogs/blackbox/dbcheck.sh

index 228622cfcc0c445e77128c6509606c3410fbe9c6..d5234d58d8ca9bdec1c0f233033600788b21dd98 100644 (file)
@@ -374,8 +374,9 @@ static int replmd_process_backlink(struct ldb_module *module, struct la_backlink
        ret = dsdb_module_dn_by_guid(module, frame, &bl->target_guid, &target_dn, parent);
        if (ret != LDB_SUCCESS) {
                struct GUID_txt_buf guid_str;
-               DEBUG(2,(__location__ ": WARNING: Failed to find target DN for linked attribute with GUID %s\n",
-                        GUID_buf_string(&bl->target_guid, &guid_str)));
+               DBG_WARNING("Failed to find target DN for linked attribute with GUID %s\n",
+                           GUID_buf_string(&bl->target_guid, &guid_str));
+               DBG_WARNING("Please run 'samba-tool dbcheck' to resolve any missing backlinks.\n");
                talloc_free(frame);
                return LDB_SUCCESS;
        }
@@ -6816,15 +6817,14 @@ static int replmd_check_target_exists(struct ldb_module *module,
                } else {
 
                        /*
-                        * TODO:
-                        * We don't handle cross-partition links well here (we
-                        * could potentially lose them), but don't fail the
-                        * replication.
+                        * The target of the cross-partition link is missing.
+                        * Continue and try to at least add the forward-link.
+                        * This isn't great, but if we can add a partial link
+                        * then it's better than nothing.
                         */
                        DEBUG(2,("Failed to resolve cross-partition link between %s and %s\n",
                                 ldb_dn_get_linearized(source_dn),
                                 ldb_dn_get_linearized(dsdb_dn->dn)));
-                       *ignore_link = true;
                }
        } else if (target_res->count != 1) {
                ldb_asprintf_errstring(ldb, "More than one object found matching objectGUID %s\n",
index 0f979abc7eb703902b7df06a8b50c36fd208c990..387ce70eefc4a9176aa174b5a604b634059c7487 100755 (executable)
@@ -27,6 +27,13 @@ dbcheck_fix_stale_links() {
        $BINDIR/samba-tool dbcheck --quiet --fix --yes remove_plausible_deleted_DN_links --attrs="member msDS-NC-Replica-Locations msDS-NC-RO-Replica-Locations" --cross-ncs $ARGS
 }
 
+# This list of attributes can be freely extended
+dbcheck_fix_crosspartition_backlinks() {
+       # we may not know the target yet when we receive a cross-partition link,
+       # which can result in a missing backlink
+       $BINDIR/samba-tool dbcheck --quiet --fix --yes fix_all_missing_backlinks --attrs="serverReference" --cross-ncs $ARGS
+}
+
 # This test shows that this does not do anything to a current
 # provision (that would be a bug)
 dbcheck_reset_well_known_acls() {
@@ -47,6 +54,7 @@ force_modules() {
 
 dbcheck_fix_one_way_links
 dbcheck_fix_stale_links
+dbcheck_fix_crosspartition_backlinks
 testit "dbcheck" dbcheck
 testit "reindex" reindex
 testit "fixed_attrs" fixed_attrs