OpenZFS 9421, 9422 - zdb show possibly leaked objects
9421 zdb should detect and print out the number of "leaked" objects 9422 zfs diff and zdb should explicitly mark objects that are on the deleted queue It is possible for zfs to "leak" objects in such a way that they are not freed, but are also not accessible via the POSIX interface. As the only way to know that this is happened is to see one of them directly in a zdb run, or by noting unaccounted space usage, zdb should be enhanced to count these objects and return failure if some are detected. We have access to the delete queue through the zfs_get_deleteq function; we should call it in dump_znode to determine if the object is on the delete queue. This is not the most efficient possible method, but it is the simplest to implement, and should suffice for the common case where there few objects on the delete queue. Also zfs diff and zdb currently traverse every single dnode in a dataset and tries to figure out the path of the object by following it's parent. When an object is placed on the delete queue, for all practical purposes it's already discarded, it's parent might not exist anymore, and another object might now have the object number that belonged to the parent. While all of the above makes sense, when trying to figure out the path of an object that is on the delete queue, we can run into issues where either it is impossible to determine the path because the parent is gone, or another dnode has taken it's place and thus we are returned a wrong path. We should therefore avoid trying to determine the path of an object on the delete queue and mark the object itself as being on the delete queue to avoid confusion. To achieve this, we currently have two ideas: 1. When putting an object on the delete queue, change it's parent object number to a known constant that means NULL. 2. When displaying objects, first check if it is present on the delete queue. Authored by: Paul Dagnelie <pcd@delphix.com> Reviewed by: Matt Ahrens <matt@delphix.com> Reviewed by: Pavel Zakharov <pavel.zakharov@delphix.com> Approved by: Matt Ahrens <mahrens@delphix.com> Ported-by: Brian Behlendorf <behlendorf1@llnl.gov> OpenZFS-issue: https://illumos.org/issues/9421 OpenZFS-issue: https://illumos.org/issues/9422 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/45ae0dd9ca Closes #7500
This commit is contained in:
parent
5e097c67f1
commit
64c1dcefe3
|
@ -106,6 +106,7 @@ uint64_t *zopt_object = NULL;
|
|||
static unsigned zopt_objects = 0;
|
||||
libzfs_handle_t *g_zfs;
|
||||
uint64_t max_inflight = 1000;
|
||||
static int leaked_objects = 0;
|
||||
|
||||
static void snprintf_blkptr_compact(char *, size_t, const blkptr_t *);
|
||||
|
||||
|
@ -1983,9 +1984,12 @@ dump_znode(objset_t *os, uint64_t object, void *data, size_t size)
|
|||
|
||||
if (dump_opt['d'] > 4) {
|
||||
error = zfs_obj_to_path(os, object, path, sizeof (path));
|
||||
if (error != 0) {
|
||||
if (error == ESTALE) {
|
||||
(void) snprintf(path, sizeof (path), "on delete queue");
|
||||
} else if (error != 0) {
|
||||
leaked_objects++;
|
||||
(void) snprintf(path, sizeof (path),
|
||||
"\?\?\?<object#%llu>", (u_longlong_t)object);
|
||||
"path not found, possibly leaked");
|
||||
}
|
||||
(void) printf("\tpath %s\n", path);
|
||||
}
|
||||
|
@ -2376,14 +2380,19 @@ dump_dir(objset_t *os)
|
|||
(double)(max_slot_used - total_slots_used)*100 /
|
||||
(double)max_slot_used);
|
||||
|
||||
ASSERT3U(object_count, ==, usedobjs);
|
||||
|
||||
(void) printf("\n");
|
||||
|
||||
if (error != ESRCH) {
|
||||
(void) fprintf(stderr, "dmu_object_next() = %d\n", error);
|
||||
abort();
|
||||
}
|
||||
|
||||
ASSERT3U(object_count, ==, usedobjs);
|
||||
if (leaked_objects != 0) {
|
||||
(void) printf("%d potentially leaked objects detected\n",
|
||||
leaked_objects);
|
||||
leaked_objects = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -5209,5 +5218,5 @@ main(int argc, char **argv)
|
|||
libzfs_fini(g_zfs);
|
||||
kernel_fini();
|
||||
|
||||
return (0);
|
||||
return (error);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2015, 2017 by Delphix. All rights reserved.
|
||||
* Copyright 2016 Joyent, Inc.
|
||||
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
|
||||
*/
|
||||
|
@ -103,7 +103,10 @@ get_stats_for_obj(differ_info_t *di, const char *dsname, uint64_t obj,
|
|||
return (0);
|
||||
}
|
||||
|
||||
if (di->zerr == EPERM) {
|
||||
if (di->zerr == ESTALE) {
|
||||
(void) snprintf(pn, maxlen, "(on_delete_queue)");
|
||||
return (0);
|
||||
} else if (di->zerr == EPERM) {
|
||||
(void) snprintf(di->errbuf, sizeof (di->errbuf),
|
||||
dgettext(TEXT_DOMAIN,
|
||||
"The sys_config privilege or diff delegated permission "
|
||||
|
|
|
@ -2120,6 +2120,17 @@ zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
|
|||
*path = '\0';
|
||||
sa_hdl = hdl;
|
||||
|
||||
uint64_t deleteq_obj;
|
||||
VERIFY0(zap_lookup(osp, MASTER_NODE_OBJ,
|
||||
ZFS_UNLINKED_SET, sizeof (uint64_t), 1, &deleteq_obj));
|
||||
error = zap_lookup_int(osp, deleteq_obj, obj);
|
||||
if (error == 0) {
|
||||
return (ESTALE);
|
||||
} else if (error != ENOENT) {
|
||||
return (error);
|
||||
}
|
||||
error = 0;
|
||||
|
||||
for (;;) {
|
||||
uint64_t pobj = 0;
|
||||
char component[MAXNAMELEN + 2];
|
||||
|
|
Loading…
Reference in New Issue