]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
MFC r334810 (by benno), r338205, r338206:
authormav <mav@FreeBSD.org>
Thu, 27 Sep 2018 17:22:40 +0000 (17:22 +0000)
committermav <mav@FreeBSD.org>
Thu, 27 Sep 2018 17:22:40 +0000 (17:22 +0000)
commitfb34649147a10714b705d2a531ae3674ed1b4071
tree30d1b346355ca0bdf91382cdce1c92ad7ba2e7f2
parent950449e37ce2dd486439cd4054eb5ea098ff3c21
MFC r334810 (by benno), r338205, r338206:
r334810:
Break recursion involving getnewvnode and zfs_rmnode.

When we're at our vnode limit, getnewvnode will call into the vnode LRU
cache to free up vnodes. If the vnode we try to recycle is a ZFS vnode we
end up, eventually, in zfs_rmnode. If the ZFS vnode we're recycling
represents something with extended attributes, zfs_rmnode will call
zfs_zget which will attempt to allocate another vnode. If the next vnode we
try to recycle is also a ZFS vnode representing something with extended
attributes we can recurse further. This ends up being unbounded and can end
up overflowing the stack.

In order to avoid this, restructure zfs_rmnode to simply add the extended
attribute directory's object ID to the unlinked set, thus not requiring the
allocation of a vnode. We then schedule a task that calls zfs_unlinked_drain
which will do the work of properly marking the vnodes for unlinking.
zfs_unlinked_drain is also called on mount so these will be cleaned up
there.

r338205:
Create separate taskqueue to call zfs_unlinked_drain().

r334810 introduced zfs_unlinked_drain() dispatch to taskqueue on every
deletion of a file with extended attributes.  Using system_taskq for that
with its multiple threads in case of multiple files deletion caused all
available CPU threads to uselessly spin on busy locks, completely blocking
the system.

Use of single dedicated taskqueue is the only easy solution I've found,
while in would be great if we could specify that some task should be
executed only once at a time, but never in parallel, while many tasks
could use different threads same time.

r338206:
Add dmu_tx_assign() error handling in zfs_unlinked_drain().

The error handling got lost during r334810, while according to the report
error there may happen in case of dataset being over quota.  In such case
just leave the node in the unlinked list to be freed sometimes later.
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c