summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2015-12-21 11:50:32 +0000
committerkib <kib@FreeBSD.org>2015-12-21 11:50:32 +0000
commit70adc1e2169681308132c25cd91bcf7eda31444b (patch)
tree7807eb51e0c1cb886698a62ce45cc19968d2bb3a /sys/ufs
parent17cf2dee7c4e8009b175da82f34d607b8097696b (diff)
downloadFreeBSD-src-70adc1e2169681308132c25cd91bcf7eda31444b.zip
FreeBSD-src-70adc1e2169681308132c25cd91bcf7eda31444b.tar.gz
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
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_softdep.c64
1 files changed, 32 insertions, 32 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index f6ee661..04ea39c 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -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;
+ request_cleanup(mp, FLUSH_INODES);
+ }
+ if (softdep_excess_items(ump, D_DIRREM)) {
req = true;
- VFS_SYNC(mp, MNT_WAIT);
- vn_finished_write(mp);
+ 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);
}
/*
OpenPOWER on IntegriCloud