]> granicus.if.org Git - zfs/commitdiff
Tag ABD pages for exclusion in kernel crash dumps
authorDon Brady <don.brady@delphix.com>
Wed, 28 Aug 2019 17:44:46 +0000 (11:44 -0600)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 28 Aug 2019 17:44:46 +0000 (10:44 -0700)
Tag the ABD data pages so that they can be identified for exclusion
from kernel crash dumps. Eliminating the zfs file data allows for
significantly smaller crash dump files. Note that ZFS in illumos has
always excluded the zfs data pages from a kernel crash dump.

This change tags ARC scatter data pages so they can be identified from
the makedumpfile(8) command. That command is used to create smaller
dump files by ignoring some memory regions and using compression. It
already filters file data from the VFS page cache and will now be able
to exclude ZFS file data pages from the dump file.

A corresponding change to makeumpfile(8) is required to identify ZFS
data pages.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Paul Dagnelie <pcd@delphix.com>
Signed-off-by: Don Brady <don.brady@delphix.com>
Closes #8899

module/zfs/abd.c

index 8b2514404a8611f070e76f49c1a9a07a4fd8294e..ac6b0b742733b80ae2a7d8d87a2c581680b4f417 100644 (file)
@@ -245,6 +245,32 @@ abd_chunkcnt_for_bytes(size_t size)
 }
 
 #ifdef _KERNEL
+/*
+ * Mark zfs data pages so they can be excluded from kernel crash dumps
+ */
+#ifdef _LP64
+#define        ABD_FILE_CACHE_PAGE     0x2F5ABDF11ECAC4E
+
+static inline void
+abd_mark_zfs_page(struct page *page)
+{
+       get_page(page);
+       SetPagePrivate(page);
+       set_page_private(page, ABD_FILE_CACHE_PAGE);
+}
+
+static inline void
+abd_unmark_zfs_page(struct page *page)
+{
+       set_page_private(page, 0UL);
+       ClearPagePrivate(page);
+       put_page(page);
+}
+#else
+#define        abd_mark_zfs_page(page)
+#define        abd_unmark_zfs_page(page)
+#endif /* _LP64 */
+
 #ifndef CONFIG_HIGHMEM
 
 #ifndef __GFP_RECLAIM
@@ -318,6 +344,7 @@ abd_alloc_pages(abd_t *abd, size_t size)
                size_t sg_size = MIN(PAGESIZE << compound_order(page),
                    remaining_size);
                sg_set_page(sg, page, sg_size, 0);
+               abd_mark_zfs_page(page);
                remaining_size -= sg_size;
 
                sg = sg_next(sg);
@@ -404,6 +431,7 @@ abd_alloc_pages(abd_t *abd, size_t size)
 
                ABDSTAT_BUMP(abdstat_scatter_orders[0]);
                sg_set_page(sg, page, PAGESIZE, 0);
+               abd_mark_zfs_page(page);
        }
 
        if (nr_pages > 1) {
@@ -430,6 +458,7 @@ abd_free_pages(abd_t *abd)
 
        abd_for_each_sg(abd, sg, nr_pages, i) {
                page = sg_page(sg);
+               abd_unmark_zfs_page(page);
                order = compound_order(page);
                __free_pages(page, order);
                ASSERT3U(sg->length, <=, PAGE_SIZE << order);