fsync: giving up on dirty on ufs partitions running vfs_write_suspend()
Andreas Longwitz
longwitz at incore.de
Fri Sep 8 13:42:25 UTC 2017
I try to describe the cause for the "fsync: given up on dirty" problem
described in
https://lists.freebsd.org/pipermail/freebsd-fs/2012-February/013804.html
or
https://lists.freebsd.org/pipermail/freebsd-fs/2013-August/018163.html
Now I run FreeBSD 10.3 Stable r317936 and sometimes I see messages like
<kern.crit> dssbkp4 kernel: fsync: giving up on dirty
<kern.crit> dssbkp4 kernel: 0xfffff80040d6c938: tag devfs, type VCHR
<kern.crit> dssbkp4 kernel: usecount 1, writecount 0, refcount 47
mountedhere 0xfffff8004083a200
<kern.crit> dssbkp4 kernel: flags (VI_ACTIVE)
<kern.crit> dssbkp4 kernel: v_object 0xfffff800409b3500 ref 0 pages
1138 cleanbuf 42 dirtybuf 4
<kern.crit> dssbkp4 kernel: lock type devfs: EXCL by thread
0xfffff800403a8a00 (pid 26, g_journal switcher, tid 100181)
<kern.crit> dssbkp4 kernel: dev mirror/gmbkp4p5.journal
<kern.crit> dssbkp4 kernel: GEOM_JOURNAL: Cannot suspend file system
/home (error=35).
on all of my servers running gjournal. Similar messages can be seen when
a snapshot is taken (e.g. dump -L) on a arbitrary ufs partition. In all
these cases the function vfs_write_suspend() was called which returned
EAGAIN. This error code is set in vop_stdfsync(), when the above
messages are created.
First I was confused about the "mountedhere" address, because the given
address does not point to a "struct mount" but (as type = VCHR
indicates) to a "struct cdev". Threfore I suggest the following patch to
improve the output of vn_printf() using the textstrings from defines in
/sys/sys/vnode.h:
--- vfs_subr.c.orig 2017-05-08 14:17:38.000000000 +0200
+++ vfs_subr.c 2017-08-30 10:45:47.549740000 +0200
@@ -3003,6 +3003,8 @@
static char *typename[] =
{"VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD",
"VMARKER"};
+static char *typetext[] =
+{"", "", "mountedhere", "", "rdev", "", "socket", "fifoinfo", "", ""};
void
vn_printf(struct vnode *vp, const char *fmt, ...)
@@ -3016,8 +3018,9 @@
va_end(ap);
printf("%p: ", (void *)vp);
printf("tag %s, type %s\n", vp->v_tag, typename[vp->v_type]);
- printf(" usecount %d, writecount %d, refcount %d mountedhere
%p\n",
- vp->v_usecount, vp->v_writecount, vp->v_holdcnt,
vp->v_mountedhere);
+ printf(" usecount %d, writecount %d, refcount %d %s %p\n",
+ vp->v_usecount, vp->v_writecount, vp->v_holdcnt,
typetext[vp->v_type],
+ vp->v_mountedhere);
buf[0] = '\0';
buf[1] = '\0';
if (vp->v_vflag & VV_ROOT)
Second I found, that the "dirty" situation during vfs_write_suspend()
only occurs when a big file (more than 10G on a partition of 116G) is
removed. If vfs_write_suspend() is called immediately after "rm
bigfile", then in vop_stdfsync() 1000 tries (maxretry) are done to wait
for the "rm bigfile" to complete. Because a lot of bitmap writes must be
done, the value 1000 is not sufficient on my servers. I have increased
maxretry and in the worst case I saw 8650 tries to complete without
"dirty". In this case the time spent in vop_stdfsync() was about 0,5
seconds. The following patch solves the "dirty problem" for me:
--- vfs_default.c.orig 2016-10-24 12:26:57.000000000 +0200
+++ vfs_default.c 2017-09-08 12:49:18.059970000 +0200
@@ -644,7 +644,7 @@
struct bufobj *bo;
struct buf *nbp;
int error = 0;
- int maxretry = 1000; /* large, arbitrarily chosen */
+ int maxretry = 100000; /* large, arbitrarily chosen */
bo = &vp->v_bufobj;
BO_LOCK(bo);
---
Andreas Longwitz
More information about the freebsd-fs
mailing list