Recheck curthread->td_su after the VFS_SYNC() call, and re-sync if the

ast was rescheduled during VFS_SYNC().  It is possible that enough
parallel writes or slow/hung volume result in VFS_SYNC() deferring to
the ast flushing of workqueue.

Reported and tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2015-12-21 11:50:32 +00:00
parent e85324c92f
commit 44de1ba141
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=292541

View File

@ -13301,43 +13301,43 @@ softdep_ast_cleanup_proc(void)
bool req;
td = curthread;
mp = td->td_su;
if (mp == NULL)
return;
td->td_su = NULL;
error = vfs_busy(mp, MBF_NOWAIT);
vfs_rel(mp);
if (error != 0)
return;
if (ffs_own_mount(mp) && MOUNTEDSOFTDEP(mp)) {
ump = VFSTOUFS(mp);
for (;;) {
req = false;
ACQUIRE_LOCK(ump);
if (softdep_excess_items(ump, D_INODEDEP)) {
req = true;
request_cleanup(mp, FLUSH_INODES);
}
if (softdep_excess_items(ump, D_DIRREM)) {
req = true;
request_cleanup(mp, FLUSH_BLOCKS);
}
FREE_LOCK(ump);
if (softdep_excess_items(ump, D_NEWBLK) ||
softdep_excess_items(ump, D_ALLOCDIRECT) ||
softdep_excess_items(ump, D_ALLOCINDIR)) {
error = vn_start_write(NULL, &mp, V_WAIT);
if (error == 0) {
while ((mp = td->td_su) != NULL) {
td->td_su = NULL;
error = vfs_busy(mp, MBF_NOWAIT);
vfs_rel(mp);
if (error != 0)
return;
if (ffs_own_mount(mp) && MOUNTEDSOFTDEP(mp)) {
ump = VFSTOUFS(mp);
for (;;) {
req = false;
ACQUIRE_LOCK(ump);
if (softdep_excess_items(ump, D_INODEDEP)) {
req = true;
VFS_SYNC(mp, MNT_WAIT);
vn_finished_write(mp);
request_cleanup(mp, FLUSH_INODES);
}
if (softdep_excess_items(ump, D_DIRREM)) {
req = true;
request_cleanup(mp, FLUSH_BLOCKS);
}
FREE_LOCK(ump);
if (softdep_excess_items(ump, D_NEWBLK) ||
softdep_excess_items(ump, D_ALLOCDIRECT) ||
softdep_excess_items(ump, D_ALLOCINDIR)) {
error = vn_start_write(NULL, &mp,
V_WAIT);
if (error == 0) {
req = true;
VFS_SYNC(mp, MNT_WAIT);
vn_finished_write(mp);
}
}
if ((td->td_pflags & TDP_KTHREAD) != 0 || !req)
break;
}
if ((td->td_pflags & TDP_KTHREAD) != 0 || !req)
break;
}
vfs_unbusy(mp);
}
vfs_unbusy(mp);
}
/*