]> granicus.if.org Git - zfs/commitdiff
Treat spill block dbufs as meta data
authorBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 2 May 2014 19:26:47 +0000 (12:26 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 5 May 2014 20:56:59 +0000 (13:56 -0700)
When the system attributes (SAs) for an object exceed what can
can be stored in the bonus area of a dnode a spill block is
allocated.  These spill blocks are currently considered data
blocks.  However, they should be accounted for as meta data
because they are effectively an extension of the dnode.

While this may seem like a minor accounting issue it has broader
implications.  The key thing to be aware of is that each spill
block will hold a reference on its parent dnode.  The dnode in
turn holds a reference on its dbuf in the dnode object.  This
means that a single 512 byte data buffer for a spill block can
pin over 16k of meta data.  This is analogous to the small file
situation described in 2b13331 where a relatively small number
of data buffer can cause the ARC to exceed the meta limit.

However, unlike the small file case a spill block can legitimately
be considered meta data.  By changing the spill block to meta data
they will now be dropped from the cache when the meta limit is
reached.  This then allows the dnodes and dbufs which the spill
block was pinning to be released.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Prakash Surya <surya1@llnl.gov>
Closes #2294

module/zfs/dbuf.c

index c8a52617178e573f12f4426b48f80dee302b45a1..4f1750650831011dc59505ea3ff9a6342ea08de8 100644 (file)
@@ -263,7 +263,10 @@ dbuf_evict_user(dmu_buf_impl_t *db)
 boolean_t
 dbuf_is_metadata(dmu_buf_impl_t *db)
 {
-       if (db->db_level > 0) {
+       /*
+        * Consider indirect blocks and spill blocks to be meta data.
+        */
+       if (db->db_level > 0 || db->db_blkid == DMU_SPILL_BLKID) {
                return (B_TRUE);
        } else {
                boolean_t is_metadata;