Pawel Jakub Dawidek wrote:
> ZFS works really stable on FreeBSD, but I'm biggest problem is how to
> control ZFS memory usage. I've no idea how to leash that beast.
> 
> FreeBSD has a backpresure mechanism. I can register my function so it
> will be called when there are memory problems, which I do. I using it
> for ARC layer.
> Even with this in place under heavy load the kernel panics, because
> memory with KM_SLEEP cannot be allocated.
> 
> Here are some statistics of memory usage when the panic occurs:
> 
> zfs_znode_cache: 356 * 11547 = 4110732 bytes
>   zil_lwb_cache: 176 * 43 = 7568 bytes
>       arc_buf_t:  20 * 7060 = 141200 bytes
>   arc_buf_hdr_t: 188 * 7060 = 1327280 bytes
>         dnode_t: 756 * 162311 = 122707116 bytes !!
>  dmu_buf_impl_t: 332 * 18649 = 6191468
>           other: 14432256 bytes (regular kmem_alloc())
> 
> There is 1GB of RAM, 320MB is for the kernel. 1/3 if kernel memory is
> configured as ARC's maximum.
> When it panics, debugger statistics show that there is around 2/3 of
> this actually allocated, but probably due memory fragmentation.
> 
> The most important part is dnode_t probably as it looks it doesn't obey
> any limits. Maybe it is a bug in my port and I'm leaking them somehow?
> On the other hand when I unload ZFS kernel module, FreeBSD's kernel
> reports any memory leaks - they exist, but are much, much smaller.
> 
> There is also quite a lot of znodes, which I'd also like to be able to
> free and not sure how. In Solaris vnode's life end in VOP_INACTIVE()
> routine, but znode if kept around. In FreeBSD VOP_INACTIVE() means "puts
> the vnode onto free vnodes list" and when we want to use this vnode for
> different file system VOP_RECLAIM() is called and VOP_RECLAIM() will be
> a good place to free znode as well, if possible.
> 
> Any ideas how to fix it?
> 
The problem is that in ZFS the vnode holds onto more memory than just
the vnode itself.  Its fine to place the vnode on a "free vnodes list"
after a VOP_INACTIVE()... but you need to make sure the you have
"released" the *extra* memory associated with the vnode:
        vnode refs a znode (356 bytes + 512 bytes for the phys)
        znode refs a dnode (756 bytes + 512-16k for the phys)
So a vnode could be holding up to 17k of data in memory!

I suggest you free up the znode at VOP_INACTIVE() rather than waiting
until VOP_RECLAIM().

-Mark

Reply via email to